The raw key on a live page
A label is added in English and the Dutch line is forgotten. Nothing complains, and a Dutch reader meets an internal key on a settings page. Here that gap stops the build.
The workspace reads in your language from the first paint.
Growth-OS speaks English and Dutch as peers. Both catalogs are compiled into the app, so the first render is already in your language with nothing to fetch and nothing to flicker. If a phrase is added in one language and forgotten in the other, the build fails before anyone meets a raw key.
The mechanism end to end, as implemented in the repository.
The URL decides first
A /nl prefix means Dutch. Without one, the app falls back to the account preference, then a strictly validated cookie, then the default.
Pages render from compiled catalogs
Copy reads from typed catalogs compiled into the app, so the server render and the first client render agree.
Switching keeps your place
The switcher rewrites the current URL, keeping path, query and hash, and updates the document language immediately.
The choice sticks
It is stored in a validated cookie and, for a signed-in teammate, on the account, so the next visit opens the same way.
Interactive example
This walkthrough demonstrates the implemented backend contract without using an account, credentials, or provider calls.
Interactive example
Deterministic sample data only. No account, provider, or network connection is used by the interaction.
Without a shared foundation, every team rebuilds these edge cases, differently.
A label is added in English and the Dutch line is forgotten. Nothing complains, and a Dutch reader meets an internal key on a settings page. Here that gap stops the build.
Someone reading in Dutch shares a page, a colleague opens it in English because the choice only lived in a cookie, and the conversation restarts. Putting the language in the URL keeps it with the link.
Loading translations after the page means every first visit flickers from keys or English to the real text. Compiled catalogs leave nothing to wait for.
Highlights
Both languages live side by side in one typed catalog. Add a phrase in one and forget the other, and compilation fails instead of shipping the gap.
Dutch pages live under /nl, so a link you paste into a channel opens in the language you were reading.
Translations are compiled in, not fetched, so the server render and the first client render already speak the right language.
Engineering guarantees
This translates the application’s own words. It does not machine-translate anything, and what we type into a record, a decision, a meeting note or a campaign brief is stored and shown exactly as written.
The boundary above is code, not a claim. These files carry the contract:
src/modules/i18n/messages.tssrc/modules/i18n/locale-navigation.tssrc/modules/i18n/MODULE.mdThese capabilities share contracts and boundaries with this one.
The docs describe the same contracts this page demonstrates.