Refactor locale class

This commit is contained in:
Paulo Gustavo Veiga 2021-02-12 19:03:47 -08:00
parent d57cec6f80
commit 6091b6a7ad
25 changed files with 95 additions and 41 deletions

View File

@ -0,0 +1,51 @@
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<LocaleCode, string>([["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'),
}

View File

@ -1,6 +1,6 @@
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import React from "react"; import React from "react";
import { activeInstanceStatus, ClientStatus } from '../../redux/clientSlice'; import { activeInstanceStatus, ClientStatus } from '../../../redux/clientSlice';
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@material-ui/core'; import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@material-ui/core';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Alert, AlertTitle } from '@material-ui/lab'; import { Alert, AlertTitle } from '@material-ui/lab';

View File

@ -1,3 +1,5 @@
import { LocaleCode } from "../app-locale"
export type NewUser = { export type NewUser = {
email: string; email: string;
firstname: string; firstname: string;
@ -62,8 +64,6 @@ export type AccountInfo = {
language: LocaleCode; language: LocaleCode;
} }
export type LocaleCode = 'en' | 'es' | 'fr' | 'de';
interface Client { interface Client {
importMap(model: ImportMapInfo): Promise<number> importMap(model: ImportMapInfo): Promise<number>
createMap(map: BasicMapInfo): Promise<number>; createMap(map: BasicMapInfo): Promise<number>;

View File

@ -1,5 +1,6 @@
import { Language } from '@material-ui/icons'; import { Language } from '@material-ui/icons';
import Client, { AccountInfo, BasicMapInfo, ChangeHistory, ImportMapInfo, Label, LocaleCode, MapInfo, NewUser } from '..'; import Client, { AccountInfo, BasicMapInfo, ChangeHistory, ImportMapInfo, Label, MapInfo, NewUser } from '..';
import { LocaleCode } from '../../app-locale';
class MockClient implements Client { class MockClient implements Client {
private maps: MapInfo[] = []; private maps: MapInfo[] = [];
private labels: Label[] = []; private labels: Label[] = [];

View File

@ -1,5 +1,6 @@
import axios from 'axios'; import axios from 'axios';
import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label, ChangeHistory, AccountInfo, ImportMapInfo, LocaleCode } from '..'; import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label, ChangeHistory, AccountInfo, ImportMapInfo } from '..';
import { LocaleCode } from '../../app-locale';
export default class RestClient implements Client { export default class RestClient implements Client {
private baseUrl: string; private baseUrl: string;

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { FormattedMessage, useIntl } from 'react-intl' import { FormattedMessage, useIntl } from 'react-intl'
import { useHistory } from 'react-router-dom' import { useHistory } from 'react-router-dom'
import Client, { ErrorInfo } from '../../client' import Client, { ErrorInfo } from '../../classes/client'
import Header from '../layout/header' import Header from '../layout/header'
import Footer from '../layout/footer' import Footer from '../layout/footer'

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { ErrorInfo } from "../../../client" import { ErrorInfo } from "../../../classes/client"
import StyledAlert from "./styled"; import StyledAlert from "./styled";

View File

@ -1,7 +1,7 @@
import { TextField } from "@material-ui/core"; import { TextField } from "@material-ui/core";
import React, { ChangeEvent } from "react"; import React, { ChangeEvent } from "react";
import { MessageDescriptor, useIntl } from "react-intl"; import { MessageDescriptor, useIntl } from "react-intl";
import { ErrorInfo } from "../../../client"; import { ErrorInfo } from "../../../classes/client";
type InputProps = { type InputProps = {
name: string; name: string;

View File

@ -3,7 +3,7 @@ import { AccountCircle, ExitToAppOutlined, SettingsApplicationsOutlined } from '
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { useQuery, useQueryClient } from "react-query"; import { useQuery, useQueryClient } from "react-query";
import Client, { ErrorInfo, AccountInfo } from "../../../client"; import Client, { ErrorInfo, AccountInfo } from "../../../classes/client";
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { activeInstance } from '../../../redux/clientSlice'; import { activeInstance } from '../../../redux/clientSlice';

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { Button, DialogContentText } from "@material-ui/core"; import { Button, DialogContentText } from "@material-ui/core";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { ErrorInfo } from "../../../../client"; import { ErrorInfo } from "../../../../classes/client";
import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTitle } from "./style"; import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTitle } from "./style";
import GlobalError from "../../../form/global-error"; import GlobalError from "../../../form/global-error";

View File

@ -5,7 +5,7 @@ import { useSelector } from 'react-redux';
import { FormControl } from '@material-ui/core'; import { FormControl } from '@material-ui/core';
import Client, { BasicMapInfo, ErrorInfo } from '../../../../client'; import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import Input from '../../../form/input'; import Input from '../../../form/input';
import BaseDialog from '../base-dialog'; import BaseDialog from '../base-dialog';

View File

@ -3,7 +3,7 @@ import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Client from "../../../../client"; import Client from "../../../../classes/client";
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import { SimpleDialogProps, fetchMapById, handleOnMutationSuccess } from ".."; import { SimpleDialogProps, fetchMapById, handleOnMutationSuccess } from "..";
import BaseDialog from "../base-dialog"; import BaseDialog from "../base-dialog";

View File

@ -3,7 +3,7 @@ import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Client from "../../../../client"; import Client from "../../../../classes/client";
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import { handleOnMutationSuccess } from ".."; import { handleOnMutationSuccess } from "..";
import BaseDialog from "../base-dialog"; import BaseDialog from "../base-dialog";

View File

@ -4,7 +4,7 @@ import { useMutation, useQueryClient } from "react-query";
import { FormControl } from "@material-ui/core"; import { FormControl } from "@material-ui/core";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Client, { BasicMapInfo, ErrorInfo } from "../../../../client"; import Client, { BasicMapInfo, ErrorInfo } from "../../../../classes/client";
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import Input from "../../../form/input"; import Input from "../../../form/input";
import { SimpleDialogProps, fetchMapById } from ".."; import { SimpleDialogProps, fetchMapById } from "..";

View File

@ -2,7 +2,7 @@ import React, { ErrorInfo } from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { useQuery } from "react-query"; import { useQuery } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Client, { ChangeHistory } from "../../../../client"; import Client, { ChangeHistory } from "../../../../classes/client";
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import { SimpleDialogProps } from ".."; import { SimpleDialogProps } from "..";
import BaseDialog from "../base-dialog"; import BaseDialog from "../base-dialog";

View File

@ -5,7 +5,7 @@ import { useSelector } from 'react-redux';
import { Button, FormControl } from '@material-ui/core'; import { Button, FormControl } from '@material-ui/core';
import Client, { BasicMapInfo, ErrorInfo } from '../../../../client'; import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import Input from '../../../form/input'; import Input from '../../../form/input';
import BaseDialog from '../base-dialog'; import BaseDialog from '../base-dialog';

View File

@ -2,9 +2,9 @@ import React from 'react';
import RenameDialog from './rename-dialog'; import RenameDialog from './rename-dialog';
import DeleteDialog from './delete-dialog'; import DeleteDialog from './delete-dialog';
import { ActionType } from '../action-chooser'; import { ActionType } from '../action-chooser';
import { ErrorInfo, MapInfo } from '../../../client'; import { ErrorInfo, MapInfo } from '../../../classes/client';
import Client from '../../../client'; import Client from '../../../classes/client';
import { useSelector } from "react-redux"; import { useSelector } from 'react-redux';
import { QueryClient, useQuery } from 'react-query'; import { QueryClient, useQuery } from 'react-query';
import { activeInstance } from '../../../redux/clientSlice'; import { activeInstance } from '../../../redux/clientSlice';
import DuplicateDialog from './duplicate-dialog'; import DuplicateDialog from './duplicate-dialog';

View File

@ -3,7 +3,7 @@ import { FormattedMessage, useIntl } from 'react-intl';
import { Card, List, ListItem, Paper, Typography } from '@material-ui/core'; import { Card, List, ListItem, Paper, Typography } from '@material-ui/core';
import { ErrorInfo } from '../../../../client'; import { ErrorInfo } from '../../../../classes/client';
import BaseDialog from '../base-dialog'; import BaseDialog from '../base-dialog';
import { fetchMapById, SimpleDialogProps } from '..'; import { fetchMapById, SimpleDialogProps } from '..';
import { useStyles } from './style'; import { useStyles } from './style';

View File

@ -5,7 +5,7 @@ import { useSelector } from 'react-redux';
import { AppBar, Checkbox, FormControl, FormControlLabel, Tab, TextareaAutosize, Typography } from '@material-ui/core'; import { AppBar, Checkbox, FormControl, FormControlLabel, Tab, TextareaAutosize, Typography } from '@material-ui/core';
import Client, { ErrorInfo } from '../../../../client'; import Client, { ErrorInfo } from '../../../../classes/client';
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import BaseDialog from '../base-dialog'; import BaseDialog from '../base-dialog';
import { TabContext, TabList, TabPanel } from '@material-ui/lab'; import { TabContext, TabList, TabPanel } from '@material-ui/lab';

View File

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Client, { BasicMapInfo, ErrorInfo } from "../../../../client"; import Client, { BasicMapInfo, ErrorInfo } from "../../../../classes/client";
import { activeInstance } from '../../../../redux/clientSlice'; import { activeInstance } from '../../../../redux/clientSlice';
import { SimpleDialogProps, fetchMapById, handleOnMutationSuccess } from ".."; import { SimpleDialogProps, fetchMapById, handleOnMutationSuccess } from "..";
import Input from "../../../form/input"; import Input from "../../../form/input";

View File

@ -15,11 +15,11 @@ import { FormattedMessage, useIntl } from 'react-intl';
import { useQuery, useMutation, useQueryClient } from 'react-query'; import { useQuery, useMutation, useQueryClient } from 'react-query';
import { activeInstance } from '../../redux/clientSlice'; import { activeInstance } from '../../redux/clientSlice';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import Client, { Label } from '../../client'; import Client, { Label } from '../../classes/client';
import ActionDispatcher from './action-dispatcher'; import ActionDispatcher from './action-dispatcher';
import { ActionType } from './action-chooser'; import { ActionType } from './action-chooser';
import AccountMenu from './account-menu'; import AccountMenu from './account-menu';
import ClientHealthSentinel from '../../client/client-health-sentinel'; import ClientHealthSentinel from '../../classes/client/client-health-sentinel';
import HelpMenu from '../help-menu'; import HelpMenu from '../help-menu';
import LanguageMenu from './language-menu'; import LanguageMenu from './language-menu';

View File

@ -2,12 +2,12 @@ import { Button, Divider, Menu, MenuItem, Tooltip } from '@material-ui/core';
import { TranslateTwoTone } from '@material-ui/icons'; import { TranslateTwoTone } from '@material-ui/icons';
import React from "react"; import React from "react";
import { useMutation, useQuery, useQueryClient } from "react-query"; import { useMutation, useQuery, useQueryClient } from "react-query";
import Client, { ErrorInfo, AccountInfo, LocaleCode } from "../../../client"; import Client, { ErrorInfo, AccountInfo } from "../../../classes/client";
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { activeInstance } from '../../../redux/clientSlice'; import { activeInstance } from '../../../redux/clientSlice';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import AppLocale, { LocaleCode, Locales } from '../../../classes/app-locale';
const localeToStr = new Map<LocaleCode, string>([["en", "English"], ["es", "Español"], ["fr", "Français"], ["de", "Deutsch"]]);
const LanguageMenu = () => { const LanguageMenu = () => {
@ -44,6 +44,7 @@ const LanguageMenu = () => {
return client.fetchAccountInfo(); return client.fetchAccountInfo();
}); });
const locale = new AppLocale(data?.language);
return ( return (
<span> <span>
<Tooltip title={intl.formatMessage({ id: 'language.change', defaultMessage: 'Change Language' })}> <Tooltip title={intl.formatMessage({ id: 'language.change', defaultMessage: 'Change Language' })}>
@ -55,7 +56,7 @@ const LanguageMenu = () => {
onClick={handleMenu} onClick={handleMenu}
startIcon={<TranslateTwoTone />} startIcon={<TranslateTwoTone />}
> >
{localeToStr.get(data?.language ? data?.language : 'en')} {locale.toString()}
</Button> </Button>
</Tooltip> </Tooltip>
<Menu id="appbar-language" <Menu id="appbar-language"
@ -73,20 +74,20 @@ const LanguageMenu = () => {
horizontal: 'right', horizontal: 'right',
}} }}
> >
<MenuItem onClick={handleOnClick} id="en"> <MenuItem onClick={handleOnClick} id={Locales.EN.code}>
{localeToStr.get('en')} {Locales.EN.label}
</MenuItem> </MenuItem>
<MenuItem onClick={handleOnClick} id="es"> <MenuItem onClick={handleOnClick} id={Locales.ES.code}>
{localeToStr.get('es')} {Locales.ES.label}
</MenuItem> </MenuItem>
<MenuItem onClick={handleOnClick} id="fr"> <MenuItem onClick={handleOnClick} id={Locales.DE.code}>
{localeToStr.get('fr')} {Locales.DE.label}
</MenuItem> </MenuItem>
<MenuItem onClick={handleOnClick} id="de"> <MenuItem onClick={handleOnClick} id={Locales.FR.code}>
{localeToStr.get('de')} {Locales.FR.label}
</MenuItem> </MenuItem>
<Divider /> <Divider />

View File

@ -19,8 +19,8 @@ import MoreHorizIcon from '@material-ui/icons/MoreHoriz';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { activeInstance } from '../../../redux/clientSlice'; import { activeInstance } from '../../../redux/clientSlice';
import { useMutation, useQuery, useQueryClient } from 'react-query'; import { useMutation, useQuery, useQueryClient } from 'react-query';
import { ErrorInfo, MapInfo } from '../../../client'; import { ErrorInfo, MapInfo } from '../../../classes/client';
import Client from '../../../client'; import Client from '../../../classes/client';
import ActionChooser, { ActionType } from '../action-chooser'; import ActionChooser, { ActionType } from '../action-chooser';
import ActionDispatcher from '../action-dispatcher'; import ActionDispatcher from '../action-dispatcher';
import { Button, InputBase, Link } from '@material-ui/core'; import { Button, InputBase, Link } from '@material-ui/core';

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import ReCAPTCHA from 'react-google-recaptcha'; import ReCAPTCHA from 'react-google-recaptcha';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import Client , { ErrorInfo} from '../../client'; import Client , { ErrorInfo} from '../../classes/client';
import FormContainer from '../layout/form-container'; import FormContainer from '../layout/form-container';
import Header from '../layout/header'; import Header from '../layout/header';

View File

@ -1,7 +1,7 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import Client from '../client'; import Client from '../classes/client';
import MockClient from '../client/mock-client'; import MockClient from '../classes/client/mock-client';
import RestClient from '../client/rest-client'; import RestClient from '../classes/client/rest-client';
interface ConfigInfo { interface ConfigInfo {
apiBaseUrl: string apiBaseUrl: string