Internationalization
Maintain English/Chinese messages, product overrides, Paraglide output, and paired MDX content.
Separate messages, overrides, and articles
| Location | Purpose |
|---|---|
packages/i18n/messages/en.json and zh.json | Base template messages |
packages/i18n/messages/en.mvp.json and zh.mvp.json | Product-specific overrides |
apps/web/src/lib/locale.tsx | UI locale, translations, and prefixed links |
apps/web/src/content/*.en.mdx / *.zh.mdx | Public long-form content |
apps/web/src/paraglide | Generated modules; do not edit manually |
Use overrides for product copy while retaining upstream message structure. Add new base keys to both languages and consume them through useLocale rather than spreading literals through components.
Add or customize a message
- Add the same key to English and Chinese base messages when introducing a new concept.
- Prefer .mvp.json overrides when changing existing product copy.
- Use t and href from the existing locale hook.
- Run development/build to regenerate Paraglide output. Fix missing keys at their source rather than suppressing types.
Example:
const { t, href } = useLocale();
return <a href={href('/app/files')}>{t('files')}</a>;The key must exist in the current message table. Add your own keys consistently instead of bypassing checks with a type assertion.
Routes and language switching
English uses /pricing, /app, and /auth/login. Chinese uses /zh/pricing, /zh/app, and /zh/auth/login. The UI hook reads the path and href applies the prefix. Paraglide also has URL, cookie, and base-locale strategies; changing a cookie alone does not rewrite the current page URL.
Use existing switch links to retain the page. APIs remain /api/* for health, callbacks, uploads, and webhooks; never add a locale prefix.
Paired MDX
Place paired <slug>.en.mdx and <slug>.zh.mdx files directly in the content directory. The current static glob is not the marketing website's Fumadocs tree and does not recursively discover arbitrary nested directories.
Legal pages normalize the legal prefix during loading. Inspect modules/public slug mapping before naming new files. Missing content returns no article rather than generating a translation; add and inspect both variants.
Adding another locale
Update messages, overrides, articles, inlang/Paraglide configuration, locale types, path parsing, switch links, SEO hreflang, and tests. Copying a ja.json file alone does not make the whole app Japanese.
The website's eight UI languages and documentation fallback are separate from the Flare template's English/Chinese implementation.
Verify and troubleshoot
Check public pages, code/password sign-in, workspace, and admin in both languages. Switching should retain the current module and survive refresh. For missing keys, inspect generation and override spelling. For empty translated articles, inspect filenames, slugs, and glob location. Run build, type-check, and desktop/mobile locale tests.
Continue with content and theme/components.