178 lines
6.2 KiB
TypeScript
178 lines
6.2 KiB
TypeScript
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"));
|
|
});
|
|
});
|