UNPKG

apphouse

Version:

Component library for React that uses observable state management and theme-able components.

191 lines (169 loc) 5.11 kB
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'; }