使用i18n实现vue2+element UI的国际化
搭建环境
安装i18n
要注意使用vue2安装i18n不能安装最新版,会不兼容。
npm install vue-i18n@8.27.1 --save
新建相关文件
其中en.js和zh.js是存放自定义的语言配置文件,change-language.vue是实现切换语言的组件的文件。index.js 是语言包入口文件。
编写代码
index.js的内容
import Vue from 'vue'
import VueI18n from 'vue-i18n'
// 引入自定义的各个语言配置文件
import zh from './config/zh';
import en from './config/en';
//element-ui自带多语言配置
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
Vue.use(VueI18n)
// 各个国家语言包
const messages = {
en: {
...en,
...enLocale
},
zh: {
...zh,
...zhLocale
},
}
export default new VueI18n({
locale: localStorage.getItem('change-language') || 'zh-CN',
messages,
silentTranslationWarn: true // 忽略翻译警告
})
change-language.vue
<template>
<el-dropdown @command="handle">
<span class="el-dropdown-link ">
{{$t('Language')}}<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item, index) of list" :key="index" :command="item.key">{{item.name}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
name: 'change-language',
data() {
return {
list: [
{ key: 'en', name: 'English' }, // 英语
{ key: 'zh-CN', name: '中文' } // 中文
]
}
},
methods: {
handle(value) {
this.$i18n.locale = value
localStorage.setItem('change-language', value)
location.reload()
}
}
}
</script>
<style scoped lang="scss">
</style>
这里我把选择的是什么语言存储到本地
localStorage.setItem('change-language', value)
实现国际化
在main.js中引入
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import element from "@/element";
import 'element-ui/lib/theme-chalk/index.css';
// 国际化
import i18n from './components/i18n';
Vue.config.productionTip = false
Vue.use(element, {
i18n: (key, value) => i18n.t(key, value)
})
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount('#app')
根据项目编写自定义的语言配置文件
en.js
const en = {
'Language': 'English',
login:{
title:"Movie Review Information Management System",
username: "Username",
password: "Password",
rememberMe: "Remember Me",
forgotPassword: "Forgot Password",
login: "Login",
loggingIn: "Logging In...",
footer: "Copyright © 2023-2024 Movie Review Information Management System All Rights Reserved.",
enterUsername: "Please enter your username",
enterPassword: "Please enter your password"
}
}
export default en;
zh.js
const zh = {
'Language': '中文',
login:{
title:'电影点评网站信息管理系统',
username: "账号",
password: "密码",
rememberMe: "记住密码",
forgotPassword: "忘记密码",
login: "登录",
loggingIn: "登录中...",
footer: "Copyright © 2023-2024 电影点评网站信息管理系统 All Rights Reserved.",
enterUsername: "请输入您的账号",
enterPassword: "请输入您的密码"
}
}
export default zh;
在登录页面调用
一旦将 VueI18n 实例挂载到 Vue 实例上,在 Vue 组件中直接使用 $t 方法,可以通过指定键(key)来获取对应语言的翻译文本。
在template中直接使用,如下:
$t('login.title')
在script中使用,如下:
this.$t('login.enterUsername')
和在template中直接使用的区别就是在前面加上了this
下面是完整代码,仅供参考
<template>
<div class="login">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">{{ $t('login.title') }}</h3>
<el-form-item prop="userNo">
<el-input
v-model="loginForm.userNo"
type="text"
auto-complete="off"
:placeholder="$t('login.enterUsername')"
>
<i slot="prefix" class="el-input__icon el-icon-user"></i>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
:placeholder="$t('login.enterPassword')"
@keyup.enter.native="handleLogin"
>
<i slot="prefix" class="el-input__icon el-icon-lock"></i>
</el-input>
</el-form-item>
<div style="margin:0 0 25px 0;text-align:left">
<el-checkbox v-model="loginForm.rememberMe">
{{ $t('login.rememberMe') }}
</el-checkbox>
<el-link type="primary" :href="'http://localhost:8080/user/forgetPassword'" style="margin-left: 10px">
{{ $t('login.forgotPassword') }}
</el-link>
</div>
<el-form-item style="width:100%;">
<el-button
:loading="loading"
size="medium"
type="primary"
style="width:100%;"
@click.native.prevent="handleLogin"
@keyup.enter="handleLogin"
>
<span v-if="!loading">{{ $t('login.login') }}</span>
<span v-else>{{ $t('login.loggingIn') }}</span>
</el-button>
</el-form-item>
</el-form>
<div class="ChangeLanguage-container" >
<!-- 添加 ChangeLanguage 组件 -->
<ChangeLanguage/>
</div>
<!-- 底部 -->
<div class="el-login-footer">
<span> {{ $t('login.footer') }}</span>
</div>
</div>
</template>
<script>
import Cookies from 'js-cookie';
import {Login} from "@/api/api";
import {
addToken,
addUserCache,
removeToken,
removeUserCache,
} from "@/api/userCache";
import userMenusMap from "@/utils/menu";
import ChangeLanguage from '@/components/i18n/change-language'
export default {
name: "Login",
components: {
ChangeLanguage // 注册 ChangeLanguage 组件
},
data() {
return {
codeUrl: "",
loginForm: {
userNo: "",
password: "",
rememberMe: false,
},
loginRules: {
userNo: [
{required: true, trigger: "blur", message: this.$t('login.enterUsername')}
],
password: [
{required: true, trigger: "blur", message: this.$t('login.enterPassword')}
]
},
loading: false,
};
},
mounted() {
removeUserCache();
removeToken();
localStorage.removeItem('home')
},
created() {
removeUserCache();
removeToken();
localStorage.removeItem('home')
this.getCookie();
},
methods: {
getCookie() {
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get('rememberMe')
const type = Cookies.get('type')
this.loginForm = {
userNo: username === undefined ? this.loginForm.userNo : username,
password: password === undefined ? this.loginForm.password : password,
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
};
},
handleLogin() {
this.$refs.loginForm.validate(async valid => {
if (valid) {
localStorage.removeItem('home');
this.loading = true;
if (this.loginForm.rememberMe) {
Cookies.set("username", this.loginForm.userNo, { expires: 30 });// 30天
Cookies.set("password", this.loginForm.password, { expires: 30 });
Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
} else {
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove('rememberMe');
Cookies.remove('type');
}
const params = {
password: this.loginForm.password,
id: this.loginForm.userNo,
}
const result = await Login(params);
if (result.code === 20000) {
let user = result.data.user;
let token = result.data.token;
addUserCache(user);
addToken(token);
this.$message({
type: "success",
message: result.message,
duration: 1000
});
const type = user.type
localStorage.setItem('home', userMenusMap[type][1])
await this.$router.push({
path: '/'
})
} else {
removeUserCache();
removeToken();
this.$message({
type: "error",
message: result.message,
duration: 1000
});
}
this.loading = false
}
});
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss">
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-image: url("/public/image/login.png");
background-size: cover;
}
.title {
margin: 0 auto 30px auto;
text-align: center;
color: #707070;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
}
.ChangeLanguage-container {
position: fixed;
width: 60px;
text-align: center;
margin-top: 332px;
color: #000000;
font-family: Arial, serif;
font-size: 12px;
letter-spacing: 1px;
background-color: #FFFFFF;
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #000000;
font-family: Arial, serif;
font-size: 12px;
letter-spacing: 1px;
}
</style>
效果图
中文:
英文:
参考文章
https://blog.csdn.net/xiakekeali/article/details/131720748
https://www.jianshu.com/p/623c7e9dfaec