| import { defineMiddleware } from "astro:middleware" |
| import { exactLocale, matchLocale } from "./i18n/locales" |
|
|
| function docsAlias(pathname: string) { |
| const hit = /^\/docs\/([^/]+)(\/.*)?$/.exec(pathname) |
| if (!hit) return null |
|
|
| const value = hit[1] ?? "" |
| const tail = hit[2] ?? "" |
| const locale = exactLocale(value) |
| if (!locale) return null |
|
|
| const next = locale === "root" ? `/docs${tail}` : `/docs/${locale}${tail}` |
| if (next === pathname) return null |
| return { |
| path: next, |
| locale, |
| } |
| } |
|
|
| function cookie(locale: string) { |
| const value = locale === "root" ? "en" : locale |
| return `oc_locale=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax` |
| } |
|
|
| function redirect(url: URL, path: string, locale?: string) { |
| const next = new URL(url.toString()) |
| next.pathname = path |
| const headers = new Headers({ |
| Location: next.toString(), |
| }) |
| if (locale) headers.set("Set-Cookie", cookie(locale)) |
| return new Response(null, { |
| status: 302, |
| headers, |
| }) |
| } |
|
|
| function localeFromCookie(header: string | null) { |
| if (!header) return null |
| const raw = header |
| .split(";") |
| .map((x) => x.trim()) |
| .find((x) => x.startsWith("oc_locale=")) |
| ?.slice("oc_locale=".length) |
| if (!raw) return null |
| return matchLocale(raw) |
| } |
|
|
| function localeFromAcceptLanguage(header: string | null) { |
| if (!header) return "root" |
|
|
| const items = header |
| .split(",") |
| .map((raw) => raw.trim()) |
| .filter(Boolean) |
| .map((raw) => { |
| const parts = raw.split(";").map((x) => x.trim()) |
| const lang = parts[0] ?? "" |
| const q = parts |
| .slice(1) |
| .find((x) => x.startsWith("q=")) |
| ?.slice(2) |
| return { |
| lang, |
| q: q ? Number.parseFloat(q) : 1, |
| } |
| }) |
| .sort((a, b) => b.q - a.q) |
|
|
| const locale = items |
| .map((item) => item.lang) |
| .filter((lang) => lang && lang !== "*") |
| .map((lang) => matchLocale(lang)) |
| .find((lang) => lang) |
|
|
| return locale ?? "root" |
| } |
|
|
| export const onRequest = defineMiddleware((ctx, next) => { |
| const alias = docsAlias(ctx.url.pathname) |
| if (alias) { |
| return redirect(ctx.url, alias.path, alias.locale) |
| } |
|
|
| if (ctx.url.pathname !== "/docs" && ctx.url.pathname !== "/docs/") return next() |
|
|
| const locale = |
| localeFromCookie(ctx.request.headers.get("cookie")) ?? |
| localeFromAcceptLanguage(ctx.request.headers.get("accept-language")) |
| if (!locale || locale === "root") return next() |
|
|
| return redirect(ctx.url, `/docs/${locale}/`) |
| }) |
|
|