UNPKG

stream-chat-react-native-core

Version:

The official React Native and Expo components for Stream Chat, a service for building chat applications

298 lines (262 loc) 11.2 kB
import { default as Dayjs } from 'dayjs'; import 'dayjs/locale/nl'; import localeData from 'dayjs/plugin/localeData'; import moment, { type Moment } from 'moment-timezone'; import frTranslations from '../../i18n/fr.json'; import nlTranslations from '../../i18n/nl.json'; import { Streami18n } from '../i18n/Streami18n'; Dayjs.extend(localeData); const customDayjsLocaleConfig = { months: 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), monthsShort: 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), ordinal: '%d.', weekdays: 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), weekdaysMin: 'su_má_tý_mi_hó_fr_le'.split('_'), weekdaysShort: 'sun_mán_týs_mik_hós_frí_ley'.split('_'), }; describe('Jest Timezone', () => { it('global config should set the timezone to UTC', () => { expect(new Date().getTimezoneOffset()).toBe(0); }); }); describe('Streami18n instance - default', () => { const streami18nOptions = { logger: () => {} }; const streami18n = new Streami18n(streami18nOptions); it('should provide default english translator', async () => { const { t: _t } = await streami18n.getTranslators(); const text = Date.now().toString(); expect(_t(text)).toBe(text); }); it('should provide dayjs with default en locale', async () => { const { tDateTimeParser } = await streami18n.getTranslators(); expect(tDateTimeParser() instanceof Dayjs).toBe(true); expect((tDateTimeParser() as Dayjs.Dayjs).locale()).toBe('en'); }); }); describe('Streami18n instance - with built-in language', () => { describe('datetime translations enabled', () => { const streami18nOptions = { language: 'nl' }; const streami18n = new Streami18n(streami18nOptions); it('should provide dutch translator', async () => { const { t: _t } = await streami18n.getTranslators(); for (const key in nlTranslations) { const value = nlTranslations[key as keyof typeof nlTranslations]; const hasTemplateInKey = key.indexOf('{{') > -1 && key.indexOf('}}') > -1; const hasTemplateInValue = typeof value === 'string' && value.indexOf('{{') > -1 && value.indexOf('}}') > -1; if (hasTemplateInKey || hasTemplateInValue || key.indexOf('duration/') > -1) { continue; } expect(_t(key)).toBe(nlTranslations[key as keyof typeof nlTranslations]); } }); it('should provide dayjs with `nl` locale', async () => { const { tDateTimeParser } = await streami18n.getTranslators(); expect(tDateTimeParser() instanceof Dayjs).toBe(true); expect((tDateTimeParser() as Dayjs.Dayjs).locale()).toBe('nl'); }); }); describe('datetime translations disabled', () => { const streami18nOptions = { disableDateTimeTranslations: true, language: 'nl', }; const streami18n = new Streami18n(streami18nOptions); it('should provide dutch translator', async () => { const { t: _t } = await streami18n.getTranslators(); for (const key in nlTranslations) { const value = nlTranslations[key as keyof typeof nlTranslations]; const hasTemplateInKey = key.indexOf('{{') > -1 && key.indexOf('}}') > -1; const hasTemplateInValue = typeof value === 'string' && value.indexOf('{{') > -1 && value.indexOf('}}') > -1; if (hasTemplateInKey || hasTemplateInValue || key.indexOf('duration/') > -1) { continue; } expect(_t(key)).toBe(nlTranslations[key as keyof typeof nlTranslations]); } }); it('should provide dayjs with default `en` locale', async () => { const { tDateTimeParser } = await streami18n.getTranslators(); expect(tDateTimeParser() instanceof Dayjs).toBe(true); expect((tDateTimeParser() as Dayjs.Dayjs).locale()).toBe('en'); }); }); describe('custom dayjs locale config', () => { const streami18nOptions = { dayjsLocaleConfigForLanguage: customDayjsLocaleConfig, language: 'nl', }; const streami18n = new Streami18n( streami18nOptions as unknown as ConstructorParameters<typeof Streami18n>[0], ); it('should provide dayjs with given custom locale config', async () => { const { tDateTimeParser } = await streami18n.getTranslators(); expect(tDateTimeParser() instanceof Dayjs).toBe(true); const localeConfig = (tDateTimeParser() as Dayjs.Dayjs).localeData() as unknown as Record< string, unknown >; for (const key in streami18nOptions.dayjsLocaleConfigForLanguage) { if (typeof localeConfig[key] === 'function') { expect((localeConfig[key] as () => unknown)()).toStrictEqual( customDayjsLocaleConfig[key as keyof typeof customDayjsLocaleConfig], ); } else { expect(localeConfig[key]).toStrictEqual( customDayjsLocaleConfig[key as keyof typeof customDayjsLocaleConfig], ); } } }); }); }); describe('Streami18n instance - with custom translations', () => { describe('datetime translations enabled', () => { const textKey1 = 'this is text one'; const textValue1 = '这是文字一'; const textKey2 = 'this is text two'; const textValue2 = '这是文字二'; const translations = { [textKey1]: textValue1, [textKey2]: textValue2, }; const streami18nOptions = { language: 'zh', translationsForLanguage: translations, }; const streami18n = new Streami18n( streami18nOptions as unknown as ConstructorParameters<typeof Streami18n>[0], ); it('should provide given (chinese in this case) translator', async () => { const { t: _t } = await streami18n.getTranslators(); expect(_t(textKey1)).toBe(textValue1); expect(_t(textKey2)).toBe(textValue2); }); it('should provide dayjs with default `en` locale', async () => { const { tDateTimeParser } = await streami18n.getTranslators(); expect(tDateTimeParser() instanceof Dayjs).toBe(true); expect((tDateTimeParser() as Dayjs.Dayjs).locale()).toBe('en'); }); }); }); describe('registerTranslation - register new language `mr` (Marathi)', () => { const streami18nOptions = { disableDateTimeTranslations: false, language: 'en', }; const streami18n = new Streami18n(streami18nOptions); const languageCode = 'mr'; const translations = { text1: 'अनुवादित मजकूर 1', text2: 'अनुवादित मजकूर 2', }; streami18n.registerTranslation( languageCode, translations as unknown as Parameters<typeof streami18n.registerTranslation>[1], customDayjsLocaleConfig as unknown as Parameters<typeof streami18n.registerTranslation>[2], ); streami18n.setLanguage('mr'); it('should add Marathi translations object to list of translations', () => { expect(streami18n.getTranslations()).toHaveProperty(languageCode, { translation: translations, }); }); it('should register dayjs locale config for Marathi translations', async () => { const { tDateTimeParser } = await streami18n.getTranslators(); expect(tDateTimeParser() instanceof Dayjs).toBe(true); const localeConfig = (tDateTimeParser() as Dayjs.Dayjs).localeData() as unknown as Record< string, unknown >; for (const key in customDayjsLocaleConfig) { if (typeof localeConfig[key] === 'function') { expect((localeConfig[key] as () => unknown)()).toStrictEqual( customDayjsLocaleConfig[key as keyof typeof customDayjsLocaleConfig], ); } else { expect(localeConfig[key]).toStrictEqual( customDayjsLocaleConfig[key as keyof typeof customDayjsLocaleConfig], ); } } }); }); describe('setLanguage - switch to french', () => { const streami18nOptions = {}; const streami18n = new Streami18n(streami18nOptions); it('should provide french translator', async () => { await streami18n.setLanguage('fr'); const { t: _t } = await streami18n.getTranslators(); for (const key in frTranslations) { // Skip keys with template strings or duration keys const value = frTranslations[key as keyof typeof frTranslations]; const hasTemplateInKey = key.indexOf('{{') > -1 && key.indexOf('}}') > -1; const hasTemplateInValue = typeof value === 'string' && value.indexOf('{{') > -1 && value.indexOf('}}') > -1; if (hasTemplateInKey || hasTemplateInValue || key.indexOf('duration/') > -1) { continue; } expect(_t(key)).toBe(frTranslations[key as keyof typeof frTranslations]); } }); }); describe('Streami18n timezone', () => { describe.each([['moment', moment]])('%s', (moduleName, module) => { it('is by default the local timezone', () => { const streamI18n = new Streami18n({ DateTimeParser: module }); const date = new Date(); expect((streamI18n.tDateTimeParser(date) as Moment).format('H')).toBe( date.getHours().toString(), ); }); it('can be set to different timezone on init', () => { const streamI18n = new Streami18n({ DateTimeParser: module, timezone: 'Europe/Prague' }); const date = new Date(); expect((streamI18n.tDateTimeParser(date) as Moment).format('H')).not.toBe( date.getHours().toString(), ); expect((streamI18n.tDateTimeParser(date) as Moment).format('H')).not.toBe( (date.getUTCHours() - 2).toString(), ); }); it('is ignored if datetime parser does not support timezones', () => { const mutableModule = module as unknown as { tz: unknown }; const tz = mutableModule.tz; delete (mutableModule as { tz?: unknown }).tz; const streamI18n = new Streami18n({ DateTimeParser: module, timezone: 'Europe/Prague' }); const date = new Date(); expect((streamI18n.tDateTimeParser(date) as Moment).format('H')).toBe( date.getHours().toString(), ); mutableModule.tz = tz; }); describe('formatters property', () => { it('contains the default timestampFormatter', () => { expect(new Streami18n().formatters.timestampFormatter).toBeDefined(); }); it('allows to override the default timestampFormatter', async () => { const i18n = new Streami18n({ formatters: { timestampFormatter: () => () => 'custom' }, translationsForLanguage: { abc: '{{ value | timestampFormatter }}' } as Record< string, string >, }); await (i18n as unknown as { init: () => Promise<void> }).init(); expect(i18n.t('abc')).toBe('custom'); }); it('allows to add new custom formatter', async () => { const i18n = new Streami18n({ formatters: { customFormatter: () => () => 'custom' }, translationsForLanguage: { abc: '{{ value | customFormatter }}' } as Record< string, string >, }); await (i18n as unknown as { init: () => Promise<void> }).init(); expect(i18n.t('abc')).toBe('custom'); }); }); }); });