/

Django Multilanguage

In this article, we will talk about translating static data into different languages in django. In our next article, we will also translate our Djano Models into different languages.

First, let's create a new django project. I'm not going to tell you about them assuming you know them.

At first we need to install the gettext package on our computer.

sudo apt install gettext

For Windows, you can download https://mlocati.github.io/articles/gettext-iconv-windows.html here.

Let's move on to the necessary adjustments through our settings.py file.

LANGUAGE_CODE = 'tr'

USE_TZ = True

USE_L10N = True

USE_I18N = True

TIME_ZONE = 'UTC'

Now that we have written these settings in our settings.py file, let's continue with our operations. We need to add this to our settings.py file to determine which languages will be on our site.

from django.utils.translation import gettext_lazy as _

LANGUAGES = (
    ('en', _('English')),
    ('tr', _('Turkish')),
)

Let's explain what we did right here. We set that there are two languages, Turkish and English, and we write them by giving a parameter to a method called gettext_lazy. If you notice, we use the gettext_lazy method with the _ (underscore) sign. This is because it is always used this way in projects and because we can handle our work with _ instead of writing it for a long time. In summary, we have to translate the words/sentences that we want to translate into different languages into this method.

Now we need to add one more MIDDLEWARE in our settings.py file.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware', # NEW
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

The middleware we just added:

'django.middleware.locale.LocaleMiddleware'

Now, there is a new setting that we will do through our settings.py file.

LOCALE_PATHS = [
    BASE_DIR / 'locale/',
]

We create an empty folder called locale/ in our main project, and then we create the folders of the languages we want translated into this folder. So it will be like this.

locale
├── en
└── tr

Now let's create a simple app and create a simple model.

from django.db import models
from django.utils.translation import gettext_lazy as _


class Article(models.Model):
    title = models.CharField(_('Başlık'), max_length=50)
    description = models.TextField(_('Açıklama'))

    def __str__(self):
        return self.title

This was also a very simple model, but whatever. As you can see, I have included the fields to be translated with underscores into my method. After performing the necessary makemigrations and migrate processes, let's save the model we created in our admin panel.

And let's create an html page and set our views to translate the data through our template.

{% load i18n %}

{% trans 'Merhaba' %}

If there is a word we want to translate/translate through our template, we will do it this way.

It looks like Merhaba now. Let's continue now.

django-admin makemessages --all --ignore=env

Here we have written — ignore=env for you to pay attention to. It must be the same as the name of the virtual environment you created, otherwise you may get an error.

As you can see, after running this command, the necessary .po files were created in our locale file. Let's examine these files now.

And as you can see, we can see where the words we want translated come here, and even in which file we can see how many lines. In the msgstr section, we write the translation in the language to be translated. After typing, we will run this command.

Let's arrange it now.

Now let's run this command.

django-admin compilemessages --ignore=env

Now we can see that the files with .mo extension are coming. Finally, we will edit the urls.py file in the base project folder.

from django.contrib import admin
from django.urls import path
from django.conf.urls.i18n import i18n_patterns

urlpatterns = [
    path('admin/', admin.site.urls),
]

urlpatterns = [
    *i18n_patterns(*urlpatterns, prefix_default_language=False),
    ]

Now let's see if it works.

By default, "Merhaba" is displayed. Now let's look at adding /en/ to our url path.

As you can see, our conversion was successful. You can create a button on your site to set the language. I will write a view for it that you can use as well.

from urllib.parse import urlparse
from django.conf import settings
from django.http import HttpResponseRedirect
from django.urls.base import resolve, reverse
from django.urls.exceptions import Resolver404
from django.utils import translation


def set_language(request, language):
    for lang, _ in settings.LANGUAGES:
        translation.activate(lang)
        try:
            view = resolve(urlparse(request.META.get("HTTP_REFERER")).path)
        except Resolver404:
            view = None
        if view:
            break
    if view:
        translation.activate(language)
        next_url = reverse(view.url_name, args=view.args, kwargs=view.kwargs)
        response = HttpResponseRedirect(next_url)
        response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)
    else:
        response = HttpResponseRedirect("/")
    return response

Let's add our new path for the url.

urlpatterns = [
    *i18n_patterns(*urlpatterns, prefix_default_language=False),
   
   # NEW
    path("set_language/<str:language>", set_language, name="set-language"),
]

You can use this view on your template like this. Of course, you can customize the language switching template by specifying your own css classes.

<a href="{% url 'set-language' 'tr' %}">TR</a>
<a href="{% url 'set-language' 'en' %}">EN</a>

Comments

    There are no comments yet.

Comment