Software localization

A Quick Guide to Django i18n

This guide will show you how to easily implement internationalization (i18n) and localization (l10n) in Django – the popular Python web framework.
Software localization blog category featured image | Phrase

Translating your web application to different languages and adding proper localization is something we all should do! This tutorial will give you a short introduction on how to get started with the Django localization process. Part of this can be easily applied to general Python localization and we also show you how you can speed up your i18n workflow even more by using Phrase.

We assume, that you have a working Django application and that you have installed gettext (for example via pip install gettext). If you havn’t used Django before, you maybe want to take a look at the official tutorial first and come back later.

Basic setup

So let’s suppose you have a Django project called mysite and an application called polls. The structure of your project should be looking something like

/

    manage.py

    mysite/

        __init__.py

        settings.py

        urls.py

        wsgi.py

    polls/

        migrations/

        __init__.py

        admin.py

        models.py

        tests.py

        views.py

The first step is to make sure that you have activated internationalization in your configuration. To do this, you have to make the following changes to mysite/settings.py:

# mysite/settings.py

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

Internationalize templates

Then you have to mark all strings which have to be translated. Suppose you have the following template file polls/templates/polls/index.html

<!-- polls/templates/polls/index.html -->

<h1>Welcome to our site!</h1>

<p>Here you find polls.</p>

This file needs to be adapted to look like this

<!-- polls/templates/polls/index.html -->

{% load i18n %}

<h1>{% trans 'WelcomeHeading' %}</h1>

<p>{% trans 'WelcomeMessage' %}</p>

so we import the localization package and replace all texts with trans 'SomeTranslationKeyName'. Alternatively, you can use the default translation text as the translation key. This way, you will always have a good default text, if there is no translation available for the peticular key.

🗒 Note » There are actually two different Django templates you might run into here. Learn about the difference between _() and {% trans %} in Django templates.

Internationalize inside Python code

When you want to localize strings within your python code (for example inside polls/views.py), you need to import the ugettext function. It is normal to alias it to _. So a simple localized view function would look like this

# polls/views.py

from django.http import HttpResponse

from django.utils.translation import ugettext as _

def index(request):

    output = _('StatusMsg')

    return HttpResponse(output)

Create translation files

Now we have to create the translation files for every locale, we want to support. To do this create the directory polls/locale and inside the directory polls run

$ django-admin makemessage -l de

where you can replace de with the locale code of the language you like to add. In our example, this command will create the gettext file polls/locale/de/LC_MESSAGES/django.po with the content

# polls/locale/de/LC_MESSAGES/django.po

...

#: templates/polls/index.html:3

msgid "WelcomeHeading"

msgstr ""

#: templates/polls/index.html:4

msgid "WelcomeMessage"

msgstr ""

and you can fill in the translations:

# polls/locale/de/LC_MESSAGES/django.po

...

#: templates/polls/index.html:3

msgid "WelcomeHeading"

msgstr "Willkommen auf unserer Seite!"

#: templates/polls/index.html:4

msgid "WelcomeMessage"

msgstr "Hier findet Ihr Umfragen."

When you have finished translating, you have to compile everything by running

$ django-admin compilemessages

again inside the directory polls.

To quickly check that your translations work, you have to change the language code inside mysite/settings.py like so

# mysite/settings.py

LANGUAGE_CODE = 'de'

When you open the polls application inside the browser, it should now be translated to German.

Speed up your process using Phrase

If you are using Phrase to manage your translations, you actually don’t need to manually create and edit the *.po files! You just have to create and translate the keys WelcomeHeading and WelcomeMessage within Phrase and use the export function to download your *.po files.

If you have installed our command line tool, the Phrase client, your workflow is even simpler. Just create a configuration file .phraseapp.yml within your project’s root directory with the following content:

# .phraseapp.yml

phraseapp:

  access_token: <your access token>

  project_id: <your project's id on PhraseApp>

  file_format: po

  pull:

    targets:

        file: "polls/locale/<locale_code>/LC_MESSAGES/django.po

Then running

$ phraseapp pull && django-admin compilemessages

in the root directory of your project will update all translations in your project.

By the way, using Phrase's in-context editor within your Django application is also really simple! You only need to install django-phrase with pip:

$ pip install django-phrase

Then just change all templates you like to use the in-context-editor on, in the following way

<!-- polls/templates/polls/index.html -->

{% load i18n %}

{% load phrase_i18n %}

{% phrase_javascript %}

<h1>{% trans 'WelcomeHeading' %}</h1>

<p>{% trans 'WelcomeMessage' %}</p>

🗒 Note » It is important to load phrase_i18n after i18n.

Finally add the following lines to your configuration and you are ready to go!

# mysite/settings.py

PHRASE_ENABLED = True

PHRASE_PROJECT_ID = 'YOUR_PROJECT_ID'

PHRASE_PREFIX = '{{__'

PHRASE_SUFFIX = '__}}'

Select locales

One usually wants to select the locale according to the user’s browser settings. In order to do this you have to change the mysite/settings.py file to the following

# mysite/settings.py

from django.utils.translation import ugettext_lazy as _

...

MIDDLEWARE_CLASSES = (

    ...,

    'django.middleware.locale.LocaleMiddleware',

    ...,

)

...

LANGUAGE_CODE = 'en-us'

LANGUAGES = (

    ('en-us', _('English')),

    ('de', _('German')),

)

This way, if the user has German as their locale, they will see the de translations. Otherwise, the default locale will be en-us. You can check that this is working properly with curl:

$ curl http://localhost:8000/polls -H "Accept-Language: de"

which should return something like this

<h1>Willkommen auf unserer Seite!</h1>

<p>Hier findet Ihr Umfragen.</p>

Keep exploring

If you want to learn more about internationalization in Django, the official documentation is always a good place to start. We also warmly recommend the following Django translation tutorial.

If you're curious about how you can set up the Phrase in-context editor within your Django application, take a look at the Phrase documentation. You can also find the full sources of the demo application we used in this tutorial on GitHub.

Want to learn more about localization and internationalization in other web frameworks for Python? Check out the following tutorials: