无须联网的多平台开源输入法框架:中州韵输入法引擎,小众而深度

本文最后更新于 2024年4月13日 下午

输入法作为人与设备的重要交互形式,直接影响着人们的数字生活。同时,输入法普遍需要连接网络,以便在云端词库中检索候选词并计算用户的喜好,但也不可避免地导致个人隐私的泄露。

也许有些人会认为,个人隐私已经在互联网上形同“裸奔”,再多泄露一下又如何?尤其是大数据当道,可能当你刚刚在搜索引擎上搜索养猫指南,下一秒电商平台可能就推荐猫粮给你。

好像挺智能的?
但是,如果还包括广告呢?之前百度输入法就在灰度测试(后来被取消,哈哈):

输入 “ 招商 ” 两字之后,联想词里出现广告

哈哈,有一说一,这个很“百度”。本以为百度会是国内的Google,但是现在看,举例Google还是挺远。

所以,这里给愿意折腾的小伙伴推荐:Rime 输入法引擎。

基于rime输入法引擎开发的rime输入法客户端,对于爱折腾、有个性化输入法的人来说,可以是神器;当然,对于不爱折腾的人来说,或许就是噩梦😈。

PS: 你可以直接查看并使用基于rime输入法引擎的输入配置: 薄荷输入法。

中州韵输入法引擎

中州韵输入法引擎/ Rime Input Method Engine,取意历史上通行的中州韵,愿写就一部汇集音韵学智慧的输入法经典之作的意思。笔者我一般喜欢称作: Rime 输入法引擎。

Rime

为什么是输入法引擎呢? 其实输入法的典型工作流程大致如下:

  • 获取和解释按键动作,每个按键包含键值、按键状态等信息。
  • 生成和分析按键序列,形成编码串。有时某些按键并不直接产生编码字符,有时组成输入串的文字不是按键所对应的字符本身。
  • 查字典,获取输入码对应的同码词列表,并进行合并和排序等操作。
  • 根据需要进行进一步的词组和句子构建。
  • 可能需要对结果进行预处理修改,如繁简转换等。
  • 完成从输入码到文字的翻译,得到一组候选文字,这些文字将在输入法界面上展示。
  • 用户确认后,文字显示在屏幕上,完成一次输入。

薄荷输入法(Rime配置模板)的输入效果

将这个过程中纯粹的逻辑部分用程序编写出来,就是输入法引擎。其中不包括:

  • 实现编码到文字转换的字典数据(字典、OpenCC 等),也称为”码表“。
  • 与操作系统、设备和输入目标程序进行交互的组件(客户端界面UI)
  • 展示输入法信息的界面(输入法候选样式)。
  • 配置工具,例如自定义快捷键、切换输入模式、选择字体大小等(配置输入法的UI界面)

所以,其实 rime 输入法引擎,本质就是输入法的核心,类似于汽车引擎里的发动机: 汽车动力的核心,但一辆汽车整体的用户体验,和它的关系不大。

所以?

Rime 输入法引擎的核心,使用C++编写,源代码是:librime(Github)

基于输入法的核心,实现客户端UI等功能产生的发行版本客户端:

  • 鼠须管/Squirrel: macOS上的 rime 客户端;
  • 小狼毫/Weasel: Windows上的 rime 客户端;
  • 小企鹅输入法/Fcitx5 For Android: Android上的Fcitx5输入法框架,其 rime 插件可以实现 rime 客户端;
  • 同文输入法/Trime: Android上的 rime 客户端,也是意难平的一个客户端,新手不建议使用同文入门;
  • 仓输入法/Hamster: iOS上的 rime 客户端;
  • iBus、Fcitx5: Linux上的输入法框架,均有相关的 rime 插件实现 rime 客户端效果。

可以看到,除去 Switch、Play Station 等平台无法适配,其实基本已经覆盖到所有主流平台。你可以在你日常使用的设备上,都使用同一个输入法引擎框架的派生产品。

客户端皮肤
最后,配合用户自己配置的词典和相关配置文件,就是完整的输入法了。

那么,为什么不温不火呢?

为什么呢?

其实…… 就是这个用户配置上……

配置概要

上文已经提及了,它是一个输入法的引擎。 这个引擎如何解析配置,达到最后的输入上屏(文字输出)效果呢?答案是: 解析YAML(YAML Ain’t a Markup Language)配置。

YAML的配置,是十分高效的、扩展性很高的配置语言、文本,它实际就是一个清单,供程序读取。

举个例子: 如果把平时通勤比作程序,那么通勤使用的交通工具抽象为YAML配置,就可以是:

1
2
3
4
# 通勤配置
# bus: 公车 / brt: 快速工具 / car: 私家车
# airplane: 飞机
Commute: airplane

当然,前提是程序,也就是你的大脑可以识别这个清单。 哈哈😄

换作 rime ,引擎内就会读取 YAML 配置,读取特定内容,编译出输入法内容程序。比如: 你可以设定每个按键的输入、在中文模式下,输入/可以选择/÷

甚至可以配合正则,实现特定的效果: 默认情况下,句号是会直接上屏的,但是我们输入网址的过程中,希望句号组合为网址的一部分,而不是把第一候选项上屏,在输入字母后输入句号,就可以使用正则:

1
2
3
4
5
6
recognizer:
# 映入默认内容
import_preset: default
patterns:
# 正则处理
url: "^[a-z]+[.].+$"

recognizer配置是rime配置引擎内的一个配置项,更多的配置项,可以参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# luna_pinyin.schema.yaml
# ...

engine: # 输入引擎设定,即挂接组件的「处方」
processors: # 一、这批组件处理各类按键消息
- ascii_composer # ※ 处理西文模式及中西文切换
- recognizer # ※ 与 matcher 搭配,处理符合特定规则的输入码,如网址、反查等
- key_binder # ※ 在特定条件下将按键绑定到其他按键,如重定义逗号、句号爲候选翻页键
- speller # ※ 拼写处理器,接受字符按键,编辑输入码
- punctuator # ※ 句读处理器,将单个字符按键直接映射爲文字符号
- selector # ※ 选字处理器,处理数字选字键、上、下候选定位、换页键
- navigator # ※ 处理输入栏内的光标移动键
- express_editor # ※ 编辑器,处理空格、回车上屏、回退键等
segmentors: # 二、这批组件识别不同内容类型,将输入码分段
- ascii_segmentor # ※ 标识西文段落
- matcher # ※ 标识符合特定规则的段落,如网址、反查等
- abc_segmentor # ※ 标识常规的文字段落
- punct_segmentor # ※ 标识句读段落
- fallback_segmentor # ※ 标识其他未标识段落
translators: # 叁、这批组件翻译特定类型的编码段爲一组候选文字
- echo_translator # ※ 没有其他候选字时,回显输入码
- punct_translator # ※ 转换标点符号
- script_translator # ※ 脚本翻译器,用于拼音等基于音节表的输入方桉
- reverse_lookup_translator # ※ 反查翻译器,用另一种编码方桉查码
filters: # 四、这批组件过滤翻译的结果
- simplifier # ※ 繁简转换
- uniquifier # ※ 过滤重複的候选字,有可能来自繁简转换

举个例子,你想设置参与组合输入法的字母(默认情况下,只有[a-z]的字母参与输入法的内容组合,直接输入[A-Z]是直接上屏)。那么你可以这样设置:

1
2
3
# 拼写设定
speller:
alphabet: zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA

或者,你想扩写方案的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 编码翻译器
translator:
# enable_correction: true # rime自带的按键纠错,适用于手机26键 参考: https://github.com/rime/librime/pull/228
# 字典文件
dictionary: rime_mint # 使用的字典文件
prism: rime_mint_flypy # 多方案共用一个词库时,为避免冲突,需要用 prism 指定一个名字。
spelling_hints: 8 # corrector.lua :为了让错音错字提示的 Lua 同时适配全拼双拼,将拼音显示在 comment 中
always_show_comments: true # corrector.lua :rime 默认在 preedit 等于 comment 时取消显示 comment,这里强制一直显示,供 corrector.lua 做判断用。
preedit_format:
- xform/([nl])v/$1ü/
- xform/([nl])ue/$1üe/
- xform/([jqxy])v/$1u/
initial_quality: 1.2 # 输入时候的权重

如果想重写半角时候和全角时候,特殊符号的内容呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
punctuator:
# 引入默认的配置
import_preset: symbols
# 重写内部部分配置
half_shape:
"#": "#"
"*": "*"
'.' : { commit: }
"`": "`"
"~": "~"
"@": "@"
"=": "="
"/": ["/", "÷",]
'\': "、"
"_" : "──"
"'": {pair: ["「", "」"]}
"[": ["【", "["]
"]": ["】", "]"]
"$": ["¥", "$", "€", "£", "¢", "¤"]
"<": ["《", "〈", "«", "<"]
">": ["》", "〉", "»", ">"]

到这里,你是不是还有点晕了? 甚至,有些人可能对YAML格式还是不了解,无法理解什么时候应该空格,什么时候应该 Tab 。尽管YAML并非复杂的编程语言,但由于 rime 其配置项繁多且深度细致,对于普通用户而言,理解和掌握所有配置细节可能会是一项颇具挑战性的任务。

晕了😵

Rime 作为一个输入法框架,用户可以通过定制词库、修改engine内的配置项,达到多语种的输入。除了一些你能想到的,比如:韩语、俄罗斯语;还可以实现意想不到的闽南语、南京话、上海话等输入:

开源社区基于rime开发的方言(部分)

感兴趣可以看看这个仓库: awesome-rime

这里推荐参考内容:

推荐新用户可以使用开源的配置模板进行rime的初始化,比如上面的薄荷输入法(一套 rime 开发模板,嘿嘿,作者碰巧就是我)、雾凇拼音(薄荷大量参考这个哦)。

薄荷输入法样式

多设备同步

相信大家一定有疑问,既然不能联网。是否有动态调配词库、多设备同步功能呢?

动态调配词库,当然是有的;至于多设备同步,有点复杂。门槛有点高。

Rime 客户端配置目录下的installation.yaml文件会在第一次部署后会自动生成;在这里可以编辑当前设备的ID和同步目录,如:

1
2
3
4
5
6
7
8
distribution_code_name: Squirrel
distribution_name: "鼠鬚管"
distribution_version: 0.16.2
install_time: "Tue Aug 1 00:28:37 2023"
# 本机的 ID 标志,默认是一串 UUID
# 你可以自定义名字,方便生成的备份文件更优雅
installation_id: "c5f45f7e-3c1c-4257-8ff7-bce78e9b5fb5"
rime_version: 1.8.5

你可以追加一个sync_dir配置:

1
2
3
4
5
6
7
8
9
10
distribution_code_name: Squirrel
distribution_name: "鼠鬚管"
distribution_version: 0.16.2
install_time: "Tue Aug 1 00:28:37 2023"
# 本机的 ID 标志,默认是一串 UUID
# 你可以自定义名字,方便生成的备份文件更优雅
installation_id: "Macbook-M2Max"
# 不设置,默认是当前配置目录下的 `sync/`
sync_dir: "/Users/mintimate/Documents/rimeSync"
rime_version: 1.8.5

配置同步目录

将所有平台的sync_dir设定为同一个目录,比如: iCloud、Dropbox、OneDrive的目录。

1
2
3
4
5
6
7
sync
├── Hamster
│ ├── luna.userdb.txt
│ └── rime_mint.userdb.txt
└── MacbookPro-M2Max
├── luna.userdb.txt
└── rime_mint.userdb.txt

这个时候,再次同步,那么会把HamsterMacbookPro-M2Max的内部用户数据进行同步合并。差异化增量更新后的结果,就会同步到sysnc内。

强大的Lua扩展

如果读者们有从事运维的小伙伴,可能对 Lua 很亲切。Lua 的设计目标是作为一种嵌入式脚本语言,提供简单、高效、可扩展的脚本编程能力,很多 Nginx 的插件、NeoVim 的扩展,都可以使用 Lua 进行实现。

Lua 提供了 C API、嵌入式解释器和数据交换功能,Rime 核心 librime ,作为 C++ 项目可以轻松集成 Lua 。配合 Lua ,可以进一步扩展输入法的功能。比如:人民币的大写转换、中国农历转换等。

人民币大写输入

中国农历转换

但是…… 这也是门槛最高的地方了。如果说上述的词库,可能还可以无编程入门,那么Lua部分,确实需要你有一定的编程功底。而且,在需要编程功底的同时,你还需要知道 rime 预留了那些接口,可以去自定义。

也就是,在懂 Lua 语法的情况下,还需要查阅 librime 的源码~~

高扩展,双刃剑

或许有些人看到这里,还是无法理解如何配置 rime ,但是一定已经了解到 rime 的高扩展。其复杂程度,可以比肩现在的任何大厂输入法。
Rime 每个地方都可以配置, 这无疑是把“双刃剑”。我认为,有两个最大的问题:

  • 无法形成可视化配置 UI : 虽然我认为输入法工具,UI 其实不是很重要;但是 rime 没有配置UI,无疑加剧了新用户的入门门槛。当是如此宏大的配置,是无法使用 UI 实现的
  • 社区教程资源强大,但教程分散: 其实这一点也可以把原因归为第一点,虽然配置项那么多,但是强大的开源社区,有大量 rime 的教程填补其上。可惜的是,大部分人是不愿意折腾的,在“快餐时代”下,很难有人愿意花时间研究输入法的配置

Rime的扩展性实在太高了, 设置你调整客户端的输入样式、外观,都需要使用 YAML 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mint_light_green:
name: "碧皓青/Mint Light Green"
author: Mintimate <"Mintimate's Blog">
translucency: true # 磨砂: false | true
mutual_exclusive: false # 色不叠加: false | true
candidate_list_layout: stacked
text_orientation: horizontal
color_space: srgb
back_color: 0xEFEFEF # 底色
candidate_text_color: 0x323232 # 文字颜色
comment_text_color: 0x878787 # 注颜色
label_color: 0x323232 # 序号颜色
hilited_candidate_back_color: 0x7BAE4F # 选中底色
hilited_candidate_text_color: 0xFFFFFF # 选中文字颜色
hilited_comment_text_color: 0xDFF0EE # 选中注颜色
hilited_candidate_label_color: 0xEFEFEF # 选中序号颜色
text_color: 0x7BAE4F # 拼音颜色 (inline_preedit: false)
hilited_text_color: 0xed9564 # 选中拼音颜色 (inline_preedit: false)

当然,外观定制涉及的配置比较少,还可以使用图形化配置并“代码生成”:

代码生成器

如果是为了调整输入方式,你可以按自己的喜好微调输入法,定制功能。比如:使用反查拆字功能:

Rime内实现反查拆字功能

或者特定符号的输出(比如我就很喜欢这个分数输出):

分数输出

那么可以调整的内容过多,图形化 UI 就无法实现这么精确的内容了。不过,其实 rime 本身的配置不难,毕竟大部分都是配置。

总归一句话: rime扩展性极高,以至于让一般用户难以上手,适合喜好折腾的人;即使你不会编程,也可以入门,但是一定需要有耐心,开拓输入法可能性的边界。

吃瓜

快速配置

最后,如果你对 rime 感兴趣,并且喜欢折腾。可以先试着使用薄荷输入法配置,作为初始化的模板,之后配合网上的教程指南,进行客制化操作。尤其是雾凇的指南和薄荷输入法的文档哦

薄荷输入法文档

举个例子,如果你想在 Windows 上基于薄荷输入法快速配置全拼输入法(薄荷输入法内包含: 小鹤双拼、全拼和五笔),那么只需要在安装小狼毫后,下载薄荷输入法的配置并解压小狼毫配置目录内:

Rime 使用薄荷配置

之后重新部署,即可使用薄荷输入法的功能(其实与其说薄荷输入法,其实是薄荷rime配置比较好…… 但是还是薄荷输入法顺口一些~)。

薄荷输入法配置生效

有机会,下次给大家介绍一下薄荷输入法吧~~

薄荷输入法 GitHub 地址

支持创作

书写文章不易,如果热心的小伙伴,想支持创作,可以加入我们的「爱发电」电圈(还可以解锁远程协助、好友位😃):

当然,也欢迎在B站或YouTube上关注我们:

更多:



无须联网的多平台开源输入法框架:中州韵输入法引擎,小众而深度
https://www.mintimate.cn/2024/04/13/GuideToRime/
作者
Mintimate
发布于
2024年4月13日
许可协议