@formatjs/intl-localematcher 0.2.25 → 0.2.29
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 +73 -0
- package/CHANGELOG.md +150 -0
- package/LICENSE.md +0 -0
- package/README.md +0 -0
- package/abstract/BestAvailableLocale.ts +24 -0
- package/abstract/BestFitMatcher.ts +80 -0
- package/abstract/CanonicalizeLocaleList.ts +8 -0
- package/abstract/LookupMatcher.ts +39 -0
- package/abstract/LookupSupportedLocales.ts +28 -0
- package/abstract/ResolveLocale.ts +100 -0
- package/abstract/UnicodeExtensionValue.ts +44 -0
- package/abstract/types.ts +5 -0
- package/abstract/utils.ts +11 -0
- package/index.ts +32 -0
- package/package.json +3 -3
- package/tests/BestFitMatcher.test.ts +23 -0
- package/tests/LookupMatcher.test.ts +17 -0
- package/tests/ResolveLocale.test.ts +47 -0
- package/tests/index.test.ts +242 -0
- package/tsconfig.json +5 -0
- package/abstract/BestAvailableLocale.d.ts +0 -7
- package/abstract/BestAvailableLocale.d.ts.map +0 -1
- package/abstract/BestAvailableLocale.js +0 -25
- package/abstract/BestFitMatcher.d.ts +0 -9
- package/abstract/BestFitMatcher.d.ts.map +0 -1
- package/abstract/BestFitMatcher.js +0 -65
- package/abstract/CanonicalizeLocaleList.d.ts +0 -6
- package/abstract/CanonicalizeLocaleList.d.ts.map +0 -1
- package/abstract/CanonicalizeLocaleList.js +0 -12
- package/abstract/LookupMatcher.d.ts +0 -9
- package/abstract/LookupMatcher.d.ts.map +0 -1
- package/abstract/LookupMatcher.js +0 -29
- package/abstract/LookupSupportedLocales.d.ts +0 -7
- package/abstract/LookupSupportedLocales.d.ts.map +0 -1
- package/abstract/LookupSupportedLocales.js +0 -23
- package/abstract/ResolveLocale.d.ts +0 -15
- package/abstract/ResolveLocale.d.ts.map +0 -1
- package/abstract/ResolveLocale.js +0 -78
- package/abstract/UnicodeExtensionValue.d.ts +0 -7
- package/abstract/UnicodeExtensionValue.d.ts.map +0 -1
- package/abstract/UnicodeExtensionValue.js +0 -50
- package/abstract/types.d.ts +0 -6
- package/abstract/types.d.ts.map +0 -1
- package/abstract/types.js +0 -2
- package/abstract/utils.d.ts +0 -3
- package/abstract/utils.d.ts.map +0 -1
- package/abstract/utils.js +0 -11
- package/index.d.ts +0 -7
- package/index.d.ts.map +0 -1
- package/index.js +0 -19
- package/lib/abstract/BestAvailableLocale.d.ts +0 -7
- package/lib/abstract/BestAvailableLocale.d.ts.map +0 -1
- package/lib/abstract/BestAvailableLocale.js +0 -21
- package/lib/abstract/BestFitMatcher.d.ts +0 -9
- package/lib/abstract/BestFitMatcher.d.ts.map +0 -1
- package/lib/abstract/BestFitMatcher.js +0 -61
- package/lib/abstract/CanonicalizeLocaleList.d.ts +0 -6
- package/lib/abstract/CanonicalizeLocaleList.d.ts.map +0 -1
- package/lib/abstract/CanonicalizeLocaleList.js +0 -8
- package/lib/abstract/LookupMatcher.d.ts +0 -9
- package/lib/abstract/LookupMatcher.d.ts.map +0 -1
- package/lib/abstract/LookupMatcher.js +0 -25
- package/lib/abstract/LookupSupportedLocales.d.ts +0 -7
- package/lib/abstract/LookupSupportedLocales.d.ts.map +0 -1
- package/lib/abstract/LookupSupportedLocales.js +0 -19
- package/lib/abstract/ResolveLocale.d.ts +0 -15
- package/lib/abstract/ResolveLocale.d.ts.map +0 -1
- package/lib/abstract/ResolveLocale.js +0 -74
- package/lib/abstract/UnicodeExtensionValue.d.ts +0 -7
- package/lib/abstract/UnicodeExtensionValue.d.ts.map +0 -1
- package/lib/abstract/UnicodeExtensionValue.js +0 -46
- package/lib/abstract/types.d.ts +0 -6
- package/lib/abstract/types.d.ts.map +0 -1
- package/lib/abstract/types.js +0 -1
- package/lib/abstract/utils.d.ts +0 -3
- package/lib/abstract/utils.d.ts.map +0 -1
- package/lib/abstract/utils.js +0 -7
- package/lib/index.d.ts +0 -7
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -13
package/BUILD
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
|
|
2
|
+
load("@aspect_rules_js//npm/private:npm_package.bzl", "npm_package")
|
|
3
|
+
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
|
|
4
|
+
load("//tools:index.bzl", "check_format", "package_json_test", "ts_compile")
|
|
5
|
+
load("//tools:jest.bzl", "jest_test")
|
|
6
|
+
|
|
7
|
+
PACKAGE_NAME = "intl-localematcher"
|
|
8
|
+
|
|
9
|
+
npm_package(
|
|
10
|
+
name = PACKAGE_NAME,
|
|
11
|
+
srcs = [
|
|
12
|
+
"LICENSE.md",
|
|
13
|
+
"README.md",
|
|
14
|
+
"package.json",
|
|
15
|
+
":dist",
|
|
16
|
+
],
|
|
17
|
+
package = "@formatjs/%s" % PACKAGE_NAME,
|
|
18
|
+
visibility = ["//visibility:public"],
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
SRCS = glob(
|
|
22
|
+
["**/*.ts"],
|
|
23
|
+
exclude = ["tests/*"],
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
ts_compile(
|
|
27
|
+
name = "dist",
|
|
28
|
+
srcs = SRCS,
|
|
29
|
+
package = "@formatjs/%s" % PACKAGE_NAME,
|
|
30
|
+
skip_esm = False,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
jest_test(
|
|
34
|
+
name = "unit",
|
|
35
|
+
srcs = SRCS + glob([
|
|
36
|
+
"tests/**/*.ts",
|
|
37
|
+
"tests/**/*.tsx",
|
|
38
|
+
"tests/**/*.snap",
|
|
39
|
+
]),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Test262
|
|
43
|
+
ts_project(
|
|
44
|
+
name = "test262-main-bundle",
|
|
45
|
+
srcs = SRCS,
|
|
46
|
+
declaration = True,
|
|
47
|
+
declaration_map = True,
|
|
48
|
+
extends = "//:tsconfig",
|
|
49
|
+
out_dir = "test262",
|
|
50
|
+
resolve_json_module = True,
|
|
51
|
+
tsconfig = "//:tsconfig.es6",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
write_source_files(
|
|
55
|
+
name = "tsconfig_json",
|
|
56
|
+
files = {"tsconfig.json": "//tools:tsconfig.golden.json"},
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
check_format(
|
|
60
|
+
name = "prettier",
|
|
61
|
+
srcs = glob(
|
|
62
|
+
[
|
|
63
|
+
"**/*",
|
|
64
|
+
],
|
|
65
|
+
exclude = [
|
|
66
|
+
"CHANGELOG.md",
|
|
67
|
+
],
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
package_json_test(
|
|
72
|
+
name = "package_json_test",
|
|
73
|
+
)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [0.2.29](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.28...@formatjs/intl-localematcher@0.2.29) (2022-08-18)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
9
|
+
|
|
10
|
+
## [0.2.28](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.27...@formatjs/intl-localematcher@0.2.28) (2022-06-06)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
13
|
+
|
|
14
|
+
## [0.2.27](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.26...@formatjs/intl-localematcher@0.2.27) (2022-05-19)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
17
|
+
|
|
18
|
+
## [0.2.26](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.25...@formatjs/intl-localematcher@0.2.26) (2022-05-19)
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **react-intl:** fix type issue with react18, fix [#3550](https://github.com/formatjs/formatjs/issues/3550) ([2567b93](https://github.com/formatjs/formatjs/commit/2567b932c5d18b097a43842563046c20ce0c49f1))
|
|
23
|
+
|
|
24
|
+
## [0.2.25](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.24...@formatjs/intl-localematcher@0.2.25) (2022-03-26)
|
|
25
|
+
|
|
26
|
+
### Bug Fixes
|
|
27
|
+
|
|
28
|
+
* **@formatjs/intl-localematcher:** adds module field to package.json, fixes [#3456](https://github.com/formatjs/formatjs/issues/3456) ([#3457](https://github.com/formatjs/formatjs/issues/3457)) ([e805d9e](https://github.com/formatjs/formatjs/commit/e805d9e29bae0298a081f760e90c8c5d2dd1aa7c))
|
|
29
|
+
|
|
30
|
+
## [0.2.24](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.23...@formatjs/intl-localematcher@0.2.24) (2022-02-06)
|
|
31
|
+
|
|
32
|
+
### Bug Fixes
|
|
33
|
+
|
|
34
|
+
* **@formatjs/intl-localematcher:** prioritize locale in front of canonicalized/minimized locale, fix [#3405](https://github.com/formatjs/formatjs/issues/3405) ([81fa22a](https://github.com/formatjs/formatjs/commit/81fa22a87d42362f4d4d8406429f3161a977cd42))
|
|
35
|
+
|
|
36
|
+
## [0.2.23](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.22...@formatjs/intl-localematcher@0.2.23) (2022-01-24)
|
|
37
|
+
|
|
38
|
+
### Bug Fixes
|
|
39
|
+
|
|
40
|
+
* **@formatjs/intl-localematcher:** fix best fit to account for canonicalization ([cacad92](https://github.com/formatjs/formatjs/commit/cacad921ed4eb2f608979fe03b8cdcd3d1719766))
|
|
41
|
+
|
|
42
|
+
## [0.2.22](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.21...@formatjs/intl-localematcher@0.2.22) (2022-01-03)
|
|
43
|
+
|
|
44
|
+
### Bug Fixes
|
|
45
|
+
|
|
46
|
+
* **@formatjs/intl-localematcher:** iterate through set instead of Array.from so we dont rely on polyfill ([2114518](https://github.com/formatjs/formatjs/commit/211451805d09aae543a8a0aeae1b62a179aaae07))
|
|
47
|
+
|
|
48
|
+
## [0.2.21](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.20...@formatjs/intl-localematcher@0.2.21) (2021-09-27)
|
|
49
|
+
|
|
50
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
51
|
+
|
|
52
|
+
## [0.2.20](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.19...@formatjs/intl-localematcher@0.2.20) (2021-08-15)
|
|
53
|
+
|
|
54
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
55
|
+
|
|
56
|
+
## [0.2.19](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.18...@formatjs/intl-localematcher@0.2.19) (2021-08-06)
|
|
57
|
+
|
|
58
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
59
|
+
|
|
60
|
+
## [0.2.18](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.17...@formatjs/intl-localematcher@0.2.18) (2021-07-24)
|
|
61
|
+
|
|
62
|
+
### Bug Fixes
|
|
63
|
+
|
|
64
|
+
* **@formatjs/intl-localematcher:** fix best fit algo, fix [#3058](https://github.com/formatjs/formatjs/issues/3058) ([c9dad00](https://github.com/formatjs/formatjs/commit/c9dad0081ba57792b3cdcf6bc1a02c5dc3f57dc1))
|
|
65
|
+
* **@formatjs/intl-localematcher:** refactor and consolidate files ([1d1a4bc](https://github.com/formatjs/formatjs/commit/1d1a4bc6e5ccbf7be774d4f0f4b2ef2c7fa334b5))
|
|
66
|
+
|
|
67
|
+
## [0.2.17](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.16...@formatjs/intl-localematcher@0.2.17) (2021-07-20)
|
|
68
|
+
|
|
69
|
+
### Bug Fixes
|
|
70
|
+
|
|
71
|
+
* **@formatjs/intl-localematcher:** Correct path to main file for @formatjs/intl-localematcher ([#3057](https://github.com/formatjs/formatjs/issues/3057)) ([e2267bb](https://github.com/formatjs/formatjs/commit/e2267bbc2645d007ccbae8dfa77bc7ad422cfde2))
|
|
72
|
+
|
|
73
|
+
## [0.2.16](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.15...@formatjs/intl-localematcher@0.2.16) (2021-06-26)
|
|
74
|
+
|
|
75
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
76
|
+
|
|
77
|
+
## [0.2.15](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.14...@formatjs/intl-localematcher@0.2.15) (2021-06-05)
|
|
78
|
+
|
|
79
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
80
|
+
|
|
81
|
+
## [0.2.14](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.13...@formatjs/intl-localematcher@0.2.14) (2021-06-01)
|
|
82
|
+
|
|
83
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
84
|
+
|
|
85
|
+
## [0.2.13](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.12...@formatjs/intl-localematcher@0.2.13) (2021-05-23)
|
|
86
|
+
|
|
87
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
88
|
+
|
|
89
|
+
## [0.2.12](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.11...@formatjs/intl-localematcher@0.2.12) (2021-05-20)
|
|
90
|
+
|
|
91
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
92
|
+
|
|
93
|
+
## [0.2.11](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.10...@formatjs/intl-localematcher@0.2.11) (2021-05-17)
|
|
94
|
+
|
|
95
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
96
|
+
|
|
97
|
+
## [0.2.10](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.9...@formatjs/intl-localematcher@0.2.10) (2021-05-10)
|
|
98
|
+
|
|
99
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
100
|
+
|
|
101
|
+
## [0.2.9](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.8...@formatjs/intl-localematcher@0.2.9) (2021-04-26)
|
|
102
|
+
|
|
103
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
104
|
+
|
|
105
|
+
## [0.2.8](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.7...@formatjs/intl-localematcher@0.2.8) (2021-04-12)
|
|
106
|
+
|
|
107
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
108
|
+
|
|
109
|
+
## [0.2.7](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.6...@formatjs/intl-localematcher@0.2.7) (2021-03-26)
|
|
110
|
+
|
|
111
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
112
|
+
|
|
113
|
+
## [0.2.6](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.5...@formatjs/intl-localematcher@0.2.6) (2021-03-15)
|
|
114
|
+
|
|
115
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
116
|
+
|
|
117
|
+
## [0.2.5](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.4...@formatjs/intl-localematcher@0.2.5) (2021-03-01)
|
|
118
|
+
|
|
119
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
120
|
+
|
|
121
|
+
## [0.2.4](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.3...@formatjs/intl-localematcher@0.2.4) (2021-02-25)
|
|
122
|
+
|
|
123
|
+
### Bug Fixes
|
|
124
|
+
|
|
125
|
+
* bump tslib version dep ([37577d2](https://github.com/formatjs/formatjs/commit/37577d22bf28d23de1d8013ba0047cf221ad8840)), closes [#2645](https://github.com/formatjs/formatjs/issues/2645)
|
|
126
|
+
|
|
127
|
+
## [0.2.3](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.2...@formatjs/intl-localematcher@0.2.3) (2021-02-25)
|
|
128
|
+
|
|
129
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
130
|
+
|
|
131
|
+
## [0.2.2](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.1...@formatjs/intl-localematcher@0.2.2) (2021-02-22)
|
|
132
|
+
|
|
133
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
134
|
+
|
|
135
|
+
## [0.2.1](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.2.0...@formatjs/intl-localematcher@0.2.1) (2021-02-21)
|
|
136
|
+
|
|
137
|
+
**Note:** Version bump only for package @formatjs/intl-localematcher
|
|
138
|
+
|
|
139
|
+
# [0.2.0](https://github.com/formatjs/formatjs/compare/@formatjs/intl-localematcher@0.1.0...@formatjs/intl-localematcher@0.2.0) (2021-02-08)
|
|
140
|
+
|
|
141
|
+
### Features
|
|
142
|
+
|
|
143
|
+
* **@formatjs/intl-localematcher:** switch entry point to prepackaged UMD file ([a0481cc](https://github.com/formatjs/formatjs/commit/a0481cc79e95960b540cafc541d555a5c228851f))
|
|
144
|
+
|
|
145
|
+
# 0.1.0 (2021-02-08)
|
|
146
|
+
|
|
147
|
+
### Features
|
|
148
|
+
|
|
149
|
+
* **@formatjs/intl-localematcher:** add ponyfill for Intl.LocaleMatcher ([e479543](https://github.com/formatjs/formatjs/commit/e479543e92e9b6c6d08f68848f25bcb9ba558ab3))
|
|
150
|
+
* **@formatjs/intl-localematcher:** reset version ([7684b54](https://github.com/formatjs/formatjs/commit/7684b543fa7c3db3aad839bae8485ec7de4ee495))
|
package/LICENSE.md
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#sec-bestavailablelocale
|
|
3
|
+
* @param availableLocales
|
|
4
|
+
* @param locale
|
|
5
|
+
*/
|
|
6
|
+
export function BestAvailableLocale(
|
|
7
|
+
availableLocales: Set<String>,
|
|
8
|
+
locale: string
|
|
9
|
+
) {
|
|
10
|
+
let candidate = locale
|
|
11
|
+
while (true) {
|
|
12
|
+
if (availableLocales.has(candidate)) {
|
|
13
|
+
return candidate
|
|
14
|
+
}
|
|
15
|
+
let pos = candidate.lastIndexOf('-')
|
|
16
|
+
if (!~pos) {
|
|
17
|
+
return undefined
|
|
18
|
+
}
|
|
19
|
+
if (pos >= 2 && candidate[pos - 2] === '-') {
|
|
20
|
+
pos -= 2
|
|
21
|
+
}
|
|
22
|
+
candidate = candidate.slice(0, pos)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {BestAvailableLocale} from './BestAvailableLocale'
|
|
2
|
+
import {LookupMatcherResult} from './types'
|
|
3
|
+
import {UNICODE_EXTENSION_SEQUENCE_REGEX} from './utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* https://tc39.es/ecma402/#sec-bestfitmatcher
|
|
7
|
+
* @param availableLocales
|
|
8
|
+
* @param requestedLocales
|
|
9
|
+
* @param getDefaultLocale
|
|
10
|
+
*/
|
|
11
|
+
export function BestFitMatcher(
|
|
12
|
+
availableLocales: Set<string>,
|
|
13
|
+
requestedLocales: string[],
|
|
14
|
+
getDefaultLocale: () => string
|
|
15
|
+
): LookupMatcherResult {
|
|
16
|
+
const minimizedAvailableLocaleMap: Record<string, string> = {}
|
|
17
|
+
const availableLocaleMap: Record<string, string> = {}
|
|
18
|
+
const canonicalizedLocaleMap: Record<string, string> = {}
|
|
19
|
+
const minimizedAvailableLocales: Set<string> = new Set()
|
|
20
|
+
availableLocales.forEach(locale => {
|
|
21
|
+
const minimizedLocale = new (Intl as any).Locale(locale)
|
|
22
|
+
.minimize()
|
|
23
|
+
.toString()
|
|
24
|
+
|
|
25
|
+
const canonicalizedLocale =
|
|
26
|
+
(Intl as any).getCanonicalLocales(locale)[0] || locale
|
|
27
|
+
|
|
28
|
+
minimizedAvailableLocaleMap[minimizedLocale] = locale
|
|
29
|
+
availableLocaleMap[locale] = locale
|
|
30
|
+
canonicalizedLocaleMap[canonicalizedLocale] = locale
|
|
31
|
+
minimizedAvailableLocales.add(minimizedLocale)
|
|
32
|
+
minimizedAvailableLocales.add(locale)
|
|
33
|
+
minimizedAvailableLocales.add(canonicalizedLocale)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
let foundLocale: string | undefined
|
|
37
|
+
for (const l of requestedLocales) {
|
|
38
|
+
if (foundLocale) {
|
|
39
|
+
break
|
|
40
|
+
}
|
|
41
|
+
const noExtensionLocale = l.replace(UNICODE_EXTENSION_SEQUENCE_REGEX, '')
|
|
42
|
+
|
|
43
|
+
if (availableLocales.has(noExtensionLocale)) {
|
|
44
|
+
foundLocale = noExtensionLocale
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (minimizedAvailableLocales.has(noExtensionLocale)) {
|
|
49
|
+
foundLocale = noExtensionLocale
|
|
50
|
+
break
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const locale = new (Intl as any).Locale(noExtensionLocale)
|
|
54
|
+
|
|
55
|
+
const maximizedRequestedLocale = locale.maximize().toString()
|
|
56
|
+
const minimizedRequestedLocale = locale.minimize().toString()
|
|
57
|
+
|
|
58
|
+
// Check minimized locale
|
|
59
|
+
if (minimizedAvailableLocales.has(minimizedRequestedLocale)) {
|
|
60
|
+
foundLocale = minimizedRequestedLocale
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Lookup algo on maximized locale
|
|
65
|
+
foundLocale = BestAvailableLocale(
|
|
66
|
+
minimizedAvailableLocales,
|
|
67
|
+
maximizedRequestedLocale
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
if (!foundLocale) {
|
|
71
|
+
return {locale: getDefaultLocale()}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
locale:
|
|
75
|
+
availableLocaleMap[foundLocale] ||
|
|
76
|
+
canonicalizedLocaleMap[foundLocale] ||
|
|
77
|
+
minimizedAvailableLocaleMap[foundLocale] ||
|
|
78
|
+
foundLocale,
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist
|
|
3
|
+
* @param locales
|
|
4
|
+
*/
|
|
5
|
+
export function CanonicalizeLocaleList(locales?: string | string[]): string[] {
|
|
6
|
+
// TODO
|
|
7
|
+
return ((Intl as any).getCanonicalLocales as any)(locales)
|
|
8
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {UNICODE_EXTENSION_SEQUENCE_REGEX} from './utils'
|
|
2
|
+
import {BestAvailableLocale} from './BestAvailableLocale'
|
|
3
|
+
import {LookupMatcherResult} from './types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* https://tc39.es/ecma402/#sec-lookupmatcher
|
|
7
|
+
* @param availableLocales
|
|
8
|
+
* @param requestedLocales
|
|
9
|
+
* @param getDefaultLocale
|
|
10
|
+
*/
|
|
11
|
+
export function LookupMatcher(
|
|
12
|
+
availableLocales: Set<string>,
|
|
13
|
+
requestedLocales: string[],
|
|
14
|
+
getDefaultLocale: () => string
|
|
15
|
+
): LookupMatcherResult {
|
|
16
|
+
const result: LookupMatcherResult = {locale: ''}
|
|
17
|
+
for (const locale of requestedLocales) {
|
|
18
|
+
const noExtensionLocale = locale.replace(
|
|
19
|
+
UNICODE_EXTENSION_SEQUENCE_REGEX,
|
|
20
|
+
''
|
|
21
|
+
)
|
|
22
|
+
const availableLocale = BestAvailableLocale(
|
|
23
|
+
availableLocales,
|
|
24
|
+
noExtensionLocale
|
|
25
|
+
)
|
|
26
|
+
if (availableLocale) {
|
|
27
|
+
result.locale = availableLocale
|
|
28
|
+
if (locale !== noExtensionLocale) {
|
|
29
|
+
result.extension = locale.slice(
|
|
30
|
+
noExtensionLocale.length + 1,
|
|
31
|
+
locale.length
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
return result
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
result.locale = getDefaultLocale()
|
|
38
|
+
return result
|
|
39
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {UNICODE_EXTENSION_SEQUENCE_REGEX} from './utils'
|
|
2
|
+
import {BestAvailableLocale} from './BestAvailableLocale'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* https://tc39.es/ecma402/#sec-lookupsupportedlocales
|
|
6
|
+
* @param availableLocales
|
|
7
|
+
* @param requestedLocales
|
|
8
|
+
*/
|
|
9
|
+
export function LookupSupportedLocales(
|
|
10
|
+
availableLocales: Set<string>,
|
|
11
|
+
requestedLocales: string[]
|
|
12
|
+
) {
|
|
13
|
+
const subset: string[] = []
|
|
14
|
+
for (const locale of requestedLocales) {
|
|
15
|
+
const noExtensionLocale = locale.replace(
|
|
16
|
+
UNICODE_EXTENSION_SEQUENCE_REGEX,
|
|
17
|
+
''
|
|
18
|
+
)
|
|
19
|
+
const availableLocale = BestAvailableLocale(
|
|
20
|
+
availableLocales,
|
|
21
|
+
noExtensionLocale
|
|
22
|
+
)
|
|
23
|
+
if (availableLocale) {
|
|
24
|
+
subset.push(availableLocale)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return subset
|
|
28
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {LookupMatcherResult} from './types'
|
|
2
|
+
import {LookupMatcher} from './LookupMatcher'
|
|
3
|
+
import {BestFitMatcher} from './BestFitMatcher'
|
|
4
|
+
import {invariant} from './utils'
|
|
5
|
+
import {UnicodeExtensionValue} from './UnicodeExtensionValue'
|
|
6
|
+
|
|
7
|
+
export interface ResolveLocaleResult {
|
|
8
|
+
locale: string
|
|
9
|
+
dataLocale: string
|
|
10
|
+
[k: string]: any
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* https://tc39.es/ecma402/#sec-resolvelocale
|
|
15
|
+
*/
|
|
16
|
+
export function ResolveLocale<K extends string, D extends {[k in K]: any}>(
|
|
17
|
+
availableLocales: Set<string>,
|
|
18
|
+
requestedLocales: string[],
|
|
19
|
+
options: {localeMatcher: string; [k: string]: string},
|
|
20
|
+
relevantExtensionKeys: K[],
|
|
21
|
+
localeData: Record<string, D | undefined>,
|
|
22
|
+
getDefaultLocale: () => string
|
|
23
|
+
): ResolveLocaleResult {
|
|
24
|
+
const matcher = options.localeMatcher
|
|
25
|
+
let r: LookupMatcherResult
|
|
26
|
+
if (matcher === 'lookup') {
|
|
27
|
+
r = LookupMatcher(availableLocales, requestedLocales, getDefaultLocale)
|
|
28
|
+
} else {
|
|
29
|
+
r = BestFitMatcher(availableLocales, requestedLocales, getDefaultLocale)
|
|
30
|
+
}
|
|
31
|
+
let foundLocale = r.locale
|
|
32
|
+
const result: ResolveLocaleResult = {locale: '', dataLocale: foundLocale}
|
|
33
|
+
let supportedExtension = '-u'
|
|
34
|
+
for (const key of relevantExtensionKeys) {
|
|
35
|
+
invariant(
|
|
36
|
+
foundLocale in localeData,
|
|
37
|
+
`Missing locale data for ${foundLocale}`
|
|
38
|
+
)
|
|
39
|
+
const foundLocaleData = localeData[foundLocale]
|
|
40
|
+
invariant(
|
|
41
|
+
typeof foundLocaleData === 'object' && foundLocaleData !== null,
|
|
42
|
+
`locale data ${key} must be an object`
|
|
43
|
+
)
|
|
44
|
+
const keyLocaleData = foundLocaleData[key]
|
|
45
|
+
invariant(
|
|
46
|
+
Array.isArray(keyLocaleData),
|
|
47
|
+
`keyLocaleData for ${key} must be an array`
|
|
48
|
+
)
|
|
49
|
+
let value = keyLocaleData[0]
|
|
50
|
+
invariant(
|
|
51
|
+
typeof value === 'string' || value === null,
|
|
52
|
+
`value must be string or null but got ${typeof value} in key ${key}`
|
|
53
|
+
)
|
|
54
|
+
let supportedExtensionAddition = ''
|
|
55
|
+
if (r.extension) {
|
|
56
|
+
const requestedValue = UnicodeExtensionValue(r.extension, key)
|
|
57
|
+
if (requestedValue !== undefined) {
|
|
58
|
+
if (requestedValue !== '') {
|
|
59
|
+
if (~keyLocaleData.indexOf(requestedValue)) {
|
|
60
|
+
value = requestedValue
|
|
61
|
+
supportedExtensionAddition = `-${key}-${value}`
|
|
62
|
+
}
|
|
63
|
+
} else if (~requestedValue.indexOf('true')) {
|
|
64
|
+
value = 'true'
|
|
65
|
+
supportedExtensionAddition = `-${key}`
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (key in options) {
|
|
70
|
+
const optionsValue = options[key]
|
|
71
|
+
invariant(
|
|
72
|
+
typeof optionsValue === 'string' ||
|
|
73
|
+
typeof optionsValue === 'undefined' ||
|
|
74
|
+
optionsValue === null,
|
|
75
|
+
'optionsValue must be String, Undefined or Null'
|
|
76
|
+
)
|
|
77
|
+
if (~keyLocaleData.indexOf(optionsValue)) {
|
|
78
|
+
if (optionsValue !== value) {
|
|
79
|
+
value = optionsValue
|
|
80
|
+
supportedExtensionAddition = ''
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
result[key] = value
|
|
85
|
+
supportedExtension += supportedExtensionAddition
|
|
86
|
+
}
|
|
87
|
+
if (supportedExtension.length > 2) {
|
|
88
|
+
const privateIndex = foundLocale.indexOf('-x-')
|
|
89
|
+
if (privateIndex === -1) {
|
|
90
|
+
foundLocale = foundLocale + supportedExtension
|
|
91
|
+
} else {
|
|
92
|
+
const preExtension = foundLocale.slice(0, privateIndex)
|
|
93
|
+
const postExtension = foundLocale.slice(privateIndex, foundLocale.length)
|
|
94
|
+
foundLocale = preExtension + supportedExtension + postExtension
|
|
95
|
+
}
|
|
96
|
+
foundLocale = (Intl as any).getCanonicalLocales(foundLocale)[0]
|
|
97
|
+
}
|
|
98
|
+
result.locale = foundLocale
|
|
99
|
+
return result
|
|
100
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {invariant} from './utils'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* https://tc39.es/ecma402/#sec-unicodeextensionvalue
|
|
5
|
+
* @param extension
|
|
6
|
+
* @param key
|
|
7
|
+
*/
|
|
8
|
+
export function UnicodeExtensionValue(extension: string, key: string) {
|
|
9
|
+
invariant(key.length === 2, 'key must have 2 elements')
|
|
10
|
+
const size = extension.length
|
|
11
|
+
let searchValue = `-${key}-`
|
|
12
|
+
let pos = extension.indexOf(searchValue)
|
|
13
|
+
if (pos !== -1) {
|
|
14
|
+
const start = pos + 4
|
|
15
|
+
let end = start
|
|
16
|
+
let k = start
|
|
17
|
+
let done = false
|
|
18
|
+
while (!done) {
|
|
19
|
+
const e = extension.indexOf('-', k)
|
|
20
|
+
let len
|
|
21
|
+
if (e === -1) {
|
|
22
|
+
len = size - k
|
|
23
|
+
} else {
|
|
24
|
+
len = e - k
|
|
25
|
+
}
|
|
26
|
+
if (len === 2) {
|
|
27
|
+
done = true
|
|
28
|
+
} else if (e === -1) {
|
|
29
|
+
end = size
|
|
30
|
+
done = true
|
|
31
|
+
} else {
|
|
32
|
+
end = e
|
|
33
|
+
k = e + 1
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return extension.slice(start, end)
|
|
37
|
+
}
|
|
38
|
+
searchValue = `-${key}`
|
|
39
|
+
pos = extension.indexOf(searchValue)
|
|
40
|
+
if (pos !== -1 && pos + 3 === size) {
|
|
41
|
+
return ''
|
|
42
|
+
}
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {CanonicalizeLocaleList} from './abstract/CanonicalizeLocaleList'
|
|
2
|
+
import {ResolveLocale} from './abstract/ResolveLocale'
|
|
3
|
+
|
|
4
|
+
export interface Opts {
|
|
5
|
+
algorithm: 'lookup' | 'best fit'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function match(
|
|
9
|
+
requestedLocales: string[],
|
|
10
|
+
availableLocales: string[],
|
|
11
|
+
defaultLocale: string,
|
|
12
|
+
opts?: Opts
|
|
13
|
+
): string {
|
|
14
|
+
const locales = availableLocales.reduce((all, l) => {
|
|
15
|
+
all.add(l)
|
|
16
|
+
return all
|
|
17
|
+
}, new Set<string>())
|
|
18
|
+
|
|
19
|
+
return ResolveLocale(
|
|
20
|
+
locales,
|
|
21
|
+
CanonicalizeLocaleList(requestedLocales),
|
|
22
|
+
{
|
|
23
|
+
localeMatcher: opts?.algorithm || 'best fit',
|
|
24
|
+
},
|
|
25
|
+
[],
|
|
26
|
+
{},
|
|
27
|
+
() => defaultLocale
|
|
28
|
+
).locale
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {LookupSupportedLocales} from './abstract/LookupSupportedLocales'
|
|
32
|
+
export {ResolveLocale} from './abstract/ResolveLocale'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formatjs/intl-localematcher",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.29",
|
|
4
4
|
"description": "Intl.LocaleMatcher ponyfill",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"intl",
|
|
@@ -25,6 +25,6 @@
|
|
|
25
25
|
"url": "https://github.com/formatjs/formatjs/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"tslib": "
|
|
28
|
+
"tslib": "2.4.0"
|
|
29
29
|
}
|
|
30
|
-
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {BestFitMatcher} from '../abstract/BestFitMatcher'
|
|
2
|
+
|
|
3
|
+
test('BestFitMatcher', function () {
|
|
4
|
+
expect(
|
|
5
|
+
BestFitMatcher(new Set(['fr', 'en']), ['fr-XX', 'en'], () => 'en')
|
|
6
|
+
).toEqual({
|
|
7
|
+
locale: 'fr',
|
|
8
|
+
})
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('BestFitMatcher zh-TW', function () {
|
|
12
|
+
expect(
|
|
13
|
+
BestFitMatcher(new Set(['zh', 'zh-Hant']), ['zh-TW'], () => 'en')
|
|
14
|
+
).toEqual({
|
|
15
|
+
locale: 'zh-Hant',
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('BestFitMatcher en', function () {
|
|
20
|
+
expect(BestFitMatcher(new Set(['en', 'und']), ['en'], () => 'en')).toEqual({
|
|
21
|
+
locale: 'en',
|
|
22
|
+
})
|
|
23
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {LookupMatcher} from '../abstract/LookupMatcher'
|
|
2
|
+
|
|
3
|
+
test('LookupMatcher', function () {
|
|
4
|
+
expect(
|
|
5
|
+
LookupMatcher(new Set(['fr', 'en']), ['fr-XX', 'en'], () => 'en')
|
|
6
|
+
).toEqual({
|
|
7
|
+
locale: 'fr',
|
|
8
|
+
})
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('LookupMatcher', function () {
|
|
12
|
+
expect(
|
|
13
|
+
LookupMatcher(new Set(['zh', 'zh-Hant']), ['zh-Hans'], () => 'en')
|
|
14
|
+
).toEqual({
|
|
15
|
+
locale: 'zh',
|
|
16
|
+
})
|
|
17
|
+
})
|