Current section
Files
Jump to
Current section
Files
src/header.gleam
import gleam/float
import gleam/list
import gleam/option.{type Option}
import gleam/result
import gleam/string
/// Parses the accept langauge header according to:
/// https://www.rfc-editor.org/rfc/rfc9110#field.accept-language
///
/// e.g. fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
pub fn parse_accept_language_header(
raw_header: String,
) -> List(#(String, Float)) {
let quality_factor = ";q="
raw_header
|> string.replace(" ", "")
|> string.split(",")
|> list.filter(fn(lang) { !string.is_empty(lang) })
|> list.filter_map(fn(lang) {
case string.contains(lang, quality_factor) {
True -> string.split_once(lang, quality_factor)
False -> Ok(#(lang, "1.0"))
}
})
|> list.filter_map(fn(lang_with_priority) {
use priority <- result.try(float.parse(lang_with_priority.1))
Ok(#(lang_with_priority.0, priority))
})
|> list.sort(fn(a, b) { float.compare(a.1, b.1) })
|> list.reverse()
}
pub fn get_first_lang_from_accept_language_header(
raw_header: String,
) -> Option(String) {
let languages_with_priority = parse_accept_language_header(raw_header)
languages_with_priority
|> list.first()
|> option.from_result()
|> option.map(fn(lang_with_priority) { lang_with_priority.0 })
}