AcceptLanguage is a lightweight, zero-dependency Elixir library for parsing the Accept-Language HTTP header field and matching user preferences against your application’s available locales.
It implements the Basic Filtering matching scheme defined in RFC 4647 Section 3.3.1, with full support for BCP 47 language tags.
Quick example
AcceptLanguage.negotiate("da, en-GB;q=0.8, en;q=0.7", [:en, :da])
# => :da
AcceptLanguage.negotiate("*, en;q=0", [:en, :fr])
# => :fr (any language except English)
AcceptLanguage.negotiate("zh-Hant", [:"zh-Hant-TW", :"zh-Hans-CN"])
# => :"zh-Hant-TW"
What it supports
- Quality values — ranks preferences by q-value, with declaration order as tie-breaker
- Prefix matching —
enmatchesen-US,en-GB, etc., respecting hyphen boundaries - Wildcards —
*matches any language not explicitly listed - Exclusions —
q=0marks languages as not acceptable - BCP 47 — script subtags (
zh-Hant), region codes (es-419), variant subtags (de-1996) - Case-insensitive matching — preserves the original casing of your atoms
Standards compliance
- RFC 7231 §5.3.5 — Accept-Language header field
- RFC 7231 §5.3.1 — Quality values
- RFC 4647 §3.3.1 — Basic Filtering
- BCP 47 — Language tag structure
Other details
- Single public function:
AcceptLanguage.negotiate/2 - Zero dependencies
- Defensive limits against adversarial headers (4 KB field size, 50 range cap)
- Elixir ~> 1.14






















