rack-i18n_locale_switcher 0.3.1 → 0.4.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 +6 -0
- data/Rakefile +5 -5
- data/lib/rack/i18n_locale_switcher.rb +47 -32
- data/rack-i18n_locale_switcher.gemspec +4 -4
- data/spec/i18n_locale_switcher_spec.rb +81 -22
- metadata +18 -18
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
= 0.4.0 / 2011-11-26
|
2
|
+
Added support configuration of sources from which to determine the locale
|
3
|
+
as well as the name of the query parameter.
|
4
|
+
Drop support for TLD since locale can't be reliably inferred from it
|
5
|
+
Code refactoring and better test coverage.
|
6
|
+
|
1
7
|
= 0.3.1 / 2011-11-25
|
2
8
|
Code refactoring
|
3
9
|
Don't "clean" then Rack environment
|
data/Rakefile
CHANGED
@@ -2,12 +2,12 @@
|
|
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.4.0') do |p|
|
6
6
|
|
7
|
-
p.description
|
8
|
-
p.url
|
9
|
-
p.author
|
10
|
-
p.email
|
7
|
+
p.description = "Detects the current locale from query parameter, path prefix, host or accept header."
|
8
|
+
p.url = "http://github.com/christoph-buente/rack-i18n_locale_switcher"
|
9
|
+
p.author = ["Christoph Bünte", "Andreas Korth"]
|
10
|
+
p.email = ["info@christophbuente.de", "andreas.korth@gmail.com"]
|
11
11
|
|
12
12
|
p.retain_gemspec = true
|
13
13
|
|
@@ -1,57 +1,72 @@
|
|
1
1
|
require 'i18n'
|
2
|
-
require 'domainatrix'
|
2
|
+
# require 'domainatrix'
|
3
3
|
|
4
4
|
module Rack
|
5
5
|
class I18nLocaleSwitcher
|
6
6
|
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
:param => 'locale',
|
9
|
+
:source => [ :param, :path, :host, :header ]
|
10
|
+
}.freeze
|
11
|
+
|
7
12
|
def initialize(app, options = {})
|
8
13
|
@app = app
|
14
|
+
|
15
|
+
invalid_options = (options.keys - DEFAULT_OPTIONS.keys)
|
16
|
+
|
17
|
+
if invalid_options.any?
|
18
|
+
raise ArgumentError, "Invalid option(s) #{ invalid_options.map(&:inspect).join(', ') }"
|
19
|
+
end
|
20
|
+
|
21
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
22
|
+
@options[:source] = Array(@options[:source]) unless @options[:source].is_a?(Array)
|
9
23
|
end
|
10
24
|
|
11
25
|
def call(env)
|
12
|
-
I18n.locale =
|
26
|
+
I18n.locale = I18n.default_locale
|
27
|
+
|
28
|
+
@options[:source].each do |source|
|
29
|
+
if locale = send(:"get_locale_from_#{source}", env)
|
30
|
+
I18n.locale = locale
|
31
|
+
break
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
13
35
|
@app.call(env)
|
14
36
|
end
|
15
37
|
|
16
38
|
private
|
17
39
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
uses.each do |use|
|
22
|
-
if locale = send(:"extract_locale_from_#{ use }", request)
|
23
|
-
unless locale.empty?
|
24
|
-
locale = locale.to_sym
|
25
|
-
return locale if I18n.available_locales.include?(locale)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
I18n.default_locale
|
30
|
-
end
|
31
|
-
|
32
|
-
def extract_locale_from_param(request)
|
33
|
-
request.params["locale"]
|
40
|
+
def get_locale_from_param(env)
|
41
|
+
env['QUERY_STRING'] =~ /\b#{ @options[:param] }=([^&]+)\b/
|
42
|
+
to_available_locale($1)
|
34
43
|
end
|
35
44
|
|
36
|
-
def
|
37
|
-
|
45
|
+
def get_locale_from_path(env)
|
46
|
+
env['PATH_INFO'] =~ /^\/([^\/]+)/
|
47
|
+
to_available_locale($1)
|
38
48
|
end
|
39
49
|
|
40
|
-
def
|
41
|
-
|
50
|
+
def get_locale_from_host(env)
|
51
|
+
env['SERVER_NAME'] =~ /^([^.]+)\.[^.]+\.[^.]+/i
|
52
|
+
to_available_locale($1)
|
42
53
|
end
|
43
54
|
|
44
|
-
def
|
45
|
-
|
55
|
+
def get_locale_from_header(env)
|
56
|
+
locale = nil
|
57
|
+
if accept = env['HTTP_ACCEPT_LANGUAGE']
|
58
|
+
locales = accept.scan(/([^;,]+)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i)
|
59
|
+
locales.sort_by{ |loc| 1 - (loc.last || 1).to_f }.each do |loc|
|
60
|
+
break if locale = to_available_locale(loc.first)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
locale
|
46
64
|
end
|
47
|
-
|
48
|
-
def
|
49
|
-
if
|
50
|
-
|
51
|
-
|
52
|
-
l.split(';q=')
|
53
|
-
}.first
|
54
|
-
lang.first.split("-").first
|
65
|
+
|
66
|
+
def to_available_locale(locale)
|
67
|
+
if locale =~ /^([a-z]{1,8})(-[a-z]{1,8})?$/i
|
68
|
+
locale = :"#{ $1.downcase }#{ ($2 || '').upcase }"
|
69
|
+
locale if I18n.available_locales.include?(locale)
|
55
70
|
end
|
56
71
|
end
|
57
72
|
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "rack-i18n_locale_switcher"
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.4.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Christoph B\u{fc}nte, Andreas Korth"]
|
9
|
-
s.date = "2011-11-
|
10
|
-
s.description = "Detects the current locale from
|
9
|
+
s.date = "2011-11-26"
|
10
|
+
s.description = "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
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"]
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = "rack-i18n_locale_switcher"
|
18
18
|
s.rubygems_version = "1.8.11"
|
19
|
-
s.summary = "Detects the current locale from
|
19
|
+
s.summary = "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
|
@@ -5,13 +5,19 @@ describe Rack::I18nLocaleSwitcher do
|
|
5
5
|
|
6
6
|
include Rack::Test::Methods
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
let :options do
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
|
12
|
+
let :app do
|
13
|
+
opts = options
|
14
|
+
rack = Rack::Builder.new do
|
10
15
|
map "/" do
|
11
|
-
use Rack::I18nLocaleSwitcher
|
16
|
+
use Rack::I18nLocaleSwitcher, opts
|
12
17
|
run lambda { |env| [200, {}, "Coolness"] }
|
13
18
|
end
|
14
|
-
|
19
|
+
end
|
20
|
+
rack.to_app
|
15
21
|
end
|
16
22
|
|
17
23
|
before do
|
@@ -19,54 +25,107 @@ describe Rack::I18nLocaleSwitcher do
|
|
19
25
|
I18n.default_locale = :en
|
20
26
|
end
|
21
27
|
|
22
|
-
it "should
|
23
|
-
get '/'
|
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/'
|
24
33
|
I18n.locale.should eql(I18n.default_locale)
|
25
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)
|
26
51
|
|
27
|
-
|
52
|
+
get 'http://de.example.com' , {}, {'HTTP_ACCEPT_LANGUAGE' => "foo"}
|
53
|
+
I18n.locale.should eql(:de)
|
28
54
|
|
29
|
-
|
30
|
-
get '/', :locale => 'de'
|
31
|
-
last_request.url.should include('?locale=de')
|
55
|
+
get 'http://de.example.com'
|
32
56
|
I18n.locale.should eql(:de)
|
33
57
|
end
|
34
58
|
|
35
|
-
it "should
|
36
|
-
get '
|
37
|
-
I18n.locale.should eql(
|
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)
|
38
65
|
end
|
39
66
|
end
|
40
67
|
|
41
|
-
context '
|
68
|
+
context 'request param' do
|
42
69
|
|
43
|
-
it "should set the
|
44
|
-
get '
|
70
|
+
it "should set the locale" do
|
71
|
+
get 'http://example.com?locale=de'
|
45
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
|
46
96
|
end
|
47
97
|
end
|
48
98
|
|
49
|
-
context 'from
|
99
|
+
context 'from path prefix ' do
|
50
100
|
|
51
101
|
it "should set the I18n locale" do
|
52
|
-
get 'http://
|
102
|
+
get 'http://example.com/de/some/path/'
|
53
103
|
I18n.locale.should eql(:de)
|
104
|
+
|
105
|
+
get 'http://example.com/en-us'
|
106
|
+
I18n.locale.should eql(:'en-US')
|
54
107
|
end
|
55
108
|
end
|
56
109
|
|
57
|
-
context 'from
|
110
|
+
context 'from host' do
|
58
111
|
|
59
112
|
it "should set the I18n locale" do
|
60
|
-
get 'http://example.
|
113
|
+
get 'http://de.example.com/'
|
61
114
|
I18n.locale.should eql(:de)
|
115
|
+
|
116
|
+
get 'http://de-de.example.com/'
|
117
|
+
I18n.locale.should eql(:'de-DE')
|
62
118
|
end
|
63
119
|
end
|
64
120
|
|
65
121
|
context 'from accept-language header' do
|
66
122
|
|
67
123
|
it "should override the client requested locale" do
|
68
|
-
get '
|
69
|
-
I18n.locale.should eql(:de)
|
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')
|
70
129
|
end
|
71
130
|
end
|
72
131
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-i18n_locale_switcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
|
-
requirement: &
|
16
|
+
requirement: &2158734100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2158734100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: i18n
|
27
|
-
requirement: &
|
27
|
+
requirement: &2158733640 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2158733640
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: domainatrix
|
38
|
-
requirement: &
|
38
|
+
requirement: &2158733180 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2158733180
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: echoe
|
49
|
-
requirement: &
|
49
|
+
requirement: &2158732720 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2158732720
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &2158732260 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2158732260
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rack-test
|
71
|
-
requirement: &
|
71
|
+
requirement: &2158731800 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,9 +76,9 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
80
|
-
description: Detects the current locale from
|
81
|
-
|
79
|
+
version_requirements: *2158731800
|
80
|
+
description: Detects the current locale from query parameter, path prefix, host or
|
81
|
+
accept header.
|
82
82
|
email:
|
83
83
|
- info@christophbuente.de
|
84
84
|
- andreas.korth@gmail.com
|
@@ -127,6 +127,6 @@ rubyforge_project: rack-i18n_locale_switcher
|
|
127
127
|
rubygems_version: 1.8.11
|
128
128
|
signing_key:
|
129
129
|
specification_version: 3
|
130
|
-
summary: Detects the current locale from
|
131
|
-
|
130
|
+
summary: Detects the current locale from query parameter, path prefix, host or accept
|
131
|
+
header.
|
132
132
|
test_files: []
|