parts/django/docs/topics/i18n/internationalization.txt
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 ====================
       
     2 Internationalization
       
     3 ====================
       
     4 
       
     5 Overview
       
     6 ========
       
     7 
       
     8 The goal of internationalization is to allow a single Web application to offer
       
     9 its content and functionality in multiple languages and locales.
       
    10 
       
    11 For text translations, you, the Django developer, can accomplish this goal by
       
    12 adding a minimal amount of hooks to your Python and templates. These hooks
       
    13 are called **translation strings**. They tell Django: "This text should be
       
    14 translated into the end user's language, if a translation for this text is
       
    15 available in that language." It's your responsibility to mark translatable
       
    16 strings; the system can only translate strings it knows about.
       
    17 
       
    18 Django takes care of using these hooks to translate Web apps, on the fly,
       
    19 according to users' language preferences.
       
    20 
       
    21 Specifying translation strings: In Python code
       
    22 ==============================================
       
    23 
       
    24 Standard translation
       
    25 --------------------
       
    26 
       
    27 Specify a translation string by using the function ``ugettext()``. It's
       
    28 convention to import this as a shorter alias, ``_``, to save typing.
       
    29 
       
    30 .. note::
       
    31     Python's standard library ``gettext`` module installs ``_()`` into the
       
    32     global namespace, as an alias for ``gettext()``. In Django, we have chosen
       
    33     not to follow this practice, for a couple of reasons:
       
    34 
       
    35       1. For international character set (Unicode) support, ``ugettext()`` is
       
    36          more useful than ``gettext()``. Sometimes, you should be using
       
    37          ``ugettext_lazy()`` as the default translation method for a particular
       
    38          file. Without ``_()`` in the global namespace, the developer has to
       
    39          think about which is the most appropriate translation function.
       
    40 
       
    41       2. The underscore character (``_``) is used to represent "the previous
       
    42          result" in Python's interactive shell and doctest tests. Installing a
       
    43          global ``_()`` function causes interference. Explicitly importing
       
    44          ``ugettext()`` as ``_()`` avoids this problem.
       
    45 
       
    46 .. highlightlang:: python
       
    47 
       
    48 In this example, the text ``"Welcome to my site."`` is marked as a translation
       
    49 string::
       
    50 
       
    51     from django.utils.translation import ugettext as _
       
    52 
       
    53     def my_view(request):
       
    54         output = _("Welcome to my site.")
       
    55         return HttpResponse(output)
       
    56 
       
    57 Obviously, you could code this without using the alias. This example is
       
    58 identical to the previous one::
       
    59 
       
    60     from django.utils.translation import ugettext
       
    61 
       
    62     def my_view(request):
       
    63         output = ugettext("Welcome to my site.")
       
    64         return HttpResponse(output)
       
    65 
       
    66 Translation works on computed values. This example is identical to the previous
       
    67 two::
       
    68 
       
    69     def my_view(request):
       
    70         words = ['Welcome', 'to', 'my', 'site.']
       
    71         output = _(' '.join(words))
       
    72         return HttpResponse(output)
       
    73 
       
    74 Translation works on variables. Again, here's an identical example::
       
    75 
       
    76     def my_view(request):
       
    77         sentence = 'Welcome to my site.'
       
    78         output = _(sentence)
       
    79         return HttpResponse(output)
       
    80 
       
    81 (The caveat with using variables or computed values, as in the previous two
       
    82 examples, is that Django's translation-string-detecting utility,
       
    83 ``django-admin.py makemessages``, won't be able to find these strings. More on
       
    84 ``makemessages`` later.)
       
    85 
       
    86 The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
       
    87 specified with Python's standard named-string interpolation syntax. Example::
       
    88 
       
    89     def my_view(request, m, d):
       
    90         output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
       
    91         return HttpResponse(output)
       
    92 
       
    93 This technique lets language-specific translations reorder the placeholder
       
    94 text. For example, an English translation may be ``"Today is November 26."``,
       
    95 while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the
       
    96 the month and the day placeholders swapped.
       
    97 
       
    98 For this reason, you should use named-string interpolation (e.g., ``%(day)s``)
       
    99 instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you
       
   100 have more than a single parameter. If you used positional interpolation,
       
   101 translations wouldn't be able to reorder placeholder text.
       
   102 
       
   103 Marking strings as no-op
       
   104 ------------------------
       
   105 
       
   106 Use the function ``django.utils.translation.ugettext_noop()`` to mark a string
       
   107 as a translation string without translating it. The string is later translated
       
   108 from a variable.
       
   109 
       
   110 Use this if you have constant strings that should be stored in the source
       
   111 language because they are exchanged over systems or users -- such as strings in
       
   112 a database -- but should be translated at the last possible point in time, such
       
   113 as when the string is presented to the user.
       
   114 
       
   115 Pluralization
       
   116 -------------
       
   117 
       
   118 Use the function ``django.utils.translation.ungettext()`` to specify pluralized
       
   119 messages.
       
   120 
       
   121 ``ungettext`` takes three arguments: the singular translation string, the plural
       
   122 translation string and the number of objects.
       
   123 
       
   124 This function is useful when you need your Django application to be localizable
       
   125 to languages where the number and complexity of `plural forms
       
   126 <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is
       
   127 greater than the two forms used in English ('object' for the singular and
       
   128 'objects' for all the cases where ``count`` is different from zero, irrespective
       
   129 of its value.)
       
   130 
       
   131 For example::
       
   132 
       
   133     from django.utils.translation import ungettext
       
   134     def hello_world(request, count):
       
   135         page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % {
       
   136             'count': count,
       
   137         }
       
   138         return HttpResponse(page)
       
   139 
       
   140 In this example the number of objects is passed to the translation languages as
       
   141 the ``count`` variable.
       
   142 
       
   143 Lets see a slightly more complex usage example::
       
   144 
       
   145     from django.utils.translation import ungettext
       
   146 
       
   147     count = Report.objects.count()
       
   148     if count == 1:
       
   149         name = Report._meta.verbose_name
       
   150     else:
       
   151         name = Report._meta.verbose_name_plural
       
   152 
       
   153     text = ungettext(
       
   154             'There is %(count)d %(name)s available.',
       
   155             'There are %(count)d %(name)s available.',
       
   156             count
       
   157     ) % {
       
   158         'count': count,
       
   159         'name': name
       
   160     }
       
   161 
       
   162 Here we reuse localizable, hopefully already translated literals (contained in
       
   163 the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for
       
   164 other parts of the sentence so all of it is consistently based on the
       
   165 cardinality of the elements at play.
       
   166 
       
   167 .. _pluralization-var-notes:
       
   168 
       
   169 .. note::
       
   170 
       
   171     When using this technique, make sure you use a single name for every
       
   172     extrapolated variable included in the literal. In the example above note how
       
   173     we used the ``name`` Python variable in both translation strings. This
       
   174     example would fail::
       
   175 
       
   176         from django.utils.translation import ungettext
       
   177         from myapp.models import Report
       
   178 
       
   179         count = Report.objects.count()
       
   180         d = {
       
   181             'count': count,
       
   182             'name': Report._meta.verbose_name,
       
   183             'plural_name': Report._meta.verbose_name_plural
       
   184         }
       
   185         text = ungettext(
       
   186                 'There is %(count)d %(name)s available.',
       
   187                 'There are %(count)d %(plural_name)s available.',
       
   188                 count
       
   189         ) % d
       
   190 
       
   191     You would get a ``a format specification for argument 'name', as in
       
   192     'msgstr[0]', doesn't exist in 'msgid'`` error when running
       
   193     ``django-admin.py compilemessages``.
       
   194 
       
   195 .. _lazy-translations:
       
   196 
       
   197 Lazy translation
       
   198 ----------------
       
   199 
       
   200 Use the function ``django.utils.translation.ugettext_lazy()`` to translate
       
   201 strings lazily -- when the value is accessed rather than when the
       
   202 ``ugettext_lazy()`` function is called.
       
   203 
       
   204 For example, to translate a model's ``help_text``, do the following::
       
   205 
       
   206     from django.utils.translation import ugettext_lazy
       
   207 
       
   208     class MyThing(models.Model):
       
   209         name = models.CharField(help_text=ugettext_lazy('This is the help text'))
       
   210 
       
   211 In this example, ``ugettext_lazy()`` stores a lazy reference to the string --
       
   212 not the actual translation. The translation itself will be done when the string
       
   213 is used in a string context, such as template rendering on the Django admin
       
   214 site.
       
   215 
       
   216 The result of a ``ugettext_lazy()`` call can be used wherever you would use a
       
   217 unicode string (an object with type ``unicode``) in Python. If you try to use
       
   218 it where a bytestring (a ``str`` object) is expected, things will not work as
       
   219 expected, since a ``ugettext_lazy()`` object doesn't know how to convert
       
   220 itself to a bytestring.  You can't use a unicode string inside a bytestring,
       
   221 either, so this is consistent with normal Python behavior. For example::
       
   222 
       
   223     # This is fine: putting a unicode proxy into a unicode string.
       
   224     u"Hello %s" % ugettext_lazy("people")
       
   225 
       
   226     # This will not work, since you cannot insert a unicode object
       
   227     # into a bytestring (nor can you insert our unicode proxy there)
       
   228     "Hello %s" % ugettext_lazy("people")
       
   229 
       
   230 If you ever see output that looks like ``"hello
       
   231 <django.utils.functional...>"``, you have tried to insert the result of
       
   232 ``ugettext_lazy()`` into a bytestring. That's a bug in your code.
       
   233 
       
   234 If you don't like the verbose name ``ugettext_lazy``, you can just alias it as
       
   235 ``_`` (underscore), like so::
       
   236 
       
   237     from django.utils.translation import ugettext_lazy as _
       
   238 
       
   239     class MyThing(models.Model):
       
   240         name = models.CharField(help_text=_('This is the help text'))
       
   241 
       
   242 Always use lazy translations in :doc:`Django models </topics/db/models>`.
       
   243 Field names and table names should be marked for translation (otherwise, they
       
   244 won't be translated in the admin interface). This means writing explicit
       
   245 ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,
       
   246 though, rather than relying on Django's default determination of
       
   247 ``verbose_name`` and ``verbose_name_plural`` by looking at the model's class
       
   248 name::
       
   249 
       
   250     from django.utils.translation import ugettext_lazy as _
       
   251 
       
   252     class MyThing(models.Model):
       
   253         name = models.CharField(_('name'), help_text=_('This is the help text'))
       
   254         class Meta:
       
   255             verbose_name = _('my thing')
       
   256             verbose_name_plural = _('mythings')
       
   257 
       
   258 Working with lazy translation objects
       
   259 -------------------------------------
       
   260 
       
   261 .. highlightlang:: python
       
   262 
       
   263 Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models
       
   264 and utility functions is a common operation. When you're working with these
       
   265 objects elsewhere in your code, you should ensure that you don't accidentally
       
   266 convert them to strings, because they should be converted as late as possible
       
   267 (so that the correct locale is in effect). This necessitates the use of a
       
   268 couple of helper functions.
       
   269 
       
   270 Joining strings: string_concat()
       
   271 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   272 
       
   273 Standard Python string joins (``''.join([...])``) will not work on lists
       
   274 containing lazy translation objects. Instead, you can use
       
   275 ``django.utils.translation.string_concat()``, which creates a lazy object that
       
   276 concatenates its contents *and* converts them to strings only when the result
       
   277 is included in a string. For example::
       
   278 
       
   279     from django.utils.translation import string_concat
       
   280     ...
       
   281     name = ugettext_lazy(u'John Lennon')
       
   282     instrument = ugettext_lazy(u'guitar')
       
   283     result = string_concat(name, ': ', instrument)
       
   284 
       
   285 In this case, the lazy translations in ``result`` will only be converted to
       
   286 strings when ``result`` itself is used in a string (usually at template
       
   287 rendering time).
       
   288 
       
   289 The allow_lazy() decorator
       
   290 ~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   291 
       
   292 Django offers many utility functions (particularly in ``django.utils``) that
       
   293 take a string as their first argument and do something to that string. These
       
   294 functions are used by template filters as well as directly in other code.
       
   295 
       
   296 If you write your own similar functions and deal with translations, you'll
       
   297 face the problem of what to do when the first argument is a lazy translation
       
   298 object. You don't want to convert it to a string immediately, because you might
       
   299 be using this function outside of a view (and hence the current thread's locale
       
   300 setting will not be correct).
       
   301 
       
   302 For cases like this, use the ``django.utils.functional.allow_lazy()``
       
   303 decorator. It modifies the function so that *if* it's called with a lazy
       
   304 translation as the first argument, the function evaluation is delayed until it
       
   305 needs to be converted to a string.
       
   306 
       
   307 For example::
       
   308 
       
   309     from django.utils.functional import allow_lazy
       
   310 
       
   311     def fancy_utility_function(s, ...):
       
   312         # Do some conversion on string 's'
       
   313         ...
       
   314     fancy_utility_function = allow_lazy(fancy_utility_function, unicode)
       
   315 
       
   316 The ``allow_lazy()`` decorator takes, in addition to the function to decorate,
       
   317 a number of extra arguments (``*args``) specifying the type(s) that the
       
   318 original function can return. Usually, it's enough to include ``unicode`` here
       
   319 and ensure that your function returns only Unicode strings.
       
   320 
       
   321 Using this decorator means you can write your function and assume that the
       
   322 input is a proper string, then add support for lazy translation objects at the
       
   323 end.
       
   324 
       
   325 .. _specifying-translation-strings-in-template-code:
       
   326 
       
   327 Specifying translation strings: In template code
       
   328 ================================================
       
   329 
       
   330 .. highlightlang:: html+django
       
   331 
       
   332 Translations in :doc:`Django templates </topics/templates>` uses two template
       
   333 tags and a slightly different syntax than in Python code. To give your template
       
   334 access to these tags, put ``{% load i18n %}`` toward the top of your template.
       
   335 
       
   336 ``trans`` template tag
       
   337 ----------------------
       
   338 
       
   339 The ``{% trans %}`` template tag translates either a constant string
       
   340 (enclosed in single or double quotes) or variable content::
       
   341 
       
   342     <title>{% trans "This is the title." %}</title>
       
   343     <title>{% trans myvar %}</title>
       
   344 
       
   345 If the ``noop`` option is present, variable lookup still takes place but the
       
   346 translation is skipped. This is useful when "stubbing out" content that will
       
   347 require translation in the future::
       
   348 
       
   349     <title>{% trans "myvar" noop %}</title>
       
   350 
       
   351 Internally, inline translations use an ``ugettext`` call.
       
   352 
       
   353 In case a template var (``myvar`` above) is passed to the tag, the tag will
       
   354 first resolve such variable to a string at run-time and then look up that
       
   355 string in the message catalogs.
       
   356 
       
   357 It's not possible to mix a template variable inside a string within ``{% trans
       
   358 %}``. If your translations require strings with variables (placeholders), use
       
   359 ``{% blocktrans %}`` instead.
       
   360 
       
   361 ``blocktrans`` template tag
       
   362 ---------------------------
       
   363 
       
   364 Contrarily to the ``trans`` tag, the ``blocktrans`` tag allows you to mark
       
   365 complex sentences consisting of literals and variable content for translation
       
   366 by making use of placeholders::
       
   367 
       
   368     {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
       
   369 
       
   370 To translate a template expression -- say, accessing object attributes or
       
   371 using template filters -- you need to bind the expression to a local variable
       
   372 for use within the translation block. Examples::
       
   373 
       
   374     {% blocktrans with article.price as amount %}
       
   375     That will cost $ {{ amount }}.
       
   376     {% endblocktrans %}
       
   377 
       
   378     {% blocktrans with value|filter as myvar %}
       
   379     This will have {{ myvar }} inside.
       
   380     {% endblocktrans %}
       
   381 
       
   382 If you need to bind more than one expression inside a ``blocktrans`` tag,
       
   383 separate the pieces with ``and``::
       
   384 
       
   385     {% blocktrans with book|title as book_t and author|title as author_t %}
       
   386     This is {{ book_t }} by {{ author_t }}
       
   387     {% endblocktrans %}
       
   388 
       
   389 This tag also provides for pluralization. To use it:
       
   390 
       
   391     * Designate and bind a counter value with the name ``count``. This value will
       
   392       be the one used to select the right plural form.
       
   393 
       
   394     * Specify both the singular and plural forms separating them with the
       
   395       ``{% plural %}`` tag within the ``{% blocktrans %}`` and
       
   396       ``{% endblocktrans %}`` tags.
       
   397 
       
   398 An example::
       
   399 
       
   400     {% blocktrans count list|length as counter %}
       
   401     There is only one {{ name }} object.
       
   402     {% plural %}
       
   403     There are {{ counter }} {{ name }} objects.
       
   404     {% endblocktrans %}
       
   405 
       
   406 A more complex example::
       
   407 
       
   408     {% blocktrans with article.price as amount count i.length as years %}
       
   409     That will cost $ {{ amount }} per year.
       
   410     {% plural %}
       
   411     That will cost $ {{ amount }} per {{ years }} years.
       
   412     {% endblocktrans %}
       
   413 
       
   414 When you use both the pluralization feature and bind values to local variables
       
   415 in addition to the counter value, keep in mind that the ``blocktrans``
       
   416 construct is internally converted to an ``ungettext`` call. This means the
       
   417 same :ref:`notes regarding ungettext variables <pluralization-var-notes>`
       
   418 apply.
       
   419 
       
   420 .. _template-translation-vars:
       
   421 
       
   422 Other tags
       
   423 ----------
       
   424 
       
   425 Each ``RequestContext`` has access to three translation-specific variables:
       
   426 
       
   427     * ``LANGUAGES`` is a list of tuples in which the first element is the
       
   428       :term:`language code` and the second is the language name (translated into
       
   429       the currently active locale).
       
   430 
       
   431     * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
       
   432       Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.)
       
   433 
       
   434     * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a
       
   435       right-to-left language, e.g.: Hebrew, Arabic. If False it's a
       
   436       left-to-right language, e.g.: English, French, German etc.
       
   437 
       
   438 If you don't use the ``RequestContext`` extension, you can get those values with
       
   439 three tags::
       
   440 
       
   441     {% get_current_language as LANGUAGE_CODE %}
       
   442     {% get_available_languages as LANGUAGES %}
       
   443     {% get_current_language_bidi as LANGUAGE_BIDI %}
       
   444 
       
   445 These tags also require a ``{% load i18n %}``.
       
   446 
       
   447 Translation hooks are also available within any template block tag that accepts
       
   448 constant strings. In those cases, just use ``_()`` syntax to specify a
       
   449 translation string::
       
   450 
       
   451     {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
       
   452 
       
   453 In this case, both the tag and the filter will see the already-translated
       
   454 string, so they don't need to be aware of translations.
       
   455 
       
   456 .. note::
       
   457     In this example, the translation infrastructure will be passed the string
       
   458     ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
       
   459     translated string will need to contain the comma so that the filter
       
   460     parsing code knows how to split up the arguments. For example, a German
       
   461     translator might translate the string ``"yes,no"`` as ``"ja,nein"``
       
   462     (keeping the comma intact).
       
   463 
       
   464 .. _Django templates: ../templates_python/
       
   465 
       
   466 Specifying translation strings: In JavaScript code
       
   467 ==================================================
       
   468 
       
   469 Adding translations to JavaScript poses some problems:
       
   470 
       
   471     * JavaScript code doesn't have access to a ``gettext`` implementation.
       
   472 
       
   473     * JavaScript code doesn't have access to .po or .mo files; they need to be
       
   474       delivered by the server.
       
   475 
       
   476     * The translation catalogs for JavaScript should be kept as small as
       
   477       possible.
       
   478 
       
   479 Django provides an integrated solution for these problems: It passes the
       
   480 translations into JavaScript, so you can call ``gettext``, etc., from within
       
   481 JavaScript.
       
   482 
       
   483 The ``javascript_catalog`` view
       
   484 -------------------------------
       
   485 
       
   486 .. module:: django.views.i18n
       
   487 
       
   488 .. function:: javascript_catalog(request, domain='djangojs', packages=None)
       
   489 
       
   490 The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog`
       
   491 view, which sends out a JavaScript code library with functions that mimic the
       
   492 ``gettext`` interface, plus an array of translation strings. Those translation
       
   493 strings are taken from the application, project or Django core, according to what
       
   494 you specify in either the info_dict or the URL.
       
   495 
       
   496 You hook it up like this::
       
   497 
       
   498     js_info_dict = {
       
   499         'packages': ('your.app.package',),
       
   500     }
       
   501 
       
   502     urlpatterns = patterns('',
       
   503         (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
       
   504     )
       
   505 
       
   506 Each string in ``packages`` should be in Python dotted-package syntax (the
       
   507 same format as the strings in ``INSTALLED_APPS``) and should refer to a package
       
   508 that contains a ``locale`` directory. If you specify multiple packages, all
       
   509 those catalogs are merged into one catalog. This is useful if you have
       
   510 JavaScript that uses strings from different applications.
       
   511 
       
   512 By default, the view uses the ``djangojs`` gettext domain. This can be
       
   513 changed by altering the ``domain`` argument.
       
   514 
       
   515 You can make the view dynamic by putting the packages into the URL pattern::
       
   516 
       
   517     urlpatterns = patterns('',
       
   518         (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
       
   519     )
       
   520 
       
   521 With this, you specify the packages as a list of package names delimited by '+'
       
   522 signs in the URL. This is especially useful if your pages use code from
       
   523 different apps and this changes often and you don't want to pull in one big
       
   524 catalog file. As a security measure, these values can only be either
       
   525 ``django.conf`` or any package from the ``INSTALLED_APPS`` setting.
       
   526 
       
   527 Using the JavaScript translation catalog
       
   528 ----------------------------------------
       
   529 
       
   530 To use the catalog, just pull in the dynamically generated script like this::
       
   531 
       
   532     <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>
       
   533 
       
   534 This uses reverse URL lookup to find the URL of the JavaScript catalog view.
       
   535 When the catalog is loaded, your JavaScript code can use the standard
       
   536 ``gettext`` interface to access it::
       
   537 
       
   538     document.write(gettext('this is to be translated'));
       
   539 
       
   540 There is also an ``ngettext`` interface::
       
   541 
       
   542     var object_cnt = 1 // or 0, or 2, or 3, ...
       
   543     s = ngettext('literal for the singular case',
       
   544             'literal for the plural case', object_cnt);
       
   545 
       
   546 and even a string interpolation function::
       
   547 
       
   548     function interpolate(fmt, obj, named);
       
   549 
       
   550 The interpolation syntax is borrowed from Python, so the ``interpolate``
       
   551 function supports both positional and named interpolation:
       
   552 
       
   553     * Positional interpolation: ``obj`` contains a JavaScript Array object
       
   554       whose elements values are then sequentially interpolated in their
       
   555       corresponding ``fmt`` placeholders in the same order they appear.
       
   556       For example::
       
   557 
       
   558         fmts = ngettext('There is %s object. Remaining: %s',
       
   559                 'There are %s objects. Remaining: %s', 11);
       
   560         s = interpolate(fmts, [11, 20]);
       
   561         // s is 'There are 11 objects. Remaining: 20'
       
   562 
       
   563     * Named interpolation: This mode is selected by passing the optional
       
   564       boolean ``named`` parameter as true. ``obj`` contains a JavaScript
       
   565       object or associative array. For example::
       
   566 
       
   567         d = {
       
   568             count: 10,
       
   569             total: 50
       
   570         };
       
   571 
       
   572         fmts = ngettext('Total: %(total)s, there is %(count)s object',
       
   573         'there are %(count)s of a total of %(total)s objects', d.count);
       
   574         s = interpolate(fmts, d, true);
       
   575 
       
   576 You shouldn't go over the top with string interpolation, though: this is still
       
   577 JavaScript, so the code has to make repeated regular-expression substitutions.
       
   578 This isn't as fast as string interpolation in Python, so keep it to those
       
   579 cases where you really need it (for example, in conjunction with ``ngettext``
       
   580 to produce proper pluralizations).
       
   581 
       
   582 The ``set_language`` redirect view
       
   583 ==================================
       
   584 
       
   585 .. function:: set_language(request)
       
   586 
       
   587 As a convenience, Django comes with a view, :meth:`django.views.i18n.set_language`,
       
   588 that sets a user's language preference and redirects back to the previous page.
       
   589 
       
   590 Activate this view by adding the following line to your URLconf::
       
   591 
       
   592     (r'^i18n/', include('django.conf.urls.i18n')),
       
   593 
       
   594 (Note that this example makes the view available at ``/i18n/setlang/``.)
       
   595 
       
   596 The view expects to be called via the ``POST`` method, with a ``language``
       
   597 parameter set in request. If session support is enabled, the view
       
   598 saves the language choice in the user's session. Otherwise, it saves the
       
   599 language choice in a cookie that is by default named ``django_language``.
       
   600 (The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)
       
   601 
       
   602 After setting the language choice, Django redirects the user, following this
       
   603 algorithm:
       
   604 
       
   605     * Django looks for a ``next`` parameter in the ``POST`` data.
       
   606     * If that doesn't exist, or is empty, Django tries the URL in the
       
   607       ``Referrer`` header.
       
   608     * If that's empty -- say, if a user's browser suppresses that header --
       
   609       then the user will be redirected to ``/`` (the site root) as a fallback.
       
   610 
       
   611 Here's example HTML template code:
       
   612 
       
   613 .. code-block:: html+django
       
   614 
       
   615     <form action="/i18n/setlang/" method="post">
       
   616     {% csrf_token %}
       
   617     <input name="next" type="hidden" value="/next/page/" />
       
   618     <select name="language">
       
   619     {% for lang in LANGUAGES %}
       
   620     <option value="{{ lang.0 }}">{{ lang.1 }}</option>
       
   621     {% endfor %}
       
   622     </select>
       
   623     <input type="submit" value="Go" />
       
   624     </form>