Dify 前端国际化(i18n)系统实战:i18n-config 模块的职责划分、语言包扩展与 i18n:check 校验

发布时间:2026/9/7 19:12:16

Dify 前端国际化(i18n)系统实战:i18n-config 模块的职责划分、语言包扩展与 i18n:check 校验
Dify 前端国际化i18n系统实战i18n-config 模块的职责划分、语言包扩展与 i18n:check 校验【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify本文以 Dify 仓库中 web/i18n-config/README.md 文档为主体系统讲解 Dify Web 端国际化体系的落地方式en-US源语言包、扁平化 key 设计、各文件的职责边界、新增 locale 与命名空间的完整流程以及pnpm i18n:check校验工具与自动化翻译工作流的机制。读完后你将能够在不破坏多语言一致性校验的前提下独立完成语言包扩展、文案修改与 CI 级校验。一、核心设计决策源语言、扁平 key 与 i18next 配置web/i18n-config/README.md 开篇就确立了整套国际化体系的三条基石规则理解它们是后续一切操作的前提web/i18n/en-US/下的英文 JSON 文件是唯一源语言source locale。其他所有 locale 目录必须保持相同的扁平 key 与占位符interpolation variables 和 markup placeholders。i18next 使用keySeparator: false即 key 中的点号.是 key 本身的组成部分而不是嵌套对象的层级分隔符。这一决定可以从 web/i18n-config/settings.ts 中得到印证export function getInitOptions(): InitOptions { return { // We do not have en for fallback load: currentOnly, fallbackLng: en-US, partialBundledLanguages: true, defaultNS, enableSelector: optimize, keySeparator: false, // 点号属于 key 本身不做嵌套解析 ns: namespaces, interpolation: { escapeValue: false, }, } }各 locale 目录与en-US的 key 集合必须严格对齐由 web/scripts/check-i18n.js 在提交前强制校验该脚本以targetLanguage en-US为基准对比其他语言包。从源码结构看这种“源语言 扁平 key 提交前校验”的组合使得 24 个受支持 locale见下文languages.ts之间的 key 漂移能够被脚本精确捕获而不依赖开发者人工记忆。二、文件职责划分Owners每个文件只负责一件事README 中最值得反复引用的部分是 “Owners” 一节——它把i18n-config目录拆分为职责单一的若干文件避免任何人把语言注册表复制到文档或代码的其他位置README 明确要求 “Do not copy the language registry into documentation. Read the current source files when adding a locale or namespace.”。文件职责源码佐证web/i18n-config/languages.ts受支持 Web locale 的唯一事实来源source of truth导出languages数组每项含value/name/prompt_name/example/supported字段web/i18n-config/language.tslocale 归一化与产品特定的 locale 映射拥有I18nText契约定义LanguagesSupported、getLanguage、localeMap、getDocLanguage等web/i18n-config/resources.ts带类型的命名空间namespace注册表文件名用 kebab-case命名空间用 camel-caseapp-debug.json→appDebug通过kebabCase(ns)转换web/i18n-config/locale-resources/locale.ts单一 locale 的**懒加载lazy loading**入口如 web/i18n-config/locale-resources/zh-Hans.ts 仅两行动态 importweb/i18n-config/settings.ts共享的 i18next 初始化选项getInitOptions()返回InitOptionsweb/scripts/check-i18n.jslocale key 校验与多余 key 的移除pnpm i18n:check的执行体当前web/i18n-config/locale-resources/目录下共存在 24 个locale.ts文件ar-TN、de-DE、en-US、es-ES、fa-IR、fr-FR、hi-IN、id-ID、it-IT、ja-JP、ko-KR、lo-LA、nl-NL、pl-PL、pt-BR、ro-RO、ru-RU、sl-SI、th-TH、tr-TR、uk-UA、vi-VN、zh-Hans、zh-Hant与 web/i18n/ 下的 24 个语言目录一一对应。2.1 语言注册表languages.ts 的结构languages.ts 是一个as const的静态数据文件每个语言条目长这样{ value: zh-Hans, name: 简体中文, prompt_name: Chinese Simplified, example: 你好Dify, supported: true, },value程序使用的 locale 标识en-US、zh-Hans、ja-JP……name面向用户的本地化显示名prompt_name英文短名用于提示语等场景example该语言的“Hello, Dify!”问候示例常用于模型提示词或 UI 预览supported是否启用。language.ts 中的LanguagesSupported正是通过languages.filter((item) item.supported).map((item) item.value)派生而来——这意味着新增或停用语言只需改这里下游类型与运行时自动收敛。I18nText类型也由该列表直接生成要求后端下发的多语言对象必须覆盖所有受支持 localeexport type I18nText Record(typeof LanguagesSupported)[number], string2.2 locale 归一化language.ts 的映射层language.ts 除了持有LanguagesSupported还承担三类映射职责getLanguage将zh-Hans/ja-JP转换为下划线形式zh_Hans/ja_JP其余 locale 一律回退到LanguagesSupported[0]即en_US。这里的下划线形式是与后端历史字段如en_US、zh_Hans、ja_JP兼容的产物因此Locale类型显式并入了这三个 legacy 值。localeMaplocale → 短码en、zh-cn、zh-tw、ja……的双写法映射en-US与en_US都指向en供依赖短码的第三方库使用。产品特定映射getDocLanguage文档站只服务zh/ja/en三种语言默认en与getAccessControlTemplateLanguage访问控制模板语言的zh/ja/en映射体现了“一个 locale 体系、多个消费方按各自能力取子集”的设计。该文件末尾的NOTICE_I18N常量则是I18nText契约的一个真实用例全站公告的title与desc按en_US/zh_Hans等下划线 key 为全部 24 个 locale 提供文案。三、命名空间注册表resources.ts 的类型安全体系resources.ts 是 README 中 “namespaces use camel case, file names use kebab case” 规则的落点其工作方式分四层37 个类型化命名空间从web/i18n/en-US/*.json逐一import typeapp、appDebug、dataset、workflow、billing……共 37 个如app-debug.json→appDebug、agent-v-2.json→agentV2聚合为RawResources类型。由于只是import type这些 import 不会进入运行时 bundle。PluralBaseResources复数键桥接i18next 的复数选择器count会让 TypeScript 难以静态推断可用 key因此该类型以类型级声明把复数基础键如common.members.seatsRemaining、workflow.nodes.iteration.error显式暴露出来。源码中的注释解释了动机“This type-only bridge exposes runtime plural base keys; selector types cannot require callers to pass count.”defaultNS app未指定命名空间时默认落在app。文件名 ↔ 命名空间的双向推导namespacesInFileName namespaces.map((ns) kebabCase(ns))由 web/i18n-config/load-resource.ts 在运行时用kebabCase(namespace)完成 camelCase → kebab-case 的动态文件名换算。这套设计让 TS 编译器能够校验“某命名空间下是否存在某个 key”命名空间注册表同时是 resources.ts#L146-L184 中namespaces数组传给 i18nextns选项的类型来源二者通过satisfies ReadonlyArraykeyof Resources强绑定新增命名空间时若忘记登记会直接报错。四、运行时链路i18next 实例、懒加载与 Cookie 切换README 没有逐行描述运行时但源码链路完整且清晰可按“资源加载 → 实例创建 → 语言切换”三步理解。4.1 locale 懒加载每个locale-resources/locale.ts只做一件事——动态 import 该 locale 的 JSON例如 zh-Hans.tsexport const loadResource (fileNamespace: string) import(../../i18n/zh-Hans/${fileNamespace}.json)load-resource.ts 中的loadLocaleResources再按 locale 动态选择模块const loadLocaleResources (locale: Locale): PromiseLocaleResourceModule { const normalized normalizeLocale(locale) return import(./locale-resources/${normalized}.ts) }normalizeLocale在这里完成第二道防线把 legacy 写法en_US/ja_JP/zh_Hans映射回连字符形式不在LanguagesSupported中的 locale 一律回退到en-USdefaultLocale en-US satisfies Locale。结合settings.ts中load: currentOnly与fallbackLng: en-US的配置注释说明 “We do not have en for fallback”运行时只会加载当前 locale 的当前命名空间这正是两级动态 importlocale 模块 → JSON 文件实现按需分包的基础。4.2 客户端实例创建client.ts 展示了标准的 i18next react-i18next 组装方式export function createI18nextInstance(lng: Locale, resources: Resource) { const instance createInstance() instance .use(initReactI18next) .use( resourcesToBackend((language, namespace) loadI18nResource(language, namespace), ), ) .init({ ...getInitOptions(), lng, resources }) return instance }i18next-resources-to-backend把自定义的loadI18nResource挂为后端i18next 缺什么命名空间就向它要而它最终落到 4.1 的动态 import。changeLanguage(lng)则通过react-i18next的getI18n()委托给全局实例保证语言切换只触发对应资源的懒加载而不重打全部包。4.3 SSR/CSR 双入口与语言切换交互web/package.json 的 exports 字段暴露了#i18n包内别名按运行环境分发到不同实现#i18n: { react-server: ./i18n-config/lib.server.ts, default: ./i18n-config/lib.client.ts }即 React Server Components 环境使用 lib.server.ts浏览器端使用 lib.client.ts另有 server.ts / client.ts 分别承担 SSR 与 CSR 侧的具体装配。面向交互的入口在 web/i18n-config/index.tsexport const i18n { defaultLocale: en-US, locales: LanguagesSupported, } as const export const setLocaleOnClient async (locale: Locale, reloadPage true) { Cookies.set(LOCALE_COOKIE_NAME, locale, { expires: 365 }) await changeLanguage(locale) if (reloadPage) location.reload() }切换语言的完整闭环是写 Cookie有效期 365 天键名为LOCALE_COOKIE_NAME→changeLanguage异步加载新 locale 资源 → 默认整页 reload 保证服务端渲染与客户端状态一致。同文件的renderI18nObject则解决反向问题——渲染后端直接下发的多语言对象优先取obj[language]其次回退obj.en_US最后取第一个非空值这恰好与I18nText的下划线 key 约定呼应。五、新增一个 localeREADME 五步流程README 的 “Add a locale” 一节给出了五步操作结合源码可以逐步展开在 languages.ts 中添加语言元数据value/name/prompt_name/example/supported: true。LanguagesSupported与I18nText会随之自动扩展未同步填充新 locale 的I18nText用例会编译报错相当于类型级提醒。创建web/i18n/locale/目录放入全部源命名空间对应的 JSON 文件当前为 web/i18n/en-US/ 下的 37 个文件如app-debug.json、dataset-pipeline.json、workflow.json……key 必须与en-US完全对齐。新建locale-resources/locale.ts照抄 zh-Hans.ts 的两行动态 import 即可并在 language.ts 中补上所需映射——至少是localeMap中的短码条目如该 locale 需服务文档站或访问控制模板还要登记DOC_LANGUAGE/ACCESS_CONTROL_TEMPLATE_LANGUAGE。同步后端语言注册表当该 locale 会被后端 API 接受时需保持 api/constants/languages.py 与前端languages.ts对齐。提交前运行完整的 i18n 校验pnpm i18n:check下一节详述。README 特别提醒language.ts同时拥有“被接受的 locale 拼写”与I18nText契约新增 locale 时二者必须同步维护否则会出现“运行时认得但类型不认”或反向的错位。六、新增或修改文案与 i18n:check 校验6.1 文案修改规则README 的 “Add or change copy” 一节规则很直白先改英文 key再更新所有受支持 locale精确保留插值变量与 markup 占位符{{name}}、{{count}}以及内嵌标签不得在翻译中增删或改名——因为占位符是前后端渲染契约的一部分。6.2 i18n:check 命令详解在web/目录下运行脚本定义见 web/package.jsoni18n:check: tsx ./scripts/check-i18n.jspnpm i18n:check pnpm i18n:check --file app billing --lang zh-Hans ja-JP不带参数全量校验所有受支持 locale 与en-US的 key 一致性--file ... --lang ...把校验范围收窄到指定命名空间与语言。两个 flag 的取值都是空格分隔的脚本源码中显式拒绝逗号--file expects space-separated values. Example: --file app billing且都至少需要一个值--auto-remove仅当确实要删除多余 locale key 时使用否则校验只会报告而不改动文件。从 check-i18n.js 的源码结构看它直接import data from ../i18n-config/languages并以supported: true的条目为语言全集——又一次印证了 “languages.ts是唯一事实来源”校验器、运行时、SSR 入口消费的是同一份注册表不存在第二份语言清单。同目录还有两个配套脚本web/package.json中定义i18n:migrate-selectors选择器迁移与i18n:prune-unused清理未使用 key属于维护性工具日常文案工作以i18n:check为主。七、自动化翻译工作流README 最后描述了仓库内置的自动翻译机制两条触发路径自动触发当main分支上web/i18n/en-US/*.json发生变更时触发 scoped translation workflow。工作流从languages.ts推导目标 locale而不是硬编码语言列表只翻译发生变化的命名空间与 key随后用i18n:check验证翻译结果仅在确实产生翻译变更时开一个 pull request。手动触发使用Translate i18n Files with Claude Codeworkflow dispatch 执行手动 scoped syncFull 模式要求显式提供文件列表。这套机制与前述设计自洽由于 key 以en-US为源且校验器以en-US为基准自动翻译只需对 diff 的 key 做最小化同步i18n:check则作为 PR 前的最终一致性闸门。八、关键路径速查内容路径本文主体文档web/i18n-config/README.md语言注册表唯一事实来源web/i18n-config/languages.tslocale 归一化与I18nText契约web/i18n-config/language.ts命名空间类型注册表37 个web/i18n-config/resources.tsi18next 共享初始化选项web/i18n-config/settings.tslocale 懒加载模块24 个web/i18n-config/locale-resources/locale 归一化 资源动态加载web/i18n-config/load-resource.ts客户端实例创建 / 语言切换web/i18n-config/client.ts交互入口Cookie、renderI18nObjectweb/i18n-config/index.ts英文源语言包web/i18n/en-US/key 校验脚本web/scripts/check-i18n.js后端语言注册表需对齐api/constants/languages.py适用前提与限制以上机制均针对 Dify Web 前端Next.js i18next react-i18next 技术栈i18n:check需在web/目录下通过 pnpm 运行--auto-remove会真实删除 locale 文件中的多余 key误用会造成文案丢失。扩展 locale 或命名空间时务必以当前源码文件为准README 明确告诫不要将语言注册表抄入文档并保证前后端两份语言注册表同步。【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

freeCodeCamp 无障碍实战:用 HTML5 header 地标元素让屏幕阅读器导航更简单

freeCodeCamp 无障碍实战:用 HTML5 header 地标元素让屏幕阅读器导航更简单

2026/9/7 19:12:16

freeCodeCamp 无障碍实战:用 HTML5 header 地标元素让屏幕阅读器导航更简单 【免费下载链接】freeCodeCamp freeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free. 项目地址: https://gitcode.com/Gi…

Joplin HTML 转 Markdown 链接降级规则解析:以 anchor_same_title_and_url 测试用例为例

Joplin HTML 转 Markdown 链接降级规则解析:以 anchor_same_title_and_url 测试用例为例

2026/9/7 19:12:16

Joplin HTML 转 Markdown 链接降级规则解析:以 anchor_same_title_and_url 测试用例为例 【免费下载链接】joplin Joplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS. 项目地址: https://gitcode…

百度编辑器上传Word合同图片自动归档与分类的落地实践

百度编辑器上传Word合同图片自动归档与分类的落地实践

2026/9/7 19:02:15

做金融行业合同管理系统这几年,我几乎每天都要面对“百度编辑器批量上传WORD合同”这个场景。运营同事把签好字的合同Word拖到后台,点击粘贴,过一会儿后台图片目录就变成了一堆随机命名的文件,谁是哪份合同的哪一页,完…

VS 2026离线安装实战:从layout制作到报错排查

VS 2026离线安装实战:从layout制作到报错排查

2026/9/7 21:12:22

Visual Studio 做离线部署这事,我在企业内网环境里前前后后折腾过不少次。每次换新版本,总会遇到几个没见过的报错,尤其是到了 VS 2026 这一代,安装器架构延续了 2022 的 layout 模式,但组件更碎、依赖更多&#xff0c…

缝制行业APS落地指南:从人工排产到智能排程的核心逻辑

缝制行业APS落地指南:从人工排产到智能排程的核心逻辑

2026/9/7 21:12:22

周一早上八点,计划员小周像往常一样打开电脑里那个排产表,但这次他已经不太想打开它了——十几个密集填满的Excel页签,七款同时在某条吊挂线上生产的衣服,三种不同颜色面料到货时间都不一样,还有两个熟手缝纫工昨天同时…

Cursor中调试C++完整链路:环境配置与断点排查实战

Cursor中调试C++完整链路:环境配置与断点排查实战

2026/9/7 21:12:22

1. 先说结论:问题往往不在Cursor,而在你的“调试链路”“Cursor根本无法调试C”这个标题,我在好几个技术社群里看到过,说这话的往往不是小白,而是从VS Code或者其他编辑器切换过来的老手。我也经历过那个阶段&#xff…

本地模型与云端工具协同:四大开源项目搭建AI工作流

本地模型与云端工具协同:四大开源项目搭建AI工作流

2026/9/7 21:12:22

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

MySQL主从自动故障切换脚本:基于GTID与VIP漂移的高可用实践

MySQL主从自动故障切换脚本:基于GTID与VIP漂移的高可用实践

2026/9/7 21:12:21

凌晨两点手机突然震动,监控告警显示MySQL主库连接数异常飙升,紧接着就是探活失败。等你揉着眼睛坐到电脑前,打开终端准备手工切换时,业务已经中断快十分钟了。这种场景对运维和DBA来说太熟悉了——主从复制架构虽然能让数据多一份…

Kubernetes Service 访问不通的三层深度排查

Kubernetes Service 访问不通的三层深度排查

2026/9/7 21:02:21

Kubernetes Service 访问不通的三层深度排查在 Kubernetes 生产环境中,“Service 访问不通”是一个发生频次极高、排查链路横跨多个网络层级的复杂故障。很多初级工程师在遇到 curl order-service:8080 报错 Connection refused 或 i/o timeout 时,往往陷…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/7 20:21:46

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/7 3:44:24

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/7 8:03:37

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

基于YOLOv8和PyQt5的麦穗稻穗检测识别系统设计与实现

基于YOLOv8和PyQt5的麦穗稻穗检测识别系统设计与实现

2026/9/7 0:01:24

这次我们来看一个把目标检测算法和桌面端工具结合得很典型的项目:基于 YOLOv8 PyQt5 的麦穗稻穗检测识别系统。这个项目本身不是新概念,但它的价值在于落地形态很完整。YOLOv8 负责核心的麦穗稻穗目标检测,PyQt5 负责提供可视化的桌面交互界…

UL 1642锂电池安全标准全解析:测试项目、认证流程与避坑指南

UL 1642锂电池安全标准全解析:测试项目、认证流程与避坑指南

2026/9/7 0:01:24

简介:UL 1642是锂电池安全领域的重要规范,本中文版资源适合锂电池制造商、检测机构工程师及产品认证相关人员阅读,用于理解电池在设计与制造层面的安全要求、测试方法与合规要点。资源共1个PDF文件,压缩包大小834KB,便…

BS EN 13814-1-2019游乐设施安全标准:设计与制造核心要点解析

BS EN 13814-1-2019游乐设施安全标准:设计与制造核心要点解析

2026/9/7 0:01:24

简介:BS EN 13814-1:2019是英国采纳欧洲标准EN 13814-1:2019的正式版本,由BSI标准出版,重点规定游乐设施和游乐设备在设计与制造环节的安全准则,与BS EN 13814-2:2019、BS EN 13814-3:2019共同取代旧版BS EN 13814:2004。该标准面…

远程协作的工作台整理

远程协作的工作台整理

2026/9/7 3:38:07

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/4 7:42:10

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/6 23:21:51

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…