lib/protocol/http/header/accept_language.rb
# frozen_string_literal: true # Released under the MIT License. # Copyright, 2025, by Samuel Williams. require_relative "split" require_relative "quoted_string" require_relative "../error" module Protocol module HTTP module Header # The `accept-language` header represents a list of languages that the client can accept. class AcceptLanguage < Split ParseError = Class.new(Error) # https://tools.ietf.org/html/rfc3066#section-2.1 NAME = /\*|[A-Z]{1,8}(-[A-Z0-9]{1,8})*/i # https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.9 QVALUE = /0(\.[0-9]{0,6})?|1(\.[0]{0,6})?/ # https://greenbytes.de/tech/webdav/rfc7231.html#quality.values LANGUAGE = /\A(?<name>#{NAME})(\s*;\s*q=(?<q>#{QVALUE}))?\z/ Language = Struct.new(:name, :q) do def quality_factor (q || 1.0).to_f end def <=> other other.quality_factor <=> self.quality_factor end end # Parse the `accept-language` header value into a list of languages. # # @returns [Array(Charset)] the list of character sets and their associated quality factors. def languages self.map do |value| if match = value.match(LANGUAGE) Language.new(match[:name], match[:q]) else raise ParseError.new("Could not parse language: #{value.inspect}") end end end end end end end