98 lines
3.3 KiB
JavaScript
98 lines
3.3 KiB
JavaScript
import { appendForwardSlash } from "@astrojs/internal-helpers/path";
|
|
import { shouldAppendForwardSlash } from "../core/build/util.js";
|
|
import { REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER } from "../core/constants.js";
|
|
import { computeFallbackRoute } from "./fallback.js";
|
|
import { I18nRouter } from "./router.js";
|
|
function createI18nMiddleware(i18n, base, trailingSlash, format) {
|
|
if (!i18n) return (_, next) => next();
|
|
const i18nRouter = new I18nRouter({
|
|
strategy: i18n.strategy,
|
|
defaultLocale: i18n.defaultLocale,
|
|
locales: i18n.locales,
|
|
base,
|
|
domains: i18n.domainLookupTable ? Object.keys(i18n.domainLookupTable).reduce(
|
|
(acc, domain) => {
|
|
const locale = i18n.domainLookupTable[domain];
|
|
if (!acc[domain]) {
|
|
acc[domain] = [];
|
|
}
|
|
acc[domain].push(locale);
|
|
return acc;
|
|
},
|
|
{}
|
|
) : void 0
|
|
});
|
|
return async (context, next) => {
|
|
const response = await next();
|
|
const typeHeader = response.headers.get(ROUTE_TYPE_HEADER);
|
|
const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
|
|
if (isReroute === "no" && typeof i18n.fallback === "undefined") {
|
|
return response;
|
|
}
|
|
if (typeHeader !== "page" && typeHeader !== "fallback") {
|
|
return response;
|
|
}
|
|
const routerContext = {
|
|
currentLocale: context.currentLocale,
|
|
currentDomain: context.url.hostname,
|
|
routeType: typeHeader,
|
|
isReroute: isReroute === "yes"
|
|
};
|
|
const routeDecision = i18nRouter.match(context.url.pathname, routerContext);
|
|
switch (routeDecision.type) {
|
|
case "redirect": {
|
|
let location = routeDecision.location;
|
|
if (shouldAppendForwardSlash(trailingSlash, format)) {
|
|
location = appendForwardSlash(location);
|
|
}
|
|
return context.redirect(location, routeDecision.status);
|
|
}
|
|
case "notFound": {
|
|
if (context.isPrerendered) {
|
|
const prerenderedRes = new Response(response.body, {
|
|
status: 404,
|
|
headers: response.headers
|
|
});
|
|
prerenderedRes.headers.set(REROUTE_DIRECTIVE_HEADER, "no");
|
|
if (routeDecision.location) {
|
|
prerenderedRes.headers.set("Location", routeDecision.location);
|
|
}
|
|
return prerenderedRes;
|
|
}
|
|
const headers = new Headers();
|
|
if (routeDecision.location) {
|
|
headers.set("Location", routeDecision.location);
|
|
}
|
|
return new Response(null, { status: 404, headers });
|
|
}
|
|
case "continue":
|
|
break;
|
|
}
|
|
if (i18n.fallback && i18n.fallbackType) {
|
|
const fallbackDecision = computeFallbackRoute({
|
|
pathname: context.url.pathname,
|
|
responseStatus: response.status,
|
|
currentLocale: context.currentLocale,
|
|
fallback: i18n.fallback,
|
|
fallbackType: i18n.fallbackType,
|
|
locales: i18n.locales,
|
|
defaultLocale: i18n.defaultLocale,
|
|
strategy: i18n.strategy,
|
|
base
|
|
});
|
|
switch (fallbackDecision.type) {
|
|
case "redirect":
|
|
return context.redirect(fallbackDecision.pathname + context.url.search);
|
|
case "rewrite":
|
|
return await context.rewrite(fallbackDecision.pathname + context.url.search);
|
|
case "none":
|
|
break;
|
|
}
|
|
}
|
|
return response;
|
|
};
|
|
}
|
|
export {
|
|
createI18nMiddleware
|
|
};
|