feat: support Korean i18n
Support Korean i18n Change-Id: Idf5efce1ad02743f0ba8734009e1bb661038c087
This commit is contained in:
parent
decd2bfec7
commit
235ee19da6
@ -19,7 +19,7 @@ module.exports = function (grunt) {
|
||||
src: ['src/**/*.{jsx,js}'],
|
||||
dest: 'src',
|
||||
options: {
|
||||
lngs: ['en', 'zh'],
|
||||
lngs: ['en', 'zh', 'ko-kr'],
|
||||
removeUnusedKeys: true,
|
||||
sort: true,
|
||||
keySeparator: false,
|
||||
@ -39,10 +39,10 @@ module.exports = function (grunt) {
|
||||
extensions: ['.js', '.jsx'],
|
||||
},
|
||||
defaultValue: (lng, ns, key) => {
|
||||
if (lng === 'zh') {
|
||||
return '';
|
||||
if (lng === 'en') {
|
||||
return key;
|
||||
}
|
||||
return key;
|
||||
return '';
|
||||
},
|
||||
},
|
||||
},
|
||||
|
10
releasenotes/notes/Support-Korean-I18n-6f258836f7b30db9.yaml
Normal file
10
releasenotes/notes/Support-Korean-I18n-6f258836f7b30db9.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support Korean I18n:
|
||||
|
||||
* Korean language switching is supported on the login page.
|
||||
|
||||
* Support switch Korean in the avatar hover box on the upper right of the page after logged in.
|
||||
|
||||
* Support automatic collection of Korean i18n file.
|
@ -14,7 +14,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { inject, observer } from 'mobx-react';
|
||||
import { Menu, Spin, Button } from 'antd';
|
||||
import { Menu, Spin, Button, Select } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
import i18n from 'core/i18n';
|
||||
import ItemActionButtons from 'components/Tables/Base/ItemActionButtons';
|
||||
@ -24,7 +24,7 @@ import OpenRc from './OpenRc';
|
||||
import HeaderDropdown from '../HeaderDropdown';
|
||||
import styles from './index.less';
|
||||
|
||||
const { getLocale, setLocale } = i18n;
|
||||
const { getLocale, setLocale, SUPPORT_LOCALES } = i18n;
|
||||
|
||||
export class AvatarDropdown extends React.Component {
|
||||
get rootStore() {
|
||||
@ -58,6 +58,51 @@ export class AvatarDropdown extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
onClickSelectLanguage = (e) => {
|
||||
e && e.preventDefault();
|
||||
e && e.stopPropagation();
|
||||
};
|
||||
|
||||
renderLanguageSwitch() {
|
||||
const selectedLang = getLocale();
|
||||
const { length } = SUPPORT_LOCALES;
|
||||
if (length > 3) {
|
||||
const options = SUPPORT_LOCALES.map((it) => ({
|
||||
label: it.shortName.toLocaleUpperCase(),
|
||||
value: it.value,
|
||||
}));
|
||||
return (
|
||||
<div style={{ float: 'right' }}>
|
||||
<Select
|
||||
options={options}
|
||||
value={selectedLang}
|
||||
onChange={this.changeLang}
|
||||
onClick={this.onClickSelectLanguage}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const btns = SUPPORT_LOCALES.map((item, index) => {
|
||||
const { value, shortName } = item;
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
className={index === 0 ? styles['no-padding-top'] : ''}
|
||||
type="link"
|
||||
disabled={selectedLang === value}
|
||||
onClick={() => {
|
||||
this.changeLang(value);
|
||||
}}
|
||||
>
|
||||
{shortName.toUpperCase()}
|
||||
</Button>
|
||||
{index !== length - 1 && <span>/</span>}
|
||||
</>
|
||||
);
|
||||
});
|
||||
return <span style={{ float: 'right' }}>{btns}</span>;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.user) {
|
||||
return (
|
||||
@ -71,7 +116,6 @@ export class AvatarDropdown extends React.Component {
|
||||
);
|
||||
}
|
||||
const { name: username } = this.user.user;
|
||||
const selectedLang = getLocale();
|
||||
// const { selectedLang } = this.state.selectedLang;
|
||||
const menuHeaderDropdown = (
|
||||
<Menu className={styles.menu} onClick={this.onMenuClick}>
|
||||
@ -97,28 +141,7 @@ export class AvatarDropdown extends React.Component {
|
||||
className={`${styles['no-hover']} ${styles['menu-item']}`}
|
||||
>
|
||||
<span>{t('Switch Language')}</span>
|
||||
<span style={{ float: 'right' }}>
|
||||
<Button
|
||||
className={styles['no-padding-top']}
|
||||
type="link"
|
||||
disabled={selectedLang === 'zh-cn'}
|
||||
onClick={() => {
|
||||
this.changeLang('zh-cn');
|
||||
}}
|
||||
>
|
||||
CN
|
||||
</Button>
|
||||
<span>/</span>
|
||||
<Button
|
||||
type="link"
|
||||
disabled={selectedLang === 'en'}
|
||||
onClick={() => {
|
||||
this.changeLang('en');
|
||||
}}
|
||||
>
|
||||
EN
|
||||
</Button>
|
||||
</span>
|
||||
{this.renderLanguageSwitch()}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="password" className={styles['menu-item']}>
|
||||
<ItemActionButtons
|
||||
|
@ -19,7 +19,7 @@ import classNames from 'classnames';
|
||||
import { GlobalOutlined } from '@ant-design/icons';
|
||||
import styles from './index.less';
|
||||
|
||||
const { getLocale, setLocale } = i18n;
|
||||
const { getLocale, setLocale, SUPPORT_LOCALES } = i18n;
|
||||
|
||||
const SelectLang = (props) => {
|
||||
const { className } = props;
|
||||
@ -29,27 +29,21 @@ const SelectLang = (props) => {
|
||||
setLocale(key, false);
|
||||
};
|
||||
|
||||
const locales = ['zh-cn', 'en'];
|
||||
const languageLabels = {
|
||||
'zh-cn': '简体中文',
|
||||
en: 'English',
|
||||
};
|
||||
const languageIcons = {
|
||||
'zh-cn': '🇨🇳',
|
||||
en: '🇺🇸',
|
||||
};
|
||||
const locales = SUPPORT_LOCALES.map((it) => it.value);
|
||||
const languageLabels = SUPPORT_LOCALES.map((it) => it.name);
|
||||
const languageIcons = SUPPORT_LOCALES.map((it) => it.icon);
|
||||
const langMenu = (
|
||||
<Menu
|
||||
className={styles.menu}
|
||||
selectedKeys={[selectedLang]}
|
||||
onClick={changeLang}
|
||||
>
|
||||
{locales.map((locale) => (
|
||||
{locales.map((locale, index) => (
|
||||
<Menu.Item key={locale}>
|
||||
<span role="img" aria-label={languageLabels[locale]}>
|
||||
{languageIcons[locale]}
|
||||
<span role="img" aria-label={languageLabels[index]}>
|
||||
{languageIcons[index]}
|
||||
</span>{' '}
|
||||
{languageLabels[locale]}
|
||||
{languageLabels[index]}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
|
@ -24,10 +24,20 @@ const SUPPORT_LOCALES = [
|
||||
{
|
||||
name: 'English',
|
||||
value: 'en',
|
||||
shortName: 'en',
|
||||
icon: 'us',
|
||||
},
|
||||
{
|
||||
name: '简体中文',
|
||||
value: 'zh-cn',
|
||||
shortName: 'zh',
|
||||
icon: 'cn',
|
||||
},
|
||||
{
|
||||
name: '한글',
|
||||
value: 'ko-kr',
|
||||
shortName: 'kr',
|
||||
icon: 'kr',
|
||||
},
|
||||
];
|
||||
|
||||
@ -63,6 +73,12 @@ const getLocale = () => {
|
||||
return currentLocale;
|
||||
};
|
||||
|
||||
const getLocaleShortName = () => {
|
||||
const fullName = getLocale();
|
||||
const item = SUPPORT_LOCALES.find((it) => it.value === fullName);
|
||||
return item ? item.shortName : fullName;
|
||||
};
|
||||
|
||||
const loadLocales = () => {
|
||||
const currentLocale = getLocale();
|
||||
return intl.init({
|
||||
@ -131,4 +147,6 @@ export default {
|
||||
init,
|
||||
t,
|
||||
isLocaleZh,
|
||||
getLocaleShortName,
|
||||
SUPPORT_LOCALES,
|
||||
};
|
||||
|
@ -36,9 +36,10 @@ export class BlankLayout extends Component {
|
||||
}
|
||||
|
||||
get title() {
|
||||
const { title: { zh = t('Cloud'), en = 'Cloud' } = {} } = this.info;
|
||||
const { isLocaleZh } = i18n;
|
||||
return isLocaleZh ? zh : en;
|
||||
const { title = { zh: t('Cloud'), en: 'Cloud' } } = this.info;
|
||||
const { getLocaleShortName } = i18n;
|
||||
const language = getLocaleShortName();
|
||||
return title[language] || t('Cloud') || 'Cloud';
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -14,8 +14,10 @@
|
||||
|
||||
import zhData from './zh.json';
|
||||
import enData from './en.json';
|
||||
import krData from './ko-kr.json';
|
||||
|
||||
export default {
|
||||
'zh-cn': zhData,
|
||||
en: enData,
|
||||
'ko-kr': krData,
|
||||
};
|
||||
|
2976
src/locales/ko-kr.json
Normal file
2976
src/locales/ko-kr.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -69,11 +69,13 @@ export class Login extends Component {
|
||||
}
|
||||
|
||||
get productName() {
|
||||
const {
|
||||
product_name: { zh = t('Cloud Platform'), en = 'Cloud Platform' } = {},
|
||||
} = this.info;
|
||||
const { isLocaleZh } = i18n;
|
||||
return t('Welcome, {name}', { name: isLocaleZh ? zh : en });
|
||||
const { product_name = { zh: t('Cloud Platform'), en: 'Cloud Platform' } } =
|
||||
this.info;
|
||||
const { getLocaleShortName } = i18n;
|
||||
const language = getLocaleShortName();
|
||||
const name =
|
||||
product_name[language] || t('Cloud Platform') || 'Cloud Platform';
|
||||
return t('Welcome, {name}', { name });
|
||||
}
|
||||
|
||||
get domains() {
|
||||
|
Loading…
Reference in New Issue
Block a user