worldwide 0.1.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5239439f9dda5abcf62fc8cbb59343a420a34ef5abe96c7b6cd23a17a633623a
4
- data.tar.gz: 8438623520e1065231f78707ebaadeee25c0bd2f5ec4f795cbde00284a69fd45
3
+ metadata.gz: 70f7f2806122734340656c024d816ec4028060de514b5dc4773529ce8bff4f37
4
+ data.tar.gz: 3c5c2237879ab05f1a77505432bca89ad50e9d5667ff1d1951b501c07f43050e
5
5
  SHA512:
6
- metadata.gz: 578e7e33cf986cda84b85c4d9e2f1092d13e3fd513b63667ee757cc6bbc937b84855ca4718a262ea5b6ecffa4203924a7fc1c5395fde98582c31adda4e1ab78d
7
- data.tar.gz: 2e28c5c0b5823979d7114b466e931429ec7376a90d1e1eb7de34c93a9dff059068ae65b548f0f3cf0f75c29c6f16051f9050ae1eb337ac51486ed0949d31c54c
6
+ metadata.gz: 1f8e9fa1416ccc24d3818e609acf7d05da6534cdb9b1e780af496151559bbb5e73540df416d85d554a3083a5add5691df2ab512fa023da3ca43d85251a89c18d
7
+ data.tar.gz: d55d1ed819560e45099c6ae1fc9e1cc5f62e0a6b62c4e9b24aa97daa78b7aae0e6cb8636dc0b6086ca5ba7f3a715badc0e7d4c60ddde09df49cb2b2c00677e8c
data/CHANGELOG.md CHANGED
@@ -28,6 +28,24 @@ Nil.
28
28
 
29
29
  ---
30
30
 
31
+ [0.3.0] - 2023-11-03
32
+ - Add code alternates for Japan [#23](https://github.com/Shopify/worldwide/pull/23)
33
+ - Add code alternates for Puerto Rico [#24](https://github.com/Shopify/worldwide/pull/24)
34
+ - Record multiple parents per region [#27](https://github.com/Shopify/worldwide/pull/27)
35
+ - Add region.building_number_may_be_in_address2 [#28](https://github.com/Shopify/worldwide/pull/28)
36
+ - Lookup by parent-child ISO and CLDR codes for dual-status territories
37
+ [#29](https://github.com/Shopify/worldwide/pull/29)
38
+ - Handle ISO_CODE only zones lookup [#26](https://github.com/Shopify/worldwide/pull/26)
39
+
40
+
41
+ [0.2.0] - 2023-11-01
42
+
43
+ - Add Region#group and Region#group_name [#15](https://github.com/Shopify/worldwide/pull/15)
44
+ - Ensure Region#has_zip? returns a boolean for all regions [#17](https://github.com/Shopify/worldwide/pull/17)
45
+ - Zip normalization bugfix when parent isocode is not set [#6](https://github.com/Shopify/worldwide/pull/6)
46
+ - Update region parent when alternates are defined [#18](https://github.com/Shopify/worldwide/pull/18)
47
+ - Add partial matching for Region#valid_zip? [#19](https://github.com/Shopify/worldwide/pull/19)
48
+
31
49
  [0.1.1] - 2023-10-27
32
50
 
33
51
  - Fix issue with deploy to rubygems.org failing
data/Gemfile.lock CHANGED
@@ -13,7 +13,7 @@ GIT
13
13
  PATH
14
14
  remote: .
15
15
  specs:
16
- worldwide (0.1.1)
16
+ worldwide (0.3.0)
17
17
  activesupport (~> 7.0)
18
18
  i18n (~> 1.12.0)
19
19
  phonelib (~> 0.8)
data/README.md CHANGED
@@ -99,7 +99,7 @@ Worldwide exposes the notion of a "region", or political subdivision. This can
99
99
 
100
100
  Note that, when exposing geographic information to users, you should be careful what you refer
101
101
  to as a "country". For backward compatibility with historical APIs, we use the term "country"
102
- to refer to what CLDR refers to as a "territory", and what we describe in our user interfarce as
102
+ to refer to what CLDR refers to as a "territory", and what we describe in our user interface as
103
103
  a "country / region". Examples of such entities include Canada, the United States, and Russia,
104
104
  but also territories with a "dual" status such as Guernsey, Hong Kong, and Martinique.
105
105
 
@@ -14,6 +14,7 @@ zip_regex: "^(IT?-?)?\\d{5}$"
14
14
  zip_example: '00144'
15
15
  phone_number_prefix: 39
16
16
  building_number_required: true
17
+ building_number_may_be_in_address2: true
17
18
  week_start_day: monday
18
19
  languages:
19
20
  - it
@@ -19,6 +19,8 @@ module Worldwide
19
19
  :example_city,
20
20
  :flag,
21
21
  :format,
22
+ :group,
23
+ :group_name,
22
24
  :cldr_code,
23
25
  :iso_code,
24
26
  :languages,
@@ -32,7 +34,9 @@ module Worldwide
32
34
  :zip_requirement,
33
35
  ]
34
36
 
35
- attr_accessor :parent
37
+ # A region may have more than one parent.
38
+ # For example, Puerto Rico (PR/US-PR) is associated with both the US and the Caribbean (029)
39
+ attr_accessor :parents
36
40
 
37
41
  # ISO-3166 three-letter code for this region, if there is one.
38
42
  # Otherwise, nil.
@@ -43,6 +47,10 @@ module Worldwide
43
47
  # If we require a building number in an address, then this will be true.
44
48
  attr_accessor :building_number_required
45
49
 
50
+ # In some countries, an address may have the building number in address2.
51
+ # If we are allowed to have a building number in address2, then this will be true.
52
+ attr_accessor :building_number_may_be_in_address2
53
+
46
54
  # Alternate codes which may be used to designate this region
47
55
  attr_accessor :code_alternates
48
56
 
@@ -65,6 +73,14 @@ module Worldwide
65
73
  # - show: how to arrange the fields when formatting an address for display
66
74
  attr_accessor :format
67
75
 
76
+ # The string that results from appending " Countries" to the adjectival form of the {group_name}
77
+ # @example
78
+ # CountryDb.country(code: "CA").group == "North American Countries"
79
+ attr_accessor :group
80
+
81
+ # The continent that this region is part of.
82
+ attr_accessor :group_name
83
+
68
84
  # If this flag is set, then we support provinces "under the hood" for this country, but we do not
69
85
  # show them as part of a formatted address. If the province is missing, we will auto-infer it
70
86
  # based on the zip (note that this auto-inference may be wrong for some addresses near a border).
@@ -207,9 +223,12 @@ module Worldwide
207
223
  @use_zone_code_as_short_name = use_zone_code_as_short_name
208
224
 
209
225
  @building_number_required = false
226
+ @building_number_may_be_in_address2 = false
210
227
  @currency = nil
211
228
  @flag = nil
212
229
  @format = {}
230
+ @group = nil
231
+ @group_name = nil
213
232
  @languages = []
214
233
  @neighbours = []
215
234
  @partial_zip_regex = nil
@@ -224,7 +243,7 @@ module Worldwide
224
243
  @zip_prefixes = []
225
244
  @zip_regex = nil
226
245
 
227
- @parent = nil
246
+ @parents = [].to_set
228
247
  @zones = []
229
248
  end
230
249
 
@@ -237,12 +256,18 @@ module Worldwide
237
256
  def add_zone(region)
238
257
  return if @zones.include?(region)
239
258
 
240
- region.parent = self
259
+ region.parents << self
241
260
  @zones.append(region)
242
261
  end
243
262
 
244
263
  # Attributes
245
264
 
265
+ def associated_country
266
+ return self if country?
267
+
268
+ parent_country
269
+ end
270
+
246
271
  # The value with which to autofill the zip, if this region has zip autofill active;
247
272
  # otherwise, nil.
248
273
  def autofill_zip
@@ -289,7 +314,7 @@ module Worldwide
289
314
 
290
315
  # Does this region have postal codes?
291
316
  def has_zip?
292
- format["show"]&.include?("{zip}")
317
+ !!format["show"]&.include?("{zip}")
293
318
  end
294
319
 
295
320
  # Is this Region considered a "province" (political subdivision of a "country")?
@@ -321,7 +346,8 @@ module Worldwide
321
346
 
322
347
  zones.find do |region|
323
348
  [search_code, alt_search_code].any? do |candidate|
324
- candidate == region.alpha_three ||
349
+ candidate == subdivision_code(region.iso_code) ||
350
+ candidate == region.alpha_three ||
325
351
  candidate == region.iso_code ||
326
352
  candidate == region.legacy_code ||
327
353
  candidate == region.numeric_three ||
@@ -357,12 +383,12 @@ module Worldwide
357
383
  end
358
384
 
359
385
  # is the given postal code value valid for this region?
360
- def valid_zip?(zip)
386
+ def valid_zip?(zip, partial_match: false)
361
387
  normalized = Zip.normalize(
362
- country_code: province? ? parent.iso_code : iso_code,
388
+ country_code: province? && associated_country.iso_code ? associated_country.iso_code : iso_code,
363
389
  zip: zip,
364
390
  )
365
- valid_normalized_zip?(normalized)
391
+ valid_normalized_zip?(normalized, partial_match: partial_match)
366
392
  end
367
393
 
368
394
  # are zones optional for this region?
@@ -372,6 +398,21 @@ module Worldwide
372
398
 
373
399
  private
374
400
 
401
+ def answers_to_cldr_code(search_code)
402
+ return false if Util.blank?(search_code) || Util.blank?(cldr_code)
403
+ return true if search_code.casecmp(cldr_code).zero?
404
+
405
+ pc = parent_country
406
+ "#{pc&.cldr_code&.downcase}#{cldr_code.downcase}" == search_code.downcase
407
+ end
408
+
409
+ def answers_to_iso_code(search_code)
410
+ return true if search_code == iso_code
411
+
412
+ pc = parent_country
413
+ "#{pc&.iso_code}-#{iso_code}" == search_code
414
+ end
415
+
375
416
  def cross_border_zip_includes_province?(zip:, province_code:)
376
417
  return false unless country?
377
418
 
@@ -396,11 +437,17 @@ module Worldwide
396
437
  INSPECTION_FIELDS.map { |field_name| "@#{field_name}=#{send(field_name).inspect}" }.join(", ")
397
438
  end
398
439
 
440
+ def parent_country
441
+ parents.find(&:country?)
442
+ end
443
+
399
444
  # Checks whether the given value is acceptable according to the regular expression defined for the country.
400
445
  # @param value [String] for the postal code
401
446
  # @return [Boolean]
402
447
  def passes_country_zip_regexp?(value:, partial_match: false)
403
- return parent.send(:passes_country_zip_regexp?, value: value, partial_match: partial_match) if province?
448
+ if province?
449
+ return associated_country.send(:passes_country_zip_regexp?, value: value, partial_match: partial_match)
450
+ end
404
451
 
405
452
  return false if partial_match && partial_zip_regex.nil?
406
453
 
@@ -433,11 +480,18 @@ module Worldwide
433
480
  end&.first
434
481
  end
435
482
 
483
+ def subdivision_code(iso_code)
484
+ return iso_code if iso_code.nil? || iso_code.length < 3
485
+
486
+ country_code, subdivision_code = iso_code.split("-")
487
+ return subdivision_code if country_code.casecmp(associated_country.iso_code).zero?
488
+ end
489
+
436
490
  def valid_normalized_zip?(normalized, province_code: nil, partial_match: false)
437
491
  if country?
438
492
  country = self
439
493
  elsif province?
440
- country = parent
494
+ country = associated_country
441
495
  province_code ||= legacy_code
442
496
  end
443
497
 
@@ -32,13 +32,13 @@ module Worldwide
32
32
  search_code = cldr.to_s.upcase
33
33
 
34
34
  @regions.find do |r|
35
- r.cldr_code.upcase == search_code
35
+ r.send(:answers_to_cldr_code, search_code)
36
36
  end
37
37
  elsif code
38
38
  search_code = code.to_s.upcase
39
39
 
40
40
  @regions.find do |r|
41
- r.iso_code == search_code || r.alpha_three == search_code || r.numeric_three == search_code
41
+ r.send(:answers_to_iso_code, search_code) || r.alpha_three == search_code || r.numeric_three == search_code
42
42
  end
43
43
  else # search by name
44
44
  search_name = name.upcase
@@ -46,6 +46,7 @@ module Worldwide
46
46
  @regions << current_region
47
47
  end
48
48
 
49
+ current_region.parents << parent if Util.present?(parent)
49
50
  parent&.add_zone(current_region)
50
51
  return current_region if children.nil?
51
52
 
@@ -58,10 +59,13 @@ module Worldwide
58
59
 
59
60
  def apply_territory_attributes(region, spec)
60
61
  region.building_number_required = spec["building_number_required"] || true
62
+ region.building_number_may_be_in_address2 = spec["building_number_may_be_in_address2"] || false
61
63
  currency_code = spec["currency"]
62
64
  region.currency = Worldwide.currency(code: currency_code) unless currency_code.nil?
63
65
  region.flag = spec["emoji"]
64
66
  region.format = spec["format"]
67
+ region.group = spec["group"]
68
+ region.group_name = spec["group_name"]
65
69
  region.hide_provinces_from_addresses = spec["hide_provinces_from_addresses"] || false
66
70
  region.languages = spec["languages"]
67
71
  region.partial_zip_regex = spec["partial_zip_regex"]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Worldwide
4
- VERSION = "0.1.1"
4
+ VERSION = "0.3.0"
5
5
  end
data/worldwide.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = "developers@shopify.com"
12
12
 
13
13
  spec.summary = "Internationalization and localization APIs"
14
- spec.description = "APIs to support i18n and l10n of Ruby code"
14
+ spec.description = "APIs for I18n, I10n, and mailing address operations in Ruby."
15
15
  spec.homepage = "https://github.com/Shopify/worldwide"
16
16
 
17
17
  spec.metadata["allowed_push_host"] = "https://rubygems.org/"
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.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-27 00:00:00.000000000 Z
11
+ date: 2023-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.8'
55
- description: APIs to support i18n and l10n of Ruby code
55
+ description: APIs for I18n, I10n, and mailing address operations in Ruby.
56
56
  email: developers@shopify.com
57
57
  executables: []
58
58
  extensions: []