Fix locale initialization and persistence
Browse files
frontend/src/core/i18n/context.tsx
CHANGED
|
@@ -1,8 +1,16 @@
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
-
import {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
import type { Locale } from "@/core/i18n";
|
|
|
|
|
|
|
| 6 |
|
| 7 |
export interface I18nContextType {
|
| 8 |
locale: Locale;
|
|
@@ -10,6 +18,7 @@ export interface I18nContextType {
|
|
| 10 |
}
|
| 11 |
|
| 12 |
export const I18nContext = createContext<I18nContextType | null>(null);
|
|
|
|
| 13 |
|
| 14 |
export function I18nProvider({
|
| 15 |
children,
|
|
@@ -20,9 +29,48 @@ export function I18nProvider({
|
|
| 20 |
}) {
|
| 21 |
const [locale, setLocale] = useState<Locale>(initialLocale);
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
const handleSetLocale = (newLocale: Locale) => {
|
| 24 |
setLocale(newLocale);
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
| 26 |
};
|
| 27 |
|
| 28 |
return (
|
|
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
+
import {
|
| 4 |
+
createContext,
|
| 5 |
+
useContext,
|
| 6 |
+
useEffect,
|
| 7 |
+
useState,
|
| 8 |
+
type ReactNode,
|
| 9 |
+
} from "react";
|
| 10 |
|
| 11 |
import type { Locale } from "@/core/i18n";
|
| 12 |
+
import { getLocaleFromCookie, setLocaleInCookie } from "@/core/i18n/cookies";
|
| 13 |
+
import { detectLocale, normalizeLocale } from "@/core/i18n/locale";
|
| 14 |
|
| 15 |
export interface I18nContextType {
|
| 16 |
locale: Locale;
|
|
|
|
| 18 |
}
|
| 19 |
|
| 20 |
export const I18nContext = createContext<I18nContextType | null>(null);
|
| 21 |
+
const LOCALE_STORAGE_KEY = "deerflow_locale";
|
| 22 |
|
| 23 |
export function I18nProvider({
|
| 24 |
children,
|
|
|
|
| 29 |
}) {
|
| 30 |
const [locale, setLocale] = useState<Locale>(initialLocale);
|
| 31 |
|
| 32 |
+
useEffect(() => {
|
| 33 |
+
// Restore locale once at app startup. LocalStorage works even when
|
| 34 |
+
// third-party cookies are restricted in embedded iframe contexts.
|
| 35 |
+
const stored =
|
| 36 |
+
typeof window === "undefined"
|
| 37 |
+
? null
|
| 38 |
+
: window.localStorage.getItem(LOCALE_STORAGE_KEY);
|
| 39 |
+
const cookieLocale = getLocaleFromCookie();
|
| 40 |
+
|
| 41 |
+
if (stored) {
|
| 42 |
+
const normalizedStored = normalizeLocale(stored);
|
| 43 |
+
setLocale(normalizedStored);
|
| 44 |
+
setLocaleInCookie(normalizedStored);
|
| 45 |
+
return;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
if (cookieLocale) {
|
| 49 |
+
const normalizedCookie = normalizeLocale(cookieLocale);
|
| 50 |
+
setLocale(normalizedCookie);
|
| 51 |
+
if (cookieLocale !== normalizedCookie) {
|
| 52 |
+
setLocaleInCookie(normalizedCookie);
|
| 53 |
+
}
|
| 54 |
+
if (typeof window !== "undefined") {
|
| 55 |
+
window.localStorage.setItem(LOCALE_STORAGE_KEY, normalizedCookie);
|
| 56 |
+
}
|
| 57 |
+
return;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
const detected = detectLocale();
|
| 61 |
+
setLocale(detected);
|
| 62 |
+
setLocaleInCookie(detected);
|
| 63 |
+
if (typeof window !== "undefined") {
|
| 64 |
+
window.localStorage.setItem(LOCALE_STORAGE_KEY, detected);
|
| 65 |
+
}
|
| 66 |
+
}, []);
|
| 67 |
+
|
| 68 |
const handleSetLocale = (newLocale: Locale) => {
|
| 69 |
setLocale(newLocale);
|
| 70 |
+
setLocaleInCookie(newLocale);
|
| 71 |
+
if (typeof window !== "undefined") {
|
| 72 |
+
window.localStorage.setItem(LOCALE_STORAGE_KEY, newLocale);
|
| 73 |
+
}
|
| 74 |
};
|
| 75 |
|
| 76 |
return (
|