Skip to main content
Every user-visible string goes through a catalog. English and Simplified Chinese are required for every new string; other locales (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:
The text catalog test treats a string as translatable when it reaches the translation layer directly: the argument of 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 titles and categories are translated the same way (an 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}.
English (en.json) is bundled and is the fallback for missing keys; other locales load lazily.

Rules

  • Add every new string to both en and zh. For source text, that is text/en.json (the English text mapped to itself) and text/zh.json. For a message key, en.json and zh.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 or languages/.
  • 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 the tx tag.
  • 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.json and zh.json for 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 in plugins/README.md (Translations). The rules on this page apply to the IDE’s own UI.