summaryrefslogtreecommitdiffstats
path: root/docs/extensions.rst
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 16:06:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 16:06:13 +0000
commitce859b2defe1fc90c7a16551291799fc37284add (patch)
tree7e6b04791662f8f268c7abc9c07d41e98a261a84 /docs/extensions.rst
parentInitial commit. (diff)
downloadjinja2-upstream.tar.xz
jinja2-upstream.zip
Adding upstream version 3.1.2.upstream/3.1.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'docs/extensions.rst')
-rw-r--r--docs/extensions.rst423
1 files changed, 423 insertions, 0 deletions
diff --git a/docs/extensions.rst b/docs/extensions.rst
new file mode 100644
index 0000000..45ead3b
--- /dev/null
+++ b/docs/extensions.rst
@@ -0,0 +1,423 @@
+.. _jinja-extensions:
+
+Extensions
+==========
+
+Jinja supports extensions that can add extra filters, tests, globals or even
+extend the parser. The main motivation of extensions is to move often used
+code into a reusable class like adding support for internationalization.
+
+
+Adding Extensions
+-----------------
+
+Extensions are added to the Jinja environment at creation time. To add an
+extension pass a list of extension classes or import paths to the
+``extensions`` parameter of the :class:`~jinja2.Environment` constructor. The following
+example creates a Jinja environment with the i18n extension loaded::
+
+ jinja_env = Environment(extensions=['jinja2.ext.i18n'])
+
+To add extensions after creation time, use the :meth:`~jinja2.Environment.add_extension` method::
+
+ jinja_env.add_extension('jinja2.ext.debug')
+
+
+.. _i18n-extension:
+
+i18n Extension
+--------------
+
+**Import name:** ``jinja2.ext.i18n``
+
+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, an application has to provide functions for ``gettext``,
+``ngettext``, and optionally ``pgettext`` and ``npgettext``, either
+globally or when rendering. A ``_()`` function is added as an alias to
+the ``gettext`` function.
+
+
+Environment Methods
+~~~~~~~~~~~~~~~~~~~
+
+After enabling the extension, the environment provides the following
+additional methods:
+
+.. method:: jinja2.Environment.install_gettext_translations(translations, newstyle=False)
+
+ Installs a translation globally for the environment. The
+ ``translations`` object must implement ``gettext``, ``ngettext``,
+ and optionally ``pgettext`` and ``npgettext``.
+ :class:`gettext.NullTranslations`, :class:`gettext.GNUTranslations`,
+ and `Babel`_\s ``Translations`` are supported.
+
+ .. versionchanged:: 3.0
+ Added ``pgettext`` and ``npgettext``.
+
+ .. versionchanged:: 2.5
+ Added new-style gettext support.
+
+.. method:: jinja2.Environment.install_null_translations(newstyle=False)
+
+ 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 Added new-style gettext support.
+
+.. method:: jinja2.Environment.install_gettext_callables(gettext, ngettext, newstyle=False, pgettext=None, npgettext=None)
+
+ Install the given ``gettext``, ``ngettext``, ``pgettext``, and
+ ``npgettext`` callables into the environment. They should behave
+ exactly like :func:`gettext.gettext`, :func:`gettext.ngettext`,
+ :func:`gettext.pgettext` and :func:`gettext.npgettext`.
+
+ If ``newstyle`` is activated, the callables are wrapped to work like
+ newstyle callables. See :ref:`newstyle-gettext` for more information.
+
+ .. versionchanged:: 3.0
+ Added ``pgettext`` and ``npgettext``.
+
+ .. versionadded:: 2.5
+ Added new-style gettext support.
+
+.. method:: jinja2.Environment.uninstall_gettext_translations()
+
+ Uninstall the environment's globally installed translation.
+
+.. method:: jinja2.Environment.extract_translations(source)
+
+ Extract localizable strings from the given template node or 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).
+ - ``message`` is the string itself, or a tuple of strings for
+ functions with multiple arguments.
+
+ 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, 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.install_gettext_translations(translations)
+
+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 in
+:ref:`the template documentation <i18n-in-templates>`.
+
+.. _gettext: https://docs.python.org/3/library/gettext.html
+.. _Babel: https://babel.pocoo.org/
+
+
+Whitespace Trimming
+~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.10
+
+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:
+
+New Style Gettext
+~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.5
+
+New style gettext calls are less to type, less error prone, and support
+autoescaping better.
+
+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.
+
+With standard ``gettext`` calls, string formatting is a separate step
+done with the ``|format`` filter. This requires duplicating work for
+``ngettext`` calls.
+
+.. sourcecode:: jinja
+
+ {{ gettext("Hello, World!") }}
+ {{ gettext("Hello, %(name)s!")|format(name=name) }}
+ {{ ngettext(
+ "%(num)d apple", "%(num)d apples", apples|count
+ )|format(num=apples|count) }}
+ {{ pgettext("greeting", "Hello, World!") }}
+ {{ npgettext(
+ "fruit", "%(num)d apple", "%(num)d apples", apples|count
+ )|format(num=apples|count) }}
+
+New style ``gettext`` make formatting part of the call, and behind the
+scenes enforce more consistency.
+
+.. sourcecode:: jinja
+
+ {{ gettext("Hello, World!") }}
+ {{ gettext("Hello, %(name)s!", name=name) }}
+ {{ ngettext("%(num)d apple", "%(num)d apples", apples|count) }}
+ {{ pgettext("greeting", "Hello, World!") }}
+ {{ npgettext("fruit", "%(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.
+
+
+Expression Statement
+--------------------
+
+**Import name:** ``jinja2.ext.do``
+
+The "do" aka expression-statement extension adds a simple ``do`` tag to the
+template engine that works like a variable expression but ignores the
+return value.
+
+.. _loopcontrols-extension:
+
+Loop Controls
+-------------
+
+**Import name:** ``jinja2.ext.loopcontrols``
+
+This extension adds support for ``break`` and ``continue`` in loops. After
+enabling, Jinja provides those two keywords which work exactly like in
+Python.
+
+.. _with-extension:
+
+With Statement
+--------------
+
+**Import name:** ``jinja2.ext.with_``
+
+.. versionchanged:: 2.9
+
+ This extension is now built-in and no longer does anything.
+
+.. _autoescape-extension:
+
+Autoescape Extension
+--------------------
+
+**Import name:** ``jinja2.ext.autoescape``
+
+.. versionchanged:: 2.9
+
+ This extension was removed and is now built-in. Enabling the
+ extension no longer does anything.
+
+
+.. _debug-extension:
+
+Debug Extension
+---------------
+
+**Import name:** ``jinja2.ext.debug``
+
+Adds a ``{% debug %}`` tag to dump the current context as well as the
+available filters and tests. This is useful to see what's available to
+use in the template without setting up a debugger.
+
+
+.. _writing-extensions:
+
+Writing Extensions
+------------------
+
+.. module:: jinja2.ext
+
+By writing extensions you can add custom tags to Jinja. This is a non-trivial
+task and usually not needed as the default tags and expressions cover all
+common use cases. The i18n extension is a good example of why extensions are
+useful. Another one would be fragment caching.
+
+When writing extensions you have to keep in mind that you are working with the
+Jinja template compiler which does not validate the node tree you are passing
+to it. If the AST is malformed you will get all kinds of compiler or runtime
+errors that are horrible to debug. Always make sure you are using the nodes
+you create correctly. The API documentation below shows which nodes exist and
+how to use them.
+
+
+Example Extensions
+------------------
+
+Cache
+~~~~~
+
+The following example implements a ``cache`` tag for Jinja by using the
+`cachelib`_ library:
+
+.. literalinclude:: examples/cache_extension.py
+ :language: python
+
+And here is how you use it in an environment::
+
+ from jinja2 import Environment
+ from cachelib import SimpleCache
+
+ env = Environment(extensions=[FragmentCacheExtension])
+ env.fragment_cache = SimpleCache()
+
+Inside the template it's then possible to mark blocks as cacheable. The
+following example caches a sidebar for 300 seconds:
+
+.. sourcecode:: html+jinja
+
+ {% cache 'sidebar', 300 %}
+ <div class="sidebar">
+ ...
+ </div>
+ {% endcache %}
+
+.. _cachelib: https://github.com/pallets/cachelib
+
+
+Inline ``gettext``
+~~~~~~~~~~~~~~~~~~
+
+The following example demonstrates using :meth:`Extension.filter_stream`
+to parse calls to the ``_()`` gettext function inline with static data
+without needing Jinja blocks.
+
+.. code-block:: html
+
+ <h1>_(Welcome)</h1>
+ <p>_(This is a paragraph)</p>
+
+It requires the i18n extension to be loaded and configured.
+
+.. literalinclude:: examples/inline_gettext_extension.py
+ :language: python
+
+
+Extension API
+-------------
+
+Extension
+~~~~~~~~~
+
+Extensions always have to extend the :class:`jinja2.ext.Extension` class:
+
+.. autoclass:: Extension
+ :members: preprocess, filter_stream, parse, attr, call_method
+
+ .. attribute:: identifier
+
+ The identifier of the extension. This is always the true import name
+ of the extension class and must not be changed.
+
+ .. attribute:: tags
+
+ If the extension implements custom tags this is a set of tag names
+ the extension is listening for.
+
+
+Parser
+~~~~~~
+
+The parser passed to :meth:`Extension.parse` provides ways to parse
+expressions of different types. The following methods may be used by
+extensions:
+
+.. autoclass:: jinja2.parser.Parser
+ :members: parse_expression, parse_tuple, parse_assign_target,
+ parse_statements, free_identifier, fail
+
+ .. attribute:: filename
+
+ The filename of the template the parser processes. This is **not**
+ the load name of the template. For the load name see :attr:`name`.
+ For templates that were not loaded form the file system this is
+ ``None``.
+
+ .. attribute:: name
+
+ The load name of the template.
+
+ .. attribute:: stream
+
+ The current :class:`~jinja2.lexer.TokenStream`
+
+.. autoclass:: jinja2.lexer.TokenStream
+ :members: push, look, eos, skip, __next__, next_if, skip_if, expect
+
+ .. attribute:: current
+
+ The current :class:`~jinja2.lexer.Token`.
+
+.. autoclass:: jinja2.lexer.Token
+ :members: test, test_any
+
+ .. attribute:: lineno
+
+ The line number of the token
+
+ .. attribute:: type
+
+ The type of the token. This string is interned so you may compare
+ it with arbitrary strings using the ``is`` operator.
+
+ .. attribute:: value
+
+ The value of the token.
+
+There is also a utility function in the lexer module that can count newline
+characters in strings:
+
+.. autofunction:: jinja2.lexer.count_newlines
+
+
+AST
+~~~
+
+The AST (Abstract Syntax Tree) is used to represent a template after parsing.
+It's build of nodes that the compiler then converts into executable Python
+code objects. Extensions that provide custom statements can return nodes to
+execute custom Python code.
+
+The list below describes all nodes that are currently available. The AST may
+change between Jinja versions but will stay backwards compatible.
+
+For more information have a look at the repr of :meth:`jinja2.Environment.parse`.
+
+.. module:: jinja2.nodes
+
+.. jinja:nodes:: jinja2.nodes.Node
+
+.. autoexception:: Impossible