@formatjs/intl-getcanonicallocales 2.0.2 → 2.0.3
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/BUILD +116 -0
- package/CHANGELOG.md +290 -0
- package/LICENSE.md +0 -0
- package/README.md +0 -0
- package/index.ts +43 -0
- package/package.json +2 -2
- package/polyfill.ts +23 -0
- package/scripts/aliases.ts +70 -0
- package/scripts/likely-subtags.ts +20 -0
- package/should-polyfill.ts +10 -0
- package/src/aliases.generated.ts +1137 -0
- package/src/canonicalizer.ts +272 -0
- package/src/emitter.ts +39 -0
- package/src/likelySubtags.generated.ts +1870 -0
- package/src/parser.ts +259 -0
- package/src/types.ts +63 -0
- package/tests/index.test.ts +24 -0
- package/tests/parser.test.ts +204 -0
- package/tsconfig.json +5 -0
- package/index.d.ts +0 -6
- package/index.d.ts.map +0 -1
- package/index.js +0 -42
- package/lib/index.d.ts +0 -6
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -31
- package/lib/polyfill.d.ts +0 -2
- package/lib/polyfill.d.ts.map +0 -1
- package/lib/polyfill.js +0 -24
- package/lib/should-polyfill.d.ts +0 -2
- package/lib/should-polyfill.d.ts.map +0 -1
- package/lib/should-polyfill.js +0 -8
- package/lib/src/aliases.generated.d.ts +0 -5
- package/lib/src/aliases.generated.d.ts.map +0 -1
- package/lib/src/aliases.generated.js +0 -1137
- package/lib/src/canonicalizer.d.ts +0 -20
- package/lib/src/canonicalizer.d.ts.map +0 -1
- package/lib/src/canonicalizer.js +0 -219
- package/lib/src/emitter.d.ts +0 -4
- package/lib/src/emitter.d.ts.map +0 -1
- package/lib/src/emitter.js +0 -28
- package/lib/src/likelySubtags.generated.d.ts +0 -2
- package/lib/src/likelySubtags.generated.d.ts.map +0 -1
- package/lib/src/likelySubtags.generated.js +0 -1870
- package/lib/src/parser.d.ts +0 -10
- package/lib/src/parser.d.ts.map +0 -1
- package/lib/src/parser.js +0 -233
- package/lib/src/types.d.ts +0 -33
- package/lib/src/types.d.ts.map +0 -1
- package/lib/src/types.js +0 -1
- package/polyfill.d.ts +0 -2
- package/polyfill.d.ts.map +0 -1
- package/polyfill.iife.js +0 -3512
- package/polyfill.js +0 -26
- package/should-polyfill.d.ts +0 -2
- package/should-polyfill.d.ts.map +0 -1
- package/should-polyfill.js +0 -12
- package/src/aliases.generated.d.ts +0 -5
- package/src/aliases.generated.d.ts.map +0 -1
- package/src/aliases.generated.js +0 -1140
- package/src/canonicalizer.d.ts +0 -20
- package/src/canonicalizer.d.ts.map +0 -1
- package/src/canonicalizer.js +0 -224
- package/src/emitter.d.ts +0 -4
- package/src/emitter.d.ts.map +0 -1
- package/src/emitter.js +0 -33
- package/src/likelySubtags.generated.d.ts +0 -2
- package/src/likelySubtags.generated.d.ts.map +0 -1
- package/src/likelySubtags.generated.js +0 -1873
- package/src/parser.d.ts +0 -10
- package/src/parser.d.ts.map +0 -1
- package/src/parser.js +0 -243
- package/src/types.d.ts +0 -33
- package/src/types.d.ts.map +0 -1
- package/src/types.js +0 -2
package/src/parser.ts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnicodeLocaleId,
|
|
3
|
+
UnicodeLanguageId,
|
|
4
|
+
UnicodeExtension,
|
|
5
|
+
TransformedExtension,
|
|
6
|
+
PuExtension,
|
|
7
|
+
OtherExtension,
|
|
8
|
+
KV,
|
|
9
|
+
} from './types'
|
|
10
|
+
|
|
11
|
+
const ALPHANUM_1_8 = /^[a-z0-9]{1,8}$/i
|
|
12
|
+
const ALPHANUM_2_8 = /^[a-z0-9]{2,8}$/i
|
|
13
|
+
const ALPHANUM_3_8 = /^[a-z0-9]{3,8}$/i
|
|
14
|
+
|
|
15
|
+
const KEY_REGEX = /^[a-z0-9][a-z]$/i
|
|
16
|
+
|
|
17
|
+
const TYPE_REGEX = /^[a-z0-9]{3,8}$/i
|
|
18
|
+
const ALPHA_4 = /^[a-z]{4}$/i
|
|
19
|
+
// alphanum-[tTuUxX]
|
|
20
|
+
const OTHER_EXTENSION_TYPE = /^[0-9a-svwyz]$/i
|
|
21
|
+
const UNICODE_REGION_SUBTAG_REGEX = /^([a-z]{2}|[0-9]{3})$/i
|
|
22
|
+
const UNICODE_VARIANT_SUBTAG_REGEX = /^([a-z0-9]{5,8}|[0-9][a-z0-9]{3})$/i
|
|
23
|
+
const UNICODE_LANGUAGE_SUBTAG_REGEX = /^([a-z]{2,3}|[a-z]{5,8})$/i
|
|
24
|
+
const TKEY_REGEX = /^[a-z][0-9]$/i
|
|
25
|
+
|
|
26
|
+
export const SEPARATOR = '-'
|
|
27
|
+
|
|
28
|
+
export function isUnicodeLanguageSubtag(lang: string): boolean {
|
|
29
|
+
return UNICODE_LANGUAGE_SUBTAG_REGEX.test(lang)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isStructurallyValidLanguageTag(tag: string): boolean {
|
|
33
|
+
try {
|
|
34
|
+
parseUnicodeLanguageId(tag.split(SEPARATOR))
|
|
35
|
+
} catch (e) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isUnicodeRegionSubtag(region: string): boolean {
|
|
42
|
+
return UNICODE_REGION_SUBTAG_REGEX.test(region)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function isUnicodeScriptSubtag(script: string): boolean {
|
|
46
|
+
return ALPHA_4.test(script)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function isUnicodeVariantSubtag(variant: string): boolean {
|
|
50
|
+
return UNICODE_VARIANT_SUBTAG_REGEX.test(variant)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function parseUnicodeLanguageId(
|
|
54
|
+
chunks: string[] | string
|
|
55
|
+
): UnicodeLanguageId {
|
|
56
|
+
if (typeof chunks === 'string') {
|
|
57
|
+
chunks = chunks.split(SEPARATOR)
|
|
58
|
+
}
|
|
59
|
+
const lang = chunks.shift()
|
|
60
|
+
if (!lang) {
|
|
61
|
+
throw new RangeError('Missing unicode_language_subtag')
|
|
62
|
+
}
|
|
63
|
+
if (lang === 'root') {
|
|
64
|
+
return {lang: 'root', variants: []}
|
|
65
|
+
}
|
|
66
|
+
// unicode_language_subtag
|
|
67
|
+
if (!isUnicodeLanguageSubtag(lang)) {
|
|
68
|
+
throw new RangeError('Malformed unicode_language_subtag')
|
|
69
|
+
}
|
|
70
|
+
let script
|
|
71
|
+
// unicode_script_subtag
|
|
72
|
+
if (chunks.length && isUnicodeScriptSubtag(chunks[0])) {
|
|
73
|
+
script = chunks.shift()
|
|
74
|
+
}
|
|
75
|
+
let region
|
|
76
|
+
// unicode_region_subtag
|
|
77
|
+
if (chunks.length && isUnicodeRegionSubtag(chunks[0])) {
|
|
78
|
+
region = chunks.shift()
|
|
79
|
+
}
|
|
80
|
+
const variants: Record<string, any> = {}
|
|
81
|
+
while (chunks.length && isUnicodeVariantSubtag(chunks[0])) {
|
|
82
|
+
const variant: string = chunks.shift()!
|
|
83
|
+
if (variant in variants) {
|
|
84
|
+
throw new RangeError(`Duplicate variant "${variant}"`)
|
|
85
|
+
}
|
|
86
|
+
variants[variant] = 1
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
lang,
|
|
90
|
+
script,
|
|
91
|
+
region,
|
|
92
|
+
variants: Object.keys(variants),
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function parseUnicodeExtension(chunks: string[]): UnicodeExtension {
|
|
97
|
+
const keywords = []
|
|
98
|
+
let keyword
|
|
99
|
+
while (chunks.length && (keyword = parseKeyword(chunks))) {
|
|
100
|
+
keywords.push(keyword)
|
|
101
|
+
}
|
|
102
|
+
if (keywords.length) {
|
|
103
|
+
return {
|
|
104
|
+
type: 'u',
|
|
105
|
+
keywords,
|
|
106
|
+
attributes: [],
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Mix of attributes & keywords
|
|
110
|
+
// Check for attributes first
|
|
111
|
+
const attributes = []
|
|
112
|
+
while (chunks.length && ALPHANUM_3_8.test(chunks[0])) {
|
|
113
|
+
attributes.push(chunks.shift()!)
|
|
114
|
+
}
|
|
115
|
+
while (chunks.length && (keyword = parseKeyword(chunks))) {
|
|
116
|
+
keywords.push(keyword)
|
|
117
|
+
}
|
|
118
|
+
if (keywords.length || attributes.length) {
|
|
119
|
+
return {
|
|
120
|
+
type: 'u',
|
|
121
|
+
attributes,
|
|
122
|
+
keywords,
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
throw new RangeError('Malformed unicode_extension')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function parseKeyword(chunks: string[]): KV | undefined {
|
|
129
|
+
let key
|
|
130
|
+
if (!KEY_REGEX.test(chunks[0])) {
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
key = chunks.shift()!
|
|
134
|
+
|
|
135
|
+
const type = []
|
|
136
|
+
while (chunks.length && TYPE_REGEX.test(chunks[0])) {
|
|
137
|
+
type.push(chunks.shift())
|
|
138
|
+
}
|
|
139
|
+
let value: string = ''
|
|
140
|
+
if (type.length) {
|
|
141
|
+
value = type.join(SEPARATOR)
|
|
142
|
+
}
|
|
143
|
+
return [key, value]
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function parseTransformedExtension(chunks: string[]): TransformedExtension {
|
|
147
|
+
let lang: UnicodeLanguageId | undefined
|
|
148
|
+
try {
|
|
149
|
+
lang = parseUnicodeLanguageId(chunks)
|
|
150
|
+
} catch (e) {
|
|
151
|
+
// Try just parsing tfield
|
|
152
|
+
}
|
|
153
|
+
const fields: KV[] = []
|
|
154
|
+
while (chunks.length && TKEY_REGEX.test(chunks[0])) {
|
|
155
|
+
const key = chunks.shift()!
|
|
156
|
+
const value = []
|
|
157
|
+
while (chunks.length && ALPHANUM_3_8.test(chunks[0])) {
|
|
158
|
+
value.push(chunks.shift())
|
|
159
|
+
}
|
|
160
|
+
if (!value.length) {
|
|
161
|
+
throw new RangeError(`Missing tvalue for tkey "${key}"`)
|
|
162
|
+
}
|
|
163
|
+
fields.push([key, value.join(SEPARATOR)])
|
|
164
|
+
}
|
|
165
|
+
if (fields.length) {
|
|
166
|
+
return {
|
|
167
|
+
type: 't',
|
|
168
|
+
fields,
|
|
169
|
+
lang,
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
throw new RangeError('Malformed transformed_extension')
|
|
173
|
+
}
|
|
174
|
+
function parsePuExtension(chunks: string[]): PuExtension {
|
|
175
|
+
const exts = []
|
|
176
|
+
while (chunks.length && ALPHANUM_1_8.test(chunks[0])) {
|
|
177
|
+
exts.push(chunks.shift())
|
|
178
|
+
}
|
|
179
|
+
if (exts.length) {
|
|
180
|
+
return {
|
|
181
|
+
type: 'x',
|
|
182
|
+
value: exts.join(SEPARATOR),
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
throw new RangeError('Malformed private_use_extension')
|
|
186
|
+
}
|
|
187
|
+
function parseOtherExtensionValue(chunks: string[]): string {
|
|
188
|
+
const exts = []
|
|
189
|
+
while (chunks.length && ALPHANUM_2_8.test(chunks[0])) {
|
|
190
|
+
exts.push(chunks.shift())
|
|
191
|
+
}
|
|
192
|
+
if (exts.length) {
|
|
193
|
+
return exts.join(SEPARATOR)
|
|
194
|
+
}
|
|
195
|
+
return ''
|
|
196
|
+
}
|
|
197
|
+
function parseExtensions(chunks: string[]): Omit<UnicodeLocaleId, 'lang'> {
|
|
198
|
+
if (!chunks.length) {
|
|
199
|
+
return {extensions: []}
|
|
200
|
+
}
|
|
201
|
+
const extensions: UnicodeLocaleId['extensions'] = []
|
|
202
|
+
let unicodeExtension
|
|
203
|
+
let transformedExtension
|
|
204
|
+
let puExtension
|
|
205
|
+
const otherExtensionMap: Record<string, OtherExtension> = {}
|
|
206
|
+
do {
|
|
207
|
+
const type = chunks.shift()!
|
|
208
|
+
switch (type) {
|
|
209
|
+
case 'u':
|
|
210
|
+
case 'U':
|
|
211
|
+
if (unicodeExtension) {
|
|
212
|
+
throw new RangeError('There can only be 1 -u- extension')
|
|
213
|
+
}
|
|
214
|
+
unicodeExtension = parseUnicodeExtension(chunks)
|
|
215
|
+
extensions.push(unicodeExtension)
|
|
216
|
+
break
|
|
217
|
+
case 't':
|
|
218
|
+
case 'T':
|
|
219
|
+
if (transformedExtension) {
|
|
220
|
+
throw new RangeError('There can only be 1 -t- extension')
|
|
221
|
+
}
|
|
222
|
+
transformedExtension = parseTransformedExtension(chunks)
|
|
223
|
+
extensions.push(transformedExtension)
|
|
224
|
+
break
|
|
225
|
+
case 'x':
|
|
226
|
+
case 'X':
|
|
227
|
+
if (puExtension) {
|
|
228
|
+
throw new RangeError('There can only be 1 -x- extension')
|
|
229
|
+
}
|
|
230
|
+
puExtension = parsePuExtension(chunks)
|
|
231
|
+
extensions.push(puExtension)
|
|
232
|
+
break
|
|
233
|
+
default:
|
|
234
|
+
if (!OTHER_EXTENSION_TYPE.test(type)) {
|
|
235
|
+
throw new RangeError('Malformed extension type')
|
|
236
|
+
}
|
|
237
|
+
if (type in otherExtensionMap) {
|
|
238
|
+
throw new RangeError(`There can only be 1 -${type}- extension`)
|
|
239
|
+
}
|
|
240
|
+
const extension: OtherExtension = {
|
|
241
|
+
type: type as 'a',
|
|
242
|
+
value: parseOtherExtensionValue(chunks),
|
|
243
|
+
}
|
|
244
|
+
otherExtensionMap[extension.type] = extension
|
|
245
|
+
extensions.push(extension)
|
|
246
|
+
break
|
|
247
|
+
}
|
|
248
|
+
} while (chunks.length)
|
|
249
|
+
return {extensions}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function parseUnicodeLocaleId(locale: string): UnicodeLocaleId {
|
|
253
|
+
const chunks = locale.split(SEPARATOR)
|
|
254
|
+
const lang = parseUnicodeLanguageId(chunks)
|
|
255
|
+
return {
|
|
256
|
+
lang,
|
|
257
|
+
...parseExtensions(chunks),
|
|
258
|
+
}
|
|
259
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export interface UnicodeLocaleId {
|
|
2
|
+
lang: UnicodeLanguageId
|
|
3
|
+
extensions: Array<
|
|
4
|
+
UnicodeExtension | TransformedExtension | PuExtension | OtherExtension
|
|
5
|
+
>
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface UnicodeLanguageId {
|
|
9
|
+
lang: string
|
|
10
|
+
script?: string
|
|
11
|
+
region?: string
|
|
12
|
+
variants: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type KV = [string, string] | [string]
|
|
16
|
+
|
|
17
|
+
export interface Extension {
|
|
18
|
+
type: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface UnicodeExtension extends Extension {
|
|
22
|
+
type: 'u'
|
|
23
|
+
keywords: KV[]
|
|
24
|
+
attributes: string[]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface TransformedExtension extends Extension {
|
|
28
|
+
type: 't'
|
|
29
|
+
fields: KV[]
|
|
30
|
+
lang?: UnicodeLanguageId
|
|
31
|
+
}
|
|
32
|
+
export interface PuExtension extends Extension {
|
|
33
|
+
type: 'x'
|
|
34
|
+
value: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface OtherExtension extends Extension {
|
|
38
|
+
type:
|
|
39
|
+
| 'a'
|
|
40
|
+
| 'b'
|
|
41
|
+
| 'c'
|
|
42
|
+
| 'd'
|
|
43
|
+
| 'e'
|
|
44
|
+
| 'f'
|
|
45
|
+
| 'g'
|
|
46
|
+
| 'h'
|
|
47
|
+
| 'i'
|
|
48
|
+
| 'j'
|
|
49
|
+
| 'k'
|
|
50
|
+
| 'l'
|
|
51
|
+
| 'm'
|
|
52
|
+
| 'n'
|
|
53
|
+
| 'o'
|
|
54
|
+
| 'p'
|
|
55
|
+
| 'q'
|
|
56
|
+
| 'r'
|
|
57
|
+
| 's'
|
|
58
|
+
| 'v'
|
|
59
|
+
| 'w'
|
|
60
|
+
| 'y'
|
|
61
|
+
| 'z'
|
|
62
|
+
value: string
|
|
63
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {getCanonicalLocales} from '../'
|
|
2
|
+
|
|
3
|
+
describe('Intl.getCanonicalLocales', () => {
|
|
4
|
+
it('regular', function () {
|
|
5
|
+
expect(
|
|
6
|
+
getCanonicalLocales('en-u-foo-bar-nu-thai-ca-buddhist-kk-true')
|
|
7
|
+
).toEqual(['en-u-bar-foo-ca-buddhist-kk-nu-thai'])
|
|
8
|
+
})
|
|
9
|
+
it('und-x-private', function () {
|
|
10
|
+
expect(getCanonicalLocales('und-x-private')).toEqual(['und-x-private'])
|
|
11
|
+
})
|
|
12
|
+
it('should canonicalize casing for zh-hANs-sG', function () {
|
|
13
|
+
expect(getCanonicalLocales('zh-hANs-sG')).toEqual(['zh-Hans-SG'])
|
|
14
|
+
})
|
|
15
|
+
it('should handle twi', function () {
|
|
16
|
+
expect(getCanonicalLocales('twi')).toEqual(['ak'])
|
|
17
|
+
})
|
|
18
|
+
it('should handle ug-Arab-CN ', function () {
|
|
19
|
+
expect(getCanonicalLocales('ug-Arab-CN')).toEqual(['ug-Arab-CN'])
|
|
20
|
+
})
|
|
21
|
+
it('canonicalizes twice', function () {
|
|
22
|
+
expect(getCanonicalLocales('und-Armn-SU')).toEqual(['und-Armn-AM'])
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {parseUnicodeLocaleId} from '../src/parser'
|
|
2
|
+
|
|
3
|
+
describe('parser', () => {
|
|
4
|
+
const invalidLanguageTags = [
|
|
5
|
+
// Unicode extension sequence is incomplete.
|
|
6
|
+
'da-u',
|
|
7
|
+
'da-u-',
|
|
8
|
+
'da-u--',
|
|
9
|
+
'da-u-t-latn',
|
|
10
|
+
'da-u-x-priv',
|
|
11
|
+
|
|
12
|
+
// Duplicate 'u' singleton.
|
|
13
|
+
'da-u-ca-gregory-u-ca-buddhist',
|
|
14
|
+
|
|
15
|
+
// https://github.com/tc39/test262/blob/5124761d2febfe5cc1427920d782219052f29a2c/harness/testIntl.js#L185
|
|
16
|
+
'', // empty tag
|
|
17
|
+
'i', // singleton alone
|
|
18
|
+
'x', // private use without subtag
|
|
19
|
+
'u', // extension singleton in first place
|
|
20
|
+
'419', // region code in first place
|
|
21
|
+
'u-nu-latn-cu-bob', // extension sequence without language
|
|
22
|
+
'hans-cmn-cn', // "hans" could theoretically be a 4-letter language code,
|
|
23
|
+
// but those can't be followed by extlang codes.
|
|
24
|
+
'cmn-hans-cn-u-u', // duplicate singleton
|
|
25
|
+
'cmn-hans-cn-t-u-ca-u', // duplicate singleton
|
|
26
|
+
'de-gregory-gregory', // duplicate variant
|
|
27
|
+
'*', // language range
|
|
28
|
+
'de-*', // language range
|
|
29
|
+
'中文', // non-ASCII letters
|
|
30
|
+
'en-ß', // non-ASCII letters
|
|
31
|
+
'ıd', // non-ASCII letters
|
|
32
|
+
'es-Latn-latn', // two scripts
|
|
33
|
+
'pl-PL-pl', // two regions
|
|
34
|
+
'u-ca-gregory', // extension in first place
|
|
35
|
+
'de-1996-1996', // duplicate numeric variant
|
|
36
|
+
'pt-u-ca-gregory-u-nu-latn', // duplicate singleton subtag
|
|
37
|
+
|
|
38
|
+
// Invalid tags starting with: https://github.com/tc39/ecma402/pull/289
|
|
39
|
+
'no-nyn', // regular grandfathered in BCP47, but invalid in UTS35
|
|
40
|
+
'i-klingon', // irregular grandfathered in BCP47, but invalid in UTS35
|
|
41
|
+
'zh-hak-CN', // language with extlang in BCP47, but invalid in UTS35
|
|
42
|
+
'sgn-ils', // language with extlang in BCP47, but invalid in UTS35
|
|
43
|
+
'x-foo', // privateuse-only in BCP47, but invalid in UTS35
|
|
44
|
+
'x-en-US-12345', // more privateuse-only variants.
|
|
45
|
+
'x-12345-12345-en-US',
|
|
46
|
+
'x-en-US-12345-12345',
|
|
47
|
+
'x-en-u-foo',
|
|
48
|
+
'x-en-u-foo-u-bar',
|
|
49
|
+
'x-u-foo',
|
|
50
|
+
|
|
51
|
+
// underscores in different parts of the language tag
|
|
52
|
+
'de_DE',
|
|
53
|
+
'DE_de',
|
|
54
|
+
'cmn_Hans',
|
|
55
|
+
'cmn-hans_cn',
|
|
56
|
+
'es_419',
|
|
57
|
+
'es-419-u-nu-latn-cu_bob',
|
|
58
|
+
'i_klingon',
|
|
59
|
+
'cmn-hans-cn-t-ca-u-ca-x_t-u',
|
|
60
|
+
'enochian_enochian',
|
|
61
|
+
'de-gregory_u-ca-gregory',
|
|
62
|
+
|
|
63
|
+
'en\u0000', // null-terminator sequence
|
|
64
|
+
' en', // leading whitespace
|
|
65
|
+
'en ', // trailing whitespace
|
|
66
|
+
'it-IT-Latn', // country before script tag
|
|
67
|
+
'de-u', // incomplete Unicode extension sequences
|
|
68
|
+
'de-u-',
|
|
69
|
+
'de-u-ca-',
|
|
70
|
+
'de-u-ca-gregory-',
|
|
71
|
+
'si-x', // incomplete private-use tags
|
|
72
|
+
'x-',
|
|
73
|
+
'x-y-',
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
for (const langtag of invalidLanguageTags) {
|
|
77
|
+
it(`new Intl.Locale("${langtag}") throws RangeError`, function () {
|
|
78
|
+
expect(() => parseUnicodeLocaleId(langtag)).toThrowError(RangeError)
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
it('en-u-foo-bar-nu-thai-ca-buddhist-kk-true', function () {
|
|
83
|
+
expect(
|
|
84
|
+
parseUnicodeLocaleId('en-u-foo-bar-nu-thai-ca-buddhist-kk-true')
|
|
85
|
+
).toEqual({
|
|
86
|
+
extensions: [
|
|
87
|
+
{
|
|
88
|
+
attributes: ['foo', 'bar'],
|
|
89
|
+
keywords: [
|
|
90
|
+
['nu', 'thai'],
|
|
91
|
+
['ca', 'buddhist'],
|
|
92
|
+
['kk', 'true'],
|
|
93
|
+
],
|
|
94
|
+
type: 'u',
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
lang: {lang: 'en', region: undefined, script: undefined, variants: []},
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
it('da-u-ca-gregory-ca-buddhist', function () {
|
|
101
|
+
expect(parseUnicodeLocaleId('da-u-ca-gregory-ca-buddhist')).toEqual({
|
|
102
|
+
extensions: [
|
|
103
|
+
{
|
|
104
|
+
attributes: [],
|
|
105
|
+
keywords: [
|
|
106
|
+
['ca', 'gregory'],
|
|
107
|
+
['ca', 'buddhist'],
|
|
108
|
+
],
|
|
109
|
+
type: 'u',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
lang: {lang: 'da', region: undefined, script: undefined, variants: []},
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
it('en-Latn-fonipa', function () {
|
|
116
|
+
expect(parseUnicodeLocaleId('en-Latn-fonipa')).toEqual({
|
|
117
|
+
extensions: [],
|
|
118
|
+
lang: {
|
|
119
|
+
lang: 'en',
|
|
120
|
+
region: undefined,
|
|
121
|
+
script: 'Latn',
|
|
122
|
+
variants: ['fonipa'],
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
it('de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn', function () {
|
|
127
|
+
expect(
|
|
128
|
+
parseUnicodeLocaleId(
|
|
129
|
+
'de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn'
|
|
130
|
+
)
|
|
131
|
+
).toEqual({
|
|
132
|
+
extensions: [
|
|
133
|
+
{
|
|
134
|
+
attributes: [],
|
|
135
|
+
keywords: [
|
|
136
|
+
['ca', 'gregory'],
|
|
137
|
+
['co', 'phonebk'],
|
|
138
|
+
['hc', 'h23'],
|
|
139
|
+
['kf', ''],
|
|
140
|
+
['kn', 'false'],
|
|
141
|
+
['nu', 'latn'],
|
|
142
|
+
],
|
|
143
|
+
type: 'u',
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
lang: {lang: 'de', region: 'DE', script: 'Latn', variants: []},
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
it('ja-Jpan-JP-u-ca-japanese-co-search-hc-h24-kf-false-kn-nu-jpanfin', function () {
|
|
150
|
+
expect(
|
|
151
|
+
parseUnicodeLocaleId(
|
|
152
|
+
'ja-Jpan-JP-u-ca-japanese-co-search-hc-h24-kf-false-kn-nu-jpanfin'
|
|
153
|
+
)
|
|
154
|
+
).toEqual({
|
|
155
|
+
extensions: [
|
|
156
|
+
{
|
|
157
|
+
attributes: [],
|
|
158
|
+
keywords: [
|
|
159
|
+
['ca', 'japanese'],
|
|
160
|
+
['co', 'search'],
|
|
161
|
+
['hc', 'h24'],
|
|
162
|
+
['kf', 'false'],
|
|
163
|
+
['kn', ''],
|
|
164
|
+
['nu', 'jpanfin'],
|
|
165
|
+
],
|
|
166
|
+
type: 'u',
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
lang: {lang: 'ja', region: 'JP', script: 'Jpan', variants: []},
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
it('fr-Latn-CA-u-ca-gregory-co-standard-hc-h11-kf-kn-false-nu-latn', function () {
|
|
173
|
+
expect(
|
|
174
|
+
parseUnicodeLocaleId(
|
|
175
|
+
'fr-Latn-CA-u-ca-gregory-co-standard-hc-h11-kf-kn-false-nu-latn'
|
|
176
|
+
)
|
|
177
|
+
).toEqual({
|
|
178
|
+
extensions: [
|
|
179
|
+
{
|
|
180
|
+
attributes: [],
|
|
181
|
+
keywords: [
|
|
182
|
+
['ca', 'gregory'],
|
|
183
|
+
['co', 'standard'],
|
|
184
|
+
['hc', 'h11'],
|
|
185
|
+
['kf', ''],
|
|
186
|
+
['kn', 'false'],
|
|
187
|
+
['nu', 'latn'],
|
|
188
|
+
],
|
|
189
|
+
type: 'u',
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
lang: {lang: 'fr', region: 'CA', script: 'Latn', variants: []},
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
it('en-a-bar-x-u-foo', function () {
|
|
196
|
+
expect(parseUnicodeLocaleId('en-a-bar-x-u-foo')).toEqual({
|
|
197
|
+
extensions: [
|
|
198
|
+
{type: 'a', value: 'bar'},
|
|
199
|
+
{type: 'x', value: 'u-foo'},
|
|
200
|
+
],
|
|
201
|
+
lang: {lang: 'en', region: undefined, script: undefined, variants: []},
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
})
|
package/tsconfig.json
ADDED
package/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare function getCanonicalLocales(locales?: string[] | string): string[];
|
|
2
|
-
export { parseUnicodeLocaleId, parseUnicodeLanguageId, isStructurallyValidLanguageTag, isUnicodeRegionSubtag, isUnicodeScriptSubtag, isUnicodeLanguageSubtag, } from './src/parser';
|
|
3
|
-
export * from './src/types';
|
|
4
|
-
export * from './src/emitter';
|
|
5
|
-
export * from './src/likelySubtags.generated';
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/intl-getcanonicallocales/index.ts"],"names":[],"mappings":"AA2BA,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAEzE;AAED,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,8BAA8B,EAC9B,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,cAAc,CAAA;AACrB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAE7B,cAAc,+BAA+B,CAAA"}
|
package/index.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isUnicodeLanguageSubtag = exports.isUnicodeScriptSubtag = exports.isUnicodeRegionSubtag = exports.isStructurallyValidLanguageTag = exports.parseUnicodeLanguageId = exports.parseUnicodeLocaleId = exports.getCanonicalLocales = void 0;
|
|
4
|
-
var tslib_1 = require("tslib");
|
|
5
|
-
var parser_1 = require("./src/parser");
|
|
6
|
-
var emitter_1 = require("./src/emitter");
|
|
7
|
-
var canonicalizer_1 = require("./src/canonicalizer");
|
|
8
|
-
/**
|
|
9
|
-
* https://tc39.es/ecma402/#sec-canonicalizelocalelist
|
|
10
|
-
* @param locales
|
|
11
|
-
*/
|
|
12
|
-
function CanonicalizeLocaleList(locales) {
|
|
13
|
-
if (locales === undefined) {
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
var seen = [];
|
|
17
|
-
if (typeof locales === 'string') {
|
|
18
|
-
locales = [locales];
|
|
19
|
-
}
|
|
20
|
-
for (var _i = 0, locales_1 = locales; _i < locales_1.length; _i++) {
|
|
21
|
-
var locale = locales_1[_i];
|
|
22
|
-
var canonicalizedTag = (0, emitter_1.emitUnicodeLocaleId)((0, canonicalizer_1.canonicalizeUnicodeLocaleId)((0, parser_1.parseUnicodeLocaleId)(locale)));
|
|
23
|
-
if (seen.indexOf(canonicalizedTag) < 0) {
|
|
24
|
-
seen.push(canonicalizedTag);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return seen;
|
|
28
|
-
}
|
|
29
|
-
function getCanonicalLocales(locales) {
|
|
30
|
-
return CanonicalizeLocaleList(locales);
|
|
31
|
-
}
|
|
32
|
-
exports.getCanonicalLocales = getCanonicalLocales;
|
|
33
|
-
var parser_2 = require("./src/parser");
|
|
34
|
-
Object.defineProperty(exports, "parseUnicodeLocaleId", { enumerable: true, get: function () { return parser_2.parseUnicodeLocaleId; } });
|
|
35
|
-
Object.defineProperty(exports, "parseUnicodeLanguageId", { enumerable: true, get: function () { return parser_2.parseUnicodeLanguageId; } });
|
|
36
|
-
Object.defineProperty(exports, "isStructurallyValidLanguageTag", { enumerable: true, get: function () { return parser_2.isStructurallyValidLanguageTag; } });
|
|
37
|
-
Object.defineProperty(exports, "isUnicodeRegionSubtag", { enumerable: true, get: function () { return parser_2.isUnicodeRegionSubtag; } });
|
|
38
|
-
Object.defineProperty(exports, "isUnicodeScriptSubtag", { enumerable: true, get: function () { return parser_2.isUnicodeScriptSubtag; } });
|
|
39
|
-
Object.defineProperty(exports, "isUnicodeLanguageSubtag", { enumerable: true, get: function () { return parser_2.isUnicodeLanguageSubtag; } });
|
|
40
|
-
(0, tslib_1.__exportStar)(require("./src/types"), exports);
|
|
41
|
-
(0, tslib_1.__exportStar)(require("./src/emitter"), exports);
|
|
42
|
-
(0, tslib_1.__exportStar)(require("./src/likelySubtags.generated"), exports);
|
package/lib/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare function getCanonicalLocales(locales?: string[] | string): string[];
|
|
2
|
-
export { parseUnicodeLocaleId, parseUnicodeLanguageId, isStructurallyValidLanguageTag, isUnicodeRegionSubtag, isUnicodeScriptSubtag, isUnicodeLanguageSubtag, } from './src/parser';
|
|
3
|
-
export * from './src/types';
|
|
4
|
-
export * from './src/emitter';
|
|
5
|
-
export * from './src/likelySubtags.generated';
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/intl-getcanonicallocales/index.ts"],"names":[],"mappings":"AA2BA,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAEzE;AAED,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,8BAA8B,EAC9B,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,cAAc,CAAA;AACrB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAE7B,cAAc,+BAA+B,CAAA"}
|
package/lib/index.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { parseUnicodeLocaleId } from './src/parser';
|
|
2
|
-
import { emitUnicodeLocaleId } from './src/emitter';
|
|
3
|
-
import { canonicalizeUnicodeLocaleId } from './src/canonicalizer';
|
|
4
|
-
/**
|
|
5
|
-
* https://tc39.es/ecma402/#sec-canonicalizelocalelist
|
|
6
|
-
* @param locales
|
|
7
|
-
*/
|
|
8
|
-
function CanonicalizeLocaleList(locales) {
|
|
9
|
-
if (locales === undefined) {
|
|
10
|
-
return [];
|
|
11
|
-
}
|
|
12
|
-
var seen = [];
|
|
13
|
-
if (typeof locales === 'string') {
|
|
14
|
-
locales = [locales];
|
|
15
|
-
}
|
|
16
|
-
for (var _i = 0, locales_1 = locales; _i < locales_1.length; _i++) {
|
|
17
|
-
var locale = locales_1[_i];
|
|
18
|
-
var canonicalizedTag = emitUnicodeLocaleId(canonicalizeUnicodeLocaleId(parseUnicodeLocaleId(locale)));
|
|
19
|
-
if (seen.indexOf(canonicalizedTag) < 0) {
|
|
20
|
-
seen.push(canonicalizedTag);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return seen;
|
|
24
|
-
}
|
|
25
|
-
export function getCanonicalLocales(locales) {
|
|
26
|
-
return CanonicalizeLocaleList(locales);
|
|
27
|
-
}
|
|
28
|
-
export { parseUnicodeLocaleId, parseUnicodeLanguageId, isStructurallyValidLanguageTag, isUnicodeRegionSubtag, isUnicodeScriptSubtag, isUnicodeLanguageSubtag, } from './src/parser';
|
|
29
|
-
export * from './src/types';
|
|
30
|
-
export * from './src/emitter';
|
|
31
|
-
export * from './src/likelySubtags.generated';
|
package/lib/polyfill.d.ts
DELETED
package/lib/polyfill.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"polyfill.d.ts","sourceRoot":"","sources":["../../../../../../packages/intl-getcanonicallocales/polyfill.ts"],"names":[],"mappings":""}
|
package/lib/polyfill.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { getCanonicalLocales } from './';
|
|
2
|
-
import { shouldPolyfill } from './should-polyfill';
|
|
3
|
-
if (typeof Intl === 'undefined') {
|
|
4
|
-
if (typeof window !== 'undefined') {
|
|
5
|
-
Object.defineProperty(window, 'Intl', {
|
|
6
|
-
value: {},
|
|
7
|
-
});
|
|
8
|
-
// @ts-ignore we don't include @types/node so global isn't a thing
|
|
9
|
-
}
|
|
10
|
-
else if (typeof global !== 'undefined') {
|
|
11
|
-
// @ts-ignore we don't include @types/node so global isn't a thing
|
|
12
|
-
Object.defineProperty(global, 'Intl', {
|
|
13
|
-
value: {},
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
if (shouldPolyfill()) {
|
|
18
|
-
Object.defineProperty(Intl, 'getCanonicalLocales', {
|
|
19
|
-
value: getCanonicalLocales,
|
|
20
|
-
writable: true,
|
|
21
|
-
enumerable: false,
|
|
22
|
-
configurable: true,
|
|
23
|
-
});
|
|
24
|
-
}
|
package/lib/should-polyfill.d.ts
DELETED