Translations in the backend refer to both the backend code itself as well as server-side rendered templates. For the backend code, the functions offered by Babel can be used, namely gettext (usually imported as _), lazy_gettext (usually imported as _l) and ngettext (for dealing with plurals). Babel is integrated via the Flask extension Flask-Babel.

from flask_babel import gettext as _
my_string = _("foo")

For server-side rendered templates using Jinja, the usual gettext/_ function can also be used. Additionally, there is the following special directive provided by the i18n Jinja extension:

{% trans %}foo{% endtrans %}


Note that care should be taken when including dynamic values in the translations, as all strings are automatically marked as safe, i.e. any HTML will not be escaped.

After marking all translatable strings accordingly, the following command can be used to update all message catalog files found in the kadi/translations directory:

kadi i18n update

After translating all strings, the following command can be used to compile the message catalogs for use in the application:

kadi i18n compile

Note that a manual restart of the development server might be required to reload the compiled message catalogs.


The i18n subcommands of the Kadi CLI can also be used to add new languages to the backend translations and for managing backend translations provided by plugins via the -p flag supported by most subcommands.


Translations in the frontend refer to both frontend code itself as well as client-side rendered templates and components. For all frontend translations, the i18next library is used, which requires translations in JSON format. The existing translations can be found inside kadi/assets/translations.

Currently, the frontend translations use the key fallback feature that i18next supports, i.e. all translations of the default language use the translation keys for the actual translation value, with the values themselves being empty. While this offers less flexibility in terms of the features that i18next provides, e.g. dealing with plurals, it allows for more consistency with the backend translations. For all translations in JavaScript files and Vue.js components, the $t function can be used:

$t('Are you sure you want to delete {{title}}?', {title: 'foo'})

Another thing that the key fallback allows is to automatically extract all translatable strings using the i18next-scanner utility, which uses the configuration as specified in i18next-scanner.config.js. The tool can be used by running the i18n script exposed by the npm command. Note that npm needs access to the package.json file, see also Managing frontend dependencies.

npm run i18n

The extracted translations are bundled together with all other frontend code as usual. See also writing frontend code.


When adding a new language, there are a few other places that need adjustments, namely some used libraries for date handling that may require additional imports to fully support the language in regards to the corresponding localization format.