From: Iskren Ivov Chernev Date: Sat, 25 Apr 2020 20:41:27 +0000 (+0300) Subject: [bugfix] Properly fallback to base locales in array getter (#5459) X-Git-Tag: 2.25.0~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4dfb749e1219e4ac5ff0b244946f819cd7e3bfc3;p=thirdparty%2Fmoment.git [bugfix] Properly fallback to base locales in array getter (#5459) 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 --- diff --git a/src/lib/locale/locales.js b/src/lib/locale/locales.js index 7de3ec572..ef9dd2b25 100644 --- a/src/lib/locale/locales.js +++ b/src/lib/locale/locales.js @@ -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; }