cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

locales.js (7793B)


      1import isArray from '../utils/is-array';
      2import isUndefined from '../utils/is-undefined';
      3import { deprecateSimple } from '../utils/deprecate';
      4import { mergeConfigs } from './set';
      5import { Locale } from './constructor';
      6import keys from '../utils/keys';
      7
      8import { baseConfig } from './base-config';
      9
     10// internal storage for locale config files
     11var locales = {},
     12    localeFamilies = {},
     13    globalLocale;
     14
     15function commonPrefix(arr1, arr2) {
     16    var i,
     17        minl = Math.min(arr1.length, arr2.length);
     18    for (i = 0; i < minl; i += 1) {
     19        if (arr1[i] !== arr2[i]) {
     20            return i;
     21        }
     22    }
     23    return minl;
     24}
     25
     26function normalizeLocale(key) {
     27    return key ? key.toLowerCase().replace('_', '-') : key;
     28}
     29
     30// pick the locale from the array
     31// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
     32// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
     33function chooseLocale(names) {
     34    var i = 0,
     35        j,
     36        next,
     37        locale,
     38        split;
     39
     40    while (i < names.length) {
     41        split = normalizeLocale(names[i]).split('-');
     42        j = split.length;
     43        next = normalizeLocale(names[i + 1]);
     44        next = next ? next.split('-') : null;
     45        while (j > 0) {
     46            locale = loadLocale(split.slice(0, j).join('-'));
     47            if (locale) {
     48                return locale;
     49            }
     50            if (
     51                next &&
     52                next.length >= j &&
     53                commonPrefix(split, next) >= j - 1
     54            ) {
     55                //the next array item is better than a shallower substring of this one
     56                break;
     57            }
     58            j--;
     59        }
     60        i++;
     61    }
     62    return globalLocale;
     63}
     64
     65function isLocaleNameSane(name) {
     66    // Prevent names that look like filesystem paths, i.e contain '/' or '\'
     67    // Ensure name is available and function returns boolean
     68    return !!(name && name.match('^[^/\\\\]*$'));
     69}
     70
     71function loadLocale(name) {
     72    var oldLocale = null,
     73        aliasedRequire;
     74    // TODO: Find a better way to register and load all the locales in Node
     75    if (
     76        locales[name] === undefined &&
     77        typeof module !== 'undefined' &&
     78        module &&
     79        module.exports &&
     80        isLocaleNameSane(name)
     81    ) {
     82        try {
     83            oldLocale = globalLocale._abbr;
     84            aliasedRequire = require;
     85            aliasedRequire('./locale/' + name);
     86            getSetGlobalLocale(oldLocale);
     87        } catch (e) {
     88            // mark as not found to avoid repeating expensive file require call causing high CPU
     89            // when trying to find en-US, en_US, en-us for every format call
     90            locales[name] = null; // null means not found
     91        }
     92    }
     93    return locales[name];
     94}
     95
     96// This function will load locale and then set the global locale.  If
     97// no arguments are passed in, it will simply return the current global
     98// locale key.
     99export function getSetGlobalLocale(key, values) {
    100    var data;
    101    if (key) {
    102        if (isUndefined(values)) {
    103            data = getLocale(key);
    104        } else {
    105            data = defineLocale(key, values);
    106        }
    107
    108        if (data) {
    109            // moment.duration._locale = moment._locale = data;
    110            globalLocale = data;
    111        } else {
    112            if (typeof console !== 'undefined' && console.warn) {
    113                //warn user if arguments are passed but the locale could not be set
    114                console.warn(
    115                    'Locale ' + key + ' not found. Did you forget to load it?'
    116                );
    117            }
    118        }
    119    }
    120
    121    return globalLocale._abbr;
    122}
    123
    124export function defineLocale(name, config) {
    125    if (config !== null) {
    126        var locale,
    127            parentConfig = baseConfig;
    128        config.abbr = name;
    129        if (locales[name] != null) {
    130            deprecateSimple(
    131                'defineLocaleOverride',
    132                'use moment.updateLocale(localeName, config) to change ' +
    133                    'an existing locale. moment.defineLocale(localeName, ' +
    134                    'config) should only be used for creating a new locale ' +
    135                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'
    136            );
    137            parentConfig = locales[name]._config;
    138        } else if (config.parentLocale != null) {
    139            if (locales[config.parentLocale] != null) {
    140                parentConfig = locales[config.parentLocale]._config;
    141            } else {
    142                locale = loadLocale(config.parentLocale);
    143                if (locale != null) {
    144                    parentConfig = locale._config;
    145                } else {
    146                    if (!localeFamilies[config.parentLocale]) {
    147                        localeFamilies[config.parentLocale] = [];
    148                    }
    149                    localeFamilies[config.parentLocale].push({
    150                        name: name,
    151                        config: config,
    152                    });
    153                    return null;
    154                }
    155            }
    156        }
    157        locales[name] = new Locale(mergeConfigs(parentConfig, config));
    158
    159        if (localeFamilies[name]) {
    160            localeFamilies[name].forEach(function (x) {
    161                defineLocale(x.name, x.config);
    162            });
    163        }
    164
    165        // backwards compat for now: also set the locale
    166        // make sure we set the locale AFTER all child locales have been
    167        // created, so we won't end up with the child locale set.
    168        getSetGlobalLocale(name);
    169
    170        return locales[name];
    171    } else {
    172        // useful for testing
    173        delete locales[name];
    174        return null;
    175    }
    176}
    177
    178export function updateLocale(name, config) {
    179    if (config != null) {
    180        var locale,
    181            tmpLocale,
    182            parentConfig = baseConfig;
    183
    184        if (locales[name] != null && locales[name].parentLocale != null) {
    185            // Update existing child locale in-place to avoid memory-leaks
    186            locales[name].set(mergeConfigs(locales[name]._config, config));
    187        } else {
    188            // MERGE
    189            tmpLocale = loadLocale(name);
    190            if (tmpLocale != null) {
    191                parentConfig = tmpLocale._config;
    192            }
    193            config = mergeConfigs(parentConfig, config);
    194            if (tmpLocale == null) {
    195                // updateLocale is called for creating a new locale
    196                // Set abbr so it will have a name (getters return
    197                // undefined otherwise).
    198                config.abbr = name;
    199            }
    200            locale = new Locale(config);
    201            locale.parentLocale = locales[name];
    202            locales[name] = locale;
    203        }
    204
    205        // backwards compat for now: also set the locale
    206        getSetGlobalLocale(name);
    207    } else {
    208        // pass null for config to unupdate, useful for tests
    209        if (locales[name] != null) {
    210            if (locales[name].parentLocale != null) {
    211                locales[name] = locales[name].parentLocale;
    212                if (name === getSetGlobalLocale()) {
    213                    getSetGlobalLocale(name);
    214                }
    215            } else if (locales[name] != null) {
    216                delete locales[name];
    217            }
    218        }
    219    }
    220    return locales[name];
    221}
    222
    223// returns locale data
    224export function getLocale(key) {
    225    var locale;
    226
    227    if (key && key._locale && key._locale._abbr) {
    228        key = key._locale._abbr;
    229    }
    230
    231    if (!key) {
    232        return globalLocale;
    233    }
    234
    235    if (!isArray(key)) {
    236        //short-circuit everything else
    237        locale = loadLocale(key);
    238        if (locale) {
    239            return locale;
    240        }
    241        key = [key];
    242    }
    243
    244    return chooseLocale(key);
    245}
    246
    247export function listLocales() {
    248    return keys(locales);
    249}