Plugins/UiExtensionPlugins/Translator/TranslatorEngines/IbmWatsonEngine.py

changeset 6411
7fd9b7ecbcfe
child 6412
d71b094845e7
equal deleted inserted replaced
6410:98a5d0cd72f5 6411:7fd9b7ecbcfe
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the IBM Watson translation engine.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode
13 except NameError:
14 pass
15
16 import json
17
18 from PyQt5.QtCore import QUrl, QByteArray
19
20 from E5Gui import E5MessageBox
21
22 from .TranslationEngine import TranslationEngine
23
24
25 class IbmWatsonEngine(TranslationEngine):
26 """
27 Class implementing the translation engine for the IBM Watson Language
28 Translator service.
29 """
30 # Documentation:
31 # https://www.ibm.com/watson/developercloud/language-translator
32 #
33 # Start page:
34 # https://www.ibm.com/watson/services/language-translator/
35
36 def __init__(self, plugin, parent=None):
37 """
38 Constructor
39
40 @param plugin reference to the plugin object
41 @type TranslatorPlugin
42 @param parent reference to the parent object
43 @type QObject
44 """
45 super(IbmWatsonEngine, self).__init__(plugin, parent)
46
47 self.__ui = parent
48
49 self.__availableTranslations = {}
50 # dictionary of sets of available translations
51
52 self.__getTranslationModels()
53
54 def engineName(self):
55 """
56 Public method to return the name of the engine.
57
58 @return engine name
59 @rtype str
60 """
61 return "ibm_watson"
62
63 def supportedLanguages(self):
64 """
65 Public method to get the supported languages.
66
67 @return list of supported language codes
68 @rtype list of str
69 """
70 return list(self.__availableTranslations.keys())
71
72 def supportedTargetLanguages(self, original):
73 """
74 Public method to get a list of supported target languages for an
75 original language.
76
77 @param original original language
78 @type str
79 @return list of supported target languages for the given original
80 @rtype list of str
81 """
82 targets = self.__availableTranslations.get(original, set())
83 return list(targets)
84
85 def hasTTS(self):
86 """
87 Public method indicating the Text-to-Speech capability.
88
89 @return flag indicating the Text-to-Speech capability
90 @rtype bool
91 """
92 return False
93
94 def getTranslation(self, requestObject, text, originalLanguage,
95 translationLanguage):
96 """
97 Public method to translate the given text.
98
99 @param requestObject reference to the request object
100 @type TranslatorRequest
101 @param text text to be translated
102 @type str
103 @param originalLanguage language code of the original
104 @type str
105 @param translationLanguage language code of the translation
106 @type str
107 @return tuple of translated text and flag indicating success
108 @rtype tuple of (str, bool)
109 """
110 apiKey = self.plugin.getPreferences("IbmKey")
111 if not apiKey:
112 return self.tr("A valid IBM Watson Language Translator key is"
113 " required."), False
114 translatorUrl = self.plugin.getPreferences("IbmUrl")
115 if not translatorUrl:
116 return self.tr("A valid IBM Watson Language Translator URL is"
117 " required."), False
118
119 params = "?version=2018-05-01"
120 url = QUrl(translatorUrl + "/v3/translate" + params)
121
122 requestDict = {
123 "text": [text],
124 "source": originalLanguage,
125 "target": translationLanguage,
126 }
127 request = QByteArray(json.dumps(requestDict).encode("utf-8"))
128
129 extraHeaders = [
130 (b"Authorization",
131 b"Basic " + QByteArray(
132 b"apikey:" + apiKey.encode("utf-8")).toBase64())
133 ]
134
135 response, ok = requestObject.post(url, request, dataType="json",
136 extraHeaders=extraHeaders)
137 if ok:
138 try:
139 responseDict = json.loads(response)
140 except ValueError:
141 return self.tr("Invalid response received"), False
142
143 if "translations" not in responseDict:
144 return self.tr("No translation available."), False
145
146 result = ""
147 translations = responseDict["translations"]
148 for translation in translations:
149 result += translation["translation"]
150 if translation != translations[-1]:
151 result += "<br/>"
152 else:
153 result = response
154 return result, ok
155
156 def __adjustLanguageCode(self, code):
157 """
158 Private method to adjust a given language code.
159
160 @param code code to be adjusted
161 @type str
162 @return adjusted language code
163 @rtype str
164 """
165 if code == "zh":
166 return "zh-CN"
167 else:
168 return code
169
170 def __getTranslationModels(self):
171 """
172 Private method to get the translation models supported by IBM Watson
173 Language Translator.
174 """
175 apiKey = self.plugin.getPreferences("IbmKey")
176 if not apiKey:
177 E5MessageBox.critical(
178 self.__ui,
179 self.tr("Error Getting Available Translations"),
180 self.tr("A valid IBM Watson Language Translator key is"
181 " required.")
182 )
183 return
184 translatorUrl = self.plugin.getPreferences("IbmUrl")
185 if not translatorUrl:
186 E5MessageBox.critical(
187 self.__ui,
188 self.tr("Error Getting Available Translations"),
189 self.tr("A valid IBM Watson Language Translator URL is"
190 " required.")
191 )
192 return
193
194 params = "?version=2018-05-01"
195 url = QUrl(translatorUrl + "/v3/models" + params)
196
197 extraHeaders = [
198 (b"Authorization",
199 b"Basic " + QByteArray(
200 b"apikey:" + apiKey.encode("utf-8")).toBase64())
201 ]
202
203 from ..TranslatorRequest import TranslatorRequest
204 requestObject = TranslatorRequest(self)
205 response, ok = requestObject.get(url, extraHeaders=extraHeaders)
206 if ok:
207 response = str(response, "utf-8", "replace")
208 try:
209 responseDict = json.loads(response)
210 except ValueError:
211 E5MessageBox.critical(
212 self.__ui,
213 self.tr("Error Getting Available Translations"),
214 self.tr("Invalid response received")
215 )
216 return
217
218 if "models" not in responseDict:
219 E5MessageBox.critical(
220 self.__ui,
221 self.tr("Error Getting Available Translations"),
222 self.tr("No translation available.")
223 )
224 return
225
226 for model in responseDict["models"]:
227 if model["status"] == "available":
228 source = self.__adjustLanguageCode(model["source"])
229 target = self.__adjustLanguageCode(model["target"])
230 if source not in self.__availableTranslations:
231 self.__availableTranslations[source] = set()
232 self.__availableTranslations[source].add(target)

eric ide

mercurial