2026-09-23·by Sijie Wang#lucerna#software#architecture

all-forms-underline

全形态下划线(标记一个,点亮所有变形)

上级:key-designs

这是本产品阅读体验中最独特的一项功能:只要保存一个词的一种变形,该词元(lemma)的所有屈折形式就会在全书范围内被加上下划线。(内部代号"Task #2"。)

形态集合。 services/formMatching.ts 为每个词元构建一个匹配集合:entryFormSet = LLM/词典抓取得到的 forms ∪ 该词的表层形式 ∪ 词元本身;normalizeForms 负责转小写、去首尾空白,并丢弃多词元的表层形式(这样 "le château" 无法匹配页面上的单个词元,但 "château" 本身仍能匹配;"ils/elles méritent" 也不会造成误匹配)。随后 buildMarkedWordsMapservices/displayUtils.ts)用每一种形式作为键建立一张映射表,阅读器只要 markedWords.get(token.toLowerCase()) 命中,就为该页面词元加上下划线(ClickableText.tsx)。

分词器必须与其他一切保持一致。 services/tokenizationService.ts 是一个支持 Unicode 的分词器(拉丁标点单独处理;中日韩汉字 / 平假名 / 片假名 / 谚文各自归为一类,中日韩汉字逐字符切分),其中还有一道法语省音合并步骤,会把 l'd'j'qu' 与其后的词重新合并为一个词元——这与写死在 LLM prompt 里的分词规则保持一致。这一点之所以关键,是因为词元边界必须在三个消费方之间完全一致:下划线匹配器、词性着色、以及 LLM 的单词分析。三者一旦不一致,下划线就会标错位置,或者颜色标错。

德语可分离动词在这里也有专门处理(客户端的 services/separableVerbService.ts 启发式规则),在 Python 引擎里则有正规处理(linguistic-two-engines)。

为什么它是承重构件而非装饰:下划线是整个 vocabulary-loop反馈界面——正是它让已保存的词在阅读时变得可见,而它依赖的正是"形态集合 + 一个与语言层保持一致的分词器"这套组合。分词器一旦出错,核心功能就会在无声无息中把标注画错地方。

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →