修改小狼毫注音輸入法的繁體用字並刪減生僻字以精簡字庫

修改小狼毫注音輸入法的繁體用字並刪減生僻字以精簡字庫

我使用小狼毫輸入法(即中州韻輸入法引擎,英文Rime,在蘋果電腦系統中稱鼠鬚管,因視窗作業系統是最常用的作業系統,故下文以運行在其上的小狼毫之名稱之)中的注音輸入方案已有多年,它已經成為了我不可或缺的一個工具。如果沒有小狼毫輸入法,我現在在電腦上就無法打字了,因為我對它進行了很大程度的客製化,我已經無法適應其他輸入法的輸入習慣。既然是我唯一使用的電腦輸入法,那麼我覺得我應該把它變得更加好用。小狼毫輸入法固然是存在不少問題的,有些問題在之前因為影響不是很大,所以我就沒有去修正干預它。但是現在為了使它更加完美,為了提高我的打字體驗,為了讓我使用起來更加得心應手,我決定動手去修正。而目前讓我在意的有兩個問題,第一個問題是小狼毫的默認繁體字用字不合我意,例如在繁體模式下它輸出的繁體字是「羣、峯」,而我更加習慣用「群、峰」這些字。這裡只是舉例,後文我會全部列出我不喜歡的字以及我偏好用的字。第二個問題是它的字庫裡面有很多生僻字,導致在打字的過程中這些生僻字因為重碼影響選字,也不美觀,更何況我是一個強迫症。

修改繁體用字

問題的產生

小狼毫的源字庫使用的是繁體字,其用意是盡量確保簡繁轉換的準確性,畢竟如果使用簡體字字庫,會存在一簡對多繁的情況,導致用程式轉成繁體字時可能會出錯。而現行繁體字雖然也存在一繁對多簡的情況,不過經過一些技術調整之後可以避免,提高機器轉換的準確度。而這裡所說的技術調整,就是指小狼毫輸入法採用了OpenCC這個中文簡繁轉換工具,此工具為了確保簡繁轉換的準確性,奉行「能分則不合」的原則,把字義不同的字區分開來。當然這裡的能分則不合並不是「發、髮」之類的老生常談,畢竟此例是屬於「必分」而非「能分」。而真正的例子是「吃」字,可組詞為「吃飯」和「口吃」,前者在台港澳這些使用繁體字的地區都是如此寫,也就是說現在的用字並不區分。而OpenCC便作了區分,分別寫作「喫飯」和「口吃」。從面向程式員的源始碼角度上來看,這樣的區分做得非常好,但是對於面向使用者來說,則不合我意,畢竟使用這樣一個罕用字可能會造成讀者的疑惑與不解。而就我自己而言,我個人亦不喜歡這個「喫」字,這個字在我的用法中,是更偏向於潮州話表「撕咬」之義的koi3,如「喫鵝腳」。除此之外,還有一些字的選取不是因為能分則不合造成的,而是追尋字理造成的。例如上面提到的「羣、峯」二字,現行台灣繁體字寫成「群、峰」,不過香港確實寫成「峯」。OpenCC之所以將此二字定為上下結構的寫法而非常用的左右結構的寫法,是因為小篆時期便是如此的上下結構。但很明顯如此不美觀的寫法是不合我意的,所以我決定改掉。

嘗試廢案

以上提到的問題要怎麼去解決呢?其中一個嘗試便是在小狼毫的配置中調用OpenCC的「繁體轉台灣」功能,即t2tw.json這個配置檔。但是台灣標註的繁體字有一個致命的問題,就是它「着、著」不分,這是我不能接受的。說句題外話,這個「着、著」甚至影響到了Google注音輸入法乃至其繼承者Gboard的簡體輸入功能,使其在簡體模式下無法輸入「著名」等詞,會變成「着名」。不過Google注音輸入法的簡體輸入功能的錯誤不止這一點,這裡就不過多拓展了。除了「着、著」不分的用字習慣問題之外,還有一個問題就是如果要啓用繁體轉台灣功能,在小狼毫裡面是要進行一個選單操作的,無法像原生的簡繁轉換那樣做成布爾值切換,並綁定到快捷鍵上,所以操作起來很不方便,特別是向我有頻繁切換簡繁體需求的更加不方便。

最終解決方法

所以這個方法只能作罷,那只能去修改小狼毫注音輸入法裡面的字庫檔案了,從原始碼的層面去解決這個問題。其實我一開始是覺得修改字庫的做法是下策,應該能避則避,但是恰好我的第二個需求——刪除生僻字精簡字庫也是不得不修改字庫的,所以便一起做了。字庫的修改分為多個步驟,如果遺漏了一些步驟,可能會導致打不出想要的字。首先,我嘗試歸納了我的繁體字使用偏好,其中大部分是偏好於台灣用字,然後有部分字則有我自己的偏好,非港台現行用字。不過我的歸納是現場回想寫出來的,考慮上肯定是有遺漏的,遺漏的部分只能通過後期打字實作中發現,然後再跟進補充。首先是我不滿意OpenCC為了符合字理所選取的一些不美觀的字,這些字可以直接等價替換,我目前所想到的有這些,左側列表是OpenCC所選取的符合字理的字,右邊列表是我選取的較為美觀的字,或許有些字本身就是陸港台某一方的標準。

羣	群
牀 床
峯 峰
麪 麵
爲 為
僞 偽
裏 裡
竈 灶
衆 眾

其次有些字因為字義不同而分開,但出於美觀考慮,我偏好合併。

喫	吃
纔 才

還有一些字我喜歡用使用人數較少的異體字,例如地名「台灣」我偏好用俗字「台」而非正字「臺」,因為俗字「台」的筆畵簡單,辨識度高,且作為地名與「高臺」的「臺」沒有直接聯繫。「戰鬪」我偏好用「鬪」而不是台港澳通行的「鬥」,因為容易與「門」混淆,所以我最終選擇了日本與韓國常用的「鬪」。起初想用筆畵較為簡單的「鬦」,但是發現實際使用的人太少,所以就選了有日本韓國背書的「鬪」。此外還有我選用「畵」去替代「畫」,因為前者辨識度稍高一點,能與「書、晝」區分,且韓語輸入法默認使用前者,定前者為正字,儘管韓國的《漢文教育用基礎漢字》選用了後者。

鬥	鬪
畫 畵
臺灣 台灣
臺北 台北
臺中 台中
臺南 台南
港臺 港台
港澳臺 港澳台
臺港澳 台港澳

確定了這些之後便可以着手修改詞庫,涉及的詞庫不止一個。分別有注音方案所用的地球拼音詞庫母表terra_pinyin.dict.yaml,預設的詞頻詞庫八股文essay.txt,以及我自己新增的一些擴充詞庫,如霧凇拼音的基礎詞庫base.dict.yaml等。修改的方法不算複雜,使用Sublime Text編輯器中的正規表示式對詞組進行手動查找替換即可,工作量不算大。比較需要注意的是八股文裡面的單字字頻也要隨着調整,例如說我取「羣」棄「群」,那麼就要記得把這兩個字的字頻數值交換一下。其他不帶輸入碼也不帶詞頻的詞庫編輯起來就非常簡單。

刪減生僻字以精簡字庫

問題的產生與嘗試廢案

小狼毫的注音輸入法採用的是地球拼音的碼表,此碼表收錄了多達47000多個漢字,要知道萬國碼中的中日韓統一表意文字基本區也才20992個漢字,可見裡面包含了很多罕用的生僻字。注音輸入法作為音碼輸入法,同音字的重碼數量是非常多的,這些生僻字的存在會增大重碼數量,儘管有了八股文字頻的干預排序,但是候選欄裡面出現那麼多生僻字還是有點影響美觀。而小狼毫官方本來是有提供字符集過濾的功能,其一曰cjk_minifier,此基於extended_charset,本來僅可用於形碼,後遷移適配至音碼,但不管如何此功能在現版本中已完全失效,不可使用;其二曰charset_filter,缺點是像繪文字之類的一些符號並不包含在GBK中,甚至如果啓用GB2312還打不出破折號,聽說在新版本的小狼毫中也失效了,故也不推薦;其三曰charset.lua,通過Lua去過濾。可惜我對Lua一竅不通,不過摸索了一下知道了啓用的方法。首先就是在用戶資料夾中新建一個lua/資料夾,把剛剛的charset.lua丟進去,當然可以先修改刪減裡面的規則。其次再在用戶資料夾中新建一個名為rime.lua的檔案去調用,內書:

local charset = require("charset")
charset_filter = charset.filter

最後在輸入方案的檔案中打補丁啓用:

patch:
engine/filters:
# 此處略去其他項目
- lua_filter@charset_filter

此舉是最值得推薦的,Lua有極高的自由度,但美中不足的是,提供的這個Lua代碼功能較少,自由度不高。例如說有些使用者可能想要設立一個黑名單字表或者白名單字表,如果懂Lua,就可以實現,但是我不懂Lua,所以只能放棄。畢竟作為強迫症,CJK基本區的字對我來說還是太多,裡面有很多我不認識的字,那我自然也用不上這些我不認識的字,所以我需要進一步的精簡。所以最後留給我的唯一解決方法就是直接去編輯詞庫。

最終解決思路

刪減生僻字的前提是要先明確哪些字對我來說是生僻字,或者更實際的思路是哪些字對我來說不是生僻字,即要有一個白名單。我首先想到的是《通用漢字規範表》,不過說實話這種官方的表經常有一個問題,就是它的呈現形式對電腦不友好,它是pdf格式的,且沒有提供txt之類的純文本格式,韓國的一些這種文件也存在類似的問題。不過好在GitHub上已經有熱心人士復刻了一字一行的純文字版。這個字表是中華人民共和國教育部、國家語言文字工作委員會於2013年頒佈的,收錄8105字,並取代了之前具有同等職能的1988年頒佈的《現代漢語通用字表(7000字)與《現代漢語常用字表(3500字)。《通用漢字規範表》分為三級,具體情況原文如下:

二、本表收字8105個,分為三級:一級字表為常用字集,收字3500個,主要滿足基礎教育和文化普及的基本用字需要。二級字表收字3000個,使用度僅次於一級字。一、二級字表合計6500字,主要滿足出版印刷、辭書編纂和信息處理等方面的一般用字需要。三級字表收字1605個,是姓氏人名、地名、科學技術術語和中小學語文教材文言文用字中未進入一、二級字表的較通用的字,主要滿足信息化時代與大眾生活密切相關的專門領域的用字需要。

根據此說明,似乎是第一級與第二級字表的6500字就已經夠用了,但事實上並非如此。簡單瀏覽第三級字表,便可以在表首發現一些常用字,例如:6501亍、6503彳、6511氕、6513仝、6531吒、6532吖、6546闫、6598冏等等。如果真的以此第一級和第二級字表為白名單,那麼不一定會有很多常用字打不出來,影響正常使用。那如果把整張字表全三級一起作為白名單呢,則字似乎有點多了。因為我發現第三級字表中確實有很多字是我既不認識也日常用不到的,裡面甚至有不少CJK擴充區的字,主要是地名用字,維基文庫給這些字加了黃色底的高亮。而且其實第二級字表裡面也有一些字我是完全不認識的。

所以靠這個《通用漢字規範表》似乎行不通了,或許這個表的常用與否,是由日常是否常用所定義的,而非計算機上是否常用來定義的。這時候我突然想到了GB2312,這個字符集在過去一段時間內非常流行,但也因為收字較少被部分人所詬病,例如有些字體僅為這個字表裡面的漢字設計,導致一些人名使用了GB2312以外的字就無法正常顯示,甚至在20多年以前會出現工作人員無法錄入或不知道怎麼錄入的情況。所以如今這個字表的實際作用已經式微了,被GBK之類的所取代了,以剛剛的字體為例,一般包含的漢字都是能達到GBK的級別了,有2萬多字。但是讓我靈光一現的是,這樣的一個字符集,它所包含的漢字雖然不多,但是確實一個比較恰當的「子集」,不管是數量(6763字)也好,選字的標準也好,都非常恰當。所以我決定以它為白名單的主體。

但是隨着而來的又有另外一個問題,GB2312收錄的字都是簡體字,但是小狼毫的詞庫是繁體字,所以我需要一個繁體字的字表來做篩選,也就是說我需要一個繁體版的GB2312,而這時後我就想到了GB12345,同樣地官方網站上的字表無法用來程式化操作,所幸GitHub上也已有純文字版本。但是GB12345又存在一個問題,就是裡面缺少一些繁體字,因為兩岸三地的繁體字標準不通,裡面僅包含中國大陸標準的繁體字。舉個例子,像是「灶」的大陸繁體是「竈」,但是台港澳基本上都是用「灶」,而GB12345就缺少了「灶」這個字。當然如果你是使用OpenCC繁體,那這個例子恰好沒有影響,但是如我前文所說,我已經改詞庫為「灶」,所以會有影響。當然有影響的不止這個字,還有其他的一些,這裡就不枚舉了,因為要解決這個問題不需要枚舉。如何補全這些繁體字呢?我的方法就是把GB2312的字用OpenCC轉換成繁體字,當然這裡不是直接用OpenCC這個工具本身去轉換,因為遇到一簡對多繁的情況就只能轉換出來其中一個繁體字而已。所以這裡我用的是OpenCC原始碼中的簡轉繁字表OpenCC/data/dictionary/STCharacters.txt。這個表大概長這個樣子,左簡右繁,簡繁之間以製表符分割,多繁之間以空格分割。

OpenCC/data/dictionary/STCharacters.txt
巨	巨 鉅
巩 鞏
巯 巰
币 幣
布 布 佈
帅 帥
师 師
帏 幃
帐 帳
帘 簾 帘
帜 幟
带 帶
帧 幀
席 席 蓆
帮 幫
帱 幬
帻 幘
帼 幗
幂 冪
干 幹 乾 干
并 並 併
幸 幸 倖
广 廣 广

我不懂Python,所以只能用Excel的VLOOKUP函數處理,走了一些彎路,不過最終還是搞定了。

不過GB2312或GB12345收錄的字還是有所欠缺,所以我下一步是結合其他字表作補充。分別有下面這些表:

具體實操

由於Excel中VLOOKUP函數的侷限性,導致有些操作要分多步完成,一些操作的先後順序也很重要。

第0步:準備好上述提及的字表,字表以一字一行的格式。

第1步:利用OpenCC原始碼中的簡繁對照字表STCharacters.txt,用VLOOKUP把裡面不在GB2312中的字替除,得到一份純繁體字子集表。這份字表裡面的字都是有對應簡體的繁體字,也就是說那些簡繁同形的不在其中。

第2步:把上面得到的純繁體字子集表與GB12345合併去重。去重可以使用Sublime Text的 Edit > Permute Lines > Unique 功能。

第3步:把GB2312中不存在,但在《現代漢語通用字表》與《通用漢字規範表》中存在的字篩選出來,此操作同樣可以用Sublime Text完成。然後再使用OpenCC轉換成繁體字,此處可以直接用OpenCC的試用網站進行轉換而無需使用Excel,因為這些字基本上是較為罕用的字,所以不會出現一簡對多繁的情況。

第4步:把上面得到的字併入母表即可。然後再把台灣的《常用國字標準字體表》與香港的《常用字字形表》併入。由於這兩個表都是繁體,所以省去了簡體轉繁體這一步,比較簡單。

第5步:再手動增加一些表外漢字,例如說一些潮州話方言用字、朝鮮漢字、日語漢字、喃字、康熙部首之類的。我目前的表是這樣的,後期打字的過程中如果發現缺字會繼續補充。

DQ表外字 >folded



























𠀾
𤰉






















第6步:把地球拼音裡面的單字,按照我的子集字表進行篩選刪減。此為最終步驟。

在上面的操作過程中,有一些軟體的操作需要注意。第一要注意的是Excel會自動識別日期、數字,所以把字表搬到Excel中進行處理的時候,要先把單元格格式設置成「文本」,避免說像jun1這種拼音被誤轉換成日期「6月1日」。第二要注意的是Sublime Text對於yaml格式的詞庫檔案,會預設採用空格代替製表符縮進,所以記得取消這個功能,否則會破壞詞庫的格式。

最終我乾脆把最終的詞庫檔案名稱命名為bopomofo.dict.yaml而非原來的地球拼音,目的是與原來的檔案作區分。同時我也會保留原來的檔案,方便以後加字。為了避免有時候偶爾要打出一些罕用字,我本來想另複製一個原版注音方案,但為了避免混淆,就沒有這樣做了,直接用明月拼音方案備用了。畢竟我使用虛擬現實設備的時候打字時,不像實體鍵盤那樣可以靠十指定位案件,而虛擬鍵盤上又沒有注音符號,所以無法使用注音輸入法,只能用拼音輸入法。而這個明月拼音因為我非常少用,所以也沒有過多地去客製它,諸如前文所說的調整繁體用字之類的操作我是沒有做的。


※ Cover image: Rime

Comments