feat: support custom locale language
support custom locale language and custom support languages. Change-Id: Ia235cb83b65c8530449f52d9ea575c3d6f603f04
This commit is contained in:
parent
dd00305998
commit
b36d5593e6
@ -139,6 +139,7 @@
|
||||
"globals": true,
|
||||
"request": true,
|
||||
"METRICDICT": true,
|
||||
"globalCSS": true
|
||||
"globalCSS": true,
|
||||
"GLOBAL_VARIABLES": true
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
host: 0.0.0.0
|
||||
port: 8088
|
||||
server: http://localhost
|
||||
|
||||
globalVariables:
|
||||
defaultLanguage: en
|
||||
supportLanguages: # use value in i18n.js
|
||||
- en
|
||||
- zh-hans
|
||||
- ko-kr
|
||||
|
@ -2,7 +2,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const yaml = require('js-yaml');
|
||||
const { merge } = require('lodash');
|
||||
const { merge, extend, has } = require('lodash');
|
||||
|
||||
const root = (dir) =>
|
||||
`${path.resolve(__dirname, './')}/${dir}`.replace(/(\/+)/g, '/');
|
||||
@ -22,16 +22,43 @@ const getServerConfig = (key) => {
|
||||
const tryFile = root('./local_config.yaml');
|
||||
if (fs.existsSync(tryFile)) {
|
||||
// merge local_config
|
||||
const local_config = loadYaml(tryFile);
|
||||
if (typeof local_config === 'object') {
|
||||
merge(config, local_config);
|
||||
const localConfig = loadYaml(tryFile);
|
||||
if (typeof localConfig === 'object') {
|
||||
merge(config, localConfig);
|
||||
}
|
||||
}
|
||||
|
||||
return key ? config[key] : config;
|
||||
};
|
||||
|
||||
const getObjectConfig = (key) => {
|
||||
// parse config yaml
|
||||
const config = loadYaml(root('./config.yaml')) || {};
|
||||
if (!has(config, key)) {
|
||||
return {};
|
||||
}
|
||||
const defaultConfig = config[key];
|
||||
|
||||
const result = defaultConfig;
|
||||
const tryFile = root('./local_config.yaml');
|
||||
if (fs.existsSync(tryFile)) {
|
||||
// merge local_config
|
||||
const localConfig = loadYaml(tryFile);
|
||||
extend(result, localConfig[key] || {});
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const getGlobalVariables = () => {
|
||||
const variables = getObjectConfig('globalVariables') || {};
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('globalVariables', variables, JSON.stringify(variables));
|
||||
return JSON.stringify(variables);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getServerConfig,
|
||||
root,
|
||||
getGlobalVariables,
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ const { normalize, resolve } = require('path');
|
||||
// const path = require("path");
|
||||
// const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const moment = require('moment');
|
||||
const { getGlobalVariables } = require('./utils');
|
||||
|
||||
const root = (path) => resolve(__dirname, `../${path}`);
|
||||
const version = moment().unix();
|
||||
@ -109,7 +110,12 @@ module.exports = {
|
||||
client: root('src/client'),
|
||||
},
|
||||
},
|
||||
plugins: [new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)],
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
GLOBAL_VARIABLES: getGlobalVariables(),
|
||||
}),
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports.version = version;
|
||||
|
@ -32,4 +32,10 @@ module.exports = {
|
||||
moduleDirectories: ['node_modules', 'src'],
|
||||
testPathIgnorePatterns: ['node_modules', '.cache', 'test/e2e', 'config'],
|
||||
setupFiles: ['<rootDir>/test/unit/setup-tests.js'],
|
||||
globals: {
|
||||
GLOBAL_VARIABLES: {
|
||||
defaultLanguage: 'en',
|
||||
supportLanguages: ['en', 'zh-hans'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support custom local language:
|
||||
|
||||
* The globalVariables in the config.yaml support default language and all support languages.
|
||||
|
||||
* Use globalVariables in the local_config.yaml to support custom local languages and custom support languages.
|
||||
|
||||
* If only one support language, the switch language icon will been auto hidden.
|
@ -103,6 +103,21 @@ export class AvatarDropdown extends React.Component {
|
||||
return <span style={{ float: 'right' }}>{btns}</span>;
|
||||
}
|
||||
|
||||
renderLanguageMenuItem() {
|
||||
if (SUPPORT_LOCALES.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Menu.Item
|
||||
key="language"
|
||||
className={`${styles['no-hover']} ${styles['menu-item']}`}
|
||||
>
|
||||
<span>{t('Switch Language')}</span>
|
||||
{this.renderLanguageSwitch()}
|
||||
</Menu.Item>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.user) {
|
||||
return (
|
||||
@ -136,13 +151,7 @@ export class AvatarDropdown extends React.Component {
|
||||
</Button>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key="language"
|
||||
className={`${styles['no-hover']} ${styles['menu-item']}`}
|
||||
>
|
||||
<span>{t('Switch Language')}</span>
|
||||
{this.renderLanguageSwitch()}
|
||||
</Menu.Item>
|
||||
{this.renderLanguageMenuItem()}
|
||||
<Menu.Item key="password" className={styles['menu-item']}>
|
||||
<ItemActionButtons
|
||||
actions={{ moreActions: [{ action: Password }] }}
|
||||
|
@ -22,6 +22,10 @@ import styles from './index.less';
|
||||
const { getLocale, setLocale, SUPPORT_LOCALES } = i18n;
|
||||
|
||||
const SelectLang = (props) => {
|
||||
if (SUPPORT_LOCALES.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { className } = props;
|
||||
const selectedLang = getLocale();
|
||||
|
||||
|
@ -14,35 +14,69 @@
|
||||
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/zh-cn';
|
||||
import _ from 'lodash';
|
||||
import _, { isArray } from 'lodash';
|
||||
import cookie from 'utils/cookie';
|
||||
import SLI18n from 'utils/translate';
|
||||
import { setLocalStorageItem } from 'utils/local-storage';
|
||||
|
||||
import locales from '../locales';
|
||||
|
||||
// shortName: the i18n name in the api
|
||||
// icon: the icon of switch language in ui
|
||||
const SUPPORT_LOCALES = [
|
||||
const SUPPORT_LOCALES_ALL = [
|
||||
{
|
||||
name: 'English',
|
||||
value: 'en',
|
||||
shortName: 'en',
|
||||
icon: 'en',
|
||||
momentName: 'en',
|
||||
},
|
||||
{
|
||||
name: '简体中文',
|
||||
value: 'zh-hans',
|
||||
shortName: 'zh',
|
||||
icon: 'zh',
|
||||
momentName: 'zhCN',
|
||||
},
|
||||
{
|
||||
name: '한글',
|
||||
value: 'ko-kr',
|
||||
shortName: 'ko',
|
||||
icon: 'ko',
|
||||
momentName: 'ko',
|
||||
},
|
||||
];
|
||||
|
||||
const getDefaultLanguageInConfig = () => {
|
||||
const { defaultLanguage } = GLOBAL_VARIABLES;
|
||||
const defaultLang = defaultLanguage || 'en';
|
||||
const inSupport = SUPPORT_LOCALES_ALL.find((it) => it.value === defaultLang);
|
||||
return inSupport ? defaultLang : 'en';
|
||||
};
|
||||
|
||||
const getSupportLanguagesInConfig = () => {
|
||||
const { supportLanguages } = GLOBAL_VARIABLES;
|
||||
const defaultLang = getDefaultLanguageInConfig();
|
||||
const defaultSupportLanguages = [defaultLang];
|
||||
if (!supportLanguages || !isArray(supportLanguages)) {
|
||||
return defaultSupportLanguages;
|
||||
}
|
||||
if (!supportLanguages.includes(defaultLang)) {
|
||||
return [...supportLanguages, defaultLang];
|
||||
}
|
||||
return supportLanguages;
|
||||
};
|
||||
|
||||
const SUPPORT_LOCALES = SUPPORT_LOCALES_ALL.filter((it) => {
|
||||
const supportLanguages = getSupportLanguagesInConfig();
|
||||
return supportLanguages.includes(it.value);
|
||||
});
|
||||
|
||||
const getMomentName = (locale) => {
|
||||
const item = SUPPORT_LOCALES_ALL.find((it) => it.value === locale);
|
||||
return (item || {}).momentName || 'en';
|
||||
};
|
||||
|
||||
const intl = new SLI18n();
|
||||
|
||||
let currentLocals = null;
|
||||
@ -63,9 +97,11 @@ const getLocale = () => {
|
||||
localStorageLocaleKey: 'lang',
|
||||
});
|
||||
|
||||
// If not found, the default is English
|
||||
const { defaultLanguage } = GLOBAL_VARIABLES;
|
||||
|
||||
// If not found, the default language is set in config.yaml
|
||||
if (!_.find(SUPPORT_LOCALES, { value: currentLocale })) {
|
||||
currentLocale = 'en';
|
||||
currentLocale = defaultLanguage;
|
||||
}
|
||||
|
||||
if (!currentLocals) {
|
||||
@ -93,7 +129,7 @@ const loadLocales = () => {
|
||||
const setLocale = (lang) => {
|
||||
setLocaleToStorage(lang);
|
||||
cookie('lang', lang);
|
||||
moment.locale(lang);
|
||||
moment.locale(getMomentName(lang));
|
||||
window.location.reload();
|
||||
return lang;
|
||||
};
|
||||
@ -104,7 +140,7 @@ const init = () => {
|
||||
const lang = getLocale();
|
||||
|
||||
if (lang === 'zh-hans') {
|
||||
moment.locale('zh', {
|
||||
moment.locale('zh-cn', {
|
||||
relativeTime: {
|
||||
s: '1秒',
|
||||
ss: '%d秒',
|
||||
@ -140,6 +176,7 @@ const t = (key, options) => intl.get(key, options);
|
||||
t.html = (key, options) => intl.getHTML(key, options);
|
||||
|
||||
loadLocales();
|
||||
init();
|
||||
window.t = t;
|
||||
|
||||
export default {
|
||||
|
@ -17,12 +17,13 @@ import ReactDOM from 'react-dom';
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { syncHistoryWithStore } from 'mobx-react-router';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import zhCN from 'antd/es/locale/zh_CN';
|
||||
import enUS from 'antd/es/locale/en_US';
|
||||
import globalRootStore from 'stores/root';
|
||||
import PageLoading from 'components/PageLoading';
|
||||
import metricDict from 'resources/prometheus/metricDict';
|
||||
import variables from 'styles/variables.less';
|
||||
import zhCN from 'antd/es/locale/zh_CN';
|
||||
import enUS from 'antd/es/locale/en_US';
|
||||
import koKR from 'antd/es/locale/ko_KR';
|
||||
import i18n from './i18n';
|
||||
import App from './App';
|
||||
|
||||
@ -33,8 +34,19 @@ window.globalCSS = variables;
|
||||
const store = globalRootStore;
|
||||
const browserHistory = createBrowserHistory();
|
||||
const history = syncHistoryWithStore(browserHistory, store.routing);
|
||||
const lang = i18n.getLocale();
|
||||
const localeProvider = lang === 'en' ? enUS : zhCN;
|
||||
|
||||
const antdLanguageMap = {
|
||||
en: enUS,
|
||||
'zh-hans': zhCN,
|
||||
'ko-kr': koKR,
|
||||
};
|
||||
|
||||
const getAntdLocale = (locale) => {
|
||||
const lang = locale || i18n.getLocale();
|
||||
return antdLanguageMap[lang] || enUS;
|
||||
};
|
||||
|
||||
const localeProvider = getAntdLocale(i18n.getLocale());
|
||||
|
||||
const render = (component) => {
|
||||
ReactDOM.render(
|
||||
|
Loading…
Reference in New Issue
Block a user