Skip to content

Commit

Permalink
feat(i18n): add react-intl and locale state (#130)
Browse files Browse the repository at this point in the history
* feat(i18n): add react-intl and local state

* feat(i18n): refetch layers when locale changes (#131)
  • Loading branch information
pwambach authored and KatvonRivia committed Oct 8, 2019
1 parent 197fcb9 commit 549f3eb
Show file tree
Hide file tree
Showing 16 changed files with 205 additions and 30 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-unused-vars": 2,
"react/prop-types": 0
}
}
4 changes: 4 additions & 0 deletions i18n/de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"layerSelector.main": "Haupt",
"layerSelector.compare": "Vergleich"
}
4 changes: 4 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"layerSelector.main": "Main",
"layerSelector.compare": "Compare"
}
81 changes: 75 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"cesium": "^1.61.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-intl": "^3.3.2",
"react-redux": "^7.1.1",
"redux": "^4.0.4",
"redux-logger": "^3.0.6",
Expand Down
13 changes: 9 additions & 4 deletions src/scripts/actions/fetch-layers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {Dispatch} from 'redux';
import config from '../config/main';

import fetchLayersApi from '../api/fetch-layers';
import {localeSelector} from '../reducers/locale';
import {State} from '../reducers/index';

export const FETCH_LAYERS_SUCCESS = 'FETCH_LAYERS_SUCCESS';
export const FETCH_LAYERS_ERROR = 'FETCH_LAYERS_ERROR';
Expand Down Expand Up @@ -40,10 +43,12 @@ function fetchLayersErrorAction(message: string) {
};
}

const fetchLayers = () => (dispatch: Dispatch) =>
fetch(config.api.layers)
.then(res => res.json())
const fetchLayers = () => (dispatch: Dispatch, getState: () => State) => {
const locale = localeSelector(getState());

return fetchLayersApi(locale)
.then(layers => dispatch(fetchLayersSuccessAction(layers)))
.catch(error => dispatch(fetchLayersErrorAction(error.message)));
};

export default fetchLayers;
31 changes: 31 additions & 0 deletions src/scripts/actions/set-locale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {ThunkDispatch} from 'redux-thunk';

import {State} from '../reducers/index';
import fetchLayers, {FetchLayersActions} from './fetch-layers';

export const SET_LOCALE = 'SET_LOCALE';

export enum Locale {
EN = 'en',
DE = 'de'
}

export interface SetLocaleAction {
type: typeof SET_LOCALE;
locale: Locale;
}

type AllThunkActions = SetLocaleAction | FetchLayersActions;

const setLocaleAction = (locale: Locale) => (
dispatch: ThunkDispatch<State, void, AllThunkActions>
) => {
dispatch({
type: SET_LOCALE,
locale
});

dispatch(fetchLayers());
};

export default setLocaleAction;
7 changes: 7 additions & 0 deletions src/scripts/api/fetch-layers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {Locale} from '../actions/set-locale';
import config from '../config/main';

export default function fetchLayers(locale: Locale) {
const url = `${config.api.layers}-${locale.toLowerCase()}.json`;
return fetch(url).then(res => res.json());
}
46 changes: 32 additions & 14 deletions src/scripts/components/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
import React, {FunctionComponent} from 'react';
import {createStore, applyMiddleware} from 'redux';
import {Provider} from 'react-redux';
import {Provider as StoreProvider, useSelector} from 'react-redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import {createLogger} from 'redux-logger';
import {IntlProvider} from 'react-intl';

import rootReducer from '../../reducers/index';
import {localeSelector} from '../../reducers/locale';
import LayerSelector from '../layer-selector/layer-selector';
import Globe from '../globe/globe';
import Menu from '../menu/menu';
import ProjectionMenu from '../projection-menu/projection-menu';

import translations from '../../i18n';
import styles from './app.styl';

const store = createStore(rootReducer, applyMiddleware(thunk, logger));
const store = createStore(
rootReducer,
applyMiddleware(thunk, createLogger({collapsed: true}))
);

const App: FunctionComponent<{}> = () => (
<Provider store={store}>
<div className={styles.app}>
<Globe />
<div className={styles.layoutContainer}>
<Menu />
<div className={styles.timeslider} />
<ProjectionMenu />
<LayerSelector />
</div>
</div>
</Provider>
<StoreProvider store={store}>
<TranslatedApp />
</StoreProvider>
);

const TranslatedApp: FunctionComponent<{}> = () => {
const locale = useSelector(localeSelector);

return (
<IntlProvider locale={locale} messages={translations[locale]}>
<div className={styles.app}>
<Globe />
<div className={styles.layoutContainer}>
<Menu />
<div className={styles.timeslider} />
<ProjectionMenu />
<LayerSelector />
</div>
</div>
</IntlProvider>
);
};

export default App;
7 changes: 5 additions & 2 deletions src/scripts/components/layer-selector/layer-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, {FunctionComponent, useEffect, useState} from 'react';
import {useSelector, useDispatch} from 'react-redux';
import {useIntl} from 'react-intl';

import {layersSelector} from '../../reducers/layers';
import {selectedLayerIdSelector} from '../../reducers/selected-layer-id';
import fetchLayers from '../../actions/fetch-layers';
Expand All @@ -9,17 +11,18 @@ import Tabs from '../tabs/tabs';
import styles from './layer-selector.styl';

const LayerSelector: FunctionComponent<{}> = () => {
const intl = useIntl();
const layers = useSelector(layersSelector);
const layerIds = useSelector(selectedLayerIdSelector);
const dispatch = useDispatch();
const tabs = [
{
id: 'main',
label: 'Main'
label: intl.formatMessage({id: 'layerSelector.main'})
},
{
id: 'compare',
label: 'Compare'
label: intl.formatMessage({id: 'layerSelector.compare'})
}
];

Expand Down
4 changes: 2 additions & 2 deletions src/scripts/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface MenuItem {
}

const Menu: FunctionComponent<{}> = () => {
const menuItems = [
const menuItems: MenuItem[] = [
{
id: 'presenter-mode',
name: 'Presenter Mode',
Expand All @@ -23,7 +23,7 @@ const Menu: FunctionComponent<{}> = () => {
{id: 'share', name: 'Share Content'},
{id: 'export', name: 'Export Data'},
{id: 'info', name: 'More Information'}
] as MenuItem[];
];

const [isOpen, setIsOpen] = useState(false);

Expand Down
2 changes: 1 addition & 1 deletion src/scripts/config/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default {
api: {
layers: 'https://storage.googleapis.com/esa-cfs-storage/layers.json'
layers: 'https://storage.googleapis.com/esa-cfs-storage/layers'
}
};
7 changes: 7 additions & 0 deletions src/scripts/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import en from '../../i18n/en.json';
import de from '../../i18n/de.json';

export default {
en,
de
};
2 changes: 2 additions & 0 deletions src/scripts/reducers/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {combineReducers} from 'redux';

import localeReducer from './locale';
import layersReducer from './layers';
import selectedLayerReducer from './selected-layer-id';
import projectionReducer from './projection';

const rootReducer = combineReducers({
locale: localeReducer,
layers: layersReducer,
selectedLayer: selectedLayerReducer,
projection: projectionReducer
Expand Down
22 changes: 22 additions & 0 deletions src/scripts/reducers/locale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {State} from './index';
import {SET_LOCALE, Locale, SetLocaleAction} from '../actions/set-locale';

const initialState: Locale = Locale.EN;

function localeReducer(
localeState: Locale = initialState,
action: SetLocaleAction
): Locale {
switch (action.type) {
case SET_LOCALE:
return action.locale;
default:
return localeState;
}
}

export function localeSelector(state: State): Locale {
return state.locale;
}

export default localeReducer;
Loading

0 comments on commit 549f3eb

Please sign in to comment.