Django translation tutorial

Templates and Javascript

January 26, 2016



This post is part of a tutorial series.

  1. Introduction
  2. Settings and translation files
  3. Templates and Javascript
  4. Setting user language

In the previous post of this tutorial series we implemented the translation of a string in the view. But in production projects most of the time we will be working with Django templates or Javascript code.

The goal for this third post is to set up the translations for Django templates and Javascript. We will continue with the project created in the previous post. If you did not follow the previous post, you may want to download the project from this link.

Translations on Django templates

Although Django allows us to create templates wherever we want, it is considered a good practice to create templates inside applications' folders. Create the template folder at languages/templates/languages/ with a index.html template inside:

{% load i18n %}

<h1>{% trans 'Hello' %}</h1>
<p>{% trans 'Welcome to my site.' %}</p>

The first line is necessary to import the translate functions. The other lines are just defining some html elements and making use of the trans function. Most of the times you will use trans for translating sentences or blocktrans to translate blocks of sentences. We also need to update our view so that it can render the template:

from django.shortcuts import render_to_response

def index(request):
    return render_to_response('languages/index.html')

Now we must instruct Django to search for translatable strings. Inside the languages directory do:

django-admin makemessages -l pt_pt

Open laguages/locale/pt_pt/LC_MESSAGES/django.po and translate the messages. Since the "Welcome to my site." string was already used previously, the makemessages command will reuse it.

#: templates/languages/index.html:3
msgid "Hello"
msgstr "Olá"

#: templates/languages/index.html:4
msgid "Welcome to my site."
msgstr "Bem-vindo ao meu site."

Finally, compile the messages with:

django-admin compilemessages

Open the project settings and make sure that the language code is set to "pt-pt" (we did this in the previous post):

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'pt-pt'  # Use pt_pt as default language
TIME_ZONE = 'UTC'

Point the browser to http://localhost:8000/languages/ and Django should render the translated template.

Translations on Javascript

Django also has support for translations on Javascript code, although the process is a little bit different. Create a small javascript file languages/static/hello.js with the following content:

document.write(gettext('Welcome to my site.'));

The gettext function, similar to its counterpart in Python, matches an input string with a translated string. Although we still have some more things to take care of, let's translate and compile the string. Cd into the languages folder and do:

django-admin makemessages -l pt_pt -d djangojs

Django will create a new file with the javascript messages in locale/pt_pt/LC_MESSAGES/djangojs.po. Open it and translate the message:

#: static/hello.js:1
msgid "Welcome to my site."
msgstr "Bem-vindo ao meu site."

To compile the messages we use the same procedure as before:

django-admin compilemessages

If everything is working fine, you will find the new compiled file in locale/pt_pt/LC_MESSAGES/djangojs.mo.

Javascript catalog

As you may notice, although we are using the gettext function in our small script, that function is not being implemented anywhere. If you run manually that small piece of code in your browser, it will complain about missing declarations. We need to set up what is called the javascript catalog.

The javascript catalog is a small script that Django uses to inject the translatable strings and all auxiliary functions into the browser. Django exports the javascript catalog to the browser using the javascript_catalog view function defined in django.view.i18n. To make use of that view, change languages/urls.py to the following:

from django.conf.urls import url
from . import views


js_info_dict = {
    'packages': ('languages', )
}

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^jsi18n/', 'django.views.i18n.javascript_catalog', js_info_dict),
]

Reload the server, point your browser to http://localhost:8000/languages/jsi18n/ and you'll see the content of the javascript catalog:

function (globals) {

    (...)

    django.catalog = {
        "Welcome to my site.": "Bem-vindo ao meu site."
    };

    django.gettext = function (msgid) {
        var value = django.catalog[msgid];
        if (typeof(value) == 'undefined') {
            return msgid;
        } else {
            return (typeof(value) == 'string') ? value : value[0];
        }
    };

    (...)
}

We can find the django.catalog variable with the translated string and the other functions being defined. Finally, we just need to make sure that our small javascript code and the catalog are being loaded in the template:

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript"
            src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
    <script type="text/javascript" src="/static/hello.js"></script>
</head>
</html>

Point the browser to http://localhost:8000/languages/.

Our javascript code is now being translated into the default language.