Django internationalization / Multiple Languages

HermantoXYZ
3 min readJul 30, 2024

--

Internationalization (i18n) in Django involves making your web application translatable into multiple languages.

Enable Internationalization in Settings



# Setting.py
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = 'en'

LANGUAGES = [

('en', _('English')),
('id', _('Indonesian')),
]

PARLER_LANGUAGES = {
None: (
{'code': 'en'},
{'code': 'id'},
),
'default': {
'fallback': 'en',
'hide_untranslated': False,
}
}

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True

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

Add Install App in Setting.py

1. Django Rosetta

django-rosetta and django-parler can be used to facilitate translation and internationalization in a Django project.

pip install django-rosetta

django-rosetta is a Django application that eases the translation process by providing a web interface for editing .po files.

App Configuration

Add rosetta to your INSTALLED_APPS in settings.py:


INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts.apps.AccountsConfig',
'rosetta', # for translation
]

Urls Configuration

add rosetta in your urls.py:

from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.urls import include, path
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = i18n_patterns(
path('admin/', admin.site.urls),
path('rosetta/', include('rosetta.urls')),
path('', include('accounts.urls')),
prefix_default_language = False
)



if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Now, you can access the Rosetta interface at `http://127.0.0.1:8000/rosetta/files/project/` to manage translations through a user-friendly web interface.

2. Django Parler

django-parler is an application for managing multilingual content in Django models. It provides an easy way to translate model fields.
Install django-parler using pip:

pip install django-parler

Configuration App in setting.py


#Setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts.apps.AccountsConfig',
'tinymce',
'parler', # for translation
]
#Setting.py
PARLER_LANGUAGES = {
None: (
{'code': 'en'},
{'code': 'id'},
),
'default': {
'fallback': 'en',
'hide_untranslated': False,
}
}

Using Parler in Models

To make a model translatable, inherit from TranslatableModel and use TranslatedFields for the fields you want to translate:


# MODEL.PY
# Requirements for translation
from django.utils.translation import gettext_lazy as _
from parler.models import TranslatableModel, TranslatedFields

class PostNews(TranslatableModel):
translations = TranslatedFields(
title=models.CharField(_("Title"), max_length=300),
content=models.TextField(_("Content"))
)
author = models.ForeignKey(User, on_delete=models.CASCADE)
images = models.ImageField(upload_to=rename_image, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
slug = models.SlugField(max_length=200, unique=True, blank=True)

def save(self, *args, **kwargs):
if not self.slug:
# Generate slug based on the translated title
self.slug = slugify(self.safe_translation_getter('title', any_language=True))
super().save(*args, **kwargs)

def __str__(self):
return self.safe_translation_getter('title', any_language=True)
python manage.py makemigrations
python manage.py migrate
# ADMINPY
from django.contrib import admin
from .models import User, PostNews, Category, Page
from tinymce.widgets import TinyMCE
from django.db import models
from tinymce.models import HTMLField
from parler.admin import TranslatableAdmin

admin.site.register(User)
# class PostNewsAdmin Content


admin.site.register(PostNews, TranslatableAdmin)
admin.site.register(Category, TranslatableAdmin)


class PageAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'created_at')
list_filter = ('author', 'created_at')
search_fields = ('title', 'author__username')
prepopulated_fields = {'slug': ('title',)}

formfield_overrides = {
models.TextField: {'widget': TinyMCE(attrs={'cols': 80, 'rows': 30})},
HTMLField: {'widget': TinyMCE(attrs={'cols': 80, 'rows': 30})},
}

admin.site.register(Page , PageAdmin)

Configuration in HTML Templates

{% extends 'home/base.html' %}
{% block title %}Fakultas EKonomi dan Bisnis UNM{% endblock %}
{% block content %}
{% load i18n %}

<div class="dropdown ms-3">
{% get_current_language as CURRENT_LANGUAGE %}
{% get_available_languages as AVAILABLE_LANGUAGES %}
{% get_language_info_list for AVAILABLE_LANGUAGES as languages %}
<a href="#" class="dropdown-toggle text-dark" data-bs-toggle="dropdown">
<small><i class="fas fa-globe-europe text-primary me-2"></i>
{% for language in languages %}
{% if language.code == CURRENT_LANGUAGE %}
{{ language.name_local }}
{% endif %}
{% endfor %}
</small>
</a>
<div class="dropdown-menu rounded">
{% for language in languages %}
<a class="dropdown-item {% if language.code == CURRENT_LANGUAGE %}active{% endif %}" href="{% if language.code == 'en' %}/{% else %}/{{ language.code }}/{% endif %}">
{{ language.name_local }}
</a>
{% endfor %}
</div>
</div>
django-admin makemessages -l en --ignore env

django-admin makemessages -l id --ignore env

Edit the .po Files: After running makemessages, a .po file will be created or updated in the locale directory of your app (e.g., locale/en/LC_MESSAGES/django.po). Open this file to translate the extracted strings into the desired language. Each entry will look something like this:

msgid "Original text"
msgstr "Translated text"
django-admin compilemessages

References:

Video Channel youtube/com/@rootamin

--

--

No responses yet