graphdb-workbench

Internationalization (i18n)

How per-module translation files are merged into a single bundle per language, and how translations are added and validated.

Contents

How It Works

Translations from different packages are merged into a single bundle per language by merge-i18n-plugin.js, which writes them to dist/assets/i18n/. That includes language-config.json, which contains the default language, the translation bundle version and the available languages.

At startup, language-bootstrap.ts loads the language configuration, selects the stored language (or the default one), and loads the default bundle into LanguageContextService (updateDefaultBundle, updateLanguageBundle). It then listens to onSelectedLanguageChanged; when the language changes, it loads that bundle and emits it through updateLanguageBundle.

Packages listen for bundle changes with LanguageContextService#onLanguageBundleChanged and apply translations independently. The Angular workbench feeds them to Transloco (see frontend-angular).

Legacy workbench translations

packages/legacy-workbench keeps its own translations in src/i18n/locale-en.json / locale-fr.json, with the language list in src/i18n/languages.json. They are not merged by the plugin; the legacy app loads them through angular-translate (i18n/locale-<lang>.json). The validator still checks them together with the other packages.

Translation File Structure

Every other package places its translation files under src/assets/i18n:

packages/
  root-config/
    src/assets/i18n/en.json
    src/assets/i18n/fr.json
  workbench/
    src/assets/i18n/en.json
    src/assets/i18n/fr.json

Translation files are JSON objects where the keys are the translation identifiers and the values are the translated strings:

src/assets/i18n/en.json:

{
  "greeting": "Hello",
  "farewell": {
    "label": "Goodbye"
  }
}

Bundling Translations

The merge plugin aggregates these files across all packages and merges them into a single bundle for each language. For example, packages/root-config/src/assets/i18n/en.json and packages/workbench/src/assets/i18n/en.json are combined into one dist/assets/i18n/en.json.

Conflicts

The plugin throws an error if multiple files define the same key for the same language. For example:
module1/src/assets/i18n/en.json

{
  "some-prop": "Hello",
  "menu.logo.link.title": {
    "label": "Goodbye"
  }
}

module2/src/assets/i18n/en.json:

{
  "another-prop": "Bonjour",
  "menu.logo.link.title": {
    "another-label": "Different Goodbye"
  }
}

Will result in an error, similar to this one:

Error: Conflict detected for key 'menu.logo.link.title' in file: packages/workbench/src/assets/i18n/en.json

Key Features

Plugin Options

Webpack Configuration

From webpack.config.common.js:

const {MergeI18nPlugin} = require('./webpack/merge-i18n-plugin.js');

new MergeI18nPlugin({
  startDirectory: './packages',
  outputDirectory: 'assets/i18n',
  replaceVersion
});

How to Add a New Language

  1. Add the language to the availableLanguages array in language-config.json.
  2. Add a translation file for it in every src/assets/i18n folder that has translations. The key in availableLanguages is the file name: ${key}.json. Avoid conflicting keys.
  3. For the legacy workbench, add src/i18n/locale-${key}.json and the language to src/i18n/languages.json.
  4. Build the application.
  5. Check the merged output in dist/assets/i18n to verify that all translations are included.

Translation Validation

To validate translations locally:

npm run validate

This runs the validate script of packages/root-config and of packages/legacy-workbench. The root-config script reads the translations of every package, legacy locale-xx.json files included, and reports missing and untranslated keys, placeholder or HTML-tag differences between languages, and keys defined in more than one package.

If the project structure differs, provide the project root manually:

SCRIPT_ROOT=/absolute/path/to/repo-root npm run validate

The root-config script writes a translation-report.json file and exits with code 1 if issues are found.

Running in Translation Validation CI

On Jenkins, the script runs automatically in the Validate stage.

If issues are found:

Look for translation-report.json under “Build Artifacts”.


See also: Developers Guide