205 lines
6.0 KiB
JavaScript
205 lines
6.0 KiB
JavaScript
import { getAllCodes, normalizeTheLocale } from "./index.js";
|
|
function parseLocale(header) {
|
|
if (header === "*") {
|
|
return [{ locale: header, qualityValue: void 0 }];
|
|
}
|
|
const result = [];
|
|
const localeValues = header.split(",").map((str) => str.trim());
|
|
for (const localeValue of localeValues) {
|
|
const split = localeValue.split(";").map((str) => str.trim());
|
|
const localeName = split[0];
|
|
const qualityValue = split[1];
|
|
if (!split) {
|
|
continue;
|
|
}
|
|
if (qualityValue && qualityValue.startsWith("q=")) {
|
|
const qualityValueAsFloat = Number.parseFloat(qualityValue.slice("q=".length));
|
|
if (Number.isNaN(qualityValueAsFloat) || qualityValueAsFloat > 1) {
|
|
result.push({
|
|
locale: localeName,
|
|
qualityValue: void 0
|
|
});
|
|
} else {
|
|
result.push({
|
|
locale: localeName,
|
|
qualityValue: qualityValueAsFloat
|
|
});
|
|
}
|
|
} else {
|
|
result.push({
|
|
locale: localeName,
|
|
qualityValue: void 0
|
|
});
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function sortAndFilterLocales(browserLocaleList, locales) {
|
|
const normalizedLocales = getAllCodes(locales).map(normalizeTheLocale);
|
|
return browserLocaleList.filter((browserLocale) => {
|
|
if (browserLocale.locale !== "*") {
|
|
return normalizedLocales.includes(normalizeTheLocale(browserLocale.locale));
|
|
}
|
|
return true;
|
|
}).sort((a, b) => {
|
|
if (a.qualityValue && b.qualityValue) {
|
|
return Math.sign(b.qualityValue - a.qualityValue);
|
|
}
|
|
return 0;
|
|
});
|
|
}
|
|
function computePreferredLocale(request, locales) {
|
|
const acceptHeader = request.headers.get("Accept-Language");
|
|
let result = void 0;
|
|
if (acceptHeader) {
|
|
const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
|
|
const firstResult = browserLocaleList.at(0);
|
|
if (firstResult && firstResult.locale !== "*") {
|
|
for (const currentLocale of locales) {
|
|
if (typeof currentLocale === "string") {
|
|
if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) {
|
|
result = currentLocale;
|
|
break;
|
|
}
|
|
} else {
|
|
for (const currentCode of currentLocale.codes) {
|
|
if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) {
|
|
result = currentCode;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function computePreferredLocaleList(request, locales) {
|
|
const acceptHeader = request.headers.get("Accept-Language");
|
|
let result = [];
|
|
if (acceptHeader) {
|
|
const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
|
|
if (browserLocaleList.length === 1 && browserLocaleList.at(0).locale === "*") {
|
|
return getAllCodes(locales);
|
|
} else if (browserLocaleList.length > 0) {
|
|
for (const browserLocale of browserLocaleList) {
|
|
for (const loopLocale of locales) {
|
|
if (typeof loopLocale === "string") {
|
|
if (normalizeTheLocale(loopLocale) === normalizeTheLocale(browserLocale.locale)) {
|
|
result.push(loopLocale);
|
|
}
|
|
} else {
|
|
for (const code of loopLocale.codes) {
|
|
if (code === browserLocale.locale) {
|
|
result.push(code);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function computeCurrentLocale(pathname, locales, defaultLocale) {
|
|
for (const segment of pathname.split("/")) {
|
|
for (const locale of locales) {
|
|
if (typeof locale === "string") {
|
|
if (!segment.includes(locale)) continue;
|
|
if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) {
|
|
return locale;
|
|
}
|
|
} else {
|
|
if (locale.path === segment) {
|
|
return locale.codes.at(0);
|
|
} else {
|
|
for (const code of locale.codes) {
|
|
if (normalizeTheLocale(code) === normalizeTheLocale(segment)) {
|
|
return code;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (const locale of locales) {
|
|
if (typeof locale === "string") {
|
|
if (locale === defaultLocale) {
|
|
return locale;
|
|
}
|
|
} else {
|
|
if (locale.path === defaultLocale) {
|
|
return locale.codes.at(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function toRoutingStrategy(routing, domains) {
|
|
let strategy;
|
|
const hasDomains = domains ? Object.keys(domains).length > 0 : false;
|
|
if (routing === "manual") {
|
|
strategy = "manual";
|
|
} else {
|
|
if (!hasDomains) {
|
|
if (routing?.prefixDefaultLocale === true) {
|
|
if (routing.redirectToDefaultLocale) {
|
|
strategy = "pathname-prefix-always";
|
|
} else {
|
|
strategy = "pathname-prefix-always-no-redirect";
|
|
}
|
|
} else {
|
|
strategy = "pathname-prefix-other-locales";
|
|
}
|
|
} else {
|
|
if (routing?.prefixDefaultLocale === true) {
|
|
if (routing.redirectToDefaultLocale) {
|
|
strategy = "domains-prefix-always";
|
|
} else {
|
|
strategy = "domains-prefix-always-no-redirect";
|
|
}
|
|
} else {
|
|
strategy = "domains-prefix-other-locales";
|
|
}
|
|
}
|
|
}
|
|
return strategy;
|
|
}
|
|
const PREFIX_DEFAULT_LOCALE = /* @__PURE__ */ new Set([
|
|
"pathname-prefix-always",
|
|
"domains-prefix-always",
|
|
"pathname-prefix-always-no-redirect",
|
|
"domains-prefix-always-no-redirect"
|
|
]);
|
|
const REDIRECT_TO_DEFAULT_LOCALE = /* @__PURE__ */ new Set([
|
|
"pathname-prefix-always-no-redirect",
|
|
"domains-prefix-always-no-redirect"
|
|
]);
|
|
function fromRoutingStrategy(strategy, fallbackType) {
|
|
let routing;
|
|
if (strategy === "manual") {
|
|
routing = "manual";
|
|
} else {
|
|
routing = {
|
|
prefixDefaultLocale: PREFIX_DEFAULT_LOCALE.has(strategy),
|
|
redirectToDefaultLocale: !REDIRECT_TO_DEFAULT_LOCALE.has(strategy),
|
|
fallbackType
|
|
};
|
|
}
|
|
return routing;
|
|
}
|
|
function toFallbackType(routing) {
|
|
if (routing === "manual") {
|
|
return "rewrite";
|
|
}
|
|
return routing.fallbackType;
|
|
}
|
|
export {
|
|
computeCurrentLocale,
|
|
computePreferredLocale,
|
|
computePreferredLocaleList,
|
|
fromRoutingStrategy,
|
|
parseLocale,
|
|
toFallbackType,
|
|
toRoutingStrategy
|
|
};
|