From ae180fa4b7f927a4aeae772975927c9888bb0cb0 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sun, 25 Nov 2018 21:50:34 +0000 Subject: [PATCH] Fixed #29986 -- Added .format() support to ngettext_lazy strings. --- django/utils/translation/__init__.py | 30 ++++++++++------ .../other/locale/de/LC_MESSAGES/django.mo | Bin 2070 -> 2587 bytes .../other/locale/de/LC_MESSAGES/django.po | 28 ++++++++++++++- tests/i18n/tests.py | 33 ++++++++++++++++++ 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index 7f5600be04..b1df722428 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -110,20 +110,30 @@ def lazy_number(func, resultclass, number=None, **kwargs): def __bool__(self): return bool(kwargs['singular']) + def _get_number_value(self, values): + try: + return values[number] + except KeyError: + raise KeyError( + "Your dictionary lacks key '%s\'. Please provide " + "it, because it is required to determine whether " + "string is singular or plural." % number + ) + + def _translate(self, number_value): + kwargs['number'] = number_value + return func(**kwargs) + + def format(self, *args, **kwargs): + number_value = self._get_number_value(kwargs) if kwargs and number else args[0] + return self._translate(number_value).format(*args, **kwargs) + def __mod__(self, rhs): if isinstance(rhs, dict) and number: - try: - number_value = rhs[number] - except KeyError: - raise KeyError( - "Your dictionary lacks key '%s\'. Please provide " - "it, because it is required to determine whether " - "string is singular or plural." % number - ) + number_value = self._get_number_value(rhs) else: number_value = rhs - kwargs['number'] = number_value - translated = func(**kwargs) + translated = self._translate(number_value) try: translated = translated % rhs except TypeError: diff --git a/tests/i18n/other/locale/de/LC_MESSAGES/django.mo b/tests/i18n/other/locale/de/LC_MESSAGES/django.mo index ef64b650ec8b1f316a2d1162f32d66eecb857338..a8716118b7e23c34c38100ae78d612f0f5aee38f 100644 GIT binary patch delta 808 zcmZY6%}X0W7{~Evw{dN)uZh-F8(Gmx>PtbPh?XAe8-gIwi_#+PQkN34FKQAjgw%`p z4=f7eLGT~Yl7j~iy_B8{g`P^$tG8af34SL=F>&D8&+P2%%x`vg8uywv{)I!^LTjO( zQ9q~{ zlz|AN_1KTY_!`GCjqP}hZ}2xh#HOn2KyCPea3iRK?iwQ9c#co8p<1K|UzAMXBKPZ< zV1M~VXO@9ZR-M8XR3|;g2>!t?JTHycb9^$(0QTV^PT&%%gB;*1JVCO`e^h}kP<>SO z?qiC)V#K*LQa6n~imicb6GgUSYYtYmNIXnm{V4UFSWRlF8cJb1Q&&vNa2znSy0Zuz9?B!hPz297>A zP&rt(Y~{nkp`O$_?(Kc|ophl!6xCbQoNUHUoAbqhR;E*Bj2WruLeg~K|Qa-cr(@1E~@9oK!#T4Fc3R|uKlF9$4^_;7@~c#S&gE3RP|=`A7C zFvno6e?VW!61@#(l~JOVCwiM>`a;oHGDLqyi{l2xg$y?f{xf*=zb5NDX3L-2IUk#H a^kSPqR7)0(zeqRynM?Uaw--IT&EOBT1}td+ diff --git a/tests/i18n/other/locale/de/LC_MESSAGES/django.po b/tests/i18n/other/locale/de/LC_MESSAGES/django.po index 822fa3796b..bbb2b02858 100644 --- a/tests/i18n/other/locale/de/LC_MESSAGES/django.po +++ b/tests/i18n/other/locale/de/LC_MESSAGES/django.po @@ -107,4 +107,30 @@ msgstr "Es gibt %(num_comments)s Kommentare" #: models.py:23 msgctxt "other comment count" msgid "There are %(num_comments)s comments" -msgstr "Andere: Es gibt %(num_comments)s Kommentare" \ No newline at end of file +msgstr "Andere: Es gibt %(num_comments)s Kommentare" + +#: tests.py:213 +msgid "{} good result" +msgid_plural "{} good results" +msgstr[0] "{} gutes Resultat" +msgstr[1] "{} guten Resultate" + +#: tests.py:214 +msgctxt "Exclamation" +msgid "{} good result" +msgid_plural "{} good results" +msgstr[0] "{} gutes Resultat!" +msgstr[1] "{} guten Resultate!" + +#: tests.py:226 +msgid "Hi {name}, {num} good result" +msgid_plural "Hi {name}, {num} good results" +msgstr[0] "Hallo {name}, {num} gutes Resultat" +msgstr[1] "Hallo {name}, {num} guten Resultate" + +#: tests.py:230 +msgctxt "Greeting" +msgid "Hi {name}, {num} good result" +msgid_plural "Hi {name}, {num} good results" +msgstr[0] "Willkommen {name}, {num} gutes Resultat" +msgstr[1] "Willkommen {name}, {num} guten Resultate" diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 317a380a2f..7b54089cf2 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -208,6 +208,39 @@ class TranslationTests(SimpleTestCase): with self.assertRaisesMessage(KeyError, 'Your dictionary lacks key'): complex_context_deferred % {'name': 'Jim'} + @override_settings(LOCALE_PATHS=extended_locale_paths) + def test_ngettext_lazy_format_style(self): + simple_with_format = ngettext_lazy('{} good result', '{} good results') + simple_context_with_format = npgettext_lazy('Exclamation', '{} good result', '{} good results') + + with translation.override('de'): + self.assertEqual(simple_with_format.format(1), '1 gutes Resultat') + self.assertEqual(simple_with_format.format(4), '4 guten Resultate') + self.assertEqual(simple_context_with_format.format(1), '1 gutes Resultat!') + self.assertEqual(simple_context_with_format.format(4), '4 guten Resultate!') + + complex_nonlazy = ngettext_lazy('Hi {name}, {num} good result', 'Hi {name}, {num} good results', 4) + complex_deferred = ngettext_lazy( + 'Hi {name}, {num} good result', 'Hi {name}, {num} good results', 'num' + ) + complex_context_nonlazy = npgettext_lazy( + 'Greeting', 'Hi {name}, {num} good result', 'Hi {name}, {num} good results', 4 + ) + complex_context_deferred = npgettext_lazy( + 'Greeting', 'Hi {name}, {num} good result', 'Hi {name}, {num} good results', 'num' + ) + with translation.override('de'): + self.assertEqual(complex_nonlazy.format(num=4, name='Jim'), 'Hallo Jim, 4 guten Resultate') + self.assertEqual(complex_deferred.format(name='Jim', num=1), 'Hallo Jim, 1 gutes Resultat') + self.assertEqual(complex_deferred.format(name='Jim', num=5), 'Hallo Jim, 5 guten Resultate') + with self.assertRaisesMessage(KeyError, 'Your dictionary lacks key'): + complex_deferred.format(name='Jim') + self.assertEqual(complex_context_nonlazy.format(num=4, name='Jim'), 'Willkommen Jim, 4 guten Resultate') + self.assertEqual(complex_context_deferred.format(name='Jim', num=1), 'Willkommen Jim, 1 gutes Resultat') + self.assertEqual(complex_context_deferred.format(name='Jim', num=5), 'Willkommen Jim, 5 guten Resultate') + with self.assertRaisesMessage(KeyError, 'Your dictionary lacks key'): + complex_context_deferred.format(name='Jim') + def test_ngettext_lazy_bool(self): self.assertTrue(ngettext_lazy('%d good result', '%d good results')) self.assertFalse(ngettext_lazy('', ''))