Specify a translation string by using the function
ugettext(). It’s convention to import this as a shorter alias,
_, to save typing.
Python’s standard library
gettext module installs
_() into the global namespace, as an alias for
gettext(). In Django, we have chosen not to follow this practice, for a couple of reasons:
- For international character set (Unicode) support,
ugettext()is more useful than
gettext(). Sometimes, you should be using
ugettext_lazy()as the default translation method for a particular file. Without
_()in the global namespace, the developer has to think about which is the most appropriate translation function.
- The underscore character (
_) is used to represent the previous result in Python’s interactive shell and doctest tests. Installing a global
_()function causes interference. Explicitly importing
_()avoids this problem.
In this example, the text “Welcome to my site.” is marked as a translation string:
Obviously, you could code this without using the alias. This example is identical to the previous one:
Translation also works on computed values. This example is identical to the previous two:
… and on variables. Again, here’s an identical example:
(The caveat with using variables or computed values, as in the previous two examples, is that Django’s translation-string-detecting utility,
django-admin makemessages, won’t be able to find these strings. More on
The strings you pass to
ugettext() can take placeholders, specified with Python’s standard named-string interpolation syntax. Example:
This technique lets language-specific translations reorder the placeholder text. For example, an English translation may be “Today is November 26.”, while a Spanish translation may be “Hoy es 26 de Noviembre.” – with the month and the day placeholders swapped.
For this reason, you should use named-string interpolation (e.g.,
%(day)s) instead of positional interpolation (e.g.,
%d) whenever you have more than a single parameter. If you used positional interpolation, translations wouldn’t be able to reorder placeholder text.
Comments for Translators
If you would like to give translators hints about a translatable string, you can add a comment prefixed with the
Translators keyword on the line preceding the string, e.g.:
The comment will then appear in the resulting
.po file associated with the translatable construct located below it and should also be displayed by most translation tools.
Just for completeness, this is the corresponding fragment of the resulting
This also works in templates. See translator-comments-in-templates for more details.
Marking Strings as No-Op
Use the function
django.utils.translation.ugettext_noop() to mark a string as a translation string without translating it. The string is later translated from a variable.
Use this if you have constant strings that should be stored in the source language because they are exchanged over systems or users – such as strings in a database – but should be translated at the last possible point in time, such as when the string is presented to the user.
Use the function
django.utils.translation.ungettext() to specify pluralized messages.
ungettext takes three arguments: the singular translation string, the plural translation string and the number of objects.
This function is useful when you need your Django application to be localizable to languages where the number and complexity of plural forms is greater than the two forms used in English (‘object’ for the singular and ‘objects’ for all the cases where
count is different from one, irrespective of its value.)
In this example the number of objects is passed to the translation languages as the
Note that pluralization is complicated and works differently in each language. Comparing
to 1 isn’t always the correct rule. This code looks sophisticated, but will produce incorrect results for some languages:
Don’t try to implement your own singular-or-plural logic, it won’t be correct. In a case like this, consider something like the following:
ungettext(), make sure you use a single name for every extrapolated variable included in the literal. In the examples above, note how we used the
name Python variable in both translation strings. This example, besides being incorrect in some languages as noted above, would fail:
You would get an error when running
Sometimes words have several meanings, such as “May” in English, which refers to a month name and to a verb. To enable translators to translate these words correctly in different contexts, you can use the
django.utils.translation.pgettext() function, or the
django.utils.translation.npgettext() function if the string needs pluralization. Both take a context string as the first variable.
In the resulting
.po file, the string will then appear as often as there are different contextual markers for the same string (the context will appear on the
msgctxt line), allowing the translator to give a different translation for each of them.
will appear in the
.po file as:
Contextual markers are also supported by the
blocktrans template tags.
Use the lazy versions of translation functions in
django.utils.translation (easily recognizable by the
lazy suffix in their names) to translate strings lazily – when the value is accessed rather than when they’re called.
These functions store a lazy reference to the string – not the actual translation. The translation itself will be done when the string is used in a string context, such as in template rendering.
This is essential when calls to these functions are located in code paths that are executed at module load time.
This is something that can easily happen when defining models, forms and model forms, because Django implements these such that their fields are actually class-level attributes. For that reason, make sure to use lazy translations in the following cases.
Model fields and relationships
For example, to translate the help text of the name field in the following model, do the following:
You can mark names of
OneToOneField relationship as translatable by using their
Just like you would do in
verbose_name you should provide a lowercase verbose name text for the relation as Django will automatically title case it when required.
Model verbose names values
It is recommended to always provide explicit
verbose_name_plural options rather than relying on the fall-back English-centric and somewhat naive determination of verbose names Django performs by looking at the model’s class name:
Model methods short_description attribute values
For model methods, you can provide translations to Django and the admin site with the
Working with Lazy Translation Objects
The result of a
ugettext_lazy() call can be used wherever you would use a Unicode string (an object with type
unicode) in Python. If you try to use it where a bytestring (a
str object) is expected, things will not work as expected, since a
ugettext_lazy() object doesn’t know how to convert itself to a bytestring. You can’t use a Unicode string inside a bytestring, either, so this is consistent with normal Python behavior. For example:
If you ever see output that looks like
"hello <django.utils.functional...>", you have tried to insert the result of
ugettext_lazy() into a bytestring. That’s a bug in your code.
If you don’t like the long
ugettext_lazy name, you can just alias it as
_ (underscore), like so:
ungettext_lazy() to mark strings in models and utility functions is a common operation. When you’re working with these objects elsewhere in your code, you should ensure that you don’t accidentally convert them to strings, because they should be converted as late as possible (so that the correct locale is in effect). This necessitates the use of the helper function described next.
Lazy translations and plural
When using lazy translation for a plural string (
[u]n[p]gettext_lazy), you generally don’t know the
number argument at the time of the string definition. Therefore, you are authorized to pass a key name instead of an integer as the
number argument. Then
number will be looked up in the dictionary under that key during string interpolation. Here’s example:
If the string contains exactly one unnamed placeholder, you can interpolate directly with the
Joining strings: string_concat()
Standard Python string joins (
''.join([...])) will not work on lists containing lazy translation objects.
Instead, you can use
django.utils.translation.string_concat(), which creates a lazy object that concatenates its contents and converts them to strings only when the result is included in a string. For example:
In this case, the lazy translations in
result will only be converted to strings when
result itself is used in a string (usually at template rendering time).
Other uses of lazy in delayed translations
For any other case where you would like to delay the translation, but have to pass the translatable string as argument to another function, you can wrap this function inside a lazy call yourself. For example:
And then later:
Localized Names of Languages
get_language_info() function provides detailed information about languages:
name_local attributes of the dictionary contain the name of the language in English and in the language itself, respectively. The
bidi attribute is True only for bi-directional languages.
The source of the language information is the
django.conf.locale module. Similar access to this information is available for template code. See below.