import { describe, expect, it } from "vitest"; import { getTranslation, loadTranslations, mergeWithEnglishFallback } from "./server"; describe("mergeWithEnglishFallback", () => { it("should merge locale translations with English fallback", () => { const localeTranslations = { // Override some existing English keys hello: "Bonjour", goodbye: "Au revoir", // Add new locale-specific keys locale_only: "French only text", }; const result = mergeWithEnglishFallback(localeTranslations); // Check that locale translations override English expect(result.hello).toBe("Bonjour"); expect(result.goodbye).toBe("Au revoir"); // Check that locale-specific keys are preserved expect(result.locale_only).toBe("French only text"); // Check that English fallback keys are present (using actual keys from the real file) expect(result).toHaveProperty("welcome"); expect(result).toHaveProperty("cancel"); // Verify the structure - should have both English and locale keys expect(Object.keys(result)).toContain("hello"); // overridden expect(Object.keys(result)).toContain("locale_only"); // locale-specific expect(Object.keys(result).length).toBeGreaterThan(3); // Should have many keys from English }); it("should use English translations as fallback when locale translations are empty", () => { const localeTranslations = {}; const result = mergeWithEnglishFallback(localeTranslations); // Should return all English translations expect(result).toHaveProperty("welcome"); expect(result).toHaveProperty("cancel"); expect(Object.keys(result).length).toBeGreaterThan(100); // English file has many keys }); it("should prioritize locale translations over English when keys overlap", () => { const localeTranslations = { welcome: "Bienvenido", cancel: "Cancelar", }; const result = mergeWithEnglishFallback(localeTranslations); // Spanish should override English expect(result.welcome).toBe("Bienvenido"); expect(result.cancel).toBe("Cancelar"); // Should still have other English keys expect(Object.keys(result).length).toBeGreaterThan(100); }); it("should handle locale translations with additional keys not in English", () => { const localeTranslations = { // Override existing English key welcome: "Ciao", // Add new keys not in English italian_greeting: "Buongiorno", italian_phrase: "Come stai?", }; const result = mergeWithEnglishFallback(localeTranslations); // Check overridden key expect(result.welcome).toBe("Ciao"); // Check Italian-specific keys expect(result.italian_greeting).toBe("Buongiorno"); expect(result.italian_phrase).toBe("Come stai?"); // Should have English keys plus the new Italian ones expect(Object.keys(result).length).toBeGreaterThan(100); expect(Object.keys(result)).toContain("italian_greeting"); expect(Object.keys(result)).toContain("italian_phrase"); }); }); describe("loadTranslations", () => { it("returns bundled English translations for locale 'en'", async () => { const result = await loadTranslations("en", "common"); expect(result).toHaveProperty("welcome", "Welcome"); expect(result).toHaveProperty("cancel", "Cancel"); expect(Object.keys(result).length).toBeGreaterThan(100); }); it("returns French translations merged with English fallback", async () => { const result = await loadTranslations("fr", "common"); expect(result).toHaveProperty("welcome", "Bienvenue"); expect(result).toHaveProperty("cancel", "Annuler"); expect(Object.keys(result).length).toBeGreaterThan(100); }); it("aliases 'zh' to 'zh-CN'", async () => { const zhResult = await loadTranslations("zh", "common"); const zhCNResult = await loadTranslations("zh-CN", "common"); expect(zhResult).toEqual(zhCNResult); }); it("falls back to English for unsupported locales", async () => { const result = await loadTranslations("xx-INVALID", "common"); expect(result).toHaveProperty("welcome", "Welcome"); expect(result).toHaveProperty("cancel", "Cancel"); }); it("falls back to 'common' namespace for unsupported namespaces", async () => { const result = await loadTranslations("en", "nonexistent-namespace"); expect(result).toHaveProperty("welcome", "Welcome"); expect(Object.keys(result).length).toBeGreaterThan(100); }); it("returns cached result on subsequent calls for the same locale", async () => { const first = await loadTranslations("de", "common"); const second = await loadTranslations("de", "common"); expect(first).toBe(second); }); it("includes English fallback keys missing from the locale file", async () => { const enResult = await loadTranslations("en", "common"); const frResult = await loadTranslations("fr", "common"); for (const key of Object.keys(enResult)) { expect(frResult).toHaveProperty(key); } }); }); describe("getTranslation", () => { it("returns a function that translates English keys", async () => { const t = await getTranslation("en", "common"); expect(typeof t).toBe("function"); expect(t("welcome")).toBe("Welcome"); expect(t("cancel")).toBe("Cancel"); }); it("returns a function that translates French keys", async () => { const t = await getTranslation("fr", "common"); expect(t("welcome")).toBe("Bienvenue"); expect(t("cancel")).toBe("Annuler"); }); it("returns the key itself for missing translation keys", async () => { const t = await getTranslation("en", "common"); expect(t("this_key_does_not_exist")).toBe("this_key_does_not_exist"); }); it("returns consistent results from cached i18n instance on subsequent calls", async () => { const first = await getTranslation("es", "common"); const second = await getTranslation("es", "common"); expect(first("welcome")).toBe(second("welcome")); expect(first("cancel")).toBe(second("cancel")); }); it("returns different translation functions for different locales", async () => { const enT = await getTranslation("en", "common"); const frT = await getTranslation("fr", "common"); expect(enT("welcome")).not.toBe(frT("welcome")); }); });