Skip to content

Commit

Permalink
Added DeepL! And fix small errors
Browse files Browse the repository at this point in the history
  • Loading branch information
alekssamos committed Aug 25, 2023
1 parent adc1573 commit 749a4a5
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 69 deletions.
44 changes: 0 additions & 44 deletions addon/doc/en/readme.md

This file was deleted.

2 changes: 2 additions & 0 deletions addon/doc/en/readme2.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ assign convenient keyboard shortcuts for YandexTranslate. Or use the already pre
> Other translators, such as "Translate", "InstantTranslate" and others,
> if there is, it is better to disable or delete it, in order to avoid conflicts.
New 4: By popular demand added DeepL API for translation . Select DeepL from the API combobox in the add-on settings.

New 3: added the ability to save translates to the cache. If you need it, check the appropriate box in the add-on settings.

New 2: Starting with the version from October 5, 2021,
Expand Down
2 changes: 2 additions & 0 deletions addon/doc/ru/readme2.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
> Другие переводчики, такие, как "Translate", "InstantTranslate" и другие,
> если есть, лучше отключить или удалить, во избежании конфликтов.
Новое 4: По многочисленным просьбам добавил DeepL API для перевода. Выберите DeepL в списке API в настройках дополнения.

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

Новое 2: Начиная с версии от 5 октября 2021,
Expand Down
20 changes: 14 additions & 6 deletions addon/globalPlugins/yandexTranslate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def makeSettings(self, sizer):
self.langList.sort()
settingsSizerHelper = gui.guiHelper.BoxSizerHelper(self, sizer=sizer)

self.apiSel = settingsSizerHelper.addLabeledControl(_("&API:"), wx.Choice, choices=["Web", "iOS", "broker1"])
self.apiSel = settingsSizerHelper.addLabeledControl(_("&API:"), wx.Choice, choices=["Web", "iOS", "broker1", "DeepL API Free", "DeepL API Pro"])
self.apiSel.SetStringSelection(ytc["api"].lower())
self.Bind(wx.EVT_CHOICE, self.onApiSel)

Expand All @@ -134,7 +134,7 @@ def makeSettings(self, sizer):
self.signals.SetValue(tobool(ytc["signals"]))
settingsSizerHelper.addItem(self.signals)

# self.key = settingsSizerHelper.addLabeledControl(_("&API key:"), wx.TextCtrl, value=ytc["key"])
self.deepl_key = settingsSizerHelper.addLabeledControl(_("&DeepL API key:"), wx.TextCtrl, value=ytc.get("deepl_key", ""))

self.generate_new_key = wx.Button(self, label=_("&Generate new API key"))
self.generate_new_key.Bind(wx.EVT_BUTTON, self.onGenerate_new_key)
Expand Down Expand Up @@ -168,7 +168,6 @@ def makeSettings(self, sizer):
settingsSizerHelper.addItem(self.reset_settings)

def postInit(self):
return True
self.onApiSel(None)
self.apiSel.SetFocus()
self.onUseProxy(None)
Expand All @@ -178,10 +177,12 @@ def onApiSel(self, event):
apitype = self.apiSel.GetStringSelection().lower()
if apitype == "web":
self.generate_new_key.Enable()
elif apitype == "ios":
elif "deepl" in apitype:
self.generate_new_key.Disable()
self.deepl_key.Enable()
else:
self.generate_new_key.Disable()
self.deepl_key.Disable()
yt = YandexFreeTranslate(config.conf["YandexTranslate"]["api"].lower())

def onGenerate_new_key(self, event):
Expand Down Expand Up @@ -234,6 +235,8 @@ def onOk(self, event):
config.conf["YandexTranslate"]["signals"] = self.signals.Value
config.conf["YandexTranslate"]["useCache"] = self.useCache.Value
config.conf["YandexTranslate"]["useProxy"] = self.useProxy.Value
if "deepl" in self.apiSel.GetStringSelection().lower():
config.conf["YandexTranslate"]["deepl_key"] = self.deepl_key.Value
if self.useProxy.Value:
config.conf["YandexTranslate"]["proxy_protocol"] = self.proxy_protocol.GetStringSelection().split(", ")[-1]
config.conf["YandexTranslate"]["proxy_host"] = self.proxy_host.Value.strip()
Expand Down Expand Up @@ -300,6 +303,7 @@ def _dc(self, s): return s.decode("UTF8")

def _HTTPRequest(self):
global _cache
mkw = {}
yt = YandexFreeTranslate(config.conf["YandexTranslate"]["api"].lower())
cacheKey = str(self._kwargs["lang"]) + str(self._kwargs["text"])
if cacheKey in _cache:
Expand All @@ -310,7 +314,9 @@ def _HTTPRequest(self):
yt.setProxy(config.conf["YandexTranslate"]["proxy_protocol"],
config.conf["YandexTranslate"]["proxy_host"], config.conf["YandexTranslate"]["proxy_port"], config.conf["YandexTranslate"]["proxy_username"], config.conf["YandexTranslate"]["proxy_password"])
try:
responseData = yt.translate(self._kwargs["lang"], "\n".join(list(map(self._dc, self._kwargs["text"]))))
if "deepl" in config.conf["YandexTranslate"]["api"]:
mkw = {"deepl_key":config.conf["YandexTranslate"]["deepl_key"]}
responseData = yt.translate(lang=self._kwargs["lang"], text="\n".join(list(map(self._dc, self._kwargs["text"]))), **mkw)
except Exception as e:
return False, e

Expand Down Expand Up @@ -395,9 +401,11 @@ def autoTranslateHandler(status, request):

def errorHandler(self, msg):
if isinstance(msg, Exception):
text = _("Unfortunately the translation is not available. Please check your Internet connection")
text = _("Unfortunately the translation is not available. Please check your Internet connection")+str(msg)
else:
text = ERRORS.get(msg)
if "deepl" in config.conf["YandexTranslate"]["api"] and "403" in text:
text = _("The wrong key is specified for DeepL")

if text is None:
text = _("Error: %s") % msg
Expand Down
64 changes: 50 additions & 14 deletions addon/globalPlugins/yandexTranslate/yandexfreetranslate.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from logHandler import log
try:
from logHandler import log
except ImportError:
import logging
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__name__)
try: from utils import smartsplit
except: from .utils import smartsplit
except ImportError: from .utils import smartsplit
import ssl
import gzip
import json
Expand Down Expand Up @@ -28,6 +33,8 @@ class YandexFreeTranslateError(Exception): pass
class YandexFreeTranslate():
error_count = 0
broker1 = 'http://alekssamosbt.ru/yt.php'
deepl_API_Free = 'https://api-free.deepl.com/v2/translate'
deepl_API_Pro = 'https://api.deepl.com/v2/translate'
siteurl = "https://translate.yandex.ru/"
apibaseurl = "https://translate.yandex.net/api/v1/tr.json/"
api=""
Expand All @@ -53,6 +60,8 @@ def _getparams(self, **p):
"id":self.key, "srv":"tr-text", "reason":"paste", "options": 4
}
params["broker1"] = {}
params["deepl api free"] = {}
params["deepl api pro"] = {}
params[self.api].update(p)
return params[self.api]
def decode_response(self, response):
Expand Down Expand Up @@ -85,6 +94,8 @@ def _create_request(self, *ar, **kw):
if len(ar) > 0 and "http" in ar[0]: url = ar[0]
if "url" in kw: url = kw["url"]
rq = urllibrequest.Request(*ar, **kw)
if "deepl" in url:
rq.add_header("Authorization", self.deepl_key)
if self.useProxy:
if self.proxy_protocol == "http" or self.proxy_protocol == "https":
fullHost = ":".join([self.proxy_host, str(self.proxy_port)])
Expand Down Expand Up @@ -137,6 +148,8 @@ def _save_key(self, key):
except:
log.exception("key file error")
def _get_key(self):
if self.api != "web":
return "x"
try:
if os.path.isfile(self.keyfilename) and (time.time() - os.path.getmtime(self.keyfilename)) < self.expiretime:
log.debug("key from file")
Expand All @@ -159,14 +172,25 @@ def regenerate_key(self):
return self.key
def __init__(self, api="broker1"):
self.api = api
self.request_body_append = ''
if not os.path.isfile(self.keyfilename) and os.path.isfile(self.backfilename):
os.rename(self.backfilename, self.keyfilename)
def translate(self, lang, text=""):
def translate(self, lang, text, deepl_key=""):
self.lang = lang
self.deepl_key = deepl_key
utr = ''
if self.api == 'broker1':
utr = self.broker1+"?"+urllibparse.urlencode(self._getparams(lang=lang))
elif self.api == 'deepl api free':
utr = self.deepl_API_Free
elif self.api == 'deepl api pro':
utr = self.deepl_API_Pro
else:
utr = self.apibaseurl+"translate?"+urllibparse.urlencode(self._getparams(lang=lang))
if "deepl" in self.api:
self.request_body_append = urllibparse.urlencode(self._getparams(target_lang=lang.split("-")[-1]))
if "-" in lang:
self.request_body_append = self.request_body_append + "&" + urllibparse.urlencode(self._getparams(source_lang=lang.split("-")[0]))
resp = {}
content = None
try:
Expand All @@ -176,17 +200,25 @@ def translate(self, lang, text=""):
if self.key == "": self.key = self._get_key()
if text == "": raise ValueError("text")
p=[]
for part in smartsplit(text, 500, 550):
parts = []
if "deepl" in self.api:
parts = smartsplit(text, 127900, 127990)
else:
parts = smartsplit(text, 500, 550)
for part in parts:
req = self._create_request(utr)
req.add_header("User-Agent", self.ua)
req.add_header("Accept", r"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 ")
req.add_header("Accept-Language", r"ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3")
req.add_header("DNT", "1")
if "deepl" in self.api:
req.add_header("User-Agent", "Translater NVDA ADDON by alekssamos")
else:
req.add_header("User-Agent", self.ua)
req.add_header("Accept", r"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 ")
req.add_header("Accept-Language", r"ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3")
req.add_header("DNT", "1")
req.add_header("Accept-Encoding", "gzip, deflate, br")
try:
response = self._create_opener().open(req, data = urllibparse.urlencode({
response = self._create_opener().open(req, data = (self.request_body_append+"&"+urllibparse.urlencode({
"text":part
}).encode("UTF8")).read()
})).encode("UTF8")).read()
content = self.decode_response(response)
resp = json.loads(content)
except (urlliberror.HTTPError, json.JSONDecodeError):
Expand All @@ -200,14 +232,18 @@ def translate(self, lang, text=""):
self.error_count = self.error_count + 1
self.regenerate_key()
return self.translate(lang, text)
if "text" not in resp:
if ("deepl" not in self.api and "text" not in resp) or ("deepl" in self.api and "translations" not in resp):
raise YandexFreeTranslateError(content)
p.append(resp["text"][0])
if "deepl" in self.api:
p.append(resp["translations"][0]["text"])
else:
p.append(resp["text"][0])
resp["text"] = p
if "deepl" in self.api:
resp["code"] = 200
resp["lang"] = resp["translations"][0]["detected_source_language"]+"-"+self.lang
return resp
except: raise
finally:
if self.useProxy:
ssl._create_default_https_context = old_context


7 changes: 4 additions & 3 deletions addon/installTasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@


def onInstall():
if "YandexTranslate" not in config.conf: config.conf["YandexTranslate"]={}
config.conf["YandexTranslate"]["api"] = "broker1"
config.conf["YandexTranslate"]["useProxy"] = False
if "YandexTranslate" not in config.conf:
config.conf["YandexTranslate"]={}
config.conf["YandexTranslate"]["api"] = "broker1"
config.conf["YandexTranslate"]["useProxy"] = False
gui.messageBox(_("Many users reported problems with the service when others were doing well. I have added a new API type to the settings of this add-on. All requests to Yandex will go through my own server. You can disable this by still selecting the web or iOS API in the add-on settings. I will collect and analyze your requests to track and fix errors."), _("Yandex Translate"), style=wx.OK | wx.ICON_WARNING)
2 changes: 1 addition & 1 deletion addon/manifest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ summary = "Yandex translator for NVDA"
description = """Translates text using service Yandex Translate."""
author = "alekssamos <[email protected]>"
url = https://github.com/alekssamos/YandexTranslate/
version = 2023.08.24
version = 2023.08.26
docFileName = readme2.html
minimumNVDAVersion = 2019.3
lastTestedNVDAVersion = 2023.4
Expand Down
2 changes: 1 addition & 1 deletion buildVars.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# Translators: Long description to be shown for this add-on on add-on information from add-ons manager
"addon_description": _("""Translates text using service Yandex Translate."""),
# version
"addon_version": "2023.08.25",
"addon_version": "2023.08.27",
# Author(s)
"addon_author": u"alekssamos <[email protected]>",
# URL for the add-on documentation support
Expand Down

0 comments on commit 749a4a5

Please sign in to comment.