Skip to content

Internationalization

formulon-cell ships with en and ja dictionaries. Locale is changed at runtime — labels update in place without remounting. Hosts can extend a bundled dictionary or register new ones.

Glossary: i18n controller

The runtime controller exposed on SpreadsheetInstance.i18n. It owns the active locale, the dictionary registry, and notifies the store on changes so the chrome can re-render.

Swap locale at runtime

ts
const instance = await Spreadsheet.mount(host, { workbook, locale: 'en' })

instance.i18n.setLocale('ja')

The localeChange event fires after the swap, so host status bars or persistence layers can sync.

Override entries without forking

i18n.extend(locale, partialDictionary) merges your overrides on top of the existing dictionary:

ts
instance.i18n.extend('ja', {
  contextMenu: {
    copy: 'コピーする'
  }
})

The override is scoped to the running instance; the package's built-in dictionary stays untouched.

Register a new locale

ts
import fr from './locales/fr.js'

instance.i18n.register('fr', fr)
instance.i18n.setLocale('fr')

Locale objects are plain JavaScript values shaped like the bundled dictionaries. A trimmed example:

ts
export default {
  meta: { locale: 'fr', label: 'Français' },
  contextMenu: {
    copy: 'Copier',
    paste: 'Coller',
    pasteSpecial: 'Collage spécial…',
    cut: 'Couper'
  },
  toolbar: {
    bold: 'Gras',
    italic: 'Italique',
    underline: 'Souligner'
  },
  // ...more sections
}

Hosts can ship dictionaries as static JSON, async-load them, or generate them from a translation pipeline.

Reading the dictionary

Host chrome and extensions can read the active dictionary through the controller:

ts
const label = instance.i18n.t('contextMenu.copy')

The same t() is what built-in chrome calls internally. Missing keys fall back to the bundled English dictionary so the UI never shows raw keys.

Locale and engine compatibility profile are separate

Engine locale behavior (date parsing, currency, list separators) is driven by the Excel compatibility profile, not the UI's i18n.setLocale. Switching the UI to French does not change formula evaluation results. See Locale profiles for the engine side.

Persisting the user's choice

Subscribe to localeChange and persist the locale yourself — the package does not write to localStorage:

ts
instance.on('localeChange', ({ locale }) => {
  localStorage.setItem('cell.locale', locale)
})

Restore on next mount:

ts
const saved = localStorage.getItem('cell.locale') ?? 'en'
const instance = await Spreadsheet.mount(host, { workbook, locale: saved })