Skip to content

Add a language ​

Nine languages ship. A tenth is one command, then the translating.

What ships ​

CodeLanguageIntl tag
enEnglishen-US
arالعربيةar
deDeutschde-DE
esEspañoles-ES
frFrançaisfr-FR
idBahasa Indonesiaid-ID
itItalianoit-IT
ptPortuguêspt-PT
trTürkçetr-TR

English is the base. It is bundled with the app; the other eight are dynamic imports, fetched when the language is chosen. One file per language, in src/locales/, holding every namespace. There is no per-module translation folder.

Add one ​

Check the plan ​

bash
npm run smart-admin -- add-locale ru --label "Русский" --dry-run
text
Adding locale "ru"
  copying from en (declared base)
  (dry run — nothing will be written)

  created   src/locales/ru.json
  edited    src/core/i18n/index.ts (AvailableLocale + lazyLocales)
  edited    src/core/i18n/localeMeta.ts (Intl tag + label + date-fns importer)
             switcher label: Русский
  edited    src/core/config/defaultConfig.ts (config.locale union)
  created   .smart-admin/locales/ru.json

Five sites. Miss one by hand and the language is half-wired: the union does not type-check, or the switcher has no label, or dates come out in English.

Run it ​

bash
npm run smart-admin -- add-locale ru --label "Русский"

The new file is a full copy of the base, structure and values, so the app runs and switches immediately with no missing-key warnings. Nothing is machine-translated.

--from <code> copies from another language instead of the base. A team adding Spanish will get further from pt than from en.

.smart-admin/locales/ru.json is the manifest. It records what was created, so remove-locale deletes exactly that rather than guessing. Commit it.

Set the region and the flag ​

The command writes intlTag: 'ru'. Open src/core/i18n/localeMeta.ts and make it the region you mean, such as ru-RU. That tag drives every number, date and currency format.

No flag is set, on purpose: a flag is a country and a locale is a language. Add flag: '/flags/ru.svg' on that row if your switcher uses flags.

Translate ​

bash
npm run smart-admin -- analyze --locales
text
  ru             100% keys  complete
      identical to en: 5744 value(s) — untranslated, or a cognate ("CRM", "Kanban", "Profil"…)

Every key is present from the first minute; the report tells you how much is still the English word. Work through src/locales/ru.json and watch that number fall.

Check the keys ​

bash
npm run check:i18n

It reads the direction the coverage report cannot: a key the code names that no file defines. A typo such as warehouses.fields.utilzation renders as that dotted string across a table header with nothing in the console, because uiText returns an unknown key verbatim. This is the gate that catches it.

It also checks every locale file. A key name with a dot in it, such as "crm-deals.timeline": { … }, fails, because vue-i18n splits a path on dots and can never reach it. A message that does not compile fails too: vue-i18n reads @ as the start of a linked message, so you@example.com in a translation breaks the page that renders it. Write it as you{'@'}example.com.

Right-to-left ​

Four codes are right-to-left: ar, he, fa and ur. Choosing one sets dir="rtl" on <html>, and the whole shell mirrors: the sidebar moves, icons flip, tables reverse their column order, and the rating's partial fill grows from the other edge.

Direction normally follows the language, but ui.direction overrides it with 'ltr' or 'rtl'. That is how the settings drawer previews a right-to-left layout without switching to Arabic, and it is the fastest way to check your own screens:

ts
import { useConfig } from '@core/config/useConfig'

useConfig().setUi('direction', 'rtl')

Set it back to 'auto' to follow the language again.

Arabic and Latin scripts both ship with fonts. A language in another script, such as Chinese or Hindi, needs a font registry entry before it looks right; add-locale warns instead of pretending it handled that.

Change the base language ​

The base is declared once, as BASE_LOCALE in src/core/i18n/index.ts. Three lines are coupled to it and cannot be derived from it, because a static import path is not an expression. npm run check:i18n checks all four agree and names the ones that do not, so moving the base is a change you can make safely.

Remove one ​

bash
npm run smart-admin -- remove-locale ru

It reads the manifest and undoes exactly what add-locale wrote. It refuses if source files still reference the code, and --force overrides that after you have read the list. --backup and --no-backup answer the backup question up front.

Where to go next ​

  • CLI — every command, flag and refusal.
  • Global config — locale, ui.direction and the feature flags around them.