Multi-language support in a Django project

The Django documentation on internationalization describes how to add multi-language support to your application. As it took me a few tries to get it right, here’s a rundown of what I did to add it to an existing project.

Step 1 — update settings.py
In settings.py, make sure that USE_I18N is set to True, which is the default. The LANGUAGE_CODE setting controls the default language for the site, so if you only need to support one language you set it here.

Then add the LocaleMiddleware class to your MIDDLEWARE_CLASSES, which for a clean project might look like this:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.locale.LocaleMiddleware',
)

Note that the order of the middleware classes makes a difference. LocaleMiddleware is needed for Django to select the user-preferred language from data in the request (i.e. cookies or the Accept-Language http header).

Step 2 — add translation keys to templates
Every template that should have translation support must load the i18n tag library using the {% load %} template tag. Once loaded, you can use the {% trans %} tag to mark a string for translation. A minimalistic hello-world template could look like this:

{% load i18n %}
{% trans "Hello" %}

Step 3 — create language files
Once your templates are set up, it’s time to create the language files. This step depends a bit on which operating system you’re running. I use Ubuntu Linux, so that’s what I’ll cover.

You can have language files local to an application as well as global for all your site. To set up language files for e.g. English and Swedish, move to the root of your project (or the root of the application), and run:

mkdir locale
django-admin.py makemessages -l en
django-admin.py makemessages -l sv

Note that you need to create the locale directory manually before running makemessages, otherwise you will get an error message. Also, if you get this error message:

Error: errors happened while running xgettext on __init__.py
/bin/sh: xgettext: not found

… it’s because your Linux distribution is missing the xgettext program. In Ubuntu, it’s provided by the gettext package:

sudo apt-get install gettext

Now that the language files are set up as ./locale/<language>/LC_MESSAGE/django.po, you can edit them and provide translations of the “Hello” key for each locale. When you’re done, they need to be compiled to .mo files before Django can use them:

django-admin.py compilemessages

Step 4 — done!
That’s all! You can try changing the LANGUAGE_CODE setting to switch between languages, or change the preferred-languages setting in your web browser (under Tools->Options->Content->Languages in Firefox), and Django should adapt automatically.

Advertisements

18 responses to “Multi-language support in a Django project

  1. Thanks a lot. The part about creating the locale directory wasn’t mentioned anywhere in the documentation, as far as I know.

  2. Thanks, I’m glad it helped!

  3. Perfect article. It should be added to official docs instead of the current i18n tutorial.

  4. Excellent to see this step by step here. Thanks devdoodles

  5. Thanks guys, I appreciate your comments!

  6. Thanks a lot. It’s hard to find good Django documentation.

  7. @Andrei – This is simply not true; Django has the best documentation of _any_ open source project I have seen, and better than most commercial ones too (and I have been around in software for 18+ years)

  8. i have still a problem
    Error: errors happened while running xgettext on VmSearchAction.py
    ./actions/VmSearchAction.py:163: warning: ‘msgid’ format string with unnamed arguments cannot be properly localized:
    The translator cannot reorder the arguments.
    Please consider using a format string with named arguments,
    and a mapping instead of a tuple for the arguments.

  9. devdoodles

    Sorry, I have no other help than what Google could provide. The posts are old but perhaps they are of some help, in case you haven’t seen them already:

    http://code.djangoproject.com/ticket/3410
    http://www.mail-archive.com/django-i18n@googlegroups.com/msg00246.html
    http://forum.emesene.org/index.php?topic=64.0

  10. This is great, so easy to follow 🙂

  11. Can I override my browser’s preference? I mean, my system and my browsers are all in English by Default, but I want to be able to load Portuguese as the first language of the site, despite the “Default” Browser language, is this possible?

    Thanks a lot.

  12. devdoodles

    Sure, but then LocaleMiddleware is not for you, since it always uses the browser’s settings to load the language.

    However, you can set request.LANGUAGE_CODE on your own based on whatever critieria you like. See the implementation of LocaleMiddleware for ideas:

    http://code.djangoproject.com/browser/django/trunk/django/middleware/locale.py

  13. Thanks for the reply, I have duplicated the locale.py MiddleWare, and made a small modification that now let me override the user’s browser settings.

    Heres the code:
    http://dpaste.com/hold/201478/

    Im not sure this is the best solution, but it is working as I expected now 🙂

  14. Hi,

    nice tutorial, but I still have a problem with picking up trans tags from my templates. My template dir is outside the project dir. Is there any way to teach the makemessages command, what dir my templates are in.

  15. Olá amigo… muito legal o seu tutorial… porém na minha aplicação eu estou tendo problemas na hora de executar o makemessages ele da que a opção “L” da xgettext não é válida… como faço para corrigir isso????

  16. Sorry, no clue. -l should work, but you could try --locale too and see if that helps, e.g. --locale=br_PT.

  17. Pingback: Internationalization in a Django Project | Suchana Prabidhi Blog

  18. Pingback: Internationalization in a Django Project |