Skip to content

Internationalization (i18n)

notectl ships with built-in support for 8 languages. All user-facing strings in the toolbar, context menus, announcements, and ARIA labels are fully localizable.

LocaleLanguageConstant
enEnglishLocale.EN
deGermanLocale.DE
esSpanishLocale.ES
frFrenchLocale.FR
zhChinese (Simplified)Locale.ZH
ruRussianLocale.RU
arArabicLocale.AR
hiHindiLocale.HI
browserAuto-detectLocale.BROWSER

Set the editor language via the locale config option. All plugins automatically resolve their strings from this setting.

import { createEditor, Locale } from '@notectl/core';
const editor = await createEditor({
locale: Locale.DE,
toolbar: [/* ... */],
});

When set to Locale.BROWSER (the default), the editor detects the language from navigator.language and uses the best available match. If the detected language has no translation, it falls back to English.

<!-- Not yet supported as HTML attribute — use the config option -->

Every plugin that renders user-facing text accepts an optional locale config parameter. This allows overriding the global locale for a specific plugin.

import {
createEditor,
Locale,
TablePlugin,
TABLE_LOCALE_FR,
} from '@notectl/core';
// Editor in German, but table plugin in French
const editor = await createEditor({
locale: Locale.DE,
toolbar: [
[new TablePlugin({ locale: TABLE_LOCALE_FR })],
],
});

Plugins resolve their locale in this order:

  1. Per-plugin config override — if provided in the plugin constructor, it wins
  2. Global LocaleService — reads the editor’s locale setting
  3. English fallback — if no translation exists for the resolved language

This is handled internally by the resolvePluginLocale() helper:

import { resolvePluginLocale } from '@notectl/core';
// Inside a plugin's init():
const locale = resolvePluginLocale(MY_LOCALES, context, this.config.locale);

Every plugin exports its locale type, default English locale, and a locale map with all translations. The naming pattern is consistent:

PluginLocale TypeDefaultMap
Text FormattingTextFormattingLocaleTEXT_FORMATTING_LOCALE_ENTEXT_FORMATTING_LOCALES
HeadingHeadingLocaleHEADING_LOCALE_ENHEADING_LOCALES
ListListLocaleLIST_LOCALE_ENLIST_LOCALES
LinkLinkLocaleLINK_LOCALE_ENLINK_LOCALES
TableTableLocaleTABLE_LOCALE_ENTABLE_LOCALES
Code BlockCodeBlockLocaleCODE_BLOCK_LOCALE_ENCODE_BLOCK_LOCALES
BlockquoteBlockquoteLocaleBLOCKQUOTE_LOCALE_ENBLOCKQUOTE_LOCALES
ImageImageLocaleIMAGE_LOCALE_ENIMAGE_LOCALES
FontFontLocaleFONT_LOCALE_ENFONT_LOCALES
Font SizeFontSizeLocaleFONT_SIZE_LOCALE_ENFONT_SIZE_LOCALES
Text ColorTextColorLocaleTEXT_COLOR_LOCALE_ENTEXT_COLOR_LOCALES
AlignmentAlignmentLocaleALIGNMENT_LOCALE_ENALIGNMENT_LOCALES
StrikethroughStrikethroughLocaleSTRIKETHROUGH_LOCALE_ENSTRIKETHROUGH_LOCALES
Superscript / SubscriptSuperSubLocaleSUPER_SUB_LOCALE_ENSUPER_SUB_LOCALES
HighlightHighlightLocaleHIGHLIGHT_LOCALE_ENHIGHLIGHT_LOCALES
Horizontal RuleHorizontalRuleLocaleHORIZONTAL_RULE_LOCALE_ENHORIZONTAL_RULE_LOCALES
PrintPrintLocalePRINT_LOCALE_ENPRINT_LOCALES
ToolbarToolbarLocaleTOOLBAR_LOCALE_ENTOOLBAR_LOCALES

All exports are available from @notectl/core:

import {
TABLE_LOCALE_EN,
TABLE_LOCALE_DE,
TABLE_LOCALE_ES,
TABLE_LOCALE_FR,
TABLE_LOCALE_ZH,
TABLE_LOCALE_RU,
TABLE_LOCALE_AR,
TABLE_LOCALE_HI,
TABLE_LOCALES,
} from '@notectl/core';

You can provide a fully custom locale by implementing the plugin’s locale interface:

import type { TableLocale } from '@notectl/core';
const myTableLocale: TableLocale = {
insertRowAbove: 'Add row above',
insertRowBelow: 'Add row below',
insertColumnLeft: 'Add column left',
insertColumnRight: 'Add column right',
deleteRow: 'Remove row',
deleteColumn: 'Remove column',
borderColorLabel: 'Border color...',
deleteTable: 'Remove table',
tableActions: 'Table actions',
menuKeyboardHint: 'Arrows to navigate, Enter to select, Esc to close',
insertRow: 'Insert row',
insertColumn: 'Insert column',
addRow: 'Add row',
addColumn: 'Add column',
tableActionsHint: 'Table actions (Right-click or Shift+F10)',
contextMenuHint: 'Right-click or Shift+F10 for table actions',
borderColor: 'Border color',
defaultColor: 'Default',
noBorders: 'No borders',
borderColorPicker: 'Border color picker',
announceBorderColorSet: (name) => `Border color set to ${name}`,
announceBorderReset: 'Borders reset to default',
borderSwatchLabel: (name) => `Border ${name}`,
announceRowInsertedAbove: 'Row added above',
announceRowInsertedBelow: 'Row added below',
announceColumnInserted: (side) => `Column added ${side}`,
announceRowDeleted: 'Row removed',
announceColumnDeleted: 'Column removed',
announceTableDeleted: 'Table removed',
insertTable: 'Insert Table',
tableAriaLabel: (rows, cols) => `Table: ${rows} rows, ${cols} columns`,
tableAriaDescription: 'Right-click or Shift+F10 for actions',
};
new TablePlugin({ locale: myTableLocale });
ExportKindDescription
LocaleConst objectEN, DE, ES, FR, ZH, RU, AR, HI, BROWSER
LocaleServiceClassResolves the active language from config
LocaleServiceKeyServiceKeyService key for accessing LocaleService
resolvePluginLocale()FunctionHelper for plugins to resolve their locale