1
1
/* eslint no-magic-numbers: 0 */
2
- /* eslint complexity: ["error", { "max": 22 }] */
2
+ /* eslint complexity: ["error", { "max": 27 }] */
3
3
4
4
import Locale from './locale' ;
5
- import { getLikelySubtagsMin } from './subtags' ;
6
5
7
- /**
8
- * Attempts to build a most likely maximum version of the locale id based
9
- * on it's minimal version.
10
- *
11
- * If possible it uses the lookup table above. If this one is missing,
12
- * it only attempts to place the language code in the region position.
13
- */
14
- function getLikelySubtagsLocale ( loc , likelySubtags ) {
15
- if ( likelySubtags ) {
16
- for ( const key of Object . keys ( likelySubtags ) ) {
17
- if ( key . toLowerCase ( ) === loc . toLowerCase ( ) ) {
18
- return new Locale ( likelySubtags [ key ] ) ;
19
- }
20
- }
21
- return null ;
22
- }
23
- return getLikelySubtagsMin ( loc ) ;
24
- }
25
-
26
- /**
27
- * Replaces the region position with a range to allow for matches
28
- * with the same language/script but from different region.
29
- */
30
- function regionRangeFor ( locale ) {
31
- locale . region = '*' ;
32
- return locale ;
33
- }
34
-
35
- function variantRangeFor ( locale ) {
36
- locale . variant = '*' ;
37
- return locale ;
38
- }
39
-
40
- function getOrParseLocaleRange ( localeStr , cache ) {
41
- if ( ! cache . has ( localeStr ) ) {
42
- cache . set ( localeStr , new Locale ( localeStr , true ) ) ;
43
- }
44
- return cache . get ( localeStr ) ;
45
- }
46
6
/**
47
7
* Negotiates the languages between the list of requested locales against
48
8
* a list of available locales.
@@ -114,43 +74,57 @@ function getOrParseLocaleRange(localeStr, cache) {
114
74
* against `sr-Latn`.
115
75
*/
116
76
export default function filterMatches (
117
- requestedLocales , availableLocales , strategy , likelySubtags
77
+ requestedLocales , availableLocales , strategy
118
78
) {
119
79
const supportedLocales = new Set ( ) ;
120
80
121
- const availableLocalesCache = new Map ( ) ;
81
+ const availLocales =
82
+ new Set ( availableLocales . map ( locale => new Locale ( locale , true ) ) ) ;
122
83
123
84
outer:
124
85
for ( const reqLocStr of requestedLocales ) {
125
- if ( strategy === 'lookup' && supportedLocales . size > 0 ) {
126
- return Array . from ( supportedLocales ) ;
127
- }
128
-
129
86
const reqLocStrLC = reqLocStr . toLowerCase ( ) ;
87
+ const requestedLocale = new Locale ( reqLocStrLC ) ;
88
+
89
+ if ( requestedLocale . language === undefined ) {
90
+ continue ;
91
+ }
130
92
131
93
// Attempt to make an exact match
132
94
// Example: `en-US` === `en-US`
133
95
for ( const availableLocale of availableLocales ) {
134
96
if ( reqLocStrLC === availableLocale . toLowerCase ( ) ) {
135
97
supportedLocales . add ( availableLocale ) ;
136
- if ( strategy !== 'matching' ) {
98
+ for ( const loc of availLocales ) {
99
+ if ( loc . isEqual ( requestedLocale ) ) {
100
+ availLocales . delete ( loc ) ;
101
+ break ;
102
+ }
103
+ }
104
+ if ( strategy === 'lookup' ) {
105
+ return Array . from ( supportedLocales ) ;
106
+ } else if ( strategy === 'matching' ) {
137
107
continue outer;
108
+ } else {
109
+ break ;
138
110
}
139
111
}
140
112
}
141
113
142
- const requestedLocale = new Locale ( reqLocStrLC ) ;
143
114
144
115
// Attempt to match against the available range
145
116
// This turns `en` into `en-*-*-*` and `en-US` into `en-*-US-*`
146
117
// Example: ['en-US'] * ['en'] = ['en']
147
- for ( const availableLocale of availableLocales ) {
148
- if ( requestedLocale . matches (
149
- getOrParseLocaleRange ( availableLocale , availableLocalesCache )
150
- ) ) {
151
- supportedLocales . add ( availableLocale ) ;
152
- if ( strategy !== 'matching' ) {
118
+ for ( const availableLocale of availLocales ) {
119
+ if ( requestedLocale . matches ( availableLocale ) ) {
120
+ supportedLocales . add ( availableLocale . string ) ;
121
+ availLocales . delete ( availableLocale ) ;
122
+ if ( strategy === 'lookup' ) {
123
+ return Array . from ( supportedLocales ) ;
124
+ } else if ( strategy === 'matching' ) {
153
125
continue outer;
126
+ } else {
127
+ break ;
154
128
}
155
129
}
156
130
}
@@ -159,48 +133,54 @@ export default function filterMatches(
159
133
// If data is available, it'll expand `en` into `en-Latn-US` and
160
134
// `zh` into `zh-Hans-CN`.
161
135
// Example: ['en'] * ['en-GB', 'en-US'] = ['en-US']
162
- const maxRequestedLocale =
163
- getLikelySubtagsLocale ( reqLocStrLC , likelySubtags ) ;
164
-
165
- if ( maxRequestedLocale ) {
166
- for ( const availableLocale of availableLocales ) {
167
- if ( maxRequestedLocale . matches (
168
- getOrParseLocaleRange ( availableLocale , availableLocalesCache )
169
- ) ) {
170
- supportedLocales . add ( availableLocale ) ;
171
- if ( strategy !== 'matching' ) {
136
+ if ( requestedLocale . addLikelySubtags ( ) ) {
137
+ for ( const availableLocale of availLocales ) {
138
+ if ( requestedLocale . matches ( availableLocale ) ) {
139
+ supportedLocales . add ( availableLocale . string ) ;
140
+ availLocales . delete ( availableLocale ) ;
141
+ if ( strategy === 'lookup' ) {
142
+ return Array . from ( supportedLocales ) ;
143
+ } else if ( strategy === 'matching' ) {
172
144
continue outer;
145
+ } else {
146
+ break ;
173
147
}
174
148
}
175
149
}
176
150
}
177
151
178
152
// Attempt to look up for a different variant for the same locale ID
179
153
// Example: ['en-US-mac'] * ['en-US-win'] = ['en-US-win']
180
- const variantRange = variantRangeFor ( maxRequestedLocale || requestedLocale ) ;
181
-
182
- for ( const availableLocale of availableLocales ) {
183
- if ( variantRange . matches (
184
- getOrParseLocaleRange ( availableLocale , availableLocalesCache )
185
- ) ) {
186
- supportedLocales . add ( availableLocale ) ;
187
- if ( strategy !== 'matching' ) {
154
+ requestedLocale . setVariantRange ( ) ;
155
+
156
+ for ( const availableLocale of availLocales ) {
157
+ if ( requestedLocale . matches ( availableLocale ) ) {
158
+ supportedLocales . add ( availableLocale . string ) ;
159
+ availLocales . delete ( availableLocale ) ;
160
+ if ( strategy === 'lookup' ) {
161
+ return Array . from ( supportedLocales ) ;
162
+ } else if ( strategy === 'matching' ) {
188
163
continue outer;
164
+ } else {
165
+ break ;
189
166
}
190
167
}
191
168
}
192
169
193
170
// Attempt to look up for a different region for the same locale ID
194
171
// Example: ['en-US'] * ['en-AU'] = ['en-AU']
195
- const regionRange = regionRangeFor ( variantRange ) ;
196
-
197
- for ( const availableLocale of availableLocales ) {
198
- if ( regionRange . matches (
199
- getOrParseLocaleRange ( availableLocale , availableLocalesCache )
200
- ) ) {
201
- supportedLocales . add ( availableLocale ) ;
202
- if ( strategy !== 'matching' ) {
172
+ requestedLocale . setRegionRange ( ) ;
173
+
174
+ for ( const availableLocale of availLocales ) {
175
+ if ( requestedLocale . matches ( availableLocale ) ) {
176
+ supportedLocales . add ( availableLocale . string ) ;
177
+ availLocales . delete ( availableLocale ) ;
178
+ if ( strategy === 'lookup' ) {
179
+ return Array . from ( supportedLocales ) ;
180
+ } else if ( strategy === 'matching' ) {
203
181
continue outer;
182
+ } else {
183
+ break ;
204
184
}
205
185
}
206
186
}
0 commit comments