Parse, inspect, format, and lightly match HTTP Accept-Language headers.
http-accept-language-kit is a clean-room TypeScript package for apps that need the raw header turned into predictable data. It has no runtime dependencies, no mutable global language registry, and no Node-only APIs.
Try the browser demo: packages.wasta-wocket.fr/http-accept-language-kit.
- TypeScript types are generated from the source.
- ESM-only package with no runtime dependencies.
- Marked as side-effect free for bundlers.
- CI runs
npm ci,typecheck,build, andtest. - Tested on Node.js 20 and 22 with GitHub Actions.
- Browser-friendly implementation with no Node-only APIs.
npm install http-accept-language-kitimport { formatAcceptLanguage, parseAcceptLanguage, pickAcceptedLanguage } from "http-accept-language-kit";
const parsed = parseAcceptLanguage("fr-CA, fr;q=0.8, en-US;q=0.6");
if (parsed.ok) {
console.log(parsed.languages[0]);
// { range: "fr-CA", quality: 1, order: 0, raw: "fr-CA", subtags: ["fr", "CA"] }
}
const selected = pickAcceptedLanguage(parsed.input, ["en-US", "fr-FR"]);
// "fr-FR"
const normalized = formatAcceptLanguage(parsed.languages);
// "fr-CA, fr;q=0.8, en-US;q=0.6"Use this when you want to inspect the header itself before deciding what to do:
- stable diagnostics for malformed ranges, duplicate
qvalues, and wildcard handling; - sorted structured results while preserving original order and raw tokens;
- a tiny matcher for exact, base-language, and wildcard cases;
- browser-friendly code that also works in workers, CLIs, and server middleware.
It is not a full locale negotiation framework and does not try to implement every language matching algorithm from ECMA-402 or BCP 47.
By default, q-values follow HTTP qvalue precision and allow at most three decimal places. Import tools that need to accept looser legacy input can opt into allowExtendedQualityPrecision.
Returns { ok, input, languages, diagnostics }. Valid languages are sorted by quality by default.
const result = parseAcceptLanguage("da, en-GB;q=0.8, en;q=0.7");Formats parsed language items back to a compact header value.
formatAcceptLanguage(result.languages, { precision: 2 });Returns the first supported language matched by quality order. Matching is intentionally small: exact match, base language match, then wildcard.
pickAcceptedLanguage("fr-CA, en;q=0.8", ["en-US", "fr-FR"]);| Option | Default | Description |
|---|---|---|
allowWildcard |
true |
Accept * ranges while still reporting a wildcard diagnostic. |
allowExtendedQualityPrecision |
false |
Accept q-values with more than three decimal places. |
clampQuality |
false |
Clamp out-of-range q values instead of rejecting them. |
keepInvalid |
false |
Include invalid items in languages for UI review flows. |
sort |
true |
Sort by descending q value and then original order. |
| Option | Default | Description |
|---|---|---|
includeQualityOne |
false |
Emit ;q=1 for full-quality ranges. |
precision |
3 |
Maximum decimal places for q values. |
Diagnostics are stable strings intended for logs, UI hints, and tests:
invalid-inputempty-headerempty-iteminvalid-language-rangeinvalid-parameterinvalid-qualityquality-precision-exceededduplicate-qualityquality-clampedwildcard-range
MPL-2.0