@inlang/paraglide-js
Version:
[](https://www.npmjs.com/package/@inlang/paraglide-js) [ => {
// @ts-expect-error - global variable definition
globalThis.document = {};
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = { hostname: "example.com" };
globalThis.window.location.reload = vi.fn();
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "de"],
},
}),
strategy: ["cookie"],
cookieName: "PARAGLIDE_LOCALE",
});
globalThis.document.cookie = "PARAGLIDE_LOCALE=en";
runtime.setLocale("de");
// set the locale
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=de; path=/; max-age=34560000");
// reloads the site if window is available
expect(globalThis.window.location.reload).toBeCalled();
});
test("sets the cookie with explicit domain to a different locale navigating subdomain", async () => {
// @ts-expect-error - global variable definition
globalThis.document = {};
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = { hostname: "web.example.com" };
globalThis.window.location.reload = vi.fn();
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "de"],
},
}),
strategy: ["cookie"],
cookieName: "PARAGLIDE_LOCALE",
cookieDomain: "example.com",
});
globalThis.document.cookie = "PARAGLIDE_LOCALE=en";
runtime.setLocale("de");
// set the locale
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=de; path=/; max-age=34560000; domain=example.com");
// reloads the site if window is available
expect(globalThis.window.location.reload).toBeCalled();
});
test("sets the cookie with explicit domain to a different locale navigating domain", async () => {
// @ts-expect-error - global variable definition
globalThis.document = {};
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = { hostname: "example.com" };
globalThis.window.location.reload = vi.fn();
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "de"],
},
}),
strategy: ["cookie"],
cookieName: "PARAGLIDE_LOCALE",
cookieDomain: "example.com",
});
globalThis.document.cookie = "PARAGLIDE_LOCALE=en";
runtime.setLocale("de");
// set the locale
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=de; path=/; max-age=34560000; domain=example.com");
// reloads the site if window is available
expect(globalThis.window.location.reload).toBeCalled();
});
test("url pattern strategy sets the window location", async () => {
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = {};
globalThis.window.location.hostname = "example.com";
globalThis.window.location.reload = vi.fn();
const runtime = await createParaglide({
blob: await newProject({
settings: { baseLocale: "en", locales: ["en", "de"] },
}),
strategy: ["url"],
urlPatterns: [
{
pattern: "https://example.:tld/:path*",
localized: [
["en", "https://example.com/:path*"],
["de", "https://example.de/:path*"],
],
},
],
});
globalThis.window.location.href = "https://example.com/page";
runtime.setLocale("de");
expect(globalThis.window.location.href).toBe("https://example.de/page");
// setting window.location.hostname automatically reloads the page
expect(globalThis.window.location.reload).not.toBeCalled();
});
test("url strategy setLocale normalizes mixed-case explicit locales", async () => {
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = {};
globalThis.window.location.hostname = "example.com";
globalThis.window.location.reload = vi.fn();
const runtime = await createParaglide({
blob: await newProject({
settings: { baseLocale: "en", locales: ["en", "de"] },
}),
strategy: ["url"],
urlPatterns: [
{
pattern: "https://example.:tld/:path*",
localized: [
["en", "https://example.com/:path*"],
["de", "https://example.de/:path*"],
],
},
],
});
globalThis.window.location.href = "https://example.com/page";
runtime.setLocale("DE");
expect(globalThis.window.location.href).toBe("https://example.de/page");
// setting window.location.hostname automatically reloads the page
expect(globalThis.window.location.reload).not.toBeCalled();
});
test("routeStrategies can disable url navigation on matching routes", async () => {
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.document = {};
// @ts-expect-error - global variable definition
globalThis.window.location = {
href: "https://example.com/dashboard",
hostname: "example.com",
reload: vi.fn(),
};
const runtime = await createParaglide({
blob: await newProject({
settings: { baseLocale: "en", locales: ["en", "fr"] },
}),
strategy: ["url", "cookie", "baseLocale"],
cookieName: "PARAGLIDE_LOCALE",
routeStrategies: [
{
match: "/dashboard/:path(.*)?",
strategy: ["cookie", "baseLocale"],
},
],
});
globalThis.document.cookie = "PARAGLIDE_LOCALE=en";
runtime.setLocale("fr");
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=fr; path=/; max-age=34560000");
expect(globalThis.window.location.href).toBe("https://example.com/dashboard");
expect(globalThis.window.location.reload).toBeCalled();
});
// `!document.cookie` was used which returned false for an empty string
test("sets the cookie when it's an empty string", async () => {
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr"],
},
}),
strategy: ["cookie"],
cookieName: "PARAGLIDE_LOCALE",
});
/** @ts-expect-error - client side api */
globalThis.document = { cookie: "" };
runtime.setLocale("en");
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=en; path=/; max-age=34560000");
});
test("when strategy precedes URL, it should set the locale and re-direct to the URL", async () => {
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr"],
},
}),
strategy: ["cookie", "url", "baseLocale"],
cookieName: "PARAGLIDE_LOCALE",
isServer: "false",
urlPatterns: [
{
pattern: "https://example.com/en/:path(.*)?",
localized: [
["en", "https://example.com/en/:path(.*)?"],
["fr", "https://example.com/fr/:path(.*)?"],
],
},
],
});
/** @ts-expect-error - client side api */
globalThis.document = { cookie: "PARAGLIDE_LOCALE=fr" };
globalThis.window = {
location: new URL("https://example.com/fr/some-path"),
};
// Cookie strategy should determine locale as French
expect(runtime.getLocale()).toBe("fr");
runtime.setLocale("en");
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=en; path=/; max-age=34560000");
expect(globalThis.window.location.href).toBe("https://example.com/en/some-path");
});
test("overwriteSetLocale receives the options object", async () => {
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr"],
},
}),
strategy: ["cookie"],
cookieName: "PARAGLIDE_LOCALE",
});
// Provide minimal browser globals to avoid strategy branches failing.
/** @ts-expect-error - browser shim for tests */
globalThis.document = { cookie: "" };
globalThis.window = {
location: {
href: "https://example.com/en",
reload: vi.fn(),
},
};
const spy = vi.fn();
runtime.overwriteSetLocale(spy);
runtime.setLocale("fr", { reload: false });
expect(spy).toHaveBeenCalledWith("fr", { reload: false });
});
// https://github.com/opral/inlang-paraglide-js/issues/430
test("should not reload when setting locale to current locale", async () => {
// @ts-expect-error - global variable definition
globalThis.document = {};
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = { hostname: "example.com" };
globalThis.window.location.reload = vi.fn();
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "de"],
},
}),
strategy: ["cookie"],
cookieName: "PARAGLIDE_LOCALE",
});
globalThis.document.cookie = "PARAGLIDE_LOCALE=en; path=/";
// Setting to the current locale (en)
runtime.setLocale("en");
// Cookie should remain unchanged
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=en; path=/; max-age=34560000");
// Should not trigger a reload
expect(globalThis.window.location.reload).not.toBeCalled();
// Setting to a different locale should still work
runtime.setLocale("de");
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=de; path=/; max-age=34560000");
expect(globalThis.window.location.reload).toBeCalled();
});
test("sets the locale to localStorage", async () => {
// @ts-expect-error - global variable definition
globalThis.localStorage = {
setItem: vi.fn(),
getItem: () => "en",
};
// @ts-expect-error - global variable definition
globalThis.window = {};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "de"],
},
}),
strategy: ["localStorage"],
});
runtime.setLocale("de");
expect(globalThis.localStorage.setItem).toHaveBeenCalledWith("PARAGLIDE_LOCALE", "de");
});
// Test that all strategies set their respective storage mechanisms
test("should set locale in all configured storage mechanisms regardless of which strategy resolved the locale", async () => {
// Setup global objects
// @ts-expect-error - global variable definition
globalThis.document = { cookie: "" };
// @ts-expect-error - global variable definition
globalThis.localStorage = {
setItem: vi.fn(),
getItem: () => null,
};
// @ts-expect-error - global variable definition
globalThis.window = {};
// @ts-expect-error - global variable definition
globalThis.window.location = {};
globalThis.window.location.hostname = "example.com";
globalThis.window.location.href = "https://example.com/en/page";
globalThis.window.location.reload = vi.fn();
// Create runtime with multiple strategies
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "de", "fr"],
},
}),
strategy: ["url", "localStorage", "cookie", "baseLocale"],
cookieName: "PARAGLIDE_LOCALE",
urlPatterns: [
{
pattern: "https://example.com/:locale/:path*",
localized: [
["en", "https://example.com/en/:path*"],
["de", "https://example.com/de/:path*"],
["fr", "https://example.com/fr/:path*"],
],
},
],
});
// Call setLocale
runtime.setLocale("fr");
// Verify that all storage mechanisms are updated
expect(globalThis.window.location.href).toBe("https://example.com/fr/page");
expect(globalThis.localStorage.setItem).toHaveBeenCalledWith("PARAGLIDE_LOCALE", "fr");
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=fr; path=/; max-age=34560000");
});
test("calls setLocale on custom strategy", async () => {
let customLocale = "en";
let setLocaleCalled = false;
globalThis.window = {
location: { reload: vi.fn() },
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-setter", "baseLocale"],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-setter", {
getLocale: () => customLocale,
setLocale: (locale) => {
customLocale = locale;
setLocaleCalled = true;
},
});
runtime.setLocale("fr");
expect(setLocaleCalled).toBe(true);
expect(customLocale).toBe("fr");
expect(globalThis.window.location.reload).toHaveBeenCalled();
});
test("calls setLocale on multiple custom strategies", async () => {
let customLocale1 = "en";
let customLocale2 = "en";
let setLocaleCalled1 = false;
let setLocaleCalled2 = false;
globalThis.window = {
location: { reload: vi.fn() },
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-multi1", "custom-multi2", "baseLocale"],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-multi1", {
getLocale: () => customLocale1,
setLocale: (locale) => {
customLocale1 = locale;
setLocaleCalled1 = true;
},
});
runtime.defineCustomClientStrategy("custom-multi2", {
getLocale: () => customLocale2,
setLocale: (locale) => {
customLocale2 = locale;
setLocaleCalled2 = true;
},
});
runtime.setLocale("de");
expect(setLocaleCalled1).toBe(true);
expect(setLocaleCalled2).toBe(true);
expect(customLocale1).toBe("de");
expect(customLocale2).toBe("de");
});
test("setLocale should return a promise if any custom setLocale function is async", async () => {
let customLocale1 = "en";
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-async", "baseLocale"],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-async", {
getLocale: () => customLocale1,
setLocale: async (locale) => {
customLocale1 = locale;
},
});
const setLocalePromise = runtime.setLocale("de");
const setLocalePromiseWithoutReload = runtime.setLocale("de", {
reload: false,
});
expect(setLocalePromise).toBeInstanceOf(Promise);
expect(setLocalePromiseWithoutReload).toBeInstanceOf(Promise);
});
test("awaits async setLocale functions to resolve in custom strategy", async () => {
let customLocale1 = "en";
globalThis.window = {
location: {
reload: vi.fn(),
},
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-async", "baseLocale"],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-async", {
getLocale: () => customLocale1,
setLocale: async (locale) => {
customLocale1 = locale;
},
});
const setLocalePromise = runtime.setLocale("de");
expect(window.location.reload).not.toHaveBeenCalled();
await setLocalePromise;
// Verify that setLocale resolved before reload was called
expect(window.location.reload).toHaveBeenCalledTimes(1);
expect(customLocale1).toBe("de");
});
test("awaits async setLocale functions to resolve in multiple custom strategies", async () => {
let customLocale1 = "en";
let customLocale2 = "en";
globalThis.window = {
location: {
reload: vi.fn(),
},
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-async1", "custom-async2", "baseLocale"],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-async1", {
getLocale: () => customLocale1,
setLocale: async (locale) => {
customLocale1 = locale;
},
});
runtime.defineCustomClientStrategy("custom-async2", {
getLocale: () => customLocale2,
setLocale: async (locale) => {
customLocale2 = locale;
},
});
const setLocalePromise = runtime.setLocale("de");
expect(window.location.reload).not.toHaveBeenCalled();
await setLocalePromise;
// Verify that setLocale resolved before reload was called
expect(window.location.reload).toHaveBeenCalledTimes(1);
expect(customLocale1).toBe("de");
expect(customLocale2).toBe("de");
});
test("reload should not run if async setLocale function rejects in custom strategy", async () => {
const customLocale1 = "en";
globalThis.window = {
location: {
reload: vi.fn(),
},
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-async", "baseLocale"],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-async", {
getLocale: () => customLocale1,
setLocale: async () => {
throw new Error("fetch error");
},
});
const error = expect(() => runtime.setLocale("de")).rejects;
await error.toThrowError(`Custom strategy "custom-async" setLocale failed.`);
await error.toMatchObject({ cause: { message: "fetch error" } });
// Verify that reload was never called
expect(window.location.reload).toHaveBeenCalledTimes(0);
expect(customLocale1).toBe("en");
});
test("custom strategy setLocale works with cookie and localStorage", async () => {
let customData = "en";
globalThis.document = { cookie: "" };
globalThis.localStorage = {
setItem: vi.fn(),
getItem: () => null,
};
globalThis.window = {
location: {
hostname: "example.com",
reload: vi.fn(),
},
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["custom-api", "localStorage", "cookie", "baseLocale"],
cookieName: "PARAGLIDE_LOCALE",
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-api", {
getLocale: () => customData,
setLocale: (locale) => {
customData = locale;
},
});
runtime.setLocale("fr");
expect(customData).toBe("fr");
expect(globalThis.localStorage.setItem).toHaveBeenCalledWith("PARAGLIDE_LOCALE", "fr");
expect(globalThis.document.cookie).toBe("PARAGLIDE_LOCALE=fr; path=/; max-age=34560000");
});
test("custom strategy setLocale integrates with URL strategy", async () => {
let customStoredLocale = "en";
globalThis.window = {
location: {
hostname: "example.com",
href: "https://example.com/en/page",
reload: vi.fn(),
},
};
const runtime = await createParaglide({
blob: await newProject({
settings: {
baseLocale: "en",
locales: ["en", "fr", "de"],
},
}),
strategy: ["url", "custom-urlIntegration", "baseLocale"],
urlPatterns: [
{
pattern: "https://example.com/:locale/:path*",
localized: [
["en", "https://example.com/en/:path*"],
["fr", "https://example.com/fr/:path*"],
["de", "https://example.com/de/:path*"],
],
},
],
isServer: "false",
});
runtime.defineCustomClientStrategy("custom-urlIntegration", {
getLocale: () => customStoredLocale,
setLocale: (locale) => {
customStoredLocale = locale;
},
});
runtime.setLocale("de");
expect(globalThis.window.location.href).toBe("https://example.com/de/page");
expect(customStoredLocale).toBe("de");
});
//# sourceMappingURL=set-locale.test.js.map