From c700ed67ef97d8ff2ead5eb47e4a29cc3bbb3294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnar=20Tumi=20=C3=9Eorsteinsson?= Date: Wed, 12 Jun 2024 13:20:15 +0200 Subject: [PATCH] Copy for translations done signal and test (#12033) --- CHANGELOG.txt | 1 + CONTRIBUTORS.md | 1 + docs/reference/signals.md | 8 ++++ docs/releases/6.2.md | 1 + wagtail/actions/copy_for_translation.py | 16 +++++++- wagtail/signals.py | 4 ++ wagtail/tests/test_signals.py | 51 ++++++++++++++++++++++++- 7 files changed, 79 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3d6a35fd6a..b01cf23c24 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -11,6 +11,7 @@ Changelog * Do not link to edit view from listing views if user has no permission to edit (Sage Abdullah) * Allow access to snippets and other model viewsets to users with "View" permission (Sage Abdullah) * Skip `ChooseParentView` if only one possible valid parent page availale (Matthias Brück) + * Add `copy_for_translation_done` signal when a page is copied for translation (Arnar Tumi Þorsteinsson) * Fix: Make `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` setting functional again (Rohit Sharma) * Fix: Enable `richtext` template tag to convert lazy translation values (Benjamin Bach) * Fix: Ensure permission labels on group permissions page are translated where available (Matt Westcott) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e8cc9ede81..c5e4aea6df 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -820,6 +820,7 @@ * Matthias Brück * Julie Rymer * Byron Peebles +* Arnar Tumi Þorsteinsson ## Translators diff --git a/docs/reference/signals.md b/docs/reference/signals.md index 7f30a1bc0f..10d077ba76 100644 --- a/docs/reference/signals.md +++ b/docs/reference/signals.md @@ -194,3 +194,11 @@ This signal is emitted from a `TaskState` when a page's task is canceled. - `instance` - The specific `TaskState` instance. - `user` - The user who canceled the task - `kwargs` - Any other arguments passed to `task_cancelled.send()` + +## copy_for_translation_done + +This signal is emitted from a `CopyPageForTranslationAction` when a page is being copied to a new locale (translated). + +- `sender` - `CopyPageForTranslationAction` +- `source_obj` - The source page +- `target_obj` - The copy of the source page in the new locale diff --git a/docs/releases/6.2.md b/docs/releases/6.2.md index 2faa795369..f505165864 100644 --- a/docs/releases/6.2.md +++ b/docs/releases/6.2.md @@ -21,6 +21,7 @@ depth: 1 * Do not link to edit view from listing views if user has no permission to edit (Sage Abdullah) * Allow access to snippets and other model viewsets to users with "View" permission (Sage Abdullah) * Skip `ChooseParentView` if only one possible valid parent page availale (Matthias Brück) + * Add `copy_for_translation_done` signal when a page is copied for translation (Arnar Tumi Þorsteinsson) ### Bug fixes diff --git a/wagtail/actions/copy_for_translation.py b/wagtail/actions/copy_for_translation.py index 0c1c41b06e..8aea869859 100644 --- a/wagtail/actions/copy_for_translation.py +++ b/wagtail/actions/copy_for_translation.py @@ -3,6 +3,7 @@ from django.db import transaction from wagtail.coreutils import find_available_slug from wagtail.models.copying import _copy +from wagtail.signals import copy_for_translation_done class ParentNotTranslatedError(Exception): @@ -79,7 +80,7 @@ class CopyPageForTranslationAction: def walk(self, current_page): for child_page in current_page.get_children(): - self._copy_for_translation( + translated_page = self._copy_for_translation( child_page if child_page.live else child_page.get_latest_revision_as_object(), @@ -88,6 +89,13 @@ class CopyPageForTranslationAction: self.alias, self.exclude_fields, ) + + copy_for_translation_done.send( + sender=self.__class__, + source_obj=child_page.specific, + target_obj=translated_page, + ) + self.walk(child_page) @transaction.atomic @@ -160,6 +168,12 @@ class CopyPageForTranslationAction: self.exclude_fields, ) + copy_for_translation_done.send( + sender=self.__class__, + source_obj=self.page, + target_obj=translated_page, + ) + if self.include_subtree: self.walk(self.page) diff --git a/wagtail/signals.py b/wagtail/signals.py index a909306618..2109f67b81 100644 --- a/wagtail/signals.py +++ b/wagtail/signals.py @@ -64,3 +64,7 @@ task_cancelled = Signal() # Required as a workaround for https://code.djangoproject.com/ticket/6870 # provides args: sender, instance pre_validate_delete = Signal() + +# Translation signals +# provides args: sender, source_obj, target_obj +copy_for_translation_done = Signal() diff --git a/wagtail/tests/test_signals.py b/wagtail/tests/test_signals.py index a93819dc79..b4fad9385c 100644 --- a/wagtail/tests/test_signals.py +++ b/wagtail/tests/test_signals.py @@ -1,9 +1,10 @@ from unittest import mock +from django.conf import settings from django.test import TestCase -from wagtail.models import Site -from wagtail.signals import page_slug_changed +from wagtail.models import Locale, Site +from wagtail.signals import copy_for_translation_done, page_slug_changed from wagtail.test.testapp.models import SimplePage from wagtail.test.utils import WagtailTestUtils @@ -97,3 +98,49 @@ class TestPageSlugChangedSignal(WagtailTestUtils, TestCase): # Check the signal was NOT fired self.assertEqual(handler.call_count, 0) + + +class TestCopyForTranslationDoneSignal(WagtailTestUtils, TestCase): + """ + Tests for the `wagtail.signals.copy_for_translation_done` signal + """ + + def setUp(self): + # Find root page + site = Site.objects.select_related("root_page").get(is_default_site=True) + root_page = site.root_page + + # Create a subpage + self.subpage = SimplePage( + title="Subpage in english", slug="subpage-in-english", content="hello" + ) + root_page.add_child(instance=self.subpage) + + # Get the languages and create locales + language_codes = dict(settings.LANGUAGES).keys() + + for language_code in language_codes: + Locale.objects.get_or_create(language_code=language_code) + + # Get the locales needed + self.locale = Locale.objects.get(language_code="en") + self.another_locale = Locale.objects.get(language_code="fr") + + root_page.copy_for_translation(self.another_locale) + + def test_signal_emitted_on_copy_for_translation_done(self): + # Connect a mock signal handler to the signal + handler = mock.MagicMock() + copy_for_translation_done.connect(handler) + + page_to_translate = SimplePage.objects.get(id=self.subpage.id) + + try: + with self.captureOnCommitCallbacks(execute=True): + page_to_translate.copy_for_translation(self.another_locale) + finally: + # Disconnect mock handler to prevent cross-test pollution + copy_for_translation_done.disconnect(handler) + + # Check the signal was fired + self.assertEqual(handler.call_count, 1)