国际化 i18n 项目中怎么实现自动化生成 json 数据,而不是通过手动添加翻译字段呢?

通常支持 i18n 的项目,都需要提供一个对应的国际化 json 数据,但是手动维护 json 数据比较麻烦,怎么才能实现自动或者一键生成 json 数据呢?

本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。


回答:

其实有很多的项目在实现这个功能,比如说之前SF社区就有人自推过自己实现的一个 i18n 管理项目 ? vue-i18n-generator - 一款方便编辑语言包代码的工具。
最近也有人分享过文章 对国际化 i18n 项目的一点思考,里面有提到过几种维护的方式,都可以借鉴一下。

其实使用 i18n-ally 开发起来就已经很方便了。

国际化 i18n 项目中怎么实现自动化生成 json 数据,而不是通过手动添加翻译字段呢?


我自己呢就是偷懒,其实是因为配置 i18n Ally 的时候总是失败,所以就自己写了一个构建脚本,维护的时候是去维护一个数组:

// /locale/modules/common/button.js

import { transferLangConfig } from '@/i18n/config'

const config = {

// 通用部分

"search": ['搜索', '檢索', 'Search'],

"reset": ['重置', '重置', 'Reset'],

"clear": ['清空', '清空', 'Clear'],

"add": ['新增', '新增', 'Add'],

"confirm": ['确认', '確認', 'Confirm'],

"select": ['选择', '選擇', 'Select'],

"delete": ['删除', '刪除', 'Delete'],

"cancel": ['取消', '取消', 'Cancel'],

"remove": ['移除', '移除', 'Remove'],

"yes": ['是', '是', 'Yes'],

"no": ['否', '否', 'No'],

// ...

}

export default transferLangConfig(config)

最后通过 "i18n-gen": "node -r esm ./locale/i18nGen.js" 这个脚本执行生成对应语言的 json 文件,大概思路如下:

// /locale/i18nGen.js

import { writeFile } from 'fs'

import { languageList } from './config.js'

import localeData from './modules/index.js'

// uni-app 不支持多层JSON数据需要转换成单层 => "common.button.submit":"提交" 这样的形式

function transfSingleLayerJSON(data, fatherKey=''){

let tempObj = {}

for(let key in data){

let prefix = `${fatherKey?fatherKey+'.':''}${key}`

if(typeof data[key] === 'object') {

Object.assign(tempObj, transfSingleLayerJSON(data[key], prefix))

} else {

tempObj[prefix] = data[key]

}

}

return tempObj

}

languageList.forEach(lang => {

const tempLocale = transfSingleLayerJSON(localeData[lang])

writeFile(`./locale/${lang}.json`, JSON.stringify(tempLocale),()=>{});

})

一些其他的相关JS示例

// /locale/config.js

export const languageList = ['zh-Hans','zh-Hant', 'en']

// 创建一个空i18n对象

const createEmptyLangConfig = () => Object.fromEntries(new Map(languageList.map(key => [key, {}])))

// 配置文件转i18n对象

export const transferLangConfig = (data) => {

const langConfig = createEmptyLangConfig()

for (const key in data) {

languageList.forEach((lang, index) => {

langConfig[lang][key] = data[key][index]

})

}

return langConfig

}

// /locale/modules/index.js

import system from './system/index.js'

import common from './common/index.js'

export default {

en:{

...components['en'],

system:system['en'],

common:common['en'],

...

},

'zh-Hans': {

...components['zh-Hans'],

system:system['zh-Hans'],

common:common['zh-Hans'],

...

},

'zh-Hant': {

...components['zh-Hant'],

system:system['zh-Hant'],

common:common['zh-Hant'],

...

}

}

// /locale/modules/common/index.js

import { transferLangConfig } from '../../config.js'

import button from './button.js'

...

// 公共部分

const common = transferLangConfig({

"no-data": ['没有数据', '沒有數據', 'No Data'],

})

export default {

'zh-Hans': {

...common['zh-Hans'],

button: button['zh-Hans'],

...

},

'zh-Hant': {

...common['zh-Hant'],

button: button['zh-Hant'],

...

},

'en': {

...common['en'],

button: button['en'],

...

}

}

至于为什么引入的时候每一次都手动去 xxx['en'] 主要是因为想比较随意的命名。有些时候并不像层级那么深。想要可以很快的使用,又想可以聚合在一起维护。


本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。

以上是 国际化 i18n 项目中怎么实现自动化生成 json 数据,而不是通过手动添加翻译字段呢? 的全部内容, 来源链接: utcz.com/p/933805.html

回到顶部