From e9af16b48d829127ce7952f0b7c620989b8a4892 Mon Sep 17 00:00:00 2001 From: Matt Westcott <matt@west.co.tt> Date: Wed, 23 Oct 2024 11:33:45 +0100 Subject: [PATCH] Improve i18n of success message for bulk page actions (#12453) Previously, translations for messages such as "1 page and 3 child pages have been published" were handled with separate branches for the "one parent page" vs "multiple parent pages" cases, to work around ngettext only being able to handle pluralisation for one item in the string. This fails for languages such as Polish where the pluralisation does not follow the straightforward one/many distinction. Instead, we can translate "N pages" and "N child pages" separately before forming the final message. We generally avoid translating sentence fragments in isolation as this can make things difficult for translators if the sentence structure does not match the English version - but this is hopefully an improvement over the current situation, as well as simplifying the code and reducing repetition. --- CHANGELOG.txt | 2 +- docs/releases/6.4.md | 2 +- .../admin/views/pages/bulk_actions/delete.py | 34 +++++---------- .../pages/bulk_actions/page_bulk_action.py | 17 ++++++++ .../admin/views/pages/bulk_actions/publish.py | 42 +++++-------------- .../views/pages/bulk_actions/unpublish.py | 42 +++++-------------- 6 files changed, 52 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index bf3448ad70..e06c11ca61 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,7 +4,7 @@ Changelog 6.4 (xx.xx.xxxx) - IN DEVELOPMENT ~~~~~~~~~~~~~~~~ - * ... + * Fix: Improve handling of translations for bulk page action confirmation messages (Matt Westcott) 6.3 LTS (xx.xx.xxxx) - IN DEVELOPMENT diff --git a/docs/releases/6.4.md b/docs/releases/6.4.md index 9dca57eabe..a7c23b8a23 100644 --- a/docs/releases/6.4.md +++ b/docs/releases/6.4.md @@ -18,7 +18,7 @@ depth: 1 ### Bug fixes - * ... + * Improve handling of translations for bulk page action confirmation messages (Matt Westcott) ### Documentation diff --git a/wagtail/admin/views/pages/bulk_actions/delete.py b/wagtail/admin/views/pages/bulk_actions/delete.py index 5235a68558..ce3c6d1c88 100644 --- a/wagtail/admin/views/pages/bulk_actions/delete.py +++ b/wagtail/admin/views/pages/bulk_actions/delete.py @@ -31,27 +31,15 @@ class DeleteBulkAction(PageBulkAction): return num_parent_objects, num_child_objects def get_success_message(self, num_parent_objects, num_child_objects): - if num_parent_objects == 1: - if num_child_objects == 0: - success_message = _("1 page has been deleted") - else: - success_message = ngettext( - "1 page and %(num_child_objects)d child page have been deleted", - "1 page and %(num_child_objects)d child pages have been deleted", - num_child_objects, - ) % {"num_child_objects": num_child_objects} + if num_child_objects > 0: + # Translators: This forms a message such as "1 page and 3 child pages have been deleted" + return _("%(parent_pages)s and %(child_pages)s have been deleted") % { + "parent_pages": self.get_parent_page_text(num_parent_objects), + "child_pages": self.get_child_page_text(num_child_objects), + } else: - if num_child_objects == 0: - success_message = _( - "%(num_parent_objects)d pages have been deleted" - ) % {"num_parent_objects": num_parent_objects} - else: - success_message = ngettext( - "%(num_parent_objects)d pages and %(num_child_objects)d child page have been deleted", - "%(num_parent_objects)d pages and %(num_child_objects)d child pages have been deleted", - num_child_objects, - ) % { - "num_child_objects": num_child_objects, - "num_parent_objects": num_parent_objects, - } - return success_message + return ngettext( + "%(num_parent_objects)d page has been deleted", + "%(num_parent_objects)d pages have been deleted", + num_parent_objects, + ) % {"num_parent_objects": num_parent_objects} diff --git a/wagtail/admin/views/pages/bulk_actions/page_bulk_action.py b/wagtail/admin/views/pages/bulk_actions/page_bulk_action.py index 0ab151646e..e72eec572b 100644 --- a/wagtail/admin/views/pages/bulk_actions/page_bulk_action.py +++ b/wagtail/admin/views/pages/bulk_actions/page_bulk_action.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.translation import ngettext from wagtail.admin.views.bulk_action import BulkAction from wagtail.admin.views.pages.search import page_filter_search @@ -55,3 +56,19 @@ class PageBulkAction(BulkAction): def get_execution_context(self): return {"user": self.request.user} + + def get_parent_page_text(self, num_parent_objects): + # Translators: This appears within a message such as "2 pages and 3 child pages have been published" + return ngettext( + "%(num_parent_objects)d page", + "%(num_parent_objects)d pages", + num_parent_objects, + ) % {"num_parent_objects": num_parent_objects} + + def get_child_page_text(self, num_child_objects): + # Translators: This appears within a message such as "2 pages and 3 child pages have been published" + return ngettext( + "%(num_child_objects)d child page", + "%(num_child_objects)d child pages", + num_child_objects, + ) % {"num_child_objects": num_child_objects} diff --git a/wagtail/admin/views/pages/bulk_actions/publish.py b/wagtail/admin/views/pages/bulk_actions/publish.py index e6f9a17893..f62ac3f2de 100644 --- a/wagtail/admin/views/pages/bulk_actions/publish.py +++ b/wagtail/admin/views/pages/bulk_actions/publish.py @@ -71,35 +71,15 @@ class PublishBulkAction(PageBulkAction): def get_success_message(self, num_parent_objects, num_child_objects): include_descendants = self.cleaned_form.cleaned_data["include_descendants"] - if num_parent_objects == 1: - if include_descendants: - if num_child_objects == 0: - success_message = _("1 page has been published") - else: - success_message = ngettext( - "1 page and %(num_child_objects)d child page have been published", - "1 page and %(num_child_objects)d child pages have been published", - num_child_objects, - ) % {"num_child_objects": num_child_objects} - else: - success_message = _("1 page has been published") + if include_descendants and num_child_objects > 0: + # Translators: This forms a message such as "1 page and 3 child pages have been published" + return _("%(parent_pages)s and %(child_pages)s have been published") % { + "parent_pages": self.get_parent_page_text(num_parent_objects), + "child_pages": self.get_child_page_text(num_child_objects), + } else: - if include_descendants: - if num_child_objects == 0: - success_message = _( - "%(num_parent_objects)d pages have been published" - ) % {"num_parent_objects": num_parent_objects} - else: - success_message = ngettext( - "%(num_parent_objects)d pages and %(num_child_objects)d child page have been published", - "%(num_parent_objects)d pages and %(num_child_objects)d child pages have been published", - num_child_objects, - ) % { - "num_child_objects": num_child_objects, - "num_parent_objects": num_parent_objects, - } - else: - success_message = _( - "%(num_parent_objects)d pages have been published" - ) % {"num_parent_objects": num_parent_objects} - return success_message + return ngettext( + "%(num_parent_objects)d page has been published", + "%(num_parent_objects)d pages have been published", + num_parent_objects, + ) % {"num_parent_objects": num_parent_objects} diff --git a/wagtail/admin/views/pages/bulk_actions/unpublish.py b/wagtail/admin/views/pages/bulk_actions/unpublish.py index 74a64fcc63..1c01d8f98c 100644 --- a/wagtail/admin/views/pages/bulk_actions/unpublish.py +++ b/wagtail/admin/views/pages/bulk_actions/unpublish.py @@ -65,35 +65,15 @@ class UnpublishBulkAction(PageBulkAction): def get_success_message(self, num_parent_objects, num_child_objects): include_descendants = self.cleaned_form.cleaned_data["include_descendants"] - if num_parent_objects == 1: - if include_descendants: - if num_child_objects == 0: - success_message = _("1 page has been unpublished") - else: - success_message = ngettext( - "1 page and %(num_child_objects)d child page have been unpublished", - "1 page and %(num_child_objects)d child pages have been unpublished", - num_child_objects, - ) % {"num_child_objects": num_child_objects} - else: - success_message = _("1 page has been unpublished") + if include_descendants and num_child_objects > 0: + # Translators: This forms a message such as "1 page and 3 child pages have been unpublished" + return _("%(parent_pages)s and %(child_pages)s have been unpublished") % { + "parent_pages": self.get_parent_page_text(num_parent_objects), + "child_pages": self.get_child_page_text(num_child_objects), + } else: - if include_descendants: - if num_child_objects == 0: - success_message = _( - "%(num_parent_objects)d pages have been unpublished" - ) % {"num_parent_objects": num_parent_objects} - else: - success_message = ngettext( - "%(num_parent_objects)d pages and %(num_child_objects)d child page have been unpublished", - "%(num_parent_objects)d pages and %(num_child_objects)d child pages have been unpublished", - num_child_objects, - ) % { - "num_child_objects": num_child_objects, - "num_parent_objects": num_parent_objects, - } - else: - success_message = _( - "%(num_parent_objects)d pages have been unpublished" - ) % {"num_parent_objects": num_parent_objects} - return success_message + return ngettext( + "%(num_parent_objects)d page has been unpublished", + "%(num_parent_objects)d pages have been unpublished", + num_parent_objects, + ) % {"num_parent_objects": num_parent_objects}