PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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