Element + Vue I18n動態import加載國際化語言包翻譯文件

需求

項目爲多頁應用,包含產品a、b、c、d、e,每個產品都有自己的翻譯文件。
一次加載所有翻譯文件是極度不合理的。於是考慮動態加載。

實現

參考官方文檔:延遲加載翻譯

項目結構

│
├── dist // 靜態資源輸出目錄
│
├── src
│   ├── assets
│   ├── components
│   ├── lang // 語言翻譯文件
│        ├── a
│            ├── en_US.js
│            └── zh_CN.js
│        ├── b
│            ├── en_US.js
│            └── zh_CN.js
│        ├── c
│            ├── en_US.js
│            └── zh_CN.js
│        ├── d
│            ├── en_US.js
│            └── zh_CN.js
│        ├── e
│            ├── en_US.js
│            └── zh_CN.js
│   ├── pages
│        ├── a
│        ├── b
│        ├── c
│        ├── d
│        ├── e
│   ├── utils
│        ├── i18n.js 
│        ├── ...

i18n.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'

import ElementLocale from 'element-ui/lib/locale'
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'

// LANG:全局變量,從cookie中獲取的當前語言版本,'zh_CN'、'en_US'
// IS_INTL:全局變量,是否爲國際版
import { LANG, IS_INTL } from '@/constant'

Vue.use(VueI18n)

const i18n = new VueI18n({
  silentTranslationWarn: true
})
// 這裏需要覆蓋Element本地化函數,不然會衝突
ElementLocale.i18n((key, value) => i18n.t(key, value))
export default i18n

/**
 * 更改vueI18n實例
 * @param lang 'zh_CN'、'en_US'
 */
function setI18nLang (lang) {
  i18n.locale = lang
  // axios.defaults.headers.common['Accept-Language'] = lang
  document.querySelector('html').setAttribute('lang', lang)
  return lang
}

/**
 * 動態加載語言
 * @param path 當前路徑(對應lang下文件夾名)
 */
const _LANGS = ['zh_CN', 'en_US']
const ELEMENT_LANG = {
  zh_CN: zhLocale,
  en_US: enLocale
}
let loadedLanguages = []

export function loadLanguageAsync (path) {
 // lang目前是從cookie中獲取,所以沒有作爲參數傳遞,此處lang也可作爲變量傳遞

 // 如果cookie中沒有獲取到語言項,國際版默認初始化爲英文
  const lang = LANG || (IS_INTL ? 'en_US' : 'zh_CN')

  if (!path || !_LANGS.includes(lang)) return

  if (i18n.locale !== lang) {
    if (!loadedLanguages.includes(lang)) {
      // 文件大時可拆分打包,目前項目中翻譯文件均爲4、5K左右,就沒拆
      // return import(/* webpackChunkName: "lang-[request]" */ `@/lang/${path}/${lang}`).then(msgs => {
      return import(`@/lang/${path}/${lang}`).then(msgs => {
        const _temp = Object.assign(msgs.default, ELEMENT_LANG[lang])
        i18n.setLocaleMessage(lang, _temp)
        loadedLanguages.push(lang)
        return setI18nLang(lang)
      })
    }
    return Promise.resolve(setI18nLang(lang))
  }
  return Promise.resolve(lang)
}

main.js

import Vue from 'vue'
import App from './label.vue'
import store from './store/index'
import router from './router/index'

import i18n, { loadLanguageAsync } from '@/utils/i18n'
import '@label/plugins/element-ui'
import '@/assets/styles/common.less'
import AppComponents from '@label/components/index' // 註冊全局組件

Vue.config.productionTip = false
Vue.use(AppComponents)

// a頁
loadLanguageAsync('a').then(_ => {
  new Vue({
    i18n,
    store,
    router,
    render: h => h(App)
  }).$mount('#app')
})

切換語言組件

主要操作:切換時setCookie後重刷頁面
原因:本來直接調用loadLanguageAsync是可以正常重刷語言包的,但是這裏由於頁面某些顯示內容是來源於後端接口的,還是得重新請求,所以重刷了整頁

setCookie('jd.erp.lang', lang || 'en_US', 1, { path: '/', domain: CUR_HOST_SUFFIX })
window.history.go(0)

組件內容如下:

// langs.vue
<template>
  <el-dropdown
    class="icon-info icon-langs"
    @command="changeLang"
  >
    <img :src="imgSrc">
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item
        v-for="item in langs"
        :key="item.value"
        :command="item.value"
        :disabled="item.value === locale"
      >
        {{ item.label }}
      </el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</template>

<script>
import { LANG, CUR_HOST_SUFFIX } from '@/constant'
import { setCookie } from '@/utils/utils'

export default {
  name: 'langs',
  data () {
    return {
      imgSrc: require('@label/assets/icons/header-langs.svg'),
      locale: LANG,
      langs: [
        { label: '中文', value: 'zh_CN' },
        { label: 'English', value: 'en_US' }
      ]
    }
  },
  methods: {
    changeLang (lang) {
      this.locale = lang
      setCookie('jd.erp.lang', lang || 'en_US', 1, { path: '/', domain: CUR_HOST_SUFFIX })
      window.history.go(0)
    }
  }
}
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章