Skip to content

Commit 7affdf8

Browse files
author
白唯
committed
feat(i18n): 主要增加了国际化方案
同时增加国际化切换语言的组件以及通用样式,调整格式
1 parent 1f9c248 commit 7affdf8

15 files changed

+662
-30
lines changed

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
"email": "997132391@qq.com",
88
"url": "http://me.ibwei.com"
99
},
10-
"publishConfig": {
11-
"registry": "https://registry.npmjs.org/"
12-
},
1310
"scripts": {
1411
"serve": "vue-cli-service serve",
1512
"build": "vue-cli-service build",
@@ -28,12 +25,15 @@
2825
"@types"
2926
],
3027
"dependencies": {
31-
"ant-design-vue": "^2.0.0-beta.6",
28+
"@vue/composition-api": "^1.0.0-beta.14",
29+
"@vueuse/core": "^4.0.0-beta.16",
30+
"ant-design-vue": "^2.0.0-beta.9",
3231
"axios": "^0.20.0",
3332
"core-js": "^3.6.5",
3433
"moment": "^2.27.0",
3534
"vue": "^3.0.0-0",
3635
"vue-class-component": "^8.0.0-0",
36+
"vue-composable": "^1.0.0-beta.10",
3737
"vue-router": "^4.0.0-0",
3838
"vuex": "^4.0.0-0",
3939
"vuex-persistedstate": "^3.1.0"

src/components/ChangeLanguage.vue

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<template>
2+
<a-dropdown :trigger="['click']">
3+
<a class="ant-dropdown-link" @click="e => e.preventDefault()" :style="{ color: titleColor, fontSize: titleSize }"> {{ i18n.languageName }}<DownOutlined /></a>
4+
<template v-slot:overlay>
5+
<a-menu class="dropdown-panel">
6+
<a-menu-item v-for="(value, key) of LanguageNameList" :key="key" @click="changeLanguage">
7+
<span :style="{ color: textColor }">{{ LanguageNameList[key] }}</span>
8+
</a-menu-item>
9+
</a-menu>
10+
</template>
11+
</a-dropdown>
12+
</template>
13+
14+
<script>
15+
import { defineComponent } from 'vue'
16+
import { setLang, i18nInstance, LanguageNameList } from '../i18n/index'
17+
import { message } from 'ant-design-vue'
18+
import { DownOutlined } from '@ant-design/icons-vue'
19+
20+
export default defineComponent({
21+
props: {
22+
titleColor: {
23+
type: String,
24+
default: '#fff'
25+
},
26+
textColor: {
27+
type: String,
28+
default: '#fff'
29+
},
30+
titleSize: {
31+
type: String,
32+
default: '16px'
33+
}
34+
},
35+
components: {
36+
DownOutlined
37+
},
38+
setup() {
39+
const { i18n } = i18nInstance
40+
const changeLanguage = e => {
41+
const lang = e.key
42+
setLang(lang).then(result => {
43+
if (result === lang) {
44+
message.success(`${i18n.value['Current Language:']} ${i18n.value.languageName}`)
45+
}
46+
})
47+
}
48+
return {
49+
LanguageNameList,
50+
changeLanguage,
51+
i18n
52+
}
53+
}
54+
})
55+
</script>
56+
57+
<style lang="less" scoped>
58+
.dropdown-panel {
59+
background: rgba(255, 255, 255, 0.3);
60+
margin-top: 10px;
61+
/deep/ .ant-dropdown-menu-item-active {
62+
background: transparent;
63+
transform: translateX(2px);
64+
transition: all 0.2s ease-in-out;
65+
}
66+
}
67+
.dropdown-panel::before {
68+
content: '';
69+
display: block;
70+
border: 10px solid transparent;
71+
border-bottom-color: rgba(255, 255, 255, 0.3);
72+
position: absolute;
73+
top: -20px;
74+
left: 50%;
75+
transform: translateX(-50%);
76+
}
77+
</style>

src/i18n/index.ts

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* vue-i18n 使用姿势说明
3+
* see more : https://pikax.me/vue-composable/composable/i18n/i18n.html#parameters
4+
*/
5+
6+
import { includes } from 'lodash'
7+
import Store from '@/store'
8+
import moment from 'moment'
9+
import { findKeyByValue } from '@/utils/common'
10+
import { useI18n } from 'vue-composable'
11+
import zhCN from '@/i18n/messages/zhCN'
12+
import en from '@/i18n/messages/en'
13+
14+
let __LOCALE__ = Store.__s('app.language')
15+
16+
if (!__LOCALE__) {
17+
__LOCALE__ = window.navigator.language.split('-').join('')
18+
Store.__s('app.language', __LOCALE__)
19+
}
20+
21+
/** 定义语言模版 */
22+
export const Locales: any = {}
23+
24+
/**
25+
* @todo 语言名字命名要考虑三个部分:一是 antdv 组件国际化的语言名字,二是 i18n模版语言的命名,三是浏览器对于语言的命名(这里会跟 http 请* 求相关,也是后端能识别的语言命名),因此要将前两种语言的名字通过字典转换成标准名称,也就是浏览器的语言名使用SO 639-1标准
26+
*/
27+
28+
export const TranslateTable: { [key: string]: string } = {
29+
en: 'en_US',
30+
zhCN: 'zh_CN'
31+
}
32+
33+
export const LanguageNameList: { [key: string]: string } = {
34+
en: 'English',
35+
zhCN: '简体(中文)'
36+
}
37+
38+
export const i18nInstance = useI18n({
39+
locale: 'zhCN',
40+
messages: {
41+
zhCN,
42+
en
43+
}
44+
})
45+
46+
/**
47+
* @description 自动加载 antd-vue 需要的语言模版
48+
*/
49+
function loadAtdLocales() {
50+
const files = require.context(
51+
'../../node_modules/ant-design-vue/es/locale-provider',
52+
true,
53+
/\.js$/
54+
)
55+
files.keys().forEach(key => {
56+
const fileName = /(?<=\/)\S+(?=\.)/.exec(key) as Array<any>
57+
if (includes(TranslateTable, fileName[0])) {
58+
const localeKey = findKeyByValue(TranslateTable, fileName[0])
59+
if (localeKey) {
60+
Locales[localeKey] = files(key).default
61+
}
62+
}
63+
})
64+
}
65+
66+
/**
67+
* @functin setLang - set the app's language
68+
* @param {string} lang - the language will be setted
69+
* @return {string} lang - langguage name
70+
*/
71+
72+
function _set(lang: keyof typeof TranslateTable): any {
73+
i18nInstance.locale.value = lang as any
74+
// 设置当前语言的时间
75+
moment.locale(TranslateTable[lang])
76+
// Axios.defaults.headers.common['Accept-Language'] = lang
77+
Store.__s('app.language', lang)
78+
return lang
79+
}
80+
81+
/**
82+
* @functin 异步加载自定义的 i18n 模版
83+
* @param {string} lang - 将要更换的语言
84+
* @return {string} lang - 返回将要更改的语言明后才能
85+
*/
86+
export function setLang(lang: string): Promise<string> {
87+
if (lang === i18nInstance.locale.value) {
88+
return Promise.resolve('same')
89+
}
90+
return Promise.resolve(_set(lang))
91+
}
92+
93+
/* 加载 antd 模版 */
94+
loadAtdLocales()
95+
96+
/** 设置初始化语言 */
97+
setLang(__LOCALE__)

src/i18n/messages/en.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
languageName: 'English',
3+
'Current Language:': 'Current Language:',
4+
cancel: 'cancel',
5+
Play: 'Play'
6+
}

src/i18n/messages/zhCN.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const zhCN = {
2+
languageName: '中文(简体)',
3+
'Current Language:': '已经成功切换到',
4+
cancel: '取消',
5+
Play: '点击播放视频'
6+
}
7+
type i18nType = typeof zhCN
8+
export default zhCN
9+
export { i18nType }

src/main.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@ loadAllPlugins(app)
2020
/** 自动注册全局组件 */
2121
registeGlobalComponent(app)
2222

23-
app.use(store).use(router).mount('#app')
23+
app
24+
.use(store)
25+
.use(router)
26+
.mount('#app')

src/plugins/antd.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1-
import { Button, Card, Row, Col, Tag, Form, Input } from 'ant-design-vue'
2-
import { createApp } from 'vue'
1+
import { Button, Card, Row, Col, Tag, Form, Input, ConfigProvider, Select, DatePicker, Dropdown, Menu, Divider, Badge, BackTop, Carousel } from 'ant-design-vue'
2+
import '@/styles/antd.less'
33

44
/**
55
* @description 手动注册 antd-vue 组件,达到按需加载目的
66
* @description Automatically register components under Button, such as Button.Group
77
* @param {ReturnType<typeof createApp>} app 整个应用的实例
88
* @returns void
99
*/
10-
export default function loadComponent(app: ReturnType<typeof createApp>) {
10+
export default function loadComponent(app: any) {
1111
app.use(Button)
1212
app.use(Card)
1313
app.use(Row)
1414
app.use(Col)
1515
app.use(Tag)
1616
app.use(Form)
1717
app.use(Input)
18+
app.use(Dropdown)
19+
app.use(Menu)
20+
app.use(Divider)
21+
app.use(ConfigProvider)
22+
app.use(Select)
23+
app.use(DatePicker)
24+
app.use(BackTop)
25+
app.use(Badge)
26+
app.use(Carousel)
1827
}

src/plugins/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { createApp } from 'vue'
66
*/
77
export function loadAllPlugins(app: ReturnType<typeof createApp>) {
88
const files = require.context('.', true, /\.ts$/)
9-
files.keys().forEach((key) => {
9+
files.keys().forEach(key => {
1010
if (key !== './index.ts') files(key).default(app)
1111
})
1212
}

src/styles/antd.less

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// 配置 antd 样式相关
2+
@import '~ant-design-vue/dist/antd.less'; // 引入官方提供的 less 样式入口文件
3+
4+
// 定制主题
5+
@primary-color : #00a971; // 全局主色
6+
@primary : #00a971;
7+
@link-color : #00a971; // 链接色
8+
@success-color : #52c41a; // 成功色
9+
@warning-color : #faad14; // 警告色
10+
@error-color : #f5222d; // 错误色
11+
@font-size-base : 14px; // 主字号
12+
@heading-color : rgba(0, 0, 0, 0.85); // 标题色
13+
@text-color : rgba(0, 0, 0, 0.65); // 主文本色
14+
@text-color-secondary: rgba(0, 0, 0, 0.45); // 次文本色
15+
@disabled-color : rgba(0, 0, 0, 0.25); // 失效色
16+
@border-radius-base : 2px; // 组件/浮层圆角
17+
@border-color-base : #d9d9d9; // 边框色
18+
@box-shadow-base : 0 2px 8px rgba(0, 0, 0, 0.15); //

src/styles/common.less

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.g-description,
2+
.g-desc {
3+
font-size : 18px;
4+
font-weight: 400;
5+
color : #333333;
6+
line-height: 27px;
7+
text-align : justify;
8+
}
9+
10+
.g-title {
11+
font-size : 36px;
12+
font-weight: 500;
13+
color : #333333;
14+
line-height: 36px;
15+
16+
}
17+
18+
.g-sub-title {
19+
font-size : 30px;
20+
font-weight: 500;
21+
color : #333333;
22+
line-height: 30px;
23+
}
24+
25+
.g-flex-row {
26+
display : flex;
27+
flex-flow : row nowrap;
28+
justify-content: center;
29+
align-items : center;
30+
}
31+
32+
.g-flex-col {
33+
display : flex;
34+
flex-flow : column nowrap;
35+
justify-content: center;
36+
align-items : center;
37+
}

src/styles/iconfont.less

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* iconfont */
2+
@font-face {
3+
font-family: 'iconfont'; /* project id 2092412 */
4+
src: url('//at.alicdn.com/t/font_2092412_vdxq6u8c7um.eot');
5+
src: url('//at.alicdn.com/t/font_2092412_vdxq6u8c7um.eot?#iefix') format('embedded-opentype'),
6+
url('//at.alicdn.com/t/font_2092412_vdxq6u8c7um.woff2') format('woff2'),
7+
url('//at.alicdn.com/t/font_2092412_vdxq6u8c7um.woff') format('woff'),
8+
url('//at.alicdn.com/t/font_2092412_vdxq6u8c7um.ttf') format('truetype'),
9+
url('//at.alicdn.com/t/font_2092412_vdxq6u8c7um.svg#iconfont') format('svg');
10+
}
11+
12+
.iconfont {
13+
font-family: 'iconfont' !important;
14+
font-size: 16px;
15+
font-style: normal;
16+
-webkit-font-smoothing: antialiased;
17+
-webkit-text-stroke-width: 0.2px;
18+
-moz-osx-font-smoothing: grayscale;
19+
}
20+
21+
/** 使用姿势 <i class="iconfont">&#x33; </i> */

src/styles/index.less

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@import './normalize.css';
2+
@import './var.less';
3+
@import './iconfont.less';
4+
@import './common.less';

0 commit comments

Comments
 (0)