news 2026/9/15 11:52:59

Joplin v1.4 拼写检查器功能全解:从启用、语言切换到源码级实现原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Joplin v1.4 拼写检查器功能全解:从启用、语言切换到源码级实现原理

Joplin v1.4 拼写检查器功能全解:从启用、语言切换到源码级实现原理

【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin

Joplin 是一款以隐私为核心的跨平台笔记应用(支持 Windows、macOS、Linux、Android 与 iOS)。本篇文章围绕 readme/news/20201126-114649.md 所记录的 v1.4 拼写检查器(Spell Checker)发布内容展开,系统讲解该功能的启用方式、两种编辑器(富文本编辑器 TinyMCE 与 Markdown 编辑器 CodeMirror)下的使用差异、语言管理与右键菜单的实战操作,并结合仓库中的SpellCheckerService、原生驱动与设置定义等源码,剖析其底层实现原理。读完本文,你将能熟练配置 Joplin 的拼写检查,并理解"启用开关—语言选择—编辑器联动"整条调用链是如何工作的。

一、背景:为什么拼写检查器是最受期待的功能

拼写检查器是 Joplin 社区投票需求(GitHub issue #275)中获得 340 票的最高呼声功能,于 v1.4 正式落地。根据原公告,这项功能长期难以实现,主要原因是 Joplin 使用了自研的富文本编辑器(Rich Text)与 Markdown 编辑器两套自定义编辑器,而拼写检查必须与编辑器底层输入模型深度耦合;直到 Electron 框架在相关能力上取得进展,加上 Caleb John 对 Markdown 编辑器的改进,才使该功能成为可能。

从源码看,这一"框架依赖"体现在两个层面:

  • 底层拼写引擎由 Electron 提供:桌面端通过packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.ts中的SpellCheckerServiceDriverNative直接调用 Electron session 的内建拼写检查 API(setSpellCheckerLanguagesgetSpellCheckerLanguagesaddWordToSpellCheckerDictionary等),并不自带词典数据。
  • 通用逻辑与编辑器解耦packages/lib/services/spellChecker/SpellCheckerService.ts中的SpellCheckerService定义了语言状态管理、历史记录、右键菜单等通用逻辑,通过抽象驱动基类packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.ts屏蔽平台差异。

也就是说,Joplin 将"拼写检查策略"与"具体实现驱动"分层:SpellCheckerServiceDriverBase声明了availableLanguagessetLanguageslanguageaddWordToSpellCheckerDictionary等接口,而桌面端驱动是 Electron 原生实现;若未来有其他平台(如移动端)接入,只需提供新的驱动即可。

二、启用拼写检查器:地球图标与 Tools 菜单

在 v1.4 中,启用或禁用拼写检查非常简单:

  1. 点击 Joplin 主窗口右上角的地球图标(globe icon);
  2. 或者通过Tools(工具)菜单 → Spell Checker(拼写检查器)打开同一菜单;
  3. 在弹出的菜单中勾选"Use spell checker"复选框即可开启。

菜单底部是"Change language"(更改语言)子菜单,其中列出了操作系统 / Electron 提供的全部可用语言。由于某些操作系统上的语言列表可能非常庞大,Joplin 会把最近选过的语言直接置顶展示在 "Use spell checker" 复选框下方,方便快速切换回常用语言。

从源码可以印证菜单的结构与交互:

  • 命令声明位于 showSpellCheckerMenu.ts,命令名为showSpellCheckerMenu,图标为fas fa-globe——这正是"地球图标"的来源。
  • 菜单项由SpellCheckerService.spellCheckerConfigMenuItems()(见 SpellCheckerService.ts)构建,其结构依次为:Use spell checker复选框(调用toggleEnabled()切换spellChecker.enabled设置)→ 最近选择语言列表(前面带分隔线)→ 分隔线 →Change language子菜单(每个语言一个复选框项,点击调用setLanguage())。

值得一提的是,当拼写检查开启且已选择语言时,工具菜单中的该项标题会动态显示当前语言(例如 "en, fr"),该逻辑由showSpellCheckerMenumapStateToTitle实现——它会读取spellChecker.languages设置,去重语言代码前缀后用逗号拼接。

三、语言选择机制与"最近使用语言"历史

语言是拼写检查的核心配置。Joplin 的语言管理有几个关键行为:

  • 默认语言为en-US:若用户从未设置过语言(spellChecker.languages为空数组),SpellCheckerService.setupDefaultLanguage()会优先尝试使用驱动当前生效的语言;若该语言不在可用列表内,则回退到en-US
  • 多语言可同时启用setLanguage()采用"切换"语义——若某语言已在启用列表中则移除,否则追加,多个语言可以同时勾选。
  • 最近选择历史:每次选择语言都会写入 KvStore 的spellCheckerService.latestSelectedLanguages键;历史上限为 5 条,且已启用(enabled)的语言始终保留在历史中,超过上限时才淘汰已禁用的语言(见 SpellCheckerService.ts 中的addLatestSelectedLanguagelanguagesHistorySizeMax = 5)。

这些行为对应的持久化设置定义在 builtInMetadata.ts:

设置键类型默认值说明
spellChecker.enabledBooltrue拼写检查总开关
spellChecker.languageString''旧版单语言设置,已废弃
spellChecker.languagesArray[]当前启用的语言代码列表(如["en-US","fr"]

其中spellChecker.language已在 Setting.ts 中标记为被spellChecker.languages取代(oldNamenewName迁移映射)。spellChecker.enabled的默认值为true,但由于 Markdown 编辑器存在独立的 Beta 开关(见下文),新用户在 Markdown 编辑器中仍默认不会触发拼写检查。

四、Markdown 编辑器 Beta 拼写检查的独立开关

原公告特别强调:即使勾选了 "Use spell checker",Markdown 编辑器中默认也不会进行拼写检查,因为该编辑器下的功能处于 Beta 状态。原因在于,为了让拼写检查生效,Markdown 编辑器需要使用一种特殊模式(contenteditable),而该模式在过去曾引发过各种问题(如光标位置不稳定、编辑内容偶发不保存或未反映到预览等)。v1.4 中该模式已表现稳定,但官方仍将其标记为 Beta。

启用步骤:

  1. 打开General(常规)设置
  2. 展开Show Advanced Settings(显示高级设置)
  3. 勾选"Enable spell checking in Markdown editor"选项。

对应源码中的设置定义为 builtInMetadata.ts 中的editor.spellcheckBeta

设置键类型默认值适用范围说明
editor.spellcheckBetaBoolfalse仅桌面端(AppType.Desktop)是否在 Markdown 编辑器中启用拼写检查(Beta)

五、源码级原理解析:拼写检查在两种编辑器中如何落地

5.1 原生驱动:Electron Session 层

桌面端的全部拼写能力最终都落在 SpellCheckerServiceDriverNative.ts 上:

  • availableLanguages直接返回session().availableSpellCheckerLanguages(由 Electron/系统提供语言列表);
  • setLanguages()会逐一校验语言:先尝试原语言代码,再尝试只保留语言部分(languageCodeOnly),若仍失败则尝试同语言的其他 locale 变体(localesFromLanguageCode),直到找到一个可被setSpellCheckerLanguages接受的值;全部失败则跳过该语言;
  • 传入空数组即可禁用拼写检查(setSpellCheckerEnabled(effectiveLanguages.length > 0)),这是复用 Electron 官方行为(见代码注释引用的 electron issue #25228);
  • 该驱动还在initialize()中处理了一个 Electron 42 on Linux 的兼容性问题:先以空语言集合初始化一次,否则默认语言会被忽略。

5.2 通用服务:状态同步与右键菜单

SpellCheckerService负责把设置状态同步给驱动:applyStateToDriver()会在启用状态或语言列表变化时调用driver.setLanguages(...)——启用时传入语言列表,禁用时传入空数组,从而让 Electron 层开/关拼写检查。

当用户右键点击拼写错误的单词时,contextMenuItems()(SpellCheckerService.ts)会构建以下菜单项:

  • 分词建议列表(每个建议点击后通过replaceMisspelling命令替换单词);
  • 若无建议则显示灰色不可用的(No suggestions)
  • Add to dictionary(加入词典):调用driver.addWordToSpellCheckerDictionary(),在 Electron 驱动中所有语言共享同一个词典。

5.3 富文本编辑器(TinyMCE):默认即生效

富文本编辑器默认开启浏览器拼写检查:在 TinyMCE.tsx 中设置了browser_spellcheck: true。同时,为了不干扰代码片段,编辑器会对行内代码(inline code)显式禁用拼写检查——将spellcheck属性设为false(见 TinyMCE.tsx 与 TinyMCE.tsx),避免代码被误报为拼写错误。

5.4 Markdown 编辑器(CodeMirror):依赖 Beta 开关

Markdown 编辑器使用 CodeMirror 实现。拼写检查是否生效取决于editor.spellcheckBeta

  • CodeMirror 5 版本中(v5/Editor.tsx):当editor.spellcheckBeta为真时,编辑器采用contenteditable输入模式(这是触发浏览器拼写检查的必要条件),并显式设置spellcheck: true;否则使用textarea模式,浏览器拼写检查不生效。这正是原公告所说的"必须启用特殊模式"。
  • CodeMirror 6 版本中(v6/utils/useEditorSettings.ts):spellcheckEnabled同样直接映射到editor.spellcheckBeta设置,并作为EditorSettings传入编辑器。

可以推断,当前仓库中的 Markdown 编辑器始终保留"默认关闭、需手动开启 Beta"的设计,这是为了避免contenteditable模式可能带来的编辑稳定性问题影响大多数用户。

六、常见问题与使用建议

  • 勾选了 "Use spell checker" 但 Markdown 编辑器中仍无红色波浪线?这是预期行为。请前往 General → Advanced Settings,勾选 "Enable spell checking in Markdown editor" 后再试。
  • 语言列表太长、找不到想要的方言?使用 "Change language" 子菜单搜索,或直接在最近使用列表中选取——系统会记住你最近选择的语言(最多 5 个)。
  • 不想让代码块被检查?富文本编辑器中 Joplin 已自动对行内代码关闭拼写检查;Markdown 编辑器下建议对代码片段使用代码块语法,以减少误报。
  • 关于 Beta 稳定性:原公告提示,Markdown 编辑器下的拼写检查依赖contenteditable特殊模式,虽然当时未发现明显缺陷,但若遇到光标错位、编辑未保存或预览不同步等问题,可在论坛反馈(Help → Joplin Forum)。

七、总结

Joplin v1.4 的拼写检查器是一个典型的"框架能力 + 应用层策略"组合:Electron 原生拼写检查提供了词典与语言数据,SpellCheckerService负责语言状态、历史记录与菜单生成,两套编辑器则各自通过设置项决定是否启用浏览器拼写检查。理解这条调用链后,你不仅能在界面中熟练配置,也能在排查"拼写检查不生效"问题时快速定位是开关未开、语言未选,还是 Markdown 编辑器的 Beta 选项未启用。

【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 11:52:47

AI时代程序员如何破局:从可替代焦虑到超级个体

说实话,这段时间我身边几乎每个做开发的朋友都在聊同一个问题:AI都这么猛了,连代码都能自己写了,咱们程序员还有没有未来?有的开始偷偷刷算法题准备跑路,有的在考虑转行做产品经理,还有的直接躺…

作者头像 李华
网站建设 2026/9/15 11:52:03

流媒体弱网优化:纯NACK重传机制设计与实战

开篇:被弱网按在地上摩擦之后,我开始折腾NACK做流媒体服务三年多,我最怕的不是流量洪峰,也不是编码参数调错,而是用户那边网络明明显示"满格",实际却在疯狂丢包。尤其是做自建流媒体服务时&#…

作者头像 李华
网站建设 2026/9/15 11:49:59

FrankenPHP 安全模型:Go 与 PHP 之间的信任边界解析

FrankenPHP 安全模型:Go 与 PHP 之间的信任边界解析 【免费下载链接】frankenphp 🧟 The modern PHP app server 项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphp 本篇技术指南系统梳理 FrankenPHP 的信任模型(trust mo…

作者头像 李华
网站建设 2026/9/15 11:48:16

Windows虚拟内存分页文件配置指南:解决内存不足与OOM问题

1. 虚拟内存不是“假内存”:分页文件在系统里的真实角色1.1 “内存不足”弹出的那一刻,系统里到底发生了什么我先描述一个场景,如果你正好经历过,就知道我在说什么:一台 16G 内存的 Windows 开发机,开着 Do…

作者头像 李华
网站建设 2026/9/15 11:47:19

vDisk技术结合VOI/IDV架构在考场信息化中的应用

1. 考场网络部署的痛点与挑战考场信息化建设一直是教育行业数字化转型的重点场景。传统PC考场在运维管理上面临着诸多难题:考试软件安装复杂、系统镜像分发困难、终端设备维护成本高、考试环境一致性难以保障。特别是在大规模考试期间,动辄数百台终端需要…

作者头像 李华