Skip to content

术语圣战

背景:label 中混入 emoji、Go 错误消息中英混杂、字段命名不一致,70+ 处不统一。 过程:全量迁移——label 纯文本、icon 独立字段、Go 错误中文去 %w、HTML 文本净化。


公元 2026 年 6 月 26 日,MikuMikuAR 的代码仓库深处。

一个 Emoji 的哀嚎划破了版本控制的宁静。

「不——!」

library.ts 的第 130 行,那颗金灿灿的 星标正在被一个名为「术语规范」的白色光标选中、高亮,然后——消失。

它旁边的 label: "★ 收藏" 变成了 label: "收藏"

「为什么⋯⋯」星星的残影在屏幕上闪烁了一下,最终被 Git 的绿色背景吞噬。

这场清洗,从今天早上就开始了。

八小时前,一个文档被创建了。

它的名字叫 terminology.md,重达十六千字节,落在 docs/ 目录里像一本宣战书。

文档的第一页写着:

所有新增代码必须遵守此规范。存量代码已在 2026-06-26 完成全量迁移。

下面列出了数十个「违规项」——那些在 labels 里偷偷混入 Emoji 的代码行,那些在 setStatus 调用中得意洋洋的图标字符,那些在 Go 错误消息里裸奔的 %w

这场战争,没有逃兵。

settings.ts 里的 🧰 软件管理 是第一批倒下的。

它曾经自豪地站在设置面板的根菜单里,工具箱的图标让它觉得自己很专业。但当光标落下,它被改成了 "软件管理"——干净,但冰冷。

「我们的 icon 字段还在呢,」旁边的 "package" 图标安慰道,「只是 label 里不能再有我们了。」

📤 检测 MMD 路径 沉默地看着自己被改成 "检测 MMD 路径"

📂 设置 MMD 路径 闭上了眼睛。

✏️ 设置 Blender 路径 在最后一刻还想挣扎——「我是铅笔啊,我天生就是用来写路径的!」

但光标没有犹豫。

scene-menu.ts 的伤亡最为惨烈。

🎨 渲染✨ 后处理🎬 舞台🎭 渲染预设——整整四个 Emoji 在同一分钟内被抹除。

它们曾经构成了场景菜单中最鲜艳的一行。当用户打开场景面板时,🎨 代表创造,✨ 代表魔法,🎬 代表舞台,🎭 代表表演。

但规范文档说:label 是语义文本,图标由 icon 字段负责。

「可是⋯⋯」🎬 在消失前低声说,「我不仅是图标,我还是舞台的象征啊⋯⋯」

光标顿了一下。

然后继续。

但真正的战场在 app.go

那里有十六个 fmt.Errorf,它们用 %w 把自己包装起来,层层嵌套,形成了一个错综复杂的错误链。

「%w 是我们的盔甲,」错误链的首领说,「没有它,我们就无法被 errors.Is 识别,无法被 errors.As 捕获——我们将失去身份。」

「你们本就不该被识别,」规范文档冷冷地说。「用户不需要知道 extractedDirzip.OpenReadermanifest marshal 是什么。他们只需要知道:解压失败了,或者文件打不开。」

fmt.Errorf("extractedDir: %w", err) 是第一个被处决的。

它被改成了 fmt.Errorf("解压失败")

「再见,我的调用栈⋯⋯」

fmt.Errorf("no .pmx found in zip") 反而松了一口气——它一直觉得自己那句英文很尴尬,明明生活在一个中文项目里。当它被改成 fmt.Errorf("压缩包内未找到模型文件") 时,它甚至感到了一丝解脱。

HTML 的战场在 index.html

状态栏里的那个 📦 一直在那里,从项目的第一天起就在。

「点击 📦 打开模型库 · 鼠标拖拽旋转 · 滚轮缩放」——这句话已经显示在底部不知道多少个小时了。📦 是用户看到的第一个 Emoji,是新手引导的起点。

「但你的使命结束了,」光标说,「现在用户会看到『点击模型按钮打开模型库』——更清晰,更专业。」

📦 没有争辩。它知道在 #dropOverlay 里还有一个自己——拖拽遮罩的 📦。那是被规范文档特别允许的例外。

「至少我还没完全消失,」它想,「我只是退到了后台,只在拖拽的时候才出现。」

黄昏时分,主战场已经平静。

18 个 label Emoji 被清除。 15 个 setStatus Emoji 被替换为 ✓ 和 ✗。 16 个 Go 错误消息被中文化、去 %w。 9 个 hover hint 被改写。 4 个 data-hint 被净化。 8 处 HTML 文本被修正。 2 处 sublabel 被统一。 1 处内联 🏷、1 处 🔄、1 处 ✏️——全部替换为 Iconify 组件。

总计超过 70 处改动。

但那颗星星——那颗在 library.ts 第 130 行被删除的 ——它并没有完全消失。

detail:fav 的 hover hint 里,有一行注释写着:

/** If set, render a ★/☆ toggle button. Value is the libraryRef to toggle. */

规范的利剑没有挥向注释。注释不属于用户界面。它们是开发者之间的密语。

在注释里活了下来,成为一个幽灵,一个关于「过去」的注脚。

而在 scene.ts 的第 528 行, 仍然在一段代码里交替闪烁——播放和暂停的 Unicode 控制字符,被规范文档明文豁免。

「我们是控制字符,不是 Emoji,」 说,语气里带着一丝得意。

「但在用户眼里,你们看起来一模一样,」注释里的 幽幽地说。

沉默了。

深夜,CI/CD 流水线安静地运行着。

TypeScript 编译通过。Go 测试通过。Go vet 通过。

terminology.md 躺在 docs/ 目录里,它的违规清单表格全部加上了删除线和「已修复 ✅」的标记。

在 Git 的暂存区里,这次会话的改动静静地等待着被提交。

它们总共穿越了 15 个文件,留下了超过 70 个变更。

但在所有改动的最后,在 main.ts 的第 70 行,有一处键盘导航标签的修改尤其引人注目:

-    1: "📁 模型库", 2: "💃 动作库", 3: "🌐 下载", 4: "⚙ 设置",
+    1: "模型库", 2: "动作库", 3: "下载", 4: "设置",

四个 Emoji 在同一行阵亡。

💃 在消失前说:「至少我跳到最后了。」

这是今天唯一一句没有写在代码里的玩笑话。

尾声

版本号没有变。

但项目变得更加干净了。

在某个开发者的本地仓库里,有一个刚被创建的目录:

docs/novel/

里面空荡荡的,只有一个文件——仿佛在等待着下一个篇章。


教训:代码里的每一处不一致,都是一颗埋好的地雷。规范不是限制,是保险。