Added test cases and support for translate_batch and translate_file
Browse files- deep_translator/libre.py +34 -4
- deep_translator/main.py +9 -1
- examples/libre.py +2 -4
- tests/test_libre.py +46 -6
deep_translator/libre.py
CHANGED
|
@@ -3,8 +3,6 @@ LibreTranslate API
|
|
| 3 |
"""
|
| 4 |
|
| 5 |
import requests
|
| 6 |
-
from bs4 import BeautifulSoup
|
| 7 |
-
from requests.models import Response
|
| 8 |
from .parent import BaseTranslator
|
| 9 |
from .constants import BASE_URLS,LIBRE_LANGUAGES_TO_CODES, LIBRE_CODES_TO_LANGUAGES
|
| 10 |
from .exceptions import (ServerException,
|
|
@@ -21,7 +19,7 @@ class LibreTranslator(BaseTranslator):
|
|
| 21 |
_languages = LIBRE_LANGUAGES_TO_CODES
|
| 22 |
supported_languages = list(_languages.keys())
|
| 23 |
|
| 24 |
-
def __init__(self, base_url = BASE_URLS.get("LIBRE_FREE"), api_key=
|
| 25 |
"""
|
| 26 |
@param source: source language to translate from
|
| 27 |
List of LibreTranslate nedpoints can be found at : https://github.com/LibreTranslate/LibreTranslate#mirrors
|
|
@@ -86,8 +84,11 @@ class LibreTranslator(BaseTranslator):
|
|
| 86 |
"q": text,
|
| 87 |
"source": self.source,
|
| 88 |
"target": self.target,
|
| 89 |
-
"
|
| 90 |
}
|
|
|
|
|
|
|
|
|
|
| 91 |
# Do the request and check the connection.
|
| 92 |
try:
|
| 93 |
response = requests.post(self.__base_url + translate_endpoint, params=params)
|
|
@@ -105,3 +106,32 @@ class LibreTranslator(BaseTranslator):
|
|
| 105 |
raise TranslationNotFound(text)
|
| 106 |
# Process and return the response.
|
| 107 |
return res['translatedText']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
"""
|
| 4 |
|
| 5 |
import requests
|
|
|
|
|
|
|
| 6 |
from .parent import BaseTranslator
|
| 7 |
from .constants import BASE_URLS,LIBRE_LANGUAGES_TO_CODES, LIBRE_CODES_TO_LANGUAGES
|
| 8 |
from .exceptions import (ServerException,
|
|
|
|
| 19 |
_languages = LIBRE_LANGUAGES_TO_CODES
|
| 20 |
supported_languages = list(_languages.keys())
|
| 21 |
|
| 22 |
+
def __init__(self,source="auto", target="en", base_url = BASE_URLS.get("LIBRE_FREE"), api_key=None, **kwargs):
|
| 23 |
"""
|
| 24 |
@param source: source language to translate from
|
| 25 |
List of LibreTranslate nedpoints can be found at : https://github.com/LibreTranslate/LibreTranslate#mirrors
|
|
|
|
| 84 |
"q": text,
|
| 85 |
"source": self.source,
|
| 86 |
"target": self.target,
|
| 87 |
+
"format": 'text'
|
| 88 |
}
|
| 89 |
+
# Add API Key if required
|
| 90 |
+
if self.api_key:
|
| 91 |
+
params["api_key"] = self.api_key
|
| 92 |
# Do the request and check the connection.
|
| 93 |
try:
|
| 94 |
response = requests.post(self.__base_url + translate_endpoint, params=params)
|
|
|
|
| 106 |
raise TranslationNotFound(text)
|
| 107 |
# Process and return the response.
|
| 108 |
return res['translatedText']
|
| 109 |
+
|
| 110 |
+
def translate_file(self, path, **kwargs):
|
| 111 |
+
"""
|
| 112 |
+
translate directly from file
|
| 113 |
+
@param path: path to the target file
|
| 114 |
+
@type path: str
|
| 115 |
+
@param kwargs: additional args
|
| 116 |
+
@return: str
|
| 117 |
+
"""
|
| 118 |
+
try:
|
| 119 |
+
with open(path) as f:
|
| 120 |
+
text = f.read().strip()
|
| 121 |
+
return self.translate(text)
|
| 122 |
+
except Exception as e:
|
| 123 |
+
raise e
|
| 124 |
+
|
| 125 |
+
def translate_batch(self, batch=None, **kwargs):
|
| 126 |
+
"""
|
| 127 |
+
translate a list of texts
|
| 128 |
+
@param batch: list of texts you want to translate
|
| 129 |
+
@return: list of translations
|
| 130 |
+
"""
|
| 131 |
+
if not batch:
|
| 132 |
+
raise Exception("Enter your text list that you want to translate")
|
| 133 |
+
arr = []
|
| 134 |
+
for i, text in enumerate(batch):
|
| 135 |
+
translated = self.translate(text, **kwargs)
|
| 136 |
+
arr.append(translated)
|
| 137 |
+
return arr
|
deep_translator/main.py
CHANGED
|
@@ -10,6 +10,7 @@ from .pons import PonsTranslator
|
|
| 10 |
from .yandex import YandexTranslator
|
| 11 |
from .microsoft import MicrosoftTranslator
|
| 12 |
from .papago import PapagoTranslator
|
|
|
|
| 13 |
|
| 14 |
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
| 15 |
@click.group()
|
|
@@ -64,6 +65,11 @@ def translate(translator, source, target, text, api_key):
|
|
| 64 |
source=source,
|
| 65 |
target=target,
|
| 66 |
api_key=api_key)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
else:
|
| 68 |
raise AttributeError("The given translator is not supported.")
|
| 69 |
|
|
@@ -105,6 +111,8 @@ def languages(translator, api_key):
|
|
| 105 |
translator = MicrosoftTranslator(api_key=api_key)
|
| 106 |
elif translator == "papago":
|
| 107 |
translator = PapagoTranslator(api_key=api_key)
|
|
|
|
|
|
|
| 108 |
else:
|
| 109 |
raise AttributeError("The given translator is not supported.")
|
| 110 |
|
|
@@ -117,7 +125,7 @@ def languages(translator, api_key):
|
|
| 117 |
@cli.command()
|
| 118 |
def list():
|
| 119 |
"""Lists available translators."""
|
| 120 |
-
click.echo("Available translators include: Google, MyMemory, QCRI, Linguee, Pons, Yandex, Microsoft (Bing), and
|
| 121 |
return 0
|
| 122 |
|
| 123 |
if __name__ == "__main__":
|
|
|
|
| 10 |
from .yandex import YandexTranslator
|
| 11 |
from .microsoft import MicrosoftTranslator
|
| 12 |
from .papago import PapagoTranslator
|
| 13 |
+
from .libre import LibreTranslator
|
| 14 |
|
| 15 |
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
| 16 |
@click.group()
|
|
|
|
| 65 |
source=source,
|
| 66 |
target=target,
|
| 67 |
api_key=api_key)
|
| 68 |
+
elif translator == "libre":
|
| 69 |
+
translator= LibreTranslator(
|
| 70 |
+
source=source,
|
| 71 |
+
target=target
|
| 72 |
+
)
|
| 73 |
else:
|
| 74 |
raise AttributeError("The given translator is not supported.")
|
| 75 |
|
|
|
|
| 111 |
translator = MicrosoftTranslator(api_key=api_key)
|
| 112 |
elif translator == "papago":
|
| 113 |
translator = PapagoTranslator(api_key=api_key)
|
| 114 |
+
elif translator == "libre":
|
| 115 |
+
translator = LibreTranslator
|
| 116 |
else:
|
| 117 |
raise AttributeError("The given translator is not supported.")
|
| 118 |
|
|
|
|
| 125 |
@cli.command()
|
| 126 |
def list():
|
| 127 |
"""Lists available translators."""
|
| 128 |
+
click.echo("Available translators include: Google, MyMemory, QCRI, Linguee, Pons, Yandex, Microsoft (Bing), Papago and LibreTranslate.")
|
| 129 |
return 0
|
| 130 |
|
| 131 |
if __name__ == "__main__":
|
examples/libre.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
| 1 |
-
|
| 2 |
from deep_translator import LibreTranslator
|
| 3 |
|
|
|
|
| 4 |
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
# print(res)
|
|
|
|
|
|
|
| 1 |
from deep_translator import LibreTranslator
|
| 2 |
|
| 3 |
+
res = LibreTranslator(source='de', target='en').translate('laufen')
|
| 4 |
|
| 5 |
+
print(res)
|
|
|
|
|
|
tests/test_libre.py
CHANGED
|
@@ -4,7 +4,29 @@
|
|
| 4 |
|
| 5 |
import pytest
|
| 6 |
from deep_translator import exceptions, LibreTranslator
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
@pytest.fixture
|
| 10 |
def libre():
|
|
@@ -17,6 +39,13 @@ def test_content(libre):
|
|
| 17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
| 18 |
assert libre.translate(text='good') is not None
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
def test_inputs():
|
| 22 |
with pytest.raises(exceptions.LanguageNotSupportedException):
|
|
@@ -25,11 +54,12 @@ def test_inputs():
|
|
| 25 |
with pytest.raises(exceptions.LanguageNotSupportedException):
|
| 26 |
LibreTranslator(source="auto", target="nothing")
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
| 33 |
|
| 34 |
def test_payload(libre):
|
| 35 |
with pytest.raises(exceptions.NotValidPayload):
|
|
@@ -47,3 +77,13 @@ def test_payload(libre):
|
|
| 47 |
|
| 48 |
def test_one_character_words():
|
| 49 |
assert LibreTranslator(source='es', target='en').translate('y') == 'and'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
import pytest
|
| 6 |
from deep_translator import exceptions, LibreTranslator
|
| 7 |
+
from deep_translator.constants import LIBRE_CODES_TO_LANGUAGES
|
| 8 |
+
import random
|
| 9 |
+
|
| 10 |
+
test_text_standard = 'Hello world.'
|
| 11 |
+
TRANSLATED_RESULTS = {
|
| 12 |
+
'English': 'Hello world.',
|
| 13 |
+
'Arabic': 'مرحبا العالم.',
|
| 14 |
+
'Chinese': '霍洛美世界。',
|
| 15 |
+
'French': 'Bonjour.',
|
| 16 |
+
'German': 'Hallo Welt.',
|
| 17 |
+
'Hindi': 'नमस्ते दुनिया।',
|
| 18 |
+
'Indonesian': 'Halo dunia.',
|
| 19 |
+
'Irish': 'Dia duit domhan.',
|
| 20 |
+
'Italian': 'Ciao mondo.',
|
| 21 |
+
'Japanese': 'こんにちは。',
|
| 22 |
+
'Korean': '안녕하세요.',
|
| 23 |
+
'Polish': 'Hello world (ang.).',
|
| 24 |
+
'Portuguese': 'Olá, mundo.',
|
| 25 |
+
'Russian': 'Привет мир.',
|
| 26 |
+
'Spanish': 'Hola mundo.',
|
| 27 |
+
'Turkish': 'Merhaba dünya.',
|
| 28 |
+
'Vietnamese': 'Xin chào.'
|
| 29 |
+
}
|
| 30 |
|
| 31 |
@pytest.fixture
|
| 32 |
def libre():
|
|
|
|
| 39 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
| 40 |
assert libre.translate(text='good') is not None
|
| 41 |
|
| 42 |
+
def test_random_tranlations_cases_multiple_names():
|
| 43 |
+
random_sample_size = 2
|
| 44 |
+
d = dict.fromkeys(list(TRANSLATED_RESULTS.keys()))
|
| 45 |
+
random_lang_names = random.sample(list(d.keys()), random_sample_size)
|
| 46 |
+
random_subset_dict = {k: TRANSLATED_RESULTS[k] for k in random_lang_names}
|
| 47 |
+
for lang, translation in random_subset_dict.items():
|
| 48 |
+
assert LibreTranslator(source='en', target=lang).translate(test_text_standard) == translation
|
| 49 |
|
| 50 |
def test_inputs():
|
| 51 |
with pytest.raises(exceptions.LanguageNotSupportedException):
|
|
|
|
| 54 |
with pytest.raises(exceptions.LanguageNotSupportedException):
|
| 55 |
LibreTranslator(source="auto", target="nothing")
|
| 56 |
|
| 57 |
+
def test_abbreviations_and_languages_mapping():
|
| 58 |
+
for abb, lang in LIBRE_CODES_TO_LANGUAGES.items():
|
| 59 |
+
if abb != 'en':
|
| 60 |
+
l1 = LibreTranslator(abb)
|
| 61 |
+
l2 = LibreTranslator(lang)
|
| 62 |
+
assert l1.source == l2.source
|
| 63 |
|
| 64 |
def test_payload(libre):
|
| 65 |
with pytest.raises(exceptions.NotValidPayload):
|
|
|
|
| 77 |
|
| 78 |
def test_one_character_words():
|
| 79 |
assert LibreTranslator(source='es', target='en').translate('y') == 'and'
|
| 80 |
+
|
| 81 |
+
def test_translate_batch():
|
| 82 |
+
words_to_translate = ['How are you','Good','Thank You']
|
| 83 |
+
translated_words = ['¿Cómo estás?','Bien.','Gracias.']
|
| 84 |
+
assert LibreTranslator(source='en',target='es').translate_batch((words_to_translate)) == translated_words
|
| 85 |
+
|
| 86 |
+
def test_translate_file():
|
| 87 |
+
filePath = 'examples/test.txt'
|
| 88 |
+
translatedText='Un párrafo es una serie de frases relacionadas que desarrollan una idea central, llamada el tema. Trate de pensar en los párrafos en términos de unidad temática: un párrafo es una frase o un grupo de oraciones que apoya una idea central y unificada. Los párrafos añaden una idea a la vez a su argumento más amplio.'
|
| 89 |
+
assert LibreTranslator(source='en',target='es').translate_file(filePath) == translatedText
|