Merge branch 'master' into feature/tencent
Browse files- deep_translator/__init__.py +2 -0
- deep_translator/baidu.py +120 -0
- deep_translator/constants.py +359 -0
- deep_translator/deepl.py +2 -2
- deep_translator/exceptions.py +13 -0
- deep_translator/google.py +3 -3
- deep_translator/libre.py +2 -2
- deep_translator/linguee.py +3 -2
- deep_translator/mymemory.py +4 -3
- deep_translator/papago.py +2 -2
- deep_translator/pons.py +2 -2
- deep_translator/qcri.py +2 -1
- deep_translator/validate.py +20 -3
- deep_translator/yandex.py +2 -2
- docs/README.rst +60 -0
- pyproject.toml +1 -1
- tests/test_baidu.py +65 -0
- tests/test_google.py +0 -8
- tests/test_libre.py +0 -3
- tests/test_linguee.py +0 -3
- tests/test_mymemory.py +3 -6
- tests/test_pons.py +0 -3
deep_translator/__init__.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
__copyright__ = "Copyright (C) 2020 Nidhal Baccouri"
|
4 |
|
|
|
5 |
from deep_translator.chatgpt import ChatGptTranslator
|
6 |
from deep_translator.deepl import DeeplTranslator
|
7 |
from deep_translator.detection import batch_detection, single_detection
|
@@ -33,6 +34,7 @@ __all__ = [
|
|
33 |
"PapagoTranslator",
|
34 |
"ChatGptTranslator",
|
35 |
"TencentTranslator",
|
|
|
36 |
"single_detection",
|
37 |
"batch_detection",
|
38 |
]
|
|
|
2 |
|
3 |
__copyright__ = "Copyright (C) 2020 Nidhal Baccouri"
|
4 |
|
5 |
+
from deep_translator.baidu import BaiduTranslator
|
6 |
from deep_translator.chatgpt import ChatGptTranslator
|
7 |
from deep_translator.deepl import DeeplTranslator
|
8 |
from deep_translator.detection import batch_detection, single_detection
|
|
|
34 |
"PapagoTranslator",
|
35 |
"ChatGptTranslator",
|
36 |
"TencentTranslator",
|
37 |
+
"BaiduTranslator",
|
38 |
"single_detection",
|
39 |
"batch_detection",
|
40 |
]
|
deep_translator/baidu.py
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
baidu translator API
|
3 |
+
"""
|
4 |
+
|
5 |
+
__copyright__ = "Copyright (C) 2020 Nidhal Baccouri"
|
6 |
+
|
7 |
+
import hashlib
|
8 |
+
import os
|
9 |
+
import random
|
10 |
+
from typing import List, Optional
|
11 |
+
|
12 |
+
import requests
|
13 |
+
|
14 |
+
from deep_translator.base import BaseTranslator
|
15 |
+
from deep_translator.constants import (
|
16 |
+
BAIDU_APPID_ENV_VAR,
|
17 |
+
BAIDU_APPKEY_ENV_VAR,
|
18 |
+
BAIDU_LANGUAGE_TO_CODE,
|
19 |
+
BASE_URLS,
|
20 |
+
)
|
21 |
+
from deep_translator.exceptions import (
|
22 |
+
ApiKeyException,
|
23 |
+
BaiduAPIerror,
|
24 |
+
ServerException,
|
25 |
+
TranslationNotFound,
|
26 |
+
)
|
27 |
+
from deep_translator.validate import is_empty, is_input_valid
|
28 |
+
|
29 |
+
|
30 |
+
class BaiduTranslator(BaseTranslator):
|
31 |
+
"""
|
32 |
+
class that wraps functions, which use the BaiduTranslator translator
|
33 |
+
under the hood to translate word(s)
|
34 |
+
"""
|
35 |
+
|
36 |
+
def __init__(
|
37 |
+
self,
|
38 |
+
source: str = "en",
|
39 |
+
target: str = "zh",
|
40 |
+
appid: Optional[str] = os.getenv(BAIDU_APPID_ENV_VAR, None),
|
41 |
+
appkey: Optional[str] = os.getenv(BAIDU_APPKEY_ENV_VAR, None),
|
42 |
+
**kwargs
|
43 |
+
):
|
44 |
+
"""
|
45 |
+
@param appid: your baidu cloud api appid.
|
46 |
+
Get one here: https://fanyi-api.baidu.com/choose
|
47 |
+
@param appkey: your baidu cloud api appkey.
|
48 |
+
@param source: source language
|
49 |
+
@param target: target language
|
50 |
+
"""
|
51 |
+
if not appid:
|
52 |
+
raise ApiKeyException(env_var=BAIDU_APPID_ENV_VAR)
|
53 |
+
|
54 |
+
if not appkey:
|
55 |
+
raise ApiKeyException(env_var=BAIDU_APPKEY_ENV_VAR)
|
56 |
+
|
57 |
+
self.appid = appid
|
58 |
+
self.appkey = appkey
|
59 |
+
super().__init__(
|
60 |
+
base_url=BASE_URLS.get("BAIDU"),
|
61 |
+
source=source,
|
62 |
+
target=target,
|
63 |
+
languages=BAIDU_LANGUAGE_TO_CODE,
|
64 |
+
**kwargs
|
65 |
+
)
|
66 |
+
|
67 |
+
def translate(self, text: str, **kwargs) -> str:
|
68 |
+
"""
|
69 |
+
@param text: text to translate
|
70 |
+
@return: translated text
|
71 |
+
"""
|
72 |
+
if is_input_valid(text):
|
73 |
+
if self._same_source_target() or is_empty(text):
|
74 |
+
return text
|
75 |
+
|
76 |
+
# Create the request parameters.
|
77 |
+
salt = random.randint(32768, 65536)
|
78 |
+
sign = hashlib.md5(
|
79 |
+
(self.appid + text + str(salt) + self.appkey).encode("utf-8")
|
80 |
+
).hexdigest()
|
81 |
+
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
82 |
+
payload = {
|
83 |
+
"appid": self.appid,
|
84 |
+
"q": text,
|
85 |
+
"from": self.source,
|
86 |
+
"to": self.target,
|
87 |
+
"salt": salt,
|
88 |
+
"sign": sign,
|
89 |
+
}
|
90 |
+
|
91 |
+
# Do the request and check the connection.
|
92 |
+
try:
|
93 |
+
response = requests.post(
|
94 |
+
self._base_url, params=payload, headers=headers
|
95 |
+
)
|
96 |
+
except ConnectionError:
|
97 |
+
raise ServerException(503)
|
98 |
+
if response.status_code != 200:
|
99 |
+
raise ServerException(response.status_code)
|
100 |
+
# Get the response and check is not empty.
|
101 |
+
res = response.json()
|
102 |
+
if not res:
|
103 |
+
raise TranslationNotFound(text)
|
104 |
+
# Process and return the response.
|
105 |
+
if "error_code" in res:
|
106 |
+
raise BaiduAPIerror(res["error_msg"])
|
107 |
+
if "trans_result" in res:
|
108 |
+
return "\n".join([s["dst"] for s in res["trans_result"]])
|
109 |
+
else:
|
110 |
+
raise TranslationNotFound(text)
|
111 |
+
|
112 |
+
def translate_file(self, path: str, **kwargs) -> str:
|
113 |
+
return self._translate_file(path, **kwargs)
|
114 |
+
|
115 |
+
def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
|
116 |
+
"""
|
117 |
+
@param batch: list of texts to translate
|
118 |
+
@return: list of translations
|
119 |
+
"""
|
120 |
+
return self._translate_batch(batch, **kwargs)
|
deep_translator/constants.py
CHANGED
@@ -9,6 +9,8 @@ QCRI_ENV_VAR = "QCRI_API_KEY"
|
|
9 |
YANDEX_ENV_VAR = "YANDEX_API_KEY"
|
10 |
TENCENT_SECRET_ID_ENV_VAR = "TENCENT_SECRET_ID"
|
11 |
TENCENT_SECRET_KEY_ENV_VAR = "TENCENT_SECRET_KEY"
|
|
|
|
|
12 |
|
13 |
|
14 |
BASE_URLS = {
|
@@ -26,6 +28,7 @@ BASE_URLS = {
|
|
26 |
"LIBRE": "https://libretranslate.com/",
|
27 |
"LIBRE_FREE": "https://libretranslate.de/",
|
28 |
"TENENT": "https://tmt.tencentcloudapi.com",
|
|
|
29 |
}
|
30 |
|
31 |
GOOGLE_LANGUAGES_TO_CODES = {
|
@@ -219,6 +222,331 @@ LINGUEE_LANGUAGES_TO_CODES = {
|
|
219 |
"japanese": "japanese",
|
220 |
}
|
221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
DEEPL_LANGUAGE_TO_CODE = {
|
223 |
"bulgarian": "bg",
|
224 |
"czech": "cs",
|
@@ -303,3 +631,34 @@ TENCENT_LANGUAGE_TO_CODE = {
|
|
303 |
"turkish": "tr",
|
304 |
"vietnamese": "vi",
|
305 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
YANDEX_ENV_VAR = "YANDEX_API_KEY"
|
10 |
TENCENT_SECRET_ID_ENV_VAR = "TENCENT_SECRET_ID"
|
11 |
TENCENT_SECRET_KEY_ENV_VAR = "TENCENT_SECRET_KEY"
|
12 |
+
BAIDU_APPID_ENV_VAR = "BAIDU_APPID"
|
13 |
+
BAIDU_APPKEY_ENV_VAR = "BAIDU_APPKEY"
|
14 |
|
15 |
|
16 |
BASE_URLS = {
|
|
|
28 |
"LIBRE": "https://libretranslate.com/",
|
29 |
"LIBRE_FREE": "https://libretranslate.de/",
|
30 |
"TENENT": "https://tmt.tencentcloudapi.com",
|
31 |
+
"BAIDU": "https://fanyi-api.baidu.com/api/trans/vip/translate",
|
32 |
}
|
33 |
|
34 |
GOOGLE_LANGUAGES_TO_CODES = {
|
|
|
222 |
"japanese": "japanese",
|
223 |
}
|
224 |
|
225 |
+
MY_MEMORY_LANGUAGES_TO_CODES = {
|
226 |
+
"acehnese": "ace-ID",
|
227 |
+
"afrikaans": "af-ZA",
|
228 |
+
"akan": "ak-GH",
|
229 |
+
"albanian": "sq-AL",
|
230 |
+
"amharic": "am-ET",
|
231 |
+
"antigua and barbuda creole english": "aig-AG",
|
232 |
+
"arabic": "ar-SA",
|
233 |
+
"arabic egyptian": "ar-EG",
|
234 |
+
"aragonese": "an-ES",
|
235 |
+
"armenian": "hy-AM",
|
236 |
+
"assamese": "as-IN",
|
237 |
+
"asturian": "ast-ES",
|
238 |
+
"austrian german": "de-AT",
|
239 |
+
"awadhi": "awa-IN",
|
240 |
+
"ayacucho quechua": "quy-PE",
|
241 |
+
"azerbaijani": "az-AZ",
|
242 |
+
"bahamas creole english": "bah-BS",
|
243 |
+
"bajan": "bjs-BB",
|
244 |
+
"balinese": "ban-ID",
|
245 |
+
"balkan gipsy": "rm-RO",
|
246 |
+
"bambara": "bm-ML",
|
247 |
+
"banjar": "bjn-ID",
|
248 |
+
"bashkir": "ba-RU",
|
249 |
+
"basque": "eu-ES",
|
250 |
+
"belarusian": "be-BY",
|
251 |
+
"belgian french": "fr-BE",
|
252 |
+
"bemba": "bem-ZM",
|
253 |
+
"bengali": "bn-IN",
|
254 |
+
"bhojpuri": "bho-IN",
|
255 |
+
"bihari": "bh-IN",
|
256 |
+
"bislama": "bi-VU",
|
257 |
+
"borana": "gax-KE",
|
258 |
+
"bosnian": "bs-BA",
|
259 |
+
"bosnian (cyrillic)": "bs-Cyrl-BA",
|
260 |
+
"breton": "br-FR",
|
261 |
+
"buginese": "bug-ID",
|
262 |
+
"bulgarian": "bg-BG",
|
263 |
+
"burmese": "my-MM",
|
264 |
+
"catalan": "ca-ES",
|
265 |
+
"catalan valencian": "cav-ES",
|
266 |
+
"cebuano": "ceb-PH",
|
267 |
+
"central atlas tamazight": "tzm-MA",
|
268 |
+
"central aymara": "ayr-BO",
|
269 |
+
"central kanuri (latin script)": "knc-NG",
|
270 |
+
"chadian arabic": "shu-TD",
|
271 |
+
"chamorro": "ch-GU",
|
272 |
+
"cherokee": "chr-US",
|
273 |
+
"chhattisgarhi": "hne-IN",
|
274 |
+
"chinese simplified": "zh-CN",
|
275 |
+
"chinese trad. (hong kong)": "zh-HK",
|
276 |
+
"chinese traditional": "zh-TW",
|
277 |
+
"chinese traditional macau": "zh-MO",
|
278 |
+
"chittagonian": "ctg-BD",
|
279 |
+
"chokwe": "cjk-AO",
|
280 |
+
"classical greek": "grc-GR",
|
281 |
+
"comorian ngazidja": "zdj-KM",
|
282 |
+
"coptic": "cop-EG",
|
283 |
+
"crimean tatar": "crh-RU",
|
284 |
+
"crioulo upper guinea": "pov-GW",
|
285 |
+
"croatian": "hr-HR",
|
286 |
+
"czech": "cs-CZ",
|
287 |
+
"danish": "da-DK",
|
288 |
+
"dari": "prs-AF",
|
289 |
+
"dimli": "diq-TR",
|
290 |
+
"dutch": "nl-NL",
|
291 |
+
"dyula": "dyu-CI",
|
292 |
+
"dzongkha": "dz-BT",
|
293 |
+
"eastern yiddish": "ydd-US",
|
294 |
+
"emakhuwa": "vmw-MZ",
|
295 |
+
"english": "en-GB",
|
296 |
+
"english australia": "en-AU",
|
297 |
+
"english canada": "en-CA",
|
298 |
+
"english india": "en-IN",
|
299 |
+
"english ireland": "en-IE",
|
300 |
+
"english new zealand": "en-NZ",
|
301 |
+
"english singapore": "en-SG",
|
302 |
+
"english south africa": "en-ZA",
|
303 |
+
"english us": "en-US",
|
304 |
+
"esperanto": "eo-EU",
|
305 |
+
"estonian": "et-EE",
|
306 |
+
"ewe": "ee-GH",
|
307 |
+
"fanagalo": "fn-FNG",
|
308 |
+
"faroese": "fo-FO",
|
309 |
+
"fijian": "fj-FJ",
|
310 |
+
"filipino": "fil-PH",
|
311 |
+
"finnish": "fi-FI",
|
312 |
+
"flemish": "nl-BE",
|
313 |
+
"fon": "fon-BJ",
|
314 |
+
"french": "fr-FR",
|
315 |
+
"french canada": "fr-CA",
|
316 |
+
"french swiss": "fr-CH",
|
317 |
+
"friulian": "fur-IT",
|
318 |
+
"fula": "ff-FUL",
|
319 |
+
"galician": "gl-ES",
|
320 |
+
"gamargu": "mfi-NG",
|
321 |
+
"garo": "grt-IN",
|
322 |
+
"georgian": "ka-GE",
|
323 |
+
"german": "de-DE",
|
324 |
+
"gilbertese": "gil-KI",
|
325 |
+
"glavda": "glw-NG",
|
326 |
+
"greek": "el-GR",
|
327 |
+
"grenadian creole english": "gcl-GD",
|
328 |
+
"guarani": "gn-PY",
|
329 |
+
"gujarati": "gu-IN",
|
330 |
+
"guyanese creole english": "gyn-GY",
|
331 |
+
"haitian creole french": "ht-HT",
|
332 |
+
"halh mongolian": "khk-MN",
|
333 |
+
"hausa": "ha-NE",
|
334 |
+
"hawaiian": "haw-US",
|
335 |
+
"hebrew": "he-IL",
|
336 |
+
"higi": "hig-NG",
|
337 |
+
"hiligaynon": "hil-PH",
|
338 |
+
"hill mari": "mrj-RU",
|
339 |
+
"hindi": "hi-IN",
|
340 |
+
"hmong": "hmn-CN",
|
341 |
+
"hungarian": "hu-HU",
|
342 |
+
"icelandic": "is-IS",
|
343 |
+
"igbo ibo": "ibo-NG",
|
344 |
+
"igbo ig": "ig-NG",
|
345 |
+
"ilocano": "ilo-PH",
|
346 |
+
"indonesian": "id-ID",
|
347 |
+
"inuktitut greenlandic": "kl-GL",
|
348 |
+
"irish gaelic": "ga-IE",
|
349 |
+
"italian": "it-IT",
|
350 |
+
"italian swiss": "it-CH",
|
351 |
+
"jamaican creole english": "jam-JM",
|
352 |
+
"japanese": "ja-JP",
|
353 |
+
"javanese": "jv-ID",
|
354 |
+
"jingpho": "kac-MM",
|
355 |
+
"k'iche'": "quc-GT",
|
356 |
+
"kabiyè": "kbp-TG",
|
357 |
+
"kabuverdianu": "kea-CV",
|
358 |
+
"kabylian": "kab-DZ",
|
359 |
+
"kalenjin": "kln-KE",
|
360 |
+
"kamba": "kam-KE",
|
361 |
+
"kannada": "kn-IN",
|
362 |
+
"kanuri": "kr-KAU",
|
363 |
+
"karen": "kar-MM",
|
364 |
+
"kashmiri (devanagari script)": "ks-IN",
|
365 |
+
"kashmiri (arabic script)": "kas-IN",
|
366 |
+
"kazakh": "kk-KZ",
|
367 |
+
"khasi": "kha-IN",
|
368 |
+
"khmer": "km-KH",
|
369 |
+
"kikuyu kik": "kik-KE",
|
370 |
+
"kikuyu ki": "ki-KE",
|
371 |
+
"kimbundu": "kmb-AO",
|
372 |
+
"kinyarwanda": "rw-RW",
|
373 |
+
"kirundi": "rn-BI",
|
374 |
+
"kisii": "guz-KE",
|
375 |
+
"kongo": "kg-CG",
|
376 |
+
"konkani": "kok-IN",
|
377 |
+
"korean": "ko-KR",
|
378 |
+
"northern kurdish": "kmr-TR",
|
379 |
+
"kurdish sorani": "ckb-IQ",
|
380 |
+
"kyrgyz": "ky-KG",
|
381 |
+
"lao": "lo-LA",
|
382 |
+
"latgalian": "ltg-LV",
|
383 |
+
"latin": "la-XN",
|
384 |
+
"latvian": "lv-LV",
|
385 |
+
"ligurian": "lij-IT",
|
386 |
+
"limburgish": "li-NL",
|
387 |
+
"lingala": "ln-LIN",
|
388 |
+
"lithuanian": "lt-LT",
|
389 |
+
"lombard": "lmo-IT",
|
390 |
+
"luba-kasai": "lua-CD",
|
391 |
+
"luganda": "lg-UG",
|
392 |
+
"luhya": "luy-KE",
|
393 |
+
"luo": "luo-KE",
|
394 |
+
"luxembourgish": "lb-LU",
|
395 |
+
"maa": "mas-KE",
|
396 |
+
"macedonian": "mk-MK",
|
397 |
+
"magahi": "mag-IN",
|
398 |
+
"maithili": "mai-IN",
|
399 |
+
"malagasy": "mg-MG",
|
400 |
+
"malay": "ms-MY",
|
401 |
+
"malayalam": "ml-IN",
|
402 |
+
"maldivian": "dv-MV",
|
403 |
+
"maltese": "mt-MT",
|
404 |
+
"mandara": "mfi-CM",
|
405 |
+
"manipuri": "mni-IN",
|
406 |
+
"manx gaelic": "gv-IM",
|
407 |
+
"maori": "mi-NZ",
|
408 |
+
"marathi": "mr-IN",
|
409 |
+
"margi": "mrt-NG",
|
410 |
+
"mari": "mhr-RU",
|
411 |
+
"marshallese": "mh-MH",
|
412 |
+
"mende": "men-SL",
|
413 |
+
"meru": "mer-KE",
|
414 |
+
"mijikenda": "nyf-KE",
|
415 |
+
"minangkabau": "min-ID",
|
416 |
+
"mizo": "lus-IN",
|
417 |
+
"mongolian": "mn-MN",
|
418 |
+
"montenegrin": "sr-ME",
|
419 |
+
"morisyen": "mfe-MU",
|
420 |
+
"moroccan arabic": "ar-MA",
|
421 |
+
"mossi": "mos-BF",
|
422 |
+
"ndau": "ndc-MZ",
|
423 |
+
"ndebele": "nr-ZA",
|
424 |
+
"nepali": "ne-NP",
|
425 |
+
"nigerian fulfulde": "fuv-NG",
|
426 |
+
"niuean": "niu-NU",
|
427 |
+
"north azerbaijani": "azj-AZ",
|
428 |
+
"sesotho": "nso-ZA",
|
429 |
+
"northern uzbek": "uzn-UZ",
|
430 |
+
"norwegian bokmål": "nb-NO",
|
431 |
+
"norwegian nynorsk": "nn-NO",
|
432 |
+
"nuer": "nus-SS",
|
433 |
+
"nyanja": "ny-MW",
|
434 |
+
"occitan": "oc-FR",
|
435 |
+
"occitan aran": "oc-ES",
|
436 |
+
"odia": "or-IN",
|
437 |
+
"oriya": "ory-IN",
|
438 |
+
"urdu": "ur-PK",
|
439 |
+
"palauan": "pau-PW",
|
440 |
+
"pali": "pi-IN",
|
441 |
+
"pangasinan": "pag-PH",
|
442 |
+
"papiamentu": "pap-CW",
|
443 |
+
"pashto": "ps-PK",
|
444 |
+
"persian": "fa-IR",
|
445 |
+
"pijin": "pis-SB",
|
446 |
+
"plateau malagasy": "plt-MG",
|
447 |
+
"polish": "pl-PL",
|
448 |
+
"portuguese": "pt-PT",
|
449 |
+
"portuguese brazil": "pt-BR",
|
450 |
+
"potawatomi": "pot-US",
|
451 |
+
"punjabi": "pa-IN",
|
452 |
+
"punjabi (pakistan)": "pnb-PK",
|
453 |
+
"quechua": "qu-PE",
|
454 |
+
"rohingya": "rhg-MM",
|
455 |
+
"rohingyalish": "rhl-MM",
|
456 |
+
"romanian": "ro-RO",
|
457 |
+
"romansh": "roh-CH",
|
458 |
+
"rundi": "run-BI",
|
459 |
+
"russian": "ru-RU",
|
460 |
+
"saint lucian creole french": "acf-LC",
|
461 |
+
"samoan": "sm-WS",
|
462 |
+
"sango": "sg-CF",
|
463 |
+
"sanskrit": "sa-IN",
|
464 |
+
"santali": "sat-IN",
|
465 |
+
"sardinian": "sc-IT",
|
466 |
+
"scots gaelic": "gd-GB",
|
467 |
+
"sena": "seh-ZW",
|
468 |
+
"serbian cyrillic": "sr-Cyrl-RS",
|
469 |
+
"serbian latin": "sr-Latn-RS",
|
470 |
+
"seselwa creole french": "crs-SC",
|
471 |
+
"setswana (south africa)": "tn-ZA",
|
472 |
+
"shan": "shn-MM",
|
473 |
+
"shona": "sn-ZW",
|
474 |
+
"sicilian": "scn-IT",
|
475 |
+
"silesian": "szl-PL",
|
476 |
+
"sindhi snd": "snd-PK",
|
477 |
+
"sindhi sd": "sd-PK",
|
478 |
+
"sinhala": "si-LK",
|
479 |
+
"slovak": "sk-SK",
|
480 |
+
"slovenian": "sl-SI",
|
481 |
+
"somali": "so-SO",
|
482 |
+
"sotho southern": "st-LS",
|
483 |
+
"south azerbaijani": "azb-AZ",
|
484 |
+
"southern pashto": "pbt-PK",
|
485 |
+
"southwestern dinka": "dik-SS",
|
486 |
+
"spanish": "es-ES",
|
487 |
+
"spanish argentina": "es-AR",
|
488 |
+
"spanish colombia": "es-CO",
|
489 |
+
"spanish latin america": "es-419",
|
490 |
+
"spanish mexico": "es-MX",
|
491 |
+
"spanish united states": "es-US",
|
492 |
+
"sranan tongo": "srn-SR",
|
493 |
+
"standard latvian": "lvs-LV",
|
494 |
+
"standard malay": "zsm-MY",
|
495 |
+
"sundanese": "su-ID",
|
496 |
+
"swahili": "sw-KE",
|
497 |
+
"swati": "ss-SZ",
|
498 |
+
"swedish": "sv-SE",
|
499 |
+
"swiss german": "de-CH",
|
500 |
+
"syriac (aramaic)": "syc-TR",
|
501 |
+
"tagalog": "tl-PH",
|
502 |
+
"tahitian": "ty-PF",
|
503 |
+
"tajik": "tg-TJ",
|
504 |
+
"tamashek (tuareg)": "tmh-DZ",
|
505 |
+
"tamasheq": "taq-ML",
|
506 |
+
"tamil india": "ta-IN",
|
507 |
+
"tamil sri lanka": "ta-LK",
|
508 |
+
"taroko": "trv-TW",
|
509 |
+
"tatar": "tt-RU",
|
510 |
+
"telugu": "te-IN",
|
511 |
+
"tetum": "tet-TL",
|
512 |
+
"thai": "th-TH",
|
513 |
+
"tibetan": "bo-CN",
|
514 |
+
"tigrinya": "ti-ET",
|
515 |
+
"tok pisin": "tpi-PG",
|
516 |
+
"tokelauan": "tkl-TK",
|
517 |
+
"tongan": "to-TO",
|
518 |
+
"tosk albanian": "als-AL",
|
519 |
+
"tsonga": "ts-ZA",
|
520 |
+
"tswa": "tsc-MZ",
|
521 |
+
"tswana": "tn-BW",
|
522 |
+
"tumbuka": "tum-MW",
|
523 |
+
"turkish": "tr-TR",
|
524 |
+
"turkmen": "tk-TM",
|
525 |
+
"tuvaluan": "tvl-TV",
|
526 |
+
"twi": "tw-GH",
|
527 |
+
"udmurt": "udm-RU",
|
528 |
+
"ukrainian": "uk-UA",
|
529 |
+
"uma": "ppk-ID",
|
530 |
+
"umbundu": "umb-AO",
|
531 |
+
"uyghur uig": "uig-CN",
|
532 |
+
"uyghur ug": "ug-CN",
|
533 |
+
"uzbek": "uz-UZ",
|
534 |
+
"venetian": "vec-IT",
|
535 |
+
"vietnamese": "vi-VN",
|
536 |
+
"vincentian creole english": "svc-VC",
|
537 |
+
"virgin islands creole english": "vic-US",
|
538 |
+
"wallisian": "wls-WF",
|
539 |
+
"waray (philippines)": "war-PH",
|
540 |
+
"welsh": "cy-GB",
|
541 |
+
"west central oromo": "gaz-ET",
|
542 |
+
"western persian": "pes-IR",
|
543 |
+
"wolof": "wo-SN",
|
544 |
+
"xhosa": "xh-ZA",
|
545 |
+
"yiddish": "yi-YD",
|
546 |
+
"yoruba": "yo-NG",
|
547 |
+
"zulu": "zu-ZA",
|
548 |
+
}
|
549 |
+
|
550 |
DEEPL_LANGUAGE_TO_CODE = {
|
551 |
"bulgarian": "bg",
|
552 |
"czech": "cs",
|
|
|
631 |
"turkish": "tr",
|
632 |
"vietnamese": "vi",
|
633 |
}
|
634 |
+
|
635 |
+
BAIDU_LANGUAGE_TO_CODE = {
|
636 |
+
"arabic": "ara",
|
637 |
+
"bulgarian": "bul",
|
638 |
+
"chinese (classical)": "wyw",
|
639 |
+
"chinese (simplified)": "zh",
|
640 |
+
"chinese (traditional)": "cht",
|
641 |
+
"czech": "cs",
|
642 |
+
"danish": "dan",
|
643 |
+
"dutch": "nl",
|
644 |
+
"english": "en",
|
645 |
+
"estonian": "est",
|
646 |
+
"finnish": "fin",
|
647 |
+
"french": "fra",
|
648 |
+
"german": "de",
|
649 |
+
"greek": "el",
|
650 |
+
"hungarian": "hu",
|
651 |
+
"italian": "it",
|
652 |
+
"japanese": "jp",
|
653 |
+
"korean": "kor",
|
654 |
+
"polish": "pl",
|
655 |
+
"portuguese": "pt",
|
656 |
+
"romanian": "ro",
|
657 |
+
"russian": "ru",
|
658 |
+
"slovenian": "slo",
|
659 |
+
"spanish": "spa",
|
660 |
+
"swedish": "swe",
|
661 |
+
"thai": "th",
|
662 |
+
"vietnamese": "vie",
|
663 |
+
"yueyu": "yue",
|
664 |
+
}
|
deep_translator/deepl.py
CHANGED
@@ -17,7 +17,7 @@ from deep_translator.exceptions import (
|
|
17 |
ServerException,
|
18 |
TranslationNotFound,
|
19 |
)
|
20 |
-
from deep_translator.validate import is_empty, is_input_valid
|
21 |
|
22 |
|
23 |
class DeeplTranslator(BaseTranslator):
|
@@ -85,7 +85,7 @@ class DeeplTranslator(BaseTranslator):
|
|
85 |
# If the answer is not success, raise server exception.
|
86 |
if response.status_code == 403:
|
87 |
raise AuthorizationException(self.api_key)
|
88 |
-
|
89 |
raise ServerException(response.status_code)
|
90 |
# Get the response and check is not empty.
|
91 |
res = response.json()
|
|
|
17 |
ServerException,
|
18 |
TranslationNotFound,
|
19 |
)
|
20 |
+
from deep_translator.validate import is_empty, is_input_valid, request_failed
|
21 |
|
22 |
|
23 |
class DeeplTranslator(BaseTranslator):
|
|
|
85 |
# If the answer is not success, raise server exception.
|
86 |
if response.status_code == 403:
|
87 |
raise AuthorizationException(self.api_key)
|
88 |
+
if request_failed(status_code=response.status_code):
|
89 |
raise ServerException(response.status_code)
|
90 |
# Get the response and check is not empty.
|
91 |
res = response.json()
|
deep_translator/exceptions.py
CHANGED
@@ -193,3 +193,16 @@ class TencentAPIerror(Exception):
|
|
193 |
|
194 |
def __str__(self):
|
195 |
return "{}: {}".format(self.message, self.api_message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
def __str__(self):
|
195 |
return "{}: {}".format(self.message, self.api_message)
|
196 |
+
|
197 |
+
|
198 |
+
class BaiduAPIerror(Exception):
|
199 |
+
"""
|
200 |
+
exception thrown if Baidu API returns one of its errors
|
201 |
+
"""
|
202 |
+
|
203 |
+
def __init__(self, api_message):
|
204 |
+
self.api_message = str(api_message)
|
205 |
+
self.message = "Baidu API returned the following error"
|
206 |
+
|
207 |
+
def __str__(self):
|
208 |
+
return "{}: {}".format(self.message, self.api_message)
|
deep_translator/google.py
CHANGED
@@ -16,7 +16,7 @@ from deep_translator.exceptions import (
|
|
16 |
TooManyRequests,
|
17 |
TranslationNotFound,
|
18 |
)
|
19 |
-
from deep_translator.validate import is_empty, is_input_valid
|
20 |
|
21 |
|
22 |
class GoogleTranslator(BaseTranslator):
|
@@ -54,7 +54,7 @@ class GoogleTranslator(BaseTranslator):
|
|
54 |
@param text: desired text to translate
|
55 |
@return: str: translated text
|
56 |
"""
|
57 |
-
if is_input_valid(text):
|
58 |
text = text.strip()
|
59 |
if self._same_source_target() or is_empty(text):
|
60 |
return text
|
@@ -70,7 +70,7 @@ class GoogleTranslator(BaseTranslator):
|
|
70 |
if response.status_code == 429:
|
71 |
raise TooManyRequests()
|
72 |
|
73 |
-
if response.status_code
|
74 |
raise RequestError()
|
75 |
|
76 |
soup = BeautifulSoup(response.text, "html.parser")
|
|
|
16 |
TooManyRequests,
|
17 |
TranslationNotFound,
|
18 |
)
|
19 |
+
from deep_translator.validate import is_empty, is_input_valid, request_failed
|
20 |
|
21 |
|
22 |
class GoogleTranslator(BaseTranslator):
|
|
|
54 |
@param text: desired text to translate
|
55 |
@return: str: translated text
|
56 |
"""
|
57 |
+
if is_input_valid(text, max_chars=5000):
|
58 |
text = text.strip()
|
59 |
if self._same_source_target() or is_empty(text):
|
60 |
return text
|
|
|
70 |
if response.status_code == 429:
|
71 |
raise TooManyRequests()
|
72 |
|
73 |
+
if request_failed(status_code=response.status_code):
|
74 |
raise RequestError()
|
75 |
|
76 |
soup = BeautifulSoup(response.text, "html.parser")
|
deep_translator/libre.py
CHANGED
@@ -20,7 +20,7 @@ from deep_translator.exceptions import (
|
|
20 |
ServerException,
|
21 |
TranslationNotFound,
|
22 |
)
|
23 |
-
from deep_translator.validate import is_empty, is_input_valid
|
24 |
|
25 |
|
26 |
class LibreTranslator(BaseTranslator):
|
@@ -95,7 +95,7 @@ class LibreTranslator(BaseTranslator):
|
|
95 |
|
96 |
if response.status_code == 403:
|
97 |
raise AuthorizationException(self.api_key)
|
98 |
-
elif response.status_code
|
99 |
raise ServerException(response.status_code)
|
100 |
# Get the response and check is not empty.
|
101 |
res = response.json()
|
|
|
20 |
ServerException,
|
21 |
TranslationNotFound,
|
22 |
)
|
23 |
+
from deep_translator.validate import is_empty, is_input_valid, request_failed
|
24 |
|
25 |
|
26 |
class LibreTranslator(BaseTranslator):
|
|
|
95 |
|
96 |
if response.status_code == 403:
|
97 |
raise AuthorizationException(self.api_key)
|
98 |
+
elif request_failed(status_code=response.status_code):
|
99 |
raise ServerException(response.status_code)
|
100 |
# Get the response and check is not empty.
|
101 |
res = response.json()
|
deep_translator/linguee.py
CHANGED
@@ -19,7 +19,7 @@ from deep_translator.exceptions import (
|
|
19 |
TooManyRequests,
|
20 |
TranslationNotFound,
|
21 |
)
|
22 |
-
from deep_translator.validate import is_empty, is_input_valid
|
23 |
|
24 |
|
25 |
class LingueeTranslator(BaseTranslator):
|
@@ -72,8 +72,9 @@ class LingueeTranslator(BaseTranslator):
|
|
72 |
if response.status_code == 429:
|
73 |
raise TooManyRequests()
|
74 |
|
75 |
-
if response.status_code
|
76 |
raise RequestError()
|
|
|
77 |
soup = BeautifulSoup(response.text, "html.parser")
|
78 |
elements = soup.find_all(self._element_tag, self._element_query)
|
79 |
response.close()
|
|
|
19 |
TooManyRequests,
|
20 |
TranslationNotFound,
|
21 |
)
|
22 |
+
from deep_translator.validate import is_empty, is_input_valid, request_failed
|
23 |
|
24 |
|
25 |
class LingueeTranslator(BaseTranslator):
|
|
|
72 |
if response.status_code == 429:
|
73 |
raise TooManyRequests()
|
74 |
|
75 |
+
if request_failed(status_code=response.status_code):
|
76 |
raise RequestError()
|
77 |
+
|
78 |
soup = BeautifulSoup(response.text, "html.parser")
|
79 |
elements = soup.find_all(self._element_tag, self._element_query)
|
80 |
response.close()
|
deep_translator/mymemory.py
CHANGED
@@ -9,13 +9,13 @@ from typing import List, Optional, Union
|
|
9 |
import requests
|
10 |
|
11 |
from deep_translator.base import BaseTranslator
|
12 |
-
from deep_translator.constants import BASE_URLS
|
13 |
from deep_translator.exceptions import (
|
14 |
RequestError,
|
15 |
TooManyRequests,
|
16 |
TranslationNotFound,
|
17 |
)
|
18 |
-
from deep_translator.validate import is_empty, is_input_valid
|
19 |
|
20 |
|
21 |
class MyMemoryTranslator(BaseTranslator):
|
@@ -41,6 +41,7 @@ class MyMemoryTranslator(BaseTranslator):
|
|
41 |
source=source,
|
42 |
target=target,
|
43 |
payload_key="q",
|
|
|
44 |
)
|
45 |
|
46 |
def translate(
|
@@ -70,7 +71,7 @@ class MyMemoryTranslator(BaseTranslator):
|
|
70 |
|
71 |
if response.status_code == 429:
|
72 |
raise TooManyRequests()
|
73 |
-
if response.status_code
|
74 |
raise RequestError()
|
75 |
|
76 |
data = response.json()
|
|
|
9 |
import requests
|
10 |
|
11 |
from deep_translator.base import BaseTranslator
|
12 |
+
from deep_translator.constants import BASE_URLS, MY_MEMORY_LANGUAGES_TO_CODES
|
13 |
from deep_translator.exceptions import (
|
14 |
RequestError,
|
15 |
TooManyRequests,
|
16 |
TranslationNotFound,
|
17 |
)
|
18 |
+
from deep_translator.validate import is_empty, is_input_valid, request_failed
|
19 |
|
20 |
|
21 |
class MyMemoryTranslator(BaseTranslator):
|
|
|
41 |
source=source,
|
42 |
target=target,
|
43 |
payload_key="q",
|
44 |
+
languages=MY_MEMORY_LANGUAGES_TO_CODES,
|
45 |
)
|
46 |
|
47 |
def translate(
|
|
|
71 |
|
72 |
if response.status_code == 429:
|
73 |
raise TooManyRequests()
|
74 |
+
if request_failed(status_code=response.status_code):
|
75 |
raise RequestError()
|
76 |
|
77 |
data = response.json()
|
deep_translator/papago.py
CHANGED
@@ -12,7 +12,7 @@ import requests
|
|
12 |
from deep_translator.base import BaseTranslator
|
13 |
from deep_translator.constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
|
14 |
from deep_translator.exceptions import TranslationNotFound
|
15 |
-
from deep_translator.validate import is_input_valid
|
16 |
|
17 |
|
18 |
class PapagoTranslator(BaseTranslator):
|
@@ -67,7 +67,7 @@ class PapagoTranslator(BaseTranslator):
|
|
67 |
response = requests.post(
|
68 |
self._base_url, headers=headers, data=payload
|
69 |
)
|
70 |
-
if response.status_code
|
71 |
raise Exception(
|
72 |
f"Translation error! -> status code: {response.status_code}"
|
73 |
)
|
|
|
12 |
from deep_translator.base import BaseTranslator
|
13 |
from deep_translator.constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
|
14 |
from deep_translator.exceptions import TranslationNotFound
|
15 |
+
from deep_translator.validate import is_input_valid, request_failed
|
16 |
|
17 |
|
18 |
class PapagoTranslator(BaseTranslator):
|
|
|
67 |
response = requests.post(
|
68 |
self._base_url, headers=headers, data=payload
|
69 |
)
|
70 |
+
if request_failed(status_code=response.status_code):
|
71 |
raise Exception(
|
72 |
f"Translation error! -> status code: {response.status_code}"
|
73 |
)
|
deep_translator/pons.py
CHANGED
@@ -19,7 +19,7 @@ from deep_translator.exceptions import (
|
|
19 |
TooManyRequests,
|
20 |
TranslationNotFound,
|
21 |
)
|
22 |
-
from deep_translator.validate import is_empty, is_input_valid
|
23 |
|
24 |
|
25 |
class PonsTranslator(BaseTranslator):
|
@@ -71,7 +71,7 @@ class PonsTranslator(BaseTranslator):
|
|
71 |
if response.status_code == 429:
|
72 |
raise TooManyRequests()
|
73 |
|
74 |
-
if response.status_code
|
75 |
raise RequestError()
|
76 |
|
77 |
soup = BeautifulSoup(response.text, "html.parser")
|
|
|
19 |
TooManyRequests,
|
20 |
TranslationNotFound,
|
21 |
)
|
22 |
+
from deep_translator.validate import is_empty, is_input_valid, request_failed
|
23 |
|
24 |
|
25 |
class PonsTranslator(BaseTranslator):
|
|
|
71 |
if response.status_code == 429:
|
72 |
raise TooManyRequests()
|
73 |
|
74 |
+
if request_failed(status_code=response.status_code):
|
75 |
raise RequestError()
|
76 |
|
77 |
soup = BeautifulSoup(response.text, "html.parser")
|
deep_translator/qcri.py
CHANGED
@@ -16,6 +16,7 @@ from deep_translator.exceptions import (
|
|
16 |
ServerException,
|
17 |
TranslationNotFound,
|
18 |
)
|
|
|
19 |
|
20 |
|
21 |
class QcriTranslator(BaseTranslator):
|
@@ -96,7 +97,7 @@ class QcriTranslator(BaseTranslator):
|
|
96 |
raise ServerException(503)
|
97 |
|
98 |
else:
|
99 |
-
if response.status_code
|
100 |
ServerException(response.status_code)
|
101 |
else:
|
102 |
res = response.json()
|
|
|
16 |
ServerException,
|
17 |
TranslationNotFound,
|
18 |
)
|
19 |
+
from deep_translator.validate import request_failed
|
20 |
|
21 |
|
22 |
class QcriTranslator(BaseTranslator):
|
|
|
97 |
raise ServerException(503)
|
98 |
|
99 |
else:
|
100 |
+
if request_failed(status_code=response.status_code):
|
101 |
ServerException(response.status_code)
|
102 |
else:
|
103 |
res = response.json()
|
deep_translator/validate.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
__copyright__ = "Copyright (C) 2020 Nidhal Baccouri"
|
2 |
|
|
|
|
|
3 |
from deep_translator.exceptions import NotValidLength, NotValidPayload
|
4 |
|
5 |
|
@@ -7,8 +9,23 @@ def is_empty(text: str) -> bool:
|
|
7 |
return text == ""
|
8 |
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
def is_input_valid(
|
11 |
-
text: str, min_chars: int = 0, max_chars: int =
|
12 |
) -> bool:
|
13 |
"""
|
14 |
validate the target text to translate
|
@@ -18,9 +35,9 @@ def is_input_valid(
|
|
18 |
@return: bool
|
19 |
"""
|
20 |
|
21 |
-
if not isinstance(text, str)
|
22 |
raise NotValidPayload(text)
|
23 |
-
if not min_chars <= len(text) < max_chars:
|
24 |
raise NotValidLength(text, min_chars, max_chars)
|
25 |
|
26 |
return True
|
|
|
1 |
__copyright__ = "Copyright (C) 2020 Nidhal Baccouri"
|
2 |
|
3 |
+
from typing import Optional
|
4 |
+
|
5 |
from deep_translator.exceptions import NotValidLength, NotValidPayload
|
6 |
|
7 |
|
|
|
9 |
return text == ""
|
10 |
|
11 |
|
12 |
+
def request_failed(status_code: int) -> bool:
|
13 |
+
"""Check if a request has failed or not.
|
14 |
+
A request is considered successfull if the status code is in the 2** range.
|
15 |
+
|
16 |
+
Args:
|
17 |
+
status_code (int): status code of the request
|
18 |
+
|
19 |
+
Returns:
|
20 |
+
bool: indicates request failure
|
21 |
+
"""
|
22 |
+
if status_code > 299 or status_code < 200:
|
23 |
+
return True
|
24 |
+
return False
|
25 |
+
|
26 |
+
|
27 |
def is_input_valid(
|
28 |
+
text: str, min_chars: int = 0, max_chars: Optional[int] = None
|
29 |
) -> bool:
|
30 |
"""
|
31 |
validate the target text to translate
|
|
|
35 |
@return: bool
|
36 |
"""
|
37 |
|
38 |
+
if not isinstance(text, str):
|
39 |
raise NotValidPayload(text)
|
40 |
+
if max_chars and (not min_chars <= len(text) < max_chars):
|
41 |
raise NotValidLength(text, min_chars, max_chars)
|
42 |
|
43 |
return True
|
deep_translator/yandex.py
CHANGED
@@ -18,7 +18,7 @@ from deep_translator.exceptions import (
|
|
18 |
TooManyRequests,
|
19 |
TranslationNotFound,
|
20 |
)
|
21 |
-
from deep_translator.validate import is_input_valid
|
22 |
|
23 |
|
24 |
class YandexTranslator(BaseTranslator):
|
@@ -75,7 +75,7 @@ class YandexTranslator(BaseTranslator):
|
|
75 |
else:
|
76 |
data = response.json()
|
77 |
|
78 |
-
if response.status_code
|
79 |
raise ServerException(response.status_code)
|
80 |
return data.get("dirs")
|
81 |
|
|
|
18 |
TooManyRequests,
|
19 |
TranslationNotFound,
|
20 |
)
|
21 |
+
from deep_translator.validate import is_input_valid, request_failed
|
22 |
|
23 |
|
24 |
class YandexTranslator(BaseTranslator):
|
|
|
75 |
else:
|
76 |
data = response.json()
|
77 |
|
78 |
+
if request_failed(status_code=response.status_code):
|
79 |
raise ServerException(response.status_code)
|
80 |
return data.get("dirs")
|
81 |
|
docs/README.rst
CHANGED
@@ -694,6 +694,66 @@ TencentTranslator
|
|
694 |
|
695 |
translated = TencentTranslator(secret_id="your-secret_id", secret_key="your-secret_key" source="en", target="zh").translate_file('path/to/file')
|
696 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
|
698 |
Proxy usage
|
699 |
-------------
|
|
|
694 |
|
695 |
translated = TencentTranslator(secret_id="your-secret_id", secret_key="your-secret_key" source="en", target="zh").translate_file('path/to/file')
|
696 |
|
697 |
+
BaiduTranslator
|
698 |
+
-----------------
|
699 |
+
|
700 |
+
.. note::
|
701 |
+
|
702 |
+
In order to use the BaiduTranslator translator, you need to generate a secret_id and a secret_key.
|
703 |
+
deep-translator supports both Pro and free APIs. Just check the examples below.
|
704 |
+
Visit http://api.fanyi.baidu.com/product/113 for more information on how to generate your Baidu appid
|
705 |
+
and appkey.
|
706 |
+
|
707 |
+
- Simple translation
|
708 |
+
|
709 |
+
.. code-block:: python
|
710 |
+
|
711 |
+
text = 'Hello world'
|
712 |
+
translated = BaiduTranslator(appid="your-appid", appkey="your-appkey" source="en", target="zh").translate(text)
|
713 |
+
|
714 |
+
- Translate batch of texts
|
715 |
+
|
716 |
+
.. code-block:: python
|
717 |
+
|
718 |
+
texts = ["Hello world", "How are you?"]
|
719 |
+
translated = BaiduTranslator(appid="your-appid", appkey="your-appkey" source="en", target="zh").translate_batch(texts)
|
720 |
+
|
721 |
+
- Translate from a file:
|
722 |
+
|
723 |
+
.. code-block:: python
|
724 |
+
|
725 |
+
translated = BaiduTranslator(appid="your-appid", appkey="your-appkey" source="en", target="zh").translate_file('path/to/file')
|
726 |
+
|
727 |
+
BaiduTranslator
|
728 |
+
-----------------
|
729 |
+
|
730 |
+
.. note::
|
731 |
+
|
732 |
+
In order to use the BaiduTranslator translator, you need to generate a secret_id and a secret_key.
|
733 |
+
deep-translator supports both Pro and free APIs. Just check the examples below.
|
734 |
+
Visit http://api.fanyi.baidu.com/product/113 for more information on how to generate your Baidu appid
|
735 |
+
and appkey.
|
736 |
+
|
737 |
+
- Simple translation
|
738 |
+
|
739 |
+
.. code-block:: python
|
740 |
+
|
741 |
+
text = 'Hello world'
|
742 |
+
translated = BaiduTranslator(appid="your-appid", appkey="your-appkey" source="en", target="zh").translate(text)
|
743 |
+
|
744 |
+
- Translate batch of texts
|
745 |
+
|
746 |
+
.. code-block:: python
|
747 |
+
|
748 |
+
texts = ["Hello world", "How are you?"]
|
749 |
+
translated = BaiduTranslator(appid="your-appid", appkey="your-appkey" source="en", target="zh").translate_batch(texts)
|
750 |
+
|
751 |
+
- Translate from a file:
|
752 |
+
|
753 |
+
.. code-block:: python
|
754 |
+
|
755 |
+
translated = BaiduTranslator(appid="your-appid", appkey="your-appkey" source="en", target="zh").translate_file('path/to/file')
|
756 |
+
|
757 |
|
758 |
Proxy usage
|
759 |
-------------
|
pyproject.toml
CHANGED
@@ -25,7 +25,7 @@ ensure_newline_before_comments = true
|
|
25 |
|
26 |
[tool.poetry]
|
27 |
name = "deep-translator"
|
28 |
-
version = "1.11.
|
29 |
description = "A flexible free and unlimited python tool to translate between different languages in a simple way using multiple translators"
|
30 |
license = "MIT"
|
31 |
authors = ["Nidhal Baccouri <[email protected]>"]
|
|
|
25 |
|
26 |
[tool.poetry]
|
27 |
name = "deep-translator"
|
28 |
+
version = "1.11.4"
|
29 |
description = "A flexible free and unlimited python tool to translate between different languages in a simple way using multiple translators"
|
30 |
license = "MIT"
|
31 |
authors = ["Nidhal Baccouri <[email protected]>"]
|
tests/test_baidu.py
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from unittest.mock import Mock, patch
|
2 |
+
|
3 |
+
import pytest
|
4 |
+
|
5 |
+
from deep_translator import BaiduTranslator
|
6 |
+
from deep_translator.exceptions import BaiduAPIerror
|
7 |
+
|
8 |
+
|
9 |
+
@patch("deep_translator.baidu.requests")
|
10 |
+
def test_simple_translation(mock_requests):
|
11 |
+
translator = BaiduTranslator(
|
12 |
+
appid="this-is-an-valid-appid",
|
13 |
+
appkey="this-is-an-valid-appkey",
|
14 |
+
source="en",
|
15 |
+
target="zh",
|
16 |
+
)
|
17 |
+
# Set the request response mock.
|
18 |
+
mock_response = Mock()
|
19 |
+
mock_response.status_code = 200
|
20 |
+
mock_response.json.return_value = {
|
21 |
+
"from": "en",
|
22 |
+
"to": "zh",
|
23 |
+
"trans_result": [{"src": "hello", "dst": "你好"}],
|
24 |
+
}
|
25 |
+
mock_requests.post.return_value = mock_response
|
26 |
+
translation = translator.translate("hello")
|
27 |
+
assert translation == "你好"
|
28 |
+
|
29 |
+
|
30 |
+
@patch("deep_translator.baidu.requests.get")
|
31 |
+
def test_wrong_api_key(mock_requests):
|
32 |
+
translator = BaiduTranslator(
|
33 |
+
appid="this-is-a-wrong-appid",
|
34 |
+
appkey="this-is-a-wrong-appkey",
|
35 |
+
source="en",
|
36 |
+
target="zh",
|
37 |
+
)
|
38 |
+
# Set the response status_code only.
|
39 |
+
mock_response = Mock()
|
40 |
+
mock_response.status_code = 200
|
41 |
+
mock_response.json.return_value = {
|
42 |
+
"error_code": "54001",
|
43 |
+
"error_msg": "Invalid Sign",
|
44 |
+
}
|
45 |
+
mock_requests.post.return_value = mock_response
|
46 |
+
with pytest.raises(BaiduAPIerror):
|
47 |
+
translator.translate("Hello")
|
48 |
+
|
49 |
+
|
50 |
+
# the remaining tests are actual requests to Baidu translator API and use appid and appkey
|
51 |
+
# if appid and appkey variable is None, they are skipped
|
52 |
+
|
53 |
+
appid = None
|
54 |
+
appkey = None
|
55 |
+
|
56 |
+
|
57 |
+
@pytest.mark.skipif(
|
58 |
+
appid is None or appkey is None,
|
59 |
+
reason="appid or appkey is not provided",
|
60 |
+
)
|
61 |
+
def test_baidu_successful_post_onetarget():
|
62 |
+
posted = BaiduTranslator(
|
63 |
+
appid=appid, appkey=appkey, source="en", target="zh"
|
64 |
+
).translate("Hello! How are you?")
|
65 |
+
assert isinstance(posted, str)
|
tests/test_google.py
CHANGED
@@ -46,14 +46,6 @@ def test_empty_text(google_translator):
|
|
46 |
|
47 |
|
48 |
def test_payload(google_translator):
|
49 |
-
with pytest.raises(exceptions.NotValidPayload):
|
50 |
-
google_translator.translate(text="1234")
|
51 |
-
google_translator.translate(text="{}")
|
52 |
-
google_translator.translate(text="%@")
|
53 |
-
|
54 |
-
with pytest.raises(exceptions.NotValidPayload):
|
55 |
-
google_translator.translate(text=123)
|
56 |
-
|
57 |
with pytest.raises(exceptions.NotValidPayload):
|
58 |
google_translator.translate(text={})
|
59 |
|
|
|
46 |
|
47 |
|
48 |
def test_payload(google_translator):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
with pytest.raises(exceptions.NotValidPayload):
|
50 |
google_translator.translate(text={})
|
51 |
|
tests/test_libre.py
CHANGED
@@ -32,9 +32,6 @@ def test_abbreviations_and_languages_mapping():
|
|
32 |
|
33 |
|
34 |
def test_payload(libre):
|
35 |
-
with pytest.raises(exceptions.NotValidPayload):
|
36 |
-
libre.translate(123)
|
37 |
-
|
38 |
with pytest.raises(exceptions.NotValidPayload):
|
39 |
libre.translate({})
|
40 |
|
|
|
32 |
|
33 |
|
34 |
def test_payload(libre):
|
|
|
|
|
|
|
35 |
with pytest.raises(exceptions.NotValidPayload):
|
36 |
libre.translate({})
|
37 |
|
tests/test_linguee.py
CHANGED
@@ -38,9 +38,6 @@ def test_inputs():
|
|
38 |
|
39 |
|
40 |
def test_payload(linguee):
|
41 |
-
with pytest.raises(exceptions.NotValidPayload):
|
42 |
-
linguee.translate(123)
|
43 |
-
|
44 |
with pytest.raises(exceptions.NotValidPayload):
|
45 |
linguee.translate({})
|
46 |
|
|
|
38 |
|
39 |
|
40 |
def test_payload(linguee):
|
|
|
|
|
|
|
41 |
with pytest.raises(exceptions.NotValidPayload):
|
42 |
linguee.translate({})
|
43 |
|
tests/test_mymemory.py
CHANGED
@@ -9,7 +9,7 @@ from deep_translator import MyMemoryTranslator, exceptions
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def mymemory():
|
12 |
-
return MyMemoryTranslator(source="en", target="fr")
|
13 |
|
14 |
|
15 |
def test_content(mymemory):
|
@@ -27,18 +27,15 @@ def test_inputs():
|
|
27 |
MyMemoryTranslator(source="auto", target="")
|
28 |
|
29 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
30 |
-
MyMemoryTranslator(source="", target="en")
|
31 |
|
32 |
-
m1 = MyMemoryTranslator("en", "fr")
|
33 |
m2 = MyMemoryTranslator("english", "french")
|
34 |
assert m1._source == m2._source
|
35 |
assert m1._target == m2._target
|
36 |
|
37 |
|
38 |
def test_payload(mymemory):
|
39 |
-
with pytest.raises(exceptions.NotValidPayload):
|
40 |
-
mymemory.translate(text=123)
|
41 |
-
|
42 |
with pytest.raises(exceptions.NotValidPayload):
|
43 |
mymemory.translate(text={})
|
44 |
|
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def mymemory():
|
12 |
+
return MyMemoryTranslator(source="en-GB", target="fr-FR")
|
13 |
|
14 |
|
15 |
def test_content(mymemory):
|
|
|
27 |
MyMemoryTranslator(source="auto", target="")
|
28 |
|
29 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
30 |
+
MyMemoryTranslator(source="", target="en-GB")
|
31 |
|
32 |
+
m1 = MyMemoryTranslator("en-GB", "fr-FR")
|
33 |
m2 = MyMemoryTranslator("english", "french")
|
34 |
assert m1._source == m2._source
|
35 |
assert m1._target == m2._target
|
36 |
|
37 |
|
38 |
def test_payload(mymemory):
|
|
|
|
|
|
|
39 |
with pytest.raises(exceptions.NotValidPayload):
|
40 |
mymemory.translate(text={})
|
41 |
|
tests/test_pons.py
CHANGED
@@ -36,9 +36,6 @@ def test_inputs():
|
|
36 |
|
37 |
|
38 |
def test_payload(pons):
|
39 |
-
with pytest.raises(exceptions.NotValidPayload):
|
40 |
-
pons.translate(123)
|
41 |
-
|
42 |
with pytest.raises(exceptions.NotValidPayload):
|
43 |
pons.translate({})
|
44 |
|
|
|
36 |
|
37 |
|
38 |
def test_payload(pons):
|
|
|
|
|
|
|
39 |
with pytest.raises(exceptions.NotValidPayload):
|
40 |
pons.translate({})
|
41 |
|