Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more options to the DeepL settings (Fixes #831) #835

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/how-to/integrations/machine-translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ WAGTAILLOCALIZE_MACHINE_TRANSLATOR = {
# Optional DeepL API setting. Accepts "default", "prefer_more" or "prefer_less".\
# For more information see the API docs https://www.deepl.com/docs-api/translate-text/
"FORMALITY": "<Your DeepL formality preference here>",
# Optional DeepL Glossary IDs by (source, target) language pairs
"GLOSSARY_IDS": {
("EN", "ES"): "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
("EN", "FR"): "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
},
# Optional timeout for the request to the DeepL API
"TIMEOUT": 30,
},
}
```
Expand Down
34 changes: 25 additions & 9 deletions wagtail_localize/machine_translators/deepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,43 @@ def get_api_endpoint(self):
return "https://api-free.deepl.com/v2/translate"
return "https://api.deepl.com/v2/translate"

def translate(self, source_locale, target_locale, strings):
def get_parameters(self, source_locale, target_locale, strings):
source_lang = language_code(source_locale.language_code)
target_lang = language_code(target_locale.language_code, is_target=True)

parameters = {
"auth_key": self.options["AUTH_KEY"],
"text": [string.data for string in strings],
"tag_handling": "xml",
"source_lang": language_code(source_locale.language_code),
"target_lang": language_code(target_locale.language_code, is_target=True),
"source_lang": source_lang,
"target_lang": target_lang,
}

if self.options.get("FORMALITY"):
if self.options["FORMALITY"] in SUPPORTED_FORMALITY_OPTIONS:
parameters["formality"] = self.options["FORMALITY"]
if formality := self.options.get("FORMALITY"):
if formality in SUPPORTED_FORMALITY_OPTIONS:
parameters["formality"] = formality
else:
warnings.warn(
f"Unsupported formality option '{formality}'. "
f"Supported options are: {', '.join(SUPPORTED_FORMALITY_OPTIONS)}"
)

if glossaries := self.options.get("GLOSSARY_IDS"):
lang_pair = (source_lang, target_lang)
if glossary_id := glossaries.get(lang_pair):
parameters["glossary_id"] = glossary_id
else:
warnings.warn(
f"Unsupported formality option '{self.options['FORMALITY']}'. Supported options are: {', '.join(SUPPORTED_FORMALITY_OPTIONS)}"
f"No glossary defined for (source, target) pair: {lang_pair}"
)

return parameters

def translate(self, source_locale, target_locale, strings):
response = requests.post(
self.get_api_endpoint(),
parameters,
timeout=30,
self.get_parameters(source_locale, target_locale, strings),
timeout=int(self.options.get("TIMEOUT", 30)),
)

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@
},
}

DEEPL_SETTINGS_WITH_GLOSSARY_IDS = {
"CLASS": "wagtail_localize.machine_translators.deepl.DeepLTranslator",
"OPTIONS": {
"AUTH_KEY": "asd-23-ssd-243-adsf-dummy-auth-key:bla",
"GLOSSARY_IDS": {
("EN", "DE"): "test-id-de",
("EN", "FR"): "test-id-fr",
},
},
}

DEEPL_SETTINGS_WITH_MISSING_GLOSSARY_IDS = {
"CLASS": "wagtail_localize.machine_translators.deepl.DeepLTranslator",
"OPTIONS": {
"AUTH_KEY": "asd-23-ssd-243-adsf-dummy-auth-key:bla",
"GLOSSARY_IDS": {
("EN", "FR"): "test-id-fr",
("EN", "DE"): "test-id-de",
},
},
}


class TestDeeplTranslator(TestCase):
@override_settings(WAGTAILLOCALIZE_MACHINE_TRANSLATOR=DEEPL_SETTINGS_FREE_ENDPOINT)
Expand Down Expand Up @@ -120,3 +142,36 @@ def test_language_code_as_target(self):
for code, expected_value in mapping.items():
with self.subTest(f"Testing language_code with {code} as target"):
self.assertEqual(expected_value, language_code(code, is_target=True))

@override_settings(
WAGTAILLOCALIZE_MACHINE_TRANSLATOR=DEEPL_SETTINGS_WITH_GLOSSARY_IDS
)
@patch("requests.post")
def test_translate_with_glossary_ids(self, mock_post):
translator = get_machine_translator()
source_locale = Mock(language_code="en")
target_locale = Mock(language_code="de")
strings = [StringValue("Test string")]

translator.translate(source_locale, target_locale, strings)

mock_post.assert_called_once()
called_args, called_kwargs = mock_post.call_args
self.assertIn("glossary_id", called_args[1])
self.assertEqual(called_args[1]["glossary_id"], "test-id-de")

@override_settings(
WAGTAILLOCALIZE_MACHINE_TRANSLATOR=DEEPL_SETTINGS_WITH_MISSING_GLOSSARY_IDS
)
@patch("requests.post")
def test_translate_with_missing_glossary_ids(self, mock_post):
translator = get_machine_translator()
source_locale = Mock(language_code="en")
target_locale = Mock(language_code="es")
strings = [StringValue("Test string")]

translator.translate(source_locale, target_locale, strings)

mock_post.assert_called_once()
called_args, called_kwargs = mock_post.call_args
self.assertNotIn("glossary_id", called_args[1])