How To Internationalize a Django App

Vincent Lossel
3 min readJul 18, 2023

--

Internationalization, often abbreviated as i18n, involves adapting a project to local specificities, making it accessible in different languages, cultures, and regions.

Django provides comprehensive support for internationalization, enabling developers to create websites that can be easily translated and localized. The framework includes numerous features such as template translation, language preferences, date formatting, and timezone management.

This article aims to provide an introduction to the various concepts surrounding internationalization in Django. For more details, the documentation offers a highly precise guide.

i18n Configuration

Internationalization with Django starts with the overall project configuration.

By default, Django’s language is set to LANGUAGE_CODE="en-US". This can be changed in the settings.py file to any language in ISO format (e.g., fr-FR for France, fr-BE for Belgium, etc.)

The middleware responsible for localization (django.middleware.locale.LocaleMiddleware) performs automatic language detection and selection based on the elements of the transmitted request. By default, Django will remember the browser’s language, but a cookie can be stored to retain user preferences. You can also consider using custom middleware to retrieve the language from information stored in the database for a logged-in user.

The USE_I18N variable must be set to True to allow Django to use internationalization tools. You also have the option to modify other elements such as date formatting, timezone usage, and number formatting.

In your project’s settings.py file, start by defining the list of languages supported by your application.

LANGUAGES = [
("en", "English"),
("fr", "Français"),
]

Template Translation

To use internationalization in templates, you need to load the necessary tools with {% load i18n %}. You can then use tags like {% trans "Lorem Ipsum" %} or {% blocktrans %}Lorem Ipsum{% endblocktrans %} to translate text directly in the HTML file.

Django also integrates tools for managing different date, time, and pluralization formats based on the user’s locale. Decimal and thousand separators can also be adapted.

Within templates, you have access to various tags for retrieving translation information. For example, {% get_current_language %} returns information about the current language, {% get_available_languages %} returns the list of available languages. These elements can be useful for displaying language-specific content or implementing a language selector.

Translation Files

Translations are stored in files containing the translated texts. Translation is facilitated through the use of Portable Object (PO) and Machine Object (MO) files.

The command python manage.py makemessages -l fr generates .po (Portable Object) files used for translation. The command python manage.py compilemessages -l fr generates .mo (Machine Object) files that will be called by the application to display the correct translation in the appropriate place.

Translation files are stored in folders designated by LOCALE_PATHS. You can access them using specific editors like Poedit or modify the files directly in your preferred text editor.

Django will traverse these folders to discover available translations corresponding to the supported languages.

Translation of Views and Models

It is also possible to translate elements outside of templates, such as views and models in Django.

from django.utils.translation import gettext as _

output = _("Bonjour")

To retrieve translated text, Django provides two methods: gettext() and gettext_lazy(). Both methods serve the same purpose of returning the text corresponding to the localization by retrieving the translation files.

However, there are a few differences between the two:

- gettext() is an immediately evaluated function that returns the translation. This means that this function may ignore the language selected by the middleware when used in a view or another module due to the application’s lifecycle.
- gettext_lazy() returns a Lazy object that will be evaluated later when the result is required. This function is mainly used in models, forms, and apps.py.

These functions can be used effectively to ensure URL localization.

from django.conf.urls.i18n import i18n_patterns
from django.urls import path
from django.utils.translation import gettext_lazy as _
from django.views.generic import TemplateView


urlpatterns += i18n_patterns(
path(_("hello-world/"), TemplateView.as_view(template_name="hello_world.html"), name="hello"),
prefix_default_language=False,
)

Using i18n_patterns for URL handling provides access to certain functionalities, such as adding the default language prefix to the URL or the language change view. The language change view, through a POST request, allows modifying the used language and storing a cookie with the user to retain their preferences.

--

--