ilib-localematcher 1.3.2 → 1.3.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.
Files changed (39) hide show
  1. package/README.md +1 -44
  2. package/lib/LocaleMatcher.js +1 -1
  3. package/lib/LocaleMatcher.js.map +1 -1
  4. package/package.json +110 -111
  5. package/src/LocaleMatcher.js +7 -7
  6. package/docs/LocaleMatcher.html +0 -1237
  7. package/docs/LocaleMatcher.js.html +0 -465
  8. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  9. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  10. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  11. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  12. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  13. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  14. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  15. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  16. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  17. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -978
  18. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  19. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  20. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  21. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  22. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -1049
  23. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  24. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  25. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  26. package/docs/ilibLocaleMatcher.md +0 -235
  27. package/docs/index.html +0 -84
  28. package/docs/scripts/collapse.js +0 -39
  29. package/docs/scripts/commonNav.js +0 -28
  30. package/docs/scripts/linenumber.js +0 -25
  31. package/docs/scripts/nav.js +0 -12
  32. package/docs/scripts/polyfill.js +0 -4
  33. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -202
  34. package/docs/scripts/prettify/lang-css.js +0 -2
  35. package/docs/scripts/prettify/prettify.js +0 -28
  36. package/docs/scripts/search.js +0 -99
  37. package/docs/styles/jsdoc.css +0 -776
  38. package/docs/styles/prettify.css +0 -80
  39. package/lib/package.json +0 -1
@@ -1,465 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
-
5
- <meta charset="utf-8">
6
- <title>LocaleMatcher.js - Documentation</title>
7
-
8
-
9
- <script src="scripts/prettify/prettify.js"></script>
10
- <script src="scripts/prettify/lang-css.js"></script>
11
- <!--[if lt IE 9]>
12
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13
- <![endif]-->
14
- <link type="text/css" rel="stylesheet" href="styles/prettify.css">
15
- <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
16
- <script src="scripts/nav.js" defer></script>
17
-
18
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
19
- </head>
20
- <body>
21
-
22
- <input type="checkbox" id="nav-trigger" class="nav-trigger" />
23
- <label for="nav-trigger" class="navicon-button x">
24
- <div class="navicon"></div>
25
- </label>
26
-
27
- <label for="nav-trigger" class="overlay"></label>
28
-
29
- <nav >
30
-
31
-
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="LocaleMatcher.html">LocaleMatcher</a><ul class='methods'><li data-type='method'><a href="LocaleMatcher.html#getLikelyLocale">getLikelyLocale</a></li><li data-type='method'><a href="LocaleMatcher.html#getLikelyLocaleMinimal">getLikelyLocaleMinimal</a></li><li data-type='method'><a href="LocaleMatcher.html#getLocale">getLocale</a></li><li data-type='method'><a href="LocaleMatcher.html#getMacroLanguage">getMacroLanguage</a></li><li data-type='method'><a href="LocaleMatcher.html#getRegionContainment">getRegionContainment</a></li><li data-type='method'><a href="LocaleMatcher.html#match">match</a></li><li data-type='method'><a href="LocaleMatcher.html#smallestCommonRegion">smallestCommonRegion</a></li></ul></li></ul>
33
-
34
- </nav>
35
-
36
- <div id="main">
37
-
38
- <h1 class="page-title">LocaleMatcher.js</h1>
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
- <section>
47
- <article>
48
- <pre class="prettyprint source linenums"><code>/*
49
- * LocaleMatcher.js - Locale matcher definition
50
- *
51
- * Copyright © 2013-2015, 2018-2019, 2021-2022 JEDLSoft
52
- *
53
- * Licensed under the Apache License, Version 2.0 (the "License");
54
- * you may not use this file except in compliance with the License.
55
- * You may obtain a copy of the License at
56
- *
57
- * http://www.apache.org/licenses/LICENSE-2.0
58
- *
59
- * Unless required by applicable law or agreed to in writing, software
60
- * distributed under the License is distributed on an "AS IS" BASIS,
61
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
62
- *
63
- * See the License for the specific language governing permissions and
64
- * limitations under the License.
65
- */
66
-
67
- // !data localematch
68
-
69
- import { Utils } from 'ilib-common';
70
- import Locale from 'ilib-locale';
71
-
72
- import { matchdata } from './localematch.js';
73
-
74
- const componentWeights = [
75
- 0.5, // language
76
- 0.2, // script
77
- 0.25, // region
78
- 0.05 // variant
79
- ];
80
-
81
- // these are languages where you have to put the script all the time,
82
- // as none of the scripts are default for the language
83
- const multiScriptLanguages = {
84
- "az": true, // Azerbaijani
85
- "kk": true, // Kazakh
86
- "ku": true, // Kurdish
87
- "ky": true, // Kyrgyz
88
- "pa": true, // Panjabi
89
- "sr": true, // Serbian
90
- "tg": true, // Tajik
91
- "uz": true, // Uzbek
92
- "zh": true // Chinese
93
- };
94
-
95
- /**
96
- * @class Represent a locale matcher instance, which is used
97
- * to see which locales can be matched with each other in
98
- * various ways.
99
- */
100
- class LocaleMatcher {
101
- /**
102
- * Create a new locale matcher instance. This is used
103
- * to see which locales can be matched with each other in
104
- * various ways.&lt;p>
105
- *
106
- * The options object may contain any of the following properties:
107
- *
108
- * &lt;ul>
109
- * &lt;li>&lt;i>locale&lt;/i> - the locale instance or locale spec to match
110
- * &lt;/ul>
111
- *
112
- * @constructor
113
- * @param {Object} options parameters to initialize this matcher
114
- */
115
- constructor(options) {
116
- this.locale = new Locale();
117
-
118
- if (options &amp;&amp; typeof(options.locale) !== 'undefined') {
119
- this.locale = (typeof(options.locale) === 'string') ? new Locale(options.locale) : options.locale;
120
- }
121
- }
122
-
123
- /**
124
- * Return the locale used to construct this instance.
125
- * @return {Locale|undefined} the locale for this matcher
126
- */
127
- getLocale() {
128
- return this.locale;
129
- }
130
-
131
- /**
132
- * Do the work
133
- * @private
134
- */
135
- _getLikelyLocale(locale) {
136
- // already full specified
137
- if (locale.language &amp;&amp; locale.script &amp;&amp; locale.region) return locale;
138
-
139
- if (typeof(matchdata.likelyLocales[locale.getSpec()]) === 'undefined') {
140
- // try various partials before giving up
141
- let partial = matchdata.likelyLocales[new Locale(locale.language, undefined, locale.region).getSpec()];
142
- if (typeof(partial) !== 'undefined') return new Locale(partial);
143
-
144
- partial = matchdata.likelyLocales[new Locale(locale.language, locale.script, undefined).getSpec()];
145
- if (typeof(partial) !== 'undefined') return new Locale(partial);
146
-
147
- partial = matchdata.likelyLocales[new Locale(locale.language, undefined, undefined).getSpec()];
148
- if (typeof(partial) !== 'undefined') return new Locale(partial);
149
-
150
- partial = matchdata.likelyLocales[new Locale(undefined, locale.script, locale.region).getSpec()];
151
- if (typeof(partial) !== 'undefined') return new Locale(partial);
152
-
153
- partial = matchdata.likelyLocales[new Locale(undefined, undefined, locale.region).getSpec()];
154
- if (typeof(partial) !== 'undefined') return new Locale(partial);
155
-
156
- partial = matchdata.likelyLocales[new Locale(undefined, locale.script, undefined).getSpec()];
157
- if (typeof(partial) !== 'undefined') return new Locale(partial);
158
-
159
- return locale;
160
- }
161
-
162
- return new Locale(matchdata.likelyLocales[locale.getSpec()]);
163
- }
164
-
165
- /**
166
- * Return an Locale instance that is fully specified based on partial information
167
- * given to the constructor of this locale matcher instance. For example, if the locale
168
- * spec given to this locale matcher instance is simply "ru" (for the Russian language),
169
- * then it will fill in the missing region and script tags and return a locale with
170
- * the specifier "ru-Cyrl-RU". (ie. Russian language, Cyrillic, Russian Federation).
171
- * Any one or two of the language, script, or region parts may be left unspecified,
172
- * and the other one or two parts will be filled in automatically. If this
173
- * class has no information about the given locale, then the locale of this
174
- * locale matcher instance is returned unchanged.
175
- *
176
- * @returns {Locale} the most likely completion of the partial locale given
177
- * to the constructor of this locale matcher instance
178
- */
179
- getLikelyLocale() {
180
- return this._getLikelyLocale(this.locale);
181
- }
182
-
183
- /**
184
- * Return an Locale instance that is specified based on partial information
185
- * given to the constructor of this locale matcher instance but which leaves out any
186
- * part of the locale specifier that is so common that it is understood. For example,
187
- * if the locale
188
- * spec given to this locale matcher instance is simply "ru" (for the Russian language),
189
- * then it will fill in the missing region and/or script tags and return a locale with
190
- * the specifier "ru-RU". (ie. Russian language, Russian Federation). Note that the
191
- * default script "Cyrl" is left out because the vast majority of text written in
192
- * Russian is written with the Cyrllic script, so that part of the locale is understood
193
- * and is commonly left out.&lt;p>
194
- *
195
- * Any one or two of the language, script, or region parts may be left unspecified,
196
- * and the other one or two parts will be filled in automatically. If this
197
- * class has no information about the given locale, then the locale of this
198
- * locale matcher instance is returned unchanged.&lt;p>
199
- *
200
- * This method returns the same information as getLikelyLocale but with the very common
201
- * parts left out.
202
- *
203
- * @returns {Locale} the most likely "minimal" completion of the partial locale given
204
- * to the constructor of this locale matcher instance where the commonly understood
205
- * parts are left out.
206
- */
207
- getLikelyLocaleMinimal() {
208
- const fullLocale = this._getLikelyLocale(this.locale);
209
- const langLocale = this._getLikelyLocale(new Locale(fullLocale.language));
210
- return fullLocale.script === langLocale.script &amp;&amp; !multiScriptLanguages[fullLocale.language] ?
211
- new Locale(fullLocale.language, undefined, fullLocale.region) :
212
- fullLocale;
213
- }
214
-
215
- /**
216
- * Return the degree that the given locale matches the current locale of this
217
- * matcher. This method returns an integer from 0 to 100. A value of 100 is
218
- * a 100% match, meaning that the two locales are exactly equivalent to each
219
- * other. (eg. "ja-JP" and "ja-JP") A value of 0 means that there 0% match or
220
- * that the two locales have nothing in common. (eg. "en-US" and "ja-JP") &lt;p>
221
- *
222
- * Locale matching is not the same as equivalence, as the degree of matching
223
- * is returned. (See Locale.equals for equivalence.)&lt;p>
224
- *
225
- * The match score is calculated based on matching the 4 locale components,
226
- * weighted by importance:
227
- *
228
- * &lt;ul>
229
- * &lt;li> language - this accounts for 50% of the match score
230
- * &lt;li> region - accounts for 25% of the match score
231
- * &lt;li> script - accounts for 20% of the match score
232
- * &lt;li> variant - accounts for 5% of the match score
233
- * &lt;/ul>
234
- *
235
- * The score is affected by the following things:
236
- *
237
- * &lt;ul>
238
- * &lt;li> A large language score is given when the language components of the locales
239
- * match exactly.
240
- * &lt;li> Higher language scores are given when the languages are linguistically
241
- * close to each other, such as dialects.
242
- * &lt;li> A small score is given when two languages are in the same
243
- * linguistic family, but one is not a dialect of the other, such as German
244
- * and Dutch.
245
- * &lt;li> A large region score is given when two locales share the same region.
246
- * &lt;li> A smaller region score is given when one region is contained within
247
- * another. For example, Hong Kong is part of China, so a moderate score is
248
- * given instead of a full score.
249
- * &lt;li> A small score is given if two regions are geographically close to
250
- * each other or are tied by history. For example, Ireland and Great Britain
251
- * are both adjacent and tied by history, so they receive a moderate score.
252
- * &lt;li> A high script score is given if the two locales share the same script.
253
- * The legibility of a common script means that there is some small kinship of the
254
- * different languages.
255
- * &lt;li> A high variant score is given if the two locales share the same
256
- * variant. Full score is given when both locales have no variant at all.
257
- * &lt;li> Locale components that are unspecified in both locales are given high
258
- * scores.
259
- * &lt;li> Locales where a particular locale component is missing in only one
260
- * locale can still match when the default for that locale component matches
261
- * the component in the other locale. The
262
- * default value for the missing component is determined using the likely locales
263
- * data. (See getLikelyLocale()) For example, "en-US" and "en-Latn-US" receive
264
- * a high script score because the default script for "en" is "Latn".
265
- * &lt;/ul>
266
- *
267
- * The intention of this method is that it can be used to determine
268
- * compatibility of locales. For example, when a user signs up for an
269
- * account on a web site, the locales that the web site supports and
270
- * the locale of the user's browser may differ, and the site needs to
271
- * pick the best locale to show the user. Let's say the
272
- * web site supports a selection of European languages such as "it-IT",
273
- * "fr-FR", "de-DE", and "en-GB". The user's
274
- * browser may be set to "it-CH". The web site code can then match "it-CH"
275
- * against each of the supported locales to find the one with the
276
- * highest score. In
277
- * this case, the best match would be "it-IT" because it shares a
278
- * language and script in common with "it-CH" and differs only in the region
279
- * component. It is not a 100% match, but it is pretty good. The web site
280
- * may decide if the match scores all fall
281
- * below a chosen threshold (perhaps 50%?), it should show the user the
282
- * default language "en-GB", because that is probably a better choice
283
- * than any other supported locale.&lt;p>
284
- *
285
- * @param {Locale} locale the other locale to match against the current one
286
- * @return {number} an integer from 0 to 100 that indicates the degree to
287
- * which these locales match each other
288
- */
289
- match(locale) {
290
- const other = new Locale(locale);
291
- let scores = [0, 0, 0, 0];
292
- let thisfull, otherfull, i;
293
-
294
- if (this.locale.language === other.language) {
295
- scores[0] = 100;
296
- } else {
297
- if (!this.locale.language || !other.language) {
298
- // check for default language
299
- thisfull = this.getLikelyLocale();
300
- otherfull = new Locale(matchdata.likelyLocales[other.getSpec()] || other.getSpec());
301
- if (thisfull.language === otherfull.language) {
302
- scores[0] = 100;
303
- }
304
- } else {
305
- // check for macro languages
306
- const mlthis = matchdata.macroLanguagesReverse[this.locale.language] || this.locale.language;
307
- const mlother = matchdata.macroLanguagesReverse[other.language] || other.language;
308
- if (mlthis === mlother) {
309
- scores[0] = 90;
310
- } else {
311
- // check for mutual intelligibility
312
- const pair = this.locale.language + "-" + other.language;
313
- scores[0] = matchdata.mutualIntelligibility[pair] || 0;
314
- }
315
- }
316
- }
317
-
318
- if (this.locale.script === other.script) {
319
- scores[1] = 100;
320
- } else {
321
- if (!this.locale.script || !other.script) {
322
- // check for default script
323
- thisfull = this.locale.script ? this.locale : new Locale(matchdata.likelyLocales[this.locale.language]);
324
- otherfull = other.script ? other : new Locale(matchdata.likelyLocales[other.language]);
325
- if (thisfull.script === otherfull.script) {
326
- scores[1] = 100;
327
- }
328
- }
329
- }
330
-
331
- if (this.locale.region === other.region) {
332
- scores[2] = 100;
333
- } else {
334
- if (!this.locale.region || !other.region) {
335
- // check for default region
336
- thisfull = this.getLikelyLocale();
337
- otherfull = new Locale(matchdata.likelyLocales[other.getSpec()] || other.getSpec());
338
- if (thisfull.region === otherfull.region) {
339
- scores[2] = 100;
340
- }
341
- } else {
342
- // check for containment
343
- const containers = matchdata.territoryContainmentReverse[this.locale.region] || [];
344
- // end at length-1 because the end is "001" which is "the whole world" -- which is not useful
345
- for (i = 0; i &lt; containers.length-1; i++) {
346
- const container = matchdata.territoryContainment[containers[i]];
347
- if (container &amp;&amp; container.indexOf(other.region) > -1) {
348
- // same area only accounts for 20% of the region score
349
- scores[2] = ((i+1) * 100 / containers.length) * 0.2;
350
- break;
351
- }
352
- }
353
- }
354
- }
355
-
356
- if (this.locale.variant === other.variant) {
357
- scores[3] = 100;
358
- }
359
-
360
- let total = 0;
361
-
362
- for (i = 0; i &lt; 4; i++) {
363
- total += scores[i] * componentWeights[i];
364
- }
365
-
366
- return Math.round(total);
367
- }
368
-
369
- /**
370
- * Return the macrolanguage associated with this locale. If the
371
- * locale's language is not part of a macro-language, then the
372
- * locale's language is returned as-is.
373
- *
374
- * @returns {string} the ISO code for the macrolanguage associated
375
- * with this locale, or language of the locale
376
- */
377
- getMacroLanguage() {
378
- return matchdata.macroLanguagesReverse[this.locale.language] || this.locale.language;
379
- }
380
-
381
- /**
382
- * Return the containment array for the given region code.
383
- * @private
384
- */
385
- _getRegionContainment(region) {
386
- return matchdata.territoryContainmentReverse[region] || [];
387
- }
388
-
389
- /**
390
- * Return the list of regions that this locale is contained within. Regions are
391
- * nested, so locales can be in multiple regions. (eg. US is in Northern North
392
- * America, North America, the Americas, the World.) Most regions are specified
393
- * using UN.49 region numbers, though some, like "EU", are letters. If the
394
- * locale is underspecified, this method will use the most likely locale method
395
- * to get the region first. For example, the locale "ja" (Japanese) is most
396
- * likely "ja-JP" (Japanese for Japan), and the region containment info for Japan
397
- * is returned.
398
- *
399
- * @returns {Array.&lt;string>} an array of region specifiers that this locale is within
400
- */
401
- getRegionContainment() {
402
- const region = this.locale.region || this.getLikelyLocale().region;
403
- return this._getRegionContainment(region);
404
- }
405
-
406
- /**
407
- * Find the smallest region that contains both the current locale and the other locale.
408
- * If the current or other locales are underspecified, this method will use the most
409
- * likely locale method
410
- * to get their regions first. For example, the locale "ja" (Japanese) is most
411
- * likely "ja-JP" (Japanese for Japan), and the region containment info for Japan
412
- * is checked against the other locale's region containment info.
413
- *
414
- * @param {string|Locale} otherLocale a locale specifier or a Locale instance to
415
- * compare against
416
- * @returns {string} the region specifier of the smallest region containing both the
417
- * current locale and other locale
418
- */
419
- smallestCommonRegion(otherLocale) {
420
- if (typeof(otherLocale) === "undefined") return "001";
421
-
422
- const thisRegion = this.locale.region || this.getLikelyLocale().region;
423
- const otherLoc = typeof(otherLocale) === "string" ? new Locale(otherLocale) : otherLocale;
424
- const otherRegion = this._getLikelyLocale(otherLoc).region;
425
-
426
- const thisRegions = this._getRegionContainment(thisRegion);
427
- const otherRegions = this._getRegionContainment(otherRegion);
428
-
429
- for (let i = 0; i &lt; thisRegions.length; i++) {
430
- if (otherRegions.indexOf(thisRegions[i]) > -1) {
431
- return thisRegions[i];
432
- }
433
- }
434
-
435
- // this default should never be reached because the world should be common to all regions
436
- return "001";
437
- }
438
- };
439
-
440
- export default LocaleMatcher;
441
- </code></pre>
442
- </article>
443
- </section>
444
-
445
-
446
-
447
-
448
-
449
-
450
- </div>
451
-
452
- <br class="clear">
453
-
454
- <footer>
455
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Mar 31 2026 18:15:44 GMT-0700 (Pacific Daylight Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
456
- </footer>
457
-
458
- <script>prettyPrint();</script>
459
- <script src="scripts/polyfill.js"></script>
460
- <script src="scripts/linenumber.js"></script>
461
-
462
-
463
-
464
- </body>
465
- </html>