Перевод выделенного текста с любого языка на русский

    Хочу поделиться с вами своим лайфхаком.
    В первую очередь он предназначен для людей, которым лень лезть в словарь всякий раз, когда они встречают незнакомое иностранное слово в тексте.

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


    У многих десктопных «словарей» есть функция для перевода выделения, которая как раз и предназначена для того, чтобы «не лазить в словарь», но почему-то у меня всегда были с ней проблемы: не переводит, когда нужно; переводит, когда не нужно и т.д.

    Наверняка, многие из вас видели различные скрипты для использования google translate из консоли, но я считаю этот способ неудобным в большинстве случаев, не смотря на то, что предпочитаю CLI.

    Я подумал, что неплохо было бы иметь возможность быстро переводить выделенный текст или слово и видеть результат, в виде оповещения рабочего стола.
    Остаётся только совместить google translate cli + selections + notifications.

    Решение


    Очень простой интерфейс для отправки уведомлений из консоли предоставляет утилита notify-send, которую можно найти в пакете libnotify-bin. Пример:
    notify-send 'title' 'message'
    Даст следующий результат


    Для получения текущего выделения в X Window System используется утилита xsel.
    xsel -o
    Выведет текущий selection в стандартный поток вывода.

    Шаг 1
    Устанавливаем необходимые пакеты:
    sudo apt-get install libnotify-bin xsel
    Я уверен, что каждый знает, как устанавливать пакеты в своей системе, поэтому не привожу примеры.

    Шаг 2
    Создаём файл с именем seltr и копируем в него следующие 2 строки:

    #!/usr/bin/env bash
    notify-send -u critical "$(xsel -o)" "$(wget -U "Mozilla/5.0" -qO - "http://translate.google.com/translate_a/t?client=t&text=$(xsel -o | sed "s/[\"'<>]//g")&sl=auto&tl=ru" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
    

    Параметр -u critical нужен для того, чтобы оповещение могло перекрывать любые окна.

    Параметры запроса google translate:
    text=$(xsel -o | sed "s/[\"']//g") → исходный текст — текущий selection с вырезанными ' и ".
    sl=auto → автоопределение исходного языка.
    tl=ru → язык результата — русский.

    Шаг 3
    Делаем этот файл исполняемым и перемещаем его в /usr/bin/:
    sudo chmod 777 ./seltr && sudo mv ./seltr /usr/bin/

    Шаг 4
    Теперь остаётся назначить комбинацию клавиш на команду seltr(мой выбор — alt+5). Для этого можно воспользоваться стандартными сердствами, которые предоставляет ваша рабочая среда, либо использовать xbindkeys.

    Как это работает


    • Выделяем какой-нибудь иностранный текст(на любом языке), в любом окне.
    • Нажимаем alt+5.
    • Получаем перевод.

    Немного скриншотов


    Английский

    Немецкий

    Французский

    Украинский

    Китайский


    Плюсы и минусы


    + Возможность переводить фрагменты текста.
    + Требуется минимальное количество действий для получения перевода.
    + Поддержка практически всех языков.
    + Отсутствие необходимости в установке отдельных словарей.

    - Не работает без подключения к интернету.
    - Нет возможности выделить текст перевода.
    *Проверенно в Unity, GNOME2, Xfce4, KDE4.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 87
    • 0
      Эм… Wellcome?
      • +2
        Исправил.
        Засиделся я вчера допоздна просто)
      • +3
        Так вот чего мне не хватало! Спасибо, очень удобная вещь!
        • +4
          Работает! :)
          Спасибо, пригодится

          image
          • 0
            А как оно с гуглопереводчиком связывается? Translate API вроде платный же сейчас?
            • +8
              В скрипте не видно? Тупо представляется браузером.
              • 0
                Упс, точно, спасибо.
                • +1
                  Еще можно воспользоваться альтернативными переводчиками. Все равно высокого качества не достичь.
                  Microsoft с ее колоссальными прибылями не скоро апи прикроет.
              • –8
                … wget -U «Mozilla/5.0»…
                Автор хачерит.
              • 0
                Ещё два минуса (вторая вообще ко всем таким программам, что перепробовал):
                — нет возможности (не описана?) забиндить просто на события выделения мышью только в некоторых прогах
                — нет возможности настроить размер шрифта.

                Объясню юз-кейс: часто читаю книги и статьи с экрана, лёжа на диване и пользуясь беспроводной мышью для листания и т. п. Естественно шрифт/масштаб ставлю покрупнее чем когда сижу за компом, но вот большинство переводчиков/словарей выводят фиксированным шрифтом и их всплывающие окна с переводом даже не реагируют на увеличение шрифта их основного окна.
                • +1
                  Чаще всего переводить приходится текст в браузере, для браузера есть уже специальные расширения, где можно переведенный текст выделить и пр. Ну если вне браузера что-то нужно что-то глянуть, то такой скриптик может и понадобится конечно.
                  • +2
                    Ну мне, например, чаще PDF приходится читать. С английским нет проблем, а вот остальные…
                    • +1
                      Вот так, тупо в лоб, должно работать:
                      echo >> ~/notes.txt && echo >> ~/notes.txt && date >> ~/notes.txt && xsel -o >> ~/notes.txt && echo >> ~/notes.txt && notify-send "Эаметка добавлена" "$(xsel -o)"
                      • 0
                        Сорри, не вам…
                      • НЛО прилетело и опубликовало эту надпись здесь
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • +1
                            Не исполнил, а не заэкранировал :) Используйте &lt; вместо <
                            • НЛО прилетело и опубликовало эту надпись здесь
                              • +2
                                Кнопка code это обычный html тег, специального поведение у него не предусмотрено.
                        • +2
                          Очередное «спасибо» автору, а я сижу теперь и пилю скрипт для использования в качестве общесистемных заметок. Чтобы по хоткею выделенный текст добавлялся в специальный файлик, по типу «добавить в заметки» в Опере.
                          • +2
                            О! Меня такая же мысль посетила.
                            Дату, время, да текст. Скрипт простой выйдет. Доберусь до дома — сделаю.
                            • +4
                              Вот, писал вам, промахнулся: habrahabr.ru/blogs/linux/137215/#comment_4569017
                            • 0
                              У меня в Debian testing c Xfce4 notify-send не заработал :-( ничего не показывает. Покопаюсь в логах…
                              • 0
                                Странно, именно Xfce я проверял на дебиане.
                                • 0
                                  notification daemon запущен?
                                  • 0
                                    не было. Установил xfce4-notifyd — он такой минималистический, что даже затухать по таймауту не умеет. Думаю, менять-ли его на notification-daemon или ну его :-)
                                • 0
                                  Google Translator для краснопанды как-то привычнее. Не особо люблю, когда в уведомлениях что-то всплывает лишнее.
                                  • 0
                                    Для возможности копирования перевода можно использовать:

                                    zenity --info --title=«Титл» --text=«текст»
                                    или загонять перевод сразу в буфер
                                    • 0
                                      использовать например для работы с буфером xclip
                                      • 0
                                        Это понятно, но просто не хочется всякий раз при переводе слова затирать буфер, ведь там может лежать что-то нужное. Если бы это было критически необходимо, я бы лучше сделал 2 команды на разные shortcut-ы:
                                        1 — без записи в буфер.
                                        2 — с записью.
                                        • 0
                                          можно и так, а можно и первый вариант мною предложенный (изменить тип оповещения)
                                          • 0
                                            можно так же вести лог переводов…
                                            • 0
                                              Кстати, у меня были идеи по этому поводу, даже хотел мониторить этот «лог» через conky.
                                              • 0
                                                ну записать не проблема:
                                                echo «text» >> filename
                                                потом парсить файл и выводить в коньки
                                                • 0
                                                  сделать в скрипте вывод и в коньках примерно следующее:
                                                  ${execi 3600 /путь/до/скрипта/наш_скрипт.sh}
                                                  • 0
                                                    Ну, всё дело в том, что я понял, что мне это не нужно)
                                                    • +1
                                                      Хорошо что поняли до того как сделали))) не потеряли время)
                                          • +1
                                            Версия с копированием в буфер перевода:
                                            #!/usr/bin/env bashtext="$(xsel -o)"
                                            translate="$(wget -U "Mozilla/5.0" -qO - "http://translate.google.com/translate_a/t?client=t&text=$(xsel -o | sed "s/[\"'<>]//g")&sl=auto&tl=ru" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
                                            echo $translate | xclip -selection clipboard # Копировать перевод в буфер
                                            notify-send -u critical $text $translate
                                            • +1
                                              Съело энтер:
                                              #!/usr/bin/env bash
                                              text="$(xsel -o)"
                                              ...
                                              • +1
                                                сори, так переводит только первое слово. Выкладываю рабочую версию
                                            • +1
                                              великолепно! спасибо.
                                              • 0
                                                оффтоп, но может кто знает утилиту, аналогичную xsel, но способную достать не только текст, но и картинки/ссылки/другие объекты из выделения?
                                                • 0
                                                  Было бы еще хорошо направление перевода определять по текущей раскладке. Например при английской раскладке — переводить текст на английский, при русской — на русский соответственно и т.д.
                                                  • 0
                                                    Подобное использую под Win translateclient.com/ru/
                                                    • +1
                                                      Супер, спасибо большое!
                                                      • +4
                                                        вдохновившись идеей (мерси за оную кстати, крайне полезная) и необходимостью поисследовать Питон (пардон если код, эмм, неоптимален и излишен), сваял быстрое дополнение для вывода более подробного перевода.

                                                        Запуск выглядит так:

                                                        notify-send -u critical "$(xsel -o)" "$(python /path/to/tran.py "$(xsel -o | sed "s/[\"'<>]//g")")"


                                                        a сам скрипт /path/to/tran.py вот так:

                                                        import httplib, urllib, argparse, re
                                                        
                                                        def argparser():
                                                            parser = argparse.ArgumentParser(description='Instant Translator')
                                                            parser.add_argument('phrase', metavar='p', type=str,
                                                                                help='phrase to translate')
                                                            args = parser.parse_args()
                                                            return args.phrase
                                                        
                                                        def retrieve(host, path):
                                                            request = httplib.HTTPConnection(host)
                                                            request.request("GET", path, "", {'User-Agent' : 'Mozilla/5.0'})
                                                            response = request.getresponse()
                                                            if response.status > 200:
                                                                return '[["{}"],"ERROR"]'.format(response.reason)
                                                            return response.read()
                                                        
                                                        def parse_item(item, depth = 0):
                                                            if type(item) is str:
                                                                if len(item) == 0:
                                                                    return ''
                                                                return "{}{}\n".format("\t" * depth, item)
                                                            result = ''
                                                            for sub_item in item:
                                                                result += parse_item(sub_item, depth + 1)
                                                            return result
                                                        
                                                        phrase = argparser()
                                                        host = 'translate.google.com'
                                                        URL = 'translate_a/t?client=t&sl=auto&tl=ru&' + urllib.urlencode({'text' : phrase})
                                                        
                                                        response = re.sub(',{2,}', ',', retrieve(host, "/" + URL))
                                                        try:
                                                            translated = eval(response)
                                                            result = ''
                                                            for item in translated:
                                                                if type(item) is str:
                                                                    result = "Translation: {} > ru\n\n{}".format(item, result)
                                                                    break
                                                                result += parse_item(item, -1)
                                                            print result
                                                        except RuntimeError as ex:
                                                            print "Something went wrong ({}): {}".format(response, ex)
                                                        


                                                        результат примерно таков:

                                                        image
                                                        • 0
                                                          Я до питона еще не добрался, так что подсказывайте :)
                                                          ImportError: No module named argparse
                                                          • 0
                                                            argparse, похоже, довольно новый класс — но он там «чисто для понта» — начало можно переписать через простые аргуметны комстроки, как

                                                            import httplib, urllib, re, sys
                                                            
                                                            def argparser():
                                                                return sys.argv[1]
                                                            
                                                            def retrieve(host, path):
                                                                request = httplib.HTTPConnection(host)
                                                            ...
                                                            

                                                            • 0
                                                              Сделал так (что было закомментил):

                                                              Traceback (most recent call last):
                                                              File "/home/ploop/tran.py", line 23, in response = re.sub(',{2,}', ',', retrieve(host, "/" + URL))
                                                              File "/usr/lib/python2.6/re.py", line 151, in sub
                                                              return _compile(pattern, 0).sub(repl, string, count)
                                                              TypeError: expected string or buffer
                                                              No summary specified.
                                                              • 0
                                                                в 2.6 как-то format не так работает — переписал с конкатенацией, запустилось на Питоне 2.6.6 (и даже, если переделать ловлю ексепшна в конце как
                                                                except RuntimeError:
                                                                    print "Something went wrong ({})".format(response)

                                                                на 2.4

                                                                попробуйте плиз:

                                                                import httplib, urllib, re, sys
                                                                
                                                                def argparser():
                                                                    return sys.argv[1]
                                                                
                                                                def retrieve(host, path):
                                                                    request = httplib.HTTPConnection(host)
                                                                    request.request("GET", path, "", {'User-Agent' : 'Mozilla/5.0'})
                                                                    response = request.getresponse()
                                                                    if response.status > 200:
                                                                        return '[["{}"],"ERROR"]'.format(response.reason)
                                                                    return response.read()
                                                                
                                                                def parse_item(item, depth = 0):
                                                                    if type(item) is str:
                                                                        if len(item) == 0:
                                                                            return ''
                                                                        return ("\t" * depth) + item + "\n"
                                                                    result = ''
                                                                    for sub_item in item:
                                                                        result += parse_item(sub_item, depth + 1)
                                                                    return result
                                                                
                                                                phrase = argparser()
                                                                host = 'translate.google.com'
                                                                URL = 'translate_a/t?client=t&sl=auto&tl=ru&' + urllib.urlencode({'text' : phrase})
                                                                
                                                                response = re.sub(',{2,}', ',', retrieve(host, "/" + URL))
                                                                try:
                                                                    translated = eval(response)
                                                                    result = ''
                                                                    for item in translated:
                                                                        if type(item) is str:
                                                                            result = "Translation: " + item + " > ru\n\n" + result
                                                                            break
                                                                        result += parse_item(item, -1)
                                                                    print result
                                                                except RuntimeError as ex:
                                                                    print "Something went wrong ({}): {}".format(response, ex)
                                                                • 0
                                                                  Во, это нормально! Спасибо!

                                                                  image
                                                          • 0
                                                            запуск слизнуло — там всё как в оригинальном решении, notify-send -u critical "$(xsel -o)" "$(python /home/halien/devel/my/python/tran.py "$(xsel -o | sed «s/[\»'<>]//g")")"
                                                          • 0
                                                            Для консольного перевода в Linux есть программа dict.
                                                            • 0
                                                              плюс гуглоперевода в том что он переводит и фразы (как — это другой вопрос =)
                                                              • 0
                                                                Да как бы не переводил, но смысл понять можно, особенно когда с китайского переводишь :)
                                                            • 0
                                                              Stardict отлично переводит выделенные слова по нажатию клавиши Win, давно пользуюсь — всё работает
                                                              • +1
                                                                Для CentoOS5 rpm пакет xsel не найден ((
                                                                пришлось собрать (i386) t.co/Gr2OKXeI, (src.rpm) t.co/W0B8asbY
                                                                • 0
                                                                  Идея не плоха, и реализовать не сложно, но, может быть, Вы не пробовали GoldenDict? (не рекламы ради)
                                                                  Сам пробовал разные подобные словари, но у многих есть свои «особенности», остановился на этом варианте, так как работает нормально, словари неплохи (поддерживает много форматов), по нажатию нужной клавиши показывает перевод.
                                                                  • +2
                                                                    > sudo chmod 777 ./seltr
                                                                    Страсти какие а
                                                                    > sudo chmod +x ./seltr
                                                                    не судьба?
                                                                    • 0
                                                                      > sudo chmod +x ./seltr

                                                                      Не на всех системах отработает одинаково ;)
                                                                      Лучше написать chmod a+x ./seltr
                                                                    • 0
                                                                      В качестве альтернативы описанному методу — GoldenDict по хоткею выдает всплывающее окно с переводом. В нем отсутствуют указанные минусы.
                                                                      Правда, его нужно предварительно настроить (как минимум, добавить необходимые словари). Зато к нему можно подключать множество форматов словарей (в том числе от Lingvo, и в том числе многие онлайновые). Имхо, лучший словарь из существующих под Linux — удобный, функциональный и стабильный.
                                                                      • 0
                                                                        Сорри, вкладка со статьей долгое время была открыта и комментария выше (через один от моего) не видел.
                                                                        • 0
                                                                          Шрифт у этого всплывающего окна дюже мелкий :(
                                                                          • +2
                                                                            В основном окне «Ctrl»+«+» несколько раз (либо в меню «View — Zoom — Zoom in», либо соответствующие значки на панели) — и проблемы больше нет ;)
                                                                            • 0
                                                                              Хм, пробовал буквально неделю назад, когда в очередной раз выбирал переводчик — не работало. И сейчас как-то не сразу сработало. Только когда последний раз решил проверить, чтобы точно написать, что это было ожидаемым поведением, но оно не реализовано.
                                                                        • 0
                                                                          Спасибо за метод, на lxde под ubutu работает
                                                                          • +1
                                                                            Подскажите, какой шрифт используется в оповещениях, внезапно очень нравится.
                                                                            • 0
                                                                              мне кажется что эта ссылка поможет ответить на ваш вопрос — font.ubuntu.com/
                                                                            • 0
                                                                              Текст можно скопировать из уведомления?
                                                                              • 0
                                                                                В ubuntu — нет. При наведении мышью уведомление размазывается и становится прозрачным, чтобы за ним был доступен интерфейс.
                                                                                Обратите внимание на мой скриншот на несколько постов выше — приходится намеренно выделять область больше, чтобы не размазалось, ближе мышь не подведёшь, а делать полный скриншот экрана и редактировать лень.
                                                                              • 0
                                                                                Ubuntu + GNOME Shell, полёт нормальный. Спасибо!
                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                    • +1
                                                                                      "… возможность перевода целого предложения.." — в этом-то и преимущество.
                                                                                    • 0
                                                                                      Если сделать два подряд перевода, то вторая нотификация ждет пока закроется первая. Как то можно сделать, что бы они не ждали а выводились подряд, несколькими штуками?
                                                                                      • 0
                                                                                        Прикрутил, спасибо! Вот только интересно: если излишне часто пользоваться, Гугл не забанит? :)
                                                                                        • 0
                                                                                          В LibreOffice не удается получить выделенную фразу.
                                                                                          text="$(xsel -o)"
                                                                                          Xsel возвращает только первое слово или обрывки фраз. Кто-то знает как решить проблему?
                                                                                          • +2
                                                                                            Здравствуйте друзья, вашему вниманию представляю код на руби, формирующий файл словаря, чтобы повторять переводимые слова перед сном. Код также кеширует все запросы в гугл (это к вопросу а не забанит ли гугл). Также имеется установщик.
                                                                                            github.com/newmen/gnome_google_translator
                                                                                            Может быть, кому-нибудь ещё понадобятся эти «навороты»… ;)
                                                                                            • +1
                                                                                              Задумка интересная с повторением :) А насчёт самой программы — в сторону gconftool-2 не смотрели? по-моему проще и логичнее через неё работать, чем xml писать и gnome перезапускать :)

                                                                                            • 0
                                                                                              Признаться, к сожалению так и не нашёл порядочной документации, в которой рассказывалось бы о том, как таки правильно создавать все эти директории и файлы. В официальной документации говорится (http://projects.gnome.org/gconf/), что всё должно быть так то и так-то, но с Gnome3, оно как-то не совсем так. Поэтому я пошёл по пути наименьшего сопротивления.
                                                                                              Но вообще, спасибо за проявленный интерес. Может быть когда-нибудь я дорасту до gconftool-2. (=
                                                                                              • 0
                                                                                                Криво постанул, немного не туда. Прошу прощения.
                                                                                              • +1
                                                                                                Модифицировал скрипт, теперь он умеет:
                                                                                                — конвертировать не только выделенный текст но и последнее набранное слово (по триггеру Ctrl+Shift_Left);
                                                                                                — при переключении раскладки автоматом переключает язык ввода (укажите свою комбинацию клавиш в последней строке);
                                                                                                Тригеры клавиш переписал на xdotool — работает более шустро и стабильно.
                                                                                                Сам скрипт.
                                                                                                • 0
                                                                                                  И еще — криво работает со скайпом, как исправить не знаю.
                                                                                                • 0
                                                                                                  уже не работает :(
                                                                                                  • 0
                                                                                                    Так гугл разве денег не хочет за API переводчика?
                                                                                                    В принципе в исходном скрипте легко меняется на API переводчика Яндекса.
                                                                                                    • +1
                                                                                                      работает тока URL изменился

                                                                                                      #!/usr/bin/env bash
                                                                                                      notify-send -u critical "$(xsel -o)" "$(wget -U "Mozilla/5.0" -qO - "https://translate.google.com/translate_a/single?client=t&sl=auto&tl=ru&hl=ru&dt=bd&dt=ex&dt=ld&dt=md&dt=qc&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&otf=2&srcrom=1&ssel=0&tsel=0&kc=3&tk=519592|450115&q=$(xsel -o | sed "s/[\"'<>]//g")&sl=auto&tl=ru" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
                                                                                                      
                                                                                                      • +1
                                                                                                        И продолжение :)
                                                                                                        habrahabr.ru/post/256063

                                                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.