diff --git a/django/utils/functional.py b/django/utils/functional.py
index 085a8fc..61c3026 100644
a
|
b
|
def lazy(func, *resultclasses):
|
153 | 153 | __hash__ = object.__hash__ |
154 | 154 | |
155 | 155 | def __mod__(self, rhs): |
| 156 | if hasattr(self, '_mod_key') and self._mod_key in rhs: |
| 157 | self.__args = self.__args[:-1] + (rhs[self._mod_key],) |
156 | 158 | if self._delegate_bytes and not six.PY3: |
157 | 159 | return bytes(self) % rhs |
158 | 160 | elif self._delegate_text: |
… |
… |
def lazy(func, *resultclasses):
|
170 | 172 | @wraps(func) |
171 | 173 | def __wrapper__(*args, **kw): |
172 | 174 | # Creates the proxy object, instead of the actual value. |
173 | | return __proxy__(args, kw) |
| 175 | proxy = __proxy__(args, kw) |
| 176 | if (func.__name__ in ('ngettext', 'ungettext', 'npgettext') and |
| 177 | isinstance(args[-1], six.string_types): |
| 178 | proxy._mod_key = args[-1] |
| 179 | return proxy |
174 | 180 | |
175 | 181 | return __wrapper__ |
176 | 182 | |
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index bd38981..ea6e8ab 100644
a
|
b
|
For a complete discussion on the usage of the following see the
|
747 | 747 | |
748 | 748 | .. function:: ngettext_lazy(singular, plural, number) |
749 | 749 | .. function:: ungettext_lazy(singular, plural, number) |
750 | | .. function:: npgettext_lazy(singular, plural, number) |
| 750 | .. function:: npgettext_lazy(context, singular, plural, number) |
751 | 751 | |
752 | | Same as the non-lazy versions above, but using lazy execution. |
| 752 | Same as the non-lazy versions above, but using lazy execution. As most of |
| 753 | the time, the ``number`` argument is not known at the time you call a lazy |
| 754 | function, you can also pass a dictionary key name in ``number`` which will |
| 755 | have to match a dictionary key at string interpolation time. |
753 | 756 | |
754 | 757 | See :ref:`lazy translations documentation <lazy-translations>`. |
755 | 758 | |
diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt
index 65c6fe2..c2429f3 100644
a
|
b
|
convert them to strings, because they should be converted as late as possible
|
408 | 408 | (so that the correct locale is in effect). This necessitates the use of the |
409 | 409 | helper function described next. |
410 | 410 | |
| 411 | Lazy translations and plural |
| 412 | ---------------------------- |
| 413 | |
| 414 | .. versionadded:: 1.5 |
| 415 | |
| 416 | When using lazy translation for a plural string (``[u]n[p]gettext_lazy``), you |
| 417 | generally don't know the ``number`` argument at the time of the string |
| 418 | definition. Therefore, you are authorized to pass a dictionary key name in place |
| 419 | of an integer as the ``number`` argument. Then, when the string is effectively |
| 420 | translated with a placeholders dictionary, the ``number`` argument will get |
| 421 | substituted by the value of the key in the dictionary:: |
| 422 | |
| 423 | class MyForm(forms.Form): |
| 424 | error_message = ungettext_lazy("You only provide %(num)d argument", |
| 425 | "You only provide %(num)d arguments", 'num') |
| 426 | |
| 427 | def clean(self): |
| 428 | ... |
| 429 | raise forms.ValidationError(self.error_message % {'num': number}) |
| 430 | |
411 | 431 | Joining strings: string_concat() |
412 | 432 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
413 | 433 | |
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..d94e903 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..6a192a3 100644
a
|
b
|
msgid "May"
|
35 | 35 | msgstr "Kann" |
36 | 36 | |
37 | 37 | #: models.py:11 |
| 38 | msgid "%(num)d good result" |
| 39 | msgid_plural "%(num)d good results" |
| 40 | msgstr[0] "%(num)d gutes Resultat" |
| 41 | msgstr[1] "%(num)d guten Resultate" |
| 42 | |
| 43 | #: models.py:11 |
38 | 44 | msgctxt "search" |
39 | 45 | msgid "%d result" |
40 | 46 | msgid_plural "%d results" |
… |
… |
msgstr "Es gibt %(num_comments)s Kommentare"
|
75 | 81 | #: models.py:23 |
76 | 82 | msgctxt "other comment count" |
77 | 83 | msgid "There are %(num_comments)s comments" |
78 | | msgstr "Andere: Es gibt %(num_comments)s Kommentare" |
79 | | No newline at end of file |
| 84 | msgstr "Andere: Es gibt %(num_comments)s Kommentare" |
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 1346383..7932c62 100644
a
|
b
|
from django.utils.safestring import mark_safe, SafeBytes, SafeString, SafeText
|
22 | 22 | from django.utils import six |
23 | 23 | from django.utils.six import PY3 |
24 | 24 | from django.utils.translation import (ugettext, ugettext_lazy, activate, |
25 | | deactivate, gettext_lazy, pgettext, npgettext, to_locale, |
| 25 | deactivate, gettext_lazy, ungettext_lazy, pgettext, npgettext, to_locale, |
26 | 26 | get_language_info, get_language, get_language_from_request, trans_real) |
27 | 27 | |
28 | 28 | |
… |
… |
extended_locale_paths = settings.LOCALE_PATHS + (
|
50 | 50 | ) |
51 | 51 | |
52 | 52 | class TranslationTests(TestCase): |
53 | | |
54 | 53 | def test_override(self): |
55 | 54 | activate('de') |
56 | 55 | with translation.override('pl'): |
… |
… |
class TranslationTests(TestCase):
|
90 | 89 | self.assertEqual(six.text_type(s2), "test") |
91 | 90 | |
92 | 91 | @override_settings(LOCALE_PATHS=extended_locale_paths) |
| 92 | def test_ungettext_lazy(self): |
| 93 | s1 = ungettext_lazy("%(num)d good result", "%(num)d good results", 4) |
| 94 | s2 = ungettext_lazy("%(num)d good result", "%(num)d good results", 'num') |
| 95 | with translation.override('de'): |
| 96 | # s1 form not very useful, as number arg is fixed at definition time |
| 97 | self.assertEqual(s1 % {'num': 1}, "1 guten Resultate") |
| 98 | self.assertEqual(s2 % {'num': 1}, "1 gutes Resultat") |
| 99 | self.assertEqual(s2 % {'num': 4}, "4 guten Resultate") |
| 100 | |
| 101 | @override_settings(LOCALE_PATHS=extended_locale_paths) |
93 | 102 | def test_pgettext(self): |
94 | 103 | trans_real._active = local() |
95 | 104 | trans_real._translations = {} |