~ubuntu-branches/ubuntu/saucy/python-django/saucy-updates

« back to all changes in this revision

Viewing changes to docs/topics/i18n/translation.txt

  • Committer: Package Import Robot
  • Author(s): Luke Faraone, Jakub Wilk, Luke Faraone
  • Date: 2013-05-09 15:10:47 UTC
  • mfrom: (1.1.21) (4.4.27 sid)
  • Revision ID: package-import@ubuntu.com-20130509151047-aqv8d71oj9wvcv8c
Tags: 1.5.1-2
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Luke Faraone ]
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
134
134
Comments for translators
135
135
------------------------
136
136
 
137
 
.. versionadded:: 1.3
138
 
 
139
137
If you would like to give translators hints about a translatable string, you
140
138
can add a comment prefixed with the ``Translators`` keyword on the line
141
139
preceding the string, e.g.::
144
142
        # Translators: This message appears on the home page only
145
143
        output = ugettext("Welcome to my site.")
146
144
 
147
 
This also works in templates with the :ttag:`comment` tag:
148
 
 
149
 
.. code-block:: html+django
150
 
 
151
 
    {% comment %}Translators: This is a text of the base template {% endcomment %}
152
 
 
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
 
147
translation tools.
 
148
 
 
149
.. note:: Just for completeness, this is the corresponding fragment of the
 
150
    resulting ``.po`` file:
 
151
 
 
152
    .. code-block:: po
 
153
 
 
154
        #. Translators: This message appears on the home page only
 
155
        # path/to/python/file.py:123
 
156
        msgid "Welcome to my site."
 
157
        msgstr ""
 
158
 
 
159
This also works in templates. See :ref:`translator-comments-in-templates` for
 
160
more details.
155
161
 
156
162
Marking strings as no-op
157
163
------------------------
255
261
Contextual markers
256
262
------------------
257
263
 
258
 
.. versionadded:: 1.3
259
 
 
260
264
Sometimes words have several meanings, such as ``"May"`` in English, which
261
265
refers to a month name and to a verb. To enable translators to translate
262
266
these words correctly in different contexts, you can use the
324
328
For example, to translate the help text of the *name* field in the following
325
329
model, do the following::
326
330
 
327
 
    from django.utils.translation import ugettext_lazy
 
331
    from django.utils.translation import ugettext_lazy as _
328
332
 
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'))
331
335
 
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::
353
357
 
354
 
    from django.utils.translation import ugettext_lazy
 
358
    from django.utils.translation import ugettext_lazy as _
355
359
 
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'))
358
362
 
359
363
        class Meta:
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')
362
366
 
363
367
Model methods ``short_description`` attribute values
364
368
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
423
427
 
424
428
    from django.utils.translation import string_concat
425
429
    ...
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)
429
433
 
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
432
436
rendering time).
433
437
 
 
438
Other uses of lazy in delayed translations
 
439
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
440
 
 
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::
 
444
 
 
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 _
 
449
 
 
450
    mark_safe_lazy = lazy(mark_safe, six.text_type)
 
451
 
 
452
And then later::
 
453
 
 
454
    lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>"))
 
455
 
434
456
Localized names of languages
435
457
----------------------------
436
458
 
437
459
.. function:: get_language_info
438
460
 
439
 
.. versionadded:: 1.3
440
 
 
441
461
The ``get_language_info()`` function provides detailed information about
442
462
languages::
443
463
 
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
448
468
 
449
469
The ``name`` and ``name_local`` attributes of the dictionary contain the name of
535
555
``blocktrans`` template tag
536
556
---------------------------
537
557
 
538
 
.. versionchanged:: 1.3
539
 
   New keyword argument format.
540
 
 
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::
608
625
 
609
 
    {% url path.to.view arg arg2 as the_url %}
 
626
    {% url 'path.to.view' arg arg2 as the_url %}
610
627
    {% blocktrans %}
611
628
    This is a URL: {{ the_url }}
612
629
    {% endblocktrans %}
620
637
 
621
638
    {% blocktrans with name=user.username context "greeting" %}Hi {{ name }}{% endblocktrans %}
622
639
 
 
640
.. _translator-comments-in-templates:
 
641
 
 
642
Comments for translators in templates
 
643
-------------------------------------
 
644
 
 
645
Just like with :ref:`Python code <translator-comments>`, these notes for
 
646
translators can be specified using comments, either with the :ttag:`comment`
 
647
tag:
 
648
 
 
649
.. code-block:: html+django
 
650
 
 
651
    {% comment %}Translators: View verb{% endcomment %}
 
652
    {% trans "View" %}
 
653
 
 
654
    {% comment %}Translators: Short intro blurb{% endcomment %}
 
655
    <p>{% blocktrans %}A multiline translatable
 
656
    literal.{% endblocktrans %}</p>
 
657
 
 
658
or with the ``{#`` ... ``#}`` :ref:`one-line comment constructs <template-comments>`:
 
659
 
 
660
.. code-block:: html+django
 
661
 
 
662
    {# Translators: Label of a button that triggers search{% endcomment #}
 
663
    <button type="submit">{% trans "Go" %}</button>
 
664
 
 
665
    {# Translators: This is a text of the base template #}
 
666
    {% blocktrans %}Ambiguous translatable block of text{% endblocktrans %}
 
667
 
 
668
.. note:: Just for completeness, these are the corresponding fragments of the
 
669
    resulting ``.po`` file:
 
670
 
 
671
    .. code-block:: po
 
672
 
 
673
        #. Translators: View verb
 
674
        # path/to/template/file.html:10
 
675
        msgid "View"
 
676
        msgstr ""
 
677
 
 
678
        #. Translators: Short intro blurb
 
679
        # path/to/template/file.html:13
 
680
        msgid ""
 
681
        "A multiline translatable"
 
682
        "literal."
 
683
        msgstr ""
 
684
 
 
685
        # ...
 
686
 
 
687
        #. Translators: Label of a button that triggers search
 
688
        # path/to/template/file.html:100
 
689
        msgid "Go"
 
690
        msgstr ""
 
691
 
 
692
        #. Translators:
 
693
        # path/to/template/file.html:103
 
694
        msgid "Ambiguous translatable block of text"
 
695
        msgstr ""
 
696
 
623
697
.. _template-translation-vars:
624
698
 
625
699
Other tags
664
738
    translator might translate the string ``"yes,no"`` as ``"ja,nein"``
665
739
    (keeping the comma intact).
666
740
 
667
 
.. versionadded:: 1.3
668
 
 
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
788
860
later.
789
861
 
790
 
.. versionchanged:: 1.3
791
 
    Directories listed in :setting:`LOCALE_PATHS` weren't included in the
792
 
    lookup algorithm until version 1.3.
793
 
 
794
862
Using the JavaScript translation catalog
795
863
----------------------------------------
796
864
 
800
868
 
801
869
.. code-block:: html+django
802
870
 
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>
804
872
 
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).
852
920
 
 
921
Note on performance
 
922
-------------------
 
923
 
 
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.
 
927
 
 
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
 
932
URL.
 
933
 
 
934
.. code-block:: python
 
935
 
 
936
    from django.views.decorators.cache import cache_page
 
937
    from django.views.i18n import javascript_catalog
 
938
 
 
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)
 
943
 
 
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.
 
949
 
 
950
.. code-block:: python
 
951
 
 
952
    from django.utils import timezone
 
953
    from django.views.decorators.http import last_modified
 
954
    from django.views.i18n import javascript_catalog
 
955
 
 
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)
 
960
 
 
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_.
 
964
 
 
965
.. _django-statici18n: http://django-statici18n.readthedocs.org/en/latest/
 
966
 
853
967
.. _url-internationalization:
854
968
 
855
969
Internationalization: in URL patterns
900
1014
 
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')),
904
1018
    )
905
1019
 
906
1020
 
925
1039
 
926
1040
    :func:`~django.conf.urls.i18n.i18n_patterns` is only allowed in your root
927
1041
    URLconf. Using it within an included URLconf will throw an
928
 
    :exc:`ImproperlyConfigured` exception.
 
1042
    :exc:`~django.core.exceptions.ImproperlyConfigured` exception.
929
1043
 
930
1044
.. warning::
931
1045
 
955
1069
 
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')),
959
1073
    )
960
1074
 
961
1075
 
1002
1116
    {% trans "View this category in:" %}
1003
1117
    {% for lang_code, lang_name in languages %}
1004
1118
        {% language lang_code %}
1005
 
        <a href="{% url category slug=category.slug %}">{{ lang_name }}</a>
 
1119
        <a href="{% url 'category' slug=category.slug %}">{{ lang_name }}</a>
1006
1120
        {% endlanguage %}
1007
1121
    {% endfor %}
1008
1122
 
1049
1163
    commands from the GNU gettext toolset: ``xgettext``, ``msgfmt``,
1050
1164
    ``msgmerge`` and ``msguniq``.
1051
1165
 
1052
 
    .. versionchanged:: 1.2
1053
 
 
1054
1166
    The minimum version of the ``gettext`` utilities supported is 0.15.
1055
1167
 
1056
1168
To create or update a message file, run this command::
1247
1359
 
1248
1360
.. highlightlang:: python
1249
1361
 
 
1362
.. currentmodule:: django.views.i18n
 
1363
 
1250
1364
.. function:: set_language(request)
1251
1365
 
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.
1255
1369
 
 
1370
Make sure that the following item is in your
 
1371
:setting:`TEMPLATE_CONTEXT_PROCESSORS` list in your settings file::
 
1372
 
 
1373
    'django.core.context_processors.i18n'
 
1374
 
1256
1375
Activate this view by adding the following line to your URLconf::
1257
1376
 
1258
1377
    (r'^i18n/', include('django.conf.urls.i18n')),
1284
1403
 
1285
1404
.. code-block:: html+django
1286
1405
 
1287
 
    <form action="/i18n/setlang/" method="post">
 
1406
    <form action="{% url 'set_language' %}" method="post">
1288
1407
    {% csrf_token %}
1289
1408
    <input name="next" type="hidden" value="{{ redirect_to }}" />
1290
1409
    <select name="language">
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.
1526
1643
 
1527
 
.. deprecated:: 1.3
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.
1533
 
 
1534
1644
.. seealso::
1535
1645
 
1536
1646
    The translations for literals included in JavaScript assets are looked up
1543
1653
etc.
1544
1654
 
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.
1549
1659
 
1550
 
.. note::
1551
 
 
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.)
1558
 
 
1559
1660
All message file repositories are structured the same way. They are:
1560
1661
 
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)``
1567
1666