# LOCALIST_VERSION = '0.5' class Localist # no default so internally usable as variables without the accessor class_attr_rw :callback, :strict2616 class_attr_rw :auto_setup do on_init do ENV["RAILS_ENV"].eql?('development') ? true : false end end # no default so internally usable as variables without the accessor class_attr_rw :supported_locales do on_set do |input| # input needs to be passed to setup_assets() because @@supported_locales is not set yet setup_assets(input) if auto_setup input end end class_attr_rw :default_locale do on_init do @@supported_locales.first end on_set do |input| supported?(input) or raise "The locale '#{input}' is not supported by the application." input end end class_attr_rw :symbol do on_init do :locale end end def self.country_code(locale) locale.split('-')[1] end def self.language_code(locale) locale.split('-')[0] end # is the locale supported? def self.supported?(locale) @@supported_locales.include?(locale) end def self.set(locale) if @@callback.nil? return elsif @@callback.is_a?(Proc) @@callback.call(locale) elsif @@callback.is_a?(Symbol) send(@@callback,locale) else raise "Wrong 'callback' type passed: #{Localist.callback.class}. It must be a Symbol or a Proc" end end def self.setup_assets(locales) flags_path = "#{RAILS_ROOT}/public/images/localist/flags" assets_path = "#{RAILS_ROOT}/vendor/plugins/localist/assets" assets_flag_path = "#{assets_path}/famfamfam_flag_icons/png" FileUtils.rm_rf(flags_path) FileUtils.makedirs(flags_path) flag_files = locales.map{|l| "#{assets_flag_path}/#{country_code(l).downcase}.png"} FileUtils.cp(flag_files, flags_path) FileUtils.cp("#{assets_path}/stylesheet.css", "#{RAILS_ROOT}/public/stylesheets/localist/stylesheet.css" ) end # Matching rules defined in RFC 2616, # section 14.4: HTTP/1.1 - Header Field Definitions - Accept-Language # returns the best language match or nil def self.best_match(client_str) # something like "it-IT;q=0.3, en-EN;q=0.5, *" client_str = client_str.dup client_locales = [] client_accepts_any = false client_str.tr_s!(' ', '') client_str.downcase! # case insensitive match client_str.split(/,/).each do |tag| lan, q = tag.split(/;/) q = q.nil? ? 1 : q.sub(/q=/,'').to_f if lan.eql?('*') client_accepts_any = true else client_locales << [ q, lan ] end end client_locales.sort!{|a,b| b[0] <=> a[0]}.map!{|a| a[1]} client_locales.each do |client_loc| @@supported_locales.each do |supported_loc| # client -> supported return supported_loc if client_loc.match(/^#{supported_loc}$/i) || # en-gb -> en-gb supported_loc.match(/^#{client_loc}-/i) || # en -> en-gb client_loc.match(/^#{supported_loc}-/i) # en-gb -> en unless @@strict2616 match_obj = supported_loc.match(/^([^-]+)-/i) unless match_obj.nil? supp_l = match_obj.captures return supported_loc if client_loc.match(/^#{supp_l}-/i) # en-us -> en-gb end end end end client_accepts_any ? default_locale : nil end end