UNPKG

@inlang/paraglide-js

Version:

[![Inlang-ecosystem compatibility badge](https://cdn.jsdelivr.net/gh/opral/monorepo@main/inlang/assets/md-badges/inlang.svg)](https://inlang.com)

322 lines (321 loc) 11.3 kB
import { newProject } from "@inlang/sdk"; import { expect, test } from "vitest"; import { createParaglide } from "../create-paraglide.js"; test("returns the locale from the cookie", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr"], }, }), strategy: ["cookie"], cookieName: "PARAGLIDE_LOCALE", }); const request = new Request("http://example.com", { headers: { cookie: `PARAGLIDE_LOCALE=fr`, }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("fr"); }); test("returns the locale from the pathname for document requests", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en"], }, }), strategy: ["url", "baseLocale"], urlPatterns: [ { pattern: "https://example.com/:path(.*)", localized: [["en", "https://example.com/en/:path(.*)"]], }, ], }); const request = new Request("https://example.com/en/home", { headers: { "Sec-Fetch-Dest": "document", }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("en"); }); test("returns the baseLocale if no other strategy matches", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en"], }, }), strategy: ["baseLocale"], }); const request = new Request("http://example.com"); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("en"); }); test("throws an error if no locale is found", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en"], }, }), strategy: ["cookie"], }); const request = new Request("http://example.com"); expect(() => runtime.extractLocaleFromRequest(request)).toThrow("No locale found. There is an error in your strategy. Try adding 'baseLocale' as the very last strategy."); }); test("returns the preferred locale from Accept-Language header", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr", "de"], }, }), strategy: ["preferredLanguage", "baseLocale"], }); // simple direct match const request = new Request("http://example.com", { headers: { "Accept-Language": "en-US;q=0.8,fr;q=0.9,de;q=0.6", }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("fr"); // language tag match const request2 = new Request("http://example.com", { headers: { "Accept-Language": "en-US;q=0.8,nl;q=0.9,de;q=0.7", }, }); const locale2 = runtime.extractLocaleFromRequest(request2); // Since "nl" isn't in our locales, and "de" has the highest q-value after "nl" expect(locale2).toBe("en"); // no match const request3 = new Request("http://example.com", { headers: { "Accept-Language": "nl;q=0.9,es;q=0.6", }, }); const locale3 = runtime.extractLocaleFromRequest(request3); expect(locale3).toBe("en"); }); test("should fall back to next strategy when cookie contains invalid locale", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr"], }, }), strategy: ["cookie", "baseLocale"], cookieName: "PARAGLIDE_LOCALE", }); // Request with an invalid locale in cookie const request = new Request("http://example.com", { headers: { cookie: `PARAGLIDE_LOCALE=invalid_locale`, }, }); // Should fall back to baseLocale expect(runtime.extractLocaleFromRequest(request)).toBe("en"); }); test("skips over localStorage strategy as it is not supported on the server", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr"], }, }), strategy: ["localStorage", "baseLocale"], }); const request = new Request("http://example.com"); // expecting baseLocale expect(runtime.extractLocaleFromRequest(request)).toBe("en"); }); test("resolves the locale from the url for all request types", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr"], }, }), strategy: ["url", "baseLocale"], urlPatterns: [ { pattern: "https://example.com/:path(.*)", localized: [ ["en", "https://example.com/en/:path(.*)"], ["fr", "https://example.com/fr/:path(.*)"], ], }, ], }); // Non-document request should still use URL strategy const request = new Request("https://example.com/fr/home", { headers: { "Sec-Fetch-Dest": "something", }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("fr"); }); test("cookie strategy precedes URL strategy for API requests with wildcards", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr", "de"], }, }), strategy: ["cookie", "url", "baseLocale"], cookieName: "PARAGLIDE_LOCALE", urlPatterns: [ { pattern: "https://example.com/:path(.*)", localized: [ ["fr", "https://example.com/fr/:path(.*)"], ["de", "https://example.com/de/:path(.*)"], ["en", "https://example.com/:path(.*)"], ], }, ], }); // API request with cookie should use cookie locale const apiRequestWithCookie = new Request("https://example.com/api/data", { headers: { "Sec-Fetch-Dest": "empty", cookie: "PARAGLIDE_LOCALE=de", }, }); const apiLocale = runtime.extractLocaleFromRequest(apiRequestWithCookie); expect(apiLocale).toBe("de"); // API request without cookie should fall back to URL strategy const apiRequestNoMatch = new Request("https://example.com/api/data", { headers: { "Sec-Fetch-Dest": "empty", }, }); const fallbackLocale = runtime.extractLocaleFromRequest(apiRequestNoMatch); expect(fallbackLocale).toBe("en"); }); // https://github.com/opral/inlang-paraglide-js/issues/436 test("preferredLanguage precedence over url", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "de"], }, }), strategy: ["url", "preferredLanguage"], urlPatterns: [ { pattern: ":protocol://:domain(.*)::port??/:path(.*)?", localized: [ ["de", ":protocol://:domain(.*)::port?/de/:path(.*)?"], ["en", ":protocol://:domain(.*)::port?/en/:path(.*)?"], ], }, ], }); // no locale in url, should use preferredLanguage const request = new Request("https://example.com/home", { headers: { "Sec-Fetch-Dest": "document", "Accept-Language": "de;q=0.9,en;q=0.8", }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("de"); }); test("returns locale from custom strategy", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr", "de"], }, }), strategy: ["custom-header", "baseLocale"], }); // Define a custom strategy that extracts locale from a custom header runtime.defineCustomServerStrategy("custom-header", { getLocale: (request) => request?.headers.get("X-Custom-Locale") ?? undefined, }); const request = new Request("http://example.com", { headers: { "X-Custom-Locale": "fr", }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("fr"); }); test("falls back to next strategy when custom strategy returns undefined", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr"], }, }), strategy: ["custom-fallback", "baseLocale"], }); runtime.defineCustomServerStrategy("custom-fallback", { getLocale: () => undefined, }); const request = new Request("http://example.com"); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("en"); // Should fall back to baseLocale }); test("custom strategy takes precedence over built-in strategies", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr", "de"], }, }), strategy: ["custom-priority", "cookie", "baseLocale"], cookieName: "PARAGLIDE_LOCALE", }); runtime.defineCustomServerStrategy("custom-priority", { getLocale: () => "de", }); const request = new Request("http://example.com", { headers: { cookie: "PARAGLIDE_LOCALE=fr", // Cookie has different locale }, }); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("de"); // Should use custom strategy, not cookie }); test("multiple custom strategies work in order", async () => { const runtime = await createParaglide({ blob: await newProject({ settings: { baseLocale: "en", locales: ["en", "fr", "de"], }, }), strategy: ["custom-first", "custom-second", "baseLocale"], }); runtime.defineCustomServerStrategy("custom-first", { getLocale: () => undefined, }); runtime.defineCustomServerStrategy("custom-second", { getLocale: () => "fr", }); const request = new Request("http://example.com"); const locale = runtime.extractLocaleFromRequest(request); expect(locale).toBe("fr"); // Should use second custom strategy });