v4 #1
@@ -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",
|
||||
},
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user