Usage

Invenio internationalization module.

This module provide features for loading and merging message catalogs. It is built on top of Flask-BabelEx and most external modules should just depend on Flask-BabelEx instead of Invenio-I18N. Only applications in need of loading and merging many message catalogs should integrate this module.

Quick start

First initialize the extension (Flask-BabelEx is also automatically initialized by the extension):

>>> from flask import Flask
>>> from flask_babelex import lazy_gettext as _
>>> app = Flask('myapp')
>>> app.config['I18N_LANGUAGES'] = [('cs', _('Czech')), ('da', _('Danish'))]
>>> from invenio_i18n import InvenioI18N
>>> i18n = InvenioI18N(app)

You can now use the Flask-BabelEx localization features:

>>> from flask_babelex import format_number
>>> with app.test_request_context(headers=[('Accept-Language', 'en')]):
...     format_number(10.1) == '10.1'
True
>>> with app.test_request_context(headers=[('Accept-Language', 'cs')]):
...     format_number(10.1) == '10,1'
True

as well as internationalization features:

>>> from flask_babelex import gettext
>>> with app.test_request_context(headers=[('Accept-Language', 'en')]):
...     gettext('Language:') == 'Language:'
True
>>> with app.test_request_context(headers=[('Accept-Language', 'cs')]):
...     gettext('Language:') == 'Jazyk:'
True

Marking strings for translation

Following is a short overview on how to mark strings in Python code and templates for translation so that they can be automatically extracted:

Python

You specify translations in Python by importing gettext or lazy_gettext from Flask-BabelEx:

>>> from flask_babelex import gettext as _
>>> _('Test') == 'Test'
True

For further details and examples see:

Jinja2

In templates you can use either the underscore function:

>>> from flask import render_template_string
>>> with app.app_context():
...     render_template_string("{{_('Test')}}") == 'Test'
True

or the {% trans %} tag:

>>> with app.app_context():
...     r = render_template_string('{% trans %}Long translation{% endtrans %}')
...     r == 'Long translation'
True

For further details and examples see:

Angular

There is also simple integration for Angular application using Angular-Gettext library. First, you need to mark HTML tags which contain translatable string or expression.

<a href="/" translate>Hello {{name}}</a>

For further details see:

Templates

This section only gives a very quick introduction into custom context variables and filters.

Context

The current_i18n global variable is available within Jinja2 templates to give access to an instance of InvenioI18N attached to current application context.

>>> with app.test_request_context(headers=[('Accept-Language', 'en')]):
...     r = render_template_string('{{ current_i18n.language }}')
...     r == 'en'
True
>>> with app.test_request_context(headers=[('Accept-Language', 'en')]):
...     r = render_template_string('{{ current_i18n.timezone }}')
...     r == 'UTC'
True
>>> with app.test_request_context(headers=[('Accept-Language', 'da')]):
...     r = render_template_string('{{ current_i18n.locale }}')
...     r == 'da'
True

Filters

There are several useful filters automatically added to the Jinja2 template context:

Macros

Invenio-I18N also provides three templates macros that you can use to render a language selector in templates with:

  • language_selector - Renders a list of links and uses GET requests to change the locale.
  • language_selector_form - Same as above, but uses POST requests to change the locale.
  • language_selector_dropdown - Renders a dropdown with languages and uses a POST request to change the locale.

You use the macros by importing one of them from invenio_i18n/macros/language_selector.html, for instance:

>>> with app.test_request_context():
...     r = render_template_string(
...         '{% from "invenio_i18n/macros/language_selector.html"'
...         '   import language_selector %}'
...         '{{ language_selector() }}'
...     )

Working with Message Catalogs

Babel package contains really good documentation which you should read first:

Angular-Gettext

This part focuses on how to configure Babel extraction for Angular application in custom babel-js.ini file:

[angular_gettext: **/static/templates/**/**.html]

To make message extraction and catalog extraction easier you can add following aliases to setup.cfg (replace ${PACKAGE_PATH} with package path):

[aliases]
extract_messages_js = extract_messages -F babel-js.ini -o \
    ${PACKAGE_PATH}/translations/messages-js.pot
init_catalog_js = init_catalog -D messages-js --input-file \
    ${PACKAGE_PATH}/translations/messages-js.pot
update_catalog_js = update_catalog -D messages-js --input-file \
    ${PACKAGE_PATH}/translations/messages-js.pot

Integration with Transifex service

There is a Python package that provides CLI. You can start by installing Transifex package and check if the tx command is available:

$ pip install transifex-client
$ tx --version
0.12.2

The integration is configured in .tx/config file (replace ${PACKAGE_PATH} and ${PACKAGE_NAME}).

[main]
host = https://www.transifex.com

[invenio.${PACKAGE_NAME}-messages]
file_filter = ${PACKAGE_PATH}/translations/<lang>/LC_MESSAGES/messages.po
source_file = ${PACKAGE_PATH}/translations/messages.pot
source_lang = en
type = PO

[invenio.${PACKAGE_NAME}-messages-js]
file_filter = ${PACKAGE_PATH}/translations/<lang>/LC_MESSAGES/messages-js.po
source_file = ${PACKAGE_PATH}/translations/messages-js.pot
source_lang = en
type = PO

1. Create message catalog

Start by extracting localizable messages from a collection of source files.

$ python setup.py extract_messages
$ python setup.py init_catalog -l <lang>

If you have localizable Angular messages run commands with _js suffix too.

$ python setup.py extract_messages_js
$ python setup.py init_catalog_js -l <lang>

2. Transifex project

Ensure project has been created on Transifex under the inveniosoftware organisation.

3. First push

Push source (.pot) and translations (.po) to Transifex.

$ tx push -s -t

Note

From now on do not edit .po files localy, but only on Transifex.

4. Fetch changes

Pull translations for a single/all language(s) from Transifex.

$ tx pull -l <lang>
$ tx pull -a

Check fetched tranlations, commit changes git commit -a -s -m 'i18n: updates from Transifex' and create pull-request.

5. Update message catalog

When new localizable messages are introduced or changes, the message catalog needs to be extracted again. Then you need to push the source files to Transifex service which will take care about updating catalogs. At the end pull translations for all languages from Transifex and commit the changes.

$ python setup.py extract_messages
$ python setup.py extract_messages_js
$ tx push -s
$ tx pull -a