Nidhal Baccouri commited on
Commit
784f56a
·
unverified ·
2 Parent(s): 721a708 7a05cd7

Merge pull request #139 from nidhaloff/refactoring

Browse files
Makefile CHANGED
@@ -47,15 +47,13 @@ clean-test: ## remove test and coverage artifacts
47
  rm -fr htmlcov/
48
  rm -fr .pytest_cache
49
 
50
- lint: ## check style with flake8
51
- flake8 deep_translator tests
 
52
 
53
  test: ## run tests quickly with the default Python
54
  pytest
55
 
56
- test-all: ## run tests on every Python version with tox
57
- tox
58
-
59
  coverage: ## check code coverage quickly with the default Python
60
  coverage run --source deep_translator -m pytest
61
  coverage report -m
 
47
  rm -fr htmlcov/
48
  rm -fr .pytest_cache
49
 
50
+ format: ## format with black
51
+ poetry run isort .
52
+ poetry run black deep_translator tests
53
 
54
  test: ## run tests quickly with the default Python
55
  pytest
56
 
 
 
 
57
  coverage: ## check code coverage quickly with the default Python
58
  coverage run --source deep_translator -m pytest
59
  coverage report -m
deep_translator/__init__.py CHANGED
@@ -1,20 +1,20 @@
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",
@@ -28,5 +28,5 @@ __all__ = [
28
  "LibreTranslator",
29
  "PapagoTranslator",
30
  "single_detection",
31
- "batch_detection"
32
  ]
 
1
  """Top-level package for Deep Translator"""
2
 
3
+ from deep_translator.deepl import DeeplTranslator
4
+ from deep_translator.detection import batch_detection, single_detection
5
+ from deep_translator.google import GoogleTranslator
6
+ from deep_translator.libre import LibreTranslator
7
+ from deep_translator.linguee import LingueeTranslator
8
+ from deep_translator.microsoft import MicrosoftTranslator
9
+ from deep_translator.mymemory import MyMemoryTranslator
10
+ from deep_translator.papago import PapagoTranslator
11
+ from deep_translator.pons import PonsTranslator
12
+ from deep_translator.qcri import QcriTranslator
13
+ from deep_translator.yandex import YandexTranslator
14
 
15
  __author__ = """Nidhal Baccouri"""
16
+ __email__ = "[email protected]"
17
+ __version__ = "1.7.1"
18
 
19
  __all__ = [
20
  "GoogleTranslator",
 
28
  "LibreTranslator",
29
  "PapagoTranslator",
30
  "single_detection",
31
+ "batch_detection",
32
  ]
deep_translator/__main__.py CHANGED
@@ -1,5 +1,4 @@
1
-
2
- from .cli import CLI
3
 
4
 
5
  def main():
 
1
+ from deep_translator.cli import CLI
 
2
 
3
 
4
  def main():
deep_translator/base.py CHANGED
@@ -1,30 +1,35 @@
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:
@@ -47,44 +52,50 @@ class BaseTranslator(ABC):
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
@@ -93,13 +104,13 @@ class BaseTranslator(ABC):
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
 
1
  """base translator class"""
2
 
 
 
3
  from abc import ABC, abstractmethod
4
+ from typing import List, Optional, Union
5
+
6
+ from deep_translator.constants import GOOGLE_LANGUAGES_TO_CODES
7
+ from deep_translator.exceptions import InvalidSourceOrTargetLanguage
8
 
9
 
10
  class BaseTranslator(ABC):
11
  """
12
  Abstract class that serve as a base translator for other different translators
13
  """
14
+
15
+ def __init__(
16
+ self,
17
+ base_url: str,
18
+ languages: dict = GOOGLE_LANGUAGES_TO_CODES,
19
+ source: str = "auto",
20
+ target: str = "en",
21
+ payload_key: Optional[str] = None,
22
+ element_tag: Optional[str] = None,
23
+ element_query: Optional[dict] = None,
24
+ **url_params
25
+ ):
26
  """
27
  @param source: source language to translate from
28
  @param target: target language to translate to
29
  """
30
  self._base_url = base_url
31
+ self.languages = languages
32
+ self.supported_languages = list(self.languages.keys())
33
  if not source:
34
  raise InvalidSourceOrTargetLanguage(source)
35
  if not target:
 
52
  @return: mapped value of the language or raise an exception if the language is not supported
53
  """
54
  for language in languages:
55
+ if language in self.languages.values() or language == "auto":
56
  yield language
57
  elif language in self.languages.keys():
58
  yield self.languages[language]
59
 
60
+ def _same_source_target(self) -> bool:
61
  return self._source == self._target
62
 
63
+ def get_supported_languages(
64
+ self, as_dict: bool = False, **kwargs
65
+ ) -> Union[list, dict]:
66
  """
67
+ return the supported languages by the Google translator
68
  @param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
69
  @return: list or dict
70
  """
71
  return self.supported_languages if not as_dict else self.languages
72
 
73
+ def is_language_supported(self, language: str, **kwargs) -> bool:
74
  """
75
  check if the language is supported by the translator
76
  @param language: a string for 1 language
77
  @return: bool or raise an Exception
78
  """
79
+ if (
80
+ language == "auto"
81
+ or language in self.languages.keys()
82
+ or language in self.languages.values()
83
+ ):
84
  return True
85
  else:
86
  return False
87
 
88
  @abstractmethod
89
+ def translate(self, text: str, **kwargs) -> str:
90
  """
91
  translate a text using a translator under the hood and return the translated text
92
  @param text: text to translate
93
  @param kwargs: additional arguments
94
  @return: str
95
  """
96
+ return NotImplemented("You need to implement the translate method!")
97
 
98
+ def _translate_file(self, path: str, **kwargs) -> str:
99
  """
100
  translate directly from file
101
  @param path: path to the target file
 
104
  @return: str
105
  """
106
  try:
107
+ with open(path, "r", encoding="utf-8") as f:
108
  text = f.read().strip()
109
  return self.translate(text)
110
  except Exception as e:
111
  raise e
112
 
113
+ def _translate_batch(self, batch: List[str], **kwargs) -> List[str]:
114
  """
115
  translate a list of texts
116
  @param batch: list of texts you want to translate
deep_translator/cli.py CHANGED
@@ -1,76 +1,94 @@
1
  """Console script for deep_translator."""
2
  import argparse
3
- from .engines import __engines__
 
 
4
 
5
 
6
  class CLI(object):
7
  translators_dict = __engines__
8
  translator = None
9
 
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."
16
- f"Supported translators: {list(self.translators_dict.keys())}")
17
- self.translator = translator_class(source=self.args.source, target=self.args.target)
 
 
 
 
18
 
19
- def translate(self):
20
  """
21
  function used to provide translations from the parsed terminal arguments
22
  @return: None
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):
30
  """
31
  function used to return the languages supported by the translator service from the parsed terminal arguments
32
  @return: None
33
  """
34
 
35
- translator_supported_languages = self.translator.get_supported_languages(as_dict=True)
36
- print(f'Languages supported by \'{self.args.translator}\' are :\n')
 
 
37
  print(translator_supported_languages)
38
 
39
- def parse_args(self):
40
  """
41
  function responsible for parsing terminal arguments and provide them for further use in the translation process
42
  """
43
- parser = argparse.ArgumentParser(add_help=True,
44
- description="Official CLI for deep-translator",
45
- usage="dt --help")
 
 
46
 
47
- parser.add_argument('--translator',
48
- '-trans',
49
- default='google',
50
- type=str,
51
- help="name of the translator you want to use")
52
- parser.add_argument('--source',
53
- '-src',
54
- default='auto',
55
- type=str,
56
- help="source language to translate from")
57
- parser.add_argument('--target',
58
- '-tg',
59
- type=str,
60
- help="target language to translate to")
61
- parser.add_argument('--text',
62
- '-txt',
63
- type=str,
64
- help="text you want to translate")
65
- parser.add_argument('--languages',
66
- '-lang',
67
- action='store_true',
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):
74
  if self.args.languages:
75
  self.get_supported_languages()
76
  else:
 
1
  """Console script for deep_translator."""
2
  import argparse
3
+ from typing import Optional
4
+
5
+ from deep_translator.engines import __engines__
6
 
7
 
8
  class CLI(object):
9
  translators_dict = __engines__
10
  translator = None
11
 
12
+ def __init__(self, custom_args: Optional[list] = None):
13
  self.custom_args = custom_args
14
  self.args = self.parse_args()
15
  translator_class = self.translators_dict.get(self.args.translator, None)
16
  if not translator_class:
17
+ raise Exception(
18
+ f"Translator {self.args.translator} is not supported."
19
+ f"Supported translators: {list(self.translators_dict.keys())}"
20
+ )
21
+ self.translator = translator_class(
22
+ source=self.args.source, target=self.args.target
23
+ )
24
 
25
+ def translate(self) -> None:
26
  """
27
  function used to provide translations from the parsed terminal arguments
28
  @return: None
29
  """
30
  res = self.translator.translate(self.args.text)
31
+ print(f"Translation from {self.args.source} to {self.args.target}")
32
  print("-" * 50)
33
+ print(f"Translation result: {res}")
34
 
35
+ def get_supported_languages(self) -> None:
36
  """
37
  function used to return the languages supported by the translator service from the parsed terminal arguments
38
  @return: None
39
  """
40
 
41
+ translator_supported_languages = self.translator.get_supported_languages(
42
+ as_dict=True
43
+ )
44
+ print(f"Languages supported by '{self.args.translator}' are :\n")
45
  print(translator_supported_languages)
46
 
47
+ def parse_args(self) -> argparse.Namespace:
48
  """
49
  function responsible for parsing terminal arguments and provide them for further use in the translation process
50
  """
51
+ parser = argparse.ArgumentParser(
52
+ add_help=True,
53
+ description="Official CLI for deep-translator",
54
+ usage="dt --help",
55
+ )
56
 
57
+ parser.add_argument(
58
+ "--translator",
59
+ "-trans",
60
+ default="google",
61
+ type=str,
62
+ help="name of the translator you want to use",
63
+ )
64
+ parser.add_argument(
65
+ "--source",
66
+ "-src",
67
+ default="auto",
68
+ type=str,
69
+ help="source language to translate from",
70
+ )
71
+ parser.add_argument(
72
+ "--target", "-tg", type=str, help="target language to translate to"
73
+ )
74
+ parser.add_argument(
75
+ "--text", "-txt", type=str, help="text you want to translate"
76
+ )
77
+ parser.add_argument(
78
+ "--languages",
79
+ "-lang",
80
+ action="store_true",
81
+ help="all the languages available with the translator"
82
+ "Run the command deep_translator -trans <translator service> -lang",
83
+ )
84
+ parsed_args = (
85
+ parser.parse_args(self.custom_args)
86
+ if self.custom_args
87
+ else parser.parse_args()
88
+ )
89
  return parsed_args
90
 
91
+ def run(self) -> None:
92
  if self.args.languages:
93
  self.get_supported_languages()
94
  else:
deep_translator/constants.py CHANGED
@@ -1,5 +1,3 @@
1
- import requests
2
-
3
  BASE_URLS = {
4
  "GOOGLE_TRANSLATE": "https://translate.google.com/m",
5
  "PONS": "https://en.pons.com/translate/",
@@ -16,155 +14,143 @@ BASE_URLS = {
16
  "LIBRE_FREE": "https://libretranslate.de/",
17
  }
18
 
19
- GOOGLE_CODES_TO_LANGUAGES = {
20
- 'af': 'afrikaans',
21
- 'sq': 'albanian',
22
- 'am': 'amharic',
23
- 'ar': 'arabic',
24
- 'hy': 'armenian',
25
- 'az': 'azerbaijani',
26
- 'eu': 'basque',
27
- 'be': 'belarusian',
28
- 'bn': 'bengali',
29
- 'bs': 'bosnian',
30
- 'bg': 'bulgarian',
31
- 'ca': 'catalan',
32
- 'ceb': 'cebuano',
33
- 'ny': 'chichewa',
34
- 'zh-CN': 'chinese (simplified)',
35
- 'zh-TW': 'chinese (traditional)',
36
- 'co': 'corsican',
37
- 'hr': 'croatian',
38
- 'cs': 'czech',
39
- 'da': 'danish',
40
- 'nl': 'dutch',
41
- 'en': 'english',
42
- 'eo': 'esperanto',
43
- 'et': 'estonian',
44
- 'tl': 'filipino',
45
- 'fi': 'finnish',
46
- 'fr': 'french',
47
- 'fy': 'frisian',
48
- 'gl': 'galician',
49
- 'ka': 'georgian',
50
- 'de': 'german',
51
- 'el': 'greek',
52
- 'gu': 'gujarati',
53
- 'ht': 'haitian creole',
54
- 'ha': 'hausa',
55
- 'haw': 'hawaiian',
56
- 'iw': 'hebrew',
57
- 'hi': 'hindi',
58
- 'hmn': 'hmong',
59
- 'hu': 'hungarian',
60
- 'is': 'icelandic',
61
- 'ig': 'igbo',
62
- 'id': 'indonesian',
63
- 'ga': 'irish',
64
- 'it': 'italian',
65
- 'ja': 'japanese',
66
- 'jw': 'javanese',
67
- 'kn': 'kannada',
68
- 'kk': 'kazakh',
69
- 'km': 'khmer',
70
- 'rw': 'kinyarwanda',
71
- 'ko': 'korean',
72
- 'ku': 'kurdish',
73
- 'ky': 'kyrgyz',
74
- 'lo': 'lao',
75
- 'la': 'latin',
76
- 'lv': 'latvian',
77
- 'lt': 'lithuanian',
78
- 'lb': 'luxembourgish',
79
- 'mk': 'macedonian',
80
- 'mg': 'malagasy',
81
- 'ms': 'malay',
82
- 'ml': 'malayalam',
83
- 'mt': 'maltese',
84
- 'mi': 'maori',
85
- 'mr': 'marathi',
86
- 'mn': 'mongolian',
87
- 'my': 'myanmar',
88
- 'ne': 'nepali',
89
- 'no': 'norwegian',
90
- 'or': 'odia',
91
- 'ps': 'pashto',
92
- 'fa': 'persian',
93
- 'pl': 'polish',
94
- 'pt': 'portuguese',
95
- 'pa': 'punjabi',
96
- 'ro': 'romanian',
97
- 'ru': 'russian',
98
- 'sm': 'samoan',
99
- 'gd': 'scots gaelic',
100
- 'sr': 'serbian',
101
- 'st': 'sesotho',
102
- 'sn': 'shona',
103
- 'sd': 'sindhi',
104
- 'si': 'sinhala',
105
- 'sk': 'slovak',
106
- 'sl': 'slovenian',
107
- 'so': 'somali',
108
- 'es': 'spanish',
109
- 'su': 'sundanese',
110
- 'sw': 'swahili',
111
- 'sv': 'swedish',
112
- 'tg': 'tajik',
113
- 'ta': 'tamil',
114
- 'tt': 'tatar',
115
- 'te': 'telugu',
116
- 'th': 'thai',
117
- 'tr': 'turkish',
118
- 'tk': 'turkmen',
119
- 'uk': 'ukrainian',
120
- 'ur': 'urdu',
121
- 'ug': 'uyghur',
122
- 'uz': 'uzbek',
123
- 'vi': 'vietnamese',
124
- 'cy': 'welsh',
125
- 'xh': 'xhosa',
126
- 'yi': 'yiddish',
127
- 'yo': 'yoruba',
128
- 'zu': 'zulu',
129
- }
130
-
131
- GOOGLE_LANGUAGES_TO_CODES = {v: k for k, v in GOOGLE_CODES_TO_LANGUAGES.items()}
132
-
133
- # This dictionary maps the primary name of language to its secondary names in list manner (if any)
134
- GOOGLE_LANGUAGES_SECONDARY_NAMES = {
135
- 'myanmar': ['burmese'],
136
- 'odia': ['oriya'],
137
- 'kurdish': ['kurmanji']
138
  }
139
 
140
-
141
  PONS_CODES_TO_LANGUAGES = {
142
- 'ar': 'arabic',
143
- 'bg': 'bulgarian',
144
- 'zh-cn': 'chinese',
145
- 'cs': 'czech',
146
- 'da': 'danish',
147
- 'nl': 'dutch',
148
- 'en': 'english',
149
- 'fr': 'french',
150
- 'de': 'german',
151
- 'el': 'greek',
152
- 'hu': 'hungarian',
153
- 'it': 'italian',
154
- 'la': 'latin',
155
- 'no': 'norwegian',
156
- 'pl': 'polish',
157
- 'pt': 'portuguese',
158
- 'ru': 'russian',
159
- 'sl': 'slovenian',
160
- 'es': 'spanish',
161
- 'sv': 'swedish',
162
- 'tr': 'turkish',
163
- 'elv': 'elvish'
164
  }
165
 
166
- PONS_LANGUAGES_TO_CODES = {v: k for k, v in PONS_CODES_TO_LANGUAGES.items()}
167
-
168
  LINGUEE_LANGUAGES_TO_CODES = {
169
  "maltese": "mt",
170
  "english": "en",
@@ -192,11 +178,9 @@ LINGUEE_LANGUAGES_TO_CODES = {
192
  "swedish": "sv",
193
  "latvian": "lv",
194
  "estonian": "et",
195
- "japanese": "ja"
196
  }
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",
@@ -221,56 +205,40 @@ DEEPL_LANGUAGE_TO_CODE = {
221
  "slovak": "sk",
222
  "slovenian": "sl",
223
  "swedish": "sv",
224
- "chinese": "zh"
225
- }
226
-
227
- DEEPL_CODE_TO_LANGUAGE = {v: k for k, v in DEEPL_LANGUAGE_TO_CODE.items()}
228
-
229
- PAPAGO_CODE_TO_LANGUAGE = {
230
- 'ko': 'Korean',
231
- 'en': 'English',
232
- 'ja': 'Japanese',
233
- 'zh-CN': 'Chinese',
234
- 'zh-TW': 'Chinese traditional',
235
- 'es': 'Spanish',
236
- 'fr': 'French',
237
- 'vi': 'Vietnamese',
238
- 'th': 'Thai',
239
- 'id': 'Indonesia'
240
- }
241
-
242
- PAPAGO_LANGUAGE_TO_CODE = {v: k for v, k in PAPAGO_CODE_TO_LANGUAGE.items()}
243
-
244
- QCRI_CODE_TO_LANGUAGE = {
245
- 'ar': 'Arabic',
246
- 'en': 'English',
247
- 'es': 'Spanish'
248
  }
249
 
250
- QCRI_LANGUAGE_TO_CODE = {
251
- v: k for k, v in QCRI_CODE_TO_LANGUAGE.items()
 
 
 
 
 
 
 
 
 
252
  }
253
 
254
- LIBRE_CODES_TO_LANGUAGES = {
255
- 'en': 'English',
256
- 'ar': 'Arabic',
257
- 'zh': 'Chinese',
258
- 'fr': 'French',
259
- 'de': 'German',
260
- 'hi': 'Hindi',
261
- 'id': 'Indonesian',
262
- 'ga': 'Irish',
263
- 'it': 'Italian',
264
- 'ja': 'Japanese',
265
- 'ko': 'Korean',
266
- 'pl': 'Polish',
267
- 'pt': 'Portuguese',
268
- 'ru': 'Russian',
269
- 'es': 'Spanish',
270
- 'tr': 'Turkish',
271
- 'vi': 'Vietnamese'
272
- }
273
 
274
  LIBRE_LANGUAGES_TO_CODES = {
275
- v: k for k, v in LIBRE_CODES_TO_LANGUAGES.items()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  }
 
 
 
1
  BASE_URLS = {
2
  "GOOGLE_TRANSLATE": "https://translate.google.com/m",
3
  "PONS": "https://en.pons.com/translate/",
 
14
  "LIBRE_FREE": "https://libretranslate.de/",
15
  }
16
 
17
+ GOOGLE_LANGUAGES_TO_CODES = {
18
+ "afrikaans": "af",
19
+ "albanian": "sq",
20
+ "amharic": "am",
21
+ "arabic": "ar",
22
+ "armenian": "hy",
23
+ "azerbaijani": "az",
24
+ "basque": "eu",
25
+ "belarusian": "be",
26
+ "bengali": "bn",
27
+ "bosnian": "bs",
28
+ "bulgarian": "bg",
29
+ "catalan": "ca",
30
+ "cebuano": "ceb",
31
+ "chichewa": "ny",
32
+ "chinese (simplified)": "zh-CN",
33
+ "chinese (traditional)": "zh-TW",
34
+ "corsican": "co",
35
+ "croatian": "hr",
36
+ "czech": "cs",
37
+ "danish": "da",
38
+ "dutch": "nl",
39
+ "english": "en",
40
+ "esperanto": "eo",
41
+ "estonian": "et",
42
+ "filipino": "tl",
43
+ "finnish": "fi",
44
+ "french": "fr",
45
+ "frisian": "fy",
46
+ "galician": "gl",
47
+ "georgian": "ka",
48
+ "german": "de",
49
+ "greek": "el",
50
+ "gujarati": "gu",
51
+ "haitian creole": "ht",
52
+ "hausa": "ha",
53
+ "hawaiian": "haw",
54
+ "hebrew": "iw",
55
+ "hindi": "hi",
56
+ "hmong": "hmn",
57
+ "hungarian": "hu",
58
+ "icelandic": "is",
59
+ "igbo": "ig",
60
+ "indonesian": "id",
61
+ "irish": "ga",
62
+ "italian": "it",
63
+ "japanese": "ja",
64
+ "javanese": "jw",
65
+ "kannada": "kn",
66
+ "kazakh": "kk",
67
+ "khmer": "km",
68
+ "kinyarwanda": "rw",
69
+ "korean": "ko",
70
+ "kurdish": "ku",
71
+ "kyrgyz": "ky",
72
+ "lao": "lo",
73
+ "latin": "la",
74
+ "latvian": "lv",
75
+ "lithuanian": "lt",
76
+ "luxembourgish": "lb",
77
+ "macedonian": "mk",
78
+ "malagasy": "mg",
79
+ "malay": "ms",
80
+ "malayalam": "ml",
81
+ "maltese": "mt",
82
+ "maori": "mi",
83
+ "marathi": "mr",
84
+ "mongolian": "mn",
85
+ "myanmar": "my",
86
+ "nepali": "ne",
87
+ "norwegian": "no",
88
+ "odia": "or",
89
+ "pashto": "ps",
90
+ "persian": "fa",
91
+ "polish": "pl",
92
+ "portuguese": "pt",
93
+ "punjabi": "pa",
94
+ "romanian": "ro",
95
+ "russian": "ru",
96
+ "samoan": "sm",
97
+ "scots gaelic": "gd",
98
+ "serbian": "sr",
99
+ "sesotho": "st",
100
+ "shona": "sn",
101
+ "sindhi": "sd",
102
+ "sinhala": "si",
103
+ "slovak": "sk",
104
+ "slovenian": "sl",
105
+ "somali": "so",
106
+ "spanish": "es",
107
+ "sundanese": "su",
108
+ "swahili": "sw",
109
+ "swedish": "sv",
110
+ "tajik": "tg",
111
+ "tamil": "ta",
112
+ "tatar": "tt",
113
+ "telugu": "te",
114
+ "thai": "th",
115
+ "turkish": "tr",
116
+ "turkmen": "tk",
117
+ "ukrainian": "uk",
118
+ "urdu": "ur",
119
+ "uyghur": "ug",
120
+ "uzbek": "uz",
121
+ "vietnamese": "vi",
122
+ "welsh": "cy",
123
+ "xhosa": "xh",
124
+ "yiddish": "yi",
125
+ "yoruba": "yo",
126
+ "zulu": "zu",
 
 
 
 
 
 
 
 
 
127
  }
128
 
 
129
  PONS_CODES_TO_LANGUAGES = {
130
+ "ar": "arabic",
131
+ "bg": "bulgarian",
132
+ "zh-cn": "chinese",
133
+ "cs": "czech",
134
+ "da": "danish",
135
+ "nl": "dutch",
136
+ "en": "english",
137
+ "fr": "french",
138
+ "de": "german",
139
+ "el": "greek",
140
+ "hu": "hungarian",
141
+ "it": "italian",
142
+ "la": "latin",
143
+ "no": "norwegian",
144
+ "pl": "polish",
145
+ "pt": "portuguese",
146
+ "ru": "russian",
147
+ "sl": "slovenian",
148
+ "es": "spanish",
149
+ "sv": "swedish",
150
+ "tr": "turkish",
151
+ "elv": "elvish",
152
  }
153
 
 
 
154
  LINGUEE_LANGUAGES_TO_CODES = {
155
  "maltese": "mt",
156
  "english": "en",
 
178
  "swedish": "sv",
179
  "latvian": "lv",
180
  "estonian": "et",
181
+ "japanese": "ja",
182
  }
183
 
 
 
184
  DEEPL_LANGUAGE_TO_CODE = {
185
  "bulgarian": "bg",
186
  "czech": "cs",
 
205
  "slovak": "sk",
206
  "slovenian": "sl",
207
  "swedish": "sv",
208
+ "chinese": "zh",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  }
210
 
211
+ PAPAGO_LANGUAGE_TO_CODE = {
212
+ "ko": "Korean",
213
+ "en": "English",
214
+ "ja": "Japanese",
215
+ "zh-CN": "Chinese",
216
+ "zh-TW": "Chinese traditional",
217
+ "es": "Spanish",
218
+ "fr": "French",
219
+ "vi": "Vietnamese",
220
+ "th": "Thai",
221
+ "id": "Indonesia",
222
  }
223
 
224
+ QCRI_LANGUAGE_TO_CODE = {"Arabic": "ar", "English": "en", "Spanish": "es"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
 
226
  LIBRE_LANGUAGES_TO_CODES = {
227
+ "English": "en",
228
+ "Arabic": "ar",
229
+ "Chinese": "zh",
230
+ "French": "fr",
231
+ "German": "de",
232
+ "Hindi": "hi",
233
+ "Indonesian": "id",
234
+ "Irish": "ga",
235
+ "Italian": "it",
236
+ "Japanese": "ja",
237
+ "Korean": "ko",
238
+ "Polish": "pl",
239
+ "Portuguese": "pt",
240
+ "Russian": "ru",
241
+ "Spanish": "es",
242
+ "Turkish": "tr",
243
+ "Vietnamese": "vi",
244
  }
deep_translator/deepl.py CHANGED
@@ -1,11 +1,15 @@
 
 
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):
@@ -13,7 +17,14 @@ class DeeplTranslator(BaseTranslator):
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/
@@ -22,39 +33,43 @@ class DeeplTranslator(BaseTranslator):
22
  """
23
  if not api_key:
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.
@@ -67,12 +82,12 @@ class DeeplTranslator(BaseTranslator):
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
@@ -80,7 +95,7 @@ class DeeplTranslator(BaseTranslator):
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)
 
1
+ from typing import List, Optional
2
+
3
  import requests
4
 
 
 
 
 
 
5
  from deep_translator.base import BaseTranslator
6
+ from deep_translator.constants import BASE_URLS, DEEPL_LANGUAGE_TO_CODE
7
+ from deep_translator.exceptions import (
8
+ AuthorizationException,
9
+ ServerException,
10
+ TranslationNotFound,
11
+ )
12
+ from deep_translator.validate import is_empty, is_input_valid
13
 
14
 
15
  class DeeplTranslator(BaseTranslator):
 
17
  class that wraps functions, which use the DeeplTranslator translator under the hood to translate word(s)
18
  """
19
 
20
+ def __init__(
21
+ self,
22
+ api_key: Optional[str] = None,
23
+ source: str = "de",
24
+ target: str = "en",
25
+ use_free_api: bool = True,
26
+ **kwargs
27
+ ):
28
  """
29
  @param api_key: your DeeplTranslator api key.
30
  Get one here: https://www.deepl.com/docs-api/accessing-the-api/
 
33
  """
34
  if not api_key:
35
  raise ServerException(401)
36
+ self.version = "v2"
37
  self.api_key = api_key
38
+ url = (
39
+ BASE_URLS.get("DEEPL_FREE").format(version=self.version)
40
+ if use_free_api
41
+ else BASE_URLS.get("DEEPL").format(version=self.version)
42
+ )
43
  super().__init__(
44
  base_url=url,
45
  source=source,
46
  target=target,
47
  languages=DEEPL_LANGUAGE_TO_CODE,
48
+ **kwargs
49
+ )
50
 
51
+ def translate(self, text: str, **kwargs) -> str:
52
  """
53
  @param text: text to translate
54
  @return: translated text
55
  """
56
+ if is_input_valid(text):
57
  if self._same_source_target() or is_empty(text):
58
  return text
59
 
60
  # Create the request parameters.
61
+ translate_endpoint = "translate"
62
  params = {
63
  "auth_key": self.api_key,
64
  "source_lang": self._source,
65
  "target_lang": self._target,
66
+ "text": text,
67
  }
68
  # Do the request and check the connection.
69
  try:
70
  response = requests.get(
71
+ self._base_url + translate_endpoint, params=params
72
+ )
73
  except ConnectionError:
74
  raise ServerException(503)
75
  # If the answer is not success, raise server exception.
 
82
  if not res:
83
  raise TranslationNotFound(text)
84
  # Process and return the response.
85
+ return res["translations"][0]["text"]
86
 
87
+ def translate_file(self, path: str, **kwargs) -> str:
88
  return self._translate_file(path, **kwargs)
89
 
90
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
91
  """
92
  @param batch: list of texts to translate
93
  @return: list of translations
 
95
  return self._translate_batch(batch, **kwargs)
96
 
97
 
98
+ if __name__ == "__main__":
99
  d = DeeplTranslator(target="en", api_key="some-key")
100
  t = d.translate("Ich habe keine ahnung")
101
  print("text: ", t)
deep_translator/detection.py CHANGED
@@ -1,14 +1,22 @@
1
  """
2
  language detection API
3
  """
 
 
4
  import requests
5
  from requests.exceptions import HTTPError
6
 
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
14
 
@@ -19,20 +27,20 @@ def get_request_body(text, api_key, *args, **kwargs):
19
 
20
  """
21
  if not api_key:
22
- raise Exception("you need to get an API_KEY for this to work. "
23
- "Get one for free here: https://detectlanguage.com/documentation")
 
 
24
  if not text:
25
  raise Exception("Please provide an input text")
26
 
27
  else:
28
  try:
29
- headers = config['headers']
30
- headers['Authorization'] = headers['Authorization'].format(api_key)
31
- response = requests.post(config['url'],
32
- json={'q': text},
33
- headers=headers)
34
 
35
- body = response.json().get('data')
36
  return body
37
 
38
  except HTTPError as e:
@@ -40,7 +48,9 @@ def get_request_body(text, api_key, *args, **kwargs):
40
  raise e
41
 
42
 
43
- def single_detection(text, api_key=None, detailed=False, *args, **kwargs):
 
 
44
  """
45
  function responsible for detecting the language from a text
46
 
@@ -51,16 +61,18 @@ def single_detection(text, api_key=None, detailed=False, *args, **kwargs):
51
  @param detailed: set to True if you want to get detailed information about the detection process
52
  """
53
  body = get_request_body(text, api_key)
54
- detections = body.get('detections')
55
  if detailed:
56
  return detections[0]
57
 
58
- lang = detections[0].get('language', None)
59
  if lang:
60
  return lang
61
 
62
 
63
- def batch_detection(text_list, api_key, detailed=False, *args, **kwargs):
 
 
64
  """
65
  function responsible for detecting the language from a text
66
 
@@ -69,10 +81,9 @@ def batch_detection(text_list, api_key, detailed=False, *args, **kwargs):
69
  @param detailed: set to True if you want to get detailed information about the detection process
70
  """
71
  body = get_request_body(text_list, api_key)
72
- detections = body.get('detections')
73
  res = [obj[0] for obj in detections]
74
  if detailed:
75
  return res
76
  else:
77
- return [obj['language'] for obj in res]
78
-
 
1
  """
2
  language detection API
3
  """
4
+ from typing import List, Optional, Union
5
+
6
  import requests
7
  from requests.exceptions import HTTPError
8
 
9
  # Module global config
10
+ config = {
11
+ "url": "https://ws.detectlanguage.com/0.2/detect",
12
+ "headers": {
13
+ "User-Agent": "Detect Language API Python Client 1.4.0",
14
+ "Authorization": "Bearer {}",
15
+ },
16
+ }
17
 
18
 
19
+ def get_request_body(text: Union[str, List[str]], api_key: str, *args, **kwargs):
20
  """
21
  send a request and return the response body parsed as dictionary
22
 
 
27
 
28
  """
29
  if not api_key:
30
+ raise Exception(
31
+ "you need to get an API_KEY for this to work. "
32
+ "Get one for free here: https://detectlanguage.com/documentation"
33
+ )
34
  if not text:
35
  raise Exception("Please provide an input text")
36
 
37
  else:
38
  try:
39
+ headers = config["headers"]
40
+ headers["Authorization"] = headers["Authorization"].format(api_key)
41
+ response = requests.post(config["url"], json={"q": text}, headers=headers)
 
 
42
 
43
+ body = response.json().get("data")
44
  return body
45
 
46
  except HTTPError as e:
 
48
  raise e
49
 
50
 
51
+ def single_detection(
52
+ text: str, api_key: Optional[str] = None, detailed: bool = False, *args, **kwargs
53
+ ):
54
  """
55
  function responsible for detecting the language from a text
56
 
 
61
  @param detailed: set to True if you want to get detailed information about the detection process
62
  """
63
  body = get_request_body(text, api_key)
64
+ detections = body.get("detections")
65
  if detailed:
66
  return detections[0]
67
 
68
+ lang = detections[0].get("language", None)
69
  if lang:
70
  return lang
71
 
72
 
73
+ def batch_detection(
74
+ text_list: List[str], api_key: str, detailed: bool = False, *args, **kwargs
75
+ ):
76
  """
77
  function responsible for detecting the language from a text
78
 
 
81
  @param detailed: set to True if you want to get detailed information about the detection process
82
  """
83
  body = get_request_body(text_list, api_key)
84
+ detections = body.get("detections")
85
  res = [obj[0] for obj in detections]
86
  if detailed:
87
  return res
88
  else:
89
+ return [obj["language"] for obj in res]
 
deep_translator/engines.py CHANGED
@@ -1,7 +1,6 @@
1
-
2
- from .base import BaseTranslator
3
 
4
  __engines__ = {
5
- translator.__name__.replace('Translator', '').lower():
6
- translator for translator in BaseTranslator.__subclasses__()
7
  }
 
1
+ from deep_translator.base import BaseTranslator
 
2
 
3
  __engines__ = {
4
+ translator.__name__.replace("Translator", "").lower(): translator
5
+ for translator in BaseTranslator.__subclasses__()
6
  }
deep_translator/exceptions.py CHANGED
@@ -30,9 +30,11 @@ class NotValidPayload(BaseError):
30
  exception thrown if the user enters an invalid payload
31
  """
32
 
33
- def __init__(self,
34
- val,
35
- message='text must be a valid text with maximum 5000 character, otherwise it cannot be translated'):
 
 
36
  super(NotValidPayload, self).__init__(val, message)
37
 
38
 
@@ -41,9 +43,7 @@ class InvalidSourceOrTargetLanguage(BaseError):
41
  exception thrown if the user enters an invalid payload
42
  """
43
 
44
- def __init__(self,
45
- val,
46
- message="Invalid source or target language!"):
47
  super(InvalidSourceOrTargetLanguage, self).__init__(val, message)
48
 
49
 
@@ -52,9 +52,11 @@ class TranslationNotFound(BaseError):
52
  exception thrown if no translation was found for the text provided by the user
53
  """
54
 
55
- def __init__(self,
56
- val,
57
- message='No translation was found using the current translator. Try another translator?'):
 
 
58
  super(TranslationNotFound, self).__init__(val, message)
59
 
60
 
@@ -63,9 +65,9 @@ class ElementNotFoundInGetRequest(BaseError):
63
  exception thrown if the html element was not found in the body parsed by beautifulsoup
64
  """
65
 
66
- def __init__(self,
67
- val,
68
- message='Required element was not found in the API response'):
69
  super(ElementNotFoundInGetRequest, self).__init__(val, message)
70
 
71
 
@@ -75,7 +77,9 @@ class NotValidLength(BaseError):
75
  """
76
 
77
  def __init__(self, val, min_chars, max_chars):
78
- message = "Text length need to be between {} and {} characters".format(min_chars, max_chars)
 
 
79
  super(NotValidLength, self).__init__(val, message)
80
 
81
 
@@ -84,8 +88,11 @@ class RequestError(Exception):
84
  exception thrown if an error occurred during the request call, e.g a connection problem.
85
  """
86
 
87
- def __init__(self, message="Request exception can happen due to an api connection error. "
88
- "Please check your connection and try again"):
 
 
 
89
  self.message = message
90
 
91
  def __str__(self):
@@ -99,7 +106,7 @@ class MicrosoftAPIerror(Exception):
99
 
100
  def __init__(self, api_message):
101
  self.api_message = str(api_message)
102
- self.message="Microsoft API returned the following error"
103
 
104
  def __str__(self):
105
  return "{}: {}".format(self.message, self.api_message)
@@ -110,7 +117,10 @@ class TooManyRequests(Exception):
110
  exception thrown if an error occurred during the request call, e.g a connection problem.
111
  """
112
 
113
- def __init__(self, message="Server Error: You made too many requests to the server. According to google, you are allowed to make 5 requests per second and up to 200k requests per day. You can wait and try again later or you can try the translate_batch function"):
 
 
 
114
  self.message = message
115
 
116
  def __str__(self):
@@ -121,6 +131,7 @@ class ServerException(Exception):
121
  """
122
  Default YandexTranslate exception from the official website
123
  """
 
124
  errors = {
125
  400: "ERR_BAD_REQUEST",
126
  401: "ERR_KEY_INVALID",
@@ -142,5 +153,5 @@ class ServerException(Exception):
142
 
143
  class AuthorizationException(Exception):
144
  def __init__(self, api_key, *args):
145
- msg = 'Unauthorized access with the api key ' + api_key
146
  super().__init__(msg, *args)
 
30
  exception thrown if the user enters an invalid payload
31
  """
32
 
33
+ def __init__(
34
+ self,
35
+ val,
36
+ message="text must be a valid text with maximum 5000 character, otherwise it cannot be translated",
37
+ ):
38
  super(NotValidPayload, self).__init__(val, message)
39
 
40
 
 
43
  exception thrown if the user enters an invalid payload
44
  """
45
 
46
+ def __init__(self, val, message="Invalid source or target language!"):
 
 
47
  super(InvalidSourceOrTargetLanguage, self).__init__(val, message)
48
 
49
 
 
52
  exception thrown if no translation was found for the text provided by the user
53
  """
54
 
55
+ def __init__(
56
+ self,
57
+ val,
58
+ message="No translation was found using the current translator. Try another translator?",
59
+ ):
60
  super(TranslationNotFound, self).__init__(val, message)
61
 
62
 
 
65
  exception thrown if the html element was not found in the body parsed by beautifulsoup
66
  """
67
 
68
+ def __init__(
69
+ self, val, message="Required element was not found in the API response"
70
+ ):
71
  super(ElementNotFoundInGetRequest, self).__init__(val, message)
72
 
73
 
 
77
  """
78
 
79
  def __init__(self, val, min_chars, max_chars):
80
+ message = (
81
+ f"Text length need to be between {min_chars} and {max_chars} characters"
82
+ )
83
  super(NotValidLength, self).__init__(val, message)
84
 
85
 
 
88
  exception thrown if an error occurred during the request call, e.g a connection problem.
89
  """
90
 
91
+ def __init__(
92
+ self,
93
+ message="Request exception can happen due to an api connection error. "
94
+ "Please check your connection and try again",
95
+ ):
96
  self.message = message
97
 
98
  def __str__(self):
 
106
 
107
  def __init__(self, api_message):
108
  self.api_message = str(api_message)
109
+ self.message = "Microsoft API returned the following error"
110
 
111
  def __str__(self):
112
  return "{}: {}".format(self.message, self.api_message)
 
117
  exception thrown if an error occurred during the request call, e.g a connection problem.
118
  """
119
 
120
+ def __init__(
121
+ self,
122
+ message="Server Error: You made too many requests to the server. According to google, you are allowed to make 5 requests per second and up to 200k requests per day. You can wait and try again later or you can try the translate_batch function",
123
+ ):
124
  self.message = message
125
 
126
  def __str__(self):
 
131
  """
132
  Default YandexTranslate exception from the official website
133
  """
134
+
135
  errors = {
136
  400: "ERR_BAD_REQUEST",
137
  401: "ERR_KEY_INVALID",
 
153
 
154
  class AuthorizationException(Exception):
155
  def __init__(self, api_key, *args):
156
+ msg = "Unauthorized access with the api key " + api_key
157
  super().__init__(msg, *args)
deep_translator/google.py CHANGED
@@ -2,61 +2,76 @@
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:
54
  raise TooManyRequests()
55
 
56
  if response.status_code != 200:
57
  raise RequestError()
58
 
59
- soup = BeautifulSoup(response.text, 'html.parser')
60
 
61
  element = soup.find(self._element_tag, self._element_query)
62
 
@@ -65,9 +80,15 @@ class GoogleTranslator(BaseTranslator):
65
  if not element:
66
  raise TranslationNotFound(text)
67
  if element.get_text(strip=True) == text.strip():
68
- to_translate_alpha = ''.join(ch for ch in text.strip() if ch.isalnum())
69
- translated_alpha = ''.join(ch for ch in element.get_text(strip=True) if ch.isalnum())
70
- if to_translate_alpha and translated_alpha and to_translate_alpha == translated_alpha:
 
 
 
 
 
 
71
  self._url_params["tl"] = self._target
72
  if "hl" not in self._url_params:
73
  return text.strip()
@@ -77,7 +98,7 @@ class GoogleTranslator(BaseTranslator):
77
  else:
78
  return element.get_text(strip=True)
79
 
80
- def translate_file(self, path, **kwargs):
81
  """
82
  translate directly from file
83
  @param path: path to the target file
@@ -87,7 +108,7 @@ class GoogleTranslator(BaseTranslator):
87
  """
88
  return self._translate_file(path, **kwargs)
89
 
90
- def translate_batch(self, batch=None, **kwargs):
91
  """
92
  translate a list of texts
93
  @param batch: list of texts you want to translate
@@ -96,6 +117,6 @@ class GoogleTranslator(BaseTranslator):
96
  return self._translate_batch(batch, **kwargs)
97
 
98
 
99
- if __name__ == '__main__':
100
  t = GoogleTranslator().translate("hallo welt")
101
  print("translation: ", t)
 
2
  google translator API
3
  """
4
 
5
+ from typing import List, Optional
6
+
 
 
 
7
  import requests
8
+ from bs4 import BeautifulSoup
9
+
10
+ from deep_translator.base import BaseTranslator
11
+ from deep_translator.constants import BASE_URLS
12
+ from deep_translator.exceptions import (
13
+ RequestError,
14
+ TooManyRequests,
15
+ TranslationNotFound,
16
+ )
17
+ from deep_translator.validate import is_empty, is_input_valid
18
 
19
 
20
  class GoogleTranslator(BaseTranslator):
21
  """
22
+ class that wraps functions, which use Google Translate under the hood to translate text(s)
23
  """
24
 
25
+ def __init__(
26
+ self,
27
+ source: str = "auto",
28
+ target: str = "en",
29
+ proxies: Optional[dict] = None,
30
+ **kwargs
31
+ ):
32
  """
33
  @param source: source language to translate from
34
  @param target: target language to translate to
35
  """
36
  self.proxies = proxies
37
+ super().__init__(
38
+ base_url=BASE_URLS.get("GOOGLE_TRANSLATE"),
39
+ source=source,
40
+ target=target,
41
+ element_tag="div",
42
+ element_query={"class": "t0"},
43
+ payload_key="q", # key of text in the url
44
+ **kwargs
45
+ )
46
 
47
  self._alt_element_query = {"class": "result-container"}
48
 
49
+ def translate(self, text: str, **kwargs) -> str:
50
  """
51
+ function to translate a text
52
  @param text: desired text to translate
53
  @return: str: translated text
54
  """
55
+ if is_input_valid(text):
56
  text = text.strip()
57
  if self._same_source_target() or is_empty(text):
58
  return text
59
+ self._url_params["tl"] = self._target
60
+ self._url_params["sl"] = self._source
61
 
62
  if self.payload_key:
63
  self._url_params[self.payload_key] = text
64
 
65
+ response = requests.get(
66
+ self._base_url, params=self._url_params, proxies=self.proxies
67
+ )
68
  if response.status_code == 429:
69
  raise TooManyRequests()
70
 
71
  if response.status_code != 200:
72
  raise RequestError()
73
 
74
+ soup = BeautifulSoup(response.text, "html.parser")
75
 
76
  element = soup.find(self._element_tag, self._element_query)
77
 
 
80
  if not element:
81
  raise TranslationNotFound(text)
82
  if element.get_text(strip=True) == text.strip():
83
+ to_translate_alpha = "".join(ch for ch in text.strip() if ch.isalnum())
84
+ translated_alpha = "".join(
85
+ ch for ch in element.get_text(strip=True) if ch.isalnum()
86
+ )
87
+ if (
88
+ to_translate_alpha
89
+ and translated_alpha
90
+ and to_translate_alpha == translated_alpha
91
+ ):
92
  self._url_params["tl"] = self._target
93
  if "hl" not in self._url_params:
94
  return text.strip()
 
98
  else:
99
  return element.get_text(strip=True)
100
 
101
+ def translate_file(self, path: str, **kwargs) -> str:
102
  """
103
  translate directly from file
104
  @param path: path to the target file
 
108
  """
109
  return self._translate_file(path, **kwargs)
110
 
111
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
112
  """
113
  translate a list of texts
114
  @param batch: list of texts you want to translate
 
117
  return self._translate_batch(batch, **kwargs)
118
 
119
 
120
+ if __name__ == "__main__":
121
  t = GoogleTranslator().translate("hallo welt")
122
  print("translation: ", t)
deep_translator/libre.py CHANGED
@@ -2,14 +2,18 @@
2
  LibreTranslate API
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):
@@ -17,7 +21,13 @@ class LibreTranslator(BaseTranslator):
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
@@ -27,34 +37,38 @@ class LibreTranslator(BaseTranslator):
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
  """
37
  function that uses microsoft translate to translate a text
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.
@@ -68,9 +82,9 @@ class LibreTranslator(BaseTranslator):
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
  """
75
  translate directly from file
76
  @param path: path to the target file
@@ -80,7 +94,7 @@ class LibreTranslator(BaseTranslator):
80
  """
81
  return self._translate_file(path, **kwargs)
82
 
83
- def translate_batch(self, batch=None, **kwargs):
84
  """
85
  translate a list of texts
86
  @param batch: list of texts you want to translate
 
2
  LibreTranslate API
3
  """
4
 
5
+ from typing import List, Optional
6
+
7
  import requests
8
 
9
+ from deep_translator.base import BaseTranslator
10
+ from deep_translator.constants import BASE_URLS, LIBRE_LANGUAGES_TO_CODES
11
+ from deep_translator.exceptions import (
12
+ AuthorizationException,
13
+ ServerException,
14
+ TranslationNotFound,
15
+ )
16
+ from deep_translator.validate import is_empty, is_input_valid
17
 
18
 
19
  class LibreTranslator(BaseTranslator):
 
21
  class that wraps functions, which use libre translator under the hood to translate text(s)
22
  """
23
 
24
+ def __init__(
25
+ self,
26
+ api_key: Optional[str] = None,
27
+ source: str = "auto",
28
+ target: str = "en",
29
+ **kwargs
30
+ ):
31
  """
32
  @param source: source language to translate from
33
  List of LibreTranslate nedpoints can be found at : https://github.com/LibreTranslate/LibreTranslate#mirrors
 
37
  if not api_key:
38
  raise ServerException(401)
39
  self.api_key = api_key
40
+ super().__init__(
41
+ base_url=BASE_URLS.get("LIBRE"),
42
+ source=source,
43
+ target=target,
44
+ languages=LIBRE_LANGUAGES_TO_CODES,
45
+ )
46
 
47
+ def translate(self, text: str, **kwargs) -> str:
48
  """
49
  function that uses microsoft translate to translate a text
50
  @param text: desired text to translate
51
  @return: str: translated text
52
  """
53
+ if is_input_valid(text):
54
  if self._same_source_target() or is_empty(text):
55
  return text
56
 
57
+ translate_endpoint = "translate"
58
  params = {
59
  "q": text,
60
  "source": self._source,
61
  "target": self._target,
62
+ "format": "text",
63
  }
64
  # Add API Key if required
65
  if self.api_key:
66
  params["api_key"] = self.api_key
67
  # Do the request and check the connection.
68
  try:
69
+ response = requests.post(
70
+ self._base_url + translate_endpoint, params=params
71
+ )
72
  except ConnectionError:
73
  raise ServerException(503)
74
  # If the answer is not success, raise server exception.
 
82
  if not res:
83
  raise TranslationNotFound(text)
84
  # Process and return the response.
85
+ return res["translatedText"]
86
 
87
+ def translate_file(self, path: str, **kwargs) -> str:
88
  """
89
  translate directly from file
90
  @param path: path to the target file
 
94
  """
95
  return self._translate_file(path, **kwargs)
96
 
97
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
98
  """
99
  translate a list of texts
100
  @param batch: list of texts you want to translate
deep_translator/linguee.py CHANGED
@@ -1,41 +1,50 @@
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
16
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  class LingueeTranslator(BaseTranslator):
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
41
  @param word: word to translate
@@ -47,9 +56,11 @@ class LingueeTranslator(BaseTranslator):
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
 
@@ -58,7 +69,7 @@ class LingueeTranslator(BaseTranslator):
58
 
59
  if response.status_code != 200:
60
  raise RequestError()
61
- soup = BeautifulSoup(response.text, 'html.parser')
62
  elements = soup.find_all(self._element_tag, self._element_query)
63
  if not elements:
64
  raise ElementNotFoundInGetRequest(elements)
@@ -66,17 +77,19 @@ class LingueeTranslator(BaseTranslator):
66
  filtered_elements = []
67
  for el in elements:
68
  try:
69
- pronoun = el.find('span', {'class': 'placeholder'}).get_text(strip=True)
 
 
70
  except AttributeError:
71
- pronoun = ''
72
- filtered_elements.append(el.get_text(strip=True).replace(pronoun, ''))
73
 
74
  if not filtered_elements:
75
  raise TranslationNotFound(word)
76
 
77
  return filtered_elements if return_all else filtered_elements[0]
78
 
79
- def translate_words(self, words, **kwargs):
80
  """
81
  translate a batch of words together by providing them in a list
82
  @param words: list of words you want to translate
@@ -90,4 +103,3 @@ class LingueeTranslator(BaseTranslator):
90
  for word in words:
91
  translated_words.append(self.translate(word=word, **kwargs))
92
  return translated_words
93
-
 
1
  """
2
  linguee translator API
3
  """
4
+ from typing import List, Optional, Union
5
+
 
 
 
 
 
 
 
 
6
  import requests
7
+ from bs4 import BeautifulSoup
8
  from requests.utils import requote_uri
9
 
10
+ from deep_translator.base import BaseTranslator
11
+ from deep_translator.constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES
12
+ from deep_translator.exceptions import (
13
+ ElementNotFoundInGetRequest,
14
+ NotValidPayload,
15
+ RequestError,
16
+ TooManyRequests,
17
+ TranslationNotFound,
18
+ )
19
+ from deep_translator.validate import is_empty, is_input_valid
20
+
21
 
22
  class LingueeTranslator(BaseTranslator):
23
  """
24
  class that wraps functions, which use the linguee translator under the hood to translate word(s)
25
  """
26
 
27
+ def __init__(
28
+ self, source: str, target: str = "en", proxies: Optional[dict] = None, **kwargs
29
+ ):
30
  """
31
  @param source: source language to translate from
32
  @param target: target language to translate to
33
  """
34
  self.proxies = proxies
35
+ super().__init__(
36
+ base_url=BASE_URLS.get("LINGUEE"),
37
+ source=source,
38
+ target=target,
39
+ languages=LINGUEE_LANGUAGES_TO_CODES,
40
+ element_tag="a",
41
+ element_query={"class": "dictLink featured"},
42
+ payload_key=None, # key of text in the url
43
+ )
44
 
45
+ def translate(
46
+ self, word: str, return_all: bool = False, **kwargs
47
+ ) -> Union[str, List[str]]:
48
  """
49
  function that uses linguee to translate a word
50
  @param word: word to translate
 
56
  if self._same_source_target() or is_empty(word):
57
  return word
58
 
59
+ if is_input_valid(word, max_chars=50):
60
  # %s-%s/translation/%s.html
61
+ url = (
62
+ f"{self._base_url}{self._source}-{self._target}/translation/{word}.html"
63
+ )
64
  url = requote_uri(url)
65
  response = requests.get(url, proxies=self.proxies)
66
 
 
69
 
70
  if response.status_code != 200:
71
  raise RequestError()
72
+ soup = BeautifulSoup(response.text, "html.parser")
73
  elements = soup.find_all(self._element_tag, self._element_query)
74
  if not elements:
75
  raise ElementNotFoundInGetRequest(elements)
 
77
  filtered_elements = []
78
  for el in elements:
79
  try:
80
+ pronoun = el.find("span", {"class": "placeholder"}).get_text(
81
+ strip=True
82
+ )
83
  except AttributeError:
84
+ pronoun = ""
85
+ filtered_elements.append(el.get_text(strip=True).replace(pronoun, ""))
86
 
87
  if not filtered_elements:
88
  raise TranslationNotFound(word)
89
 
90
  return filtered_elements if return_all else filtered_elements[0]
91
 
92
+ def translate_words(self, words: List[str], **kwargs) -> List[str]:
93
  """
94
  translate a batch of words together by providing them in a list
95
  @param words: list of words you want to translate
 
103
  for word in words:
104
  translated_words.append(self.translate(word=word, **kwargs))
105
  return translated_words
 
deep_translator/microsoft.py CHANGED
@@ -1,12 +1,15 @@
1
  # -*- coding: utf-8 -*-
2
 
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):
@@ -14,7 +17,15 @@ class MicrosoftTranslator(BaseTranslator):
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
@@ -41,19 +52,18 @@ class MicrosoftTranslator(BaseTranslator):
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
  """
58
  function that uses microsoft translate to translate a text
59
  @param text: desired text to translate
@@ -62,32 +72,35 @@ class MicrosoftTranslator(BaseTranslator):
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
  """
92
  translate from a file
93
  @param path: path to file
@@ -95,7 +108,7 @@ class MicrosoftTranslator(BaseTranslator):
95
  """
96
  return self._translate_file(path, **kwargs)
97
 
98
- def translate_batch(self, batch, **kwargs):
99
  """
100
  translate a batch of texts
101
  @param batch: list of texts to translate
 
1
  # -*- coding: utf-8 -*-
2
 
 
3
  import logging
4
  import sys
5
+ from typing import List, Optional
6
+
7
+ import requests
8
+
9
+ from deep_translator.base import BaseTranslator
10
+ from deep_translator.constants import BASE_URLS
11
+ from deep_translator.exceptions import MicrosoftAPIerror, ServerException
12
+ from deep_translator.validate import is_input_valid
13
 
14
 
15
  class MicrosoftTranslator(BaseTranslator):
 
17
  the class that wraps functions, which use the Microsoft translator under the hood to translate word(s)
18
  """
19
 
20
+ def __init__(
21
+ self,
22
+ api_key: Optional[str] = None,
23
+ region: Optional[str] = None,
24
+ source: str = "auto",
25
+ target: str = "en",
26
+ proxies: Optional[dict] = None,
27
+ **kwargs,
28
+ ):
29
  """
30
  @params api_key and target are the required params
31
  @param api_key: your Microsoft API key
 
52
  source=source,
53
  target=target,
54
  languages=MICROSOFT_CODES_TO_LANGUAGES,
55
+ **kwargs,
56
  )
57
 
58
  def _get_supported_languages(self):
59
 
60
+ microsoft_languages_api_url = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation"
 
61
  microsoft_languages_response = requests.get(microsoft_languages_api_url)
62
+ translation_dict = microsoft_languages_response.json()["translation"]
63
 
64
+ return {translation_dict[k]["name"].lower(): k for k in translation_dict.keys()}
65
 
66
+ def translate(self, text: str, **kwargs) -> str:
67
  """
68
  function that uses microsoft translate to translate a text
69
  @param text: desired text to translate
 
72
  # a body must be a list of dicts to process multiple texts;
73
  # I have not added multiple text processing here since it is covered by the translate_batch method
74
 
75
+ if is_input_valid(text):
76
+ self._url_params["from"] = self._source
77
+ self._url_params["to"] = self._target
78
 
79
+ valid_microsoft_json = [{"text": text}]
80
  try:
81
+ requested = requests.post(
82
+ self._base_url,
83
+ params=self._url_params,
84
+ headers=self.headers,
85
+ json=valid_microsoft_json,
86
+ proxies=self.proxies,
87
+ )
88
  except requests.exceptions.RequestException:
89
  exc_type, value, traceback = sys.exc_info()
90
  logging.warning(f"Returned error: {exc_type.__name__}")
91
 
92
  # Where Microsoft API responds with an api error, it returns a dict in response.json()
93
  if type(requested.json()) is dict:
94
+ error_message = requested.json()["error"]
95
  raise MicrosoftAPIerror(error_message)
96
  # Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
97
  elif type(requested.json()) is list:
98
+ all_translations = [
99
+ i["text"] for i in requested.json()[0]["translations"]
100
+ ]
101
  return "\n".join(all_translations)
102
 
103
+ def translate_file(self, path: str, **kwargs) -> str:
104
  """
105
  translate from a file
106
  @param path: path to file
 
108
  """
109
  return self._translate_file(path, **kwargs)
110
 
111
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
112
  """
113
  translate a batch of texts
114
  @param batch: list of texts to translate
deep_translator/mymemory.py CHANGED
@@ -1,34 +1,48 @@
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
  """
33
  function that uses the mymemory translator to translate a text
34
  @param text: desired text to translate
@@ -36,20 +50,20 @@ class MyMemoryTranslator(BaseTranslator):
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:
55
  raise TooManyRequests()
@@ -60,27 +74,27 @@ class MyMemoryTranslator(BaseTranslator):
60
  if not data:
61
  TranslationNotFound(text)
62
 
63
- translation = data.get('responseData').get('translatedText')
64
  if translation:
65
  return translation
66
 
67
  elif not translation:
68
- all_matches = data.get('matches')
69
- matches = (match['translation'] for match in all_matches)
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
76
- @param path: path to the target file
77
- @type path: str
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
  """
85
  translate a list of texts
86
  @param batch: list of texts you want to translate
 
1
  """
2
  mymemory translator API
3
  """
4
+ from typing import List, Optional, Union
5
+
 
 
 
 
 
6
  import requests
7
 
8
+ from deep_translator.base import BaseTranslator
9
+ from deep_translator.constants import BASE_URLS
10
+ from deep_translator.exceptions import (
11
+ RequestError,
12
+ TooManyRequests,
13
+ TranslationNotFound,
14
+ )
15
+ from deep_translator.validate import is_empty, is_input_valid
16
+
17
 
18
  class MyMemoryTranslator(BaseTranslator):
19
  """
20
  class that uses the mymemory translator to translate texts
21
  """
22
+
23
+ def __init__(
24
+ self,
25
+ source: str = "auto",
26
+ target: str = "en",
27
+ proxies: Optional[dict] = None,
28
+ **kwargs,
29
+ ):
30
  """
31
  @param source: source language to translate from
32
  @param target: target language to translate to
33
  """
34
  self.proxies = proxies
35
+ self.email = kwargs.get("email", None)
36
+ super().__init__(
37
+ base_url=BASE_URLS.get("MYMEMORY"),
38
+ source=source,
39
+ target=target,
40
+ payload_key="q",
41
+ )
42
 
43
+ def translate(
44
+ self, text: str, return_all: bool = False, **kwargs
45
+ ) -> Union[str, List[str]]:
46
  """
47
  function that uses the mymemory translator to translate a text
48
  @param text: desired text to translate
 
50
  @param return_all: set to True to return all synonym/similars of the translated text
51
  @return: str or list
52
  """
53
+ if is_input_valid(text, max_chars=500):
54
  text = text.strip()
55
  if self._same_source_target() or is_empty(text):
56
  return text
57
 
58
+ self._url_params["langpair"] = f"{self._source}|{self._target}"
59
  if self.payload_key:
60
  self._url_params[self.payload_key] = text
61
  if self.email:
62
+ self._url_params["de"] = self.email
63
 
64
+ response = requests.get(
65
+ self._base_url, params=self._url_params, proxies=self.proxies
66
+ )
67
 
68
  if response.status_code == 429:
69
  raise TooManyRequests()
 
74
  if not data:
75
  TranslationNotFound(text)
76
 
77
+ translation = data.get("responseData").get("translatedText")
78
  if translation:
79
  return translation
80
 
81
  elif not translation:
82
+ all_matches = data.get("matches")
83
+ matches = (match["translation"] for match in all_matches)
84
  next_match = next(matches)
85
  return next_match if not return_all else list(all_matches)
86
 
87
+ def translate_file(self, path: str, **kwargs) -> str:
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
  return self._translate_file(path, **kwargs)
96
 
97
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
98
  """
99
  translate a list of texts
100
  @param batch: list of texts you want to translate
deep_translator/papago.py CHANGED
@@ -2,12 +2,14 @@
2
  google translator API
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):
@@ -15,14 +17,22 @@ class PapagoTranslator(BaseTranslator):
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
  """
20
  @param source: source language to translate from
21
  @param target: target language to translate to
22
  """
23
  if not client_id or not secret_key:
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
@@ -31,31 +41,27 @@ class PapagoTranslator(BaseTranslator):
31
  source=source,
32
  target=target,
33
  languages=PAPAGO_LANGUAGE_TO_CODE,
34
- **kwargs
35
  )
36
 
37
- def translate(self, text, **kwargs):
38
  """
39
  function that uses google translate to translate a text
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)
@@ -67,7 +73,7 @@ class PapagoTranslator(BaseTranslator):
67
  translated_text = result.get("translatedText")
68
  return translated_text
69
 
70
- def translate_file(self, path, **kwargs):
71
  """
72
  translate directly from file
73
  @param path: path to the target file
@@ -77,7 +83,7 @@ class PapagoTranslator(BaseTranslator):
77
  """
78
  return self._translate_file(path, **kwargs)
79
 
80
- def translate_batch(self, batch=None, **kwargs):
81
  """
82
  translate a list of texts
83
  @param batch: list of texts you want to translate
 
2
  google translator API
3
  """
4
  import json
5
+ from typing import List, Optional
6
+
 
7
  import requests
8
 
9
+ from deep_translator.base import BaseTranslator
10
+ from deep_translator.constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
11
+ from deep_translator.exceptions import TranslationNotFound
12
+ from deep_translator.validate import is_input_valid
13
 
14
 
15
  class PapagoTranslator(BaseTranslator):
 
17
  class that wraps functions, which use google translate under the hood to translate text(s)
18
  """
19
 
20
+ def __init__(
21
+ self,
22
+ client_id: Optional[str] = None,
23
+ secret_key: Optional[str] = None,
24
+ source: str = "auto",
25
+ target: str = "en",
26
+ **kwargs,
27
+ ):
28
  """
29
  @param source: source language to translate from
30
  @param target: target language to translate to
31
  """
32
  if not client_id or not secret_key:
33
  raise Exception(
34
+ "Please pass your client id and secret key! visit the papago website for more infos"
35
+ )
36
 
37
  self.client_id = client_id
38
  self.secret_key = secret_key
 
41
  source=source,
42
  target=target,
43
  languages=PAPAGO_LANGUAGE_TO_CODE,
44
+ **kwargs,
45
  )
46
 
47
+ def translate(self, text: str, **kwargs) -> str:
48
  """
49
  function that uses google translate to translate a text
50
  @param text: desired text to translate
51
  @return: str: translated text
52
  """
53
+ if is_input_valid(text):
54
+ payload = {"source": self._source, "target": self._target, "text": text}
 
 
 
 
55
  headers = {
56
+ "X-Naver-Client-Id": self.client_id,
57
+ "X-Naver-Client-Secret": self.secret_key,
58
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
59
  }
60
+ response = requests.post(self._base_url, headers=headers, data=payload)
 
61
  if response.status_code != 200:
62
  raise Exception(
63
+ f"Translation error! -> status code: {response.status_code}"
64
+ )
65
  res_body = json.loads(response.text)
66
  if "message" not in res_body:
67
  raise TranslationNotFound(text)
 
73
  translated_text = result.get("translatedText")
74
  return translated_text
75
 
76
+ def translate_file(self, path: str, **kwargs) -> str:
77
  """
78
  translate directly from file
79
  @param path: path to the target file
 
83
  """
84
  return self._translate_file(path, **kwargs)
85
 
86
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
87
  """
88
  translate a list of texts
89
  @param batch: list of texts you want to translate
deep_translator/pons.py CHANGED
@@ -1,43 +1,51 @@
1
  """
2
  pons translator API
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
 
19
  class PonsTranslator(BaseTranslator):
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
43
  @param word: word to translate
@@ -46,10 +54,10 @@ class PonsTranslator(BaseTranslator):
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
 
@@ -59,7 +67,7 @@ class PonsTranslator(BaseTranslator):
59
  if response.status_code != 200:
60
  raise RequestError()
61
 
62
- soup = BeautifulSoup(response.text, 'html.parser')
63
  elements = soup.findAll(self._element_tag, self._element_query)
64
 
65
  if not elements:
@@ -67,9 +75,9 @@ class PonsTranslator(BaseTranslator):
67
 
68
  filtered_elements = []
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:
@@ -82,7 +90,7 @@ class PonsTranslator(BaseTranslator):
82
 
83
  return word_list if return_all else word_list[0]
84
 
85
- def translate_words(self, words, **kwargs):
86
  """
87
  translate a batch of words together by providing them in a list
88
  @param words: list of words you want to translate
@@ -96,4 +104,3 @@ class PonsTranslator(BaseTranslator):
96
  for word in words:
97
  translated_words.append(self.translate(word=word, **kwargs))
98
  return translated_words
99
-
 
1
  """
2
  pons translator API
3
  """
4
+ from typing import List, Optional, Union
 
5
 
6
+ import requests
7
+ from bs4 import BeautifulSoup
 
 
 
 
 
 
 
8
  from requests.utils import requote_uri
9
 
10
+ from deep_translator.base import BaseTranslator
11
+ from deep_translator.constants import BASE_URLS, PONS_CODES_TO_LANGUAGES
12
+ from deep_translator.exceptions import (
13
+ ElementNotFoundInGetRequest,
14
+ NotValidPayload,
15
+ RequestError,
16
+ TooManyRequests,
17
+ TranslationNotFound,
18
+ )
19
+ from deep_translator.validate import is_empty, is_input_valid
20
+
21
 
22
  class PonsTranslator(BaseTranslator):
23
  """
24
  class that uses PONS translator to translate words
25
  """
26
 
27
+ def __init__(
28
+ self, source: str, target: str = "en", proxies: Optional[dict] = None, **kwargs
29
+ ):
30
  """
31
  @param source: source language to translate from
32
  @param target: target language to translate to
33
  """
34
  self.proxies = proxies
35
+ super().__init__(
36
+ base_url=BASE_URLS.get("PONS"),
37
+ languages=PONS_CODES_TO_LANGUAGES,
38
+ source=source,
39
+ target=target,
40
+ payload_key=None,
41
+ element_tag="div",
42
+ element_query={"class": "target"},
43
+ **kwargs,
44
+ )
45
+
46
+ def translate(
47
+ self, word: str, return_all: bool = False, **kwargs
48
+ ) -> Union[str, List[str]]:
49
  """
50
  function that uses PONS to translate a word
51
  @param word: word to translate
 
54
  @type return_all: bool
55
  @return: str: translated word
56
  """
57
+ if is_input_valid(word, max_chars=50):
58
  if self._same_source_target() or is_empty(word):
59
  return word
60
+ url = f"{self._base_url}{self._source}-{self._target}/{word}"
61
  url = requote_uri(url)
62
  response = requests.get(url, proxies=self.proxies)
63
 
 
67
  if response.status_code != 200:
68
  raise RequestError()
69
 
70
+ soup = BeautifulSoup(response.text, "html.parser")
71
  elements = soup.findAll(self._element_tag, self._element_query)
72
 
73
  if not elements:
 
75
 
76
  filtered_elements = []
77
  for el in elements:
78
+ temp = ""
79
+ for e in el.findAll("a"):
80
+ temp += e.get_text() + " "
81
  filtered_elements.append(temp)
82
 
83
  if not filtered_elements:
 
90
 
91
  return word_list if return_all else word_list[0]
92
 
93
+ def translate_words(self, words: List[str], **kwargs) -> List[str]:
94
  """
95
  translate a batch of words together by providing them in a list
96
  @param words: list of words you want to translate
 
104
  for word in words:
105
  translated_words.append(self.translate(word=word, **kwargs))
106
  return translated_words
 
deep_translator/qcri.py CHANGED
@@ -1,8 +1,10 @@
 
1
 
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):
@@ -10,7 +12,13 @@ class QcriTranslator(BaseTranslator):
10
  class that wraps functions, which use the QRCI translator under the hood to translate word(s)
11
  """
12
 
13
- def __init__(self, api_key=None, source="en", target="en", **kwargs):
 
 
 
 
 
 
14
  """
15
  @param api_key: your qrci api key. Get one for free here https://mt.qcri.org/api/v1/ref
16
  """
@@ -24,23 +32,25 @@ class QcriTranslator(BaseTranslator):
24
  "translate": "translate",
25
  }
26
 
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
@@ -57,12 +67,12 @@ class QcriTranslator(BaseTranslator):
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:
68
  response = self._get("translate", params=params, return_text=False)
@@ -79,10 +89,10 @@ class QcriTranslator(BaseTranslator):
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
 
1
+ from typing import List, Optional
2
 
3
  import requests
4
+
5
+ from deep_translator.base import BaseTranslator
6
+ from deep_translator.constants import BASE_URLS, QCRI_LANGUAGE_TO_CODE
7
+ from deep_translator.exceptions import ServerException, TranslationNotFound
8
 
9
 
10
  class QcriTranslator(BaseTranslator):
 
12
  class that wraps functions, which use the QRCI translator under the hood to translate word(s)
13
  """
14
 
15
+ def __init__(
16
+ self,
17
+ api_key: Optional[str] = None,
18
+ source: str = "en",
19
+ target: str = "en",
20
+ **kwargs,
21
+ ):
22
  """
23
  @param api_key: your qrci api key. Get one for free here https://mt.qcri.org/api/v1/ref
24
  """
 
32
  "translate": "translate",
33
  }
34
 
35
+ self.params = {"key": self.api_key}
 
 
36
  super().__init__(
37
  base_url=BASE_URLS.get("QcriTranslator"),
38
  source=source,
39
  target=target,
40
  languages=QCRI_LANGUAGE_TO_CODE,
41
+ **kwargs,
42
  )
43
 
44
+ def _get(
45
+ self, endpoint: str, params: Optional[dict] = None, return_text: bool = True
46
+ ):
47
  if not params:
48
  params = self.params
49
  try:
50
+ res = requests.get(
51
+ self._base_url.format(endpoint=self.api_endpoints[endpoint]),
52
+ params=params,
53
+ )
54
  return res.text if return_text else res
55
  except Exception as e:
56
  raise e
 
67
  def domains(self):
68
  return self.get_domains()
69
 
70
+ def translate(self, text: str, **kwargs) -> str:
71
  params = {
72
  "key": self.api_key,
73
+ "langpair": f"{self._source}-{self._target}",
74
  "domain": kwargs["domain"],
75
+ "text": text,
76
  }
77
  try:
78
  response = self._get("translate", params=params, return_text=False)
 
89
  raise TranslationNotFound(text)
90
  return translation
91
 
92
+ def translate_file(self, path: str, **kwargs) -> str:
93
  return self._translate_file(path, **kwargs)
94
 
95
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
96
  """
97
  translate a batch of texts
98
  @domain: domain
deep_translator/validate.py CHANGED
@@ -1,13 +1,11 @@
 
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
 
1
+ from deep_translator.exceptions import NotValidLength, NotValidPayload
2
 
 
 
3
 
4
+ def is_empty(text: str) -> bool:
 
5
  return text == ""
6
 
7
 
8
+ def is_input_valid(text: str, min_chars: int = 0, max_chars: int = 5000) -> bool:
9
  """
10
  validate the target text to translate
11
  @param min_chars: min characters
deep_translator/yandex.py CHANGED
@@ -1,11 +1,19 @@
1
  """
2
  Yandex translator API
3
  """
 
 
4
  import requests
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):
@@ -13,7 +21,13 @@ class YandexTranslator(BaseTranslator):
13
  class that wraps functions, which use the yandex translator under the hood to translate word(s)
14
  """
15
 
16
- def __init__(self, api_key=None, source="en", target="de", **kwargs):
 
 
 
 
 
 
17
  """
18
  @param api_key: your yandex api key
19
  """
@@ -27,10 +41,7 @@ class YandexTranslator(BaseTranslator):
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):
@@ -41,14 +52,12 @@ class YandexTranslator(BaseTranslator):
41
  return self.get_supported_languages()
42
 
43
  @property
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(
51
- url, params={"key": self.api_key}, proxies=proxies)
52
  except requests.exceptions.ConnectionError:
53
  raise ServerException(503)
54
  else:
@@ -58,7 +67,7 @@ class YandexTranslator(BaseTranslator):
58
  raise ServerException(response.status_code)
59
  return data.get("dirs")
60
 
61
- def detect(self, text, proxies=None):
62
  response = None
63
  params = {
64
  "text": text,
@@ -66,8 +75,7 @@ class YandexTranslator(BaseTranslator):
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
 
73
  except RequestError:
@@ -78,43 +86,46 @@ class YandexTranslator(BaseTranslator):
78
  raise ServerException(response.status_code)
79
  else:
80
  response = response.json()
81
- language = response['lang']
82
- status_code = response['code']
83
  if status_code != 200:
84
  raise RequestError()
85
  elif not language:
86
  raise ServerException(501)
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
  """
119
  translate from a file
120
  @param path: path to file
@@ -122,11 +133,10 @@ class YandexTranslator(BaseTranslator):
122
  """
123
  return self._translate_file(path, **kwargs)
124
 
125
- def translate_batch(self, batch, **kwargs):
126
  """
127
  translate a batch of texts
128
  @param batch: list of texts to translate
129
  @return: list of translations
130
  """
131
  return self._translate_batch(batch, **kwargs)
132
-
 
1
  """
2
  Yandex translator API
3
  """
4
+ from typing import List, Optional
5
+
6
  import requests
7
+
8
+ from deep_translator.base import BaseTranslator
9
+ from deep_translator.constants import BASE_URLS
10
+ from deep_translator.exceptions import (
11
+ RequestError,
12
+ ServerException,
13
+ TooManyRequests,
14
+ TranslationNotFound,
15
+ )
16
+ from deep_translator.validate import is_input_valid
17
 
18
 
19
  class YandexTranslator(BaseTranslator):
 
21
  class that wraps functions, which use the yandex translator under the hood to translate word(s)
22
  """
23
 
24
+ def __init__(
25
+ self,
26
+ api_key: Optional[str] = None,
27
+ source: str = "en",
28
+ target: str = "de",
29
+ **kwargs
30
+ ):
31
  """
32
  @param api_key: your yandex api key
33
  """
 
41
  "translate": "translate",
42
  }
43
  super().__init__(
44
+ base_url=BASE_URLS.get("YANDEX"), source=source, target=target, **kwargs
 
 
 
45
  )
46
 
47
  def _get_supported_languages(self):
 
52
  return self.get_supported_languages()
53
 
54
  @property
55
+ def dirs(self, proxies: Optional[dict] = None):
56
 
57
  try:
58
+ url = self._base_url.format(version=self.api_version, endpoint="getLangs")
 
59
  print("url: ", url)
60
+ response = requests.get(url, params={"key": self.api_key}, proxies=proxies)
 
61
  except requests.exceptions.ConnectionError:
62
  raise ServerException(503)
63
  else:
 
67
  raise ServerException(response.status_code)
68
  return data.get("dirs")
69
 
70
+ def detect(self, text: str, proxies: Optional[dict] = None):
71
  response = None
72
  params = {
73
  "text": text,
 
75
  "key": self.api_key,
76
  }
77
  try:
78
+ url = self._base_url.format(version=self.api_version, endpoint="detect")
 
79
  response = requests.post(url, data=params, proxies=proxies)
80
 
81
  except RequestError:
 
86
  raise ServerException(response.status_code)
87
  else:
88
  response = response.json()
89
+ language = response["lang"]
90
+ status_code = response["code"]
91
  if status_code != 200:
92
  raise RequestError()
93
  elif not language:
94
  raise ServerException(501)
95
  return language
96
 
97
+ def translate(self, text: str, proxies: Optional[dict] = None, **kwargs) -> str:
98
+ if is_input_valid(text):
99
  params = {
100
  "text": text,
101
  "format": "plain",
102
+ "lang": self._target
103
+ if self._source == "auto"
104
+ else "{}-{}".format(self._source, self._target),
105
+ "key": self.api_key,
106
  }
107
  try:
108
  url = self._base_url.format(
109
+ version=self.api_version, endpoint="translate"
110
+ )
111
  response = requests.post(url, data=params, proxies=proxies)
112
  except ConnectionError:
113
  raise ServerException(503)
114
  else:
115
  response = response.json()
116
 
117
+ if response["code"] == 429:
118
  raise TooManyRequests()
119
 
120
+ if response["code"] != 200:
121
+ raise ServerException(response["code"])
122
 
123
+ if not response["text"]:
124
  raise TranslationNotFound()
125
 
126
+ return response["text"]
127
 
128
+ def translate_file(self, path: str, **kwargs) -> str:
129
  """
130
  translate from a file
131
  @param path: path to file
 
133
  """
134
  return self._translate_file(path, **kwargs)
135
 
136
+ def translate_batch(self, batch: List[str], **kwargs) -> List[str]:
137
  """
138
  translate a batch of texts
139
  @param batch: list of texts to translate
140
  @return: list of translations
141
  """
142
  return self._translate_batch(batch, **kwargs)
 
docs/conf.py CHANGED
@@ -19,6 +19,7 @@
19
  #
20
  import os
21
  import sys
 
22
  sys.path.insert(0, os.path.abspath('..'))
23
 
24
  # import deep_translator
@@ -58,6 +59,7 @@ author = "Nidhal Baccouri"
58
  #
59
  # The short X.Y version.
60
  import toml
 
61
  with open("../pyproject.toml", "r") as f:
62
  tom = toml.load(f)
63
  version = tom['tool']['poetry']['version']
 
19
  #
20
  import os
21
  import sys
22
+
23
  sys.path.insert(0, os.path.abspath('..'))
24
 
25
  # import deep_translator
 
59
  #
60
  # The short X.Y version.
61
  import toml
62
+
63
  with open("../pyproject.toml", "r") as f:
64
  tom = toml.load(f)
65
  version = tom['tool']['poetry']['version']
examples/linguee.py CHANGED
@@ -1,7 +1,6 @@
1
 
2
  from deep_translator import LingueeTranslator
3
 
4
-
5
  res = LingueeTranslator(source='de', target='en').translate('laufen', return_all=False)
6
 
7
  print(res)
 
1
 
2
  from deep_translator import LingueeTranslator
3
 
 
4
  res = LingueeTranslator(source='de', target='en').translate('laufen', return_all=False)
5
 
6
  print(res)
examples/mymemory.py CHANGED
@@ -1,7 +1,6 @@
1
 
2
  from deep_translator import MyMemoryTranslator
3
 
4
-
5
  res = MyMemoryTranslator(source='ar', target='en').translate('آخُذ اَلْباص.')
6
 
7
  print(res)
 
1
 
2
  from deep_translator import MyMemoryTranslator
3
 
 
4
  res = MyMemoryTranslator(source='ar', target='en').translate('آخُذ اَلْباص.')
5
 
6
  print(res)
examples/pons.py CHANGED
@@ -1,7 +1,6 @@
1
 
2
  from deep_translator import PonsTranslator
3
 
4
-
5
  res = PonsTranslator(source='en', target='de').translate('good', return_all=False)
6
 
7
  print(res)
 
1
 
2
  from deep_translator import PonsTranslator
3
 
 
4
  res = PonsTranslator(source='en', target='de').translate('good', return_all=False)
5
 
6
  print(res)
examples/trans.py CHANGED
@@ -1,5 +1,4 @@
1
- from deep_translator import GoogleTranslator, PonsTranslator, LingueeTranslator
2
-
3
 
4
  # examples using google translate
5
 
 
1
+ from deep_translator import GoogleTranslator, LingueeTranslator, PonsTranslator
 
2
 
3
  # examples using google translate
4
 
poetry.lock CHANGED
@@ -54,6 +54,29 @@ soupsieve = ">1.2"
54
  html5lib = ["html5lib"]
55
  lxml = ["lxml"]
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  [[package]]
58
  name = "bleach"
59
  version = "4.1.0"
@@ -97,6 +120,18 @@ python-versions = ">=3.5.0"
97
  [package.extras]
98
  unicode_backport = ["unicodedata2"]
99
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  [[package]]
101
  name = "colorama"
102
  version = "0.4.4"
@@ -184,6 +219,20 @@ category = "dev"
184
  optional = false
185
  python-versions = "*"
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  [[package]]
188
  name = "jeepney"
189
  version = "0.7.1"
@@ -236,6 +285,14 @@ category = "dev"
236
  optional = false
237
  python-versions = ">=3.6"
238
 
 
 
 
 
 
 
 
 
239
  [[package]]
240
  name = "packaging"
241
  version = "21.3"
@@ -247,6 +304,14 @@ python-versions = ">=3.6"
247
  [package.dependencies]
248
  pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
249
 
 
 
 
 
 
 
 
 
250
  [[package]]
251
  name = "pkginfo"
252
  version = "1.8.2"
@@ -258,6 +323,18 @@ python-versions = "*"
258
  [package.extras]
259
  testing = ["coverage", "nose"]
260
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  [[package]]
262
  name = "pluggy"
263
  version = "1.0.0"
@@ -561,6 +638,14 @@ category = "dev"
561
  optional = false
562
  python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
563
 
 
 
 
 
 
 
 
 
564
  [[package]]
565
  name = "tqdm"
566
  version = "4.62.3"
@@ -597,6 +682,14 @@ rfc3986 = ">=1.4.0"
597
  tqdm = ">=4.14"
598
  urllib3 = ">=1.26.0"
599
 
 
 
 
 
 
 
 
 
600
  [[package]]
601
  name = "typing-extensions"
602
  version = "4.0.1"
@@ -641,7 +734,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
641
  [metadata]
642
  lock-version = "1.1"
643
  python-versions = "^3.7"
644
- content-hash = "2877a59ad1ac817881dcea5583bd7f07310ab5da4301dda5dadbe598b9ec6511"
645
 
646
  [metadata.files]
647
  alabaster = [
@@ -664,6 +757,31 @@ beautifulsoup4 = [
664
  {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
665
  {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
666
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
667
  bleach = [
668
  {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"},
669
  {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"},
@@ -728,6 +846,10 @@ charset-normalizer = [
728
  {file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"},
729
  {file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"},
730
  ]
 
 
 
 
731
  colorama = [
732
  {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
733
  {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
@@ -828,6 +950,10 @@ iniconfig = [
828
  {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
829
  {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
830
  ]
 
 
 
 
831
  jeepney = [
832
  {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"},
833
  {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"},
@@ -876,14 +1002,26 @@ markupsafe = [
876
  {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
877
  {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
878
  ]
 
 
 
 
879
  packaging = [
880
  {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
881
  {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
882
  ]
 
 
 
 
883
  pkginfo = [
884
  {file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"},
885
  {file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"},
886
  ]
 
 
 
 
887
  pluggy = [
888
  {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
889
  {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
@@ -984,6 +1122,10 @@ toml = [
984
  {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
985
  {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
986
  ]
 
 
 
 
987
  tqdm = [
988
  {file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"},
989
  {file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"},
@@ -992,6 +1134,32 @@ twine = [
992
  {file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"},
993
  {file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"},
994
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
995
  typing-extensions = [
996
  {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
997
  {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
 
54
  html5lib = ["html5lib"]
55
  lxml = ["lxml"]
56
 
57
+ [[package]]
58
+ name = "black"
59
+ version = "22.1.0"
60
+ description = "The uncompromising code formatter."
61
+ category = "dev"
62
+ optional = false
63
+ python-versions = ">=3.6.2"
64
+
65
+ [package.dependencies]
66
+ click = ">=8.0.0"
67
+ mypy-extensions = ">=0.4.3"
68
+ pathspec = ">=0.9.0"
69
+ platformdirs = ">=2"
70
+ tomli = ">=1.1.0"
71
+ typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""}
72
+ typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
73
+
74
+ [package.extras]
75
+ colorama = ["colorama (>=0.4.3)"]
76
+ d = ["aiohttp (>=3.7.4)"]
77
+ jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
78
+ uvloop = ["uvloop (>=0.15.2)"]
79
+
80
  [[package]]
81
  name = "bleach"
82
  version = "4.1.0"
 
120
  [package.extras]
121
  unicode_backport = ["unicodedata2"]
122
 
123
+ [[package]]
124
+ name = "click"
125
+ version = "8.0.4"
126
+ description = "Composable command line interface toolkit"
127
+ category = "dev"
128
+ optional = false
129
+ python-versions = ">=3.6"
130
+
131
+ [package.dependencies]
132
+ colorama = {version = "*", markers = "platform_system == \"Windows\""}
133
+ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
134
+
135
  [[package]]
136
  name = "colorama"
137
  version = "0.4.4"
 
219
  optional = false
220
  python-versions = "*"
221
 
222
+ [[package]]
223
+ name = "isort"
224
+ version = "5.10.1"
225
+ description = "A Python utility / library to sort Python imports."
226
+ category = "dev"
227
+ optional = false
228
+ python-versions = ">=3.6.1,<4.0"
229
+
230
+ [package.extras]
231
+ pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
232
+ requirements_deprecated_finder = ["pipreqs", "pip-api"]
233
+ colors = ["colorama (>=0.4.3,<0.5.0)"]
234
+ plugins = ["setuptools"]
235
+
236
  [[package]]
237
  name = "jeepney"
238
  version = "0.7.1"
 
285
  optional = false
286
  python-versions = ">=3.6"
287
 
288
+ [[package]]
289
+ name = "mypy-extensions"
290
+ version = "0.4.3"
291
+ description = "Experimental type system extensions for programs checked with the mypy typechecker."
292
+ category = "dev"
293
+ optional = false
294
+ python-versions = "*"
295
+
296
  [[package]]
297
  name = "packaging"
298
  version = "21.3"
 
304
  [package.dependencies]
305
  pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
306
 
307
+ [[package]]
308
+ name = "pathspec"
309
+ version = "0.9.0"
310
+ description = "Utility library for gitignore style pattern matching of file paths."
311
+ category = "dev"
312
+ optional = false
313
+ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
314
+
315
  [[package]]
316
  name = "pkginfo"
317
  version = "1.8.2"
 
323
  [package.extras]
324
  testing = ["coverage", "nose"]
325
 
326
+ [[package]]
327
+ name = "platformdirs"
328
+ version = "2.5.1"
329
+ description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
330
+ category = "dev"
331
+ optional = false
332
+ python-versions = ">=3.7"
333
+
334
+ [package.extras]
335
+ docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
336
+ test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
337
+
338
  [[package]]
339
  name = "pluggy"
340
  version = "1.0.0"
 
638
  optional = false
639
  python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
640
 
641
+ [[package]]
642
+ name = "tomli"
643
+ version = "2.0.1"
644
+ description = "A lil' TOML parser"
645
+ category = "dev"
646
+ optional = false
647
+ python-versions = ">=3.7"
648
+
649
  [[package]]
650
  name = "tqdm"
651
  version = "4.62.3"
 
682
  tqdm = ">=4.14"
683
  urllib3 = ">=1.26.0"
684
 
685
+ [[package]]
686
+ name = "typed-ast"
687
+ version = "1.5.2"
688
+ description = "a fork of Python 2 and 3 ast modules with type comment support"
689
+ category = "dev"
690
+ optional = false
691
+ python-versions = ">=3.6"
692
+
693
  [[package]]
694
  name = "typing-extensions"
695
  version = "4.0.1"
 
734
  [metadata]
735
  lock-version = "1.1"
736
  python-versions = "^3.7"
737
+ content-hash = "999f9269962bc8ce6f5ad597f7aa7afc6d5a4382b8cadfd8ffe75cd8ed16a41e"
738
 
739
  [metadata.files]
740
  alabaster = [
 
757
  {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
758
  {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
759
  ]
760
+ black = [
761
+ {file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"},
762
+ {file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"},
763
+ {file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"},
764
+ {file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"},
765
+ {file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"},
766
+ {file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"},
767
+ {file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"},
768
+ {file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"},
769
+ {file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"},
770
+ {file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"},
771
+ {file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"},
772
+ {file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"},
773
+ {file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"},
774
+ {file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"},
775
+ {file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"},
776
+ {file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"},
777
+ {file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"},
778
+ {file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"},
779
+ {file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"},
780
+ {file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"},
781
+ {file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"},
782
+ {file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"},
783
+ {file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"},
784
+ ]
785
  bleach = [
786
  {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"},
787
  {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"},
 
846
  {file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"},
847
  {file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"},
848
  ]
849
+ click = [
850
+ {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"},
851
+ {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"},
852
+ ]
853
  colorama = [
854
  {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
855
  {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
 
950
  {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
951
  {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
952
  ]
953
+ isort = [
954
+ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
955
+ {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
956
+ ]
957
  jeepney = [
958
  {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"},
959
  {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"},
 
1002
  {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
1003
  {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
1004
  ]
1005
+ mypy-extensions = [
1006
+ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
1007
+ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
1008
+ ]
1009
  packaging = [
1010
  {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
1011
  {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
1012
  ]
1013
+ pathspec = [
1014
+ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
1015
+ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
1016
+ ]
1017
  pkginfo = [
1018
  {file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"},
1019
  {file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"},
1020
  ]
1021
+ platformdirs = [
1022
+ {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"},
1023
+ {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
1024
+ ]
1025
  pluggy = [
1026
  {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
1027
  {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
 
1122
  {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
1123
  {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
1124
  ]
1125
+ tomli = [
1126
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
1127
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
1128
+ ]
1129
  tqdm = [
1130
  {file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"},
1131
  {file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"},
 
1134
  {file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"},
1135
  {file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"},
1136
  ]
1137
+ typed-ast = [
1138
+ {file = "typed_ast-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:183b183b7771a508395d2cbffd6db67d6ad52958a5fdc99f450d954003900266"},
1139
+ {file = "typed_ast-1.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:676d051b1da67a852c0447621fdd11c4e104827417bf216092ec3e286f7da596"},
1140
+ {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc2542e83ac8399752bc16e0b35e038bdb659ba237f4222616b4e83fb9654985"},
1141
+ {file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74cac86cc586db8dfda0ce65d8bcd2bf17b58668dfcc3652762f3ef0e6677e76"},
1142
+ {file = "typed_ast-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:18fe320f354d6f9ad3147859b6e16649a0781425268c4dde596093177660e71a"},
1143
+ {file = "typed_ast-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:31d8c6b2df19a777bc8826770b872a45a1f30cfefcfd729491baa5237faae837"},
1144
+ {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:963a0ccc9a4188524e6e6d39b12c9ca24cc2d45a71cfdd04a26d883c922b4b78"},
1145
+ {file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb77764ea470f14fcbb89d51bc6bbf5e7623446ac4ed06cbd9ca9495b62e36e"},
1146
+ {file = "typed_ast-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:294a6903a4d087db805a7656989f613371915fc45c8cc0ddc5c5a0a8ad9bea4d"},
1147
+ {file = "typed_ast-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26a432dc219c6b6f38be20a958cbe1abffcc5492821d7e27f08606ef99e0dffd"},
1148
+ {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7407cfcad702f0b6c0e0f3e7ab876cd1d2c13b14ce770e412c0c4b9728a0f88"},
1149
+ {file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f30ddd110634c2d7534b2d4e0e22967e88366b0d356b24de87419cc4410c41b7"},
1150
+ {file = "typed_ast-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8c08d6625bb258179b6e512f55ad20f9dfef019bbfbe3095247401e053a3ea30"},
1151
+ {file = "typed_ast-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:90904d889ab8e81a956f2c0935a523cc4e077c7847a836abee832f868d5c26a4"},
1152
+ {file = "typed_ast-1.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bbebc31bf11762b63bf61aaae232becb41c5bf6b3461b80a4df7e791fabb3aca"},
1153
+ {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29dd9a3a9d259c9fa19d19738d021632d673f6ed9b35a739f48e5f807f264fb"},
1154
+ {file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:58ae097a325e9bb7a684572d20eb3e1809802c5c9ec7108e85da1eb6c1a3331b"},
1155
+ {file = "typed_ast-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:da0a98d458010bf4fe535f2d1e367a2e2060e105978873c04c04212fb20543f7"},
1156
+ {file = "typed_ast-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:33b4a19ddc9fc551ebabca9765d54d04600c4a50eda13893dadf67ed81d9a098"},
1157
+ {file = "typed_ast-1.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1098df9a0592dd4c8c0ccfc2e98931278a6c6c53cb3a3e2cf7e9ee3b06153344"},
1158
+ {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c47c3b43fe3a39ddf8de1d40dbbfca60ac8530a36c9b198ea5b9efac75c09e"},
1159
+ {file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f290617f74a610849bd8f5514e34ae3d09eafd521dceaa6cf68b3f4414266d4e"},
1160
+ {file = "typed_ast-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:df05aa5b241e2e8045f5f4367a9f6187b09c4cdf8578bb219861c4e27c443db5"},
1161
+ {file = "typed_ast-1.5.2.tar.gz", hash = "sha256:525a2d4088e70a9f75b08b3f87a51acc9cde640e19cc523c7e41aa355564ae27"},
1162
+ ]
1163
  typing-extensions = [
1164
  {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
1165
  {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
pyproject.toml CHANGED
@@ -40,6 +40,8 @@ twine = "^3.4.2"
40
  pytest = "^6.2.4"
41
  pytest-runner = "^5.3.1"
42
  toml = "^0.10.2"
 
 
43
 
44
  [build-system]
45
  requires = ["poetry-core>=1.0.0"]
 
40
  pytest = "^6.2.4"
41
  pytest-runner = "^5.3.1"
42
  toml = "^0.10.2"
43
+ black = "^22.1.0"
44
+ isort = "^5.10.1"
45
 
46
  [build-system]
47
  requires = ["poetry-core>=1.0.0"]
tests/test_cli.py CHANGED
@@ -2,22 +2,22 @@
2
 
3
  """Tests for the CLI interface."""
4
 
5
- from deep_translator.cli import CLI
6
- import pytest
7
  import sys
8
 
 
 
 
 
9
 
10
  @pytest.fixture
11
  def mock_args():
12
- sys.argv[1:] = ['--source', 'en', '--target', 'de', '--text', 'hello']
13
  return CLI(sys.argv[1:]).parse_args()
14
 
15
 
16
  def test_source(mock_args):
17
- assert mock_args.source == 'en'
18
 
19
 
20
  def test_target(mock_args):
21
- assert mock_args.target == 'de'
22
-
23
-
 
2
 
3
  """Tests for the CLI interface."""
4
 
 
 
5
  import sys
6
 
7
+ import pytest
8
+
9
+ from deep_translator.cli import CLI
10
+
11
 
12
  @pytest.fixture
13
  def mock_args():
14
+ sys.argv[1:] = ["--source", "en", "--target", "de", "--text", "hello"]
15
  return CLI(sys.argv[1:]).parse_args()
16
 
17
 
18
  def test_source(mock_args):
19
+ assert mock_args.source == "en"
20
 
21
 
22
  def test_target(mock_args):
23
+ assert mock_args.target == "de"
 
 
tests/test_data.py CHANGED
@@ -1,4 +1,4 @@
1
- test_text_standard = 'Hello world.'
2
 
3
  TRANSLATED_RESULTS = {
4
  "afrikaans": "Hello Wêreld.",
@@ -108,5 +108,5 @@ TRANSLATED_RESULTS = {
108
  "xhosa": "Molo Lizwe.",
109
  "yiddish": "העלא וועלט.",
110
  "yoruba": "Mo ki O Ile Aiye.",
111
- "zulu": "Sawubona Mhlaba."
112
  }
 
1
+ test_text_standard = "Hello world."
2
 
3
  TRANSLATED_RESULTS = {
4
  "afrikaans": "Hello Wêreld.",
 
108
  "xhosa": "Molo Lizwe.",
109
  "yiddish": "העלא וועלט.",
110
  "yoruba": "Mo ki O Ile Aiye.",
111
+ "zulu": "Sawubona Mhlaba.",
112
  }
tests/test_deepl.py CHANGED
@@ -1,29 +1,31 @@
 
 
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
13
- mock_response.json.return_value = {
14
- "translations": [{
15
- "text": "hola"
16
- }]
17
- }
18
  mock_requests.get.return_value = mock_response
19
- translation = translator.translate('hello')
20
- assert translation == 'hola'
21
 
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):
29
- translator.translate('Hello')
 
1
+ from unittest.mock import Mock, patch
2
+
3
  import pytest
4
+
5
  from deep_translator.deepl import DeeplTranslator
6
  from deep_translator.exceptions import AuthorizationException
7
 
8
 
9
+ @patch("deep_translator.deepl.requests")
10
  def test_simple_translation(mock_requests):
11
+ translator = DeeplTranslator(
12
+ api_key="imagine-this-is-an-valid-api-key", source="en", target="es"
13
+ )
14
  # Set the request response mock.
15
  mock_response = Mock()
16
  mock_response.status_code = 200
17
+ mock_response.json.return_value = {"translations": [{"text": "hola"}]}
 
 
 
 
18
  mock_requests.get.return_value = mock_response
19
+ translation = translator.translate("hello")
20
+ assert translation == "hola"
21
 
22
 
23
+ @patch("deep_translator.deepl.requests.get")
24
  def test_wrong_api_key(mock_requests):
25
+ translator = DeeplTranslator(
26
+ api_key="this-is-a-wrong-api-key!", source="en", target="es"
27
+ )
28
  # Set the response status_code only.
29
  mock_requests.return_value = Mock(status_code=403)
30
  with pytest.raises(AuthorizationException):
31
+ translator.translate("Hello")
tests/test_google.py CHANGED
@@ -3,8 +3,9 @@
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
@@ -12,16 +13,16 @@ 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
@@ -47,9 +48,9 @@ def test_empty_text(google_translator):
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)
@@ -61,8 +62,8 @@ def test_payload(google_translator):
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'
 
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
+
7
+ from deep_translator import GoogleTranslator, exceptions
8
+ from deep_translator.constants import GOOGLE_LANGUAGES_TO_CODES
9
 
10
 
11
  @pytest.fixture
 
13
  """Sample pytest fixture.
14
  See more at: http://doc.pytest.org/en/latest/fixture.html
15
  """
16
+ return GoogleTranslator(target="en")
17
 
18
 
19
  def test_content(google_translator):
20
  """Sample pytest test function with the pytest fixture as an argument."""
21
+ assert google_translator.translate(text="좋은") == "good"
22
 
23
 
24
  def test_abbreviations_and_languages_mapping():
25
+ for abb, lang in GOOGLE_LANGUAGES_TO_CODES.items():
26
  g1 = GoogleTranslator(abb)
27
  g2 = GoogleTranslator(lang)
28
  assert g1._source == g2._source
 
48
  def test_payload(google_translator):
49
 
50
  with pytest.raises(exceptions.NotValidPayload):
51
+ google_translator.translate(text="1234")
52
+ google_translator.translate(text="{}")
53
+ google_translator.translate(text="%@")
54
 
55
  with pytest.raises(exceptions.NotValidPayload):
56
  google_translator.translate(text=123)
 
62
  google_translator.translate(text=[])
63
 
64
  with pytest.raises(exceptions.NotValidLength):
65
+ google_translator.translate("a" * 5001)
66
 
67
 
68
  def test_one_character_words():
69
+ assert GoogleTranslator(source="es", target="en").translate("o") == "or"
tests/test_libre.py CHANGED
@@ -3,30 +3,31 @@
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
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
 
 
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
+
7
+ from deep_translator import LibreTranslator, exceptions
8
+ from deep_translator.constants import LIBRE_LANGUAGES_TO_CODES
9
 
10
 
11
  @pytest.fixture
12
  def libre():
13
+ return LibreTranslator(source="en", target="fr", api_key="some_key")
14
 
15
 
16
  def test_inputs():
17
  with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
18
+ LibreTranslator(source="", target="", api_key="some_key")
19
 
20
  with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
21
+ LibreTranslator(source="auto", target="", api_key="some_key")
22
 
23
  with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
24
+ LibreTranslator(source="", target="en", api_key="some_key")
25
 
26
 
27
  def test_abbreviations_and_languages_mapping():
28
+ for abb, lang in LIBRE_LANGUAGES_TO_CODES.items():
29
+ l1 = LibreTranslator(source=abb, api_key="some_key")
30
+ l2 = LibreTranslator(source=lang, api_key="some_key")
31
  assert l1._source == l2._source
32
 
33
 
tests/test_linguee.py CHANGED
@@ -3,19 +3,20 @@
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
- from deep_translator import exceptions, LingueeTranslator
 
7
 
8
 
9
  @pytest.fixture
10
  def linguee():
11
- return LingueeTranslator(source="english", target='german')
12
 
13
 
14
  def test_content(linguee):
15
  """Sample pytest test function with the pytest fixture as an argument."""
16
  # from bs4 import BeautifulSoup
17
  # assert 'GitHub' in BeautifulSoup(response.content).title.string
18
- assert linguee.translate(word='good') is not None
19
 
20
 
21
  def test_inputs():
@@ -46,4 +47,4 @@ def test_payload(linguee):
46
  linguee.translate([])
47
 
48
  with pytest.raises(exceptions.NotValidLength):
49
- linguee.translate("a"*51)
 
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
+
7
+ from deep_translator import LingueeTranslator, exceptions
8
 
9
 
10
  @pytest.fixture
11
  def linguee():
12
+ return LingueeTranslator(source="english", target="german")
13
 
14
 
15
  def test_content(linguee):
16
  """Sample pytest test function with the pytest fixture as an argument."""
17
  # from bs4 import BeautifulSoup
18
  # assert 'GitHub' in BeautifulSoup(response.content).title.string
19
+ assert linguee.translate(word="good") is not None
20
 
21
 
22
  def test_inputs():
 
47
  linguee.translate([])
48
 
49
  with pytest.raises(exceptions.NotValidLength):
50
+ linguee.translate("a" * 51)
tests/test_microsoft_trans.py CHANGED
@@ -2,30 +2,40 @@
2
 
3
  """Tests for `deep_translator` package."""
4
 
5
- import pytest
6
  from unittest.mock import patch
 
 
7
  import requests
8
 
9
- from deep_translator import exceptions, MicrosoftTranslator
10
 
11
 
12
  # mocked request.post
13
- @patch.object(requests, 'post')
14
  def test_microsoft_successful_post_mock(mock_request_post):
15
- returned_json = [{'translations': [{'text': 'See you later!', 'to': 'en'}]}]
 
16
  def res():
17
  r = requests.Response()
 
18
  def json_func():
19
  return returned_json
 
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
@@ -36,13 +46,17 @@ APIkey = None
36
 
37
  @pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
38
  def test_microsoft_successful_post_onetarget():
39
- posted = MicrosoftTranslator(api_key=APIkey, target="en").translate("auf wiedersehen!")
 
 
40
  assert isinstance(posted, str)
41
 
42
 
43
  @pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
44
  def test_microsoft_successful_post_twotargets():
45
- posted = MicrosoftTranslator(api_key=APIkey, target=["en", "ru"]).translate("auf wiedersehen!")
 
 
46
  assert isinstance(posted, str)
47
 
48
 
@@ -58,5 +72,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)
 
2
 
3
  """Tests for `deep_translator` package."""
4
 
 
5
  from unittest.mock import patch
6
+
7
+ import pytest
8
  import requests
9
 
10
+ from deep_translator import MicrosoftTranslator, exceptions
11
 
12
 
13
  # mocked request.post
14
+ @patch.object(requests, "post")
15
  def test_microsoft_successful_post_mock(mock_request_post):
16
+ returned_json = [{"translations": [{"text": "See you later!", "to": "en"}]}]
17
+
18
  def res():
19
  r = requests.Response()
20
+
21
  def json_func():
22
  return returned_json
23
+
24
  r.json = json_func
25
  return r
26
+
27
  mock_request_post.return_value = res()
28
+ assert (
29
+ MicrosoftTranslator(api_key="an_api_key", source="de", target="en").translate(
30
+ "auf wiedersehen!"
31
+ )
32
+ == "See you later!"
33
+ )
34
 
35
 
36
  def test_MicrosoftAPIerror():
37
  with pytest.raises(exceptions.MicrosoftAPIerror):
38
+ MicrosoftTranslator(api_key="empty", source="de", target="en").translate("text")
39
 
40
 
41
  # the remaining tests are actual requests to Microsoft API and use an api key
 
46
 
47
  @pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
48
  def test_microsoft_successful_post_onetarget():
49
+ posted = MicrosoftTranslator(api_key=APIkey, target="en").translate(
50
+ "auf wiedersehen!"
51
+ )
52
  assert isinstance(posted, str)
53
 
54
 
55
  @pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
56
  def test_microsoft_successful_post_twotargets():
57
+ posted = MicrosoftTranslator(api_key=APIkey, target=["en", "ru"]).translate(
58
+ "auf wiedersehen!"
59
+ )
60
  assert isinstance(posted, str)
61
 
62
 
 
72
  def test_abbreviations():
73
  m1 = MicrosoftTranslator(api_key=APIkey, source="en", target="fr")
74
  m2 = MicrosoftTranslator(api_key=APIkey, source="English", target="French")
75
+ assert "".join(m1._source) == "".join(m2._source)
76
+ assert "".join(m1._target) == "".join(m2._target)
tests/test_mymemory.py CHANGED
@@ -3,19 +3,20 @@
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
- from deep_translator import exceptions, MyMemoryTranslator
 
7
 
8
 
9
  @pytest.fixture
10
  def mymemory():
11
- return MyMemoryTranslator(source="en", target='fr')
12
 
13
 
14
  def test_content(mymemory):
15
  """Sample pytest test function with the pytest fixture as an argument."""
16
  # from bs4 import BeautifulSoup
17
  # assert 'GitHub' in BeautifulSoup(response.content).title.string
18
- assert mymemory.translate(text='good') is not None
19
 
20
 
21
  def test_inputs():
@@ -46,6 +47,4 @@ def test_payload(mymemory):
46
  mymemory.translate(text=[])
47
 
48
  with pytest.raises(exceptions.NotValidLength):
49
- mymemory.translate(text="a"*501)
50
-
51
-
 
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
+
7
+ from deep_translator import MyMemoryTranslator, exceptions
8
 
9
 
10
  @pytest.fixture
11
  def mymemory():
12
+ return MyMemoryTranslator(source="en", target="fr")
13
 
14
 
15
  def test_content(mymemory):
16
  """Sample pytest test function with the pytest fixture as an argument."""
17
  # from bs4 import BeautifulSoup
18
  # assert 'GitHub' in BeautifulSoup(response.content).title.string
19
+ assert mymemory.translate(text="good") is not None
20
 
21
 
22
  def test_inputs():
 
47
  mymemory.translate(text=[])
48
 
49
  with pytest.raises(exceptions.NotValidLength):
50
+ mymemory.translate(text="a" * 501)
 
 
tests/test_pons.py CHANGED
@@ -3,19 +3,20 @@
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
- from deep_translator import exceptions, PonsTranslator
 
7
 
8
 
9
  @pytest.fixture
10
  def pons():
11
- return PonsTranslator(source="english", target='french')
12
 
13
 
14
  def test_content(pons):
15
  """Sample pytest test function with the pytest fixture as an argument."""
16
  # from bs4 import BeautifulSoup
17
  # assert 'GitHub' in BeautifulSoup(response.content).title.string
18
- assert pons.translate(word='good') is not None
19
 
20
 
21
  def test_inputs():
@@ -46,4 +47,3 @@ def test_payload(pons):
46
 
47
  with pytest.raises(exceptions.NotValidLength):
48
  pons.translate("a" * 51)
49
-
 
3
  """Tests for `deep_translator` package."""
4
 
5
  import pytest
6
+
7
+ from deep_translator import PonsTranslator, exceptions
8
 
9
 
10
  @pytest.fixture
11
  def pons():
12
+ return PonsTranslator(source="english", target="french")
13
 
14
 
15
  def test_content(pons):
16
  """Sample pytest test function with the pytest fixture as an argument."""
17
  # from bs4 import BeautifulSoup
18
  # assert 'GitHub' in BeautifulSoup(response.content).title.string
19
+ assert pons.translate(word="good") is not None
20
 
21
 
22
  def test_inputs():
 
47
 
48
  with pytest.raises(exceptions.NotValidLength):
49
  pons.translate("a" * 51)