Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
201 lines (140 sloc) 6.61 KB

Localizing themes with Jinja2

1. Localize templates

To enable the jinja2.ext.i18n extension in your templates, you must add it to JINJA_EXTENSIONS in your Pelican configuration

JINJA_EXTENSIONS = ['jinja2.ext.i18n', ...]

Then follow the Jinja2 templating documentation for the I18N plugin to make your templates localizable. This usually means surrounding strings with the {% trans %} directive or using gettext() in expressions

{% trans %}translatable content{% endtrans %}
{{ gettext('a translatable string') }}

For pluralization support, etc. consult the documentation.

To enable newstyle gettext calls the I18N_GETTEXT_NEWSTYLE config variable must be set to True (default).

2. Specify translations location

The jinja2.ext.i18n extension uses the Python gettext library for translating strings.

In your Pelican config you can give the path in which to look for translations in the I18N_GETTEXT_LOCALEDIR variable. If not given, it is assumed to be the translations subfolder in the top folder of the theme specified by THEME.

The domain of the translations (the name of each translation file is is controlled by the I18N_GETTEXT_DOMAIN config variable (defaults to messages).


With the following in your Pelican settings file

I18N_GETTEXT_LOCALEDIR = 'some/path/'
I18N_GETTEXT_DOMAIN = 'my_domain'

the translation for language 'cz' will be expected to be in some/path/cz/LC_MESSAGES/

3. Extract translatable strings and translate them

There are many ways to extract translatable strings and create gettext compatible translations. You can create the *.po and *.mo message catalog files yourself, or you can use some helper tool as described in the Python gettext library tutorial.

You of course don't need to provide a translation for the language in which the templates are written which is assumed to be the original DEFAULT_LANG. This can be overridden in the I18N_TEMPLATES_LANG variable.

Recommended tool: babel

Babel makes it easy to extract translatable strings from the localized Jinja2 templates and assists with creating translations as documented in this Jinja2-Babel tutorial [1] on which the following is based.

1. Add babel mapping

Let's assume that you are localizing a theme in themes/my_theme/ and that you use the default settings, i.e. the default domain messages and will put the translations in the translations subdirectory of the theme directory as themes/my_theme/translations/.

It is up to you where to store babel mappings and translation files templates (*.pot), but a convenient place is to put them in themes/my_theme/ and work in that directory. From now on let's assume that it will be our current working directory (CWD).

To tell babel to extract translatable strings from the templates create a mapping file babel.cfg with the following line

[jinja2: templates/**.html]

2. Extract translatable strings from templates

Run the following command to create a messages.pot message catalog template file from extracted translatable strings

pybabel extract --mapping babel.cfg --output messages.pot ./

3. Initialize message catalogs

If you want to translate the template to language lang, run the following command to create a message catalog translations/lang/LC_MESSAGES/messages.po using the template messages.pot

pybabel init --input-file messages.pot --output-dir translations/ --locale lang --domain messages

babel expects lang to be a valid locale identifier, so if e.g. you are translating for language cz but the corresponding locale is cs, you have to use the locale identifier. Nevertheless, the gettext infrastructure should later correctly find the locale for a given language.

4. Fill the message catalogs

The message catalog files format is quite intuitive, it is fully documented in the GNU gettext manual. Essentially, you fill in the msgstr strings

msgid "just a simple string"
msgstr "jenom jednoduchý řetězec"

msgid ""
"some multiline string"
"looks like this"
msgstr ""
"nějaký více řádkový řetězec"
"vypadá takto"

You might also want to remove #,fuzzy flags once the translation is complete and reviewed to show that it can be compiled.

5. Compile the message catalogs

The message catalogs must be compiled into binary format using this command

pybabel compile --directory translations/ --domain messages

This command might complain about "fuzzy" translations, which means you should review the translations and once done, remove the fuzzy flag line.

(6.) Update the catalogs when templates change

If you add any translatable patterns into your templates, you have to update your message catalogs too. First you extract a new message catalog template as described in the 2. step. Then you run the following command [2]

pybabel update --input-file messages.pot --output-dir translations/ --domain messages

This will merge the new patterns with the old ones. Once you review and fill them, you have to recompile them as described in the 5. step.

[1]Although the tutorial is focused on Flask-based web applications, the linked translation tutorial is not Flask-specific.
[2]If you get an error TypeError: must be str, not bytes with Python 3.3, it is likely you are suffering from this bug. Until the fix is released, you can use babel with Python 2.7.