PageRenderTime 128ms CodeModel.GetById 80ms app.highlight 6ms RepoModel.GetById 34ms app.codeStats 1ms

/docs/topics/i18n/internationalization.txt

https://code.google.com/p/mango-py/
Plain Text | 803 lines | 577 code | 226 blank | 0 comment | 0 complexity | 3d573a3d91d35fa57ab07488672e82e4 MD5 | raw file
  1====================
  2Internationalization
  3====================
  4
  5.. module:: django.utils.translation
  6
  7Overview
  8========
  9
 10The goal of internationalization is to allow a single Web application to offer
 11its content and functionality in multiple languages and locales.
 12
 13For text translations, you, the Django developer, can accomplish this goal by
 14adding a minimal amount of hooks to your Python and templates. These hooks
 15are called **translation strings**. They tell Django: "This text should be
 16translated into the end user's language, if a translation for this text is
 17available in that language." It's your responsibility to mark translatable
 18strings; the system can only translate strings it knows about.
 19
 20Django takes care of using these hooks to translate Web apps, on the fly,
 21according to users' language preferences.
 22
 23Specifying translation strings: In Python code
 24==============================================
 25
 26Standard translation
 27--------------------
 28
 29Specify a translation string by using the function
 30:func:`~django.utils.translation.ugettext`. It's convention to import this
 31as a shorter alias, ``_``, to save typing.
 32
 33.. note::
 34    Python's standard library ``gettext`` module installs ``_()`` into the
 35    global namespace, as an alias for ``gettext()``. In Django, we have chosen
 36    not to follow this practice, for a couple of reasons:
 37
 38      1. For international character set (Unicode) support,
 39         :func:`~django.utils.translation.ugettext` is more useful than
 40         ``gettext()``. Sometimes, you should be using
 41         :func:`~django.utils.translation.ugettext_lazy` as the default
 42         translation method for a particular file. Without ``_()`` in the
 43         global namespace, the developer has to think about which is the
 44         most appropriate translation function.
 45
 46      2. The underscore character (``_``) is used to represent "the previous
 47         result" in Python's interactive shell and doctest tests. Installing a
 48         global ``_()`` function causes interference. Explicitly importing
 49         ``ugettext()`` as ``_()`` avoids this problem.
 50
 51.. highlightlang:: python
 52
 53In this example, the text ``"Welcome to my site."`` is marked as a translation
 54string::
 55
 56    from django.utils.translation import ugettext as _
 57
 58    def my_view(request):
 59        output = _("Welcome to my site.")
 60        return HttpResponse(output)
 61
 62Obviously, you could code this without using the alias. This example is
 63identical to the previous one::
 64
 65    from django.utils.translation import ugettext
 66
 67    def my_view(request):
 68        output = ugettext("Welcome to my site.")
 69        return HttpResponse(output)
 70
 71Translation works on computed values. This example is identical to the previous
 72two::
 73
 74    def my_view(request):
 75        words = ['Welcome', 'to', 'my', 'site.']
 76        output = _(' '.join(words))
 77        return HttpResponse(output)
 78
 79Translation works on variables. Again, here's an identical example::
 80
 81    def my_view(request):
 82        sentence = 'Welcome to my site.'
 83        output = _(sentence)
 84        return HttpResponse(output)
 85
 86(The caveat with using variables or computed values, as in the previous two
 87examples, is that Django's translation-string-detecting utility,
 88``django-admin.py makemessages``, won't be able to find these strings. More on
 89``makemessages`` later.)
 90
 91The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
 92specified with Python's standard named-string interpolation syntax. Example::
 93
 94    def my_view(request, m, d):
 95        output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
 96        return HttpResponse(output)
 97
 98This technique lets language-specific translations reorder the placeholder
 99text. For example, an English translation may be ``"Today is November 26."``,
100while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the
101the month and the day placeholders swapped.
102
103For this reason, you should use named-string interpolation (e.g., ``%(day)s``)
104instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you
105have more than a single parameter. If you used positional interpolation,
106translations wouldn't be able to reorder placeholder text.
107
108.. _translator-comments:
109
110Comments for translators
111------------------------
112
113.. versionadded:: 1.3
114
115If you would like to give translators hints about a translatable string, you
116can add a comment prefixed with the ``Translators`` keyword on the line
117preceding the string, e.g.::
118
119    def my_view(request):
120        # Translators: This message appears on the home page only
121        output = ugettext("Welcome to my site.")
122
123This also works in templates with the :ttag:`comment` tag:
124
125.. code-block:: html+django
126
127    {% comment %}Translators: This is a text of the base template {% endcomment %}
128
129The comment will then appear in the resulting .po file and should also be
130displayed by most translation tools.
131
132Marking strings as no-op
133------------------------
134
135Use the function :func:`django.utils.translation.ugettext_noop()` to mark a
136string as a translation string without translating it. The string is later
137translated from a variable.
138
139Use this if you have constant strings that should be stored in the source
140language because they are exchanged over systems or users -- such as strings
141in a database -- but should be translated at the last possible point in time,
142such as when the string is presented to the user.
143
144Pluralization
145-------------
146
147Use the function :func:`django.utils.translation.ungettext()` to specify
148pluralized messages.
149
150``ungettext`` takes three arguments: the singular translation string, the plural
151translation string and the number of objects.
152
153This function is useful when you need your Django application to be localizable
154to languages where the number and complexity of `plural forms
155<http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is
156greater than the two forms used in English ('object' for the singular and
157'objects' for all the cases where ``count`` is different from one, irrespective
158of its value.)
159
160For example::
161
162    from django.utils.translation import ungettext
163
164    def hello_world(request, count):
165        page = ungettext(
166            'there is %(count)d object',
167            'there are %(count)d objects',
168        count) % {
169            'count': count,
170        }
171        return HttpResponse(page)
172
173In this example the number of objects is passed to the translation
174languages as the ``count`` variable.
175
176Lets see a slightly more complex usage example::
177
178    from django.utils.translation import ungettext
179
180    count = Report.objects.count()
181    if count == 1:
182        name = Report._meta.verbose_name
183    else:
184        name = Report._meta.verbose_name_plural
185
186    text = ungettext(
187            'There is %(count)d %(name)s available.',
188            'There are %(count)d %(name)s available.',
189            count
190    ) % {
191        'count': count,
192        'name': name
193    }
194
195Here we reuse localizable, hopefully already translated literals (contained in
196the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for
197other parts of the sentence so all of it is consistently based on the
198cardinality of the elements at play.
199
200.. _pluralization-var-notes:
201
202.. note::
203
204    When using this technique, make sure you use a single name for every
205    extrapolated variable included in the literal. In the example above note how
206    we used the ``name`` Python variable in both translation strings. This
207    example would fail::
208
209        from django.utils.translation import ungettext
210        from myapp.models import Report
211
212        count = Report.objects.count()
213        d = {
214            'count': count,
215            'name': Report._meta.verbose_name,
216            'plural_name': Report._meta.verbose_name_plural
217        }
218        text = ungettext(
219                'There is %(count)d %(name)s available.',
220                'There are %(count)d %(plural_name)s available.',
221                count
222        ) % d
223
224    You would get a ``a format specification for argument 'name', as in
225    'msgstr[0]', doesn't exist in 'msgid'`` error when running
226    ``django-admin.py compilemessages``.
227
228.. _contextual-markers:
229
230Contextual markers
231------------------
232
233.. versionadded:: 1.3
234
235Sometimes words have several meanings, such as ``"May"`` in English, which
236refers to a month name and to a verb. To enable translators to translate
237these words correctly in different contexts, you can use the
238:func:`django.utils.translation.pgettext()` function, or the
239:func:`django.utils.translation.npgettext()` function if the string needs
240pluralization. Both take a context string as the first variable.
241
242In the resulting .po file, the string will then appear as often as there are
243different contextual markers for the same string (the context will appear on
244the ``msgctxt`` line), allowing the translator to give a different translation
245for each of them.
246
247For example::
248
249    from django.utils.translation import pgettext
250
251    month = pgettext("month name", "May")
252
253or::
254
255    from django.utils.translation import pgettext_lazy
256
257    class MyThing(models.Model):
258        name = models.CharField(help_text=pgettext_lazy(
259            'help text for MyThing model', 'This is the help text'))
260
261will appear in the .po file as:
262
263.. code-block:: po
264
265    msgctxt "month name"
266    msgid "May"
267    msgstr ""
268
269.. _lazy-translations:
270
271Lazy translation
272----------------
273
274Use the function :func:`django.utils.translation.ugettext_lazy()` to translate
275strings lazily -- when the value is accessed rather than when the
276``ugettext_lazy()`` function is called.
277
278For example, to translate a model's ``help_text``, do the following::
279
280    from django.utils.translation import ugettext_lazy
281
282    class MyThing(models.Model):
283        name = models.CharField(help_text=ugettext_lazy('This is the help text'))
284
285In this example, ``ugettext_lazy()`` stores a lazy reference to the string --
286not the actual translation. The translation itself will be done when the string
287is used in a string context, such as template rendering on the Django admin
288site.
289
290The result of a ``ugettext_lazy()`` call can be used wherever you would use a
291unicode string (an object with type ``unicode``) in Python. If you try to use
292it where a bytestring (a ``str`` object) is expected, things will not work as
293expected, since a ``ugettext_lazy()`` object doesn't know how to convert
294itself to a bytestring. You can't use a unicode string inside a bytestring,
295either, so this is consistent with normal Python behavior. For example::
296
297    # This is fine: putting a unicode proxy into a unicode string.
298    u"Hello %s" % ugettext_lazy("people")
299
300    # This will not work, since you cannot insert a unicode object
301    # into a bytestring (nor can you insert our unicode proxy there)
302    "Hello %s" % ugettext_lazy("people")
303
304If you ever see output that looks like ``"hello
305<django.utils.functional...>"``, you have tried to insert the result of
306``ugettext_lazy()`` into a bytestring. That's a bug in your code.
307
308If you don't like the verbose name ``ugettext_lazy``, you can just alias it as
309``_`` (underscore), like so::
310
311    from django.utils.translation import ugettext_lazy as _
312
313    class MyThing(models.Model):
314        name = models.CharField(help_text=_('This is the help text'))
315
316Always use lazy translations in :doc:`Django models </topics/db/models>`.
317Field names and table names should be marked for translation (otherwise, they
318won't be translated in the admin interface). This means writing explicit
319``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class,
320though, rather than relying on Django's default determination of
321``verbose_name`` and ``verbose_name_plural`` by looking at the model's class
322name::
323
324    from django.utils.translation import ugettext_lazy as _
325
326    class MyThing(models.Model):
327        name = models.CharField(_('name'), help_text=_('This is the help text'))
328
329        class Meta:
330            verbose_name = _('my thing')
331            verbose_name_plural = _('mythings')
332
333Notes on model classes translation
334~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
335
336Your model classes may not only contain normal fields: you may have relations
337(with a ``ForeignKey`` field) or additional model methods you may use for
338columns in the Django admin site.
339
340If you have models with foreign keys and you use the Django admin site, you can
341provide translations for the relation itself by using the ``verbose_name``
342parameter on the ``ForeignKey`` object::
343
344    class MyThing(models.Model):
345        kind = models.ForeignKey(ThingKind, related_name='kinds',
346                                 verbose_name=_('kind'))
347
348As you would do for the ``verbose_name`` and ``verbose_name_plural`` settings of
349a model Meta class, you should provide a lowercase verbose name text for the
350relation as Django will automatically titlecase it when required.
351
352For model methods, you can provide translations to Django and the admin site
353with the ``short_description`` parameter set on the corresponding method::
354
355    class MyThing(models.Model):
356        kind = models.ForeignKey(ThingKind, related_name='kinds',
357                                 verbose_name=_('kind'))
358
359        def is_mouse(self):
360            return self.kind.type == MOUSE_TYPE
361        is_mouse.short_description = _('Is it a mouse?')
362
363As always with model classes translations, don't forget to use the lazy
364translation method!
365
366Working with lazy translation objects
367-------------------------------------
368
369Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models
370and utility functions is a common operation. When you're working with these
371objects elsewhere in your code, you should ensure that you don't accidentally
372convert them to strings, because they should be converted as late as possible
373(so that the correct locale is in effect). This necessitates the use of a
374couple of helper functions.
375
376Joining strings: string_concat()
377~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
378
379Standard Python string joins (``''.join([...])``) will not work on lists
380containing lazy translation objects. Instead, you can use
381:func:`django.utils.translation.string_concat()`, which creates a lazy object
382that concatenates its contents *and* converts them to strings only when the
383result is included in a string. For example::
384
385    from django.utils.translation import string_concat
386    ...
387    name = ugettext_lazy(u'John Lennon')
388    instrument = ugettext_lazy(u'guitar')
389    result = string_concat(name, ': ', instrument)
390
391In this case, the lazy translations in ``result`` will only be converted to
392strings when ``result`` itself is used in a string (usually at template
393rendering time).
394
395Localized names of languages
396============================
397
398.. function:: get_language_info
399
400.. versionadded:: 1.3
401
402The ``get_language_info()`` function provides detailed information about
403languages::
404
405    >>> from django.utils.translation import get_language_info
406    >>> li = get_language_info('de')
407    >>> print li['name'], li['name_local'], li['bidi']
408    German Deutsch False
409
410The ``name`` and ``name_local`` attributes of the dictionary contain the name of
411the language in English and in the language itself, respectively.  The ``bidi``
412attribute is True only for bi-directional languages.
413
414The source of the language information is the ``django.conf.locale`` module.
415Similar access to this information is available for template code. See below.
416
417.. _specifying-translation-strings-in-template-code:
418
419Specifying translation strings: In template code
420================================================
421
422.. highlightlang:: html+django
423
424Translations in :doc:`Django templates </topics/templates>` uses two template
425tags and a slightly different syntax than in Python code. To give your template
426access to these tags, put ``{% load i18n %}`` toward the top of your template.
427
428``trans`` template tag
429----------------------
430
431The ``{% trans %}`` template tag translates either a constant string
432(enclosed in single or double quotes) or variable content::
433
434    <title>{% trans "This is the title." %}</title>
435    <title>{% trans myvar %}</title>
436
437If the ``noop`` option is present, variable lookup still takes place but the
438translation is skipped. This is useful when "stubbing out" content that will
439require translation in the future::
440
441    <title>{% trans "myvar" noop %}</title>
442
443Internally, inline translations use an
444:func:`~django.utils.translation.ugettext` call.
445
446In case a template var (``myvar`` above) is passed to the tag, the tag will
447first resolve such variable to a string at run-time and then look up that
448string in the message catalogs.
449
450It's not possible to mix a template variable inside a string within ``{% trans
451%}``. If your translations require strings with variables (placeholders), use
452``{% blocktrans %}`` instead.
453
454``blocktrans`` template tag
455---------------------------
456
457.. versionchanged:: 1.3
458   New keyword argument format.
459
460Contrarily to the ``trans`` tag, the ``blocktrans`` tag allows you to mark
461complex sentences consisting of literals and variable content for translation
462by making use of placeholders::
463
464    {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
465
466To translate a template expression -- say, accessing object attributes or
467using template filters -- you need to bind the expression to a local variable
468for use within the translation block. Examples::
469
470    {% blocktrans with amount=article.price %}
471    That will cost $ {{ amount }}.
472    {% endblocktrans %}
473
474    {% blocktrans with myvar=value|filter %}
475    This will have {{ myvar }} inside.
476    {% endblocktrans %}
477
478You can use multiple expressions inside a single ``blocktrans`` tag::
479
480    {% blocktrans with book_t=book|title and author_t=author|title %}
481    This is {{ book_t }} by {{ author_t }}
482    {% endblocktrans %}
483
484.. note:: The previous more verbose format is still supported:
485   ``{% blocktrans with book|title as book_t and author|title as author_t %}``
486
487This tag also provides for pluralization. To use it:
488
489    * Designate and bind a counter value with the name ``count``. This value will
490      be the one used to select the right plural form.
491
492    * Specify both the singular and plural forms separating them with the
493      ``{% plural %}`` tag within the ``{% blocktrans %}`` and
494      ``{% endblocktrans %}`` tags.
495
496An example::
497
498    {% blocktrans count counter=list|length %}
499    There is only one {{ name }} object.
500    {% plural %}
501    There are {{ counter }} {{ name }} objects.
502    {% endblocktrans %}
503
504A more complex example::
505
506    {% blocktrans with amount=article.price count years=i.length %}
507    That will cost $ {{ amount }} per year.
508    {% plural %}
509    That will cost $ {{ amount }} per {{ years }} years.
510    {% endblocktrans %}
511
512When you use both the pluralization feature and bind values to local variables
513in addition to the counter value, keep in mind that the ``blocktrans``
514construct is internally converted to an ``ungettext`` call. This means the
515same :ref:`notes regarding ungettext variables <pluralization-var-notes>`
516apply.
517
518Reverse URL lookups cannot be carried out within the ``blocktrans`` and should
519be retrieved (and stored) beforehand::
520
521    {% url path.to.view arg arg2 as the_url %}
522    {% blocktrans %}
523    This is a URL: {{ the_url }}
524    {% endblocktrans %}
525
526.. _template-translation-vars:
527
528Other tags
529----------
530
531Each ``RequestContext`` has access to three translation-specific variables:
532
533    * ``LANGUAGES`` is a list of tuples in which the first element is the
534      :term:`language code` and the second is the language name (translated into
535      the currently active locale).
536
537    * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
538      Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.)
539
540    * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a
541      right-to-left language, e.g.: Hebrew, Arabic. If False it's a
542      left-to-right language, e.g.: English, French, German etc.
543
544If you don't use the ``RequestContext`` extension, you can get those values with
545three tags::
546
547    {% get_current_language as LANGUAGE_CODE %}
548    {% get_available_languages as LANGUAGES %}
549    {% get_current_language_bidi as LANGUAGE_BIDI %}
550
551These tags also require a ``{% load i18n %}``.
552
553Translation hooks are also available within any template block tag that accepts
554constant strings. In those cases, just use ``_()`` syntax to specify a
555translation string::
556
557    {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
558
559In this case, both the tag and the filter will see the already-translated
560string, so they don't need to be aware of translations.
561
562.. note::
563    In this example, the translation infrastructure will be passed the string
564    ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
565    translated string will need to contain the comma so that the filter
566    parsing code knows how to split up the arguments. For example, a German
567    translator might translate the string ``"yes,no"`` as ``"ja,nein"``
568    (keeping the comma intact).
569
570.. versionadded:: 1.3
571
572You can also retrieve information about any of the available languages using
573provided template tags and filters. To get information about a single language,
574use the ``{% get_language_info %}`` tag::
575
576    {% get_language_info for LANGUAGE_CODE as lang %}
577    {% get_language_info for "pl" as lang %}
578
579You can then access the information::
580
581    Language code: {{ lang.code }}<br />
582    Name of language: {{ lang.name_local }}<br />
583    Name in English: {{ lang.name }}<br />
584    Bi-directional: {{ lang.bidi }}
585
586You can also use the ``{% get_language_info_list %}`` template tag to retrieve
587information for a list of languages (e.g. active languages as specified in
588:setting:`LANGUAGES`). See :ref:`the section about the set_language redirect
589view <set_language-redirect-view>` for an example of how to display a language
590selector using ``{% get_language_info_list %}``.
591
592In addition to :setting:`LANGUAGES` style nested tuples,
593``{% get_language_info_list %}`` supports simple lists of language codes.
594If you do this in your view:
595
596.. code-block:: python
597
598    return render_to_response('mytemplate.html', {
599        'available_languages': ['en', 'es', 'fr'],
600    }, RequestContext(request))
601
602you can iterate over those languages in the template::
603
604  {% get_language_info_list for available_languages as langs %}
605  {% for lang in langs %} ... {% endfor %}
606
607There are also simple filters available for convenience:
608
609    * ``{{ LANGUAGE_CODE|language_name }}`` ("German")
610    * ``{{ LANGUAGE_CODE|language_name_local }}`` ("Deutsch")
611    * ``{{ LANGUAGE_CODE|bidi }}`` (False)
612
613.. _Django templates: ../templates_python/
614
615Specifying translation strings: In JavaScript code
616==================================================
617
618.. highlightlang:: python
619
620Adding translations to JavaScript poses some problems:
621
622    * JavaScript code doesn't have access to a ``gettext`` implementation.
623
624    * JavaScript code doesn't have access to .po or .mo files; they need to be
625      delivered by the server.
626
627    * The translation catalogs for JavaScript should be kept as small as
628      possible.
629
630Django provides an integrated solution for these problems: It passes the
631translations into JavaScript, so you can call ``gettext``, etc., from within
632JavaScript.
633
634.. _javascript_catalog-view:
635
636The ``javascript_catalog`` view
637-------------------------------
638
639.. module:: django.views.i18n
640
641.. function:: javascript_catalog(request, domain='djangojs', packages=None)
642
643The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog`
644view, which sends out a JavaScript code library with functions that mimic the
645``gettext`` interface, plus an array of translation strings. Those translation
646strings are taken from applications or Django core, according to what you
647specify in either the info_dict or the URL. Paths listed in
648:setting:`LOCALE_PATHS` are also included.
649
650You hook it up like this::
651
652    js_info_dict = {
653        'packages': ('your.app.package',),
654    }
655
656    urlpatterns = patterns('',
657        (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
658    )
659
660Each string in ``packages`` should be in Python dotted-package syntax (the
661same format as the strings in :setting:`INSTALLED_APPS`) and should refer to a
662package that contains a ``locale`` directory. If you specify multiple packages,
663all those catalogs are merged into one catalog. This is useful if you have
664JavaScript that uses strings from different applications.
665
666The precedence of translations is such that the packages appearing later in the
667``packages`` argument have higher precedence than the ones appearing at the
668beginning, this is important in the case of clashing translations for the same
669literal.
670
671By default, the view uses the ``djangojs`` gettext domain. This can be
672changed by altering the ``domain`` argument.
673
674You can make the view dynamic by putting the packages into the URL pattern::
675
676    urlpatterns = patterns('',
677        (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
678    )
679
680With this, you specify the packages as a list of package names delimited by '+'
681signs in the URL. This is especially useful if your pages use code from
682different apps and this changes often and you don't want to pull in one big
683catalog file. As a security measure, these values can only be either
684``django.conf`` or any package from the :setting:`INSTALLED_APPS` setting.
685
686The JavaScript translations found in the paths listed in the
687:setting:`LOCALE_PATHS` setting are also always included. To keep consistency
688with the translations lookup order algorithm used for Python and templates, the
689directories listed in :setting:`LOCALE_PATHS` have the highest precedence with
690the ones appearing first having higher precedence than the ones appearing
691later.
692
693.. versionchanged:: 1.3
694    Directories listed in :setting:`LOCALE_PATHS` weren't included in the
695    lookup algorithm until version 1.3.
696
697Using the JavaScript translation catalog
698----------------------------------------
699
700.. highlightlang:: javascript
701
702To use the catalog, just pull in the dynamically generated script like this:
703
704.. code-block:: html+django
705
706    <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>
707
708This uses reverse URL lookup to find the URL of the JavaScript catalog view.
709When the catalog is loaded, your JavaScript code can use the standard
710``gettext`` interface to access it::
711
712    document.write(gettext('this is to be translated'));
713
714There is also an ``ngettext`` interface::
715
716    var object_cnt = 1 // or 0, or 2, or 3, ...
717    s = ngettext('literal for the singular case',
718            'literal for the plural case', object_cnt);
719
720and even a string interpolation function::
721
722    function interpolate(fmt, obj, named);
723
724The interpolation syntax is borrowed from Python, so the ``interpolate``
725function supports both positional and named interpolation:
726
727    * Positional interpolation: ``obj`` contains a JavaScript Array object
728      whose elements values are then sequentially interpolated in their
729      corresponding ``fmt`` placeholders in the same order they appear.
730      For example::
731
732        fmts = ngettext('There is %s object. Remaining: %s',
733                'There are %s objects. Remaining: %s', 11);
734        s = interpolate(fmts, [11, 20]);
735        // s is 'There are 11 objects. Remaining: 20'
736
737    * Named interpolation: This mode is selected by passing the optional
738      boolean ``named`` parameter as true. ``obj`` contains a JavaScript
739      object or associative array. For example::
740
741        d = {
742            count: 10,
743            total: 50
744        };
745
746        fmts = ngettext('Total: %(total)s, there is %(count)s object',
747        'there are %(count)s of a total of %(total)s objects', d.count);
748        s = interpolate(fmts, d, true);
749
750You shouldn't go over the top with string interpolation, though: this is still
751JavaScript, so the code has to make repeated regular-expression substitutions.
752This isn't as fast as string interpolation in Python, so keep it to those
753cases where you really need it (for example, in conjunction with ``ngettext``
754to produce proper pluralizations).
755
756.. _set_language-redirect-view:
757
758The ``set_language`` redirect view
759==================================
760
761.. highlightlang:: python
762
763.. function:: set_language(request)
764
765As a convenience, Django comes with a view, :func:`django.views.i18n.set_language`,
766that sets a user's language preference and redirects back to the previous page.
767
768Activate this view by adding the following line to your URLconf::
769
770    (r'^i18n/', include('django.conf.urls.i18n')),
771
772(Note that this example makes the view available at ``/i18n/setlang/``.)
773
774The view expects to be called via the ``POST`` method, with a ``language``
775parameter set in request. If session support is enabled, the view
776saves the language choice in the user's session. Otherwise, it saves the
777language choice in a cookie that is by default named ``django_language``.
778(The name can be changed through the :setting:`LANGUAGE_COOKIE_NAME` setting.)
779
780After setting the language choice, Django redirects the user, following this
781algorithm:
782
783    * Django looks for a ``next`` parameter in the ``POST`` data.
784    * If that doesn't exist, or is empty, Django tries the URL in the
785      ``Referrer`` header.
786    * If that's empty -- say, if a user's browser suppresses that header --
787      then the user will be redirected to ``/`` (the site root) as a fallback.
788
789Here's example HTML template code:
790
791.. code-block:: html+django
792
793    <form action="/i18n/setlang/" method="post">
794    {% csrf_token %}
795    <input name="next" type="hidden" value="/next/page/" />
796    <select name="language">
797    {% get_language_info_list for LANGUAGES as languages %}
798    {% for language in languages %}
799    <option value="{{ language.code }}">{{ language.name_local }} ({{ language.code }})</option>
800    {% endfor %}
801    </select>
802    <input type="submit" value="Go" />
803    </form>