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:
parent
4f00a2d316
commit
67e6e0fcf3
|
@ -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.
|
|
@ -18,7 +18,6 @@ you quickly accomplish common tasks.
|
|||
deployment/index
|
||||
error-reporting
|
||||
initial-data
|
||||
i18n
|
||||
jython
|
||||
legacy-databases
|
||||
outputting-csv
|
||||
|
|
|
@ -56,7 +56,7 @@ Browse the following sections to find out how:
|
|||
triaging-tickets
|
||||
writing-code/index
|
||||
writing-documentation
|
||||
translations
|
||||
localizing
|
||||
committing-code
|
||||
|
||||
.. _django-users: http://groups.google.com/group/django-users
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
=======================================
|
||||
Submitting and maintaining translations
|
||||
=======================================
|
||||
=================
|
||||
Localizing Django
|
||||
=================
|
||||
|
||||
Various parts of Django, such as the admin site and validation error messages,
|
||||
are internationalized. This means they display different text depending on each
|
||||
user's language setting. For this, Django uses the same internationalization and
|
||||
localization infrastructure available to Django applications, described in the
|
||||
:doc:`i18n documentation</topics/i18n/index>`.
|
||||
are internationalized. This means they display differently depending on each
|
||||
user's language or country. For this, Django uses the same internationalization
|
||||
and localization infrastructure available to Django applications, described in
|
||||
the :doc:`i18n documentation </topics/i18n/index>`.
|
||||
|
||||
Internationalization
|
||||
--------------------
|
||||
Translations
|
||||
------------
|
||||
|
||||
Translations are contributed by Django users worldwide. The translation work is
|
||||
coordinated at `Transifex`_.
|
||||
|
@ -45,8 +45,8 @@ do:
|
|||
For more information about how to use Transifex, read the
|
||||
`Transifex User Guide`_.
|
||||
|
||||
Localization
|
||||
------------
|
||||
Formats
|
||||
-------
|
||||
|
||||
You can also review ``conf/locale/<locale>/formats.py``. This file describes
|
||||
the date, time and numbers formatting particularities of your locale. See
|
|
@ -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
|
||||
:mod:`django.contrib.localflavor` in the :setting:`INSTALLED_APPS` setting, so
|
||||
the internationalization system can find the catalog, as explained in
|
||||
:ref:`using-translations-in-your-own-projects`.
|
||||
:ref:`how-django-discovers-translations`.
|
||||
|
||||
Adding flavors
|
||||
==============
|
||||
|
|
|
@ -1243,7 +1243,7 @@ LOCALE_PATHS
|
|||
Default: ``()`` (Empty tuple)
|
||||
|
||||
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::
|
||||
|
||||
|
@ -2038,10 +2038,10 @@ USE_I18N
|
|||
|
||||
Default: ``True``
|
||||
|
||||
A boolean that specifies whether Django's internationalization system should be
|
||||
enabled. This provides an easy way to turn it off, for performance. If this is
|
||||
set to ``False``, Django will make some optimizations so as not to load the
|
||||
internationalization machinery.
|
||||
A boolean that specifies whether Django's translation system should be enabled.
|
||||
This provides an easy way to turn it off, for performance. If this is set to
|
||||
``False``, Django will make some optimizations so as not to load the
|
||||
translation machinery.
|
||||
|
||||
See also :setting:`USE_L10N`
|
||||
|
||||
|
@ -2054,9 +2054,9 @@ USE_L10N
|
|||
|
||||
Default: ``False``
|
||||
|
||||
A boolean that specifies if data will be localized by default or not. If this
|
||||
is set to ``True``, e.g. Django will display numbers and dates using the
|
||||
format of the current locale.
|
||||
A boolean that specifies if localized formatting of data will be enabled by
|
||||
default or not. If this is set to ``True``, e.g. Django will display numbers and
|
||||
dates using the format of the current locale.
|
||||
|
||||
See also :setting:`USE_I18N` and :setting:`LANGUAGE_CODE`
|
||||
|
||||
|
|
|
@ -455,7 +455,7 @@ appropriate entities.
|
|||
:synopsis: Internationalization support.
|
||||
|
||||
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)
|
||||
|
||||
|
|
|
@ -494,12 +494,9 @@ more on these decorators.
|
|||
.. versionadded:: 1.2
|
||||
|
||||
If :setting:`USE_I18N` is set to ``True`` then the generated cache key will
|
||||
include the name of the active :term:`language<language code>`.
|
||||
This allows you to easily 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.
|
||||
include the name of the active :term:`language<language code>` -- see also
|
||||
:ref:`how-django-discovers-language-preference`). This allows you to easily
|
||||
cache multilingual sites without having to create the cache key yourself.
|
||||
|
||||
__ `Controlling cache: Using other headers`_
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -2,64 +2,77 @@
|
|||
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::
|
||||
:hidden:
|
||||
:maxdepth: 1
|
||||
|
||||
translation
|
||||
formatting
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The goal of internationalization and localization is to allow a single Web
|
||||
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
|
||||
deployment
|
||||
Writing the translations and local formats. Usually done by translators.
|
||||
|
||||
.. _ seealso::
|
||||
|
||||
For more general information about the topic, see the `GNU gettext documentation`_
|
||||
and the `Wikipedia article`_.
|
||||
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
|
||||
.. _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::
|
||||
|
||||
locale name
|
||||
A locale name, either a language specification of the form ``ll`` or a
|
||||
combined language and country specification of the form ``ll_CC``.
|
||||
Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. Note the underscore in
|
||||
some of them and the case of the part located to its right.
|
||||
Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. The language part is
|
||||
always is lower case and the country part in upper case. The separator
|
||||
is an underscore.
|
||||
|
||||
language code
|
||||
Represents the name of a language. Browsers send the names of the
|
||||
languages they accept in the ``Accept-Language`` HTTP header using this
|
||||
format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Note the ``-``
|
||||
separator.
|
||||
format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Both the language
|
||||
and the country parts are in lower case. The separator is a dash.
|
||||
|
||||
message file
|
||||
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
|
||||
A literal that can be translated.
|
||||
|
||||
.. _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.
|
||||
format file
|
||||
A format file is a Python module that defines the data formats for a given
|
||||
locale.
|
|
@ -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.
|
|
@ -1,27 +1,44 @@
|
|||
====================
|
||||
Internationalization
|
||||
====================
|
||||
===========
|
||||
Translation
|
||||
===========
|
||||
|
||||
.. module:: django.utils.translation
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The goal of internationalization is to allow a single Web application to offer
|
||||
its content and functionality in multiple languages and locales.
|
||||
In order to make a Django project translatable, you have to add a minimal amount
|
||||
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
|
||||
adding a minimal amount of hooks to your Python and templates. These hooks
|
||||
are called **translation strings**. 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.
|
||||
Django then provides utilities to extract the translation strings into a
|
||||
:term:`message file`. This file is a convenient way for translators to provide
|
||||
the equivalent of the translation strings in the target language. Once the
|
||||
translators have filled in the message file, it must be compiled. This process
|
||||
relies on the GNU gettext toolset.
|
||||
|
||||
Django takes care of using these hooks to translate Web apps, on the fly,
|
||||
according to users' language preferences.
|
||||
Once this is done, Django takes care of translating Web apps on the fly in each
|
||||
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
|
||||
--------------------
|
||||
|
@ -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
|
||||
examples, is that Django's translation-string-detecting utility,
|
||||
``django-admin.py makemessages``, won't be able to find these strings. More on
|
||||
``makemessages`` later.)
|
||||
:djadmin:`django-admin.py makemessages <makemessages>`, won't be able to find
|
||||
these strings. More on :djadmin:`makemessages` later.)
|
||||
|
||||
The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
|
||||
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 %}
|
||||
|
||||
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.
|
||||
|
||||
Marking strings as no-op
|
||||
|
@ -221,9 +238,10 @@ cardinality of the elements at play.
|
|||
count
|
||||
) % d
|
||||
|
||||
You would get a ``a format specification for argument 'name', as in
|
||||
'msgstr[0]', doesn't exist in 'msgid'`` error when running
|
||||
``django-admin.py compilemessages``.
|
||||
You would get an error when running :djadmin:`django-admin.py
|
||||
compilemessages <compilemessages>`::
|
||||
|
||||
a format specification for argument 'name', as in 'msgstr[0]', doesn't exist in 'msgid'
|
||||
|
||||
.. _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
|
||||
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
|
||||
different contextual markers for the same string (the context will appear on
|
||||
the ``msgctxt`` line), allowing the translator to give a different translation
|
||||
for each of them.
|
||||
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 the
|
||||
``msgctxt`` line), allowing the translator to give a different translation for
|
||||
each of them.
|
||||
|
||||
For example::
|
||||
|
||||
|
@ -258,7 +276,7 @@ or::
|
|||
name = models.CharField(help_text=pgettext_lazy(
|
||||
'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
|
||||
|
||||
|
@ -333,7 +351,7 @@ name::
|
|||
|
||||
class Meta:
|
||||
verbose_name = _('my thing')
|
||||
verbose_name_plural = _('mythings')
|
||||
verbose_name_plural = _('my things')
|
||||
|
||||
Notes on model classes translation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -398,7 +416,7 @@ strings when ``result`` itself is used in a string (usually at template
|
|||
rendering time).
|
||||
|
||||
Localized names of languages
|
||||
============================
|
||||
----------------------------
|
||||
|
||||
.. 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
|
||||
================================================
|
||||
Internationalization: in template code
|
||||
======================================
|
||||
|
||||
.. highlightlang:: html+django
|
||||
|
||||
|
@ -672,8 +690,8 @@ There are also simple filters available for convenience:
|
|||
|
||||
.. _Django templates: ../templates_python/
|
||||
|
||||
Specifying translation strings: In JavaScript code
|
||||
==================================================
|
||||
Internationalization: in JavaScript code
|
||||
========================================
|
||||
|
||||
.. 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 .po or .mo files; they need to be
|
||||
delivered by the server.
|
||||
* JavaScript code doesn't have access to ``.po`` or ``.mo`` files; they need to
|
||||
be delivered by the server.
|
||||
|
||||
* The translation catalogs for JavaScript should be kept as small as
|
||||
possible.
|
||||
|
@ -700,12 +718,12 @@ The ``javascript_catalog`` view
|
|||
|
||||
.. function:: javascript_catalog(request, domain='djangojs', packages=None)
|
||||
|
||||
The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog`
|
||||
view, which sends out a JavaScript code library with functions that mimic the
|
||||
``gettext`` interface, plus an array of translation strings. Those translation
|
||||
strings are taken from applications or Django core, according to what you
|
||||
specify in either the info_dict or the URL. Paths listed in
|
||||
:setting:`LOCALE_PATHS` are also included.
|
||||
The main solution to these problems is the
|
||||
:meth:`django.views.i18n.javascript_catalog` view, which sends out a JavaScript
|
||||
code library with functions that mimic the ``gettext`` interface, plus an array
|
||||
of translation strings. Those translation strings are taken from applications or
|
||||
Django core, according to what you specify in either the ``info_dict`` or the
|
||||
URL. Paths listed in :setting:`LOCALE_PATHS` are also included.
|
||||
|
||||
You hook it up like this::
|
||||
|
||||
|
@ -815,8 +833,8 @@ to produce proper pluralizations).
|
|||
|
||||
.. _url-internationalization:
|
||||
|
||||
Specifying translation strings: In URL patterns
|
||||
===============================================
|
||||
Internationalization: in URL patterns
|
||||
=====================================
|
||||
|
||||
.. 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
|
||||
information), the :func:`~django.core.urlresolvers.reverse` function will
|
||||
return the URL in the active language. Example::
|
||||
After you've created the translations, the
|
||||
:func:`~django.core.urlresolvers.reverse` function will return the URL in the
|
||||
active language. Example::
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
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.
|
||||
|
||||
.. _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:
|
||||
|
||||
The ``set_language`` redirect view
|
||||
==================================
|
||||
----------------------------------
|
||||
|
||||
.. highlightlang:: python
|
||||
|
||||
|
@ -1019,3 +1269,293 @@ Here's example HTML template code:
|
|||
</select>
|
||||
<input type="submit" value="Go" />
|
||||
</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.
|
Loading…
Reference in New Issue