v4 #1

Merged
yamen merged 19 commits from v4 into main 2026-04-26 00:38:14 +02:00
2 changed files with 24 additions and 9 deletions
Showing only changes of commit eef3edf7e8 - Show all commits

View File

@@ -5,10 +5,16 @@
* they go through type-checking and tree-shaking, and so non-translators
* can't ship a broken JSON file that blocks the build.
*
* Language detection order:
* 1. localStorage key ``encoach-lang`` (explicit user pick)
* 2. ``navigator.language``
* 3. fallback ``en``
* Language selection order (product decision: English is the default UI
* language at startup; Arabic is opt-in via the language toggle):
* 1. localStorage key ``encoach-lang`` (explicit user pick, persisted)
* 2. ``en`` — fallback used on first visit, regardless of browser locale
*
* We intentionally do **not** read ``navigator.language`` anymore: an
* Arabic-locale browser should still land on the English UI the first time
* a user visits, because the QA team and the product manager both sign off
* against the English baseline. Users that actively want Arabic flip the
* toggle once and the preference is remembered from then on.
*
* RTL handling: whenever the active language switches to one of RTL_LANGS,
* we flip ``document.documentElement.dir`` so Tailwind's RTL utilities +
@@ -31,6 +37,8 @@ export const SUPPORTED_LANGS = [
export type SupportedLang = (typeof SUPPORTED_LANGS)[number]["code"];
export const DEFAULT_LANG: SupportedLang = "en";
i18n
.use(LanguageDetector)
.use(initReactI18next)
@@ -39,11 +47,16 @@ i18n
en: { translation: en },
ar: { translation: ar },
},
fallbackLng: "en",
// Explicit default — english is the baseline UI language at startup.
lng: DEFAULT_LANG,
fallbackLng: DEFAULT_LANG,
supportedLngs: SUPPORTED_LANGS.map((l) => l.code),
interpolation: { escapeValue: false },
detection: {
order: ["localStorage", "navigator", "htmlTag"],
// Only honour the user's saved pick. Navigator/htmlTag detection was
// removed so Arabic-locale browsers don't silently boot the UI in
// Arabic before the user has chosen.
order: ["localStorage"],
caches: ["localStorage"],
lookupLocalStorage: "encoach-lang",
},

View File

@@ -131,15 +131,17 @@ function refreshOnce(): Promise<boolean> {
}
function getCurrentLanguage(): string {
// Mirrors the i18n bootstrap in src/i18n/index.ts: the user's explicit
// pick wins; everything else falls back to English. We intentionally do
// not consult navigator.language here so AI-generated content stays in
// English on first visit (matching the UI default) until the user flips
// the language toggle.
try {
const stored = localStorage.getItem("encoach-lang");
if (stored) return stored;
} catch {
// localStorage unavailable (SSR, sandboxing, etc.)
}
if (typeof navigator !== "undefined" && navigator.language) {
return navigator.language.split("-")[0];
}
return "en";
}