diff --git a/packages/webapp/src/app.tsx b/packages/webapp/src/app.tsx index e382b1d6..bee4065d 100644 --- a/packages/webapp/src/app.tsx +++ b/packages/webapp/src/app.tsx @@ -14,71 +14,76 @@ import { Provider } from 'react-redux'; import { QueryClient, QueryClientProvider } from 'react-query'; import { CssBaseline, ThemeProvider } from '@material-ui/core'; import { theme } from './theme' - -function loadLocaleData(language: string) { - switch (language) { - case 'es': - return require('./compiled-lang/es.json') - default: - return require('./compiled-lang/en.json') - } -} +import AppI18n, { Locale, Locales } from './classes/app-i18n'; const queryClient = new QueryClient({ defaultOptions: { queries: { refetchIntervalInBackground: false, - staleTime: 5*1000*60 // 10 minutes + staleTime: 5 * 1000 * 60 // 10 minutes } } }); const App = () => { const [messages, setMessages] = useState(undefined); - // Boostrap i18n ... - const locale = (navigator.languages && navigator.languages[0]) - || navigator.language - || 'en-US'; + const [appi18n, setAppi18n] = useState( new AppI18n('es')); useEffect(() => { - const language = locale.split('-')[0]; - const fetchData = async () => { - const messages = await loadLocaleData(language); - setMessages(messages); + + // @Todo: Why can not be dynamc ? + const loadResourceBundle = async (locale: Locale) => { + let result; + console.log("Language:" + locale.code); + + switch (locale.code) { + case 'en': + result = require('./compiled-lang/en.json'); + break; + case 'es': + result = require('./compiled-lang/es.json'); + break; + } + return result; } + const fetchData = async () => { + const locale = appi18n.getLocale(); + const msg = await loadResourceBundle(locale); + setMessages(msg); + } fetchData(); }, []); return messages ? ( - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + ) :
Loading ...
diff --git a/packages/webapp/src/classes/app-i18n/index.ts b/packages/webapp/src/classes/app-i18n/index.ts new file mode 100644 index 00000000..612fab69 --- /dev/null +++ b/packages/webapp/src/classes/app-i18n/index.ts @@ -0,0 +1,70 @@ +export class Locale { + code: LocaleCode; + label: string; + + constructor(code: LocaleCode, label: string) { + this.code = code; + this.label = label; + } +} + +export default class AppI18n { + private locale: Locale = Locales.EN; + + constructor(localeCode: string) { + try { + this.locale = localeFromStr(localeCode) + } catch { + this.locale = this.browserLocale(); + } + } + + getLocale(): Locale { + return this.locale; + } + + resourceBundle(): string { + return `./compiled-lang/${this.locale.code}.json`; + } + + private browserLocale(): Locale { + let localeCode = (navigator.languages && navigator.languages[0]) + || navigator.language; + + // Just remove the variant ... + localeCode = localeCode.split('-')[0]; + + let result = Locales.EN; + try { + result = localeFromStr(localeCode) + } catch { + console.warn(`Unsupported languange code ${localeCode}`); + } + + return result; + } +} + +export type LocaleCode = 'en' | 'es' | 'fr' | 'de'; + +export const Locales = +{ + EN: new Locale('en', 'English'), + ES: new Locale('es', 'Español'), + DE: new Locale('de', 'Français'), + FR: new Locale('fr', 'Deutsch'), +} + +export const localeFromStr = (code: string): Locale => { + const locales: Locale[] = Object + .values(Locales); + + const result = locales + .find((l) => l.code == code); + + if (!result) { + throw `Langunage code could not be found in list of default supported: + ${code}` + } + + return result; +} \ No newline at end of file diff --git a/packages/webapp/src/classes/app-locale/index.ts b/packages/webapp/src/classes/app-locale/index.ts deleted file mode 100644 index 7684abde..00000000 --- a/packages/webapp/src/classes/app-locale/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -export class Locale { - code: LocaleCode; - label: string; - - constructor(code: LocaleCode) { - this.code = code; - - const label = LocalToStr.get(code); - this.label = label ? label : 'Undefined'; - } -} - -export default class AppLocale { - - private localeCode: LocaleCode = 'en'; - - constructor(locale?: LocaleCode) { - this.localeCode = locale ? locale : this.defaultLocale(); - } - - toString(): string { - const result = LocalToStr.get(this.localeCode); - if (result == null) { - throw `Locale could not be translated: ${this.localeCode}` - } - return result ? result : 'Undefined'; - } - - private defaultLocale(): LocaleCode { - const browserLocale = (navigator.languages && navigator.languages[0]) - || navigator.language; - - // Is a supported language ? - let result:LocaleCode = 'en'; - if (LocalToStr.get(browserLocale as LocaleCode)) { - result = browserLocale as LocaleCode; - } - - return result; - } -} -const LocalToStr = new Map([["en", "English"], ["es", "Español"], ["fr", "Français"], ["de", "Deutsch"]]); -export type LocaleCode = 'en' | 'es' | 'fr' | 'de'; - -export const Locales = -{ - EN: new Locale('en'), - ES: new Locale('es'), - DE: new Locale('de'), - FR: new Locale('fr'), -} \ No newline at end of file diff --git a/packages/webapp/src/classes/client/index.ts b/packages/webapp/src/classes/client/index.ts index e9595280..3c95cfc3 100644 --- a/packages/webapp/src/classes/client/index.ts +++ b/packages/webapp/src/classes/client/index.ts @@ -1,4 +1,4 @@ -import { LocaleCode } from "../app-locale" +import { Locale, LocaleCode } from "../app-i18n" export type NewUser = { email: string; @@ -61,7 +61,7 @@ export type AccountInfo = { firstName: string; lastName: string; email: string; - language: LocaleCode; + locale: Locale; } interface Client { diff --git a/packages/webapp/src/classes/client/mock-client/index.ts b/packages/webapp/src/classes/client/mock-client/index.ts index efe0fec2..6127b979 100644 --- a/packages/webapp/src/classes/client/mock-client/index.ts +++ b/packages/webapp/src/classes/client/mock-client/index.ts @@ -1,6 +1,5 @@ -import { Language } from '@material-ui/icons'; import Client, { AccountInfo, BasicMapInfo, ChangeHistory, ImportMapInfo, Label, MapInfo, NewUser } from '..'; -import { LocaleCode } from '../../app-locale'; +import { LocaleCode, localeFromStr, Locales } from '../../app-i18n'; class MockClient implements Client { private maps: MapInfo[] = []; private labels: Label[] = []; @@ -51,11 +50,12 @@ class MockClient implements Client { firstName: 'Costme', lastName: 'Fulanito', email: 'test@example.com', - language: locale ? locale : 'en' + locale: localeFromStr(locale) }); } + deleteMaps(ids: number[]): Promise { - ids.forEach(id => this.deleteMap(id)); + ids.forEach(id => this.deleteMap(id)); return Promise.resolve(); } revertHistory(id: number, cid: number): Promise { diff --git a/packages/webapp/src/classes/client/rest-client/index.ts b/packages/webapp/src/classes/client/rest-client/index.ts index 6b8c260f..437c02c8 100644 --- a/packages/webapp/src/classes/client/rest-client/index.ts +++ b/packages/webapp/src/classes/client/rest-client/index.ts @@ -1,6 +1,6 @@ import axios from 'axios'; import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label, ChangeHistory, AccountInfo, ImportMapInfo } from '..'; -import { LocaleCode } from '../../app-locale'; +import { LocaleCode, localeFromStr, Locales } from '../../app-i18n'; export default class RestClient implements Client { private baseUrl: string; @@ -45,7 +45,7 @@ export default class RestClient implements Client { lastName: account.lastName ? account.lastName : '', firstName: account.fistName ? account.fistName : '', email: account.email, - language: locale ? locale : 'en' + locale: locale ? localeFromStr(locale) : Locales.EN }); }).catch(error => { const errorInfo = this.parseResponseOnError(error.response); diff --git a/packages/webapp/src/components/maps-page/language-menu/index.tsx b/packages/webapp/src/components/maps-page/language-menu/index.tsx index 3691c561..2ac17f4f 100644 --- a/packages/webapp/src/components/maps-page/language-menu/index.tsx +++ b/packages/webapp/src/components/maps-page/language-menu/index.tsx @@ -6,7 +6,7 @@ import Client, { ErrorInfo, AccountInfo } from "../../../classes/client"; import { useSelector } from 'react-redux'; import { activeInstance } from '../../../redux/clientSlice'; import { FormattedMessage, useIntl } from 'react-intl'; -import AppLocale, { LocaleCode, Locales } from '../../../classes/app-locale'; +import AppI18n, { LocaleCode, Locales } from '../../../classes/app-i18n'; @@ -44,7 +44,7 @@ const LanguageMenu = () => { return client.fetchAccountInfo(); }); - const locale = new AppLocale(data?.language); + const locale = data?.locale; return ( @@ -56,7 +56,7 @@ const LanguageMenu = () => { onClick={handleMenu} startIcon={} > - {locale.toString()} + {locale?.label}