@mailwoman/codex 7.2.0 → 7.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.
- package/address-system-conventions.ts +68 -0
- package/au/delivery-service.ts +179 -0
- package/au/index.ts +15 -0
- package/au/level-designator.ts +209 -0
- package/au/postcode.ts +51 -0
- package/au/state.ts +35 -0
- package/ca/index.ts +12 -0
- package/ca/postal-code.ts +121 -0
- package/ca/province.ts +99 -0
- package/ca/street-type.ts +167 -0
- package/country/codes.ts +534 -0
- package/country/country.ts +125 -0
- package/country/index.ts +15 -0
- package/country/names.ts +274 -0
- package/country/official-languages.ts +397 -0
- package/country/reference-data.ts +267 -0
- package/country/reference.ts +47 -0
- package/country/subdivision.ts +93 -0
- package/de/bundesland.ts +102 -0
- package/de/index.ts +12 -0
- package/de/postleitzahl.ts +91 -0
- package/de/street-type.ts +83 -0
- package/fr/cedex.ts +56 -0
- package/fr/code-postal.ts +105 -0
- package/fr/departement.ts +142 -0
- package/fr/index.ts +14 -0
- package/fr/region.ts +93 -0
- package/fr/voie.ts +98 -0
- package/gb/country.ts +74 -0
- package/gb/index.ts +14 -0
- package/gb/postcode-area.ts +107 -0
- package/gb/postcode.ts +109 -0
- package/gb/street-type.ts +90 -0
- package/index.ts +38 -0
- package/jp/address-unit.ts +87 -0
- package/jp/index.ts +13 -0
- package/jp/postal-code.ts +93 -0
- package/jp/prefecture.ts +173 -0
- package/level-semantics.ts +623 -0
- package/nz/delivery-service.ts +211 -0
- package/nz/index.ts +12 -0
- package/nz/postcode.ts +42 -0
- package/out/country/index.d.ts +1 -0
- package/out/country/index.d.ts.map +1 -1
- package/out/country/index.js +1 -0
- package/out/country/index.js.map +1 -1
- package/out/country/subdivision.d.ts +44 -0
- package/out/country/subdivision.d.ts.map +1 -0
- package/out/country/subdivision.js +76 -0
- package/out/country/subdivision.js.map +1 -0
- package/package.json +81 -37
- package/postcode-systems.ts +68 -0
- package/tools/build-country-surface-lexicon.ts +166 -0
- package/tools/export-country-surfaces.ts +46 -0
- package/tools/generate-country-reference.ts +153 -0
- package/tools/generate-official-languages.ts +188 -0
- package/tools/index.ts +12 -0
- package/us/floor-designator.ts +119 -0
- package/us/index.ts +19 -0
- package/us/military-address.ts +199 -0
- package/us/po-box.ts +82 -0
- package/us/state.ts +156 -0
- package/us/street-directional.ts +220 -0
- package/us/street-suffix.ts +345 -0
- package/us/unit-designator.ts +223 -0
- package/us/zipcode.ts +212 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* GENERATED — do not edit by hand. Country calling codes (E.164) + currencies (ISO 4217), derived
|
|
7
|
+
* from mledoze/countries (https://github.com/mledoze/countries, ODbL). NANP members map to 1.
|
|
8
|
+
* Regenerate with: mailwoman dev generate country-reference
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Static per-country reference: calling code + currency. */
|
|
12
|
+
export interface CountryReference {
|
|
13
|
+
callingCode?: number
|
|
14
|
+
currency?: { isoCode: string; name?: string; symbol?: string }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** ISO 3166-1 alpha-2 → reference. */
|
|
18
|
+
export const COUNTRY_REFERENCE: Record<string, CountryReference> = {
|
|
19
|
+
AD: { callingCode: 376, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
20
|
+
AE: { callingCode: 971, currency: { isoCode: "AED", name: "United Arab Emirates dirham", symbol: "د.إ" } },
|
|
21
|
+
AF: { callingCode: 93, currency: { isoCode: "AFN", name: "Afghan afghani", symbol: "؋" } },
|
|
22
|
+
AG: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
23
|
+
AI: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
24
|
+
AL: { callingCode: 355, currency: { isoCode: "ALL", name: "Albanian lek", symbol: "L" } },
|
|
25
|
+
AM: { callingCode: 374, currency: { isoCode: "AMD", name: "Armenian dram", symbol: "֏" } },
|
|
26
|
+
AO: { callingCode: 244, currency: { isoCode: "AOA", name: "Angolan kwanza", symbol: "Kz" } },
|
|
27
|
+
AR: { callingCode: 54, currency: { isoCode: "ARS", name: "Argentine peso", symbol: "$" } },
|
|
28
|
+
AS: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
29
|
+
AT: { callingCode: 43, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
30
|
+
AU: { callingCode: 61, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
31
|
+
AW: { callingCode: 297, currency: { isoCode: "AWG", name: "Aruban florin", symbol: "ƒ" } },
|
|
32
|
+
AX: { callingCode: 35818, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
33
|
+
AZ: { callingCode: 994, currency: { isoCode: "AZN", name: "Azerbaijani manat", symbol: "₼" } },
|
|
34
|
+
BA: { callingCode: 387, currency: { isoCode: "BAM", name: "Bosnia and Herzegovina convertible mark", symbol: "KM" } },
|
|
35
|
+
BB: { callingCode: 1, currency: { isoCode: "BBD", name: "Barbadian dollar", symbol: "$" } },
|
|
36
|
+
BD: { callingCode: 880, currency: { isoCode: "BDT", name: "Bangladeshi taka", symbol: "৳" } },
|
|
37
|
+
BE: { callingCode: 32, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
38
|
+
BF: { callingCode: 226, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
39
|
+
BG: { callingCode: 359, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
40
|
+
BH: { callingCode: 973, currency: { isoCode: "BHD", name: "Bahraini dinar", symbol: ".د.ب" } },
|
|
41
|
+
BI: { callingCode: 257, currency: { isoCode: "BIF", name: "Burundian franc", symbol: "Fr" } },
|
|
42
|
+
BJ: { callingCode: 229, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
43
|
+
BL: { callingCode: 590, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
44
|
+
BM: { callingCode: 1, currency: { isoCode: "BMD", name: "Bermudian dollar", symbol: "$" } },
|
|
45
|
+
BN: { callingCode: 673, currency: { isoCode: "BND", name: "Brunei dollar", symbol: "$" } },
|
|
46
|
+
BO: { callingCode: 591, currency: { isoCode: "BOB", name: "Bolivian boliviano", symbol: "Bs." } },
|
|
47
|
+
BQ: { callingCode: 599, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
48
|
+
BR: { callingCode: 55, currency: { isoCode: "BRL", name: "Brazilian real", symbol: "R$" } },
|
|
49
|
+
BS: { callingCode: 1, currency: { isoCode: "BSD", name: "Bahamian dollar", symbol: "$" } },
|
|
50
|
+
BT: { callingCode: 975, currency: { isoCode: "BTN", name: "Bhutanese ngultrum", symbol: "Nu." } },
|
|
51
|
+
BV: { callingCode: 47 },
|
|
52
|
+
BW: { callingCode: 267, currency: { isoCode: "BWP", name: "Botswana pula", symbol: "P" } },
|
|
53
|
+
BY: { callingCode: 375, currency: { isoCode: "BYN", name: "Belarusian ruble", symbol: "Br" } },
|
|
54
|
+
BZ: { callingCode: 501, currency: { isoCode: "BZD", name: "Belize dollar", symbol: "$" } },
|
|
55
|
+
CA: { callingCode: 1, currency: { isoCode: "CAD", name: "Canadian dollar", symbol: "$" } },
|
|
56
|
+
CC: { callingCode: 61, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
57
|
+
CD: { callingCode: 243, currency: { isoCode: "CDF", name: "Congolese franc", symbol: "FC" } },
|
|
58
|
+
CF: { callingCode: 236, currency: { isoCode: "XAF", name: "Central African CFA franc", symbol: "Fr" } },
|
|
59
|
+
CG: { callingCode: 242, currency: { isoCode: "XAF", name: "Central African CFA franc", symbol: "Fr" } },
|
|
60
|
+
CH: { callingCode: 41, currency: { isoCode: "CHF", name: "Swiss franc", symbol: "Fr." } },
|
|
61
|
+
CI: { callingCode: 225, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
62
|
+
CK: { callingCode: 682, currency: { isoCode: "CKD", name: "Cook Islands dollar", symbol: "$" } },
|
|
63
|
+
CL: { callingCode: 56, currency: { isoCode: "CLP", name: "Chilean peso", symbol: "$" } },
|
|
64
|
+
CM: { callingCode: 237, currency: { isoCode: "XAF", name: "Central African CFA franc", symbol: "Fr" } },
|
|
65
|
+
CN: { callingCode: 86, currency: { isoCode: "CNY", name: "Chinese yuan", symbol: "¥" } },
|
|
66
|
+
CO: { callingCode: 57, currency: { isoCode: "COP", name: "Colombian peso", symbol: "$" } },
|
|
67
|
+
CR: { callingCode: 506, currency: { isoCode: "CRC", name: "Costa Rican colón", symbol: "₡" } },
|
|
68
|
+
CU: { callingCode: 53, currency: { isoCode: "CUC", name: "Cuban convertible peso", symbol: "$" } },
|
|
69
|
+
CV: { callingCode: 238, currency: { isoCode: "CVE", name: "Cape Verdean escudo", symbol: "Esc" } },
|
|
70
|
+
CW: { callingCode: 599, currency: { isoCode: "ANG", name: "Netherlands Antillean guilder", symbol: "ƒ" } },
|
|
71
|
+
CX: { callingCode: 61, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
72
|
+
CY: { callingCode: 357, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
73
|
+
CZ: { callingCode: 420, currency: { isoCode: "CZK", name: "Czech koruna", symbol: "Kč" } },
|
|
74
|
+
DE: { callingCode: 49, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
75
|
+
DJ: { callingCode: 253, currency: { isoCode: "DJF", name: "Djiboutian franc", symbol: "Fr" } },
|
|
76
|
+
DK: { callingCode: 45, currency: { isoCode: "DKK", name: "Danish krone", symbol: "kr" } },
|
|
77
|
+
DM: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
78
|
+
DO: { callingCode: 1, currency: { isoCode: "DOP", name: "Dominican peso", symbol: "$" } },
|
|
79
|
+
DZ: { callingCode: 213, currency: { isoCode: "DZD", name: "Algerian dinar", symbol: "د.ج" } },
|
|
80
|
+
EC: { callingCode: 593, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
81
|
+
EE: { callingCode: 372, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
82
|
+
EG: { callingCode: 20, currency: { isoCode: "EGP", name: "Egyptian pound", symbol: "£" } },
|
|
83
|
+
EH: { callingCode: 2, currency: { isoCode: "DZD", name: "Algerian dinar", symbol: "دج" } },
|
|
84
|
+
ER: { callingCode: 291, currency: { isoCode: "ERN", name: "Eritrean nakfa", symbol: "Nfk" } },
|
|
85
|
+
ES: { callingCode: 34, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
86
|
+
ET: { callingCode: 251, currency: { isoCode: "ETB", name: "Ethiopian birr", symbol: "Br" } },
|
|
87
|
+
FI: { callingCode: 358, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
88
|
+
FJ: { callingCode: 679, currency: { isoCode: "FJD", name: "Fijian dollar", symbol: "$" } },
|
|
89
|
+
FK: { callingCode: 500, currency: { isoCode: "FKP", name: "Falkland Islands pound", symbol: "£" } },
|
|
90
|
+
FM: { callingCode: 691 },
|
|
91
|
+
FO: { callingCode: 298, currency: { isoCode: "DKK", name: "Danish krone", symbol: "kr" } },
|
|
92
|
+
FR: { callingCode: 33, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
93
|
+
GA: { callingCode: 241, currency: { isoCode: "XAF", name: "Central African CFA franc", symbol: "Fr" } },
|
|
94
|
+
GB: { callingCode: 44, currency: { isoCode: "GBP", name: "British pound", symbol: "£" } },
|
|
95
|
+
GD: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
96
|
+
GE: { callingCode: 995, currency: { isoCode: "GEL", name: "lari", symbol: "₾" } },
|
|
97
|
+
GF: { callingCode: 594, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
98
|
+
GG: { callingCode: 44, currency: { isoCode: "GBP", name: "British pound", symbol: "£" } },
|
|
99
|
+
GH: { callingCode: 233, currency: { isoCode: "GHS", name: "Ghanaian cedi", symbol: "₵" } },
|
|
100
|
+
GI: { callingCode: 350, currency: { isoCode: "GIP", name: "Gibraltar pound", symbol: "£" } },
|
|
101
|
+
GL: { callingCode: 299, currency: { isoCode: "DKK", name: "krone", symbol: "kr." } },
|
|
102
|
+
GM: { callingCode: 220, currency: { isoCode: "GMD", name: "dalasi", symbol: "D" } },
|
|
103
|
+
GN: { callingCode: 224, currency: { isoCode: "GNF", name: "Guinean franc", symbol: "Fr" } },
|
|
104
|
+
GP: { callingCode: 590, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
105
|
+
GQ: { callingCode: 240, currency: { isoCode: "XAF", name: "Central African CFA franc", symbol: "Fr" } },
|
|
106
|
+
GR: { callingCode: 30, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
107
|
+
GS: { callingCode: 500, currency: { isoCode: "SHP", name: "Saint Helena pound", symbol: "£" } },
|
|
108
|
+
GT: { callingCode: 502, currency: { isoCode: "GTQ", name: "Guatemalan quetzal", symbol: "Q" } },
|
|
109
|
+
GU: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
110
|
+
GW: { callingCode: 245, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
111
|
+
GY: { callingCode: 592, currency: { isoCode: "GYD", name: "Guyanese dollar", symbol: "$" } },
|
|
112
|
+
HK: { callingCode: 852, currency: { isoCode: "HKD", name: "Hong Kong dollar", symbol: "$" } },
|
|
113
|
+
HN: { callingCode: 504, currency: { isoCode: "HNL", name: "Honduran lempira", symbol: "L" } },
|
|
114
|
+
HR: { callingCode: 385, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
115
|
+
HT: { callingCode: 509, currency: { isoCode: "HTG", name: "Haitian gourde", symbol: "G" } },
|
|
116
|
+
HU: { callingCode: 36, currency: { isoCode: "HUF", name: "Hungarian forint", symbol: "Ft" } },
|
|
117
|
+
ID: { callingCode: 62, currency: { isoCode: "IDR", name: "Indonesian rupiah", symbol: "Rp" } },
|
|
118
|
+
IE: { callingCode: 353, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
119
|
+
IL: { callingCode: 972, currency: { isoCode: "ILS", name: "Israeli new shekel", symbol: "₪" } },
|
|
120
|
+
IM: { callingCode: 44, currency: { isoCode: "GBP", name: "British pound", symbol: "£" } },
|
|
121
|
+
IN: { callingCode: 91, currency: { isoCode: "INR", name: "Indian rupee", symbol: "₹" } },
|
|
122
|
+
IO: { callingCode: 246, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
123
|
+
IQ: { callingCode: 964, currency: { isoCode: "IQD", name: "Iraqi dinar", symbol: "ع.د" } },
|
|
124
|
+
IR: { callingCode: 98, currency: { isoCode: "IRR", name: "Iranian rial", symbol: "﷼" } },
|
|
125
|
+
IS: { callingCode: 354, currency: { isoCode: "ISK", name: "Icelandic króna", symbol: "kr" } },
|
|
126
|
+
IT: { callingCode: 39, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
127
|
+
JE: { callingCode: 44, currency: { isoCode: "GBP", name: "British pound", symbol: "£" } },
|
|
128
|
+
JM: { callingCode: 1, currency: { isoCode: "JMD", name: "Jamaican dollar", symbol: "$" } },
|
|
129
|
+
JO: { callingCode: 962, currency: { isoCode: "JOD", name: "Jordanian dinar", symbol: "د.ا" } },
|
|
130
|
+
JP: { callingCode: 81, currency: { isoCode: "JPY", name: "Japanese yen", symbol: "¥" } },
|
|
131
|
+
KE: { callingCode: 254, currency: { isoCode: "KES", name: "Kenyan shilling", symbol: "Sh" } },
|
|
132
|
+
KG: { callingCode: 996, currency: { isoCode: "KGS", name: "Kyrgyzstani som", symbol: "с" } },
|
|
133
|
+
KH: { callingCode: 855, currency: { isoCode: "KHR", name: "Cambodian riel", symbol: "៛" } },
|
|
134
|
+
KI: { callingCode: 686, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
135
|
+
KM: { callingCode: 269, currency: { isoCode: "KMF", name: "Comorian franc", symbol: "Fr" } },
|
|
136
|
+
KN: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
137
|
+
KP: { callingCode: 850, currency: { isoCode: "KPW", name: "North Korean won", symbol: "₩" } },
|
|
138
|
+
KR: { callingCode: 82, currency: { isoCode: "KRW", name: "South Korean won", symbol: "₩" } },
|
|
139
|
+
KW: { callingCode: 965, currency: { isoCode: "KWD", name: "Kuwaiti dinar", symbol: "د.ك" } },
|
|
140
|
+
KY: { callingCode: 1, currency: { isoCode: "KYD", name: "Cayman Islands dollar", symbol: "$" } },
|
|
141
|
+
KZ: { callingCode: 7, currency: { isoCode: "KZT", name: "Kazakhstani tenge", symbol: "₸" } },
|
|
142
|
+
LA: { callingCode: 856, currency: { isoCode: "LAK", name: "Lao kip", symbol: "₭" } },
|
|
143
|
+
LB: { callingCode: 961, currency: { isoCode: "LBP", name: "Lebanese pound", symbol: "ل.ل" } },
|
|
144
|
+
LC: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
145
|
+
LI: { callingCode: 423, currency: { isoCode: "CHF", name: "Swiss franc", symbol: "Fr" } },
|
|
146
|
+
LK: { callingCode: 94, currency: { isoCode: "LKR", name: "Sri Lankan rupee", symbol: "Rs රු" } },
|
|
147
|
+
LR: { callingCode: 231, currency: { isoCode: "LRD", name: "Liberian dollar", symbol: "$" } },
|
|
148
|
+
LS: { callingCode: 266, currency: { isoCode: "LSL", name: "Lesotho loti", symbol: "L" } },
|
|
149
|
+
LT: { callingCode: 370, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
150
|
+
LU: { callingCode: 352, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
151
|
+
LV: { callingCode: 371, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
152
|
+
LY: { callingCode: 218, currency: { isoCode: "LYD", name: "Libyan dinar", symbol: "ل.د" } },
|
|
153
|
+
MA: { callingCode: 212, currency: { isoCode: "MAD", name: "Moroccan dirham", symbol: "د.م." } },
|
|
154
|
+
MC: { callingCode: 377, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
155
|
+
MD: { callingCode: 373, currency: { isoCode: "MDL", name: "Moldovan leu", symbol: "L" } },
|
|
156
|
+
ME: { callingCode: 382, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
157
|
+
MF: { callingCode: 590, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
158
|
+
MG: { callingCode: 261, currency: { isoCode: "MGA", name: "Malagasy ariary", symbol: "Ar" } },
|
|
159
|
+
MH: { callingCode: 692, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
160
|
+
MK: { callingCode: 389, currency: { isoCode: "MKD", name: "denar", symbol: "den" } },
|
|
161
|
+
ML: { callingCode: 223, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
162
|
+
MM: { callingCode: 95, currency: { isoCode: "MMK", name: "Burmese kyat", symbol: "Ks" } },
|
|
163
|
+
MN: { callingCode: 976, currency: { isoCode: "MNT", name: "Mongolian tögrög", symbol: "₮" } },
|
|
164
|
+
MO: { callingCode: 853, currency: { isoCode: "MOP", name: "Macanese pataca", symbol: "P" } },
|
|
165
|
+
MP: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
166
|
+
MQ: { callingCode: 596, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
167
|
+
MR: { callingCode: 222, currency: { isoCode: "MRU", name: "Mauritanian ouguiya", symbol: "UM" } },
|
|
168
|
+
MS: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
169
|
+
MT: { callingCode: 356, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
170
|
+
MU: { callingCode: 230, currency: { isoCode: "MUR", name: "Mauritian rupee", symbol: "₨" } },
|
|
171
|
+
MV: { callingCode: 960, currency: { isoCode: "MVR", name: "Maldivian rufiyaa", symbol: ".ރ" } },
|
|
172
|
+
MW: { callingCode: 265, currency: { isoCode: "MWK", name: "Malawian kwacha", symbol: "MK" } },
|
|
173
|
+
MX: { callingCode: 52, currency: { isoCode: "MXN", name: "Mexican peso", symbol: "$" } },
|
|
174
|
+
MY: { callingCode: 60, currency: { isoCode: "MYR", name: "Malaysian ringgit", symbol: "RM" } },
|
|
175
|
+
MZ: { callingCode: 258, currency: { isoCode: "MZN", name: "Mozambican metical", symbol: "MT" } },
|
|
176
|
+
NA: { callingCode: 264, currency: { isoCode: "NAD", name: "Namibian dollar", symbol: "$" } },
|
|
177
|
+
NC: { callingCode: 687, currency: { isoCode: "XPF", name: "CFP franc", symbol: "₣" } },
|
|
178
|
+
NE: { callingCode: 227, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
179
|
+
NF: { callingCode: 672, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
180
|
+
NG: { callingCode: 234, currency: { isoCode: "NGN", name: "Nigerian naira", symbol: "₦" } },
|
|
181
|
+
NI: { callingCode: 505, currency: { isoCode: "NIO", name: "Nicaraguan córdoba", symbol: "C$" } },
|
|
182
|
+
NL: { callingCode: 31, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
183
|
+
NO: { callingCode: 47, currency: { isoCode: "NOK", name: "Norwegian krone", symbol: "kr" } },
|
|
184
|
+
NP: { callingCode: 977, currency: { isoCode: "NPR", name: "Nepalese rupee", symbol: "₨" } },
|
|
185
|
+
NR: { callingCode: 674, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
186
|
+
NU: { callingCode: 683, currency: { isoCode: "NZD", name: "New Zealand dollar", symbol: "$" } },
|
|
187
|
+
NZ: { callingCode: 64, currency: { isoCode: "NZD", name: "New Zealand dollar", symbol: "$" } },
|
|
188
|
+
OM: { callingCode: 968, currency: { isoCode: "OMR", name: "Omani rial", symbol: "ر.ع." } },
|
|
189
|
+
PA: { callingCode: 507, currency: { isoCode: "PAB", name: "Panamanian balboa", symbol: "B/." } },
|
|
190
|
+
PE: { callingCode: 51, currency: { isoCode: "PEN", name: "Peruvian sol", symbol: "S/." } },
|
|
191
|
+
PF: { callingCode: 689, currency: { isoCode: "XPF", name: "CFP franc", symbol: "₣" } },
|
|
192
|
+
PG: { callingCode: 675, currency: { isoCode: "PGK", name: "Papua New Guinean kina", symbol: "K" } },
|
|
193
|
+
PH: { callingCode: 63, currency: { isoCode: "PHP", name: "Philippine peso", symbol: "₱" } },
|
|
194
|
+
PK: { callingCode: 92, currency: { isoCode: "PKR", name: "Pakistani rupee", symbol: "₨" } },
|
|
195
|
+
PL: { callingCode: 48, currency: { isoCode: "PLN", name: "Polish złoty", symbol: "zł" } },
|
|
196
|
+
PM: { callingCode: 508, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
197
|
+
PN: { callingCode: 64, currency: { isoCode: "NZD", name: "New Zealand dollar", symbol: "$" } },
|
|
198
|
+
PR: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
199
|
+
PS: { callingCode: 970, currency: { isoCode: "EGP", name: "Egyptian pound", symbol: "E£" } },
|
|
200
|
+
PT: { callingCode: 351, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
201
|
+
PW: { callingCode: 680, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
202
|
+
PY: { callingCode: 595, currency: { isoCode: "PYG", name: "Paraguayan guaraní", symbol: "₲" } },
|
|
203
|
+
QA: { callingCode: 974, currency: { isoCode: "QAR", name: "Qatari riyal", symbol: "ر.ق" } },
|
|
204
|
+
RE: { callingCode: 262, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
205
|
+
RO: { callingCode: 40, currency: { isoCode: "RON", name: "Romanian leu", symbol: "lei" } },
|
|
206
|
+
RS: { callingCode: 381, currency: { isoCode: "RSD", name: "Serbian dinar", symbol: "дин." } },
|
|
207
|
+
RU: { callingCode: 7, currency: { isoCode: "RUB", name: "Russian ruble", symbol: "₽" } },
|
|
208
|
+
RW: { callingCode: 250, currency: { isoCode: "RWF", name: "Rwandan franc", symbol: "Fr" } },
|
|
209
|
+
SA: { callingCode: 966, currency: { isoCode: "SAR", name: "Saudi riyal", symbol: "ر.س" } },
|
|
210
|
+
SB: { callingCode: 677, currency: { isoCode: "SBD", name: "Solomon Islands dollar", symbol: "$" } },
|
|
211
|
+
SC: { callingCode: 248, currency: { isoCode: "SCR", name: "Seychellois rupee", symbol: "₨" } },
|
|
212
|
+
SD: { callingCode: 249, currency: { isoCode: "SDG", name: "Sudanese pound", symbol: "PT" } },
|
|
213
|
+
SE: { callingCode: 46, currency: { isoCode: "SEK", name: "Swedish krona", symbol: "kr" } },
|
|
214
|
+
SG: { callingCode: 65, currency: { isoCode: "SGD", name: "Singapore dollar", symbol: "$" } },
|
|
215
|
+
SH: { callingCode: 2, currency: { isoCode: "GBP", name: "Pound sterling", symbol: "£" } },
|
|
216
|
+
SI: { callingCode: 386, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
217
|
+
SJ: { callingCode: 4779, currency: { isoCode: "NOK", name: "krone", symbol: "kr" } },
|
|
218
|
+
SK: { callingCode: 421, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
219
|
+
SL: { callingCode: 232, currency: { isoCode: "SLL", name: "Sierra Leonean leone", symbol: "Le" } },
|
|
220
|
+
SM: { callingCode: 378, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
221
|
+
SN: { callingCode: 221, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
222
|
+
SO: { callingCode: 252, currency: { isoCode: "SOS", name: "Somali shilling", symbol: "Sh" } },
|
|
223
|
+
SR: { callingCode: 597, currency: { isoCode: "SRD", name: "Surinamese dollar", symbol: "$" } },
|
|
224
|
+
SS: { callingCode: 211, currency: { isoCode: "SSP", name: "South Sudanese pound", symbol: "£" } },
|
|
225
|
+
ST: { callingCode: 239, currency: { isoCode: "STN", name: "São Tomé and Príncipe dobra", symbol: "Db" } },
|
|
226
|
+
SV: { callingCode: 503, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
227
|
+
SX: { callingCode: 1, currency: { isoCode: "ANG", name: "Netherlands Antillean guilder", symbol: "ƒ" } },
|
|
228
|
+
SY: { callingCode: 963, currency: { isoCode: "SYP", name: "Syrian pound", symbol: "£" } },
|
|
229
|
+
SZ: { callingCode: 268, currency: { isoCode: "SZL", name: "Swazi lilangeni", symbol: "L" } },
|
|
230
|
+
TC: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
231
|
+
TD: { callingCode: 235, currency: { isoCode: "XAF", name: "Central African CFA franc", symbol: "Fr" } },
|
|
232
|
+
TF: { callingCode: 262, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
233
|
+
TG: { callingCode: 228, currency: { isoCode: "XOF", name: "West African CFA franc", symbol: "Fr" } },
|
|
234
|
+
TH: { callingCode: 66, currency: { isoCode: "THB", name: "Thai baht", symbol: "฿" } },
|
|
235
|
+
TJ: { callingCode: 992, currency: { isoCode: "TJS", name: "Tajikistani somoni", symbol: "ЅМ" } },
|
|
236
|
+
TK: { callingCode: 690, currency: { isoCode: "NZD", name: "New Zealand dollar", symbol: "$" } },
|
|
237
|
+
TL: { callingCode: 670, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
238
|
+
TM: { callingCode: 993, currency: { isoCode: "TMT", name: "Turkmenistan manat", symbol: "m" } },
|
|
239
|
+
TN: { callingCode: 216, currency: { isoCode: "TND", name: "Tunisian dinar", symbol: "د.ت" } },
|
|
240
|
+
TO: { callingCode: 676, currency: { isoCode: "TOP", name: "Tongan paʻanga", symbol: "T$" } },
|
|
241
|
+
TR: { callingCode: 90, currency: { isoCode: "TRY", name: "Turkish lira", symbol: "₺" } },
|
|
242
|
+
TT: { callingCode: 1, currency: { isoCode: "TTD", name: "Trinidad and Tobago dollar", symbol: "$" } },
|
|
243
|
+
TV: { callingCode: 688, currency: { isoCode: "AUD", name: "Australian dollar", symbol: "$" } },
|
|
244
|
+
TW: { callingCode: 886, currency: { isoCode: "TWD", name: "New Taiwan dollar", symbol: "$" } },
|
|
245
|
+
TZ: { callingCode: 255, currency: { isoCode: "TZS", name: "Tanzanian shilling", symbol: "Sh" } },
|
|
246
|
+
UA: { callingCode: 380, currency: { isoCode: "UAH", name: "Ukrainian hryvnia", symbol: "₴" } },
|
|
247
|
+
UG: { callingCode: 256, currency: { isoCode: "UGX", name: "Ugandan shilling", symbol: "Sh" } },
|
|
248
|
+
UM: { callingCode: 268, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
249
|
+
US: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
250
|
+
UY: { callingCode: 598, currency: { isoCode: "UYU", name: "Uruguayan peso", symbol: "$" } },
|
|
251
|
+
UZ: { callingCode: 998, currency: { isoCode: "UZS", name: "Uzbekistani soʻm", symbol: "so'm" } },
|
|
252
|
+
VA: { callingCode: 3, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
253
|
+
VC: { callingCode: 1, currency: { isoCode: "XCD", name: "Eastern Caribbean dollar", symbol: "$" } },
|
|
254
|
+
VE: { callingCode: 58, currency: { isoCode: "VES", name: "Venezuelan bolívar soberano", symbol: "Bs.S." } },
|
|
255
|
+
VG: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
256
|
+
VI: { callingCode: 1, currency: { isoCode: "USD", name: "United States dollar", symbol: "$" } },
|
|
257
|
+
VN: { callingCode: 84, currency: { isoCode: "VND", name: "Vietnamese đồng", symbol: "₫" } },
|
|
258
|
+
VU: { callingCode: 678, currency: { isoCode: "VUV", name: "Vanuatu vatu", symbol: "Vt" } },
|
|
259
|
+
WF: { callingCode: 681, currency: { isoCode: "XPF", name: "CFP franc", symbol: "₣" } },
|
|
260
|
+
WS: { callingCode: 685, currency: { isoCode: "WST", name: "Samoan tālā", symbol: "T" } },
|
|
261
|
+
XK: { callingCode: 383, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
262
|
+
YE: { callingCode: 967, currency: { isoCode: "YER", name: "Yemeni rial", symbol: "﷼" } },
|
|
263
|
+
YT: { callingCode: 262, currency: { isoCode: "EUR", name: "Euro", symbol: "€" } },
|
|
264
|
+
ZA: { callingCode: 27, currency: { isoCode: "ZAR", name: "South African rand", symbol: "R" } },
|
|
265
|
+
ZM: { callingCode: 260, currency: { isoCode: "ZMW", name: "Zambian kwacha", symbol: "ZK" } },
|
|
266
|
+
ZW: { callingCode: 263, currency: { isoCode: "BWP", name: "Botswana pula", symbol: "P" } },
|
|
267
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Country-reference annotators. The flag emoji is a pure function of the ISO 3166-1 alpha-2 code
|
|
7
|
+
* (two Regional Indicator Symbols); calling code + currency come from {@link COUNTRY_REFERENCE}, a
|
|
8
|
+
* table generated from mledoze/countries (provenance-tracked, not hand-typed — the
|
|
9
|
+
* no-load-bearing-trivia rule).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { AnnotationSet, Annotator } from "@mailwoman/annotations"
|
|
13
|
+
|
|
14
|
+
import { COUNTRY_REFERENCE } from "./reference-data.ts"
|
|
15
|
+
|
|
16
|
+
const REGIONAL_INDICATOR_BASE = 0x1f1e6
|
|
17
|
+
const A_UPPER = "A".charCodeAt(0)
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The flag emoji for an ISO 3166-1 alpha-2 country code, formed from the two Regional Indicator Symbols (`US` → 🇺🇸).
|
|
21
|
+
* Returns `""` for anything that is not two ASCII letters.
|
|
22
|
+
*/
|
|
23
|
+
export function countryFlag(alpha2: string): string {
|
|
24
|
+
const code = alpha2.toUpperCase()
|
|
25
|
+
|
|
26
|
+
if (!/^[A-Z]{2}$/.test(code)) return ""
|
|
27
|
+
|
|
28
|
+
return String.fromCodePoint(...[...code].map((c) => REGIONAL_INDICATOR_BASE + c.charCodeAt(0) - A_UPPER))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Fill the country-reference slice (ISO 3166 alpha-2, flag, calling code, currency) from a resolved country code.
|
|
33
|
+
* Abstains on anything that isn't two ASCII letters.
|
|
34
|
+
*/
|
|
35
|
+
export const countryReferenceAnnotator: Annotator = ({ countryCode }): Partial<AnnotationSet> => {
|
|
36
|
+
if (!countryCode || !/^[A-Za-z]{2}$/.test(countryCode)) return {}
|
|
37
|
+
const alpha2 = countryCode.toUpperCase()
|
|
38
|
+
const ref = COUNTRY_REFERENCE[alpha2]
|
|
39
|
+
const flag = countryFlag(alpha2)
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
iso3166: { alpha2 },
|
|
43
|
+
...(flag ? { flag } : {}),
|
|
44
|
+
...(ref?.callingCode != null ? { callingCode: ref.callingCode } : {}),
|
|
45
|
+
...(ref?.currency ? { currency: ref.currency } : {}),
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* ISO 3166-2 subdivision → country reference, the cross-country complement to `country.ts`'s
|
|
7
|
+
* ISO 3166-1 `matchCountry`. A subdivision token ("QC", "Ontario", "Illinois") names a first-level
|
|
8
|
+
* admin unit whose COUNTRY is the piece the resolver needs when a region qualifier is the only
|
|
9
|
+
* signal that the locale-inferred default country is wrong ("Montreal QC" under a US locale).
|
|
10
|
+
*
|
|
11
|
+
* Scope is deliberately minimal: the two subdivision systems whose two-letter codes people write
|
|
12
|
+
* ON THE ADDRESS LINE and whose homonymous localities collide across the border — US states
|
|
13
|
+
* (`us/state.ts`) and Canadian provinces (`ca/province.ts`). Both directions are covered: the ISO
|
|
14
|
+
* code (`QC` → Quebec) and the full name (`Quebec` / `Québec` → the `QC` record), so a resolver
|
|
15
|
+
* can expand the abbreviation the gazetteer FTS index lacks ("QC" is not an alt-name of Québec)
|
|
16
|
+
* into the full name it does carry. This is a soft prior, not a routing decision — the gazetteer
|
|
17
|
+
* still does the geographic confirmation (per the registry-backed-soft-prior doctrine).
|
|
18
|
+
*
|
|
19
|
+
* The US and Canadian code sets are disjoint (no two-letter code, and no full name, collides
|
|
20
|
+
* between the two), so the combined lookup below is unambiguous. `CA` resolves to California the
|
|
21
|
+
* US state (Canada's provinces carry no `CA` subdivision code), never to Canada the country —
|
|
22
|
+
* country recognition stays with `matchCountry`.
|
|
23
|
+
*
|
|
24
|
+
* Source: the underlying `US_STATE_BY_ABBREVIATION` (USPS Publication 28, Appendix B) and
|
|
25
|
+
* `CA_PROVINCES` (ISO 3166-2:CA) tables. No new provenance is introduced here — this module only
|
|
26
|
+
* re-keys those two existing tables into one subdivision→country view.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { CA_PROVINCES } from "../ca/province.ts"
|
|
30
|
+
import { US_STATE_BY_ABBREVIATION } from "../us/state.ts"
|
|
31
|
+
|
|
32
|
+
/** A resolved subdivision: its ISO 3166-2 code (sans country prefix), canonical English name, and ISO 3166-1 country. */
|
|
33
|
+
export interface SubdivisionMatch {
|
|
34
|
+
/** ISO 3166-2 subdivision code without the country prefix (e.g. `QC` for `CA-QC`, `IL` for `US-IL`). */
|
|
35
|
+
code: string
|
|
36
|
+
/** Canonical English name (e.g. `Quebec`, `Illinois`). */
|
|
37
|
+
name: string
|
|
38
|
+
/** ISO 3166-1 alpha-2 country the subdivision belongs to (`CA`, `US`). */
|
|
39
|
+
country: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike (mirrors `ca/province.ts`). */
|
|
43
|
+
function foldName(s: string): string {
|
|
44
|
+
return s
|
|
45
|
+
.toLowerCase()
|
|
46
|
+
.normalize("NFD")
|
|
47
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
48
|
+
.replace(/[^a-z0-9]+/g, " ")
|
|
49
|
+
.trim()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Folded surface form (ISO code, English name, or — for CA — co-official French name) → subdivision. Built once. US
|
|
54
|
+
* states are inserted first and never overwritten, so on the (currently empty) event of a future code/name collision
|
|
55
|
+
* the US entry wins deterministically; today the two sets are disjoint.
|
|
56
|
+
*/
|
|
57
|
+
const SUBDIVISION_LOOKUP: ReadonlyMap<string, SubdivisionMatch> = (() => {
|
|
58
|
+
const out = new Map<string, SubdivisionMatch>()
|
|
59
|
+
const put = (key: string, match: SubdivisionMatch): void => {
|
|
60
|
+
const folded = foldName(key)
|
|
61
|
+
|
|
62
|
+
if (folded.length > 0 && !out.has(folded)) {
|
|
63
|
+
out.set(folded, match)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const [code, name] of Object.entries(US_STATE_BY_ABBREVIATION)) {
|
|
68
|
+
const match: SubdivisionMatch = { code, name, country: "US" }
|
|
69
|
+
put(code, match)
|
|
70
|
+
put(name, match)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (const info of Object.values(CA_PROVINCES)) {
|
|
74
|
+
const match: SubdivisionMatch = { code: info.code, name: info.name, country: "CA" }
|
|
75
|
+
put(info.code, match)
|
|
76
|
+
put(info.name, match)
|
|
77
|
+
put(info.french, match)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return out
|
|
81
|
+
})()
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Resolve a first-level subdivision surface form (ISO 3166-2 code, English name, or co-official French name for CA;
|
|
85
|
+
* accents optional) to its `{ code, name, country }`. Case- and diacritic-insensitive. Returns null for anything that
|
|
86
|
+
* isn't a US state or Canadian province/territory — including bare country tokens (use {@link matchCountry} for
|
|
87
|
+
* those).
|
|
88
|
+
*/
|
|
89
|
+
export function matchSubdivision(token: string | null | undefined): SubdivisionMatch | null {
|
|
90
|
+
if (!token || typeof token !== "string") return null
|
|
91
|
+
|
|
92
|
+
return SUBDIVISION_LOOKUP.get(foldName(token)) ?? null
|
|
93
|
+
}
|
package/de/bundesland.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The 16 German federal states (Bundesländer), keyed by their ISO 3166-2:DE subdivision code.
|
|
7
|
+
*
|
|
8
|
+
* The US analog is `us/state.ts`. The informative difference: a US state's two-letter code (`CA`)
|
|
9
|
+
* is the USPS abbreviation people actually write in an address, whereas a German address almost
|
|
10
|
+
* never carries the Bundesland at all — it is `PLZ City`, and the state is inferred. So these
|
|
11
|
+
* codes matter for resolver region-matching and display, not for parsing the surface string.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Per-state record: ISO 3166-2:DE code, native German name, and the common English exonym. */
|
|
15
|
+
export interface GermanStateInfo {
|
|
16
|
+
/** ISO 3166-2:DE subdivision code without the `DE-` prefix (e.g. `BY` for `DE-BY`). */
|
|
17
|
+
code: string
|
|
18
|
+
/** Native German name (e.g. `Bayern`). */
|
|
19
|
+
name: string
|
|
20
|
+
/** Common English name (e.g. `Bavaria`). */
|
|
21
|
+
english: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* ISO 3166-2:DE code → state info, for all 16 Bundesländer. Codes are the official subdivision codes minus the `DE-`
|
|
26
|
+
* prefix.
|
|
27
|
+
*/
|
|
28
|
+
export const DE_BUNDESLAENDER = {
|
|
29
|
+
BW: { code: "BW", name: "Baden-Württemberg", english: "Baden-Württemberg" },
|
|
30
|
+
BY: { code: "BY", name: "Bayern", english: "Bavaria" },
|
|
31
|
+
BE: { code: "BE", name: "Berlin", english: "Berlin" },
|
|
32
|
+
BB: { code: "BB", name: "Brandenburg", english: "Brandenburg" },
|
|
33
|
+
HB: { code: "HB", name: "Bremen", english: "Bremen" },
|
|
34
|
+
HH: { code: "HH", name: "Hamburg", english: "Hamburg" },
|
|
35
|
+
HE: { code: "HE", name: "Hessen", english: "Hesse" },
|
|
36
|
+
MV: { code: "MV", name: "Mecklenburg-Vorpommern", english: "Mecklenburg-Western Pomerania" },
|
|
37
|
+
NI: { code: "NI", name: "Niedersachsen", english: "Lower Saxony" },
|
|
38
|
+
NW: { code: "NW", name: "Nordrhein-Westfalen", english: "North Rhine-Westphalia" },
|
|
39
|
+
RP: { code: "RP", name: "Rheinland-Pfalz", english: "Rhineland-Palatinate" },
|
|
40
|
+
SL: { code: "SL", name: "Saarland", english: "Saarland" },
|
|
41
|
+
SN: { code: "SN", name: "Sachsen", english: "Saxony" },
|
|
42
|
+
ST: { code: "ST", name: "Sachsen-Anhalt", english: "Saxony-Anhalt" },
|
|
43
|
+
SH: { code: "SH", name: "Schleswig-Holstein", english: "Schleswig-Holstein" },
|
|
44
|
+
TH: { code: "TH", name: "Thüringen", english: "Thuringia" },
|
|
45
|
+
} as const satisfies Record<string, GermanStateInfo>
|
|
46
|
+
|
|
47
|
+
/** An ISO 3166-2:DE state code (`BW`, `BY`, `BE`, …). */
|
|
48
|
+
export type GermanStateCode = keyof typeof DE_BUNDESLAENDER
|
|
49
|
+
|
|
50
|
+
const STATE_CODE_SET: ReadonlySet<string> = new Set(Object.keys(DE_BUNDESLAENDER))
|
|
51
|
+
|
|
52
|
+
/** Type-predicate for an ISO 3166-2:DE state code. Case-insensitive. */
|
|
53
|
+
export function isGermanStateCode(input: unknown): input is GermanStateCode {
|
|
54
|
+
return typeof input === "string" && STATE_CODE_SET.has(input.toUpperCase())
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Name (native German, English exonym, or common alias) → ISO 3166-2:DE code, lowercase-keyed. Includes the everyday
|
|
59
|
+
* aliases a parser actually meets: `NRW` for Nordrhein-Westfalen, `Bavaria` for Bayern, `Saxony` for Sachsen. The point
|
|
60
|
+
* is resolver region-matching: a German parse emits a region surface form, and the eval needs to map it to a code
|
|
61
|
+
* without a US-USPS-shaped matcher.
|
|
62
|
+
*/
|
|
63
|
+
export const DE_STATE_NAME_TO_CODE: ReadonlyMap<string, GermanStateCode> = (() => {
|
|
64
|
+
const out = new Map<string, GermanStateCode>()
|
|
65
|
+
|
|
66
|
+
for (const code of Object.keys(DE_BUNDESLAENDER) as GermanStateCode[]) {
|
|
67
|
+
const info = DE_BUNDESLAENDER[code]
|
|
68
|
+
out.set(info.name.toLowerCase(), code)
|
|
69
|
+
out.set(info.english.toLowerCase(), code)
|
|
70
|
+
out.set(code.toLowerCase(), code)
|
|
71
|
+
}
|
|
72
|
+
// Everyday aliases that are neither the ISO code nor the canonical name.
|
|
73
|
+
const aliases: Record<string, GermanStateCode> = {
|
|
74
|
+
nrw: "NW",
|
|
75
|
+
"nordrhein westfalen": "NW",
|
|
76
|
+
"baden wurttemberg": "BW",
|
|
77
|
+
"baden-wuerttemberg": "BW",
|
|
78
|
+
"baden wuerttemberg": "BW",
|
|
79
|
+
thueringen: "TH",
|
|
80
|
+
"freie hansestadt bremen": "HB",
|
|
81
|
+
"freie und hansestadt hamburg": "HH",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (const [alias, code] of Object.entries(aliases)) {
|
|
85
|
+
out.set(alias, code)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return out
|
|
89
|
+
})()
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Resolve a German state surface form (code, German name, English name, or common alias) to its ISO 3166-2:DE code.
|
|
93
|
+
* Returns null when unrecognized.
|
|
94
|
+
*/
|
|
95
|
+
export function lookupGermanState(input: string | null | undefined): GermanStateCode | null {
|
|
96
|
+
if (!input || typeof input !== "string") return null
|
|
97
|
+
const key = input.trim().toLowerCase()
|
|
98
|
+
|
|
99
|
+
if (STATE_CODE_SET.has(key.toUpperCase())) return key.toUpperCase() as GermanStateCode
|
|
100
|
+
|
|
101
|
+
return DE_STATE_NAME_TO_CODE.get(key) ?? null
|
|
102
|
+
}
|
package/de/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The German address system (Deutsche Post / ISO 3166-2:DE): street types, postal codes
|
|
7
|
+
* (Postleitzahl), and the federal states (Bundesländer).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export * from "./bundesland.ts"
|
|
11
|
+
export * from "./postleitzahl.ts"
|
|
12
|
+
export * from "./street-type.ts"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* German postal codes (Postleitzahl, PLZ): the branded type, the shape, normalization, and the
|
|
7
|
+
* first-digit → Leitzone geographic prior.
|
|
8
|
+
*
|
|
9
|
+
* The US analog is `us/zipcode.ts`, and the contrast is the informative part. A US ZIP's first
|
|
10
|
+
* digit maps cleanly to a band of states (`StateAbbreviationZipCodePrefixRecord`). A German PLZ's
|
|
11
|
+
* first digit maps to a **Leitzone** — a postal routing region that deliberately **crosses
|
|
12
|
+
* Bundesland borders** (Leitzone 6 covers Frankfurt in Hessen, Saarbrücken in Saarland, and Mainz
|
|
13
|
+
* in Rheinland-Pfalz). So the PLZ prior narrows geography, but it does NOT narrow the state the
|
|
14
|
+
* way a US ZIP does — a lesson for any code that tries to derive a German region from a postcode
|
|
15
|
+
* alone.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { Tagged } from "type-fest"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A German postal code: five digits since the 1993 reform (`12623`). A bare 5-digit string, same shape as a US ZIP or a
|
|
22
|
+
* French code postal — disambiguation is the parser's job, not the shape's.
|
|
23
|
+
*
|
|
24
|
+
* @category Postal
|
|
25
|
+
* @type string
|
|
26
|
+
* @title Postleitzahl
|
|
27
|
+
* @pattern ^\d{5}$
|
|
28
|
+
*/
|
|
29
|
+
export type Postleitzahl = Tagged<string, "Postleitzahl">
|
|
30
|
+
|
|
31
|
+
/** The PLZ shape: exactly five digits. */
|
|
32
|
+
export const PLZ_PATTERN = /^\d{5}$/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Normalize a PLZ surface form to the bare five digits: strip the `D-` / `DE-` country courtesy prefix and surrounding
|
|
36
|
+
* whitespace (`D-68161` → `68161`). Returns null if the result is not a PLZ.
|
|
37
|
+
*/
|
|
38
|
+
export function normalizePLZ(raw: unknown): Postleitzahl | null {
|
|
39
|
+
if (typeof raw !== "string") return null
|
|
40
|
+
const s = raw.trim().toUpperCase().replace(/^DE?-/, "")
|
|
41
|
+
|
|
42
|
+
return PLZ_PATTERN.test(s) ? (s as Postleitzahl) : null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Type-predicate for a (normalized) German postal code. */
|
|
46
|
+
export function isPostleitzahl(input: unknown): input is Postleitzahl {
|
|
47
|
+
return typeof input === "string" && PLZ_PATTERN.test(input)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A PLZ Leitzone first digit. */
|
|
51
|
+
export type LeitzoneDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
|
|
52
|
+
|
|
53
|
+
/** Per-Leitzone descriptor: the routing region and a few anchor cities (coarse, postal not admin). */
|
|
54
|
+
export interface LeitzoneInfo {
|
|
55
|
+
digit: LeitzoneDigit
|
|
56
|
+
/** Coarse routing-region label. */
|
|
57
|
+
region: string
|
|
58
|
+
/** Well-known anchor cities in the zone (illustrative, not exhaustive). */
|
|
59
|
+
cities: readonly string[]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* PLZ first digit → Leitzone. A coarse, postal-routing prior: these zones cross Bundesland borders, so the label is
|
|
64
|
+
* "which corner of Germany", not "which state". Anchor cities are the safe, well-known way to pin a zone without
|
|
65
|
+
* over-claiming a boundary the routing geography does not actually follow.
|
|
66
|
+
*/
|
|
67
|
+
export const PLZ_LEITZONEN = {
|
|
68
|
+
0: { digit: 0, region: "Sachsen / Ostthüringen", cities: ["Leipzig", "Dresden", "Chemnitz"] },
|
|
69
|
+
1: { digit: 1, region: "Berlin / Brandenburg / Mecklenburg-Vorpommern", cities: ["Berlin", "Potsdam", "Rostock"] },
|
|
70
|
+
2: { digit: 2, region: "Hamburg / Schleswig-Holstein / Bremen", cities: ["Hamburg", "Kiel", "Bremen"] },
|
|
71
|
+
3: { digit: 3, region: "Niedersachsen / Nordhessen", cities: ["Hannover", "Braunschweig", "Kassel"] },
|
|
72
|
+
4: { digit: 4, region: "nördliches Nordrhein-Westfalen", cities: ["Düsseldorf", "Dortmund", "Münster"] },
|
|
73
|
+
5: { digit: 5, region: "südliches NRW / nördliches Rheinland-Pfalz", cities: ["Köln", "Bonn", "Aachen"] },
|
|
74
|
+
6: {
|
|
75
|
+
digit: 6,
|
|
76
|
+
region: "Südhessen / Rheinland-Pfalz / Saarland",
|
|
77
|
+
cities: ["Frankfurt am Main", "Mainz", "Saarbrücken"],
|
|
78
|
+
},
|
|
79
|
+
7: { digit: 7, region: "Baden-Württemberg", cities: ["Stuttgart", "Karlsruhe", "Freiburg"] },
|
|
80
|
+
8: { digit: 8, region: "südliches Bayern", cities: ["München", "Augsburg", "Ingolstadt"] },
|
|
81
|
+
9: { digit: 9, region: "nördliches Bayern / Oberpfalz", cities: ["Nürnberg", "Würzburg", "Regensburg"] },
|
|
82
|
+
} as const satisfies Record<LeitzoneDigit, LeitzoneInfo>
|
|
83
|
+
|
|
84
|
+
/** The Leitzone of a PLZ (its first digit's routing region), or null if the input is not a PLZ. */
|
|
85
|
+
export function leitzoneOf(plz: unknown): LeitzoneInfo | null {
|
|
86
|
+
const normalized = normalizePLZ(plz)
|
|
87
|
+
|
|
88
|
+
if (!normalized) return null
|
|
89
|
+
|
|
90
|
+
return PLZ_LEITZONEN[Number(normalized[0]) as LeitzoneDigit]
|
|
91
|
+
}
|