diff --git a/Gemfile b/Gemfile index ad89c2a..ea12762 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,5 @@ -source "http://rubygems.org" +source :rubygems -# Specify your gem's dependencies in http_accept_language.gemspec gemspec +gem "test-unit", ">=2.5.1" +gem "rake" diff --git a/lib/http_accept_language.rb b/lib/http_accept_language.rb index f1110ee..275ef7f 100644 --- a/lib/http_accept_language.rb +++ b/lib/http_accept_language.rb @@ -55,11 +55,48 @@ def compatible_language_from(available_languages) end.compact.first end + # Returns a supplied list of available locals without any extra application info + # that may be attached to the locale for storage in the application. + # + # Example: + # [ja_JP-x1, en-US-x4, en_UK-x5, fr-FR-x3] => [ja-JP, en-US, en-UK, fr-FR] + # + def sanitize_available_locales(available_languages) + available_languages.map do |avail| + split_locale = avail.split(/[_-]/) + + split_locale.map do |e| + e unless e.match(/x|[0-9*]/) + end.compact.join("-") + end + end + + # Returns the first of the user preferred languages that is + # also found in available languages. Finds best fit by matching on + # primary language first and secondarily on region. If no matching region is + # found, return the first language in the group matching that primary language. + # + # Example: + # + # request.language_region_compatible(available_languages) + # + def language_region_compatible_from(available_languages) + available_languages = sanitize_available_locales(available_languages) + user_preferred_languages.map do |x| #en-US + lang_group = available_languages.select do |y| # en + y = y.to_s + x.split('-', 2).first == y.split('-', 2).first + end + lang_group.find{|l| l == x} || lang_group.first #en-US, en-UK + end.compact.first + end end -if defined?(ActionDispatch::Request) - ActionDispatch::Request.send :include, HttpAcceptLanguage -elsif defined?(ActionDispatch::AbstractRequest) - ActionDispatch::AbstractRequest.send :include, HttpAcceptLanguage -elsif defined?(ActionDispatch::CgiRequest) - ActionDispatch::CgiRequest.send :include, HttpAcceptLanguage + +if defined?(ActionPack) + classes = if ActionPack::VERSION::MAJOR == 2 + [ActionController::Request, ActionController::CgiRequest] + else + [ActionDispatch::Request] + end + classes.each{|c| c.send :include, HttpAcceptLanguage } end diff --git a/rails/init.rb b/rails/init.rb deleted file mode 100644 index 7d3dba1..0000000 --- a/rails/init.rb +++ /dev/null @@ -1 +0,0 @@ -require "http_accept_language" diff --git a/test/http_accept_language_test.rb b/test/http_accept_language_test.rb index 41c47fd..315252a 100644 --- a/test/http_accept_language_test.rb +++ b/test/http_accept_language_test.rb @@ -2,6 +2,24 @@ require 'http_accept_language' require 'test/unit' +module ActionPack + module VERSION + MAJOR = 3 + end +end + +module ActionDispatch + class Request + end +end + +module ActionController + class CgiRequest + end + class Request + end +end + class MockedCgiRequest include HttpAcceptLanguage def env @@ -37,13 +55,48 @@ def test_should_find_first_compatible_from_user_preferred request.env['HTTP_ACCEPT_LANGUAGE'] = 'en-us,de-de' assert_equal 'en', request.compatible_language_from(%w{de en}) end - + def test_should_accept_symbols_as_available_languages request.env['HTTP_ACCEPT_LANGUAGE'] = 'en-us' assert_equal :"en-HK", request.compatible_language_from([:"en-HK"]) end + def test_should_sanitize_available_language_names + assert_equal ["en-UK", "en-US", "ja-JP", "pt-BR"], request.sanitize_available_locales(%w{en_UK-x3 en-US-x1 ja_JP-x2 pt-BR-x5}) + end + + def test_should_find_most_compatible_language_from_user_preferred + request.env['HTTP_ACCEPT_LANGUAGE'] = 'ja,en-gb,en-us,fr-fr' + assert_equal "ja-JP", request.language_region_compatible_from(%w{en-UK en-US ja-JP}) + end + + def test_should_be_included_into_actionpack_v2 + silence_warnings do + ActionPack::VERSION.const_set(:MAJOR, 2) + end + load "http_accept_language.rb" + + assert_include ActionController::Request.ancestors, HttpAcceptLanguage + assert_include ActionController::CgiRequest.ancestors, HttpAcceptLanguage + end + + def test_should_be_included_into_actionpack_v3 + silence_warnings do + ActionPack::VERSION.const_set(:MAJOR, 3) + end + load "http_accept_language.rb" + assert_include ActionDispatch::Request.ancestors, HttpAcceptLanguage + end + private + + def silence_warnings + old_verbose, $VERBOSE = $VERBOSE, nil + yield + ensure + $VERBOSE = old_verbose + end + def request @request ||= MockedCgiRequest.new end