Skip to content

Commit

Permalink
Actually set I18n.locale based on http header
Browse files Browse the repository at this point in the history
  • Loading branch information
pjg committed Aug 9, 2011
1 parent ba28e4c commit 1c6dfbe
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 3 deletions.
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--color
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Locale Detector

This Rails gem makes use of the HTTP_ACCEPT_LANGUAGE http header send by web browsers with every request, to set the `I18n.locale` variable.
When this fails (for example if there is no such http header as is the case for Google bot), it will try to determine the locale based on the toplevel domain suffix (so it will set 'de' for the `example.de` domain).
This Rails gem makes use of the HTTP_ACCEPT_LANGUAGE http header sent by web browsers with every request, to set the `I18n.locale` setting.
When this fails (for example if there is no such http header - as is the case for Google bot), it will try to determine the locale based on the toplevel domain suffix (so it will set 'de' for the `example.de` domain).
When both fail, it will fall back to the `LocaleDetector.fallback_locale`, which is 'en' by default and can be overriden in `config/initializers/locale_detector.rb`.

The HTTP_ACCEPT_LANGUAGE header parser is based on:
https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language.rb


## Installation

Expand Down
12 changes: 11 additions & 1 deletion lib/locale_detector/filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ module Filter
protected

def set_locale
I18n.locale = 'en'
I18n.locale = begin
request.env['HTTP_ACCEPT_LANGUAGE'].split(/\s*,\s*/).collect do |l|
l += ';q=1.0' unless l =~ /;q=\d+\.\d+$/
l.split(';q=')
end.sort do |x,y|
raise "Incorrect format" unless x.first =~ /^[a-z\-]+$/i
y.last.to_f <=> x.last.to_f
end.first.first.gsub(/-[a-z]+$/i, '').downcase
rescue # rescue (anything) from the malformed (or missing) accept language headers
LocaleDetector.fallback_locale
end
end
end
end
4 changes: 4 additions & 0 deletions locale_detector.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ Gem::Specification.new do |s|

s.add_dependency 'rails', ['>= 3.0.0']
s.add_dependency 'i18n', ['>= 0.5.0']
s.add_development_dependency 'guard', ['>= 0.5.0']
s.add_development_dependency 'guard-rspec', ['>= 0.4.0']
s.add_development_dependency 'rspec', ['>= 2.6']
s.add_development_dependency 'rspec-rails', ['>= 2.6']
end
9 changes: 9 additions & 0 deletions spec/locale_detector/fallback_locale_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'spec_helper'

describe LocaleDetector do

subject { LocaleDetector.fallback_locale }

it { should_not be_empty }

end
24 changes: 24 additions & 0 deletions spec/locale_detector/filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'spec_helper'

describe LocaleDetector::Filter do

def set_locale(opts = {})
filter = Object.new.extend(LocaleDetector::Filter)
request = double('request', :env => { 'HTTP_ACCEPT_LANGUAGE' => opts[:language] })
filter.stub(:request).and_return(request)
filter.send(:set_locale)
end

specify { set_locale(:language => nil).should eql(LocaleDetector.fallback_locale) }

specify { set_locale(:language => 'pl').should eql('pl') }

specify { set_locale(:language => 'pl-PL').should eql('pl') }

specify { set_locale(:language => 'pl,en-us;q=0.7,en;q=0.3').should eql('pl') }

specify { set_locale(:language => 'lt,en-us;q=0.8,en;q=0.6,ru;q=0.4,pl;q=0.2').should eql('lt') }

specify { set_locale(:language => 'pl-PL;q=0.1,en-us;q=0.7,en;q=0.3').should eql('en') }

end
9 changes: 9 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$:.unshift(File.dirname(__FILE__))

require 'rails'
require 'locale_detector'

RSpec.configure do |config|
config.mock_with :rspec
end

0 comments on commit 1c6dfbe

Please sign in to comment.