以前做前端国际化的项目的时候,因为业务不是很复杂,相关的需求一般都停留在文案的翻译上,即国际化多语言,基本上使用相关的 I18n 插件即可满足开发的需求。但是随着业务的迭代和需求复杂度的增加,这些 I18n 插件不一定能满足相关的需求开发。

这里讲一下技术栈基于 Vue的实现,因此相关的解决方案也是基于 Vue 以及相关的国际化插件(vue-i18n)进行展开。


背景

1- 没有大量语言包文件

当项目比较简单,没有大量语言包文件的时候,将语言包直接打包进业务代码中是没有太大问题的。

2- 有大量语言包文件

这个时候是需要考虑:

  • 语言包单独打包。
  • 减少业务代码体积 。
  • 通过异步加载的方式去使用。
  • 考虑到国际化语言包相对来说是非高频修改的内容,因此可以考虑将语言包进行缓存,每次页面渲染时优先从缓存中获取语言包来加快页面打开速度。

解决方案

从 2.6.0 版本开始,webpack的 import 语法可以指定不同的模式解析动态导入,具体可以参见文档(https://webpack.docschina.org/api/module-methods/#import-)
因此结合 webpack 及 vue-i18n 提供的相关的 API 即可完成语言包的分包及异步加载语言包,同时在运行时完成语言的切换的工作。

文件目录结构:

src
|--components
|--pages
|--di18n-locales  // 项目应用语言包
|   |--zh-CN.js
|   |--en-US.js
|   |--pt-US.js
|--App.vue
|--main.js

main.js:

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import App from './App.vue'

Vue.use(VueI18n)

const i18n = new VueI18n({
    locale: 'en',
    messages: {}
})

function loadI18nMessages(lang) {
    return import(`./di18n-locales/${lang}`).then(msg => {
        i18n.setLocaleMessage(lang, msg.default)
        i18n.locale = lang
        return Promise.resolve()
    })
}

loadI18nMessages('zh').then(() => {
  new Vue({
    el: '#app',
    i18n,
    render: h => h(App)
  })
})

以上首先解决了语言包的分包和异步加载的问题.


语言包做缓存,以及相关的缓存机制,思路

打开页面后,优先判断 localStorage 是否存在对应语言包文件,如果有的话,那么直接从 localStorage 中同步的获取语言包,然后完成页面的渲染,如果没有的话,那么需要异步从 CDN 获取语言包,并将语言包缓存到 localStorage 当中,然后完成页面的渲染.


语言包做缓存,以及相关的缓存机制, 需要考虑到以下的问题
  1. 如果语言包发生了更新,那么如何更新 localStorage 中缓存的语言包?

    首先在代码编译的环节,通过 webpack 插件去完成每次编译后,语言包的版本 hash 值的收集工作,同时注入到业务代码当中。当页面打开,业务代码开始运行后,首先会判断业务代码中语言包的版本和 localStorage 中缓存的版本是否一致,如果一致则同步获取对应语言包文件,若不一致,则异步获取语言包

  2. 在 localStorage 中版本号及语言包的存储方式?

    数据都是存储到 localStorage 当中的, localStorage 因为是按域名进行划分的,所以如果多个国际化项目部署在同一域名下,那么可按项目名进行 namespace 的划分,避免语言包/版本hash被覆盖。


总结:

初期对于国际化项目做的一些简单的优化。总结一下就是:语言包单独打包成 chunk,并提供异步加载及 localStorage 存储的功能,加快下次页面打开速度。

Logo

前往低代码交流专区

更多推荐