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
|
deployment/index
|
||||||
error-reporting
|
error-reporting
|
||||||
initial-data
|
initial-data
|
||||||
i18n
|
|
||||||
jython
|
jython
|
||||||
legacy-databases
|
legacy-databases
|
||||||
outputting-csv
|
outputting-csv
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
==============
|
==============
|
||||||
|
|
|
@ -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`
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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`_
|
||||||
|
|
||||||
|
|
|
@ -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
|
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.
|
|
|
@ -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
|
.. 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.
|
Loading…
Reference in New Issue