|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2017 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the DeepL translation engine. |
|
8 """ |
|
9 |
|
10 import json |
|
11 |
|
12 from PyQt5.QtCore import QUrl, QByteArray, QTimer |
|
13 |
|
14 import Utilities |
|
15 |
|
16 from .TranslationEngine import TranslationEngine |
|
17 |
|
18 |
|
19 class DeepLEngine(TranslationEngine): |
|
20 """ |
|
21 Class implementing the translation engine for the DeepL |
|
22 translation service. |
|
23 """ |
|
24 TranslatorUrl = "https://api.deepl.com/v1/translate" |
|
25 MaxTranslationTextLen = 30 * 1024 |
|
26 |
|
27 def __init__(self, plugin, parent=None): |
|
28 """ |
|
29 Constructor |
|
30 |
|
31 @param plugin reference to the plugin object |
|
32 @type TranslatorPlugin |
|
33 @param parent reference to the parent object |
|
34 @type QObject |
|
35 """ |
|
36 super().__init__(plugin, parent) |
|
37 |
|
38 QTimer.singleShot(0, self.availableTranslationsLoaded.emit) |
|
39 |
|
40 def engineName(self): |
|
41 """ |
|
42 Public method to return the name of the engine. |
|
43 |
|
44 @return engine name |
|
45 @rtype str |
|
46 """ |
|
47 return "deepl" |
|
48 |
|
49 def supportedLanguages(self): |
|
50 """ |
|
51 Public method to get the supported languages. |
|
52 |
|
53 @return list of supported language codes |
|
54 @rtype list of str |
|
55 """ |
|
56 return ["de", "en", "es", "fr", "it", "nl", "pl", ] |
|
57 |
|
58 def getTranslation(self, requestObject, text, originalLanguage, |
|
59 translationLanguage): |
|
60 """ |
|
61 Public method to translate the given text. |
|
62 |
|
63 @param requestObject reference to the request object |
|
64 (TranslatorRequest) |
|
65 @param text text to be translated (string) |
|
66 @param originalLanguage language code of the original (string) |
|
67 @param translationLanguage language code of the translation (string) |
|
68 @return tuple of translated text (string) and flag indicating |
|
69 success (boolean) |
|
70 """ |
|
71 if len(text) > self.MaxTranslationTextLen: |
|
72 return ( |
|
73 self.tr("DeepL: Text to be translated exceeds the translation" |
|
74 " limit of {0} characters.") |
|
75 .format(self.MaxTranslationTextLen), |
|
76 False |
|
77 ) |
|
78 |
|
79 apiKey = self.plugin.getPreferences("DeeplKey") |
|
80 if not apiKey: |
|
81 return self.tr("A valid DeepL Pro key is required."), False |
|
82 |
|
83 params = QByteArray( |
|
84 "auth_key={0}&source_lang={1}&target_lang={2}&text=".format( |
|
85 apiKey, originalLanguage.upper(), translationLanguage.upper()) |
|
86 .encode("utf-8")) |
|
87 encodedText = ( |
|
88 QByteArray(Utilities.html_encode(text).encode("utf-8")) |
|
89 .toPercentEncoding() |
|
90 ) |
|
91 request = params + encodedText |
|
92 response, ok = requestObject.post(QUrl(self.TranslatorUrl), request) |
|
93 if ok: |
|
94 try: |
|
95 responseDict = json.loads(response) |
|
96 except ValueError: |
|
97 return self.tr("Invalid response received from DeepL"), False |
|
98 |
|
99 if "translations" not in responseDict: |
|
100 return self.tr("DeepL call returned an unknown result"), False |
|
101 |
|
102 translations = responseDict["translations"] |
|
103 if len(translations) == 0: |
|
104 return self.tr("<p>DeepL: No translation found</p>"), True |
|
105 |
|
106 # show sentence by sentence separated by a line |
|
107 result = ( |
|
108 "<p>" + |
|
109 "<hr/>".join([t["text"] for t in translations]) + |
|
110 "</p>" |
|
111 ) |
|
112 |
|
113 else: |
|
114 result = response |
|
115 return result, ok |