VonaJS: I18n如何支持Swagger多语言

VonaJS提供的I18n支持模块化体系。每个业务模块都可以单独提供自己的 I18n 语言资源。我们先了解I18n的一般用法,然后再看看如何支持Swagger多语言

初始化代码骨架

我们先在模块demo-student中初始化I18n的代码骨架

1. Cli命令

bash 复制代码
$ vona :init:locale demo-student

2. 菜单命令

bash 复制代码
右键菜单 - [模块路径]: `Vona Init/Locale`

定义语言资源

以模块demo-student为例,定义模块的语言资源:

  • 英文

src/module/demo-student/src/config/locale/en-us.ts

diff 复制代码
export default {
+ StudentName: 'Student Name',
};
  • 中文

src/module/demo-student/src/config/locale/zh-cn.ts

diff 复制代码
export default {
+ StudentName: '学生名称',
};

使用语言资源

可以通过 Scope 实例提供的locale对象获取模块的语言资源,支持类型化提示

typescript 复制代码
class ControllerStudent {
  @Web.get('test')
  test() {
    // use current locale
    const message1 = this.scope.locale.StudentName();
    // use locale en-us
    const message2 = this.scope.locale.StudentName.locale('en-us');
    // use locale zh-cn
    const message3 = this.scope.locale.StudentName.locale('zh-cn');
    console.log(message1, message2, message3);
  }
}  

跨模块使用语言资源

typescript 复制代码
class ControllerStudent {
  @Web.get('test')
  test() {
    // use current locale
    const message1 = this.$scope.demoStudent.locale.StudentName();
    // use locale en-us
    const message2 = this.$scope.demoStudent.locale.StudentName.locale('en-us');
    // use locale zh-cn
    const message3 = this.$scope.demoStudent.locale.StudentName.locale('zh-cn');
    console.log(message1, message2, message3);
  }
}  

覆盖语言资源

可以使用项目级别的语言资源覆盖模块级别的语言资源

  • 英文

src/backend/config/locale/en-us.ts

diff 复制代码
export default {
  modules: {
+   'demo-student': {
+     StudentName: 'Student Name!',
+   },
  },
};
  • 中文

src/backend/config/locale/zh-cn.ts

diff 复制代码
export default {
  modules: {
+   'demo-student': {
+     StudentName: '学生名称!',
+   },
  },
};

当前locale

1. 获取当前locale

typescript 复制代码
const locale = this.ctx.locale;

2. 设置当前locale

typescript 复制代码
this.ctx.locale = 'en-us';

3. 获取缺省locale

typescript 复制代码
const localeDefault = this.$scope.i18n.config.defaultLocale;

获取当前locale的规则

当用户访问后端 API 时,后端会自动根据规则获取当前 locale

1. 模块配置

I18n 是由模块 a-i18n 提供的核心能力,可以在 App config 中修改模块的配置:

src/backend/config/config/config.ts

typescript 复制代码
// modules
config.modules = {
  'a-i18n': {
    defaultLocale: 'en-us',
    queryField: 'x-vona-locale',
    headerField: 'x-vona-locale',
    cookieField: 'locale',
  },
};
名称 说明
defaultLocale Default locale
queryField 从request query中获取当前locale,query key默认为x-vona-locale
headerField 从request header中获取当前locale,header key默认为x-vona-locale
cookieField 从request cookie中获取当前locale,cookie key默认为locale

2. 规则次序

系统按以下次序,依次判断当前 locale

queryField > headerField > cookieField > Header: Accept-Language > defaultLocale

添加新语言

VonaJS 默认提供了两个语言:en-uszh-cn。下面演示如何添加新语言zh-tw

1. 添加类型定义

采用接口合并机制添加新语言的类型定义

在 VSCode 编辑器中,输入代码片段recordlocale,自动生成代码骨架:

typescript 复制代码
declare module 'vona' {
  export interface ILocaleRecord {
    : never;
  }
}

调整代码,然后添加zh-tw

diff 复制代码
declare module 'vona' {
  export interface ILocaleRecord {
+   'zh-tw': never;
  }
}

2. 添加语言资源

新建语言文件zh-tw.ts,然后添加语言资源

src/module/demo-student/src/config/locale/zh-tw.ts

typescript 复制代码
export default {
  StudentName: '學生名稱',
};

复数

1. 定义语言资源

src/module/demo-student/src/config/locale/en-us.ts

diff 复制代码
export default {
+ TestApples_: '%d apples',
+ TestApples_0: 'no apples',
+ TestApples_1: 'one apple',
};

src/module/demo-student/src/config/locale/zh-cn.ts

diff 复制代码
export default {
+ TestApples_: '%d个苹果',
+ TestApples_0: '没有苹果',
};

2. 使用语言资源

typescript 复制代码
this.ctx.locale = 'en-us';
const apple0 = this.scope.locale.TestApples_(0);
const apple1 = this.scope.locale.TestApples_(1);
const apple2 = this.scope.locale.TestApples_(2);
console.log(`${apple0}, ${apple1}, ${apple2}`);

控制台输出如下:

bash 复制代码
no apples, one apple, 2 apples
  • TestApples_: 缺省语言资源。语言资源添加后缀_,可以提示开发者该语言资源需要传入参数
  • TestApples_{n}: 可以针对任何具体的n提供独立的语言资源。系统在进行语言翻译时,如果找不到具体n的语言资源,就使用缺省语言资源TestApples_

复数: 多参数

如果语言资源支持多参数,那么可以明确指定哪个参数支持复数

1. 定义语言资源

src/module/demo-student/src/config/locale/en-us.ts

diff 复制代码
export default {
+ TestNameApples_: '%s has %d apples',
+ TestNameApples_0_1: '%s has no apples',
+ TestNameApples_1_1: '%s has one apple',
};

src/module/demo-student/src/config/locale/zh-cn.ts

diff 复制代码
export default {
+ TestNameApples_: '%s有%d个苹果',
+ TestNameApples_0_1: '%s没有苹果',
};

2. 使用语言资源

typescript 复制代码
this.ctx.locale = 'en-us';
const apple0 = this.scope.locale.TestNameApples_('Tom', 0);
const apple1 = this.scope.locale.TestNameApples_('Tom', 1);
const apple2 = this.scope.locale.TestNameApples_('Tom', 2);
console.log(`${apple0}, ${apple1}, ${apple2}`);

控制台输出如下:

bash 复制代码
Tom has no apples, Tom has one apple, Tom has 2 apples
  • TestNameApples_: 缺省语言资源。语言资源添加后缀_,可以提示开发者该语言资源需要传入参数
  • TestNameApples_{n}_{ordinal}: ordinal代表参数序数

Swagger/Openapi

VonaJS 提供了一组工具函数,为 Swagger/Openapi 实现 I18n 国际化

比如,为EntityStudent的字段name提供国际化的title信息

1. $localeScope

在设置字段 title 信息时,要使用语言资源FullKey。在实际生成 Swagger/Openapi 元数据时,系统会自动将语言资源FullKey翻译为指定的语言

diff 复制代码
+ import { $localeScope } from 'vona';

class EntityStudent {
+ @Api.field(v.title($localeScope('demo-student', 'Name')))
  name: string;
}
  • v.title: 设置 title 信息
  • $localeScope: 传入模块名称语言资源Key,从而生成语言资源FullKey: demo-student::Name

2. $locale

VonaJS 还提供了一个简化的工具函数$locale

diff 复制代码
+ import { $locale } from '../.metadata/index.ts';

class EntityStudent {
+ @Api.field(v.title($locale('Name')))
  name: string;
}
  • $locale: 传入语言资源Key,从而生成语言资源FullKey: demo-student::Name
    • 每个模块都提供了 <math xmlns="http://www.w3.org/1998/Math/MathML"> l o c a l e 函数,因此,使用本模块的 locale 函数,因此,使用本模块的 </math>locale函数,因此,使用本模块的locale 函数就可以取得模块名称

资源

相关推荐
奶糖的次元空间2 小时前
带你用 Javascript 生成器玩转「会暂停」的函数
node.js
Hao_Harrision7 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨| RangeSlider(范围滑块组件)
前端·typescript·react·tailwindcss·vite7
孟无岐9 小时前
【Laya】Base64Tool 编码工具类使用说明
typescript·游戏引擎·游戏程序·laya
Hilaku9 小时前
我是如何用一行 JS 代码,让你的浏览器内存瞬间崩溃的?
前端·javascript·node.js
五仁火烧9 小时前
npm run build命令详解
前端·vue.js·npm·node.js
老前端的功夫9 小时前
TypeScript索引访问类型深度解析:类型系统的动态访问与模式匹配
前端·javascript·ubuntu·架构·typescript·前端框架
前端付豪9 小时前
NodeJs 做了什么 Fundamentals Internals
前端·开源·node.js
Irene199110 小时前
使用 TypeScript 编写一个 Vue 3 模态框(Modal)组件
javascript·vue.js·typescript
踢球的打工仔10 小时前
typescript-void和never
前端·javascript·typescript
奔跑的web.10 小时前
TypeScript 全面详解:对象类型的语法规则
开发语言·前端·javascript·typescript·vue