詳解vue element plus多語言切換
前言
最近接手一個項目,該項目多國傢使用,需要支持多語言的切換,在此記錄。
解決一下問題:
- 如何實現多語言切換 ?
- 如何動態切換語言並更改elementUI語言 ?
- 更改完elementUI組件視圖不更新?
- 如何全局使用 $t 函數 ?
- 如何在js文件裡使用vue-i18n ?
如何實現多語言切換 ?
1、安裝包vue-i18n
npm i vue-i18n --save
2、在src目錄下新建如圖:
en.js
const EN = { login: { title: 'User Login' }, } export default EN
pl-pl.js
const PL_PL = { login: { title: 'Użytkownik jest zalogowany' }, } export default PL_PL
zh-cn.js
const ZH_CN = { login: { title: '用戶登錄' }, } export default ZH_CN
index.js
import { createI18n } from 'vue-i18n/index' import 'dayjs/locale/zh-cn' import zh from './zh-cn' import en from './en' import pl from './pl-pl' const messages = { 'zh-cn': zh, 'en': en, 'pl': pl } // Gets the current locale export function getLanguage() { // Use the language of choice const chooselang = localStorage.getItem('locale') if (chooselang) return chooselang // if not shoose language const lang = (navigator.language || navigator.browserLanguage).toLowerCase() const locales = Object.keys(messages) return locales.includes(lang) ? lang : 'zh-cn' } const i18n = createI18n({ locale: getLanguage(), fallbackLocale: 'en', global: true, messages }) export function $t(args) { return i18n.global.tc(args) } console.log($t('login.title')) export default (app) => { app.use(i18n) }
說明
getLanguage 函數 判斷當前localStorage是否已有選擇過語言如果沒有則獲取當前瀏覽器的語言;
封裝 $t 函數並導出用在js文件中
3、 在main.js中
import language, { getLanguage, $t } from './language' language(app)
4、在vue文件中使用
<template> //1. <div class="login clamp ta-c fs-28 fw-b m-b10">{{ $t('login.title') }}</div> //2. <el-input v-model="$t('login.title')"></el-input> </template>
如何動態切換語言並更改elementUI語言 ?
1、利用vuex,在mutations中寫一個方法更改element語言
// ----------------------- state ----------------------------- import { getLanguage } from '@/language' const state = { lang: getLanguage() } export default state // ----------------------- mutations----------------------------- import * as Types from './types' import locale from 'element-plus/lib/locale' import localeZH from 'element-plus/lib/locale/lang/zh-cn' import localeEN from 'element-plus/lib/locale/lang/en' import localePL from 'element-plus/lib/locale/lang/pl' const element = { 'zh-cn': localeZH, 'en': localeEN, 'pl': localePL } const mutations = { // 切換語言 [Types.SET_LANG](state, lang) { state.lang = lang localStorage.setItem('locale', lang) locale.use(element[lang]) } } export default mutations // ----------------------- types----------------------------- export const SET_LANG = 'SET_LANG'
2、使用
import * as Types from '@/store/types' import { useI18n } from "vue-i18n"; export default { setup(props,ctx) { const { locale: lang } = useI18n({ useScope: "global" }) let store = useStore() const handelLanguage = (name) => { lang.value = name store.commit(Types.SET_LANG, name) } return { handelLanguage } } }
更改完elementUI組件視圖不更新?
這時你會發現就算我們提交commit去更改elementUI的語言 頁面上也沒有發生變化,因為視圖組件並沒有更新,如何刷新組件使之重新加載呢?
1、 在router-view上控制視圖顯示/隱藏
// ----------------------- template----------------------------- <router-view v-if="isReloadRouter"/> // ----------------------- script----------------------------- const reload = () => { state.isReloadRouter = false nextTick(() => { state.isReloadRouter = true }) } provide("reload", reload) <-- 自行引入 provide nextTick ->
2、 在切換語言時調用reload
const handelLanguage = (name) => { lang.value = name store.commit(Types.SET_LANG, name) inject('reload')() }
3、需在main.js中調用一下commit,不然第一次進入elementUI 不會更改語言
import language, { getLanguage, $t } from './language' import '@/styles/elementDefault.scss' store.commit(Types.SET_LANG, getLanguage())
如何全局使用 $t 函數 ? 如何在js文件裡使用vue-i18n ?
全局掛在 $t 函數 ,在js文件裡直接使用 $t 函數。
方法一:通過app.config.globalProperties掛在到全局
方法二: 通過provide、inject來實現
import language, { getLanguage, $t } from './language' const app = createApp(App); // ----------------------- app.config.globalProperties ----------------------------- app.config.globalProperties.$t = $t // 使用 import { getCurrentInstance } from 'vue' const { proxy } = getCurrentInstance() proxy.$t() // ----------------------- provide、inject ----------------------------- // main.js中 app.provide('$t', $t) // 使用 const $t = inject('$t') ElMessage.warning({ message: $t('login.warnMessage'), type: 'warning' });
vue3不推薦在原型鏈上掛載一些東西,而更推薦使用provide、inject,所以最好使用通過依賴和註入provide和inject的方式
在router.js中不能直接使用$t, 需自行引入該函數
import { $t } from '@/language' { path: '/mainManage/device', name: 'device', hidden: false, meta: { icon: 'circle', title: $t('router.device') }, component: () => import(/* webpackChunkName: "device" */ '@/views/mainManage/device') },
目前有一問題:因為我菜單展示的字段取的是路由信息裡的title,router.js隻在項目第一次進入的時候調用,當切換語言的時候菜單字段不會動態切換,隻有刷新瀏覽器才會改變,如有解決方法希望留言告知!!!
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- vue3如何使用provide實現狀態管理詳解
- vue中的inject用法及說明
- 應用provide與inject刷新Vue頁面方法
- vue3組件通信的方式總結及實例用法
- vue3中 provide 和 inject 用法及原理