mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-22 14:47:56 +01:00
Complete i18n support
This commit is contained in:
parent
77e3d24eb1
commit
ca833d60de
@ -5,8 +5,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="<%=PUBLIC_URL%>/favicon.ico" />
|
<link rel="icon" href="<%=PUBLIC_URL%>/favicon.ico" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" rel="stylesheet" />
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
|
@ -25,8 +25,8 @@ const queryClient = new QueryClient({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [appi18n, setAppi18n] = useState<AppI18n>(new AppI18n('es'));
|
const appi18n = new AppI18n();
|
||||||
const locale = appi18n.getLocale();
|
const locale = appi18n.getBrowserLocale();
|
||||||
|
|
||||||
return locale.message ? (
|
return locale.message ? (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { fetchAccount } from './../../redux/clientSlice';
|
||||||
|
|
||||||
export class Locale {
|
export class Locale {
|
||||||
code: LocaleCode;
|
code: LocaleCode;
|
||||||
label: string;
|
label: string;
|
||||||
@ -11,21 +13,17 @@ export class Locale {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class AppI18n {
|
export default class AppI18n {
|
||||||
private locale: Locale = Locales.EN;
|
|
||||||
|
|
||||||
constructor(localeCode: string) {
|
constructor() {
|
||||||
try {
|
|
||||||
this.locale = localeFromStr(localeCode)
|
|
||||||
} catch {
|
|
||||||
this.locale = this.browserLocale();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getLocale(): Locale {
|
public getUserLocale(): Locale {
|
||||||
return this.locale;
|
const account = fetchAccount();
|
||||||
|
return account ? account.locale : this.getBrowserLocale();
|
||||||
}
|
}
|
||||||
|
|
||||||
private browserLocale(): Locale {
|
public getBrowserLocale(): Locale {
|
||||||
let localeCode = (navigator.languages && navigator.languages[0])
|
let localeCode = (navigator.languages && navigator.languages[0])
|
||||||
|| navigator.language;
|
|| navigator.language;
|
||||||
|
|
||||||
@ -49,8 +47,8 @@ export const Locales =
|
|||||||
{
|
{
|
||||||
EN: new Locale('en', 'English', require('./../../compiled-lang/en.json')),
|
EN: new Locale('en', 'English', require('./../../compiled-lang/en.json')),
|
||||||
ES: new Locale('es', 'Español', require('./../../compiled-lang/es.json')),
|
ES: new Locale('es', 'Español', require('./../../compiled-lang/es.json')),
|
||||||
DE: new Locale('de', 'Français', require('./../../compiled-lang/de.json')),
|
DE: new Locale('fr', 'Français', require('./../../compiled-lang/fr.json')),
|
||||||
FR: new Locale('fr', 'Deutsch', require('./../../compiled-lang/fr.json')),
|
FR: new Locale('de', 'Deutsch', require('./../../compiled-lang/de.json')),
|
||||||
}
|
}
|
||||||
|
|
||||||
export const localeFromStr = (code: string): Locale => {
|
export const localeFromStr = (code: string): Locale => {
|
||||||
|
@ -45,6 +45,7 @@ class MockClient implements Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchAccountInfo(): Promise<AccountInfo> {
|
fetchAccountInfo(): Promise<AccountInfo> {
|
||||||
|
console.log('Fetch account info ...')
|
||||||
const locale: LocaleCode | null = localStorage.getItem('locale') as LocaleCode;
|
const locale: LocaleCode | null = localStorage.getItem('locale') as LocaleCode;
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
firstName: 'Costme',
|
firstName: 'Costme',
|
||||||
|
@ -12,7 +12,19 @@ export default class RestClient implements Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
||||||
throw "Method not implemented";
|
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||||
|
axios.put(`${this.baseUrl}/c/restful/account/locale`,
|
||||||
|
locale,
|
||||||
|
{ headers: { 'Content-Type': 'text/plain' } }
|
||||||
|
).then(() => {
|
||||||
|
// All was ok, let's sent to success page ...;
|
||||||
|
success();
|
||||||
|
}).catch(error => {
|
||||||
|
const errorInfo = this.parseResponseOnError(error.response);
|
||||||
|
reject(errorInfo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Promise(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
importMap(model: ImportMapInfo): Promise<number> {
|
importMap(model: ImportMapInfo): Promise<number> {
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
"action.new": [
|
"action.new": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
"value": "New Map"
|
"value": "New Map German"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"action.open": [
|
"action.open": [
|
||||||
|
@ -22,6 +22,7 @@ import AccountMenu from './account-menu';
|
|||||||
import ClientHealthSentinel from '../../classes/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';
|
||||||
|
import AppI18n, { Locales } from '../../classes/app-i18n';
|
||||||
|
|
||||||
const logoIcon = require('../../images/logo-small.svg');
|
const logoIcon = require('../../images/logo-small.svg');
|
||||||
const poweredByIcon = require('../../images/pwrdby-white.svg');
|
const poweredByIcon = require('../../images/pwrdby-white.svg');
|
||||||
@ -107,94 +108,100 @@ const MapsPage = () => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
// Configure using user settings ...
|
||||||
|
const appi18n = new AppI18n();
|
||||||
|
const userLocale = appi18n.getUserLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<IntlProvider locale={userLocale.code} defaultLocale={Locales.EN.code} messages={userLocale.message} >
|
||||||
<ClientHealthSentinel />
|
<div className={classes.root}>
|
||||||
<AppBar
|
<ClientHealthSentinel />
|
||||||
position="fixed"
|
<AppBar
|
||||||
className={clsx(classes.appBar, {
|
position="fixed"
|
||||||
[classes.appBarShift]: open,
|
className={clsx(classes.appBar, {
|
||||||
})}
|
[classes.appBarShift]: open,
|
||||||
variant='outlined'
|
})}
|
||||||
elevation={0}>
|
variant='outlined'
|
||||||
|
elevation={0}>
|
||||||
|
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Tooltip title={intl.formatMessage({ id: 'maps.create-tooltip', defaultMessage: 'Create a New Map' })}>
|
<Tooltip title={intl.formatMessage({ id: 'maps.create-tooltip', defaultMessage: 'Create a New Map' })}>
|
||||||
<Button color="primary"
|
<Button color="primary"
|
||||||
size="medium"
|
size="medium"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
type="button"
|
type="button"
|
||||||
disableElevation={true}
|
disableElevation={true}
|
||||||
startIcon={<AddCircleTwoTone />}
|
startIcon={<AddCircleTwoTone />}
|
||||||
className={classes.newMapButton}
|
className={classes.newMapButton}
|
||||||
onClick={() => setActiveDialog('create')}>
|
onClick={() => setActiveDialog('create')}>
|
||||||
<FormattedMessage id="action.new" defaultMessage="New Map" />
|
<FormattedMessage id="action.new" defaultMessage="New Map" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip title={intl.formatMessage({ id: 'maps.import-desc', defaultMessage: 'Import from other tools' })}>
|
<Tooltip title={intl.formatMessage({ id: 'maps.import-desc', defaultMessage: 'Import from other tools' })}>
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
size="medium"
|
size="medium"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
type="button"
|
type="button"
|
||||||
disableElevation={true}
|
disableElevation={true}
|
||||||
startIcon={<CloudUploadTwoTone />}
|
startIcon={<CloudUploadTwoTone />}
|
||||||
className={classes.importButton}
|
className={classes.importButton}
|
||||||
onClick={() => setActiveDialog('import')}>
|
onClick={() => setActiveDialog('import')}>
|
||||||
<FormattedMessage id="action.import" defaultMessage="Import" />
|
<FormattedMessage id="action.import" defaultMessage="Import" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<ActionDispatcher action={activeDialog} onClose={() => setActiveDialog(undefined)} mapsId={[]} />
|
<ActionDispatcher action={activeDialog} onClose={() => setActiveDialog(undefined)} mapsId={[]} />
|
||||||
|
|
||||||
<div className={classes.rightButtonGroup}>
|
<div className={classes.rightButtonGroup}>
|
||||||
<LanguageMenu />
|
<LanguageMenu />
|
||||||
<HelpMenu />
|
<HelpMenu />
|
||||||
<AccountMenu />
|
<AccountMenu />
|
||||||
</div>
|
</div>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
<Drawer
|
<Drawer
|
||||||
variant="permanent"
|
variant="permanent"
|
||||||
className={clsx(classes.drawer, {
|
className={clsx(classes.drawer, {
|
||||||
[classes.drawerOpen]: open
|
|
||||||
})}
|
|
||||||
classes={{
|
|
||||||
paper: clsx({
|
|
||||||
[classes.drawerOpen]: open
|
[classes.drawerOpen]: open
|
||||||
}),
|
})}
|
||||||
}}>
|
classes={{
|
||||||
|
paper: clsx({
|
||||||
|
[classes.drawerOpen]: open
|
||||||
|
}),
|
||||||
|
}}>
|
||||||
|
|
||||||
<div style={{ padding: "20px 0 20px 15px" }}>
|
<div style={{ padding: "20px 0 20px 15px" }}>
|
||||||
<img src={logoIcon} alt="logo" />
|
<img src={logoIcon} alt="logo" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<List component="nav">
|
<List component="nav">
|
||||||
{filterButtons.map(buttonInfo => {
|
{filterButtons.map(buttonInfo => {
|
||||||
return (<StyleListItem
|
return (<StyleListItem
|
||||||
icon={buttonInfo.icon}
|
icon={buttonInfo.icon}
|
||||||
label={buttonInfo.label}
|
label={buttonInfo.label}
|
||||||
filter={buttonInfo.filter}
|
filter={buttonInfo.filter}
|
||||||
active={filter}
|
active={filter}
|
||||||
onClick={handleMenuClick}
|
onClick={handleMenuClick}
|
||||||
onDelete={handleLabelDelete}
|
onDelete={handleLabelDelete}
|
||||||
key={`${buttonInfo.filter.type}:${(buttonInfo.filter as LabelFilter).label}`}
|
key={`${buttonInfo.filter.type}:${(buttonInfo.filter as LabelFilter).label}`}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<div style={{ position: 'absolute', bottom: '10px', left: '20px' }}>
|
<div style={{ position: 'absolute', bottom: '10px', left: '20px' }}>
|
||||||
<Link href="http://www.wisemapping.org/">
|
<Link href="http://www.wisemapping.org/">
|
||||||
<img src={poweredByIcon} alt="Powered By WiseMapping" />
|
<img src={poweredByIcon} alt="Powered By WiseMapping" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<main className={classes.content}>
|
<main className={classes.content}>
|
||||||
<div className={classes.toolbar} />
|
<div className={classes.toolbar} />
|
||||||
<MapsList filter={filter} />
|
<MapsList filter={filter} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
</IntlProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user