mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(ui): sync document locale metadata
This commit is contained in:
@@ -19,6 +19,16 @@ type LocaleTranslationLoader = (locale: Locale) => Promise<TranslationMap | null
|
||||
|
||||
export { SUPPORTED_LOCALES, isSupportedLocale };
|
||||
|
||||
const RTL_LOCALES = new Set<Locale>(["ar", "fa"]);
|
||||
|
||||
function syncDocumentLocale(locale: Locale): void {
|
||||
if (typeof document === "undefined") {
|
||||
return;
|
||||
}
|
||||
document.documentElement.lang = locale;
|
||||
document.documentElement.dir = RTL_LOCALES.has(locale) ? "rtl" : "ltr";
|
||||
}
|
||||
|
||||
class I18nManager {
|
||||
private locale: Locale = DEFAULT_LOCALE;
|
||||
private translations: Partial<Record<Locale, TranslationMap>> = { [DEFAULT_LOCALE]: en };
|
||||
@@ -75,6 +85,7 @@ class I18nManager {
|
||||
const initialLocale = this.resolveInitialLocale();
|
||||
if (initialLocale === DEFAULT_LOCALE) {
|
||||
this.locale = DEFAULT_LOCALE;
|
||||
syncDocumentLocale(DEFAULT_LOCALE);
|
||||
return;
|
||||
}
|
||||
// Use the normal locale setter so startup locale loading follows the same
|
||||
@@ -128,6 +139,7 @@ class I18nManager {
|
||||
}
|
||||
this.pendingLocale = null;
|
||||
this.locale = locale;
|
||||
syncDocumentLocale(locale);
|
||||
this.persistLocale(locale);
|
||||
this.notify();
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ async function importFreshTranslate() {
|
||||
);
|
||||
}
|
||||
|
||||
function stubDocumentLocaleMetadata() {
|
||||
const documentElement = { lang: "", dir: "" };
|
||||
vi.stubGlobal("document", { documentElement } as unknown as Document);
|
||||
return documentElement;
|
||||
}
|
||||
|
||||
describe("i18n", () => {
|
||||
function flatten(value: Record<string, string | Record<string, unknown>>, prefix = ""): string[] {
|
||||
return Object.entries(value).flatMap(([key, nested]) => {
|
||||
@@ -135,6 +141,27 @@ describe("i18n", () => {
|
||||
expect(fresh.t("common.health")).toBe("健康状况");
|
||||
});
|
||||
|
||||
it("syncs canonical document locale metadata on startup", async () => {
|
||||
const documentElement = stubDocumentLocaleMetadata();
|
||||
vi.stubGlobal("navigator", { language: "fa-IR" } as Navigator);
|
||||
localStorage.removeItem("openclaw.i18n.locale");
|
||||
|
||||
const fresh = await importFreshTranslate();
|
||||
|
||||
await vi.waitFor(() => expect(fresh.i18n.getLocale()).toBe("fa"));
|
||||
expect(documentElement).toEqual({ lang: "fa", dir: "rtl" });
|
||||
});
|
||||
|
||||
it("syncs document locale metadata when the locale changes", async () => {
|
||||
const documentElement = stubDocumentLocaleMetadata();
|
||||
|
||||
await translate.i18n.setLocale("ar");
|
||||
expect(documentElement).toEqual({ lang: "ar", dir: "rtl" });
|
||||
|
||||
await translate.i18n.setLocale("de");
|
||||
expect(documentElement).toEqual({ lang: "de", dir: "ltr" });
|
||||
});
|
||||
|
||||
it.each([
|
||||
["zh-Hant", "zh-TW"],
|
||||
["zh-Hant-TW", "zh-TW"],
|
||||
|
||||
Reference in New Issue
Block a user