mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #34221 -- Honored translation precedence with mixed plural forms.
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						parent
						
							1f3f0cd8ca
						
					
				
				
					commit
					b579485d99
				
			| @@ -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) | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user