Open ztl8702 opened 6 years ago
跨音節拼寫運算的問題的確值得研究。 現在 Rime 沒有支持這項功能,因爲我對這個問題的認識有限,不夠自信能作出足夠通用、能解決一類問題的程序。
變調在漢語方言中普遍存在。輕聲也許可以看作類似性質的問題。 官話等方言的兒化韻(還包括子變韻、合音詞)屬於另一種情況,涉及音節數目的增減。 還有人提到其他語言的,如泰文,也有跨音節處理的需求。
可以肯定的是,以平臺支持這項功能,比實現單獨一例難度要高。 作用於單個音節的拼寫運算,也不算很簡單,但至少定義和用法已經很明確了。 跨音節要怎麼做,我還沒有想周全。
另一番討論 https://github.com/rime/librime/issues/85 ,提出一種不同思路,即將輸入串變形後再查詢。這種思路難點在於應對輸入串到字典編碼的轉換有歧義的情況。
Encoder
固然是用來註音的,但必須用他的場合其實是在打字的時候爲用戶輸入的新詞編碼。
而預先準備好的詞典,我們有時間,可以利用各種手段完成註音。未必要用 Rime 的編碼器——這種場合他只爲詞典製作者提供些許方便,然而是可替代的——如果詞典文件已經完成編碼,就不需要動用。
我想說明:使用外部工具或腳本生成註音,未必構成「濫用」。無論在內存中完成編碼(註音)還是在外存(詞典文件)完成,最終結果是一致的,即寫入 .bin
文件的是全部已註音詞條。
惟一可能構成問題的用法是,人工標記的詞條與工具生成的數據混同在一個文件裏。這可以通過引入額外的處理步驟解決:詞典源文件→用外部工具生成註音→結果存入中間詞典文件→ 由 Rime 讀取並轉換爲固態詞典。添加這個中間步驟另有好處:可以不受 Rime 功能限制,實現任意有針對性的轉換規則。
總之,凡是可以前期處理的數據,我傾向於在 Rime 之外做預處理。這也符合讓程序專注於一項任務、組合多個程序完成複雜功能的 UNIX 哲學。
決定實現用程序註音之前,必須考察:規則是否普遍適用?舉一個「兒化韻」的例子:
由「猴兒」(h)ou+er = (h)our
總結出的規則並不能用於「幼兒」等不讀作兒化韻的詞,因此簡單地對匹配該形式的音節序列施加轉換並不嚴謹。這時候在詞典文件中列明詞條的註音,就關係到最終詞典的質量了,類似於爲詞語中的多音字註音的消除歧義、防止生成錯誤註音的作用。
或當先以外部工具批量按規則生成註音,再人工審查編輯定稿。分離出一個前期步驟爲我們提供了這樣的靈活性。
背景
我在参与制作一个基于 Rime 的福州话的输入方案,其中遇到的一个问题是,福州话有比较复杂的(跨音节的)语流音变,导致使用
script_translator
时感到有些限制。因为(如果我理解正确的话):而福州话的跨音节变化规律主要包括:
连读变调 (Tone sandhi) 即两个字分开单念的时候声调可能是 甲(声调a) 和 乙字(声调b),但是连成一个词汇之后,前一个字的声调会发生变化,所以组成的词汇是
甲(声调a')乙(声调b)
。例子:教 kau212 + 员 uong53 => 教员 kau44 uong53
韵母交替/变韵 (Vowel alternation) 即福州话的单字声调 (citation tone) 可分为两个集合 Set A 和 Set B。若一个字的声调,由于连读变调的关系,从 Set A 声调之一变到 Set B 声调之一,其韵母发生对应的(规律性)改变。变韵是受连读变调直接影响的。换句话说,韵母的变化是声调变化的函数。例子:
耳 ngei242 + 机 gi44 => 耳机 ngi44 gi44
声母类化 (Consonantal sandhi) 即两个字连成词汇的时候,前一个字的韵尾和后一个字的声母会条件性地发生改变。独立于前两种变化。例子:
下 a242 + 昼 dau212 => 下昼 a53 lau212
以及一个三种变化都有的例子:
裤 kou212 + 头 tau53 => 裤头 ku44 lau53
值得注意的是,并不是所有情况下,福州话的词汇都是适用连读后的音,有时(根据上下文、重音位置、词汇本身的常用程度等等因素)会用单个字的发音(即没有发生上述的连读音变)。福州话的使用者并非总是能分辨出一个词汇中,每个音节“本来的发音”是什么(特别是一些方言词或与官话差别较远的词汇),而有时是将连读后的多音节发音整体认读的。因此从使用者的角度,输入法需要兼容 “单个字的发音” 和 “连读后的发音”。即一个词汇,无论用单个字发音,抑或是根据上述规则连读后的发音,来录入,都能打得出来。
目前的解决方案
目前我们的一个原型其实是用了一个很粗暴的解决方案,就是给一个词汇在dict.yaml里注多个发音,比如:
有时一个词汇不止需要2行的注音,比如说可能有
{都不变(单字音), 只变声母, 只变韵母和声调, 韵母声调和声母都变}
四种组合,对应不同语境下的发音,或者对使用者本身的混淆进行容错处理。理论上我们可以用程序来生成一个词汇的多种可能发音,但是这样做,感觉是在“滥用”词典文件,同时我担心可能对词频会有影响,而且没法用在内置的“八股文”上面。
最新的想法
稍微研究了 librime 的代码之后,我目前的另一个想法是定制一个专门的 Encoder,将上述的福州话连读规律考虑进去。具体而言,当这个 Encoder 遇到未注音的词(可能来自“八股文”或者我们自己的词典文件):
甲乙
(“甲”、“乙”仅作为符号示意,并非表示 jia、yi 这两个字)甲
和乙
的单字发音。为方便解释,将其分别解析为(声母,韵腹,韵尾,声调)
这样的四维向量,假设为甲(c1, n1, f1, t1)
、乙(c2, n2, f2, t2)
((c1',n1',f1',t1'),(c2',n2',f2',t2'))
。可能会有多个结果。似乎只要在 encoder 成功完成匹配、即将保存结果的之前,插入上述逻辑,在 RawCode 上做改动即可。大约就是这个位置: https://github.com/rime/librime/blob/9e1114e58cbcd5c0da8b3786148984cca9a3fc09/src/rime/algo/encoder.cc#L269
我觉得挑战主要集中在:
因为我刚刚开始熟悉 librime 的代码,有许多东西还不太了解。把这些写出来,一方面自己理清思路,另一方面也想请教各位:基于我描述的问题,有没有更好的解决方案?欢迎任何想法和建议。谢谢!