From 7bfd881f03150c8c66a2349dc4e613a7afbcae58 Mon Sep 17 00:00:00 2001 From: tognee Date: Fri, 20 Dec 2024 15:18:11 +0100 Subject: [PATCH] Skip creating `StringTranslation`s if the machine translators do not provide the translation (#819) --- .../tests/test_edit_translation.py | 123 ++++++++++++++++++ wagtail_localize/views/edit_translation.py | 6 + 2 files changed, 129 insertions(+) diff --git a/wagtail_localize/tests/test_edit_translation.py b/wagtail_localize/tests/test_edit_translation.py index 7a7bf893..e62e5b0e 100644 --- a/wagtail_localize/tests/test_edit_translation.py +++ b/wagtail_localize/tests/test_edit_translation.py @@ -33,6 +33,7 @@ from wagtail.models import Locale, Page, Revision from wagtail.test.utils import WagtailTestUtils +from wagtail_localize.machine_translators.dummy import translate_html from wagtail_localize.models import ( OverridableSegment, SegmentOverride, @@ -43,6 +44,7 @@ TranslationLog, TranslationSource, ) +from wagtail_localize.strings import StringValue from wagtail_localize.test.models import ( Header, NavigationLink, @@ -90,6 +92,23 @@ ] +# Patches for translation skipping tests +def patched_translate(source_locale, target_locale, strings): + result = {} + for string in strings: + if not all(ord(c) < 128 for c in string.data): + continue + result[string] = StringValue(translate_html(string.data)) + + return result + + +def patched_translate_html(html): + if not all(ord(c) < 128 for c in html): + return None + return translate_html(html) + + class EditTranslationTestData(WagtailTestUtils): def setUp(self): self.login() @@ -3400,6 +3419,110 @@ def test_machine_translate_page(self): self.assertEqual(translation_3.tool_name, "Dummy translator") self.assertEqual(translation_3.last_translated_by, self.user) + @patch( + "wagtail_localize.machine_translators.dummy.DummyTranslator.translate", + side_effect=patched_translate, + ) + def test_machine_translate_page_with_translate_skip(self, mock_translate_html): + response = self.client.post( + reverse( + "wagtail_localize:machine_translate", args=[self.page_translation.id] + ), + { + "next": reverse("wagtailadmin_pages:edit", args=[self.fr_page.id]), + }, + ) + + self.assertRedirects( + response, reverse("wagtailadmin_pages:edit", args=[self.fr_page.id]) + ) + + translation_1 = StringTranslation.objects.get( + translation_of__data="A char field", + context__path="test_charfield", + locale=self.fr_locale, + ) + + self.assertEqual(translation_1.data, "field char A") + self.assertEqual( + translation_1.translation_type, StringTranslation.TRANSLATION_TYPE_MACHINE + ) + self.assertEqual(translation_1.tool_name, "Dummy translator") + self.assertEqual(translation_1.last_translated_by, self.user) + + translation_2 = StringTranslation.objects.get( + translation_of__data='This is a link.', + context__path="test_richtextfield", + locale=self.fr_locale, + ) + + self.assertEqual(translation_2.data, '.link a is This') + self.assertEqual( + translation_2.translation_type, StringTranslation.TRANSLATION_TYPE_MACHINE + ) + self.assertEqual(translation_2.tool_name, "Dummy translator") + self.assertEqual(translation_2.last_translated_by, self.user) + + translation_3 = StringTranslation.objects.filter( + translation_of__data="Special characters: '\"!? セキレイ", + context__path="test_richtextfield", + locale=self.fr_locale, + ).first() + + self.assertIsNone(translation_3) + + @patch( + "wagtail_localize.machine_translators.dummy.translate_html", + side_effect=patched_translate_html, + ) + def test_machine_translate_page_with_translate_html_skip(self, mock_translate_html): + response = self.client.post( + reverse( + "wagtail_localize:machine_translate", args=[self.page_translation.id] + ), + { + "next": reverse("wagtailadmin_pages:edit", args=[self.fr_page.id]), + }, + ) + + self.assertRedirects( + response, reverse("wagtailadmin_pages:edit", args=[self.fr_page.id]) + ) + + translation_1 = StringTranslation.objects.get( + translation_of__data="A char field", + context__path="test_charfield", + locale=self.fr_locale, + ) + + self.assertEqual(translation_1.data, "field char A") + self.assertEqual( + translation_1.translation_type, StringTranslation.TRANSLATION_TYPE_MACHINE + ) + self.assertEqual(translation_1.tool_name, "Dummy translator") + self.assertEqual(translation_1.last_translated_by, self.user) + + translation_2 = StringTranslation.objects.get( + translation_of__data='This is a link.', + context__path="test_richtextfield", + locale=self.fr_locale, + ) + + self.assertEqual(translation_2.data, '.link a is This') + self.assertEqual( + translation_2.translation_type, StringTranslation.TRANSLATION_TYPE_MACHINE + ) + self.assertEqual(translation_2.tool_name, "Dummy translator") + self.assertEqual(translation_2.last_translated_by, self.user) + + translation_3 = StringTranslation.objects.filter( + translation_of__data="Special characters: '\"!? セキレイ", + context__path="test_richtextfield", + locale=self.fr_locale, + ).first() + + self.assertIsNone(translation_3) + def test_machine_translate_snippet(self): response = self.client.post( reverse( diff --git a/wagtail_localize/views/edit_translation.py b/wagtail_localize/views/edit_translation.py index b2a13076..6fced275 100644 --- a/wagtail_localize/views/edit_translation.py +++ b/wagtail_localize/views/edit_translation.py @@ -1412,6 +1412,12 @@ def apply_machine_translation(translation_id, user, machine_translator): with transaction.atomic(): for string, contexts in segments.items(): + if ( + translations.get(string) is None + or translations[string].data is None + ): + # Don't create a translation if the machine can't provide + continue for string_id, context_id in contexts: StringTranslation.objects.get_or_create( translation_of_id=string_id,