xref: /expo/apps/test-suite/tests/Localization.js (revision 17185210)
1a47a1472SVille Immonenimport * as Localization from 'expo-localization';
2f2c6b866SŁukasz Kosmatyimport i18n from 'i18n-js';
3d1736fc2SHein Rutjesimport { Platform } from 'react-native';
4740b3867SJames Ide
5ad26c082SEvan Baconconst en = {
667f55e2bSStanisław Chmiela  good: 'good',
767f55e2bSStanisław Chmiela  morning: 'morning',
8ad26c082SEvan Bacon};
9ad26c082SEvan Bacon
10ad26c082SEvan Baconconst fr = {
1167f55e2bSStanisław Chmiela  good: 'bien',
1267f55e2bSStanisław Chmiela  morning: 'matin',
1367f55e2bSStanisław Chmiela};
1467f55e2bSStanisław Chmiela
1567f55e2bSStanisław Chmielaconst pl = {
1667f55e2bSStanisław Chmiela  good: 'dobry',
1767f55e2bSStanisław Chmiela  morning: 'rano',
18ad26c082SEvan Bacon};
19740b3867SJames Ide
20740b3867SJames Ideexport const name = 'Localization';
21740b3867SJames Ide
22740b3867SJames Ideexport function test(t) {
23ad26c082SEvan Bacon  function validateString(result) {
24ad26c082SEvan Bacon    t.expect(result).toBeDefined();
25ad26c082SEvan Bacon    t.expect(typeof result).toBe('string');
26ad26c082SEvan Bacon    t.expect(result.length > 0).toBe(true);
27ad26c082SEvan Bacon  }
28ad26c082SEvan Bacon
29ad26c082SEvan Bacon  function validateStringArray(result) {
30ad26c082SEvan Bacon    t.expect(result).toBeDefined();
31ad26c082SEvan Bacon    t.expect(Array.isArray(result)).toBe(true);
32ad26c082SEvan Bacon  }
33ad26c082SEvan Bacon
34d1736fc2SHein Rutjes  t.describe(`Localization methods`, () => {
35*17185210Saleqsio    t.it('expect to getLocales return preferred locales', () => {
36*17185210Saleqsio      const locales = Localization.getLocales();
37*17185210Saleqsio      t.expect(locales.length).toBeGreaterThanOrEqual(1);
38*17185210Saleqsio      const {
39*17185210Saleqsio        languageTag,
40*17185210Saleqsio        languageCode,
41*17185210Saleqsio        regionCode,
42*17185210Saleqsio        currencyCode,
43*17185210Saleqsio        currencySymbol,
44*17185210Saleqsio        decimalSeparator,
45*17185210Saleqsio        digitGroupingSeparator,
46*17185210Saleqsio        textDirection,
47*17185210Saleqsio        measurementSystem,
48*17185210Saleqsio      } = locales[0];
49*17185210Saleqsio      validateString(languageTag);
50*17185210Saleqsio      validateString(languageCode);
51*17185210Saleqsio      // following properties can be nullish if the locale does not provide/override them
52*17185210Saleqsio      t.expect(regionCode).toBeDefined();
53*17185210Saleqsio      t.expect(currencyCode).toBeDefined();
54*17185210Saleqsio      t.expect(currencySymbol).toBeDefined();
55*17185210Saleqsio      t.expect(decimalSeparator).toBeDefined();
56*17185210Saleqsio      t.expect(digitGroupingSeparator).toBeDefined();
57*17185210Saleqsio      t.expect(textDirection).toBeDefined();
58*17185210Saleqsio      if (textDirection) {
59*17185210Saleqsio        t.expect(['rtl', 'ltr'].includes(textDirection)).toBe(true);
60*17185210Saleqsio      }
61*17185210Saleqsio      t.expect(measurementSystem).toBeDefined();
62*17185210Saleqsio      if (measurementSystem) {
63*17185210Saleqsio        t.expect(['metric', 'us', 'uk'].includes(measurementSystem)).toBe(true);
64*17185210Saleqsio      }
65*17185210Saleqsio    });
66*17185210Saleqsio
67*17185210Saleqsio    t.it('expect getCalendars to return at least a single calendar', () => {
68*17185210Saleqsio      const calendars = Localization.getCalendars();
69*17185210Saleqsio      t.expect(calendars.length).toBeGreaterThanOrEqual(1);
70*17185210Saleqsio      const { calendar, uses24hourClock, firstWeekday, timeZone } = calendars[0];
71*17185210Saleqsio      t.expect(calendar).toBeDefined();
72*17185210Saleqsio      t.expect(timeZone).toBeDefined();
73*17185210Saleqsio      // following properties can be nullish if the locale does not provide/override them
74*17185210Saleqsio      t.expect(uses24hourClock).toBeDefined();
75*17185210Saleqsio      if (uses24hourClock !== null) {
76*17185210Saleqsio        t.expect(typeof uses24hourClock).toBe('boolean');
77*17185210Saleqsio      }
78*17185210Saleqsio      t.expect(firstWeekday).toBeDefined();
79*17185210Saleqsio      if (firstWeekday !== null) {
80*17185210Saleqsio        t.expect(typeof firstWeekday).toBe('number');
81*17185210Saleqsio      }
82*17185210Saleqsio    });
83*17185210Saleqsio
84d1736fc2SHein Rutjes    t.it('expect async to return locale', async () => {
85ad26c082SEvan Bacon      const {
86d1736fc2SHein Rutjes        currency,
87d1736fc2SHein Rutjes        decimalSeparator,
88d1736fc2SHein Rutjes        digitGroupingSeparator,
89d1736fc2SHein Rutjes        isoCurrencyCodes,
90d1736fc2SHein Rutjes        isMetric,
91d1736fc2SHein Rutjes        isRTL,
92ad26c082SEvan Bacon        locale,
93ad26c082SEvan Bacon        locales,
94ad26c082SEvan Bacon        timezone,
95f2c6b866SŁukasz Kosmaty        region,
96ad26c082SEvan Bacon      } = await Localization.getLocalizationAsync();
97ad26c082SEvan Bacon
98ad26c082SEvan Bacon      validateString(locale);
99ad26c082SEvan Bacon      validateString(timezone);
100d1736fc2SHein Rutjes      if (Platform.OS !== 'web' || region) {
101f2c6b866SŁukasz Kosmaty        validateString(region);
102f2c6b866SŁukasz Kosmaty      }
103ad26c082SEvan Bacon      validateStringArray(isoCurrencyCodes);
104ad26c082SEvan Bacon      validateStringArray(locales);
105ad26c082SEvan Bacon      t.expect(locales[0]).toBe(Localization.locale);
106ad26c082SEvan Bacon      t.expect(typeof isRTL).toBe('boolean');
107d1736fc2SHein Rutjes      t.expect(typeof isMetric).toBe('boolean');
108d1736fc2SHein Rutjes      validateString(decimalSeparator);
109d1736fc2SHein Rutjes      validateString(digitGroupingSeparator);
110d1736fc2SHein Rutjes      if (Platform.OS !== 'web' || currency) {
111d1736fc2SHein Rutjes        validateString(currency);
112d1736fc2SHein Rutjes      }
113ad26c082SEvan Bacon    });
114ad26c082SEvan Bacon  });
115ad26c082SEvan Bacon
116ad26c082SEvan Bacon  t.describe(`Localization defines constants`, () => {
117d1736fc2SHein Rutjes    t.it('Gets the region', async () => {
118f2c6b866SŁukasz Kosmaty      const result = Localization.region;
119d1736fc2SHein Rutjes      if (Platform.OS !== 'web' || result) {
120d1736fc2SHein Rutjes        validateString(result);
121f2c6b866SŁukasz Kosmaty      }
122d1736fc2SHein Rutjes    });
123d1736fc2SHein Rutjes    t.it('Gets the locale', async () => {
124d1736fc2SHein Rutjes      validateString(Localization.locale);
125740b3867SJames Ide    });
126740b3867SJames Ide    t.it('Gets the preferred locales', async () => {
127ad26c082SEvan Bacon      const result = Localization.locales;
128d1736fc2SHein Rutjes      validateStringArray(result);
129ad26c082SEvan Bacon      t.expect(result.length > 0).toBe(true);
130ad26c082SEvan Bacon      t.expect(result[0]).toBe(Localization.locale);
131740b3867SJames Ide    });
132740b3867SJames Ide    t.it('Gets ISO currency codes', async () => {
133ad26c082SEvan Bacon      const result = Localization.isoCurrencyCodes;
134d1736fc2SHein Rutjes      validateStringArray(result);
135d1736fc2SHein Rutjes      result.map(validateString);
136740b3867SJames Ide    });
137d1736fc2SHein Rutjes    t.it('Gets the timezone', async () => {
138ad26c082SEvan Bacon      const result = Localization.timezone;
139d1736fc2SHein Rutjes      if (result || Platform.OS !== 'web') {
140d1736fc2SHein Rutjes        validateString(Localization.timezone);
141f1fde1fbSEvan Bacon      }
142d1736fc2SHein Rutjes    });
143d1736fc2SHein Rutjes    t.it('Gets the layout direction (ltr only)', async () => {
144ad26c082SEvan Bacon      const result = Localization.isRTL;
145d1736fc2SHein Rutjes      t.expect(typeof result).toBe('boolean');
146ad26c082SEvan Bacon      t.expect(result).toBe(false);
147ad26c082SEvan Bacon    });
148d1736fc2SHein Rutjes    t.it('Gets the measurement system (metric)', async () => {
149d1736fc2SHein Rutjes      const result = Localization.isMetric;
150d1736fc2SHein Rutjes      t.expect(typeof result).toBe('boolean');
151d1736fc2SHein Rutjes    });
152d1736fc2SHein Rutjes    t.it('Gets the decimal separator', async () => {
153d1736fc2SHein Rutjes      validateString(Localization.decimalSeparator);
154d1736fc2SHein Rutjes    });
155d1736fc2SHein Rutjes    t.it('Gets the grouping separator', async () => {
156d1736fc2SHein Rutjes      const result = Localization.decimalSeparator;
157d1736fc2SHein Rutjes      t.expect(result).toBeDefined();
158d1736fc2SHein Rutjes      t.expect(typeof result).toBe('string');
159d1736fc2SHein Rutjes    });
160d1736fc2SHein Rutjes    if (Platform.OS !== 'web') {
161d1736fc2SHein Rutjes      t.it('Gets the currency', async () => {
162d1736fc2SHein Rutjes        validateString(Localization.currency);
163d1736fc2SHein Rutjes      });
164d1736fc2SHein Rutjes    }
165ad26c082SEvan Bacon  });
166ad26c082SEvan Bacon
167ad26c082SEvan Bacon  t.describe(`Localization works with i18n-js`, () => {
168ad26c082SEvan Bacon    i18n.locale = Localization.locale;
16967f55e2bSStanisław Chmiela    i18n.translations = { en, fr, pl };
170ad26c082SEvan Bacon    i18n.missingTranslationPrefix = 'EE: ';
171ad26c082SEvan Bacon    i18n.fallbacks = true;
172ad26c082SEvan Bacon
17367f55e2bSStanisław Chmiela    t.it('expect language to match strings (en, pl, fr supported)', async () => {
17467f55e2bSStanisław Chmiela      const target = 'good';
175ad26c082SEvan Bacon
176ad26c082SEvan Bacon      i18n.locale = Localization.locale;
177ad26c082SEvan Bacon
178ad26c082SEvan Bacon      const expoPredictedLangTag = Localization.locale.split('-')[0];
179ad26c082SEvan Bacon      const translation = i18n.translations[expoPredictedLangTag];
180ad26c082SEvan Bacon
181ad26c082SEvan Bacon      t.expect(translation[target]).toBe(i18n.t(target));
182ad26c082SEvan Bacon    });
183ad26c082SEvan Bacon  });
184740b3867SJames Ide}
185