diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2021-09-02 20:33:23 -0700 |
---|---|---|
committer | Anton Tananaev <anton.tananaev@gmail.com> | 2021-09-02 20:33:23 -0700 |
commit | e07d5ff079527da0c07c4f8ede0aaef272517393 (patch) | |
tree | 1941791e4b8ab4b98c3eeefb5e0d00b34ff1bec0 | |
parent | 2b34c3d6c00c29b1590403e5d62e18b91145abcc (diff) | |
parent | 363198118bba28ad3a37e200a7db2ca02bf2eae7 (diff) | |
download | trackermap-web-e07d5ff079527da0c07c4f8ede0aaef272517393.tar.gz trackermap-web-e07d5ff079527da0c07c4f8ede0aaef272517393.tar.bz2 trackermap-web-e07d5ff079527da0c07c4f8ede0aaef272517393.zip |
Merge into oyhan-master
-rw-r--r-- | modern/src/App.js | 87 | ||||
-rw-r--r-- | modern/src/common/localization.js | 45 | ||||
-rw-r--r-- | modern/src/components/registration/LoginForm.js | 21 |
3 files changed, 98 insertions, 55 deletions
diff --git a/modern/src/App.js b/modern/src/App.js index ac7cdb26..5143ad88 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -38,53 +38,56 @@ import ResetPasswordForm from './components/registration/ResetPasswordForm'; import theme from './theme'; import GeofencesPage from './GeofencesPage'; import GeofencePage from './GeofencePage'; +import { LocalizationProvider } from './common/localization'; const App = () => { const initialized = useSelector((state) => !!state.session.server && !!state.session.user); return ( - <ThemeProvider theme={theme}> - <CssBaseline /> - <SocketController /> - <CachingController /> - <Switch> - <Route exact path="/login" component={LoginForm} /> - <Route exact path="/register" component={RegisterForm} /> - <Route exact path="/reset-password" component={ResetPasswordForm} /> - <Route> - {!initialized ? (<LinearProgress />) : ( - <Switch> - <Route exact path="/" component={MainPage} /> - <Route exact path="/replay" component={ReplayPage} /> - <Route exact path="/position/:id?" component={PositionPage} /> - <Route exact path="/user/:id?" component={UserPage} /> - <Route exact path="/device/:id?" component={DevicePage} /> - <Route exact path="/geofence/:id?" component={GeofencePage} /> - <Route exact path="/geofences" component={GeofencesPage} /> - <Route exact path="/settings/notifications" component={NotificationsPage} /> - <Route exact path="/settings/notification/:id?" component={NotificationPage} /> - <Route exact path="/settings/groups" component={GroupsPage} /> - <Route exact path="/settings/group/:id?" component={GroupPage} /> - <Route exact path="/settings/drivers" component={DriversPage} /> - <Route exact path="/settings/driver/:id?" component={DriverPage} /> - <Route exact path="/settings/attributes" component={ComputedAttributesPage} /> - <Route exact path="/settings/attribute/:id?" component={ComputedAttributePage} /> - <Route exact path="/settings/maintenances" component={MaintenancesPage} /> - <Route exact path="/settings/maintenance/:id?" component={MaintenancePage} /> - <Route exact path="/admin/server" component={ServerPage} /> - <Route exact path="/admin/users" component={UsersPage} /> - <Route exact path="/admin/statistics" component={StatisticsPage} /> - <Route exact path="/reports/route" component={RouteReportPage} /> - <Route exact path="/reports/event" component={EventReportPage} /> - <Route exact path="/reports/trip" component={TripReportPage} /> - <Route exact path="/reports/stop" component={StopReportPage} /> - <Route exact path="/reports/summary" component={SummaryReportPage} /> - <Route exact path="/reports/chart" component={ChartReportPage} /> - </Switch> - )} - </Route> - </Switch> - </ThemeProvider> + <LocalizationProvider> + <ThemeProvider theme={theme}> + <CssBaseline /> + <SocketController /> + <CachingController /> + <Switch> + <Route exact path="/login" component={LoginForm} /> + <Route exact path="/register" component={RegisterForm} /> + <Route exact path="/reset-password" component={ResetPasswordForm} /> + <Route> + {!initialized ? (<LinearProgress />) : ( + <Switch> + <Route exact path="/" component={MainPage} /> + <Route exact path="/replay" component={ReplayPage} /> + <Route exact path="/position/:id?" component={PositionPage} /> + <Route exact path="/user/:id?" component={UserPage} /> + <Route exact path="/device/:id?" component={DevicePage} /> + <Route exact path="/geofence/:id?" component={GeofencePage} /> + <Route exact path="/geofences" component={GeofencesPage} /> + <Route exact path="/settings/notifications" component={NotificationsPage} /> + <Route exact path="/settings/notification/:id?" component={NotificationPage} /> + <Route exact path="/settings/groups" component={GroupsPage} /> + <Route exact path="/settings/group/:id?" component={GroupPage} /> + <Route exact path="/settings/drivers" component={DriversPage} /> + <Route exact path="/settings/driver/:id?" component={DriverPage} /> + <Route exact path="/settings/attributes" component={ComputedAttributesPage} /> + <Route exact path="/settings/attribute/:id?" component={ComputedAttributePage} /> + <Route exact path="/settings/maintenances" component={MaintenancesPage} /> + <Route exact path="/settings/maintenance/:id?" component={MaintenancePage} /> + <Route exact path="/admin/server" component={ServerPage} /> + <Route exact path="/admin/users" component={UsersPage} /> + <Route exact path="/admin/statistics" component={StatisticsPage} /> + <Route exact path="/reports/route" component={RouteReportPage} /> + <Route exact path="/reports/event" component={EventReportPage} /> + <Route exact path="/reports/trip" component={TripReportPage} /> + <Route exact path="/reports/stop" component={StopReportPage} /> + <Route exact path="/reports/summary" component={SummaryReportPage} /> + <Route exact path="/reports/chart" component={ChartReportPage} /> + </Switch> + )} + </Route> + </Switch> + </ThemeProvider> + </LocalizationProvider> ); }; diff --git a/modern/src/common/localization.js b/modern/src/common/localization.js index 9e2123a9..90a5739a 100644 --- a/modern/src/common/localization.js +++ b/modern/src/common/localization.js @@ -1,3 +1,5 @@ +import React, { useState, createContext, useContext } from "react"; + import af from '../../../web/l10n/af.json'; import ar from '../../../web/l10n/ar.json'; import az from '../../../web/l10n/az.json'; @@ -110,8 +112,9 @@ const supportedLanguages = { zh_TW: { data: zh_TW, name: '中文 (Taiwan)' }, }; -const languages = window.navigator.languages !== undefined ? window.navigator.languages.slice() : []; -let language = window.navigator.userLanguage || window.navigator.language; +const languageList = Object.entries(supportedLanguages).map((values) => ({ code: values[0], name: values[1].name })); +const languages = localStorage.getItem('language') ? [localStorage.getItem('language')] : (window.navigator.languages !== undefined ? window.navigator.languages.slice() : []); +let language = localStorage.getItem('language') || window.navigator.userLanguage || window.navigator.language; languages.push(language); languages.push(language.substring(0, 2)); languages.push('en'); @@ -128,8 +131,40 @@ for (let i = 0; i < languages.length; i++) { } } -const selectedLanguage = supportedLanguages[language]; +let selectedLanguage = supportedLanguages[language]; + +export const findStringKeys = (predicate) => { + return Object.keys(selectedLanguage.data).filter(predicate); +} + +export default key => { + return selectedLanguage.data[key]; +}; + +const setSelectedLanguage = (language) => { + selectedLanguage = supportedLanguages[language]; + localStorage.setItem('language', language); +} + +const defaultLanguage = language; + +const LocalizationContext = createContext({ + language +}); -export const findStringKeys = (predicate) => Object.keys(selectedLanguage.data).filter(predicate); +export function LocalizationProvider(props) { + const [language, setLanguage] = useState(defaultLanguage); + + const handleLanguageChange = (nextLanguage) => { + setSelectedLanguage(nextLanguage); + setLanguage(nextLanguage); + }; + + return <LocalizationContext.Provider value={{ language, setLanguage: handleLanguageChange, languageList }}> + {props.children} + </LocalizationContext.Provider> +} -export default (key) => selectedLanguage.data[key]; +export const useLocalization = () => { + return useContext(LocalizationContext); +}
\ No newline at end of file diff --git a/modern/src/components/registration/LoginForm.js b/modern/src/components/registration/LoginForm.js index e6da05e3..9b5ca3ed 100644 --- a/modern/src/components/registration/LoginForm.js +++ b/modern/src/components/registration/LoginForm.js @@ -6,7 +6,7 @@ import { useTheme } from '@material-ui/core/styles'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { sessionActions } from '../../store'; -import t from '../../common/localization'; +import t, { useLocalization } from '../../common/localization'; import StartPage from '../../StartPage'; const useStyles = makeStyles((theme) => ({ @@ -24,6 +24,7 @@ const LoginForm = () => { const dispatch = useDispatch(); const history = useHistory(); const theme = useTheme(); + const { language, languageList, setLanguage } = useLocalization(); const [failed, setFailed] = useState(false); const [email, setEmail] = useState(''); @@ -61,16 +62,20 @@ const LoginForm = () => { } }; + const handleLanguageChange = (e) => { + setLanguage(e.target.value); + }; + return ( <StartPage> <Grid container direction="column" spacing={2}> {useMediaQuery(theme.breakpoints.down('md')) && ( - <Grid item className={classes.logoContainer}> - <svg height="64" width="240"> - <use xlinkHref="/logo.svg#img" /> - </svg> - </Grid> + <Grid item className={classes.logoContainer}> + <svg height="64" width="240"> + <use xlinkHref="/logo.svg#img" /> + </svg> + </Grid> )} <Grid item> <TextField @@ -124,8 +129,8 @@ const LoginForm = () => { <Grid item xs> <FormControl variant="filled" fullWidth> <InputLabel>{t('loginLanguage')}</InputLabel> - <Select> - <MenuItem value="en">English</MenuItem> + <Select value={language} onChange={handleLanguageChange}> + {languageList.map((lang) => <MenuItem key={lang.code} value={lang.code}>{lang.name}</MenuItem>)} </Select> </FormControl> </Grid> |