Skip to content

User locale

A user’s preferred locale travels end-to-end, from the browser to the server, into the session JWT, and into triggered mails and background jobs : so e.g. a magic-link email renders in the sender’s locale rather than a server default.

  • The client sends document.documentElement.lang as an X-Locale header (or Accept-Language) on requests.
  • The server exposes it as an always-present ctx.locale; handlers can answer locale-dependently and derive mail locales from it.

2. Session persistence (SessionUser.locale in the JWT)

Section titled “2. Session persistence (SessionUser.locale in the JWT)”
  • The user’s chosen locale is written into the JWT at login (locale claim) and threaded through login / invite-accept / MFA handlers.
  • SessionUser.locale survives cross-device and background jobs: a job running on the user’s behalf knows their locale.
  • ctx.locale falls back from the live X-Locale signal to SessionUser.locale, keeping a consistent locale even when a request carries no browser locale.

All auth mails (signup, password-reset, email-verification, invite, account-unlock) render in the requester’s locale:

  • appUrl may be a function (locale) => string to build locale-aware landing paths (e.g. /de/...).
  • Mails derive the locale from ctx.locale / SessionUser.locale, never a hard-coded server default.
  • New outbound mails: always derive locale from ctx.locale (fallback SessionUser.locale), never hard-code a server default.
  • Use appUrl as (locale) => string when the landing path is locale-sensitive.