Django Integration
Learn how to integrate i18next with Django applications for internationalization.
Integrate internationalization with your Django application to support multiple languages using Lengrise-managed translations, with both server-side rendering and template-based capabilities.
Prerequisites
- Django project (v3.2+)
- Python (v3.7+)
- Package manager (pip, poetry)
- Translations downloaded from Lengrise
Pull Translation Files
First, you must pull your translation files from Lengrise API. These files will contain all the translated text for your application.
- Go to the Installation Guide and follow the steps to download your translations
- Convert the downloaded JSON files to Django locale format or use them directly with a custom solution
- Place the translated files in your project as shown in the project structure below
Integration Setup
Django comes with built-in internationalization support, but you may need to install additional packages for JSON handling:
python pip install django-rosetta
Project Structure
Configuration Steps
1. Configure Django Settings
Update your settings.py
file to enable internationalization:
from django.utils.translation import gettext_lazy as _
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Internationalization settings
LANGUAGE_CODE = 'en'
# Enable translations
USE_I18N = True
# Enable localization
USE_L10N = True
# Enable timezone support
USE_TZ = True
# Available languages
LANGUAGES = [
('en', _('English')),
('es', _('Spanish')),
]
# Path to locale files
LOCALE_PATHS = [
os.path.join(BASE_DIR, 'locale'),
]
# Add the LocaleMiddleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # Add this line
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# Templates configuration
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'app/templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.i18n', # Add this line
],
},
},
]
# Optional, if using Rosetta for translation management
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app',
'rosetta', # Add this line if using Rosetta
]
2. Update URLs Configuration
Update your project/urls.py
file to include language selection URLs:
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import gettext_lazy as _
urlpatterns = [
# Non-localized URLs
path('i18n/', include('django.conf.urls.i18n')), # Language switching
]
# Localized URLs - will include language prefix
urlpatterns += i18n_patterns(
path(_('admin/'), admin.site.urls),
path('', include('app.urls')),
path('rosetta/', include('rosetta.urls')), # Optional, if using Rosetta
prefix_default_language=True, # Set to False to omit prefix for default language
)
3. Create a Base Template with Language Switcher
Create a file at app/templates/base.html
:
{% load i18n %}
{% load static %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% trans "My Multilingual Site" %}{% endblock %}</title>
<style>
.language-switcher {
margin: 1rem 0;
}
.language-switcher ul {
display: flex;
list-style-type: none;
padding: 0;
}
.language-switcher li {
margin-right: 1rem;
}
.language-switcher a {
text-decoration: none;
color: #333;
}
.language-switcher a.active {
font-weight: bold;
color: #0066cc;
}
</style>
</head>
<body>
<header>
<h1>{% trans "My Multilingual Django Site" %}</h1>
<nav>
<ul>
<li><a href="{% url 'home' %}">{% trans "Home" %}</a></li>
<li><a href="{% url 'about' %}">{% trans "About" %}</a></li>
<li><a href="{% url 'contact' %}">{% trans "Contact" %}</a></li>
</ul>
</nav>
<!-- Language Switcher -->
<div class="language-switcher">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language" onchange="this.form.submit()">
{% get_current_language as CURRENT_LANGUAGE %}
{% get_available_languages as LANGUAGES %}
{% for lang_code, lang_name in LANGUAGES %}
<option value="{{ lang_code }}" {% if lang_code == CURRENT_LANGUAGE %}selected{% endif %}>
{{ lang_name }}
</option>
{% endfor %}
</select>
</form>
</div>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>{% blocktrans with year=current_year %}© {{ year }} My Website. All rights reserved.{% endblocktrans %}</p>
</footer>
</body>
</html>
4. Create Views
Update your app/views.py
file:
from django.shortcuts import render
from django.utils.translation import gettext as _
from django.utils import timezone
def home(request):
current_year = timezone.now().year
# Example of translatable content with variables
message = _("Hello, welcome to our site!")
items_count = 5
items_message = _("You have %(count)d item") % {'count': items_count}
if items_count != 1:
items_message = _("You have %(count)d items") % {'count': items_count}
context = {
'message': message,
'items_message': items_message,
'current_year': current_year,
}
return render(request, 'index.html', context)
def about(request):
current_year = timezone.now().year
return render(request, 'about.html', {'current_year': current_year})
def contact(request):
current_year = timezone.now().year
return render(request, 'contact.html', {'current_year': current_year})
5. Create URLs for your App
Create a file at app/urls.py
:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('about/', views.about, name='about'),
path('contact/', views.contact, name='contact'),
]
6. Create a Home Page Template
Create a file at app/templates/index.html
:
{% extends 'base.html' %} {% load i18n %} {% block title %}{% trans "Home" %} -
{{ block.super }}{% endblock %} {% block content %}
<h1>{% trans "Welcome to our site" %}</h1>
<p>{{ message }}</p>
<section>
<h2>{% trans "Features" %}</h2>
<ul>
<li>{% trans "Easy to use" %}</li>
<li>{% trans "Fast translation" %}</li>
<li>{% trans "Flexible integration" %}</li>
</ul>
</section>
<p>{{ items_message }}</p>
<p>
{% blocktrans with name="Django Developer" %}Hello, {{ name }}!{%
endblocktrans %}
</p>
{% endblock %}
Working with Translations
1. Extracting Translatable Strings
Run the following command to extract strings from your templates and Python code:
python manage.py makemessages -l en -l es
This will create or update your .po
files in the locale
directory.
2. Editing Translation Files
Edit the .po
files in locale/es/LC_MESSAGES/django.po
to add Spanish translations:
#: templates/base.html:7
msgid "My Multilingual Site"
msgstr "Mi Sitio Multilingüe"
#: templates/base.html:18
msgid "My Multilingual Django Site"
msgstr "Mi Sitio Django Multilingüe"
#: templates/base.html:21
msgid "Home"
msgstr "Inicio"
#: templates/base.html:22
msgid "About"
msgstr "Acerca de"
#: templates/base.html:23
msgid "Contact"
msgstr "Contacto"
#: templates/index.html:6
msgid "Welcome to our site"
msgstr "Bienvenido a nuestro sitio"
#: views.py:8
msgid "Hello, welcome to our site!"
msgstr "¡Hola, bienvenido a nuestro sitio!"
#: views.py:10
#, python-format
msgid "You have %(count)d item"
msgstr "Tienes %(count)d elemento"
#: views.py:12
#, python-format
msgid "You have %(count)d items"
msgstr "Tienes %(count)d elementos"
#: templates/index.html:14
msgid "Easy to use"
msgstr "Fácil de usar"
#: templates/index.html:15
msgid "Fast translation"
msgstr "Traducción rápida"
#: templates/index.html:16
msgid "Flexible integration"
msgstr "Integración flexible"
#: templates/index.html:21
#, python-format
msgid "Hello, %(name)s!"
msgstr "¡Hola, %(name)s!"
3. Compiling Translations
After editing the .po
files, compile them to .mo
files:
python manage.py compilemessages
4. Using Translations in Python Code
In your Python code, you can use various translation functions:
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy as _lazy
from django.utils.translation import ngettext
# For regular strings
message = _("Hello")
# For strings in class definitions, models, etc.
class MyModel(models.Model):
title = models.CharField(_lazy("Title"), max_length=100)
# For pluralization
item_count = 5
message = ngettext(
'There is %(count)d item',
'There are %(count)d items',
item_count
) % {'count': item_count}
5. Using Translations in Templates
In your Django templates, you can use translation tags:
{% load i18n %}
<!-- Simple translation -->
<h1>{% trans "Welcome" %}</h1>
<!-- Translation with variables -->
{% blocktrans with user_name=user.username %} Hello, {{ user_name }}! {%
endblocktrans %}
<!-- Pluralization in templates -->
{% blocktrans count counter=items.count %} There is {{ counter }} item. {%
plural %} There are {{ counter }} items. {% endblocktrans %}
Using JSON Files for JavaScript
If you want to use your Lengrise JSON files directly for JavaScript translations:
1. Create a JavaScript Language Switcher
Create a file at static/js/language-switcher.js
:
document.addEventListener("DOMContentLoaded", function () {
// Load translations for the current language
const currentLanguage = document.documentElement.lang || "en";
let translations = {};
// Fetch translations from your JSON file
fetch(`/static/locales/${currentLanguage}.json`)
.then((response) => response.json())
.then((data) => {
translations = data;
// Translate all elements with data-i18n attribute
translateElements();
})
.catch((error) => console.error("Error loading translations:", error));
// Function to translate elements
function translateElements() {
document.querySelectorAll("[data-i18n]").forEach((element) => {
const key = element.getAttribute("data-i18n");
const translation = getNestedTranslation(key, translations);
if (translation) {
element.textContent = translation;
}
});
}
// Helper function to handle nested keys (e.g. "user.greeting")
function getNestedTranslation(key, obj) {
return key.split(".").reduce((p, c) => (p && p[c] ? p[c] : null), obj);
}
// Function to translate with parameters
window.translate = function (key, params = {}) {
let translation = getNestedTranslation(key, translations);
if (!translation) return key;
// Replace parameters
Object.keys(params).forEach((param) => {
translation = translation.replace(
new RegExp(`{{\\s*${param}\\s*}}`, "g"),
params[param]
);
});
return translation;
};
});
2. Include the Script in Your Template
Add this to your base.html
:
{% load static %}
<!-- Add this near the end of your body tag -->
<script src="{% static 'js/language-switcher.js' %}"></script>
3. Using JavaScript Translations
In your HTML, you can use data attributes for translation:
<div data-i18n="welcome.title"></div>
<div data-i18n="features.easy"></div>
<!-- For dynamic translations with JavaScript -->
<script>
document.getElementById("greeting").textContent = translate("greeting", {
name: "JavaScript User",
});
</script>
Resources
For more detailed information, check out these resources:
- Django Translation Documentation
- Django Internationalization Documentation
- Django-Rosetta (for translation management)