144
142
# Translators: This message appears on the home page only
145
143
output = ugettext("Welcome to my site.")
147
This also works in templates with the :ttag:`comment` tag:
149
.. code-block:: html+django
151
{% comment %}Translators: This is a text of the base template {% endcomment %}
153
The comment will then appear in the resulting ``.po`` file and should also be
154
displayed by most translation tools.
145
The comment will then appear in the resulting ``.po`` file associated with the
146
translatable contruct located below it and should also be displayed by most
149
.. note:: Just for completeness, this is the corresponding fragment of the
150
resulting ``.po`` file:
154
#. Translators: This message appears on the home page only
155
# path/to/python/file.py:123
156
msgid "Welcome to my site."
159
This also works in templates. See :ref:`translator-comments-in-templates` for
156
162
Marking strings as no-op
157
163
------------------------
324
328
For example, to translate the help text of the *name* field in the following
325
329
model, do the following::
327
from django.utils.translation import ugettext_lazy
331
from django.utils.translation import ugettext_lazy as _
329
333
class MyThing(models.Model):
330
name = models.CharField(help_text=ugettext_lazy('This is the help text'))
334
name = models.CharField(help_text=_('This is the help text'))
332
336
You can mark names of ``ForeignKey``, ``ManyTomanyField`` or ``OneToOneField``
333
337
relationship as translatable by using their ``verbose_name`` options::
349
353
:attr:`~django.db.models.Options.verbose_name` and
350
354
:attr:`~django.db.models.Options.verbose_name_plural` options rather than
351
355
relying on the fallback English-centric and somewhat naïve determination of
352
verbose names Django performs bu looking at the model's class name::
356
verbose names Django performs by looking at the model's class name::
354
from django.utils.translation import ugettext_lazy
358
from django.utils.translation import ugettext_lazy as _
356
360
class MyThing(models.Model):
357
name = models.CharField(_('name'), help_text=ugettext_lazy('This is the help text'))
361
name = models.CharField(_('name'), help_text=_('This is the help text'))
360
verbose_name = ugettext_lazy('my thing')
361
verbose_name_plural = ugettext_lazy('my things')
364
verbose_name = _('my thing')
365
verbose_name_plural = _('my things')
363
367
Model methods ``short_description`` attribute values
364
368
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
424
428
from django.utils.translation import string_concat
426
name = ugettext_lazy(u'John Lennon')
427
instrument = ugettext_lazy(u'guitar')
430
name = ugettext_lazy('John Lennon')
431
instrument = ugettext_lazy('guitar')
428
432
result = string_concat(name, ': ', instrument)
430
434
In this case, the lazy translations in ``result`` will only be converted to
431
435
strings when ``result`` itself is used in a string (usually at template
438
Other uses of lazy in delayed translations
439
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
441
For any other case where you would like to delay the translation, but have to
442
pass the translatable string as argument to another function, you can wrap
443
this function inside a lazy call yourself. For example::
445
from django.utils import six # Python 3 compatibility
446
from django.utils.functional import lazy
447
from django.utils.safestring import mark_safe
448
from django.utils.translation import ugettext_lazy as _
450
mark_safe_lazy = lazy(mark_safe, six.text_type)
454
lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>"))
434
456
Localized names of languages
435
457
----------------------------
437
459
.. function:: get_language_info
439
.. versionadded:: 1.3
441
461
The ``get_language_info()`` function provides detailed information about
444
464
>>> from django.utils.translation import get_language_info
445
465
>>> li = get_language_info('de')
446
>>> print li['name'], li['name_local'], li['bidi']
466
>>> print(li['name'], li['name_local'], li['bidi'])
447
467
German Deutsch False
449
469
The ``name`` and ``name_local`` attributes of the dictionary contain the name of
535
555
``blocktrans`` template tag
536
556
---------------------------
538
.. versionchanged:: 1.3
539
New keyword argument format.
541
558
Contrarily to the :ttag:`trans` tag, the ``blocktrans`` tag allows you to mark
542
559
complex sentences consisting of literals and variable content for translation
543
560
by making use of placeholders::
606
623
Reverse URL lookups cannot be carried out within the ``blocktrans`` and should
607
624
be retrieved (and stored) beforehand::
609
{% url path.to.view arg arg2 as the_url %}
626
{% url 'path.to.view' arg arg2 as the_url %}
611
628
This is a URL: {{ the_url }}
612
629
{% endblocktrans %}
621
638
{% blocktrans with name=user.username context "greeting" %}Hi {{ name }}{% endblocktrans %}
640
.. _translator-comments-in-templates:
642
Comments for translators in templates
643
-------------------------------------
645
Just like with :ref:`Python code <translator-comments>`, these notes for
646
translators can be specified using comments, either with the :ttag:`comment`
649
.. code-block:: html+django
651
{% comment %}Translators: View verb{% endcomment %}
654
{% comment %}Translators: Short intro blurb{% endcomment %}
655
<p>{% blocktrans %}A multiline translatable
656
literal.{% endblocktrans %}</p>
658
or with the ``{#`` ... ``#}`` :ref:`one-line comment constructs <template-comments>`:
660
.. code-block:: html+django
662
{# Translators: Label of a button that triggers search{% endcomment #}
663
<button type="submit">{% trans "Go" %}</button>
665
{# Translators: This is a text of the base template #}
666
{% blocktrans %}Ambiguous translatable block of text{% endblocktrans %}
668
.. note:: Just for completeness, these are the corresponding fragments of the
669
resulting ``.po`` file:
673
#. Translators: View verb
674
# path/to/template/file.html:10
678
#. Translators: Short intro blurb
679
# path/to/template/file.html:13
681
"A multiline translatable"
687
#. Translators: Label of a button that triggers search
688
# path/to/template/file.html:100
693
# path/to/template/file.html:103
694
msgid "Ambiguous translatable block of text"
623
697
.. _template-translation-vars:
664
738
translator might translate the string ``"yes,no"`` as ``"ja,nein"``
665
739
(keeping the comma intact).
667
.. versionadded:: 1.3
669
741
You can also retrieve information about any of the available languages using
670
742
provided template tags and filters. To get information about a single language,
671
743
use the ``{% get_language_info %}`` tag::
787
859
the ones appearing first having higher precedence than the ones appearing
790
.. versionchanged:: 1.3
791
Directories listed in :setting:`LOCALE_PATHS` weren't included in the
792
lookup algorithm until version 1.3.
794
862
Using the JavaScript translation catalog
795
863
----------------------------------------
801
869
.. code-block:: html+django
803
<script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>
871
<script type="text/javascript" src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
805
873
This uses reverse URL lookup to find the URL of the JavaScript catalog view.
806
874
When the catalog is loaded, your JavaScript code can use the standard
850
918
cases where you really need it (for example, in conjunction with ``ngettext``
851
919
to produce proper pluralizations).
924
The :func:`~django.views.i18n.javascript_catalog` view generates the catalog
925
from ``.mo`` files on every request. Since its output is constant — at least
926
for a given version of a site — it's a good candidate for caching.
928
Server-side caching will reduce CPU load. It's easily implemented with the
929
:func:`~django.views.decorators.cache.cache_page` decorator. To trigger cache
930
invalidation when your translations change, provide a version-dependant key
931
prefix, as shown in the example below, or map the view at a version-dependant
934
.. code-block:: python
936
from django.views.decorators.cache import cache_page
937
from django.views.i18n import javascript_catalog
939
# The value returned by get_version() must change when translations change.
940
@cache_page(86400, key_prefix='js18n-%s' % get_version())
941
def cached_javascript_catalog(request, domain='djangojs', packages=None):
942
return javascript_catalog(request, domain, packages)
944
Client-side caching will save bandwidth and make your site load faster. If
945
you're using ETags (:setting:`USE_ETAGS = True <USE_ETAGS>`), you're already
946
covered. Otherwise, you can apply :ref:`conditional decorators
947
<conditional-decorators>`. In the following example, the cache is invalidated
948
whenever your restart your application server.
950
.. code-block:: python
952
from django.utils import timezone
953
from django.views.decorators.http import last_modified
954
from django.views.i18n import javascript_catalog
956
last_modified_date = timezone.now()
957
@last_modified(lambda req, **kw: last_modified_date)
958
def cached_javascript_catalog(request, domain='djangojs', packages=None):
959
return javascript_catalog(request, domain, packages)
961
You can even pre-generate the javascript catalog as part of your deployment
962
procedure and serve it as a static file. This radical technique is implemented
963
in django-statici18n_.
965
.. _django-statici18n: http://django-statici18n.readthedocs.org/en/latest/
853
967
.. _url-internationalization:
855
969
Internationalization: in URL patterns
901
1015
urlpatterns += i18n_patterns('',
902
1016
url(r'^about/$', 'about.view', name='about'),
903
url(r'^news/$', include(news_patterns, namespace='news')),
1017
url(r'^news/', include(news_patterns, namespace='news')),
956
1070
urlpatterns += i18n_patterns('',
957
1071
url(_(r'^about/$'), 'about.view', name='about'),
958
url(_(r'^news/$'), include(news_patterns, namespace='news')),
1072
url(_(r'^news/'), include(news_patterns, namespace='news')),
1049
1163
commands from the GNU gettext toolset: ``xgettext``, ``msgfmt``,
1050
1164
``msgmerge`` and ``msguniq``.
1052
.. versionchanged:: 1.2
1054
1166
The minimum version of the ``gettext`` utilities supported is 0.15.
1056
1168
To create or update a message file, run this command::
1248
1360
.. highlightlang:: python
1362
.. currentmodule:: django.views.i18n
1250
1364
.. function:: set_language(request)
1252
1366
As a convenience, Django comes with a view, :func:`django.views.i18n.set_language`,
1253
1367
that sets a user's language preference and redirects to a given URL or, by default,
1254
1368
back to the previous page.
1370
Make sure that the following item is in your
1371
:setting:`TEMPLATE_CONTEXT_PROCESSORS` list in your settings file::
1373
'django.core.context_processors.i18n'
1256
1375
Activate this view by adding the following line to your URLconf::
1258
1377
(r'^i18n/', include('django.conf.urls.i18n')),
1519
1638
2. Then, it looks for and uses if it exists a ``locale`` directory in each
1520
1639
of the installed apps listed in :setting:`INSTALLED_APPS`. The ones
1521
1640
appearing first have higher precedence than the ones appearing later.
1522
3. Then, it looks for a ``locale`` directory in the project directory, or
1523
more accurately, in the directory containing your settings file.
1524
4. Finally, the Django-provided base translation in ``django/conf/locale``
1641
3. Finally, the Django-provided base translation in ``django/conf/locale``
1525
1642
is used as a fallback.
1528
Lookup in the ``locale`` subdirectory of the directory containing your
1529
settings file (item 3 above) is deprecated since the 1.3 release and will be
1530
removed in Django 1.5. You can use the :setting:`LOCALE_PATHS` setting
1531
instead, by listing the absolute filesystem path of such ``locale``
1532
directory in the setting value.
1536
1646
The translations for literals included in JavaScript assets are looked up
1545
1655
This way, you can write applications that include their own translations, and
1546
you can override base translations in your project path. Or, you can just build
1656
you can override base translations in your project. Or, you can just build
1547
1657
a big project out of several apps and put all translations into one big common
1548
1658
message file specific to the project you are composing. The choice is yours.
1552
If you're using manually configured settings, as described in
1553
:ref:`settings-without-django-settings-module`, the ``locale`` directory in
1554
the project directory will not be examined, since Django loses the ability
1555
to work out the location of the project directory. (Django normally uses the
1556
location of the settings file to determine this, and a settings file doesn't
1557
exist if you're manually configuring your settings.)
1559
1660
All message file repositories are structured the same way. They are:
1561
1662
* All paths listed in :setting:`LOCALE_PATHS` in your settings file are
1562
1663
searched for ``<language>/LC_MESSAGES/django.(po|mo)``
1563
* ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` --
1564
deprecated, see above.
1565
1664
* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
1566
1665
* ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``