this repo has no description
at main 87 lines 2.3 kB view raw
1import localeMatch from './locale-match.js'; 2import mem from './mem.js'; 3 4function initLocales() { 5 const newLocales = [...navigator.languages]; 6 try { 7 const dtfLocale = new Intl.DateTimeFormat().resolvedOptions().locale; 8 if (!newLocales.includes(dtfLocale)) { 9 newLocales.unshift(dtfLocale); 10 } 11 } catch {} 12 return newLocales; 13} 14 15let locales = initLocales(); 16 17// For testing: refresh locales from current navigator state 18export function refreshLocales() { 19 locales = initLocales(); 20} 21 22const createLocale = mem((language, options = {}) => { 23 try { 24 return new Intl.Locale(language, options); 25 } catch { 26 // Fallback to simple string splitting 27 // May not work properly due to how complicated this is 28 if (!language) return null; 29 30 // https://www.w3.org/International/articles/language-tags/ 31 // Parts: language-extlang-script-region-variant-extension-privateuse 32 const [langPart, ...parts] = language.split('-', 4); 33 const regionPart = parts.pop() || null; 34 const fallbackLocale = { 35 language: langPart, 36 region: regionPart, 37 ...options, 38 toString: () => { 39 const lang = fallbackLocale.language; 40 const middle = parts.length > 0 ? `-${parts.join('-')}-` : '-'; 41 const reg = fallbackLocale.region; 42 return reg ? `${lang}${middle}${reg}` : lang; 43 }, 44 }; 45 return fallbackLocale; 46 } 47}); 48 49const _DateTimeFormat = (locale, opts) => { 50 const options = opts; 51 52 const appLocale = createLocale(locale); 53 54 // Find first user locale with a region 55 let userRegion = null; 56 for (const loc of locales) { 57 const region = createLocale(loc)?.region; 58 if (region) { 59 userRegion = region; 60 break; 61 } 62 } 63 64 const userRegionLocale = 65 userRegion && appLocale && appLocale.region !== userRegion 66 ? createLocale(appLocale.language, { 67 ...appLocale, 68 region: userRegion, 69 })?.toString() 70 : null; 71 72 const matchedLocale = localeMatch( 73 [userRegionLocale, locale, locale?.replace(/-[a-z]+$/i, '')], 74 locales, 75 locale, 76 ); 77 78 try { 79 return new Intl.DateTimeFormat(matchedLocale, options); 80 } catch { 81 return new Intl.DateTimeFormat(undefined, options); 82 } 83}; 84 85const DateTimeFormat = mem(_DateTimeFormat); 86 87export default DateTimeFormat;