Vue3+vite优化基础架构(3)--- 优化vue-i18n国际化配置

news/2024/9/24 13:22:41/

Vue3+vite优化基础架构(3)--- 优化vue-i18n国际化配置

  • 说明
  • 全部页面进行中英文使用
  • 测试中英文切换
  • 对ElementPlus里面的所有组件进行中英文切换

说明

这里记录下自己在Vue3+vite的项目增加全局中英文切换按钮对页面进行中英文切换及同时对ElementPlus里面的所有组件进行中英文切换,不使用ts语法,方便以后直接使用。这里承接自己的博客Vue3+vite优化基础架构(2)— 全局接口请求loading加载这篇博客,在该博客项目的基础上增加全局中英文切换按钮对页面进行中英文切换及同时对ElementPlus里面的所有组件进行中英文切换。

全部页面进行中英文使用

在src/store/modules/userStore.js文件下增加如下代码:
在这里插入图片描述

userStore.js文件代码如下:

javascript">//使用pinia来管理全局状态
import { defineStore } from "pinia"/*defineStore 是需要传参数的,其中第一个参数是id,就是一个唯一的值,
简单点说就可以理解成是一个命名空间.
第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state,
第二个是 getters,
第三个是 actions。
*/
//声明了一个useUserStore方法
const useUserStore = defineStore('user', {//准备state——用于存储数据state: () => {return {//当前激活菜单的indexactiveMenu: '',//绑定值,选中选项卡的nameeditableTabsValue: '',//tab标签选项卡内容editableTabs: [],//tab页路由地址及参数tabRouterList: [],//中英文语言,默认中文language: 'zh'}},//使用persist插件对state里面属性进行缓存persist: {enabled: true,//开启缓存,默认缓存所有state里面的属性,默认key为defineStore里面的id值,这里id值为user,所以默认key为user//自定义持久化参数,指定以下state里面的属性进行缓存,未指定的不进行缓存strategies: [{// 自定义keykey: 'activeMenu',// 自定义存储方式,默认sessionStoragestorage: sessionStorage,// 指定要持久化的数据paths: ['activeMenu']},{key: 'editableTabsValue',storage: sessionStorage,paths: ['editableTabsValue']},{key: 'editableTabs',storage: sessionStorage,paths: ['editableTabs']},{key: 'tabRouterList',storage: sessionStorage,paths: ['tabRouterList']},{key: 'language',storage: sessionStorage,paths: ['language']}]},getters: {},//准备actions——用于响应组件中的动作和用于操作数据(state),pinia中只有state、getter、action,抛弃了Vuex中的Mutationactions: {/*** 修改state中数据的方法* @param name 需要修改的属性名* @param value 修改值*/updateState([name, value]) {this[name] = value},//动态添加tab标签,item为当前点击的菜单项addTab(item) {const newTab = {title: item.meta.title,name: item.url,iconClass: item.meta.icon,}// 判断当前editableTabs中是否存在该tab标签if (this.editableTabs.findIndex(item => item.title === newTab.title) === -1) {this.editableTabs.push(newTab);this.editableTabsValue = newTab.name;this.activeMenu = newTab.name;}},//移除tab标签removeTab(targetName) {let tabs = this.editableTabslet activeName = this.editableTabsValueif (activeName === targetName) {tabs.forEach((tab, index) => {if (tab.name === targetName) {let nextTab = tabs[index + 1] || tabs[index - 1]if (nextTab) {activeName = nextTab.name}}})}this.activeMenu = activeNamethis.editableTabsValue = activeNamethis.editableTabs = tabs.filter(tab => tab.name !== targetName)this.tabRouterList = this.tabRouterList.filter(item => item.path !== targetName)}}
})export default useUserStore

在src/views/layout/components/navbar.vue文件下增加如下代码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

navbar.vue全部代码如下:

javascript"><!--通用布局头部内容-->
<template><el-row><el-col :span="20"><el-tabsv-model="store.editableTabsValue"type="border-card"closable@tab-remove="handleTabRemove"@tab-click="handleTabClick"v-if="store.editableTabs.length !== 0"><el-tab-pane v-for="item in store.editableTabs" :key="item.name" :name="item.name" :label="item.title"><!-- 右键菜单开始:自定义标签页显示名称,保证每个标签页都能实现右键菜单 --><template #label><el-dropdowntrigger="contextmenu":id="item.name"@visible-change="handleChange($event, item.name)"ref="dropdownRef"><span style="font-size: 16px;color: #909399;":class="store.editableTabsValue === item.name ? 'label' : ''"><SvgIcon :iconClass="item.iconClass"></SvgIcon>{{ item.title }}</span><template #dropdown><el-dropdown-menu><el-dropdown-item @click="closeCurrent(item.name)"><el-icon><Close /></el-icon>关闭当前标签页</el-dropdown-item><el-dropdown-item @click="closeLeft(item.name)" v-if="show(item.name, 'left')"><el-icon><DArrowLeft /></el-icon>关闭左侧标签页</el-dropdown-item><el-dropdown-item @click="closeRight(item.name)" v-if="show(item.name, 'right')"><el-icon><DArrowRight /></el-icon>关闭右侧标签页</el-dropdown-item><el-dropdown-item @click="closeOther(item.name)" v-if="store.editableTabs.length > 1"><el-icon><Operation /></el-icon>关闭其他标签页</el-dropdown-item><el-dropdown-item @click="closeAll()"><el-icon><Minus /></el-icon>关闭全部标签页</el-dropdown-item></el-dropdown-menu></template></el-dropdown></template><!-- 右键菜单结束 --></el-tab-pane></el-tabs></el-col><el-col :span="4"><div class="header"><!-- 语言切换 --><div class="language" @click="languageSwitch">{{ store.language === "en" ? "中文" : "English" }}</div><!--trigger="click"通过点击下标触发--><div style="cursor: pointer;"><el-dropdown trigger="click"><span>{{ $t("username") }}<SvgIcon iconClass="arrowDown" /></span><template #dropdown><el-dropdown-menu><el-dropdown-item @click="logout">退出登录</el-dropdown-item></el-dropdown-menu></template></el-dropdown></div></div></el-col></el-row>
</template><script setup name="navbar">//引入全局状态里面的关于菜单栏列表数据和相关方法import useUserStore from '@/store/modules/userStore'import { useRouter, useRoute } from "vue-router"import { onMounted, ref, computed } from 'vue'import { useI18n } from "vue-i18n"import {Close,DArrowLeft,DArrowRight,Operation,Minus} from '@element-plus/icons-vue'//接手全局状态里面的属性和方法const store = useUserStore();//使用路由相当于$router,系统路由方法const router = useRouter()//使用路由相当于$route,点击菜单栏时当前点击的路由页面里面的属性值const route = useRoute()//使用useI18nconst { t, locale } = useI18n()//用户名const username = '超级管理员'//触发右键菜单标签页为第一个时,不展示【关闭左侧标签页】//触发右键菜单标签页为最后一个时,不展示【关闭右侧标签页】const show = (name, type) => {const index = store.editableTabs.findIndex((item) => name === item.name)return type === 'left' ? index !== 0 : index !== store.editableTabs.length - 1}//右键菜单refconst dropdownRef = ref()//在触发右键菜单后,关闭其他tab页上的右键菜单const handleChange = (visible, name) => {if (!visible) returndropdownRef.value.forEach((item) => {if (item.id === name) returnitem.handleClose()})}//关闭当前tab页const closeCurrent = (targetName) => {handleTabRemove(targetName)}//关闭左侧tab页const closeLeft = (targetName) => {//查找当前点击的tab页所在位置let currentIndex = store.editableTabs.findIndex((item) => item.name === targetName)//查找当前激活标签页indexconst activeIndex = store.editableTabs.findIndex((item) => item.name === store.editableTabsValue)//关闭左侧tab页store.editableTabs.splice(0, currentIndex)//删除对应的左侧历史路由store.tabRouterList.splice(0, currentIndex)//如果当前关闭点击的tab页包含激活的tab页,则将激活tab页重置为当前点击的tabif (activeIndex < currentIndex) {//将当前激活的tab页改为当前点击的store.updateState(['editableTabsValue', targetName])//将激活菜单改为当前点击的store.updateState(['activeMenu', targetName])//路由跳转到当前点击的tab页//查询当前点击的tab页缓存路由参数let result = store.tabRouterList.find(item => item.path === targetName);//路由跳转且带上对应tab页的参数router.push({ path: targetName, query: result.query })}}//关闭右侧tab页const closeRight = (targetName) => {//查找当前点击的tab页所在位置let currentIndex = store.editableTabs.findIndex((item) => item.name === targetName)//查找当前激活标签页indexconst activeIndex = store.editableTabs.findIndex((item) => item.name === store.editableTabsValue)//关闭右侧tab页store.editableTabs.splice(currentIndex + 1)//删除对应的右侧历史路由store.tabRouterList.splice(currentIndex + 1)//如果当前关闭点击的tab页包含激活的tab页,则将激活tab页重置为当前点击的tabif (activeIndex > currentIndex) {//将当前激活的tab页改为当前点击的store.updateState(['editableTabsValue', targetName])//将激活菜单改为当前点击的store.updateState(['activeMenu', targetName])//路由跳转到当前点击的tab页//查询当前点击的tab页缓存路由参数let result = store.tabRouterList.find(item => item.path === targetName);//路由跳转且带上对应tab页的参数router.push({ path: targetName, query: result.query })}}//关闭其他tab页const closeOther = (targetName) => {//查找当前点击的tab页所在位置let currentIndex = store.editableTabs.findIndex((item) => item.name === targetName)//关闭其他标签页store.editableTabs = [store.editableTabs[currentIndex]]//删除除当前点击外的历史路由store.tabRouterList = [store.tabRouterList[currentIndex]]//如果当前点击的不等于当前激活的if (targetName !== store.editableTabsValue) {//将当前激活的tab页改为当前点击的store.updateState(['editableTabsValue', targetName])//将激活菜单改为当前点击的store.updateState(['activeMenu', targetName])//路由跳转到当前点击的tab页//查询当前点击的tab页缓存路由参数let result = store.tabRouterList.find(item => item.path === targetName);//路由跳转且带上对应tab页的参数router.push({ path: targetName, query: result.query })}}//关闭全部tab页const closeAll = () => {//清空tabs数组store.editableTabs.length = 0//清空历史路由store.tabRouterList.length = 0//当前选中tab页设置为空store.updateState(['editableTabsValue', ''])//当前激活菜单设置为空store.updateState(['activeMenu', ''])//跳转到首页router.push('home')}//处理tab标签x按钮的移除function handleTabRemove(targetName) {//如果editableTabs列表不为空数组if (store.editableTabs.length > 0) {//如果当前所在的tab页路由地址与移除的tab页名一样,则移到前面一个tab页且路由跳转if (route.path === targetName) {let tabs = store.editableTabstabs.forEach((tab, index) => {if (tab.name === targetName) {//获取当前tab的后一个或者前一个let nextTab = tabs[index + 1] || tabs[index - 1]//如果有值就移到它上面,没有就是最后一个跳转到首页if (nextTab) {//根据name属性进行查询当前tab页的缓存路由参数let result = store.tabRouterList.find(item => item.path === nextTab.name);//路由跳转且带上对应tab页的参数router.push({ path: nextTab.name, query: result.query })} else {// 更改tab标签绑定值,选中选项卡的namestore.updateState(['editableTabsValue', ''])// 更改当前激活的菜单store.updateState(['activeMenu', ''])//当删除的是最后一个tab页的时候,跳转到首页router.push('home')}}})//从editableTabs中移除当前tab标签store.removeTab(targetName)} else {//从editableTabs中移除当前tab标签store.removeTab(targetName)}}}//tab标签被选中时触发的事件function handleTabClick(tab) {store.updateState(['activeMenu', tab.props.name])store.updateState(['editableTabsValue', tab.props.name])// 判断当前url地址和即将跳转的是否一致,不一致进行跳转,防止跳转多次if (tab.props.name !== route.path) {// 根据name属性进行查询let result = store.tabRouterList.find(item => item.path === tab.props.name);//路由跳转且带上对应tab页的参数router.push({ path: tab.props.name, query: result.query })}}//页面刷新时,保留当前语言类型,不然会被重置为默认语言中文function setLanguage(){//如果sessionStorage里面的language为en,则表示要切换到英文语言。否则为中文。if(store.language==="en"){//将语言切换为英文locale.value='en'}else {//将语言切换为中文locale.value='zh'}}//页面初始化时调用语言方法setLanguage()//中英文语言切换function languageSwitch(){//如果sessionStorage里面的language为en,则表示要切换到中文语言。否则为英文。if(store.language==="en"){//将语言切换为中文locale.value='zh'//将language设置为zh中文store.language='zh'}else {//将语言切换为英文locale.value='en'//将language设置为zh中文store.language='en'}//语言切换后延迟刷新页面setTimeout(() => {window.location.reload()}, 300)}//退出登录方法function logout() {}
</script><style lang="less" scoped>//设置高度:deep(.el-tabs__nav-scroll) {height: 60px;}//去掉el-tabs的边框:deep(.el-tabs) {border: none;}.header {height: 62px;position: absolute;right: 30px;top: 0px;z-index: 1; //不设置这个,el-down点击出不来,被tab标签页长度挡住了display: flex;align-items: center; //垂直居中}//tab标签页里面字体设置.label {color: #1B68B6 !important; //激活标签页高亮font-size: 16px;}:deep(.el-tabs__item) {&:hover {span {color: #1B68B6 !important; //鼠标移到标签页高亮}}}.language{cursor: pointer;margin-right: 20px;color: #49A1F3;font: 14px 微软雅黑 宋体;}
</style>

src/locale/language/en.js文件代码如下:

javascript">export default {en: {username: 'Admin',home: 'I am home',tip: 'request error'}
}

src/locale/language/zh.js文件代码如下:

javascript">export default {zh: {username: '超级管理员',home: '我是首页',tip: '请求失败'}
}

src/views/home/index.vue首页文件代码如下,这里只对首页里面的内容做中英文切换,用来测试是否可以实现:

javascript"><!--home首页代码-->
<template><!--对页面内容进行中英文切换--><div>{{ $t("home") }}</div>
</template><script setup name="home">
import {login} from '@/api/login'
import { useI18n } from "vue-i18n"//使用useI18n
const { t } = useI18n()const data={username:"test111",password:"123456"}login(data).then( res => {console.info("请求成功")
}).catch(err => {console.info("请求失败,",err)//在js里面对提示进行中英文切换alert(t('tip'))
})</script><style lang="less" scoped></style>

测试中英文切换

谷歌浏览器页面效果如下:
在这里插入图片描述
点击English按钮后切换为英文效果如下:
在这里插入图片描述

对ElementPlus里面的所有组件进行中英文切换

main.js代码如下:

javascript">import { createApp } from 'vue'
//引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//将element-plus里面默认语言英文改为中文,需要引入它
import zhCn from 'element-plus/dist/locale/zh-cn'
//element-plus组件全局样式和html全局样式引入
import './styles/element-plus.less'
import './styles/common.less'
//引入dayjs日期插件
import dayjs from 'dayjs'
//引入国际化配置
import lang from './locale'
//引入router路由
import router from './router'
//引入pinia状态管理
import pinia from './store'
//引入svg-icons
import 'virtual:svg-icons-register'
import App from './App.vue'const app = createApp(App)
//使用element-plus,并设置语言为中文
app.use(ElementPlus, {locale: zhCn,
})
//通过provide全局注入工具函数
app.provide('$dayjs', dayjs)
//国际化配置使用
app.use(lang)
//使用router路由
app.use(router)
//使用pinia状态管理
app.use(pinia)
app.mount('#app')

src/App.vue文件代码如下:

javascript"><template><div><!--在路由入口这里使用ElConfigProvider对ElementPlus组件进行中英文切换--><el-config-provider :locale="locale"><!--路由入口 在App.vue中使用<router-view>组件来渲染要显示的组件--><router-view/></el-config-provider></div>
</template><script setup name="App">import { reactive } from 'vue'import { ElConfigProvider } from 'element-plus'import zhCn from 'element-plus/es/locale/lang/zh-cn'//引入全局状态里面的关于菜单栏列表数据和相关方法import useUserStore from '@/store/modules/userStore'//接手全局状态里面的属性和方法const store = useUserStore()//将ElementPlus里面的组件进行中英文切换const { locale } = reactive({locale: store.language==='en'?'':zhCn})
</script><style scoped></style>

src/views/home/index.vue首页文件代码如下,这里对日期选择器控件进行中英文切换测试:

javascript"><!--home首页代码-->
<template><!--对ElementPlus里面的组件进行中英文切换--><el-date-picker type="date"/><!--对页面内容进行中英文切换--><div>{{ $t("home") }}</div>
</template><script setup name="home">
import {login} from '@/api/login'
import { useI18n } from "vue-i18n"//使用useI18n
const { t } = useI18n()const data={username:"test111",password:"123456"}login(data).then( res => {console.info("请求成功")
}).catch(err => {console.info("请求失败,",err)//在js里面对提示进行中英文切换alert(t('tip'))
})</script><style lang="less" scoped></style>

谷歌浏览器效果如下:
日期选择器中文效果如下:
在这里插入图片描述
语言切换为英文后效果如下:
在这里插入图片描述
好了,到这里vue-i18n国际化配置应该是可以直接到项目中直接实际使用了。又进步了一点点。


http://www.ppmy.cn/news/1456873.html

相关文章

PyCharm怎么安装Comate与使用示范

目录 简单介绍Comate 安装步骤详解 Comate使用示范详解 使用总结 简单介绍Comate Baidu Comate智能编码助手是一款基于文心大模型打造的编码辅助工具&#xff0c;具备多重优势&#xff0c;包括代码智能、应用场景丰富、创造价值高、广泛应用等。它能帮助开发者提升编码效率…

论文复现丨多车场带货物权重车辆路径问题:改进邻域搜索算法

引言 本系列文章是路径优化问题学习过程中一个完整的学习路线。问题从简单的单车场容量约束CVRP问题到多车场容量约束MDCVRP问题&#xff0c;再到多车场容量时间窗口复杂约束MDCVRPTW问题&#xff0c;复杂度是逐渐提升的。 如果大家想学习某一个算法&#xff0c;建议从最简单…

JavaScript异步编程——02-Ajax入门和发送http请求

同步和异步回顾 同步和异步的简单理解 同步&#xff1a;必须等待前面的任务完成&#xff0c;才能继续后面的任务。 异步&#xff1a;不受当前任务的影响。 拿排队举例&#xff1a; 同步&#xff1a;在银行排队时&#xff0c;只有等到你了&#xff0c;才能够去处理业务。 异…

.[[MyFile@waifu.club]].svh勒索病毒数据库恢复方案

.[[MyFilewaifu.club]].svh勒索病毒有什么特点&#xff1f; .[[MyFilewaifu.club]].svh是一种最近多发的勒索病毒&#xff0c;它通过加密受害者的文件并要求支付赎金来解锁&#xff0c;从而达到勒索钱财的目的。恢复重要数据请添加技术服务号(safe130)。以下是关于这种病毒的详…

经典的设计模式和Python示例(一)

目录 一、工厂模式&#xff08;Factory Pattern&#xff09; 二、单例模式&#xff08;Singleton Pattern&#xff09; 三、观察者模式&#xff08;Observer Pattern&#xff09; 一、工厂模式&#xff08;Factory Pattern&#xff09; 工厂模式&#xff08;Factory Pattern…

使用curl命令查看服务器端口开放情况

目录 1.ssh端口 22 2.mysql数据库端口 3306 3.web应用端口 &#xff08;Jellyfin 8082&#xff09; &#xff08;wordpress 8088&#xff09; &#xff08;tomcat 8080&#xff09; 4.不存在的端口 5.被防火墙阻挡的端口 1.ssh端口 22 curl -v 10.10.10.205:22 curl…

SOL链DApp智能合约代币质押挖矿分红系统开发

随着区块链技术的不断发展和普及&#xff0c;越来越多的项目开始探索基于区块链的去中心化应用&#xff08;DApp&#xff09;。Solana&#xff08;SOL&#xff09;作为一条高性能、低成本的区块链网络&#xff0c;吸引了众多开发者和项目&#xff0c;其中包括了各种类型的DApp&…

初始Linux(基础命令)

前言&#xff1a; 我们不能总沉浸在编程语言中&#xff0c;虽然代码能力提升了&#xff0c;但是也只是开胃小菜。我们要朝着更高的方向发展。 最近小编一直在刷力扣&#xff0c;以至于博客更新的比较少。今天就带各位开始学习全新的知识——Linux.至于为啥要学&#xff1f; Lin…