免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Harper 方言感知拼写检查:深入解析 Spell.US.md 测试夹具与美式英语拼写纠正机制

Harper 方言感知拼写检查:深入解析 Spell.US.md 测试夹具与美式英语拼写纠正机制 Harper 方言感知拼写检查深入解析 Spell.US.md 测试夹具与美式英语拼写纠正机制【免费下载链接】harperOffline, privacy-first grammar checker. Fast, open-source, Rust-powered项目地址: https://gitcode.com/GitHub_Trending/har/harper本文以 harper-core 测试目录中的 Spell.US.md 测试夹具为切入点系统讲解 Harper 这款 Rust 离线语法检查器如何通过文件名约定与快照测试机制验证在其他英语方言中拼写正确、但在美式英语中属于错误的词汇纠正能力。读完本文你将理解 Harper 的方言模型Dialect/DialectFlags、方言自动检测与手动覆盖机制、基于 FST 与 Levenshtein 自动机的模糊拼写建议管线以及如何阅读与扩展这类方言拼写回归测试。一、Spell.US.md 是什么一份反美式拼写的测试语料Spell.US.md 位于 harper-core 的测试语料目录全文只有两段文字加一份词表却承担着精确的测试职责。文档原文明确说明This document contains a list of words spelled correctly in some dialects of English, but not American English. This is designed to test the spelling suggestions we give for such mistakes.即该文档收录了一批在英式及其他英语方言中拼写正确、但在美式英语中属于拼写错误的词汇用来验证 Harper 对这类方言性拼写错误给出的拼写建议是否正确。它属于整个harper-core/tests/text/快照测试语料库的一部分——与 Spell.md、Alices Adventures in Wonderland.md 等文件一样会被快照测试工具逐词扫描并对比输出结果。完整词表原文数据逐一保留文档## Words一节给出的完整词表如下AfterwardsCentreLabelledFlavourFavouredHonourGreyQuarrelledQuarrellingRecognisedNeighbourNeighbouringClamourTheatreAnalyse这些词覆盖了英式与美式拼写的几类典型差异逐一可在 Harper 的内置词典 dictionary.dict 中找到带方言标注的词条佐证类别英式拼写词表中的词美式拼写词典中的方言标注示例-our / -orFlavour、Favoured、Honour、Clamour、Neighbour、Neighbouringflavor、favored、honor、clamor、neighborcolour/~NwSJVGdrE!_₹与color/~NwSJVGdrE见下文标注符号说明-re / -erCentre、Theatrecenter、theatertheatre/NwSg!_₹与theater/~NwSg-ll- / -l-Labelled、Quarrelled、Quarrellinglabeled、quarreled、quarrelinglabelled/JVtTUr!_₹、quarrelled/VtT!_₹、quarrelling/V6Nm!_₹-ise / -izeRecognised、Analyserecognized、analyzerecognise/VdSGB!_₹与recognize/~VdSGB、analyse/VdSGr!_₹与analyze/~VdSGr-ay / -eyGreygraygrey/J^pVdGSNwg!_₹单词差异Afterwardsafterward—从源码结构与词典标注可以推断Harper 将方言有效词的元数据写入词典条目没有任何方言标注的词默认为所有方言通用而带特定方言标注的词仅在对应方言下视为正确dict_word_metadata.rs 的注释明确写道If no dialects are defined, it can be assumed that the word is valid in all dialects of English。二、核心机制文件名中的.US.方言覆盖约定Spell.US.md 最独特之处在于它的文件名本身就是测试配置。文档原文To achieve this, the filename of this file contains.US., which will tell the snapshot generator to use the American dialect, rather than trying to use an automatically detected dialect.也就是说快照生成器会从文件名中解析方言缩写.US.强制使用美式方言而不是走自动检测文档方言的路径。这一步的逻辑实现在 harper-core/tests/snapshot.rs 的try_get_dialect_override函数中fn try_get_dialect_override(path: Path) - OptionDialect { path.file_stem()? .to_string_lossy() .split(.) .filter_map(Dialect::try_from_abbr) .exactly_one() // If we find multiple overrides, its unlikely that a dialect override is intended. .ok() }其工作流程是取文件名主干不含扩展名按.切分将每一段交给Dialect::try_from_abbr尝试解析为方言只有恰好解析出一个方言缩写时才视为有效覆盖exactly_one保证否则返回None走自动检测。所以Spell.US.md会被切分为Spell与US两段其中US被解析为美式方言覆盖。Dialect::try_from_abbr支持的完整缩写映射定义在 dict_word_metadata.rs缩写方言位掩码值USAmerican美式1 0CACanadian加拿大1 1AUAustralian澳大利亚1 2GBBritish英式1 3INIndian印度1 4同一文件还提供try_from_bcp47dict_word_metadata.rs将en-US、en-GB这类 BCP-47 语言标签转换为对应的Dialect。由此可以推断按同样约定在 tests/text 目录下新建Spell.GB.md即可生成以英式方言为基准的同类快照测试这一约定在run_tests.rs的测试用例命名如yogurt_british_clean.md、issue_2054.md使用Dialect::British中也有体现。覆盖 vs 自动检测的完整链路快照测试的入口在 harper-core/tests/linters.rs#[test] fn test_most_lints() { snapshot::snapshot_all_text_files(linters, .snap.yml, |source, dialect_override| { let dict FstDictionary::curated(); let document Document::new_markdown_default(source, dict); let mut linter LintGroup::new_curated( dict, dialect_override.unwrap_or_else(|| { Dialect::try_guess_from_document(document).unwrap_or(Dialect::American) }), ); // ... }); }优先级链条清晰可见手动覆盖优先dialect_override即从.US.等文件名解析出的方言非空时直接使用自动检测兜底无覆盖时调用Dialect::try_guess_from_document从文档内容推断方言推断失败再回退到Dialect::American。自动检测的实现同样值得展开DialectFlags::get_most_used_dialects_from_documentdict_word_metadata.rs遍历文档中的每个单词对五种方言分别计数——只要某词的dialects标志启用该方言is_dialect_enabled就为该方言 1最后取计数最高的一种若并列最高则全部启用此时TryFromDialectFlags for Dialect会因多于一位生效而返回Err。这里有一个重要的语义细节DialectFlags::is_dialect_enableddict_word_metadata.rs在标志为空即词典未给该词标注任何方言时返回true与源码注释一致——空标志隐含所有方言通用。因此像analyse/VdSGr!_₹这样带!英式标注的词在美式方言下不启用而没有任何标注的普通词在任意方言下都算正确。三、为什么需要这份语料方言是拼写正确性的前提Spell.US.md 的存在本质上是为了约束一个核心设计原则Harper 的拼写正确是方言相关的。同样的拼写在英式英语中正确、在美式英语中就要报错并给出美式建议。这一点在拼写检查器SpellCheck的实现中有充分体现。SpellCheck 的结构体持有一个dialect: Dialect字段构造函数SpellCheck::new(dictionary, dialect)显式接收方言参数。在实际 lint 过程中spell_check.rs对每个单词先通过词元元数据的dialects.is_dialect_enabled(self.dialect)判断该词在当前方言下是否合法若合法且词典能精确命中含小写归一化后的命中直接跳过否则视为拼写错误进入模糊匹配建议流程。这意味着同一段文本在不同方言配置下会得到不同的检查结果。源码测试提供了最直观的印证spell_check.rsamerican_color_in_british_dialect在英式方言下检查Do you like the color?期望产生 1 条 lint美式color在英式下被判错canadian_words_in_australian_dialect在澳式方言下检查Does your mom like yogourt?期望 2 条mom与yogourt在澳式下被判错australian_verandah_in_american_dialectverandah在澳式下合法0 条在美式、英式、加式下各产生 1 条 lint。而 Spell.US.md 的 15 个词正是把这种方言差异浓缩成最小可验证集合全部在美式方言下报错且建议必须指向正确的美式拼写。生成出的快照文件 harper-core/tests/text/linters/Spell.US.snap.yml 中可见形如Did you mean to spellAfterwardsthis way?的输出正是该文件作用的结果。四、拼写建议从何而来FST 词典 Levenshtein 自动机Spell.US.md 中每个词都期望被报错并给出建议而建议的产生依赖 Harper 的模糊词典查找管线。这一管线的核心是FstDictionaryfst_dictionary.rs一种基于有限状态转移器FST的不可变词典其设计要点包括结构化存储词表排序去重后写入fst::MapBuilder每个词映射到WordId同一份数据还备份在MutableDictionary中用于精确查找与元数据读取fst_dictionary.rsLevenshtein 自动机用levenshtein_automata构建 DFA 做模糊检索默认期望编辑距离为 3、且置换transposition如 recieve/receive 式的两字母换位按距离 1 计const EXPECTED_DISTANCE: u8 3; const TRANSPOSITION_COST_ONE: bool true;线程本地缓存构建器不同编辑距离的 DFA 构建器按距离缓存避免重复构建的高昂开销fst_dictionary.rs大小写双路检索查询时若原文不是小写会额外构建小写 DFA 再合并结果取每个候选词的最小距离fst_dictionary.rs。拼写建议的入口函数是suggest_correct_spellingharper-core/src/spell/mod.rs调用词典的fuzzy_match得到候选及编辑距离再交给order_suggestions按score_suggestion打分排序。SpellCheck在实际运行时还做了一层距离退避uncached_suggest_correct_spellingspell_check.rs实为 spell_check.rs从编辑距离 2 开始递增到 4逐级扩大模糊匹配范围直到找到建议为止找到后还需经过方言过滤——仅保留is_dialect_enabled(self.dialect)为真的候选这正是 Spell.US.md 场景的关键并截取前MAX_SUGGESTIONS 3条。此外spell_check.rs 用容量 10000 的 LRU 缓存保存建议结果避免重复计算。五、方言差异的加分项专门化的拼写差异探测器通用编辑距离无法解释为何colour与color会被优先互推。为此harper-core/src/spell/mod.rs 定义了一组方言差异探测器专门识别仅因方言拼写惯例不同而相差一个字符的词对并在score_suggestion中为命中者大幅降分分数越低排名越靠前探测器函数典型词对降分幅度-ou- / -o-is_ou_misspellingcolor / colour编辑距离为 1 且命中时 −6-s-/-z-、-s-/-c-、-k-/-c-is_cksz_misspellingrealize / realise、defense / defence、skepticism / scepticism同上 −6-er / -reis_er_misspellingmeter / metre编辑距离 ≤ 2 时 −15-ll- / -l-is_ll_misspellingtraveler / traveller编辑距离为 1 时 −6-ay / -eyis_ay_ey_misspellinggray / grey编辑距离为 1 时 −6-ei / -ieis_ei_ie_misspellingreceived / recieved编辑距离 ≤ 2 时 −11th 缺失is_th_h_missingsomething / somthing恒 −6对照 Spell.US.md 的词表可以发现几乎每个词都能映射到对应探测器Centre/Theatre→is_er_misspellingLabelled/Quarrelled/Quarrelling→is_ll_misspellingFlavour/Favoured/Honour/Clamour/Neighbour→is_ou_misspellingGrey→is_ay_ey_misspellingRecognised/Analyse→is_cksz_misspelling。换言之这份词表实际在系统化地覆盖探测器矩阵确保每类方言差异都能被正确识别并推荐出美式拼写。score_suggestionharper-core/src/spell/mod.rs的完整打分规则还包含首字母相同 −10、复数词尾s相同 −5、仅差撇号 −8、常见词 −4、缩写建议 −5、双词都无元音 10惩罚等最终按总分排序输出建议列表。六、词典里的方言标注从 annotations.json 到 dictionary.dictSpell.US.md 的词之所以在美式方言下报错根源在于内置词典对词条的方言标注。Harper 的词典使用一种带注释符的压缩格式单词后紧跟/加一长串属性字符其中方言标注定义在 harper-core/annotations.json标注字符含义对应方言American property美式AMERICAN!GB property英式BRITISHCA property加式注释自嘲 at symbol resembles an a inside a CCANADIAN_AU property注释 down underAUSTRALIAN₹IN property印度INDIAN这些标注以propagate: true传播到整个词族并最终写入DictWordMetadata.dialects字段。在 dictionary.dict 中可找到词表中各词的实条colour/~NwSJVGdrE!_₹ colour 带英/加/澳/印标注独缺美式 color/~NwSJVGdrE color 带美式标注 theatre/NwSg!_₹ theatre 英/加/澳/印 theater/~NwSg theater 美式 analyse/VdSGr!_₹ analyse 英/加/澳/印 analyze/~VdSGr analyze 美式 recognise/VdSGB!_₹ recognise 英式 recognize/~VdSGB recognize 美式 labelled/JVtTUr!_₹ labelled 英/加/澳/印 quarrelled/VtT!_₹ quarrelled 英式 quarrelling/V6Nm!_₹ quarrelling 英式 grey/J^pVdGSNwg!_₹ grey 英/加/澳/印可见词表中每个英式词条都带有英式!标注而不包含美式标注于是is_dialect_enabled(Dialect::American)返回 false触发拼写报错。词条的dict_word_metadata.rs侧则定义了DialectFlags位标志dict_word_metadata.rs用u8承载五位方言位并通过is_dialect_enabled/is_dialect_enabled_strict两种语义区分未标注即全方言合法与严格启用。七、如何验证与运行这套测试Spell.US.md 本身是测试输入它的验证产物是两份快照lint 快照harper-core/tests/text/linters/Spell.US.snap.yml逐行记录每个词被报出的 lint 种类Spelling、优先级与建议文本词性标注快照harper-core/tests/text/tagged/Spell.US.md记录分词与词性标注结果其中Afterwards、Recognised等词在美式方言覆盖下也被正常分词标注。快照对比逻辑在 harper-core/tests/snapshot.rs 的tag_file中先读取源文件并统一换行符为\n解析方言覆盖调用create_snapshot生成快照字符串再与磁盘上的既有快照比对——不一致或缺失时重写快照并返回错误从而使测试失败起到防止行为回归的作用。在仓库根目录运行cargo test -p harper-core即可执行全部快照测试包括test_most_lints与词性标注测试。若你修改了内置词典或打分规则导致行为变化快照测试会提示 mismatch届时可删除对应.snap.yml重新生成快照以更新期望输出这是测试夹具的标准维护方式不属于对源码逻辑的改动。八、总结一份小语料背后的方言检查设计全景从 15 个单词的 Spell.US.md 出发可以完整还原 Harper 方言感知拼写检查的设计链条测试约定文件名内嵌.US./.GB.等缩写由 snapshot.rs 的try_get_dialect_override解析为方言覆盖优先于Dialect::try_guess_from_document的自动检测方言模型dict_word_metadata.rs 定义Dialect枚举与DialectFlags位标志支持 US/CA/AU/GB/IN 五种方言及 BCP-47 语言标签空标志隐含全方言合法词典标注annotations.json 定义、!、、_、₹五个方言属性字符写入 dictionary.dict 的词条检查与建议spell_check.rs 的SpellChecklinter 按当前方言过滤合法词fst_dictionary.rs 的 FST Levenshtein 自动机做模糊查找spell/mod.rs 的系列方言差异探测器ou/o、er/re、ll/l、ay/ey、cksz、ei/ie确保方言变体建议被优先排序回归保障快照测试将每次行为固化任何词典或算法改动若影响方言判断都会在 diff 中暴露。对于想要为 Harper 贡献方言相关能力的开发者这套体系给出了清晰的扩展路径在词表中添加带方言标注的词条 → 在 tests/text 下按.XX.命名约定新建语料 → 运行快照测试生成基线 → 检查 lint 与 tagged 两份快照是否符合预期。一份看似简单的单词清单实则是整个方言检查机制的最小回归测试集。【免费下载链接】harperOffline, privacy-first grammar checker. Fast, open-source, Rust-powered项目地址: https://gitcode.com/GitHub_Trending/har/harper创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表