Яндекс-Перевод в терминале через Java

    Используя API переводчика написал для себя простую программу для перевода слов и фраз, и чтобы из любого места работало. Хотел использовать curl, но непонятно почему получал ошибку что такого языка нет.

    Теперь вместо скучного, а иногда медленного, а иногда такого ярко-белого нового таба с лишней информацией пишу в терминале trans hello и получаю перевод на русский, а если trans привет — на английский. Разумеется можно вводить и фразы, в кавычках. Работает быстренько.

    import javax.net.ssl.HttpsURLConnection;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.net.URLEncoder;
    
    public class YandexTranslate {
    	private static int i = 0;
    	public static void main(String[] args) throws IOException {
    		System.out.println(translate("ru", args[0]));
    	}
    
    	private static String translate(String lang, String input) throws IOException {
    		String urlStr = "https://translate.yandex.net/api/v1.5/tr.json/translate?key=trnsl.1.1.20150627T071448Z.117dacaac1e63b79.6b1b4bb84635161fcd400dace9fb2220d6f344ef";
    		URL urlObj = new URL(urlStr);
    		HttpsURLConnection connection = (HttpsURLConnection)urlObj.openConnection();
    		connection.setRequestMethod("POST");
    		connection.setDoOutput(true);
    		DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
    		dataOutputStream.writeBytes("text=" + URLEncoder.encode(input, "UTF-8") + "&lang=" + lang);
    
    		InputStream response = connection.getInputStream();
    		String json = new java.util.Scanner(response).nextLine();
    		int start = json.indexOf("[");
    		int end = json.indexOf("]");
    		String translated = json.substring(start + 2, end - 1);
    		i++;
    		if (translated.equals(input) && i < 2) {
    			// if return equal of entered text - we need change direction of translation
    			return translate("en", input);
    		} else return translated;
    	}
    }
    
    

    Чтобы перевод работал в любой директории, нужно в /usr/bin положить .class-файл и trans.sh для его вызова:
    #!/bin/bash
    if [ $# -eq 0 ]
      then
        echo "Enter text for translate"
        exit 1;
    fi
    java -classpath /usr/bin/ YandexTranslate "$1"
    

    И сделать его исполняемым: sudo chmod +x trans.sh

    Если вы вместо перевода начнете получать сообщение о том что ключ кончился, или мало-ли-что — тут можно получить новый кей — вставьте его куда надо в Java-коде, после чего откомпилируйте (javac YandexTranslate.java) и скопируйте с заменой на /usr/bin.

    Также этот код доступен на Гитхабе.

    Также пользователи Firefox могут воспользоваться моим экстеншеном-переводчиком — он интегрирован в контекстное меню, быстрый-минималистичный и не оказывает влияния на DOM, после установки сразу работает и не требует рестарта браузера. На данный момент единственный Яндекс-переводчик для текущих версий Firefox.

    UPD: Такие штуки лучше делать сразу на баше, но сразу у меня не получилось, но после того как bockra показал свой скрипт, я его дописал — чтобы не надо было указывать направление перевода, и можно без ковычек писать сразу несколько слов. Так и не смог добиться перевода нескольких слов с амперсантом, но и халера с ним.
    #!/bin/bash
    #
    # simple console util for translation text to any language using Yandex Translate API
    # use: trans 'call me, baby
    # will return translation of a phrase to ru or en language
    # more example at http://api.yandex.ru/translate/
    #
    
    input=${@//[&]/%26}
    link='https://translate.yandex.net/api/v1.5/tr.json/translate?key=trnsl.1.1.20150627T071448Z.117dacaac1e63b79.6b1b4bb84635161fcd400dace9fb2220d6f344ef&lang='
    function translate() {
    	translated=$(curl -s "$link$key&lang=$1&text=$input" | awk -F'"' {' print $10 '})
    }
    
    translate "ru"
    if [ "$translated" == "$input" ]
    	then
    		translate "en"
    fi
    echo $translated
    
    Share post

    Similar posts

    Comments 32

      0
      что-то новенькое, спасибо

      а почему яндекс, а не гугл?
        +1
        Мне кажется en-ru/ru-en переводится лучше Яндексом, да и пинг наверное до сервера Яндекса меньше :)
          0
          Если кому-то интересно, то с китайского на русский лучше всего (по моим тестам) переводит Бинг.
          Хотелось бы поставить Яндекс на второе место, но у него есть фатальные ошибки перевода (в моих кусках перевода), о которых я давно сообщил в тех поддержку, мне ответили, но до сих пор нет изменений. Наверное через какое-то время Яндекс будет на втором месте, а на третьем останется Гугл.
            0
            Основная проблема Яндеса в том, что что сервис перевода и сервис словаря — это два отдельных сервиса. Сравните, например, выдачу Яндекса и Гугла на «fox» или «Quick brown fox jumps over the lazy dog». У Гугла побогаче будет:

            ato.su/resizer/i/5/1/97a28d88.png
            ato.su/resizer/i/6/7/57cd1b6f.png

            У Яндекса нечто подобное можно получить только при обращении к словарям, да и то только в первом случае («fox»).
            0
            Я раньше пользовался api от Google, а вчера обнаружил, что Google деньги берет за Translate.
            А на месте автора я бы API Key бы убрал.
            И проще наверное было создать javascript bookmark в Хроме.
              0
              Не берут, просто другой URL нужен. Всё это уже пережёвывалось здесь: habrahabr.ru/post/256063
                +1
                Берут, берут.
                https://cloud.google.com/translate/v2/pricing
                А то что вы привели, это не вызов API, а неправомерное использование чужого сервиса, на мой взгляд.
                Для дома поиграться может и сойдет, но в прод не вариант.
                  0
                  Для прод можно и платить, тем более что это вообще уже забота конечного юзера. Тут же явно домашние наколенные поделки обсуждаются.

                  В любом случае пока у Яндекса не объединены словари и перевод, гугловский вариант куда полезней. Если б там можно было платить за фактическое количество знаков — почему бы и не? Но к миллиону даже близко не подберусь :)
            +13
            <зануда>
            • Составлять url слиянием строк, серьезно?
            • Разбирать json руками, серьезно?
            • Делать бесконечный рекурсивный вызов, серьезно?
            • Игнорировать все аргументы командной строки, кроме первого, серьезно?
            • Выкладывать это на Хабр, серьезно?
            </зануда>
              0
              1) Ведь в таком маленьком коде проще слиять строки, разве нет? Каковы ваши аргументы против слияния?
              2) Разбирать json руками — опять же — зачем усложнять?
              3) Рекурсия не бесконечна, вызов самого себя происходит только если вернулось то же что ввел пользователь. Можно было конечно сразу определять язык, но это было бы чуть больше кода и все-равно два запроса к серверу.
              4) Какие еще нужны аргументы командной строки?
              5) Почему выложил на Хабр — сам искал такое решение, в том числе и на Хабре.
                +9
                1) Ведь в таком маленьком коде проще слиять строки, разве нет? Каковы ваши аргументы против слияния?

                trans "R&D"

                Ожидание — «НИОКР», реальность — «Р».
                2) Разбирать json руками — опять же — зачем усложнять?

                JSON экранирует ряд символов, например ", \n и т.д., поэтому нужен нормальный парсер.
                3) Рекурсия не бесконечна, вызов самого себя происходит только если вернулось то же что ввел пользователь. Можно было конечно сразу определять язык, но это было бы чуть больше кода и все-равно два запроса к серверу.

                trans "123"

                4) Какие еще нужны аргументы командной строки?

                Joiner.on(" ").join(args)

                5) Почему выложил на Хабр — сам искал такое решение, в том числе и на Хабре.

                Заранее извиняюсь, но на Хабр имеет смысл выкладывать нетривиальные решения, а не суповой набор из багов уровня средней школы.
                  0
                  ок, спасибо за обратную связь, обновил:
                  1) Теперь можно делать trans «R&D»
                  2) Я не буду в консоли вводить что-то со слешем для перевода — не хочу превращать .class-файл в .jar-файл используя например gson для парсинга.
                  3) Теперь вызов метода самого себя происходит лишь единожды.
                  4) Joiner.on(" ").join(args) не понимаю, что это?
                  5) Мне очень стыдно, но уже 13 человек добавили в избранное :)
                    +1
                    2) Я не буду в консоли вводить что-то со слешем для перевода — не хочу превращать .class-файл в .jar-файл используя например gson для парсинга.

                    Замечательный подход, далеко пойдете :)
                    3) Теперь вызов метода самого себя происходит лишь единожды.

                    private static int i = 0;
                    /* ... */
                    i++;
                    if (translated.equals(input) && i < 2) {
                        // if return equal of entered text - we need change direction of translation
                        return translate("en", input);
                    } else return translated;
                    

                    А здесь, уважаемые зрители, яркий пример kostyl'-driven development.
                    4) Joiner.on(" ").join(args) не понимаю, что это?

                    А это возможность делать trans many words without escaping.
                    Если быть еще точнее, то это, например, com.google.common.base.Joiner.
              +4
              А зачем тут джава-то?
              Может не так экранировали ссылку?

              Вот мой помощник в переводе :)
              #!/bin/bash
              #
              # simple console util for translation text to any language using Yandex Translate API
              # use: Translate.sh ru 'call me, baby'
              # will return translation of a phrase to ru language
              # more example at http://api.yandex.ru/translate/
              #
              
              to=$1
              text=$2
              
              link='https://translate.yandex.net/api/v1.5/tr.json/translate?key='
              key='-- key from http://api.yandex.ru/key/keyslist.xml --'
              
              curl -s "$link$key&lang=$to&text=$text" | awk -F'"' {' print $10 '}
              
                –4
                Когда я пробовал делать 'curl $link' то получал {«code»:501,«message»:«The specified translation direction is not supported»}
                Да, надо было просто в кавычки поставить адрес… Тогда бы и не писал на Яве. Хотя я читал кто-то не любит ставить curl, а jre может быть установлен :)
                  0
                  >я читал кто-то не любит ставить curl, а jre может быть установлен

                  А может и наоборот. Но wget должон быть :) В общем, всё тут, и в комментах особенно: habrahabr.ru/post/256063
                    0
                    Это зависит от системы. Иногда есть и curl, и wget, иногда что-то одно, иногда ни того, ни другого.
                      0
                      А поставить религия не позволяет, ага. Но на java качалки писать и велосипеды изобретать — это запросто :-)
                        0
                        Вы меня с автором этой «статьи» не путаете?
                          0
                          Ну не поставил тег irony, каюсь ;-)
                  +1
                  Хотя тест Руслана на «R&D» тоже не прошел :)
                    0
                    sudo apt-get install gridsite-clients && man urlencode
                    0
                    Дописал ваш скрипт и добавил в пост.
                    +8
                    Во-первых — баян.
                    Во-вторых — зачем здесь Ява?! Я, конечно, Java разработчик, обожаю этот язык, но для такой тривиальной задачи такой инструмент — крайне не подходящее решение на мой взгляд. Ребята решали подобную задачу средствами Bash. Ну максимум — Питон, как-никак скриптовый язык, не требующий никакой компиляции.
                    В-третьих — крайне неуклюжая, «сырая» реализация. Как уже говорили, работа с JSON, например. Наверное, будет открытием, но в JSR 353 (https://jcp.org/en/jsr/detail?id=353) была введена поддержка JSON парсера. А это значит, что можно и без подключения сторонних библиотек реализовать гармоничное решение. (http://www.oracle.com/technetwork/articles/java/json-1973242.html)

                    Вы были бы молодцом, если бы подобное решение осталось в кулуарах Вашего ПК.
                    Не хочу показаться занудой, но до статьи на хабре — это точно не дотягивает.
                      –1
                       String json = new java.util.Scanner(response).nextLine();
                              int start = json.indexOf("[");
                              int end = json.indexOf("]");
                              String translated = json.substring(start + 2, end - 1);
                              i++;
                              if (translated.equals(input) && i < 2) {
                                  // if return equal of entered text - we need change direction of translation
                                  return translate("en", input);
                              } else return translated;
                      

                      Ужас какой )
                        0
                        Назовите пост «Яндекс-Перевод в терминале через Java в 30 строк» и часть претензий отпадёт :)
                          0
                          Затронули больную, за последнее время, для меня тему, давно хотел подобное написать. Java нет у меня, зато везде есть node.js.
                          github.com/nkt/yandex.translate — быстренько накидал реализацию.
                            0
                            yandex-translate hello | say # It's talking!

                            У вас она еще и говорит?
                              0
                              Сама программа нет. Но в osx есть программа say (думаю под linux есть аналоги), а оператор | перенаправляет stdout в stdin следующей программы. Таким образом можно воспроизводить переводы.
                                0
                                А аналогов xsel и notify-send в osx нет? Просто неудобно же вводить слова руками в консоли, и в консоли же получать результат (если не перенаправлять куда-то, конечно).
                                  0
                                  Вы меня вдохновили сделать два скрипта для баша для TTS через Яндекс и Гугл :)

                                  Теперь пишу в консоли
                                  tts-y hello world
                                  или
                                  tts-g hello world
                                  И слушаю произношение :)
                              0
                              можно без ковычек писать сразу несколько слов. Так и не смог добиться перевода нескольких слов с амперсантом, но и халера с ним.
                              Кроме переводчика стоит добавить в арсенал aspell/hunspell. Можно:
                              — создавать дочерние процессы с помощью java.lang.Process, получить stdin и stdout и обернуть aspell/hunspell,
                              — использовать только первый аргумент (проверять орфографию по одному слову же удобнее),
                              — добавить в код константу, соответствующую epoch time через N часов и сравнивать System.currentTimeMillis()/1000 с этой константой и падать, если она оказалась меньше (чтоб периодически перекомпилировать эту обёртку.

                              Only users with full accounts can post comments. Log in, please.