Теперь вместо скучного, а иногда медленного, а иногда такого ярко-белого нового таба с лишней информацией пишу в терминале 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
Комментарии (32)
EuroElessar
27.06.2015 05:21+13<зануда>
- Составлять url слиянием строк, серьезно?
- Разбирать json руками, серьезно?
- Делать бесконечный рекурсивный вызов, серьезно?
- Игнорировать все аргументы командной строки, кроме первого, серьезно?
- Выкладывать это на Хабр, серьезно?
007 Автор
27.06.2015 08:411) Ведь в таком маленьком коде проще слиять строки, разве нет? Каковы ваши аргументы против слияния?
2) Разбирать json руками — опять же — зачем усложнять?
3) Рекурсия не бесконечна, вызов самого себя происходит только если вернулось то же что ввел пользователь. Можно было конечно сразу определять язык, но это было бы чуть больше кода и все-равно два запроса к серверу.
4) Какие еще нужны аргументы командной строки?
5) Почему выложил на Хабр — сам искал такое решение, в том числе и на Хабре.EuroElessar
27.06.2015 08:58+91) Ведь в таком маленьком коде проще слиять строки, разве нет? Каковы ваши аргументы против слияния?
trans "R&D"
Ожидание — «НИОКР», реальность — «Р».
2) Разбирать json руками — опять же — зачем усложнять?
JSON экранирует ряд символов, например ", \n и т.д., поэтому нужен нормальный парсер.
3) Рекурсия не бесконечна, вызов самого себя происходит только если вернулось то же что ввел пользователь. Можно было конечно сразу определять язык, но это было бы чуть больше кода и все-равно два запроса к серверу.
trans "123"
4) Какие еще нужны аргументы командной строки?
Joiner.on(" ").join(args)
5) Почему выложил на Хабр — сам искал такое решение, в том числе и на Хабре.
Заранее извиняюсь, но на Хабр имеет смысл выкладывать нетривиальные решения, а не суповой набор из багов уровня средней школы.007 Автор
27.06.2015 10:53ок, спасибо за обратную связь, обновил:
1) Теперь можно делать trans «R&D»
2) Я не буду в консоли вводить что-то со слешем для перевода — не хочу превращать .class-файл в .jar-файл используя например gson для парсинга.
3) Теперь вызов метода самого себя происходит лишь единожды.
4) Joiner.on(" ").join(args) не понимаю, что это?
5) Мне очень стыдно, но уже 13 человек добавили в избранное :)EuroElessar
27.06.2015 11:43+12) Я не буду в консоли вводить что-то со слешем для перевода — не хочу превращать .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.
bockra
27.06.2015 11:12+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 '}
007 Автор
27.06.2015 11:47-4Когда я пробовал делать 'curl $link' то получал {«code»:501,«message»:«The specified translation direction is not supported»}
Да, надо было просто в кавычки поставить адрес… Тогда бы и не писал на Яве. Хотя я читал кто-то не любит ставить curl, а jre может быть установлен :)kloppspb
27.06.2015 15:35>я читал кто-то не любит ставить curl, а jre может быть установлен
А может и наоборот. Но wget должон быть :) В общем, всё тут, и в комментах особенно: habrahabr.ru/post/256063grossws
30.06.2015 05:08Это зависит от системы. Иногда есть и curl, и wget, иногда что-то одно, иногда ни того, ни другого.
ruslanys
27.06.2015 12:37+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)
Вы были бы молодцом, если бы подобное решение осталось в кулуарах Вашего ПК.
Не хочу показаться занудой, но до статьи на хабре — это точно не дотягивает.
MaximChistov
27.06.2015 22:25-1String 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;
Ужас какой )
aNNiMON
27.06.2015 23:02Назовите пост «Яндекс-Перевод в терминале через Java в 30 строк» и часть претензий отпадёт :)
hell0w0rd
28.06.2015 02:43Затронули больную, за последнее время, для меня тему, давно хотел подобное написать. Java нет у меня, зато везде есть node.js.
github.com/nkt/yandex.translate — быстренько накидал реализацию.007 Автор
28.06.2015 14:15yandex-translate hello | say # It's talking!
У вас она еще и говорит?hell0w0rd
28.06.2015 14:32Сама программа нет. Но в osx есть программа say (думаю под linux есть аналоги), а оператор | перенаправляет stdout в stdin следующей программы. Таким образом можно воспроизводить переводы.
kloppspb
28.06.2015 15:27А аналогов xsel и notify-send в osx нет? Просто неудобно же вводить слова руками в консоли, и в консоли же получать результат (если не перенаправлять куда-то, конечно).
grossws
30.06.2015 05:03можно без ковычек писать сразу несколько слов. Так и не смог добиться перевода нескольких слов с амперсантом, но и халера с ним.
Кроме переводчика стоит добавить в арсенал aspell/hunspell. Можно:
— создавать дочерние процессы с помощью java.lang.Process, получить stdin и stdout и обернуть aspell/hunspell,
— использовать только первый аргумент (проверять орфографию по одному слову же удобнее),
— добавить в код константу, соответствующую epoch time через N часов и сравниватьSystem.currentTimeMillis()/1000
с этой константой и падать, если она оказалась меньше (чтоб периодически перекомпилировать эту обёртку.
tobilko
что-то новенькое, спасибо
а почему яндекс, а не гугл?
007 Автор
Мне кажется en-ru/ru-en переводится лучше Яндексом, да и пинг наверное до сервера Яндекса меньше :)
Pryada
Если кому-то интересно, то с китайского на русский лучше всего (по моим тестам) переводит Бинг.
Хотелось бы поставить Яндекс на второе место, но у него есть фатальные ошибки перевода (в моих кусках перевода), о которых я давно сообщил в тех поддержку, мне ответили, но до сих пор нет изменений. Наверное через какое-то время Яндекс будет на втором месте, а на третьем останется Гугл.
kloppspb
Основная проблема Яндеса в том, что что сервис перевода и сервис словаря — это два отдельных сервиса. Сравните, например, выдачу Яндекса и Гугла на «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»).
drwatson32
Я раньше пользовался api от Google, а вчера обнаружил, что Google деньги берет за Translate.
А на месте автора я бы API Key бы убрал.
И проще наверное было создать javascript bookmark в Хроме.
kloppspb
Не берут, просто другой URL нужен. Всё это уже пережёвывалось здесь: habrahabr.ru/post/256063
drwatson32
Берут, берут.
https://cloud.google.com/translate/v2/pricing
А то что вы привели, это не вызов API, а неправомерное использование чужого сервиса, на мой взгляд.
Для дома поиграться может и сойдет, но в прод не вариант.
kloppspb
Для прод можно и платить, тем более что это вообще уже забота конечного юзера. Тут же явно домашние наколенные поделки обсуждаются.
В любом случае пока у Яндекса не объединены словари и перевод, гугловский вариант куда полезней. Если б там можно было платить за фактическое количество знаков — почему бы и не? Но к миллиону даже близко не подберусь :)