worldwide 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94f52548c00b327fa3649904eb25487d9e029fc34512e0edc4cf42e82690845b
4
- data.tar.gz: aa1b423717212544a46c9286d3ffdcb1683071fd09a9ef54a372920fe9042dc0
3
+ metadata.gz: 1aced99de70bc88aa872fd56bf0aea847c81bcf3b12987e031ce39a51e9dbdd0
4
+ data.tar.gz: de70d75e3374938d1611ef3c0541ce7d880d4dbf5ad3b45fb4dddeeb6ef75382
5
5
  SHA512:
6
- metadata.gz: '08ba06ef3c1a28929ee81b7e32143b572ac5b80c869244b724a22c33ca89038e23220ecc7f6bc7cf28f56f6599f84887dabbd5d3db1dd68661991c75bd3745ff'
7
- data.tar.gz: 78fc15cb9692b9086a3bf0c3627b8285cba0acd396dc8287e0a260b2dc1168dc3e9d24091123cf0907d001f44d9a04203485b5b707d1a206deeb1a0949a56afc
6
+ metadata.gz: e77fdb3041498e31ab8cec400ca4be14e531939e9f99fa800aae011d1a7be0e076fc6b4e65ea4ca877b98a051dc6e88994b71d27582cb083fb8c71ac0645e65f
7
+ data.tar.gz: bb7c2b6963ab30589320b70db8af56942ce454d01cbf6dc7f13c7da74c86964513de2711a31bd9fa07457e96fcb810f482d89e31a214acf5454f47ec21517dfc
data/CHANGELOG.md CHANGED
@@ -29,6 +29,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
29
29
 
30
30
  ---
31
31
 
32
+ ## [0.12.0] - 2024-05-15
33
+
34
+ - Add pry-byebug gem [#149](https://github.com/Shopify/worldwide/pull/149)
35
+ - Introduce additional_address_fields to Region class and define them for BE, BR, CL, CO, ES, ID, MX, NL, PH, TR, VN [#148](https://github.com/Shopify/worldwide/pull/148)
36
+ - Define format_extended attribute on 12 country regions [#150](https://github.com/Shopify/worldwide/pull/150)
37
+
32
38
  ## [0.11.1] - 2024-05-13
33
39
 
34
40
  - Handle blank strings for Region, country_code parameter in Zip normalization
data/Gemfile CHANGED
@@ -19,6 +19,7 @@ group :development do
19
19
  gem "rubocop-shopify", require: false
20
20
  gem "rubocop", require: false
21
21
  gem "ruby-lsp", require: false
22
+ gem "pry-byebug", require: false
22
23
  end
23
24
 
24
25
  group :test do
data/Gemfile.lock CHANGED
@@ -13,7 +13,7 @@ GIT
13
13
  PATH
14
14
  remote: .
15
15
  specs:
16
- worldwide (0.11.1)
16
+ worldwide (0.12.0)
17
17
  activesupport (~> 7.0)
18
18
  i18n
19
19
  phonelib (~> 0.8)
@@ -36,6 +36,8 @@ GEM
36
36
  base64 (0.1.1)
37
37
  bigdecimal (3.1.4)
38
38
  builder (3.2.4)
39
+ byebug (11.1.3)
40
+ coderay (1.1.3)
39
41
  concurrent-ruby (1.2.2)
40
42
  connection_pool (2.4.1)
41
43
  drb (2.1.1)
@@ -44,6 +46,7 @@ GEM
44
46
  concurrent-ruby (~> 1.0)
45
47
  json (2.7.1)
46
48
  language_server-protocol (3.17.0.3)
49
+ method_source (1.1.0)
47
50
  minitest (5.17.0)
48
51
  minitest-focus (1.3.1)
49
52
  minitest (>= 4, < 6)
@@ -55,9 +58,9 @@ GEM
55
58
  mocha (2.0.2)
56
59
  ruby2_keywords (>= 0.0.5)
57
60
  mutex_m (0.1.2)
58
- nokogiri (1.16.2-arm64-darwin)
61
+ nokogiri (1.16.5-arm64-darwin)
59
62
  racc (~> 1.4)
60
- nokogiri (1.16.2-x86_64-linux)
63
+ nokogiri (1.16.5-x86_64-linux)
61
64
  racc (~> 1.4)
62
65
  parallel (1.24.0)
63
66
  parser (3.3.0.5)
@@ -65,6 +68,12 @@ GEM
65
68
  racc
66
69
  phonelib (0.8.7)
67
70
  prettier_print (1.2.0)
71
+ pry (0.14.2)
72
+ coderay (~> 1.1)
73
+ method_source (~> 1.0)
74
+ pry-byebug (3.10.1)
75
+ byebug (~> 11.0)
76
+ pry (>= 0.13, < 0.15)
68
77
  psych (5.1.0)
69
78
  stringio
70
79
  racc (1.7.3)
@@ -122,6 +131,7 @@ DEPENDENCIES
122
131
  minitest-focus
123
132
  minitest-reporters
124
133
  mocha
134
+ pry-byebug
125
135
  rake (~> 13.0)
126
136
  rake-compiler
127
137
  rubocop
data/README.md CHANGED
@@ -377,6 +377,8 @@ $ I18n.with_locale(:'zh-CN') { lon.single_line }
377
377
  => "英国London"
378
378
  ```
379
379
 
380
+ Address format strings are described in detail [here](docs/address_format_strings.md).
381
+
380
382
  #### Validation
381
383
 
382
384
  ```ruby
@@ -24,5 +24,13 @@ languages:
24
24
  format:
25
25
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}_{phone}"
26
26
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{country}_{phone}"
27
+ format_extended:
28
+ edit: "{country}_{firstName}{lastName}_{company}_{streetName}{streetNumber}_{address2}_{zip}{city}_{phone}"
29
+ additional_address_fields:
30
+ address1:
31
+ - key: streetName
32
+ required: true
33
+ - key: streetNumber
34
+ required: false
27
35
  emoji: "\U0001F1E7\U0001F1EA"
28
36
  timezone: Europe/Brussels
@@ -19,6 +19,21 @@ languages:
19
19
  format:
20
20
  edit: "{country}_{firstName}{lastName}_{company}_{zip}_{address1}_{address2}_{city}{province}_{phone}"
21
21
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city} {province}_{country}_{phone}"
22
+ format_extended:
23
+ edit: "{country}_{firstName}{lastName}_{company}_{zip}_{streetName}{streetNumber}_{address2}{neighborhood}_{city}{province}_{phone}"
24
+ additional_address_fields:
25
+ address1:
26
+ - key: streetName
27
+ required: true
28
+ - key: streetNumber
29
+ decorator: ","
30
+ required: true
31
+ address2:
32
+ - key: address2
33
+ required: false
34
+ - key: neighborhood
35
+ decorator: ","
36
+ required: false
22
37
  emoji: "\U0001F1E7\U0001F1F7"
23
38
  localized_data:
24
39
  - name: tax_credential_br
@@ -0,0 +1,25 @@
1
+ ---
2
+ en:
3
+ worldwide:
4
+ CL:
5
+ addresses:
6
+ neighborhood:
7
+ label:
8
+ default: Commune
9
+ optional: Commune (optional)
10
+ errors:
11
+ blank: Enter a commune
12
+ too_long: Commune is too long (maximum is 255 characters)
13
+ contains_emojis: Commune cannot contain emojis
14
+ contains_mathematical_symbols: Commune cannot contain mathematical symbols
15
+ contains_restricted_characters: Commune can only contain letters, numbers,
16
+ local characters, and special characters
17
+ contains_too_many_words: Commune cannot have more than %{word_count}
18
+ words
19
+ contains_html_tags: Commune cannot contain HTML tags.
20
+ contains_url: Commune cannot contain URLs.
21
+ unknown_for_city: Enter a valid commune name for %{city}.
22
+ unknown_for_zip: Enter a valid commune name for %{zip}.
23
+ unknown_for_address: Commune may be incorrect.
24
+ warnings:
25
+ contains_too_many_words: Commune is recommended to have less than %{word_count} words
@@ -14,6 +14,19 @@ week_start_day: sunday
14
14
  format:
15
15
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}_{province}_{phone}"
16
16
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{province}_{country}_{phone}"
17
+ format_extended:
18
+ edit: "{country}_{firstName}{lastName}_{company}_{streetName}{streetNumber}_{address2}{neighborhood}_{zip}{city}_{province}_{phone}"
19
+ additional_address_fields:
20
+ address1:
21
+ - key: streetName
22
+ required: true
23
+ - key: streetNumber
24
+ required: false
25
+ address2:
26
+ - key: address2
27
+ required: false
28
+ - key: neighborhood
29
+ required: false
17
30
  emoji: "\U0001F1E8\U0001F1F1"
18
31
  languages:
19
32
  - es
@@ -15,6 +15,14 @@ week_start_day: sunday
15
15
  format:
16
16
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{city}{province}{zip}_{phone}"
17
17
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city} {province}_{country}_{phone}"
18
+ format_extended:
19
+ edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}{neighborhood}_{city}{province}{zip}_{phone}"
20
+ additional_address_fields:
21
+ address2:
22
+ - key: address2
23
+ required: false
24
+ - key: neighborhood
25
+ required: false
18
26
  emoji: "\U0001F1E8\U0001F1F4"
19
27
  languages:
20
28
  - es
@@ -21,6 +21,14 @@ languages:
21
21
  format:
22
22
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}{province}_{phone}"
23
23
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{province}_{country}_{phone}"
24
+ format_extended:
25
+ edit: "{country}_{firstName}{lastName}_{company}_{streetName}{streetNumber}_{address2}_{zip}{city}{province}_{phone}"
26
+ additional_address_fields:
27
+ address1:
28
+ - key: streetName
29
+ required: true
30
+ - key: streetNumber
31
+ required: false
24
32
  emoji: "\U0001F1EA\U0001F1F8"
25
33
  zones:
26
34
  - name: A Coruña
@@ -17,6 +17,15 @@ languages:
17
17
  format:
18
18
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{city}_{province}{zip}_{phone}"
19
19
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{city}_{province} {zip}_{country}_{phone}"
20
+ format_extended:
21
+ edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}{neighborhood}_{city}_{province}{zip}_{phone}"
22
+ additional_address_fields:
23
+ address2:
24
+ - key: address2
25
+ required: false
26
+ - key: neighborhood
27
+ decorator: ","
28
+ required: false
20
29
  emoji: "\U0001F1EE\U0001F1E9"
21
30
  zones:
22
31
  - name: Aceh
@@ -15,6 +15,19 @@ week_start_day: sunday
15
15
  format:
16
16
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}{province}_{phone}"
17
17
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city} {province}_{country}_{phone}"
18
+ format_extended:
19
+ edit: "{country}_{firstName}{lastName}_{company}_{streetName}{streetNumber}_{address2}{neighborhood}_{zip}{city}{province}_{phone}"
20
+ additional_address_fields:
21
+ address1:
22
+ - key: streetName
23
+ required: true
24
+ - key: streetNumber
25
+ required: false
26
+ address2:
27
+ - key: address2
28
+ required: false
29
+ - key: neighborhood
30
+ required: true
18
31
  emoji: "\U0001F1F2\U0001F1FD"
19
32
  languages:
20
33
  - es
@@ -23,5 +23,13 @@ languages:
23
23
  format:
24
24
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}_{phone}"
25
25
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{country}_{phone}"
26
+ format_extended:
27
+ edit: "{country}_{firstName}{lastName}_{company}_{streetName}{streetNumber}_{address2}_{zip}{city}_{phone}"
28
+ additional_address_fields:
29
+ address1:
30
+ - key: streetName
31
+ required: true
32
+ - key: streetNumber
33
+ required: true
26
34
  emoji: "\U0001F1F3\U0001F1F1"
27
35
  timezone: Europe/Amsterdam
@@ -15,6 +15,15 @@ week_start_day: sunday
15
15
  format:
16
16
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}_{province}_{phone}"
17
17
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{province}_{country}_{phone}"
18
+ format_extended:
19
+ edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}{neighborhood}_{zip}{city}_{province}_{phone}"
20
+ additional_address_fields:
21
+ address2:
22
+ - key: address2
23
+ required: false
24
+ - key: neighborhood
25
+ decorator: "Barangay"
26
+ required: true
18
27
  emoji: "\U0001F1F5\U0001F1ED"
19
28
  languages:
20
29
  - en
@@ -0,0 +1,25 @@
1
+ ---
2
+ en:
3
+ worldwide:
4
+ TR:
5
+ addresses:
6
+ neighborhood:
7
+ label:
8
+ default: District
9
+ optional: District (optional)
10
+ errors:
11
+ blank: Enter a district
12
+ too_long: District is too long (maximum is 255 characters)
13
+ contains_emojis: District cannot contain emojis
14
+ contains_mathematical_symbols: District cannot contain mathematical symbols
15
+ contains_restricted_characters: District can only contain letters, numbers,
16
+ local characters, and special characters
17
+ contains_too_many_words: District cannot have more than %{word_count}
18
+ words
19
+ contains_html_tags: District cannot contain HTML tags.
20
+ contains_url: District cannot contain URLs.
21
+ unknown_for_city: Enter a valid district name for %{city}.
22
+ unknown_for_zip: Enter a valid district name for %{zip}.
23
+ unknown_for_address: District may be incorrect.
24
+ warnings:
25
+ contains_too_many_words: District is recommended to have less than %{word_count} words
@@ -16,6 +16,14 @@ week_start_day: monday
16
16
  format:
17
17
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{zip}{city}_{phone}"
18
18
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{country}_{phone}"
19
+ format_extended:
20
+ edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}{neighborhood}_{zip}{city}_{phone}"
21
+ additional_address_fields:
22
+ address2:
23
+ - key: address2
24
+ required: false
25
+ - key: neighborhood
26
+ required: false
19
27
  emoji: "\U0001F1F9\U0001F1F7"
20
28
  languages:
21
29
  - tr
@@ -0,0 +1,25 @@
1
+ ---
2
+ en:
3
+ worldwide:
4
+ TW:
5
+ addresses:
6
+ neighborhood:
7
+ label:
8
+ default: District
9
+ optional: District (optional)
10
+ errors:
11
+ blank: Enter a district
12
+ too_long: District is too long (maximum is 255 characters)
13
+ contains_emojis: District cannot contain emojis
14
+ contains_mathematical_symbols: District cannot contain mathematical symbols
15
+ contains_restricted_characters: District can only contain letters, numbers,
16
+ local characters, and special characters
17
+ contains_too_many_words: District cannot have more than %{word_count}
18
+ words
19
+ contains_html_tags: District cannot contain HTML tags.
20
+ contains_url: District cannot contain URLs.
21
+ unknown_for_city: Enter a valid district name for %{city}.
22
+ unknown_for_zip: Enter a valid district name for %{zip}.
23
+ unknown_for_address: District may be incorrect.
24
+ warnings:
25
+ contains_too_many_words: District is recommended to have less than %{word_count} words
@@ -17,6 +17,8 @@ week_start_day: sunday
17
17
  format:
18
18
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{city}{zip}_{phone}"
19
19
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{zip} {city}_{country}_{phone}"
20
+ format_extended:
21
+ edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{neighborhood}{city}{zip}_{phone}"
20
22
  emoji: "\U0001F1F9\U0001F1FC"
21
23
  languages:
22
24
  - "zh-TW"
@@ -0,0 +1,25 @@
1
+ ---
2
+ en:
3
+ worldwide:
4
+ VN:
5
+ addresses:
6
+ neighborhood:
7
+ label:
8
+ default: Ward
9
+ optional: Ward (optional)
10
+ errors:
11
+ blank: Enter a ward
12
+ too_long: Ward is too long (maximum is 255 characters)
13
+ contains_emojis: Ward cannot contain emojis
14
+ contains_mathematical_symbols: Ward cannot contain mathematical symbols
15
+ contains_restricted_characters: Ward can only contain letters, numbers,
16
+ local characters, and special characters
17
+ contains_too_many_words: Ward cannot have more than %{word_count}
18
+ words
19
+ contains_html_tags: Ward cannot contain HTML tags.
20
+ contains_url: Ward cannot contain URLs.
21
+ unknown_for_city: Enter a valid ward name for %{city}.
22
+ unknown_for_zip: Enter a valid ward name for %{zip}.
23
+ unknown_for_address: Ward may be incorrect.
24
+ warnings:
25
+ contains_too_many_words: Ward is recommended to have less than %{word_count} words
@@ -13,6 +13,15 @@ week_start_day: monday
13
13
  format:
14
14
  edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{city}{zip}_{phone}"
15
15
  show: "{firstName} {lastName}_{company}_{address1}_{address2}_{city} {zip}_{country}_{phone}"
16
+ format_extended:
17
+ edit: "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{neighborhood}_{city}{zip}_{phone}"
18
+ additional_address_fields:
19
+ address2:
20
+ - key: address2
21
+ required: false
22
+ - key: neighborhood
23
+ decorator: ", Quận"
24
+ required: false
16
25
  emoji: "\U0001F1FB\U0001F1F3"
17
26
  languages:
18
27
  - fr
@@ -63,6 +63,42 @@ en:
63
63
  unknown_for_address: Address line 1 may be incorrect.
64
64
  warnings:
65
65
  contains_too_many_words: Address line 1 is recommended to have less than %{word_count} words
66
+ street_name:
67
+ label:
68
+ default: Street
69
+ optional: Street (optional)
70
+ errors:
71
+ blank: Enter a street name
72
+ too_long: Street is too long (maximum is 255 characters)
73
+ contains_emojis: Street cannot contain emojis
74
+ contains_mathematical_symbols: Street cannot contain mathematical symbols
75
+ contains_restricted_characters: Street can only contain letters, numbers,
76
+ local characters, and special characters
77
+ contains_too_many_words: Street cannot have more than %{word_count} words
78
+ contains_html_tags: Street cannot contain HTML tags.
79
+ contains_url: Street cannot contain URLs.
80
+ street_unknown_for_zip: Enter a valid street name for %{zip}.
81
+ unknown_for_address: Street may be incorrect.
82
+ warnings:
83
+ contains_too_many_words: Street is recommended to have less than %{word_count} words
84
+ street_number:
85
+ label:
86
+ default: Building number
87
+ optional: Building number (optional)
88
+ errors:
89
+ blank: Enter a building number
90
+ too_long: Building number is too long (maximum is 255 characters)
91
+ contains_emojis: Building number cannot contain emojis
92
+ contains_mathematical_symbols: Building number cannot contain mathematical symbols
93
+ contains_restricted_characters: Building number can only contain letters,
94
+ numbers, local characters, and special characters
95
+ contains_html_tags: Building number cannot contain HTML tags.
96
+ contains_url: Building number cannot contain URLs.
97
+ building_number_invalid: Building number couldn't be located for %{street},
98
+ %{zip}.
99
+ unknown_for_address: Building number may be incorrect.
100
+ warnings:
101
+ contains_too_many_words: Building number is recommended to have less than %{word_count} words
66
102
  address2:
67
103
  label:
68
104
  default: Apartment, suite, etc.
@@ -83,9 +119,28 @@ en:
83
119
  building_number_invalid: Building number couldn't be located for %{street},
84
120
  %{zip}.
85
121
  unknown_for_address: Address line 2 may be incorrect.
86
-
87
122
  warnings:
88
123
  contains_too_many_words: Address line 2 is recommended to have less than %{word_count} words
124
+ neighborhood:
125
+ label:
126
+ default: Neighborhood
127
+ optional: Neighborhood (optional)
128
+ errors:
129
+ blank: Enter a neighborhood
130
+ too_long: Neighborhood is too long (maximum is 255 characters)
131
+ contains_emojis: Neighborhood cannot contain emojis
132
+ contains_mathematical_symbols: Neighborhood cannot contain mathematical symbols
133
+ contains_restricted_characters: Neighborhood can only contain letters, numbers,
134
+ local characters, and special characters
135
+ contains_too_many_words: Neighborhood cannot have more than %{word_count}
136
+ words
137
+ contains_html_tags: Neighborhood cannot contain HTML tags.
138
+ contains_url: Neighborhood cannot contain URLs.
139
+ unknown_for_city: Enter a valid neighborhood name for %{city}.
140
+ unknown_for_zip: Enter a valid neighborhood name for %{zip}.
141
+ unknown_for_address: Neighborhood may be incorrect.
142
+ warnings:
143
+ contains_too_many_words: Neighborhood is recommended to have less than %{word_count} words
89
144
  city:
90
145
  label:
91
146
  default: City
@@ -0,0 +1,111 @@
1
+ # Address format strings
2
+
3
+ ## Introduction <!-- omit in toc -->
4
+
5
+ Worldwide defines different address format strings that control the layout of address elements for each country region.
6
+
7
+ Each format string has a different syntax, and is meant for use in different scenarios.
8
+
9
+ This page aims to document these syntaxes, their usage and limitations for those who need to create/edit them.
10
+
11
+ **⚠️ Warning:** You shouldn't parse these format strings yourself, but instead make use of the higher-level libraries that already consume these strings. This document is meant for those creating the higher-level libraries, or for those who need to make changes to these format strings.
12
+
13
+ ## Table of Contents <!-- omit in toc -->
14
+
15
+ - [Address format strings](#address-format-strings)
16
+ - [`edit`](#edit)
17
+ - [English description](#english-description)
18
+ - [Grammar](#grammar)
19
+ - [`show`](#show)
20
+ - [English description](#english-description-1)
21
+ - [Grammar](#grammar-1)
22
+ - [Limitations](#limitations)
23
+ - [No escaping of special characters](#no-escaping-of-special-characters)
24
+ - [No space-less formats](#no-space-less-formats)
25
+ - [No free-standing prefix/suffix characters](#no-free-standing-prefixsuffix-characters)
26
+ - [No special concatenation characters](#no-special-concatenation-characters)
27
+
28
+ ## `edit`
29
+
30
+ The `edit` address format string controls the layout of elements within an address input form for a country region.
31
+
32
+ e.g., `{company}_{address1}_{address2}_{city}_{country}{province}{zip}_{phone}`
33
+
34
+ ![Example address input form formatted using the `edit` address format](images/edit.png)
35
+
36
+ **⚠️ Warning:** There's a lot more to creating an address form than just the layout of the fields (error messages, optionality, placeholders, etc.) You probably shouldn't parse `edit` yourself; use a pre-existing, higher-level library instead. This document is meant for those creating the higher-level libraries.
37
+
38
+ ### English description
39
+
40
+ 1. Fields are specified by wrapping the field name in curly braces: `{field_name}`
41
+ 2. Lines of fields are separated by an underscore `_`
42
+
43
+ ### Grammar
44
+
45
+ Below is the EBNF ([extended Backus-Naur form](https://en.wikipedia.org/wiki/Extended_Backus-Naur_form)) for `edit` address format strings:
46
+
47
+ ```
48
+ EditFormatString ::= Lines
49
+ Lines ::= Line (LineSeparator Lines)?
50
+ LineSeparator ::= '_'
51
+ Line ::= Field+
52
+ Field ::= '{' Identifier '}'
53
+ Identifier ::= [a-zA-Z0-9_]+
54
+ ```
55
+
56
+ ## `show`
57
+
58
+ The `show` address format string controls how addresses should be rendered as part of a UI.
59
+
60
+ e.g., `{firstName} {lastName}_{company}_{address1}_{address2}_{city} {province} {zip}_{country}_{phone}`
61
+
62
+ ![Example address formatted using the `show` address format](images/show.png)
63
+
64
+ ### English description
65
+
66
+ 1. Fields are specified by wrapping the field name in curly braces: `{field_name}`
67
+ 2. Lines of fields are separated by an underscore `_`
68
+ 3. Fields are separated by an space character
69
+ 4. Other characters are permitted as prefixes/suffixes of a field
70
+ * Note: the prefix of a field is separated from the suffix of a preceding field by the space character separating the fields
71
+
72
+ ### Grammar
73
+
74
+ Below is the EBNF ([extended Backus-Naur form](https://en.wikipedia.org/wiki/Extended_Backus-Naur_form)) for `show` address format strings:
75
+
76
+ ```
77
+ ShowFormatString ::= Lines
78
+ Lines ::= Line (LineSeparator Lines)?
79
+ LineSeparator ::= '_'
80
+ Line ::= PrefixedSuffixedField (FieldSeparator PrefixedSuffixedField)*
81
+ FieldSeparator ::= ' '
82
+ PrefixedSuffixedField ::= (Prefix? Field Suffix?)
83
+ Field ::= '{' Identifier '}'
84
+ Identifier ::= [a-zA-Z0-9_]+
85
+ Prefix ::= Text
86
+ Suffix ::= Text
87
+ Text ::= [^_{} ]+
88
+ ```
89
+
90
+ ### Limitations
91
+
92
+ There are a number of limitations to the `show` syntax that cannot cover the complexity of the world's address formatting.
93
+
94
+ #### No escaping of special characters
95
+
96
+ There is no support for escaping special characters: `{`, `}`, `_`, `<space>`
97
+
98
+ #### No space-less formats
99
+
100
+ Since the fields are space-separated, there is no way to specify a non-separator space character.
101
+ However, many languages (e.g., English) are space-delimited, so libraries using the `show` string end up concatenatiing the fields together using spaces, even if the language doesn't require spaces (e.g., Japanese).
102
+
103
+ #### No free-standing prefix/suffix characters
104
+
105
+ There is no way to specify prefix/suffix characters that will be included regardless of the provided values.
106
+ Any characters besides a field name are either prefixes or suffixes of a field, and therefore if a value for the field is not provided, the associated prefix/suffix characters are also not provided.
107
+
108
+ #### No special concatenation characters
109
+
110
+ There is no way to specify characters other than space characters for concatenating two fields.
111
+ For example, in Brazil, when the `city` and `province` fields are formatted adjacent to one another, instead of a space between the fields, ` - ` should be used. These concatenation characters are neither a prefix nor a suffix of either field, so cannot be specified in this format's syntax.
Binary file
Binary file
@@ -11,7 +11,10 @@ module Worldwide
11
11
  :last_name,
12
12
  :company,
13
13
  :address1,
14
+ :street_name,
15
+ :street_number,
14
16
  :address2,
17
+ :neighborhood,
15
18
  :city,
16
19
  :province,
17
20
  :zip,
@@ -19,6 +19,7 @@ module Worldwide
19
19
  :example_city,
20
20
  :flag,
21
21
  :format,
22
+ :format_extended,
22
23
  :group,
23
24
  :group_name,
24
25
  :cldr_code,
@@ -32,6 +33,7 @@ module Worldwide
32
33
  :zip_example,
33
34
  :zip_regex,
34
35
  :zip_requirement,
36
+ :additional_address_fields,
35
37
  ]
36
38
 
37
39
  # A region may have more than one parent.
@@ -73,6 +75,12 @@ module Worldwide
73
75
  # - show: how to arrange the fields when formatting an address for display
74
76
  attr_accessor :format
75
77
 
78
+ # Hash of strings denoting how to format an address in this region, including substitute and/or additional fields.
79
+ # The format is described in https://shopify.engineering/handling-addresses-from-all-around-the-world
80
+ # - edit: the fields to present on an address input form
81
+ # - show: how to arrange the fields when formatting an address for display
82
+ attr_accessor :format_extended
83
+
76
84
  # The string that results from appending " Countries" to the adjectival form of the {group_name}
77
85
  # @example
78
86
  # Worldwide.region(code: "CA").group == "North American Countries"
@@ -189,6 +197,9 @@ module Worldwide
189
197
  # If true, then the province is optional for addresses in this region.
190
198
  attr_accessor :province_optional
191
199
 
200
+ # A hash of additional address fields and the rules for concatening them into the standard fields
201
+ attr_accessor :additional_address_fields
202
+
192
203
  def initialize(
193
204
  alpha_three: nil,
194
205
  continent: false,
@@ -224,11 +235,13 @@ module Worldwide
224
235
  @tax_rate = tax_rate
225
236
  @use_zone_code_as_short_name = use_zone_code_as_short_name
226
237
 
238
+ @additional_address_fields = {}
227
239
  @building_number_required = false
228
240
  @building_number_may_be_in_address2 = false
229
241
  @currency = nil
230
242
  @flag = nil
231
243
  @format = {}
244
+ @format_extended = {}
232
245
  @group = nil
233
246
  @group_name = nil
234
247
  @languages = []
@@ -95,6 +95,7 @@ module Worldwide
95
95
  end
96
96
 
97
97
  def apply_territory_attributes(region, spec)
98
+ region.additional_address_fields = spec["additional_address_fields"] || {}
98
99
  region.building_number_required = spec["building_number_required"] || false
99
100
  region.building_number_may_be_in_address2 = spec["building_number_may_be_in_address2"] || false
100
101
  currency_code = spec["currency"]
@@ -102,6 +103,7 @@ module Worldwide
102
103
  region.currency = Worldwide.currency(code: currency_code) unless currency_code.nil?
103
104
  region.flag = spec["emoji"]
104
105
  region.format = spec["format"]
106
+ region.format_extended = spec["format_extended"] || {}
105
107
  region.group = spec["group"]
106
108
  region.group_name = spec["group_name"]
107
109
  region.hide_provinces_from_addresses = spec["hide_provinces_from_addresses"] || false
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Worldwide
4
- VERSION = "0.11.1"
4
+ VERSION = "0.12.0"
5
5
  end
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.11.1
4
+ version: 0.12.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-05-13 00:00:00.000000000 Z
11
+ date: 2024-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -6552,6 +6552,7 @@ files:
6552
6552
  - db/data/regions/CI.yml
6553
6553
  - db/data/regions/CK.yml
6554
6554
  - db/data/regions/CL.yml
6555
+ - db/data/regions/CL/en.yml
6555
6556
  - db/data/regions/CM.yml
6556
6557
  - db/data/regions/CN.yml
6557
6558
  - db/data/regions/CN/bg-BG.yml
@@ -7947,9 +7948,11 @@ files:
7947
7948
  - db/data/regions/TN.yml
7948
7949
  - db/data/regions/TO.yml
7949
7950
  - db/data/regions/TR.yml
7951
+ - db/data/regions/TR/en.yml
7950
7952
  - db/data/regions/TT.yml
7951
7953
  - db/data/regions/TV.yml
7952
7954
  - db/data/regions/TW.yml
7955
+ - db/data/regions/TW/en.yml
7953
7956
  - db/data/regions/TZ.yml
7954
7957
  - db/data/regions/UA.yml
7955
7958
  - db/data/regions/UG.yml
@@ -8061,6 +8064,7 @@ files:
8061
8064
  - db/data/regions/VE.yml
8062
8065
  - db/data/regions/VG.yml
8063
8066
  - db/data/regions/VN.yml
8067
+ - db/data/regions/VN/en.yml
8064
8068
  - db/data/regions/VU.yml
8065
8069
  - db/data/regions/WF.yml
8066
8070
  - db/data/regions/WS.yml
@@ -8171,6 +8175,9 @@ files:
8171
8175
  - db/data/regions/_default/zh-TW.yml
8172
8176
  - db/data/world.yml
8173
8177
  - db/extant_outcodes.yml
8178
+ - docs/address_format_strings.md
8179
+ - docs/images/edit.png
8180
+ - docs/images/show.png
8174
8181
  - formats.md
8175
8182
  - lib/worldwide.rb
8176
8183
  - lib/worldwide/address.rb