]> git.ipfire.org Git - thirdparty/moment.git/commitdiff
[bugfix] Properly fallback to base locales in array getter (#5459)
authorIskren Ivov Chernev <iskren.chernev@gmail.com>
Sat, 25 Apr 2020 20:41:27 +0000 (23:41 +0300)
committerGitHub <noreply@github.com>
Sat, 25 Apr 2020 20:41:27 +0000 (23:41 +0300)
It looks like the existing implementation of this feature was pretty
well thought out and correct, the problem was that a compareArray
function was used which was comparing arrays in a rather bizzare
fashion that was not in line with what a "normal person" would expect.
So now the array comparator is correct, and the logic works properly.

The logic works as follows -- the next locale is picked and tried as-is.
If that fails, the code normally tries to chop the last bit (normally
the country designation) and try again. However, if the next array
element has the same or longer prefix as the one to be tried, the
iteration continues. So for example if the array has the sequence

    "AA-BB", "AA-CC", "XX-YY"

then first "AA-BB" is tried, then a naive solution would try "AA", but
this one instead checks to see that "AA-CC" is actually more concrete
than "AA", so it tries "AA-CC" next, and only after it fails (if it
fails) it tries "AA", because "XX-YY" does not have "AA" as prefix. So
in the end the following locales are tried in this order (assuming all
fail so the next one is tried):

    "AA-BB", "AA-CC", "AA", "XX-YY", "XX"

Fixes #4780

src/lib/locale/locales.js

index 7de3ec572926c0ebfaa47ccc3f49d23d5840ec86..ef9dd2b25aa82fb7ec86beab80d3dd50ddd3d691 100644 (file)
@@ -1,6 +1,5 @@
 import isArray from '../utils/is-array';
 import isUndefined from '../utils/is-undefined';
-import compareArrays from '../utils/compare-arrays';
 import { deprecateSimple } from '../utils/deprecate';
 import { mergeConfigs } from './set';
 import { Locale } from './constructor';
@@ -13,6 +12,16 @@ var locales = {};
 var localeFamilies = {};
 var globalLocale;
 
+function commonPrefix(arr1, arr2) {
+    var i, minl = Math.min(arr1.length, arr2.length);
+    for (i = 0; i < minl; i += 1) {
+        if (arr1[i] !== arr2[i]) {
+            return i;
+        }
+    }
+    return minl;
+}
+
 function normalizeLocale(key) {
     return key ? key.toLowerCase().replace('_', '-') : key;
 }
@@ -33,7 +42,7 @@ function chooseLocale(names) {
             if (locale) {
                 return locale;
             }
-            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+            if (next && next.length >= j && commonPrefix(split, next) >= j - 1) {
                 //the next array item is better than a shallower substring of this one
                 break;
             }