Method: AcceptLanguage::Matcher#initialize

Defined in:
lib/accept_language/matcher.rb

#initialize(**languages_range) ⇒ Matcher

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a new Matcher instance from parsed language preferences.

The initialization process:

  1. Separates excluded tags (+q=0+) from preferred tags (+q > 0+)

  2. Sorts preferred tags by descending quality value

  3. Preserves original order for tags with equal quality (stable sort)

Exclusion Rules

Only specific language tags with q=0 are added to the exclusion set. The wildcard * is explicitly NOT added even when *;q=0 is present, because:

  • Adding * to exclusions would break prefix matching logic

  • *;q=0 semantics are: “no unlisted language is acceptable”

  • This is achieved by having an empty preferred_langtags (no wildcards)

Stable Sorting

Ruby’s sort_by is stable since Ruby 2.0, meaning elements with equal sort keys maintain their relative order. This ensures that when multiple languages have the same quality value, the first one declared in the Accept-Language header wins.

Examples:

Matcher.new("en" => 1000, "fr" => 800, "de" => 0)
# preferred_langtags: ["en", "fr"]
# excluded_langtags: #<Set: {"de"}>

Since:

  • 1.0.0



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/accept_language/matcher.rb', line 190

def initialize(**languages_range)
  @excluded_langtags = ::Set[]

  languages_range.each do |langtag, quality|
    next unless quality.zero? && !wildcard?(langtag)

    # Exclude specific language tags, but NOT the wildcard.
    # When "*;q=0" is specified, all non-listed languages become
    # unacceptable implicitly (they won't match any preferred_langtags).
    # Adding "*" to excluded_langtags would break prefix_match? logic.
    @excluded_langtags << langtag
  end

  # Sort by descending quality. Ruby's sort_by is stable, so languages
  # with identical quality values preserve their original order from
  # the Accept-Language header (first declared = higher priority).
  @preferred_langtags = languages_range
                        .reject { |_, quality| quality.zero? }
                        .sort_by { |_, quality| -quality }
                        .map(&:first)
end