133 lines
4.0 KiB
JavaScript
133 lines
4.0 KiB
JavaScript
import { REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER } from "../core/constants.js";
|
|
import { isRequestServerIsland, requestIs404Or500 } from "../core/routing/match.js";
|
|
import {
|
|
normalizeTheLocale,
|
|
notFound,
|
|
redirectToDefaultLocale,
|
|
redirectToFallback,
|
|
requestHasLocale
|
|
} from "./index.js";
|
|
function createI18nMiddleware(i18n, base, trailingSlash, format) {
|
|
if (!i18n) return (_, next) => next();
|
|
const payload = {
|
|
...i18n,
|
|
trailingSlash,
|
|
base,
|
|
format,
|
|
domains: {}
|
|
};
|
|
const _redirectToDefaultLocale = redirectToDefaultLocale(payload);
|
|
const _noFoundForNonLocaleRoute = notFound(payload);
|
|
const _requestHasLocale = requestHasLocale(payload.locales);
|
|
const _redirectToFallback = redirectToFallback(payload);
|
|
const prefixAlways = (context, response) => {
|
|
const url = context.url;
|
|
if (url.pathname === base + "/" || url.pathname === base) {
|
|
return _redirectToDefaultLocale(context);
|
|
} else if (!_requestHasLocale(context)) {
|
|
return _noFoundForNonLocaleRoute(context, response);
|
|
}
|
|
return void 0;
|
|
};
|
|
const prefixOtherLocales = (context, response) => {
|
|
let pathnameContainsDefaultLocale = false;
|
|
const url = context.url;
|
|
for (const segment of url.pathname.split("/")) {
|
|
if (normalizeTheLocale(segment) === normalizeTheLocale(i18n.defaultLocale)) {
|
|
pathnameContainsDefaultLocale = true;
|
|
break;
|
|
}
|
|
}
|
|
if (pathnameContainsDefaultLocale) {
|
|
const newLocation = url.pathname.replace(`/${i18n.defaultLocale}`, "");
|
|
response.headers.set("Location", newLocation);
|
|
return _noFoundForNonLocaleRoute(context);
|
|
}
|
|
return void 0;
|
|
};
|
|
return async (context, next) => {
|
|
const response = await next();
|
|
const type = response.headers.get(ROUTE_TYPE_HEADER);
|
|
const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
|
|
if (isReroute === "no" && typeof i18n.fallback === "undefined") {
|
|
return response;
|
|
}
|
|
if (type !== "page" && type !== "fallback") {
|
|
return response;
|
|
}
|
|
if (requestIs404Or500(context.request, base)) {
|
|
return response;
|
|
}
|
|
if (isRequestServerIsland(context.request, base)) {
|
|
return response;
|
|
}
|
|
const { currentLocale } = context;
|
|
switch (i18n.strategy) {
|
|
// NOTE: theoretically, we should never hit this code path
|
|
case "manual": {
|
|
return response;
|
|
}
|
|
case "domains-prefix-other-locales": {
|
|
if (localeHasntDomain(i18n, currentLocale)) {
|
|
const result = prefixOtherLocales(context, response);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case "pathname-prefix-other-locales": {
|
|
const result = prefixOtherLocales(context, response);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
break;
|
|
}
|
|
case "domains-prefix-always-no-redirect": {
|
|
if (localeHasntDomain(i18n, currentLocale)) {
|
|
const result = _noFoundForNonLocaleRoute(context, response);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case "pathname-prefix-always-no-redirect": {
|
|
const result = _noFoundForNonLocaleRoute(context, response);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
break;
|
|
}
|
|
case "pathname-prefix-always": {
|
|
const result = prefixAlways(context, response);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
break;
|
|
}
|
|
case "domains-prefix-always": {
|
|
if (localeHasntDomain(i18n, currentLocale)) {
|
|
const result = prefixAlways(context, response);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return _redirectToFallback(context, response);
|
|
};
|
|
}
|
|
function localeHasntDomain(i18n, currentLocale) {
|
|
for (const domainLocale of Object.values(i18n.domainLookupTable)) {
|
|
if (domainLocale === currentLocale) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
export {
|
|
createI18nMiddleware
|
|
};
|