1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Fixed #34221 -- Honored translation precedence with mixed plural forms.

This commit is contained in:
Claude Paroz 2024-09-14 19:10:01 +02:00 committed by Sarah Boyce
parent 1f3f0cd8ca
commit b579485d99
2 changed files with 48 additions and 6 deletions

View File

@ -103,11 +103,9 @@ class TranslationCatalog:
yield from cat.keys() yield from cat.keys()
def update(self, trans): def update(self, trans):
# Merge if plural function is the same, else prepend. # Merge if plural function is the same as the top catalog, else prepend.
for cat, plural in zip(self._catalogs, self._plurals): if trans.plural.__code__ == self._plurals[0]:
if trans.plural.__code__ == plural.__code__: self._catalogs[0].update(trans._catalog)
cat.update(trans._catalog)
break
else: else:
self._catalogs.insert(0, trans._catalog.copy()) self._catalogs.insert(0, trans._catalog.copy())
self._plurals.insert(0, trans.plural) self._plurals.insert(0, trans.plural)

View File

@ -8,7 +8,7 @@ import tempfile
from contextlib import contextmanager from contextlib import contextmanager
from importlib import import_module from importlib import import_module
from pathlib import Path from pathlib import Path
from unittest import mock from unittest import mock, skipUnless
from asgiref.local import Local from asgiref.local import Local
@ -17,6 +17,7 @@ from django.apps import AppConfig
from django.conf import settings from django.conf import settings
from django.conf.locale import LANG_INFO from django.conf.locale import LANG_INFO
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.core.management.utils import find_command, popen_wrapper
from django.template import Context, Template from django.template import Context, Template
from django.test import RequestFactory, SimpleTestCase, TestCase, override_settings from django.test import RequestFactory, SimpleTestCase, TestCase, override_settings
from django.utils import translation from django.utils import translation
@ -130,6 +131,49 @@ class TranslationTests(SimpleTestCase):
self.assertEqual(french._catalog[("%d singular", 0)], "%d singulier") self.assertEqual(french._catalog[("%d singular", 0)], "%d singulier")
self.assertEqual(french._catalog[("%(num)d hour", 0)], "%(num)d heure") self.assertEqual(french._catalog[("%(num)d hour", 0)], "%(num)d heure")
@translation.override("fr")
@skipUnless(find_command("msgfmt"), "msgfmt is mandatory for this test")
def test_multiple_plurals_merge(self):
def _create_translation_from_string(content):
with tempfile.TemporaryDirectory() as dirname:
po_path = Path(dirname).joinpath("fr", "LC_MESSAGES", "django.po")
po_path.parent.mkdir(parents=True)
po_path.write_text(content)
errors = popen_wrapper(
["msgfmt", "-o", po_path.with_suffix(".mo"), po_path]
)[1]
if errors:
self.fail(f"msgfmt compilation error: {errors}")
return gettext_module.translation(
domain="django",
localedir=dirname,
languages=["fr"],
)
french = trans_real.catalog()
# Merge a new translation file with different plural forms.
catalog1 = _create_translation_from_string(
'msgid ""\n'
'msgstr ""\n'
'"Content-Type: text/plain; charset=UTF-8\\n"\n'
'"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==0 ? 1 : 2);\\n"\n'
'msgid "I win"\n'
'msgstr "Je perds"\n'
)
french.merge(catalog1)
# Merge a second translation file with plural forms from django.conf.
catalog2 = _create_translation_from_string(
'msgid ""\n'
'msgstr ""\n'
'"Content-Type: text/plain; charset=UTF-8\\n"\n'
'"Plural-Forms: Plural-Forms: nplurals=2; plural=(n > 1);\\n"\n'
'msgid "I win"\n'
'msgstr "Je gagne"\n'
)
french.merge(catalog2)
# Translations from this last one are supposed to win.
self.assertEqual(french.gettext("I win"), "Je gagne")
def test_override(self): def test_override(self):
activate("de") activate("de")
try: try: