internationalization.txt 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  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. .. templatetag:: trans
  312. ``trans`` template tag
  313. ----------------------
  314. The ``{% trans %}`` template tag translates either a constant string
  315. (enclosed in single or double quotes) or variable content::
  316. <title>{% trans "This is the title." %}</title>
  317. <title>{% trans myvar %}</title>
  318. If the ``noop`` option is present, variable lookup still takes place but the
  319. translation is skipped. This is useful when "stubbing out" content that will
  320. require translation in the future::
  321. <title>{% trans "myvar" noop %}</title>
  322. Internally, inline translations use an
  323. :func:`~django.utils.translation.ugettext` call.
  324. In case a template var (``myvar`` above) is passed to the tag, the tag will
  325. first resolve such variable to a string at run-time and then look up that
  326. string in the message catalogs.
  327. It's not possible to mix a template variable inside a string within ``{% trans
  328. %}``. If your translations require strings with variables (placeholders), use
  329. ``{% blocktrans %}`` instead.
  330. .. versionchanged:: 1.4
  331. If you'd like to retrieve a translated string without displaying it, you can
  332. use the following syntax::
  333. {% trans "This is the title" as the_title %}
  334. <title>{{ the_title }}</title>
  335. <meta name="description" content="{{ the_title }}">
  336. In practice you'll use this to get strings that are used in multiple places
  337. or should be used as arguments for other template tags or filters::
  338. {% trans "starting point" as start %}
  339. {% trans "end point" as end %}
  340. {% trans "La Grande Boucle" as race %}
  341. <h1>
  342. <a href="/" title="{% blocktrans %}Back to '{{ race }}' homepage{% endblocktrans %}">{{ race }}</a>
  343. </h1>
  344. <p>
  345. {% for stage in tour_stages %}
  346. {% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}<br />{% else %}, {% endif %}
  347. {% endfor %}
  348. </p>
  349. .. templatetag:: blocktrans
  350. ``blocktrans`` template tag
  351. ---------------------------
  352. .. versionchanged:: 1.3
  353. New keyword argument format.
  354. Contrarily to the :ttag:`trans` tag, the ``blocktrans`` tag allows you to mark
  355. complex sentences consisting of literals and variable content for translation
  356. by making use of placeholders::
  357. {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
  358. To translate a template expression -- say, accessing object attributes or
  359. using template filters -- you need to bind the expression to a local variable
  360. for use within the translation block. Examples::
  361. {% blocktrans with amount=article.price %}
  362. That will cost $ {{ amount }}.
  363. {% endblocktrans %}
  364. {% blocktrans with myvar=value|filter %}
  365. This will have {{ myvar }} inside.
  366. {% endblocktrans %}
  367. You can use multiple expressions inside a single ``blocktrans`` tag::
  368. {% blocktrans with book_t=book|title author_t=author|title %}
  369. This is {{ book_t }} by {{ author_t }}
  370. {% endblocktrans %}
  371. .. note:: The previous more verbose format is still supported:
  372. ``{% blocktrans with book|title as book_t and author|title as author_t %}``
  373. .. versionchanged:: 1.4
  374. If resolving one of the block arguments fails, blocktrans will fall back to
  375. the default language by deactivating the currently active language
  376. temporarily with the :func:`~django.utils.translation.deactivate_all`
  377. function.
  378. This tag also provides for pluralization. To use it:
  379. * Designate and bind a counter value with the name ``count``. This value will
  380. be the one used to select the right plural form.
  381. * Specify both the singular and plural forms separating them with the
  382. ``{% plural %}`` tag within the ``{% blocktrans %}`` and
  383. ``{% endblocktrans %}`` tags.
  384. An example::
  385. {% blocktrans count counter=list|length %}
  386. There is only one {{ name }} object.
  387. {% plural %}
  388. There are {{ counter }} {{ name }} objects.
  389. {% endblocktrans %}
  390. A more complex example::
  391. {% blocktrans with amount=article.price count years=i.length %}
  392. That will cost $ {{ amount }} per year.
  393. {% plural %}
  394. That will cost $ {{ amount }} per {{ years }} years.
  395. {% endblocktrans %}
  396. When you use both the pluralization feature and bind values to local variables
  397. in addition to the counter value, keep in mind that the ``blocktrans``
  398. construct is internally converted to an ``ungettext`` call. This means the
  399. same :ref:`notes regarding ungettext variables <pluralization-var-notes>`
  400. apply.
  401. Reverse URL lookups cannot be carried out within the ``blocktrans`` and should
  402. be retrieved (and stored) beforehand::
  403. {% url path.to.view arg arg2 as the_url %}
  404. {% blocktrans %}
  405. This is a URL: {{ the_url }}
  406. {% endblocktrans %}
  407. .. _template-translation-vars:
  408. Other tags
  409. ----------
  410. Each ``RequestContext`` has access to three translation-specific variables:
  411. * ``LANGUAGES`` is a list of tuples in which the first element is the
  412. :term:`language code` and the second is the language name (translated into
  413. the currently active locale).
  414. * ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
  415. Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.)
  416. * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a
  417. right-to-left language, e.g.: Hebrew, Arabic. If False it's a
  418. left-to-right language, e.g.: English, French, German etc.
  419. If you don't use the ``RequestContext`` extension, you can get those values with
  420. three tags::
  421. {% get_current_language as LANGUAGE_CODE %}
  422. {% get_available_languages as LANGUAGES %}
  423. {% get_current_language_bidi as LANGUAGE_BIDI %}
  424. These tags also require a ``{% load i18n %}``.
  425. Translation hooks are also available within any template block tag that accepts
  426. constant strings. In those cases, just use ``_()`` syntax to specify a
  427. translation string::
  428. {% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
  429. In this case, both the tag and the filter will see the already-translated
  430. string, so they don't need to be aware of translations.
  431. .. note::
  432. In this example, the translation infrastructure will be passed the string
  433. ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
  434. translated string will need to contain the comma so that the filter
  435. parsing code knows how to split up the arguments. For example, a German
  436. translator might translate the string ``"yes,no"`` as ``"ja,nein"``
  437. (keeping the comma intact).
  438. .. versionadded:: 1.3
  439. You can also retrieve information about any of the available languages using
  440. provided template tags and filters. To get information about a single language,
  441. use the ``{% get_language_info %}`` tag::
  442. {% get_language_info for LANGUAGE_CODE as lang %}
  443. {% get_language_info for "pl" as lang %}
  444. You can then access the information::
  445. Language code: {{ lang.code }}<br />
  446. Name of language: {{ lang.name_local }}<br />
  447. Name in English: {{ lang.name }}<br />
  448. Bi-directional: {{ lang.bidi }}
  449. You can also use the ``{% get_language_info_list %}`` template tag to retrieve
  450. information for a list of languages (e.g. active languages as specified in
  451. :setting:`LANGUAGES`). See :ref:`the section about the set_language redirect
  452. view <set_language-redirect-view>` for an example of how to display a language
  453. selector using ``{% get_language_info_list %}``.
  454. In addition to :setting:`LANGUAGES` style nested tuples,
  455. ``{% get_language_info_list %}`` supports simple lists of language codes.
  456. If you do this in your view:
  457. .. code-block:: python
  458. return render_to_response('mytemplate.html', {
  459. 'available_languages': ['en', 'es', 'fr'],
  460. }, RequestContext(request))
  461. you can iterate over those languages in the template::
  462. {% get_language_info_list for available_languages as langs %}
  463. {% for lang in langs %} ... {% endfor %}
  464. There are also simple filters available for convenience:
  465. * ``{{ LANGUAGE_CODE|language_name }}`` ("German")
  466. * ``{{ LANGUAGE_CODE|language_name_local }}`` ("Deutsch")
  467. * ``{{ LANGUAGE_CODE|bidi }}`` (False)
  468. .. _Django templates: ../templates_python/
  469. Specifying translation strings: In JavaScript code
  470. ==================================================
  471. .. highlightlang:: python
  472. Adding translations to JavaScript poses some problems:
  473. * JavaScript code doesn't have access to a ``gettext`` implementation.
  474. * JavaScript code doesn't have access to .po or .mo files; they need to be
  475. delivered by the server.
  476. * The translation catalogs for JavaScript should be kept as small as
  477. possible.
  478. Django provides an integrated solution for these problems: It passes the
  479. translations into JavaScript, so you can call ``gettext``, etc., from within
  480. JavaScript.
  481. .. _javascript_catalog-view:
  482. The ``javascript_catalog`` view
  483. -------------------------------
  484. .. module:: django.views.i18n
  485. .. function:: javascript_catalog(request, domain='djangojs', packages=None)
  486. The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog`
  487. view, which sends out a JavaScript code library with functions that mimic the
  488. ``gettext`` interface, plus an array of translation strings. Those translation
  489. strings are taken from applications or Django core, according to what you
  490. specify in either the info_dict or the URL. Paths listed in
  491. :setting:`LOCALE_PATHS` are also included.
  492. You hook it up like this::
  493. js_info_dict = {
  494. 'packages': ('your.app.package',),
  495. }
  496. urlpatterns = patterns('',
  497. (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
  498. )
  499. Each string in ``packages`` should be in Python dotted-package syntax (the
  500. same format as the strings in :setting:`INSTALLED_APPS`) and should refer to a
  501. package that contains a ``locale`` directory. If you specify multiple packages,
  502. all those catalogs are merged into one catalog. This is useful if you have
  503. JavaScript that uses strings from different applications.
  504. The precedence of translations is such that the packages appearing later in the
  505. ``packages`` argument have higher precedence than the ones appearing at the
  506. beginning, this is important in the case of clashing translations for the same
  507. literal.
  508. By default, the view uses the ``djangojs`` gettext domain. This can be
  509. changed by altering the ``domain`` argument.
  510. You can make the view dynamic by putting the packages into the URL pattern::
  511. urlpatterns = patterns('',
  512. (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
  513. )
  514. With this, you specify the packages as a list of package names delimited by '+'
  515. signs in the URL. This is especially useful if your pages use code from
  516. different apps and this changes often and you don't want to pull in one big
  517. catalog file. As a security measure, these values can only be either
  518. ``django.conf`` or any package from the :setting:`INSTALLED_APPS` setting.
  519. The JavaScript translations found in the paths listed in the
  520. :setting:`LOCALE_PATHS` setting are also always included. To keep consistency
  521. with the translations lookup order algorithm used for Python and templates, the
  522. directories listed in :setting:`LOCALE_PATHS` have the highest precedence with
  523. the ones appearing first having higher precedence than the ones appearing
  524. later.
  525. .. versionchanged:: 1.3
  526. Directories listed in :setting:`LOCALE_PATHS` weren't included in the
  527. lookup algorithm until version 1.3.
  528. Using the JavaScript translation catalog
  529. ----------------------------------------
  530. .. highlightlang:: javascript
  531. To use the catalog, just pull in the dynamically generated script like this:
  532. .. code-block:: html+django
  533. <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>
  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. document.write(gettext('this is to be translated'));
  538. There is also an ``ngettext`` interface::
  539. var object_cnt = 1 // or 0, or 2, or 3, ...
  540. s = ngettext('literal for the singular case',
  541. 'literal for the plural case', object_cnt);
  542. and even a string interpolation function::
  543. function interpolate(fmt, obj, named);
  544. The interpolation syntax is borrowed from Python, so the ``interpolate``
  545. function supports both positional and named interpolation:
  546. * Positional interpolation: ``obj`` contains a JavaScript Array object
  547. whose elements values are then sequentially interpolated in their
  548. corresponding ``fmt`` placeholders in the same order they appear.
  549. For example::
  550. fmts = ngettext('There is %s object. Remaining: %s',
  551. 'There are %s objects. Remaining: %s', 11);
  552. s = interpolate(fmts, [11, 20]);
  553. // s is 'There are 11 objects. Remaining: 20'
  554. * Named interpolation: This mode is selected by passing the optional
  555. boolean ``named`` parameter as true. ``obj`` contains a JavaScript
  556. object or associative array. For example::
  557. d = {
  558. count: 10,
  559. total: 50
  560. };
  561. fmts = ngettext('Total: %(total)s, there is %(count)s object',
  562. 'there are %(count)s of a total of %(total)s objects', d.count);
  563. s = interpolate(fmts, d, true);
  564. You shouldn't go over the top with string interpolation, though: this is still
  565. JavaScript, so the code has to make repeated regular-expression substitutions.
  566. This isn't as fast as string interpolation in Python, so keep it to those
  567. cases where you really need it (for example, in conjunction with ``ngettext``
  568. to produce proper pluralizations).
  569. .. _url-internationalization:
  570. Specifying translation strings: In URL patterns
  571. ===============================================
  572. .. versionadded:: 1.4
  573. .. module:: django.conf.urls.i18n
  574. Django provides two mechanisms to internationalize URL patterns:
  575. * Adding the language prefix to the root of the URL patterns to make it
  576. possible for :class:`~django.middleware.locale.LocaleMiddleware` to detect
  577. the language to activate from the requested URL.
  578. * Making URL patterns themselves translatable via the
  579. :func:`django.utils.translation.ugettext_lazy()` function.
  580. .. warning::
  581. Using either one of these features requires that an active language be set
  582. for each request; in other words, you need to have
  583. :class:`django.middleware.locale.LocaleMiddleware` in your
  584. :setting:`MIDDLEWARE_CLASSES` setting.
  585. Language prefix in URL patterns
  586. -------------------------------
  587. .. function:: i18n_patterns(prefix, pattern_description, ...)
  588. This function can be used in your root URLconf as a replacement for the normal
  589. :func:`django.conf.urls.patterns` function. Django will automatically
  590. prepend the current active language code to all url patterns defined within
  591. :func:`~django.conf.urls.i18n.i18n_patterns`. Example URL patterns::
  592. from django.conf.urls import patterns, include, url
  593. from django.conf.urls.i18n import i18n_patterns
  594. urlpatterns = patterns(''
  595. url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'),
  596. )
  597. news_patterns = patterns(''
  598. url(r'^$', 'news.views.index', name='index'),
  599. url(r'^category/(?P<slug>[\w-]+)/$', 'news.views.category', name='category'),
  600. url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'),
  601. )
  602. urlpatterns += i18n_patterns('',
  603. url(r'^about/$', 'about.view', name='about'),
  604. url(r'^news/$', include(news_patterns, namespace='news')),
  605. )
  606. After defining these URL patterns, Django will automatically add the
  607. language prefix to the URL patterns that were added by the ``i18n_patterns``
  608. function. Example::
  609. from django.core.urlresolvers import reverse
  610. from django.utils.translation import activate
  611. >>> activate('en')
  612. >>> reverse('sitemap_xml')
  613. '/sitemap.xml'
  614. >>> reverse('news:index')
  615. '/en/news/'
  616. >>> activate('nl')
  617. >>> reverse('news:detail', kwargs={'slug': 'news-slug'})
  618. '/nl/news/news-slug/'
  619. .. warning::
  620. :func:`~django.conf.urls.i18n.i18n_patterns` is only allowed in your root
  621. URLconf. Using it within an included URLconf will throw an
  622. :exc:`ImproperlyConfigured` exception.
  623. .. warning::
  624. Ensure that you don't have non-prefixed URL patterns that might collide
  625. with an automatically-added language prefix.
  626. Translating URL patterns
  627. ------------------------
  628. URL patterns can also be marked translatable using the
  629. :func:`~django.utils.translation.ugettext_lazy` function. Example::
  630. from django.conf.urls import patterns, include, url
  631. from django.conf.urls.i18n import i18n_patterns
  632. from django.utils.translation import ugettext_lazy as _
  633. urlpatterns = patterns(''
  634. url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'),
  635. )
  636. news_patterns = patterns(''
  637. url(r'^$', 'news.views.index', name='index'),
  638. url(_(r'^category/(?P<slug>[\w-]+)/$'), 'news.views.category', name='category'),
  639. url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'),
  640. )
  641. urlpatterns += i18n_patterns('',
  642. url(_(r'^about/$'), 'about.view', name='about'),
  643. url(_(r'^news/$'), include(news_patterns, namespace='news')),
  644. )
  645. After you've created the translations (see :doc:`localization` for more
  646. information), the :func:`~django.core.urlresolvers.reverse` function will
  647. return the URL in the active language. Example::
  648. from django.core.urlresolvers import reverse
  649. from django.utils.translation import activate
  650. >>> activate('en')
  651. >>> reverse('news:category', kwargs={'slug': 'recent'})
  652. '/en/news/category/recent/'
  653. >>> activate('nl')
  654. >>> reverse('news:category', kwargs={'slug': 'recent'})
  655. '/nl/nieuws/categorie/recent/'
  656. .. warning::
  657. In most cases, it's best to use translated URLs only within a
  658. language-code-prefixed block of patterns (using
  659. :func:`~django.conf.urls.i18n.i18n_patterns`), to avoid the possibility
  660. that a carelessly translated URL causes a collision with a non-translated
  661. URL pattern.
  662. .. _reversing_in_templates:
  663. .. templatetag:: language
  664. Reversing in templates
  665. ----------------------
  666. If localized URLs get reversed in templates they always use the current
  667. language. To link to a URL in another language use the ``language``
  668. template tag. It enables the given language in the enclosed template section:
  669. .. code-block:: html+django
  670. {% load i18n %}
  671. {% get_available_languages as languages %}
  672. {% trans "View this category in:" %}
  673. {% for lang_code, lang_name in languages %}
  674. {% language lang_code %}
  675. <a href="{% url category slug=category.slug %}">{{ lang_name }}</a>
  676. {% endlanguage %}
  677. {% endfor %}
  678. The :ttag:`language` tag expects the language code as the only argument.
  679. .. _set_language-redirect-view:
  680. The ``set_language`` redirect view
  681. ==================================
  682. .. highlightlang:: python
  683. .. function:: set_language(request)
  684. As a convenience, Django comes with a view, :func:`django.views.i18n.set_language`,
  685. that sets a user's language preference and redirects back to the previous page.
  686. Activate this view by adding the following line to your URLconf::
  687. (r'^i18n/', include('django.conf.urls.i18n')),
  688. (Note that this example makes the view available at ``/i18n/setlang/``.)
  689. The view expects to be called via the ``POST`` method, with a ``language``
  690. parameter set in request. If session support is enabled, the view
  691. saves the language choice in the user's session. Otherwise, it saves the
  692. language choice in a cookie that is by default named ``django_language``.
  693. (The name can be changed through the :setting:`LANGUAGE_COOKIE_NAME` setting.)
  694. After setting the language choice, Django redirects the user, following this
  695. algorithm:
  696. * Django looks for a ``next`` parameter in the ``POST`` data.
  697. * If that doesn't exist, or is empty, Django tries the URL in the
  698. ``Referrer`` header.
  699. * If that's empty -- say, if a user's browser suppresses that header --
  700. then the user will be redirected to ``/`` (the site root) as a fallback.
  701. Here's example HTML template code:
  702. .. code-block:: html+django
  703. <form action="/i18n/setlang/" method="post">
  704. {% csrf_token %}
  705. <input name="next" type="hidden" value="/next/page/" />
  706. <select name="language">
  707. {% get_language_info_list for LANGUAGES as languages %}
  708. {% for language in languages %}
  709. <option value="{{ language.code }}">{{ language.name_local }} ({{ language.code }})</option>
  710. {% endfor %}
  711. </select>
  712. <input type="submit" value="Go" />
  713. </form>