Localization & i18n

Internationalization in MintJams CMS has two layers. It supports English (en) and Japanese (ja) today, and is designed so that adding a locale is "drop in one JSON file".

Layer What it controls Source of truth
Localization preference locale, time zone, number format, currency per user (Preferences → Localization)
Message bundles the translated strings /etc/i18n/<locale>.json in JCR

Message bundles

Flat JSON files at JCR /etc/i18n/. The locale is the last dot-delimited segment of the file name (before .json).

/etc/i18n/en.json                  → locale "en"  (core: common.* / webtop.* / cms.*)
/etc/i18n/ja.json                  → locale "ja"
/etc/i18n/content-browser.en.json  → locale "en"  (an app's bundle)
/etc/i18n/content-browser.ja.json  → locale "ja"
/etc/i18n/commerce.ja.json         → locale "ja"  (an add-on module)

Files for the same locale are merged. Each unit (core, each app, add-ons) contributes keys in its own namespace, so you add things without editing another file. At runtime, edits under /etc/i18n/ are hot-reloaded and every app repaints.

Key namespaces

Prefix Owner Example
common.* shared UI primitives common.save
webtop.* the shell (desktop, menus, windows) webtop.startMenu.signOut
app.<appId>.* an individual app app.preferences.localization.title
cms.* cross-cutting platform messages (validation, errors) cms.validation.string.tooLong

An app's display title is localized under app.<appId>.title (falling back to title in app.yml).

Message format

Bundles are formatted with intl-messageformat, so values can use ICU placeholders, plurals and select.

"cms.validation.string.tooLong": "Value is too long (max {max} chars)",
"app.tasks.count": "{count, plural, =0 {No tasks} one {# task} other {# tasks}}"

Authoring rules

  • Keep keys in sync across locales (en is the ultimate fallback; a key missing from en is a bug)
  • Never concatenate translated fragments (word order differs by language); put one sentence in one key with placeholders
  • Don't put user data in keys (keys are identifiers)

Localization preferences

Users set the following in Preferences → Localization; changes apply live across all apps.

  • Language — display language for Webtop and apps
  • Time zone — for date and time display
  • Number format — locale for numbers, dates and lists
  • Currency — default currency for monetary values

Each can be "Auto"; when empty it falls back to the system/browser default (resolution order: exact → language-only → en).

Adding a locale

For each existing unit (core and each <appId>), drop in a <locale>.json with the same key set. No code change is needed: the loader derives the locale from the file name, and the Preferences language list is populated from the available bundles.

Using formatting (for developers)

Apps format values with shared helpers that follow the user's effective locale, time zone and currency.

import { formatNumber, formatCurrency, formatDate } from "../../composables/use-localization.js";