Multi-Language Support for Django

Standard

Hi everyone,

The multi-language feature of the sites we create is a critical feature in the later stages of the projects. Let’s see how we can easily add this feature to our Django applications…

We have 2 options to add multi-language feature,

  1. Adding multiple languages at the start of the project
  2. Gaining multi-language feature by writing middleware when needed in the later stages of the project

If we move forward starting from the first scenario;

Adding Multi-language at Startup to Django

After creating our project, we add the following 2 lines under settings.py;

LANGUAGE_CODE = 'en-us'
USE_L10N = True

These parameters activate our default language option and features that allow us to do language translations under the template.

Now we create a sample template;

{% load i18n %}
<!doctype html>
<html lang="en">
<head>
    <title>Sample Page for Testing Multilanguage</title>
</head>
<body>
<div>
    <h1>{% trans "Hello World!" %} (en) !</h1>
    <h1> {{ sample_text }}</h1>
</div>
</body>
</html>

The string I added with the h1 tag here will be our examples to see how we can transform the text in a sample template with the multi-language feature, and the “sample_text” below will be examples to see how a variable from the backend changes on the front-end.

Under view.py, we use the “gettext” function to use our samples on a language-based basis. This function helps us to bring the text corresponding to our text from the languages under the locales directory in django. If it doesn’t find a match, it returns the text we typed by default. The translation in the 3rd line allows us to access features such as manipulating the language feature on the backend (or bringing the language that is valid when we want it with get_language()).

If we apply our example;

from django.shortcuts import render
from django.utils.translation import gettext as _
from django.utils import translation


def index(request):
    sample_text = _("Hello world from multi language app!")
    return render(request, 'home.html', {'sample_text': sample_text})


def index_tr(request):
    with translation.override("tr"):
        sample_text = _("Hello world from multi language app!")
    return render(request, 'home.html', {'sample_text': sample_text})

Let’s add the pages we created under urls.py;

  path('', index),
  path('tr/', index_tr),

Now let’s enter the following commands in order to have django automatically create our first PO file;

mkdir locale
django-admin makemessages -l tr

If everything went well, we should see our tr file under the “local” directory;

After typing and completing the texts, Django needs to convert it to a “mo” file in order to use it:

django-admin compilemessages

We must not forget to run this command again after each text we add.

Finally, we complete the process of automating the language conversion by giving the path of the language file we created under settings.py to Django;

LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), )

Adding User-based Multi-languages Feature to Django

Let’s say we created our project with a single language feature at the beginning, but the day came, and the PO said “hello guys, we urgently need multi-language support!” said. If PO had come with such a request at the beginning of the project, we could have solved the problem more simply by extending Django’s user class and adding a language option; let me show you right away we extend our User class under models.py as follows;

class User(auth_base.AbstractBaseUser, auth.PermissionsMixin):
    # ...
    language = models.CharField(max_length=10,
                                choices=settings.LANGUAGES,
                                default=settings.LANGUAGE_CODE)

For our feature to work, we install the following package;

pip install django-user-language-middleware

We add this middleware to middleware variable under the settings.py;

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
    ...
    'user_language_middleware.UserLanguageMiddleware',
    ...
]

It is done! 🙂

Multi-language Support by Installing Our Own Middleware

Let’s say you don’t want to use the above package. In that case, to provide the management yourself, by creating a file called middlewares.py under your Django project, you can create a middleware in the following way and use it by adding it as middleware in the same way;

from django.utils import translation

def language_middleware(get_response):
    def middleware(request):
        user = getattr(request, 'user', None)
        if user is not None and user.is_authenticated:
            translation.activate(user.language)
        response = get_response(request)
        translation.deactivate()
        return response
    return middleware

See you in my next article 🙂

You can find the code of the sample project from the Github repository here.

Resources;

https://docs.djangoproject.com/en/4.1/topics/i18n/translation/#how-django-discovers-language-preference
https://testdriven.io/blog/multiple-languages-in-django/
https://djangowaves.com/tutorial/multiple-languages-in-Django/
https://stackoverflow.com/questions/37367576/django-language-code-not-working
https://stackoverflow.com/questions/10280881/django-site-with-2-languages
https://stackoverflow.com/questions/42953521/set-or-change-the-default-language-dynamically-according-to-the-user-django
https://stackoverflow.com/questions/9625492/in-django-what-is-i18n

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.