diff --git a/docs/topics/i18n.txt b/docs/topics/i18n.txt index 86c03221aa6..7bf51c11c59 100644 --- a/docs/topics/i18n.txt +++ b/docs/topics/i18n.txt @@ -223,7 +223,19 @@ Pluralization ~~~~~~~~~~~~~ Use the function ``django.utils.translation.ungettext()`` to specify pluralized -messages. Example:: +messages. + +``ungettext`` takes three arguments: the singular translation string, the plural +translation string and the number of objects. + +This function is useful when your need you Django application to be localizable +to languages where the number and complexity of `plural forms +`_ is +greater than the two forms used in English ('object' for the singular and +'objects' for all the cases where ``count`` is different from zero, irrespective +of its value.) + +For example:: from django.utils.translation import ungettext def hello_world(request, count): @@ -232,9 +244,61 @@ messages. Example:: } return HttpResponse(page) -``ungettext`` takes three arguments: the singular translation string, the plural -translation string and the number of objects (which is passed to the -translation languages as the ``count`` variable). +In this example the number of objects is passed to the translation languages as +the ``count`` variable. + +Lets see a slightly more complex usage example:: + + from django.utils.translation import ungettext + + count = Report.objects.count() + if count == 1: + name = Report._meta.verbose_name + else: + name = Report._meta.verbose_name_plural + + text = ungettext( + 'There is %(count)d %(name)s available.', + 'There are %(count)d %(name)s available.', + count + ) % { + 'count': count, + 'name': name + } + +Here we reuse localizable, hopefully already translated literals (contained in +the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for +other parts of the sentence so all of it is consistently based on the +cardinality of the elements at play. + +.. _pluralization-var-notes: + +.. note:: + + When using this technique, make sure you use a single name for every + extrapolated variable included in the literal. In the example above note how + we used the ``name`` Python variable in both translation strings. This + example would fail:: + + from django.utils.translation import ungettext + from myapp.models import Report + + count = Report.objects.count() + d = { + 'count': count, + 'name': Report._meta.verbose_name + 'plural_name': Report._meta.verbose_name_plural + } + text = ungettext( + 'There is %(count)d %(name)s available.', + 'There are %(count)d %(plural_name)s available.', + count + ) % d + + You would get a ``a format specification for argument 'name', as in + 'msgstr[0]', doesn't exist in 'msgid'`` error when running + ``django-admin.py compilemessages`` or a ``KeyError`` Python exception at + runtime. In template code ---------------- @@ -257,6 +321,8 @@ content that will require translation in the future:: {% trans "myvar" noop %} +Internally, inline translations use an ``ugettext`` call. + It's not possible to mix a template variable inside a string within ``{% trans %}``. If your translations require strings with variables (placeholders), use ``{% blocktrans %}``:: @@ -288,8 +354,11 @@ To pluralize, specify both the singular and plural forms with the There are {{ counter }} {{ name }} objects. {% endblocktrans %} -Internally, all block and inline translations use the appropriate -``ugettext`` / ``ungettext`` call. +When you use the pluralization feature and bind additional values to local +variables apart from the counter value that selects the translated literal to be +used, have in mind that the ``blocktrans`` construct is internally converted +to an ``ungettext`` call. This means the same :ref:`notes regarding ungettext +variables ` apply. Each ``RequestContext`` has access to three translation-specific variables: