While Django provides a rich set of internationalization 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.
Calling this function with the value ‘de’ will give you “
Willkommen”, regardless of
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.
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
djangojs. This string domain is used to differentiate between different programs that store their data in a common message-file library (usually
djangodomain is used for python and template translation strings and is loaded into the global translation catalogs. The
- Django doesn’t use
xgettextalone. It uses Python wrappers around
msgfmt. This is mostly for convenience.
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 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
LANGUAGE_CODE. Django uses this language as the default translation – the final attempt if no better matching translation is found through one of the methods employed by the locale middleware (see below).
If all you want is to run Django with your native language all you need to do is set
LANGUAGE_CODE and make sure the corresponding message files and their compiled versions (
If you want to let each individual user specify which language they prefer, then you also need to use the
LocaleMiddleware enables language selection based on data from the request. It customizes content for each user.
'django.middleware.locale.LocaleMiddleware' to your
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
LocaleMiddlewaremakes use of session data. And it should come before
CommonMiddlewareneeds an activated language in order to resolve the requested URL.
- If you use
LocaleMiddlewareafter it. For example, your
MIDDLEWARE_CLASSESmight look like this:
For more on middleware, see Chapter 17.
LocaleMiddleware tries to determine the user’s language preference by following this algorithm:
- First, it looks for the language prefix in the requested URL. This is only performed when you are using the
i18n_patternsfunction in your root URLconf. See url-internationalization for more information about the language prefix and how to internationalize URL patterns.
- Failing that, it looks for the
LANGUAGE_SESSION_KEYkey in the current user’s session.
- Failing that, it looks for a cookie. The name of the cookie used is set by the
LANGUAGE_COOKIE_NAMEsetting. (The default name is
- Failing that, it looks at the
Accept-LanguageHTTP 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
- In each of these places, the language preference is expected to be in the standard language format, as a string. For example, Brazilian Portuguese is
- 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
deavailable, Django uses
- Only languages listed in the
LANGUAGESsetting 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
LANGUAGESto a list of languages. For example:
This example restricts languages that are available for automatic selection to German and English (and any sublanguage, like
- If you define a custom
LANGUAGESsetting, as explained in the previous bullet, you can mark the language names as translation strings – but use
ugettext()to avoid a circular import. Here’s a sample settings file:
LocaleMiddleware determines the user’s preference, it makes this preference available as
request.LANGUAGE_CODE for each
HttpRequest. Feel free to read this value in your view code. Here’s a simple example:
Note that, with static (middleware-less) translation, the language is in
settings.LANGUAGE_CODE, while with dynamic (middleware) translation, it’s in
How Django Discovers Translations
At runtime, Django builds an in-memory unified catalog of literal 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 message files (
.mo) and the precedence of multiple translations for the same literal:
- The directories listed in
LOCALE_PATHShave the highest precedence, with the ones appearing first having higher precedence than the ones appearing later.
- Then, it looks for and uses if it exists a
localedirectory in each of the installed apps listed in
INSTALLED_APPS. The ones appearing first have higher precedence than the ones appearing later.
- Finally, the Django-provided base translation in
django/conf/localeis used as a fallback.
In all cases the name of the directory containing the translation is expected to be named using locale name notation. E.g.
This way, you can write applications that include their own translations, and you can override base translations in your project. 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.
All message file repositories are structured the same way. They are:
- All paths listed in
LOCALE_PATHSin your settings file are searched for
To create message files, you use the
django-admin makemessages tool. And you use
django-admin compilemessages to produce the binary
.mo files that are used by
You can also run
django-admin compilemessages to make the compiler process all the directories in your
In the next chapter we will be looking at security in Django.