HotTranslator — перевод текста в мессенжерах «на лету»

в 13:21, , рубрики: иностранные языки, мессенджеры, общение, переводчик, переводчик google, метки: , , , ,

В комментариях к моей прошлой статье пользователь vvzvlad натолкнул меня на идею программы, которая бы помогала вам при общении с иностранцами, а именно переводила бы предложения на необходимый для вас язык при нажатии на хоткей.
HotTranslator — перевод текста в мессенжерах «на лету»
В итоге получилась программка под названием HotTranslator, которую вы можете скачать здесь.
Файл проекта находится здесь.
HotTranslator — перевод текста в мессенжерах «на лету»

Под катом вы увидите пояснения и её исходники.

Если вы не хотите разбираться в коде, а хотите только посмотреть, как работает программа, то можете смело прокручивать в конец статьи.

Приступаем

Для начала нам необходимо импортировать необходимые функции.

       [DllImport("User32.dll", SetLastError = true)]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool RegisterHotKey(IntPtr hWnd, int id,
uint fsModifiers, uint vk);

       [DllImport("User32.dll", SetLastError = true)]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern ushort GlobalAddAtom(string name);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern ushort GlobalDeleteAtom(ushort nAtom);

       [DllImport("user32.dll", SetLastError = true)]
       public static extern void keybd_event(byte bVk, byte bScan,
uint dwFlags, int dwExtraInfo);

       ushort atom;

Затем нам необходимо зарегистрировать хоткей в системе.

 atom = GlobalAddAtom("HotTranslator");
           if (!RegisterHotKey(this.Handle, atom,
Settings.Default.FirstKey, Settings.Default.SecondKey))
           {
               Form2 form = new Form2();
               form.textBox1.Text = "Возникла ошибка при регистрации
хоткея. Возможно, данная комбинация уже занята.";
               form.Show();
               this.Show();
           }

И написать метод, который отвечает за обработку хоткея.

protected override void WndProc(ref Message m)
       {
           //Если сработал HotKey
           if (m.Msg == 0x0312)
           {
               //Эмулируем нажатие Ctrl+C
               CtrlCEmul();

               Thread.Sleep(150);

               //И начинаем выполнять главную функцию
               MainFunction();
               return;

           }
           base.WndProc(ref m);
       }

Также нам нужно написать функции для эмуляции copy-paste.

       void CtrlCEmul()
       {
           keybd_event(0x11, 0, 0, 0);
           keybd_event((byte)'C', 0, 0, 0);
           keybd_event((byte)'C', 0, 0x2, 0);
           keybd_event(0x11, 0, 0x2, 0);
       }

       void CtrlVEmul()
       {
           keybd_event(0x11, 0, 0, 0);
           keybd_event((byte)'V', 0, 0, 0);
           keybd_event((byte)'V', 0, 0x2, 0);
           keybd_event(0x11, 0, 0x2, 0);
       }

А также функцию для получения перевода из Гугл Переводчика.

private string GetTranslate(string message, string toLang)
       {
           //Создаём необходимые объекты для работы с веб-запросами
           using (HttpRequest request = new HttpRequest())
           {
               StringDictionary reqParams = new StringDictionary();

               //Задаём необходимые параметры веб-запроса
               request.UserAgent = HttpHelper.RandomChromeUserAgent();

               reqParams["tl"] = toLang;
               reqParams["sl"] = "auto";
               reqParams["client"] = "x";

               string translate = "";

               //Разделяем текст на предложения
               string[] ms = message.Split(new string[] { "." },
StringSplitOptions.RemoveEmptyEntries);

               foreach (string mes in ms)
               {
                   if (mes==" ")
                       continue;

                   reqParams["text"] = mes;
                   //Получаем ответ от сервера
                   string s = request.Get(
                       "http://translate.google.ru/translate_a/t",
reqParams).ToText();

                   //Выдираем из него перевод
                   string ts = s.Substring(":"", "",");

                   if (ts.Contains('"'))
                   {
                       ts = ts.Replace("\", "");
                   }

                   //Склеиваем предложения
                   if (translate != "")
                   {
                       translate = translate + ". " + ts;
                   }
                   else
                   {
                       translate = ts;
                   }
               }
               return translate;
           }
       }

Ну и основной метод, который будет разбирать наши желания.

void MainFunction()
       {
           string text = "";

           for (int i = 0; i < 10; i++)
           {
               try
               {
                   //Получаем содержимое буфера обмена
                   text = Clipboard.GetText();
               }
               catch (Exception e)
               { }
               Thread.Sleep(50);
           }


           //Если сообщение НЕ имеет формат язык::Предложение, то
переводим предложение на заданный язык
           string[] message = text.Split(new string[] { "::" },
StringSplitOptions.None);

           if (message.Length != 2)
           {
               //Если предложение содержит русские буквы
               if (text.Contains('а') || text.Contains('о') ||
text.Contains('и'))
               {
                   //Получаем перевод на стандартный язык
                   string translate = GetTranslate(text,
Settings.Default.ToLang);

                   //Заносим перевод в буфер обмена
                   for (int i = 0; i < 10; i++)
                   {
                       try
                       {
                           Clipboard.SetText(translate);
                           continue;
                       }
                       catch (Exception)
                       {
                       }
                       Thread.Sleep(50);
                   }

                   //Эмулируем нажатие Ctrl+V
                   CtrlVEmul();
               }

               //Если предложение НЕ содержит русские буквы
               else
               {
                   //Переводим его на русский
                   string translate = GetTranslate(text, "ru");

                   //И выводим его согласно настройкам
                   if (Settings.Default.UseBaloon)
                   {
                       notifyIcon1.BalloonTipText = translate;
                       notifyIcon1.ShowBalloonTip(5000);
                   }
                   else
                   {
                       Form2 form = new Form2();
                       form.textBox1.Text = translate;
                       form.Show();
                   }
               }
           }

          //Если сообщение имеет формат язык::Предложение, то переводим предложение на заданный язык
           else
           {

               string mess = message[1];
               string toLang = message[0];
               //Переводим его с заданными параметрами
               string translate = GetTranslate(mess, toLang);

               //Заносим перевод в буфер обмена
               for (int i = 0; i < 10; i++)
               {
                   try
                   {
                       Clipboard.SetText(translate);
                       continue;
                   }
                   catch (Exception)
                   {
                   }
                   Thread.Sleep(50);
               }

               //Эмулируем нажатие Ctrl+V
               CtrlVEmul();
           }

       }

Теперь немного пояснений.
Все методы для работы с буфером обмена лучше помещать в блоки try catch, ибо иногда буфер может быть занят другой операцией, и возникнет исключение, но обычно 50-100 мс хватает для завершения предыдущей операции.
Также я опустил работу с интерфейсом и настройками. Их вы сможете посмотреть в проекте.

Для работы с http запросами я использовал библиотеку xNet, которую вы можете скачать здесь.

Что же у нас получилось?

А получилась у нас программа, которая помогает вам в общении с иностранцами. Если вы выделяете иностранный язык, и нажимаете хоткей, она выведет вам baloon или окно (зависит от настроек) с переводом.
Если вы выделяете русское предложение, то она переведёт его на язык по умолчанию (зависит от настроек), а также, если вам нужно писать сразу нескольким людям на разных языках, вы можете использовать синтаксис язык:: Сообщение, который позволит перевести сообщение с русского на заданный язык.

Краткая инструкция

Выделяете текст, и нажимаете хоткей (по умолчанию Ctrl+Tab), и программа сама сделает, что нужно.
Окно настроек вызывается двойным щелчком на иконку приложения.

Disclaimer: мопед не мой, как и программа. Ее написал уважаемый RoboNET, и попросил меня опубликовать, потому что у него не хватает кармы. Благодарите его, я сам радуюсь программе.

Автор: vvzvlad

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js