Merge pull request #136 from nidhaloff/features/engine
Browse files- deep_translator/__init__.py +6 -11
- deep_translator/__main__.py +0 -1
- deep_translator/base.py +114 -0
- deep_translator/cli.py +2 -4
- deep_translator/constants.py +1 -11
- deep_translator/deepl.py +52 -62
- deep_translator/detection.py +1 -0
- deep_translator/engine.py +0 -45
- deep_translator/engines.py +7 -0
- deep_translator/exceptions.py +1 -2
- deep_translator/{google_trans.py → google.py} +22 -121
- deep_translator/libre.py +43 -91
- deep_translator/linguee.py +13 -51
- deep_translator/microsoft.py +50 -97
- deep_translator/mymemory.py +16 -103
- deep_translator/papago.py +40 -115
- deep_translator/parent.py +0 -80
- deep_translator/pons.py +16 -53
- deep_translator/qcri.py +18 -22
- deep_translator/validate.py +24 -0
- deep_translator/yandex.py +38 -50
- docs/README.rst +13 -13
- docs/history.rst +2 -2
- docs/modules.rst +4 -4
- docs/usage.rst +12 -12
- examples/trans.py +10 -5
- pyproject.toml +1 -1
- tests/test_deepl.py +3 -3
- tests/test_google.py +68 -0
- tests/test_google_trans.py +0 -175
- tests/test_libre.py +11 -56
- tests/test_linguee.py +7 -16
- tests/test_microsoft_trans.py +4 -4
- tests/test_mymemory.py +7 -9
- tests/test_pons.py +7 -15
deep_translator/__init__.py
CHANGED
@@ -1,21 +1,20 @@
|
|
1 |
"""Top-level package for Deep Translator"""
|
2 |
|
3 |
-
from .
|
4 |
from .pons import PonsTranslator
|
5 |
from .linguee import LingueeTranslator
|
6 |
from .mymemory import MyMemoryTranslator
|
7 |
from .yandex import YandexTranslator
|
8 |
-
from .qcri import
|
9 |
-
from .deepl import
|
10 |
from .detection import single_detection, batch_detection
|
11 |
from .microsoft import MicrosoftTranslator
|
12 |
from .papago import PapagoTranslator
|
13 |
from .libre import LibreTranslator
|
14 |
-
from .engine import generate_engines_dict, engine
|
15 |
|
16 |
__author__ = """Nidhal Baccouri"""
|
17 |
__email__ = '[email protected]'
|
18 |
-
__version__ = '1.
|
19 |
|
20 |
__all__ = [
|
21 |
"GoogleTranslator",
|
@@ -24,14 +23,10 @@ __all__ = [
|
|
24 |
"MyMemoryTranslator",
|
25 |
"YandexTranslator",
|
26 |
"MicrosoftTranslator",
|
27 |
-
"
|
28 |
-
"
|
29 |
"LibreTranslator",
|
30 |
"PapagoTranslator",
|
31 |
"single_detection",
|
32 |
"batch_detection"
|
33 |
]
|
34 |
-
|
35 |
-
__engines__ = generate_engines_dict(__all__, locals())
|
36 |
-
del generate_engines_dict
|
37 |
-
engine.translation_engines = __engines__
|
|
|
1 |
"""Top-level package for Deep Translator"""
|
2 |
|
3 |
+
from .google import GoogleTranslator
|
4 |
from .pons import PonsTranslator
|
5 |
from .linguee import LingueeTranslator
|
6 |
from .mymemory import MyMemoryTranslator
|
7 |
from .yandex import YandexTranslator
|
8 |
+
from .qcri import QcriTranslator
|
9 |
+
from .deepl import DeeplTranslator
|
10 |
from .detection import single_detection, batch_detection
|
11 |
from .microsoft import MicrosoftTranslator
|
12 |
from .papago import PapagoTranslator
|
13 |
from .libre import LibreTranslator
|
|
|
14 |
|
15 |
__author__ = """Nidhal Baccouri"""
|
16 |
__email__ = '[email protected]'
|
17 |
+
__version__ = '1.7.1'
|
18 |
|
19 |
__all__ = [
|
20 |
"GoogleTranslator",
|
|
|
23 |
"MyMemoryTranslator",
|
24 |
"YandexTranslator",
|
25 |
"MicrosoftTranslator",
|
26 |
+
"QcriTranslator",
|
27 |
+
"DeeplTranslator",
|
28 |
"LibreTranslator",
|
29 |
"PapagoTranslator",
|
30 |
"single_detection",
|
31 |
"batch_detection"
|
32 |
]
|
|
|
|
|
|
|
|
deep_translator/__main__.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
|
2 |
-
import argparse
|
3 |
from .cli import CLI
|
4 |
|
5 |
|
|
|
1 |
|
|
|
2 |
from .cli import CLI
|
3 |
|
4 |
|
deep_translator/base.py
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""base translator class"""
|
2 |
+
|
3 |
+
from .constants import GOOGLE_LANGUAGES_TO_CODES
|
4 |
+
from .exceptions import InvalidSourceOrTargetLanguage
|
5 |
+
from abc import ABC, abstractmethod
|
6 |
+
|
7 |
+
|
8 |
+
class BaseTranslator(ABC):
|
9 |
+
"""
|
10 |
+
Abstract class that serve as a base translator for other different translators
|
11 |
+
"""
|
12 |
+
def __init__(self,
|
13 |
+
base_url=None,
|
14 |
+
source="auto",
|
15 |
+
target="en",
|
16 |
+
payload_key=None,
|
17 |
+
element_tag=None,
|
18 |
+
element_query=None,
|
19 |
+
languages=None,
|
20 |
+
**url_params):
|
21 |
+
"""
|
22 |
+
@param source: source language to translate from
|
23 |
+
@param target: target language to translate to
|
24 |
+
"""
|
25 |
+
self._base_url = base_url
|
26 |
+
self.languages: dict = GOOGLE_LANGUAGES_TO_CODES if not languages else languages
|
27 |
+
self.supported_languages: list = list(self.languages.keys())
|
28 |
+
if not source:
|
29 |
+
raise InvalidSourceOrTargetLanguage(source)
|
30 |
+
if not target:
|
31 |
+
raise InvalidSourceOrTargetLanguage(target)
|
32 |
+
|
33 |
+
self._source, self._target = self._map_language_to_code(source, target)
|
34 |
+
self._url_params = url_params
|
35 |
+
self._element_tag = element_tag
|
36 |
+
self._element_query = element_query
|
37 |
+
self.payload_key = payload_key
|
38 |
+
super().__init__()
|
39 |
+
|
40 |
+
def _type(self):
|
41 |
+
return self.__class__.__name__
|
42 |
+
|
43 |
+
def _map_language_to_code(self, *languages):
|
44 |
+
"""
|
45 |
+
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
46 |
+
@param languages: list of languages
|
47 |
+
@return: mapped value of the language or raise an exception if the language is not supported
|
48 |
+
"""
|
49 |
+
for language in languages:
|
50 |
+
if language in self.languages.values() or language == 'auto':
|
51 |
+
yield language
|
52 |
+
elif language in self.languages.keys():
|
53 |
+
yield self.languages[language]
|
54 |
+
|
55 |
+
def _same_source_target(self):
|
56 |
+
return self._source == self._target
|
57 |
+
|
58 |
+
def get_supported_languages(self, as_dict=False, **kwargs):
|
59 |
+
"""
|
60 |
+
return the supported languages by the google translator
|
61 |
+
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
62 |
+
@return: list or dict
|
63 |
+
"""
|
64 |
+
return self.supported_languages if not as_dict else self.languages
|
65 |
+
|
66 |
+
def is_language_supported(self, language, **kwargs):
|
67 |
+
"""
|
68 |
+
check if the language is supported by the translator
|
69 |
+
@param language: a string for 1 language
|
70 |
+
@return: bool or raise an Exception
|
71 |
+
"""
|
72 |
+
if language == 'auto' or language in self.languages.keys() or language in self.languages.values():
|
73 |
+
return True
|
74 |
+
else:
|
75 |
+
return False
|
76 |
+
|
77 |
+
@abstractmethod
|
78 |
+
def translate(self, text, **kwargs):
|
79 |
+
"""
|
80 |
+
translate a text using a translator under the hood and return the translated text
|
81 |
+
@param text: text to translate
|
82 |
+
@param kwargs: additional arguments
|
83 |
+
@return: str
|
84 |
+
"""
|
85 |
+
return NotImplemented('You need to implement the translate method!')
|
86 |
+
|
87 |
+
def _translate_file(self, path, **kwargs):
|
88 |
+
"""
|
89 |
+
translate directly from file
|
90 |
+
@param path: path to the target file
|
91 |
+
@type path: str
|
92 |
+
@param kwargs: additional args
|
93 |
+
@return: str
|
94 |
+
"""
|
95 |
+
try:
|
96 |
+
with open(path, 'r', encoding='utf-8') as f:
|
97 |
+
text = f.read().strip()
|
98 |
+
return self.translate(text)
|
99 |
+
except Exception as e:
|
100 |
+
raise e
|
101 |
+
|
102 |
+
def _translate_batch(self, batch=None, **kwargs):
|
103 |
+
"""
|
104 |
+
translate a list of texts
|
105 |
+
@param batch: list of texts you want to translate
|
106 |
+
@return: list of translations
|
107 |
+
"""
|
108 |
+
if not batch:
|
109 |
+
raise Exception("Enter your text list that you want to translate")
|
110 |
+
arr = []
|
111 |
+
for i, text in enumerate(batch):
|
112 |
+
translated = self.translate(text, **kwargs)
|
113 |
+
arr.append(translated)
|
114 |
+
return arr
|
deep_translator/cli.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
"""Console script for deep_translator."""
|
2 |
-
from . import __engines__
|
3 |
import argparse
|
|
|
4 |
|
5 |
|
6 |
class CLI(object):
|
@@ -10,7 +10,6 @@ class CLI(object):
|
|
10 |
def __init__(self, custom_args=None):
|
11 |
self.custom_args = custom_args
|
12 |
self.args = self.parse_args()
|
13 |
-
# print(f'{__engines__}')
|
14 |
translator_class = self.translators_dict.get(self.args.translator, None)
|
15 |
if not translator_class:
|
16 |
raise Exception(f"Translator {self.args.translator} is not supported."
|
@@ -24,7 +23,7 @@ class CLI(object):
|
|
24 |
"""
|
25 |
res = self.translator.translate(self.args.text)
|
26 |
print("Translation from {} to {}".format(self.args.source, self.args.target))
|
27 |
-
print("-"*50)
|
28 |
print("Translation result: {}".format(res))
|
29 |
|
30 |
def get_supported_languages(self):
|
@@ -69,7 +68,6 @@ class CLI(object):
|
|
69 |
help="all the languages available with the translator"
|
70 |
"Run the command deep_translator -trans <translator service> -lang")
|
71 |
parsed_args = parser.parse_args(self.custom_args) if self.custom_args else parser.parse_args()
|
72 |
-
print(f"parsed args: {parsed_args}")
|
73 |
return parsed_args
|
74 |
|
75 |
def run(self):
|
|
|
1 |
"""Console script for deep_translator."""
|
|
|
2 |
import argparse
|
3 |
+
from .engines import __engines__
|
4 |
|
5 |
|
6 |
class CLI(object):
|
|
|
10 |
def __init__(self, custom_args=None):
|
11 |
self.custom_args = custom_args
|
12 |
self.args = self.parse_args()
|
|
|
13 |
translator_class = self.translators_dict.get(self.args.translator, None)
|
14 |
if not translator_class:
|
15 |
raise Exception(f"Translator {self.args.translator} is not supported."
|
|
|
23 |
"""
|
24 |
res = self.translator.translate(self.args.text)
|
25 |
print("Translation from {} to {}".format(self.args.source, self.args.target))
|
26 |
+
print("-" * 50)
|
27 |
print("Translation result: {}".format(res))
|
28 |
|
29 |
def get_supported_languages(self):
|
|
|
68 |
help="all the languages available with the translator"
|
69 |
"Run the command deep_translator -trans <translator service> -lang")
|
70 |
parsed_args = parser.parse_args(self.custom_args) if self.custom_args else parser.parse_args()
|
|
|
71 |
return parsed_args
|
72 |
|
73 |
def run(self):
|
deep_translator/constants.py
CHANGED
@@ -8,7 +8,7 @@ BASE_URLS = {
|
|
8 |
"MYMEMORY": "http://api.mymemory.translated.net/get",
|
9 |
"QCRI": "https://mt.qcri.org/api/v1/{endpoint}?",
|
10 |
"DEEPL": "https://api.deepl.com/{version}/",
|
11 |
-
"DEEPL_FREE": "https://api-free.deepl.com/
|
12 |
"MICROSOFT_TRANSLATE": "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0",
|
13 |
"PAPAGO": "https://papago.naver.com/",
|
14 |
"PAPAGO_API": "https://openapi.naver.com/v1/papago/n2mt",
|
@@ -197,16 +197,6 @@ LINGUEE_LANGUAGES_TO_CODES = {
|
|
197 |
|
198 |
LINGUEE_CODE_TO_LANGUAGE = {v: k for k, v in LINGUEE_LANGUAGES_TO_CODES.items()}
|
199 |
|
200 |
-
# "72e9e2cc7c992db4dcbdd6fb9f91a0d1"
|
201 |
-
|
202 |
-
# obtaining the current list of supported Microsoft languages for translation
|
203 |
-
|
204 |
-
microsoft_languages_api_url = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation"
|
205 |
-
microsoft_languages_response = requests.get(microsoft_languages_api_url)
|
206 |
-
translation_dict = microsoft_languages_response.json()['translation']
|
207 |
-
|
208 |
-
MICROSOFT_CODES_TO_LANGUAGES = {translation_dict[k]['name'].lower(): k for k in translation_dict.keys()}
|
209 |
-
|
210 |
DEEPL_LANGUAGE_TO_CODE = {
|
211 |
"bulgarian": "bg",
|
212 |
"czech": "cs",
|
|
|
8 |
"MYMEMORY": "http://api.mymemory.translated.net/get",
|
9 |
"QCRI": "https://mt.qcri.org/api/v1/{endpoint}?",
|
10 |
"DEEPL": "https://api.deepl.com/{version}/",
|
11 |
+
"DEEPL_FREE": "https://api-free.deepl.com/{version}/",
|
12 |
"MICROSOFT_TRANSLATE": "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0",
|
13 |
"PAPAGO": "https://papago.naver.com/",
|
14 |
"PAPAGO_API": "https://openapi.naver.com/v1/papago/n2mt",
|
|
|
197 |
|
198 |
LINGUEE_CODE_TO_LANGUAGE = {v: k for k, v in LINGUEE_LANGUAGES_TO_CODES.items()}
|
199 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
DEEPL_LANGUAGE_TO_CODE = {
|
201 |
"bulgarian": "bg",
|
202 |
"czech": "cs",
|
deep_translator/deepl.py
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
import requests
|
2 |
-
|
3 |
-
from .
|
|
|
|
|
4 |
TranslationNotFound,
|
5 |
-
LanguageNotSupportedException,
|
6 |
AuthorizationException)
|
7 |
-
from .
|
8 |
|
9 |
|
10 |
-
class
|
11 |
"""
|
12 |
-
class that wraps functions, which use the
|
13 |
"""
|
14 |
-
_languages = DEEPL_LANGUAGE_TO_CODE
|
15 |
|
16 |
-
def __init__(self, api_key=None, source="
|
17 |
"""
|
18 |
-
@param api_key: your
|
19 |
Get one here: https://www.deepl.com/docs-api/accessing-the-api/
|
20 |
@param source: source language
|
21 |
@param target: target language
|
@@ -24,73 +24,63 @@ class DeepL(object):
|
|
24 |
raise ServerException(401)
|
25 |
self.version = 'v2'
|
26 |
self.api_key = api_key
|
27 |
-
|
28 |
-
|
29 |
-
if use_free_api:
|
30 |
-
self.__base_url = BASE_URLS.get(
|
31 |
-
"DEEPL_FREE").format(version=self.version)
|
32 |
-
else:
|
33 |
-
self.__base_url = BASE_URLS.get(
|
34 |
"DEEPL").format(version=self.version)
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
def translate(self, text, **kwargs):
|
37 |
"""
|
38 |
@param text: text to translate
|
39 |
@return: translated text
|
40 |
"""
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
raise
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
def translate_batch(self, batch, **kwargs):
|
68 |
"""
|
69 |
@param batch: list of texts to translate
|
70 |
@return: list of translations
|
71 |
"""
|
72 |
-
return
|
73 |
-
|
74 |
-
@staticmethod
|
75 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
76 |
-
return [*DeepL._languages.keys()] if not as_dict else DeepL._languages
|
77 |
-
|
78 |
-
def _is_language_supported(self, lang, **kwargs):
|
79 |
-
# The language is supported when is in the dicionary.
|
80 |
-
return lang == 'auto' or lang in self._languages.keys() or lang in self._languages.values()
|
81 |
-
|
82 |
-
def _map_language_to_code(self, lang, **kwargs):
|
83 |
-
if lang in self._languages.keys():
|
84 |
-
return self._languages[lang]
|
85 |
-
elif lang in self._languages.values():
|
86 |
-
return lang
|
87 |
-
raise LanguageNotSupportedException(lang)
|
88 |
-
|
89 |
-
|
90 |
-
BaseTranslator.register(DeepL)
|
91 |
|
92 |
|
93 |
if __name__ == '__main__':
|
94 |
-
d =
|
95 |
-
t = d.translate("
|
96 |
print("text: ", t)
|
|
|
1 |
import requests
|
2 |
+
|
3 |
+
from deep_translator.validate import is_empty, validate_input
|
4 |
+
from deep_translator.constants import BASE_URLS, DEEPL_LANGUAGE_TO_CODE
|
5 |
+
from deep_translator.exceptions import (ServerException,
|
6 |
TranslationNotFound,
|
|
|
7 |
AuthorizationException)
|
8 |
+
from deep_translator.base import BaseTranslator
|
9 |
|
10 |
|
11 |
+
class DeeplTranslator(BaseTranslator):
|
12 |
"""
|
13 |
+
class that wraps functions, which use the DeeplTranslator translator under the hood to translate word(s)
|
14 |
"""
|
|
|
15 |
|
16 |
+
def __init__(self, api_key=None, source="de", target="en", use_free_api=True, **kwargs):
|
17 |
"""
|
18 |
+
@param api_key: your DeeplTranslator api key.
|
19 |
Get one here: https://www.deepl.com/docs-api/accessing-the-api/
|
20 |
@param source: source language
|
21 |
@param target: target language
|
|
|
24 |
raise ServerException(401)
|
25 |
self.version = 'v2'
|
26 |
self.api_key = api_key
|
27 |
+
url = BASE_URLS.get(
|
28 |
+
"DEEPL_FREE").format(version=self.version) if use_free_api else BASE_URLS.get(
|
|
|
|
|
|
|
|
|
|
|
29 |
"DEEPL").format(version=self.version)
|
30 |
+
super().__init__(
|
31 |
+
base_url=url,
|
32 |
+
source=source,
|
33 |
+
target=target,
|
34 |
+
languages=DEEPL_LANGUAGE_TO_CODE,
|
35 |
+
**kwargs)
|
36 |
|
37 |
def translate(self, text, **kwargs):
|
38 |
"""
|
39 |
@param text: text to translate
|
40 |
@return: translated text
|
41 |
"""
|
42 |
+
if validate_input(text):
|
43 |
+
if self._same_source_target() or is_empty(text):
|
44 |
+
return text
|
45 |
+
|
46 |
+
# Create the request parameters.
|
47 |
+
translate_endpoint = 'translate'
|
48 |
+
params = {
|
49 |
+
"auth_key": self.api_key,
|
50 |
+
"source_lang": self._source,
|
51 |
+
"target_lang": self._target,
|
52 |
+
"text": text
|
53 |
+
}
|
54 |
+
# Do the request and check the connection.
|
55 |
+
try:
|
56 |
+
response = requests.get(
|
57 |
+
self._base_url + translate_endpoint, params=params)
|
58 |
+
except ConnectionError:
|
59 |
+
raise ServerException(503)
|
60 |
+
# If the answer is not success, raise server exception.
|
61 |
+
if response.status_code == 403:
|
62 |
+
raise AuthorizationException(self.api_key)
|
63 |
+
elif response.status_code != 200:
|
64 |
+
raise ServerException(response.status_code)
|
65 |
+
# Get the response and check is not empty.
|
66 |
+
res = response.json()
|
67 |
+
if not res:
|
68 |
+
raise TranslationNotFound(text)
|
69 |
+
# Process and return the response.
|
70 |
+
return res['translations'][0]['text']
|
71 |
+
|
72 |
+
def translate_file(self, path, **kwargs):
|
73 |
+
return self._translate_file(path, **kwargs)
|
74 |
|
75 |
def translate_batch(self, batch, **kwargs):
|
76 |
"""
|
77 |
@param batch: list of texts to translate
|
78 |
@return: list of translations
|
79 |
"""
|
80 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
|
83 |
if __name__ == '__main__':
|
84 |
+
d = DeeplTranslator(target="en", api_key="some-key")
|
85 |
+
t = d.translate("Ich habe keine ahnung")
|
86 |
print("text: ", t)
|
deep_translator/detection.py
CHANGED
@@ -7,6 +7,7 @@ from requests.exceptions import HTTPError
|
|
7 |
# Module global config
|
8 |
config = {"url": 'https://ws.detectlanguage.com/0.2/detect',"headers": {'User-Agent': 'Detect Language API Python Client 1.4.0','Authorization': 'Bearer {}',}}
|
9 |
|
|
|
10 |
def get_request_body(text, api_key, *args, **kwargs):
|
11 |
"""
|
12 |
send a request and return the response body parsed as dictionary
|
|
|
7 |
# Module global config
|
8 |
config = {"url": 'https://ws.detectlanguage.com/0.2/detect',"headers": {'User-Agent': 'Detect Language API Python Client 1.4.0','Authorization': 'Bearer {}',}}
|
9 |
|
10 |
+
|
11 |
def get_request_body(text, api_key, *args, **kwargs):
|
12 |
"""
|
13 |
send a request and return the response body parsed as dictionary
|
deep_translator/engine.py
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
from .parent import BaseTranslator
|
2 |
-
|
3 |
-
# BaseTranslator.register(YandexTranslator)
|
4 |
-
# BaseTranslator.register(QCRI)
|
5 |
-
# BaseTranslator.register(DeepL)
|
6 |
-
# BaseTranslator.register(MicrosoftTranslator)
|
7 |
-
# BaseTranslator.register(PapagoTranslator)
|
8 |
-
|
9 |
-
|
10 |
-
def generate_engines_dict(_all: list, _locals: dict) -> dict:
|
11 |
-
base_translator_type = BaseTranslator
|
12 |
-
|
13 |
-
def is_translator(__object: object) -> bool:
|
14 |
-
try:
|
15 |
-
return issubclass(__object, base_translator_type)
|
16 |
-
except TypeError:
|
17 |
-
return False
|
18 |
-
|
19 |
-
translation_engines = {}
|
20 |
-
for _object in _all:
|
21 |
-
__object = _locals.get(_object, 'failed')
|
22 |
-
key_name = _object.replace('Translator', '').lower()
|
23 |
-
if is_translator(__object):
|
24 |
-
translation_engines.update({key_name: __object})
|
25 |
-
return translation_engines
|
26 |
-
|
27 |
-
|
28 |
-
def engine(engine_name: str, *args, **kwargs) -> BaseTranslator:
|
29 |
-
"""Return translation engine.
|
30 |
-
|
31 |
-
Free and keyless engines are 'google', 'pons', 'linguee', 'mymemory',
|
32 |
-
'libre'.
|
33 |
-
|
34 |
-
Args:
|
35 |
-
engine_name: the name of the engine
|
36 |
-
*args: positional argument to pass to the engine
|
37 |
-
**kwargs: named argument to pass to the engine
|
38 |
-
Return:
|
39 |
-
A translation engine
|
40 |
-
"""
|
41 |
-
try:
|
42 |
-
return engine.translation_engines[engine_name.lower()](*args, **kwargs)
|
43 |
-
except KeyError:
|
44 |
-
keys = '\', \''.join(engine.translation_engines.keys())
|
45 |
-
raise(KeyError(f'Please provide a valid engine name (\'{keys}\')'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deep_translator/engines.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from .base import BaseTranslator
|
3 |
+
|
4 |
+
__engines__ = {
|
5 |
+
translator.__name__.replace('Translator', '').lower():
|
6 |
+
translator for translator in BaseTranslator.__subclasses__()
|
7 |
+
}
|
deep_translator/exceptions.py
CHANGED
@@ -43,11 +43,10 @@ class InvalidSourceOrTargetLanguage(BaseError):
|
|
43 |
|
44 |
def __init__(self,
|
45 |
val,
|
46 |
-
message="source
|
47 |
super(InvalidSourceOrTargetLanguage, self).__init__(val, message)
|
48 |
|
49 |
|
50 |
-
|
51 |
class TranslationNotFound(BaseError):
|
52 |
"""
|
53 |
exception thrown if no translation was found for the text provided by the user
|
|
|
43 |
|
44 |
def __init__(self,
|
45 |
val,
|
46 |
+
message="Invalid source or target language!"):
|
47 |
super(InvalidSourceOrTargetLanguage, self).__init__(val, message)
|
48 |
|
49 |
|
|
|
50 |
class TranslationNotFound(BaseError):
|
51 |
"""
|
52 |
exception thrown if no translation was found for the text provided by the user
|
deep_translator/{google_trans.py → google.py}
RENAMED
@@ -2,118 +2,52 @@
|
|
2 |
google translator API
|
3 |
"""
|
4 |
|
5 |
-
from .constants import BASE_URLS
|
6 |
-
from .exceptions import TooManyRequests,
|
7 |
-
from .
|
|
|
8 |
from bs4 import BeautifulSoup
|
9 |
import requests
|
10 |
-
from time import sleep
|
11 |
-
import warnings
|
12 |
-
import logging
|
13 |
|
14 |
|
15 |
class GoogleTranslator(BaseTranslator):
|
16 |
"""
|
17 |
class that wraps functions, which use google translate under the hood to translate text(s)
|
18 |
"""
|
19 |
-
_languages = GOOGLE_LANGUAGES_TO_CODES
|
20 |
-
supported_languages = list(_languages.keys())
|
21 |
|
22 |
def __init__(self, source="auto", target="en", proxies=None, **kwargs):
|
23 |
"""
|
24 |
@param source: source language to translate from
|
25 |
@param target: target language to translate to
|
26 |
"""
|
27 |
-
self.__base_url = BASE_URLS.get("GOOGLE_TRANSLATE")
|
28 |
self.proxies = proxies
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
source_lower=source.lower()
|
37 |
-
if not target in self._languages.values():
|
38 |
-
target_lower=target.lower()
|
39 |
-
#######################################
|
40 |
-
|
41 |
-
if self.is_language_supported(source_lower, target_lower):
|
42 |
-
self._source, self._target = self._map_language_to_code(source_lower, target_lower)
|
43 |
-
|
44 |
-
super(GoogleTranslator, self).__init__(base_url=self.__base_url,
|
45 |
-
source=self._source,
|
46 |
-
target=self._target,
|
47 |
-
element_tag='div',
|
48 |
-
element_query={"class": "t0"},
|
49 |
-
payload_key='q', # key of text in the url
|
50 |
-
tl=self._target,
|
51 |
-
sl=self._source,
|
52 |
-
**kwargs)
|
53 |
|
54 |
self._alt_element_query = {"class": "result-container"}
|
55 |
|
56 |
-
@staticmethod
|
57 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
58 |
-
"""
|
59 |
-
return the supported languages by the google translator
|
60 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
61 |
-
@return: list or dict
|
62 |
-
"""
|
63 |
-
return GoogleTranslator.supported_languages if not as_dict else GoogleTranslator._languages
|
64 |
-
|
65 |
-
def is_secondary(self, lang):
|
66 |
-
"""
|
67 |
-
Function to check if lang is a secondary name of any primary language
|
68 |
-
@param lang: language name
|
69 |
-
@return: primary name of a language if found otherwise False
|
70 |
-
"""
|
71 |
-
for primary_name, secondary_names in GOOGLE_LANGUAGES_SECONDARY_NAMES.items():
|
72 |
-
if lang in secondary_names:
|
73 |
-
return primary_name
|
74 |
-
return False
|
75 |
-
|
76 |
-
def _map_language_to_code(self, *languages):
|
77 |
-
"""
|
78 |
-
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
79 |
-
@param languages: list of languages
|
80 |
-
@return: mapped value of the language or raise an exception if the language is not supported
|
81 |
-
"""
|
82 |
-
for language in languages:
|
83 |
-
if language in self._languages.values() or language == 'auto':
|
84 |
-
yield language
|
85 |
-
elif language in self._languages.keys():
|
86 |
-
yield self._languages[language]
|
87 |
-
else:
|
88 |
-
yield self._languages[self.is_secondary(language)]
|
89 |
-
|
90 |
-
def is_language_supported(self, *languages):
|
91 |
-
"""
|
92 |
-
check if the language is supported by the translator
|
93 |
-
@param languages: list of languages
|
94 |
-
@return: bool or raise an Exception
|
95 |
-
"""
|
96 |
-
for lang in languages:
|
97 |
-
if lang != 'auto' and lang not in self._languages.keys():
|
98 |
-
if lang != 'auto' and lang not in self._languages.values():
|
99 |
-
if not self.is_secondary(lang):
|
100 |
-
raise LanguageNotSupportedException(lang)
|
101 |
-
return True
|
102 |
-
|
103 |
def translate(self, text, **kwargs):
|
104 |
"""
|
105 |
function that uses google translate to translate a text
|
106 |
@param text: desired text to translate
|
107 |
@return: str: translated text
|
108 |
"""
|
109 |
-
|
110 |
-
if self._validate_payload(text):
|
111 |
text = text.strip()
|
|
|
|
|
|
|
|
|
112 |
|
113 |
if self.payload_key:
|
114 |
self._url_params[self.payload_key] = text
|
115 |
|
116 |
-
response = requests.get(self.
|
117 |
params=self._url_params,
|
118 |
proxies=self.proxies)
|
119 |
if response.status_code == 429:
|
@@ -151,37 +85,7 @@ class GoogleTranslator(BaseTranslator):
|
|
151 |
@param kwargs: additional args
|
152 |
@return: str
|
153 |
"""
|
154 |
-
|
155 |
-
with open(path, 'r', encoding='utf-8') as f:
|
156 |
-
text = f.read().strip()
|
157 |
-
return self.translate(text)
|
158 |
-
except Exception as e:
|
159 |
-
raise e
|
160 |
-
|
161 |
-
def translate_sentences(self, sentences=None, **kwargs):
|
162 |
-
"""
|
163 |
-
translate many sentences together. This makes sense if you have sentences with different languages
|
164 |
-
and you want to translate all to unified language. This is handy because it detects
|
165 |
-
automatically the language of each sentence and then translate it.
|
166 |
-
|
167 |
-
@param sentences: list of sentences to translate
|
168 |
-
@return: list of all translated sentences
|
169 |
-
"""
|
170 |
-
warnings.warn("deprecated. Use the translate_batch function instead", DeprecationWarning, stacklevel=2)
|
171 |
-
logging.warning("deprecated. Use the translate_batch function instead")
|
172 |
-
if not sentences:
|
173 |
-
raise NotValidPayload(sentences)
|
174 |
-
|
175 |
-
translated_sentences = []
|
176 |
-
try:
|
177 |
-
for sentence in sentences:
|
178 |
-
translated = self.translate(text=sentence)
|
179 |
-
translated_sentences.append(translated)
|
180 |
-
|
181 |
-
return translated_sentences
|
182 |
-
|
183 |
-
except Exception as e:
|
184 |
-
raise e
|
185 |
|
186 |
def translate_batch(self, batch=None, **kwargs):
|
187 |
"""
|
@@ -189,12 +93,9 @@ class GoogleTranslator(BaseTranslator):
|
|
189 |
@param batch: list of texts you want to translate
|
190 |
@return: list of translations
|
191 |
"""
|
192 |
-
|
193 |
-
raise Exception("Enter your text list that you want to translate")
|
194 |
-
arr = []
|
195 |
-
for i, text in enumerate(batch):
|
196 |
|
197 |
-
translated = self.translate(text, **kwargs)
|
198 |
-
arr.append(translated)
|
199 |
-
return arr
|
200 |
|
|
|
|
|
|
|
|
2 |
google translator API
|
3 |
"""
|
4 |
|
5 |
+
from deep_translator.constants import BASE_URLS
|
6 |
+
from deep_translator.exceptions import TooManyRequests, TranslationNotFound, RequestError
|
7 |
+
from deep_translator.base import BaseTranslator
|
8 |
+
from deep_translator.validate import validate_input, is_empty
|
9 |
from bs4 import BeautifulSoup
|
10 |
import requests
|
|
|
|
|
|
|
11 |
|
12 |
|
13 |
class GoogleTranslator(BaseTranslator):
|
14 |
"""
|
15 |
class that wraps functions, which use google translate under the hood to translate text(s)
|
16 |
"""
|
|
|
|
|
17 |
|
18 |
def __init__(self, source="auto", target="en", proxies=None, **kwargs):
|
19 |
"""
|
20 |
@param source: source language to translate from
|
21 |
@param target: target language to translate to
|
22 |
"""
|
|
|
23 |
self.proxies = proxies
|
24 |
+
super().__init__(base_url=BASE_URLS.get("GOOGLE_TRANSLATE"),
|
25 |
+
source=source,
|
26 |
+
target=target,
|
27 |
+
element_tag='div',
|
28 |
+
element_query={"class": "t0"},
|
29 |
+
payload_key='q', # key of text in the url
|
30 |
+
**kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
self._alt_element_query = {"class": "result-container"}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
def translate(self, text, **kwargs):
|
35 |
"""
|
36 |
function that uses google translate to translate a text
|
37 |
@param text: desired text to translate
|
38 |
@return: str: translated text
|
39 |
"""
|
40 |
+
if validate_input(text):
|
|
|
41 |
text = text.strip()
|
42 |
+
if self._same_source_target() or is_empty(text):
|
43 |
+
return text
|
44 |
+
self._url_params['tl'] = self._target
|
45 |
+
self._url_params['sl'] = self._source
|
46 |
|
47 |
if self.payload_key:
|
48 |
self._url_params[self.payload_key] = text
|
49 |
|
50 |
+
response = requests.get(self._base_url,
|
51 |
params=self._url_params,
|
52 |
proxies=self.proxies)
|
53 |
if response.status_code == 429:
|
|
|
85 |
@param kwargs: additional args
|
86 |
@return: str
|
87 |
"""
|
88 |
+
return self._translate_file(path, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
|
90 |
def translate_batch(self, batch=None, **kwargs):
|
91 |
"""
|
|
|
93 |
@param batch: list of texts you want to translate
|
94 |
@return: list of translations
|
95 |
"""
|
96 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
|
97 |
|
|
|
|
|
|
|
98 |
|
99 |
+
if __name__ == '__main__':
|
100 |
+
t = GoogleTranslator().translate("hallo welt")
|
101 |
+
print("translation: ", t)
|
deep_translator/libre.py
CHANGED
@@ -3,71 +3,34 @@ LibreTranslate API
|
|
3 |
"""
|
4 |
|
5 |
import requests
|
6 |
-
|
7 |
-
from .
|
|
|
|
|
8 |
from .exceptions import (ServerException,
|
9 |
-
|
10 |
-
|
11 |
-
AuthorizationException,
|
12 |
-
NotValidPayload)
|
13 |
|
14 |
|
15 |
class LibreTranslator(BaseTranslator):
|
16 |
"""
|
17 |
class that wraps functions, which use libre translator under the hood to translate text(s)
|
18 |
"""
|
19 |
-
_languages = LIBRE_LANGUAGES_TO_CODES
|
20 |
-
supported_languages = list(_languages.keys())
|
21 |
|
22 |
-
def __init__(self,source="auto", target="en",
|
23 |
"""
|
24 |
@param source: source language to translate from
|
25 |
List of LibreTranslate nedpoints can be found at : https://github.com/LibreTranslate/LibreTranslate#mirrors
|
26 |
Some require an API key
|
27 |
@param target: target language to translate to
|
28 |
"""
|
29 |
-
if
|
30 |
raise ServerException(401)
|
31 |
-
self.__base_url = base_url
|
32 |
self.api_key = api_key
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
self.target = self._map_language_to_code(target)
|
38 |
-
|
39 |
-
|
40 |
-
@staticmethod
|
41 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
42 |
-
"""
|
43 |
-
return the supported languages by the libre translator
|
44 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
45 |
-
@return: list or dict
|
46 |
-
"""
|
47 |
-
return [*LibreTranslator._languages.keys()] if not as_dict else LibreTranslator._languages
|
48 |
-
|
49 |
-
def _map_language_to_code(self, language, **kwargs):
|
50 |
-
"""
|
51 |
-
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
52 |
-
@param language: a string for 1 language
|
53 |
-
@return: mapped value of the language or raise an exception if the language is not supported
|
54 |
-
"""
|
55 |
-
if language in self._languages.keys():
|
56 |
-
return self._languages[language]
|
57 |
-
elif language in self._languages.values():
|
58 |
-
return language
|
59 |
-
raise LanguageNotSupportedException(language)
|
60 |
-
|
61 |
-
def _is_language_supported(self, language, **kwargs):
|
62 |
-
"""
|
63 |
-
check if the language is supported by the translator
|
64 |
-
@param language: a string for 1 language
|
65 |
-
@return: bool or raise an Exception
|
66 |
-
"""
|
67 |
-
if language == 'auto' or language in self._languages.keys() or language in self._languages.values():
|
68 |
-
return True
|
69 |
-
else:
|
70 |
-
raise LanguageNotSupportedException(language)
|
71 |
|
72 |
def translate(self, text, **kwargs):
|
73 |
"""
|
@@ -75,37 +38,37 @@ class LibreTranslator(BaseTranslator):
|
|
75 |
@param text: desired text to translate
|
76 |
@return: str: translated text
|
77 |
"""
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
|
110 |
def translate_file(self, path, **kwargs):
|
111 |
"""
|
@@ -115,12 +78,7 @@ class LibreTranslator(BaseTranslator):
|
|
115 |
@param kwargs: additional args
|
116 |
@return: str
|
117 |
"""
|
118 |
-
|
119 |
-
with open(path, 'r', encoding='utf-8') as f:
|
120 |
-
text = f.read().strip()
|
121 |
-
return self.translate(text)
|
122 |
-
except Exception as e:
|
123 |
-
raise e
|
124 |
|
125 |
def translate_batch(self, batch=None, **kwargs):
|
126 |
"""
|
@@ -128,10 +86,4 @@ class LibreTranslator(BaseTranslator):
|
|
128 |
@param batch: list of texts you want to translate
|
129 |
@return: list of translations
|
130 |
"""
|
131 |
-
|
132 |
-
raise Exception("Enter your text list that you want to translate")
|
133 |
-
arr = []
|
134 |
-
for i, text in enumerate(batch):
|
135 |
-
translated = self.translate(text, **kwargs)
|
136 |
-
arr.append(translated)
|
137 |
-
return arr
|
|
|
3 |
"""
|
4 |
|
5 |
import requests
|
6 |
+
|
7 |
+
from .validate import is_empty, validate_input
|
8 |
+
from .base import BaseTranslator
|
9 |
+
from .constants import BASE_URLS,LIBRE_LANGUAGES_TO_CODES
|
10 |
from .exceptions import (ServerException,
|
11 |
+
TranslationNotFound,
|
12 |
+
AuthorizationException)
|
|
|
|
|
13 |
|
14 |
|
15 |
class LibreTranslator(BaseTranslator):
|
16 |
"""
|
17 |
class that wraps functions, which use libre translator under the hood to translate text(s)
|
18 |
"""
|
|
|
|
|
19 |
|
20 |
+
def __init__(self, source="auto", target="en", api_key=None, **kwargs):
|
21 |
"""
|
22 |
@param source: source language to translate from
|
23 |
List of LibreTranslate nedpoints can be found at : https://github.com/LibreTranslate/LibreTranslate#mirrors
|
24 |
Some require an API key
|
25 |
@param target: target language to translate to
|
26 |
"""
|
27 |
+
if not api_key:
|
28 |
raise ServerException(401)
|
|
|
29 |
self.api_key = api_key
|
30 |
+
super().__init__(base_url=BASE_URLS.get("LIBRE"),
|
31 |
+
source=source,
|
32 |
+
target=target,
|
33 |
+
languages=LIBRE_LANGUAGES_TO_CODES)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
def translate(self, text, **kwargs):
|
36 |
"""
|
|
|
38 |
@param text: desired text to translate
|
39 |
@return: str: translated text
|
40 |
"""
|
41 |
+
if validate_input(text):
|
42 |
+
if self._same_source_target() or is_empty(text):
|
43 |
+
return text
|
44 |
|
45 |
+
translate_endpoint = 'translate'
|
46 |
+
params = {
|
47 |
+
"q": text,
|
48 |
+
"source": self._source,
|
49 |
+
"target": self._target,
|
50 |
+
"format": 'text'
|
51 |
+
}
|
52 |
+
# Add API Key if required
|
53 |
+
if self.api_key:
|
54 |
+
params["api_key"] = self.api_key
|
55 |
+
# Do the request and check the connection.
|
56 |
+
try:
|
57 |
+
response = requests.post(self._base_url + translate_endpoint, params=params)
|
58 |
+
except ConnectionError:
|
59 |
+
raise ServerException(503)
|
60 |
+
# If the answer is not success, raise server exception.
|
61 |
|
62 |
+
if response.status_code == 403:
|
63 |
+
raise AuthorizationException(self.api_key)
|
64 |
+
elif response.status_code != 200:
|
65 |
+
raise ServerException(response.status_code)
|
66 |
+
# Get the response and check is not empty.
|
67 |
+
res = response.json()
|
68 |
+
if not res:
|
69 |
+
raise TranslationNotFound(text)
|
70 |
+
# Process and return the response.
|
71 |
+
return res['translatedText']
|
72 |
|
73 |
def translate_file(self, path, **kwargs):
|
74 |
"""
|
|
|
78 |
@param kwargs: additional args
|
79 |
@return: str
|
80 |
"""
|
81 |
+
return self._translate_file(path, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
def translate_batch(self, batch=None, **kwargs):
|
84 |
"""
|
|
|
86 |
@param batch: list of texts you want to translate
|
87 |
@return: list of translations
|
88 |
"""
|
89 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
deep_translator/linguee.py
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
"""
|
2 |
linguee translator API
|
3 |
"""
|
4 |
-
|
5 |
-
from .constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES
|
6 |
-
from .exceptions import (
|
7 |
TranslationNotFound,
|
8 |
NotValidPayload,
|
9 |
ElementNotFoundInGetRequest,
|
10 |
RequestError,
|
11 |
TooManyRequests)
|
12 |
-
from .
|
13 |
from bs4 import BeautifulSoup
|
14 |
import requests
|
15 |
from requests.utils import requote_uri
|
@@ -19,63 +19,22 @@ class LingueeTranslator(BaseTranslator):
|
|
19 |
"""
|
20 |
class that wraps functions, which use the linguee translator under the hood to translate word(s)
|
21 |
"""
|
22 |
-
_languages = LINGUEE_LANGUAGES_TO_CODES
|
23 |
-
supported_languages = list(_languages.keys())
|
24 |
|
25 |
def __init__(self, source, target="en", proxies=None, **kwargs):
|
26 |
"""
|
27 |
@param source: source language to translate from
|
28 |
@param target: target language to translate to
|
29 |
"""
|
30 |
-
self.__base_url = BASE_URLS.get("LINGUEE")
|
31 |
self.proxies = proxies
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
super().__init__(base_url=self.__base_url,
|
37 |
-
source=self._source,
|
38 |
-
target=self._target,
|
39 |
element_tag='a',
|
40 |
element_query={'class': 'dictLink featured'},
|
41 |
payload_key=None, # key of text in the url
|
42 |
)
|
43 |
|
44 |
-
@staticmethod
|
45 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
46 |
-
"""
|
47 |
-
return the supported languages by the linguee translator
|
48 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
49 |
-
@return: list or dict
|
50 |
-
"""
|
51 |
-
return LingueeTranslator.supported_languages if not as_dict else LingueeTranslator._languages
|
52 |
-
|
53 |
-
def _map_language_to_code(self, *languages, **kwargs):
|
54 |
-
"""
|
55 |
-
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
56 |
-
@param languages: list of languages
|
57 |
-
@return: mapped value of the language or raise an exception if the language is not supported
|
58 |
-
"""
|
59 |
-
for language in languages:
|
60 |
-
if language in self._languages.values():
|
61 |
-
yield LINGUEE_CODE_TO_LANGUAGE[language]
|
62 |
-
elif language in self._languages.keys():
|
63 |
-
yield language
|
64 |
-
else:
|
65 |
-
raise LanguageNotSupportedException(language)
|
66 |
-
|
67 |
-
def is_language_supported(self, *languages, **kwargs):
|
68 |
-
"""
|
69 |
-
check if the language is supported by the translator
|
70 |
-
@param languages: list of languages
|
71 |
-
@return: bool or raise an Exception
|
72 |
-
"""
|
73 |
-
for lang in languages:
|
74 |
-
if lang not in self._languages.keys():
|
75 |
-
if lang not in self._languages.values():
|
76 |
-
raise LanguageNotSupportedException(lang)
|
77 |
-
return True
|
78 |
-
|
79 |
def translate(self, word, return_all=False, **kwargs):
|
80 |
"""
|
81 |
function that uses linguee to translate a word
|
@@ -85,9 +44,12 @@ class LingueeTranslator(BaseTranslator):
|
|
85 |
@type return_all: bool
|
86 |
@return: str: translated word
|
87 |
"""
|
88 |
-
if self.
|
|
|
|
|
|
|
89 |
# %s-%s/translation/%s.html
|
90 |
-
url = "{}{}-{}/translation/{}.html".format(self.
|
91 |
url = requote_uri(url)
|
92 |
response = requests.get(url, proxies=self.proxies)
|
93 |
|
|
|
1 |
"""
|
2 |
linguee translator API
|
3 |
"""
|
4 |
+
from .validate import validate_input, is_empty
|
5 |
+
from .constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES
|
6 |
+
from .exceptions import (
|
7 |
TranslationNotFound,
|
8 |
NotValidPayload,
|
9 |
ElementNotFoundInGetRequest,
|
10 |
RequestError,
|
11 |
TooManyRequests)
|
12 |
+
from .base import BaseTranslator
|
13 |
from bs4 import BeautifulSoup
|
14 |
import requests
|
15 |
from requests.utils import requote_uri
|
|
|
19 |
"""
|
20 |
class that wraps functions, which use the linguee translator under the hood to translate word(s)
|
21 |
"""
|
|
|
|
|
22 |
|
23 |
def __init__(self, source, target="en", proxies=None, **kwargs):
|
24 |
"""
|
25 |
@param source: source language to translate from
|
26 |
@param target: target language to translate to
|
27 |
"""
|
|
|
28 |
self.proxies = proxies
|
29 |
+
super().__init__(base_url=BASE_URLS.get("LINGUEE"),
|
30 |
+
source=source,
|
31 |
+
target=target,
|
32 |
+
languages=LINGUEE_LANGUAGES_TO_CODES,
|
|
|
|
|
|
|
33 |
element_tag='a',
|
34 |
element_query={'class': 'dictLink featured'},
|
35 |
payload_key=None, # key of text in the url
|
36 |
)
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
def translate(self, word, return_all=False, **kwargs):
|
39 |
"""
|
40 |
function that uses linguee to translate a word
|
|
|
44 |
@type return_all: bool
|
45 |
@return: str: translated word
|
46 |
"""
|
47 |
+
if self._same_source_target() or is_empty(word):
|
48 |
+
return word
|
49 |
+
|
50 |
+
if validate_input(word, max_chars=50):
|
51 |
# %s-%s/translation/%s.html
|
52 |
+
url = "{}{}-{}/translation/{}.html".format(self._base_url, self._source, self._target, word)
|
53 |
url = requote_uri(url)
|
54 |
response = requests.get(url, proxies=self.proxies)
|
55 |
|
deep_translator/microsoft.py
CHANGED
@@ -3,31 +3,30 @@
|
|
3 |
import requests
|
4 |
import logging
|
5 |
import sys
|
|
|
|
|
|
|
|
|
6 |
|
7 |
-
from .constants import BASE_URLS, MICROSOFT_CODES_TO_LANGUAGES
|
8 |
-
from .exceptions import LanguageNotSupportedException, ServerException, MicrosoftAPIerror
|
9 |
-
from .parent import BaseTranslator
|
10 |
|
11 |
-
|
12 |
-
class MicrosoftTranslator:
|
13 |
"""
|
14 |
the class that wraps functions, which use the Microsoft translator under the hood to translate word(s)
|
15 |
"""
|
16 |
|
17 |
-
_languages = MICROSOFT_CODES_TO_LANGUAGES
|
18 |
-
supported_languages = list(_languages.values())
|
19 |
-
|
20 |
def __init__(self, api_key=None, region=None, source=None, target=None, proxies=None, **kwargs):
|
21 |
"""
|
22 |
@params api_key and target are the required params
|
23 |
@param api_key: your Microsoft API key
|
24 |
@param region: your Microsoft Location
|
25 |
"""
|
|
|
|
|
|
|
26 |
if not api_key:
|
27 |
raise ServerException(401)
|
28 |
-
else:
|
29 |
-
self.api_key = api_key
|
30 |
|
|
|
31 |
self.proxies = proxies
|
32 |
self.headers = {
|
33 |
"Ocp-Apim-Subscription-Key": self.api_key,
|
@@ -37,65 +36,22 @@ class MicrosoftTranslator:
|
|
37 |
if region:
|
38 |
self.region = region
|
39 |
self.headers["Ocp-Apim-Subscription-Region"] = self.region
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
|
42 |
-
raise ServerException(401)
|
43 |
-
else:
|
44 |
-
if type(target) is str:
|
45 |
-
self.target = target.lower()
|
46 |
-
else:
|
47 |
-
self.target = [i.lower() for i in target]
|
48 |
-
if self.is_language_supported(self.target):
|
49 |
-
self.target = self._map_language_to_code(self.target)
|
50 |
-
|
51 |
-
self.url_params = {'to': self.target, **kwargs}
|
52 |
-
|
53 |
-
if source:
|
54 |
-
self.source = source.lower()
|
55 |
-
if self.is_language_supported(self.source):
|
56 |
-
self.source = self._map_language_to_code(self.source)
|
57 |
-
self.url_params['from'] = self.source
|
58 |
-
|
59 |
-
self.__base_url = BASE_URLS.get("MICROSOFT_TRANSLATE")
|
60 |
-
|
61 |
-
@staticmethod
|
62 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
63 |
-
"""
|
64 |
-
return the languages supported by the microsoft translator
|
65 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
66 |
-
@return: list or dict
|
67 |
-
"""
|
68 |
-
return MicrosoftTranslator.supported_languages if not as_dict else MicrosoftTranslator._languages
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
if type(language) is str:
|
77 |
-
language = [language]
|
78 |
-
for lang in language:
|
79 |
-
if lang in self._languages.values():
|
80 |
-
yield lang
|
81 |
-
elif lang in self._languages.keys():
|
82 |
-
yield self._languages[lang]
|
83 |
-
else:
|
84 |
-
raise LanguageNotSupportedException(lang)
|
85 |
-
|
86 |
-
def is_language_supported(self, language, **kwargs):
|
87 |
-
"""
|
88 |
-
check if the language is supported by the translator
|
89 |
-
@param language: a string (if 1 lang) or a list (if multiple langs)
|
90 |
-
@return: bool or raise an Exception
|
91 |
-
"""
|
92 |
-
if type(language) is str:
|
93 |
-
language = [language]
|
94 |
-
for lang in language:
|
95 |
-
if lang not in self._languages.keys():
|
96 |
-
if lang not in self._languages.values():
|
97 |
-
raise LanguageNotSupportedException(lang)
|
98 |
-
return True
|
99 |
|
100 |
def translate(self, text, **kwargs):
|
101 |
"""
|
@@ -105,26 +61,31 @@ class MicrosoftTranslator:
|
|
105 |
"""
|
106 |
# a body must be a list of dicts to process multiple texts;
|
107 |
# I have not added multiple text processing here since it is covered by the translate_batch method
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
def translate_file(self, path, **kwargs):
|
130 |
"""
|
@@ -132,12 +93,7 @@ class MicrosoftTranslator:
|
|
132 |
@param path: path to file
|
133 |
@return: translated text
|
134 |
"""
|
135 |
-
|
136 |
-
with open(path, 'r', encoding='utf-8') as f:
|
137 |
-
text = f.read().strip()
|
138 |
-
return self.translate(text)
|
139 |
-
except Exception as e:
|
140 |
-
raise e
|
141 |
|
142 |
def translate_batch(self, batch, **kwargs):
|
143 |
"""
|
@@ -145,7 +101,4 @@ class MicrosoftTranslator:
|
|
145 |
@param batch: list of texts to translate
|
146 |
@return: list of translations
|
147 |
"""
|
148 |
-
return
|
149 |
-
|
150 |
-
|
151 |
-
BaseTranslator.register(MicrosoftTranslator)
|
|
|
3 |
import requests
|
4 |
import logging
|
5 |
import sys
|
6 |
+
from .constants import BASE_URLS
|
7 |
+
from .exceptions import ServerException, MicrosoftAPIerror
|
8 |
+
from .base import BaseTranslator
|
9 |
+
from .validate import validate_input
|
10 |
|
|
|
|
|
|
|
11 |
|
12 |
+
class MicrosoftTranslator(BaseTranslator):
|
|
|
13 |
"""
|
14 |
the class that wraps functions, which use the Microsoft translator under the hood to translate word(s)
|
15 |
"""
|
16 |
|
|
|
|
|
|
|
17 |
def __init__(self, api_key=None, region=None, source=None, target=None, proxies=None, **kwargs):
|
18 |
"""
|
19 |
@params api_key and target are the required params
|
20 |
@param api_key: your Microsoft API key
|
21 |
@param region: your Microsoft Location
|
22 |
"""
|
23 |
+
|
24 |
+
MICROSOFT_CODES_TO_LANGUAGES = self._get_supported_languages()
|
25 |
+
|
26 |
if not api_key:
|
27 |
raise ServerException(401)
|
|
|
|
|
28 |
|
29 |
+
self.api_key = api_key
|
30 |
self.proxies = proxies
|
31 |
self.headers = {
|
32 |
"Ocp-Apim-Subscription-Key": self.api_key,
|
|
|
36 |
if region:
|
37 |
self.region = region
|
38 |
self.headers["Ocp-Apim-Subscription-Region"] = self.region
|
39 |
+
super().__init__(
|
40 |
+
base_url=BASE_URLS.get("MICROSOFT_TRANSLATE"),
|
41 |
+
source=source,
|
42 |
+
target=target,
|
43 |
+
languages=MICROSOFT_CODES_TO_LANGUAGES,
|
44 |
+
**kwargs
|
45 |
+
)
|
46 |
|
47 |
+
def _get_supported_languages(self):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
+
microsoft_languages_api_url = \
|
50 |
+
"https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation"
|
51 |
+
microsoft_languages_response = requests.get(microsoft_languages_api_url)
|
52 |
+
translation_dict = microsoft_languages_response.json()['translation']
|
53 |
+
|
54 |
+
return {translation_dict[k]['name'].lower(): k for k in translation_dict.keys()}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
def translate(self, text, **kwargs):
|
57 |
"""
|
|
|
61 |
"""
|
62 |
# a body must be a list of dicts to process multiple texts;
|
63 |
# I have not added multiple text processing here since it is covered by the translate_batch method
|
64 |
+
|
65 |
+
if validate_input(text):
|
66 |
+
self._url_params['from'] = self._source
|
67 |
+
self._url_params['to'] = self._target
|
68 |
+
|
69 |
+
valid_microsoft_json = [{'text': text}]
|
70 |
+
try:
|
71 |
+
requested = requests.post(self._base_url,
|
72 |
+
params=self._url_params,
|
73 |
+
headers=self.headers,
|
74 |
+
json=valid_microsoft_json,
|
75 |
+
proxies=self.proxies)
|
76 |
+
except requests.exceptions.RequestException:
|
77 |
+
exc_type, value, traceback = sys.exc_info()
|
78 |
+
logging.warning(f"Returned error: {exc_type.__name__}")
|
79 |
+
|
80 |
+
# Where Microsoft API responds with an api error, it returns a dict in response.json()
|
81 |
+
if type(requested.json()) is dict:
|
82 |
+
error_message = requested.json()['error']
|
83 |
+
raise MicrosoftAPIerror(error_message)
|
84 |
+
# Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
|
85 |
+
elif type(requested.json()) is list:
|
86 |
+
all_translations = [i['text']
|
87 |
+
for i in requested.json()[0]['translations']]
|
88 |
+
return "\n".join(all_translations)
|
89 |
|
90 |
def translate_file(self, path, **kwargs):
|
91 |
"""
|
|
|
93 |
@param path: path to file
|
94 |
@return: translated text
|
95 |
"""
|
96 |
+
return self._translate_file(path, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
def translate_batch(self, batch, **kwargs):
|
99 |
"""
|
|
|
101 |
@param batch: list of texts to translate
|
102 |
@return: list of translations
|
103 |
"""
|
104 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
deep_translator/mymemory.py
CHANGED
@@ -1,79 +1,32 @@
|
|
1 |
"""
|
2 |
mymemory translator API
|
3 |
"""
|
4 |
-
import
|
5 |
-
import
|
6 |
-
|
7 |
-
from .constants import BASE_URLS, GOOGLE_LANGUAGES_TO_CODES
|
8 |
-
from .exceptions import (NotValidPayload,
|
9 |
TranslationNotFound,
|
10 |
-
LanguageNotSupportedException,
|
11 |
RequestError,
|
12 |
TooManyRequests)
|
13 |
-
from .
|
14 |
import requests
|
15 |
-
from time import sleep
|
16 |
|
17 |
|
18 |
class MyMemoryTranslator(BaseTranslator):
|
19 |
"""
|
20 |
class that uses the mymemory translator to translate texts
|
21 |
"""
|
22 |
-
_languages = GOOGLE_LANGUAGES_TO_CODES
|
23 |
-
supported_languages = list(_languages.keys())
|
24 |
-
|
25 |
def __init__(self, source="auto", target="en", proxies=None, **kwargs):
|
26 |
"""
|
27 |
@param source: source language to translate from
|
28 |
@param target: target language to translate to
|
29 |
"""
|
30 |
-
self.__base_url = BASE_URLS.get("MYMEMORY")
|
31 |
self.proxies = proxies
|
32 |
-
if self.is_language_supported(source, target):
|
33 |
-
self._source, self._target = self._map_language_to_code(source.lower(), target.lower())
|
34 |
-
self._source = self._source if self._source != 'auto' else 'Lao'
|
35 |
-
|
36 |
self.email = kwargs.get('email', None)
|
37 |
-
super(
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
@staticmethod
|
44 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
45 |
-
"""
|
46 |
-
return the supported languages by the mymemory translator
|
47 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
48 |
-
@return: list or dict
|
49 |
-
"""
|
50 |
-
return MyMemoryTranslator.supported_languages if not as_dict else MyMemoryTranslator._languages
|
51 |
-
|
52 |
-
def _map_language_to_code(self, *languages):
|
53 |
-
"""
|
54 |
-
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
55 |
-
@param languages: list of languages
|
56 |
-
@return: mapped value of the language or raise an exception if the language is not supported
|
57 |
-
"""
|
58 |
-
for language in languages:
|
59 |
-
if language in self._languages.values() or language == 'auto':
|
60 |
-
yield language
|
61 |
-
elif language in self._languages.keys():
|
62 |
-
yield self._languages[language]
|
63 |
-
else:
|
64 |
-
raise LanguageNotSupportedException(language)
|
65 |
-
|
66 |
-
def is_language_supported(self, *languages):
|
67 |
-
"""
|
68 |
-
check if the language is supported by the translator
|
69 |
-
@param languages: list of languages
|
70 |
-
@return: bool or raise an Exception
|
71 |
-
"""
|
72 |
-
for lang in languages:
|
73 |
-
if lang != 'auto' and lang not in self._languages.keys():
|
74 |
-
if lang != 'auto' and lang not in self._languages.values():
|
75 |
-
raise LanguageNotSupportedException(lang)
|
76 |
-
return True
|
77 |
|
78 |
def translate(self, text, return_all=False, **kwargs):
|
79 |
"""
|
@@ -83,18 +36,19 @@ class MyMemoryTranslator(BaseTranslator):
|
|
83 |
@param return_all: set to True to return all synonym/similars of the translated text
|
84 |
@return: str or list
|
85 |
"""
|
86 |
-
|
87 |
-
if self._validate_payload(text, max_chars=500):
|
88 |
text = text.strip()
|
|
|
|
|
89 |
|
|
|
90 |
if self.payload_key:
|
91 |
self._url_params[self.payload_key] = text
|
92 |
if self.email:
|
93 |
self._url_params['de'] = self.email
|
94 |
|
95 |
-
response = requests.get(self.
|
96 |
params=self._url_params,
|
97 |
-
headers=self.headers,
|
98 |
proxies=self.proxies)
|
99 |
|
100 |
if response.status_code == 429:
|
@@ -116,32 +70,6 @@ class MyMemoryTranslator(BaseTranslator):
|
|
116 |
next_match = next(matches)
|
117 |
return next_match if not return_all else list(all_matches)
|
118 |
|
119 |
-
def translate_sentences(self, sentences=None, **kwargs):
|
120 |
-
"""
|
121 |
-
translate many sentences together. This makes sense if you have sentences with different languages
|
122 |
-
and you want to translate all to unified language. This is handy because it detects
|
123 |
-
automatically the language of each sentence and then translate it.
|
124 |
-
|
125 |
-
@param sentences: list of sentences to translate
|
126 |
-
@return: list of all translated sentences
|
127 |
-
"""
|
128 |
-
warn_msg = "deprecated. Use the translate_batch function instead"
|
129 |
-
warnings.warn(warn_msg, DeprecationWarning, stacklevel=2)
|
130 |
-
logging.warning(warn_msg)
|
131 |
-
if not sentences:
|
132 |
-
raise NotValidPayload(sentences)
|
133 |
-
|
134 |
-
translated_sentences = []
|
135 |
-
try:
|
136 |
-
for sentence in sentences:
|
137 |
-
translated = self.translate(text=sentence, **kwargs)
|
138 |
-
translated_sentences.append(translated)
|
139 |
-
|
140 |
-
return translated_sentences
|
141 |
-
|
142 |
-
except Exception as e:
|
143 |
-
raise e
|
144 |
-
|
145 |
def translate_file(self, path, **kwargs):
|
146 |
"""
|
147 |
translate directly from file
|
@@ -150,13 +78,7 @@ class MyMemoryTranslator(BaseTranslator):
|
|
150 |
@param kwargs: additional args
|
151 |
@return: str
|
152 |
"""
|
153 |
-
|
154 |
-
with open(path, 'r', encoding='utf-8') as f:
|
155 |
-
text = f.read().strip()
|
156 |
-
|
157 |
-
return self.translate(text=text)
|
158 |
-
except Exception as e:
|
159 |
-
raise e
|
160 |
|
161 |
def translate_batch(self, batch=None, **kwargs):
|
162 |
"""
|
@@ -164,13 +86,4 @@ class MyMemoryTranslator(BaseTranslator):
|
|
164 |
@param batch: list of texts you want to translate
|
165 |
@return: list of translations
|
166 |
"""
|
167 |
-
|
168 |
-
raise Exception("Enter your text list that you want to translate")
|
169 |
-
|
170 |
-
arr = []
|
171 |
-
for text in batch:
|
172 |
-
translated = self.translate(text, **kwargs)
|
173 |
-
arr.append(translated)
|
174 |
-
sleep(2)
|
175 |
-
|
176 |
-
return arr
|
|
|
1 |
"""
|
2 |
mymemory translator API
|
3 |
"""
|
4 |
+
from .validate import is_empty, validate_input
|
5 |
+
from .constants import BASE_URLS
|
6 |
+
from .exceptions import (
|
|
|
|
|
7 |
TranslationNotFound,
|
|
|
8 |
RequestError,
|
9 |
TooManyRequests)
|
10 |
+
from .base import BaseTranslator
|
11 |
import requests
|
|
|
12 |
|
13 |
|
14 |
class MyMemoryTranslator(BaseTranslator):
|
15 |
"""
|
16 |
class that uses the mymemory translator to translate texts
|
17 |
"""
|
|
|
|
|
|
|
18 |
def __init__(self, source="auto", target="en", proxies=None, **kwargs):
|
19 |
"""
|
20 |
@param source: source language to translate from
|
21 |
@param target: target language to translate to
|
22 |
"""
|
|
|
23 |
self.proxies = proxies
|
|
|
|
|
|
|
|
|
24 |
self.email = kwargs.get('email', None)
|
25 |
+
super().__init__(base_url=BASE_URLS.get("MYMEMORY"),
|
26 |
+
source=source,
|
27 |
+
target=target,
|
28 |
+
payload_key='q',
|
29 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
def translate(self, text, return_all=False, **kwargs):
|
32 |
"""
|
|
|
36 |
@param return_all: set to True to return all synonym/similars of the translated text
|
37 |
@return: str or list
|
38 |
"""
|
39 |
+
if validate_input(text, max_chars=500):
|
|
|
40 |
text = text.strip()
|
41 |
+
if self._same_source_target() or is_empty(text):
|
42 |
+
return text
|
43 |
|
44 |
+
self._url_params['langpair'] = '{}|{}'.format(self._source, self._target)
|
45 |
if self.payload_key:
|
46 |
self._url_params[self.payload_key] = text
|
47 |
if self.email:
|
48 |
self._url_params['de'] = self.email
|
49 |
|
50 |
+
response = requests.get(self._base_url,
|
51 |
params=self._url_params,
|
|
|
52 |
proxies=self.proxies)
|
53 |
|
54 |
if response.status_code == 429:
|
|
|
70 |
next_match = next(matches)
|
71 |
return next_match if not return_all else list(all_matches)
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
def translate_file(self, path, **kwargs):
|
74 |
"""
|
75 |
translate directly from file
|
|
|
78 |
@param kwargs: additional args
|
79 |
@return: str
|
80 |
"""
|
81 |
+
return self._translate_file(path, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
def translate_batch(self, batch=None, **kwargs):
|
84 |
"""
|
|
|
86 |
@param batch: list of texts you want to translate
|
87 |
@return: list of translations
|
88 |
"""
|
89 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deep_translator/papago.py
CHANGED
@@ -3,19 +3,17 @@ google translator API
|
|
3 |
"""
|
4 |
import json
|
5 |
from .constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
|
6 |
-
from .exceptions import
|
7 |
-
from .
|
8 |
import requests
|
9 |
-
import warnings
|
10 |
-
import logging
|
11 |
|
|
|
12 |
|
13 |
-
|
|
|
14 |
"""
|
15 |
class that wraps functions, which use google translate under the hood to translate text(s)
|
16 |
"""
|
17 |
-
_languages = PAPAGO_LANGUAGE_TO_CODE
|
18 |
-
supported_languages = list(_languages.keys())
|
19 |
|
20 |
def __init__(self, client_id=None, secret_key=None, source="auto", target="en", **kwargs):
|
21 |
"""
|
@@ -26,47 +24,15 @@ class PapagoTranslator(object):
|
|
26 |
raise Exception(
|
27 |
"Please pass your client id and secret key! visit the papago website for more infos")
|
28 |
|
29 |
-
self.__base_url = BASE_URLS.get("PAPAGO_API")
|
30 |
self.client_id = client_id
|
31 |
self.secret_key = secret_key
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
return the supported languages by the google translator
|
40 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
41 |
-
@return: list or dict
|
42 |
-
"""
|
43 |
-
return PapagoTranslator.supported_languages if not as_dict else PapagoTranslator._languages
|
44 |
-
|
45 |
-
def _map_language_to_code(self, *languages):
|
46 |
-
"""
|
47 |
-
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
48 |
-
@param languages: list of languages
|
49 |
-
@return: mapped value of the language or raise an exception if the language is not supported
|
50 |
-
"""
|
51 |
-
for language in languages:
|
52 |
-
if language in self._languages.values() or language == 'auto':
|
53 |
-
yield language
|
54 |
-
elif language in self._languages.keys():
|
55 |
-
yield self._languages[language]
|
56 |
-
else:
|
57 |
-
raise LanguageNotSupportedException(language)
|
58 |
-
|
59 |
-
def is_language_supported(self, *languages):
|
60 |
-
"""
|
61 |
-
check if the language is supported by the translator
|
62 |
-
@param languages: list of languages
|
63 |
-
@return: bool or raise an Exception
|
64 |
-
"""
|
65 |
-
for lang in languages:
|
66 |
-
if lang != 'auto' and lang not in self._languages.keys():
|
67 |
-
if lang != 'auto' and lang not in self._languages.values():
|
68 |
-
raise LanguageNotSupportedException(lang)
|
69 |
-
return True
|
70 |
|
71 |
def translate(self, text, **kwargs):
|
72 |
"""
|
@@ -74,32 +40,32 @@ class PapagoTranslator(object):
|
|
74 |
@param text: desired text to translate
|
75 |
@return: str: translated text
|
76 |
"""
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
|
104 |
def translate_file(self, path, **kwargs):
|
105 |
"""
|
@@ -109,38 +75,7 @@ class PapagoTranslator(object):
|
|
109 |
@param kwargs: additional args
|
110 |
@return: str
|
111 |
"""
|
112 |
-
|
113 |
-
with open(path, 'r', encoding='utf-8') as f:
|
114 |
-
text = f.read().strip()
|
115 |
-
return self.translate(text)
|
116 |
-
except Exception as e:
|
117 |
-
raise e
|
118 |
-
|
119 |
-
def translate_sentences(self, sentences=None, **kwargs):
|
120 |
-
"""
|
121 |
-
translate many sentences together. This makes sense if you have sentences with different languages
|
122 |
-
and you want to translate all to unified language. This is handy because it detects
|
123 |
-
automatically the language of each sentence and then translate it.
|
124 |
-
|
125 |
-
@param sentences: list of sentences to translate
|
126 |
-
@return: list of all translated sentences
|
127 |
-
"""
|
128 |
-
warnings.warn("deprecated. Use the translate_batch function instead",
|
129 |
-
DeprecationWarning, stacklevel=2)
|
130 |
-
logging.warning("deprecated. Use the translate_batch function instead")
|
131 |
-
if not sentences:
|
132 |
-
raise NotValidPayload(sentences)
|
133 |
-
|
134 |
-
translated_sentences = []
|
135 |
-
try:
|
136 |
-
for sentence in sentences:
|
137 |
-
translated = self.translate(text=sentence)
|
138 |
-
translated_sentences.append(translated)
|
139 |
-
|
140 |
-
return translated_sentences
|
141 |
-
|
142 |
-
except Exception as e:
|
143 |
-
raise e
|
144 |
|
145 |
def translate_batch(self, batch=None, **kwargs):
|
146 |
"""
|
@@ -148,14 +83,4 @@ class PapagoTranslator(object):
|
|
148 |
@param batch: list of texts you want to translate
|
149 |
@return: list of translations
|
150 |
"""
|
151 |
-
|
152 |
-
raise Exception("Enter your text list that you want to translate")
|
153 |
-
arr = []
|
154 |
-
for i, text in enumerate(batch):
|
155 |
-
|
156 |
-
translated = self.translate(text, **kwargs)
|
157 |
-
arr.append(translated)
|
158 |
-
return arr
|
159 |
-
|
160 |
-
|
161 |
-
BaseTranslator.register(PapagoTranslator)
|
|
|
3 |
"""
|
4 |
import json
|
5 |
from .constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
|
6 |
+
from .exceptions import TranslationNotFound
|
7 |
+
from .base import BaseTranslator
|
8 |
import requests
|
|
|
|
|
9 |
|
10 |
+
from .validate import validate_input
|
11 |
|
12 |
+
|
13 |
+
class PapagoTranslator(BaseTranslator):
|
14 |
"""
|
15 |
class that wraps functions, which use google translate under the hood to translate text(s)
|
16 |
"""
|
|
|
|
|
17 |
|
18 |
def __init__(self, client_id=None, secret_key=None, source="auto", target="en", **kwargs):
|
19 |
"""
|
|
|
24 |
raise Exception(
|
25 |
"Please pass your client id and secret key! visit the papago website for more infos")
|
26 |
|
|
|
27 |
self.client_id = client_id
|
28 |
self.secret_key = secret_key
|
29 |
+
super().__init__(
|
30 |
+
base_url=BASE_URLS.get("PAPAGO_API"),
|
31 |
+
source=source,
|
32 |
+
target=target,
|
33 |
+
languages=PAPAGO_LANGUAGE_TO_CODE,
|
34 |
+
**kwargs
|
35 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
def translate(self, text, **kwargs):
|
38 |
"""
|
|
|
40 |
@param text: desired text to translate
|
41 |
@return: str: translated text
|
42 |
"""
|
43 |
+
if validate_input(text):
|
44 |
+
payload = {
|
45 |
+
"source": self._source,
|
46 |
+
"target": self._target,
|
47 |
+
"text": text
|
48 |
+
}
|
49 |
+
headers = {
|
50 |
+
'X-Naver-Client-Id': self.client_id,
|
51 |
+
'X-Naver-Client-Secret': self.secret_key,
|
52 |
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
53 |
+
}
|
54 |
+
response = requests.post(
|
55 |
+
self._base_url, headers=headers, data=payload)
|
56 |
+
if response.status_code != 200:
|
57 |
+
raise Exception(
|
58 |
+
f'Translation error! -> status code: {response.status_code}')
|
59 |
+
res_body = json.loads(response.text)
|
60 |
+
if "message" not in res_body:
|
61 |
+
raise TranslationNotFound(text)
|
62 |
+
|
63 |
+
msg = res_body.get("message")
|
64 |
+
result = msg.get("result", None)
|
65 |
+
if not result:
|
66 |
+
raise TranslationNotFound(text)
|
67 |
+
translated_text = result.get("translatedText")
|
68 |
+
return translated_text
|
69 |
|
70 |
def translate_file(self, path, **kwargs):
|
71 |
"""
|
|
|
75 |
@param kwargs: additional args
|
76 |
@return: str
|
77 |
"""
|
78 |
+
return self._translate_file(path, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
def translate_batch(self, batch=None, **kwargs):
|
81 |
"""
|
|
|
83 |
@param batch: list of texts you want to translate
|
84 |
@return: list of translations
|
85 |
"""
|
86 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deep_translator/parent.py
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
"""parent translator class"""
|
2 |
-
|
3 |
-
from .exceptions import NotValidPayload, NotValidLength, InvalidSourceOrTargetLanguage
|
4 |
-
from abc import ABC, abstractmethod
|
5 |
-
import string
|
6 |
-
|
7 |
-
|
8 |
-
class BaseTranslator(ABC):
|
9 |
-
"""
|
10 |
-
Abstract class that serve as a parent translator for other different translators
|
11 |
-
"""
|
12 |
-
def __init__(self,
|
13 |
-
base_url=None,
|
14 |
-
source="auto",
|
15 |
-
target="en",
|
16 |
-
payload_key=None,
|
17 |
-
element_tag=None,
|
18 |
-
element_query=None,
|
19 |
-
**url_params):
|
20 |
-
"""
|
21 |
-
@param source: source language to translate from
|
22 |
-
@param target: target language to translate to
|
23 |
-
"""
|
24 |
-
if source == target:
|
25 |
-
raise InvalidSourceOrTargetLanguage(source)
|
26 |
-
|
27 |
-
self.__base_url = base_url
|
28 |
-
self._source = source
|
29 |
-
self._target = target
|
30 |
-
self._url_params = url_params
|
31 |
-
self._element_tag = element_tag
|
32 |
-
self._element_query = element_query
|
33 |
-
self.payload_key = payload_key
|
34 |
-
self.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) '
|
35 |
-
'AppleWebit/535.19'
|
36 |
-
'(KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19'}
|
37 |
-
super(BaseTranslator, self).__init__()
|
38 |
-
|
39 |
-
@staticmethod
|
40 |
-
def _validate_payload(payload, min_chars=1, max_chars=5000):
|
41 |
-
"""
|
42 |
-
validate the target text to translate
|
43 |
-
@param payload: text to translate
|
44 |
-
@return: bool
|
45 |
-
"""
|
46 |
-
|
47 |
-
if not payload or not isinstance(payload, str) or not payload.strip() or payload.isdigit():
|
48 |
-
raise NotValidPayload(payload)
|
49 |
-
|
50 |
-
# check if payload contains only symbols
|
51 |
-
if all(i in string.punctuation for i in payload):
|
52 |
-
raise NotValidPayload(payload)
|
53 |
-
|
54 |
-
if not BaseTranslator.__check_length(payload, min_chars, max_chars):
|
55 |
-
raise NotValidLength(payload, min_chars, max_chars)
|
56 |
-
return True
|
57 |
-
|
58 |
-
@staticmethod
|
59 |
-
def __check_length(payload, min_chars, max_chars):
|
60 |
-
"""
|
61 |
-
check length of the provided target text to translate
|
62 |
-
@param payload: text to translate
|
63 |
-
@param min_chars: minimum characters allowed
|
64 |
-
@param max_chars: maximum characters allowed
|
65 |
-
@return: bool
|
66 |
-
"""
|
67 |
-
return True if min_chars <= len(payload) < max_chars else False
|
68 |
-
|
69 |
-
@abstractmethod
|
70 |
-
def translate(self, text, **kwargs):
|
71 |
-
"""
|
72 |
-
translate a text using a translator under the hood and return the translated text
|
73 |
-
@param text: text to translate
|
74 |
-
@param kwargs: additional arguments
|
75 |
-
@return: str
|
76 |
-
"""
|
77 |
-
return NotImplemented('You need to implement the translate method!')
|
78 |
-
|
79 |
-
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deep_translator/pons.py
CHANGED
@@ -3,14 +3,16 @@ pons translator API
|
|
3 |
"""
|
4 |
from bs4 import BeautifulSoup
|
5 |
import requests
|
6 |
-
|
7 |
-
from .
|
|
|
|
|
8 |
TranslationNotFound,
|
9 |
NotValidPayload,
|
10 |
ElementNotFoundInGetRequest,
|
11 |
RequestError,
|
12 |
TooManyRequests)
|
13 |
-
from .
|
14 |
from requests.utils import requote_uri
|
15 |
|
16 |
|
@@ -18,62 +20,23 @@ class PonsTranslator(BaseTranslator):
|
|
18 |
"""
|
19 |
class that uses PONS translator to translate words
|
20 |
"""
|
21 |
-
_languages = PONS_LANGUAGES_TO_CODES
|
22 |
-
supported_languages = list(_languages.keys())
|
23 |
|
24 |
def __init__(self, source, target="en", proxies=None, **kwargs):
|
25 |
"""
|
26 |
@param source: source language to translate from
|
27 |
@param target: target language to translate to
|
28 |
"""
|
29 |
-
self.__base_url = BASE_URLS.get("PONS")
|
30 |
self.proxies = proxies
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
source=self._source,
|
36 |
-
target=self._target,
|
37 |
payload_key=None,
|
38 |
element_tag='div',
|
39 |
-
element_query={"class": "target"}
|
|
|
40 |
)
|
41 |
|
42 |
-
@staticmethod
|
43 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
44 |
-
"""
|
45 |
-
return the supported languages by the linguee translator
|
46 |
-
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
47 |
-
@return: list or dict
|
48 |
-
"""
|
49 |
-
return PonsTranslator.supported_languages if not as_dict else PonsTranslator._languages
|
50 |
-
|
51 |
-
def _map_language_to_code(self, *languages, **kwargs):
|
52 |
-
"""
|
53 |
-
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
54 |
-
@param languages: list of languages
|
55 |
-
@return: mapped value of the language or raise an exception if the language is not supported
|
56 |
-
"""
|
57 |
-
for language in languages:
|
58 |
-
if language in self._languages.values():
|
59 |
-
yield PONS_CODES_TO_LANGUAGES[language]
|
60 |
-
elif language in self._languages.keys():
|
61 |
-
yield language
|
62 |
-
else:
|
63 |
-
raise LanguageNotSupportedException(language)
|
64 |
-
|
65 |
-
def is_language_supported(self, *languages, **kwargs):
|
66 |
-
"""
|
67 |
-
check if the language is supported by the translator
|
68 |
-
@param languages: list of languages
|
69 |
-
@return: bool or raise an Exception
|
70 |
-
"""
|
71 |
-
for lang in languages:
|
72 |
-
if lang not in self._languages.keys():
|
73 |
-
if lang not in self._languages.values():
|
74 |
-
raise LanguageNotSupportedException(lang)
|
75 |
-
return True
|
76 |
-
|
77 |
def translate(self, word, return_all=False, **kwargs):
|
78 |
"""
|
79 |
function that uses PONS to translate a word
|
@@ -83,8 +46,10 @@ class PonsTranslator(BaseTranslator):
|
|
83 |
@type return_all: bool
|
84 |
@return: str: translated word
|
85 |
"""
|
86 |
-
if
|
87 |
-
|
|
|
|
|
88 |
url = requote_uri(url)
|
89 |
response = requests.get(url, proxies=self.proxies)
|
90 |
|
@@ -104,9 +69,7 @@ class PonsTranslator(BaseTranslator):
|
|
104 |
for el in elements:
|
105 |
temp = ''
|
106 |
for e in el.findAll('a'):
|
107 |
-
|
108 |
-
if e and "/translate/{}-{}/".format(self._target, self._source) in e.get('href'):
|
109 |
-
temp += e.get_text() + ' '
|
110 |
filtered_elements.append(temp)
|
111 |
|
112 |
if not filtered_elements:
|
|
|
3 |
"""
|
4 |
from bs4 import BeautifulSoup
|
5 |
import requests
|
6 |
+
|
7 |
+
from .validate import validate_input, is_empty
|
8 |
+
from .constants import BASE_URLS, PONS_CODES_TO_LANGUAGES
|
9 |
+
from .exceptions import (
|
10 |
TranslationNotFound,
|
11 |
NotValidPayload,
|
12 |
ElementNotFoundInGetRequest,
|
13 |
RequestError,
|
14 |
TooManyRequests)
|
15 |
+
from .base import BaseTranslator
|
16 |
from requests.utils import requote_uri
|
17 |
|
18 |
|
|
|
20 |
"""
|
21 |
class that uses PONS translator to translate words
|
22 |
"""
|
|
|
|
|
23 |
|
24 |
def __init__(self, source, target="en", proxies=None, **kwargs):
|
25 |
"""
|
26 |
@param source: source language to translate from
|
27 |
@param target: target language to translate to
|
28 |
"""
|
|
|
29 |
self.proxies = proxies
|
30 |
+
super().__init__(base_url=BASE_URLS.get("PONS"),
|
31 |
+
languages=PONS_CODES_TO_LANGUAGES,
|
32 |
+
source=source,
|
33 |
+
target=target,
|
|
|
|
|
34 |
payload_key=None,
|
35 |
element_tag='div',
|
36 |
+
element_query={"class": "target"},
|
37 |
+
**kwargs
|
38 |
)
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
def translate(self, word, return_all=False, **kwargs):
|
41 |
"""
|
42 |
function that uses PONS to translate a word
|
|
|
46 |
@type return_all: bool
|
47 |
@return: str: translated word
|
48 |
"""
|
49 |
+
if validate_input(word, max_chars=50):
|
50 |
+
if self._same_source_target() or is_empty(word):
|
51 |
+
return word
|
52 |
+
url = "{}{}-{}/{}".format(self._base_url, self._source, self._target, word)
|
53 |
url = requote_uri(url)
|
54 |
response = requests.get(url, proxies=self.proxies)
|
55 |
|
|
|
69 |
for el in elements:
|
70 |
temp = ''
|
71 |
for e in el.findAll('a'):
|
72 |
+
temp += e.get_text() + ' '
|
|
|
|
|
73 |
filtered_elements.append(temp)
|
74 |
|
75 |
if not filtered_elements:
|
deep_translator/qcri.py
CHANGED
@@ -2,10 +2,10 @@
|
|
2 |
import requests
|
3 |
from .constants import BASE_URLS, QCRI_LANGUAGE_TO_CODE
|
4 |
from .exceptions import (ServerException, TranslationNotFound)
|
5 |
-
from .
|
6 |
|
7 |
|
8 |
-
class
|
9 |
"""
|
10 |
class that wraps functions, which use the QRCI translator under the hood to translate word(s)
|
11 |
"""
|
@@ -17,9 +17,6 @@ class QCRI(object):
|
|
17 |
|
18 |
if not api_key:
|
19 |
raise ServerException(401)
|
20 |
-
self.__base_url = BASE_URLS.get("QCRI")
|
21 |
-
self.source = source
|
22 |
-
self.target = target
|
23 |
self.api_key = api_key
|
24 |
self.api_endpoints = {
|
25 |
"get_languages": "getLanguagePairs",
|
@@ -30,25 +27,24 @@ class QCRI(object):
|
|
30 |
self.params = {
|
31 |
"key": self.api_key
|
32 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
def _get(self, endpoint, params=None, return_text=True):
|
35 |
if not params:
|
36 |
params = self.params
|
37 |
try:
|
38 |
-
res = requests.get(self.
|
39 |
endpoint=self.api_endpoints[endpoint]), params=params)
|
40 |
return res.text if return_text else res
|
41 |
except Exception as e:
|
42 |
raise e
|
43 |
|
44 |
-
@staticmethod
|
45 |
-
def get_supported_languages(as_dict=False, **kwargs):
|
46 |
-
# Have no use for this as the format is not what we need
|
47 |
-
# Save this for whenever
|
48 |
-
# pairs = self._get("get_languages")
|
49 |
-
# Using a this one instead
|
50 |
-
return [*QCRI_LANGUAGE_TO_CODE.keys()] if not as_dict else QCRI_LANGUAGE_TO_CODE
|
51 |
-
|
52 |
@property
|
53 |
def languages(self):
|
54 |
return self.get_supported_languages()
|
@@ -61,11 +57,11 @@ class QCRI(object):
|
|
61 |
def domains(self):
|
62 |
return self.get_domains()
|
63 |
|
64 |
-
def translate(self, text,
|
65 |
params = {
|
66 |
"key": self.api_key,
|
67 |
-
"langpair": "{}-{}".format(self.
|
68 |
-
"domain": domain,
|
69 |
"text": text
|
70 |
}
|
71 |
try:
|
@@ -83,14 +79,14 @@ class QCRI(object):
|
|
83 |
raise TranslationNotFound(text)
|
84 |
return translation
|
85 |
|
86 |
-
def
|
|
|
|
|
|
|
87 |
"""
|
88 |
translate a batch of texts
|
89 |
@domain: domain
|
90 |
@param batch: list of texts to translate
|
91 |
@return: list of translations
|
92 |
"""
|
93 |
-
return
|
94 |
-
|
95 |
-
|
96 |
-
BaseTranslator.register(QCRI)
|
|
|
2 |
import requests
|
3 |
from .constants import BASE_URLS, QCRI_LANGUAGE_TO_CODE
|
4 |
from .exceptions import (ServerException, TranslationNotFound)
|
5 |
+
from .base import BaseTranslator
|
6 |
|
7 |
|
8 |
+
class QcriTranslator(BaseTranslator):
|
9 |
"""
|
10 |
class that wraps functions, which use the QRCI translator under the hood to translate word(s)
|
11 |
"""
|
|
|
17 |
|
18 |
if not api_key:
|
19 |
raise ServerException(401)
|
|
|
|
|
|
|
20 |
self.api_key = api_key
|
21 |
self.api_endpoints = {
|
22 |
"get_languages": "getLanguagePairs",
|
|
|
27 |
self.params = {
|
28 |
"key": self.api_key
|
29 |
}
|
30 |
+
super().__init__(
|
31 |
+
base_url=BASE_URLS.get("QcriTranslator"),
|
32 |
+
source=source,
|
33 |
+
target=target,
|
34 |
+
languages=QCRI_LANGUAGE_TO_CODE,
|
35 |
+
**kwargs
|
36 |
+
)
|
37 |
|
38 |
def _get(self, endpoint, params=None, return_text=True):
|
39 |
if not params:
|
40 |
params = self.params
|
41 |
try:
|
42 |
+
res = requests.get(self._base_url.format(
|
43 |
endpoint=self.api_endpoints[endpoint]), params=params)
|
44 |
return res.text if return_text else res
|
45 |
except Exception as e:
|
46 |
raise e
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
@property
|
49 |
def languages(self):
|
50 |
return self.get_supported_languages()
|
|
|
57 |
def domains(self):
|
58 |
return self.get_domains()
|
59 |
|
60 |
+
def translate(self, text, **kwargs):
|
61 |
params = {
|
62 |
"key": self.api_key,
|
63 |
+
"langpair": "{}-{}".format(self._source, self._target),
|
64 |
+
"domain": kwargs["domain"],
|
65 |
"text": text
|
66 |
}
|
67 |
try:
|
|
|
79 |
raise TranslationNotFound(text)
|
80 |
return translation
|
81 |
|
82 |
+
def translate_file(self, path, **kwargs):
|
83 |
+
return self._translate_file(path, **kwargs)
|
84 |
+
|
85 |
+
def translate_batch(self, batch, **kwargs):
|
86 |
"""
|
87 |
translate a batch of texts
|
88 |
@domain: domain
|
89 |
@param batch: list of texts to translate
|
90 |
@return: list of translations
|
91 |
"""
|
92 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
|
|
|
deep_translator/validate.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from .exceptions import NotValidPayload, NotValidLength
|
3 |
+
import string
|
4 |
+
|
5 |
+
|
6 |
+
def is_empty(text: str):
|
7 |
+
return text == ""
|
8 |
+
|
9 |
+
|
10 |
+
def validate_input(text: str, min_chars: int = 0, max_chars: int = 5000):
|
11 |
+
"""
|
12 |
+
validate the target text to translate
|
13 |
+
@param min_chars: min characters
|
14 |
+
@param max_chars: max characters
|
15 |
+
@param text: text to translate
|
16 |
+
@return: bool
|
17 |
+
"""
|
18 |
+
|
19 |
+
if not isinstance(text, str) or text.isdigit():
|
20 |
+
raise NotValidPayload(text)
|
21 |
+
if not min_chars <= len(text) < max_chars:
|
22 |
+
raise NotValidLength(text, min_chars, max_chars)
|
23 |
+
|
24 |
+
return True
|
deep_translator/yandex.py
CHANGED
@@ -5,10 +5,10 @@ import requests
|
|
5 |
from .constants import BASE_URLS
|
6 |
from .exceptions import (RequestError, ServerException,
|
7 |
TranslationNotFound, TooManyRequests)
|
8 |
-
from .
|
9 |
|
10 |
|
11 |
-
class YandexTranslator(
|
12 |
"""
|
13 |
class that wraps functions, which use the yandex translator under the hood to translate word(s)
|
14 |
"""
|
@@ -19,10 +19,6 @@ class YandexTranslator(object):
|
|
19 |
"""
|
20 |
if not api_key:
|
21 |
raise ServerException(401)
|
22 |
-
self.__base_url = BASE_URLS.get("YANDEX")
|
23 |
-
self.source = source
|
24 |
-
self.target = target
|
25 |
-
|
26 |
self.api_key = api_key
|
27 |
self.api_version = "v1.5"
|
28 |
self.api_endpoints = {
|
@@ -30,13 +26,12 @@ class YandexTranslator(object):
|
|
30 |
"detect": "detect",
|
31 |
"translate": "translate",
|
32 |
}
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
"""
|
40 |
|
41 |
def _get_supported_languages(self):
|
42 |
return set(x.split("-")[0] for x in self.dirs)
|
@@ -49,7 +44,7 @@ class YandexTranslator(object):
|
|
49 |
def dirs(self, proxies=None):
|
50 |
|
51 |
try:
|
52 |
-
url = self.
|
53 |
version=self.api_version, endpoint="getLangs")
|
54 |
print("url: ", url)
|
55 |
response = requests.get(
|
@@ -71,7 +66,7 @@ class YandexTranslator(object):
|
|
71 |
"key": self.api_key,
|
72 |
}
|
73 |
try:
|
74 |
-
url = self.
|
75 |
version=self.api_version, endpoint="detect")
|
76 |
response = requests.post(url, data=params, proxies=proxies)
|
77 |
|
@@ -92,31 +87,32 @@ class YandexTranslator(object):
|
|
92 |
return language
|
93 |
|
94 |
def translate(self, text, proxies=None, **kwargs):
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
|
|
120 |
|
121 |
def translate_file(self, path, **kwargs):
|
122 |
"""
|
@@ -124,13 +120,7 @@ class YandexTranslator(object):
|
|
124 |
@param path: path to file
|
125 |
@return: translated text
|
126 |
"""
|
127 |
-
|
128 |
-
with open(path, 'r', encoding='utf-8') as f:
|
129 |
-
text = f.read()
|
130 |
-
|
131 |
-
return self.translate(text)
|
132 |
-
except Exception as e:
|
133 |
-
raise e
|
134 |
|
135 |
def translate_batch(self, batch, **kwargs):
|
136 |
"""
|
@@ -138,7 +128,5 @@ class YandexTranslator(object):
|
|
138 |
@param batch: list of texts to translate
|
139 |
@return: list of translations
|
140 |
"""
|
141 |
-
return
|
142 |
-
|
143 |
|
144 |
-
BaseTranslator.register(YandexTranslator)
|
|
|
5 |
from .constants import BASE_URLS
|
6 |
from .exceptions import (RequestError, ServerException,
|
7 |
TranslationNotFound, TooManyRequests)
|
8 |
+
from .base import BaseTranslator
|
9 |
|
10 |
|
11 |
+
class YandexTranslator(BaseTranslator):
|
12 |
"""
|
13 |
class that wraps functions, which use the yandex translator under the hood to translate word(s)
|
14 |
"""
|
|
|
19 |
"""
|
20 |
if not api_key:
|
21 |
raise ServerException(401)
|
|
|
|
|
|
|
|
|
22 |
self.api_key = api_key
|
23 |
self.api_version = "v1.5"
|
24 |
self.api_endpoints = {
|
|
|
26 |
"detect": "detect",
|
27 |
"translate": "translate",
|
28 |
}
|
29 |
+
super().__init__(
|
30 |
+
base_url=BASE_URLS.get("YANDEX"),
|
31 |
+
source=source,
|
32 |
+
target=target,
|
33 |
+
**kwargs
|
34 |
+
)
|
|
|
35 |
|
36 |
def _get_supported_languages(self):
|
37 |
return set(x.split("-")[0] for x in self.dirs)
|
|
|
44 |
def dirs(self, proxies=None):
|
45 |
|
46 |
try:
|
47 |
+
url = self._base_url.format(
|
48 |
version=self.api_version, endpoint="getLangs")
|
49 |
print("url: ", url)
|
50 |
response = requests.get(
|
|
|
66 |
"key": self.api_key,
|
67 |
}
|
68 |
try:
|
69 |
+
url = self._base_url.format(
|
70 |
version=self.api_version, endpoint="detect")
|
71 |
response = requests.post(url, data=params, proxies=proxies)
|
72 |
|
|
|
87 |
return language
|
88 |
|
89 |
def translate(self, text, proxies=None, **kwargs):
|
90 |
+
if validate_input(text):
|
91 |
+
params = {
|
92 |
+
"text": text,
|
93 |
+
"format": "plain",
|
94 |
+
"lang": self._target if self._source == "auto" else "{}-{}".format(self._source, self._target),
|
95 |
+
"key": self.api_key
|
96 |
+
}
|
97 |
+
try:
|
98 |
+
url = self._base_url.format(
|
99 |
+
version=self.api_version, endpoint="translate")
|
100 |
+
response = requests.post(url, data=params, proxies=proxies)
|
101 |
+
except ConnectionError:
|
102 |
+
raise ServerException(503)
|
103 |
+
else:
|
104 |
+
response = response.json()
|
105 |
+
|
106 |
+
if response['code'] == 429:
|
107 |
+
raise TooManyRequests()
|
108 |
+
|
109 |
+
if response['code'] != 200:
|
110 |
+
raise ServerException(response['code'])
|
111 |
+
|
112 |
+
if not response['text']:
|
113 |
+
raise TranslationNotFound()
|
114 |
+
|
115 |
+
return response['text']
|
116 |
|
117 |
def translate_file(self, path, **kwargs):
|
118 |
"""
|
|
|
120 |
@param path: path to file
|
121 |
@return: translated text
|
122 |
"""
|
123 |
+
return self._translate_file(path, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
|
125 |
def translate_batch(self, batch, **kwargs):
|
126 |
"""
|
|
|
128 |
@param batch: list of texts to translate
|
129 |
@return: list of translations
|
130 |
"""
|
131 |
+
return self._translate_batch(batch, **kwargs)
|
|
|
132 |
|
|
docs/README.rst
CHANGED
@@ -106,8 +106,8 @@ Features
|
|
106 |
* Support for the `Linguee translator <https://www.linguee.com/>`_
|
107 |
* Support for the `Mymemory translator <https://mymemory.translated.net/>`_
|
108 |
* Support for the `Yandex translator <https://yandex.com/>`_ (version >= 1.2.1)
|
109 |
-
* Support for the `
|
110 |
-
* Support for the `
|
111 |
* Support for the `Papago translator <https://papago.naver.com/>`_ (version >= 1.4.4)
|
112 |
* Support for the `Libre translator <https://libretranslate.com/>`_
|
113 |
* Support for proxy usage
|
@@ -187,8 +187,8 @@ Imports
|
|
187 |
MyMemoryTranslator,
|
188 |
YandexTranslator,
|
189 |
PapagoTranslator,
|
190 |
-
|
191 |
-
|
192 |
single_detection,
|
193 |
batch_detection)
|
194 |
|
@@ -306,12 +306,12 @@ Mymemory Translator
|
|
306 |
translated = MyMemoryTranslator(source='en', target='fr').translate_file(path)
|
307 |
|
308 |
|
309 |
-
|
310 |
-----------------
|
311 |
|
312 |
.. note::
|
313 |
|
314 |
-
In order to use the
|
315 |
deep-translator supports both Pro and free APIs. Just check the examples below.
|
316 |
Visit https://www.deepl.com/en/docs-api/ for more information on how to generate your Deepl api key
|
317 |
|
@@ -321,7 +321,7 @@ DeepL Translator
|
|
321 |
|
322 |
text = 'Keep it up. You are awesome'
|
323 |
|
324 |
-
translated =
|
325 |
|
326 |
.. note::
|
327 |
deep-translator uses free deepl api by default. If you have the pro version then simply set the use_free_api to false.
|
@@ -334,14 +334,14 @@ DeepL Translator
|
|
334 |
texts = ["hallo welt", "guten morgen"]
|
335 |
|
336 |
# the translate_sentences function is deprecated, use the translate_batch function instead
|
337 |
-
translated =
|
338 |
|
339 |
-
|
340 |
--------------------
|
341 |
|
342 |
.. note::
|
343 |
|
344 |
-
In order to use the
|
345 |
for more information
|
346 |
|
347 |
- Check languages
|
@@ -349,14 +349,14 @@ QCRI Translator
|
|
349 |
.. code-block:: python
|
350 |
|
351 |
# as a property
|
352 |
-
print("language pairs: ",
|
353 |
|
354 |
- Check domains
|
355 |
|
356 |
.. code-block:: python
|
357 |
|
358 |
# as a property
|
359 |
-
print("domains: ",
|
360 |
|
361 |
- Text translation
|
362 |
|
@@ -364,7 +364,7 @@ QCRI Translator
|
|
364 |
|
365 |
text = 'Education is great'
|
366 |
|
367 |
-
translated =
|
368 |
# output -> التعليم هو عظيم
|
369 |
|
370 |
# see docs for batch translation and more.
|
|
|
106 |
* Support for the `Linguee translator <https://www.linguee.com/>`_
|
107 |
* Support for the `Mymemory translator <https://mymemory.translated.net/>`_
|
108 |
* Support for the `Yandex translator <https://yandex.com/>`_ (version >= 1.2.1)
|
109 |
+
* Support for the `QcriTranslator translator <https://mt.qcri.org/api/>`_ (version >= 1.2.4)
|
110 |
+
* Support for the `DeeplTranslator translator <https://www.deepl.com/en/translator/>`_ (version >= 1.2.5)
|
111 |
* Support for the `Papago translator <https://papago.naver.com/>`_ (version >= 1.4.4)
|
112 |
* Support for the `Libre translator <https://libretranslate.com/>`_
|
113 |
* Support for proxy usage
|
|
|
187 |
MyMemoryTranslator,
|
188 |
YandexTranslator,
|
189 |
PapagoTranslator,
|
190 |
+
DeeplTranslator,
|
191 |
+
QcriTranslator,
|
192 |
single_detection,
|
193 |
batch_detection)
|
194 |
|
|
|
306 |
translated = MyMemoryTranslator(source='en', target='fr').translate_file(path)
|
307 |
|
308 |
|
309 |
+
DeeplTranslator Translator
|
310 |
-----------------
|
311 |
|
312 |
.. note::
|
313 |
|
314 |
+
In order to use the DeeplTranslator translator, you need to generate an api key. Deepl offers a Pro and a free API.
|
315 |
deep-translator supports both Pro and free APIs. Just check the examples below.
|
316 |
Visit https://www.deepl.com/en/docs-api/ for more information on how to generate your Deepl api key
|
317 |
|
|
|
321 |
|
322 |
text = 'Keep it up. You are awesome'
|
323 |
|
324 |
+
translated = DeeplTranslator(api_key="your_api_key", source="en", target="en", use_free_api=True).translate(text)
|
325 |
|
326 |
.. note::
|
327 |
deep-translator uses free deepl api by default. If you have the pro version then simply set the use_free_api to false.
|
|
|
334 |
texts = ["hallo welt", "guten morgen"]
|
335 |
|
336 |
# the translate_sentences function is deprecated, use the translate_batch function instead
|
337 |
+
translated = DeeplTranslator("your_api_key").translate_batch(texts)
|
338 |
|
339 |
+
QcriTranslator Translator
|
340 |
--------------------
|
341 |
|
342 |
.. note::
|
343 |
|
344 |
+
In order to use the QcriTranslator translator, you need to generate a free api key. Visit https://mt.qcri.org/api/
|
345 |
for more information
|
346 |
|
347 |
- Check languages
|
|
|
349 |
.. code-block:: python
|
350 |
|
351 |
# as a property
|
352 |
+
print("language pairs: ", QcriTranslator("your_api_key").languages)
|
353 |
|
354 |
- Check domains
|
355 |
|
356 |
.. code-block:: python
|
357 |
|
358 |
# as a property
|
359 |
+
print("domains: ", QcriTranslator("your_api_key").domains)
|
360 |
|
361 |
- Text translation
|
362 |
|
|
|
364 |
|
365 |
text = 'Education is great'
|
366 |
|
367 |
+
translated = QcriTranslator("your_api_key").translate(source='en', target='ar', domain="news", text=text)
|
368 |
# output -> التعليم هو عظيم
|
369 |
|
370 |
# see docs for batch translation and more.
|
docs/history.rst
CHANGED
@@ -11,8 +11,8 @@ Important History
|
|
11 |
- 1.3.4 bug fixes for the dutch language
|
12 |
- 1.3.3 fixed bug in google translate
|
13 |
|
14 |
-
- 1.2.5: added support for the
|
15 |
-
- 1.2.4: added support for the
|
16 |
- 1.2.1: added support for the yandex translator
|
17 |
- 1.1.9: fixed bug in requests
|
18 |
- 1.1.5: added language detection
|
|
|
11 |
- 1.3.4 bug fixes for the dutch language
|
12 |
- 1.3.3 fixed bug in google translate
|
13 |
|
14 |
+
- 1.2.5: added support for the DeeplTranslator translator
|
15 |
+
- 1.2.4: added support for the QcriTranslator translator
|
16 |
- 1.2.1: added support for the yandex translator
|
17 |
- 1.1.9: fixed bug in requests
|
18 |
- 1.1.5: added language detection
|
docs/modules.rst
CHANGED
@@ -20,7 +20,7 @@ Exceptions
|
|
20 |
:undoc-members:
|
21 |
:show-inheritance:
|
22 |
|
23 |
-
|
24 |
Language Detection Library
|
25 |
----------------------------------
|
26 |
|
@@ -40,7 +40,7 @@ Google Translator
|
|
40 |
:undoc-members:
|
41 |
:show-inheritance:
|
42 |
|
43 |
-
|
44 |
----------------------------------
|
45 |
|
46 |
.. automodule:: deep_translator.deepl
|
@@ -88,7 +88,7 @@ Pons
|
|
88 |
:undoc-members:
|
89 |
:show-inheritance:
|
90 |
|
91 |
-
|
92 |
----------------------------------
|
93 |
|
94 |
.. automodule:: deep_translator.qcri
|
@@ -102,4 +102,4 @@ Yandex
|
|
102 |
.. automodule:: deep_translator.yandex
|
103 |
:members:
|
104 |
:undoc-members:
|
105 |
-
:show-inheritance:
|
|
|
20 |
:undoc-members:
|
21 |
:show-inheritance:
|
22 |
|
23 |
+
|
24 |
Language Detection Library
|
25 |
----------------------------------
|
26 |
|
|
|
40 |
:undoc-members:
|
41 |
:show-inheritance:
|
42 |
|
43 |
+
DeeplTranslator
|
44 |
----------------------------------
|
45 |
|
46 |
.. automodule:: deep_translator.deepl
|
|
|
88 |
:undoc-members:
|
89 |
:show-inheritance:
|
90 |
|
91 |
+
QcriTranslator
|
92 |
----------------------------------
|
93 |
|
94 |
.. automodule:: deep_translator.qcri
|
|
|
102 |
.. automodule:: deep_translator.yandex
|
103 |
:members:
|
104 |
:undoc-members:
|
105 |
+
:show-inheritance:
|
docs/usage.rst
CHANGED
@@ -22,8 +22,8 @@ Imports
|
|
22 |
LingueeTranslator,
|
23 |
MyMemoryTranslator,
|
24 |
YandexTranslator,
|
25 |
-
|
26 |
-
|
27 |
single_detection,
|
28 |
batch_detection)
|
29 |
|
@@ -140,12 +140,12 @@ Mymemory Translator
|
|
140 |
translated = MyMemoryTranslator(source='en', target='fr').translate_file(path)
|
141 |
|
142 |
|
143 |
-
|
144 |
-----------------
|
145 |
|
146 |
.. note::
|
147 |
|
148 |
-
In order to use the
|
149 |
for more information
|
150 |
|
151 |
- Simple translation
|
@@ -154,7 +154,7 @@ DeepL Translator
|
|
154 |
|
155 |
text = 'Keep it up. You are awesome'
|
156 |
|
157 |
-
translated =
|
158 |
|
159 |
- Translate batch of texts
|
160 |
|
@@ -163,14 +163,14 @@ DeepL Translator
|
|
163 |
texts = ["hallo welt", "guten morgen"]
|
164 |
|
165 |
# the translate_sentences function is deprecated, use the translate_batch function instead
|
166 |
-
translated =
|
167 |
|
168 |
-
|
169 |
--------------------
|
170 |
|
171 |
.. note::
|
172 |
|
173 |
-
In order to use the
|
174 |
for more information
|
175 |
|
176 |
- Check languages
|
@@ -178,14 +178,14 @@ QCRI Translator
|
|
178 |
.. code-block:: python
|
179 |
|
180 |
# as a property
|
181 |
-
print("language pairs: ",
|
182 |
|
183 |
- Check domains
|
184 |
|
185 |
.. code-block:: python
|
186 |
|
187 |
# as a property
|
188 |
-
print("domains: ",
|
189 |
|
190 |
- Text translation
|
191 |
|
@@ -193,7 +193,7 @@ QCRI Translator
|
|
193 |
|
194 |
text = 'Education is great'
|
195 |
|
196 |
-
translated =
|
197 |
# output -> التعليم هو عظيم
|
198 |
|
199 |
# see docs for batch translation and more.
|
@@ -306,7 +306,7 @@ Libre Translator
|
|
306 |
.. note::
|
307 |
|
308 |
Libre translate has multiple `mirrors <https://github.com/LibreTranslate/LibreTranslate#mirrors>`_ which can be used for the API endpoint.
|
309 |
-
Some require an API key to be used. By default the base url is set to `libretranslate.de <https://libretranslate.de/>`_ .
|
310 |
This can be set using the "base_url" input parameter.
|
311 |
|
312 |
.. code-block:: python
|
|
|
22 |
LingueeTranslator,
|
23 |
MyMemoryTranslator,
|
24 |
YandexTranslator,
|
25 |
+
DeeplTranslator,
|
26 |
+
QcriTranslator,
|
27 |
single_detection,
|
28 |
batch_detection)
|
29 |
|
|
|
140 |
translated = MyMemoryTranslator(source='en', target='fr').translate_file(path)
|
141 |
|
142 |
|
143 |
+
DeeplTranslator Translator
|
144 |
-----------------
|
145 |
|
146 |
.. note::
|
147 |
|
148 |
+
In order to use the DeeplTranslator translator, you need to generate an api key. Visit https://www.deepl.com/en/docs-api/
|
149 |
for more information
|
150 |
|
151 |
- Simple translation
|
|
|
154 |
|
155 |
text = 'Keep it up. You are awesome'
|
156 |
|
157 |
+
translated = DeeplTranslator("your_api_key").translate(text)
|
158 |
|
159 |
- Translate batch of texts
|
160 |
|
|
|
163 |
texts = ["hallo welt", "guten morgen"]
|
164 |
|
165 |
# the translate_sentences function is deprecated, use the translate_batch function instead
|
166 |
+
translated = DeeplTranslator("your_api_key").translate_batch(texts)
|
167 |
|
168 |
+
QcriTranslator Translator
|
169 |
--------------------
|
170 |
|
171 |
.. note::
|
172 |
|
173 |
+
In order to use the QcriTranslator translator, you need to generate a free api key. Visit https://mt.qcri.org/api/
|
174 |
for more information
|
175 |
|
176 |
- Check languages
|
|
|
178 |
.. code-block:: python
|
179 |
|
180 |
# as a property
|
181 |
+
print("language pairs: ", QcriTranslator("your_api_key").languages)
|
182 |
|
183 |
- Check domains
|
184 |
|
185 |
.. code-block:: python
|
186 |
|
187 |
# as a property
|
188 |
+
print("domains: ", QcriTranslator("your_api_key").domains)
|
189 |
|
190 |
- Text translation
|
191 |
|
|
|
193 |
|
194 |
text = 'Education is great'
|
195 |
|
196 |
+
translated = QcriTranslator("your_api_key").translate(source='en', target='ar', domain="news", text=text)
|
197 |
# output -> التعليم هو عظيم
|
198 |
|
199 |
# see docs for batch translation and more.
|
|
|
306 |
.. note::
|
307 |
|
308 |
Libre translate has multiple `mirrors <https://github.com/LibreTranslate/LibreTranslate#mirrors>`_ which can be used for the API endpoint.
|
309 |
+
Some require an API key to be used. By default the base url is set to `libretranslate.de <https://libretranslate.de/>`_ .
|
310 |
This can be set using the "base_url" input parameter.
|
311 |
|
312 |
.. code-block:: python
|
examples/trans.py
CHANGED
@@ -5,12 +5,16 @@ from deep_translator import GoogleTranslator, PonsTranslator, LingueeTranslator
|
|
5 |
|
6 |
english_text = 'happy coding'
|
7 |
chinese_text = '這很好'
|
|
|
|
|
|
|
8 |
|
9 |
-
|
10 |
-
|
11 |
|
12 |
-
|
13 |
-
|
|
|
14 |
|
15 |
# examples using linguee:
|
16 |
text = 'cute'
|
@@ -19,5 +23,6 @@ print("Using Linguee ==> the translated text: ", translated)
|
|
19 |
|
20 |
# examples using pons:
|
21 |
text = 'good'
|
22 |
-
translated = PonsTranslator(source='
|
23 |
print("using Pons ==> the translated text: ", translated)
|
|
|
|
5 |
|
6 |
english_text = 'happy coding'
|
7 |
chinese_text = '這很好'
|
8 |
+
translator = GoogleTranslator(source='auto', target='german')
|
9 |
+
result1 = translator.translate(text=english_text)
|
10 |
+
result2 = translator.translate(text=chinese_text)
|
11 |
|
12 |
+
print(f"original english text: {english_text} | translated text: {result1}")
|
13 |
+
print(f"original chinese text: {chinese_text} | translated text: {result2}")
|
14 |
|
15 |
+
# file translation
|
16 |
+
result_file = translator.translate_file('./test.txt')
|
17 |
+
print("file translation: ", result_file)
|
18 |
|
19 |
# examples using linguee:
|
20 |
text = 'cute'
|
|
|
23 |
|
24 |
# examples using pons:
|
25 |
text = 'good'
|
26 |
+
translated = PonsTranslator(source='en', target='ar').translate(word=text)
|
27 |
print("using Pons ==> the translated text: ", translated)
|
28 |
+
|
pyproject.toml
CHANGED
@@ -9,7 +9,7 @@ readme = "docs/README.rst"
|
|
9 |
homepage = "https://github.com/nidhaloff/deep_translator"
|
10 |
repository = "https://github.com/nidhaloff/deep_translator"
|
11 |
documentation = "https://deep-translator.readthedocs.io/en/latest/"
|
12 |
-
keywords = ["deep_translator", "deepL", "
|
13 |
classifiers = [
|
14 |
"Development Status :: 5 - Production/Stable",
|
15 |
"Intended Audience :: Developers",
|
|
|
9 |
homepage = "https://github.com/nidhaloff/deep_translator"
|
10 |
repository = "https://github.com/nidhaloff/deep_translator"
|
11 |
documentation = "https://deep-translator.readthedocs.io/en/latest/"
|
12 |
+
keywords = ["deep_translator", "deepL", "DeeplTranslator", "translator", "translation", "automation", "web scraping", "google translator", "google translation", "google trans", "PONS", "YANDEX", "MyMemory translator", "Linguee", "QcriTranslator", "Language", "Language detection", "detect language", "free translation", "unlimited translation", "translate for free"]
|
13 |
classifiers = [
|
14 |
"Development Status :: 5 - Production/Stable",
|
15 |
"Intended Audience :: Developers",
|
tests/test_deepl.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
import pytest
|
2 |
from unittest.mock import Mock, PropertyMock, patch
|
3 |
-
from deep_translator.deepl import
|
4 |
from deep_translator.exceptions import AuthorizationException
|
5 |
|
6 |
|
7 |
@patch('deep_translator.deepl.requests')
|
8 |
def test_simple_translation(mock_requests):
|
9 |
-
translator =
|
10 |
# Set the request response mock.
|
11 |
mock_response = Mock()
|
12 |
mock_response.status_code = 200
|
@@ -22,7 +22,7 @@ def test_simple_translation(mock_requests):
|
|
22 |
|
23 |
@patch('deep_translator.deepl.requests.get')
|
24 |
def test_wrong_api_key(mock_requests):
|
25 |
-
translator =
|
26 |
# Set the response status_code only.
|
27 |
mock_requests.return_value = Mock(status_code=403)
|
28 |
with pytest.raises(AuthorizationException):
|
|
|
1 |
import pytest
|
2 |
from unittest.mock import Mock, PropertyMock, patch
|
3 |
+
from deep_translator.deepl import DeeplTranslator
|
4 |
from deep_translator.exceptions import AuthorizationException
|
5 |
|
6 |
|
7 |
@patch('deep_translator.deepl.requests')
|
8 |
def test_simple_translation(mock_requests):
|
9 |
+
translator = DeeplTranslator(api_key='imagine-this-is-an-valid-api-key', source='en', target='es')
|
10 |
# Set the request response mock.
|
11 |
mock_response = Mock()
|
12 |
mock_response.status_code = 200
|
|
|
22 |
|
23 |
@patch('deep_translator.deepl.requests.get')
|
24 |
def test_wrong_api_key(mock_requests):
|
25 |
+
translator = DeeplTranslator(api_key='this-is-a-wrong-api-key!', source="en", target="es")
|
26 |
# Set the response status_code only.
|
27 |
mock_requests.return_value = Mock(status_code=403)
|
28 |
with pytest.raises(AuthorizationException):
|
tests/test_google.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
|
3 |
+
"""Tests for `deep_translator` package."""
|
4 |
+
|
5 |
+
import pytest
|
6 |
+
from deep_translator import exceptions, GoogleTranslator
|
7 |
+
from deep_translator.constants import GOOGLE_CODES_TO_LANGUAGES
|
8 |
+
|
9 |
+
|
10 |
+
@pytest.fixture
|
11 |
+
def google_translator():
|
12 |
+
"""Sample pytest fixture.
|
13 |
+
See more at: http://doc.pytest.org/en/latest/fixture.html
|
14 |
+
"""
|
15 |
+
return GoogleTranslator(target='en')
|
16 |
+
|
17 |
+
|
18 |
+
def test_content(google_translator):
|
19 |
+
"""Sample pytest test function with the pytest fixture as an argument."""
|
20 |
+
assert google_translator.translate(text='좋은') == "good"
|
21 |
+
|
22 |
+
|
23 |
+
def test_abbreviations_and_languages_mapping():
|
24 |
+
for abb, lang in GOOGLE_CODES_TO_LANGUAGES.items():
|
25 |
+
g1 = GoogleTranslator(abb)
|
26 |
+
g2 = GoogleTranslator(lang)
|
27 |
+
assert g1._source == g2._source
|
28 |
+
|
29 |
+
|
30 |
+
def test_inputs():
|
31 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
32 |
+
GoogleTranslator(source="", target="")
|
33 |
+
|
34 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
35 |
+
GoogleTranslator(source="auto", target="")
|
36 |
+
|
37 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
38 |
+
GoogleTranslator(source="", target="en")
|
39 |
+
|
40 |
+
|
41 |
+
def test_empty_text(google_translator):
|
42 |
+
empty_txt = ""
|
43 |
+
res = google_translator.translate(text=empty_txt)
|
44 |
+
assert res == empty_txt
|
45 |
+
|
46 |
+
|
47 |
+
def test_payload(google_translator):
|
48 |
+
|
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 |
+
|
60 |
+
with pytest.raises(exceptions.NotValidPayload):
|
61 |
+
google_translator.translate(text=[])
|
62 |
+
|
63 |
+
with pytest.raises(exceptions.NotValidLength):
|
64 |
+
google_translator.translate("a"*5001)
|
65 |
+
|
66 |
+
|
67 |
+
def test_one_character_words():
|
68 |
+
assert GoogleTranslator(source='es', target='en').translate('o') == 'or'
|
tests/test_google_trans.py
DELETED
@@ -1,175 +0,0 @@
|
|
1 |
-
#!/usr/bin/env python
|
2 |
-
|
3 |
-
"""Tests for `deep_translator` package."""
|
4 |
-
|
5 |
-
import pytest
|
6 |
-
from deep_translator import exceptions, GoogleTranslator
|
7 |
-
from deep_translator.constants import GOOGLE_CODES_TO_LANGUAGES
|
8 |
-
|
9 |
-
|
10 |
-
test_text_standard = 'Hello world.'
|
11 |
-
|
12 |
-
TRANSLATED_RESULTS = {
|
13 |
-
"afrikaans": "Hello Wêreld.",
|
14 |
-
"albanian": "Përshendetje Botë.",
|
15 |
-
"amharic": "ሰላም ልዑል.",
|
16 |
-
"arabic": "مرحبا بالعالم.",
|
17 |
-
"armenian": "Բարեւ աշխարհ.",
|
18 |
-
"azerbaijani": "Salam dünya.",
|
19 |
-
"basque": "Kaixo Mundua.",
|
20 |
-
"belarusian": "Прывітанне Сусвет.",
|
21 |
-
"bengali": "ওহে বিশ্ব.",
|
22 |
-
"bosnian": "Zdravo svijete.",
|
23 |
-
"bulgarian": "Здравей свят.",
|
24 |
-
"catalan": "Hola món.",
|
25 |
-
"cebuano": "Kumusta kalibutan.",
|
26 |
-
"chichewa": "Moni Dziko Lapansi.",
|
27 |
-
"chinese (simplified)": "你好,世界。",
|
28 |
-
"chinese (traditional)": "你好,世界。",
|
29 |
-
"corsican": "Bonghjornu mondu.",
|
30 |
-
"croatian": "Pozdrav svijete.",
|
31 |
-
"czech": "Ahoj světe.",
|
32 |
-
"danish": "Hej Verden.",
|
33 |
-
"dutch": "Hallo Wereld.",
|
34 |
-
"esperanto": "Saluton mondo.",
|
35 |
-
"estonian": "Tere, Maailm.",
|
36 |
-
"filipino": "Kamusta mundo",
|
37 |
-
"finnish": "Hei maailma.",
|
38 |
-
"french": "Bonjour le monde.",
|
39 |
-
"frisian": "Hallo wrâld.",
|
40 |
-
"galician": "Ola mundo.",
|
41 |
-
"georgian": "Გამარჯობა მსოფლიო.",
|
42 |
-
"german": "Hallo Welt.",
|
43 |
-
"greek": "Γειά σου Κόσμε.",
|
44 |
-
"gujarati": "હેલો વર્લ્ડ.",
|
45 |
-
"haitian creole": "Bonjou mond.",
|
46 |
-
"hausa": "Sannu Duniya.",
|
47 |
-
"hawaiian": "Aloha honua.",
|
48 |
-
"hebrew": "שלום עולם.",
|
49 |
-
"hindi": "नमस्ते दुनिया।",
|
50 |
-
"hmong": "Nyob zoo ntiaj teb.",
|
51 |
-
"hungarian": "Helló Világ.",
|
52 |
-
"icelandic": "Halló heimur.",
|
53 |
-
"igbo": "Ndewo Ụwa.",
|
54 |
-
"indonesian": "Halo Dunia.",
|
55 |
-
"irish": "Dia duit ar domhan.",
|
56 |
-
"italian": "Ciao mondo.",
|
57 |
-
"japanese": "こんにちは世界。",
|
58 |
-
"javanese": "Halo jagad.",
|
59 |
-
"kannada": "ಹಲೋ ವಿಶ್ವ.",
|
60 |
-
"kazakh": "Сәлем Әлем.",
|
61 |
-
"khmer": "សួស្តីពិភពលោក។",
|
62 |
-
"kinyarwanda": "Mwaramutse isi.",
|
63 |
-
"korean": "안녕하세요 세계입니다.",
|
64 |
-
"kurdish": "Hello cîhanê.",
|
65 |
-
"kyrgyz": "Салам дүйнө.",
|
66 |
-
"lao": "ສະບາຍດີຊາວໂລກ.",
|
67 |
-
"latin": "Salve mundi.",
|
68 |
-
"latvian": "Sveika pasaule.",
|
69 |
-
"lithuanian": "Labas pasauli.",
|
70 |
-
"luxembourgish": "Moien Welt.",
|
71 |
-
"macedonian": "Здраво свету.",
|
72 |
-
"malagasy": "Hello World.",
|
73 |
-
"malay": "Hai dunia.",
|
74 |
-
"malayalam": "ഹലോ വേൾഡ്.",
|
75 |
-
"maltese": "Hello dinja.",
|
76 |
-
"maori": "Kia ora te ao.",
|
77 |
-
"marathi": "नमस्कार जग.",
|
78 |
-
"mongolian": "Сайн уу ертөнц.",
|
79 |
-
"myanmar": "မင်္ဂလာပါကမ္ဘာလောက။",
|
80 |
-
"nepali": "नमस्कार संसार।",
|
81 |
-
"norwegian": "Hei Verden.",
|
82 |
-
"odia": "ନମସ୍କାର ବିଶ୍ୱବାସି।",
|
83 |
-
"pashto": "سلام نړی.",
|
84 |
-
"persian": "سلام دنیا.",
|
85 |
-
"polish": "Witaj świecie.",
|
86 |
-
"portuguese": "Olá Mundo.",
|
87 |
-
"punjabi": "ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ ਦੁਨਿਆ.",
|
88 |
-
"romanian": "Salut Lume.",
|
89 |
-
"russian": "Привет, мир.",
|
90 |
-
"samoan": "Talofa lalolagi.",
|
91 |
-
"scots gaelic": "Hàlo a Shaoghail.",
|
92 |
-
"serbian": "Здраво Свете.",
|
93 |
-
"sesotho": "Lefatše Lumela.",
|
94 |
-
"shona": "Mhoro nyika.",
|
95 |
-
"sindhi": "هيلو دنيا.",
|
96 |
-
"sinhala": "හෙලෝ වර්ල්ඩ්.",
|
97 |
-
"slovak": "Ahoj svet.",
|
98 |
-
"slovenian": "Pozdravljen, svet.",
|
99 |
-
"somali": "Salaamu calaykum.",
|
100 |
-
"spanish": "Hola Mundo.",
|
101 |
-
"sundanese": "Halo Dunya.",
|
102 |
-
"swahili": "Salamu, Dunia.",
|
103 |
-
"swedish": "Hej världen.",
|
104 |
-
"tajik": "Салом Ҷаҳон.",
|
105 |
-
"tamil": "வணக்கம் உலகம்.",
|
106 |
-
"tatar": "Сәлам, Дөнья.",
|
107 |
-
"telugu": "హలో వరల్డ్.",
|
108 |
-
"thai": "สวัสดีชาวโลก.",
|
109 |
-
"turkish": "Selam Dünya.",
|
110 |
-
"turkmen": "Salam dünýä.",
|
111 |
-
"ukrainian": "Привіт Світ.",
|
112 |
-
"urdu": "سلام دنیا۔",
|
113 |
-
"uyghur": "ياخشىمۇسىز دۇنيا.",
|
114 |
-
"uzbek": "Salom Dunyo.",
|
115 |
-
"vietnamese": "Chào thế giới.",
|
116 |
-
"welsh": "Helo Byd.",
|
117 |
-
"xhosa": "Molo Lizwe.",
|
118 |
-
"yiddish": "העלא וועלט.",
|
119 |
-
"yoruba": "Mo ki O Ile Aiye.",
|
120 |
-
"zulu": "Sawubona Mhlaba."
|
121 |
-
}
|
122 |
-
|
123 |
-
|
124 |
-
@pytest.fixture
|
125 |
-
def google_translator():
|
126 |
-
"""Sample pytest fixture.
|
127 |
-
See more at: http://doc.pytest.org/en/latest/fixture.html
|
128 |
-
"""
|
129 |
-
return GoogleTranslator(target='en')
|
130 |
-
|
131 |
-
|
132 |
-
def test_content(google_translator):
|
133 |
-
"""Sample pytest test function with the pytest fixture as an argument."""
|
134 |
-
# from bs4 import BeautifulSoup
|
135 |
-
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
136 |
-
assert google_translator.translate(text='좋은') == "good"
|
137 |
-
|
138 |
-
|
139 |
-
def test_abbreviations_and_languages_mapping():
|
140 |
-
for abb, lang in GOOGLE_CODES_TO_LANGUAGES.items():
|
141 |
-
if abb != 'en':
|
142 |
-
g1 = GoogleTranslator(abb)
|
143 |
-
g2 = GoogleTranslator(lang)
|
144 |
-
assert g1._source == g2._source
|
145 |
-
|
146 |
-
|
147 |
-
def test_inputs():
|
148 |
-
with pytest.raises(exceptions.LanguageNotSupportedException):
|
149 |
-
GoogleTranslator(source="", target="")
|
150 |
-
|
151 |
-
with pytest.raises(exceptions.LanguageNotSupportedException):
|
152 |
-
GoogleTranslator(source="auto", target="nothing")
|
153 |
-
|
154 |
-
def test_payload(google_translator):
|
155 |
-
|
156 |
-
with pytest.raises(exceptions.NotValidPayload):
|
157 |
-
google_translator.translate(text="")
|
158 |
-
google_translator.translate(text='1234')
|
159 |
-
google_translator.translate(text='{}')
|
160 |
-
google_translator.translate(text='%@')
|
161 |
-
|
162 |
-
with pytest.raises(exceptions.NotValidPayload):
|
163 |
-
google_translator.translate(text=123)
|
164 |
-
|
165 |
-
with pytest.raises(exceptions.NotValidPayload):
|
166 |
-
google_translator.translate(text={})
|
167 |
-
|
168 |
-
with pytest.raises(exceptions.NotValidPayload):
|
169 |
-
google_translator.translate(text=[])
|
170 |
-
|
171 |
-
with pytest.raises(exceptions.NotValidLength):
|
172 |
-
google_translator.translate("a"*5001)
|
173 |
-
|
174 |
-
def test_one_character_words():
|
175 |
-
assert GoogleTranslator(source='es', target='en').translate('o') == 'or'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test_libre.py
CHANGED
@@ -6,60 +6,31 @@ import pytest
|
|
6 |
from deep_translator import exceptions, LibreTranslator
|
7 |
from deep_translator.constants import LIBRE_CODES_TO_LANGUAGES
|
8 |
|
9 |
-
test_text_standard = 'Hello world.'
|
10 |
-
TRANSLATED_RESULTS = {
|
11 |
-
'English': 'Hello world.',
|
12 |
-
'Arabic': 'مرحبا العالم.',
|
13 |
-
'Chinese': '霍洛美世界。',
|
14 |
-
'French': 'Bonjour.',
|
15 |
-
'German': 'Hallo Welt.',
|
16 |
-
'Hindi': 'नमस्ते दुनिया।',
|
17 |
-
'Indonesian': 'Halo dunia.',
|
18 |
-
'Irish': 'Dia duit domhan.',
|
19 |
-
'Italian': 'Ciao mondo.',
|
20 |
-
'Japanese': 'こんにちは。',
|
21 |
-
'Korean': '안녕하세요.',
|
22 |
-
'Polish': 'Hello world (ang.).',
|
23 |
-
'Portuguese': 'Olá, mundo.',
|
24 |
-
'Russian': 'Привет мир.',
|
25 |
-
'Spanish': 'Hola mundo.',
|
26 |
-
'Turkish': 'Merhaba dünya.',
|
27 |
-
'Vietnamese': 'Xin chào.'
|
28 |
-
}
|
29 |
-
|
30 |
|
31 |
@pytest.fixture
|
32 |
def libre():
|
33 |
-
return LibreTranslator(source="en", target='fr')
|
34 |
-
|
35 |
-
|
36 |
-
def test_content(libre):
|
37 |
-
"""Sample pytest test function with the pytest fixture as an argument."""
|
38 |
-
# from bs4 import BeautifulSoup
|
39 |
-
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
40 |
-
assert libre.translate(text='good') is not None
|
41 |
|
42 |
|
43 |
def test_inputs():
|
44 |
-
with pytest.raises(exceptions.
|
45 |
-
LibreTranslator(source="", target="")
|
46 |
|
47 |
-
with pytest.raises(exceptions.
|
48 |
-
LibreTranslator(source="auto", target="
|
|
|
|
|
|
|
49 |
|
50 |
|
51 |
def test_abbreviations_and_languages_mapping():
|
52 |
for abb, lang in LIBRE_CODES_TO_LANGUAGES.items():
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
assert l1.source == l2.source
|
57 |
|
58 |
|
59 |
def test_payload(libre):
|
60 |
-
with pytest.raises(exceptions.NotValidPayload):
|
61 |
-
libre.translate("")
|
62 |
-
|
63 |
with pytest.raises(exceptions.NotValidPayload):
|
64 |
libre.translate(123)
|
65 |
|
@@ -68,19 +39,3 @@ def test_payload(libre):
|
|
68 |
|
69 |
with pytest.raises(exceptions.NotValidPayload):
|
70 |
libre.translate([])
|
71 |
-
|
72 |
-
|
73 |
-
def test_one_character_words():
|
74 |
-
assert LibreTranslator(source='es', target='en').translate('y') == 'and'
|
75 |
-
|
76 |
-
|
77 |
-
def test_translate_batch():
|
78 |
-
words_to_translate = ['How are you', 'Good', 'Thank You']
|
79 |
-
translated_words = ['¿Cómo estás?', 'Bien.', 'Gracias.']
|
80 |
-
assert LibreTranslator(source='en', target='es').translate_batch((words_to_translate)) == translated_words
|
81 |
-
|
82 |
-
|
83 |
-
def test_translate_file():
|
84 |
-
filePath = 'examples/test.txt'
|
85 |
-
translatedText = 'Un párrafo es una serie de frases relacionadas que desarrollan una idea central, llamada el tema. Trate de pensar en los párrafos en términos de unidad temática: un párrafo es una frase o un grupo de oraciones que apoya una idea central y unificada. Los párrafos añaden una idea a la vez a su argumento más amplio.'
|
86 |
-
assert LibreTranslator(source='en', target='es').translate_file(filePath) == translatedText
|
|
|
6 |
from deep_translator import exceptions, LibreTranslator
|
7 |
from deep_translator.constants import LIBRE_CODES_TO_LANGUAGES
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def libre():
|
12 |
+
return LibreTranslator(source="en", target='fr', api_key='some_key')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
|
15 |
def test_inputs():
|
16 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
17 |
+
LibreTranslator(source="", target="", api_key='some_key')
|
18 |
|
19 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
20 |
+
LibreTranslator(source="auto", target="", api_key='some_key')
|
21 |
+
|
22 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
+
LibreTranslator(source="", target="en", api_key='some_key')
|
24 |
|
25 |
|
26 |
def test_abbreviations_and_languages_mapping():
|
27 |
for abb, lang in LIBRE_CODES_TO_LANGUAGES.items():
|
28 |
+
l1 = LibreTranslator(abb, api_key='some_key')
|
29 |
+
l2 = LibreTranslator(lang, api_key='some_key')
|
30 |
+
assert l1._source == l2._source
|
|
|
31 |
|
32 |
|
33 |
def test_payload(libre):
|
|
|
|
|
|
|
34 |
with pytest.raises(exceptions.NotValidPayload):
|
35 |
libre.translate(123)
|
36 |
|
|
|
39 |
|
40 |
with pytest.raises(exceptions.NotValidPayload):
|
41 |
libre.translate([])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test_linguee.py
CHANGED
@@ -8,7 +8,7 @@ from deep_translator import exceptions, LingueeTranslator
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def linguee():
|
11 |
-
return LingueeTranslator(source="english", target='
|
12 |
|
13 |
|
14 |
def test_content(linguee):
|
@@ -19,11 +19,14 @@ def test_content(linguee):
|
|
19 |
|
20 |
|
21 |
def test_inputs():
|
22 |
-
with pytest.raises(exceptions.
|
23 |
LingueeTranslator(source="", target="")
|
24 |
|
25 |
-
with pytest.raises(exceptions.
|
26 |
-
LingueeTranslator(source="auto", target="
|
|
|
|
|
|
|
27 |
|
28 |
l1 = LingueeTranslator("en", "fr")
|
29 |
l2 = LingueeTranslator("english", "french")
|
@@ -33,9 +36,6 @@ def test_inputs():
|
|
33 |
|
34 |
def test_payload(linguee):
|
35 |
|
36 |
-
with pytest.raises(exceptions.NotValidPayload):
|
37 |
-
linguee.translate("")
|
38 |
-
|
39 |
with pytest.raises(exceptions.NotValidPayload):
|
40 |
linguee.translate(123)
|
41 |
|
@@ -47,12 +47,3 @@ def test_payload(linguee):
|
|
47 |
|
48 |
with pytest.raises(exceptions.NotValidLength):
|
49 |
linguee.translate("a"*51)
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
def test_translate_words(linguee):
|
54 |
-
words = ['hello', 'world']
|
55 |
-
translated_words = linguee.translate_words(words)
|
56 |
-
|
57 |
-
def test_one_character_words():
|
58 |
-
assert LingueeTranslator(source='es', target='en').translate('y') == 'and'
|
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def linguee():
|
11 |
+
return LingueeTranslator(source="english", target='german')
|
12 |
|
13 |
|
14 |
def test_content(linguee):
|
|
|
19 |
|
20 |
|
21 |
def test_inputs():
|
22 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
LingueeTranslator(source="", target="")
|
24 |
|
25 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
26 |
+
LingueeTranslator(source="auto", target="")
|
27 |
+
|
28 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
29 |
+
LingueeTranslator(source="", target="en")
|
30 |
|
31 |
l1 = LingueeTranslator("en", "fr")
|
32 |
l2 = LingueeTranslator("english", "french")
|
|
|
36 |
|
37 |
def test_payload(linguee):
|
38 |
|
|
|
|
|
|
|
39 |
with pytest.raises(exceptions.NotValidPayload):
|
40 |
linguee.translate(123)
|
41 |
|
|
|
47 |
|
48 |
with pytest.raises(exceptions.NotValidLength):
|
49 |
linguee.translate("a"*51)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test_microsoft_trans.py
CHANGED
@@ -20,12 +20,12 @@ def test_microsoft_successful_post_mock(mock_request_post):
|
|
20 |
r.json = json_func
|
21 |
return r
|
22 |
mock_request_post.return_value = res()
|
23 |
-
assert MicrosoftTranslator(api_key="an_api_key", target="en").translate("auf wiedersehen!") == "See you later!"
|
24 |
|
25 |
|
26 |
def test_MicrosoftAPIerror():
|
27 |
with pytest.raises(exceptions.MicrosoftAPIerror):
|
28 |
-
MicrosoftTranslator(api_key="empty", target="en").translate("text")
|
29 |
|
30 |
|
31 |
# the remaining tests are actual requests to Microsoft API and use an api key
|
@@ -58,5 +58,5 @@ def test_incorrect_target_attributes():
|
|
58 |
def test_abbreviations():
|
59 |
m1 = MicrosoftTranslator(api_key=APIkey, source="en", target="fr")
|
60 |
m2 = MicrosoftTranslator(api_key=APIkey, source="English", target="French")
|
61 |
-
assert ''.join(m1.
|
62 |
-
assert ''.join(m1.
|
|
|
20 |
r.json = json_func
|
21 |
return r
|
22 |
mock_request_post.return_value = res()
|
23 |
+
assert MicrosoftTranslator(api_key="an_api_key", source='de', target="en").translate("auf wiedersehen!") == "See you later!"
|
24 |
|
25 |
|
26 |
def test_MicrosoftAPIerror():
|
27 |
with pytest.raises(exceptions.MicrosoftAPIerror):
|
28 |
+
MicrosoftTranslator(api_key="empty", source='de', target="en").translate("text")
|
29 |
|
30 |
|
31 |
# the remaining tests are actual requests to Microsoft API and use an api key
|
|
|
58 |
def test_abbreviations():
|
59 |
m1 = MicrosoftTranslator(api_key=APIkey, source="en", target="fr")
|
60 |
m2 = MicrosoftTranslator(api_key=APIkey, source="English", target="French")
|
61 |
+
assert ''.join(m1._source) == ''.join(m2._source)
|
62 |
+
assert ''.join(m1._target) == ''.join(m2._target)
|
tests/test_mymemory.py
CHANGED
@@ -19,11 +19,15 @@ def test_content(mymemory):
|
|
19 |
|
20 |
|
21 |
def test_inputs():
|
22 |
-
with pytest.raises(exceptions.
|
23 |
MyMemoryTranslator(source="", target="")
|
24 |
|
25 |
-
with pytest.raises(exceptions.
|
26 |
-
MyMemoryTranslator(source="auto", target="
|
|
|
|
|
|
|
|
|
27 |
m1 = MyMemoryTranslator("en", "fr")
|
28 |
m2 = MyMemoryTranslator("english", "french")
|
29 |
assert m1._source == m2._source
|
@@ -32,9 +36,6 @@ def test_inputs():
|
|
32 |
|
33 |
def test_payload(mymemory):
|
34 |
|
35 |
-
with pytest.raises(exceptions.NotValidPayload):
|
36 |
-
mymemory.translate(text="")
|
37 |
-
|
38 |
with pytest.raises(exceptions.NotValidPayload):
|
39 |
mymemory.translate(text=123)
|
40 |
|
@@ -48,6 +49,3 @@ def test_payload(mymemory):
|
|
48 |
mymemory.translate(text="a"*501)
|
49 |
|
50 |
|
51 |
-
def test_one_character_words(mymemory):
|
52 |
-
assert mymemory.translate('I')
|
53 |
-
|
|
|
19 |
|
20 |
|
21 |
def test_inputs():
|
22 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
MyMemoryTranslator(source="", target="")
|
24 |
|
25 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
26 |
+
MyMemoryTranslator(source="auto", target="")
|
27 |
+
|
28 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
29 |
+
MyMemoryTranslator(source="", target="en")
|
30 |
+
|
31 |
m1 = MyMemoryTranslator("en", "fr")
|
32 |
m2 = MyMemoryTranslator("english", "french")
|
33 |
assert m1._source == m2._source
|
|
|
36 |
|
37 |
def test_payload(mymemory):
|
38 |
|
|
|
|
|
|
|
39 |
with pytest.raises(exceptions.NotValidPayload):
|
40 |
mymemory.translate(text=123)
|
41 |
|
|
|
49 |
mymemory.translate(text="a"*501)
|
50 |
|
51 |
|
|
|
|
|
|
tests/test_pons.py
CHANGED
@@ -19,11 +19,15 @@ def test_content(pons):
|
|
19 |
|
20 |
|
21 |
def test_inputs():
|
22 |
-
with pytest.raises(exceptions.
|
23 |
PonsTranslator(source="", target="")
|
24 |
|
25 |
-
with pytest.raises(exceptions.
|
26 |
-
PonsTranslator(source="auto", target="
|
|
|
|
|
|
|
|
|
27 |
l1 = PonsTranslator("en", "fr")
|
28 |
l2 = PonsTranslator("english", "french")
|
29 |
assert l1._source == l2._source
|
@@ -31,10 +35,6 @@ def test_inputs():
|
|
31 |
|
32 |
|
33 |
def test_payload(pons):
|
34 |
-
|
35 |
-
with pytest.raises(exceptions.NotValidPayload):
|
36 |
-
pons.translate("")
|
37 |
-
|
38 |
with pytest.raises(exceptions.NotValidPayload):
|
39 |
pons.translate(123)
|
40 |
|
@@ -47,11 +47,3 @@ def test_payload(pons):
|
|
47 |
with pytest.raises(exceptions.NotValidLength):
|
48 |
pons.translate("a" * 51)
|
49 |
|
50 |
-
|
51 |
-
|
52 |
-
def test_translate_words(pons):
|
53 |
-
words = ['hello', 'world']
|
54 |
-
translated_words = pons.translate_words(words)
|
55 |
-
|
56 |
-
def test_one_character_words(pons):
|
57 |
-
assert pons.translate('I')
|
|
|
19 |
|
20 |
|
21 |
def test_inputs():
|
22 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
PonsTranslator(source="", target="")
|
24 |
|
25 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
26 |
+
PonsTranslator(source="auto", target="")
|
27 |
+
|
28 |
+
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
29 |
+
PonsTranslator(source="", target="en")
|
30 |
+
|
31 |
l1 = PonsTranslator("en", "fr")
|
32 |
l2 = PonsTranslator("english", "french")
|
33 |
assert l1._source == l2._source
|
|
|
35 |
|
36 |
|
37 |
def test_payload(pons):
|
|
|
|
|
|
|
|
|
38 |
with pytest.raises(exceptions.NotValidPayload):
|
39 |
pons.translate(123)
|
40 |
|
|
|
47 |
with pytest.raises(exceptions.NotValidLength):
|
48 |
pons.translate("a" * 51)
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|