mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-16 05:13:36 +00:00
Guard language switching failures (#1002)
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { describe, expect, it, beforeEach } from "vitest";
|
||||
|
||||
import { changeAppLanguage, normalizeLanguageCode } from "./i18n";
|
||||
|
||||
describe("i18n language handling", () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it("normalizes persisted desktop language codes", () => {
|
||||
expect(normalizeLanguageCode("zh_CN")).toBe("zh-CN");
|
||||
expect(normalizeLanguageCode("pt_br")).toBe("pt-BR");
|
||||
expect(normalizeLanguageCode("EN-us")).toBe("en");
|
||||
expect(normalizeLanguageCode("unknown")).toBe("en");
|
||||
});
|
||||
|
||||
it("stores the normalized language after a successful switch", async () => {
|
||||
await expect(changeAppLanguage("zh_CN")).resolves.toBe("zh-CN");
|
||||
expect(localStorage.getItem("i18nextLng")).toBe("zh-CN");
|
||||
});
|
||||
});
|
||||
+29
-10
@@ -43,31 +43,43 @@ const localeLoaders = {
|
||||
"zh-TW": () => import("../locales/translated/zh_TW.json"),
|
||||
} satisfies Record<string, () => Promise<LocaleModule>>;
|
||||
|
||||
const supportedLngs = ["en", ...Object.keys(localeLoaders)];
|
||||
export const supportedLngs = ["en", ...Object.keys(localeLoaders)];
|
||||
|
||||
export function normalizeLanguageCode(language?: string | null): string {
|
||||
if (!language) return "en";
|
||||
|
||||
const normalized = language.replaceAll("_", "-");
|
||||
if (supportedLngs.includes(normalized)) return normalized;
|
||||
|
||||
const exactMatch = supportedLngs.find(
|
||||
(supported) => supported.toLowerCase() === normalized.toLowerCase(),
|
||||
);
|
||||
if (exactMatch) return exactMatch;
|
||||
|
||||
const baseLanguage = normalized.split("-")[0];
|
||||
return supportedLngs.includes(baseLanguage) ? baseLanguage : "en";
|
||||
}
|
||||
|
||||
const localeBackend: BackendModule = {
|
||||
type: "backend",
|
||||
init: () => {},
|
||||
read: (language, _namespace, callback) => {
|
||||
if (language === "en") {
|
||||
const normalizedLanguage = normalizeLanguageCode(language);
|
||||
|
||||
if (normalizedLanguage === "en") {
|
||||
callback(null, enTranslation);
|
||||
return;
|
||||
}
|
||||
|
||||
const loadLocale = localeLoaders[language];
|
||||
const loadLocale = localeLoaders[normalizedLanguage];
|
||||
if (!loadLocale) {
|
||||
callback(new Error(`Unsupported language: ${language}`), false);
|
||||
callback(null, enTranslation);
|
||||
return;
|
||||
}
|
||||
|
||||
loadLocale()
|
||||
.then((module) => callback(null, module.default))
|
||||
.catch((error: unknown) => {
|
||||
callback(
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
false,
|
||||
);
|
||||
});
|
||||
.catch(() => callback(null, enTranslation));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -104,4 +116,11 @@ i18n
|
||||
},
|
||||
});
|
||||
|
||||
export async function changeAppLanguage(language: string): Promise<string> {
|
||||
const normalizedLanguage = normalizeLanguageCode(language);
|
||||
await i18n.changeLanguage(normalizedLanguage);
|
||||
localStorage.setItem("i18nextLng", normalizedLanguage);
|
||||
return normalizedLanguage;
|
||||
}
|
||||
|
||||
export default i18n;
|
||||
|
||||
Reference in New Issue
Block a user