我给 NVDA 写代码之不让屏幕阅读器说“废话”

作为熟练使用屏幕阅读器的视障者,你可能不得不赞同我这个观点:我们无法忍受屏幕阅读器多说一句“废话”。很简单,效率至上,我们希望屏幕阅读器读的每一个字都有其用途。

哪里不够好?

对于 NVDA 来说,有这样两项设置 "Speak typed characters" 和 "Speak typed words",即“朗读输入的字符”(NVDA+2)和“朗读输入的单词”(NVDA+3)。
NVDA 键盘设置面板
很好理解,对于前者,当我们在键盘上键入字符后会读出所键入的字符(如 1、2、3、A、B、C),而对于后者,当我们连续键入一些字符并按下空格后会读出这个字符所组成的单词(如 "world")。这当然没问题,但在一些场景下这种设计显得不够精细,无疑会降低效率。

例如:

在文件管理器的文件列表中,我们可能经常会通过键入文件名首字母的方式将焦点快速定位到相应的文件。此时 "Speak typed characters" 这个选项打开后, NVDA 会先读出所键入的字符,随后才读出实际定位到的文件,例如: F:Files、N:Notepad 在这个场景下,可能更理想的行为是,键入首字母后直接读出所匹配的文件,如: Files、Notepad 等。

在一些 Web 页面,我们可能希望在焦点模式下使用 Web 本身提供的键盘快捷键,例如 Google Chat 或 GMail 的屏幕阅读器导航支持,以及 Bilibili 的播放器控制等。以 Chat 为例,按 h 然后按 c 即可转到私信区域。如果此时按空格键,那么 NVDA 会将 hc 作为单词读出,这是不必要的。

对此,曾经社区里有用户提出:我们是否可以根据场景决定是否让 NVDA 读出字符/单词呢?在以往的设计中当然是不可以的,用户只有两种选择,要么开要么关。太粗暴了啊!

怎么做?

经过我的一些探索,借助 NVDA 的扩展插件机制,该需求的确是可以轻松实现的。所以我开发了一个插件来实施这项改进,简单的 NVDA 插件如下:

https://github.com/cary-rowen/NVDA-CustomSpeakTypedCharacters/

当我在 NVDA 国际社区发布该插件后,收到了一些赞誉,同时有人提醒,在 NVDA 的 GitHub 上已经有人提出过相关的 Issue/Feature request 也已经得到 triage 分别是 #16848、#10331、#3027。

Dalen 的评论
Luke 的评论

恰好,以上插件算是一个原型,我希望通过社区分发以验证思路之可行性,同时 Subscribe 相关的 issue 并表明我愿意向 NVDA Core 贡献这项改进。

说做就做,错过等一年!

因为 NVDA 每年的第一个稳定版是唯一接受 Breaking change 的版本,以上改进牵扯到 API 的变更。基于已有 issue 和相关讨论,在2024年的年末,我在 NVDA 的 GitHub 中提交了 PR#17505,以期将这项改进引入 NVDA Core 从而让更多人受益。

社区反馈良好!开源贡献者的开心瞬间!
Adriani90 的评论
amirmahdifard 的评论
CyrilleB79 的评论
简而言之,这项改进分别在原本的 "Speak typed characters" 和 "Speak typed words" 选项中新增了一种模式 "Only in edit controls"(仅在编辑控件中)。

确切的说,所谓的可编辑控件,在这里定义为:命令行终端、可编辑的文本和文档控件。针对 "Speak typed characters" 此 PR 新增的选项被设为 NVDA 的初始默认设置。

经过一些讨论和 Code review 这项改进已经被合并到了 NVDA2025.1 目前已在 Alpha (开发快照)中可用,
NVDA 键盘设置面板中的新选项
但如果你是普通 NVDA 用户,这里并不推荐你在生产环境中为了尝试该特性升级到 Alpha 版,你可以在当前的稳定版 2024.4.2 中转到“插件商店”安装“输入朗读模式自定义”插件来尝试此改进。

关于代码贡献的一点碎碎念

不是给 NVDA 贡献的第一个 PR 只是 2024 年的最后一个 PR,但这次贡献还是有些不太一样的地方。

Coding style 方面,前段时间 NV Access 放弃了 flake8 转而拥抱 ruff 并且集成了自动化的 Pre-commit auto-fix 来优雅的 fix lintting 让贡献体验好了不少。

Upgrade steps 方面,牵扯到对原有配置项的更改,所以必须编写一些迁移代码来做到这一点,确保不破坏用户的已有设置,如果可能,还要为用户升级设置,以前是不太了解 NVDA 对用户配置的管理机制的。

globalCommands 中实现了一个 toggleIntegerValue 的 Helper function 用于更好的处理类似的多选项切换,后续应该被广泛的复用,或许也值得在未来对 globalCommands 进行一些 Code refactoring 的工作,这个文件中的代码已经超过了5000行,好在都是不太复杂的逻辑。

总的来说不是一项有难度的贡献,然而无论从解决个人需求的角度还是从社区反响的角度来看,都是一项有意义的改进。

OK 聊到这儿,如果这项改进对你有用,求夸夸~

新春快乐!

标签: none

添加新评论