Language Support internals
Overview
Runtime language switching for the bpmn-js / dmn-js modeler UI is implemented as a standalone library (libs/bpmn-i18n/) exposing a bpmn-js DI module (TranslateModule) and a translation service (CustomTranslator). The extension host pushes the active locale; the webview re-imports the current diagram to force bpmn-js to re-evaluate every translate() call.
See the user-facing Language Support page for the list of supported locales and how to switch at runtime.
System overview
| Component | Role |
|---|---|
libs/bpmn-i18n/ | Translation library — dictionaries, CustomTranslator, TranslateModule |
libs/bpmn-i18n/src/languages/{locale}/ | Per-locale dictionary files (bpmn-js, dmn-js, properties-panel, other) |
apps/vscode-plugin/src/shared/infrastructure/VsCodeSettings.ts | Reads the miragon.bpmnModeler.language setting |
apps/bpmn-webview/src/main.ts | Handles LanguageQuery, triggers refreshDiagram() |
CustomTranslator looks up UI strings in per-locale dictionaries and supports {param} placeholder substitution (e.g. "Append {type}" → "Ajouter {type}"). The active locale is switched at runtime via setLanguage(locale).
TranslateModule registers CustomTranslator as an __init__ service and exposes it under the customTranslator and translate DI keys.
Entry points
- Host side —
SettingsParticipantsubscribesBpmnSettingsBroadcasterfor each opened BPMN editor. The broadcaster watches configuration changes formiragon.bpmnModeler.languageand pushes aLanguageQueryto that webview via its ownsetLanguage(). The initial locale is pushed when the webview requests settings on load (GetBpmnModelerSettingCommand). - Webview side —
apps/bpmn-webview/src/main.tshandlesLanguageQuery, callsCustomTranslator.setLanguage(locale), and triggersrefreshDiagram().
Key files
| File | Purpose |
|---|---|
libs/bpmn-i18n/src/TranslateModule.ts | CustomTranslator class and DI module |
libs/bpmn-i18n/src/languages/index.ts | Locale registry, supportedLanguages array, dictionaries map |
libs/bpmn-i18n/src/languages/{locale}/ | Per-locale translation dictionaries (four files each) |
libs/shared/src/lib/modeler.ts | LanguageQuery message type |
apps/vscode-plugin/package.json | Setting and command definitions |
apps/vscode-plugin/src/shared/infrastructure/VsCodeSettings.ts | getLanguage() setting reader |
apps/vscode-plugin/src/modeler/bpmn/controller/editor-participants/SettingsParticipant.ts | Subscribes the settings broadcaster per opened BPMN editor |
apps/vscode-plugin/src/modeler/bpmn/service/BpmnSettingsBroadcaster.ts | Watches the language setting; setLanguage() sends LanguageQuery to the webview |
apps/vscode-plugin/src/modeler/bpmn/controller/CommandController.ts | changeLanguage command handler (QuickPick) |
apps/bpmn-webview/src/main.ts | LanguageQuery handler, refreshDiagram() |
apps/bpmn-webview/src/app/modeler.ts | BpmnModeler.create() accepts TranslateModule |
Message protocol
| Message | Direction | Payload |
|---|---|---|
LanguageQuery | host → webview | { locale: SupportedLocale } |
There is no webview → host message — the host always pushes the current locale.
Interaction flow
Dictionary structure
Each locale has its own directory under libs/bpmn-i18n/src/languages/{locale}/ with four translation files:
| File | Scope |
|---|---|
bpmn-js.ts | bpmn-js modeler UI (palette, context pad, labels) |
dmn-js.ts | dmn-js modeler UI |
properties-panel.ts | Properties panel labels and descriptions |
other.ts | Miscellaneous UI strings |
Each file exports a Record<string, string> mapping English source text to translated text. The locale's index.ts merges all four into a single dictionary. All dictionaries are cached in a dictionaries map for fast lookup.
Adding a new language
- Create a new directory under
libs/bpmn-i18n/src/languages/{locale}/with the four translation files. Copy an existing locale (e.g.en/) as a template. - Export the merged dictionary from
libs/bpmn-i18n/src/languages/{locale}/index.ts. - Register the new locale in
libs/bpmn-i18n/src/languages/index.ts:- Add it to the
SupportedLocaleunion type. - Add an entry to the
supportedLanguagesarray with the locale code and display label. - Add it to the
dictionariesmap.
- Add it to the
- Add the locale to the
enumandenumItemLabelsarrays inapps/vscode-plugin/package.jsonunder themiragon.bpmnModeler.languagesetting definition.
Gotchas
- Diagram re-import is required on language change. Already-rendered UI elements (palette entries, context pad items) retain their original text — re-importing forces bpmn-js to call
translate()again for every label. - Four files per locale, four places to register. If you add a string to
bpmn-js.tsfor one locale and forget the others, that string falls through to the English source (the identity mapping) — silent divergence. - Viewport must be saved and restored around the re-import, otherwise the user is scrolled back to the diagram origin on every language change.
Related
- bpmn-js
Translate— the upstream contractCustomTranslatorimplements - Architecture overview — DI module + message contract primer