python

Яндекс.переводчик для Linux на Python GUI

  • среда, 23 октября 2019 г. в 00:49:02
https://habr.com/ru/post/472516/
  • Python
  • GTK+
  • Яндекс API


Приветствую хабражителей!


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


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


image


Вначале был translate-shell...


Translate-shell вещь достаточно удобная, особненно, если пишешь, допустим, в Vi/vim. Переключился в соседнюю консоль и переводи.


Ключи простейшие и запоминаются легко.


$ trans -b -e yandex -t en "Простые ключи."
Simple keys.
или
$ echo -e "\nС перенаправлением.\n"|trans -b -e yandex -t en

With redirection.

Но этого как обычно было мало. Захотелось графики.


Работа в SublimeText и Zeal несколько удобней, нежели голая консоль.


image


Хм… Подумал-подумал, и решил прикрутить переводчик на горячую клавишу.
Выбор пал на gxmessage. Zenity меня не устроил, уж и не помню почему.
Был написан код:


#!/bin/bash
# Name script trans.sh
TEXT=$(xclip -selection primary -o)
TRANS=$(trans -e yandex -hl en -tl ru -b "$TEXT")
if [ "$TRANS" ]; then
gxmessage -geometry 1000x800 -bg "#aaaaaa" -title "Translate" -wrap -center -font  "Menlo Regular 24" "$TRANS"

else
gxmessage -geometry 1000x800 -bg "#aaaaaa" -title "Translate" -wrap -center -font  "Menlo Regular 24" "Нет связи с сервисом"
fi

И назначен на Ctrl+1. В IceWm это легко. Правим $HOME/.icewm/keys


key "Ctrl+1" $HOME/progs/trans.sh

Некоторое время меня это устраивало. На "контрол+1" с английского, "контрол+2" на английский. Хорошо...


image


Но тут translate-shell начал давать сбои.


image


Не знаю, что произошло у разрабов, но меня это совсем огорчило.
Я решил, пора, давно на питоне не писал.


Недолгие поиски в гугл привели меня к Yandex.API, Python и GTK+ 3 в виде модуля gi.


Почему gi, ведь обычно писал на PyQt5? Он на моей машине работает значительно быстрее. Машина не новая, памяти тоже(по современным меркам) не ахти.


image


Модуль GTK+ 3 для python был для меня вновинку. Целый вечер разбирался с синтаксисом на сайтах раз, два и три.


Так родился код:
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
import sys
import requests
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Pango
import warnings
warnings.filterwarnings("ignore")
import os
CURRDIR = os.path.dirname(os.path.abspath(__file__))
ICON = os.path.join(CURRDIR, 'yandex-48.xpm')

headers = {
    'User-Agent': ('Mozilla/5.0 (Windows NT 6.0; rv:14.0) Gecko/20100101 '
                   'Firefox/14.0.1'),
    'Accept':
    'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language':
    'ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3',
    'Accept-Encoding':
    'gzip, deflate',
    'Connection':
    'keep-alive',
    'DNT':
    '1'
}
URLDETECT = "https://translate.yandex.net/api/v1.5/tr.json/detect"
URLTRANS = "https://translate.yandex.net/api/v1.5/tr.json/translate"
KEY = "you-API-key"

def clip():
    clipboard = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
    clip = clipboard.wait_for_text()
    return clip

def detect():
    params = {"key": KEY, "text": clip(), "lang": 'ru'}
    respdetect = requests.get(URLDETECT, params=params, headers=headers).json()
    if 'lang' in respdetect.keys():
        respdetect = respdetect
    else:
        respdetect = {'code': 200, 'lang': 'en'}
    langtetect = respdetect["lang"]
    if langtetect != 'ru':
        langout = langtetect + '-ru'
    else:
        langout = 'ru-en'
    return langout

def translate():
    params = {"key": KEY, "text": clip(), "lang": detect()}
    response = requests.get(URLTRANS, params=params, headers=headers).json()
    if 'text' in response.keys():
        response = response
    else:
        response = {'code': 200, 'lang': 'en-ru', 'text': ['the buffer is empty']
        }
    output = ''.join(response["text"])
    return output

class TextViewWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title=f"Yandex Translator {detect()}")
        self.set_default_size(1000, 350)
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
        self.grid = Gtk.Grid()
        self.add(self.grid)
        self.create_textview()
        self.create_toolbar()
        self.key_Esc = Gdk.keyval_from_name("Escape")
        self.connect("key-press-event", self._key)

    def create_toolbar(self):
        toolbar = Gtk.Toolbar()
        self.grid.attach(toolbar, 1, 1, 1, 1)
        new_button = Gtk.ToolButton.new_from_stock(Gtk.STOCK_CLOSE)
        new_button.set_is_important(True)
        toolbar.insert(new_button, 0)
        new_button.connect("clicked", self.on_button_clicked, self.tag_bold)
        new_button.show()

    def on_button_clicked(self, widget, tag):
        Gtk.main_quit()

    def create_textview(self):
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        self.grid.attach(scrolledwindow, 0, 0, 2, 1)
        self.textview = Gtk.TextView()
        self.textbuffer = self.textview.get_buffer()
        self.textbuffer.set_text(f"{translate()}")
        scrolledwindow.add(self.textview)
        self.textview.set_wrap_mode(Gtk.WrapMode.WORD)
        self.tag_bold = self.textbuffer.create_tag("bold",
                                                   weight=Pango.Weight.BOLD)
        self.textview.modify_font(Pango.FontDescription('Menlo Regular 24'))

    def _key(self, widg, event):
        if event.keyval == self.key_Esc:
            Gtk.main_quit()

win = TextViewWindow()
win.connect("destroy", Gtk.main_quit)
win.set_icon_from_file(ICON)
win.show_all()
Gtk.main()

В итоге имею автопереводчик на горячей клавише.


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


Проект полностью на github.


P.S.: Буду рад критике кода.