@formatjs/intl-localematcher 0.7.2 → 0.7.4
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/README.md +38 -0
- package/abstract/BestAvailableLocale.js +9 -1
- package/abstract/regions.generated.js +1170 -1311
- package/abstract/utils.d.ts +37 -1
- package/abstract/utils.js +221 -7
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
1
|
# Intl LocaleMatcher
|
|
2
2
|
|
|
3
3
|
We've migrated the docs to https://formatjs.github.io/docs/polyfills/intl-localematcher.
|
|
4
|
+
|
|
5
|
+
## Performance
|
|
6
|
+
|
|
7
|
+
This package implements a highly optimized three-tier locale matching algorithm that provides excellent performance even with large locale sets (700+ locales).
|
|
8
|
+
|
|
9
|
+
### Benchmark Results
|
|
10
|
+
|
|
11
|
+
Benchmarked with 725 CLDR locales on Node.js:
|
|
12
|
+
|
|
13
|
+
| Scenario | Latency | Throughput | Relative Performance |
|
|
14
|
+
| ------------------------------------------------------- | ------- | ---------- | -------------------- |
|
|
15
|
+
| **Tier 1: Exact Match** (`en`) | 1.38ms | 730 ops/s | Baseline |
|
|
16
|
+
| **Tier 2: 1-level Fallback** (`en-US` → `en`) | 1.39ms | 725 ops/s | 1.01x slower |
|
|
17
|
+
| **Tier 2: Maximized Match** (`zh-TW` → `zh-Hant`) | 1.40ms | 720 ops/s | 1.02x slower |
|
|
18
|
+
| **Tier 3: CLDR Distance** (`sr-Latn-BA` → `sr-Latn-BA`) | 1.38ms | 730 ops/s | 1.00x slower |
|
|
19
|
+
| **Tier 3: Fuzzy Match** (`en-XZ` → `en`) | 1.50ms | 670 ops/s | 1.09x slower |
|
|
20
|
+
|
|
21
|
+
### Real-world Impact
|
|
22
|
+
|
|
23
|
+
The optimization in this package resolved [issue #4936](https://github.com/formatjs/formatjs/issues/4936), where `DurationFormat` instantiation was taking **610ms** on React Native/Hermes due to slow locale matching against 700+ auto-loaded locales.
|
|
24
|
+
|
|
25
|
+
**After optimization:**
|
|
26
|
+
|
|
27
|
+
- Common case (`en-US`): **1.39ms** per instantiation
|
|
28
|
+
- Chinese locales (`zh-TW`): **1.40ms** per instantiation
|
|
29
|
+
- Serbo-Croatian locales: **1.38ms** per instantiation
|
|
30
|
+
|
|
31
|
+
**Performance improvement: 439x faster** 🚀
|
|
32
|
+
|
|
33
|
+
### Three-Tier Optimization
|
|
34
|
+
|
|
35
|
+
The algorithm uses three tiers for maximum performance:
|
|
36
|
+
|
|
37
|
+
1. **Tier 1 (Exact Match)**: O(1) Set lookup for exact locale matches
|
|
38
|
+
2. **Tier 2 (Maximization + Fallback)**: Progressive subtag removal with locale maximization
|
|
39
|
+
3. **Tier 3 (CLDR Distance)**: Full UTS #35 Enhanced Language Matching with memoization
|
|
40
|
+
|
|
41
|
+
This design ensures that common cases (exact matches and simple fallbacks) are extremely fast, while complex scenarios (script/region matching, language distances) still perform well.
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
// Cache for Set conversions to avoid repeated array->Set conversions
|
|
2
|
+
var availableLocalesSetCache = new WeakMap();
|
|
1
3
|
/**
|
|
2
4
|
* https://tc39.es/ecma402/#sec-bestavailablelocale
|
|
3
5
|
* @param availableLocales
|
|
4
6
|
* @param locale
|
|
5
7
|
*/
|
|
6
8
|
export function BestAvailableLocale(availableLocales, locale) {
|
|
9
|
+
// Fast path: use Set for O(1) lookups instead of O(n) indexOf
|
|
10
|
+
var availableSet = availableLocalesSetCache.get(availableLocales);
|
|
11
|
+
if (!availableSet) {
|
|
12
|
+
availableSet = new Set(availableLocales);
|
|
13
|
+
availableLocalesSetCache.set(availableLocales, availableSet);
|
|
14
|
+
}
|
|
7
15
|
var candidate = locale;
|
|
8
16
|
while (true) {
|
|
9
|
-
if (
|
|
17
|
+
if (availableSet.has(candidate)) {
|
|
10
18
|
return candidate;
|
|
11
19
|
}
|
|
12
20
|
var pos = candidate.lastIndexOf('-');
|