manueljpconde teaches Mike to speak five languages

The mikeEU fork gets end-to-end localisation in English, Portuguese, Spanish, French, and German, with English as the safe fallback everywhere.

i18n

manueljpconde has wired full-interface translation into Mike: menus, login and account screens, sidebar navigation, and the everyday labels all now render in any of five languages. A switcher lets a user change language on the fly without a page reload, and the choice is saved to their account - so sign in from a different machine and the app comes up in the language you picked.

Notably, this was built without leaning on an off-the-shelf translation library. The team wrote a thin in-house layer instead, keeping the moving parts small and easy to audit. English remains the guaranteed fallback at every layer, so nothing breaks if a phrase hasn't been translated yet. This is a first pass - some text is still English-only - but the foundation is in place.

So what If your practice or product serves clients across Europe, or anyone who'd rather not work in English, this is the difference between a tool people tolerate and one they actually adopt.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

2 commits from manueljpconde/mikeEU, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
346b8197 feat: add localization support for en/pt/es/fr/de (#4) Manuel Conde 2026-05-10 ↗ GitHub
commit body
Adds i18n infrastructure (thin custom + native Intl, no library) covering
auth pages, sidebar nav, language switcher, and common labels across the
five supported locales. English is canonical fallback at every layer.

- Schema: user_profiles.locale text column with named CHECK constraint
- Backend: PATCH /user/profile accepts/persists locale with allowlist validation
- Frontend: server-side locale resolution (cookie -> Accept-Language -> en)
  in root layout; client I18nProvider for runtime switching; ProfileLocaleSync
  applies authenticated profile.locale one-way
- Cookie 'mike_locale' (non-httpOnly, Path=/, Max-Age=1y, SameSite=Lax)
- Catalog validator with structural + placeholder + plural-shape checks
- 51 automated tests (46 frontend + 5 backend) on pure logic; React surface
  covered manually
- Coupled allowlist triple flagged: schema CHECK / backend SUPPORTED_LOCALES
  / frontend SupportedLocale must move together

Spec:  https://github.com/manueljpconde/mikeEU/issues/4#issuecomment-4414976968
Plan:  https://github.com/manueljpconde/mikeEU/issues/4#issuecomment-4414987693
GO:    https://github.com/manueljpconde/mikeEU/issues/4#issuecomment-4415157201

Closes #4
cb6b9a2f fix(i18n): four review findings on PR #10 Manuel Conde 2026-05-10 ↗ GitHub
commit body
1. npm test scripts: replace quoted-glob args (which tsx received literally
   and didn't expand on bash 3.2) with a Node-based test discovery script
   per repo. Both `npm test --prefix frontend` and `npm test --prefix
   backend` now run the suites correctly.

2. Validator now rejects duplicate top-level JSON keys via a state-machine
   raw-text scan (findDuplicateTopLevelKeys), restoring the contract
   promised in spec rule 4. JSON.parse silently dedupes; this catches
   editor mistakes before runtime sees the deduped catalog.

3. Signup persists the active i18n locale alongside name/organisation
   so a guest who selected pt/es/fr/de doesn't get snapped back to en
   when ProfileLocaleSync applies the (default 'en') profile after
   signup.

4. Client setLocale now syncs document.documentElement.lang via useEffect
   on locale change. SSR sets it once; the effect keeps it in sync after
   user-driven switches.

Tests: frontend 55/55 (added 9 in findDuplicateTopLevelKeys.test.ts),
backend 34/34. Both `npm test` and `npm run lint:catalogs` runnable
without manual glob expansion.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-249.md from inside the repo you want the changes in.

⬇ Download capture-thread-249.md