UNPKG

5.83 kBJavaScriptView Raw
1/* eslint-env browser */
2import { Platform } from 'expo-modules-core';
3import * as rtlDetect from 'rtl-detect';
4const getNavigatorLocales = () => {
5 return Platform.isDOMAvailable ? navigator.languages || [navigator.language] : [];
6};
7const WEB_LANGUAGE_CHANGE_EVENT = 'languagechange';
8// https://wisevoter.com/country-rankings/countries-that-use-fahrenheit/
9const USES_FAHRENHEIT = [
10 'AG',
11 'BZ',
12 'VG',
13 'FM',
14 'MH',
15 'MS',
16 'KN',
17 'BS',
18 'CY',
19 'TC',
20 'US',
21 'LR',
22 'PW',
23 'KY',
24];
25export function addLocaleListener(listener) {
26 addEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener);
27 return {
28 remove: () => removeEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener),
29 };
30}
31export function addCalendarListener(listener) {
32 addEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener);
33 return {
34 remove: () => removeEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener),
35 };
36}
37export function removeSubscription(subscription) {
38 subscription.remove();
39}
40export default {
41 get currency() {
42 // TODO: Add support
43 return null;
44 },
45 get decimalSeparator() {
46 return (1.1).toLocaleString().substring(1, 2);
47 },
48 get digitGroupingSeparator() {
49 const value = (1000).toLocaleString();
50 return value.length === 5 ? value.substring(1, 2) : '';
51 },
52 get isRTL() {
53 return rtlDetect.isRtlLang(this.locale) ?? false;
54 },
55 get isMetric() {
56 const { region } = this;
57 switch (region) {
58 case 'US': // USA
59 case 'LR': // Liberia
60 case 'MM': // Myanmar
61 return false;
62 }
63 return true;
64 },
65 get locale() {
66 if (!Platform.isDOMAvailable) {
67 return '';
68 }
69 const locale = navigator.language ||
70 navigator['systemLanguage'] ||
71 navigator['browserLanguage'] ||
72 navigator['userLanguage'] ||
73 this.locales[0];
74 return locale;
75 },
76 get locales() {
77 if (!Platform.isDOMAvailable) {
78 return [];
79 }
80 const { languages = [] } = navigator;
81 return Array.from(languages);
82 },
83 get timezone() {
84 const defaultTimeZone = 'Etc/UTC';
85 if (typeof Intl === 'undefined') {
86 return defaultTimeZone;
87 }
88 return Intl.DateTimeFormat().resolvedOptions().timeZone || defaultTimeZone;
89 },
90 get isoCurrencyCodes() {
91 // TODO(Bacon): Add this - very low priority
92 return [];
93 },
94 get region() {
95 // There is no way to obtain the current region, as is possible on native.
96 // Instead, use the country-code from the locale when possible (e.g. "en-US").
97 const { locale } = this;
98 const [, ...suffixes] = typeof locale === 'string' ? locale.split('-') : [];
99 for (const suffix of suffixes) {
100 if (suffix.length === 2) {
101 return suffix.toUpperCase();
102 }
103 }
104 return null;
105 },
106 getLocales() {
107 const locales = getNavigatorLocales();
108 return locales?.map((languageTag) => {
109 // TextInfo is an experimental API that is not available in all browsers.
110 // We might want to consider using a locale lookup table instead.
111 const locale = typeof Intl !== 'undefined'
112 ? new Intl.Locale(languageTag)
113 : { region: null, textInfo: null, language: null };
114 const { region, textInfo, language } = locale;
115 // Properties added only for compatibility with native, use `toLocaleString` instead.
116 const digitGroupingSeparator = Array.from((10000).toLocaleString(languageTag)).filter((c) => c > '9' || c < '0')[0] ||
117 null; // using 1e5 instead of 1e4 since for some locales (like pl-PL) 1e4 does not use digit grouping
118 const decimalSeparator = (1.1).toLocaleString(languageTag).substring(1, 2);
119 const temperatureUnit = region ? regionToTemperatureUnit(region) : null;
120 return {
121 languageTag,
122 languageCode: language || languageTag.split('-')[0] || 'en',
123 textDirection: textInfo?.direction || null,
124 digitGroupingSeparator,
125 decimalSeparator,
126 measurementSystem: null,
127 currencyCode: null,
128 currencySymbol: null,
129 regionCode: region || null,
130 temperatureUnit,
131 };
132 });
133 },
134 getCalendars() {
135 const locale = ((typeof Intl !== 'undefined'
136 ? Intl.DateTimeFormat().resolvedOptions()
137 : null) ?? null);
138 return [
139 {
140 calendar: (locale?.calendar || locale?.calendars?.[0]) || null,
141 timeZone: locale?.timeZone || locale?.timeZones?.[0] || null,
142 uses24hourClock: (locale?.hourCycle || locale?.hourCycles?.[0])?.startsWith('h2') ?? null, //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle
143 firstWeekday: locale?.weekInfo?.firstDay || null,
144 },
145 ];
146 },
147 async getLocalizationAsync() {
148 const { currency, decimalSeparator, digitGroupingSeparator, isoCurrencyCodes, isMetric, isRTL, locale, locales, region, timezone, } = this;
149 return {
150 currency,
151 decimalSeparator,
152 digitGroupingSeparator,
153 isoCurrencyCodes,
154 isMetric,
155 isRTL,
156 locale,
157 locales,
158 region,
159 timezone,
160 };
161 },
162};
163function regionToTemperatureUnit(region) {
164 return USES_FAHRENHEIT.includes(region) ? 'fahrenheit' : 'celsius';
165}
166//# sourceMappingURL=ExpoLocalization.js.map
\No newline at end of file