1const hasIntl = typeof Intl === 'object' && !!Intl 2const Collator = hasIntl && Intl.Collator 3const cache = new Map() 4 5const collatorCompare = (locale, opts) => { 6 const collator = new Collator(locale, opts) 7 return (a, b) => collator.compare(a, b) 8} 9 10const localeCompare = (locale, opts) => (a, b) => a.localeCompare(b, locale, opts) 11 12const knownOptions = [ 13 'sensitivity', 14 'numeric', 15 'ignorePunctuation', 16 'caseFirst', 17] 18 19const { hasOwnProperty } = Object.prototype 20 21module.exports = (locale, options = {}) => { 22 if (!locale || typeof locale !== 'string') 23 throw new TypeError('locale required') 24 25 const opts = knownOptions.reduce((opts, k) => { 26 if (hasOwnProperty.call(options, k)) { 27 opts[k] = options[k] 28 } 29 return opts 30 }, {}) 31 const key = `${locale}\n${JSON.stringify(opts)}` 32 33 if (cache.has(key)) 34 return cache.get(key) 35 36 const compare = hasIntl 37 ? collatorCompare(locale, opts) 38 : localeCompare(locale, opts) 39 cache.set(key, compare) 40 41 return compare 42} 43