diff options
| author | Adam <[email protected]> | 2026-02-09 11:34:35 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-09 11:34:35 -0600 |
| commit | dc53086c1e73d43d3a28fc4cdf161e83d09b1877 (patch) | |
| tree | 45a1d0e38de958d0886a5120b2806b21db74145b /packages/web/src/middleware.ts | |
| parent | f74c0339cc6315f7e7743e26b7eab47ce026c239 (diff) | |
| download | opencode-dc53086c1e73d43d3a28fc4cdf161e83d09b1877.tar.gz opencode-dc53086c1e73d43d3a28fc4cdf161e83d09b1877.zip | |
wip(docs): i18n (#12681)
Diffstat (limited to 'packages/web/src/middleware.ts')
| -rw-r--r-- | packages/web/src/middleware.ts | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/packages/web/src/middleware.ts b/packages/web/src/middleware.ts new file mode 100644 index 000000000..5b2d33666 --- /dev/null +++ b/packages/web/src/middleware.ts @@ -0,0 +1,77 @@ +import { defineMiddleware } from "astro:middleware" +import { 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 = matchLocale(value) + if (!locale) return null + if (locale === "root") return `/docs${tail}` + if (value === locale) return null + + return `/docs/${locale}${tail}` +} + +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) { + const url = new URL(ctx.request.url) + url.pathname = alias + return ctx.redirect(url.toString(), 302) + } + + 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() + + const url = new URL(ctx.request.url) + url.pathname = `/docs/${locale}/` + return ctx.redirect(url.toString(), 302) +}) |
