Localize a plugin's interface
Add Russian and English translations to a BDEngine plugin without conflicting with other extensions.
Let’s add Russian and English text to a button and a window. The plugin registers
its dictionaries through editorAPI.registerTranslations() and reads strings with
the global gT() function. The editor user selects the language.
Before starting, choose a unique plugin namespace. Download the complete translations.js example. After installation, click the language icon in the toolbar.
Choose a namespace
We’ll use the namespace my-plugin and the simple keys title and message.
Registration turns them into my-plugin.title and my-plugin.message.
This prefix separates the plugin’s strings from the editor and other extensions.
A key that already contains a dot is treated as a full key. For example,
window.title stays window.title; it does not become my-plugin.window.title.
To organize keys into groups, supply the full key my-plugin.window.title yourself
or use simple keys such as windowTitle.
Using the file’s @namespace for the dictionary is convenient, but the namespace
is passed as a separate argument. It is not a model’s game tag or an export ID.
Register dictionaries
const namespace = 'my-plugin';const result = window.editorAPI.registerTranslations(namespace, { 'ru-RU': { title: 'Моё окно', message: 'Плагин готов к работе.', }, 'en-US': { title: 'My window', message: 'The plugin is ready.', },});
console.log(result); // {ok: true, added: 4, conflicts: 0} for these four entries.Outer keys identify languages; each inner dictionary is flat and contains strings.
Do not pass a nested object such as window: {title: ...}. ru-RU and en-US are
enough for this example; the editor also normalizes supported aliases such as ru
and en.
Register translations before creating the interface. Existing core strings and
strings owned by another namespace are protected from overwriting. Conflicting keys
are skipped and increase conflicts. Registering your own keys again with the same
namespace updates their values. added counts dictionary entries across languages,
not just unique key names.
ok: true means the call passed its overall validation, but does not guarantee that
every entry was accepted. Invalid languages, dictionaries, or values may be skipped
with a console warning. Check added, conflicts, and the contents of your dictionaries.
For return values and normalization, see the registerTranslations contract.
Use gT
gT accepts a full key, a fallback string, and optional translation parameters:
const t = (key, fallback) => window.gT(`my-plugin.${key}`, fallback);
const button = window.editorAPI.addButtonTool('icon-languages', () => { const panel = window.editorAPI.createWindow( t('title', 'My window'), 'my-plugin.window', 'icon-languages', 520, 300, 320, 220 ); const message = document.createElement('p'); message.textContent = t('message', 'The plugin is ready.'); panel.container.append(message);});button.title = t('title', 'My window');button.setAttribute('aria-label', button.title);If a string is missing in the current language, the editor first uses the English
en-US dictionary. If no matching translation is found, gT returns the supplied
fallback; without one, it returns the key itself. A fallback is not an automatic
translation.
Use textContent for text in your own DOM, as in the example. The complete downloadable
file also avoids creating a second window on repeated clicks: it focuses the existing
one. To test fallback behavior, it deliberately requests the missing key
bde.docs.translations.missing with an English fallback string.
For buttons and windows, see the interface reference.
Check languages and missing translations
- Install the example and open its window with the editor set to Russian. The title and main message should be Russian; the last line shows the intentional fallback.
- Switch the editor language to English. The current language-switching implementation reloads the editor; after loading, the installed plugin registers its dictionaries again.
- Reopen the window and check the English strings and button label.
- To test language fallback in your own copy, remove only the Russian
messagevalue, keeping the English one. The English string should appear in the Russian locale. Then remove the key from both dictionaries and check the fallback argument passed togT. - Check that
conflictsis zero. If it is not, correct the full keys or choose your own namespace rather than trying to overwrite someone else’s dictionary.
Created DOM nodes are not automatically linked to keys: gT() returns a string
at the time of the call. Updating dictionaries does not change previously assigned
textContent. If you need that behavior, the plugin must read and assign the string again.
There is currently no public method for removing a registered dictionary. The complete
example removes its button and window when run again through its own dispose()
function. This is the example’s own convention, not an automatic editor lifecycle.
Deleting the plugin and reloading ends its use together with the current dictionaries.
Dictionary structure, fallback order, and language switching were checked against
publicFunctions.js, Locale.js, and localeConfig.js. Plugin authors provide
translations for any additional languages themselves.