Skip to main content

Django JavaScript Translation

Introduction

While Django's template system provides powerful internationalization capabilities for your HTML content, modern web applications often rely on JavaScript to create interactive user experiences. To maintain a consistent multilingual experience throughout your application, Django provides a way to make JavaScript code translatable, just like your Python code and templates.

In this tutorial, we'll explore how Django enables JavaScript translation, how to set it up in your project, and how to implement translation functions in your JavaScript code. By the end, you'll be able to create a fully internationalized web application where both server-side and client-side text can be displayed in multiple languages.

Prerequisites

Before getting started, make sure you:

  • Have a basic understanding of Django
  • Know how to set up Django internationalization in Python and templates
  • Have some familiarity with JavaScript

Understanding the Challenge

JavaScript is executed in the browser, but translations are typically stored on the server. So how does Django make translations available to JavaScript? The solution involves:

  1. Generating a JavaScript catalog with all translations
  2. Serving this catalog to the browser
  3. Providing JavaScript functions to use these translations

Let's go through the process step by step.

Setting Up JavaScript Translation

Step 1: Configure Settings

First, ensure your Django project has internationalization properly configured in your settings.py:

python
INSTALLED_APPS = [
# ...
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize', # Recommended for i18n features
# ...
# Your apps
]

MIDDLEWARE = [
# ...
'django.middleware.locale.LocaleMiddleware', # Must be after session and before common
# ...
]

USE_I18N = True
USE_L10N = True

LANGUAGES = [
('en', 'English'),
('es', 'Spanish'),
('fr', 'French'),
# Add more languages as needed
]

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

Step 2: Configure URLs

Add the JavaScript catalog view to your URL patterns. In your urls.py:

python
from django.urls import path
from django.views.i18n import JavaScriptCatalog

urlpatterns = [
# ... your other URL patterns
path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'),
]

This view will generate and serve a JavaScript file with all the translations your JavaScript code will need.

Step 3: Include the JavaScript Catalog in Your Templates

Now, include the JavaScript catalog in the templates where you need translations:

html
{% load i18n %}

<html>
<head>
<title>{% trans "My Multilingual Site" %}</title>
<script src="{% url 'javascript-catalog' %}"></script>
<!-- Your other scripts -->
</head>
<body>
<!-- Your content here -->
</body>
</html>

Using JavaScript Translation Functions

Once you've included the JavaScript catalog in your template, you'll have access to several translation functions:

Basic Translation: gettext and ngettext

The most common translation function is gettext(), which works similarly to Django's {% trans %} template tag:

javascript
// Basic translation
const message = gettext('Welcome to our site');
console.log(message); // Will output the translated version in the current language

// For plural forms
const count = 5;
const message = ngettext('You have one notification',
'You have %(count)s notifications',
count);
console.log(interpolate(message, {count: count}, true));

Output (English):

Welcome to our site
You have 5 notifications

Output (Spanish - example):

Bienvenido a nuestro sitio
Tienes 5 notificaciones

String Interpolation: interpolate

To include variables in your translations, use the interpolate function:

javascript
const name = 'Alice';
const message = gettext('Hello, %(name)s!');
const result = interpolate(message, {name: name}, true);
console.log(result); // "Hello, Alice!" (in the current language)

Date and Number Formatting

Django also provides get_format and gettext_noop functions:

javascript
// Get date format for the current locale
const dateFormat = get_format('DATE_FORMAT');
console.log(dateFormat); // e.g., "N j, Y" for English, different for other languages

// Mark a string for translation without translating it immediately
const lazyTranslation = gettext_noop('This will be translated later');
// Later...
const translatedNow = gettext(lazyTranslation);

Real-World Examples

Form Validation Messages

A common use case is displaying validation messages in forms:

javascript
function validateForm() {
const email = document.getElementById('email').value;

if (!email.includes('@')) {
const errorMsg = gettext('Please enter a valid email address');
document.getElementById('email-error').textContent = errorMsg;
return false;
}

return true;
}

Interactive User Interface

Let's build a small component that shows a countdown with properly pluralized text:

javascript
function updateCountdown(seconds) {
const countdownEl = document.getElementById('countdown');

if (seconds <= 0) {
countdownEl.textContent = gettext('Time is up!');
return;
}

const message = ngettext(
'You have %(count)s second remaining',
'You have %(count)s seconds remaining',
seconds
);
countdownEl.textContent = interpolate(message, {count: seconds}, true);

setTimeout(() => updateCountdown(seconds - 1), 1000);
}

// Start a 30-second countdown
updateCountdown(30);

AJAX Content

When loading content via AJAX, you might need translations for the dynamically loaded content:

javascript
async function loadUserMessages() {
try {
const response = await fetch('/api/messages/');
const messages = await response.json();

const messageContainer = document.getElementById('messages');
messageContainer.innerHTML = '';

if (messages.length === 0) {
messageContainer.textContent = gettext('No new messages');
return;
}

const header = document.createElement('h3');
const messageText = ngettext(
'You have %(count)s new message',
'You have %(count)s new messages',
messages.length
);
header.textContent = interpolate(messageText, {count: messages.length}, true);
messageContainer.appendChild(header);

// Display messages...
} catch (error) {
console.error(gettext('Failed to load messages'), error);
}
}

Performance Optimization

The JavaScript catalog can become large if your application has many translations. Here are some optimization tips:

1. Domain-specific Catalogs

You can create domain-specific catalogs to load only the translations needed for specific parts of your application:

python
# urls.py
urlpatterns = [
path('jsi18n/myapp/', JavaScriptCatalog.as_view(packages=['myapp']), name='javascript-catalog-myapp'),
]

Then in your template:

html
<script src="{% url 'javascript-catalog-myapp' %}"></script>

2. Using the django-statici18n Package

For production environments, consider using the django-statici18n package, which pre-generates the JavaScript catalogs as static files during deployment:

bash
pip install django-statici18n

Add it to your INSTALLED_APPS:

python
INSTALLED_APPS = [
# ...
'statici18n',
]

And generate the static catalogs:

bash
python manage.py compilejsi18n

Marking Strings for Translation

Just like in Python code, you need to mark JavaScript strings for translation so that Django can extract them:

javascript
// This string will be collected for translation
const message1 = gettext('Hello, world!');

// This won't be collected because it's not using gettext
const message2 = 'Hello, world!';

To extract these strings, run:

bash
django-admin makemessages -d djangojs -l es  # For Spanish

The -d djangojs flag tells Django to look for translatable strings in JavaScript files.

Summary

Django's JavaScript translation functionality provides a seamless way to internationalize both the server and client sides of your web application. By following the steps in this tutorial, you've learned how to:

  1. Configure your Django project for JavaScript translations
  2. Include the JavaScript catalog in your templates
  3. Use translation functions like gettext, ngettext, and interpolate in your JavaScript code
  4. Optimize performance for production environments
  5. Mark and extract strings for translation

With these tools, you can create truly multilingual web applications that provide a consistent experience to users, regardless of their language preference.

Additional Resources

Exercises

  1. Set up JavaScript translation in a simple Django project with at least two languages.
  2. Create a form with client-side validation that displays error messages in multiple languages.
  3. Build a countdown component that correctly pluralizes time units in different languages.
  4. Optimize the JavaScript catalog loading for a specific app in your project.
  5. Implement a language switcher that updates the page text without a full page reload.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)