Localization
Every UI string in the DMS can be a $-prefixed i18n key instead of literal text. The mechanics below explain how resolution, namespaces, and locale files fit together.
The $-key convention
A label that starts with $ is an i18n key; anything else is literal text. The $ is a runtime sentinel only — the key in the JSON file does not include it.
// backend page/permission/DataType metadata
displayName: "$page.tasks.title"; // resolves to t("page.tasks.title")
displayName: "Tasks"; // literal — passes through unchanged
The frontend resolves it through useTranslation().processI18n, which strips the $ and calls @nuxtjs/i18n's t().
Namespaces
Every namespace maps to a top-level object in the locale JSON (without the $). Two rules keep layers from stepping on each other:
- The base layers own the shared namespaces —
$cms.*,$common.*,$page.*,$menu.*,$error.*, and so on. Because locales merge across layers, adding a key under one of these is possible — do it deliberately, never by accident. - Your module or project takes a namespace of its own: the maintained modules use
cms_<name>(e.g.$cms_automation.title); a project does the same (e.g.$my_app.report.perm.regenerate).
Error keys live in the shared error.* namespace (see Error feedback for how backend messages reach it).
Ship your locales
Your layer declares its languages in the i18n.locales array of its nuxt.config.ts: each entry pairs a code (en, fr) with a locale file, conventionally named <layer>-<locale>.json. Entries with the same code merge across layers at build time — that is how every layer contributes to the same language, and why a namespace can receive keys from several layers. The DMS base layers ship en and fr; your layer joins them by declaring the same codes with its own files.
{
"my_app": {
"report": {
"title": "Reports",
"perm": { "regenerate": "Regenerate the report" }
}
}
}
Reference a key as "$my_app.report.title" in backend metadata, or t("my_app.report.title") in a Vue template. When a key must exist in several files (one per language), grep a neighboring key to find them all quickly.
Backend services
Cross-cutting DMS services a module can use — hooks, notifications, realtime publishing, job locks, HTML rendering, and the export-job engine.
Frontend layer
Author a custom Nuxt layer and understand the machine that loads it — component naming, overrides, layer config in Vue, the .acms cache, and the catch-all renderer.