Translating the console¶
The web console ships in English and French. Every text of the interface lives in JSON files, one folder per language; adding a language means adding a folder, nothing else. No API or .NET change is needed.
Where the texts are¶
web/src/locales/
en/ reference language: every key exists here first
meta.json { "meta": { "name": "English", "dir": "ltr" } }
common.json app, common, nav, errors, validation, login, tls, step-up, permissions, command palette
dashboard.json dashboard, watch list
users.json user list, profile, attributes, account status, manager, history, export, lifecycle, lockout
groups.json groups, membership, group picker
roles-delegations.json roles, delegations, scopes, operators, simulator, deny reasons, tiers
audit.json audit log and audit action names
config.json configuration, diagnostics, branding, directory settings
helpdesk.json reset, unlock, ticket, caller verification, dictation, recent users, helpdesk settings
sso.json sign-in settings (SSO), security (MFA)
setup.json setup wizard
onboarding.json new user, templates
fr/ same files, same keys
The split by file is only for convenience: at start-up web/src/i18n/index.ts finds every locales/<code>/*.json file
(Vite import.meta.glob), deep-merges the files of each language into one tree and registers the language. A top-level key
must live in only one file of a language; the file names must be the same in every language.
Add a language¶
- Copy
web/src/locales/entoweb/src/locales/<code>, where<code>is a BCP 47 tag:de,it,es,pt-BR... - Edit
meta.json:nameis the language's own name as its speakers write it (Deutsch,Italiano), shown in the language picker;dirisltr, orrtlfor right-to-left scripts (the page'sdirattribute follows it). - Translate the values, never the keys. Keep the JSON structure and the
{{placeholders}}as they are. - Run the tests in
web/:
npx vitest run src/i18n # parity: same keys as English, same placeholders, meta.name present, no empty text
npx vitest run # the whole suite
If a newly added file is not picked up, run npx vitest --clearCache once.
5. Build (npm run build). The language appears automatically in the top-bar picker and in the language buttons of the password
dictation view. It is chosen at first visit when it matches the browser's preferred languages (de-CH matches de); otherwise
the console starts in French. The operator's choice is remembered in the browser.
A partially translated language still works: missing texts fall back to English. The parity test, however, fails until every key is translated, so a release never ships a half-done language by accident.
Rules for translators¶
- Placeholders
{{name}},{{count}},{{dc}}... are replaced at run time. Keep each one, with the same name; you may move it within the sentence. The parity test checks this. - Plurals use the i18next suffixes
_zero,_one,_two,_few,_many,_other(Unicode CLDR rules for the language). English and French use_oneand_other; a language with more forms (Polish, Arabic...) adds the forms it needs, for examplekey_one,key_few,key_many,key_other, and drops nothing that English has (keep_oneand_other). A plural form may leave out{{count}}("within the next day"). - No HTML: texts are rendered as plain text. Markup is shown literally.
- Keep product and protocol names as they are: Active Directory, LDAPS, Teleport, OU, UPN, SID, TOTP.
- Error codes: the API never sends sentences; it sends codes (
not_found,step_up_required,name_taken...). The console translates them by key:errors.<code>for generic errors, and per-feature tables such aseditErrors.*,roleErrors.*,operatorErrors.*,groupErrors.*,helpdeskErrors.*,onboarding.errors.*,dirSettings.errors.*,diag.codes.*,denyReasons.*,auditActions.*. An unknown code falls back to the genericerrors.unexpected_error, or to the code itself. - Dictation and the message sent to the user after a password reset are in
helpdesk.json:dictation.speech(the words spoken around the NATO letters, which stay the same in every language: "capital", "digit", the digit and symbol names) andreset.userMessage(the ready-to-send message). The operator can pick any available language for them, independently of the interface language.
What stays in English (or untranslated)¶
- Server logs, audit records (action names and stored fields; the audit page translates action names for display), the exported AD delegation script and the configuration files.
- Directory data: names, descriptions, OU paths, attribute values are shown as stored in AD.
- Generated passphrases: the server has French and English word lists only; the French list is used when the interface is in French, the English list otherwise.
- CSV exports use
;as separator when the interface is in French,,otherwise.