3 minute read

In the frontend (JavaScript) and the backend (CakePHP backend) we use English as base language and wrap strings in translation functions. Those strings are extracted from the code and translated to other languages.

Translation Functions

Backend

In the backend PHP code the __() function marks strings to be translated, for example:

$this->Flash->success(__('The note has been saved.'));

The strings may contain placeholders.

__('The following {0} types are missing: {1}.',
	$missingScope,
	implode(', ',$missing_links)
)

See the I18n CakePHP documentation.

Frontend

In JS files, the strings are translated using the t() function from the lingui package:

import {i18n}  from '/js/lingui.js';

i18n.t('String to be translated')

Generating Translation Files

The translation functions read translation files. For creating those translation files, we use POT and PO files. POT files (Portable Object Template) are text files extracted from the code. They contain the strings to be translated after the msgid key, followed by an empty string with the key msgstr in the next line:

msgid "Hello world"
msgstr ""

Those template files are copied to or merged with PO (Portable Object) files. In the PO files the empty strings after msgstr are replaced by appropriate translations using Poedit (see below). Each language lives in its own file. The following lines are an example from a French PO file:

msgid "Hello world"
msgstr "Bonjour le monde"

POT and PO files follow the GNU Gettext format, We use a structure containing source code references after #:, for example:

#: Model/Entity/Article.php:583
#: Model/Entity/Project.php:230
msgid "Norm data"
msgstr "Normdaten"

MO (Machine Object) files are binary versions that can be created with the msgfmt program. MO files are not currently used by Epigraf.

Extract Translation Templates from Backend Code (PHP)

The strings are automatically extracted from the code to create translation files. For translations on the global application level use:

`bin/cake i18n extract`

The resulting POT files contain the strings to be translated:

  • ressources/locales/default.pot
  • ressources/locales/cake.pot
  • ressources/locales/authenticate.pot

Translation templates for plugin code are created by the same command, and are located in the respective plugin directories under resources/locales/:

bin/cake i18n extract --plugin Epi
bin/cake i18n extract --plugin Files
bin/cake i18n extract --plugin Widgets
bin/cake i18n extract --plugin Rest

Notes for using the extract function:

  • Confirm the path src with Enter and then D
  • No messages from CakePHP core
  • Confirm the path to output with Enter
  • Merge all domain strings: y

Extract Translation Templates from Frontend Code (JavaScript)

Strings to be translated are extracted from JavaScript code with npm, which calls lingui extract:

npm run lingui-extract

This will update the file resources/locales/en_DE/js_messages.po.

Which Javascript files are taken into account is defined in the lingui.config.js file in the include key:

import { formatter } from "@lingui/format-po";

module.exports = {
    locales: ["de_DE"],
    sourceLocale: "en",
    catalogs: [
        {
            path: "resources/locales/{locale}/js_messages",
            exclude: ["plugins/Widgets/webroot/js/*.min.js"],
            include: [
              "plugins/Widgets/webroot/js/*.js",
               "plugins/Epi/webroot/js/*.js"
           ]
        }
    ],
    format: formatter({ explicitIdAsDefault: true })
};

The path key defines the name of the resulting PO file, ready for translations.

Translations with Poedit

For translations, we use the program Poedit. After starting Poedit, select “Edit translation”, navigate to the appropriate location in the repository and select the PO file.

Only PO files are translated, not the templates. If new strings have been extracted from the PHP or JS code, the POT files must be merged into the PO files:

  • Choose “Catalog” -> “Update from POT file”.
  • The new POT file is now automatically compared with the current PO file,

Changes are highlighted in orange.

Backend PO files are to be found in the resources/locales folder. Each plugin in the plugins folder has an own translation file. The frontend PO file is js_messages.po file.

Poedit will automatically list all strings that need to be translated. Work through the list. If you are unsure, you can mark entries for revision in the program. They will be highlighted in orange. The translation is saved by clicking “Save”.

Update Translations

In order for the translations to be displayed, the backend cache needs to be cleared after changes to the translation files:

bin/cake cache clear_all

The frontend translations are loaded from JavaScript files in the htdocs/msg folder. Update the file by the following npm command (which triggers calls to lingui compile and webpack):

npm run lingui-build