204 lines
8.8 KiB
TypeScript
204 lines
8.8 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import moment from 'moment';
|
|
import {getLocales} from 'react-native-localize';
|
|
|
|
import en from '@assets/i18n/en.json';
|
|
import * as logUtils from '@utils/log';
|
|
|
|
import {
|
|
getLocaleFromLanguage,
|
|
resetMomentLocale,
|
|
getTranslations,
|
|
getLocalizedMessage,
|
|
DEFAULT_LOCALE,
|
|
} from './index';
|
|
|
|
jest.mock('react-native-localize', () => ({
|
|
getLocales: jest.fn().mockReturnValue([{languageTag: 'en'}]),
|
|
}));
|
|
|
|
jest.mock('@utils/log', () => ({
|
|
logError: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('@assets/i18n/en.json', () => ({test: 'Test', hello: 'Hello'}));
|
|
jest.mock('@assets/i18n/bg.json', () => ({test: 'Тест', hello: 'Здравейте'}));
|
|
jest.mock('@assets/i18n/de.json', () => ({test: 'Test', hello: 'Hallo'}));
|
|
jest.mock('@assets/i18n/en_AU.json', () => ({test: 'Test', hello: 'G\'day'}));
|
|
jest.mock('@assets/i18n/es.json', () => ({test: 'Prueba', hello: 'Hola'}));
|
|
jest.mock('@assets/i18n/fa.json', () => ({test: 'تست', hello: 'سلام'}));
|
|
jest.mock('@assets/i18n/fr.json', () => ({test: 'Test', hello: 'Bonjour'}));
|
|
jest.mock('@assets/i18n/hu.json', () => ({test: 'Teszt', hello: 'Helló'}));
|
|
jest.mock('@assets/i18n/it.json', () => ({test: 'Test', hello: 'Ciao'}));
|
|
jest.mock('@assets/i18n/ja.json', () => ({test: 'テスト', hello: 'こんにちは'}));
|
|
jest.mock('@assets/i18n/ko.json', () => ({test: '테스트', hello: '안녕하세요'}));
|
|
jest.mock('@assets/i18n/nl.json', () => ({test: 'Test', hello: 'Hallo'}));
|
|
jest.mock('@assets/i18n/pl.json', () => ({test: 'Test', hello: 'Cześć'}));
|
|
jest.mock('@assets/i18n/pt-BR.json', () => ({test: 'Teste', hello: 'Olá'}));
|
|
jest.mock('@assets/i18n/ro.json', () => ({test: 'Test', hello: 'Bună'}));
|
|
jest.mock('@assets/i18n/ru.json', () => ({test: 'Тест', hello: 'Привет'}));
|
|
jest.mock('@assets/i18n/sv.json', () => ({test: 'Test', hello: 'Hej'}));
|
|
jest.mock('@assets/i18n/tr.json', () => ({test: 'Test', hello: 'Merhaba'}));
|
|
jest.mock('@assets/i18n/uk.json', () => ({test: 'Тест', hello: 'Привіт'}));
|
|
jest.mock('@assets/i18n/vi.json', () => ({test: 'Kiểm tra', hello: 'Xin chào'}));
|
|
jest.mock('@assets/i18n/zh-CN.json', () => ({test: '测试', hello: '你好'}));
|
|
jest.mock('@assets/i18n/zh-TW.json', () => ({test: '測試', hello: '你好'}));
|
|
|
|
describe('i18n', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
jest.mocked(getLocales).mockReturnValue([{
|
|
languageTag: 'en',
|
|
languageCode: '',
|
|
countryCode: '',
|
|
isRTL: false,
|
|
}]);
|
|
});
|
|
|
|
describe('getLocaleFromLanguage', () => {
|
|
it('returns correct locale for full language code', () => {
|
|
expect(getLocaleFromLanguage('es-ES')).toBe('es');
|
|
expect(getLocaleFromLanguage('pt-BR')).toBe('pt-BR');
|
|
expect(getLocaleFromLanguage('zh-TW')).toBe('zh-TW');
|
|
expect(getLocaleFromLanguage('zh-CN')).toBe('zh-CN');
|
|
expect(getLocaleFromLanguage('en-AU')).toBe('en-AU');
|
|
});
|
|
|
|
it('returns correct locale for language code', () => {
|
|
expect(getLocaleFromLanguage('es')).toBe('es');
|
|
expect(getLocaleFromLanguage('en')).toBe('en');
|
|
expect(getLocaleFromLanguage('fr')).toBe('fr');
|
|
expect(getLocaleFromLanguage('de')).toBe('de');
|
|
expect(getLocaleFromLanguage('ja')).toBe('ja');
|
|
});
|
|
|
|
it('returns default locale for unsupported language', () => {
|
|
expect(getLocaleFromLanguage('xx')).toBe('en');
|
|
expect(getLocaleFromLanguage('')).toBe('en');
|
|
expect(getLocaleFromLanguage('not-valid')).toBe('en');
|
|
});
|
|
});
|
|
|
|
describe('resetMomentLocale', () => {
|
|
let spy: jest.SpyInstance;
|
|
|
|
beforeEach(() => {
|
|
spy = jest.spyOn(moment, 'locale');
|
|
});
|
|
|
|
afterEach(() => {
|
|
spy.mockRestore();
|
|
});
|
|
|
|
it('sets moment locale correctly for various languages', () => {
|
|
resetMomentLocale('es-ES');
|
|
expect(spy).toHaveBeenCalledWith('es');
|
|
|
|
resetMomentLocale('en');
|
|
expect(spy).toHaveBeenCalledWith('en');
|
|
|
|
resetMomentLocale('zh-TW');
|
|
expect(spy).toHaveBeenCalledWith('zh');
|
|
|
|
resetMomentLocale('pt-BR');
|
|
expect(spy).toHaveBeenCalledWith('pt');
|
|
});
|
|
|
|
it('uses default locale when no locale provided', () => {
|
|
resetMomentLocale();
|
|
expect(spy).toHaveBeenCalledWith(DEFAULT_LOCALE.split('-')[0]);
|
|
});
|
|
|
|
it('handles invalid locales gracefully', () => {
|
|
resetMomentLocale('invalid-locale');
|
|
expect(spy).toHaveBeenCalledWith('invalid');
|
|
|
|
resetMomentLocale('');
|
|
expect(spy).toHaveBeenCalledWith(DEFAULT_LOCALE.split('-')[0]);
|
|
});
|
|
});
|
|
|
|
describe('getTranslations', () => {
|
|
beforeEach(() => {
|
|
(logUtils.logError as jest.Mock).mockClear();
|
|
});
|
|
|
|
it('returns correct translations for all supported locales', () => {
|
|
const testCases = [
|
|
{locale: 'bg', hello: 'Здравейте', test: 'Тест'},
|
|
{locale: 'de', hello: 'Hallo', test: 'Test'},
|
|
{locale: 'en', hello: 'Hello', test: 'Test'},
|
|
{locale: 'en-AU', hello: 'G\'day', test: 'Test'},
|
|
{locale: 'es', hello: 'Hola', test: 'Prueba'},
|
|
{locale: 'fa', hello: 'سلام', test: 'تست'},
|
|
{locale: 'fr', hello: 'Bonjour', test: 'Test'},
|
|
{locale: 'hu', hello: 'Helló', test: 'Teszt'},
|
|
{locale: 'it', hello: 'Ciao', test: 'Test'},
|
|
{locale: 'ja', hello: 'こんにちは', test: 'テスト'},
|
|
{locale: 'ko', hello: '안녕하세요', test: '테스트'},
|
|
{locale: 'nl', hello: 'Hallo', test: 'Test'},
|
|
{locale: 'pl', hello: 'Cześć', test: 'Test'},
|
|
{locale: 'pt-BR', hello: 'Olá', test: 'Teste'},
|
|
{locale: 'ro', hello: 'Bună', test: 'Test'},
|
|
{locale: 'ru', hello: 'Привет', test: 'Тест'},
|
|
{locale: 'sv', hello: 'Hej', test: 'Test'},
|
|
{locale: 'tr', hello: 'Merhaba', test: 'Test'},
|
|
{locale: 'uk', hello: 'Привіт', test: 'Тест'},
|
|
{locale: 'vi', hello: 'Xin chào', test: 'Kiểm tra'},
|
|
{locale: 'zh-CN', hello: '你好', test: '测试'},
|
|
{locale: 'zh-TW', hello: '你好', test: '測試'},
|
|
];
|
|
|
|
testCases.forEach(({locale, hello, test: testWord}) => {
|
|
const translations = getTranslations(locale);
|
|
expect(translations.hello).toBe(hello);
|
|
expect(translations.test).toBe(testWord);
|
|
});
|
|
});
|
|
|
|
it('returns english translations for unsupported locale', () => {
|
|
const translations = getTranslations('xx');
|
|
expect(translations).toEqual(en);
|
|
expect(logUtils.logError).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('loads correct polyfills for Chinese locales', () => {
|
|
const zhCNTranslations = getTranslations('zh-CN');
|
|
expect(zhCNTranslations.hello).toBe('你好');
|
|
expect(zhCNTranslations.test).toBe('测试');
|
|
|
|
const zhTWTranslations = getTranslations('zh-TW');
|
|
expect(zhTWTranslations.hello).toBe('你好');
|
|
expect(zhTWTranslations.test).toBe('測試');
|
|
});
|
|
});
|
|
|
|
describe('getLocalizedMessage', () => {
|
|
it('returns correct message for existing key in various languages', () => {
|
|
expect(getLocalizedMessage('en', 'test')).toBe('Test');
|
|
expect(getLocalizedMessage('es', 'test')).toBe('Prueba');
|
|
expect(getLocalizedMessage('en', 'hello')).toBe('Hello');
|
|
expect(getLocalizedMessage('es', 'hello')).toBe('Hola');
|
|
});
|
|
|
|
it('returns default message when key not found', () => {
|
|
expect(getLocalizedMessage('en', 'nonexistent', 'Default')).toBe('Default');
|
|
expect(getLocalizedMessage('es', 'nonexistent', 'Por defecto')).toBe('Por defecto');
|
|
});
|
|
|
|
it('returns empty string when no translation or default', () => {
|
|
expect(getLocalizedMessage('en', 'nonexistent')).toBe('');
|
|
expect(getLocalizedMessage('es', 'nonexistent')).toBe('');
|
|
});
|
|
|
|
it('handles invalid inputs gracefully', () => {
|
|
expect(getLocalizedMessage('', 'test')).toBe('Test');
|
|
expect(getLocalizedMessage('invalid-locale', 'test')).toBe('Test');
|
|
expect(getLocalizedMessage('en', '')).toBe('');
|
|
expect(getLocalizedMessage('en', undefined as unknown as string)).toBe('');
|
|
expect(getLocalizedMessage('en', null as unknown as string)).toBe('');
|
|
});
|
|
});
|
|
});
|