Пишем консольный переводчик для *nix на Python

Здравствуйте. Наверняка Вам встречались незнакомые английские слова или фразы, и Вам постоянно приходилось лезть в браузер, открывать сайт с онлайн переводчиком и переводить, при этом думая как хорошо было бы, если это было реализовано бы в виде софта под *nix.

Под операционные системы семейства Windows существует уже давно много переводчиков, а вот для unix систем, лично я, пока не встречал.

На старт!


И так начнём, писать мы будем на языке программирования python. Он есть практически во всех *nix системах.
Для написания переводчика, нам понадобится одна библиотека не входящая в стандартный набор python'a — simplejson. Скачать её можно на официальном сайте.

После того как скачали, можете либо установить в систему, либо положить папку simplesjon расположенную в архиве рядом с нашим исполняемым python файлом.

Раздобыли simplejson? Теперь создадим файл translate.py и перейдём от теории к практике.
Программировать можно в чём угодно, хоть в nano, но я предпочитаю редактор Geany.

У нас должна получится вот такая структура проекта:
  • ..
  • simplejson/
    • __init__.py
    • decoder.py
    • encoder.py
    • scanner.py
    • tool.py

  • translate.py


Библиотеку мы трогать не будем, поэтому переходим к файлу translate.py:
Делаем импорт необходимых нам библиотек:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import httplib 
import urllib2
import simplejson as json
import sys


Самая главная и единственная функция

user_agent = 'Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.0.4) Gecko/2008120916 Gentoo Firefox/3.0.4' #на всякий случай меняем User-Agent маскируясь под браузер

def translate_handler(lang,body):
	body = ' '.join(body)
	if len(sys.argv)<2: print u'$ en/ru text'; return # проверка на количество аргументов
	try:
		if lang=='ru': req = urllib2.Request(unicode(u'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s' % (urllib2.quote(body),u'en%7Cru')),'utf-8') # если в аргументе указан перевод на русский язык, формируем нехитрый запрос гуглу
		elif lang=='en': req = urllib2.Request(unicode(u'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s' % (urllib2.quote(body),u'ru%7Cen')),'utf-8') # тоже самое и с английским
		elif lang=='en': print str(unicode(body,'utf-8'))
		else: print u'Available languages: en, ru'; return
		req.add_header('User-Agent',user_agent) # здесь меняем в заголовке User-Agent
		reqf = urllib2.urlopen(req) # отправляем запрос
	except urllib2.HTTPError, e: print str(e)
	answ=json.load(reqf) # читаем через json полученный результат
	if answ['responseStatus']!=200: print str(answ['responseStatus'])+': '+answ['responseDetails'] # на случай если гуглу стало плохо и перевести не удалось
	elif answ['responseData']: print answ['responseData']['translatedText']
	else: print u'unknown error >_<'
		
translate_handler(sys.argv[1],sys.argv[2:]) # вызов функции



На всякий случай опубликую весь код целиком:


#!/usr/bin/evn python
# -*- coding: utf-8 -*-

import httplib
import urllib2
import simplejson as json
import sys

user_agent = 'Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.0.4) Gecko/2008120916 Gentoo Firefox/3.0.4'

def translate_handler(lang,body):
	body = ' '.join(body)
	if len(sys.argv)<2: print u'$ en/ru text'; return
	try:
		if lang=='ru': req = urllib2.Request(unicode(u'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s' % (urllib2.quote(body),u'en%7Cru')),'utf-8')
		elif lang=='en': req = urllib2.Request(unicode(u'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s' % (urllib2.quote(body),u'ru%7Cen')),'utf-8')
		elif lang=='en': print str(unicode(body,'utf-8'))
		else: print u'Available languages: en, ru'; return
		req.add_header('User-Agent',user_agent)
		reqf = urllib2.urlopen(req)
	except urllib2.HTTPError, e: print str(e)
	answ=json.load(reqf)
	if answ['responseStatus']!=200: print str(answ['responseStatus'])+': '+answ['responseDetails']
	elif answ['responseData']: print answ['responseData']['translatedText']
	else: print u'unknown error >_<'
		
translate_handler(sys.argv[1],sys.argv[2:])



На этом разработка программной части закончена. Можете проверить и запустить файл таким образом:
python translate.py en привет — переведёт текст на английский
python translate.py ru hello — переведёт текст на русский

«Но это же не удобно» — скажите вы. Действительно, набирать такую большую команду запуска в консоли действительно затруднительно.

Решение


Возьмём папку с проектом и переместим её какую нибудь директорию например в /usr/share
и получится у нас /usr/share/translate

Затем в вашем BINDIR'e (у меня на debian — /usr/bin) создадим 2 файла, en и ru:

Сожержимое файла /usr/bin/ru:

python /usr/share/translate/translate.py ru $$*
Сожержимое файла /usr/bin/en:

python /usr/share/translate/translate.py en $$*

Итого:


В нашей системе теперь появилось 2 новые команды: en и ru соответственно.
Теперь пользоваться стало на много удобнее: en текст для перевода или же ru текст для перевода

Можно заюзать еще вот так:
ferym@ferym-desktop:~$ ping -c 3 ya.ru | xargs ru $*
 PING ya.ru (77.88.21.3) 56 (84) байт данных. 64 байт из www.yandex.ru (77.88.21.3): icmp_seq = 1 TTL = 60 время = 6,20 мс 64 байт от www.yandex.ru (77.88.21.3): 2 = icmp_seq TTL = 60 время = 4,10 мс 64 байт с www.yandex.ru (77.88.21.3): icmp_seq = 3 TTL = 60 время = 3,78 мс --- ya.ru пинг статистика --- 3 пакеты, передаваемые, 3 получили, 0% потери пакетов, время 2001ms RTT мин / ср / макс / mdev = 3.787/4.698/6.207/1.074 мс


Минусы:

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

Спасибо за внимание.

UPD: Я никому не навязываю своё мнение, я показал как реализовал это я
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 26
  • 0
    Всё это, конечно, хорошо, но простите, это уже который по счёту?
    • 0
      Какой по счёту не знаю, но лично я писал его для себя, и никому свою точку зрения не навязываю, я просто показываю свой пример реализации.
    • +5
      Под операционные системы семейства Windows существует уже давно много переводчиков
      Ога, целый один вменяемый переводчик, и тот переводит достаточно убого по сравнению с онлайн-сервисами.

      весь перевод осуществляется через интернет. Но в век интернет-технологий, когда интернет в каждом доме — я думаю это не проблема.
      Может хотя бы 1 декабря этого года люди наконец поймут, что привязка на облачные сервисы с закрытым исходным кодом это зло? Ну или хотя бы шапки страниц с описанием API читать научатся.
      • +4
        > Действительно, набирать такую большую команду запуска в консоли действительно затруднительно.

        echo 'alias ru="python ~/src/translate/translate.py ru"' >> .bashrc
        • –1
          Посмотрите в своем репозитории и вы обнаружите значительное количество разнообразных словарей и переводчиков, причем со своими базами, без необходимости в интернет-подключении.
          Да, чем вам не угодила встроенная библиотека json?
        • 0
          > при этом думая как хорошо было бы, если это было реализовано бы в виде софта под *nix.

          У меня есть подозрение, что автор опоздал со статьёй лет так на 5. А то и больше.
          • 0
            Автор молодец. Эта статья очень поможет новичкам, так как пример, мне кажется, заставит писателя продолжить ) К простенькому скрипту можно прикрутить много чего. Ну лучше с такой статьи начать чем с хеловорлда) Или не так, хороша стать тем, кому хелловорлд не помог влиться )
            • +2
              Абсолютно плюсую. Человек старается и двигается в правильном направлении. Свой велосипед как-то ближе к телу.
            • 0
              Стоит прикрутить автовыбор языка, тем более, что это делается элементарно
              • +7
                Пара советов:
                1) Прочтите и соблюдайте PEP8 (http://www.python.org/dev/peps/pep-0008/)
                2) Зачем вам прикидыватся браузером?
                3) Зачем так много кода завернуто в try? HTTPError бросает только urlopen.
                4) Забыли закрыть соединение. Вместо try/catch заверните urllib в contextmanager
                5) Как уже сказали, воспользуйтесь стандартной json-библиотекой.
                6) Не храните сторониие библиотеки в одной папке со своим кодом. На досуге почитайте про distutils, virtualenv и pip.
                • +4
                  Да, и еще. Заголовок скрипта замените на
                  #!/usr/bin/env python

                  Python не обязан находится в /usr/bin
                • 0
                  В обёртке (/usr/bin/ru) лучше юзать "$@" вместо $*
                  • +1
                    А, еще кроме «en» можно дополнительно сделать аналогичную подстановку «англ».
                    Это позволит избежать переключения раскладки при наборе команды.
                    То есть набирать можно будет так:

                    англ привет

                    Предвидя возражение желающих минуснуть этот коммент, что типа, все равно раскладку переключать придется, и типа нефиг выпендриваться, отвечу:
                    Если возникает необходимость не одно слово проверять, а несколько, и причем не сразу, то раскладку между несколькими командами и вовсе не нужно будет ни разу переключать.

                    англ привет

                    англ пока

                    Если же подстановка «англ» кому-то (кто очень часто будет этой командой пользоваться) покажется чересчур длинной, по сравнению с тем же «en», то также дополнительно можно заюзать подстановку «ё».
                    Эта буква очень удобно расположена с края клавиатуры и позволит сэкономить на несколько нажатиях.

                    ё привет

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

                    en ghbdtn

                    преобразовывать в скорректированный аналог:

                    en привет

                    А, еще можно кэшировать результаты (чтоб при полном совпадении запроса не делать лишних обращений в Интернет).
                    • 0
                      имхо, проще научится быстро печатать.
                      и никаких проблем с изменением раскладки не будет ;)
                      • 0
                        ну так реализуй :)
                      • 0
                        Я для себя сделал просто bat-ник, который grep-ает словарик.

                        @ECHO OFF
                        if "%1" == "" (
                        echo "usage: dic "
                        ) else (
                        @ECHO ON
                        grep %1 d:\dic\enru.txt
                        @ECHO OFF
                        )
                        • 0
                          Прошу прощения за хабрапарсер.
                        • +1
                          Статья ценна уроком по Python, а так — # aptitude install dictd

                          Под него много словарей (я пользовался английским и эсперанто) и клиентов, консольных и гуевых, довольно мощные утилиты конвертации словарей в формат dict.

                          Доступ в интернет не обязателен, если сервер стоит у вас на локалке, но есть приятный момент — в сети существуют рабочие сервера dict, и вы можете соединяться с ними при помощи любого клиента dict, не устанавливая себе сервер.
                        • +3
                          Нашел однажды на commandlinefu.com:
                          bahbka@bahbka-notebook:~$ grep translate .bashrc
                          translate(){ wget -qO- "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=$1&langpair=${2:-en}|${3:-ru}" | sed 's/.*"translatedText":"\([^"]*\)".*}/\1\n/'; }
                          bahbka@bahbka-notebook:~$ translate hello
                          привет

                          Проще некуда уже :)
                          • 0
                            Где-то нашел решение для яндекс словарей, чуток его допилил и положит вот такую функцию в ~/.bashrc:

                            trans() {
                            curl -s 'm.slovari.yandex.ru/translate.xml?lang=en-ru-en&text='"$1" | grep -Eo '[аa1]\)
                            ' | head -n 1 | awk -F'>' '{print $3}' | awk -F'<' '{print $1}'
                            }

                            • 0
                              Эх… Уже не работает… Код страницы изменился :(
                              • 0
                                Тоже сделал клиента такого, только на питоне.

                                sudo easy_install yaslov && yaslov привет

                                goo.gl/6jW0u
                              • 0
                                О! Брат-велосипедостроитель :)

                                А я на баше писал скрипт для простенького словарика (трехъязычный: русско-английско-карачаевский). Англо-русский словарь брал уже даже не помню где, а карачаево-русский получил путем grep'ания табличек с какого-то сайта.
                                • НЛО прилетело и опубликовало эту надпись здесь

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