Hack to prevent _proxy__kw hack. Not sure it is better though.
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py | |
index f3cc634..d3c9200 100644 | |
--- a/django/utils/translation/__init__.py | |
+++ b/django/utils/translation/__init__.py | |
@@ -80,11 +80,52 @@ def npgettext(context, singular, plural, number): | |
return _trans.npgettext(context, singular, plural, number) | |
gettext_lazy = lazy(gettext, str) | |
-ngettext_lazy = lazy(ngettext, str) | |
ugettext_lazy = lazy(ugettext, six.text_type) | |
-ungettext_lazy = lazy(ungettext, six.text_type) | |
pgettext_lazy = lazy(pgettext, six.text_type) | |
-npgettext_lazy = lazy(npgettext, six.text_type) | |
+ | |
+ | |
+def lazy_number(func, resultclass, number=None, **kwargs): | |
+ class ModClass(resultclass): | |
+ def setup(self, func, **kwargs): | |
+ self.__kw = kwargs | |
+ self.__func = func | |
+ | |
+ def __mod__(self, rhs): | |
+ if isinstance(rhs, dict) and number: | |
+ number_value = rhs[number] | |
+ else: | |
+ number_value = rhs | |
+ self.__kw['number'] = number_value | |
+ result = self.__func(**self.__kw) | |
+ return result % rhs | |
+ | |
+ if isinstance(number, int): | |
+ kwargs['number'] = number | |
+ proxy = lazy(func, *(resultclass,))(**kwargs) | |
+ else: | |
+ def proxyfunc(**kwargs): | |
+ mc = ModClass() | |
+ mc.setup(func, **kwargs) | |
+ return mc | |
+ proxy = lazy(proxyfunc, *(ModClass,))(**kwargs) | |
+ return proxy | |
+ | |
+def ngettext_lazy(singular, plural, number=None): | |
+ return lazy_number( | |
+ ngettext, str, singular=singular, plural=plural, number=number) | |
+ | |
+def ungettext_lazy(singular, plural, number=None): | |
+ return lazy_number( | |
+ ungettext, six.text_type, singular=singular, plural=plural, number=number) | |
+ | |
+def npgettext_lazy(context, singular, plural, number=None): | |
+ return lazy_number( | |
+ npgettext, six.text_type, context=context, singular=singular, plural=plural, number=number) | |
+ | |
+ | |
def activate(language): | |
return _trans.activate(language) | |
diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt | |
index 01f168b..bf09d36 100644 | |
--- a/docs/topics/i18n/translation.txt | |
+++ b/docs/topics/i18n/translation.txt | |
@@ -406,6 +406,33 @@ convert them to strings, because they should be converted as late as possible | |
(so that the correct locale is in effect). This necessitates the use of the | |
helper function described next. | |
+Lazy translations and plural | |
+---------------------------- | |
+ | |
+.. versionadded:: 1.5 | |
+ | |
+When using lazy translation for a plural string (``[u]n[p]gettext_lazy``), you | |
+generally don't know the ``number`` argument at the time of the string | |
+definition. Therefore, you are authorized to pass a dictionary key name in place | |
+of an integer as the ``number`` argument. Then, when the string is effectively | |
+translated with a placeholders dictionary, the ``number`` argument will get | |
+substituted by the value of the key in the dictionary. Alternatively, if the | |
+string contains only one unnamed placeholder, you can also omit passing the | |
+``number`` argument at all. For example:: | |
+ | |
+ class MyForm(forms.Form): | |
+ error1_message = ungettext_lazy("You only provided %(num)d argument", | |
+ "You only provided %(num)d arguments", 'num') | |
+ error2_message = ungettext_lazy("You provided %d argument", | |
+ "You provided %d arguments") | |
+ | |
+ def clean(self): | |
+ if err_1: | |
+ raise forms.ValidationError(self.error1_message % {'num': number}) | |
+ if err_2: | |
+ raise forms.ValidationError(self.error2_message % number) | |
+ | |
+ | |
Joining strings: string_concat() | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo | |
index f825e39..b43f282 100644 | |
Binary files a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo and b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo differ | |
diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po | |
index a471d38..e138bb0 100644 | |
--- a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po | |
+++ b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po | |
@@ -35,6 +35,18 @@ msgid "May" | |
msgstr "Kann" | |
#: models.py:11 | |
+msgid "%d good result" | |
+msgid_plural "%d good results" | |
+msgstr[0] "%d gutes Resultat" | |
+msgstr[1] "%d guten Resultate" | |
+ | |
+#: models.py:11 | |
+msgid "Hi %(name)s, %(num)d good result" | |
+msgid_plural "Hi %(name)s, %(num)d good results" | |
+msgstr[0] "Hallo %(name)s, %(num)d gutes Resultat" | |
+msgstr[1] "Hallo %(name)s, %(num)d guten Resultate" | |
+ | |
+#: models.py:11 | |
msgctxt "search" | |
msgid "%d result" | |
msgid_plural "%d results" | |
@@ -75,4 +87,4 @@ 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" | |
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py | |
index d9843c2..b06616f 100644 | |
--- a/tests/regressiontests/i18n/tests.py | |
+++ b/tests/regressiontests/i18n/tests.py | |
@@ -23,7 +23,7 @@ from django.utils.safestring import mark_safe, SafeBytes, SafeString, SafeText | |
from django.utils import six | |
from django.utils.six import PY3 | |
from django.utils.translation import (ugettext, ugettext_lazy, activate, | |
- deactivate, gettext_lazy, pgettext, npgettext, to_locale, | |
+ deactivate, gettext_lazy, ungettext_lazy, pgettext, npgettext, to_locale, | |
get_language_info, get_language, get_language_from_request, trans_real) | |
@@ -52,7 +52,6 @@ extended_locale_paths = settings.LOCALE_PATHS + ( | |
) | |
class TranslationTests(TestCase): | |
- | |
def test_override(self): | |
activate('de') | |
with translation.override('pl'): | |
@@ -96,6 +95,20 @@ class TranslationTests(TestCase): | |
self.assertEqual(six.text_type(s2), "test") | |
@override_settings(LOCALE_PATHS=extended_locale_paths) | |
+ def test_ungettext_lazy(self): | |
+ s = ungettext_lazy("%d good result", "%d good result") | |
+ with translation.override('de'): | |
+ self.assertEqual(s % 1, "1 gutes Resultat") | |
+ self.assertEqual(s % 4, "4 guten Resultate") | |
+ | |
+ s1 = ungettext_lazy("Hi %(name)s, %(num)d good result", "Hi %(name)s, %(num)d good results", 4) | |
+ s2 = ungettext_lazy("Hi %(name)s, %(num)d good result", "Hi %(name)s, %(num)d good results", 'num') | |
+ with translation.override('de'): | |
+ self.assertEqual(s1 % {'num': 4, 'name': 'Jim'}, "Hallo Jim, 4 guten Resultate") | |
+ self.assertEqual(s2 % {'name': 'Jim', 'num': 1}, "Hallo Jim, 1 gutes Resultat") | |
+ self.assertEqual(s2 % {'name': 'Jim', 'num': 5}, "Hallo Jim, 5 guten Resultate") | |
+ | |
+ @override_settings(LOCALE_PATHS=extended_locale_paths) | |
def test_pgettext(self): | |
trans_real._active = local() | |
trans_real._translations = {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment