Skip to content

Commit fc0da0a

Browse files
committed
[CE-343] Enable i18n in operator dashboard
Support language change in operator dashboard. Change-Id: Iae84884f919f554e2a46de14687e386dcd155b74 Signed-off-by: Haitao Yue <hightall@me.com>
1 parent 60ca1af commit fc0da0a

File tree

8 files changed

+97
-20
lines changed

8 files changed

+97
-20
lines changed

src/themes/react/static/dashboard/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"precommit": "npm run lint-staged",
88
"start": "cross-env ESLINT=none roadhog dev",
99
"start:no-proxy": "cross-env NO_PROXY=true ESLINT=none roadhog dev",
10-
"build": "cross-env ESLINT=none roadhog build",
10+
"build": "cross-env ESLINT=none COMPRESS=none roadhog build",
1111
"build:dev": "cross-env ESLINT=none COMPRESS=none roadhog build",
1212
"site": "roadhog-api-doc static && gh-pages -d dist",
1313
"analyze": "cross-env ANALYZE=true roadhog build",

src/themes/react/static/dashboard/src/common/menu.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
SPDX-License-Identifier: Apache-2.0
33
*/
44
import { IntlProvider, defineMessages } from 'react-intl';
5-
import { isUrl } from '../utils/utils';
6-
import enLocale from '../locales/en-US';
5+
import { isUrl, getLocale } from '../utils/utils';
76

8-
const intlProvider = new IntlProvider({ locale: enLocale.locale, messages: enLocale.messages }, {});
7+
const currentLocale = getLocale();
8+
const intlProvider = new IntlProvider(
9+
{ locale: currentLocale.locale, messages: currentLocale.messages },
10+
{}
11+
);
912
const { intl } = intlProvider.getChildContext();
1013

1114
const messages = defineMessages({

src/themes/react/static/dashboard/src/components/GlobalHeader/index.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
SPDX-License-Identifier: Apache-2.0
33
*/
44
import React, { PureComponent } from 'react';
5-
import { Menu, Icon, Spin, Dropdown, Avatar, Divider } from 'antd';
5+
import { Menu, Icon, Spin, Dropdown, Avatar, Divider, Button } from 'antd';
66
import Debounce from 'lodash-decorators/debounce';
77
import { Link } from 'dva/router';
88
import styles from './index.less';
9+
import { getLang } from '../../utils/utils';
910

11+
const language = getLang();
1012
export default class GlobalHeader extends PureComponent {
1113
componentWillUnmount() {
1214
this.triggerResizeEvent.cancel();
@@ -23,6 +25,10 @@ export default class GlobalHeader extends PureComponent {
2325
event.initEvent('resize', true, false);
2426
window.dispatchEvent(event);
2527
}
28+
changeLanguage = () => {
29+
localStorage.setItem('language', language === 'en' ? 'zh-CN' : 'en');
30+
window.location.reload();
31+
};
2632
render() {
2733
const { collapsed, isMobile, logo, onMenuClick } = this.props;
2834
const menu = (
@@ -46,6 +52,9 @@ export default class GlobalHeader extends PureComponent {
4652
onClick={this.toggle}
4753
/>
4854
<div className={styles.right}>
55+
<Button size="small" onClick={this.changeLanguage}>
56+
{language === 'en' ? '中文' : 'En'}
57+
</Button>
4958
{window.username ? (
5059
<Dropdown overlay={menu}>
5160
<span className={`${styles.action} ${styles.account}`}>

src/themes/react/static/dashboard/src/locales/en.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,9 @@
33
"Menu.Overview": "Overview",
44
"Menu.Host": "Host",
55
"Menu.Chain": "Chain",
6-
"Menu.UserManagement": "User Management"
6+
"Menu.UserManagement": "User Management",
7+
"Overview.Title.Host": "Host",
8+
"Overview.Title.Cluster": "Cluster",
9+
"Overview.Title.Status": "Status",
10+
"Overview.Title.Type": "Type"
711
}

src/themes/react/static/dashboard/src/locales/zh.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,9 @@
33
"Menu.Overview": "系统概况",
44
"Menu.Host": "主机管理",
55
"Menu.Chain": "链管理",
6-
"Menu.UserManagement": "用户管理"
6+
"Menu.UserManagement": "用户管理",
7+
"Overview.Title.Host": "主机",
8+
"Overview.Title.Cluster": "集群",
9+
"Overview.Title.Status": "状态",
10+
"Overview.Title.Type": "类型"
711
}

src/themes/react/static/dashboard/src/router.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,20 @@ import zhCN from 'antd/lib/locale-provider/zh_CN';
99
import dynamic from 'dva/dynamic';
1010
import { getRouterData } from './common/router';
1111
import styles from './index.less';
12-
import enLocale from './locales/en-US';
12+
import { getLocale } from './utils/utils';
1313

1414
const { ConnectedRouter } = routerRedux;
1515
dynamic.setDefaultLoadingComponent(() => {
1616
return <Spin size="large" className={styles.globalSpin} />;
1717
});
1818

19-
addLocaleData(enLocale.data);
19+
const currentLocale = getLocale();
20+
addLocaleData(currentLocale.data);
2021
function RouterConfig({ history, app }) {
2122
const routerData = getRouterData(app);
2223
const BasicLayout = routerData['/'].component;
2324
return (
24-
<IntlProvider locale={enLocale.locale} messages={enLocale.messages}>
25+
<IntlProvider locale={currentLocale.locale} messages={currentLocale.messages}>
2526
<LocaleProvider locale={zhCN}>
2627
<ConnectedRouter history={history}>
2728
<Switch>

src/themes/react/static/dashboard/src/routes/Overview/index.js

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,31 @@
44
import React, { Component, Fragment } from 'react';
55
import { Row, Col, Card, Radio } from 'antd';
66
import { connect } from 'dva';
7+
import { defineMessages, FormattedMessage } from 'react-intl';
78
import { Pie } from 'components/Charts';
89
import styles from './index.less';
910

11+
const messages = defineMessages({
12+
title: {
13+
host: {
14+
id: 'Overview.Title.Host',
15+
defaultMessage: 'Host',
16+
},
17+
cluster: {
18+
id: 'Overview.Title.Cluster',
19+
defaultMessage: 'Cluster',
20+
},
21+
status: {
22+
id: 'Overview.Title.Status',
23+
defaultMessage: 'Status',
24+
},
25+
type: {
26+
id: 'Overview.Title.Type',
27+
defaultMessage: 'Type',
28+
},
29+
},
30+
});
31+
1032
@connect(({ overview, loading }) => ({
1133
overview,
1234
loadingClusterStatus: loading.effects['overview/fetchClusterStatus'],
@@ -48,26 +70,37 @@ export default class Analysis extends Component {
4870
loading={loadingHostStatus}
4971
className={styles.pieChartCard}
5072
bordered={false}
51-
title="Host"
73+
title={<FormattedMessage {...messages.title.host} />}
5274
bodyStyle={{ padding: 24 }}
5375
style={{ marginTop: 24, minHeight: 409 }}
5476
extra={
5577
<div className={styles.pieChartCardExtra}>
5678
<div className={styles.pieChartTypeRadio}>
5779
<Radio.Group value={hostTypeValue} onChange={this.hostTypeChange}>
58-
<Radio.Button value="status">Status</Radio.Button>
59-
<Radio.Button value="type">Types</Radio.Button>
80+
<Radio.Button value="status">
81+
<FormattedMessage {...messages.title.status} />
82+
</Radio.Button>
83+
<Radio.Button value="type">
84+
<FormattedMessage {...messages.title.type} />
85+
</Radio.Button>
6086
</Radio.Group>
6187
</div>
6288
</div>
6389
}
6490
>
6591
<h4 style={{ marginTop: 8, marginBottom: 32 }}>
66-
Host <span className={styles.pieChartSubTitle}>{hostTypeValue}</span>
92+
<FormattedMessage {...messages.title.host} />{' '}
93+
<span className={styles.pieChartSubTitle}>
94+
<FormattedMessage {...messages.title[hostTypeValue]} />
95+
</span>
6796
</h4>
6897
<Pie
6998
hasLegend
70-
subTitle={<span className={styles.pieChartSubTitle}>{hostTypeValue}</span>}
99+
subTitle={
100+
<span className={styles.pieChartSubTitle}>
101+
<FormattedMessage {...messages.title[hostTypeValue]} />
102+
</span>
103+
}
71104
total={() => (
72105
<span>
73106
{hostTypeValue === 'type'
@@ -86,26 +119,37 @@ export default class Analysis extends Component {
86119
className={styles.pieChartCard}
87120
loading={loadingClusterStatus}
88121
bordered={false}
89-
title="Cluster"
122+
title={<FormattedMessage {...messages.title.cluster} />}
90123
bodyStyle={{ padding: 24 }}
91124
style={{ marginTop: 24, minHeight: 409 }}
92125
extra={
93126
<div className={styles.pieChartCardExtra}>
94127
<div className={styles.pieChartTypeRadio}>
95128
<Radio.Group value={clusterTypeValue} onChange={this.clusterTypeChange}>
96-
<Radio.Button value="status">Status</Radio.Button>
97-
<Radio.Button value="type">Types</Radio.Button>
129+
<Radio.Button value="status">
130+
<FormattedMessage {...messages.title.status} />
131+
</Radio.Button>
132+
<Radio.Button value="type">
133+
<FormattedMessage {...messages.title.type} />
134+
</Radio.Button>
98135
</Radio.Group>
99136
</div>
100137
</div>
101138
}
102139
>
103140
<h4 style={{ marginTop: 8, marginBottom: 32 }}>
104-
Cluster <span className={styles.pieChartSubTitle}>{clusterTypeValue}</span>
141+
<FormattedMessage {...messages.title.cluster} />{' '}
142+
<span className={styles.pieChartSubTitle}>
143+
<FormattedMessage {...messages.title[clusterTypeValue]} />
144+
</span>
105145
</h4>
106146
<Pie
107147
hasLegend
108-
subTitle={<span className={styles.pieChartSubTitle}>{clusterTypeValue}</span>}
148+
subTitle={
149+
<span className={styles.pieChartSubTitle}>
150+
<FormattedMessage {...messages.title[clusterTypeValue]} />
151+
</span>
152+
}
109153
total={() => (
110154
<span>
111155
{clusterTypeValue === 'type'

src/themes/react/static/dashboard/src/utils/utils.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
SPDX-License-Identifier: Apache-2.0
33
*/
44
import moment from 'moment';
5+
import enLocale from '../locales/en-US';
6+
import zhLocale from '../locales/zh-CN';
57

68
export function fixedZero(val) {
79
return val * 1 < 10 ? `0${val}` : val;
@@ -134,3 +136,13 @@ const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-
134136
export function isUrl(path) {
135137
return reg.test(path);
136138
}
139+
140+
export function getLocale() {
141+
return ((window.localStorage && localStorage.getItem('language')) || (navigator.language || navigator.browserLanguage).toLowerCase()) === 'en'
142+
? enLocale
143+
: zhLocale;
144+
}
145+
146+
export function getLang() {
147+
return (window.localStorage && localStorage.getItem('language')) || (navigator.language || navigator.browserLanguage).toLowerCase();
148+
}

0 commit comments

Comments
 (0)