i18n
CI/CD Pipeline / Build and Push PocketBase Docker Image (push) Successful in 8s
CI/CD Pipeline / i18n Catalog Check (push) Failing after 10s
CI/CD Pipeline / Build and Push App Docker Image (push) Skipped
CI/CD Pipeline / Deploy to Kubernetes (push) Skipped

This commit is contained in:
yohlo
2026-08-08 15:29:40 -07:00
parent 22c282d8fa
commit 0a7b5fa00f
178 changed files with 13099 additions and 1285 deletions
+56
View File
@@ -0,0 +1,56 @@
---
name: add-language
description: Add or remove a UI language/locale — config, catalog generation, translation agents, SMS/date/meta integration, and verification. Use when asked to add, enable, support, or remove a language.
---
# Adding a language
Example: adding French (`fr`). Five places name the locale set — update all:
1. `src/lib/i18n/index.ts``SUPPORTED_LOCALES` + `LOCALE_LABELS` (label in
the language itself, no region clarifier: `fr: "Français"`).
2. `lingui.config.ts``locales`.
3. `src/lib/mantine/mantine-provider.tsx``DAYJS_LOCALE` map + the matching
`import 'dayjs/locale/fr'` (calendar month/weekday names come from dayjs;
without this, calendars stay English).
4. `src/lib/i18n/meta.ts``OG_LOCALE_BY_LOCALE` (fr → fr_FR).
5. `src/lib/twilio/index.ts``TWILIO_VERIFY_LOCALES` ONLY if Twilio Verify
supports the code (https://www.twilio.com/docs/verify/supported-languages).
Unsupported codes must stay out — the allowlist silently falls back to the
service-default English SMS instead of failing the login send.
Then generate + translate:
6. `bun run extract` creates `src/locales/fr/messages.po` (every msgid, empty
msgstr).
7. Translate via a chunked agent workflow (this repo's proven recipe):
- Split en.po entry blocks (split on blank lines, skip header) into ~60-entry
chunks; one sonnet agent per chunk RETURNS translated entries (never let
parallel agents edit one .po). Validate each returned chunk by msgid count;
retry failures once.
- Merge by msgid back into the locale .po. Match msgids by exact bytes —
watch non-breaking spaces (\xa0) in msgids, which agents normalize away;
patch those few by hand.
- Agent rules: msgstr single-line, ICU placeholders/plural keywords and
`<0>` tags preserved (translate only human words inside branches; plural
categories follow the target language's CLDR set), FLXN/Flexxon/Spotify
untranslated, casual sporty tone, register decided up front (tú/du/です・ます).
8. `bun run i18n:check` must pass (0 missing). Optionally run per-locale
native-reviewer agents over the full .po (fidelity, register, glossary
consistency, ICU integrity) and apply their FIX lines.
9. `bunx tsc --noEmit && bun run build`; confirm the new locale appears as its
own lazy `messages-*.js` chunk in dist/client/assets.
10. Manual check: switch language in Settings (persists to SuperTokens
metadata), confirm UI + calendar + SMS behavior.
# Removing a language
Reverse of the above: delete from the five locale-set sites (skip Twilio if it
was never listed), `rm -rf src/locales/<code>`, drop the dayjs import, then
`bun run i18n:check` + tsc. Users with the removed locale saved in metadata
fall back to English automatically via `resolveLocale`.
Fallback semantics: untranslated entries render English (msgid); unauth
visitors get Accept-Language detection (SSR first paint on public routes is
English, corrected after hydration); authed users get their saved locale
server-rendered.