docs(i18n): add conventions guide and wire docs navigation
This commit is contained in:
86
docs/product-engineering/i18n-conventions.md
Normal file
86
docs/product-engineering/i18n-conventions.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# i18n Conventions
|
||||
|
||||
## Scope
|
||||
|
||||
This document defines translation conventions for both apps in MVP0+.
|
||||
|
||||
- Public app i18n: `next-intl` message namespaces and route-level usage
|
||||
- Admin app i18n: JSON dictionaries + runtime resolver/provider
|
||||
- Shared locale contract: `@cms/i18n` (`de`, `en`, `es`, `fr`; default `en`)
|
||||
|
||||
## Locale Policy
|
||||
|
||||
- Source of truth: `packages/i18n/src/index.ts`
|
||||
- Current enabled locales are code-driven and shared across web/admin.
|
||||
- Admin-managed locale toggles are planned for a later MVP.
|
||||
|
||||
## Key Naming Conventions
|
||||
|
||||
- Use `camelCase` for keys.
|
||||
- Group by domain namespace (not by component filename).
|
||||
- Keep keys stable; update values, not key names, during copy edits.
|
||||
|
||||
### Public app namespaces
|
||||
|
||||
- `Layout.*`
|
||||
- `Home.*`
|
||||
- `LanguageSwitcher.*`
|
||||
- Page-specific namespaces, e.g. `About.*`, `Contact.*`
|
||||
- Metadata namespace: `Seo.*`
|
||||
|
||||
### Admin app namespaces
|
||||
|
||||
- `common.*`
|
||||
- `auth.*`
|
||||
- `dashboard.*`
|
||||
- `settings.*`
|
||||
|
||||
## Message Structure
|
||||
|
||||
- Keep messages as nested JSON objects.
|
||||
- Avoid very deep nesting (prefer 2-3 levels).
|
||||
- Keep punctuation in translation values, not code.
|
||||
- Avoid embedding HTML in message strings.
|
||||
|
||||
## Fallback Rules
|
||||
|
||||
- Unknown/invalid locale values fallback to default locale `en`.
|
||||
- Missing translation key behavior:
|
||||
- Admin: `translateMessage` returns provided fallback, else key.
|
||||
- Public: ensure required keys exist in locale JSON; avoid runtime missing-key states.
|
||||
|
||||
## Adding New Translation Keys
|
||||
|
||||
1. Add key/value in `apps/*/src/messages/en.json`.
|
||||
2. Add equivalent key in `de/es/fr` JSON files.
|
||||
3. Use key via translator:
|
||||
- Web: `useTranslations("Namespace")` or `getTranslations("Namespace")`
|
||||
- Admin: `useAdminT()` or server-side `translateMessage(...)`
|
||||
4. Add/adjust tests for behavior where relevant.
|
||||
|
||||
## Translation Workflow
|
||||
|
||||
1. Author English source copy first.
|
||||
2. Add keys in all supported locales in same change.
|
||||
3. Keep semantic parity across locales.
|
||||
4. Run checks:
|
||||
- `bun run check`
|
||||
- `bun run typecheck`
|
||||
- `bun run test`
|
||||
5. For route-level i18n behavior changes, run e2e smoke:
|
||||
- `bunx playwright test --grep "i18n smoke"`
|
||||
|
||||
## QA Checklist
|
||||
|
||||
- Locale switch persists after refresh.
|
||||
- Page headings and navigation labels translate correctly.
|
||||
- Metadata (`Seo`) strings resolve per locale.
|
||||
- No missing-key placeholders visible in UI.
|
||||
|
||||
## Related Files
|
||||
|
||||
- `apps/web/src/i18n/request.ts`
|
||||
- `apps/web/src/i18n/routing.ts`
|
||||
- `apps/admin/src/i18n/server.ts`
|
||||
- `apps/admin/src/i18n/messages.ts`
|
||||
- `packages/i18n/src/index.ts`
|
||||
Reference in New Issue
Block a user