accounts-frontend/packages/app/services/i18n/i18n.ts

106 lines
2.9 KiB
TypeScript

import { IntlShape, createIntl, createIntlCache } from 'react-intl';
import captcha from 'app/services/captcha';
import locales from 'app/i18n';
import intlPolyfill from './intlPolyfill';
export const SUPPORTED_LANGUAGES = Object.keys(locales);
export const DEFAULT_LANGUAGE = 'en';
function getBrowserPreferredLanguages(): string[] {
return ([] as string[]).concat(navigator['languages'] || []).concat(navigator['language'] || []);
}
function detectLanguage(userLanguages: string[], availableLanguages: string[], defaultLanguage: string): string {
return (
userLanguages
.map((lang) => (lang.split('-').shift() || '').toLowerCase())
.find((lang) => availableLanguages.indexOf(lang) !== -1) || defaultLanguage
);
}
const cache = createIntlCache();
let intl: IntlShape;
class I18N {
detectLanguage(lang: string = ''): string {
return detectLanguage(
[lang].concat(getBrowserPreferredLanguages()).filter((item) => !!item),
SUPPORTED_LANGUAGES,
DEFAULT_LANGUAGE,
);
}
getIntl(): IntlShape {
if (!intl) {
intl = createIntl(
{
locale: 'en',
messages: {},
},
cache,
);
}
return intl;
}
async changeLocale(locale: string = DEFAULT_LANGUAGE): Promise<IntlShape> {
const { messages } = await this.require(locale);
captcha.setLang(locale);
intl = createIntl(
{
locale,
messages,
},
cache,
);
return intl;
}
async ensureIntl() {
await intlPolyfill('en');
}
async require(locale: string): Promise<{
locale: string;
messages: Record<string, string>;
}> {
try {
const [{ default: messages }] = await Promise.all([
import(/* webpackChunkName: "locale-[request]" */ `app/i18n/${locale}.json`),
intlPolyfill(locale),
]);
return {
locale,
messages,
};
} catch (err) {
if (process.env.NODE_ENV !== 'production') {
if (err.message === "Cannot find module './en.json'") {
console.warn(
[
"Locales module for the source language isn't exists.",
'You may generate this file by running yarn i18n:extract command.',
'Until then, defaultMessages will be used for displaying on the site.',
].join(' '),
);
} else {
console.error(err);
}
return { locale, messages: {} };
}
throw err;
}
}
}
export default new I18N();