☰
Uniswap Interface 翻译术语表治理:i18n 术语级联的加载机制、词条格式与 CI 校验实践
2026/10/13 6:44:31 网站建设 项目流程
  • 区块链
  • DeFi
  • 前端
  • 移动开发

【免费下载链接】interface

🦄 Open source interfaces for the Uniswap protocol

项目地址:https://gitcode.com/gh_mirrors/in/interface
点击查看免费下载

导读

Uniswap Interface 仓库(interface)的.i18n/glossary/目录承载着 AI 翻译流水线所依赖的"术语级联"(terminology cascade):它决定每个语言环境下哪些词必须保留英文、哪些词必须使用特定译法、哪些译法属于硬性禁用。本篇指南以仓库内的 .i18n/glossary/README.md 为主线,结合实际词条文件与校验脚本,讲解术语表的"替换不合并"加载优先级、目录分层结构、词条字段格式,以及让错误词条在 PR 阶段而非翻译运行时被拦截的 CI 校验机制。读完后你将能准确回答:一个新术语应该写进哪个文件、一个翻译修正应该落成词条还是直接改译文、以及为什么误删一个 YAML 文件会静默影响所有语种的翻译结果。

术语级联:替换而非合并的加载优先级

@uniswap/i18n-cli(内部工具包)在为应用字符串执行翻译时,会加载一个"术语级联":它由core/(跨语种通用词条)与locales/(各语种词条)两部分组成,对应仓库内的.i18n/glossary/core/与.i18n/glossary/locales/目录。

这一级联整体替换CLI 包内部内置的"种子术语表"(seed glossary),而不是与种子合并。因此:

  • 本目录中的词条只可能被新增(added),绝不会被种子整体覆盖(never wholesale replaced);
  • 本目录最初是种子术语表的逐字节拷贝(byte-for-byte copy);
  • 一旦某个文件被删除,该文件的词条就会从每一次翻译运行中静默消失——因为"替换"语义下没有备份可回退。

从源码结构看,这一设计意图是让术语治理完全由仓库掌控:CLI 只负责在加载时解析文件,词条的增删改全部以.i18n/glossary/下的内容为准,保证同一份词条同时作用于 Web、Mobile 等多个应用端。

替换语义的两个直接后果

后果一:CLI 种子更新不再自动流入本仓库

由于是"替换不合并",一旦.i18n/glossary/目录存在,新版本@uniswap/i18n-cli内置种子术语表的改进不会自动进入本仓库。文档明确指出:即使升级I18N_CLI_VERSION,看起来像是更新了术语,实际上没有任何效果。因此:

  • 升级 CLI 版本的人,应当把该包seed/glossary与.i18n/glossary/做一次 diff,将有价值的改进手工移植进本目录;
  • 这个动作没有自动化保障,属于人工职责,是维护本目录最容易踩的坑。

后果二:未使用的 locale 文件有意保留

目录中保留了例如locales/fil-PH.yml这样没有对应应用 locale 映射的文件(仓库的Locale枚举中并不存在菲律宾语)。文档解释这是刻意为之:

  • 这些文件在运行时零成本;
  • 让目录始终是种子的严格超集(strict superset),"拷贝保真度"(copy-fidelity)这件事才是可验证、可检查的。

也就是说,fil-PH.yml的存在不是为了某个实际语种,而是为了维护"本目录 = 种子 + 仓库增量"这一可审计的对应关系。

style 指南路径注释:为保真而保留的"死链接"

locales/*.yml文件头部注释中会出现../../style/locales/*.md这样的路径,例如fr-FR.yml中的(see ../../style/locales/fr-FR.md)。这些路径指向随@uniswap/i18n-cli包分发的各语种风格指南,刻意不复制进本仓库:

  • 对 CLI 而言,这些路径在它自己的安装目录下可以正常解析;
  • 对仓库而言,它们是无效路径(.i18n/下并无style/目录);
  • 注释保持原样,是为了让词条文件与种子术语表保持逐字节一致。

因此阅读这些文件时,风格指南需要从已安装的 CLI 包内查看,而不是在仓库中寻找。

目录结构与词条形态

三层结构

.i18n/glossary/下只允许存在三个 tier 目录(由校验脚本中的KNOWN_TIERS常量锁定):

目录作用
core/跨所有语种生效的通用词条,典型如 DNT(Do-Not-Translate,不可翻译)品牌词
domains/预留的领域级词条层(当前仓库未使用该目录)
locales/各语种专属词条,文件名即 locale 代码,如zh-CN.yml、fr-FR.yml

根目录只允许README.md这一个文件。除此之外,任何散落在根目录的.yml或未知 tier 目录都会被校验脚本拒绝,因为它们会被 CLI 加载器静默忽略——看起来提交了,实际对任何一次运行都没有贡献。

core:全局 DNT 品牌词

.i18n/glossary/core/crypto.yml 是核心词条的代表。它收录的是"每个语种都必须保留英文"的词:品牌名(Uniswap、Unichain、Ethereum)、协议术语(calldata、gas)、产品名(Uniswap Wallet、Uniswap Web App)等。机制上,DNT 掩码器(DNT masker)会在模型看到源文本之前把这些词替换为占位符,翻译完成后再还原,从而在机制上杜绝误译。审计曾实际捕获过这类失败模式:

  • calldata被译成"通话数据"(phone-call data 的直译);
  • NFT被展开成"非同质化代币"这种"圈内没人说的正式学术展开"。

词条还体现了长短语优先掩码的排序约定:Uniswap Wallet作为一个整体被掩码,保证单元完整性,而单独的Uniswap和wallet各自走自己的规则。同族的Uniswap Interface、Uniswap Mobile、Uniswap Extension、UniswapX、Trading API以及Touch ID、Windows Hello、Apple Pay、Google Pay、PayPal等品牌均如此处理(其中Twitter还带forbidden,用于拦截供应商把品牌提前改写成 "X" 的行为)。

协议与交易术语同样在 core 中做了 DNT 处理:Tick(集中流动性价格网格原语)、Timelock/Time lock、bps、FDV、MC、Spread(区分大小写,大写标签是术语、小写散文自由翻译)、Flags(v4 hook 权限位域)、Call data、bug bounty等,每条都记录了供应商误译的实例作为佐证。

locales:preferred / forbidden 双轨约束

各语种文件在 core 之上叠加preferred(推荐译法)与forbidden(硬性禁用译法)两套规则。以 .i18n/glossary/locales/zh-CN.yml 为例:

  • 基础词条:wallet→ 钱包、swap→ 兑换、slippage→ 滑点、TVL→ 总锁仓量、seed phrase→ 种子短语;
  • 营销关键主张词条:app fee必须译为 "App 手续费"(保持 App 为拉丁字母、手续费=交易手续费),并forbidden掉 "应用费用""应用程序费用""应用程序手续费"三个字面译法,因为 "Zero app fees" 是核心营销主张;
  • 审计修复型词条:report(数据质量反馈)必须用"报告"而非"举报"(举报在大陆语境带执法/投诉色彩,会劝退用户反馈错误数据);claim(unitags 首次注册用户名)必须用"申领"而非"认领"(认领是领取遗失物);bid(Toucan 拍卖竞价)必须用"竞价"而非"出价";passcode必须用 "PIN 码" 以与文本凭据password(密码)区分;
  • 安全词条:passkey→ 通行密钥(forbidden掉裸英文 "passkey")、private keys→ 私钥;
  • onchain从 core 的全局 DNT 中重新划定到 locale 层:对 zh-CN 而言,"链上"才是地道且对应用商店受众更可读的译法,同时用forbidden: ["onchain", "on-chain"]防止英文回归。

fr-FR.yml则展示了更复杂的治理链:swap按角色拆分(role-split)——动词/CTA 本地化为 "Échanger",而作为品牌功能标签的英文 "Swap" 保留;wrap/unwrap/mint经母语评审后保留英文,因为法语直译(envelopper/déballer/frapper)全是假朋友(false friend);yield系列(yield/earnings/rewards)则建立了 Earn 域财务概念分类法,用termType区分 rate 与 amount。每个词条都记录了来源(Notion 指南、原生评审、bug-bash、TLM 裁定)与日期,形成完整的 provenance 链。

词条字段速查

综合core/crypto.yml、locales/*.yml与校验脚本中的枚举定义,一条词条可携带的字段如下:

字段含义典型取值
term要匹配的源词任意字符串,必填且非空
doNotTranslate是否掩码保留英文true
preferred各语种推荐译法{ zh-CN: "钱包" }
forbidden各语种硬性禁用译法{ zh-CN: ["应用费用"] }
caseSensitive大小写敏感匹配true
partOfSpeech词性noun/verb/adjective/acronym/phrase
termType术语类型枚举rate/amount/activity/action/phrase/name
status词条状态枚举draft/corpus-derived/native-ratified/legal-approved
gender语法性别(拉丁语系)masculine/feminine
description治理说明(来源、反例、适用范围)自由文本

校验脚本 scripts/i18n-glossary.test.ts 中复制了 CLI 加载器的枚举定义:TERM_TYPES = ['rate', 'amount', 'activity', 'action', 'phrase', 'name']、GLOSSARY_STATUSES = ['draft', 'corpus-derived', 'native-ratified', 'legal-approved']。该脚本注释特别说明:如果 CLI 升级扩展了这些枚举,需要同步扩展脚本中的拷贝;过期拷贝会 fail-closed(拒绝 CLI 本可接受的值),绝不会 fail-open。另注意,仅有description而无任何匹配/掩码字段的词条,解析为上下文注释(context note):它只会进入翻译/审校 prompt 作为策略指引,不参与掩码或扫描。

CI 校验:让坏词条死在 PR 里

@uniswap/i18n-cli在加载词条时会执行一组校验,仓库将同一组校验镜像到了 scripts/i18n-glossary.test.ts,在 PR CI 中运行。这样格式错误的词条会在PR 阶段失败,而不是拖到下一次定时翻译运行才爆雷(文档明确写道:a malformed entry fails the PR instead of the next scheduled translation run)。

脚本用Bun.YAML解析(无需 node_modules,与该 CI 步骤的其他测试一致),逐文件执行与 CLI 加载器(@uniswap/i18n-cli的src/glossary/load.ts)完全相同的检查:

  • 每个.yml/.yaml文件顶层必须是YAML 数组;
  • 每条词条必须是对象,且term为非空字符串;
  • termType/status若出现,必须是合法枚举值;
  • 目录布局检查:只允许core/domains/locales三个 tier 目录;根目录除README.md外不得有散落文件;tier 目录内只允许 YAML 文件;
  • 目录非空检查:空词条库会静默回落到 CLI 种子,因此yamlFiles().length > 0是硬性断言。

测试输出形如${file} entry [${idx}] is missing a non-empty string "term",精确到文件与数组下标,便于定位。运行方式为bun test scripts/i18n-glossary.test.ts。配套的 scripts/i18n-memory.test.ts 则守护.i18n/memory/<locale>.json翻译记忆分片(v1 shard 结构、locale 自洽、字节数上限与工作流环境变量I18N_MEMORY_MAX_BYTES联动),并明确将自身定位为 glossary 校验的姊妹闸门。

内容治理:什么该进词条、什么不该进

文档给出了清晰的判定标准:

  • 术语修正(terminology corrections)——来自翻译 PR 评审中发现的错误或不一致的术语渲染——应当落成词条,这样修复会作用于每一次未来的运行,而不是只改一条字符串。zh-CN.yml中report/claim/bid等"审计快速修复"条目即属此类,每条都注明了受影响的 key 命名空间(如reporting.*.data.*、unitags.*、transaction.status.submitBid.*)。
  • 一次性语气/措辞调整(one-off tone or phrasing fixes)——应当保留为人类在 locale 文件里的直接编辑。手工编辑过的字符串会被视为未跟踪(untracked),不会重新排队,流水线不会覆盖它。
  • 自动扫描(automated sweep)——可以提议词条,但绝不允许自动提交(must never auto-commit):一条错误的forbidden词条会导致整轮运行失败,因此每条词条都必须经过人工评审。这解释了为什么词条文件中的status存在draft→native-ratified→legal-approved的评审状态演进,以及大量词条标注 "pending native confirmation"。

与翻译流水线的衔接:配置文件与记忆分片

词条级联只是整个 i18n 流水线的一环。仓库根部的 i18n.config.ts 定义了 CLI 的其余输入:

  • 源语言为en-US,源文件指向packages/uniswap/src/i18n/locales/source/en-US.json;
  • 目标模板为packages/uniswap/src/i18n/locales/translations/{locale}.json;
  • locale 列表不从配置文件手写,而是从packages/uniswap/src/features/language/constants.ts的Locale枚举派生(getLocaleTranslationKey会把zh-Hans→zh-CN、zh-Hant→zh-TW、所有es-*变体 →es-ES),再剔除英文源并排序——这解释了为什么locales/目录下存在es-MX.yml却不存在es-419.yml等对应关系;
  • 该配置文件由 CLI 用裸bun import()加载且不带本仓库 node_modules,因此 scripts/i18n-config.test.ts 强制其依赖图只含相对导入、无外部依赖。

翻译记忆(translation memory)则记录每次翻译单元的哈希与状态:.i18n/memory/zh-CN.json中每条目携带sourceHash、glossaryHash、styleHash与status: clean、approvedBy: agent等字段——词条内容的变化会反映为glossaryHash的更新,驱动已译字符串的失效重译。glossary、memory、config 三者共同构成这套可审计、可回滚的翻译治理体系。

小结

.i18n/glossary/不是一份普通的翻译对照表,而是一套以"替换不合并"为基石的术语治理系统:core 层锁定全球通用的品牌与术语(DNT 掩码机制杜绝误译),locales 层用 preferred/forbidden 双轨约束每个语种的地道表达与禁区,CI 镜像校验让格式错误在 PR 阶段暴露,翻译记忆与词条哈希联动保证已译内容随词条变更正确失效。维护者需要记住三条铁律:升级 CLI 版本时必须手工 diff 种子词条;删除任何词条文件等于静默移除全部语种的对应规则;自动扫描只能提议、永远不能自动提交词条。

  • 区块链
  • DeFi
  • 前端
  • 移动开发

【免费下载链接】interface

🦄 Open source interfaces for the Uniswap protocol

项目地址:https://gitcode.com/gh_mirrors/in/interface
点击查看免费下载

相关推荐

上一篇:为 Livewire 添加新功能:从 wire 指令到全栈功能的完整开发指南
下一篇:ClusterFuzz 开发环境准备指南:依赖安装、pipenv 与常见问题排查

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询