前言
之前在做编辑器Paas平台时收到一个上级的需求。为了支持业务团队能够自定义一些文案因此sdk需要提供接口来更改SDK的一些文案,以及支持海外用户使用因此NestJs中间层服务返回的一些系统信息也需要国际化。 接下来就来讲解一下NestJS如何国际化以及SDK如何让业务团队自定义一些文案
NestJs语言国际化
针对NestJs语言国际化需要使用的是nestjs-i18n来进行实现。
- 安装
pnpm add nestjs-i18n
- 设置翻译文件
一般在将文件src -> i18n -> ZH/EN.../目录下需要注意如下两点:
- 目前不支持ts\js文件,只支持json\yaml..
- 目前文件
必须有EN\ZH目录(文件名自定义)不能直接i18n/ZH.json没有中间那一层目录,这里的ZH/EN文件名language为域,该域名会在后续调用使用到
-
配置module层 只需要
根module中注册它即可,因为I18nModule是一个全局的module只需注册一次,其就可以在全局使用了 -
在service/controller层使用 只需要通过
构建器或者@Inject装饰器将I18nService注入进去即可调用translate的方法
function helloWork(@Body() options: Ioptions){
this.i18n.translate(
'language.app_switch_language_successfully',
{ lang: options.i18nLanguage }
)
}
从client端携带options.i18nLanguage参数用于表示当前client端所处的语言环境。其实也很好理解一个中层服务同时服务于很多客户端的,因此接口返回的语言是有客户端语言环境决定的
- 在后端是没有统一设置language语言的,不像前端可以统一设置I18N.changeLanguage('EN')这种。因为服务器是针对多个用户的
- 一般都是通过http请求
参数来进行语言的设置 throw和logger不需要国际化,只有面向用户的文本才需要
- 配置
nest-cli设置 在NestJs在编译时不会自动将静态文件打包进去,因此我们需要配置compilerOptions。
这里需要注意 在NestJs中配置assets包含的静态目录只对src下的目录生效,如果你的静态目录不在src目录下那么只能手动copy或者写个shell脚本复制到dist目录了
{
...
"compilerOptions": {
"assets": [
{ "include": "..、i18n/**/*", "watchAssets": true }
]
}
}
因为我的仓库类型是多包(monorepo)的类型,因为我这边还需要多设置一个outDir属性
{
...
"compilerOptions": {
"assets": [
{
"include": "..、i18n/**/*",
"watchAssets": true,
"outDir":'./dist/apps/i18n' -> 打包之后输出的文件目录
}
]
}
}
至此我们就完成了NestJS的国际化功能
sdk自定义文案
接下来实现给业务团队自定义sdk内部文案,因为sdk内部组件已经使用了i18n来进行文案国际化,因此这里依旧借助i18n的addResources能力来更新SDK内部组件文案
- 初始化
首先在初始化SDK时定义当前语言(language)和需要更替的文案资源(languageResource)。当然languageResource的数据里key必须跟sdk内部定义的language.json的key保持一致(如果你有更好的方案或者能够忽略这层映射关系可以留言哦~)
new AKclown({
language:'ZH',
languageResource:[
{ lang:'ZH', resource: { key: 'value' } 或者json数据都行 },
{ lang:'EN', resource: { key: 'value' } 或者json数据都行 }
]
})
- SDK内部实现
除了在初始化sdk时调用initI18进行初始化,还需要给提供updateLanguageResource方法允许业务团队中途变更文案,使其更加灵活
class AKclown{
constructor(params:Iparams){
initI18(params)
}
// 初始化文案资源
initI18(params:Iparams){
for(let item of params.languageResource){
i18next.addResources( item.lang, 'translation', item.resources )
}
i18next.changeLanguage(params.language)
}
// 中途更新文案资源
updateLanguageResource(payload){
for(let item of payload){
i18next.addResources( item.lang, 'translation', item.resources )
}
}
}
经过如上两步骤我们就实现了SDK自定义文案了,是不是so easy呢
总结
通过如上步骤我们学会了如何做NestJS语言国际化需求以及SDK中提供业务方自定义文案能力。
在这里感谢My Boss让我学到了,哈哈哈
其他
在react项目中需要使用useTralate和with...才会自动更新,如果直接使用i18n.t()..需要手动刷新才生效