Created
August 30, 2023 16:43
-
-
Save Recursing/f739303a3fc3397132b2ae7e06cfe5ed to your computer and use it in GitHub Desktop.
Parse accept-language header. Somehow I couldn't find a good enough implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Adapted from https://github.com/vercel/next.js/blob/dda62b693e3e9cf9fd566085e7372c46c16fa14a/packages/next/src/server/accept-header.ts#L13 | |
interface Selection { | |
pos: number | |
q: number | |
token: string | |
} | |
export function acceptedLanguages(rawHeader: string) { | |
const header = rawHeader.replace(/[ \t]/g, '') | |
const parts = header.split(',') | |
const selections: Selection[] = [] | |
for (let i = 0; i < parts.length; ++i) { | |
const part = parts[i] | |
if (!part) { | |
continue | |
} | |
const params = part.split(';') | |
if (params.length > 2) { | |
console.error(`Invalid 'accept-language' header`, rawHeader) | |
continue | |
} | |
const token = params[0].toLowerCase() | |
if (!token) { | |
console.error(`Invalid 'accept-language' header`, rawHeader) | |
continue | |
} | |
const selection: Selection = { token, pos: i, q: 1 } | |
if (params.length === 2) { | |
const q = params[1] | |
const [key, value] = q.split('=') | |
if (!value || (key !== 'q' && key !== 'Q')) { | |
console.error(`Invalid 'accept-language' header`, rawHeader) | |
continue | |
} | |
const score = parseFloat(value) | |
if (score === 0) { | |
continue | |
} | |
if (Number.isFinite(score) && score <= 1 && score >= 0.001) { | |
selection.q = score | |
} | |
} | |
selections.push(selection) | |
} | |
selections.sort((a, b) => { | |
if (b.q !== a.q) { | |
return b.q - a.q | |
} | |
return a.pos - b.pos | |
}) | |
return selections.map((selection) => selection.token) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment