一、添加国际化
先看效果
中文
英文
1、安装vue-i18n
npm install vue-i18n@8.24.5 -S (我这里node版本10.24.2)
2、新增文件
1)在src目录下新增lang文件夹,并在lang文件夹下新建如下文件
index.js
代码如下:
// 进行多语言支持配置
import Vue from 'vue' // 引入Vue
import VueI18n from 'vue-i18n' // 引入国际化的插件包
import Cookies from 'js-cookie' // 引入 Cookies 保存当前默认语言选项
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui 英文包
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui 中文包
// 自定义的中英文配置
import enLocale from './en'
import zhLocale from './zh'
Vue.use(VueI18n); // 全局注册国际化包
// 创建国际化插件的实例
const i18n = new VueI18n({
// 指定语言类型 zh表示中文 en表示英文 set locale 设置默认初始化的语言 i18n
locale: Cookies.get('language') || 'zh',
// 将将elementUI语言包 和自定义语言包 加入到插件语言数据里 set locale messages
messages: {
// 英文环境下的语言数据
en: {
...enLocale,
...elementEnLocale
},
// 中文环境下的语言数据
zh: {
...zhLocale,
...elementZhLocale
}
}
});
export default i18n
zh.js和en.js分别对应不同的语言,这里仅中文和英文,可自行添加别的语言
2)在src下的util文件夹新建i8n.js文件
代码如下
// 翻译router.meta。标题,用于面包屑侧边栏tagsview
export function generateTitle(title) {
const hasKey = this.$te('route.' + title)
if (hasKey) {
// $t :this method from vue-i18n, inject in @/lang/index.js
return this.$t('route.' + title)
}
return title
}
3、配置i8n
1) 在main.js文件中添加如下内容
代码如下
//国际化
import i18n from './lang'
Vue.use(ElementUI,{
i18n: (key,value) => i18n.t(key,value)
})
2)修改store文件夹
修改modules文件夹下的app.js文件,添加如下内容
代码如下
language: Cookies.get('language') || 'zh'
SET_LANGUAGE: (state, language) => {
state.language = language
Cookies.set('language', language)
}
setLanguage({
commit
}, language) {
commit('SET_LANGUAGE', language)
},
getters.js文件中添加如下内容
代码如下
language: state => state.app.language,
size: state => state.app.size,
4、应用
1) 在topheader中加入选择下拉框(可自行选择地方)
在layout-components-Navbar.vue中添加如下内容
代码如下
<template>
<lang-select class="right-menu-item hover-effect"/>
</template>
2)添加语言选择下拉框组件
在src components文件夹新建 LangSelect-index.vue文件
代码如下
这里加了一些图片样式,可自行修改
<template>
<el-dropdown trigger="click" class="international" @command="handleSetLanguage">
<div style="margin-right: 15px">
<img src="../../assets/language.png" style="width: 20px;height: 20px;margin-right: 8px;margin-top: 2px"/>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :disabled="language==='zh'" command="zh">
<div>
<img src="../../assets/chineseflag.png" style="width: 15px;margin-right: 8px"/>
中文
</div>
</el-dropdown-item>
<el-dropdown-item :disabled="language==='en'" command="en">
<div>
<img src="../../assets/english.png" style="width: 15px;margin-right: 8px"/>
English
</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
name: "LangSelect",
computed: {
language() {
return this.$store.getters.language
}
},
data(){
return{
}
},
created() {
},
watch:{
},
methods: {
handleSetLanguage(lang) {
this.$i18n.locale = lang;
this.$store.dispatch('app/setLanguage', lang)
this.$message.success('切换语言成功!!')
}
}
}
</script>
<style>
</style>
至此大致国际化功能已经实现,在页面中通过 $t('') 来渲染即可
可使用{{ }}或者v-bind方式实现
5、面包屑,侧边菜单栏转换
1)面包屑 (这里面包屑的实现就不讲解了,可自行查阅)
修改如下内容
代码如下
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ generateTitle(item.meta.title) }}</span>
<a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
import { generateTitle } from '@/utils/i18n'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
generateTitle,
getBreadcrumb() {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>
2)侧边菜单栏
修改如下内容
代码如下
<template>
<div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateTitle(onlyOneChild.meta.title)" />
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="generateTitle(item.meta.title)" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
</div>
</template>
<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
import { generateTitle } from '@/utils/i18n'
export default {
name: 'SidebarItem',
components: { Item, AppLink },
mixins: [FixiOSBug],
props: {
// route object
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
}
},
data() {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: refactor with render function
this.onlyOneChild = null
return {}
},
methods: {
generateTitle,
hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
return true
}
return false
},
resolvePath(routePath) {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
}
return path.resolve(this.basePath, routePath)
}
}
}
</script>
英文的翻译名称与路由中的meta中的title一致
只需在route中编写,因为在i8n.js中已经做了处理 如图
想要获取当前的语言可以通过 this.$store.getters.language 来获取,