rack-geo-locale 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +39 -0
- data/Guardfile +4 -0
- data/LICENSE +7 -0
- data/Readme.md +0 -0
- data/VERSION +1 -0
- data/lib/rack/geo_locale.rb +47 -0
- data/rack-geo-locale.gemspec +23 -0
- data/spec/lib/rack/geo_locale_spec.rb +86 -0
- metadata +111 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rack-geo-locale (0.0.1)
|
5
|
+
geoip
|
6
|
+
rack
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
ffi (1.0.11)
|
13
|
+
geoip (1.1.2)
|
14
|
+
guard (1.0.1)
|
15
|
+
ffi (>= 0.5.0)
|
16
|
+
thor (~> 0.14.6)
|
17
|
+
guard-rspec (0.7.0)
|
18
|
+
guard (>= 0.10.0)
|
19
|
+
rack (1.4.1)
|
20
|
+
rack-test (0.6.1)
|
21
|
+
rack (>= 1.0)
|
22
|
+
rspec (2.9.0)
|
23
|
+
rspec-core (~> 2.9.0)
|
24
|
+
rspec-expectations (~> 2.9.0)
|
25
|
+
rspec-mocks (~> 2.9.0)
|
26
|
+
rspec-core (2.9.0)
|
27
|
+
rspec-expectations (2.9.0)
|
28
|
+
diff-lcs (~> 1.1.3)
|
29
|
+
rspec-mocks (2.9.0)
|
30
|
+
thor (0.14.6)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
guard-rspec
|
37
|
+
rack-geo-locale!
|
38
|
+
rack-test
|
39
|
+
rspec
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (C) 2012 Bohemian Wrappsody AB
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Readme.md
ADDED
File without changes
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class GeoLocale
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
|
8
|
+
@geoip = GeoIP.new(ENV["GEOIP_DATABASE"])
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env["locale.country"] = parse_country(env)
|
13
|
+
env["locale.languages"] = parse_languages(env)
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def parse_country(env)
|
20
|
+
remote_addr = env["REMOTE_ADDR"]
|
21
|
+
|
22
|
+
return nil unless remote_addr
|
23
|
+
|
24
|
+
result = @geoip.country(remote_addr).country_code2
|
25
|
+
|
26
|
+
if result != "--"
|
27
|
+
result
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_languages(env)
|
34
|
+
env["HTTP_ACCEPT_LANGUAGE"] ||= ""
|
35
|
+
language_ranges = env["HTTP_ACCEPT_LANGUAGE"].split(",")
|
36
|
+
language_ranges.map do |language_range|
|
37
|
+
language_range += ';q=1.0' unless language_range =~ /;q=\d+\.\d+$/
|
38
|
+
|
39
|
+
locale, q = language_range.split(";q=")
|
40
|
+
|
41
|
+
language = locale.strip.split("-").first
|
42
|
+
|
43
|
+
{:language => language, :q => q}
|
44
|
+
end.sort {|x, y| y[:q] <=> x[:q]}.map{|lr| lr[:language]}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "rack-geo-locale"
|
5
|
+
s.version = File.read('VERSION').to_s
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.authors = ["Joakim Ekberg"]
|
8
|
+
s.email = ["joakim@wrapp.com"]
|
9
|
+
s.homepage = "https://github.com/wrapp/rack-geo-locale"
|
10
|
+
s.summary = "Rack middleware used to guess the visitors locale based on GeoIP and HTTP_ACCEPT_LANGUAGE."
|
11
|
+
s.description = "Simple Rack middleware for setting the locale.country via GeoIP using the MaxMind GeoIP database, and setting the locale.languages based on the HTTP_ACCEPT_LANGUAGE header."
|
12
|
+
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_development_dependency "rspec"
|
19
|
+
s.add_development_dependency "rack-test"
|
20
|
+
s.add_development_dependency "guard-rspec"
|
21
|
+
s.add_runtime_dependency "rack"
|
22
|
+
s.add_runtime_dependency "geoip"
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require 'rack/geo_locale'
|
3
|
+
require 'geoip'
|
4
|
+
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
def app
|
8
|
+
Rack::GeoLocale.new(proc {|env| [200, {}, 'hello']})
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Rack::GeoLocale do
|
12
|
+
describe "GeoIP" do
|
13
|
+
before do
|
14
|
+
geoip = double("geoip")
|
15
|
+
geoip.stub(:country).with("10.0.0.1").and_return(GeoIP::Country.new("10.0.0.1", "10.0.0.1", 191, "SE", "SWE", "Sweden", "EU"))
|
16
|
+
geoip.stub(:country).with("10.0.0.2").and_return(GeoIP::Country.new("10.0.0.2", "10.0.0.2", 225, "US", "USA", "USA", "NA"))
|
17
|
+
geoip.stub(:country).with("10.0.0.3").and_return(GeoIP::Country.new("10.0.0.3", "10.0.0.3", 0, "--", "---", "N/A", "--"))
|
18
|
+
|
19
|
+
GeoIP.stub :new => geoip
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should handle an empty REMOTE_ADDR field" do
|
23
|
+
get '/', {}, {"REMOTE_ADDR" => nil}
|
24
|
+
last_request.env["locale.country"].should == nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should resolve 10.0.0.1 to SE" do
|
28
|
+
get '/', {}, {"REMOTE_ADDR" => "10.0.0.1"}
|
29
|
+
last_request.env["locale.country"].should == "SE"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should resolve 10.0.0.2 to US" do
|
33
|
+
get '/', {}, {"REMOTE_ADDR" => "10.0.0.2"}
|
34
|
+
last_request.env["locale.country"].should == "US"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should resolve 10.0.0.3 to nil" do
|
38
|
+
get '/', {}, {"REMOTE_ADDR" => "10.0.0.3"}
|
39
|
+
last_request.env["locale.country"].should == nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "parsing HTTP_ACCEPT_LANGUAGE" do
|
44
|
+
it "should return an empty result if no HTTP_ACCEPT_LANGUAGE passed" do
|
45
|
+
get '/', {}, {}
|
46
|
+
last_request.env["locale.languages"].should == []
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should parse HTTP_ACCEPT_LANGUAGE 'en'" do
|
50
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "en"}
|
51
|
+
last_request.env["locale.languages"].should == ["en"]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should parse HTTP_ACCEPT_LANGUAGE 'sv'" do
|
55
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "sv"}
|
56
|
+
last_request.env["locale.languages"].should == ["sv"]
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should parse HTTP_ACCEPT_LANGUAGE 'sv;q=0.1, en'" do
|
60
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "sv;q=0.1, en"}
|
61
|
+
last_request.env["locale.languages"].should == ["en", "sv"]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should parse HTTP_ACCEPT_LANGUAGE 'sv, en'" do
|
65
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "sv, en"}
|
66
|
+
last_request.env["locale.languages"].should == ["sv", "en"]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should parse HTTP_ACCEPT_LANGUAGE 'en;q=0.4, de;q=0.7'" do
|
70
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "en;q=0.4, de;q=0.7"}
|
71
|
+
last_request.env["locale.languages"].should == ["de", "en"]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should parse HTTP_ACCEPT_LANGUAGE 'en-US;q=0.7'" do
|
75
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "en-US;q=0.7"}
|
76
|
+
last_request.env["locale.languages"].should == ["en"]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "missing database" do
|
81
|
+
xit "should fallback on HTTP_ACCEPT_LANGUAGE" do
|
82
|
+
get '/', {}, {"HTTP_ACCEPT_LANGUAGE" => "en-US;q=0.7"}
|
83
|
+
last_request.env["locale.languages"].should == ["en"]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-geo-locale
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joakim Ekberg
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70169376395940 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70169376395940
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack-test
|
27
|
+
requirement: &70169376395300 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70169376395300
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: guard-rspec
|
38
|
+
requirement: &70169376394740 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70169376394740
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rack
|
49
|
+
requirement: &70169376394220 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70169376394220
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: geoip
|
60
|
+
requirement: &70169376393660 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70169376393660
|
69
|
+
description: Simple Rack middleware for setting the locale.country via GeoIP using
|
70
|
+
the MaxMind GeoIP database, and setting the locale.languages based on the HTTP_ACCEPT_LANGUAGE
|
71
|
+
header.
|
72
|
+
email:
|
73
|
+
- joakim@wrapp.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- Guardfile
|
81
|
+
- LICENSE
|
82
|
+
- Readme.md
|
83
|
+
- VERSION
|
84
|
+
- lib/rack/geo_locale.rb
|
85
|
+
- rack-geo-locale.gemspec
|
86
|
+
- spec/lib/rack/geo_locale_spec.rb
|
87
|
+
homepage: https://github.com/wrapp/rack-geo-locale
|
88
|
+
licenses: []
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.8.15
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Rack middleware used to guess the visitors locale based on GeoIP and HTTP_ACCEPT_LANGUAGE.
|
111
|
+
test_files: []
|