es, fr, ko, pl, pt) may lack entries, and their UI shows the English text until a translator adds it.
Two catalogs
Source text
Most text is written in English at the call site. The UI primitives (labels, buttons, menus, dialogs, tooltips) pass the strings they are given through the source-text catalog, so this is translated automatically:tx / txTemplate, the text children of T, Button and Dialog, and props or object keys such as label, title, description, tooltip, placeholder, message, hint, aria-label.
Text built at runtime uses the tx tag, which looks up a template with named placeholders:
src/platform/locales/text/zh.json
action.<id> message key, if present, takes precedence). The English title stays searchable in Find Action.
Messages
Keyed messages use an ICU-lite syntax:{name}parameters (numbers are locale-formatted);{n, plural, =0 {none} one {# file} other {# files}};{g, select, a {…} other {…}};{n, number}.
en.json) is bundled and is the fallback for missing keys; other locales load lazily.
Rules
- Add every new string to both
enandzh. For source text, that istext/en.json(the English text mapped to itself) andtext/zh.json. For a message key,en.jsonandzh.json. - Rewording a string drops its translation. Source-text keys are the English text, so if you change the wording at the call site, update the catalog entries too.
- Remove entries you orphan. The test fails on catalog entries whose text no longer appears anywhere in
src/, the Rust crates orlanguages/. - Translate whole sentences. Don’t splice English words into translated text (
${kind.toLowerCase()},${n === 1 ? "" : "s"}); write one text per variant, or use a plural message. - No untagged template literals in an exact lookup:
`Cannot open ${path}`can never be translated. Use thetxtag. - Backend text (error messages and the like) counts as used as long as the literal appears in the source; add its translation like any other text.
- Chinese terminology: follow the existing entries in
text/zh.jsonandzh.jsonfor the same concepts, so one English term doesn’t get two translations.
Tests
Run them on their own while iterating:
Plugins
Plugins ship their own translations in the package; that mechanism is documented for plugin authors inplugins/README.md (Translations). The rules on this page apply to the IDE’s own UI.