Skip to content
FrameworkJavaScript

i18n API: translate Blok's interface

Internationalization support for translating UI strings, plus the runtime `i18n.update()` mutator that switches language in place. The locale catalogue itself ships as a separate published entry point, `@bloklabs/core/locales`: only English is bundled, the other 68 locales load on demand, and `normalizeLocale()` is the pre-flight check for a locale you did not hard-code — `i18n.update({ locale })` with an unsupported tag keeps the current locale and warns on the console instead of throwing.

Reaching the editor instance

The methods below run on the editor you created with new Blok(). They are available once editor.isReady resolves.

TypeScript
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;

// Call any API method on it.
editor.caret.setToLastBlock('end');

Methods

i18n.t(dictKey, vars?)

string

Translate a key from the global dictionary, optionally interpolating string or number values.

When to use

Look up a UI string from the active dictionary inside a tool, so your tool localises with the editor.

TypeScript
const text = editor.i18n.t('toolNames.text');
console.log(text); // 'Text' (or translated string)

const limit = editor.i18n.t('tools.image.emptyMaxSize', { size: '10 MB' });
console.log(limit); // 'max 10 MB' (or translated string)

i18n.has(dictKey)

boolean

Check if a translation exists for the given key.

When to use

Check a key exists before translating, to fall back gracefully when a tool ships partial dictionaries.

TypeScript
if (editor.i18n.has('toolNames.text')) {
  const translation = editor.i18n.t('toolNames.text');
}

i18n.getEnglishTranslation(key)

string

Get the English translation for a key (used for multilingual search).

When to use

Returns the English value regardless of locale — used to index content for multilingual search.

TypeScript
const english = editor.i18n.getEnglishTranslation('toolNames.heading');
console.log(english); // 'Heading'

i18n.getLocale()

string

Get the active locale code (e.g. 'en').

When to use

Returns the active locale code (e.g. 'en') so a tool can branch on the editor's current language.

TypeScript
const locale = editor.i18n.getLocale();
console.log(locale); // 'en'

i18n.getDirection()

'ltr' | 'rtl'

Get the text direction currently in effect — derived from the active locale unless an explicit `direction` override was set. Editor instance only: the `api.i18n` handed to tools carries just `t`, `has`, `getEnglishTranslation` and `getLocale`, so a tool must take the direction from the host (its own config, or the `i18n:changed` event) rather than calling this.

When to use

Returns 'ltr' or 'rtl' for the active locale, so host chrome around the editor can mirror itself alongside it.

TypeScript
if (editor.i18n.getDirection() === 'rtl') {
  // mirror your own chrome next to the editor
}

i18n.update({ locale?, messages?, direction? })

Promise<void>

Switch language at runtime. `config.i18n` is otherwise read once during boot, so a host with a language switcher had to recreate the editor to relabel it — losing caret, focus, selection and undo history. `update()` relabels in place instead: no recreation, nothing lost. `locale` accepts any supported code or `'auto'` to re-run browser detection; `messages` merges host overrides over the locale dictionary and is re-applied automatically after every later locale change (a bare locale flip never silently drops your custom strings); `direction` overrides the direction implied by the locale, which you normally do not need. Calls are serialized internally, so lazily-loaded locale chunks cannot land out of order — the last call wins. Scope: everything. Chrome built on demand (block settings, the convert menu, notifications, screen-reader announcements) picks up the new locale the next time it opens; the eagerly-stamped chrome (toolbar and plus-button labels, tooltips, the toolbox list) is relabelled immediately; and block content — placeholders, media-toolbar labels, cell controls, anything a tool resolved while rendering — is repainted from your data, including tools that know nothing about locale changes. The repaint is invisible to you: `onChange` does not fire, scroll is kept, and the caret returns to the block that had it. Fires the `i18n:changed` event with `{ locale, direction }`. Available synchronously after construction — a call made before `isReady` is applied once the editor has booted. `update()` and `getDirection()` are exposed on the editor instance only, not on the `api.i18n` handed to tools (which carries just `t`, `has`, `getEnglishTranslation` and `getLocale`), so a third-party tool cannot flip the host's locale. The React/Vue/Angular adapters drive it reactively: change the `i18n` prop/input and the editor follows in place. Note `defaultLocale` is not accepted — it only decides the fallback while resolving the initial locale.

When to use

Switches locale and host message overrides at runtime, relabelling the editor in place — a language switcher no longer has to recreate the editor and throw away caret, focus and undo history.

TypeScript
// Host language switcher — no remount, caret and undo survive.
await editor.i18n.update({ locale: 'ru' });

// Locale plus your own overrides on top of it.
await editor.i18n.update({
  locale: 'fr',
  messages: { 'toolNames.text': 'Paragraphe' },
});

// Follow the browser again.
await editor.i18n.update({ locale: 'auto' });

editor.events.on('i18n:changed', ({ locale, direction }) => {
  document.documentElement.dir = direction;
});

normalizeLocale(tag)

SupportedLocale | null

From `@bloklabs/core/locales`. Normalizes an arbitrary BCP-47 language tag — region-tagged (`'en-US'`), script-tagged (`'zh-Hant'`) or aliased (`'nb'` → `'no'`, `'ckb'` → `'ku'`) — to a supported Blok locale, and returns `null` when the tag is unsupported. The same normalizer runs on browser detection and on explicit `config.i18n.locale` / `i18n.update({ locale })`, so a `null` here is exactly the tag that `update()` would refuse: it keeps the current locale and warns on the console rather than throwing.

TypeScript
import { normalizeLocale } from '@bloklabs/core/locales';

// 'en-US' -> 'en'; null when the tag is not supported
const code = normalizeLocale(navigator.language);

if (code !== null) {
  await editor.i18n.update({ locale: code });
}

loadLocale(code)

Promise<LocaleConfig>

From `@bloklabs/core/locales`. Loads one locale on demand. Only English is bundled — the other 68 are fetched when asked for.

TypeScript
import { loadLocale } from '@bloklabs/core/locales';

const fr = await loadLocale('fr');

preloadLocales(codes)

Promise<void>

From `@bloklabs/core/locales`. Loads several locales up front — e.g. the ones your language switcher offers — so a later switch does not wait on a fetch.

TypeScript
import { preloadLocales } from '@bloklabs/core/locales';

await preloadLocales(['fr', 'de', 'ru']);

buildRegistry(codes)

Promise<LocaleRegistry>

From `@bloklabs/core/locales`. Loads the given codes and returns them together as a `LocaleRegistry`.

TypeScript
import { buildRegistry } from '@bloklabs/core/locales';

const registry = await buildRegistry(['en', 'ru']);

getLocaleSync(code)

LocaleConfig | undefined

From `@bloklabs/core/locales`. Returns an already-loaded locale synchronously, or `undefined` when it has not been loaded yet.

TypeScript
import { getLocaleSync, loadLocale } from '@bloklabs/core/locales';

const ru = getLocaleSync('ru') ?? await loadLocale('ru');

getDirection(code)

'ltr' | 'rtl'

From `@bloklabs/core/locales`. Text direction for a locale CODE. Not the same function as `editor.i18n.getDirection()`, which takes no argument and reports the direction the mounted editor is currently using.

TypeScript
import { getDirection } from '@bloklabs/core/locales';

document.documentElement.dir = getDirection('ar'); // 'rtl'

Properties

PropertyTypeDescription
DEFAULT_LOCALESupportedLocaleFrom `@bloklabs/core/locales`. The default locale code, `'en'`.
ALL_LOCALE_CODESreadonly SupportedLocale[]From `@bloklabs/core/locales`. All 69 supported locale codes — the list to build a language switcher from, or to hand to `preloadLocales`.
enLocaleLocaleConfigFrom `@bloklabs/core/locales`. The English dictionary, the only locale bundled by default and the fallback for missing keys.