【国际化】自动提取语言配置文件及使用

简单介绍

i18next-scanner

node插件,扫描您的代码,提取翻译键/值,然后将它们合并到i18n资源文件中。

vue-i18n

Vue.js 的国际化插件,提供本地化相关功能,集成在vue当中。

i18next-scanner 使用

安装

1
yarn add i18next-scanner -D

添加到 package.json scripts

1
2
3
"scripts": {
"scan": "i18next-scanner"
},

i18next-scanner 指令会寻找当前目录下的 i18next-scanner.config.js 文件,缺少就会报错。

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const fs = require('fs')
const { crc32 } = require('crc')
module.exports = {
input: [
'src/**/*.{js,vue}',
// Use ! to filter out files or directories
'!src/config/i18n/**',
'!**/node_modules/**'
],
output: './', // 输出目录
options: {
debug: true,
func: false,
trans: false,
lngs: ['cn', 'en'],
defaultLng: 'cn',
resource: {
loadPath: './src/config/i18n/{{lng}}/{{ns}}.json', // 输入路径
savePath: './src/config/i18n/{{lng}}/{{ns}}.json', // 输出路径
jsonIndent: 2,
lineEnding: '\n'
},
removeUnusedKeys: false, // 移除未使用的 key
nsSeparator: false, // namespace separator
keySeparator: false, // key separator
interpolation: {
prefix: '{{',
suffix: '}}'
}
},
transform: function customTransform(file, enc, done) { // 自己通过该函数来加工key或value
'use strict'
const parser = this.parser
const content = fs.readFileSync(file.path, enc)
/**
* @param {list} array 指定扫描的标识
*/
parser.parseFuncFromString(content, { list: ['lang'] }, (key, options) => {
options.defaultValue = key
// 将传入的文字转成配置的 key,不一定非用 crc,别的也行,如果内容不会影响 json 格式,不用也行
let hashKey = `k${crc32(key).toString(16)}`
parser.set(hashKey, options)
})
done()
}
}

配置文件添加之后, i18next-scanner 就能使扫描文字了,运行:

1
yarn scan

会根据配置中的语言空间导出到对应的文件夹,导出的文件长这样:

1
2
3
4
5
6
7
8
{
"kee8ae330": "查询",
"k50d471b2": "重置",
"kebceb256": "修改中...",
"k2d46b71b": "删除中...",
"kb135e9bd": "下载中...",
"ked2baf28": "加载中..."
}

通过以上方式,实现中文作为代码中的多语言的key,而且用中文作为key不会导致索引语言包导致的性能或索取不准确的问题,因为中文会先转化为crc32的key然后对象的再去索引同样以crc32为key的语言包,这样可以实现中文作为代码中的key,却实际上还是以准备的hashkey来索引语言包。

这样就不需要自己写配置文件,使用的时候再一个个去对了,直接在需要使用多语言的地方加上扫描标识方法就能本地化。

i18n 使用

i18n index.js

通过 lang 方法,将文字再转为 key,lang() 同时也是 i18next-scanner 扫描标识。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from './en/translation.json'
import cn from './cn/translation.json'
import crc32 from 'crc/crc32'

/* 语言包导入 */
Vue.use(VueI18n)

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

export function lang(key) {
let hashKey = `k${crc32(key).toString(16)}`
let words = i18n.t(hashKey)
if (words === hashKey) {
words = key
console.log(key, '-没翻译')
}
return words
};

export default i18n

main.js

1
2
3
4
5
6
import Vue from 'vue'
import i18n, { lang } from './config/i18n/index.js'

Vue.prototype.$lang = lang

new Vue({ ..., i18n })

代码中使用

html

1
<button>{{ $lang('查询') }}</button>

js

1
const hide = this.$message.loading(this.$lang('修改中...'), 0)

至此就大功告成了

拓展

微前端中动态切换语言

主项目中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<div class="lang" @click="switchLang">{{ langConfig[lang] }}</div>
</template>

<script>
export default {
data() {
return {
langConfig: {
'cn': 'English',
'en': '中文'
},
lang: 'cn'
}
},
methods: {
switchLang() {
this.lang = this.lang === 'cn' ? 'en' : 'cn'
this.$root.storeModule.commit('setLang', this.lang)
// i18n 的实例方法
this.$i18n.locale = this.lang
},
}
};
</script>

子项目 App.vue 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<a-locale-provider :locale="locale">
<div id="content">
<router-view/>
</div>
</a-locale-provider>
</template>

<script>
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
export default {
data () {
return {
locale: zhCN
}
},
watch: {
'$root.storeModule.state.lang'(lang) {
console.log('call $root.storeModule.state.lang')
this.$i18n.locale = lang
this.locale = lang === 'cn' ? zhCN : enUS
}
}
}
</script>

总结

对比传统 i18n 做法的优点:

  1. 省时省力,不再需要创建配置文件后挨个匹配路径
  2. 可读性更好,本地化的位置直接就是中文汉字,不会因为丢失文字而不知其意
  3. 效率高、成本低、开发无感,只需要把本地化的地方加上标识,扫描后的文件翻译即可

对比传统 i18n 做法的缺点:

  1. 灵活性稍微降低,使用中文作为配置的 key,会导致一样的中文都是一样的 key,那么翻译也会一样。当出现位置不同,中文相同,而翻译想要更明确时,会比较麻烦
  2. 配置文件较大,一种语言空间的配置都在一个 json 中,没法同种语言多个配置按需加载

另外,i18next-scanner 还有一个很大的缺陷,它只能通过 functionattr 来标识提取的内容

参考链接

i18next-scanner https://github.com/i18next/i18next-scanner

vue-i18n https://github.com/kazupon/vue-i18n

zcmzks vue或react多语言自动化实现扫描代码的多语言-i18next-scanner https://www.cnblogs.com/jocongmin/articles/12716786.html

作者

朷北

发布于

2020-04-22

更新于

2023-03-07

许可协议

评论