Skip to main content

Django Translation Strings

Introduction

When building web applications with Django that need to support multiple languages, translation strings are your primary tool for making text content translatable. Django's translation system is based on GNU gettext, providing a robust framework to mark strings for translation and then render them in the appropriate language based on the user's preference.

In this guide, we'll explore how Django handles translation strings, how to mark text for translation in your Python code and templates, and how to use these features to create a truly international web application.

Translation String Basics

What Are Translation Strings?

Translation strings are pieces of text in your Django application that are marked for translation. When a user accesses your site, Django renders these strings in their preferred language if a translation is available.

Setting Up Translations

Before we dive into translation strings, let's ensure our Django project is properly configured for internationalization:

python
# settings.py

MIDDLEWARE = [
# ...
'django.middleware.locale.LocaleMiddleware',
# ...
]

LANGUAGE_CODE = 'en-us' # Default language

USE_I18N = True # Enable internationalization
USE_L10N = True # Enable localization

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

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

The LOCALE_PATHS setting tells Django where to look for translation files. Make sure to create this directory structure.

Marking Strings for Translation in Python Code

Django provides several functions to mark strings for translation in your Python code.

The gettext Function

The most common function is gettext(), which is typically imported as an alias _.

python
from django.utils.translation import gettext as _

def my_view(request):
output = _("Welcome to my site.")
return render(request, 'my_template.html', {'message': output})

When this view is processed, if the user's language is set to Spanish, they'll see "Bienvenido a mi sitio." (assuming you've provided this translation).

Lazy Translation

Sometimes you need to translate a string but don't want the translation to happen immediately, such as at module load time:

python
from django.utils.translation import gettext_lazy as _

class MyModel(models.Model):
name = models.CharField(_('name'), max_length=100)
description = models.TextField(_('description'), blank=True)

The gettext_lazy() function marks these strings for translation but doesn't actually translate them until they're rendered to a string, which is perfect for model fields.

Handling Pluralization

For strings that need different forms based on a count, use ngettext():

python
from django.utils.translation import ngettext

def display_items(count):
message = ngettext(
'There is %(count)d item.',
'There are %(count)d items.',
count
) % {'count': count}
return message

Input:

python
print(display_items(1))  # With English selected
print(display_items(5)) # With English selected

Output:

There is 1 item.
There are 5 items.

Translation Strings in Templates

Django also allows you to mark strings for translation in your templates.

Using the {% translate %} Template Tag

First, load the internationalization tags in your template:

html
{% load i18n %}

<h1>{% translate "Welcome to our website" %}</h1>
<p>{% translate "This content is translatable" %}</p>

Template Tags with Variables

You can include variables in translated strings using the blocktranslate tag:

html
{% load i18n %}

{% blocktranslate with user_name=user.name %}
Hello, {{ user_name }}! Welcome to our website.
{% endblocktranslate %}

Handling Pluralization in Templates

Similar to Python code, you can handle pluralization in templates:

html
{% load i18n %}

{% blocktranslate count counter=list|length %}
There is {{ counter }} item in the list.
{% plural %}
There are {{ counter }} items in the list.
{% endblocktranslate %}

Context-Specific Translations

Sometimes the same word in English might translate differently in another language depending on context. Django handles this with the pgettext() function:

python
from django.utils.translation import pgettext

month = pgettext("month name", "May")
verb = pgettext("verb", "May")

In templates:

html
{% load i18n %}

{% translate "May" context "month name" %}
{% translate "May" context "verb" %}

Creating Translation Files

After marking strings for translation, you need to create translation files:

  1. Run the makemessages command:
bash
django-admin makemessages -l es  # Create/update Spanish translation file
  1. This creates/updates a .po file in your locale directory. Edit this file to add translations.

  2. Compile the translations:

bash
django-admin compilemessages

Here's a sample .po file entry:

#: models.py:10
msgid "Welcome to my site."
msgstr "Bienvenido a mi sitio."

Real-World Examples

Multi-language Blog Post

python
# models.py
from django.db import models
from django.utils.translation import gettext_lazy as _

class BlogPost(models.Model):
title = models.CharField(_('title'), max_length=200)
content = models.TextField(_('content'))

class Meta:
verbose_name = _('blog post')
verbose_name_plural = _('blog posts')

Localized Date Formatting

python
# views.py
from django.utils import timezone
from django.utils.formats import date_format
from django.utils.translation import get_language

def event_view(request):
event_date = timezone.now()
# Format date according to the current language
formatted_date = date_format(event_date, format='DATETIME_FORMAT', use_l10n=True)
return render(request, 'event.html', {'date': formatted_date})

Language Selector

html
<!-- language_selector.html -->
{% load i18n %}

<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>

Remember to include Django's built-in language selection view in your URLs:

python
# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include

urlpatterns = [
path('i18n/', include('django.conf.urls.i18n')),
]

urlpatterns += i18n_patterns(
path('', include('myapp.urls')),
)

Best Practices

  1. Mark All User-Facing Strings: Even if you only support one language now, marking strings makes future translations easier.

  2. Use Context When Necessary: Different meanings of the same word require context markers.

  3. Be Careful with Variables: Sentence structure varies between languages, so avoid constructing sentences from fragments.

  4. Keep Translations Updated: Run makemessages regularly as you add new content.

  5. Use Lazy Translation: In models and anywhere that strings are evaluated during module import.

  6. Test Your Translations: Verify how your site looks in each supported language.

Common Pitfalls

  • Forgetting Apostrophes: Strings like _("Don't forget me") need special handling due to the quote in "Don't".

  • String Concatenation: Avoid _("Hello") + " " + name. Instead, use _("Hello %(name)s") % {'name': name}.

  • Translating Settings: Settings are loaded before the translation system, so they can't be translated directly.

Summary

Django's translation system provides powerful tools for internationalizing your web application. By properly marking strings for translation in both Python code and templates, you can create a site that offers a localized experience to users around the world.

The basic workflow is:

  1. Mark strings for translation using gettext functions
  2. Generate message files with makemessages
  3. Translate the strings in .po files
  4. Compile translations with compilemessages
  5. Ensure proper language selection in your application

With these tools and techniques, you can make your Django application accessible to users regardless of their language preference.

Additional Resources

Exercises

  1. Create a simple Django application with at least three views, and mark all user-facing strings for translation.

  2. Add support for at least two languages in your application.

  3. Implement a language selector that allows users to switch between available languages.

  4. Create a model with translatable fields and verbose names.

  5. Practice handling pluralization in both Python code and templates.



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