For AI agents: fetch the complete documentation index at /llms.txt, the full documentation corpus at /llms-full.txt, the agent skill at /skill.md, or this page as Markdown at /docs/web/i18n.md (or send Accept: text/markdown).
Locales and copy
Use the four-locale dictionary scaffold for app chrome, settings labels, mail, and notification events.
Setup and configuration
Before any step, read Before you start and Terminal basics. These instructions assume you opened the full supastack monorepo in VS Code; its root package.json marks the repository root. In pnpm commands, a workspace package is an app or shared-code folder; in the product, a workspace is a team's data container and security boundary. corepack pnpm --filter ... selects one package from the monorepo while commands run from its root. If you opened only a synced mobile or desktop folder, it does not contain the Web backend, Docker setup, or root scripts: run the backend from this monorepo or a reachable hosted server, and use the platform folder's own scripts. An environment variable is a named setting stored in a local .env file or your hosting dashboard; restart the relevant app after changing it, and keep server secrets out of NEXT_PUBLIC_ and EXPO_PUBLIC_ values.
1. Open packages/i18n/src/index.ts in VS Code to see the supported language names and locale helpers; locate the matching dictionary files before changing product copy.
2. Add the same new key and translation to English, German, Spanish, and French dictionaries.
3. From the repository root run corepack pnpm test -- packages/i18n/src/index.test.ts and start Web with corepack pnpm --filter @supastack/web dev. Expected: the language switcher changes the visible text while preserving the current page path.
Locales live in @supastack/i18n with SUPPORTED_LOCALES, LOCALE_COOKIE, resolveLocale, getDictionary, and localePath. Proxy sets x-supastack-locale and handles canonical English redirects; LanguageSwitcher updates the cookie and preserves active sub-paths. Key app routes (/dashboard, /settings, /billing, /chat) work directly under /[locale] prefixes alongside the soft /{locale} marketing home.
Dictionaries cover marketing nav, settings section labels, organization settings chrome, transactional mail (invite/OTP/magic-link/AI/billing), notification preference labels, and in-app notification event copy.
import { getDictionary, resolveLocale, LOCALE_COOKIE } from "@supastack/i18n";
const locale = resolveLocale([
cookieStore.get(LOCALE_COOKIE)?.value,
headers.get("x-supastack-locale"),
headers.get("accept-language"),
]);
const copy = getDictionary(locale);Commands to copy
Follow the comments to see which folder a command runs in. If two terminals are labeled, open two terminal windows and keep the first command running while you use the second.
corepack pnpm test -- packages/i18n/src/index.test.ts
corepack pnpm --filter @supastack/web devImplementation workflow
Pass locale into server-rendered settings/org pages and into notificationCopyForEvent / auth mail delivery options when available. Keep English as DEFAULT_LOCALE and avoid inventing marketing claims outside dictionary keys.
Transactional mail stays separate from outreach. Expand dictionaries before nesting every marketing route under [locale].
Verification and troubleshooting
If English appears for one phrase, check that the key exists in all four dictionaries and that the page asks for the same key. If switching languages returns to the homepage, preserve the current path when building the locale link. Keep email copy on the transactional email path; do not reuse it as bulk outreach.
Run packages/i18n Vitest, proxy tests, and locale-app-routes tests. Spot-check LanguageSwitcher on / and localized Settings/org/dashboard/billing/chat headings when the locale prefix is de/es/fr.