display: none;
}
-h2.subheading {
- margin: -55px 0 35px 200px;
- font-weight: normal;
- font-size: 30px;
- color: #444;
-}
-
-h2.plain {
- margin: 0;
-}
-
#jinjalogo {
background-image: url(jinjalogo.png);
background-repeat: no-repeat;
background: url(watermark_blur.png) -120px -114px;
}
-#contentwrapper h3,
-#contentwrapper h3 a {
- color: #b41717;
- font-size: 26px;
- margin: 20px 0 0 -5px;
+#contentwrapper h2,
+#contentwrapper h2 a {
+ color: #222;
+ font-size: 24px;
+ margin: 20px 0 0 0;
}
-#contentwrapper h4,
-#contentwrapper h4 a {
+#contentwrapper h3,
+#contentwrapper h3 a {
color: #b41717;
font-size: 20px;
margin: 20px 0 0 0;
dl dt big {
font-size: 100%;
}
+
+ul.search {
+ margin: 10px 0 0 30px;
+ padding: 0;
+}
+
+ul.search li {
+ margin: 10px 0 0 0;
+ padding: 0;
+}
+
+ul.search div.context {
+ font-size: 12px;
+ padding: 4px 0 0 20px;
+ color: #888;
+}
+
+span.highlight {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}">
{%- endif %}
+ {% block extrahead %}{% endblock %}
</head>
<body>
<div id="content">
function will automatically search for all of the words. Pages
containing less words won't appear in the result list.
</p>
- <form action="" method="get">
- <input type="text" name="q" value="" />
- <input type="submit" value="search" />
- </form>
+ <form action="" method="get"><p>
+ <input type="text" name="q" value="">
+ <input type="submit" value="search">
+ </p></form>
{% if search_performed %}
<h2>Search Results</h2>
{% if not search_results %}
High Level API
--------------
-.. autoclass:: jinja2.environment.Environment
- :members: from_string, get_template, join_path, overlay
+.. autoclass:: jinja2.environment.Environment([options])
+ :members: from_string, get_template, join_path, parse
.. attribute:: shared
overridden by templates. As long as no template was loaded it's safe
to modify this dict. For more details see :ref:`global-namespace`.
+ .. automethod:: overlay([options])
+
.. autoclass:: jinja2.Template
- :members: render, stream, generate, make_module, module
+ :members: make_module, module, new_context
.. attribute:: globals
- foo
+ The dict with the globals of that template. It's unsafe to modify
+ this dict as it may be shared with other templates or the environment
+ that loaded the template.
.. attribute:: name
- foo
+ The loading name of the template. If the template was loaded from a
+ string this is `None`.
+
+ .. automethod:: render([context])
+
+ .. automethod:: generate([context])
+
+ .. automethod:: stream([context])
.. autoclass:: jinja2.environment.TemplateStream
--- /dev/null
+.. _jinja-extensions:
+
+Extensions
+==========
+
+.. module:: jinja2.ext
+
+Jinja2 supports extensions that can add extra filters, tests, globals or even
+extend the parser. The main motivation of extensions is it to move often used
+code into a reusable class like adding support for internationalization.
+
+
+Adding Extensions
+-----------------
+
+Extensions are added to the Jinja2 environment at creation time. Once the
+environment is created additional extensions cannot be added. To add an
+extension pass a list of extension classes or import paths to the
+`environment` parameter of the :class:`Environment` constructor. The following
+example creates a Jinja2 environment with the i18n extension loaded::
+
+ jinja_env = Environment(extensions=['jinja.ext.i18n'])
+
+
+Built-in Extensions
+-------------------
+
+.. _i18n-extension:
+
+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`.
+
+After enabling dummy `_`, `gettext` and `ngettext` functions are added to
+the template globals. A internationalized application has to override those
+methods with more useful versions.
+
+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::
+
+ translations = get_gettext_translations()
+ env = Environment(extensions=['jinja.ext.i18n'])
+ env.globals.update(
+ gettext=translations.ugettext,
+ ngettext=translations.ungettext
+ )
+
+The `get_gettext_translations` function would return the translator for the
+current configuration. Keep in mind that Jinja2 uses unicode internally so
+you must pass the `ugettext` and `ungettext` functions to the template.
+
+The default `_` function injected by the extension calls `gettext`
+automatically.
+
+If you want to pass the gettext function into the context at render time
+because you don't know the language/translations earlier and the optimizer
+is enabled (which it is per default), you have to unregister the `gettext`
+and `ugettext` functions first::
+
+ del env.globals['gettext'], env.globals['ugettext']
+
+Jinja2 also provides a way to extract recognized strings. For one the
+`jinja.ext` module provides a function that can return all the occurences
+of gettext calls in a node (as returned by :meth:`Environment.parse`):
+
+.. autofunction:: extract_from_ast
+
+If `babel`_ is installed :ref:`the babel integration <babel-integration>`
+can be used to.
+
+The usage of the `i18n` extension for template designers is covered as part
+:ref:`of the template documentation <i18n-in-templates>`.
+
+
+.. _gettext: http://docs.python.org/dev/library/gettext
+.. _babel: http://babel.edgewall.org/
+
+.. _writing-extensions:
+
+Writing Extensions
+------------------
+
+TODO
intro
api
templates
+ extensions
+ integration
changelog
+If you can't find the information you're looking for, have a look at the
+index of try to find it using the search function:
+
* :ref:`genindex`
+* :ref:`search`
--- /dev/null
+Integration
+===========
+
+Jinja2 provides some code for integration into other tools such as frameworks,
+the `Babel`_ library or your favourite editor for fancy code highlighting.
+This is a brief description of whats included.
+
+.. _babel-integration:
+
+Babel Integration
+-----------------
+
+Jinja provides support for extracting gettext messages from templates via a
+`Babel`_ extractor entry point called `jinja2.ext.babel_extract`. The Babel
+support is implemented as part of the :ref:`i18n-extension` extension.
+
+Gettext messages extracted from both `trans` tags and code expressions.
+
+To extract gettext messages from templates, the project needs a Jinja2 section
+in its Babel extraction method `mapping file`_:
+
+.. sourcecode:: ini
+
+ [jinja: **/templates/**.html]
+ encoding = utf-8
+
+The syntax related options of the :class:`Environment` are also available as
+configuration values in the mapping file. For example to tell the extraction
+that templates use ``%`` as `line_statement_prefix` you can use this code:
+
+.. sourcecode:: ini
+
+ [jinja: **/templates/**.html]
+ encoding = utf-8
+ line_statement_prefix = %
+
+:ref:`jinja-extensions` may also be defined by passing a comma separated list
+of import paths as `extensions` value. The i18n extension is added
+automatically.
+
+.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration
+
+Django
+------
+
+TODO
+
+Pylons
+------
+
+TODO
+
+WSGI
+----
+
+TODO
+
+TextMate
+--------
+
+TODO
+
+Vim
+---
+
+TODO
+
+.. _Babel: http://babel.edgewall.org/
The key-features are...
- ... **configurable syntax**. If you are generating LaTeX or other formats
- with Jinja you can change the delimiters to something that integrates better
+ with Jinja2 you can change the delimiters to something that integrates better
into the LaTeX markup.
- ... **fast**. While performance is not the primarily target of Jinja2 it's
to the very minimum.
- ... **easy to debug**. Jinja2 integrates directly into the python traceback
- system which allows you to debug Jinja templates with regular python
+ system which allows you to debug Jinja2 templates with regular python
debugging helpers.
- ... **secure**. It's possible to evaluate untrusted template code if the
.. _ctypes: http://python.net/crew/theller/ctypes/
+Installation
+------------
+
+You have multiple ways to install Jinja2. If you are unsure what to do, go
+with the Python egg or tarball.
+
+As a Python egg (via easy_install)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can install the most recent Jinja2 version using `easy_install`_::
+
+ sudo easy_install Jinja2
+
+This will install a Jinja2 egg in your Python installation's site-packages
+directory.
+
+From the tarball release
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Download the most recent tarball from the `download page`_
+2. Unpack the tarball
+3. ``sudo python setup.py install``
+
+Note that the last command will automatically download and install
+`setuptools`_ if you don't already have it installed. This requires a working
+internet connection.
+
+This will install Jinja2 into your Python installation's site-packages directory.
+
+Installing the development version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Install `mercurial`_
+2. ``svn co http://dev.pocoo.org/hg/jinja2-main jinja2``
+3. ``cd jinja2``
+4. ``ln -s jinja2 /usr/lib/python2.X/site-packages``
+
+As an alternative to steps 4 you can also do ``python setup.py develop``
+which will install the package via setuptools in development mode. This also
+has the advantage that the C extensions are compiled.
+
+Alternative you can use `easy_install`_ to install the current development
+snapshot::
+
+ sudo easy_install Jinja2==dev
+
+.. _download page: http://jinja.pocoo.org/2/download
+.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
+.. _mercurial: http://www.selenic.com/mercurial/
+
+
Basic API Usage
---------------
-This section gives you a brief introduction to the Python API for Jinja templates.
+This section gives you a brief introduction to the Python API for Jinja2 templates.
The most basic way to create a template and render it is through
:class:`Template`. This however is not the recommended way to work with it,
is disabled regular text is returned. This is useful to generate simple
contents for layout testing.
-.. function:: dict(**items)
+.. function:: dict(\**items)
A convenient alternative to dict literals. ``{'foo': 'bar'}`` is the same
as ``dict(foo='bar')``.
+
+
+Extensions
+----------
+
+The following sections cover the built-in Jinja2 extensions that may be
+enabled by the application. The application could also provide further
+extensions not covered by this documentation. In that case there should
+be a separate document explaining the 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`::
+
+ <p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
+
+To translate a template expression --- say, using template filters or just
+accessing an attribute of an object --- you need to bind the expression to a
+name for use within the translation block::
+
+ <p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
+
+If you need to bind more than one expression inside a `trans` tag, separate
+the pieces with a comma (``,``)::
+
+ {% 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 with the `pluralize`
+tag, which appears between `trans` and `endtrans`::
+
+ {% trans count=list|length %}
+ There is {{ count }} {{ name }} object.
+ {% pluralize %}
+ There are {{ count }} {{ name }} objects.
+ {% endtrans %}
+
+Per 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`::
+
+ {% trans ..., user_count=users|length %}...
+ {% pluralize user_count %}...{% endtrans %}
+
+It's also possible to translate strings in expressions. For that purpose
+three functions exist:
+
+_ `gettext`: translate a single string
+- `ngettext`: translate a pluralizable string
+- `_`: alias for `gettext`
+
+For example you can print a translated string easily this way::
+
+ {{ _('Hello World!') }}
+
+To use placeholders you can use the `format` filter::
+
+ {{ _('Hello %(user)s!')|format(user=user.username) }}
+ or
+ {{ _('Hello %s')|format(user.username) }}
+
+For multiple placeholders always use keyword arguments to `format` as other
+languages may not use the words in the same order.
`extensions`
List of Jinja extensions to use. This can either be import paths
- as strings or extension classes.
+ as strings or extension classes. For more information have a
+ look at :ref:`the extensions documentation <jinja-extensions>`.
`optimized`
should the optimizer be enabled? Default is `True`.
tree of nodes is used by the compiler to convert the template into
executable source- or bytecode. This is useful for debugging or to
extract information from templates.
+
+ If you are :ref:`developing Jinja2 extensions <writing-extensions>`
+ this gives you a good overview of the node tree generated.
"""
try:
return Parser(self, source, filename).parse()
from jinja2.environment import get_spontaneous_environment
from jinja2.runtime import Undefined, concat
from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
-from jinja2.utils import import_string, Markup
+from jinja2.utils import contextfunction, import_string, Markup
# the only real useful gettext functions for a Jinja template. Note
)
-class TransExtension(Extension):
+class InternationalizationExtension(Extension):
"""This extension adds gettext support to Jinja."""
tags = set(['trans'])
def __init__(self, environment):
Extension.__init__(self, environment)
environment.globals.update({
- '_': lambda x: x,
+ '_': contextfunction(lambda c, x: c['gettext'](x)),
'gettext': lambda x: x,
'ngettext': lambda s, p, n: (s, p)[n != 1]
})
if not extension:
continue
extension = import_string(extension)
- if extension is TransExtension:
+ if extension is InternationalizationExtension:
have_trans_extension = True
extensions.append(extension)
if not have_trans_extension:
- extensions.append(TransExtension)
+ extensions.append(InternationalizationExtension)
environment = get_spontaneous_environment(
options.get('block_start_string', '{%'),
node = environment.parse(fileobj.read().decode(encoding))
for lineno, func, message in extract_from_ast(node, keywords):
yield lineno, func, message, []
+
+
+#: nicer import names
+i18n = InternationalizationExtension
+cache = CacheExtension
i18n_env = Environment(
loader=DictLoader(templates),
- extensions=['jinja2.ext.TransExtension']
+ extensions=['jinja2.ext.i18n']
)
i18n_env.globals.update({
'_': gettext,