Internationalization (i18n & l10n)

Internationalization in Django means preparing your application so its text and formats can be translated and adapted for different languages and regions — you mark strings for translation with gettext and template tags, configure the languages you support, and let Django serve each visitor content in their own language.

Learn Internationalization (i18n & l10n) in our free Django course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

Part of the free Django course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll mark strings with the _() function, translate templates with {' '} and {' '}, wire up LocaleMiddleware and the LANGUAGES setting, and run makemessages and compilemessages to build your .po and .mo files.

Internationalization (i18n) is the work of making your code translatable; localization (l10n) is supplying the actual translations and regional formats. The first step is always the same: tell Django which strings are user-facing so they can be collected and translated later.

In Python code you do this with gettext , which is conventionally imported as _ . Wrapping a string in _() marks it for translation without changing what it returns today.

For text that is evaluated at import time — model field labels or default values — use gettext_lazy instead, so translation is deferred until the active language is known.

Templates have their own translation tags. First load the library with {' '} at the top of the file. Then use {' '} for a single literal string, and {' '} when the text contains variables.

Three settings turn the system on: USE_I18N = True enables translation, LANGUAGE_CODE names the default language, and LANGUAGES lists the languages you offer. LocaleMiddleware then picks the active language for each request from the URL, session, cookie, or browser header.

With strings marked and settings in place, you run the two-step message workflow. makemessages collects strings into editable .po files; you translate them; then compilemessages builds the binary .mo files Django reads at runtime.

Fill in the blank with the translation function (imported as _ ) so the label is looked up in the active language.

You edited the .po file but never compiled it, so Django is still reading the old (or empty) .mo .

✅ Fix: run python manage.py compilemessages after every change to a .po file.

You used a translation tag without loading the library first.

LocaleMiddleware is missing or out of order, so the requested language is never activated.

✅ Fix: add LocaleMiddleware after SessionMiddleware and before CommonMiddleware , and confirm the language is listed in LANGUAGES .

Build a tiny translation system with two languages and a _() helper that switches based on the active language — exactly what Django does under the hood.

Lesson 25 complete — your app now speaks many languages!

You can mark strings with _() , translate templates with {' '} and {' '} , configure USE_I18N , LANGUAGES , and LocaleMiddleware , and run makemessages and compilemessages to build your .po and .mo files.

🚀 Up next: GraphQL APIs with Graphene — expose your data through a flexible GraphQL schema instead of REST.

Practice quiz

What is the difference between internationalization (i18n) and localization (l10n)?

  • i18n prepares code so it can be translated; l10n provides the actual translations and regional formats
  • i18n is server-side, l10n is client-side
  • i18n is for dates, l10n is for currency
  • They are two names for the same thing

Answer: i18n prepares code so it can be translated; l10n provides the actual translations and regional formats. Internationalization is the engineering work of making strings translatable; localization is supplying the translations and locale-specific formats.

Which function is the standard way to mark a string for translation in Python code?

  • localize()
  • i18n()
  • gettext (often imported as _)
  • translate()

Answer: gettext (often imported as _). django.utils.translation.gettext, conventionally aliased to _, marks strings so makemessages can collect them.

Which template tag must you load before using trans or blocktrans?

  • {% load static %}
  • {% load i18n %}
  • {% load l10n %}
  • {% load translation %}

Answer: {% load i18n %}. You must put {% load i18n %} at the top of a template before using the translation tags.

Which template tag translates a literal string with no variables?

  • {% blocktrans %}
  • {% localize %}
  • {% gettext %}
  • {% trans %}

Answer: {% trans %}. {% trans "text" %} marks and translates a single literal string in a template.

When do you need {% blocktrans %} instead of {% trans %}?

  • When the text contains template variables or placeholders
  • When the text is shorter than 10 characters
  • When translating numbers
  • When the page uses a base template

Answer: When the text contains template variables or placeholders. {% blocktrans %} handles strings that interpolate variables, which {% trans %} cannot do.

Which middleware selects the active language from the request?

  • CommonMiddleware
  • django.middleware.locale.LocaleMiddleware
  • SecurityMiddleware
  • SessionMiddleware

Answer: django.middleware.locale.LocaleMiddleware. LocaleMiddleware inspects the URL, session, cookie, and Accept-Language header to choose the language.

Which setting must be True for Django's translation system to be active?

  • USE_TZ
  • USE_TRANSLATION
  • USE_L10N
  • USE_I18N

Answer: USE_I18N. USE_I18N must be True to enable Django's translation machinery.

Which management command scans your code for marked strings and creates or updates .po files?

  • collectstatic
  • maketranslations
  • makemessages
  • compilemessages

Answer: makemessages. manage.py makemessages collects translatable strings into .po message files for each locale.

What does compilemessages produce from your .po files?

  • HTML files
  • Compiled binary .mo files Django reads at runtime
  • JSON files
  • Python modules

Answer: Compiled binary .mo files Django reads at runtime. compilemessages converts human-edited .po files into the binary .mo files Django loads at runtime.

Which setting defines the default language used when no translation is selected?

  • LANGUAGE_CODE
  • LOCALE_CODE
  • DEFAULT_LANGUAGE
  • LANGUAGES

Answer: LANGUAGE_CODE. LANGUAGE_CODE sets the default language, for example 'en-us', used as a fallback.