class AcceptLanguage::Matcher

@note Compare an Accept-Language header value with your application's

supported languages to find the common languages that could be presented
to a user.

@example

Matcher.new("da" => 1.0, "en-GB" => 0.8, "en" => 0.7).call(:ug, :kk, :ru, :en) # => :en
Matcher.new("da" => 1.0, "en-GB" => 0.8, "en" => 0.7).call(:fr, :en, :"en-GB") # => :"en-GB"

Attributes

excluded_langtags[R]
preferred_langtags[R]

Public Class Methods

new(**languages_range) click to toggle source

@param [Hash<String, BigDecimal>] languages_range A list of accepted

languages with their respective qualities.
# File lib/accept_language/matcher.rb, line 15
def initialize(**languages_range)
  @excluded_langtags = Set[]
  langtags = []

  languages_range.select do |langtag, quality|
    if quality.zero?
      @excluded_langtags << langtag unless langtag.eql?("*")
    else
      level = (quality * 1_000).to_i
      langtags[level] = langtag
    end
  end

  @preferred_langtags = langtags.compact.reverse
end

Public Instance Methods

call(*available_langtags) click to toggle source

@param [Array<String, Symbol>] available_langtags The list of available

languages.

@example Uyghur, Kazakh, Russian and English languages are available.

call(:ug, :kk, :ru, :en)

@return [String, Symbol, nil] The language that best matches.

# File lib/accept_language/matcher.rb, line 36
def call(*available_langtags)
  available_langtags = drop_unacceptable(*available_langtags)

  preferred_langtags.each do |preferred_tag|
    if preferred_tag.eql?("*")
      langtag = any_other_langtag(*available_langtags)
      return langtag unless langtag.nil?
    else
      available_langtags.each do |available_langtag|
        return available_langtag if available_langtag.match?(/\A#{preferred_tag}/i)
      end
    end
  end

  nil
end

Private Instance Methods

any_other_langtag(*available_langtags) click to toggle source
# File lib/accept_language/matcher.rb, line 55
def any_other_langtag(*available_langtags)
  available_langtags.find do |available_langtag|
    langtags = preferred_langtags - ["*"]

    langtags.none? do |langtag|
      available_langtag.match?(/\A#{langtag}/i)
    end
  end
end
drop_unacceptable(*available_langtags) click to toggle source
# File lib/accept_language/matcher.rb, line 65
def drop_unacceptable(*available_langtags)
  available_langtags.inject(Set[]) do |langtags, available_langtag|
    next langtags if unacceptable?(available_langtag)

    langtags + Set[available_langtag]
  end
end
unacceptable?(langtag) click to toggle source
# File lib/accept_language/matcher.rb, line 73
def unacceptable?(langtag)
  excluded_langtags.any? do |excluded_langtag|
    langtag.match?(/\A#{excluded_langtag}/i)
  end
end