恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
TypeDoc 国际化机制详解:`--lang` 选项、本地化文件编写与插件字符串翻译
首页
资讯中心
/
TypeDoc 国际化机制详解:`--lang` 选项、本地化文件编写与插件字符串翻译
TypeDoc 国际化机制详解:`--lang` 选项、本地化文件编写与插件字符串翻译
发布时间:2026/9/25 11:25:15
开发工具文档【免费下载链接】typedocDocumentation generator for TypeScript projects.项目地址https://gitcode.com/gh_mirrors/ty/typedoc点击查看免费下载TypeDoc 自 0.26 版本起为其控制台输出和生成的 HTML/JSON 文档提供了完整的国际化i18n支持。本文以官方文档 site/development/internationalization.md 为主线结合源码逐层剖析该机制的完整实现如何理解--lang选项的工作方式、如何在locales目录下编写一个新的语言文件、buildTranslation/buildIncompleteTranslation背后的类型校验原理以及第三方插件如何通过声明合并与addTranslations把自有字符串纳入 TypeDoc 的翻译体系。读完本文你可以独立为 TypeDoc 贡献一个完整或部分的 locale也可以在自己的插件中接入 TypeDoc 的统一国际化方案。一、功能范围--lang影响哪些输出国际化能力由--lang选项控制它会同时作用于两个层面控制台输出TypeDoc 运行期间通过Logger打印的 INFO 及以上级别消息加载插件、转换进度、错误与警告统计等生成的 HTML / JSON 输出渲染进文档页面的内置文案。在选项声明层面lang被定义为一个字符串类型、默认值为en的参数声明位置在 src/lib/utils/options/sources/typedoc.ts第 52–57 行options.addDeclaration({ name: lang, help: () i18n.help_lang(), type: ParameterType.String, defaultValue: en, });值得注意的是help: () i18n.help_lang()这句本身就说明了选项的帮助文本也是可翻译字符串的一部分——TypeDoc 的选项帮助信息同样走国际化流程。运行时Application在启动阶段把lang选项的值传给Internationalization实例见 src/lib/application.ts 第 302 行附近this.internationalization.setLocale(this.lang)。Internationalization类位于 src/lib/internationalization/internationalization.ts其核心逻辑非常直观setLocale(locale: string): void { if (this.loadedLocale ! locale) { const defaultTranslations translations.get(locale) || translations.get(en) || {}; const overrides this.locales.get(locale); setTranslations({ ...defaultTranslations, ...overrides }); this.loadedLocale locale; } }这里体现了两级合并策略内置语言包translationsMap为基础运行时通过addTranslations注册的覆写this.locales优先级更高。若请求的语言不存在则回退到英文——这与文档中“未提供的字符串自动回退到默认英文”的行为一致。当前仓库内置了六个语言包在 src/lib/internationalization/internationalization.ts 第 11–18 行注册const translations new Mapstring, Recordstring, string([ [de, de], [en, en], [fr, fr], [ja, ja], [ko, ko], [zh, zh], ]);对应的源文件位于 src/lib/internationalization/locales/ 目录de.ts、en.ts、fr.ts、ja.ts、ko.ts、zh.ts。以 src/lib/internationalization/locales/zh.ts 为例可以看到一个真实的未完成的中文翻译文件长什么样// Please DO NOT include machine generated translations here. // If adding a new key, leave it commented out for a native speaker // to update. import { buildIncompleteTranslation } from ../locale-utils.ts; export default buildIncompleteTranslation({ loaded_multiple_times_0: TypeDoc 已加载多次。这通常是由具有自己的 TypeDoc 安装的插件引起的。加载的路径为\n{0}, unsupported_ts_version_0: 您正在使用不受支持的 TypeScript 版本运行如果 TypeDoc 崩溃这就是原因。TypeDoc 支持 {0}, no_compiler_options_set: 未设置编译器选项。这可能意味着 TypeDoc 没有找到你的 tsconfig.json。生成的文档可能为空, // ……共 576 行仅覆盖部分键 });二、添加一个新 Locale完整步骤官方文档给出了添加新语言的标准流程这里完整继承并结合源码补充细节。2.1 文件位置与模板新语言文件应放在src/lib/internationalization/locales/目录下。英文默认语言的字符串定义在该目录的en.ts中而 src/lib/internationalization/translatable.ts 负责基于英文字符串推导类型约束详见第三节。一个最小可用的新语言文件如下文档原文示例// zh.cts import { buildTranslation } from ../translatable; export buildTranslation({ docs_generated_at_0: 文档生成于 {0}, });需要说明两个实际细节示例中使用export 是 CommonJS 风格的写法.cts仓库中现有的zh.ts等文件使用export default buildIncompleteTranslation({...})的 ESM 风格两者在构建流程中等价示例中的docs_generated_at_0对应文档页脚“文档生成于 {日期}”这类内置文案。2.2buildTranslation与buildIncompleteTranslation的取舍两个构建函数定义在 src/lib/internationalization/locale-utils.tsexport function buildTranslationconst T extends BuiltinTranslatableStringConstraints( translations: T, ) { return translations; } export function buildIncompleteTranslation const T extends PartialBuiltinTranslatableStringConstraints, (translations: T) { return translations; }从源码结构看这两个函数本身只是恒等返回真正的约束全部发生在类型参数上buildTranslation要求参数满足BuiltinTranslatableStringConstraints——即必须覆盖所有内置翻译键且每个键的占位符数量正确。提交不完整翻译时buildTranslation会直接报编译错误缺失属性。这正对应文档中的说法“This will give a compiler error onbuildTranslationsince the translation object does not provide a translation for every string supported by TypeDoc.”buildIncompleteTranslation的参数类型是Partial...允许只翻译一部分键。文档明确建议如果提交 PR 时翻译尚未完成应改用buildIncompleteTranslation不完整的翻译同样非常受欢迎。2.3 占位符Placeholder格式约定这是翻译工作中最容易出错的部分文档的核心约定可以概括为两条键名内嵌占位符序号翻译键的命名会包含数字后缀来标示占位符数量。例如docs_generated_at_0表示该字符串有 1 个占位符_0found_0_errors_and_1_warnings有 2 个_0与_1。这一约定类似 TypeScript 自身错误码的命名习惯其目的正是让翻译者在编辑时就知道应写入多少个{n}。翻译值中写{n}占位翻译字符串中应在占位符出现的位置写{0}、{1}……运行时代替填充。运行时替换逻辑在 src/lib/utils-common/i18n.ts 第 26–38 行i18n是一个 Proxyexport const i18n new Proxy({}, { get(_, key) { return (...args: string[]) { const template String(translations[key] || key); return template.replace(/\{(\d)\}/g, (_, index) { return args[index] ?? (no placeholder); }); }; }, has(_, key) { return Object.prototype.hasOwnProperty.call(translations, key); }, }) as TranslationProxy;从这段实现可以读出三个事实未翻译的键会回退为键名本身translations[key] || key而不是崩溃占位符按正则/\{(\d)\}/g匹配并用位置参数填充若参数数量不足缺失位置会渲染为字面量(no placeholder)这是一种可观察的失败信号方便本地化缺陷在页面中被发现。此外i18n对象还导出了TranslatedString类型string { [TranslatedString]: true }和translateTagName函数。后者负责把param这类注释标签名翻译为对应的tag_*键在英文中则按首字母大写规则生成标题形式的标签名——这意味着每个文档注释标签名summary、remarks、defaultValue……也有独立的翻译条目这些tag_*键由 translatable.ts 中的类型推导自动并入TranslatableStrings。2.4 关于机器翻译的明确警告官方文档中有一段重要的IMPORTANT提示值得原样强调请勿提交你并不熟悉的语言的机器生成翻译。TypeDoc 依赖贡献者来保证所收录翻译的准确性。这一点在 zh.ts 文件头部也以英文注释的形式重申“Please DO NOT include machine generated translations here. If adding a new key, leave it commented out for a native speaker to update.”。参与本地化的正确姿势是母语者贡献 缺失键保持注释状态等待补全。三、校验机制编译期与测试期的双重保障官方文档在 “Validation” 一节说明了buildTranslation与buildIncompleteTranslation会校验占位符数量与默认语言一致。这一承诺在源码中由一套精巧的类型体操兑现全部位于 src/lib/internationalization/translatable.ts从英文字符串推导参数元组。BuildTranslationArguments递归匹配字符串字面量中的{n}片段把每个占位符收集为元组元素type BuildTranslationArgumentsT extends string, Acc extends any[] [] T extends ${string}{${bigint}}${infer R} ? BuildTranslationArgumentsR, [...Acc, string] : Acc;因此BuiltinTranslatableStringArgs中每个键对应的类型是一个精确长度的元组0 个占位符即[]1 个即[string]。从参数数量生成字符串约束。BuildConstraint递归构造形如string{0}string{1}...的模板类型TranslationConstraint是预计算的 0–5 个占位符约束数组。也就是说一个名为xxx_0的键其值必须匹配string{0}string这样的模式否则translatable satisfies {...}处的编译器检查translatable.ts 第 61–65 行会报错。拒绝未知键与多余键。文档指出如果按示例直接把全新对象字面量传给构建函数函数还能校验翻译没有提供默认语言中不存在的键——因为参数类型是satisfies风格约束到BuiltinTranslatableStringConstraints的精确键集合多出来的键无法通过类型检查。文档也如实交代了这套静态校验的边界“这可以检查字符串是否漏掉占位符但无法发现使用了 TypeDoc 不会定义的占位符例如写成了{9}而实际只传了 2 个参数”。这类问题由单元测试兜底——例如 src/test/slow/internationalization-usage.test.ts 会遍历英文默认语言包中的每一个键通过 TypeScript 语言服务的引用分析断言该键确实在代码中被引用排除其他 locale 文件与 translatable.ts 自身未使用的键会让测试失败。这保证了默认语言包不会积累死键各语言翻译始终与英文键集同步。四、翻译插件自定义字符串这是文档的第二大主题插件如何使用 TypeDoc 的国际化模块为插件自己声明的字符串提供翻译。4.1 声明合并扩展TranslatableStringsaddTranslations要求所有可翻译字符串都已在TranslatableStrings接口中声明。该接口定义在 internationalization.ts 第 55 行本身就继承了内置字符串的类型export interface TranslatableStrings extends BuiltinTranslatableStringArgs {}其 JSDoc 明确写道“Plugins may use declaration merging to add members to this interface to use TypeDocs internationalization module.” 插件侧按文档给出的标准写法操作以下示例完整继承自官方文档import * as td from typedoc; declare module typedoc { interface TranslatableStrings { // 定义一个无参的可翻译字符串 plugin_example_hello_world: []; // 定义一个需要一个参数的可翻译字符串 // 按约定键名应包含每个占位符的索引编号 plugin_example_hello_0: [string]; } } export function load(app: td.Application) { app.internationalization.addTranslations(en, { plugin_example_hello_world: Hello World!, plugin_example_hello_0: Hello {0}!, }); app.logger.info(app.i18n.plugin_example_hello_world()); // 输出 Hello World! app.logger.info(app.i18n.plugin_example_hello_0(TypeDoc)); // 输出 Hello TypeDoc! }声明合并中的元组字面量[]、[string]直接决定了i18n代理上对应函数的参数签名由于TranslationProxy类型是按TranslatableStrings[K]生成的函数类型见 internationalization.ts 第 60–64 行占位符数量在插件侧同样享有编译期保护。4.2 运行时注入与配置文件中覆写addTranslations的实现internationalization.ts 第 86–91 行做了两件事把翻译存入对应 locale 的 map若该 locale 恰好是当前已加载的语言则立即addTranslations进全局翻译表使新字符串立刻可用。除了插件在load(app)中自行注册仓库还为“不写代码、只写配置”的场景提供了locales配置项声明见 src/lib/utils/options/sources/typedoc.ts 第 58–74 行options.addDeclaration({ name: locales, help: () i18n.help_locales(), type: ParameterType.Mixed, configFileOnly: true, // 只能出现在配置文件不能是命令行参数 defaultValue: {}, // validate: 必须是“locale - 键 - 字符串”的嵌套对象 });在 src/lib/application.ts 第 323 行附近Application启动时会遍历locales选项的每个条目并调用this.internationalization.addTranslations(lang, locales)。这意味着如果一个插件的字符串你只需要翻译给自己的项目看不必 fork 插件直接在typedoc.json中写一个locales字段覆写即可。同时getSupportedLanguages()会把“注册了非空覆写”的语言也计为受支持语言用于hasTranslations的判断。五、小结与实操清单查看文档官方指南位于 site/development/internationalization.md插件 API 参考见TranslatableStrings与Internationalization.addTranslations的接口文档由本仓库自动生成。为 TypeDoc 增加语言在 src/lib/internationalization/locales/ 新建文件完整的用buildTranslation不完整的用buildIncompleteTranslation见 locale-utils.ts键名保留_0/_1后缀翻译值写{n}占位符只提交母语级别的翻译。让插件字符串可翻译declare module typedoc声明合并 app.internationalization.addTranslations(...)用户侧可用typedoc.json的locales字段免代码覆写。校验链路编译期由 translatable.ts 的类型约束保证占位符数量与键集合正确运行期由 i18n.ts 的 Proxy 兜底渲染测试期由 src/test/slow/internationalization-usage.test.ts 保证默认语言包无死键。适用前提说明以上分析基于当前仓库TypeDoc ≥ 0.26 特性集lang选项默认为en内置语言为 de/en/fr/ja/ko/zh如果你的项目锁定在更早版本国际化相关 API 与本文描述可能不一致请以对应版本的仓库内容为准。赞分享开发工具文档【免费下载链接】typedocDocumentation generator for TypeScript projects.项目地址https://gitcode.com/gh_mirrors/ty/typedoc点击查看免费下载相关推荐Luanti国际化实战80语言翻译机制与.po文件本地化完整流程Luanti国际化实战80语言翻译机制与.po文件本地化完整流程 Luanti 原名 Minetest是一个开源体素游戏创作平台其国际化体系让游戏界面游戏开发图形学vue-cli UI 国际化实战指南翻译标准 UI 与 Vue CLI 插件的本地化机制vue cli UI 国际化实战指南翻译标准 UI 与 Vue CLI 插件的本地化机制 本文围绕 vue cli 官方文档《UI 本地化》展开系统讲解如何前端开发工具构建工具Sails 国际化之 config/locales 目录locale 字符串文件的组织、加载与翻译实践Sails 国际化之 config/locales 目录locale 字符串文件的组织、加载与翻译实践 config/locales 目录是 Sails 应用后端上一篇B站抢票神器跨平台自动化工具助你告别抢票焦虑下一篇飞书文档批量导出工具高效迁移700文档的完整技术方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考