apphouse
Version:
Component library for React that uses observable state management and theme-able components.
191 lines (169 loc) • 5.11 kB
text/typescript
import { autorun, makeAutoObservable } from 'mobx';
import { fromPromise, FULFILLED } from 'mobx-utils';
import { IntlConfig } from 'react-intl';
export const SupportedLocales = [
'en-us',
'pt-br'
// "th-th",
// "es-es",
// "fr-fr",
// "ko-kr",
];
export const localeBundles: Record<symbol, IntlConfig['messages']> = {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
'en-us': import('./en-us.json')
// "pt-br": import("./strings/pt-br.json"),
// "th-th": import("./strings/th-th.json"),
// "es-es": import("./strings/es-es.json"),
// "fr-fr": import("./strings/fr-fr.json"),
// "ko-kr": import("./strings/ko-kr.json"),
};
interface OptionsType {
value: string;
label: string;
}
// Class to handle locales
const DEFAULT_LOCALE = 'en-us';
export class Locale {
private defaultLocale: string;
supportedLanguages: string[];
locale: string;
strings: any;
constructor(defaultLocale?: string) {
this.defaultLocale = defaultLocale || DEFAULT_LOCALE;
this.locale = getSupportedLanguage();
this.supportedLanguages = SupportedLocales;
this.getStringsFromLocale(this.locale).then((messages) => {
this.setStrings(messages);
});
makeAutoObservable(this);
}
get selectedLocale(): string {
return this.locale;
}
get messages(): Record<symbol, IntlConfig['messages']> {
return this.strings;
}
get supportedLanguagesList() {
return this.supportedLanguages;
}
public getDefaultLocale = (): string => {
return this.defaultLocale;
};
public getLocaleFromUrl = (userLocale?: string): string => {
const pathname = window ? window?.location.pathname : '';
const urlParams = pathname.split('/');
const languageFromUrlParam =
urlParams.length >= 2 ? urlParams[1] : undefined;
const shouldOverwriteUserLocale = languageFromUrlParam !== userLocale;
// url param will rewrite user preferences
const loc = shouldOverwriteUserLocale ? languageFromUrlParam : userLocale;
// check if the language is supported, otherwise display default locale
const locale =
loc && this.supportedLanguagesList.includes(loc) ? loc : DEFAULT_LOCALE;
return locale;
};
setLocale = async (locale: string) => {
const strings = await this.getStringsFromLocale(locale);
this.setStrings(strings);
this.locale = locale;
};
setStrings = (messages: any) => {
this.strings = messages;
};
getStringsFromLocale = async (locale: string) => {
if (this.supportedLanguages.includes(locale)) {
//@ts-ignore
return await localeBundles[locale].then((messages: any) => messages);
} else {
// default to DEFAULT_LOCALE
//@ts-ignore
return await localeBundles[DEFAULT_LOCALE].then(
(messages: any) => messages
);
}
};
setStringsForLocale = (locale: string): void => {
if (this.supportedLanguages.includes(locale)) {
this.locale = locale;
//@ts-ignore
const status = fromPromise(localeBundles[locale]);
const disposer = autorun(() => {
if (status.state === FULFILLED) {
//@ts-ignore
this.strings = status.value;
disposer();
}
});
} else {
// default to DEFAULT_LOCALE
this.locale = DEFAULT_LOCALE;
//@ts-ignore
const status = fromPromise(localeBundles[DEFAULT_LOCALE]);
const disposer = autorun(() => {
if (status.state === FULFILLED) {
//@ts-ignore
this.strings = status.value;
disposer();
}
});
}
};
getSupportedLanguagesOptions = (): Array<OptionsType> => {
return Object.keys(localeBundles).map((key) => ({
value: key,
label: key
}));
};
}
export const currentLocale = new Locale(DEFAULT_LOCALE);
export function getFirstBrowserLanguage() {
const nav: any = window?.navigator;
const browserLanguagePropertyKeys = [
'language',
'browserLanguage',
'systemLanguage',
'userLanguage'
];
let i;
let language;
let len;
let shortLanguage = null;
// support for HTML 5.1 "navigator.languages"
if (Array.isArray(nav.languages)) {
for (i = 0; i < nav.languages.length; i++) {
language = nav.languages[i];
len = language.length;
if (!shortLanguage && len) {
shortLanguage = language;
}
if (language && len > 2) {
return language;
}
}
}
// support for other well known properties in browsers
for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
language = nav[browserLanguagePropertyKeys[i]];
//skip this loop iteration if property is null/undefined. IE11 fix.
if (language == null) {
continue;
}
len = language.length;
if (!shortLanguage && len) {
shortLanguage = language;
}
if (language && len > 2) {
return language;
}
}
return shortLanguage;
}
export function getSupportedLanguage() {
// const lang = getFirstBrowserLanguage().toLowerCase();
// if (SupportedLocales.includes(lang)) {
// return lang;
// }
return 'en-us';
}