价格

架构总览

相关源文件

本页面内容基于以下源文件生成:

i18n-pro/core 是一个轻量级的国际化(i18n)解决方案,采用分层架构设计,将命令行工具、翻译服务与运行时库清晰分离。该项目支持 8 种主流翻译平台(百度、有道、腾讯、阿里云、微软、Google、GoogleX、OpenAI),提供从源码文本提取到多语言包生成的完整工作流。

核心架构分层

系统采用三层架构设计,各层职责明确,通过配置文件和类型系统进行解耦。

正在加载图表渲染器...

CLI 入口层

CLI 入口层负责命令行参数解析与命令分发,是用户与系统交互的入口点。

职责边界

  • 解析 process.argv 获取命令和参数
  • 分发到对应的命令处理函数
  • 处理国际化语言包加载和设置

入口 API

  • execCommand():主入口函数,解析命令并分发

关键数据结构

typescript
1// 命令行参数对象
2const argObj = transferArgsToObj(args)
3const configPath = (argObj['--path'] || argObj['-P']) as string

命令分发逻辑

  • init:初始化配置文件
  • translate / t:执行翻译任务
  • version / v:显示版本信息
  • help / h:显示帮助信息

证据:src/bin/index.ts:213-251 展示了完整的命令分发逻辑,包括参数解析和 switch-case 命令路由。

翻译服务层

翻译服务层是核心业务逻辑所在,负责多平台翻译器适配与配置管理。

职责边界

  • 管理翻译器配置(支持 8 种平台)
  • 实现文本翻译的核心逻辑
  • 处理翻译请求的分批与限流

入口 API

  • setTranslateConfig():设置翻译器配置
  • translateTextsToLang():翻译文本到指定语言

关键数据结构

typescript
1// 翻译器配置
2config = configProp[`${translator}Config`]
3currentTranslatorImpl = translatorImplMap[translator]
4
5// 翻译请求参数
6{
7  texts: string[],  // 需要翻译的文本内容
8  from: string,     // 源语言
9  to: string,       // 目标语言
10  tokens: number    // token 长度
11}

错误处理

  • 翻译器不存在时:process.exit(1) 终止进程
  • 配置为空时:输出错误信息并退出

证据:src/bin/translate/index.ts:107-169 展示了翻译器配置验证和翻译实现函数的完整逻辑。

运行时库层

运行时库层提供国际化状态管理与翻译函数,供应用程序在运行时使用。

职责边界

  • 管理多命名空间的 i18n 状态
  • 支持动态加载语言包
  • 提供翻译函数 t()

入口 API

  • initI18n():初始化 i18n 实例
  • setI18n():更新 i18n 状态

关键数据结构

typescript
1// i18n 状态
2state[namespace] = Object.freeze(newState)
3
4// 命名空间与条件
5type Condition = {
6  namespace: string
7  locale: null | string
8}

动态语言包加载: 当语言包为函数类型时,异步加载并合并到状态中。

证据:src/lib/index.ts:11-77 展示了 setI18n 的状态管理逻辑和 initI18n 的初始化流程。

配置系统设计

配置系统支持 TypeScript 和 JavaScript 两种格式,通过 esbuild 编译 TS 配置文件实现动态加载。

多格式配置文件支持

TS 配置编译流程

  1. 检测运行环境(测试/生产)
  2. 使用 esbuild 编译 TS 为 ESM 模块
  3. 动态导入编译后的模块
  4. 返回配置对象

关键实现

typescript
1await build({
2  entryPoints: [tsPath],
3  outfile: outputPath,
4  bundle: true,
5  format: 'esm',
6  platform: 'node',
7  logLevel: 'silent',
8})

证据:src/bin/config.ts:28-103 展示了 TS 配置文件的 esbuild 编译加载逻辑和 initConfig 初始化函数。

配置解析与验证流程

解析流程

  1. 验证文件是否存在
  2. 调用 loadTsEsmConfig 加载配置
  3. 验证配置对象有效性(非空对象)

错误处理

  • 文件不存在:返回 false
  • 配置无效:抛出错误并退出进程

证据:src/bin/config.ts:110-149 展示了 parseTsConfig 的文件验证和错误处理逻辑。

多翻译平台配置类型定义

配置类型系统采用联合类型设计,支持 8 种翻译平台的差异化配置。

基础配置结构

typescript
1type BasicConfig = {
2  funcName: string,        // 自定义函数名,默认为 t
3  entry?: string,          // 入口文件
4  fileRegExp?: RegExp,     // 匹配文件名的正则表达式
5  input?: string | string[], // Glob 语法过滤文件
6  output: {
7    path: string,          // 输出目录
8    langType?: 'single' | 'multiple', // 输出方式
9    indentSize?: number    // 缩进大小
10  },
11  translator?: Translator  // 翻译平台
12}

平台配置示例

平台必需配置可选配置
百度appid, keydelay, codeLocaleMap
有道appKey, keydelay, codeLocaleMap
腾讯secretId, secretKey, regionprojectId, language
阿里云accessKeyId, accessKeySecretscene, apiType, endpoint
微软key, locationdelay, codeLocaleMap
GoogleprojectIdlocation
GoogleX-proxy
OpenAIkeymodel, proxy

证据:src/type.ts:1-100 展示了基础配置结构和各翻译平台的配置类型定义。

类型系统与接口设计

类型系统是架构稳定性的基石,通过严格的类型定义确保配置和接口的正确性。

翻译函数接口

Translate 接口定义了翻译函数的完整契约:

typescript
1export interface Translate {
2  (text: string, ...args: Array<string | number | unknown>): string
3  t: (key: string, text: string, ...args: Array<string | number | unknown>) => string
4  withLocale: (locale?: string) => Translate
5}

接口说明

  • 主函数:直接翻译文本,支持动态参数插值
  • t 方法:基于自定义 key 的翻译
  • withLocale 方法:返回绑定指定 locale 的新翻译函数

证据:src/lib/type.ts:126-157 展示了 Translate 接口的完整定义和 Condition 类型。

多翻译平台配置联合类型

系统使用联合类型管理多平台配置:

typescript
1export type UnionTranslatorConfig =
2  | BaiduConfig
3  | YoudaoConfig
4  | TencentConfig
5  | AliyunConfig
6  | MicrosoftConfig
7  | GoogleConfig
8  | GooglexConfig
9  | OpenAIConfig

类型推导机制: 通过 translator 字段自动推导对应的配置类型:

typescript
1type DefineTranslatorConfig<T extends Translator, C extends object> = {
2  translator: T
3} & Record<`${T}Config`, C>

证据:src/type.ts:200-281 展示了联合类型定义和 MaxLengthConfig 等核心类型。

语言包与内部配置类型

语言包类型

typescript
1export type LangPack = Record<string, string>
2export type Langs = Record<string, LangPack>

内部配置类型

typescript
1export type InnerConfig = {
2  maxLengthConfig: MaxLengthConfig
3}
4
5export type MaxLengthConfig = {
6  maxLengthType: MaxLengthType  // 限制类型
7  maxLength: number             // 最大字符数
8  maxArrayLength?: number       // 数组最大长度
9  separator?: string            // 分隔符
10}

证据:src/type.ts:100-200 展示了各翻译平台配置类型和内部配置定义。

翻译流程数据流

以下时序图展示了从命令行输入到语言包生成的完整数据流:

正在加载图表渲染器...

流程要点说明

  1. 配置加载阶段:CLI 入口调用 readConfig 解析配置文件,获取翻译器配置和输出设置
  2. 文本提取阶段:根据 entryfileRegExpinput 参数扫描源码文件,提取待翻译文本
  3. 翻译执行阶段
    • 根据 maxLength 配置分批处理文本
    • 调用翻译平台 API 进行翻译
    • 根据 delay 配置添加请求间隔,避免频率限制
  4. 结果输出阶段:根据 langType 配置生成单文件或多文件语言包

关键边界条件

  • 文件列表为空时:直接返回,不执行翻译
  • 翻译失败时:记录错误信息,继续处理其他文本
  • 增量模式:跳过已翻译的文本

核心设计决策与取舍

1. 采用 esbuild 编译 TS 配置文件

决策:使用 esbuild 而非 ts-node 或 tsc 编译 TypeScript 配置文件

理由

  • esbuild 编译速度比 tsc 快 10-100 倍
  • 配置文件通常较小,不需要完整的类型检查
  • 支持 ESM 动态导入,与现代构建工具兼容

限制

  • 不支持某些高级 TypeScript 特性(如 const enum)
  • 测试环境下需要特殊处理,避免编译问题

证据:src/bin/config.ts:54-65 展示了 esbuild 编译配置。

2. 多翻译器适配器模式

决策:使用适配器模式统一 8 种翻译平台的接口

理由

  • 不同平台 API 差异大(认证方式、请求格式、响应结构)
  • 适配器模式隔离平台差异,核心逻辑保持稳定
  • 便于扩展新的翻译平台

实现

typescript
1const translatorImplMap = {
2  baidu: baiduTranslate,
3  youdao: youdaoTranslate,
4  // ...
5}
6currentTranslatorImpl = translatorImplMap[translator]

限制

  • 需要为每个平台实现适配器
  • 平台特定功能(如术语库)难以统一暴露

3. 分批翻译策略

决策:根据 MaxLengthType 实现多种分批策略

理由

  • 不同翻译平台对请求大小限制不同
  • GoogleX 无官方限制,但需要控制请求大小
  • OpenAI 使用 Token 计费,需要控制 Token 数量

策略类型

类型说明适用平台
allStrLength所有字符数限制百度、有道
strLengthAndArrLength单字符+数组长度限制腾讯
allStrLengthAndArrLength总字符+数组长度限制阿里云
allTokenLengthToken 长度限制OpenAI

证据:src/type.ts:243-269 展示了 MaxLengthTypeMaxLengthConfig 定义。

4. 命名空间隔离的 i18n 状态管理

决策:使用命名空间隔离不同模块的 i18n 状态

理由

  • 大型应用可能有多个独立模块,各自维护语言包
  • 避免语言包 key 冲突
  • 支持按需加载语言包

实现

typescript
1state[namespace] = Object.freeze(newState)

限制

  • 增加了 API 复杂度
  • 需要开发者手动管理命名空间

证据:src/lib/index.ts:55-76 展示了命名空间管理逻辑。

5. 自定义 Chalk 实现替代第三方库

决策:实现轻量级 Chalk 替代品,而非依赖 chalk 库

理由

  • 减少依赖体积
  • 仅需基础样式功能(颜色、加粗)
  • 避免 chalk ESM 迁移带来的兼容性问题

实现

typescript
1const chalk = function (...res: Array<string | number>) {
2  return res.join(' ')
3} as Chalk

证据:src/bin/chalk.ts:78-125 展示了类 Chalk 的链式调用实现。

6. 双模式语言包输出

决策:支持 singlemultiple 两种语言包输出模式

理由

  • single 模式:适合小型项目,减少文件数量
  • multiple 模式:适合大型项目,按需加载语言包

实现差异

javascript
1// single 模式:langs.json
2{ "en": {...}, "jp": {...} }
3
4// multiple 模式:en.json, jp.json
5{ "key": "value" }

证据:src/type.ts:36-63 展示了 langType 配置说明。

7. 增量翻译模式

决策:默认启用增量翻译,通过 --non-incremental 参数禁用

理由

  • 避免重复翻译已处理的文本
  • 节省翻译 API 调用成本
  • 提高翻译速度

实现

typescript
1incrementalMode: !args.includes(NON_INCREMENTAL)

证据:src/bin/index.ts:233-236 展示了增量模式判断逻辑。

技术选型

技术用途选型理由替代方案
TypeScript主要开发语言类型安全,提升代码质量JavaScript + JSDoc
esbuildTS 配置编译极快的编译速度ts-node, tsc
Rollup库打包支持 UMD 格式,Tree-shakingwebpack, esbuild
Vitest单元测试快速、兼容 Jest APIJest, Mocha
Node httpsHTTP 请求内置模块,无依赖axios, node-fetch
https-proxy-agent代理支持支持 HTTP/HTTPS 代理proxy-agent
ESLint代码检查社区标准,插件丰富Biome
Prettier代码格式化统一代码风格dprint
jsx-to-md文档生成支持 JSX 编写 MarkdownTypeDoc, Docusaurus

模块依赖关系

正在加载图表渲染器...

依赖关系说明

  1. 命令行模块bin/index.ts 作为入口,依赖配置解析和翻译服务
  2. 翻译服务:依赖 HTTP 客户端和类型定义
  3. 运行时库:独立模块,仅依赖类型定义
  4. 类型系统:作为基础层,被所有模块依赖

关键设计

  • 运行时库与命令行工具完全解耦,可独立使用
  • 类型定义集中在 type.ts,便于跨模块共享
  • 外部依赖最小化,仅保留必要工具

关键配置与启动流程

配置文件示例

javascript
1// i18nrc.js
2module.exports = {
3  funcName: 't',
4  entry: path.join(__dirname, './src/bin/'),
5  fileRegExp: /.*\.[jt]s$/,
6  output: {
7    path: path.join(__dirname, './i18n/'),
8    langType: 'single',
9  },
10  translator: 'googlex',
11  googlexConfig: {
12    from: 'zh-CN',
13    to: ['en'],
14    proxy: 'http://127.0.0.1:7997',
15  },
16}

证据:i18nrc.js:1-17 展示了项目的实际配置文件。

启动流程

  1. 环境检测:检查 NODE_ENV 确定运行模式
  2. 语言包加载:尝试加载 i18n/langs.json,失败则使用默认中文
  3. 命令解析:解析 process.argv 获取命令和参数
  4. 配置读取:根据 --path 参数定位配置文件
  5. 命令执行:分发到对应的命令处理函数

模块导出入口

javascript
1// index.js
2if (process.env.NODE_ENV === 'production') {
3  module.exports = require('./dist/src/lib/index.min.js')
4} else {
5  module.exports = require('./dist/src/lib/index.js')
6}

证据:index.js:1-7 展示了根据环境变量区分导出策略。

构建配置

项目使用 Rollup 构建 UMD 格式输出:

javascript
1export default formats.map((format, index) => {
2  return {
3    input: 'src/lib/index.ts',
4    output: {
5      file: `dist/src/lib/index${suffix ? '.' + suffix : ''}.js`,
6      format: format.includes('.') ? format.split('.')[0] : format,
7      name: 'i18nPro',
8    },
9    plugins: [
10      ts({ /* TypeScript 配置 */ }),
11      prettier(),
12      terser({ /* 压缩配置 */ })
13    ],
14  }
15})

证据:rollup.config.js:1-61 展示了完整的 Rollup 构建配置。

测试配置

使用 Vitest 作为测试框架:

typescript
1export default defineConfig({
2  test: {
3    globals: true,
4    coverage: {
5      provider: 'istanbul',
6      reporter: ['json', 'html', 'text-summary', 'text'],
7    },
8  },
9})

证据:vitest.config.ts:1-12 展示了 Vitest 测试配置。