Merge pull request #139 from nidhaloff/refactoring
Browse files- Makefile +3 -5
- deep_translator/__init__.py +14 -14
- deep_translator/__main__.py +1 -2
- deep_translator/base.py +35 -24
- deep_translator/cli.py +58 -40
- deep_translator/constants.py +163 -195
- deep_translator/deepl.py +35 -20
- deep_translator/detection.py +28 -17
- deep_translator/engines.py +3 -4
- deep_translator/exceptions.py +29 -18
- deep_translator/google.py +50 -29
- deep_translator/libre.py +33 -19
- deep_translator/linguee.py +40 -28
- deep_translator/microsoft.py +39 -26
- deep_translator/mymemory.py +46 -32
- deep_translator/papago.py +28 -22
- deep_translator/pons.py +38 -31
- deep_translator/qcri.py +26 -16
- deep_translator/validate.py +3 -5
- deep_translator/yandex.py +42 -32
- docs/conf.py +2 -0
- examples/linguee.py +0 -1
- examples/mymemory.py +0 -1
- examples/pons.py +0 -1
- examples/trans.py +1 -2
- poetry.lock +169 -1
- pyproject.toml +2 -0
- tests/test_cli.py +7 -7
- tests/test_data.py +2 -2
- tests/test_deepl.py +15 -13
- tests/test_google.py +11 -10
- tests/test_libre.py +10 -9
- tests/test_linguee.py +5 -4
- tests/test_microsoft_trans.py +24 -10
- tests/test_mymemory.py +5 -6
- tests/test_pons.py +4 -4
Makefile
CHANGED
@@ -47,15 +47,13 @@ clean-test: ## remove test and coverage artifacts
|
|
47 |
rm -fr htmlcov/
|
48 |
rm -fr .pytest_cache
|
49 |
|
50 |
-
|
51 |
-
|
|
|
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 .
|
4 |
-
from .
|
5 |
-
from .
|
6 |
-
from .
|
7 |
-
from .
|
8 |
-
from .
|
9 |
-
from .
|
10 |
-
from .
|
11 |
-
from .
|
12 |
-
from .
|
13 |
-
from .
|
14 |
|
15 |
__author__ = """Nidhal Baccouri"""
|
16 |
-
__email__ =
|
17 |
-
__version__ =
|
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 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
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
|
27 |
-
self.supported_languages
|
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 ==
|
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(
|
|
|
|
|
59 |
"""
|
60 |
-
return the supported languages by the
|
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
|
|
|
|
|
|
|
|
|
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(
|
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,
|
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
|
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
|
|
|
|
|
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(
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
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 {
|
26 |
print("-" * 50)
|
27 |
-
print("Translation result: {}"
|
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(
|
36 |
-
|
|
|
|
|
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(
|
44 |
-
|
45 |
-
|
|
|
|
|
46 |
|
47 |
-
parser.add_argument(
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
parser.add_argument(
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
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 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
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 |
-
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
}
|
253 |
|
254 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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__(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 =
|
26 |
self.api_key = api_key
|
27 |
-
url =
|
28 |
-
|
29 |
-
|
|
|
|
|
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
|
43 |
if self._same_source_target() or is_empty(text):
|
44 |
return text
|
45 |
|
46 |
# Create the request parameters.
|
47 |
-
translate_endpoint =
|
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[
|
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__ ==
|
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 = {
|
|
|
|
|
|
|
|
|
|
|
|
|
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(
|
23 |
-
|
|
|
|
|
24 |
if not text:
|
25 |
raise Exception("Please provide an input text")
|
26 |
|
27 |
else:
|
28 |
try:
|
29 |
-
headers = config[
|
30 |
-
headers[
|
31 |
-
response = requests.post(config[
|
32 |
-
json={'q': text},
|
33 |
-
headers=headers)
|
34 |
|
35 |
-
body = response.json().get(
|
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(
|
|
|
|
|
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(
|
55 |
if detailed:
|
56 |
return detections[0]
|
57 |
|
58 |
-
lang = detections[0].get(
|
59 |
if lang:
|
60 |
return lang
|
61 |
|
62 |
|
63 |
-
def batch_detection(
|
|
|
|
|
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(
|
73 |
res = [obj[0] for obj in detections]
|
74 |
if detailed:
|
75 |
return res
|
76 |
else:
|
77 |
-
return [obj[
|
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 |
-
|
6 |
-
|
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__(
|
34 |
-
|
35 |
-
|
|
|
|
|
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__(
|
56 |
-
|
57 |
-
|
|
|
|
|
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__(
|
67 |
-
|
68 |
-
|
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 =
|
|
|
|
|
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__(
|
88 |
-
|
|
|
|
|
|
|
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__(
|
|
|
|
|
|
|
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 =
|
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
|
6 |
-
|
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
|
16 |
"""
|
17 |
|
18 |
-
def __init__(
|
|
|
|
|
|
|
|
|
|
|
|
|
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__(
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
31 |
|
32 |
self._alt_element_query = {"class": "result-container"}
|
33 |
|
34 |
-
def translate(self, text, **kwargs):
|
35 |
"""
|
36 |
-
function
|
37 |
@param text: desired text to translate
|
38 |
@return: str: translated text
|
39 |
"""
|
40 |
-
if
|
41 |
text = text.strip()
|
42 |
if self._same_source_target() or is_empty(text):
|
43 |
return text
|
44 |
-
self._url_params[
|
45 |
-
self._url_params[
|
46 |
|
47 |
if self.payload_key:
|
48 |
self._url_params[self.payload_key] = text
|
49 |
|
50 |
-
response = requests.get(
|
51 |
-
|
52 |
-
|
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,
|
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 =
|
69 |
-
translated_alpha =
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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__ ==
|
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 .
|
8 |
-
from .
|
9 |
-
from .
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
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__(
|
|
|
|
|
|
|
|
|
|
|
|
|
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__(
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
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
|
42 |
if self._same_source_target() or is_empty(text):
|
43 |
return text
|
44 |
|
45 |
-
translate_endpoint =
|
46 |
params = {
|
47 |
"q": text,
|
48 |
"source": self._source,
|
49 |
"target": self._target,
|
50 |
-
"format":
|
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(
|
|
|
|
|
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[
|
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
|
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
|
5 |
-
|
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__(
|
|
|
|
|
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__(
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
37 |
|
38 |
-
def translate(
|
|
|
|
|
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
|
51 |
# %s-%s/translation/%s.html
|
52 |
-
url =
|
|
|
|
|
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,
|
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(
|
|
|
|
|
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
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
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__(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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()[
|
53 |
|
54 |
-
return {translation_dict[k][
|
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
|
66 |
-
self._url_params[
|
67 |
-
self._url_params[
|
68 |
|
69 |
-
valid_microsoft_json = [{
|
70 |
try:
|
71 |
-
requested = requests.post(
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
|
|
|
|
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()[
|
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 = [
|
87 |
-
|
|
|
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
|
5 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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(
|
25 |
-
super().__init__(
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
30 |
|
31 |
-
def translate(
|
|
|
|
|
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
|
40 |
text = text.strip()
|
41 |
if self._same_source_target() or is_empty(text):
|
42 |
return text
|
43 |
|
44 |
-
self._url_params[
|
45 |
if self.payload_key:
|
46 |
self._url_params[self.payload_key] = text
|
47 |
if self.email:
|
48 |
-
self._url_params[
|
49 |
|
50 |
-
response = requests.get(
|
51 |
-
|
52 |
-
|
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(
|
64 |
if translation:
|
65 |
return translation
|
66 |
|
67 |
elif not translation:
|
68 |
-
all_matches = data.get(
|
69 |
-
matches = (match[
|
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
|
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
|
6 |
-
|
7 |
-
from .base import BaseTranslator
|
8 |
import requests
|
9 |
|
10 |
-
from .
|
|
|
|
|
|
|
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__(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
44 |
-
payload = {
|
45 |
-
"source": self._source,
|
46 |
-
"target": self._target,
|
47 |
-
"text": text
|
48 |
-
}
|
49 |
headers = {
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
}
|
54 |
-
response = requests.post(
|
55 |
-
self._base_url, headers=headers, data=payload)
|
56 |
if response.status_code != 200:
|
57 |
raise Exception(
|
58 |
-
f
|
|
|
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
|
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
|
5 |
-
import requests
|
6 |
|
7 |
-
|
8 |
-
from
|
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__(
|
|
|
|
|
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__(
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
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
|
50 |
if self._same_source_target() or is_empty(word):
|
51 |
return word
|
52 |
-
url = "{}{}-{}/{}"
|
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,
|
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(
|
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 |
-
|
4 |
-
from .
|
5 |
-
from .
|
|
|
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__(
|
|
|
|
|
|
|
|
|
|
|
|
|
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(
|
|
|
|
|
39 |
if not params:
|
40 |
params = self.params
|
41 |
try:
|
42 |
-
res = requests.get(
|
43 |
-
endpoint=self.api_endpoints[endpoint]),
|
|
|
|
|
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": "{}-{
|
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
|
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 |
-
|
6 |
-
from .
|
7 |
-
|
8 |
-
from .
|
|
|
|
|
|
|
|
|
|
|
|
|
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__(
|
|
|
|
|
|
|
|
|
|
|
|
|
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[
|
82 |
-
status_code = response[
|
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
|
91 |
params = {
|
92 |
"text": text,
|
93 |
"format": "plain",
|
94 |
-
"lang": self._target
|
95 |
-
|
|
|
|
|
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[
|
107 |
raise TooManyRequests()
|
108 |
|
109 |
-
if response[
|
110 |
-
raise ServerException(response[
|
111 |
|
112 |
-
if not response[
|
113 |
raise TranslationNotFound()
|
114 |
|
115 |
-
return response[
|
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,
|
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 = "
|
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:] = [
|
13 |
return CLI(sys.argv[1:]).parse_args()
|
14 |
|
15 |
|
16 |
def test_source(mock_args):
|
17 |
-
assert mock_args.source ==
|
18 |
|
19 |
|
20 |
def test_target(mock_args):
|
21 |
-
assert mock_args.target ==
|
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 =
|
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 |
-
|
3 |
from deep_translator.deepl import DeeplTranslator
|
4 |
from deep_translator.exceptions import AuthorizationException
|
5 |
|
6 |
|
7 |
-
@patch(
|
8 |
def test_simple_translation(mock_requests):
|
9 |
-
translator = DeeplTranslator(
|
|
|
|
|
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(
|
20 |
-
assert translation ==
|
21 |
|
22 |
|
23 |
-
@patch(
|
24 |
def test_wrong_api_key(mock_requests):
|
25 |
-
translator = DeeplTranslator(
|
|
|
|
|
26 |
# Set the response status_code only.
|
27 |
mock_requests.return_value = Mock(status_code=403)
|
28 |
with pytest.raises(AuthorizationException):
|
29 |
-
translator.translate(
|
|
|
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 |
-
|
7 |
-
from deep_translator
|
|
|
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=
|
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=
|
21 |
|
22 |
|
23 |
def test_abbreviations_and_languages_mapping():
|
24 |
-
for abb, lang in
|
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=
|
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=
|
|
|
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 |
-
|
7 |
-
from deep_translator
|
|
|
8 |
|
9 |
|
10 |
@pytest.fixture
|
11 |
def libre():
|
12 |
-
return LibreTranslator(source="en", target=
|
13 |
|
14 |
|
15 |
def test_inputs():
|
16 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
17 |
-
LibreTranslator(source="", target="", api_key=
|
18 |
|
19 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
20 |
-
LibreTranslator(source="auto", target="", api_key=
|
21 |
|
22 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
-
LibreTranslator(source="", target="en", api_key=
|
24 |
|
25 |
|
26 |
def test_abbreviations_and_languages_mapping():
|
27 |
-
for abb, lang in
|
28 |
-
l1 = LibreTranslator(abb, api_key=
|
29 |
-
l2 = LibreTranslator(lang, api_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 |
-
|
|
|
7 |
|
8 |
|
9 |
@pytest.fixture
|
10 |
def linguee():
|
11 |
-
return LingueeTranslator(source="english", target=
|
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=
|
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
|
10 |
|
11 |
|
12 |
# mocked request.post
|
13 |
-
@patch.object(requests,
|
14 |
def test_microsoft_successful_post_mock(mock_request_post):
|
15 |
-
returned_json = [{
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
|
26 |
def test_MicrosoftAPIerror():
|
27 |
with pytest.raises(exceptions.MicrosoftAPIerror):
|
28 |
-
MicrosoftTranslator(api_key="empty", source=
|
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(
|
|
|
|
|
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(
|
|
|
|
|
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
|
62 |
-
assert
|
|
|
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 |
-
|
|
|
7 |
|
8 |
|
9 |
@pytest.fixture
|
10 |
def mymemory():
|
11 |
-
return MyMemoryTranslator(source="en", target=
|
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=
|
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 |
-
|
|
|
7 |
|
8 |
|
9 |
@pytest.fixture
|
10 |
def pons():
|
11 |
-
return PonsTranslator(source="english", target=
|
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=
|
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)
|
|