rack-i18n_locale_switcher 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5 -1
- data/Manifest +1 -1
- data/Rakefile +2 -2
- data/lib/rack/i18n_locale_switcher.rb +98 -26
- data/rack-i18n_locale_switcher.gemspec +10 -13
- data/spec/rack/i18n_locale_switcher_spec.rb +298 -0
- metadata +101 -79
- data/spec/i18n_locale_switcher_spec.rb +0 -131
data/CHANGELOG
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
+
= 0.5.0 / 2011-11-29
|
2
|
+
Added option to redirect to a given URL scheme.
|
3
|
+
Added support for canonical URLs with the default locale.
|
4
|
+
|
1
5
|
= 0.4.0 / 2011-11-26
|
2
|
-
Added support
|
6
|
+
Added support for configuring of sources from which to determine the locale
|
3
7
|
as well as the name of the query parameter.
|
4
8
|
Drop support for TLD since locale can't be reliably inferred from it
|
5
9
|
Code refactoring and better test coverage.
|
data/Manifest
CHANGED
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('rack-i18n_locale_switcher', '0.
|
5
|
+
Echoe.new('rack-i18n_locale_switcher', '0.5.0') do |p|
|
6
6
|
|
7
7
|
p.description = "Detects the current locale from query parameter, path prefix, host or accept header."
|
8
8
|
p.url = "http://github.com/christoph-buente/rack-i18n_locale_switcher"
|
@@ -20,7 +20,7 @@ Echoe.new('rack-i18n_locale_switcher', '0.4.0') do |p|
|
|
20
20
|
*.tmproj
|
21
21
|
}
|
22
22
|
|
23
|
-
p.runtime_dependencies = [ "rack", "i18n"
|
23
|
+
p.runtime_dependencies = [ "rack", "i18n" ]
|
24
24
|
p.development_dependencies = [ "echoe", "rspec", "rack-test" ]
|
25
25
|
end
|
26
26
|
|
@@ -1,12 +1,18 @@
|
|
1
1
|
require 'i18n'
|
2
|
-
# require 'domainatrix'
|
3
2
|
|
4
3
|
module Rack
|
5
4
|
class I18nLocaleSwitcher
|
6
5
|
|
6
|
+
LOCALE_PATTERN = '([a-z]{1,8})(-[a-zA-Z]{1,8})?'.freeze
|
7
|
+
|
8
|
+
SOURCES = [ :param, :path, :host, :header ].freeze
|
9
|
+
REDIRECTS = [ :param, :path, :host ].freeze
|
10
|
+
|
7
11
|
DEFAULT_OPTIONS = {
|
8
|
-
:param
|
9
|
-
:source
|
12
|
+
:param => 'locale',
|
13
|
+
:source => SOURCES,
|
14
|
+
:redirect => nil,
|
15
|
+
:canonical => false
|
10
16
|
}.freeze
|
11
17
|
|
12
18
|
def initialize(app, options = {})
|
@@ -18,54 +24,120 @@ module Rack
|
|
18
24
|
raise ArgumentError, "Invalid option(s) #{ invalid_options.map(&:inspect).join(', ') }"
|
19
25
|
end
|
20
26
|
|
21
|
-
|
22
|
-
|
27
|
+
options = DEFAULT_OPTIONS.merge(options)
|
28
|
+
|
29
|
+
@param = options[:param]
|
30
|
+
@canonical = options[:canonical]
|
31
|
+
|
32
|
+
@sources = options[:source]
|
33
|
+
@sources = Array(@sources) unless @sources.is_a?(Array)
|
34
|
+
|
35
|
+
invalid_sources = @sources - SOURCES
|
36
|
+
|
37
|
+
if invalid_sources.any?
|
38
|
+
raise ArgumentError, "Invalid source(s) #{ invalid_sources.map(&:inspect).join(', ') }"
|
39
|
+
end
|
40
|
+
|
41
|
+
@redirect = options[:redirect]
|
42
|
+
|
43
|
+
unless @redirect.nil? || REDIRECTS.include?(@redirect)
|
44
|
+
raise ArgumentError, "Invalid redirect option #{ @redirect.inspect }"
|
45
|
+
end
|
23
46
|
end
|
24
47
|
|
25
48
|
def call(env)
|
26
49
|
I18n.locale = I18n.default_locale
|
27
50
|
|
28
|
-
|
29
|
-
|
51
|
+
env['PATH_INFO'].gsub!(/([^\/])\/$/, '\1')
|
52
|
+
|
53
|
+
request = Rack::Request.new(env)
|
54
|
+
request_url = request.url
|
55
|
+
|
56
|
+
source = nil
|
57
|
+
@sources.each do |src|
|
58
|
+
locale = send(:"extract_locale_from_#{src}", env)
|
59
|
+
if locale && source.nil?
|
60
|
+
source = src
|
30
61
|
I18n.locale = locale
|
31
|
-
break
|
32
62
|
end
|
33
63
|
end
|
34
|
-
|
64
|
+
|
65
|
+
if @redirect
|
66
|
+
unless @canonical && I18n.locale == I18n.default_locale
|
67
|
+
send(:"set_locale_in_#@redirect", env)
|
68
|
+
end
|
69
|
+
|
70
|
+
if request.url != request_url
|
71
|
+
env['PATH_INFO'] = '' if env['PATH_INFO'] == '/'
|
72
|
+
return [ 301, { 'Location' => request.url }, ["Redirecting"]]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
35
76
|
@app.call(env)
|
36
77
|
end
|
37
78
|
|
38
79
|
private
|
80
|
+
|
81
|
+
def extract_locale_from_param(env)
|
82
|
+
query_string = env['QUERY_STRING'].gsub(/\b#{ @param }=#{ LOCALE_PATTERN }(?:&|$)/, '')
|
39
83
|
|
40
|
-
|
41
|
-
|
42
|
-
|
84
|
+
if locale = available_locale($1, $2)
|
85
|
+
env['QUERY_STRING'] = query_string.gsub(/&$/, '')
|
86
|
+
end
|
87
|
+
locale
|
43
88
|
end
|
44
89
|
|
45
|
-
def
|
46
|
-
env['PATH_INFO']
|
47
|
-
|
90
|
+
def extract_locale_from_path(env)
|
91
|
+
path_info = env['PATH_INFO'].gsub(/^\/#{ LOCALE_PATTERN }\b/, '')
|
92
|
+
|
93
|
+
if locale = available_locale($1, $2)
|
94
|
+
env['PATH_INFO'] = path_info
|
95
|
+
end
|
96
|
+
locale
|
48
97
|
end
|
49
98
|
|
50
|
-
def
|
51
|
-
env['
|
52
|
-
|
99
|
+
def extract_locale_from_host(env)
|
100
|
+
env['HTTP_HOST'] ||= "#{ env['SERVER_NAME'] }:#{ env['SERVER_PORT'] }"
|
101
|
+
|
102
|
+
http_host = env['HTTP_HOST'].gsub(/^#{ LOCALE_PATTERN }\./, '')
|
103
|
+
|
104
|
+
if locale = available_locale($1, $2)
|
105
|
+
env['HTTP_HOST'] = http_host
|
106
|
+
env['SERVER_NAME'] = http_host.gsub(/:\d+$/, '')
|
107
|
+
end
|
108
|
+
locale
|
53
109
|
end
|
54
110
|
|
55
|
-
def
|
56
|
-
locale = nil
|
111
|
+
def extract_locale_from_header(env)
|
112
|
+
locale = nil
|
57
113
|
if accept = env['HTTP_ACCEPT_LANGUAGE']
|
58
|
-
locales = accept.scan(
|
114
|
+
locales = accept.scan(/#{ LOCALE_PATTERN }\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i)
|
59
115
|
locales.sort_by{ |loc| 1 - (loc.last || 1).to_f }.each do |loc|
|
60
|
-
break if locale =
|
116
|
+
break if locale = available_locale(*loc[0,2])
|
61
117
|
end
|
62
|
-
end
|
118
|
+
end
|
63
119
|
locale
|
64
120
|
end
|
121
|
+
|
122
|
+
def set_locale_in_param(env)
|
123
|
+
env['QUERY_STRING'] << '&' unless env['QUERY_STRING'].empty?
|
124
|
+
env['QUERY_STRING'] << "#{ @param }=#{ I18n.locale }"
|
125
|
+
end
|
126
|
+
|
127
|
+
def set_locale_in_path(env)
|
128
|
+
env['PATH_INFO'] = "/#{ I18n.locale }#{ env['PATH_INFO'] }"
|
129
|
+
env['PATH_INFO'].gsub!(/\/$/, '')
|
130
|
+
end
|
131
|
+
|
132
|
+
def set_locale_in_host(env)
|
133
|
+
['HTTP_HOST', 'SERVER_NAME'].each do |key|
|
134
|
+
env[ key ] = "#{ I18n.locale }.#{ env[ key ] }"
|
135
|
+
end
|
136
|
+
end
|
65
137
|
|
66
|
-
def
|
67
|
-
if
|
68
|
-
locale = :"#{
|
138
|
+
def available_locale(language, region)
|
139
|
+
if language
|
140
|
+
locale = :"#{ language.downcase }#{ (region || '').upcase }"
|
69
141
|
locale if I18n.available_locales.include?(locale)
|
70
142
|
end
|
71
143
|
end
|
@@ -1,22 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version = "0.
|
4
|
+
s.name = %q{rack-i18n_locale_switcher}
|
5
|
+
s.version = "0.5.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = ["Christoph B\
|
9
|
-
s.date =
|
10
|
-
s.description =
|
8
|
+
s.authors = ["Christoph B\303\274nte, Andreas Korth"]
|
9
|
+
s.date = %q{2011-11-29}
|
10
|
+
s.description = %q{Detects the current locale from query parameter, path prefix, host or accept header.}
|
11
11
|
s.email = ["info@christophbuente.de", "andreas.korth@gmail.com"]
|
12
12
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "lib/rack/i18n_locale_switcher.rb"]
|
13
|
-
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.md", "Rakefile", "lib/rack/i18n_locale_switcher.rb", "rack-i18n_locale_switcher.gemspec", "spec/i18n_locale_switcher_spec.rb"]
|
14
|
-
s.homepage =
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.md", "Rakefile", "lib/rack/i18n_locale_switcher.rb", "rack-i18n_locale_switcher.gemspec", "spec/rack/i18n_locale_switcher_spec.rb"]
|
14
|
+
s.homepage = %q{http://github.com/christoph-buente/rack-i18n_locale_switcher}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack-i18n_locale_switcher", "--main", "README.md"]
|
16
16
|
s.require_paths = ["lib"]
|
17
|
-
s.rubyforge_project =
|
18
|
-
s.rubygems_version =
|
19
|
-
s.summary =
|
17
|
+
s.rubyforge_project = %q{rack-i18n_locale_switcher}
|
18
|
+
s.rubygems_version = %q{1.6.2}
|
19
|
+
s.summary = %q{Detects the current locale from query parameter, path prefix, host or accept header.}
|
20
20
|
|
21
21
|
if s.respond_to? :specification_version then
|
22
22
|
s.specification_version = 3
|
@@ -24,14 +24,12 @@ Gem::Specification.new do |s|
|
|
24
24
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
25
|
s.add_runtime_dependency(%q<rack>, [">= 0"])
|
26
26
|
s.add_runtime_dependency(%q<i18n>, [">= 0"])
|
27
|
-
s.add_runtime_dependency(%q<domainatrix>, [">= 0"])
|
28
27
|
s.add_development_dependency(%q<echoe>, [">= 0"])
|
29
28
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
30
29
|
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
31
30
|
else
|
32
31
|
s.add_dependency(%q<rack>, [">= 0"])
|
33
32
|
s.add_dependency(%q<i18n>, [">= 0"])
|
34
|
-
s.add_dependency(%q<domainatrix>, [">= 0"])
|
35
33
|
s.add_dependency(%q<echoe>, [">= 0"])
|
36
34
|
s.add_dependency(%q<rspec>, [">= 0"])
|
37
35
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
@@ -39,7 +37,6 @@ Gem::Specification.new do |s|
|
|
39
37
|
else
|
40
38
|
s.add_dependency(%q<rack>, [">= 0"])
|
41
39
|
s.add_dependency(%q<i18n>, [">= 0"])
|
42
|
-
s.add_dependency(%q<domainatrix>, [">= 0"])
|
43
40
|
s.add_dependency(%q<echoe>, [">= 0"])
|
44
41
|
s.add_dependency(%q<rspec>, [">= 0"])
|
45
42
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
@@ -0,0 +1,298 @@
|
|
1
|
+
require 'rack/i18n_locale_switcher'
|
2
|
+
require 'rack/test'
|
3
|
+
|
4
|
+
describe Rack::I18nLocaleSwitcher do
|
5
|
+
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
let :options do
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
|
12
|
+
let :app do
|
13
|
+
opts = options
|
14
|
+
rack = Rack::Builder.new do
|
15
|
+
map "/" do
|
16
|
+
use Rack::I18nLocaleSwitcher, opts
|
17
|
+
run lambda { |env| [200, {}, "Coolness"] }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
rack.to_app
|
21
|
+
end
|
22
|
+
|
23
|
+
before do
|
24
|
+
I18n.available_locales = [:en, :'en-US', :de, :'de-DE', :es]
|
25
|
+
I18n.default_locale = :en
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should fall back to the locale to default locale" do
|
29
|
+
get "http://example.com/some/path"
|
30
|
+
I18n.locale.should eql(I18n.default_locale)
|
31
|
+
|
32
|
+
get "http://www.example.com/"
|
33
|
+
I18n.locale.should eql(I18n.default_locale)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not accept invalid options" do
|
37
|
+
expect {
|
38
|
+
Rack::I18nLocaleSwitcher.new("app", :not_an_option => "foo")
|
39
|
+
}.to raise_error(ArgumentError, "Invalid option(s) :not_an_option")
|
40
|
+
|
41
|
+
expect {
|
42
|
+
Rack::I18nLocaleSwitcher.new("app", :source => [ :not_a_source ])
|
43
|
+
}.to raise_error(ArgumentError, "Invalid source(s) :not_a_source")
|
44
|
+
|
45
|
+
expect {
|
46
|
+
Rack::I18nLocaleSwitcher.new("app", :redirect => :not_a_source)
|
47
|
+
}.to raise_error(ArgumentError, "Invalid redirect option :not_a_source")
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with custom sources" do
|
51
|
+
|
52
|
+
let :options do
|
53
|
+
{ :source => [ :header, :host ] }
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should honor the sequence" do
|
57
|
+
get "http://de.example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "es"}
|
58
|
+
I18n.locale.should eql(:es)
|
59
|
+
|
60
|
+
get "http://de.example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "foo"}
|
61
|
+
I18n.locale.should eql(:de)
|
62
|
+
|
63
|
+
get "http://de.example.com"
|
64
|
+
I18n.locale.should eql(:de)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should ignore other sources" do
|
68
|
+
get "http://example.com?locale=de"
|
69
|
+
I18n.locale.should eql(:en)
|
70
|
+
|
71
|
+
get "http://example.com/de"
|
72
|
+
I18n.locale.should eql(:en)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "request param" do
|
77
|
+
|
78
|
+
it "should set the locale" do
|
79
|
+
get "http://example.com?locale=de"
|
80
|
+
I18n.locale.should eql(:de)
|
81
|
+
|
82
|
+
get "http://example.com?locale=en-US"
|
83
|
+
I18n.locale.should eql(:'en-US')
|
84
|
+
|
85
|
+
get "http://example.com/some/path?foo=bar&locale=es¶m=value"
|
86
|
+
I18n.locale.should eql(:es)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should not set an unavailable locale" do
|
90
|
+
get "http://example.com?locale=xx"
|
91
|
+
I18n.locale.should eql(I18n.default_locale)
|
92
|
+
end
|
93
|
+
|
94
|
+
context "name" do
|
95
|
+
|
96
|
+
let :options do
|
97
|
+
{ :param => "lang" }
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should be configurable" do
|
101
|
+
get "http://example.com?lang=de"
|
102
|
+
I18n.locale.should eql(:de)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "from path prefix " do
|
108
|
+
|
109
|
+
it "should set the I18n locale" do
|
110
|
+
get "http://example.com/de/some/path/"
|
111
|
+
I18n.locale.should eql(:de)
|
112
|
+
|
113
|
+
get "http://example.com/en-us"
|
114
|
+
I18n.locale.should eql(:'en-US')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context "from host" do
|
119
|
+
|
120
|
+
it "should set the I18n locale" do
|
121
|
+
get "http://de.example.com/"
|
122
|
+
I18n.locale.should eql(:de)
|
123
|
+
|
124
|
+
get "http://de-de.example.com/"
|
125
|
+
I18n.locale.should eql(:'de-DE')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "from accept-language header" do
|
130
|
+
|
131
|
+
it "should override the client requested locale" do
|
132
|
+
get "http://example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "de-de,de,en;q=0.5"}
|
133
|
+
I18n.locale.should eql(:'de-DE')
|
134
|
+
|
135
|
+
get "http://example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "en;q=0.5,en-US;q=0.8,es;q=0.7"}
|
136
|
+
I18n.locale.should eql(:'en-US')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
shared_examples_for "a redirect with the default locale" do
|
141
|
+
|
142
|
+
it "should redirect to the canonical URL" do
|
143
|
+
%w{
|
144
|
+
http://en.example.com
|
145
|
+
http://example.com/en
|
146
|
+
http://example.com?locale=en
|
147
|
+
}.each do |url|
|
148
|
+
get url
|
149
|
+
last_response.should be_redirect
|
150
|
+
last_response.location.should eql("http://example.com")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should not redirect if the locale was set in the accept header" do
|
155
|
+
get "http://example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "en"}
|
156
|
+
last_response.should_not be_redirect
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "redirect to path" do
|
161
|
+
|
162
|
+
let :options do
|
163
|
+
{ :redirect => :path }
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should not redirect if the locale was set with the path" do
|
167
|
+
%w{
|
168
|
+
http://example.com/de
|
169
|
+
http://example.com/en
|
170
|
+
http://example.com/en/
|
171
|
+
http://example.com/en/foo/bar
|
172
|
+
}.each do |url|
|
173
|
+
get url
|
174
|
+
last_response.should_not be_redirect
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should redirect if the locale was set by other means" do
|
179
|
+
{
|
180
|
+
"http://en.example.com" => "http://example.com/en",
|
181
|
+
"http://en.example.com/de" => "http://example.com/de",
|
182
|
+
"http://de.example.com" => "http://example.com/de",
|
183
|
+
"http://example.com?locale=de" => "http://example.com/de"
|
184
|
+
}.each do |url, redirect_url|
|
185
|
+
get url
|
186
|
+
last_response.should be_redirect
|
187
|
+
last_response.location.should eql(redirect_url)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should redirect if the locale was set with an accept header" do
|
192
|
+
get "http://example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "de"}
|
193
|
+
last_response.should be_redirect
|
194
|
+
last_response.location.should eql("http://example.com/de")
|
195
|
+
end
|
196
|
+
|
197
|
+
context "canonical" do
|
198
|
+
|
199
|
+
let :options do
|
200
|
+
{ :redirect => :path, :canonical => true }
|
201
|
+
end
|
202
|
+
|
203
|
+
it_should_behave_like "a redirect with the default locale"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "host" do
|
208
|
+
|
209
|
+
let :options do
|
210
|
+
{ :redirect => :host }
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not redirect if the locale was set with the host" do
|
214
|
+
%w{
|
215
|
+
http://de.example.com
|
216
|
+
http://en.example.com/
|
217
|
+
http://en.example.com/foo/bar
|
218
|
+
}.each do |url|
|
219
|
+
get url
|
220
|
+
last_response.should_not be_redirect
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should redirect if the locale was set by other means" do
|
225
|
+
{
|
226
|
+
"http://example.com/en" => "http://en.example.com",
|
227
|
+
"http://en.example.com/de" => "http://de.example.com",
|
228
|
+
"http://example.com/de" => "http://de.example.com",
|
229
|
+
"http://example.com?locale=de" => "http://de.example.com"
|
230
|
+
}.each do |url, redirect_url|
|
231
|
+
get url
|
232
|
+
last_response.should be_redirect
|
233
|
+
last_response.location.should eql(redirect_url)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should redirect if the locale was set with an accept header" do
|
238
|
+
get "http://example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "de"}
|
239
|
+
last_response.should be_redirect
|
240
|
+
last_response.location.should eql("http://de.example.com")
|
241
|
+
end
|
242
|
+
|
243
|
+
context "canonical" do
|
244
|
+
|
245
|
+
let :options do
|
246
|
+
{ :redirect => :host, :canonical => true }
|
247
|
+
end
|
248
|
+
|
249
|
+
it_should_behave_like "a redirect with the default locale"
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context "param" do
|
254
|
+
|
255
|
+
let :options do
|
256
|
+
{ :redirect => :param }
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should not redirect if the locale was set with a param" do
|
260
|
+
%w{
|
261
|
+
http://example.com?locale=de
|
262
|
+
http://example.com/?locale=en
|
263
|
+
http://example.com/foo/bar?locale=en
|
264
|
+
}.each do |url|
|
265
|
+
get url
|
266
|
+
last_response.should_not be_redirect
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should redirect if the locale was set by other means" do
|
271
|
+
{
|
272
|
+
"http://example.com/en" => "http://example.com?locale=en",
|
273
|
+
"http://de.example.com/foo/bar" => "http://example.com/foo/bar?locale=de",
|
274
|
+
"http://example.com/de" => "http://example.com?locale=de",
|
275
|
+
"http://en.example.com?locale=de" => "http://example.com?locale=de"
|
276
|
+
}.each do |url, redirect_url|
|
277
|
+
get url
|
278
|
+
last_response.should be_redirect
|
279
|
+
last_response.location.should eql(redirect_url)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should redirect if the locale was set with an accept header" do
|
284
|
+
get "http://example.com" , nil, {"HTTP_ACCEPT_LANGUAGE" => "de"}
|
285
|
+
last_response.should be_redirect
|
286
|
+
last_response.location.should eql("http://example.com?locale=de")
|
287
|
+
end
|
288
|
+
|
289
|
+
context "canonical" do
|
290
|
+
|
291
|
+
let :options do
|
292
|
+
{ :redirect => :param, :canonical => true }
|
293
|
+
end
|
294
|
+
|
295
|
+
it_should_behave_like "a redirect with the default locale"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
metadata
CHANGED
@@ -1,95 +1,107 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-i18n_locale_switcher
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
- Christoph
|
12
|
+
authors:
|
13
|
+
- "Christoph B\xC3\xBCnte, Andreas Korth"
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
17
|
+
|
18
|
+
date: 2011-11-29 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
23
22
|
prerelease: false
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: i18n
|
27
|
-
requirement: &2158733640 !ruby/object:Gem::Requirement
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
28
24
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
33
32
|
type: :runtime
|
33
|
+
name: rack
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
34
36
|
prerelease: false
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: domainatrix
|
38
|
-
requirement: &2158733180 !ruby/object:Gem::Requirement
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
38
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
44
46
|
type: :runtime
|
47
|
+
name: i18n
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
45
50
|
prerelease: false
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: echoe
|
49
|
-
requirement: &2158732720 !ruby/object:Gem::Requirement
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
52
|
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
55
60
|
type: :development
|
61
|
+
name: echoe
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
56
64
|
prerelease: false
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: rspec
|
60
|
-
requirement: &2158732260 !ruby/object:Gem::Requirement
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
61
66
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
66
74
|
type: :development
|
75
|
+
name: rspec
|
76
|
+
version_requirements: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
67
78
|
prerelease: false
|
68
|
-
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rack-test
|
71
|
-
requirement: &2158731800 !ruby/object:Gem::Requirement
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
72
80
|
none: false
|
73
|
-
requirements:
|
74
|
-
- -
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
77
88
|
type: :development
|
78
|
-
|
79
|
-
version_requirements: *
|
80
|
-
description: Detects the current locale from query parameter, path prefix, host or
|
81
|
-
|
82
|
-
email:
|
89
|
+
name: rack-test
|
90
|
+
version_requirements: *id005
|
91
|
+
description: Detects the current locale from query parameter, path prefix, host or accept header.
|
92
|
+
email:
|
83
93
|
- info@christophbuente.de
|
84
94
|
- andreas.korth@gmail.com
|
85
95
|
executables: []
|
96
|
+
|
86
97
|
extensions: []
|
87
|
-
|
98
|
+
|
99
|
+
extra_rdoc_files:
|
88
100
|
- CHANGELOG
|
89
101
|
- LICENSE
|
90
102
|
- README.md
|
91
103
|
- lib/rack/i18n_locale_switcher.rb
|
92
|
-
files:
|
104
|
+
files:
|
93
105
|
- CHANGELOG
|
94
106
|
- LICENSE
|
95
107
|
- Manifest
|
@@ -97,36 +109,46 @@ files:
|
|
97
109
|
- Rakefile
|
98
110
|
- lib/rack/i18n_locale_switcher.rb
|
99
111
|
- rack-i18n_locale_switcher.gemspec
|
100
|
-
- spec/i18n_locale_switcher_spec.rb
|
112
|
+
- spec/rack/i18n_locale_switcher_spec.rb
|
113
|
+
has_rdoc: true
|
101
114
|
homepage: http://github.com/christoph-buente/rack-i18n_locale_switcher
|
102
115
|
licenses: []
|
116
|
+
|
103
117
|
post_install_message:
|
104
|
-
rdoc_options:
|
118
|
+
rdoc_options:
|
105
119
|
- --line-numbers
|
106
120
|
- --inline-source
|
107
121
|
- --title
|
108
122
|
- Rack-i18n_locale_switcher
|
109
123
|
- --main
|
110
124
|
- README.md
|
111
|
-
require_paths:
|
125
|
+
require_paths:
|
112
126
|
- lib
|
113
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
128
|
none: false
|
115
|
-
requirements:
|
116
|
-
- -
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
|
119
|
-
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
hash: 3
|
133
|
+
segments:
|
134
|
+
- 0
|
135
|
+
version: "0"
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
137
|
none: false
|
121
|
-
requirements:
|
122
|
-
- -
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 11
|
142
|
+
segments:
|
143
|
+
- 1
|
144
|
+
- 2
|
145
|
+
version: "1.2"
|
125
146
|
requirements: []
|
147
|
+
|
126
148
|
rubyforge_project: rack-i18n_locale_switcher
|
127
|
-
rubygems_version: 1.
|
149
|
+
rubygems_version: 1.6.2
|
128
150
|
signing_key:
|
129
151
|
specification_version: 3
|
130
|
-
summary: Detects the current locale from query parameter, path prefix, host or accept
|
131
|
-
header.
|
152
|
+
summary: Detects the current locale from query parameter, path prefix, host or accept header.
|
132
153
|
test_files: []
|
154
|
+
|
@@ -1,131 +0,0 @@
|
|
1
|
-
require 'rack/i18n_locale_switcher'
|
2
|
-
require 'rack/test'
|
3
|
-
|
4
|
-
describe Rack::I18nLocaleSwitcher do
|
5
|
-
|
6
|
-
include Rack::Test::Methods
|
7
|
-
|
8
|
-
let :options do
|
9
|
-
{}
|
10
|
-
end
|
11
|
-
|
12
|
-
let :app do
|
13
|
-
opts = options
|
14
|
-
rack = Rack::Builder.new do
|
15
|
-
map "/" do
|
16
|
-
use Rack::I18nLocaleSwitcher, opts
|
17
|
-
run lambda { |env| [200, {}, "Coolness"] }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
rack.to_app
|
21
|
-
end
|
22
|
-
|
23
|
-
before do
|
24
|
-
I18n.available_locales = [:en, :'en-US', :de, :'de-DE', :es]
|
25
|
-
I18n.default_locale = :en
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should fall back to the locale to default locale" do
|
29
|
-
get 'http://example.com/some/path'
|
30
|
-
I18n.locale.should eql(I18n.default_locale)
|
31
|
-
|
32
|
-
get 'http://www.example.com/'
|
33
|
-
I18n.locale.should eql(I18n.default_locale)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should not accept invalid options" do
|
37
|
-
expect {
|
38
|
-
Rack::I18nLocaleSwitcher.new('app', :not_an_option => 'foo')
|
39
|
-
}.to raise_error(ArgumentError, "Invalid option(s) :not_an_option")
|
40
|
-
end
|
41
|
-
|
42
|
-
context 'with custom sources' do
|
43
|
-
|
44
|
-
let :options do
|
45
|
-
{ :source => [ :header, :host ] }
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should honor the sequence" do
|
49
|
-
get 'http://de.example.com' , {}, {'HTTP_ACCEPT_LANGUAGE' => "es"}
|
50
|
-
I18n.locale.should eql(:es)
|
51
|
-
|
52
|
-
get 'http://de.example.com' , {}, {'HTTP_ACCEPT_LANGUAGE' => "foo"}
|
53
|
-
I18n.locale.should eql(:de)
|
54
|
-
|
55
|
-
get 'http://de.example.com'
|
56
|
-
I18n.locale.should eql(:de)
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should ignore other sources" do
|
60
|
-
get 'http://example.com?locale=de'
|
61
|
-
I18n.locale.should eql(:en)
|
62
|
-
|
63
|
-
get 'http://example.com/de'
|
64
|
-
I18n.locale.should eql(:en)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'request param' do
|
69
|
-
|
70
|
-
it "should set the locale" do
|
71
|
-
get 'http://example.com?locale=de'
|
72
|
-
I18n.locale.should eql(:de)
|
73
|
-
|
74
|
-
get 'http://example.com?locale=en-US'
|
75
|
-
I18n.locale.should eql(:'en-US')
|
76
|
-
|
77
|
-
get 'http://example.com/some/path?foo=bar&locale=es¶m=value'
|
78
|
-
I18n.locale.should eql(:es)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should not set an unavailable locale" do
|
82
|
-
get 'http://example.com?locale=xx'
|
83
|
-
I18n.locale.should eql(I18n.default_locale)
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'name' do
|
87
|
-
|
88
|
-
let :options do
|
89
|
-
{ :param => 'lang' }
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should be configurable" do
|
93
|
-
get 'http://example.com?lang=de'
|
94
|
-
I18n.locale.should eql(:de)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
context 'from path prefix ' do
|
100
|
-
|
101
|
-
it "should set the I18n locale" do
|
102
|
-
get 'http://example.com/de/some/path/'
|
103
|
-
I18n.locale.should eql(:de)
|
104
|
-
|
105
|
-
get 'http://example.com/en-us'
|
106
|
-
I18n.locale.should eql(:'en-US')
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'from host' do
|
111
|
-
|
112
|
-
it "should set the I18n locale" do
|
113
|
-
get 'http://de.example.com/'
|
114
|
-
I18n.locale.should eql(:de)
|
115
|
-
|
116
|
-
get 'http://de-de.example.com/'
|
117
|
-
I18n.locale.should eql(:'de-DE')
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context 'from accept-language header' do
|
122
|
-
|
123
|
-
it "should override the client requested locale" do
|
124
|
-
get 'http://example.com' , {}, {'HTTP_ACCEPT_LANGUAGE' => "de-de,de,en;q=0.5"}
|
125
|
-
I18n.locale.should eql(:'de-DE')
|
126
|
-
|
127
|
-
get 'http://example.com' , {}, {'HTTP_ACCEPT_LANGUAGE' => "en;q=0.5,en-US;q=0.8,es;q=0.7"}
|
128
|
-
I18n.locale.should eql(:'en-US')
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|