Vite4 + Vue3 + Pinia2 + ElementPlus 实现国际化包括Element内部组件以及表单校验(超详细)

不要问为啥要使用国际化(vue-i18n),现在很多主流的UI框架,上去你会发现他们的文档都是支持多语言的。那我们在工作中难免会有潜在的客户是来自其他国家的。随着时间的推移可能还会支持更多的语言种类,那程序的设计就很至关重要,不可能说多一个国家的客户,我们就去改一次程序。合理的方案应该是运维或者不懂开发的同事直接通过编辑文件或者数据库数据就能增加一种语言才是最实际的。至于采用存储文件还是数据库。根据自己的需求合理安排就好。

程序我已经搭建好了Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)

一、安装vue-i18n和js-cookie 🌟 🌟 🌟

这里用到cookie的原因是,比如我们设置的是中文,那么我们后续进入系统默认的就应该是中文。

yarn add vue-i18n js-cookie -S
yarn add @types/js-cookie -D

二、开始编写cook和i18n逻辑 ✨ ✨ ✨

1、新建文件src/utils/cookies.ts

// @ts-ignore
import Cookies from 'js-cookie'
// key自己随意设置
const languageKey = 'ts_EtcEnd_language'
export const getLanguage = () => Cookies.get(languageKey)
export const setLanguage = (language: string) => Cookies.set(languageKey, language)

2、新建文件src/basics/lang/zh.ts和en.ts分别代表中文和英文

我是做了分类,如果全写在一个对象里面,难免会有重复的key。所以分类能够尽量去减少这个问题的出现。rouer代表路由,system代表系统,login代表登录。

export default {
  route: {
    home: '首页',
    home1: '首页1'
  },
  system: {
    title: 'Etc.End的演示案例',
  },
  login: {
    userName: '请输入用户名',
    passWord: '请输入密码',
    logIn: '登录',
    userNameMessage: '请输入正确的用户名',
    passWordMessage: '密码长度为6~30'
  }
}
export default {
  route: {
    home: 'Home',
    home1: 'Home1',
  },
  system: {
    title: 'Etc.End Demonstrate Case',
  },
  login: {
    userName: 'Please input userName',
    passWord: 'Please input password',
    logIn: 'Login',
    userNameMessage: 'Please enter the correct user name',
    passWordMessage: 'The password length is 6 ~ 30'
  }
}

3、新建文件src/basics/lang/index.ts

// @ts-ignore
import { createI18n } from 'vue-i18n'
import { getLanguage } from '@/utils/cookies'

import enLocale from './en'
import zhLocale from './zh'

const messages = {
    en: {
        ...enLocale
    },
    'zh-cn': {
        ...zhLocale
    }
}

export const getLocale = () => {
    //读取cookie存入的当前语言
    const cookieLanguage = getLanguage()
    //如果有返回当前语言
    if (cookieLanguage) {
        return cookieLanguage
    }
    //如果没有,获取系统语言
    const language = navigator.language.toLowerCase()
    //获取messages 语言 遍历
    const locales = Object.keys(messages)
    for (const locale of locales) {
        //如果messages 包里面有系统语言返回
        if (language.indexOf(locale) > -1) {
            return locale
        }
    }
    // 默认语言 简体中文
    return 'zh-cn'
}
//注册i8n实例并引入语言文件
const i18n = createI18n({
    legacy: false, // 是否启用传统模式,默认true启用,需要在Composition API中使用则设为false
    globalInjection: true, // 全局注入,页面内调用全局i18n需要用$t('xxx'),而非t('xxx')
    locale: getLocale(), //默认显示的语言
    messages //引入语言文件
})

export default i18n;

三、使用 💥 💥 💥

1、修改src/main.ts

引入刚刚写好的src/basics/lang/index.ts文件

import { createApp } from 'vue'

import App from './App.vue'
import 'animate.css'
import { createPinia } from 'pinia';
import { registerStore } from '@/pinia';
import router from '@/router';
import '@/router/permission'
import 'element-plus/theme-chalk/dark/css-vars.css'
import "element-plus/theme-chalk/el-message.css";
import "element-plus/theme-chalk/el-message-box.css";

// 国际化
import i18n from '@/basics/lang'

const app = createApp(App);
app.use(i18n)
app.use(router)
app.use(createPinia())
registerStore()

app.mount('#app')

2、修改src/App.vue

<template>
  <el-config-provider :locale="language === 'zh-cn' ? elementZhLocale : elementEnLocale" :key="language === 'zh-cn' ? 'zh-cn' : 'en'">
    <router-view />
  </el-config-provider>
</template>

<script lang="ts">
import appStore from "@/pinia";
import elementZhLocale from 'element-plus/lib/locale/lang/zh-cn'
import elementEnLocale from 'element-plus/lib/locale/lang/en'

export default defineComponent({
  setup() {
    // 因为我这里只有两种语言,如果你的语种比较多,可以把element-plus的语种放入数组中遍历,通过elementZhLocale.name去匹配输出
    // el-config-provider应该是有bug,切换语种的时候组件内部的子组件语种不会随之刷新,所以必须要上key强制刷新组件.

    const language = computed(() => (appStore.appModule.language))

    return {
      language,
      elementZhLocale,
      elementEnLocale,
    }
  }
})
</script>

<style>
html,body,#app {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
}
</style>

3、新建文件src/views/login.vue

<template>
  <div>
    <el-select v-model="language" @change="handleSetLanguage">
      <el-option v-for="locale in $i18n.availableLocales"
                 :key="locale"
                 :disabled="language===locale" :value="locale">{{ locale }}</el-option>
    </el-select>

    <el-form
        ref="loginFormRef"
        :model="loginForm"
        :rules="loginRules"
        class="login-form"
        autocomplete="on"
        label-position="left"
    >
      <div class="title-container tracking-in-contract-bck">
        <h3 class="title heartbeat">
          {{ $t('system.title') }}
        </h3>
      </div>

      <el-form-item prop="userName">
        <el-input
            v-model="loginForm.userName"
            :placeholder="$t('login.userName')"
            name="userName"
        />
      </el-form-item>
      <el-form-item prop="passWord">
        <el-input
            :key="passwordType"
            v-model="loginForm.passWord"
            :placeholder="$t('login.passWord')"
            :type="passwordType"
            name="passWord"
            @blur="capsTooltip = false"
        />
      </el-form-item>

      <el-button
          :loading="loading"
          type="primary"
      >
        {{ $t('login.logIn') }}
      </el-button>
    </el-form>
    <el-select v-model="selectValue" style="margin-top: 20px;">
      <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
      />
    </el-select>
  </div>
</template>

<script lang="ts">
import { useRoute } from "vue-router";
import { useI18n } from 'vue-i18n'
import appStore from "@/pinia";

export default defineComponent({
  setup() {

    const route = useRoute()

    const { proxy }:any = getCurrentInstance()

    const language = ref<string>(appStore.appModule.language)

    const loginFormRef = ref(null)

    const { t } = useI18n()

    const state = reactive({
      loginForm: {
        userName: '',
        passWord: '',
      },
      selectValue: '',
      options: [
        {
          value: 'Option1',
          label: 'Option1',
        },
        {
          value: 'Option2',
          label: 'Option2',
        },
        {
          value: 'Option3',
          label: 'Option3',
        },
        {
          value: 'Option4',
          label: 'Option4',
        },
        {
          value: 'Option5',
          label: 'Option5',
        },
      ],
      loginRules: {
        userName: [{ message: computed(()=> t('login.userNameMessage')), required: true, trigger: 'blur' }],
        passWord: [{ message: computed(()=> t('login.passWordMessage')), required: true, trigger: 'blur', min: 4, max: 30 }]
      },
      passwordType: 'passWord',
      loading: false,
      capsTooltip: false
    })

    const handleSetLanguage = (lang: string) => {
      proxy.$i18n.locale = lang
      appStore.appModule.setLanguage(lang)
      // 这里是修改当前页面在浏览器的标签名称
      const title = route.meta.title ? `${t(`route.${route.meta.title}`)} - ${t('system.title')}` : `${t('system.title')}`
      document.title = title
    }

    return {
      ...toRefs(state),
      loginFormRef,
      language,
      handleSetLanguage,

    }
  }
})
</script>

3、新建src/pinia/modules/app.ts文件

import { defineStore } from 'pinia';
import { getLocale } from "@/basics/lang";
import { setLanguage } from "@/utils/cookies";

interface IAppState {
    language: string
}

export const appModule = defineStore({
    id: 'app',
    state(): IAppState{
        return {
            language: getLocale(),
        }
    },
    getters:{},
    actions:{
        setLanguage(language: string) {
            this.language = language
            setLanguage(language)
        },
    }
})

4、修改src/pinia/modules/permission.ts

增加login路由,因为我是动态路由,没有做的小伙伴自己手动去增加以下login路由就好。Vite4 + Vue3 + vue-router4 动态路由

const list:MenuType[] = [
    {
        path: '/',
        title: 'ts-super-web',
        component: 'Layout',
        redirect: '/home',
        children: [
            {
                title: 'home',
                path: 'home',
                component: 'home'
            },
            {
                title: 'home1',
                path: 'home1',
                component: 'home1'
            },
            {
                title: 'login',
                path: 'login',
                component: 'login'
            }
        ]
    }
]

四、最终效果 ⚡️ ⚡️ ⚡️

我是Etc.End。如果文章对你有所帮助,能否帮我点个免费的赞和收藏😍。

👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Vite是一个用于快速构建现代化的Web项目的构建工具,它专注于开发阶段的快速热重载,并使用ES模块作为原生的开发模式。Vue3是Vue.js的最新版本,它在性能、开发体验和可维护性上都有所提升。 针对你提到的具体的库和框架: - Vue Router是Vue.js官方的路由管理器,用于实现页面之间的导航和路由控制。你可以通过npm安装vue-router,并在项目中进行配置和使用。 - Pinia是Vue.js的状态管理库,它提供了一种简单而强大的方式来管理应用程序的状态。你可以集成Pinia到你的Vue项目中,以便更好地组织和共享你的应用程序状态。 - Axios是一个基于Promise的HTTP客户端,用于通过网络发送异步请求。你可以使用Axios来处理与服务器的通信,并获取数据来更新你的Vue应用程序。 - Element Plus是一套基于Vue3的组件库,包含了丰富的UI组件,可以帮助你快速搭建漂亮的用户界面。你可以在项目中安装和使用Element Plus来实现各种交互效果和用户界面。 如果你想使用ViteVue3和以上提到的库和框架来创建一个项目,你可以按照以下步骤进行: 1. 安装Vite:通过npm全局安装Vite,然后使用Vite命令初始化一个新的项目。 2. 配置Vite:根据你的项目需求,在Vite的配置文件中添加Vue Router、Pinia、Axios和Element Plus的相关配置。 3. 安装和配置Vue Router:通过npm安装Vue Router,并在项目中配置和使用Vue Router来管理应用程序的路由。 4. 集成Pinia:通过npm安装Pinia,并在项目中引入和配置Pinia,以便在应用程序中使用Pinia来管理状态。 5. 使用Axios:通过npm安装Axios,并在项目中引入和配置Axios,以便进行网络请求和数据获取。 6. 引入Element Plus:通过npm安装Element Plus,并在项目中按需引入和使用Element Plus的组件,以搭建漂亮的用户界面。 希望以上信息对你有帮助,祝你在使用ViteVue3和这些库和框架时取得成功!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vite-vue-ts精简模版集成pinia+svg+router+@src](https://download.csdn.net/download/ldy889/85018930)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vite+vue3+ts+vue-router+pinia+axios+element-plus](https://blog.csdn.net/zy_080400/article/details/127125359)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Etc.End

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值