当前位置:   article > 正文

Vite2+Vue3学习笔记(四):引入Vue-i18n并实现按钮切换页面语言_i18n改变首页

i18n改变首页

目录

参考链接

前言

项目码云Gitea地址

其他文章

四、引入Vue-i18n并实现按钮切换语言

1.安装vue-i18n

 package.json

2.准备语言文件

3.配置文件

4.全局配置

5.修改首页src/components/Main.vue

1)在Element Plus容器布局的例子基础上修改下拉菜单,增加单选按钮组和头像:

2)在setup()中使用vue-i18n:

3)修改单选按钮组和下拉菜单文本,渲染en_US.js中自定义的文本:

4)添加change事件监听单选按钮组,实现点击按钮切换自定义国际化文件的功能:

6. 配置Element Plus组件国际化

7.折腾系列之添加退出登录事件

8.折腾系列之替换首页el-main


参考链接

vue3.0配置vue-i18n - 易函123 - 博客园

vue3国际化如何使用vue-i18n以及解决切换语言不刷新的问题 - baifangzi - 博客园

前言

        本人职场小白,公司让学习Vite和Vue3并搭建项目Demo,借这个机会自己尝试写写博客,主要目的是搭项目,所以原理性的知识没有过多阐述,写博客时也根据步骤复现了,对于新手直接跟着操作就可以把项目搭起来,少走了很多弯路,希望对大家有帮助。

        文中参考链接都有附上,参考时可以看看,如果有任何错误或意见也欢迎大家指点。

项目码云Gitea地址

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博客

四、引入Vue-i18n并实现按钮切换语言

官网:Installation | Vue I18n

1.安装vue-i18n

npm i vue-i18n@next --save

  •  package.json

  1. {
  2.   "name": "test-demo-1",
  3.   "version": "0.0.0",
  4.   "scripts": {
  5.     "dev": "vite",
  6.     "build": "vite build",
  7.     "serve": "vite preview"
  8.   },
  9.   "dependencies": {
  10.     "axios": "^0.24.0",
  11.     "element-plus": "^1.2.0-beta.3",
  12.     "sass": "^1.43.5",
  13.     "scss": "^0.2.4",
  14.     "vue": "^3.2.16",
  15.     "vue-i18n": "^9.2.0-beta.20",
  16.     "vue-router": "^4.0.12"
  17.   },
  18.   "devDependencies": {
  19.     "@vitejs/plugin-vue": "^1.9.3",
  20.     "vite": "^2.6.4"
  21.   }
  22. }

2.准备语言文件

  • src/lang/zh_CN.js

自定义中文文本。

  1. const zh_CN = {
  2.     nav: {
  3.         chi: '简体中文',
  4.         eng: '英语',
  5.         personalCenter: '个人中心',
  6.         logout: '退出登录',
  7.     },
  8. };
  9. export default zh_CN;
  • src/lang/en_US.js

自定义英文文本。

  1. const en_US = {
  2.     nav: {
  3.         chi: 'CN',
  4.         eng: 'EN',
  5.         personalCenter: 'Personal Center',
  6.         logout: 'Sign Out',
  7.     },
  8. };
  9. export default en_US;

3.配置文件

  • src/lang/index.js

  1. import { createI18n } from 'vue-i18n';
  2. // 自定义国际化文件
  3. import zh_CN from './zh_CN';
  4. import en_US from './en_US';
  5. const i18n = createI18n({
  6.     legacy: false, // Composition API 模式
  7.     globalInjection: true, // 全局注册 $t方法
  8.     // 默认语言
  9.     locale: 'zh_CN',
  10.     // 语言库
  11.     messages: {
  12.         zh_CN: zh_CN,
  13.         en_US: en_US
  14.     }
  15. });
  16. // 将i18n暴露出去,在main.js中引入挂载
  17. export default i18n;

4.全局配置

  • src/main.js

  1. // 引入Vue-i18n
  2. import i18n from './lang'
  3. app.use(i18n);

5.修改首页src/components/Main.vue

1)在Element Plus容器布局的例子基础上修改下拉菜单,增加单选按钮组和头像:

官网:Container 布局容器 | Element Plus

  1. <template>
  2.   <el-container style="border: 1px solid #eee">
  3.     <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
  4.       <el-menu :default-openeds="['1', '3']" style="height: 100%">
  5.         ......
  6.       </el-menu>
  7.     </el-aside>
  8.     <el-container>
  9.       <el-header class="flex-center-flex-end">
  10.         <el-radio-group
  11.           v-model="toggle_locale"
  12.           size="mini"
  13.           border
  14.           style="margin-right: 20px"
  15.         >
  16.           <el-radio-button label="简体中文"></el-radio-button>
  17.           <el-radio-button label="英语"></el-radio-button>
  18.         </el-radio-group>
  19.         <el-dropdown>
  20.           <el-avatar
  21.             src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
  22.           ></el-avatar>
  23.           <template #dropdown>
  24.             <el-dropdown-menu>
  25.               <el-dropdown-item>个人中心</el-dropdown-item>
  26.               <el-dropdown-item>退出登录</el-dropdown-item>
  27.             </el-dropdown-menu>
  28.           </template>
  29.         </el-dropdown>
  30.       </el-header>
  31.       <el-main>
  32.         ......
  33.       </el-main>
  34.     </el-container>
  35.   </el-container>
  36. </template>
  37. <script lang="ts">
  38. import { defineComponent, ref } from "vue";
  39. import { Message, Menu, Setting } from "@element-plus/icons";
  40. export default defineComponent({
  41.   components: {
  42.     Message,
  43. Setting,
  44.     "icon-menu": Menu,
  45.   },
  46.   setup() {
  47.     return {
  48.       toggle_locale: ref("简体中文"), //和el-radio-button的label保持一致
  49.     };
  50.   },
  51. });
  52. </script>
  53. <style>
  54. .el-header {
  55.   background-color: #b3c0d1;
  56.   color: var(--el-text-color-primary);
  57.   line-height: 60px;
  58. }
  59. .el-aside {
  60.   color: var(--el-text-color-primary);
  61. }
  62. .flex-center-flex-end {
  63.   display: flex;
  64.   align-items: center;
  65.   justify-content: flex-end;
  66. }
  67. </style>

2)在setup()中使用vue-i18n:

  1. <script lang="ts">
  2. import { defineComponent, ref } from "vue";
  3. import { useI18n } from "vue-i18n";
  4. export default defineComponent({
  5.   setup() {
  6.     // i18n
  7.     const { locale } = useI18n(); // vue-i18n提供了一个钩子函数 useI18n(),暴露出locale属性用于切换语言
  8.     locale.value = "en_US"; // 要切换的语言
  9.     const chi = useI18n().t("nav.chi");
  10.     const eng = useI18n().t("nav.eng");
  11.     let myLocale = useI18n().locale.value; // 记录自定义国际化文件的locale值,为【后续和Element Plus国际化文件的locale区分开】做准备
  12.    
  13. // 切换按钮组选中值
  14.     const toggle_locale = myLocale === "en_US" ? ref(chi) : ref(eng);
  15.     return {
  16.       // i18n
  17.       chi,
  18.       eng,
  19.       toggle_locale,
  20.     };
  21.   },
  22. });
  23. </script>

3)修改单选按钮组和下拉菜单文本,渲染en_US.js中自定义的文本:

  1. <el-header class="flex-center-flex-end">
  2. <el-radio-group
  3.   v-model="toggle_locale"
  4.   size="mini"
  5.   border
  6.   style="margin-right: 20px"
  7. >
  8.   <el-radio-button :label="chi">{{ $t("nav.chi") }}</el-radio-button>
  9.   <el-radio-button :label="eng">{{ $t("nav.eng") }}</el-radio-button>
  10. </el-radio-group>
  11. <el-dropdown>
  12.   <el-avatar
  13.     src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
  14.   ></el-avatar>
  15.   <template #dropdown>
  16.     <el-dropdown-menu>
  17.       <el-dropdown-item>{{ $t("nav.personalCenter") }}</el-dropdown-item>
  18.       <el-dropdown-item>{{ $t("nav.logout") }}</el-dropdown-item>
  19.     </el-dropdown-menu>
  20.   </template>
  21. </el-dropdown>
  22. </el-header>

4)添加change事件监听单选按钮组,实现点击按钮切换自定义国际化文件的功能:

  • <template>
  1. <el-radio-group
  2.     v-model="toggle_locale"
  3.     size="mini"
  4.     border
  5.     style="margin-right: 20px"
  6.     @change="changeLanguage"
  7.   >
  8.     <el-radio-button :label="chi">{{ $t("nav.chi") }}</el-radio-button>
  9.     <el-radio-button :label="eng">{{ $t("nav.eng") }}</el-radio-button>
  10. </el-radio-group>
  • <script> - setup()

按钮切换后把当前语言环境记录到localStorage中,用户刷新页面时根据localStorage的是否有值渲染当前页面的文本(※处)。

  1. // i18n
  2. const { locale } = useI18n(); // vue-i18n提供了一个钩子函数 useI18n(),暴露出locale属性用于切换语言
  3. locale.value = localStorage.getItem("locale") || "zh_CN"; // 要切换的语言 ——※
  4. const chi = useI18n().t("nav.chi");
  5. const eng = useI18n().t("nav.eng");
  6. let myLocale = useI18n().locale.value;
  7. const changeLanguage = (e) => {
  8.   if (e == chi) {
  9.     myLocale = "zh_CN";
  10.     locale.value = "zh_CN";
  11.   } else if (e == eng) {
  12.     myLocale = "en_US";
  13.     locale.value = "en_US";
  14.   }
  15.   localStorage.setItem("locale", myLocale); // ——※
  16. };
  17. // 定义方法集合,整体return出去
  18. let methods = {
  19.   // 切换语言
  20.   changeLanguage,
  21. };
  22. return {
  23.   // i18n
  24.   chi,
  25.   eng,
  26.   toggle_locale,
  27.   ...methods,
  28. };

到这里就可以实现按钮切换页面语言了,但其实还没结束......

引入Element Plus的取色器组件(随便一个组件都可以),会发现切换按钮时,只有通过{{t("")}}或者userI18n().t()两种方式渲染的文本会变化,组件内部文本是不会切换语言的,所以需要配置Element Plus组件国际化。

6. 配置Element Plus组件国际化

参考官方文档:

国际化全局配置:国际化 | Element Plus

使用Config Provider全局配置:全局配置 | Element Plus

  • src/main.js

全局配置,判断当前localStorage的值并初始化:

  1. // Element Plus全局配置国际化
  2. import zhCn from "element-plus/lib/locale/lang/zh-cn";
  3. import en from "element-plus/lib/locale/lang/en";
  4. // app.use(ElementPlus);
  5. app.use(ElementPlus, {
  6.     // locale: zhCn,
  7.     locale: localStorage.getItem('locale') == 'zh_CN' ? zhCn : en,
  8. });
  9. app.mount('#app');
  • src/components/Main.vue

  • <template>

把el-container包裹在el-config-provider中:

  1. <template>
  2.   <el-config-provider :locale="elLocale">
  3.     <el-container>
  4. ......
  5. </el-container>
  6.   </el-config-provider>
  7. </template>
  • <script>

修改※处。

注意:要删除<script>标签后面的【lang="ts"】,否则会报错。

  1. <script>
  2. // ElementPlus组件国际化
  3. import { ElConfigProvider } from "element-plus";
  4. import zhCn from "element-plus/lib/locale/lang/zh-cn";
  5. import en from "element-plus/lib/locale/lang/en";
  6. export default defineComponent({
  7.   components: {
  8.     ElConfigProvider,
  9.   },
  10.   setup() {
  11.     // i18n
  12. // 自定义国际化
  13.     const { locale } = useI18n(); // vue-i18n提供了一个钩子函数 useI18n(),暴露出locale属性用于切换语言
  14.     locale.value = localStorage.getItem("locale") || "zh_CN"; // 要切换的语言
  15.     const chi = useI18n().t("nav.chi");
  16.     const eng = useI18n().t("nav.eng");
  17.     let myLocale = useI18n().locale.value;
  18. // Element Plus组件国际化
  19.     const elLocale_zh = ref(zhCn);
  20.     const elLocale_en = ref(en);
  21.     let elLocale = localStorage.getItem("locale") == "zh_CN" ? elLocale_zh : elLocale_en;
  22.     // 切换按钮组选中值
  23.     const toggle_locale = myLocale === "zh_CN" ? ref(chi) : ref(eng);
  24. // 单选按钮组监听事件
  25.     const changeLanguage = (e) => {
  26.       if (e == chi) {
  27.         myLocale = "zh_CN";
  28.         locale.value = "zh_CN";
  29. // 组件国际化
  30.         const temp = elLocale_zh.value;
  31.         elLocale_zh.value = elLocale_en.value;
  32.         elLocale_en.value = temp;
  33.       } else if (e == eng) {
  34.         myLocale = "en_US";
  35.         locale.value = "en_US";
  36. // 组件国际化
  37.         const temp = elLocale_en.value;
  38.         elLocale_en.value = elLocale_zh.value;
  39.         elLocale_zh.value = temp;
  40.       }
  41.       localStorage.setItem("locale", myLocale);
  42.     };
  43.     let methods = {
  44.       // 切换语言
  45.       changeLanguage,
  46.     };
  47.     return {
  48.       // i18n
  49.       chi,
  50.       eng,
  51.       toggle_locale,
  52. colorPicker: ref("#409EFF"),
  53.       elLocale,
  54.       ...methods,
  55.     };
  56.   },
  57. });
  58. </script>

7.折腾系列之添加退出登录事件

  • <template>

  1. <el-dropdown-menu>
  2.     <el-dropdown-item>{{ $t("nav.personalCenter") }}</el-dropdown-item>
  3.     <el-dropdown-item @click="logout">{{ $t("nav.logout") }}</el-dropdown-item>
  4. </el-dropdown-menu>
  • <script> - setup()

  1. // 退出登录
  2. const logout = () => {
  3.   localStorage.removeItem("Token");
  4.   window.location.href = "/login";
  5. };
  6. let methods = {
  7.   // 退出登录
  8.   logout,
  9.   // 切换语言
  10.   changeLanguage,
  11. };

8.折腾系列之替换首页el-main

  • src/views/AppList.vue

  1. <template>
  2.   <el-table :data="tableData">
  3.     <el-table-column prop="date" label="Date" width="140"> </el-table-column>
  4.     <el-table-column prop="name" label="Name" width="120"> </el-table-column>
  5.     <el-table-column prop="address" label="Address"> </el-table-column>
  6.   </el-table>
  7. </template>
  8. <script>
  9. import { defineComponent, ref } from "vue";
  10. export default defineComponent({
  11.   components: {},
  12.   setup() {
  13.     // 表格数据
  14.     const item = {
  15.       date: "2016-05-02",
  16.       name: "Tom",
  17.       address: "No. 189, Grove St, Los Angeles",
  18.     };
  19.     const tableData = ref(Array(20).fill(item));
  20.     let methods = {};
  21.     return {
  22.       // 表格数据
  23.       tableData,
  24.       ...methods,
  25.     };
  26.   },
  27. });
  28. </script>
  29. <style></style>
  • src/components/Main.vue

  1. <el-main>
  2.   <router-view></router-view>
  3. </el-main>
  • src/router/index.js

  1. import { createRouter, createWebHistory } from "vue-router";
  2. const routerHistory = createWebHistory();
  3. const router = createRouter({
  4.     history: routerHistory,
  5.     routes: [{
  6.         path: "/login",
  7.         name: "login",
  8.         component: () =>
  9.             import ("../components/Login.vue")
  10.     }, {
  11.         path: "/", // 父级路径
  12.         name: "main",
  13.         component: () =>
  14.             import ("../components/Main.vue"),
  15.         children: [{
  16.                 path: "/", // 空路径路由的路径与父级路径保持一致,否则会显示Main.vue,没有渲染router-view
  17.                 redirect: "/appList"
  18.             }, // 定义空路径,用户访问localhost:5000时跳转至首页
  19.             {
  20.                 path: "/appList",
  21.                 name: "appList",
  22.                 component: () =>
  23.                     import ("../views/AppList.vue")
  24.             }
  25.         ]
  26.     }, {
  27.         path: "/:pathMatch(.*)*",
  28.         name: "notFound",
  29.         component: () =>
  30.             import ("../components/NotFound.vue")
  31.     }]
  32. });
  33. // 路由守卫
  34. router.beforeEach((to) => {
  35.     let token = localStorage.getItem('Token');
  36.     if (token && to.path === '/login')
  37.         return "/appList";
  38.     else if (!token && to.path !== '/login')
  39.         return "/login";
  40. });
  41. export default router;

2022年04月13日更新:

感谢评论区涩谷同学提出的问题,测试后发现了问题,代码更新记录请戳链接:

Gitee仓库代码更新记录

  1. <!-- Main.vue -->
  2. <el-dropdown>
  3. {{ $t("label.test") }}
  4. {{ testRefreshData1 }}
  5. </el-dropdown>
  1. // Main.vue
  2. /**
  3. * 测试更新自定义data是否需要刷新
  4. * 解析:确实需要手动刷新页面才会更新,个人理解是国际化相关配置文件只在页面加载时重新引入,而setup中的响应式数据是热更新的,只要lang文件夹下的文件内容没有改变,就不会重新引入,所以需要手动刷新使页面重新import相关文件。
  5. * 测试:修改zh_CN中的label.test文本时页面是自动刷新的,所以按钮切换无效。
  6. * 结论:如果确实需要按钮切换更新页面文本,建议:
  7. * 1.要么自己在template中使用{{t()}},这个可以实现无刷新按钮切换;
  8. * 2.要么就在setup中监测自定义data的改变,一改变就强制刷新页面【不推荐,用户体验不好】。
  9. */
  10. const testRefreshData1 = reactive(useI18n().t("label.test"));
  11. return {
  12. testRefreshData1,
  13. }
  1. // 国际化配置文件
  2. const zh_CN = {
  3. nav: {
  4. chi: '简体中文',
  5. eng: '英语',
  6. personalCenter: '个人中心',
  7. logout: '退出登录',
  8. },
  9. label: {
  10. test: '测试刷新更新文本'
  11. }
  12. };
  13. export default zh_CN;
  14. const en_US = {
  15. nav: {
  16. chi: 'CN',
  17. eng: 'EN',
  18. personalCenter: 'Personal Center',
  19. logout: 'Sign Out',
  20. },
  21. label: {
  22. test: 'Test Refresh Update Text'
  23. }
  24. };
  25. export default en_US;

如果解释不对请大神们指出,谢谢~

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/418103
推荐阅读
相关标签
  

闽ICP备14008679号