Translating the Interface¶
The web interface ships in English and French. Every text shown by the interface lives in JSON files, one folder per language; the code never contains user-facing strings. Adding a language needs no code change: add a folder, and the language appears in the language picker.
Where the texts are¶
packages/frontend/src/locales/
en/ English (reference language, and fallback)
meta.json name of the language in the picker
common.json shell, navigation, sign-in, API errors (errors.*)
steward.json one file per page / feature (audit, cluster, nodes, windows...)
issues-*.json validation messages (issues.*)
fr/ French: same files, same keys
At start-up the interface loads every locales/<code>/*.json file and merges the files of a folder
into one translation table. File names only organize the work: what matters is the key path inside
the files (audit.title, issues.cluster.acmeEmailRequired...). A key must be defined in one file
only.
Rules for the values:
{{name}}is a placeholder replaced at run time: keep it as is (you may move it in the sentence).- Keys ending in
_one/_otherare plural forms; add the forms your language needs (for example_few,_many), following the i18next plural rules. - Lists (JSON arrays, e.g. post-install checklists) are translated item by item.
- Product and protocol names (Teleport, Active Directory, RDP, LDAP, ACME,
tctl) are not translated.
Adding a language¶
- Copy
packages/frontend/src/locales/entopackages/frontend/src/locales/<code>, where<code>is the base language tag in lower case (de,es,it,nl...). - Edit
<code>/meta.json: the native name of the language and its writing direction.
{ "meta": { "name": "Deutsch", "dir": "ltr" } }
Use "dir": "rtl" for right-to-left languages (Arabic, Hebrew).
3. Translate the values of every file. Do not rename, add or remove keys.
4. Run the parity test:
cd packages/frontend
npx vitest run src/i18n/locales.test.ts
It fails, with the list of keys, when your language has a key that English does not have or misses
one, when meta.name is missing, or when a validation code has no English or French translation.
5. Build (npm run build) and start the application: the language is listed in the picker (top right)
under its native name.
Which language is shown: the choice saved in the browser if any, otherwise the first language of the browser preferences that the application provides, otherwise English. A key missing from a language is shown in English, so a partial translation never breaks a page (the parity test still reports it).
Validation messages and API error codes¶
The back end and the front end share the same validators (packages/shared). Each validation issue
carries a stable code, optional params and an English message:
{ "path": "cluster.acmeEmail", "severity": "error", "code": "cluster.acmeEmailRequired",
"message": "An ACME contact e-mail address is required." }
The interface shows the translation of issues.<code> (from the issues-*.json files), with the
params interpolated ({{filter}}, {{code}}...). When a code has no translation, the English message
is shown. When you add a validation rule in packages/shared, give it a code with the
err(path, 'area.name', 'English message', params) / warn(...) helpers and add issues.area.name
to every language; the test src/i18n/locales.test.ts reads the shared sources and fails on a
code that has no English or French entry.
API errors use the same idea: the server answers with a stable error code
(see Error codes & Debugging) and the interface shows
errors.<code> (in common.json), or a generic message when the code is unknown. Teleport connection
problems (teleport_* codes) are translated under tp.* (shell.json).
What stays in English¶
- Generated files: Bash and PowerShell scripts,
teleport.yaml, Docker Compose files and theREADMEfiles inside the downloaded bundles. They are read by administrators on servers, copied into tickets and searched for on the internet; one language keeps them consistent. Their error lines start with a stable code (see the Error codes page). - Logs and the audit log: back-end logs, the audit log details and script output shown in the interface are recorded as produced.
- Free text produced by the server that has no code yet (for example the details of some verification checks) is shown as sent.
- This documentation is written in English.