Add an i18n key
SupaCloud’s web UI uses Paraglide for
internationalisation. Message catalogs live in web/messages/en.json and web/messages/de.json.
Generated code in web/src/lib/paraglide/ is produced from those files — do not edit the
generated files directly.
-
Add the key to
web/messages/en.json.Keys must match
[a-z0-9_]+(lowercase, digits, underscores only). Choose a name that is descriptive and scoped to the feature, for exampleworkspace_rename_label.web/messages/en.json "workspace_rename_label": "Rename workspace" -
Add the same key to
web/messages/de.jsonwith a German translation.Both catalogs must stay in sync — the architecture test
"uses Paraglide-safe message ids"fails if the key sets differ.web/messages/de.json "workspace_rename_label": "Workspace umbenennen" -
Regenerate the Paraglide output.
Terminal window cd webnpm run i18n:compileThis runs the
paraglide-js compilepipeline and theclean-paraglide.mjspost-processor. The files underweb/src/lib/paraglide/are updated in place. -
Use the key in a Svelte component.
Import
mfrom the generated module and call it as a function:<script lang="ts">import { m } from "$lib/paraglide/messages.js";</script><button>{m.workspace_rename_label()}</button>Never embed a raw string literal for user-visible copy — the architecture test
"keeps obvious Svelte template copy behind Paraglide calls"fails on literal text inside Svelte templates. -
Verify locally before committing.
Terminal window cd webnpx svelte-check --threshold error # 0 type errorsnpm run lint # oxlint — 0 findingsnpx vitest run # architecture tests pass
i18n-lint guard — “team” for the tenant
Section titled “i18n-lint guard — “team” for the tenant”The frontend architecture test "forbids new user-facing Workspace/Teams copy outside the agent/delivery namespaces" scans every value in both catalogs for the word team/teams (case-insensitive).
A new key whose value contains “team” or “teams” will fail CI unless its key name matches one of the allowed namespaces:
| Allowed key pattern | Purpose |
|---|---|
teammate |
Multi-agent “Teammates” feature |
agent_teams |
Agent team grouping |
delivery_* |
Delivery board screen copy |
issue_tracker_team_key |
Linear “Team key” field label |
notify_to_placeholder |
Sample notify address copy |
If the copy you are adding refers to a tenant (a Workspace or Organisation), use those words instead. “Team” and “Teams” are reserved for the agent domain. See the ubiquitous language glossary and ADR 0040.
Parametrised messages
Section titled “Parametrised messages”If the string needs a runtime value, add a placeholder in ICU MessageFormat syntax:
"task_cost_summary": "Total cost: {amount}"The generated function then accepts a typed argument:
{m.task_cost_summary({ amount: formattedCost })}Keep placeholder names short, lowercase, and descriptive.