{"version":3,"file":"locale.mjs","names":[],"sources":["../../src/ui/locale.ts"],"sourcesContent":["export type LocaleOptions<Locale extends string = string> = {\n  locales: readonly Locale[];\n  defaultLocale: Locale;\n  cookieName: string;\n};\n\nexport function readLocaleCookie(cookie: string, cookieName: string): string | undefined {\n  for (const part of cookie.split(\";\")) {\n    const [name, ...valueParts] = part.trim().split(\"=\");\n    if (name !== cookieName) continue;\n    try {\n      return decodeURIComponent(valueParts.join(\"=\"));\n    } catch {\n      return undefined;\n    }\n  }\n  return undefined;\n}\n\nexport function matchLocale<const Locale extends string>(\n  candidate: string | null | undefined,\n  locales: readonly Locale[],\n): Locale | undefined {\n  if (!candidate) return undefined;\n  const normalized = candidate.trim().toLowerCase();\n  const exact = locales.find((locale) => locale.toLowerCase() === normalized);\n  if (exact) return exact;\n  const base = normalized.split(\"-\")[0];\n  return locales.find((locale) => locale.toLowerCase() === base);\n}\n\nexport function readAcceptLanguage(header: string | null): string[] {\n  return (header ?? \"\")\n    .split(\",\")\n    .map((part, index) => {\n      const [language = \"\", ...parameters] = part.trim().split(\";\");\n      const quality = parameters.find((parameter) => parameter.trim().startsWith(\"q=\"));\n      return { language, quality: quality ? Number(quality.trim().slice(2)) : 1, index };\n    })\n    .filter(({ language, quality }) => language && quality > 0 && quality <= 1)\n    .sort((a, b) => b.quality - a.quality || a.index - b.index)\n    .map(({ language }) => language);\n}\n\nexport function resolveLocale<const Locale extends string>({\n  preferredLocale,\n  cookie,\n  browserLocales,\n  locales,\n  defaultLocale,\n  cookieName,\n}: LocaleOptions<Locale> & {\n  preferredLocale?: string | null;\n  cookie: string;\n  browserLocales: readonly string[];\n}): Locale {\n  const preferred = matchLocale(preferredLocale, locales);\n  if (preferred) return preferred;\n  const saved = matchLocale(readLocaleCookie(cookie, cookieName), locales);\n  if (saved) return saved;\n  for (const browserLocale of browserLocales) {\n    const matched = matchLocale(browserLocale, locales);\n    if (matched) return matched;\n  }\n  return defaultLocale;\n}\n\nexport function serializeLocaleCookie(cookieName: string, locale: string, secure: boolean): string {\n  return `${cookieName}=${encodeURIComponent(locale)}; Path=/; Max-Age=31536000; SameSite=Lax${secure ? \"; Secure\" : \"\"}`;\n}\n"],"mappings":";AAMA,SAAgB,iBAAiB,QAAgB,YAAwC;CACvF,KAAK,MAAM,QAAQ,OAAO,MAAM,GAAG,GAAG;EACpC,MAAM,CAAC,MAAM,GAAG,cAAc,KAAK,KAAK,CAAC,CAAC,MAAM,GAAG;EACnD,IAAI,SAAS,YAAY;EACzB,IAAI;GACF,OAAO,mBAAmB,WAAW,KAAK,GAAG,CAAC;EAChD,QAAQ;GACN;EACF;CACF;AAEF;AAEA,SAAgB,YACd,WACA,SACoB;CACpB,IAAI,CAAC,WAAW,OAAO;CACvB,MAAM,aAAa,UAAU,KAAK,CAAC,CAAC,YAAY;CAChD,MAAM,QAAQ,QAAQ,MAAM,WAAW,OAAO,YAAY,MAAM,UAAU;CAC1E,IAAI,OAAO,OAAO;CAClB,MAAM,OAAO,WAAW,MAAM,GAAG,CAAC,CAAC;CACnC,OAAO,QAAQ,MAAM,WAAW,OAAO,YAAY,MAAM,IAAI;AAC/D;AAEA,SAAgB,mBAAmB,QAAiC;CAClE,QAAQ,UAAU,GAAE,CACjB,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,UAAU;EACpB,MAAM,CAAC,WAAW,IAAI,GAAG,cAAc,KAAK,KAAK,CAAC,CAAC,MAAM,GAAG;EAC5D,MAAM,UAAU,WAAW,MAAM,cAAc,UAAU,KAAK,CAAC,CAAC,WAAW,IAAI,CAAC;EAChF,OAAO;GAAE;GAAU,SAAS,UAAU,OAAO,QAAQ,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI;GAAG;EAAM;CACnF,CAAC,CAAC,CACD,QAAQ,EAAE,UAAU,cAAc,YAAY,UAAU,KAAK,WAAW,CAAC,CAAC,CAC1E,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,CAC1D,KAAK,EAAE,eAAe,QAAQ;AACnC;AAEA,SAAgB,cAA2C,EACzD,iBACA,QACA,gBACA,SACA,eACA,cAKS;CACT,MAAM,YAAY,YAAY,iBAAiB,OAAO;CACtD,IAAI,WAAW,OAAO;CACtB,MAAM,QAAQ,YAAY,iBAAiB,QAAQ,UAAU,GAAG,OAAO;CACvE,IAAI,OAAO,OAAO;CAClB,KAAK,MAAM,iBAAiB,gBAAgB;EAC1C,MAAM,UAAU,YAAY,eAAe,OAAO;EAClD,IAAI,SAAS,OAAO;CACtB;CACA,OAAO;AACT;AAEA,SAAgB,sBAAsB,YAAoB,QAAgB,QAAyB;CACjG,OAAO,GAAG,WAAW,GAAG,mBAAmB,MAAM,EAAE,0CAA0C,SAAS,aAAa;AACrH"}