赞
踩
目录
1)在Element Plus容器布局的例子基础上修改下拉菜单,增加单选按钮组和头像:
3)修改单选按钮组和下拉菜单文本,渲染en_US.js中自定义的文本:
4)添加change事件监听单选按钮组,实现点击按钮切换自定义国际化文件的功能:
vue3.0配置vue-i18n - 易函123 - 博客园
vue3国际化如何使用vue-i18n以及解决切换语言不刷新的问题 - baifangzi - 博客园
本人职场小白,公司让学习Vite和Vue3并搭建项目Demo,借这个机会自己尝试写写博客,主要目的是搭项目,所以原理性的知识没有过多阐述,写博客时也根据步骤复现了,对于新手直接跟着操作就可以把项目搭起来,少走了很多弯路,希望对大家有帮助。
文中参考链接都有附上,参考时可以看看,如果有任何错误或意见也欢迎大家指点。
Vite-Demo: 使用vite2.0及vue3.0并集成Element Plus,开发后台管理系统demo。https://gitee.com/YG-CST/vite-demo
Vite2+Vue3学习笔记(一):Vue3.0项目搭建及配置过程_YGいくこさん的博客-CSDN博客
Vite2+Vue3学习笔记(二):引入Vue-Router_YGいくこさん的博客-CSDN博客
Vite2+Vue3学习笔记(三):引入Axios并调用后端接口_YGいくこさん的博客-CSDN博客
npm i vue-i18n@next --save
- {
- "name": "test-demo-1",
- "version": "0.0.0",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "serve": "vite preview"
- },
- "dependencies": {
- "axios": "^0.24.0",
- "element-plus": "^1.2.0-beta.3",
- "sass": "^1.43.5",
- "scss": "^0.2.4",
- "vue": "^3.2.16",
- "vue-i18n": "^9.2.0-beta.20",
- "vue-router": "^4.0.12"
- },
- "devDependencies": {
- "@vitejs/plugin-vue": "^1.9.3",
- "vite": "^2.6.4"
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
src/lang/zh_CN.js
自定义中文文本。
- const zh_CN = {
- nav: {
- chi: '简体中文',
- eng: '英语',
- personalCenter: '个人中心',
- logout: '退出登录',
- },
- };
- export default zh_CN;
src/lang/en_US.js
自定义英文文本。
- const en_US = {
- nav: {
- chi: 'CN',
- eng: 'EN',
- personalCenter: 'Personal Center',
- logout: 'Sign Out',
- },
- };
- export default en_US;
src/lang/index.js
- import { createI18n } from 'vue-i18n';
-
- // 自定义国际化文件
- import zh_CN from './zh_CN';
- import en_US from './en_US';
-
- const i18n = createI18n({
- legacy: false, // Composition API 模式
- globalInjection: true, // 全局注册 $t方法
- // 默认语言
- locale: 'zh_CN',
- // 语言库
- messages: {
- zh_CN: zh_CN,
- en_US: en_US
- }
- });
-
- // 将i18n暴露出去,在main.js中引入挂载
- export default i18n;
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
src/main.js
- // 引入Vue-i18n
- import i18n from './lang'
-
- app.use(i18n);
官网:Container 布局容器 | Element Plus
- <template>
- <el-container style="border: 1px solid #eee">
- <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
- <el-menu :default-openeds="['1', '3']" style="height: 100%">
- ......
- </el-menu>
- </el-aside>
- <el-container>
- <el-header class="flex-center-flex-end">
- <el-radio-group
- v-model="toggle_locale"
- size="mini"
- border
- style="margin-right: 20px"
- >
- <el-radio-button label="简体中文"></el-radio-button>
- <el-radio-button label="英语"></el-radio-button>
- </el-radio-group>
- <el-dropdown>
- <el-avatar
- src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
- ></el-avatar>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item>个人中心</el-dropdown-item>
- <el-dropdown-item>退出登录</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </el-header>
- <el-main>
- ......
- </el-main>
- </el-container>
- </el-container>
- </template>
- <script lang="ts">
- import { defineComponent, ref } from "vue";
- import { Message, Menu, Setting } from "@element-plus/icons";
- export default defineComponent({
- components: {
- Message,
- Setting,
- "icon-menu": Menu,
- },
- setup() {
- return {
- toggle_locale: ref("简体中文"), //和el-radio-button的label保持一致
- };
- },
- });
- </script>
- <style>
- .el-header {
- background-color: #b3c0d1;
- color: var(--el-text-color-primary);
- line-height: 60px;
- }
- .el-aside {
- color: var(--el-text-color-primary);
- }
- .flex-center-flex-end {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- }
- </style>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- <script lang="ts">
- import { defineComponent, ref } from "vue";
- import { useI18n } from "vue-i18n";
-
- export default defineComponent({
- setup() {
- // i18n
- const { locale } = useI18n(); // vue-i18n提供了一个钩子函数 useI18n(),暴露出locale属性用于切换语言
- locale.value = "en_US"; // 要切换的语言
- const chi = useI18n().t("nav.chi");
- const eng = useI18n().t("nav.eng");
- let myLocale = useI18n().locale.value; // 记录自定义国际化文件的locale值,为【后续和Element Plus国际化文件的locale区分开】做准备
-
- // 切换按钮组选中值
- const toggle_locale = myLocale === "en_US" ? ref(chi) : ref(eng);
-
- return {
- // i18n
- chi,
- eng,
- toggle_locale,
- };
- },
- });
- </script>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- <el-header class="flex-center-flex-end">
- <el-radio-group
- v-model="toggle_locale"
- size="mini"
- border
- style="margin-right: 20px"
- >
- <el-radio-button :label="chi">{{ $t("nav.chi") }}</el-radio-button>
- <el-radio-button :label="eng">{{ $t("nav.eng") }}</el-radio-button>
- </el-radio-group>
- <el-dropdown>
- <el-avatar
- src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
- ></el-avatar>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item>{{ $t("nav.personalCenter") }}</el-dropdown-item>
- <el-dropdown-item>{{ $t("nav.logout") }}</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </el-header>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- <el-radio-group
- v-model="toggle_locale"
- size="mini"
- border
- style="margin-right: 20px"
- @change="changeLanguage"
- >
- <el-radio-button :label="chi">{{ $t("nav.chi") }}</el-radio-button>
- <el-radio-button :label="eng">{{ $t("nav.eng") }}</el-radio-button>
- </el-radio-group>
按钮切换后把当前语言环境记录到localStorage中,用户刷新页面时根据localStorage的是否有值渲染当前页面的文本(※处)。
- // i18n
- const { locale } = useI18n(); // vue-i18n提供了一个钩子函数 useI18n(),暴露出locale属性用于切换语言
- locale.value = localStorage.getItem("locale") || "zh_CN"; // 要切换的语言 ——※
- const chi = useI18n().t("nav.chi");
- const eng = useI18n().t("nav.eng");
- let myLocale = useI18n().locale.value;
-
- const changeLanguage = (e) => {
- if (e == chi) {
- myLocale = "zh_CN";
- locale.value = "zh_CN";
- } else if (e == eng) {
- myLocale = "en_US";
- locale.value = "en_US";
- }
- localStorage.setItem("locale", myLocale); // ——※
- };
-
- // 定义方法集合,整体return出去
- let methods = {
- // 切换语言
- changeLanguage,
- };
- return {
- // i18n
- chi,
- eng,
- toggle_locale,
- ...methods,
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
到这里就可以实现按钮切换页面语言了,但其实还没结束......
引入Element Plus的取色器组件(随便一个组件都可以),会发现切换按钮时,只有通过{{t("")}}或者userI18n().t()两种方式渲染的文本会变化,组件内部文本是不会切换语言的,所以需要配置Element Plus组件国际化。
参考官方文档:
国际化全局配置:国际化 | Element Plus
使用Config Provider全局配置:全局配置 | Element Plus
src/main.js
全局配置,判断当前localStorage的值并初始化:
- // Element Plus全局配置国际化
- import zhCn from "element-plus/lib/locale/lang/zh-cn";
- import en from "element-plus/lib/locale/lang/en";
-
- // app.use(ElementPlus);
- app.use(ElementPlus, {
- // locale: zhCn,
- locale: localStorage.getItem('locale') == 'zh_CN' ? zhCn : en,
- });
- app.mount('#app');
src/components/Main.vue
<template>
把el-container包裹在el-config-provider中:
- <template>
- <el-config-provider :locale="elLocale">
- <el-container>
- ......
- </el-container>
- </el-config-provider>
- </template>
修改※处。
注意:要删除<script>标签后面的【lang="ts"】,否则会报错。
- <script>
- // ElementPlus组件国际化
- import { ElConfigProvider } from "element-plus";
- import zhCn from "element-plus/lib/locale/lang/zh-cn";
- import en from "element-plus/lib/locale/lang/en";
-
- export default defineComponent({
- components: {
- ElConfigProvider,
- },
- setup() {
- // i18n
- // 自定义国际化
- const { locale } = useI18n(); // vue-i18n提供了一个钩子函数 useI18n(),暴露出locale属性用于切换语言
- locale.value = localStorage.getItem("locale") || "zh_CN"; // 要切换的语言
- const chi = useI18n().t("nav.chi");
- const eng = useI18n().t("nav.eng");
- let myLocale = useI18n().locale.value;
-
- // Element Plus组件国际化
- const elLocale_zh = ref(zhCn);
- const elLocale_en = ref(en);
- let elLocale = localStorage.getItem("locale") == "zh_CN" ? elLocale_zh : elLocale_en;
-
- // 切换按钮组选中值
- const toggle_locale = myLocale === "zh_CN" ? ref(chi) : ref(eng);
-
- // 单选按钮组监听事件
- const changeLanguage = (e) => {
- if (e == chi) {
- myLocale = "zh_CN";
- locale.value = "zh_CN";
- // 组件国际化
- const temp = elLocale_zh.value;
- elLocale_zh.value = elLocale_en.value;
- elLocale_en.value = temp;
- } else if (e == eng) {
- myLocale = "en_US";
- locale.value = "en_US";
- // 组件国际化
- const temp = elLocale_en.value;
- elLocale_en.value = elLocale_zh.value;
- elLocale_zh.value = temp;
- }
- localStorage.setItem("locale", myLocale);
- };
-
- let methods = {
- // 切换语言
- changeLanguage,
- };
-
- return {
- // i18n
- chi,
- eng,
- toggle_locale,
- colorPicker: ref("#409EFF"),
- elLocale,
- ...methods,
- };
- },
- });
- </script>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
<template>
- <el-dropdown-menu>
- <el-dropdown-item>{{ $t("nav.personalCenter") }}</el-dropdown-item>
- <el-dropdown-item @click="logout">{{ $t("nav.logout") }}</el-dropdown-item>
- </el-dropdown-menu>
<script> - setup()
- // 退出登录
- const logout = () => {
- localStorage.removeItem("Token");
- window.location.href = "/login";
- };
-
- let methods = {
- // 退出登录
- logout,
- // 切换语言
- changeLanguage,
- };
src/views/AppList.vue
- <template>
- <el-table :data="tableData">
- <el-table-column prop="date" label="Date" width="140"> </el-table-column>
- <el-table-column prop="name" label="Name" width="120"> </el-table-column>
- <el-table-column prop="address" label="Address"> </el-table-column>
- </el-table>
- </template>
-
- <script>
- import { defineComponent, ref } from "vue";
- export default defineComponent({
- components: {},
- setup() {
- // 表格数据
- const item = {
- date: "2016-05-02",
- name: "Tom",
- address: "No. 189, Grove St, Los Angeles",
- };
- const tableData = ref(Array(20).fill(item));
- let methods = {};
- return {
- // 表格数据
- tableData,
- ...methods,
- };
- },
- });
- </script>
-
- <style></style>
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
src/components/Main.vue
- <el-main>
- <router-view></router-view>
- </el-main>
src/router/index.js
- import { createRouter, createWebHistory } from "vue-router";
- const routerHistory = createWebHistory();
- const router = createRouter({
- history: routerHistory,
- routes: [{
- path: "/login",
- name: "login",
- component: () =>
- import ("../components/Login.vue")
- }, {
- path: "/", // 父级路径
- name: "main",
- component: () =>
- import ("../components/Main.vue"),
- children: [{
- path: "/", // 空路径路由的路径与父级路径保持一致,否则会显示Main.vue,没有渲染router-view
- redirect: "/appList"
- }, // 定义空路径,用户访问localhost:5000时跳转至首页
- {
- path: "/appList",
- name: "appList",
- component: () =>
- import ("../views/AppList.vue")
- }
- ]
- }, {
- path: "/:pathMatch(.*)*",
- name: "notFound",
- component: () =>
- import ("../components/NotFound.vue")
- }]
- });
-
- // 路由守卫
- router.beforeEach((to) => {
- let token = localStorage.getItem('Token');
- if (token && to.path === '/login')
- return "/appList";
- else if (!token && to.path !== '/login')
- return "/login";
- });
-
- export default router;
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
感谢评论区涩谷同学提出的问题,测试后发现了问题,代码更新记录请戳链接:
- <!-- Main.vue -->
- <el-dropdown>
- {{ $t("label.test") }}
- {{ testRefreshData1 }}
- </el-dropdown>
- // Main.vue
- /**
- * 测试更新自定义data是否需要刷新
- * 解析:确实需要手动刷新页面才会更新,个人理解是国际化相关配置文件只在页面加载时重新引入,而setup中的响应式数据是热更新的,只要lang文件夹下的文件内容没有改变,就不会重新引入,所以需要手动刷新使页面重新import相关文件。
- * 测试:修改zh_CN中的label.test文本时页面是自动刷新的,所以按钮切换无效。
- * 结论:如果确实需要按钮切换更新页面文本,建议:
- * 1.要么自己在template中使用{{t()}},这个可以实现无刷新按钮切换;
- * 2.要么就在setup中监测自定义data的改变,一改变就强制刷新页面【不推荐,用户体验不好】。
- */
- const testRefreshData1 = reactive(useI18n().t("label.test"));
-
- return {
- testRefreshData1,
- }
- // 国际化配置文件
- const zh_CN = {
- nav: {
- chi: '简体中文',
- eng: '英语',
- personalCenter: '个人中心',
- logout: '退出登录',
- },
- label: {
- test: '测试刷新更新文本'
- }
- };
-
- export default zh_CN;
-
-
- const en_US = {
- nav: {
- chi: 'CN',
- eng: 'EN',
- personalCenter: 'Personal Center',
- logout: 'Sign Out',
- },
- label: {
- test: 'Test Refresh Update Text'
- }
- };
-
- export default en_US;
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
如果解释不对请大神们指出,谢谢~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。