Vue项目国际化改造

Yukino 1,004 2022-04-08
背景:以前的项目要进行国际化改造...

一、引入Vue-i18n

  1. 安装vue-i18n
    如果是Vue2的项目,需要指定8版本,目前默认的稳定版本是9,是不支持Vue2的
npm i vue-i18n@8.27.1      # 建议在npm找到最新的8版本号进行安装

如果是Vue3的项目,则可以直接安装

npm i vue-i18n
  1. 创建locales目录

目录结构如下:

├─locales/
│  └─lang/
│      ├─en-US/
│      ├─zh-CN/
│      ├─en-US.js
│      └─zh-CN.js
│  └─index.js

locales下有两个东西,一个是上图中的lang目录,另外一个是index.js,其中导入语言包,然后创建、导出vue-i18n实例。

zh-CN、en-US下存放的就是对应对应的语言包(一系列的json文件),在zh-CN.js中批量导入zh-CN目录下所有的json,并进行导出(这个后面会说详细实现)。

  1. 创建vue-i18n实例
    首先先看看语言包,这里我选用的是json作为文件格式,因为json的格式下面的插件是支持直接更改的,js格式则不支持,大致如下:
// locales/lang/zh-CN/test.json
{
  "test": "测试"
}

然后来到zh-CN.js中批量导入语言文件:

// locales/lang/zh-CN.js
function combineMessgaeFiles (files) {
  let message = {}
  files.keys().forEach(path => {
    // 以文件名作为namespace,避免不同文件中的key值冲突
    const namespace = path.replace('./', '').replace('.json', '')
    const messageFile = files(path)
    const messageWithNamespace = Object.keys(messageFile).reduce((res, key) => {
      res[`${namespace}.${key}`] = messageFile[key]
      return res
    }, {})
    message = Object.assign(message, messageWithNamespace)
  })
  return message
}

const files = require.context('./zh-CN/', false, /.json$/)
let autoLoadZhCn = combineMessgaeFiles(files)

export default {
  ...autoLoadZhCn
}

接下来就可以用处理好的语言包创建vue-i18n实例对象了

// locales/index.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { getLanguageCache } from '../utils/cache'
import autoLoadZhCn from './lang/zh_CN'
import autoLoadEn from './lang/en_US'

Vue.use(VueI18n)

const language = getLanguageCache()
const messages = {
  'zh-CN': autoLoadZhCn,
  'en-US': autoLoadEn
}

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

export default i18n

最后在创建vue对象时引入vue-i18n

// src/main.js
import Vue from 'vue'
import App from './App'
import i18n from './locales'

new Vue({
  el: '#app',
  i18n,
  render: h => h(App)
})
  1. ui组件(element-ui)国际化配置
    ui组件的国际化最好还是参考官网上的指南,这里的仅供参考。
    主要是两步:
  • 引入语言包
// locales/lang/zh-CN.js
import elZhLocale from 'element-ui/lib/locale/lang/zh-CN'

const files = require.context('./zh-CN/', false, /.json$/)
let autoLoadZhCn = combineMessgaeFiles(files)

export default {
  ...autoLoadZhCn,
  ...elZhLocale
}
  • 配置i18n函数
// src/main.js
import Vue from 'vue'
import App from './App'
import i18n from './locales'

Vue.use(element, {
  i18n: (key, value) => i18n.t(key, value)
})

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

二、i18n Ally插件(VSCode)安装配置

先介绍下这个插件,这个插件可以通过配置,读取、更改语言包,并可以检测代码中的硬编码文本,快速的对其进行提取、更改,下面介绍下这个插件的配置使用:

  1. 安装
    直接在插件市场中搜索、安装即可。
  2. 配置
    插件配置有两种方式:
    方法一:在VS Code的设置中进行设置
    方法二:在项目根目录创建.vscode目录,在目录下创建setting.json进行配置(这是针对工作区的,也就是当前项目的,切换项目之后设置不会保留)

这里我采用的是方式二,这样对着官方的文档配置起来会相对方便一点,下面是我的配置文件:

{
  "i18n-ally.localesPaths": [
    "src/locales/lang"
  ],
  "i18n-ally.localeCountryMap": {
    "CHINA": "zh-CN",
    "ENGLISH": "en-US"
  },
  "i18n-ally.enabledParsers": ["json"],
  "i18n-ally.languageTagSystem": "legacy",
  "i18n-ally.displayLanguage": "zh-CN",
  "i18n-ally.keystyle": "nested",
  "i18n-ally.sortKeys": true,
  "i18n-ally.namespace": true,
  "i18n-ally.extract.parsers.html": {
    "attributes": ["text", "title", "alt", "placeholder", "label", "aria-label", "content", "empty-text", "prev-text", "next-text", "confirmText", "range-separator", "start-placeholder", "end-placeholder"]
  },
}

下面是对参数进行说明:

  • localesPaths:语言包所在目录
  • localeCountryMap:语言和国家的映射
  • enabledParsers:使用哪些格式作为翻译文件
  • displayLanguage:预览显示的语言
  • keystyle:默认提取的key的命名格式
  • sortKeys:在添加语言后,自动排序
  • namespace:是否启用namespace,启用namespace后会在key前自动加上文件名
  • extract.parsers.html:硬编码校验的属性列表,插件会检验此数组中的属性,如果不在此属性列表的会被忽略,默认是"text", "title", "alt", "placeholder", "label", "aria-label", "content"这些,可以添加一些UI组件中会用到的属性。

配置完成这些之后,就可以借助插件进行文本提取、翻译了,具体效果可以查看i18n-ally的动图,这里就不再展示了。

最后吐槽一句,就算有插件帮助也很累啊,在文本量很大的情况下...