Project

General

Profile

« Previous | Next » 

Revision da98a035

Added by Marc Dequènes over 15 years ago

  • ID da98a03580322c76f904995eb845c1bb48ff80f7

[evol] RFC2616 Accept-Language field support #2 (moved out of cyborghood namespace btw)

View differences:

lib/cyborghood/language.rb
require 'locale'
module CyborgHood
# RFC2616 Accept-Language field
# (used in RFC2798 'preferredLanguage' attribute type)
class AcceptLanguage
LANG_RANGE_Q_PATTERN="([a-z]{1,8}(-[a-z]{1,8})*(;q=)|\*)"
ACCEPT_LANG_PATTERN="#{LANG_RANGE_Q_PATTERN}( *, *#{LANG_RANGE_Q_PATTERN})*"
attr_reader :sorted_lang_list
private :new
def initialize(sorted_lang_list)
@sorted_lang_list = sorted_lang_list
end
def self.parse(accept_language_list)
return nil unless accept_language_list =~ Regexp.new(ACCEPT_LANG_PATTERN, Regexp::EXTENDED | Regexp::IGNORECASE)
list = accept_language_list.split(',').collect do |lang_range_q|
lang_range, quality = lang_range_q.split(';')
quality ||= 1
[Locale::Object.new(lang_range), quality]
end
sorted_list = list.sort do |l1, l2|
r = l1[1] <=> l2[1]
# if quality is equal, then prefer the most specific language tag
if r == 0
l1[0].to_iso3066.size <=> l2[0].to_iso3066.size
else
r
end
end
new(sorted_list)
end
def reduce(available_language_list)
# return a new object with ordered matching language tags
end
end
end
lib/language.rb
require 'locale'
module HTTPHeaders
# RFC2616 Accept-Language field
# (also used in RFC2798 'preferredLanguage' LDAP attribute type)
class AcceptLanguage
LANG_RANGE_Q_PATTERN="([a-z]{1,8}(-[a-z]{1,8})*(;q=)|\*)"
ACCEPT_LANG_PATTERN="#{LANG_RANGE_Q_PATTERN}( *, *#{LANG_RANGE_Q_PATTERN})*"
attr_reader :sorted_language_list
private :new
def initialize(sorted_language_list)
# if no preference list, then assume that all languages are equally acceptable
@sorted_language_list = sorted_language_list.empty? ? ["*"] : sorted_language_list
end
def self.parse(accept_language_list)
return nil unless accept_language_list =~ Regexp.new(ACCEPT_LANG_PATTERN, Regexp::EXTENDED | Regexp::IGNORECASE)
list = accept_language_list.split(',').collect do |lang_range_q|
lang_range, quality = lang_range_q.split(';')
quality ||= 1
LanguageRange.new(lang_range, quality)
end
new(list.sort)
end
def reduce(available_language_list)
tag_list = available_language_list.collect do |tag|
l_tag = Locale::Object.new(tag)
match = []
@sorted_language_list.each do |lr|
match << lr if lr.range == "*" or
lr.range == l_tag.to_iso3066 or
(lr.range + "-" == l_tag.to_iso3066[0, lr.range.size + 1])
end
match.sort_by {|lr| lr.range.size }
quality = match.empty? ? 0 : match.last.quality
LanguageRange.new(l_tag, quality)
end
acceptable_tag_list = tag_list.select {|lt| lr.quality != 0 }
acceptable_tag_list.sort
end
end
class LanguageRange
include Sortable
attr_reader :quality
def initialize(lang_range, quality)
@l_lang_range = (lang_range.is_a? Locale::Object) ? lang_range : Locale::Object.new(lang_range)
@quality = quality.to_f
end
def range
@l_lang_range.to_iso3066
end
def <=>(lr)
r = self.quality <=> lr.quality
# if quality is equal, then prefer the most specific language range
if r == 0
self.range.size <=> lr.range.size
else
r
end
end
end
end

Also available in: Unified diff