feat(i18n): add next-intl internationalization scaffold

⛔ closed · #168 · Open-Legal-Products/mike ← tksuns12/mike · opened 2mo ago by tksuns12 · closed 20d ago · +2,044-793 across 77 files · ↗ on GitHub

From the PR description

Summary

Adds internationalization (i18n) to the frontend using next-intl (v4, App Router, cookie-based - no URL changes). All user-facing UI strings are extracted into a typed message catalog. English-only for now; adding a language is a matter of dropping in messages/<locale>.json.

What's included

Infrastructure

  • next-intl@4.13 wired via createNextIntlPlugin in next.config.ts
  • src/i18n/config.ts - single source of truth: locales, default locale, cookie name, labels
  • src/i18n/request.ts - resolves locale from the NEXT_LOCALE cookie (fallback en)
  • src/i18n/actions.ts - setLocale server action (writes the cookie)
  • NextIntlClientProvider in the root layout + dynamic <html lang>
  • src/types/next-intl.d.ts - typed messages: every t('key') is compile-checked against en.json
  • LanguageSwitcher component (design-system dropdown), mounted on the Account page
  • Localized generateMetadata, error, not-found, and global-error (the last self-provides its own NextIntlClientProvider because it replaces the root layout when active)

String migration

  • ~85 components/pages migrated from hardcoded English to useTranslations() / getTranslations()
  • messages/en.json: 671 keys across 16 namespaces (Common, Shared, Documents, Projects, Assistant, Tabular, Workflows, Modals, Auth, Account, ...)

Adding a new language

  1. Add the code to locales + a label to localeLabels in src/i18n/config.ts
  2. Add messages/<locale>.json (same shape as en.json)

The switcher and cookie handling pick it up automatically - no other wiring needed.

Deliberately left as-is

  • Brand name ("Mike"), model provider names (Anthropic/Google/OpenAI), and version codes (V{n})
  • console.*, API field names, route paths, and LLM prompt strings (not UI copy)
  • Date formatting already uses locale-aware toLocaleDateString

Test plan

  • tsc --noEmit - 0 errors (typed catalog validates all 671 keys against t() calls)
  • next build - all 20 routes compile
  • No new ESLint errors vs main
  • Manual: switch language on /account, confirm NEXT_LOCALE cookie is set and server components re-render
  • Manual: spot-check key screens (assistant, projects, tabular reviews, workflows) render expected copy

Our analysis

Add cookie-based i18n with next-intl and a typed message catalog — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-168.md from inside the repo you want the changes in.

⬇ Download capture-pull-168.md