=
commited on
Commit
·
f36740b
1
Parent(s):
fb68c2a
fixed the requests issue and added a check on text length
Browse files- deep_translator/cli.py +11 -6
- deep_translator/configs.py +4 -0
- deep_translator/detection.py +24 -0
- deep_translator/exceptions.py +37 -1
- deep_translator/google_trans.py +29 -6
- deep_translator/linguee.py +43 -6
- deep_translator/mymemory.py +42 -10
- deep_translator/parent.py +17 -4
- deep_translator/pons.py +41 -6
- deep_translator/tests/test_google_trans.py +4 -0
- deep_translator/tests/test_linguee.py +3 -0
- deep_translator/tests/test_mymemory.py +4 -0
- deep_translator/tests/test_pons.py +4 -0
deep_translator/cli.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
"""Console script for deep_translator."""
|
|
|
2 |
import argparse
|
3 |
import sys
|
4 |
from .google_trans import GoogleTranslator
|
@@ -8,6 +9,11 @@ from .linguee import LingueeTranslator
|
|
8 |
|
9 |
|
10 |
def translate(args):
|
|
|
|
|
|
|
|
|
|
|
11 |
translator = None
|
12 |
if args.translator == 'google':
|
13 |
translator = GoogleTranslator(source=args.source, target=args.target)
|
@@ -26,7 +32,10 @@ def translate(args):
|
|
26 |
|
27 |
|
28 |
def main():
|
29 |
-
"""
|
|
|
|
|
|
|
30 |
parser = argparse.ArgumentParser()
|
31 |
parser.add_argument('--translator', '-trans',
|
32 |
default='google', type=str, help="name of the translator you want to use")
|
@@ -36,12 +45,8 @@ def main():
|
|
36 |
|
37 |
args = parser.parse_args()
|
38 |
translate(args)
|
39 |
-
#
|
40 |
-
# print("Replace this message by putting your code into "
|
41 |
-
# "deep_translator.cli.main")
|
42 |
-
# return 0
|
43 |
|
44 |
|
45 |
if __name__ == "__main__":
|
46 |
-
# sys.exit(main()) # pragma: no cover
|
47 |
main()
|
|
|
1 |
"""Console script for deep_translator."""
|
2 |
+
|
3 |
import argparse
|
4 |
import sys
|
5 |
from .google_trans import GoogleTranslator
|
|
|
9 |
|
10 |
|
11 |
def translate(args):
|
12 |
+
"""
|
13 |
+
function used to provide translations from the parsed terminal arguments
|
14 |
+
@param args: parsed terminal arguments
|
15 |
+
@return: None
|
16 |
+
"""
|
17 |
translator = None
|
18 |
if args.translator == 'google':
|
19 |
translator = GoogleTranslator(source=args.source, target=args.target)
|
|
|
32 |
|
33 |
|
34 |
def main():
|
35 |
+
"""
|
36 |
+
function responsible for parsing terminal arguments and provide them for further use in the translation process
|
37 |
+
|
38 |
+
"""
|
39 |
parser = argparse.ArgumentParser()
|
40 |
parser.add_argument('--translator', '-trans',
|
41 |
default='google', type=str, help="name of the translator you want to use")
|
|
|
45 |
|
46 |
args = parser.parse_args()
|
47 |
translate(args)
|
48 |
+
# sys.exit()
|
|
|
|
|
|
|
49 |
|
50 |
|
51 |
if __name__ == "__main__":
|
|
|
52 |
main()
|
deep_translator/configs.py
CHANGED
@@ -1,3 +1,7 @@
|
|
|
|
|
|
|
|
|
|
1 |
config = {
|
2 |
"url": 'https://ws.detectlanguage.com/0.2/detect',
|
3 |
"headers": {
|
|
|
1 |
+
"""
|
2 |
+
configuration object that holds data about the language detection api
|
3 |
+
"""
|
4 |
+
|
5 |
config = {
|
6 |
"url": 'https://ws.detectlanguage.com/0.2/detect',
|
7 |
"headers": {
|
deep_translator/detection.py
CHANGED
@@ -1,10 +1,21 @@
|
|
|
|
|
|
|
|
1 |
import requests
|
2 |
from deep_translator.configs import config
|
3 |
from requests.exceptions import HTTPError
|
4 |
|
5 |
|
6 |
def get_request_body(text, api_key, *args):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
|
|
8 |
if not api_key:
|
9 |
raise Exception("you need to get an API_KEY for this to work. "
|
10 |
"Get one for free here: https://detectlanguage.com/documentation")
|
@@ -30,6 +41,12 @@ def get_request_body(text, api_key, *args):
|
|
30 |
def single_detection(text, api_key=None, detailed=False, *args, **kwargs):
|
31 |
"""
|
32 |
function responsible for detecting the language from a text
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
"""
|
34 |
body = get_request_body(text, api_key)
|
35 |
detections = body.get('detections')
|
@@ -42,6 +59,13 @@ def single_detection(text, api_key=None, detailed=False, *args, **kwargs):
|
|
42 |
|
43 |
|
44 |
def batch_detection(text_list, api_key, detailed=False, *args):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
body = get_request_body(text_list, api_key)
|
46 |
detections = body.get('detections')
|
47 |
res = [obj[0] for obj in detections]
|
|
|
1 |
+
"""
|
2 |
+
language detection API
|
3 |
+
"""
|
4 |
import requests
|
5 |
from deep_translator.configs import config
|
6 |
from requests.exceptions import HTTPError
|
7 |
|
8 |
|
9 |
def get_request_body(text, api_key, *args):
|
10 |
+
"""
|
11 |
+
send a request and return the response body parsed as dictionary
|
12 |
+
|
13 |
+
@param text: target text that you want to detect its language
|
14 |
+
@type text: str
|
15 |
+
@type api_key: str
|
16 |
+
@param api_key: your private API key
|
17 |
|
18 |
+
"""
|
19 |
if not api_key:
|
20 |
raise Exception("you need to get an API_KEY for this to work. "
|
21 |
"Get one for free here: https://detectlanguage.com/documentation")
|
|
|
41 |
def single_detection(text, api_key=None, detailed=False, *args, **kwargs):
|
42 |
"""
|
43 |
function responsible for detecting the language from a text
|
44 |
+
|
45 |
+
@param text: target text that you want to detect its language
|
46 |
+
@type text: str
|
47 |
+
@type api_key: str
|
48 |
+
@param api_key: your private API key
|
49 |
+
@param detailed: set to True if you want to get detailed information about the detection process
|
50 |
"""
|
51 |
body = get_request_body(text, api_key)
|
52 |
detections = body.get('detections')
|
|
|
59 |
|
60 |
|
61 |
def batch_detection(text_list, api_key, detailed=False, *args):
|
62 |
+
"""
|
63 |
+
function responsible for detecting the language from a text
|
64 |
+
|
65 |
+
@param text_list: target batch that you want to detect its language
|
66 |
+
@param api_key: your private API key
|
67 |
+
@param detailed: set to True if you want to get detailed information about the detection process
|
68 |
+
"""
|
69 |
body = get_request_body(text_list, api_key)
|
70 |
detections = body.get('detections')
|
71 |
res = [obj[0] for obj in detections]
|
deep_translator/exceptions.py
CHANGED
@@ -1,6 +1,14 @@
|
|
1 |
|
|
|
2 |
class BaseError(Exception):
|
|
|
|
|
|
|
3 |
def __init__(self, val, message):
|
|
|
|
|
|
|
|
|
4 |
self.val = val
|
5 |
self.message = message
|
6 |
super().__init__()
|
@@ -10,11 +18,17 @@ class BaseError(Exception):
|
|
10 |
|
11 |
|
12 |
class LanguageNotSupportedException(BaseError):
|
|
|
|
|
|
|
13 |
def __init__(self, val, message="There is no support for the chosen language"):
|
14 |
super().__init__(val, message)
|
15 |
|
16 |
|
17 |
class NotValidPayload(BaseError):
|
|
|
|
|
|
|
18 |
def __init__(self,
|
19 |
val,
|
20 |
message='text must be a valid text with maximum 5000 character, otherwise it cannot be translated'):
|
@@ -22,6 +36,9 @@ class NotValidPayload(BaseError):
|
|
22 |
|
23 |
|
24 |
class TranslationNotFound(BaseError):
|
|
|
|
|
|
|
25 |
def __init__(self,
|
26 |
val,
|
27 |
message='No translation was found using the current translator. Try another translator?'):
|
@@ -29,6 +46,9 @@ class TranslationNotFound(BaseError):
|
|
29 |
|
30 |
|
31 |
class ElementNotFoundInGetRequest(BaseError):
|
|
|
|
|
|
|
32 |
def __init__(self,
|
33 |
val,
|
34 |
message='Required element was not found in the API response'):
|
@@ -36,5 +56,21 @@ class ElementNotFoundInGetRequest(BaseError):
|
|
36 |
|
37 |
|
38 |
class NotValidLength(BaseError):
|
39 |
-
|
|
|
|
|
|
|
|
|
40 |
super(NotValidLength, self).__init__(val, message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
+
|
3 |
class BaseError(Exception):
|
4 |
+
"""
|
5 |
+
base error structure class
|
6 |
+
"""
|
7 |
def __init__(self, val, message):
|
8 |
+
"""
|
9 |
+
@param val: actual value
|
10 |
+
@param message: message shown to the user
|
11 |
+
"""
|
12 |
self.val = val
|
13 |
self.message = message
|
14 |
super().__init__()
|
|
|
18 |
|
19 |
|
20 |
class LanguageNotSupportedException(BaseError):
|
21 |
+
"""
|
22 |
+
exception thrown if the user uses a language that is not supported by the deep_translator
|
23 |
+
"""
|
24 |
def __init__(self, val, message="There is no support for the chosen language"):
|
25 |
super().__init__(val, message)
|
26 |
|
27 |
|
28 |
class NotValidPayload(BaseError):
|
29 |
+
"""
|
30 |
+
exception thrown if the user enters an invalid payload
|
31 |
+
"""
|
32 |
def __init__(self,
|
33 |
val,
|
34 |
message='text must be a valid text with maximum 5000 character, otherwise it cannot be translated'):
|
|
|
36 |
|
37 |
|
38 |
class TranslationNotFound(BaseError):
|
39 |
+
"""
|
40 |
+
exception thrown if no translation was found for the text provided by the user
|
41 |
+
"""
|
42 |
def __init__(self,
|
43 |
val,
|
44 |
message='No translation was found using the current translator. Try another translator?'):
|
|
|
46 |
|
47 |
|
48 |
class ElementNotFoundInGetRequest(BaseError):
|
49 |
+
"""
|
50 |
+
exception thrown if the html element was not found in the body parsed by beautifulsoup
|
51 |
+
"""
|
52 |
def __init__(self,
|
53 |
val,
|
54 |
message='Required element was not found in the API response'):
|
|
|
56 |
|
57 |
|
58 |
class NotValidLength(BaseError):
|
59 |
+
"""
|
60 |
+
exception thrown if the provided text exceed the length limit of the translator
|
61 |
+
"""
|
62 |
+
def __init__(self, val, min_chars, max_chars):
|
63 |
+
message = "Text length need to be between {} and {} characters".format(min_chars, max_chars)
|
64 |
super(NotValidLength, self).__init__(val, message)
|
65 |
+
|
66 |
+
|
67 |
+
class RequestError(Exception):
|
68 |
+
"""
|
69 |
+
exception thrown if an error occured during the request call, e.g a connection problem.
|
70 |
+
"""
|
71 |
+
def __init__(self, message="Request exception can happen due to an api connection error. "
|
72 |
+
"Please check your connection and try again"):
|
73 |
+
self.message = message
|
74 |
+
|
75 |
+
def __str__(self):
|
76 |
+
return self.message
|
deep_translator/google_trans.py
CHANGED
@@ -1,6 +1,9 @@
|
|
|
|
|
|
|
|
1 |
|
2 |
from deep_translator.constants import BASE_URLS, GOOGLE_LANGUAGES_TO_CODES
|
3 |
-
from deep_translator.exceptions import LanguageNotSupportedException, TranslationNotFound, NotValidPayload
|
4 |
from deep_translator.parent import BaseTranslator
|
5 |
from bs4 import BeautifulSoup
|
6 |
import requests
|
@@ -8,7 +11,7 @@ import requests
|
|
8 |
|
9 |
class GoogleTranslator(BaseTranslator):
|
10 |
"""
|
11 |
-
class that
|
12 |
"""
|
13 |
_languages = GOOGLE_LANGUAGES_TO_CODES
|
14 |
supported_languages = list(_languages.keys())
|
@@ -34,12 +37,17 @@ class GoogleTranslator(BaseTranslator):
|
|
34 |
|
35 |
@staticmethod
|
36 |
def get_supported_languages(as_dict=False):
|
|
|
|
|
|
|
|
|
|
|
37 |
return GoogleTranslator.supported_languages if not as_dict else GoogleTranslator._languages
|
38 |
|
39 |
def _map_language_to_code(self, *languages):
|
40 |
"""
|
41 |
-
|
42 |
-
@param
|
43 |
@return: mapped value of the language or raise an exception if the language is not supported
|
44 |
"""
|
45 |
for language in languages:
|
@@ -51,6 +59,11 @@ class GoogleTranslator(BaseTranslator):
|
|
51 |
raise LanguageNotSupportedException(language)
|
52 |
|
53 |
def is_language_supported(self, *languages):
|
|
|
|
|
|
|
|
|
|
|
54 |
for lang in languages:
|
55 |
if lang != 'auto' and lang not in self._languages.keys():
|
56 |
if lang != 'auto' and lang not in self._languages.values():
|
@@ -59,7 +72,7 @@ class GoogleTranslator(BaseTranslator):
|
|
59 |
|
60 |
def translate(self, text, **kwargs):
|
61 |
"""
|
62 |
-
|
63 |
@param text: desired text to translate
|
64 |
@return: str: translated text
|
65 |
"""
|
@@ -73,15 +86,25 @@ class GoogleTranslator(BaseTranslator):
|
|
73 |
response = requests.get(self.__base_url,
|
74 |
params=self._url_params)
|
75 |
|
|
|
|
|
|
|
76 |
soup = BeautifulSoup(response.text, 'html.parser')
|
77 |
element = soup.find(self._element_tag, self._element_query)
|
|
|
78 |
if not element:
|
79 |
-
# raise ElementNotFoundInGetRequest(element)
|
80 |
raise TranslationNotFound(text)
|
81 |
|
82 |
return element.get_text(strip=True)
|
83 |
|
84 |
def translate_file(self, path, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
try:
|
86 |
with open(path) as f:
|
87 |
text = f.read()
|
|
|
1 |
+
"""
|
2 |
+
google translator API
|
3 |
+
"""
|
4 |
|
5 |
from deep_translator.constants import BASE_URLS, GOOGLE_LANGUAGES_TO_CODES
|
6 |
+
from deep_translator.exceptions import LanguageNotSupportedException, TranslationNotFound, NotValidPayload, RequestError
|
7 |
from deep_translator.parent import BaseTranslator
|
8 |
from bs4 import BeautifulSoup
|
9 |
import requests
|
|
|
11 |
|
12 |
class GoogleTranslator(BaseTranslator):
|
13 |
"""
|
14 |
+
class that wraps functions, which use google translate under the hood to translate text(s)
|
15 |
"""
|
16 |
_languages = GOOGLE_LANGUAGES_TO_CODES
|
17 |
supported_languages = list(_languages.keys())
|
|
|
37 |
|
38 |
@staticmethod
|
39 |
def get_supported_languages(as_dict=False):
|
40 |
+
"""
|
41 |
+
return the supported languages by the google translator
|
42 |
+
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
43 |
+
@return: list or dict
|
44 |
+
"""
|
45 |
return GoogleTranslator.supported_languages if not as_dict else GoogleTranslator._languages
|
46 |
|
47 |
def _map_language_to_code(self, *languages):
|
48 |
"""
|
49 |
+
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
50 |
+
@param languages: list of languages
|
51 |
@return: mapped value of the language or raise an exception if the language is not supported
|
52 |
"""
|
53 |
for language in languages:
|
|
|
59 |
raise LanguageNotSupportedException(language)
|
60 |
|
61 |
def is_language_supported(self, *languages):
|
62 |
+
"""
|
63 |
+
check if the language is supported by the translator
|
64 |
+
@param languages: list of languages
|
65 |
+
@return: bool or raise an Exception
|
66 |
+
"""
|
67 |
for lang in languages:
|
68 |
if lang != 'auto' and lang not in self._languages.keys():
|
69 |
if lang != 'auto' and lang not in self._languages.values():
|
|
|
72 |
|
73 |
def translate(self, text, **kwargs):
|
74 |
"""
|
75 |
+
function that uses google translate to translate a text
|
76 |
@param text: desired text to translate
|
77 |
@return: str: translated text
|
78 |
"""
|
|
|
86 |
response = requests.get(self.__base_url,
|
87 |
params=self._url_params)
|
88 |
|
89 |
+
if response.status_code != 200:
|
90 |
+
raise RequestError()
|
91 |
+
|
92 |
soup = BeautifulSoup(response.text, 'html.parser')
|
93 |
element = soup.find(self._element_tag, self._element_query)
|
94 |
+
|
95 |
if not element:
|
|
|
96 |
raise TranslationNotFound(text)
|
97 |
|
98 |
return element.get_text(strip=True)
|
99 |
|
100 |
def translate_file(self, path, **kwargs):
|
101 |
+
"""
|
102 |
+
translate directly from file
|
103 |
+
@param path: path to the target file
|
104 |
+
@type path: str
|
105 |
+
@param kwargs: additional args
|
106 |
+
@return: str
|
107 |
+
"""
|
108 |
try:
|
109 |
with open(path) as f:
|
110 |
text = f.read()
|
deep_translator/linguee.py
CHANGED
@@ -1,5 +1,13 @@
|
|
|
|
|
|
|
|
|
|
1 |
from deep_translator.constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES, LINGUEE_CODE_TO_LANGUAGE
|
2 |
-
from deep_translator.exceptions import LanguageNotSupportedException,
|
|
|
|
|
|
|
|
|
3 |
from deep_translator.parent import BaseTranslator
|
4 |
from bs4 import BeautifulSoup
|
5 |
import requests
|
@@ -7,6 +15,9 @@ from requests.utils import requote_uri
|
|
7 |
|
8 |
|
9 |
class LingueeTranslator(BaseTranslator):
|
|
|
|
|
|
|
10 |
_languages = LINGUEE_LANGUAGES_TO_CODES
|
11 |
supported_languages = list(_languages.keys())
|
12 |
|
@@ -30,13 +41,19 @@ class LingueeTranslator(BaseTranslator):
|
|
30 |
|
31 |
@staticmethod
|
32 |
def get_supported_languages(as_dict=False):
|
|
|
|
|
|
|
|
|
|
|
33 |
return LingueeTranslator.supported_languages if not as_dict else LingueeTranslator._languages
|
34 |
|
35 |
def _map_language_to_code(self, *languages, **kwargs):
|
36 |
"""
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
40 |
for language in languages:
|
41 |
if language in self._languages.values():
|
42 |
yield LINGUEE_CODE_TO_LANGUAGE[language]
|
@@ -46,6 +63,11 @@ class LingueeTranslator(BaseTranslator):
|
|
46 |
raise LanguageNotSupportedException(language)
|
47 |
|
48 |
def is_language_supported(self, *languages, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
49 |
for lang in languages:
|
50 |
if lang not in self._languages.keys():
|
51 |
if lang not in self._languages.values():
|
@@ -53,12 +75,21 @@ class LingueeTranslator(BaseTranslator):
|
|
53 |
return True
|
54 |
|
55 |
def translate(self, word, return_all=False, **kwargs):
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
# %s-%s/translation/%s.html
|
59 |
url = "{}{}-{}/translation/{}.html".format(self.__base_url, self._source, self._target, word)
|
60 |
url = requote_uri(url)
|
61 |
response = requests.get(url)
|
|
|
|
|
62 |
soup = BeautifulSoup(response.text, 'html.parser')
|
63 |
elements = soup.find_all(self._element_tag, self._element_query)
|
64 |
if not elements:
|
@@ -78,6 +109,12 @@ class LingueeTranslator(BaseTranslator):
|
|
78 |
return filtered_elements if return_all else filtered_elements[0]
|
79 |
|
80 |
def translate_words(self, words, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
if not words:
|
82 |
raise NotValidPayload(words)
|
83 |
|
|
|
1 |
+
"""
|
2 |
+
linguee translator API
|
3 |
+
"""
|
4 |
+
|
5 |
from deep_translator.constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES, LINGUEE_CODE_TO_LANGUAGE
|
6 |
+
from deep_translator.exceptions import (LanguageNotSupportedException,
|
7 |
+
TranslationNotFound,
|
8 |
+
NotValidPayload,
|
9 |
+
ElementNotFoundInGetRequest,
|
10 |
+
RequestError)
|
11 |
from deep_translator.parent import BaseTranslator
|
12 |
from bs4 import BeautifulSoup
|
13 |
import requests
|
|
|
15 |
|
16 |
|
17 |
class LingueeTranslator(BaseTranslator):
|
18 |
+
"""
|
19 |
+
class that wraps functions, which use the linguee translator under the hood to translate word(s)
|
20 |
+
"""
|
21 |
_languages = LINGUEE_LANGUAGES_TO_CODES
|
22 |
supported_languages = list(_languages.keys())
|
23 |
|
|
|
41 |
|
42 |
@staticmethod
|
43 |
def get_supported_languages(as_dict=False):
|
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 LingueeTranslator.supported_languages if not as_dict else LingueeTranslator._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 LINGUEE_CODE_TO_LANGUAGE[language]
|
|
|
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():
|
|
|
75 |
return True
|
76 |
|
77 |
def translate(self, word, return_all=False, **kwargs):
|
78 |
+
"""
|
79 |
+
function that uses linguee to translate a word
|
80 |
+
@param word: word to translate
|
81 |
+
@type word: str
|
82 |
+
@param return_all: set to True to return all synonym of the translated word
|
83 |
+
@type return_all: bool
|
84 |
+
@return: str: translated word
|
85 |
+
"""
|
86 |
+
if self._validate_payload(word, max_chars=50):
|
87 |
# %s-%s/translation/%s.html
|
88 |
url = "{}{}-{}/translation/{}.html".format(self.__base_url, self._source, self._target, word)
|
89 |
url = requote_uri(url)
|
90 |
response = requests.get(url)
|
91 |
+
if response.status_code != 200:
|
92 |
+
raise RequestError()
|
93 |
soup = BeautifulSoup(response.text, 'html.parser')
|
94 |
elements = soup.find_all(self._element_tag, self._element_query)
|
95 |
if not elements:
|
|
|
109 |
return filtered_elements if return_all else filtered_elements[0]
|
110 |
|
111 |
def translate_words(self, words, **kwargs):
|
112 |
+
"""
|
113 |
+
translate a batch of words together by providing them in a list
|
114 |
+
@param words: list of words you want to translate
|
115 |
+
@param kwargs: additional args
|
116 |
+
@return: list of translated words
|
117 |
+
"""
|
118 |
if not words:
|
119 |
raise NotValidPayload(words)
|
120 |
|
deep_translator/mymemory.py
CHANGED
@@ -1,13 +1,15 @@
|
|
1 |
-
|
|
|
|
|
2 |
from deep_translator.constants import BASE_URLS, GOOGLE_LANGUAGES_TO_CODES
|
3 |
-
from deep_translator.exceptions import NotValidPayload, TranslationNotFound, LanguageNotSupportedException
|
4 |
from deep_translator.parent import BaseTranslator
|
5 |
import requests
|
6 |
|
7 |
|
8 |
class MyMemoryTranslator(BaseTranslator):
|
9 |
"""
|
10 |
-
class that uses
|
11 |
"""
|
12 |
_languages = GOOGLE_LANGUAGES_TO_CODES
|
13 |
supported_languages = list(_languages.keys())
|
@@ -32,13 +34,18 @@ class MyMemoryTranslator(BaseTranslator):
|
|
32 |
|
33 |
@staticmethod
|
34 |
def get_supported_languages(as_dict=False):
|
|
|
|
|
|
|
|
|
|
|
35 |
return MyMemoryTranslator.supported_languages if not as_dict else MyMemoryTranslator._languages
|
36 |
|
37 |
def _map_language_to_code(self, *languages):
|
38 |
"""
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
"""
|
43 |
for language in languages:
|
44 |
if language in self._languages.values() or language == 'auto':
|
@@ -49,6 +56,11 @@ class MyMemoryTranslator(BaseTranslator):
|
|
49 |
raise LanguageNotSupportedException(language)
|
50 |
|
51 |
def is_language_supported(self, *languages):
|
|
|
|
|
|
|
|
|
|
|
52 |
for lang in languages:
|
53 |
if lang != 'auto' and lang not in self._languages.keys():
|
54 |
if lang != 'auto' and lang not in self._languages.values():
|
@@ -57,13 +69,14 @@ class MyMemoryTranslator(BaseTranslator):
|
|
57 |
|
58 |
def translate(self, text, return_all=False, **kwargs):
|
59 |
"""
|
60 |
-
|
61 |
@param text: desired text to translate
|
62 |
-
@
|
63 |
-
@
|
|
|
64 |
"""
|
65 |
|
66 |
-
if self._validate_payload(text):
|
67 |
text = text.strip()
|
68 |
|
69 |
if self.payload_key:
|
@@ -74,6 +87,10 @@ class MyMemoryTranslator(BaseTranslator):
|
|
74 |
response = requests.get(self.__base_url,
|
75 |
params=self._url_params,
|
76 |
headers=self.headers)
|
|
|
|
|
|
|
|
|
77 |
data = response.json()
|
78 |
if not data:
|
79 |
TranslationNotFound(text)
|
@@ -111,3 +128,18 @@ class MyMemoryTranslator(BaseTranslator):
|
|
111 |
except Exception as e:
|
112 |
raise e
|
113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
mymemory translator API
|
3 |
+
"""
|
4 |
from deep_translator.constants import BASE_URLS, GOOGLE_LANGUAGES_TO_CODES
|
5 |
+
from deep_translator.exceptions import NotValidPayload, TranslationNotFound, LanguageNotSupportedException, RequestError
|
6 |
from deep_translator.parent import BaseTranslator
|
7 |
import requests
|
8 |
|
9 |
|
10 |
class MyMemoryTranslator(BaseTranslator):
|
11 |
"""
|
12 |
+
class that uses the mymemory translator to translate texts
|
13 |
"""
|
14 |
_languages = GOOGLE_LANGUAGES_TO_CODES
|
15 |
supported_languages = list(_languages.keys())
|
|
|
34 |
|
35 |
@staticmethod
|
36 |
def get_supported_languages(as_dict=False):
|
37 |
+
"""
|
38 |
+
return the supported languages by the mymemory translator
|
39 |
+
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
40 |
+
@return: list or dict
|
41 |
+
"""
|
42 |
return MyMemoryTranslator.supported_languages if not as_dict else MyMemoryTranslator._languages
|
43 |
|
44 |
def _map_language_to_code(self, *languages):
|
45 |
"""
|
46 |
+
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
47 |
+
@param languages: list of languages
|
48 |
+
@return: mapped value of the language or raise an exception if the language is not supported
|
49 |
"""
|
50 |
for language in languages:
|
51 |
if language in self._languages.values() or language == 'auto':
|
|
|
56 |
raise LanguageNotSupportedException(language)
|
57 |
|
58 |
def is_language_supported(self, *languages):
|
59 |
+
"""
|
60 |
+
check if the language is supported by the translator
|
61 |
+
@param languages: list of languages
|
62 |
+
@return: bool or raise an Exception
|
63 |
+
"""
|
64 |
for lang in languages:
|
65 |
if lang != 'auto' and lang not in self._languages.keys():
|
66 |
if lang != 'auto' and lang not in self._languages.values():
|
|
|
69 |
|
70 |
def translate(self, text, return_all=False, **kwargs):
|
71 |
"""
|
72 |
+
function that uses the mymemory translator to translate a text
|
73 |
@param text: desired text to translate
|
74 |
+
@type text: str
|
75 |
+
@param return_all: set to True to return all synonym/similars of the translated text
|
76 |
+
@return: str or list
|
77 |
"""
|
78 |
|
79 |
+
if self._validate_payload(text, max_chars=500):
|
80 |
text = text.strip()
|
81 |
|
82 |
if self.payload_key:
|
|
|
87 |
response = requests.get(self.__base_url,
|
88 |
params=self._url_params,
|
89 |
headers=self.headers)
|
90 |
+
|
91 |
+
if response.status_code != 200:
|
92 |
+
raise RequestError()
|
93 |
+
|
94 |
data = response.json()
|
95 |
if not data:
|
96 |
TranslationNotFound(text)
|
|
|
128 |
except Exception as e:
|
129 |
raise e
|
130 |
|
131 |
+
def translate_file(self, path, **kwargs):
|
132 |
+
"""
|
133 |
+
translate directly from file
|
134 |
+
@param path: path to the target file
|
135 |
+
@type path: str
|
136 |
+
@param kwargs: additional args
|
137 |
+
@return: str
|
138 |
+
"""
|
139 |
+
try:
|
140 |
+
with open(path) as f:
|
141 |
+
text = f.read()
|
142 |
+
|
143 |
+
return self.translate(text=text)
|
144 |
+
except Exception as e:
|
145 |
+
raise e
|
deep_translator/parent.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
"""
|
2 |
|
3 |
from deep_translator.exceptions import NotValidPayload, NotValidLength
|
4 |
from abc import ABC, abstractmethod
|
@@ -6,7 +6,7 @@ from abc import ABC, abstractmethod
|
|
6 |
|
7 |
class BaseTranslator(ABC):
|
8 |
"""
|
9 |
-
class that serve as a parent translator
|
10 |
"""
|
11 |
def __init__(self,
|
12 |
base_url=None,
|
@@ -34,7 +34,7 @@ class BaseTranslator(ABC):
|
|
34 |
@staticmethod
|
35 |
def _validate_payload(payload, min_chars=1, max_chars=5000):
|
36 |
"""
|
37 |
-
validate the
|
38 |
@param payload: text to translate
|
39 |
@return: bool
|
40 |
"""
|
@@ -42,14 +42,27 @@ class BaseTranslator(ABC):
|
|
42 |
if not payload or not isinstance(payload, str):
|
43 |
raise NotValidPayload(payload)
|
44 |
if not BaseTranslator.__check_length(payload, min_chars, max_chars):
|
45 |
-
raise NotValidLength
|
46 |
return True
|
47 |
|
48 |
@staticmethod
|
49 |
def __check_length(payload, min_chars, max_chars):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
return True if min_chars < len(payload) < max_chars else False
|
51 |
|
52 |
@abstractmethod
|
53 |
def translate(self, text, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
return NotImplemented('You need to implement the translate method!')
|
55 |
|
|
|
1 |
+
"""parent translator class"""
|
2 |
|
3 |
from deep_translator.exceptions import NotValidPayload, NotValidLength
|
4 |
from abc import ABC, abstractmethod
|
|
|
6 |
|
7 |
class BaseTranslator(ABC):
|
8 |
"""
|
9 |
+
Abstract class that serve as a parent translator for other different translators
|
10 |
"""
|
11 |
def __init__(self,
|
12 |
base_url=None,
|
|
|
34 |
@staticmethod
|
35 |
def _validate_payload(payload, min_chars=1, max_chars=5000):
|
36 |
"""
|
37 |
+
validate the target text to translate
|
38 |
@param payload: text to translate
|
39 |
@return: bool
|
40 |
"""
|
|
|
42 |
if not payload or not isinstance(payload, str):
|
43 |
raise NotValidPayload(payload)
|
44 |
if not BaseTranslator.__check_length(payload, min_chars, max_chars):
|
45 |
+
raise NotValidLength(payload, min_chars, max_chars)
|
46 |
return True
|
47 |
|
48 |
@staticmethod
|
49 |
def __check_length(payload, min_chars, max_chars):
|
50 |
+
"""
|
51 |
+
check length of the provided target text to translate
|
52 |
+
@param payload: text to translate
|
53 |
+
@param min_chars: minimum characters allowed
|
54 |
+
@param max_chars: maximum characters allowed
|
55 |
+
@return: bool
|
56 |
+
"""
|
57 |
return True if min_chars < len(payload) < max_chars else False
|
58 |
|
59 |
@abstractmethod
|
60 |
def translate(self, text, **kwargs):
|
61 |
+
"""
|
62 |
+
translate a text using a translator under the hood and return the translated text
|
63 |
+
@param text: text to translate
|
64 |
+
@param kwargs: additional arguments
|
65 |
+
@return: str
|
66 |
+
"""
|
67 |
return NotImplemented('You need to implement the translate method!')
|
68 |
|
deep_translator/pons.py
CHANGED
@@ -1,8 +1,14 @@
|
|
1 |
-
|
|
|
|
|
2 |
from bs4 import BeautifulSoup
|
3 |
import requests
|
4 |
from deep_translator.constants import BASE_URLS, PONS_LANGUAGES_TO_CODES, PONS_CODES_TO_LANGUAGES
|
5 |
-
from deep_translator.exceptions import LanguageNotSupportedException,
|
|
|
|
|
|
|
|
|
6 |
from deep_translator.parent import BaseTranslator
|
7 |
from requests.utils import requote_uri
|
8 |
|
@@ -34,12 +40,18 @@ class PonsTranslator(BaseTranslator):
|
|
34 |
|
35 |
@staticmethod
|
36 |
def get_supported_languages(as_dict=False):
|
|
|
|
|
|
|
|
|
|
|
37 |
return PonsTranslator.supported_languages if not as_dict else PonsTranslator._languages
|
38 |
|
39 |
def _map_language_to_code(self, *languages, **kwargs):
|
40 |
"""
|
41 |
-
|
42 |
-
|
|
|
43 |
"""
|
44 |
for language in languages:
|
45 |
if language in self._languages.values():
|
@@ -50,6 +62,11 @@ class PonsTranslator(BaseTranslator):
|
|
50 |
raise LanguageNotSupportedException(language)
|
51 |
|
52 |
def is_language_supported(self, *languages, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
53 |
for lang in languages:
|
54 |
if lang not in self._languages.keys():
|
55 |
if lang not in self._languages.values():
|
@@ -57,13 +74,25 @@ class PonsTranslator(BaseTranslator):
|
|
57 |
return True
|
58 |
|
59 |
def translate(self, word, return_all=False, **kwargs):
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
url = "{}{}-{}/{}".format(self.__base_url, self._source, self._target, word)
|
63 |
url = requote_uri(url)
|
64 |
response = requests.get(url)
|
|
|
|
|
|
|
|
|
65 |
soup = BeautifulSoup(response.text, 'html.parser')
|
66 |
elements = soup.findAll(self._element_tag, self._element_query)
|
|
|
67 |
if not elements:
|
68 |
raise ElementNotFoundInGetRequest(word)
|
69 |
|
@@ -87,6 +116,12 @@ class PonsTranslator(BaseTranslator):
|
|
87 |
return word_list if return_all else word_list[0]
|
88 |
|
89 |
def translate_words(self, words, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
if not words:
|
91 |
raise NotValidPayload(words)
|
92 |
|
|
|
1 |
+
"""
|
2 |
+
pons translator API
|
3 |
+
"""
|
4 |
from bs4 import BeautifulSoup
|
5 |
import requests
|
6 |
from deep_translator.constants import BASE_URLS, PONS_LANGUAGES_TO_CODES, PONS_CODES_TO_LANGUAGES
|
7 |
+
from deep_translator.exceptions import (LanguageNotSupportedException,
|
8 |
+
TranslationNotFound,
|
9 |
+
NotValidPayload,
|
10 |
+
ElementNotFoundInGetRequest,
|
11 |
+
RequestError)
|
12 |
from deep_translator.parent import BaseTranslator
|
13 |
from requests.utils import requote_uri
|
14 |
|
|
|
40 |
|
41 |
@staticmethod
|
42 |
def get_supported_languages(as_dict=False):
|
43 |
+
"""
|
44 |
+
return the supported languages by the linguee translator
|
45 |
+
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
|
46 |
+
@return: list or dict
|
47 |
+
"""
|
48 |
return PonsTranslator.supported_languages if not as_dict else PonsTranslator._languages
|
49 |
|
50 |
def _map_language_to_code(self, *languages, **kwargs):
|
51 |
"""
|
52 |
+
map language to its corresponding code (abbreviation) if the language was passed by its full name by the user
|
53 |
+
@param languages: list of languages
|
54 |
+
@return: mapped value of the language or raise an exception if the language is not supported
|
55 |
"""
|
56 |
for language in languages:
|
57 |
if language in self._languages.values():
|
|
|
62 |
raise LanguageNotSupportedException(language)
|
63 |
|
64 |
def is_language_supported(self, *languages, **kwargs):
|
65 |
+
"""
|
66 |
+
check if the language is supported by the translator
|
67 |
+
@param languages: list of languages
|
68 |
+
@return: bool or raise an Exception
|
69 |
+
"""
|
70 |
for lang in languages:
|
71 |
if lang not in self._languages.keys():
|
72 |
if lang not in self._languages.values():
|
|
|
74 |
return True
|
75 |
|
76 |
def translate(self, word, return_all=False, **kwargs):
|
77 |
+
"""
|
78 |
+
function that uses PONS to translate a word
|
79 |
+
@param word: word to translate
|
80 |
+
@type word: str
|
81 |
+
@param return_all: set to True to return all synonym of the translated word
|
82 |
+
@type return_all: bool
|
83 |
+
@return: str: translated word
|
84 |
+
"""
|
85 |
+
if self._validate_payload(word, max_chars=50):
|
86 |
url = "{}{}-{}/{}".format(self.__base_url, self._source, self._target, word)
|
87 |
url = requote_uri(url)
|
88 |
response = requests.get(url)
|
89 |
+
|
90 |
+
if response.status_code != 200:
|
91 |
+
raise RequestError()
|
92 |
+
|
93 |
soup = BeautifulSoup(response.text, 'html.parser')
|
94 |
elements = soup.findAll(self._element_tag, self._element_query)
|
95 |
+
|
96 |
if not elements:
|
97 |
raise ElementNotFoundInGetRequest(word)
|
98 |
|
|
|
116 |
return word_list if return_all else word_list[0]
|
117 |
|
118 |
def translate_words(self, words, **kwargs):
|
119 |
+
"""
|
120 |
+
translate a batch of words together by providing them in a list
|
121 |
+
@param words: list of words you want to translate
|
122 |
+
@param kwargs: additional args
|
123 |
+
@return: list of translated words
|
124 |
+
"""
|
125 |
if not words:
|
126 |
raise NotValidPayload(words)
|
127 |
|
deep_translator/tests/test_google_trans.py
CHANGED
@@ -29,6 +29,7 @@ def test_inputs():
|
|
29 |
with pytest.raises(exceptions.LanguageNotSupportedException):
|
30 |
GoogleTranslator(source="auto", target="nothing")
|
31 |
|
|
|
32 |
g1 = GoogleTranslator("en", "fr")
|
33 |
g2 = GoogleTranslator("english", "french")
|
34 |
assert g1._source == g2._source
|
@@ -48,3 +49,6 @@ def test_payload(google_translator):
|
|
48 |
|
49 |
with pytest.raises(exceptions.NotValidPayload):
|
50 |
google_translator.translate(text=[])
|
|
|
|
|
|
|
|
29 |
with pytest.raises(exceptions.LanguageNotSupportedException):
|
30 |
GoogleTranslator(source="auto", target="nothing")
|
31 |
|
32 |
+
# test abbreviations and languages
|
33 |
g1 = GoogleTranslator("en", "fr")
|
34 |
g2 = GoogleTranslator("english", "french")
|
35 |
assert g1._source == g2._source
|
|
|
49 |
|
50 |
with pytest.raises(exceptions.NotValidPayload):
|
51 |
google_translator.translate(text=[])
|
52 |
+
|
53 |
+
with pytest.raises(exceptions.NotValidLength):
|
54 |
+
google_translator.translate("a"*5001)
|
deep_translator/tests/test_linguee.py
CHANGED
@@ -44,3 +44,6 @@ def test_payload(linguee):
|
|
44 |
|
45 |
with pytest.raises(exceptions.NotValidPayload):
|
46 |
linguee.translate([])
|
|
|
|
|
|
|
|
44 |
|
45 |
with pytest.raises(exceptions.NotValidPayload):
|
46 |
linguee.translate([])
|
47 |
+
|
48 |
+
with pytest.raises(exceptions.NotValidLength):
|
49 |
+
linguee.translate("a"*51)
|
deep_translator/tests/test_mymemory.py
CHANGED
@@ -29,6 +29,7 @@ def test_inputs():
|
|
29 |
assert m1._source == m2._source
|
30 |
assert m1._target == m2._target
|
31 |
|
|
|
32 |
def test_payload(mymemory):
|
33 |
|
34 |
with pytest.raises(exceptions.NotValidPayload):
|
@@ -42,3 +43,6 @@ def test_payload(mymemory):
|
|
42 |
|
43 |
with pytest.raises(exceptions.NotValidPayload):
|
44 |
mymemory.translate(text=[])
|
|
|
|
|
|
|
|
29 |
assert m1._source == m2._source
|
30 |
assert m1._target == m2._target
|
31 |
|
32 |
+
|
33 |
def test_payload(mymemory):
|
34 |
|
35 |
with pytest.raises(exceptions.NotValidPayload):
|
|
|
43 |
|
44 |
with pytest.raises(exceptions.NotValidPayload):
|
45 |
mymemory.translate(text=[])
|
46 |
+
|
47 |
+
with pytest.raises(exceptions.NotValidLength):
|
48 |
+
mymemory.translate(text="a"*501)
|
deep_translator/tests/test_pons.py
CHANGED
@@ -29,6 +29,7 @@ def test_inputs():
|
|
29 |
assert l1._source == l2._source
|
30 |
assert l1._target == l2._target
|
31 |
|
|
|
32 |
def test_payload(pons):
|
33 |
|
34 |
with pytest.raises(exceptions.NotValidPayload):
|
@@ -42,3 +43,6 @@ def test_payload(pons):
|
|
42 |
|
43 |
with pytest.raises(exceptions.NotValidPayload):
|
44 |
pons.translate([])
|
|
|
|
|
|
|
|
29 |
assert l1._source == l2._source
|
30 |
assert l1._target == l2._target
|
31 |
|
32 |
+
|
33 |
def test_payload(pons):
|
34 |
|
35 |
with pytest.raises(exceptions.NotValidPayload):
|
|
|
43 |
|
44 |
with pytest.raises(exceptions.NotValidPayload):
|
45 |
pons.translate([])
|
46 |
+
|
47 |
+
with pytest.raises(exceptions.NotValidLength):
|
48 |
+
pons.translate("a" * 51)
|