**Import name:** ``jinja2.ext.i18n``
-The i18n extension can be used in combination with `gettext`_ or `babel`_. If
-the i18n extension is enabled Jinja2 provides a ``trans`` statement that marks
-the wrapped string as translatable and calls ``gettext``.
+The i18n extension can be used in combination with `gettext`_ or
+`Babel`_. When it's enabled, Jinja provides a ``trans`` statement that
+marks a block as translatable and calls ``gettext``.
-After enabling, dummy ``_`` function that forwards calls to ``gettext`` is added
-to the environment globals. An internationalized application then has to
-provide a ``gettext`` function and optionally an ``ngettext`` function into the
-namespace, either globally or for each rendering.
+After enabling, an application has to provide ``gettext`` and
+``ngettext`` functions, either globally or when rendering. A ``_()``
+function is added as an alias to the ``gettext`` function.
Environment Methods
~~~~~~~~~~~~~~~~~~~
.. method:: jinja2.Environment.install_gettext_translations(translations, newstyle=False)
- Installs a translation globally for that environment. The translations
- object provided must implement at least ``ugettext`` and ``ungettext``.
- The ``gettext.NullTranslations`` and ``gettext.GNUTranslations`` classes
- as well as `Babel`_\s ``Translations`` class are supported.
+ Installs a translation globally for the environment. The
+ ``translations`` object must implement ``gettext`` and ``ngettext``
+ (or ``ugettext`` and ``ungettext`` for Python 2).
+ :class:`gettext.NullTranslations`, :class:`gettext.GNUTranslations`,
+ and `Babel`_\s ``Translations`` are supported.
- .. versionchanged:: 2.5 newstyle gettext added
+ .. versionchanged:: 2.5 Added new-style gettext support.
.. method:: jinja2.Environment.install_null_translations(newstyle=False)
- Install dummy gettext functions. This is useful if you want to prepare
- the application for internationalization but don't want to implement the
- full internationalization system yet.
+ Install no-op gettext functions. This is useful if you want to
+ prepare the application for internationalization but don't want to
+ implement the full system yet.
- .. versionchanged:: 2.5 newstyle gettext added
+ .. versionchanged:: 2.5 Added new-style gettext support.
.. method:: jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False)
- Installs the given ``gettext`` and ``ngettext`` callables into the
- environment as globals. They are supposed to behave exactly like the
- standard library's :func:`gettext.ugettext` and
- :func:`gettext.ungettext` functions.
+ Install the given ``gettext`` and ``ngettext`` callables into the
+ environment. They should behave exactly like
+ :func:`gettext.gettext` and :func:`gettext.ngettext` (or
+ ``ugettext`` and ``ungettext`` for Python 2).
If ``newstyle`` is activated, the callables are wrapped to work like
newstyle callables. See :ref:`newstyle-gettext` for more information.
- .. versionadded:: 2.5
+ .. versionadded:: 2.5 Added new-style gettext support.
.. method:: jinja2.Environment.uninstall_gettext_translations()
- Uninstall the translations again.
+ Uninstall the environment's globally installed translation.
.. method:: jinja2.Environment.extract_translations(source)
For every string found this function yields a ``(lineno, function,
message)`` tuple, where:
- * ``lineno`` is the number of the line on which the string was found,
- * ``function`` is the name of the ``gettext`` function used (if the
- string was extracted from embedded Python code), and
- * ``message`` is the string itself (a ``unicode`` object, or a tuple
- of ``unicode`` objects for functions with multiple string arguments).
+ - ``lineno`` is the number of the line on which the string was
+ found.
+ - ``function`` is the name of the ``gettext`` function used (if
+ the string was extracted from embedded Python code).
+ - ``message`` is the string itself (``unicode`` on Python 2), or a
+ tuple of strings for functions with multiple arguments.
- If `Babel`_ is installed, :ref:`the babel integration <babel-integration>`
- can be used to extract strings for babel.
+ If `Babel`_ is installed, see :ref:`babel-integration` to extract
+ the strings.
-For a web application that is available in multiple languages but gives all
-the users the same language (for example a multilingual forum software
-installed for a French community) may load the translations once and add the
-translation methods to the environment at environment generation time::
+For a web application that is available in multiple languages but gives
+all the users the same language (for example, multilingual forum
+software installed for a French community), the translation may be
+installed when the environment is created.
+
+.. code-block:: python
translations = get_gettext_translations()
- env = Environment(extensions=['jinja2.ext.i18n'])
+ env = Environment(extensions=["jinja2.ext.i18n"])
env.install_gettext_translations(translations)
-The ``get_gettext_translations`` function would return the translator for the
-current configuration. (For example by using ``gettext.find``)
+The ``get_gettext_translations`` function would return the translator
+for the current configuration, for example by using ``gettext.find``.
-The usage of the ``i18n`` extension for template designers is covered as part
-:ref:`of the template documentation <i18n-in-templates>`.
+The usage of the ``i18n`` extension for template designers is covered in
+:ref:`the template documentation <i18n-in-templates>`.
.. _gettext: https://docs.python.org/3/library/gettext.html
.. _Babel: http://babel.pocoo.org/
-.. _newstyle-gettext:
Whitespace Trimming
~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.10
-Linebreaks and surrounding whitespace can be automatically trimmed by enabling
-the ``ext.i18n.trimmed`` :ref:`policy <ext-i18n-trimmed>`.
+Within ``{% trans %}`` blocks, it can be useful to trim line breaks and
+whitespace so that the block of text looks like a simple string with
+single spaces in the translation file.
+
+Linebreaks and surrounding whitespace can be automatically trimmed by
+enabling the ``ext.i18n.trimmed`` :ref:`policy <ext-i18n-trimmed>`.
-Newstyle Gettext
-~~~~~~~~~~~~~~~~
+.. _newstyle-gettext:
+
+New Style Gettext
+~~~~~~~~~~~~~~~~~
.. versionadded:: 2.5
-Starting with version 2.5 you can use newstyle gettext calls. These are
-inspired by trac's internal gettext functions and are fully supported by
-the babel extraction tool. They might not work as expected by other
-extraction tools in case you are not using Babel's.
+New style gettext calls are less to type, less error prone, and support
+autoescaping better.
-What's the big difference between standard and newstyle gettext calls? In
-general they are less to type and less error prone. Also if they are used
-in an autoescaping environment they better support automatic escaping.
-Here are some common differences between old and new calls:
+You can use "new style" gettext calls by setting
+``env.newstyle_gettext = True`` or passing ``newstyle=True`` to
+``env.install_translations``. They are fully supported by the Babel
+extraction tool, but might not work as expected with other extraction
+tools.
-standard gettext:
+With standard ``gettext`` calls, string formatting is a separate step
+done with the ``|format`` filter. This requires duplicating work for
+``ngettext`` calls.
-.. sourcecode:: html+jinja
+.. sourcecode:: jinja
- {{ gettext('Hello World!') }}
- {{ gettext('Hello %(name)s!')|format(name='World') }}
- {{ ngettext('%(num)d apple', '%(num)d apples', apples|count)|format(
- num=apples|count
- )}}
+ {{ gettext("Hello, World!") }}
+ {{ gettext("Hello, %(name)s!")|format(name=name) }}
+ {{ ngettext(
+ "%(num)d apple", "%(num)d apples", apples|count
+ )|format(num=apples|count) }}
-newstyle gettext looks like this instead:
+New style ``gettext`` make formatting part of the call, and behind the
+scenes enforce more consistency.
-.. sourcecode:: html+jinja
+.. sourcecode:: jinja
+
+ {{ gettext("Hello, World!") }}
+ {{ gettext("Hello, %(name)s!", name=name) }}
+ {{ ngettext("%(num)d apple", "%(num)d apples", apples|count) }}
+
+The advantages of newstyle gettext are:
+
+- There's no separate formatting step, you don't have to remember to
+ use the ``|format`` filter.
+- Only named placeholders are allowed. This solves a common problem
+ translators face because positional placeholders can't switch
+ positions meaningfully. Named placeholders always carry semantic
+ information about what value goes where.
+- String formatting is used even if no placeholders are used, which
+ makes all strings use a consistent format. Remember to escape any
+ raw percent signs as ``%%``, such as ``100%%``.
+- The translated string is marked safe, formatting performs escaping
+ as needed. Mark a parameter as ``|safe`` if it has already been
+ escaped.
- {{ gettext('Hello World!') }}
- {{ gettext('Hello %(name)s!', name='World') }}
- {{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
-
-The advantages of newstyle gettext are that you have less to type and that
-named placeholders become mandatory. The latter sounds like a
-disadvantage but solves a lot of troubles translators are often facing
-when they are unable to switch the positions of two placeholder. With
-newstyle gettext, all format strings look the same.
-
-Furthermore with newstyle gettext, string formatting is also used if no
-placeholders are used which makes all strings behave exactly the same.
-Last but not least are newstyle gettext calls able to properly mark
-strings for autoescaping which solves lots of escaping related issues many
-templates are experiencing over time when using autoescaping.
Expression Statement
--------------------
be a separate document explaining said :ref:`extensions
<jinja-extensions>`.
+
.. _i18n-in-templates:
i18n
~~~~
-If the i18n extension is enabled, it's possible to mark parts in the template
-as translatable. To mark a section as translatable, you can use `trans`::
+If the :ref:`i18n-extension` is enabled, it's possible to mark text in
+the template as translatable. To mark a section as translatable, use a
+``trans`` block:
+
+.. code-block:: jinja
+
+ {% trans %}Hello, {{ user }}!{% endtrans %}
+
+Inside the block, no statements are allowed, only text and simple
+variable tags.
+
+Variable tags can only be a name, not attribute access, filters, or
+other expressions. To use an expression, bind it to a name in the
+``trans`` tag for use in the block.
- <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
+.. code-block:: jinja
-To translate a template expression --- say, using template filters, or by just
-accessing an attribute of an object --- you need to bind the expression to a
-name for use within the translation block::
+ {% trans user=user.username %}Hello, {{ user }}!{% endtrans %}
- <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
+To bind more than one expression, separate each with a comma (``,``).
-If you need to bind more than one expression inside a `trans` tag, separate
-the pieces with a comma (``,``)::
+.. code-block:: jinja
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}
-Inside trans tags no statements are allowed, only variable tags are.
+To pluralize, specify both the singular and plural forms separated by
+the ``pluralize`` tag.
-To pluralize, specify both the singular and plural forms with the `pluralize`
-tag, which appears between `trans` and `endtrans`::
+.. code-block:: jinja
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
There are {{ count }} {{ name }} objects.
{% endtrans %}
-By default, the first variable in a block is used to determine the correct
-singular or plural form. If that doesn't work out, you can specify the name
-which should be used for pluralizing by adding it as parameter to `pluralize`::
+By default, the first variable in a block is used to determine whether
+to use singular or plural form. If that isn't correct, specify the
+variable used for pluralizing as a parameter to ``pluralize``.
+
+.. code-block:: jinja
{% trans ..., user_count=users|length %}...
{% pluralize user_count %}...{% endtrans %}
-When translating longer blocks of text, whitespace and linebreaks result in
-rather ugly and error-prone translation strings. To avoid this, a trans block
-can be marked as trimmed which will replace all linebreaks and the whitespace
-surrounding them with a single space and remove leading/trailing whitespace::
+When translating blocks of text, whitespace and linebreaks result in
+hard to read and error-prone translation strings. To avoid this, a trans
+block can be marked as trimmed, which will replace all linebreaks and
+the whitespace surrounding them with a single space and remove leading
+and trailing whitespace.
+
+.. code-block:: jinja
{% trans trimmed book_title=book.title %}
This is {{ book_title }}.
You should read it!
{% endtrans %}
-If trimming is enabled globally, the `notrimmed` modifier can be used to
-disable it for a `trans` block.
+This results in ``This is %(book_title)s. You should read it!`` in the
+translation file.
+
+If trimming is enabled globally, the ``notrimmed`` modifier can be used
+to disable it for a block.
.. versionadded:: 2.10
- The `trimmed` and `notrimmed` modifiers have been added.
+ The ``trimmed`` and ``notrimmed`` modifiers have been added.
-It's also possible to translate strings in expressions. For that purpose,
-three functions exist:
+It's possible to translate strings in expressions with these functions:
-- `gettext`: translate a single string
-- `ngettext`: translate a pluralizable string
-- `_`: alias for `gettext`
+- ``gettext``: translate a single string
+- ``ngettext``: translate a pluralizable string
+- ``_``: alias for ``gettext``
-For example, you can easily print a translated string like this::
+You can print a translated string like this:
- {{ _('Hello World!') }}
+.. code-block:: jinja
-To use placeholders, use the `format` filter::
+ {{ _("Hello, World!") }}
- {{ _('Hello %(user)s!')|format(user=user.username) }}
+To use placeholders, use the ``format`` filter.
-For multiple placeholders, always use keyword arguments to `format`,
-as other languages may not use the words in the same order.
+.. code-block:: jinja
-.. versionchanged:: 2.5
+ {{ _("Hello, %(user)s!")|format(user=user.username) }}
-If newstyle gettext calls are activated (:ref:`newstyle-gettext`), using
-placeholders is a lot easier:
+Always use keyword arguments to ``format``, as other languages may not
+use the words in the same order.
-.. sourcecode:: html+jinja
+If :ref:`newstyle-gettext` calls are activated, using placeholders is
+easier. Formatting is part of the ``gettext`` call instead of using the
+``format`` filter.
+
+.. sourcecode:: jinja
{{ gettext('Hello World!') }}
{{ gettext('Hello %(name)s!', name='World') }}
{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
-Note that the `ngettext` function's format string automatically receives
-the count as a `num` parameter in addition to the regular parameters.
+The ``ngettext`` function's format string automatically receives the
+count as a ``num`` parameter in addition to the given parameters.
Expression Statement