How to make your translations available to your UI built with AngularJS

This guide is kindly provided by Colin Sippl from the University Library of Regensburg.

Problem

The Invenio internationalisation module invenio-i18n provides you with Jinja2 macros and filters for i18N to display translated text in templates. However, translations are not available in the AngularJS app.

Solution

You can use the AngularJS extension angular-gettext to load the translations and make them available in the AngularJS app. The extension adds a new filter translate that can be used in AngularJS templates, for example <p>{{ ('Hello world!' | translate) }}<p>.

The following example will refer to a new Invenio 3.2 installation, with site name my_site.

  1. Create the new language using Python Babel:

pybabel init -i my_site/translations/de/LC_MESSAGES/messages.pot -d my_site/translations -l de

  1. Compile the new language:

pybabel compile -d my_site/translations

  1. Create a new AngularJS translation module inside the AngularJS modules folder, e.g. /my_site/translation.js:
angular.module('mySiteAppTranslations')
    .run(['gettextCatalog', function (gettextCatalog) {
        gettextCatalog.setCurrentLanguage(document.documentElement.lang);
    }]);
  1. Make sure to add this new module as a dependency to your app.js:
 (function (angular) {
   angular.element(document).ready(function() {
     angular.bootstrap(
       document.getElementById("invenio-search-app"), [
         'invenioSearch', 'mySiteAppTranslations'
       ]
     );
   });
 })(angular);
  1. Add the app.js and the translation.js files as well as the angular-gettext NPM dependency to your webpack.py or bundle.py. Don’t forget it to update the Python entry points in the setup.py if this is a new file. Add also AngularGettextFilter to compile GNU gettext messages to angular-gettext module.
"""JS/CSS bundles for theme."""

import os

from flask_assets import Bundle
from invenio_assets import NpmBundle, AngularGettextFilter, GlobBundle
from pkg_resources import resource_filename

# see RERO-ILS https://github.com/rero/rero-ils/blob/10139f87bd4b877d9b4c77829ac2f730fcf0d7a3/rero_ils/bundles.py
# loads translations from messages catalog
def catalog(domain):
    """Return glob matching path to translated messages for a given domain."""
    return os.path.join(
        os.path.abspath(resource_filename('my_site', 'translations')),
        '*',  # language code
        'LC_MESSAGES',
        '{0}.po'.format(domain),
    )

i18n = GlobBundle(
    catalog('messages'),
    filters=AngularGettextFilter(catalog_name='mySiteAppTranslations'),
)

js = NpmBundle(
    i18n,
    Bundle(
        'js/app.js'
    ),
    depends=(
        'js/app.js',
        'js/my_site/*.js'
    ),
    filters='jsmin',
    output="gen/my_site.%(version)s.js",
    npm={
        'angular': '~1.4.9',
        'angular-gettext': '~2.4.1',
    }
)