Internationalization
The files in tooling/internationalization/messages/ are source catalogs for every application workspace. Keep all locale files structurally identical. When you add a message, update every locale.
Message Keys
Use flat semantic keys in lower snake case. Build each key from the durable owner and role of the message:
<surface>_<feature>_<element>_<role>Not every key needs all four segments. Use only the segments needed to make the message unambiguous:
api_hello_greetingdesktop_local_files_empty_stateshared_locale_switchweb_landing_hero_headline_first- Start with the application workspace or
sharedfor messages used across multiple surfaces. - Follow the feature boundaries of the repository where they exist.
- Name the final segment after the UI or domain role of the message. Do not use its current English wording.
- Treat an assigned key as a stable identifier. Do not rename it only because the copy changes or a component moves.
- Give messages that evolve independently separate keys, even when their source text is identical.
- Do not use nested JSON or dotted keys. Flat keys compile to direct
m.key()calls. They remain readable in editors without translation previews.
Adding Messages
- Add the same key to
tooling/internationalization/messages/en.jsonand every translated catalog. - Preserve the same variables, markup, and variants in every locale.
- Run
bun run fixto format the catalogs consistently. - Run
bun run codegento regenerate the Paraglide output for each workspace. - Before you commit, run
bun run check.
The message-format plugin sorts keys in ascending order when it writes the catalogs. This keeps related prefixes together and reduces noise in diffs.