Nidhal Baccouri commited on
Commit
721a708
·
unverified ·
2 Parent(s): 0cfe8e5 7216951

Merge pull request #136 from nidhaloff/features/engine

Browse files
deep_translator/__init__.py CHANGED
@@ -1,21 +1,20 @@
1
  """Top-level package for Deep Translator"""
2
 
3
- from .google_trans 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 QCRI
9
- from .deepl import DeepL
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.6.1'
19
 
20
  __all__ = [
21
  "GoogleTranslator",
@@ -24,14 +23,10 @@ __all__ = [
24
  "MyMemoryTranslator",
25
  "YandexTranslator",
26
  "MicrosoftTranslator",
27
- "QCRI",
28
- "DeepL",
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/v2/",
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
- from .constants import BASE_URLS, DEEPL_LANGUAGE_TO_CODE
3
- from .exceptions import (ServerException,
 
 
4
  TranslationNotFound,
5
- LanguageNotSupportedException,
6
  AuthorizationException)
7
- from .parent import BaseTranslator
8
 
9
 
10
- class DeepL(object):
11
  """
12
- class that wraps functions, which use the DeepL translator under the hood to translate word(s)
13
  """
14
- _languages = DEEPL_LANGUAGE_TO_CODE
15
 
16
- def __init__(self, api_key=None, source="en", target="en", use_free_api=True, **kwargs):
17
  """
18
- @param api_key: your DeepL 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,73 +24,63 @@ class DeepL(object):
24
  raise ServerException(401)
25
  self.version = 'v2'
26
  self.api_key = api_key
27
- self.source = self._map_language_to_code(source)
28
- self.target = self._map_language_to_code(target)
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
- # Create the request parameters.
42
- translate_endpoint = 'translate'
43
- params = {
44
- "auth_key": self.api_key,
45
- "source_lang": self.source,
46
- "target_lang": self.target,
47
- "text": text
48
- }
49
- # Do the request and check the connection.
50
- try:
51
- response = requests.get(
52
- self.__base_url + translate_endpoint, params=params)
53
- except ConnectionError:
54
- raise ServerException(503)
55
- # If the answer is not success, raise server exception.
56
- if response.status_code == 403:
57
- raise AuthorizationException(self.api_key)
58
- elif response.status_code != 200:
59
- raise ServerException(response.status_code)
60
- # Get the response and check is not empty.
61
- res = response.json()
62
- if not res:
63
- raise TranslationNotFound(text)
64
- # Process and return the response.
65
- return res['translations'][0]['text']
 
 
 
 
 
 
 
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 [self.translate(text, **kwargs) for text in batch]
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 = DeepL(target="de")
95
- t = d.translate("I have no idea")
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 and target language can't be the same"):
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, GOOGLE_LANGUAGES_TO_CODES, GOOGLE_LANGUAGES_SECONDARY_NAMES
6
- from .exceptions import TooManyRequests, LanguageNotSupportedException, TranslationNotFound, NotValidPayload, RequestError
7
- from .parent import BaseTranslator
 
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
- # code snipppet that converts the language into lower-case and skip lower-case conversion for abbreviations
31
- # since abbreviations like zh-CN if converted to lower-case will result into error
32
- #######################################
33
- source_lower = source
34
- target_lower = target
35
- if not source in self._languages.values():
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.__base_url,
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
- try:
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
- if not batch:
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
- from .parent import BaseTranslator
7
- from .constants import BASE_URLS,LIBRE_LANGUAGES_TO_CODES, LIBRE_CODES_TO_LANGUAGES
 
 
8
  from .exceptions import (ServerException,
9
- TranslationNotFound,
10
- LanguageNotSupportedException,
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", base_url = BASE_URLS.get("LIBRE_FREE"), api_key=None, **kwargs):
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 base_url == BASE_URLS.get("LIBRE") and not api_key:
30
  raise ServerException(401)
31
- self.__base_url = base_url
32
  self.api_key = api_key
33
- if source == "auto":
34
- self.source = "auto"
35
- else:
36
- self.source = self._map_language_to_code(source)
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
- # Create the request parameters.
79
- if type(text) != str or text == "":
80
- raise NotValidPayload(text)
81
 
82
- translate_endpoint = 'translate'
83
- params = {
84
- "q": text,
85
- "source": self.source,
86
- "target": self.target,
87
- "format": 'text'
88
- }
89
- # Add API Key if required
90
- if self.api_key:
91
- params["api_key"] = self.api_key
92
- # Do the request and check the connection.
93
- try:
94
- response = requests.post(self.__base_url + translate_endpoint, params=params)
95
- except ConnectionError:
96
- raise ServerException(503)
97
- # If the answer is not success, raise server exception.
98
 
99
- if response.status_code == 403:
100
- raise AuthorizationException(self.api_key)
101
- elif response.status_code != 200:
102
- raise ServerException(response.status_code)
103
- # Get the response and check is not empty.
104
- res = response.json()
105
- if not res:
106
- raise TranslationNotFound(text)
107
- # Process and return the response.
108
- return res['translatedText']
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
- try:
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
- if not batch:
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, LINGUEE_CODE_TO_LANGUAGE
6
- from .exceptions import (LanguageNotSupportedException,
7
  TranslationNotFound,
8
  NotValidPayload,
9
  ElementNotFoundInGetRequest,
10
  RequestError,
11
  TooManyRequests)
12
- from .parent import BaseTranslator
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
- if self.is_language_supported(source, target):
34
- self._source, self._target = self._map_language_to_code(source.lower(), target.lower())
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._validate_payload(word, max_chars=50):
 
 
 
89
  # %s-%s/translation/%s.html
90
- url = "{}{}-{}/translation/{}.html".format(self.__base_url, self._source, self._target, word)
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
- if not target:
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
- def _map_language_to_code(self, language, **kwargs):
71
- """
72
- map the language to its corresponding code (abbreviation) if the language was passed by its full name by the user
73
- @param language: a string (if 1 lang) or a list (if multiple langs)
74
- @return: mapped value of the language or raise an exception if the language is not supported
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
- valid_microsoft_json = [{'text': text}]
109
- try:
110
- requested = requests.post(self.__base_url,
111
- params=self.url_params,
112
- headers=self.headers,
113
- json=valid_microsoft_json,
114
- proxies=self.proxies)
115
- except requests.exceptions.RequestException:
116
- exc_type, value, traceback = sys.exc_info()
117
- logging.warning(f"Returned error: {exc_type.__name__}")
118
-
119
- # Where Microsoft API responds with an api error, it returns a dict in response.json()
120
- if type(requested.json()) is dict:
121
- error_message = requested.json()['error']
122
- raise MicrosoftAPIerror(error_message)
123
- # Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
124
- elif type(requested.json()) is list:
125
- all_translations = [i['text']
126
- for i in requested.json()[0]['translations']]
127
- return "\n".join(all_translations)
 
 
 
 
 
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
- try:
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 [self.translate(text, **kwargs) for text in batch]
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 logging
5
- import warnings
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 .parent import BaseTranslator
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(MyMemoryTranslator, self).__init__(base_url=self.__base_url,
38
- source=self._source,
39
- target=self._target,
40
- payload_key='q',
41
- langpair='{}|{}'.format(self._source, self._target))
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.__base_url,
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
- try:
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
- if not batch:
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 LanguageNotSupportedException, TranslationNotFound, NotValidPayload
7
- from .parent import BaseTranslator
8
  import requests
9
- import warnings
10
- import logging
11
 
 
12
 
13
- class PapagoTranslator(object):
 
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
- if self.is_language_supported(source, target):
33
- self._source, self._target = self._map_language_to_code(
34
- source.lower(), target.lower())
35
-
36
- @staticmethod
37
- def get_supported_languages(as_dict=False, **kwargs):
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
- payload = {
79
- "source": self._source,
80
- "target": self._target,
81
- "text": text
82
- }
83
- headers = {
84
- 'X-Naver-Client-Id': self.client_id,
85
- 'X-Naver-Client-Secret': self.secret_key,
86
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
87
- }
88
- response = requests.post(
89
- self.__base_url, headers=headers, data=payload)
90
- if response.status_code != 200:
91
- raise Exception(
92
- f'Translation error! -> status code: {response.status_code}')
93
- res_body = json.loads(response.text)
94
- if "message" not in res_body:
95
- raise TranslationNotFound(text)
96
-
97
- msg = res_body.get("message")
98
- result = msg.get("result", None)
99
- if not result:
100
- raise TranslationNotFound(text)
101
- translated_text = result.get("translatedText")
102
- return translated_text
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
- try:
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
- if not batch:
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
- from .constants import BASE_URLS, PONS_LANGUAGES_TO_CODES, PONS_CODES_TO_LANGUAGES
7
- from .exceptions import (LanguageNotSupportedException,
 
 
8
  TranslationNotFound,
9
  NotValidPayload,
10
  ElementNotFoundInGetRequest,
11
  RequestError,
12
  TooManyRequests)
13
- from .parent import BaseTranslator
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
- if self.is_language_supported(source, target):
32
- self._source, self._target = self._map_language_to_code(source, target)
33
-
34
- super().__init__(base_url=self.__base_url,
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 self._validate_payload(word, max_chars=50):
87
- url = "{}{}-{}/{}".format(self.__base_url, self._source, self._target, word)
 
 
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
- if e.parent.name == 'div':
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 .parent import BaseTranslator
6
 
7
 
8
- class QCRI(object):
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.__base_url.format(
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, domain, **kwargs):
65
  params = {
66
  "key": self.api_key,
67
- "langpair": "{}-{}".format(self.source, self.target),
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 translate_batch(self, batch, domain, **kwargs):
 
 
 
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 [self.translate(domain, text, **kwargs) for text in batch]
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 .parent import BaseTranslator
9
 
10
 
11
- class YandexTranslator(object):
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
- @staticmethod
35
- def get_supported_languages(as_dict=False, **kwargs):
36
- """ this method is just for consistency."""
37
- return """ this method is just for consistency. You need to create an instance of yandex and access
38
- supported languages using the languages property or call _get_supported_languages
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.__base_url.format(
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.__base_url.format(
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
- params = {
96
- "text": text,
97
- "format": "plain",
98
- "lang": self.target if self.source == "auto" else "{}-{}".format(self.source, self.target),
99
- "key": self.api_key
100
- }
101
- try:
102
- url = self.__base_url.format(
103
- version=self.api_version, endpoint="translate")
104
- response = requests.post(url, data=params, proxies=proxies)
105
- except ConnectionError:
106
- raise ServerException(503)
107
- else:
108
- response = response.json()
109
-
110
- if response['code'] == 429:
111
- raise TooManyRequests()
112
-
113
- if response['code'] != 200:
114
- raise ServerException(response['code'])
115
-
116
- if not response['text']:
117
- raise TranslationNotFound()
118
-
119
- return response['text']
 
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
- try:
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 [self.translate(text, **kwargs) for text in batch]
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 `QCRI translator <https://mt.qcri.org/api/>`_ (version >= 1.2.4)
110
- * Support for the `DeepL 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,8 +187,8 @@ Imports
187
  MyMemoryTranslator,
188
  YandexTranslator,
189
  PapagoTranslator,
190
- DeepL,
191
- QCRI,
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
- DeepL Translator
310
  -----------------
311
 
312
  .. note::
313
 
314
- In order to use the DeepL 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,7 +321,7 @@ DeepL Translator
321
 
322
  text = 'Keep it up. You are awesome'
323
 
324
- translated = DeepL(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,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 = DeepL("your_api_key").translate_batch(texts)
338
 
339
- QCRI Translator
340
  --------------------
341
 
342
  .. note::
343
 
344
- In order to use the QCRI translator, you need to generate a free api key. Visit https://mt.qcri.org/api/
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: ", QCRI("your_api_key").languages)
353
 
354
  - Check domains
355
 
356
  .. code-block:: python
357
 
358
  # as a property
359
- print("domains: ", QCRI("your_api_key").domains)
360
 
361
  - Text translation
362
 
@@ -364,7 +364,7 @@ QCRI Translator
364
 
365
  text = 'Education is great'
366
 
367
- translated = QCRI("your_api_key").translate(source='en', target='ar', domain="news", text=text)
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 DeepL translator
15
- - 1.2.4: added support for the QCRI 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
 
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
- DeepL
44
  ----------------------------------
45
 
46
  .. automodule:: deep_translator.deepl
@@ -88,7 +88,7 @@ Pons
88
  :undoc-members:
89
  :show-inheritance:
90
 
91
- QCRI
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
- DeepL,
26
- QCRI,
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
- DeepL Translator
144
  -----------------
145
 
146
  .. note::
147
 
148
- In order to use the DeepL 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,7 +154,7 @@ DeepL Translator
154
 
155
  text = 'Keep it up. You are awesome'
156
 
157
- translated = DeepL("your_api_key").translate(text)
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 = DeepL("your_api_key").translate_batch(texts)
167
 
168
- QCRI Translator
169
  --------------------
170
 
171
  .. note::
172
 
173
- In order to use the QCRI translator, you need to generate a free api key. Visit https://mt.qcri.org/api/
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: ", QCRI("your_api_key").languages)
182
 
183
  - Check domains
184
 
185
  .. code-block:: python
186
 
187
  # as a property
188
- print("domains: ", QCRI("your_api_key").domains)
189
 
190
  - Text translation
191
 
@@ -193,7 +193,7 @@ QCRI Translator
193
 
194
  text = 'Education is great'
195
 
196
- translated = QCRI("your_api_key").translate(source='en', target='ar', domain="news", text=text)
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
- result_german = GoogleTranslator(source='english', target='german').translate(text=english_text)
10
- result_french = GoogleTranslator(source='auto', target='french').translate(text=chinese_text)
11
 
12
- print(f"original english text: {english_text} | translated text: {result_german}") # result: fröhliche Codierung
13
- print(f"original chinese text: {chinese_text} | translated text: {result_french}") # result: C' est bon
 
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='english', target='arabic').translate(word=text)
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", "DeepL", "translator", "translation", "automation", "web scraping", "google translator", "google translation", "google trans", "PONS", "YANDEX", "MyMemory translator", "Linguee", "QCRI", "Language", "Language detection", "detect language", "free translation", "unlimited translation", "translate for free"]
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 DeepL
4
  from deep_translator.exceptions import AuthorizationException
5
 
6
 
7
  @patch('deep_translator.deepl.requests')
8
  def test_simple_translation(mock_requests):
9
- translator = DeepL(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,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 = DeepL(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):
 
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.LanguageNotSupportedException):
45
- LibreTranslator(source="", target="")
46
 
47
- with pytest.raises(exceptions.LanguageNotSupportedException):
48
- LibreTranslator(source="auto", target="nothing")
 
 
 
49
 
50
 
51
  def test_abbreviations_and_languages_mapping():
52
  for abb, lang in LIBRE_CODES_TO_LANGUAGES.items():
53
- if abb != 'en':
54
- l1 = LibreTranslator(abb)
55
- l2 = LibreTranslator(lang)
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='french')
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.LanguageNotSupportedException):
23
  LingueeTranslator(source="", target="")
24
 
25
- with pytest.raises(exceptions.LanguageNotSupportedException):
26
- LingueeTranslator(source="auto", target="nothing")
 
 
 
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.source) == ''.join(m2.source)
62
- assert ''.join(m1.target) == ''.join(m2.target)
 
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.LanguageNotSupportedException):
23
  MyMemoryTranslator(source="", target="")
24
 
25
- with pytest.raises(exceptions.LanguageNotSupportedException):
26
- MyMemoryTranslator(source="auto", target="nothing")
 
 
 
 
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.LanguageNotSupportedException):
23
  PonsTranslator(source="", target="")
24
 
25
- with pytest.raises(exceptions.LanguageNotSupportedException):
26
- PonsTranslator(source="auto", target="nothing")
 
 
 
 
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