Added language switching drop-down menu.

This commit is contained in:
zuiidea
2018-10-15 15:08:48 +08:00
parent 66a6e55191
commit f6454e71f0
9 changed files with 209 additions and 55 deletions
+4 -1
View File
@@ -39,7 +39,10 @@ export default {
if (item.path) {
newRoutes.push(
Object.assign({}, item, {
path: `/:lang(${i18n.languages.join('|')})` + item.path,
path:
`/:lang(${i18n.languages
.map(item => item.key)
.join('|')})` + item.path,
})
)
}
+63
View File
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<rect style="fill:#F0F0F0;" width="512" height="512"/>
<g>
<rect y="64" style="fill:#D80027;" width="512" height="64"/>
<rect y="192" style="fill:#D80027;" width="512" height="64"/>
<rect y="320" style="fill:#D80027;" width="512" height="64"/>
<rect y="448" style="fill:#D80027;" width="512" height="64"/>
</g>
<rect style="fill:#2E52B2;" width="256" height="275.69"/>
<g>
<polygon style="fill:#F0F0F0;" points="51.518,115.318 45.924,132.529 27.826,132.529 42.469,143.163 36.875,160.375
51.518,149.741 66.155,160.375 60.56,143.163 75.203,132.529 57.106,132.529 "/>
<polygon style="fill:#F0F0F0;" points="57.106,194.645 51.518,177.434 45.924,194.645 27.826,194.645 42.469,205.279
36.875,222.49 51.518,211.857 66.155,222.49 60.56,205.279 75.203,194.645 "/>
<polygon style="fill:#F0F0F0;" points="51.518,53.202 45.924,70.414 27.826,70.414 42.469,81.047 36.875,98.259 51.518,87.625
66.155,98.259 60.56,81.047 75.203,70.414 57.106,70.414 "/>
<polygon style="fill:#F0F0F0;" points="128.003,115.318 122.409,132.529 104.311,132.529 118.954,143.163 113.36,160.375
128.003,149.741 142.64,160.375 137.045,143.163 151.689,132.529 133.591,132.529 "/>
<polygon style="fill:#F0F0F0;" points="133.591,194.645 128.003,177.434 122.409,194.645 104.311,194.645 118.954,205.279
113.36,222.49 128.003,211.857 142.64,222.49 137.045,205.279 151.689,194.645 "/>
<polygon style="fill:#F0F0F0;" points="210.076,194.645 204.489,177.434 198.894,194.645 180.797,194.645 195.44,205.279
189.845,222.49 204.489,211.857 219.125,222.49 213.531,205.279 228.174,194.645 "/>
<polygon style="fill:#F0F0F0;" points="204.489,115.318 198.894,132.529 180.797,132.529 195.44,143.163 189.845,160.375
204.489,149.741 219.125,160.375 213.531,143.163 228.174,132.529 210.076,132.529 "/>
<polygon style="fill:#F0F0F0;" points="128.003,53.202 122.409,70.414 104.311,70.414 118.954,81.047 113.36,98.259
128.003,87.625 142.64,98.259 137.045,81.047 151.689,70.414 133.591,70.414 "/>
<polygon style="fill:#F0F0F0;" points="204.489,53.202 198.894,70.414 180.797,70.414 195.44,81.047 189.845,98.259
204.489,87.625 219.125,98.259 213.531,81.047 228.174,70.414 210.076,70.414 "/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-49 141 512 512" style="enable-background:new -49 141 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#D80027;}
.st1{fill:#FFDA44;}
</style>
<rect x="-49" y="141" class="st0" width="512" height="512"/>
<g>
<polygon class="st1" points="91.1,296.8 113.2,364.8 184.7,364.8 126.9,406.9 149,474.9 91.1,432.9 33.2,474.9 55.4,406.9
-2.5,364.8 69,364.8 "/>
<polygon class="st1" points="254.5,537.5 237.6,516.7 212.6,526.4 227.1,503.9 210.2,483 236.1,489.9 250.7,467.4 252.1,494.2
278.1,501.1 253,510.7 "/>
<polygon class="st1" points="288.1,476.5 296.1,450.9 274.2,435.4 301,435 308.9,409.4 317.6,434.8 344.4,434.5 322.9,450.5
331.5,475.9 309.6,460.4 "/>
<polygon class="st1" points="333.4,328.9 321.6,353 340.8,371.7 314.3,367.9 302.5,391.9 297.9,365.5 271.3,361.7 295.1,349.2
290.5,322.7 309.7,341.4 "/>
<polygon class="st1" points="255.2,255.9 253.2,282.6 278.1,292.7 252,299.1 250.1,325.9 236,303.1 209.9,309.5 227.2,289
213,266.3 237.9,276.4 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+56 -22
View File
@@ -1,19 +1,71 @@
import React, { PureComponent, Fragment } from 'react'
import PropTypes from 'prop-types'
import { Menu, Icon, Layout, Avatar } from 'antd'
import { Trans } from '@lingui/react'
import { Trans, withI18n } from '@lingui/react'
import { setLocale } from 'utils'
import classnames from 'classnames'
import config from 'config'
import styles from './Header.less'
const { SubMenu } = Menu
@withI18n()
class Header extends PureComponent {
handleClickMenu = e => {
e.key === 'SignOut' && this.props.onSignOut()
}
render() {
const { username, avatar, collapsed, onCollapseChange } = this.props
const { username, avatar, collapsed, onCollapseChange, i18n } = this.props
const rightContent = [
<Menu key="user" mode="horizontal" onClick={this.handleClickMenu}>
<SubMenu
title={
<Fragment>
<span style={{ color: '#999', marginRight: 4 }}>
<Trans>Hi,</Trans>
</span>
<span>{username}</span>
<Avatar style={{ marginLeft: 8 }} src={avatar} />
</Fragment>
}
>
<Menu.Item key="SignOut">
<Trans>Sign out</Trans>
</Menu.Item>
</SubMenu>
</Menu>,
]
if (config.i18n) {
const { languages } = config.i18n
const currentLanguage = languages.find(
item => item.key === i18n._language
)
rightContent.unshift(
<Menu
key="language"
selectedKeys={[currentLanguage.key]}
onClick={data => {
setLocale(data.key)
}}
mode="horizontal"
>
<SubMenu title={<Avatar size="small" src={currentLanguage.flag} />}>
{languages.map(item => (
<Menu.Item key={item.key}>
<Avatar
size="small"
style={{ marginRight: 8 }}
src={item.flag}
/>
{item.title}
</Menu.Item>
))}
</SubMenu>
</Menu>
)
}
return (
<Layout.Header className={styles.header}>
<div
@@ -28,25 +80,7 @@ class Header extends PureComponent {
/>
</div>
<div className={styles.rightContainer}>
<Menu mode="horizontal" onClick={this.handleClickMenu}>
<SubMenu
title={
<Fragment>
<span style={{ color: '#999', marginRight: 4 }}>
<Trans>Hi,</Trans>
</span>
<span>{username}</span>
<Avatar style={{ marginLeft: 8 }} src={avatar} />
</Fragment>
}
>
<Menu.Item key="SignOut">
<Trans>Sign out</Trans>
</Menu.Item>
</SubMenu>
</Menu>
</div>
<div className={styles.rightContainer}>{rightContent}</div>
</Layout.Header>
)
}
+1 -1
View File
@@ -123,7 +123,7 @@ class PrimaryLayout extends PureComponent {
</Content>
<BackTop
className={styles.backTop}
target={() => document.getElementById('primaryLayout')}
target={() => document.querySelector('#primaryLayout>div')}
/>
<GlobalFooter
className={styles.footer}
+19 -10
View File
@@ -1,3 +1,5 @@
@import '~themes/vars.less';
@media (max-width: 767px) {
.content {
padding: 12px;
@@ -11,6 +13,19 @@
.backTop {
right: 50px;
:global {
.ant-back-top-content {
background: @primary-color;
opacity: 0.3;
transition: all 0.3s;
box-shadow: 0 0 15px 1px rgba(69, 65, 78, 0.1);
&:hover {
opacity: 1;
}
}
}
}
.content {
@@ -26,14 +41,8 @@
.footer {
background: #fff;
}
:global {
.antd-pro-global-footer-globalFooter {
margin-top: 0;
margin-bottom: 0;
padding-top: 24px;
padding-bottom: 24px;
background: #fff;
}
margin-top: 0;
margin-bottom: 0;
padding-top: 24px;
padding-bottom: 24px;
}
+14 -19
View File
@@ -2,9 +2,9 @@ import React, { PureComponent, Fragment } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'dva'
import { Button, Row, Form, Icon, Input } from 'antd'
import router from 'umi/router'
import { GlobalFooter } from 'ant-design-pro'
import { Trans, withI18n } from '@lingui/react'
import { setLocale } from 'utils'
import config from 'utils/config'
import styles from './index.less'
@@ -26,34 +26,29 @@ class Login extends PureComponent {
}
render() {
const { loading, form, i18n, location } = this.props
const { loading, form, i18n } = this.props
const { getFieldDecorator } = form
const footerLinks = [
let footerLinks = [
{
key: 'github',
title: <Icon type="github" />,
href: 'https://github.com/zuiidea/antd-admin',
blankTarget: true,
},
{
key: 'English',
title: (
<span onClick={() => router.push(`/en/login${location.search}`)}>
English
</span>
),
},
{
key: 'Chinese',
title: (
<span onClick={() => router.push(`/zh/login${location.search}`)}>
中文
</span>
),
},
]
if (config.i18n) {
footerLinks = footerLinks.concat(
config.i18n.languages.map(item => ({
key: item.key,
title: (
<span onClick={setLocale.bind(null, item.key)}>{item.title}</span>
),
}))
)
}
return (
<Fragment>
<div className={styles.form}>
+13 -1
View File
@@ -18,7 +18,19 @@ module.exports = {
/* I18n configuration, `languages` and `defaultLanguage` are required currently. */
i18n: {
languages: ['en', 'zh'],
/* Countrys flags: https://www.flaticon.com/packs/countrys-flags */
languages: [
{
key: 'en',
title: 'English',
flag: '/america.svg',
},
{
key: 'zh',
title: '中文',
flag: '/china.svg',
},
],
defaultLanguage: 'en',
},
}
+16 -1
View File
@@ -8,7 +8,8 @@ export config from './config'
export request from './request'
export { Color } from './theme'
export const { languages, defaultLanguage } = i18n
export const { defaultLanguage } = i18n
export const languages = i18n.languages.map(item => item.key)
/**
* Query objects that specify keys and values in an array where all values are objects.
@@ -237,3 +238,17 @@ export function queryLayout(layouts, pathname) {
return result
}
export function getLocale() {
return langFromPath(window.location.pathname)
}
export function setLocale(language) {
if (getLocale() !== language) {
umiRouter.push({
pathname: `/${language}${deLangPrefix(window.location.pathname)}${
window.location.search
}`,
})
}
}