countries 4.2.3 → 5.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.github/workflows/tests.yml +1 -5
- data/.rubocop.yml +40 -1
- data/.rubocop_todo.yml +8 -41
- data/CHANGELOG.md +7 -2
- data/Gemfile +5 -3
- data/README.markdown +22 -5
- data/Rakefile +13 -31
- data/bin/console +1 -0
- data/countries.gemspec +7 -5
- data/lib/countries/cache/countries.json +1 -1
- data/lib/countries/configuration.rb +2 -0
- data/lib/countries/country/class_methods.rb +12 -97
- data/lib/countries/country/currency_methods.rb +2 -0
- data/lib/countries/country/emoji.rb +2 -3
- data/lib/countries/country/finder_methods.rb +81 -0
- data/lib/countries/country.rb +3 -40
- data/lib/countries/data/countries/KN.yaml +0 -1
- data/lib/countries/data.rb +34 -37
- data/lib/countries/global.rb +2 -0
- data/lib/countries/iso3166.rb +3 -0
- data/lib/countries/kwarg_struct.rb +2 -0
- data/lib/countries/mongoid.rb +2 -0
- data/lib/countries/sources/cldr/downloader.rb +8 -8
- data/lib/countries/sources/cldr/subdivision.rb +3 -0
- data/lib/countries/sources/cldr/subdivision_updater.rb +23 -17
- data/lib/countries/sources/local/cached_loader.rb +3 -0
- data/lib/countries/sources/local/subdivision.rb +5 -2
- data/lib/countries/sources.rb +2 -0
- data/lib/countries/structure.rb +1 -1
- data/lib/countries/subdivision.rb +2 -0
- data/lib/countries/tasks/geocoding.rake +15 -6
- data/lib/countries/tasks/postal_codes.rake +5 -3
- data/lib/countries/timezones.rb +5 -2
- data/lib/countries/translations.rb +2 -0
- data/lib/countries/version.rb +3 -1
- data/lib/countries.rb +2 -0
- data/spec/00_global_spec.rb +2 -0
- data/spec/configuration_spec.rb +11 -5
- data/spec/country_spec.rb +71 -22
- data/spec/data_spec.rb +24 -18
- data/spec/mongoid_spec.rb +2 -2
- data/spec/perf_spec.rb +16 -16
- data/spec/spec_helper.rb +2 -0
- data/spec/subdivision_spec.rb +6 -4
- data/spec/thread_safety_spec.rb +4 -3
- data/spec/timezone_spec.rb +2 -0
- metadata +14 -12
- data/lib/countries/setup.rb +0 -18
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'sixarm_ruby_unaccent'
|
2
4
|
|
3
5
|
module ISO3166
|
4
6
|
UNSEARCHABLE_METHODS = [:translations].freeze
|
5
7
|
|
6
|
-
def self
|
8
|
+
def self.Country(country_data_or_country)
|
7
9
|
case country_data_or_country
|
8
10
|
when ISO3166::Country
|
9
11
|
country_data_or_country
|
@@ -15,9 +17,6 @@ module ISO3166
|
|
15
17
|
end
|
16
18
|
|
17
19
|
module CountryClassMethods
|
18
|
-
FIND_BY_REGEX = /^find_(all_)?(country_|countries_)?by_(.+)/
|
19
|
-
SEARCH_TERM_FILTER_REGEX = /\(|\)|\[\]|,/
|
20
|
-
|
21
20
|
def new(country_data)
|
22
21
|
super if country_data.is_a?(Hash) || codes.include?(country_data.to_s.upcase)
|
23
22
|
end
|
@@ -33,10 +32,6 @@ module ISO3166
|
|
33
32
|
|
34
33
|
alias countries all
|
35
34
|
|
36
|
-
def all_translated(locale = 'en')
|
37
|
-
translations(locale).values
|
38
|
-
end
|
39
|
-
|
40
35
|
def all_names_with_codes(locale = 'en')
|
41
36
|
Country.all.map do |c|
|
42
37
|
lc = (c.translation(locale) || c.iso_short_name)
|
@@ -50,6 +45,10 @@ module ISO3166
|
|
50
45
|
end
|
51
46
|
end
|
52
47
|
|
48
|
+
def all_translated(locale = 'en')
|
49
|
+
translations(locale).values
|
50
|
+
end
|
51
|
+
|
53
52
|
def translations(locale = 'en')
|
54
53
|
i18n_data_countries = I18nData.countries(locale.upcase)
|
55
54
|
|
@@ -62,54 +61,6 @@ module ISO3166
|
|
62
61
|
i18n_data_countries.merge(custom_countries)
|
63
62
|
end
|
64
63
|
|
65
|
-
def search(query)
|
66
|
-
country = new(query.to_s.upcase)
|
67
|
-
country && country.valid? ? country : nil
|
68
|
-
end
|
69
|
-
|
70
|
-
def [](query)
|
71
|
-
search(query)
|
72
|
-
end
|
73
|
-
|
74
|
-
def method_missing(method_name, *arguments)
|
75
|
-
matches = method_name.to_s.match(FIND_BY_REGEX)
|
76
|
-
return_all = matches[1]
|
77
|
-
super unless matches
|
78
|
-
|
79
|
-
if matches[3] == 'names'
|
80
|
-
if RUBY_VERSION =~ /^3\.\d\.\d/
|
81
|
-
warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
|
82
|
-
else
|
83
|
-
warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
countries = find_by(matches[3], arguments[0], matches[2])
|
88
|
-
return_all ? countries : countries.last
|
89
|
-
end
|
90
|
-
|
91
|
-
def respond_to_missing?(method_name, include_private = false)
|
92
|
-
matches = method_name.to_s.match(FIND_BY_REGEX)
|
93
|
-
if matches && matches[3]
|
94
|
-
instance_methods.include?(matches[3].to_sym)
|
95
|
-
else
|
96
|
-
super
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def find_all_by(attribute, val)
|
101
|
-
attributes, lookup_value = parse_attributes(attribute, val)
|
102
|
-
|
103
|
-
ISO3166::Data.cache.select do |_, v|
|
104
|
-
country = Country.new(v)
|
105
|
-
attributes.any? do |attr|
|
106
|
-
Array(country.send(attr)).any? do |n|
|
107
|
-
lookup_value === cached(n) { parse_value(n) }
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
64
|
def subdivisions(alpha2)
|
114
65
|
@subdivisions ||= {}
|
115
66
|
@subdivisions[alpha2] ||= create_subdivisions(subdivision_data(alpha2))
|
@@ -124,51 +75,14 @@ module ISO3166
|
|
124
75
|
|
125
76
|
protected
|
126
77
|
|
127
|
-
def strip_accents(
|
128
|
-
if
|
129
|
-
Regexp.new(
|
78
|
+
def strip_accents(string)
|
79
|
+
if string.is_a?(Regexp)
|
80
|
+
Regexp.new(string.source.unaccent, 'i')
|
130
81
|
else
|
131
|
-
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def parse_attributes(attribute, val)
|
136
|
-
raise "Invalid attribute name '#{attribute}'" unless searchable_attribute?(attribute.to_sym)
|
137
|
-
|
138
|
-
attributes = Array(attribute.to_s)
|
139
|
-
if attribute.to_s == 'name'
|
140
|
-
if RUBY_VERSION =~ /^3\.\d\.\d/
|
141
|
-
warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
|
142
|
-
else
|
143
|
-
warn "DEPRECATION WARNING: 'find_by_name' and 'find_*_by_name' methods are deprecated, please refer to the README file for more information on this change.", uplevel: 1
|
144
|
-
end
|
145
|
-
# 'find_by_name' and 'find_*_by_name' will be changed for 5.0
|
146
|
-
# The addition of 'iso_short_name' here ensures the behaviour of 4.1 is kept for 4.2
|
147
|
-
attributes = %w[iso_short_name unofficial_names translated_names]
|
148
|
-
end
|
149
|
-
|
150
|
-
[attributes, parse_value(val)]
|
151
|
-
end
|
152
|
-
|
153
|
-
def searchable_attribute?(attribute)
|
154
|
-
searchable_attributes.include?(attribute.to_sym)
|
155
|
-
end
|
156
|
-
|
157
|
-
def searchable_attributes
|
158
|
-
instance_methods - UNSEARCHABLE_METHODS
|
159
|
-
end
|
160
|
-
|
161
|
-
def find_by(attribute, value, obj = nil)
|
162
|
-
find_all_by(attribute.downcase, value).map do |country|
|
163
|
-
obj.nil? ? country : new(country.last)
|
82
|
+
string.to_s.unaccent.downcase
|
164
83
|
end
|
165
84
|
end
|
166
85
|
|
167
|
-
def parse_value(value)
|
168
|
-
value = value.gsub(SEARCH_TERM_FILTER_REGEX, '') if value.respond_to?(:gsub)
|
169
|
-
strip_accents(value)
|
170
|
-
end
|
171
|
-
|
172
86
|
def subdivision_data(alpha2)
|
173
87
|
file = subdivision_file_path(alpha2)
|
174
88
|
File.exist?(file) ? YAML.load_file(file) : {}
|
@@ -190,6 +104,7 @@ module ISO3166
|
|
190
104
|
def cached(value)
|
191
105
|
@_parsed_values_cache ||= {}
|
192
106
|
return @_parsed_values_cache[value] if @_parsed_values_cache[value]
|
107
|
+
|
193
108
|
@_parsed_values_cache[value] = yield
|
194
109
|
end
|
195
110
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
# encoding: utf-8
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module ISO3166
|
5
4
|
module Emoji
|
@@ -36,7 +35,7 @@ module ISO3166
|
|
36
35
|
#
|
37
36
|
# The emoji flag for this country, using Unicode Regional Indicator characters. e.g: "U+1F1FA U+1F1F8" for 🇺🇸
|
38
37
|
def emoji_flag
|
39
|
-
alpha2.downcase.chars.map { |c| CODE_POINTS[c] }.join
|
38
|
+
alpha2.downcase.chars.map { |c| CODE_POINTS[c] }.join
|
40
39
|
end
|
41
40
|
end
|
42
41
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ISO3166
|
4
|
+
module CountryFinderMethods
|
5
|
+
FIND_BY_REGEX = /^find_(all_)?(country_|countries_)?by_(.+)/.freeze
|
6
|
+
SEARCH_TERM_FILTER_REGEX = /\(|\)|\[\]|,/.freeze
|
7
|
+
|
8
|
+
def search(query)
|
9
|
+
country = new(query.to_s.upcase)
|
10
|
+
country&.valid? ? country : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](query)
|
14
|
+
search(query)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_all_by(attribute, val)
|
18
|
+
attributes, lookup_value = parse_attributes(attribute, val)
|
19
|
+
|
20
|
+
ISO3166::Data.cache.select do |_, v|
|
21
|
+
country = Country.new(v)
|
22
|
+
attributes.any? do |attr|
|
23
|
+
Array(country.send(attr)).any? do |n|
|
24
|
+
lookup_value === cached(n) { parse_value(n) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(method_name, *arguments)
|
31
|
+
matches = method_name.to_s.match(FIND_BY_REGEX)
|
32
|
+
return_all = matches[1]
|
33
|
+
super unless matches
|
34
|
+
|
35
|
+
countries = find_by(matches[3], arguments[0], matches[2])
|
36
|
+
return_all ? countries : countries.last
|
37
|
+
end
|
38
|
+
|
39
|
+
def respond_to_missing?(method_name, include_private = false)
|
40
|
+
matches = method_name.to_s.match(FIND_BY_REGEX)
|
41
|
+
if matches && matches[3]
|
42
|
+
instance_methods.include?(matches[3].to_sym)
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def find_by(attribute, value, obj = nil)
|
51
|
+
find_all_by(attribute.downcase, value).map do |country|
|
52
|
+
obj.nil? ? country : new(country.last)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_attributes(attribute, val)
|
57
|
+
raise "Invalid attribute name '#{attribute}'" unless searchable_attribute?(attribute.to_sym)
|
58
|
+
|
59
|
+
attributes = Array(attribute.to_s)
|
60
|
+
if attribute.to_s == 'any_name'
|
61
|
+
attributes = %w[iso_long_name iso_short_name unofficial_names translated_names]
|
62
|
+
end
|
63
|
+
|
64
|
+
[attributes, parse_value(val)]
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_value(value)
|
68
|
+
value = value.gsub(SEARCH_TERM_FILTER_REGEX, '') if value.respond_to?(:gsub)
|
69
|
+
strip_accents(value)
|
70
|
+
end
|
71
|
+
|
72
|
+
def searchable_attribute?(attribute)
|
73
|
+
searchable_attributes.include?(attribute.to_sym)
|
74
|
+
end
|
75
|
+
|
76
|
+
def searchable_attributes
|
77
|
+
# Add name and names until we complete the deprecation of the finders
|
78
|
+
instance_methods - UNSEARCHABLE_METHODS + [:name, :names, :any_name]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/countries/country.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ISO3166
|
2
4
|
class Country
|
3
5
|
extend CountryClassMethods
|
6
|
+
extend CountryFinderMethods
|
4
7
|
include Emoji
|
5
8
|
attr_reader :data
|
6
9
|
|
@@ -31,24 +34,6 @@ module ISO3166
|
|
31
34
|
alias zip_format postal_code_format
|
32
35
|
alias languages languages_official
|
33
36
|
|
34
|
-
def latitude_dec
|
35
|
-
if RUBY_VERSION =~ /^3\.\d\.\d/
|
36
|
-
warn "DEPRECATION WARNING: The Country#latitude_dec method has been deprecated and will be removed in 5.0. Please use Country#latitude instead.", uplevel: 1, category: :deprecated
|
37
|
-
else
|
38
|
-
warn "DEPRECATION WARNING: The Country#latitude_dec method has been deprecated and will be removed in 5.0. Please use Country#latitude instead.", uplevel: 1
|
39
|
-
end
|
40
|
-
latitude
|
41
|
-
end
|
42
|
-
|
43
|
-
def longitude_dec
|
44
|
-
if RUBY_VERSION =~ /^3\.\d\.\d/
|
45
|
-
warn "DEPRECATION WARNING: The Country#longitude_dec method has been deprecated and will be removed in 5.0. Please use Country#longitude instead.", uplevel: 1, category: :deprecated
|
46
|
-
else
|
47
|
-
warn "DEPRECATION WARNING: The Country#longitude_dec method has been deprecated and will be removed in 5.0. Please use Country#longitude instead.", uplevel: 1
|
48
|
-
end
|
49
|
-
longitude
|
50
|
-
end
|
51
|
-
|
52
37
|
def ==(other)
|
53
38
|
other.respond_to?(:alpha2) && other.alpha2 == alpha2
|
54
39
|
end
|
@@ -136,28 +121,6 @@ module ISO3166
|
|
136
121
|
@local_name ||= local_names.first
|
137
122
|
end
|
138
123
|
|
139
|
-
# @return [String] This Country's ISO Short Name
|
140
|
-
# @deprecated Use {#iso_short_name} instead.
|
141
|
-
def name
|
142
|
-
if RUBY_VERSION =~ /^3\.\d\.\d/
|
143
|
-
warn "DEPRECATION WARNING: The Country#name method has been deprecated. Please use Country#iso_short_name instead or refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
|
144
|
-
else
|
145
|
-
warn "DEPRECATION WARNING: The Country#name method has been deprecated. Please use Country#iso_short_name instead or refer to the README file for more information on this change.", uplevel: 1
|
146
|
-
end
|
147
|
-
iso_short_name
|
148
|
-
end
|
149
|
-
|
150
|
-
# @return [Array<String>] Array of unofficial, slang names or aliases for this Country
|
151
|
-
# @deprecated Use {#unofficial_names} instead.
|
152
|
-
def names
|
153
|
-
if RUBY_VERSION =~ /^3\.\d\.\d/
|
154
|
-
warn "DEPRECATION WARNING: The Country#names method has been deprecated. Please use Country#unofficial_names instead or refer to the README file for more information on this change.", uplevel: 1, category: :deprecated
|
155
|
-
else
|
156
|
-
warn "DEPRECATION WARNING: The Country#names method has been deprecated. Please use Country#unofficial_names instead or refer to the README file for more information on this change.", uplevel: 1
|
157
|
-
end
|
158
|
-
unofficial_names
|
159
|
-
end
|
160
|
-
|
161
124
|
# @!attribute alpha2
|
162
125
|
# @return [String] the ISO3166 alpha-2 code for this Country
|
163
126
|
#
|
data/lib/countries/data.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ISO3166
|
2
4
|
# Handles building the in memory store of countries data
|
3
5
|
class Data
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
@cache_dir = [File.dirname(__FILE__), 'cache']
|
7
|
+
@cache = {}
|
8
|
+
@registered_data = {}
|
9
|
+
@mutex = Mutex.new
|
8
10
|
|
9
11
|
def initialize(alpha2)
|
10
12
|
@alpha2 = alpha2.to_s.upcase
|
@@ -15,30 +17,23 @@ module ISO3166
|
|
15
17
|
end
|
16
18
|
|
17
19
|
class << self
|
18
|
-
def cache_dir
|
19
|
-
@@cache_dir
|
20
|
-
end
|
21
|
-
|
22
|
-
def cache_dir=(value)
|
23
|
-
@@cache_dir = value
|
24
|
-
end
|
25
20
|
|
26
21
|
# Registers a new Country with custom data.
|
27
22
|
# If you are overriding an existing country, this does not perform a deep merge so you will need to __bring in all data you wish to be available__.
|
28
23
|
# Overriding an existing country will also remove it from the internal management of translations.
|
29
24
|
def register(data)
|
30
25
|
alpha2 = data[:alpha2].upcase
|
31
|
-
|
32
|
-
|
26
|
+
@registered_data[alpha2] = deep_stringify_keys(data)
|
27
|
+
@registered_data[alpha2]['translations'] = \
|
33
28
|
Translations.new.merge(data['translations'] || {})
|
34
|
-
|
29
|
+
@cache = cache.merge(@registered_data)
|
35
30
|
end
|
36
31
|
|
37
32
|
# Removes a country from the loaded data
|
38
33
|
def unregister(alpha2)
|
39
34
|
alpha2 = alpha2.to_s.upcase
|
40
|
-
|
41
|
-
|
35
|
+
@cache.delete(alpha2)
|
36
|
+
@registered_data.delete(alpha2)
|
42
37
|
end
|
43
38
|
|
44
39
|
def cache
|
@@ -47,8 +42,8 @@ module ISO3166
|
|
47
42
|
|
48
43
|
# Resets the loaded data and cache
|
49
44
|
def reset
|
50
|
-
|
51
|
-
|
45
|
+
@cache = {}
|
46
|
+
@registered_data = {}
|
52
47
|
ISO3166.configuration.loaded_locales = []
|
53
48
|
end
|
54
49
|
|
@@ -60,16 +55,19 @@ module ISO3166
|
|
60
55
|
def update_cache
|
61
56
|
load_data!
|
62
57
|
sync_translations!
|
63
|
-
|
58
|
+
@cache
|
64
59
|
end
|
65
60
|
|
61
|
+
private
|
62
|
+
|
66
63
|
def load_data!
|
67
|
-
return
|
64
|
+
return @cache unless load_required?
|
65
|
+
|
68
66
|
synchronized do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
@cache = load_cache %w[countries.json]
|
68
|
+
@_country_codes = @cache.keys
|
69
|
+
@cache = @cache.merge(@registered_data)
|
70
|
+
@cache
|
73
71
|
end
|
74
72
|
end
|
75
73
|
|
@@ -85,11 +83,9 @@ module ISO3166
|
|
85
83
|
end
|
86
84
|
end
|
87
85
|
|
88
|
-
private
|
89
|
-
|
90
86
|
def synchronized(&block)
|
91
87
|
if use_mutex?
|
92
|
-
|
88
|
+
@mutex.synchronize(&block)
|
93
89
|
else
|
94
90
|
block.call
|
95
91
|
end
|
@@ -102,17 +98,17 @@ module ISO3166
|
|
102
98
|
|
103
99
|
def load_required?
|
104
100
|
synchronized do
|
105
|
-
|
101
|
+
@cache.empty?
|
106
102
|
end
|
107
103
|
end
|
108
104
|
|
109
105
|
def loaded_codes
|
110
|
-
|
106
|
+
@cache.keys
|
111
107
|
end
|
112
108
|
|
113
109
|
# Codes that we have translations for in dataset
|
114
110
|
def internal_codes
|
115
|
-
|
111
|
+
@_country_codes - @registered_data.keys
|
116
112
|
end
|
117
113
|
|
118
114
|
def cache_flush_required?
|
@@ -139,9 +135,9 @@ module ISO3166
|
|
139
135
|
synchronized do
|
140
136
|
locale_names = load_cache(['locales', "#{locale}.json"])
|
141
137
|
internal_codes.each do |alpha2|
|
142
|
-
|
143
|
-
|
144
|
-
|
138
|
+
@cache[alpha2]['translations'] ||= Translations.new
|
139
|
+
@cache[alpha2]['translations'][locale] = locale_names[alpha2].freeze
|
140
|
+
@cache[alpha2]['translated_names'] = @cache[alpha2]['translations'].values.freeze
|
145
141
|
end
|
146
142
|
ISO3166.configuration.loaded_locales << locale
|
147
143
|
end
|
@@ -150,8 +146,8 @@ module ISO3166
|
|
150
146
|
def unload_translations(locale)
|
151
147
|
synchronized do
|
152
148
|
internal_codes.each do |alpha2|
|
153
|
-
|
154
|
-
|
149
|
+
@cache[alpha2]['translations'].delete(locale)
|
150
|
+
@cache[alpha2]['translated_names'] = @cache[alpha2]['translations'].values.freeze
|
155
151
|
end
|
156
152
|
ISO3166.configuration.loaded_locales.delete(locale)
|
157
153
|
end
|
@@ -163,7 +159,7 @@ module ISO3166
|
|
163
159
|
end
|
164
160
|
|
165
161
|
def datafile_path(file_array)
|
166
|
-
File.join([
|
162
|
+
File.join([@cache_dir] + file_array)
|
167
163
|
end
|
168
164
|
|
169
165
|
def deep_stringify_keys(data)
|
@@ -171,7 +167,8 @@ module ISO3166
|
|
171
167
|
data.transform_values! do |v|
|
172
168
|
v.is_a?(Hash) ? deep_stringify_keys(v) : v
|
173
169
|
end
|
174
|
-
|
170
|
+
|
171
|
+
data
|
175
172
|
end
|
176
173
|
end
|
177
174
|
end
|
data/lib/countries/global.rb
CHANGED
data/lib/countries/iso3166.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
require 'json'
|
3
5
|
require 'i18n_data'
|
@@ -8,6 +10,7 @@ require 'countries/data'
|
|
8
10
|
require 'countries/structure'
|
9
11
|
require 'countries/translations'
|
10
12
|
require 'countries/country/class_methods'
|
13
|
+
require 'countries/country/finder_methods'
|
11
14
|
require 'countries/country/emoji'
|
12
15
|
require 'countries/country'
|
13
16
|
require 'countries/subdivision'
|
data/lib/countries/mongoid.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
require 'net/http'
|
3
5
|
require 'nokogiri'
|
@@ -19,19 +21,17 @@ module Sources
|
|
19
21
|
def download_folder(type)
|
20
22
|
folder = File.join(ISO3166_ROOT_PATH, 'tmp', 'cldr', 'trunk', 'common', type)
|
21
23
|
FileUtils.mkdir_p(folder)
|
22
|
-
url = URI.parse("https://api.github.com/repos/unicode-org/cldr/contents/common
|
24
|
+
url = URI.parse("https://api.github.com/repos/unicode-org/cldr/contents/common/#{type}")
|
23
25
|
path_listing = JSON.parse(Net::HTTP.get_response(url).body)
|
24
26
|
path_listing.each do |path|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
next unless path['name'] =~ /\.xml$/
|
28
|
+
|
29
|
+
File.open(File.join(folder, path['name']), 'w') do |f|
|
30
|
+
raw_url = URI.parse(path['download_url'])
|
31
|
+
f.write(Net::HTTP.get_response(raw_url).body)
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
33
|
-
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sources
|
2
4
|
module CLDR
|
3
5
|
# Auxiliary Subdivision class to support loading Unicode CLDR data to update local files
|
4
6
|
class Subdivision
|
5
7
|
attr_reader :xml, :language_code
|
8
|
+
|
6
9
|
def initialize(language_code:, xml:)
|
7
10
|
@language_code = language_code
|
8
11
|
@xml = xml
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support'
|
2
4
|
require 'active_support/core_ext/hash/deep_merge'
|
3
5
|
require 'nokogiri'
|
@@ -9,25 +11,29 @@ module Sources
|
|
9
11
|
class SubdivisionUpdater
|
10
12
|
def call
|
11
13
|
d = Dir['./tmp/cldr/trunk/common/subdivisions/*.xml']
|
12
|
-
loader = Sources::Local::CachedLoader.new(Sources::Local::Subdivision)
|
13
|
-
d.each
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
@loader = Sources::Local::CachedLoader.new(Sources::Local::Subdivision)
|
15
|
+
d.each { |file_path| update_locale(file_path) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_locale(file_path)
|
19
|
+
language_data = Nokogiri::XML(File.read(file_path))
|
20
|
+
language_code = File.basename(file_path, '.*')
|
21
|
+
subdivisions = language_data.css('subdivision')
|
22
|
+
next if subdivisions.empty?
|
23
|
+
|
24
|
+
last_country_code_seen = nil
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
last_country_code_seen = subdivision.country_code
|
26
|
+
subdivisions.each_with_index do |subdivision, index|
|
27
|
+
subdivision = Sources::CLDR::Subdivision.new(language_code: language_code, xml: subdivision)
|
28
|
+
data = @loader.load(subdivision.country_code)
|
29
|
+
data[subdivision.code] ||= {}
|
30
|
+
data[subdivision.code] = data[subdivision.code].deep_merge(subdivision.to_h)
|
31
|
+
if (last_country_code_seen && last_country_code_seen != subdivision.country_code) ||
|
32
|
+
index == subdivisions.size - 1
|
33
|
+
puts "Updated #{subdivision.country_code} with language_code #{language_code}"
|
34
|
+
@loader.save(subdivision.country_code, data)
|
30
35
|
end
|
36
|
+
last_country_code_seen = subdivision.country_code
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sources
|
2
4
|
# Support code to allow updating subdivision data from the Unicode CLDR repository
|
3
5
|
module Local
|
4
6
|
# Loader for locally-cached data, to allow merging Unicode CLDR data with existing local data
|
5
7
|
class CachedLoader
|
6
8
|
attr_reader :klass
|
9
|
+
|
7
10
|
def initialize(klass)
|
8
11
|
@klass = klass
|
9
12
|
@loaded_countries = {}
|
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sources
|
2
4
|
module Local
|
3
5
|
# Auxiliary Subdivision class to support loading the local subdivision data to be updated with Unicode CLDR data
|
4
6
|
class Subdivision
|
5
7
|
attr_reader :code
|
8
|
+
|
6
9
|
def initialize(code)
|
7
10
|
@code = code
|
8
11
|
end
|
@@ -16,8 +19,8 @@ module Sources
|
|
16
19
|
end
|
17
20
|
|
18
21
|
def save(data)
|
19
|
-
File.
|
20
|
-
rescue
|
22
|
+
File.write(file_path, data.to_yaml)
|
23
|
+
rescue StandardError
|
21
24
|
puts "failed to read #{file}: #{$ERROR_INFO}"
|
22
25
|
end
|
23
26
|
|