Fixed #17087 -- Re-organized the i18n docs to reduce confusion between USE_I18N/USE_L10N and the concepts of internationalization/localisation. Re

moved some duplicate content.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@17026 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Aymeric Augustin 2011-10-22 17:17:57 +00:00
parent 4f00a2d316
commit 67e6e0fcf3
13 changed files with 846 additions and 877 deletions

View File

@ -1,121 +0,0 @@
.. _using-translations-in-your-own-projects:
===============================================
Using internationalization in your own projects
===============================================
At runtime, Django builds an in-memory unified catalog of literals-translations.
To achieve this it looks for translations by following this algorithm regarding
the order in which it examines the different file paths to load the compiled
:term:`message files <message file>` (``.mo``) and the precedence of multiple
translations for the same literal:
1. The directories listed in :setting:`LOCALE_PATHS` have the highest
precedence, with the ones appearing first having higher precedence than
the ones appearing later.
2. Then, it looks for and uses if it exists a ``locale`` directory in each
of the installed apps listed in :setting:`INSTALLED_APPS`. The ones
appearing first have higher precedence than the ones appearing later.
3. Then, it looks for a ``locale`` directory in the project directory, or
more accurately, in the directory containing your settings file.
4. Finally, the Django-provided base translation in ``django/conf/locale``
is used as a fallback.
.. deprecated:: 1.3
Lookup in the ``locale`` subdirectory of the directory containing your
settings file (item 3 above) is deprecated since the 1.3 release and will be
removed in Django 1.5. You can use the :setting:`LOCALE_PATHS` setting
instead, by listing the absolute filesystem path of such ``locale``
directory in the setting value.
.. seealso::
The translations for literals included in JavaScript assets are looked up
following a similar but not identical algorithm. See the
:ref:`javascript_catalog view documentation <javascript_catalog-view>` for
more details.
In all cases the name of the directory containing the translation is expected to
be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
etc.
This way, you can write applications that include their own translations, and
you can override base translations in your project path. Or, you can just build
a big project out of several apps and put all translations into one big common
message file specific to the project you are composing. The choice is yours.
.. note::
If you're using manually configured settings, as described in
:ref:`settings-without-django-settings-module`, the ``locale`` directory in
the project directory will not be examined, since Django loses the ability
to work out the location of the project directory. (Django normally uses the
location of the settings file to determine this, and a settings file doesn't
exist if you're manually configuring your settings.)
All message file repositories are structured the same way. They are:
* All paths listed in :setting:`LOCALE_PATHS` in your settings file are
searched for ``<language>/LC_MESSAGES/django.(po|mo)``
* ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` --
deprecated, see above.
* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
* ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>`
tool. You only need to be in the same directory where the ``locale/`` directory
is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>`
to produce the binary ``.mo`` files that are used by ``gettext``. Read the
:doc:`/topics/i18n/localization` document for more details.
You can also run ``django-admin.py compilemessages --settings=path.to.settings``
to make the compiler process all the directories in your :setting:`LOCALE_PATHS`
setting.
Finally, you should give some thought to the structure of your translation
files. If your applications need to be delivered to other users and will
be used in other projects, you might want to use app-specific translations.
But using app-specific translations and project-specific translations could
produce weird problems with ``makemessages``: It will traverse all directories
below the current path and so might put message IDs into a unified, common
message file for the current project that are already in application message
files.
The easiest way out is to store applications that are not part of the project
(and so carry their own translations) outside the project tree. That way,
``django-admin.py makemessages``, when ran on a project level will only extract
strings that are connected to your explicit project and not strings that are
distributed independently.
Using translations outside views and templates
==============================================
While Django provides a rich set of i18n tools for use in views and templates,
it does not restrict the usage to Django-specific code. The Django translation
mechanisms can be used to translate arbitrary texts to any language that is
supported by Django (as long as an appropriate translation catalog exists, of
course). You can load a translation catalog, activate it and translate text to
language of your choice, but remember to switch back to original language, as
activating a translation catalog is done on per-thread basis and such change
will affect code running in the same thread.
For example::
from django.utils import translation
def welcome_translated(language):
cur_language = translation.get_language()
try:
translation.activate(language)
text = translation.ugettext('welcome')
finally:
translation.activate(cur_language)
return text
Calling this function with the value 'de' will give you ``"Willkommen"``,
regardless of :setting:`LANGUAGE_CODE` and language set by middleware.
Functions of particular interest are ``django.utils.translation.get_language()``
which returns the language used in the current thread,
``django.utils.translation.activate()`` which activates a translation catalog
for the current thread, and ``django.utils.translation.check_for_language()``
which checks if the given language is supported by Django.

View File

@ -18,7 +18,6 @@ you quickly accomplish common tasks.
deployment/index deployment/index
error-reporting error-reporting
initial-data initial-data
i18n
jython jython
legacy-databases legacy-databases
outputting-csv outputting-csv

View File

@ -56,7 +56,7 @@ Browse the following sections to find out how:
triaging-tickets triaging-tickets
writing-code/index writing-code/index
writing-documentation writing-documentation
translations localizing
committing-code committing-code
.. _django-users: http://groups.google.com/group/django-users .. _django-users: http://groups.google.com/group/django-users

View File

@ -1,15 +1,15 @@
======================================= =================
Submitting and maintaining translations Localizing Django
======================================= =================
Various parts of Django, such as the admin site and validation error messages, Various parts of Django, such as the admin site and validation error messages,
are internationalized. This means they display different text depending on each are internationalized. This means they display differently depending on each
user's language setting. For this, Django uses the same internationalization and user's language or country. For this, Django uses the same internationalization
localization infrastructure available to Django applications, described in the and localization infrastructure available to Django applications, described in
:doc:`i18n documentation</topics/i18n/index>`. the :doc:`i18n documentation </topics/i18n/index>`.
Internationalization Translations
-------------------- ------------
Translations are contributed by Django users worldwide. The translation work is Translations are contributed by Django users worldwide. The translation work is
coordinated at `Transifex`_. coordinated at `Transifex`_.
@ -45,8 +45,8 @@ do:
For more information about how to use Transifex, read the For more information about how to use Transifex, read the
`Transifex User Guide`_. `Transifex User Guide`_.
Localization Formats
------------ -------
You can also review ``conf/locale/<locale>/formats.py``. This file describes You can also review ``conf/locale/<locale>/formats.py``. This file describes
the date, time and numbers formatting particularities of your locale. See the date, time and numbers formatting particularities of your locale. See

View File

@ -146,7 +146,7 @@ Django's general catalog in ``django/conf/locale``. If you want localflavor's
texts to be translated, like form fields error messages, you must include texts to be translated, like form fields error messages, you must include
:mod:`django.contrib.localflavor` in the :setting:`INSTALLED_APPS` setting, so :mod:`django.contrib.localflavor` in the :setting:`INSTALLED_APPS` setting, so
the internationalization system can find the catalog, as explained in the internationalization system can find the catalog, as explained in
:ref:`using-translations-in-your-own-projects`. :ref:`how-django-discovers-translations`.
Adding flavors Adding flavors
============== ==============

View File

@ -1243,7 +1243,7 @@ LOCALE_PATHS
Default: ``()`` (Empty tuple) Default: ``()`` (Empty tuple)
A tuple of directories where Django looks for translation files. A tuple of directories where Django looks for translation files.
See :ref:`using-translations-in-your-own-projects`. See :ref:`how-django-discovers-translations`.
Example:: Example::
@ -2038,10 +2038,10 @@ USE_I18N
Default: ``True`` Default: ``True``
A boolean that specifies whether Django's internationalization system should be A boolean that specifies whether Django's translation system should be enabled.
enabled. This provides an easy way to turn it off, for performance. If this is This provides an easy way to turn it off, for performance. If this is set to
set to ``False``, Django will make some optimizations so as not to load the ``False``, Django will make some optimizations so as not to load the
internationalization machinery. translation machinery.
See also :setting:`USE_L10N` See also :setting:`USE_L10N`
@ -2054,9 +2054,9 @@ USE_L10N
Default: ``False`` Default: ``False``
A boolean that specifies if data will be localized by default or not. If this A boolean that specifies if localized formatting of data will be enabled by
is set to ``True``, e.g. Django will display numbers and dates using the default or not. If this is set to ``True``, e.g. Django will display numbers and
format of the current locale. dates using the format of the current locale.
See also :setting:`USE_I18N` and :setting:`LANGUAGE_CODE` See also :setting:`USE_I18N` and :setting:`LANGUAGE_CODE`

View File

@ -455,7 +455,7 @@ appropriate entities.
:synopsis: Internationalization support. :synopsis: Internationalization support.
For a complete discussion on the usage of the following see the For a complete discussion on the usage of the following see the
:doc:`Internationalization documentation </topics/i18n/internationalization>`. :doc:`translation documentation </topics/i18n/translation>`.
.. function:: gettext(message) .. function:: gettext(message)

View File

@ -494,12 +494,9 @@ more on these decorators.
.. versionadded:: 1.2 .. versionadded:: 1.2
If :setting:`USE_I18N` is set to ``True`` then the generated cache key will If :setting:`USE_I18N` is set to ``True`` then the generated cache key will
include the name of the active :term:`language<language code>`. include the name of the active :term:`language<language code>` -- see also
This allows you to easily cache multilingual sites without having to create :ref:`how-django-discovers-language-preference`). This allows you to easily
the cache key yourself. cache multilingual sites without having to create the cache key yourself.
See :doc:`/topics/i18n/deployment` for more on how Django discovers the active
language.
__ `Controlling cache: Using other headers`_ __ `Controlling cache: Using other headers`_

View File

@ -1,217 +0,0 @@
==========================
Deployment of translations
==========================
If you don't need internationalization
======================================
Django's internationalization hooks are on by default, and that means there's a
bit of i18n-related overhead in certain places of the framework. If you don't
use internationalization, you should take the two seconds to set
:setting:`USE_I18N = False <USE_I18N>` in your settings file. If
:setting:`USE_I18N` is set to ``False``, then Django will make some
optimizations so as not to load the internationalization machinery.
You'll probably also want to remove ``'django.core.context_processors.i18n'``
from your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting.
.. note::
There is also an independent but related :setting:`USE_L10N` setting that
controls if Django should implement format localization.
If :setting:`USE_L10N` is set to ``True``, Django will handle numbers times,
and dates in the format of the current locale. That includes representation
of these field types on templates and allowed input formats for dates,
times on model forms.
See :ref:`format-localization` for more details.
If you do need internationalization
===================================
.. _how-django-discovers-language-preference:
How Django discovers language preference
----------------------------------------
Once you've prepared your translations -- or, if you just want to use the
translations that come with Django -- you'll just need to activate translation
for your app.
Behind the scenes, Django has a very flexible model of deciding which language
should be used -- installation-wide, for a particular user, or both.
To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.
Django uses this language as the default translation -- the final attempt if no
other translator finds a translation.
If all you want to do is run Django with your native language, and a language
file is available for it, all you need to do is set :setting:`LANGUAGE_CODE`.
If you want to let each individual user specify which language he or she
prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language
selection based on data from the request. It customizes content for each user.
To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``
to your :setting:`MIDDLEWARE_CLASSES` setting. Because middleware order
matters, you should follow these guidelines:
* Make sure it's one of the first middlewares installed.
* It should come after ``SessionMiddleware``, because ``LocaleMiddleware``
makes use of session data. And it should come before ``CommonMiddleware``
because ``CommonMiddleware`` needs an activated language in order
to resolve the requested URL.
* If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.
For example, your :setting:`MIDDLEWARE_CLASSES` might look like this::
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
(For more on middleware, see the :doc:`middleware documentation
</topics/http/middleware>`.)
``LocaleMiddleware`` tries to determine the user's language preference by
following this algorithm:
.. versionchanged:: 1.4
* First, it looks for the language prefix in the requested URL. This is
only performed when you are using the ``i18n_patterns`` function in your
root URLconf. See :ref:`url-internationalization` for more information
about the language prefix and how to internationalize URL patterns.
* Failing that, it looks for a ``django_language`` key in the current
user's session.
* Failing that, it looks for a cookie.
The name of the cookie used is set by the :setting:`LANGUAGE_COOKIE_NAME`
setting. (The default name is ``django_language``.)
* Failing that, it looks at the ``Accept-Language`` HTTP header. This
header is sent by your browser and tells the server which language(s) you
prefer, in order by priority. Django tries each language in the header
until it finds one with available translations.
* Failing that, it uses the global :setting:`LANGUAGE_CODE` setting.
.. _locale-middleware-notes:
Notes:
* In each of these places, the language preference is expected to be in the
standard :term:`language format<language code>`, as a string. For example,
Brazilian Portuguese is ``pt-br``.
* If a base language is available but the sublanguage specified is not,
Django uses the base language. For example, if a user specifies ``de-at``
(Austrian German) but Django only has ``de`` available, Django uses
``de``.
* Only languages listed in the :setting:`LANGUAGES` setting can be selected.
If you want to restrict the language selection to a subset of provided
languages (because your application doesn't provide all those languages),
set :setting:`LANGUAGES` to a list of languages. For example::
LANGUAGES = (
('de', _('German')),
('en', _('English')),
)
This example restricts languages that are available for automatic
selection to German and English (and any sublanguage, like de-ch or
en-us).
* If you define a custom :setting:`LANGUAGES` setting, as explained in the
previous bullet, it's OK to mark the languages as translation strings
-- but use a "dummy" ``ugettext()`` function, not the one in
``django.utils.translation``. You should *never* import
``django.utils.translation`` from within your settings file, because that
module in itself depends on the settings, and that would cause a circular
import.
The solution is to use a "dummy" ``ugettext()`` function. Here's a sample
settings file::
ugettext = lambda s: s
LANGUAGES = (
('de', ugettext('German')),
('en', ugettext('English')),
)
With this arrangement, ``django-admin.py makemessages`` will still find
and mark these strings for translation, but the translation won't happen
at runtime -- so you'll have to remember to wrap the languages in the
*real* ``ugettext()`` in any code that uses :setting:`LANGUAGES` at
runtime.
* The ``LocaleMiddleware`` can only select languages for which there is a
Django-provided base translation. If you want to provide translations
for your application that aren't already in the set of translations
in Django's source tree, you'll want to provide at least a basic
one as described in the :ref:`Locale restrictions<locale-restrictions>`
note.
Once ``LocaleMiddleware`` determines the user's preference, it makes this
preference available as ``request.LANGUAGE_CODE`` for each
:class:`~django.http.HttpRequest`. Feel free to read this value in your view
code. Here's a simple example::
def hello_world(request, count):
if request.LANGUAGE_CODE == 'de-at':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")
Note that, with static (middleware-less) translation, the language is in
``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
in ``request.LANGUAGE_CODE``.
.. _settings file: ../settings/
.. _middleware documentation: ../middleware/
.. _session: ../sessions/
.. _request object: ../request_response/#httprequest-objects
How Django discovers translations
---------------------------------
As described in :ref:`using-translations-in-your-own-projects`, Django looks for
translations by following this algorithm regarding the order in which it
examines the different file paths to load the compiled :term:`message files
<message file>` (``.mo``) and the precedence of multiple translations for the
same literal:
1. The directories listed in :setting:`LOCALE_PATHS` have the highest
precedence, with the ones appearing first having higher precedence than
the ones appearing later.
2. Then, it looks for and uses if it exists a ``locale`` directory in each
of the installed apps listed in :setting:`INSTALLED_APPS`. The ones
appearing first have higher precedence than the ones appearing later.
3. Then, it looks for a ``locale`` directory in the project directory, or
more accurately, in the directory containing your settings file.
4. Finally, the Django-provided base translation in ``django/conf/locale``
is used as a fallback.
.. deprecated:: 1.3
Lookup in the ``locale`` subdirectory of the directory containing your
settings file (item 3 above) is deprecated since the 1.3 release and will be
removed in Django 1.5. You can use the :setting:`LOCALE_PATHS` setting
instead, by listing the absolute filesystem path of such ``locale``
directory in the setting value.
.. seealso::
The translations for literals included in JavaScript assets are looked up
following a similar but not identical algorithm. See the
:ref:`javascript_catalog view documentation <javascript_catalog-view>` for
more details.
In all cases the name of the directory containing the translation is expected to
be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
etc.

View File

@ -0,0 +1,182 @@
===================
Format localization
===================
.. _format-localization:
.. versionadded:: 1.2
Overview
========
Django's formatting system is capable to display dates, times and numbers in templates using the format specified for the current :term:`locale <locale
name>`. It also handles localized input in forms.
When it's enabled, two users accessing the same content may see dates, times and
numbers formatted in different ways, depending on the formats for their current
locale.
The formatting system is disabled by default. To enable it, it's
necessary to set :setting:`USE_L10N = True <USE_L10N>` in your settings file.
.. note::
The default :file:`settings.py` file created by :djadmin:`django-admin.py
startproject <startproject>` includes :setting:`USE_L10N = True <USE_L10N>`
for convenience.
.. note::
There is also an independent but related :setting:`USE_I18N` setting that
controls if Django should activate translation. See
:doc:`/topics/i18n/translation` for more details.
Locale aware input in forms
===========================
When formatting is enabled, Django can use localized formats when parsing dates,
times and numbers in forms. That means it tries different formats for different
locales when guessing the format used by the user when inputting data on forms.
.. note::
Django uses different formats for displaying data to those it uses for
parsing data. Most notably, the formats for parsing dates can't use the
``%a`` (abbreviated weekday name), ``%A`` (full weekday name),
``%b`` (abbreviated month name), ``%B`` (full month name),
or ``%p`` (AM/PM).
To enable a form field to localize input and output data simply use its
``localize`` argument::
class CashRegisterForm(forms.Form):
product = forms.CharField()
revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
.. _topic-l10n-templates:
Controlling localization in templates
=====================================
When you have enabled formatting with :setting:`USE_L10N`, Django
will try to use a locale specific format whenever it outputs a value
in a template.
However, it may not always be appropriate to use localized values --
for example, if you're outputting Javascript or XML that is designed
to be machine-readable, you will always want unlocalized values. You
may also want to use localization in selected templates, rather than
using localization everywhere.
To allow for fine control over the use of localization, Django
provides the ``l10n`` template library that contains the following
tags and filters.
Template tags
-------------
.. templatetag:: localize
localize
~~~~~~~~
.. versionadded:: 1.3
Enables or disables localization of template variables in the
contained block.
This tag allows a more fine grained control of localization than
:setting:`USE_L10N`.
To activate or deactivate localization for a template block, use::
{% load l10n %}
{% localize on %}
{{ value }}
{% endlocalize %}
{% localize off %}
{{ value }}
{% endlocalize %}
.. note::
The value of :setting:`USE_L10N` isn't respected inside of a
``{% localize %}`` block.
See :tfilter:`localize` and :tfilter:`unlocalize` for template filters that will
do the same job on a per-variable basis.
Template filters
----------------
.. templatefilter:: localize
localize
~~~~~~~~
.. versionadded:: 1.3
Forces localization of a single value.
For example::
{% load l10n %}
{{ value|localize }}
To disable localization on a single value, use :tfilter:`unlocalize`. To control
localization over a large section of a template, use the :ttag:`localize` template
tag.
.. templatefilter:: unlocalize
unlocalize
~~~~~~~~~~
.. versionadded:: 1.3
Forces a single value to be printed without localization.
For example::
{% load l10n %}
{{ value|unlocalize }}
To force localization of a single value, use :tfilter:`localize`. To
control localization over a large section of a template, use the
:ttag:`localize` template tag.
Creating custom format files
============================
Django provides format definitions for many locales, but sometimes you might
want to create your own, because a format files doesn't exist for your locale,
or because you want to overwrite some of the values.
To use custom formats, specify the path where you'll place format files first.
To do that, just set your :setting:`FORMAT_MODULE_PATH` setting to the package
where format files will exist, for instance::
FORMAT_MODULE_PATH = 'mysite.formats'
Files are not placed directly in this directory, but in a directory named as
the locale, and must be named ``formats.py``.
To customize the English formats, a structure like this would be needed::
mysite/
formats/
__init__.py
en/
__init__.py
formats.py
where :file:`formats.py` contains custom format definitions. For example::
THOUSAND_SEPARATOR = ' '
to use a space as a thousand separator, instead of the default for English,
a comma.

View File

@ -2,64 +2,77 @@
Internationalization and localization Internationalization and localization
===================================== =====================================
Overview
========
Django has full support for internationalization of text in code and
templates, and format localization of dates and numbers. Here's how it works.
Essentially, Django does two things:
* It allows developers and template authors to specify which parts of
their apps should be translatable.
* It uses these hooks to translate Web apps for particular users according
to their language preferences.
The complete process can be seen as divided in three stages. It is also possible
to identify an identical number of roles with very well defined responsibilities
associated with each of these tasks (although it's perfectly normal if you
find yourself performing more than one of these roles):
* For application authors wishing to make sure their Django apps can be
used in different locales: :doc:`/topics/i18n/internationalization`.
* For translators wanting to translate Django apps: :doc:`/topics/i18n/localization`.
* For system administrators/final users setting up internationalized apps or
developers integrating third party apps: :doc:`/topics/i18n/deployment`.
.. toctree:: .. toctree::
:hidden: :hidden:
:maxdepth: 1 :maxdepth: 1
internationalization translation
localization formatting
deployment
.. _ seealso:: Overview
========
For more general information about the topic, see the `GNU gettext documentation`_ The goal of internationalization and localization is to allow a single Web
and the `Wikipedia article`_. application to offer its content in languages and formats tailored to the
audience.
Django has full support for :doc:`translation of text
</topics/i18n/translation>` and :doc:`formatting of dates, times and numbers
</topics/i18n/formatting>`.
Essentially, Django does two things:
* It allows developers and template authors to specify which parts of their apps
should be translated or formatted for local languages and cultures.
* It uses these hooks to localize Web apps for particular users according to
their preferences.
Obviously, translation depends on the target language. Formatting usually
depends on the target country.
Definitions
===========
The words "internationalization" and "localization" often cause confusion;
here's a simplified definition:
.. glossary::
internationalization
Preparing the software for localization. Usually done by developers.
localization
Writing the translations and local formats. Usually done by translators.
More details can be found in the `W3C Web Internationalization FAQ`_, the `Wikipedia article`_ or the `GNU gettext documentation`_.
.. _W3C Web Internationalization FAQ: http://www.w3.org/International/questions/qa-i18n
.. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts .. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts
.. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization .. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization
Glossary .. warning::
========
First lets define some terms that will help us to handle a common language: Translation and formatting are controlled by :setting:`USE_I18N` and
:setting:`USE_L10N` settings respectively. However, both features involve
internationalization and localization. The names of the settings are an
unfortunate result of Django's history.
Here are some other terms that will help us to handle a common language:
.. glossary:: .. glossary::
locale name locale name
A locale name, either a language specification of the form ``ll`` or a A locale name, either a language specification of the form ``ll`` or a
combined language and country specification of the form ``ll_CC``. combined language and country specification of the form ``ll_CC``.
Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. Note the underscore in Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. The language part is
some of them and the case of the part located to its right. always is lower case and the country part in upper case. The separator
is an underscore.
language code language code
Represents the name of a language. Browsers send the names of the Represents the name of a language. Browsers send the names of the
languages they accept in the ``Accept-Language`` HTTP header using this languages they accept in the ``Accept-Language`` HTTP header using this
format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Note the ``-`` format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Both the language
separator. and the country parts are in lower case. The separator is a dash.
message file message file
A message file is a plain-text file, representing a single language, A message file is a plain-text file, representing a single language,
@ -70,21 +83,6 @@ First lets define some terms that will help us to handle a common language:
translation string translation string
A literal that can be translated. A literal that can be translated.
.. _specialties-of-django-i18n: format file
A format file is a Python module that defines the data formats for a given
Specialties of Django translation locale.
=================================
Django's translation machinery uses the standard ``gettext`` module that comes
with Python. If you know ``gettext``, you might note these specialties in the
way Django does translation:
* The string domain is ``django`` or ``djangojs``. This string domain is
used to differentiate between different programs that store their data
in a common message-file library (usually ``/usr/share/locale/``). The
``django`` domain is used for python and template translation strings
and is loaded into the global translation catalogs. The ``djangojs``
domain is only used for JavaScript translation catalogs to make sure
that those are as small as possible.
* Django doesn't use ``xgettext`` alone. It uses Python wrappers around
``xgettext`` and ``msgfmt``. This is mostly for convenience.

View File

@ -1,409 +0,0 @@
============
Localization
============
This document covers three localization-related topics: `Creating language
files`_ , `locale aware date, time and numbers input/output in forms`_,
and `controlling localization in templates`_.
.. _`Creating language files`: how-to-create-language-files_
.. _`locale aware date, time and numbers input/output in forms`: format-localization_
.. _`controlling localization in templates`: topic-l10n-templates_
.. seealso::
The :doc:`/howto/i18n` document included with the Django HOW-TO documents collection.
.. _how-to-create-language-files:
How to create language files
============================
Once the string literals of an application have been tagged for later
translation, the translation themselves need to be written (or obtained). Here's
how that works.
.. _locale-restrictions:
.. admonition:: Locale restrictions
Django does not support localizing your application into a locale for which
Django itself has not been translated. In this case, it will ignore your
translation files. If you were to try this and Django supported it, you
would inevitably see a mixture of translated strings (from your application)
and English strings (from Django itself). If you want to support a locale
for your application that is not already part of Django, you'll need to make
at least a minimal translation of the Django core.
A good starting point is to copy the Django English ``.po`` file and to
translate at least some :term:`translation strings <translation string>`.
Message files
-------------
The first step is to create a :term:`message file` for a new language. A message
file is a plain-text file, representing a single language, that contains all
available translation strings and how they should be represented in the given
language. Message files have a ``.po`` file extension.
Django comes with a tool, ``django-admin.py makemessages``, that automates the
creation and upkeep of these files.
.. admonition:: Gettext utilities
The ``makemessages`` command (and ``compilemessages`` discussed later) use
commands from the GNU gettext toolset: ``xgettext``, ``msgfmt``,
``msgmerge`` and ``msguniq``.
.. versionchanged:: 1.2
The minimum version of the ``gettext`` utilities supported is 0.15.
To create or update a message file, run this command::
django-admin.py makemessages -l de
...where ``de`` is the language code for the message file you want to create.
The language code, in this case, is in :term:`locale format<locale name>`. For
example, it's ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian
German.
The script should be run from one of two places:
* The root directory of your Django project.
* The root directory of your Django app.
The script runs over your project source tree or your application source tree
and pulls out all strings marked for translation. It creates (or updates) a
message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``
example, the file will be ``locale/de/LC_MESSAGES/django.po``.
By default ``django-admin.py makemessages`` examines every file that has the
``.html`` or ``.txt`` file extension. In case you want to override that
default, use the ``--extension`` or ``-e`` option to specify the file
extensions to examine::
django-admin.py makemessages -l de -e txt
Separate multiple extensions with commas and/or use ``-e`` or ``--extension``
multiple times::
django-admin.py makemessages -l de -e html,txt -e xml
When :ref:`creating message files from JavaScript source code
<creating-message-files-from-js-code>` you need to use the special 'djangojs'
domain, **not** ``-e js``.
.. admonition:: No gettext?
If you don't have the ``gettext`` utilities installed, ``django-admin.py
makemessages`` will create empty files. If that's the case, either install
the ``gettext`` utilities or just copy the English message file
(``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting
point; it's just an empty translation file.
.. admonition:: Working on Windows?
If you're using Windows and need to install the GNU gettext utilities so
``django-admin makemessages`` works see :ref:`gettext_on_windows` for more
information.
The format of ``.po`` files is straightforward. Each ``.po`` file contains a
small bit of metadata, such as the translation maintainer's contact
information, but the bulk of the file is a list of **messages** -- simple
mappings between translation strings and the actual translated text for the
particular language.
For example, if your Django app contained a translation string for the text
``"Welcome to my site."``, like so::
_("Welcome to my site.")
...then ``django-admin.py makemessages`` will have created a ``.po`` file
containing the following snippet -- a message::
#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""
A quick explanation:
* ``msgid`` is the translation string, which appears in the source. Don't
change it.
* ``msgstr`` is where you put the language-specific translation. It starts
out empty, so it's your responsibility to change it. Make sure you keep
the quotes around your translation.
* As a convenience, each message includes, in the form of a comment line
prefixed with ``#`` and located above the ``msgid`` line, the filename and
line number from which the translation string was gleaned.
Long messages are a special case. There, the first string directly after the
``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
written over the next few lines as one string per line. Those strings are
directly concatenated. Don't forget trailing spaces within the strings;
otherwise, they'll be tacked together without whitespace!
.. admonition:: Mind your charset
When creating a PO file with your favorite text editor, first edit
the charset line (search for ``"CHARSET"``) and set it to the charset
you'll be using to edit the content. Due to the way the ``gettext`` tools
work internally and because we want to allow non-ASCII source strings in
Django's core and your applications, you **must** use UTF-8 as the encoding
for your PO file. This means that everybody will be using the same
encoding, which is important when Django processes the PO files.
To reexamine all source code and templates for new translation strings and
update all message files for **all** languages, run this::
django-admin.py makemessages -a
Compiling message files
-----------------------
After you create your message file -- and each time you make changes to it --
you'll need to compile it into a more efficient form, for use by ``gettext``.
Do this with the ``django-admin.py compilemessages`` utility.
This tool runs over all available ``.po`` files and creates ``.mo`` files, which
are binary files optimized for use by ``gettext``. In the same directory from
which you ran ``django-admin.py makemessages``, run ``django-admin.py
compilemessages`` like this::
django-admin.py compilemessages
That's it. Your translations are ready for use.
.. admonition:: Working on Windows?
If you're using Windows and need to install the GNU gettext utilities so
``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more
information.
.. admonition:: .po files: Encoding and BOM usage.
Django only supports ``.po`` files encoded in UTF-8 and without any BOM
(Byte Order Mark) so if your text editor adds such marks to the beginning of
files by default then you will need to reconfigure it.
.. _creating-message-files-from-js-code:
Creating message files from JavaScript source code
==================================================
You create and update the message files the same way as the other Django
message files -- with the ``django-admin.py makemessages`` tool. The only
difference is you need to explicitly specify what in gettext parlance is known
as a domain in this case the ``djangojs`` domain, by providing a ``-d djangojs``
parameter, like this::
django-admin.py makemessages -d djangojs -l de
This would create or update the message file for JavaScript for German.
After updating message files, just run ``django-admin.py compilemessages``
the same way as you do with normal Django message files.
.. _gettext_on_windows:
``gettext`` on Windows
======================
This is only needed for people who either want to extract message IDs or compile
message files (``.po``). Translation work itself just involves editing existing
files of this type, but if you want to create your own message files, or want to
test or compile a changed message file, you will need the ``gettext`` utilities:
* Download the following zip files from the GNOME servers
http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one
of its mirrors_
* ``gettext-runtime-X.zip``
* ``gettext-tools-X.zip``
``X`` is the version number, we are requiring ``0.15`` or higher.
* Extract the contents of the ``bin\`` directories in both files to the
same folder on your system (i.e. ``C:\Program Files\gettext-utils``)
* Update the system PATH:
* ``Control Panel > System > Advanced > Environment Variables``.
* In the ``System variables`` list, click ``Path``, click ``Edit``.
* Add ``;C:\Program Files\gettext-utils\bin`` at the end of the
``Variable value`` field.
.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS
You may also use ``gettext`` binaries you have obtained elsewhere, so long as
the ``xgettext --version`` command works properly. Do not attempt to use Django
translation utilities with a ``gettext`` package if the command ``xgettext
--version`` entered at a Windows command prompt causes a popup window saying
"xgettext.exe has generated errors and will be closed by Windows".
.. _format-localization:
Format localization
===================
.. versionadded:: 1.2
Django's formatting system is disabled by default. To enable it, it's
necessary to set :setting:`USE_L10N = True <USE_L10N>` in your settings file.
.. note::
The default :file:`settings.py` file created by :djadmin:`django-admin.py
startproject <startproject>` includes :setting:`USE_L10N = True <USE_L10N>`
for convenience.
When using Django's formatting system, dates and numbers on templates will be
displayed using the format specified for the current locale. Two users
accessing the same content, but in different language, will see date and
number fields formatted in different ways, depending on the format for their
current locale.
Django will also use localized formats when parsing data in forms. That means
Django uses different formats for different locales when guessing the format
used by the user when inputting data on forms.
.. note::
Django uses different formats for displaying data to those it uses for
parsing data. Most notably, the formats for parsing dates can't use the
``%a`` (abbreviated weekday name), ``%A`` (full weekday name),
``%b`` (abbreviated month name), ``%B`` (full month name),
or ``%p`` (AM/PM).
To enable a form field to localize input and output data simply use its
``localize`` argument::
class CashRegisterForm(forms.Form):
product = forms.CharField()
revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)
Creating custom format files
----------------------------
Django provides format definitions for many locales, but sometimes you might
want to create your own, because a format files doesn't exist for your locale,
or because you want to overwrite some of the values.
To use custom formats, first thing to do, is to specify the path where you'll
place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH`
setting to the path (in the format ``'foo.bar.baz``) where format files
will exists.
Files are not placed directly in this directory, but in a directory named as
the locale, and must be named ``formats.py``.
To customize the English formats, a structure like this would be needed::
mysite/
formats/
__init__.py
en/
__init__.py
formats.py
where :file:`formats.py` contains custom format definitions. For example::
THOUSAND_SEPARATOR = ' '
to use a space as a thousand separator, instead of the default for English,
a comma.
.. _topic-l10n-templates:
Controlling localization in templates
=====================================
When you have enabled localization using :setting:`USE_L10N`, Django
will try to use a locale specific format whenever it outputs a value
in a template.
However, it may not always be appropriate to use localized values --
for example, if you're outputting Javascript or XML that is designed
to be machine-readable, you will always want unlocalized values. You
may also want to use localization in selected templates, rather than
using localization everywhere.
To allow for fine control over the use of localization, Django
provides the ``l10n`` template library that contains the following
tags and filters.
Template tags
-------------
.. templatetag:: localize
localize
~~~~~~~~
.. versionadded:: 1.3
Enables or disables localization of template variables in the
contained block.
This tag allows a more fine grained control of localization than
:setting:`USE_L10N`.
To activate or deactivate localization for a template block, use::
{% load l10n %}
{% localize on %}
{{ value }}
{% endlocalize %}
{% localize off %}
{{ value }}
{% endlocalize %}
.. note::
The value of :setting:`USE_L10N` is not respected inside of a
`{% localize %}` block.
See :tfilter:`localized` and :tfilter:`unlocalized` for a template filter that will
do the same job on a per-variable basis.
Template filters
----------------
.. templatefilter:: localize
localize
~~~~~~~~
.. versionadded:: 1.3
Forces localization of a single value.
For example::
{% load l10n %}
{{ value|localize }}
To disable localization on a single value, use :tfilter:`unlocalize`. To control
localization over a large section of a template, use the :ttag:`localize` template
tag.
.. templatefilter:: unlocalize
unlocalize
~~~~~~~~~~
.. versionadded:: 1.3
Forces a single value to be printed without localization.
For example::
{% load l10n %}
{{ value|unlocalize }}
To force localization of a single value, use :tfilter:`localize`. To
control localization over a large section of a template, use the
:ttag:`localize` template tag.

View File

@ -1,27 +1,44 @@
==================== ===========
Internationalization Translation
==================== ===========
.. module:: django.utils.translation .. module:: django.utils.translation
Overview Overview
======== ========
The goal of internationalization is to allow a single Web application to offer In order to make a Django project translatable, you have to add a minimal amount
its content and functionality in multiple languages and locales. of hooks to your Python code and templates. These hooks are called
:term:`translation strings <translation string>`. They tell Django: "This text
should be translated into the end user's language, if a translation for this
text is available in that language." It's your responsibility to mark
translatable strings; the system can only translate strings it knows about.
For text translations, you, the Django developer, can accomplish this goal by Django then provides utilities to extract the translation strings into a
adding a minimal amount of hooks to your Python and templates. These hooks :term:`message file`. This file is a convenient way for translators to provide
are called **translation strings**. They tell Django: "This text should be the equivalent of the translation strings in the target language. Once the
translated into the end user's language, if a translation for this text is translators have filled in the message file, it must be compiled. This process
available in that language." It's your responsibility to mark translatable relies on the GNU gettext toolset.
strings; the system can only translate strings it knows about.
Django takes care of using these hooks to translate Web apps, on the fly, Once this is done, Django takes care of translating Web apps on the fly in each
according to users' language preferences. available language, according to users' language preferences.
Specifying translation strings: In Python code Django's internationalization hooks are on by default, and that means there's a
============================================== bit of i18n-related overhead in certain places of the framework. If you don't
use internationalization, you should take the two seconds to set
:setting:`USE_I18N = False <USE_I18N>` in your settings file. Then Django will
make some optimizations so as not to load the internationalization machinery.
You'll probably also want to remove ``'django.core.context_processors.i18n'``
from your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting.
.. note::
There is also an independent but related :setting:`USE_L10N` setting that
controls if Django should implement format localization. See
:doc:`/topics/i18n/formatting` for more details.
Internationalization: in Python code
====================================
Standard translation Standard translation
-------------------- --------------------
@ -85,8 +102,8 @@ Translation works on variables. Again, here's an identical example::
(The caveat with using variables or computed values, as in the previous two (The caveat with using variables or computed values, as in the previous two
examples, is that Django's translation-string-detecting utility, examples, is that Django's translation-string-detecting utility,
``django-admin.py makemessages``, won't be able to find these strings. More on :djadmin:`django-admin.py makemessages <makemessages>`, won't be able to find
``makemessages`` later.) these strings. More on :djadmin:`makemessages` later.)
The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
specified with Python's standard named-string interpolation syntax. Example:: specified with Python's standard named-string interpolation syntax. Example::
@ -126,7 +143,7 @@ This also works in templates with the :ttag:`comment` tag:
{% comment %}Translators: This is a text of the base template {% endcomment %} {% comment %}Translators: This is a text of the base template {% endcomment %}
The comment will then appear in the resulting .po file and should also be The comment will then appear in the resulting ``.po`` file and should also be
displayed by most translation tools. displayed by most translation tools.
Marking strings as no-op Marking strings as no-op
@ -221,9 +238,10 @@ cardinality of the elements at play.
count count
) % d ) % d
You would get a ``a format specification for argument 'name', as in You would get an error when running :djadmin:`django-admin.py
'msgstr[0]', doesn't exist in 'msgid'`` error when running compilemessages <compilemessages>`::
``django-admin.py compilemessages``.
a format specification for argument 'name', as in 'msgstr[0]', doesn't exist in 'msgid'
.. _contextual-markers: .. _contextual-markers:
@ -239,10 +257,10 @@ these words correctly in different contexts, you can use the
:func:`django.utils.translation.npgettext()` function if the string needs :func:`django.utils.translation.npgettext()` function if the string needs
pluralization. Both take a context string as the first variable. pluralization. Both take a context string as the first variable.
In the resulting .po file, the string will then appear as often as there are In the resulting ``.po`` file, the string will then appear as often as there are
different contextual markers for the same string (the context will appear on different contextual markers for the same string (the context will appear on the
the ``msgctxt`` line), allowing the translator to give a different translation ``msgctxt`` line), allowing the translator to give a different translation for
for each of them. each of them.
For example:: For example::
@ -258,7 +276,7 @@ or::
name = models.CharField(help_text=pgettext_lazy( name = models.CharField(help_text=pgettext_lazy(
'help text for MyThing model', 'This is the help text')) 'help text for MyThing model', 'This is the help text'))
will appear in the .po file as: will appear in the ``.po`` file as:
.. code-block:: po .. code-block:: po
@ -333,7 +351,7 @@ name::
class Meta: class Meta:
verbose_name = _('my thing') verbose_name = _('my thing')
verbose_name_plural = _('mythings') verbose_name_plural = _('my things')
Notes on model classes translation Notes on model classes translation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -398,7 +416,7 @@ strings when ``result`` itself is used in a string (usually at template
rendering time). rendering time).
Localized names of languages Localized names of languages
============================ ----------------------------
.. function:: get_language_info .. function:: get_language_info
@ -421,8 +439,8 @@ Similar access to this information is available for template code. See below.
.. _specifying-translation-strings-in-template-code: .. _specifying-translation-strings-in-template-code:
Specifying translation strings: In template code Internationalization: in template code
================================================ ======================================
.. highlightlang:: html+django .. highlightlang:: html+django
@ -672,8 +690,8 @@ There are also simple filters available for convenience:
.. _Django templates: ../templates_python/ .. _Django templates: ../templates_python/
Specifying translation strings: In JavaScript code Internationalization: in JavaScript code
================================================== ========================================
.. highlightlang:: python .. highlightlang:: python
@ -681,8 +699,8 @@ Adding translations to JavaScript poses some problems:
* JavaScript code doesn't have access to a ``gettext`` implementation. * JavaScript code doesn't have access to a ``gettext`` implementation.
* JavaScript code doesn't have access to .po or .mo files; they need to be * JavaScript code doesn't have access to ``.po`` or ``.mo`` files; they need to
delivered by the server. be delivered by the server.
* The translation catalogs for JavaScript should be kept as small as * The translation catalogs for JavaScript should be kept as small as
possible. possible.
@ -700,12 +718,12 @@ The ``javascript_catalog`` view
.. function:: javascript_catalog(request, domain='djangojs', packages=None) .. function:: javascript_catalog(request, domain='djangojs', packages=None)
The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog` The main solution to these problems is the
view, which sends out a JavaScript code library with functions that mimic the :meth:`django.views.i18n.javascript_catalog` view, which sends out a JavaScript
``gettext`` interface, plus an array of translation strings. Those translation code library with functions that mimic the ``gettext`` interface, plus an array
strings are taken from applications or Django core, according to what you of translation strings. Those translation strings are taken from applications or
specify in either the info_dict or the URL. Paths listed in Django core, according to what you specify in either the ``info_dict`` or the
:setting:`LOCALE_PATHS` are also included. URL. Paths listed in :setting:`LOCALE_PATHS` are also included.
You hook it up like this:: You hook it up like this::
@ -815,8 +833,8 @@ to produce proper pluralizations).
.. _url-internationalization: .. _url-internationalization:
Specifying translation strings: In URL patterns Internationalization: in URL patterns
=============================================== =====================================
.. versionadded:: 1.4 .. versionadded:: 1.4
@ -922,9 +940,9 @@ URL patterns can also be marked translatable using the
) )
After you've created the translations (see :doc:`localization` for more After you've created the translations, the
information), the :func:`~django.core.urlresolvers.reverse` function will :func:`~django.core.urlresolvers.reverse` function will return the URL in the
return the URL in the active language. Example:: active language. Example::
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import activate from django.utils.translation import activate
@ -971,10 +989,242 @@ template tag. It enables the given language in the enclosed template section:
The :ttag:`language` tag expects the language code as the only argument. The :ttag:`language` tag expects the language code as the only argument.
.. _how-to-create-language-files:
Localization: how to create language files
==========================================
Once the string literals of an application have been tagged for later
translation, the translation themselves need to be written (or obtained). Here's
how that works.
.. _locale-restrictions:
.. admonition:: Locale restrictions
Django does not support localizing your application into a locale for which
Django itself has not been translated. In this case, it will ignore your
translation files. If you were to try this and Django supported it, you
would inevitably see a mixture of translated strings (from your application)
and English strings (from Django itself). If you want to support a locale
for your application that is not already part of Django, you'll need to make
at least a minimal translation of the Django core.
A good starting point is to copy the Django English ``.po`` file and to
translate at least some :term:`translation strings <translation string>`.
Message files
-------------
The first step is to create a :term:`message file` for a new language. A message
file is a plain-text file, representing a single language, that contains all
available translation strings and how they should be represented in the given
language. Message files have a ``.po`` file extension.
Django comes with a tool, :djadmin:`django-admin.py makemessages
<makemessages>`, that automates the creation and upkeep of these files.
.. admonition:: Gettext utilities
The ``makemessages`` command (and ``compilemessages`` discussed later) use
commands from the GNU gettext toolset: ``xgettext``, ``msgfmt``,
``msgmerge`` and ``msguniq``.
.. versionchanged:: 1.2
The minimum version of the ``gettext`` utilities supported is 0.15.
To create or update a message file, run this command::
django-admin.py makemessages -l de
...where ``de`` is the language code for the message file you want to create.
The language code, in this case, is in :term:`locale format<locale name>`. For
example, it's ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian
German.
The script should be run from one of two places:
* The root directory of your Django project.
* The root directory of your Django app.
The script runs over your project source tree or your application source tree
and pulls out all strings marked for translation. It creates (or updates) a
message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``
example, the file will be ``locale/de/LC_MESSAGES/django.po``.
By default :djadmin:`django-admin.py makemessages <makemessages>` examines every
file that has the ``.html`` or ``.txt`` file extension. In case you want to
override that default, use the ``--extension`` or ``-e`` option to specify the
file extensions to examine::
django-admin.py makemessages -l de -e txt
Separate multiple extensions with commas and/or use ``-e`` or ``--extension``
multiple times::
django-admin.py makemessages -l de -e html,txt -e xml
.. warning::
When :ref:`creating message files from JavaScript source code
<creating-message-files-from-js-code>` you need to use the special
'djangojs' domain, **not** ``-e js``.
.. admonition:: No gettext?
If you don't have the ``gettext`` utilities installed,
:djadmin:`makemessages` will create empty files. If that's the case, either
install the ``gettext`` utilities or just copy the English message file
(``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting
point; it's just an empty translation file.
.. admonition:: Working on Windows?
If you're using Windows and need to install the GNU gettext utilities so
:djadmin:`makemessages` works, see :ref:`gettext_on_windows` for more
information.
The format of ``.po`` files is straightforward. Each ``.po`` file contains a
small bit of metadata, such as the translation maintainer's contact
information, but the bulk of the file is a list of **messages** -- simple
mappings between translation strings and the actual translated text for the
particular language.
For example, if your Django app contained a translation string for the text
``"Welcome to my site."``, like so::
_("Welcome to my site.")
...then :djadmin:`django-admin.py makemessages <makemessages>` will have created
a ``.po`` file containing the following snippet -- a message::
#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""
A quick explanation:
* ``msgid`` is the translation string, which appears in the source. Don't
change it.
* ``msgstr`` is where you put the language-specific translation. It starts
out empty, so it's your responsibility to change it. Make sure you keep
the quotes around your translation.
* As a convenience, each message includes, in the form of a comment line
prefixed with ``#`` and located above the ``msgid`` line, the filename and
line number from which the translation string was gleaned.
Long messages are a special case. There, the first string directly after the
``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be
written over the next few lines as one string per line. Those strings are
directly concatenated. Don't forget trailing spaces within the strings;
otherwise, they'll be tacked together without whitespace!
.. admonition:: Mind your charset
When creating a PO file with your favorite text editor, first edit
the charset line (search for ``"CHARSET"``) and set it to the charset
you'll be using to edit the content. Due to the way the ``gettext`` tools
work internally and because we want to allow non-ASCII source strings in
Django's core and your applications, you **must** use UTF-8 as the encoding
for your PO file. This means that everybody will be using the same
encoding, which is important when Django processes the PO files.
To reexamine all source code and templates for new translation strings and
update all message files for **all** languages, run this::
django-admin.py makemessages -a
Compiling message files
-----------------------
After you create your message file -- and each time you make changes to it --
you'll need to compile it into a more efficient form, for use by ``gettext``. Do
this with the :djadmin:`django-admin.py compilemessages <compilemessages>`
utility.
This tool runs over all available ``.po`` files and creates ``.mo`` files, which
are binary files optimized for use by ``gettext``. In the same directory from
which you ran :djadmin:`django-admin.py makemessages <makemessages>`, run :djadmin:`django-admin.py compilemessages <compilemessages>` like this::
django-admin.py compilemessages
That's it. Your translations are ready for use.
.. admonition:: Working on Windows?
If you're using Windows and need to install the GNU gettext utilities so
:djadmin:`django-admin.py compilemessages <compilemessages>` works see
:ref:`gettext_on_windows` for more information.
.. admonition:: .po files: Encoding and BOM usage.
Django only supports ``.po`` files encoded in UTF-8 and without any BOM
(Byte Order Mark) so if your text editor adds such marks to the beginning of
files by default then you will need to reconfigure it.
.. _creating-message-files-from-js-code:
Creating message files from JavaScript source code
--------------------------------------------------
You create and update the message files the same way as the other Django message
files -- with the :djadmin:`django-admin.py makemessages <makemessages>` tool.
The only difference is you need to explicitly specify what in gettext parlance
is known as a domain in this case the ``djangojs`` domain, by providing a ``-d
djangojs`` parameter, like this::
django-admin.py makemessages -d djangojs -l de
This would create or update the message file for JavaScript for German. After
updating message files, just run :djadmin:`django-admin.py compilemessages
<compilemessages>` the same way as you do with normal Django message files.
.. _gettext_on_windows:
``gettext`` on Windows
----------------------
This is only needed for people who either want to extract message IDs or compile
message files (``.po``). Translation work itself just involves editing existing
files of this type, but if you want to create your own message files, or want to
test or compile a changed message file, you will need the ``gettext`` utilities:
* Download the following zip files from the GNOME servers
http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one
of its mirrors_
* ``gettext-runtime-X.zip``
* ``gettext-tools-X.zip``
``X`` is the version number, we are requiring ``0.15`` or higher.
* Extract the contents of the ``bin\`` directories in both files to the
same folder on your system (i.e. ``C:\Program Files\gettext-utils``)
* Update the system PATH:
* ``Control Panel > System > Advanced > Environment Variables``.
* In the ``System variables`` list, click ``Path``, click ``Edit``.
* Add ``;C:\Program Files\gettext-utils\bin`` at the end of the
``Variable value`` field.
.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS
You may also use ``gettext`` binaries you have obtained elsewhere, so long as
the ``xgettext --version`` command works properly. Do not attempt to use Django
translation utilities with a ``gettext`` package if the command ``xgettext
--version`` entered at a Windows command prompt causes a popup window saying
"xgettext.exe has generated errors and will be closed by Windows".
Miscellaneous
=============
.. _set_language-redirect-view: .. _set_language-redirect-view:
The ``set_language`` redirect view The ``set_language`` redirect view
================================== ----------------------------------
.. highlightlang:: python .. highlightlang:: python
@ -1019,3 +1269,293 @@ Here's example HTML template code:
</select> </select>
<input type="submit" value="Go" /> <input type="submit" value="Go" />
</form> </form>
Using translations outside views and templates
----------------------------------------------
While Django provides a rich set of i18n tools for use in views and templates,
it does not restrict the usage to Django-specific code. The Django translation
mechanisms can be used to translate arbitrary texts to any language that is
supported by Django (as long as an appropriate translation catalog exists, of
course). You can load a translation catalog, activate it and translate text to
language of your choice, but remember to switch back to original language, as
activating a translation catalog is done on per-thread basis and such change
will affect code running in the same thread.
For example::
from django.utils import translation
def welcome_translated(language):
cur_language = translation.get_language()
try:
translation.activate(language)
text = translation.ugettext('welcome')
finally:
translation.activate(cur_language)
return text
Calling this function with the value 'de' will give you ``"Willkommen"``,
regardless of :setting:`LANGUAGE_CODE` and language set by middleware.
Functions of particular interest are ``django.utils.translation.get_language()``
which returns the language used in the current thread,
``django.utils.translation.activate()`` which activates a translation catalog
for the current thread, and ``django.utils.translation.check_for_language()``
which checks if the given language is supported by Django.
Implementation notes
====================
.. _specialties-of-django-i18n:
Specialties of Django translation
---------------------------------
Django's translation machinery uses the standard ``gettext`` module that comes
with Python. If you know ``gettext``, you might note these specialties in the
way Django does translation:
* The string domain is ``django`` or ``djangojs``. This string domain is
used to differentiate between different programs that store their data
in a common message-file library (usually ``/usr/share/locale/``). The
``django`` domain is used for python and template translation strings
and is loaded into the global translation catalogs. The ``djangojs``
domain is only used for JavaScript translation catalogs to make sure
that those are as small as possible.
* Django doesn't use ``xgettext`` alone. It uses Python wrappers around
``xgettext`` and ``msgfmt``. This is mostly for convenience.
.. _how-django-discovers-language-preference:
How Django discovers language preference
----------------------------------------
Once you've prepared your translations -- or, if you just want to use the
translations that come with Django -- you'll just need to activate translation
for your app.
Behind the scenes, Django has a very flexible model of deciding which language
should be used -- installation-wide, for a particular user, or both.
To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`.
Django uses this language as the default translation -- the final attempt if no
other translator finds a translation.
If all you want to do is run Django with your native language, and a language
file is available for it, all you need to do is set :setting:`LANGUAGE_CODE`.
If you want to let each individual user specify which language he or she
prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language
selection based on data from the request. It customizes content for each user.
To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``
to your :setting:`MIDDLEWARE_CLASSES` setting. Because middleware order
matters, you should follow these guidelines:
* Make sure it's one of the first middlewares installed.
* It should come after ``SessionMiddleware``, because ``LocaleMiddleware``
makes use of session data. And it should come before ``CommonMiddleware``
because ``CommonMiddleware`` needs an activated language in order
to resolve the requested URL.
* If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.
For example, your :setting:`MIDDLEWARE_CLASSES` might look like this::
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
(For more on middleware, see the :doc:`middleware documentation
</topics/http/middleware>`.)
``LocaleMiddleware`` tries to determine the user's language preference by
following this algorithm:
.. versionchanged:: 1.4
* First, it looks for the language prefix in the requested URL. This is
only performed when you are using the ``i18n_patterns`` function in your
root URLconf. See :ref:`url-internationalization` for more information
about the language prefix and how to internationalize URL patterns.
* Failing that, it looks for a ``django_language`` key in the current
user's session.
* Failing that, it looks for a cookie.
The name of the cookie used is set by the :setting:`LANGUAGE_COOKIE_NAME`
setting. (The default name is ``django_language``.)
* Failing that, it looks at the ``Accept-Language`` HTTP header. This
header is sent by your browser and tells the server which language(s) you
prefer, in order by priority. Django tries each language in the header
until it finds one with available translations.
* Failing that, it uses the global :setting:`LANGUAGE_CODE` setting.
.. _locale-middleware-notes:
Notes:
* In each of these places, the language preference is expected to be in the
standard :term:`language format<language code>`, as a string. For example,
Brazilian Portuguese is ``pt-br``.
* If a base language is available but the sublanguage specified is not,
Django uses the base language. For example, if a user specifies ``de-at``
(Austrian German) but Django only has ``de`` available, Django uses
``de``.
* Only languages listed in the :setting:`LANGUAGES` setting can be selected.
If you want to restrict the language selection to a subset of provided
languages (because your application doesn't provide all those languages),
set :setting:`LANGUAGES` to a list of languages. For example::
LANGUAGES = (
('de', _('German')),
('en', _('English')),
)
This example restricts languages that are available for automatic
selection to German and English (and any sublanguage, like de-ch or
en-us).
* If you define a custom :setting:`LANGUAGES` setting, as explained in the
previous bullet, it's OK to mark the languages as translation strings
-- but use a "dummy" ``ugettext()`` function, not the one in
``django.utils.translation``. You should *never* import
``django.utils.translation`` from within your settings file, because that
module in itself depends on the settings, and that would cause a circular
import.
The solution is to use a "dummy" ``ugettext()`` function. Here's a sample
settings file::
ugettext = lambda s: s
LANGUAGES = (
('de', ugettext('German')),
('en', ugettext('English')),
)
With this arrangement, :djadmin:`django-admin.py makemessages <makemessages>`
will still find and mark these strings for translation, but the translation
won't happen at runtime -- so you'll have to remember to wrap the languages in
the *real* ``ugettext()`` in any code that uses :setting:`LANGUAGES` at
runtime.
* The ``LocaleMiddleware`` can only select languages for which there is a
Django-provided base translation. If you want to provide translations
for your application that aren't already in the set of translations
in Django's source tree, you'll want to provide at least a basic
one as described in the :ref:`Locale restrictions<locale-restrictions>`
note.
Once ``LocaleMiddleware`` determines the user's preference, it makes this
preference available as ``request.LANGUAGE_CODE`` for each
:class:`~django.http.HttpRequest`. Feel free to read this value in your view
code. Here's a simple example::
def hello_world(request, count):
if request.LANGUAGE_CODE == 'de-at':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")
Note that, with static (middleware-less) translation, the language is in
``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
in ``request.LANGUAGE_CODE``.
.. _settings file: ../settings/
.. _middleware documentation: ../middleware/
.. _session: ../sessions/
.. _request object: ../request_response/#httprequest-objects
.. _how-django-discovers-translations:
How Django discovers translations
---------------------------------
At runtime, Django builds an in-memory unified catalog of literals-translations.
To achieve this it looks for translations by following this algorithm regarding
the order in which it examines the different file paths to load the compiled
:term:`message files <message file>` (``.mo``) and the precedence of multiple
translations for the same literal:
1. The directories listed in :setting:`LOCALE_PATHS` have the highest
precedence, with the ones appearing first having higher precedence than
the ones appearing later.
2. Then, it looks for and uses if it exists a ``locale`` directory in each
of the installed apps listed in :setting:`INSTALLED_APPS`. The ones
appearing first have higher precedence than the ones appearing later.
3. Then, it looks for a ``locale`` directory in the project directory, or
more accurately, in the directory containing your settings file.
4. Finally, the Django-provided base translation in ``django/conf/locale``
is used as a fallback.
.. deprecated:: 1.3
Lookup in the ``locale`` subdirectory of the directory containing your
settings file (item 3 above) is deprecated since the 1.3 release and will be
removed in Django 1.5. You can use the :setting:`LOCALE_PATHS` setting
instead, by listing the absolute filesystem path of such ``locale``
directory in the setting value.
.. seealso::
The translations for literals included in JavaScript assets are looked up
following a similar but not identical algorithm. See the
:ref:`javascript_catalog view documentation <javascript_catalog-view>` for
more details.
In all cases the name of the directory containing the translation is expected to
be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
etc.
This way, you can write applications that include their own translations, and
you can override base translations in your project path. Or, you can just build
a big project out of several apps and put all translations into one big common
message file specific to the project you are composing. The choice is yours.
.. note::
If you're using manually configured settings, as described in
:ref:`settings-without-django-settings-module`, the ``locale`` directory in
the project directory will not be examined, since Django loses the ability
to work out the location of the project directory. (Django normally uses the
location of the settings file to determine this, and a settings file doesn't
exist if you're manually configuring your settings.)
All message file repositories are structured the same way. They are:
* All paths listed in :setting:`LOCALE_PATHS` in your settings file are
searched for ``<language>/LC_MESSAGES/django.(po|mo)``
* ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` --
deprecated, see above.
* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
* ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>`
tool. You only need to be in the same directory where the ``locale/`` directory
is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>`
to produce the binary ``.mo`` files that are used by ``gettext``.
You can also run :djadmin:`django-admin.py compilemessages
--settings=path.to.settings <compilemessages>` to make the compiler process all
the directories in your :setting:`LOCALE_PATHS` setting.
Finally, you should give some thought to the structure of your translation
files. If your applications need to be delivered to other users and will be used
in other projects, you might want to use app-specific translations. But using
app-specific translations and project-specific translations could produce weird
problems with :djadmin:`makemessages`: it will traverse all directories below
the current path and so might put message IDs into a unified, common message
file for the current project that are already in application message files.
The easiest way out is to store applications that are not part of the project
(and so carry their own translations) outside the project tree. That way,
:djadmin:`django-admin.py makemessages <makemessages>`, when ran on a project
level will only extract strings that are connected to your explicit project and
not strings that are distributed independently.