Localisation
Splitjar ships in six locales: English (Australia / Britain / United States), German, French, and Spanish. Localisation covers UI copy, email content, error messages, accessibility labels, and rotating subject-line variants.
How a locale is chosen
The order of resolution is:
- Explicit user choice. If the user clicked the locale chip in the header, that choice is stored with an
sj-locale-explicitflag and honoured. - Browser’s
navigator.language. Used on first visit when no explicit choice has been stored. en-AUfallback. Anything else, anything missing.
The same shape applies to currency, but driven by Cloudflare’s request.cf.country (geo IP) — not by language. A French speaker in Tbilisi gets EUR if they’re at home and GEL if they’re travelling, without intervention.
Per-user locale on the server
Once a user signs in, their chosen locale is persisted on the users.locale column (migration 0021). Outbound emails resolve copy via copyForRecipient(env, email), which loads the locale from the recipient’s user row. Anonymous bounce-email recipients (no users row) get en-AU.
Voice per locale
Each locale carries its own voice register that mirrors the spirit of the en-AU original:
- Deutsch: Sie-form throughout. Trocken, untertrieben, leise amüsiert.
- Français: vous-form. Pince-sans-rire, ironie retenue.
- Español: tú-form. Seco, conversacional, irónico contenido.
Metaphors translate too — “jar” becomes Glas (de), pot (fr), bote (es).
Forbidden words by locale
The voice-lint script enforces a forbidden-word list per locale to catch marketing tics:
| Locale | Forbidden |
|---|---|
| en | journey, seamless, effortless, awesome, amazing, game-changer, level up, unlock |
| de | toll, super, einfach, bequem, reibungslos |
| fr | incroyable, magique, fluide, sans effort |
| es | increíble, mágico, sin esfuerzo, facilísimo |
Run npm run lint:voice to check. Append to scripts/voice-lint.mjs to extend.
Currencies
Four billing currencies are supported: AUD, USD, GBP, EUR. AUD is GST-inclusive (tax_behavior=inclusive on the Stripe price). Other currencies are exclusive of any local tax.
Receipts in any currency are accepted. Conversion to the jar’s base currency happens at extraction time using the FX rate plus the configured margin (default 2.5%, owner-overridable).