worldwide 0.10.3 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -1
  3. data/CHANGELOG.md +34 -25
  4. data/Gemfile.lock +15 -13
  5. data/db/data/regions/AE/bg-BG.yml +1 -0
  6. data/db/data/regions/AE/cs.yml +1 -0
  7. data/db/data/regions/AE/da.yml +1 -0
  8. data/db/data/regions/AE/de.yml +1 -0
  9. data/db/data/regions/AE/el.yml +1 -0
  10. data/db/data/regions/AE/en.yml +1 -0
  11. data/db/data/regions/AE/es.yml +1 -0
  12. data/db/data/regions/AE/fi.yml +1 -0
  13. data/db/data/regions/AE/fr.yml +1 -0
  14. data/db/data/regions/AE/hi.yml +1 -0
  15. data/db/data/regions/AE/hr-HR.yml +1 -0
  16. data/db/data/regions/AE/hu.yml +1 -0
  17. data/db/data/regions/AE/id.yml +1 -0
  18. data/db/data/regions/AE/it.yml +1 -0
  19. data/db/data/regions/AE/ja.yml +1 -0
  20. data/db/data/regions/AE/ko.yml +1 -0
  21. data/db/data/regions/AE/lt-LT.yml +1 -0
  22. data/db/data/regions/AE/nb.yml +1 -0
  23. data/db/data/regions/AE/nl.yml +1 -0
  24. data/db/data/regions/AE/pl.yml +1 -0
  25. data/db/data/regions/AE/pt-BR.yml +1 -0
  26. data/db/data/regions/AE/pt-PT.yml +1 -0
  27. data/db/data/regions/AE/ro-RO.yml +1 -0
  28. data/db/data/regions/AE/ru.yml +1 -0
  29. data/db/data/regions/AE/sk-SK.yml +1 -0
  30. data/db/data/regions/AE/sl-SI.yml +1 -0
  31. data/db/data/regions/AE/sv.yml +1 -0
  32. data/db/data/regions/AE/th.yml +1 -0
  33. data/db/data/regions/AE/tr.yml +1 -0
  34. data/db/data/regions/AE/vi.yml +1 -0
  35. data/db/data/regions/AE/zh-CN.yml +1 -0
  36. data/db/data/regions/AE/zh-TW.yml +1 -0
  37. data/db/data/regions/CA/bg-BG.yml +1 -0
  38. data/db/data/regions/CA/cs.yml +1 -0
  39. data/db/data/regions/CA/da.yml +1 -0
  40. data/db/data/regions/CA/de.yml +1 -0
  41. data/db/data/regions/CA/el.yml +1 -0
  42. data/db/data/regions/CA/es.yml +1 -0
  43. data/db/data/regions/CA/fi.yml +1 -0
  44. data/db/data/regions/CA/fr.yml +1 -0
  45. data/db/data/regions/CA/hi.yml +1 -0
  46. data/db/data/regions/CA/hr-HR.yml +1 -0
  47. data/db/data/regions/CA/hu.yml +1 -0
  48. data/db/data/regions/CA/id.yml +1 -0
  49. data/db/data/regions/CA/it.yml +1 -0
  50. data/db/data/regions/CA/ja.yml +1 -0
  51. data/db/data/regions/CA/ko.yml +1 -0
  52. data/db/data/regions/CA/lt-LT.yml +1 -0
  53. data/db/data/regions/CA/ms.yml +1 -0
  54. data/db/data/regions/CA/nb.yml +1 -0
  55. data/db/data/regions/CA/nl.yml +1 -0
  56. data/db/data/regions/CA/pl.yml +1 -0
  57. data/db/data/regions/CA/pt-BR.yml +1 -0
  58. data/db/data/regions/CA/pt-PT.yml +1 -0
  59. data/db/data/regions/CA/ro-RO.yml +2 -0
  60. data/db/data/regions/CA/ru.yml +1 -0
  61. data/db/data/regions/CA/sk-SK.yml +1 -0
  62. data/db/data/regions/CA/sl-SI.yml +1 -0
  63. data/db/data/regions/CA/sv.yml +1 -0
  64. data/db/data/regions/CA/th.yml +1 -0
  65. data/db/data/regions/CA/tr.yml +1 -0
  66. data/db/data/regions/CA/vi.yml +1 -0
  67. data/db/data/regions/CA/zh-CN.yml +1 -0
  68. data/db/data/regions/CA/zh-TW.yml +1 -0
  69. data/db/data/regions/GB.yml +1 -1
  70. data/db/data/regions/JP/ja.yml +1 -1
  71. data/db/data/regions/US/bg-BG.yml +2 -0
  72. data/db/data/regions/US/cs.yml +2 -0
  73. data/db/data/regions/US/da.yml +2 -0
  74. data/db/data/regions/US/de.yml +2 -0
  75. data/db/data/regions/US/el.yml +2 -0
  76. data/db/data/regions/US/es.yml +2 -0
  77. data/db/data/regions/US/fi.yml +2 -0
  78. data/db/data/regions/US/fr.yml +2 -0
  79. data/db/data/regions/US/hi.yml +2 -0
  80. data/db/data/regions/US/hr-HR.yml +2 -0
  81. data/db/data/regions/US/hu.yml +2 -0
  82. data/db/data/regions/US/id.yml +2 -0
  83. data/db/data/regions/US/it.yml +2 -0
  84. data/db/data/regions/US/ja.yml +2 -0
  85. data/db/data/regions/US/ko.yml +2 -0
  86. data/db/data/regions/US/lt-LT.yml +2 -0
  87. data/db/data/regions/US/ms.yml +2 -0
  88. data/db/data/regions/US/nb.yml +2 -0
  89. data/db/data/regions/US/nl.yml +2 -0
  90. data/db/data/regions/US/pl.yml +2 -0
  91. data/db/data/regions/US/pt-BR.yml +2 -0
  92. data/db/data/regions/US/pt-PT.yml +2 -0
  93. data/db/data/regions/US/ro-RO.yml +3 -0
  94. data/db/data/regions/US/ru.yml +2 -0
  95. data/db/data/regions/US/sk-SK.yml +2 -0
  96. data/db/data/regions/US/sl-SI.yml +2 -0
  97. data/db/data/regions/US/sv.yml +2 -0
  98. data/db/data/regions/US/th.yml +2 -0
  99. data/db/data/regions/US/tr.yml +2 -0
  100. data/db/data/regions/US/vi.yml +2 -0
  101. data/db/data/regions/US/zh-CN.yml +2 -0
  102. data/db/data/regions/US/zh-TW.yml +2 -0
  103. data/db/extant_outcodes.yml +3134 -0
  104. data/lib/worldwide/address.rb +1 -1
  105. data/lib/worldwide/address_validator.rb +1 -1
  106. data/lib/worldwide/currencies.rb +1 -1
  107. data/lib/worldwide/currency.rb +3 -7
  108. data/lib/worldwide/extant_outcodes.rb +32 -0
  109. data/lib/worldwide/phone.rb +5 -0
  110. data/lib/worldwide/region.rb +8 -3
  111. data/lib/worldwide/regions_loader.rb +2 -2
  112. data/lib/worldwide/version.rb +1 -1
  113. data/lib/worldwide/zip.rb +118 -39
  114. data/lib/worldwide.rb +1 -0
  115. metadata +5 -3
@@ -300,7 +300,7 @@ module Worldwide
300
300
  end
301
301
 
302
302
  def normalize_city
303
- Worldwide.region(code: @country_code)&.field(key: :city)&.autofill || @city
303
+ Worldwide.region(code: @country_code)&.autofill_city || @city
304
304
  end
305
305
 
306
306
  def normalize_country_code(autocorrect_level:)
@@ -73,7 +73,7 @@ module Worldwide
73
73
 
74
74
  return [] if country.nil?
75
75
  return [] if country.zones.nil?
76
- return [] if country.zones.select(&:province?).empty?
76
+ return [] if country.zones.none?(&:province?)
77
77
  return [] if country.hide_provinces_from_addresses
78
78
 
79
79
  if Util.blank?(address.province_code)
@@ -45,7 +45,7 @@ module Worldwide
45
45
  end
46
46
 
47
47
  def currency_codes
48
- @currency_codes ||= YAML.safe_load(File.read(CURRENCY_CODES_FILE_PATH))
48
+ @currency_codes ||= YAML.safe_load_file(CURRENCY_CODES_FILE_PATH)
49
49
  end
50
50
 
51
51
  def map_alpha_three_to_numeric_three
@@ -12,15 +12,11 @@ module Worldwide
12
12
 
13
13
  class << self
14
14
  def digits_and_rounding
15
- @digits_and_rounding ||= YAML.safe_load(
16
- File.read(File.join(Worldwide::Paths::OTHER_DATA_ROOT, "currency", "digits.yml")),
17
- ).freeze
15
+ @digits_and_rounding ||= YAML.safe_load_file(File.join(Worldwide::Paths::OTHER_DATA_ROOT, "currency", "digits.yml")).freeze
18
16
  end
19
17
 
20
18
  def minor_symbols
21
- @minor_symbols ||= YAML.safe_load(
22
- File.read(File.join(Worldwide::Paths::OTHER_DATA_ROOT, "currency", "minor_symbols.yml")),
23
- ).freeze
19
+ @minor_symbols ||= YAML.safe_load_file(File.join(Worldwide::Paths::OTHER_DATA_ROOT, "currency", "minor_symbols.yml")).freeze
24
20
  end
25
21
  end
26
22
 
@@ -170,7 +166,7 @@ module Worldwide
170
166
 
171
167
  if prefix?(locale)
172
168
  if formatted.include?("-")
173
- "-#{symbol}#{space}#{formatted.sub(/\-/, "")}"
169
+ "-#{symbol}#{space}#{formatted.sub("-", "")}"
174
170
  else
175
171
  "#{symbol}#{space}#{formatted}"
176
172
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "singleton"
5
+ require "yaml"
6
+
7
+ module Worldwide
8
+ class ExtantOutcodes
9
+ include Singleton
10
+
11
+ class << self
12
+ extend Forwardable
13
+ def_delegators :instance, :for_country
14
+ end
15
+
16
+ def for_country(code:)
17
+ extant[code.to_s.downcase]
18
+ end
19
+
20
+ private
21
+
22
+ def initialize
23
+ @extant = nil
24
+ end
25
+
26
+ def extant
27
+ @extant ||= YAML.safe_load_file("#{::Worldwide::Paths::GEM_ROOT}/db/extant_outcodes.yml").dig("extant_outcodes")&.map do |key, value|
28
+ [key, value.to_set]
29
+ end&.to_h || {}
30
+ end
31
+ end
32
+ end
@@ -48,6 +48,11 @@ module Worldwide
48
48
  @parsed_number.valid?
49
49
  end
50
50
 
51
+ # Returns the country prefix for the phone number
52
+ def country_prefix
53
+ @parsed_number.country_code
54
+ end
55
+
51
56
  private
52
57
 
53
58
  # For various reasons, Worldwide considers these territories to be zones inside the USA
@@ -291,9 +291,14 @@ module Worldwide
291
291
  zip_example if @zip_autofill_enabled
292
292
  end
293
293
 
294
+ # The value with which to autofill the city, if this region has a default city; otherwise, nil.
295
+ def autofill_city(locale: I18n.locale)
296
+ field(key: :city).autofill(locale: locale)
297
+ end
298
+
294
299
  # Does this region require cities to be specified?
295
300
  def city_required?
296
- field(key: :city).autofill(locale: :en).nil?
301
+ autofill_city(locale: :en).nil?
297
302
  end
298
303
 
299
304
  # Is this Region a continent?
@@ -386,7 +391,7 @@ module Worldwide
386
391
  # If the Region has an autofill zip, return the value that will be autofilled
387
392
  # Otherwise, return nil
388
393
  def zip_autofill
389
- return zip_example if zip_autofill_enabled
394
+ zip_example if zip_autofill_enabled
390
395
  end
391
396
 
392
397
  # is a postal code required for this region?
@@ -511,7 +516,7 @@ module Worldwide
511
516
  return iso_code if iso_code.nil? || iso_code.length < 3
512
517
 
513
518
  country_code, subdivision_code = iso_code.split("-")
514
- return subdivision_code if country_code.casecmp(associated_country.iso_code).zero?
519
+ subdivision_code if country_code.casecmp(associated_country.iso_code).zero?
515
520
  end
516
521
 
517
522
  def valid_normalized_zip?(normalized, province_code: nil, partial_match: false)
@@ -199,7 +199,7 @@ module Worldwide
199
199
 
200
200
  def country_codes
201
201
  @country_codes ||=
202
- YAML.safe_load(File.read("#{Worldwide::Paths::DB_DATA_ROOT}/country_codes.yml"))["country_codes"]
202
+ YAML.safe_load_file("#{Worldwide::Paths::DB_DATA_ROOT}/country_codes.yml")["country_codes"]
203
203
  end
204
204
 
205
205
  def find_region(code:)
@@ -212,7 +212,7 @@ module Worldwide
212
212
  end
213
213
 
214
214
  def load_territory(filename)
215
- spec = YAML.safe_load(File.read(filename))
215
+ spec = YAML.safe_load_file(filename)
216
216
  code = spec["code"]
217
217
 
218
218
  loaded_regions = []
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Worldwide
4
- VERSION = "0.10.3"
4
+ VERSION = "0.11.0"
5
5
  end
data/lib/worldwide/zip.rb CHANGED
@@ -107,40 +107,38 @@ module Worldwide
107
107
  zip = strip_extraneous_characters(zip: zip, country_code: country_code)
108
108
  end
109
109
 
110
- result = if gb_style?(country_code: country.iso_code)
111
- normalize_for_gb(zip: zip)
110
+ return normalize_for_gb(zip: zip) if gb_style?(country_code: country.iso_code)
111
+
112
+ # Remove both normal-width and double-width spaces
113
+ zip.delete!("  ")
114
+ zip = replace_letters_and_numbers(country_code: country.iso_code, zip: zip)
115
+
116
+ result = if "BD" == country.iso_code
117
+ normalize_for_bd(zip: zip)
118
+ elsif "FO" == country.iso_code
119
+ normalize_for_fo(zip: zip)
120
+ elsif "GH" == country.iso_code
121
+ normalize_for_gh(zip: zip)
122
+ elsif "HT" == country.iso_code
123
+ normalize_for_ht(zip: zip)
124
+ elsif "LK" == country.iso_code
125
+ normalize_for_lk(zip: zip)
126
+ elsif "MD" == country.iso_code
127
+ normalize_for_md(zip: zip)
128
+ elsif "MG" == country.iso_code
129
+ normalize_for_mg(zip: zip)
130
+ elsif "NG" == country.iso_code
131
+ normalize_for_ng(zip: zip)
132
+ elsif "SG" == country.iso_code
133
+ normalize_for_sg(zip: zip)
134
+ elsif "MA" == country.iso_code
135
+ normalize_for_ma(zip: zip)
136
+ elsif "XK" == country.iso_code
137
+ normalize_for_xk(zip: zip)
138
+ elsif "BR" == country.iso_code || "JP" == country.iso_code
139
+ insert_spaces_and_hyphens_for_partial_code(country_code: country.iso_code, zip: zip)
112
140
  else
113
- # Remove both normal-width and double-width spaces
114
- zip.delete!("  ")
115
- zip = replace_letters_and_numbers(country_code: country.iso_code, zip: zip)
116
-
117
- if "BD" == country.iso_code
118
- normalize_for_bd(zip: zip)
119
- elsif "FO" == country.iso_code
120
- normalize_for_fo(zip: zip)
121
- elsif "GH" == country.iso_code
122
- normalize_for_gh(zip: zip)
123
- elsif "HT" == country.iso_code
124
- normalize_for_ht(zip: zip)
125
- elsif "LK" == country.iso_code
126
- normalize_for_lk(zip: zip)
127
- elsif "MD" == country.iso_code
128
- normalize_for_md(zip: zip)
129
- elsif "MG" == country.iso_code
130
- normalize_for_mg(zip: zip)
131
- elsif "NG" == country.iso_code
132
- normalize_for_ng(zip: zip)
133
- elsif "SG" == country.iso_code
134
- normalize_for_sg(zip: zip)
135
- elsif "MA" == country.iso_code
136
- normalize_for_ma(zip: zip)
137
- elsif "XK" == country.iso_code
138
- normalize_for_xk(zip: zip)
139
- elsif "BR" == country.iso_code || "JP" == country.iso_code
140
- insert_spaces_and_hyphens_for_partial_code(country_code: country.iso_code, zip: zip)
141
- else
142
- insert_spaces_and_hyphens(country_code: country.iso_code, zip: zip)
143
- end
141
+ insert_spaces_and_hyphens(country_code: country.iso_code, zip: zip)
144
142
  end
145
143
 
146
144
  if country.send(:valid_normalized_zip?, result)
@@ -161,7 +159,26 @@ module Worldwide
161
159
 
162
160
  return zip unless @split_code_countries.include?(country_code.to_s.upcase)
163
161
 
164
- normalize(country_code: country_code, zip: zip)&.split(" ")&.first
162
+ normalized_input = normalize(country_code: country_code, zip: zip).upcase
163
+ normalized_country_code = country_code.to_s.upcase
164
+
165
+ if Worldwide.region(code: country_code).valid_zip?(normalized_input)
166
+ # We successfully normalized the postcode, so we can split on the space to determine the outcode
167
+ normalized_input&.split(" ")&.first
168
+ else
169
+ # We have either an invalid or an incomplete postcode. Let's try some fancy heuristics
170
+ case country_code.to_s.upcase
171
+ when "CA", "IE"
172
+ # the FSA / routing code is the first 3 characters
173
+ normalized_input[0..2]
174
+ when "GB", "GG", "IM", "JE"
175
+ gb_style_outcode(country_code: normalized_country_code, input: normalized_input)
176
+ when "GI"
177
+ "GX11"
178
+ else
179
+ normalized_input
180
+ end
181
+ end
165
182
  end
166
183
 
167
184
  def strip_optional_country_prefix(country_code:, zip:)
@@ -195,6 +212,55 @@ module Worldwide
195
212
  end
196
213
  end
197
214
 
215
+ def gb_style_outcode(country_code:, input:)
216
+ normalized = input
217
+
218
+ m = /^([A-Z]{1,2})/.match(normalized)
219
+ return normalized if m.nil?
220
+
221
+ area = m[1]
222
+ return normalized if area.nil?
223
+
224
+ # Let's get the first, second and third characters following the area
225
+ first = normalized[area.length]
226
+ second = normalized[area.length + 1]
227
+ third = normalized[area.length + 2]
228
+
229
+ candidate = case area
230
+ when "E", "EC", "N", "NW", "SE", "SW", "W", "WC"
231
+ # These London districts may include a single-letter suffix as part of the district
232
+ # In all such cases, the district is one digit + one letter
233
+
234
+ if /[A-Z]/.match?(second)
235
+ # This must be a district suffix, so disctrict consists of first + second
236
+ "#{area}#{first}#{second}".strip
237
+ elsif /[A-Z]/.match?(third)
238
+ # Because third is a letter, second must be the sector, and the district must be a single digit
239
+ "#{area}#{first}".strip
240
+ else
241
+ # Otherwise, we'll assume that we've got a two-digit district
242
+ "#{area}#{first}#{second}".strip
243
+ end
244
+ else
245
+ # The outcode is the area plus at most two digits following it
246
+
247
+ if /[A-Z]/.match?(third)
248
+ # Because third is a letter, second must be the sector, and the district must be a single digit
249
+ "#{area}#{first}"
250
+ else
251
+ "#{area}#{first}#{second}".strip
252
+ end
253
+ end
254
+
255
+ if /[0-9]/.match?(second) && !Worldwide::ExtantOutcodes.for_country(code: country_code).include?(candidate)
256
+ # We've guessed a two-digit district that does not actually exist, so we'll assume a single-digit district.
257
+ # For example, "GL71" can't be an outcode, so we'll assume the user meant outcode "GL7".
258
+ "#{area}#{first}"
259
+ else
260
+ candidate
261
+ end
262
+ end
263
+
198
264
  private
199
265
 
200
266
  # Countries that use GB-style postal code spacing, and should normalize the same way as GB
@@ -350,7 +416,7 @@ module Worldwide
350
416
  GB_POSTAL_TOWN_WITH_SECOND_CHAR_OH = ["C", "S", "P", "Y"]
351
417
  private_constant :GB_POSTAL_TOWN_WITH_SECOND_CHAR_OH
352
418
 
353
- # Based on postal code formats here: https://en.wikipedia.org/wiki/List_of_postal_codes
419
+ # Based on postal code formats here: https://en.wikipedia.org/wiki/List_of_zips
354
420
  NUMERIC_ONLY_ZIP_COUNTRIES = Set.new([
355
421
  "AF",
356
422
  "AL",
@@ -528,6 +594,8 @@ module Worldwide
528
594
  confidence = candidate_regex[1]
529
595
 
530
596
  normalized = normalize(country_code: candidate_code, zip: zip, allow_autofill: false)
597
+ next unless /[A-Z]/.match?(normalized) # Numeric-only postal codes are insufficiently specific
598
+
531
599
  if normalized.match(regex)
532
600
  candidate = Worldwide.region(code: candidate_code)
533
601
  suggestions.append([candidate, confidence]) if candidate.valid_zip?(normalized)
@@ -784,11 +852,22 @@ module Worldwide
784
852
  return "#{postal_town}#{division}#{division_suffix} #{digit}#{alpha}"
785
853
  end
786
854
 
787
- # Check for outcode-only postcode
788
- m = upcased.match(/^([A-Z]{1,2}\d{1,2}[A-Z]{0,1})\s*$/)
789
- if !m.nil? && m[1].length <= 4
855
+ # If the input is only the postcode area (one or two letters), return just that with no trailing space
856
+ return upcased.strip if /^[A-Z]{1,2}$/.match?(upcased.strip)
857
+
858
+ inferred_outcode = gb_style_outcode(country_code: "GB", input: upcased)
859
+
860
+ if inferred_outcode.strip == upcased.strip
790
861
  # Note that we're intentionally appending a space, so that this outcode will work for prefix matching
791
- "#{m[1]} "
862
+ return "#{inferred_outcode.strip} "
863
+ end
864
+
865
+ if inferred_outcode.nil?
866
+ # Fallback to returning the unmodified input if we weren't able to make sense of it
867
+ input
868
+ else
869
+ remainder = upcased[inferred_outcode.length..-1]
870
+ "#{inferred_outcode.strip} #{remainder.strip}"
792
871
  end
793
872
  end
794
873
 
data/lib/worldwide.rb CHANGED
@@ -10,6 +10,7 @@ require "worldwide/locale"
10
10
  require "worldwide/locales"
11
11
  require "worldwide/paths"
12
12
  require "worldwide/version"
13
+ require "worldwide/extant_outcodes"
13
14
 
14
15
  require "worldwide/address"
15
16
  require "worldwide/address_validator"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: worldwide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.3
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-14 00:00:00.000000000 Z
11
+ date: 2024-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -8170,6 +8170,7 @@ files:
8170
8170
  - db/data/regions/_default/zh-CN.yml
8171
8171
  - db/data/regions/_default/zh-TW.yml
8172
8172
  - db/data/world.yml
8173
+ - db/extant_outcodes.yml
8173
8174
  - formats.md
8174
8175
  - lib/worldwide.rb
8175
8176
  - lib/worldwide/address.rb
@@ -8185,6 +8186,7 @@ files:
8185
8186
  - lib/worldwide/currency.rb
8186
8187
  - lib/worldwide/deprecated_time_zone_mapper.rb
8187
8188
  - lib/worldwide/discounts.rb
8189
+ - lib/worldwide/extant_outcodes.rb
8188
8190
  - lib/worldwide/field.rb
8189
8191
  - lib/worldwide/fields.rb
8190
8192
  - lib/worldwide/i18n_exception_handler.rb
@@ -8231,7 +8233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
8231
8233
  - !ruby/object:Gem::Version
8232
8234
  version: '0'
8233
8235
  requirements: []
8234
- rubygems_version: 3.5.6
8236
+ rubygems_version: 3.5.7
8235
8237
  signing_key:
8236
8238
  specification_version: 4
8237
8239
  summary: Internationalization and localization APIs