Django was originally developed right in the middle of the United States – quite literally, as Lawrence, Kansas, is less than 40 miles from the geographic center of the continental United States. Like most open source projects, though, Django’s community grew to include people from all over the globe. As Django’s community became increasingly diverse, internationalization and localization became increasingly important.

Django itself is fully internationalized; all strings are marked for translation, and settings control the display of locale-dependent values like dates and times. Django also ships with more than 50 different localization files. If you’re not a native English speaker, there’s a good chance that Django is already translated into your primary language.

The same internationalization framework used for these localizations is available for you to use in your own code and templates.

Because many developers have at best a fuzzy understanding of what internationalization and localization actually mean, we will begin with a few definitions.



Refers to the process of designing programs for the potential use of any locale. This process is usually done by software developers. Internationalization includes marking text (such as UI elements and error messages) for future translation, abstracting the display of dates and times so that different local standards may be observed, providing support for differing time zones, and generally making sure that the code contains no assumptions about the location of its users. You’ll often see internationalization abbreviated I18N. (The 18 refers to the number of letters omitted between the initial I and the terminal N.)


Refers to the process of actually translating an internationalized program for use in a particular locale. This work is usually done by translators. You’ll sometimes see localization abbreviated as L10N.

Here are some other terms that will help us to handle a common language:

locale name

A locale name, either a language specification of the form ll or a combined language and country specification of the form ll_CC. Examples: it, de_AT, es, pt_BR. The language part is always in lower case and the country part in upper case. The separator is an underscore.

language code

Represents the name of a language. Browsers send the names of the languages they accept in the Accept-Language HTTP header using this format. Examples: it, de-at, es, pt-br. Language codes are generally represented in lower-case, but the HTTP Accept-Language header is case-insensitive. The separator is a dash.

message file

A message file is a plain-text file, representing a single language, that contains all available translation strings and how they should be represented in the given language. Message files have a .po file extension.

translation string

A literal that can be translated.

format file

A format file is a Python module that defines the data formats for a given locale.


In order to make a Django project translatable, you have to add a minimal number of hooks to your Python code and templates. These hooks are called translation strings. They tell Django: This text should be translated into the end user’s language, if a translation for this text is available in that language. It’s your responsibility to mark translatable strings; the system can only translate strings it knows about.

Django then provides utilities to extract the translation strings into a message file. This file is a convenient way for translators to provide the equivalent of the translation strings in the target language. Once the translators have filled in the message file, it must be compiled. This process relies on the GNU gettext toolset.

Once this is done, Django takes care of translating Web apps on the fly in each available language, according to users’ language preferences.

Essentially, Django does two things:

  • It lets developers and template authors specify which parts of their applications should be translatable.
  • It uses that information to translate Web applications for particular users according to their language preferences.

Django’s internationalization hooks are on by default, and that means there’s a bit of i18n-related overhead in certain places of the framework. If you don’t use internationalization, you should take the two seconds to set USE_I18N = False in your settings file. Then Django will make some optimizations so as not to load the internationalization machinery, which will save you some overhead. There is also an independent but related USE_L10N setting that controls if Django should implement format localization.