Skip to content

feat(admin): multilingual admin UI with per-user language#1

Merged
proggeramlug merged 1 commit into
mainfrom
feat/admin-i18n
May 23, 2026
Merged

feat(admin): multilingual admin UI with per-user language#1
proggeramlug merged 1 commit into
mainfrom
feat/admin-i18n

Conversation

@proggeramlug
Copy link
Copy Markdown
Member

What

Makes the server-rendered admin panel multilingual in the 13 locales shipped by perry/landing (en, de, es, fr, it, ja, ko, pt, th, tr, vi, id, zh-Hans). Each user picks their own display language, persisted to users.locale.

How

  • src/admin/i18n/ (new): bundled per-locale TS message bags — en.ts is the source of truth and the runtime fallback; makeT() gives a t('dot.path', vars) translator with {placeholder} interpolation + t.plural(). Locale helpers (coerceLocale handles de-ATde, zh-CNzh-Hans; negotiateLocale parses Accept-Language). Per-request middleware resolves users.localeskelpoAdminLang cookie → Accept-Language → en, mounted on adminRoutes so it covers every admin path (incl. /admin).
  • Externalized every visible admin string across layout.tsx, routes.tsx, screens.tsx, contentEditor.tsx (nav, dashboard, content editor, settings, media incl. inline-JS prompts via injected window.SKELPO_I18N, forms, users, redirects, menus, jobs, webhooks, flash messages, status badges, <html lang>). Content/setting data, API paths, and capability names stay verbatim.
  • Per-user setting: new /admin/profile page + a sidebar quick-switcher that saves to users.locale + cookie and reloads in place.
  • CLI lockstep: users create/update gain --locale (the API already accepted it).

Notes

  • Plural selection uses the English n===1 rule across all locales — fine for these 13.
  • Translations are machine-generated, usable now, structured for easy refinement (edit en.ts, re-run the key-parity test).
  • site.locales (content translation tabs) is intentionally untouched — that's separate from the admin UI language.

Verification

  • npm run typecheck — clean.
  • npm run test:unit57/57 pass, including 11 new i18n tests + a key-parity check (all 12 locales have the same 320 keys as en).
  • End-to-end render of /admin/login across locales confirms correct <html lang> + translated output (zh-CN → zh-Hans, de → "Anmelden", ja → "サインイン").

Make the server-rendered admin panel multilingual in the 13 locales
shipped by perry/landing (en, de, es, fr, it, ja, ko, pt, th, tr, vi,
id, zh-Hans). Each user picks their display language; it persists to
users.locale.

- src/admin/i18n: bundled per-locale TS message bags (en is source of
  truth + runtime fallback), t()/t.plural() translator, locale helpers
  (coerceLocale, negotiateLocale), and per-request middleware resolving
  user.locale -> skelpoAdminLang cookie -> Accept-Language -> en.
- Externalize every visible admin string (nav, dashboard, content
  editor, settings, media incl. inline-JS prompts, forms, users,
  redirects, menus, jobs, webhooks, flash messages, status badges,
  <html lang>) to t(). Data/API paths/capability names stay verbatim.
- /admin/profile page + sidebar quick-switcher to set the language.
- CLI: users create/update gain --locale (lockstep with the API).
- Tests: unit coverage for translator, negotiation, and key parity
  across all 12 locales (320 keys each).
@proggeramlug proggeramlug merged commit 58b9ae1 into main May 23, 2026
2 checks passed
@proggeramlug proggeramlug deleted the feat/admin-i18n branch May 23, 2026 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant