Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 1x 24x 46x 46x 46x 23x 23x 38x 18x 37x 23x 21x 21x 29x 312x 13x 16x 16x 8x 10x | interface AcceptLanguageEntry {
code: string;
quality: number;
}
/** Parses the Accept-Language HTTP header (e.g., "en-US,en;q=0.9,fr;q=0.8"). */
export function parseAcceptLanguage(header: string): AcceptLanguageEntry[] {
return header
.split(",")
.map((item) => {
const [code, q = "1"] = item.trim().split(";q=");
return { code: code, quality: parseFloat(q) };
})
.filter((entry) => entry.code.length > 0);
}
/** Looks up a supported locale based on an Accept-Language HTTP header. */
export function lookupAcceptLanguage(header: string, supportedLocales: string[]): string | undefined {
// Consider accepted locales by descending quality.
const acceptLocales = parseAcceptLanguage(header)
.filter((e) => e.quality > 0) // q=0 should not be matched
.sort((a, b) => b.quality - a.quality)
.map((e) => e.code);
for (const acceptLocale of acceptLocales) {
// RFC 4647 lookup: First check pt-BR, then pt
let possibleLocale = acceptLocale;
while (true) {
for (const supportedLocale of supportedLocales) {
if (
possibleLocale.localeCompare(supportedLocale, undefined, {
sensitivity: "base", // Case-insensitive
}) === 0
) {
return supportedLocale;
}
}
// Strip the last suffix
const lastDashIndex = possibleLocale.lastIndexOf("-");
if (lastDashIndex === -1) break;
possibleLocale = possibleLocale.slice(0, lastDashIndex);
}
}
return undefined;
}
|