rime / librime

Rime Input Method Engine, the core library
https://rime.im
BSD 3-Clause "New" or "Revised" License
3.45k stars 562 forks source link

在*.dict.yaml文件中添加comment列 #538

Open zhuangzhemin opened 2 years ago

zhuangzhemin commented 2 years ago

可以在*.dict.yaml文件中添加comment列吗?我想实现如下输入英文单词时带有中文提示的效果。 image

这个功能目前可以用lua插件来实现,但是词库大了之后,会有处理容量和初始化时间的问题。如果能编译成固态词典,容量和性能都会好很多。谢谢!

---
name: ECDICT
version: "1.0.0"
sort: by_weight
use_preset_vocabulary: false
columns:
  - text
  - code
  - weight
  - comment
...

the the 100 art. 那
of  of  95  prep. 的, 属于
and and 93  conj. 和, 与\n[计] 与
in  in  93  prep. 在...期间, 在...之内, 处于...之中, 从事于, 按照, 穿着\nadv. 进入, 朝里, 在里面, 在屋里\na. 在里面的, 在朝的\nn. 执政者, 交情
Eliot00 commented 2 years ago

同希望增加這个功能

zhuangzhemin commented 2 years ago

oniondelta大佬给了一个建议:(强烈感谢!)

這邊作法供參考: 不依賴 lua,建立一個無法輸出任何東西的英漢翻譯方案,方案字典內容如下:

eduction  [ɪ'dʌkʃən]@@n.@引出@;@推斷
eductor   [iː'dʌktə]@@n.@排泄器@(噴射器@;@排放裝置@;@排放管)
effluence ['eflʊəns]@@n.@流出@;@流出物

然後把該方案以濾鏡方式,掛到欲翻譯的 tags 上,以下掛接在 [ easy_en ]上,非[ abc ]上

e_reverse_lookup:
  tags: [ easy_en ]
  overwrite_comment: true
  dictionary: easy_en_comment
  comment_format:
    - xform/@@/\n          /
    - xform/@/ /

這邊實作在 Win 上 comment 太長程式會崩潰,Mac 上不會,故 Win 上使用還需修改 comment_format 正則, 把解釋縮短限定在一定字數內,才不會遇到崩潰情形。

我按照这个方法,用reverse_lookup查找的方式,改了一份Rime配置在我的github,已经可以实现用*reverse.bin查找、标识中文释义作为英文词汇的comment的需求。这个版本的处理能力和性能比我一开始改的lua插件生成table的方式明显好多了。

engine:
  processors:
    - lua_processor@ecdict_processor               # 非ASCII模式下,使用右shift键切换中英/英文模式
    - ascii_composer
  translators:
    - punct_translator
    - script_translator
    - table_translator@flypy_phrases
    - table_translator@wiki_zh
    - table_translator@custom_phrase_completion
    - table_translator@custom_phrase_no_completion
    - reverse_lookup_translator
    - table_translator@ecdict
  filters:
    - reverse_lookup_filter@ecdict_reverse_lookup  # 反查英文单词/词组的中文释义,作为comment显示
    - lua_filter@ecdict_filter                     # 控制中英混合输入或者纯英文输入,以及截断过长的comment
    - simplifier
    - uniquifier
ecdict:                           # 英文单词
  enable_encoder: false
  encode_commit_history: false
  enable_sentence: false
  enable_completion: true         # 是否启用英文输入联想补全
  enable_user_dict: true
  dictionary: ecdict
  initial_quality: 1

ecdict_reverse_lookup:            # 查询英文单词/词组的中文释义, 作为Comment进行提示
  overwrite_comment: true
  dictionary: ECDICT_reverse
  comment_format:
    - xform/\\n/ /
    - xform/^/ /
    # - xform/^(.{1,80}).*$/$1/   # 截断过长的comment,用xform截断中文comment最后一个字符可能会出现乱码, 改成用lua_filter处理

这边生成reverse.bin的时候还遇到一个问题,ecdict_reverse.dict.yaml里面的code列是中文释义,用原始ecdcit词典内容的话,会有很多条目生成不出来。我把code列里面的空白字符清理掉、“[]"换成"()"后就可以了。这个问题的原因还有待追查。

还有一个问题是现在的版本,dict.yaml文件我对全小写的单词复制了首字母大写和全大写这两种额外的格式,dict文件变得臃肿,而且全小写、首字母大写、全大写几种形态的词频没办法合并统计,这个也有待解决。

oniondelta commented 2 years ago
  1. code 中「空白」為字與字編碼分隔用,如:好奇-hao4 qi2, 之前提供的作法把英文單字當一個字(非詞句)標注 code,故 code 中「空白」需清除。 Mac 上實作“[]"可不用換成"()"。

  2. 詞頻合併意思是? reverse.dict.yaml ,只是提供 comment ,不用字頻吧?! 這邊因非融入[ abc ]中,故排序整理 dict 詞條前後順序,dict 中設定 sort: original。 如設在[ abc ]中,可調整 initial_quality: 和調整 translators: 中排序,使中文在前或英文在前。 如非要用字頻調序,可去除字典中所有字頻,在 dict 中用八股文如: vocabulary: essay-english,把字頻帶入。 以下為實作日文八股文內容,然後用 vocabulary: essay-japanese 掛載到 dict 中去做調頻。

    か   117280
    き   117280
    く   117280
    け   117280
  3. 還有一種更簡約的作法,只用一個附加方案,以方案 easy_en 為例,字典如下:

    isanomal    isanomal⌗[,aisә'nɔmәl]@@n.@[氣]等距平(線)
    isarithm    isarithm⌗@@n.@等值線@@[網絡]@等數線
    isaurore    isaurore⌗[ai'sɔ:rɔ:]@@[地物]極光等頻線

    「⌗」是關鍵,必須原字典中的 code 和 comment 翻譯中不存在該符號 方案 easy_en 中:

    speller:
    algebra:
    - xform/⌗.*$//

    主方案中,同之前作法,只是 easy_en 自己濾鏡(反查)自己:

    e_reverse_lookup:
    tags: [ easy_en ]
    dictionary: easy_en
    comment_format:
    - xform/^.+⌗//
zhuangzhemin commented 2 years ago
  1. code 中「空白」為字與字編碼分隔用,如:好奇-hao4 qi2, 之前提供的作法把英文單字當一個字(非詞句)標注 code,故 code 中「空白」需清除。 Mac 上實作“[]"可不用換成"()"。

学习到了,感谢。我之前这样替换是从原始情况下能出comment和没有comment的条目对比后自己猜的规律。

  1. 詞頻合併意思是?

词频合并是这样的。我在ECDICT.dict.yaml文件中对同一个单词额外生成了首字母大写和全大写的条目,以便输入时也能匹配到这两种情况。但是小写、首字母大写、全大写这几个条目的词频是各自独立的。我期望的结果是能合并起来统一调整。

the the 100
The The 100
THE THE 100
of  of  95
Of  Of  95
OF  OF  95
  1. 還有一種更簡約的作法,只用一個附加方案,以方案 easy_en 為例,字典如下:
isanomal  isanomal⌗[,aisә'nɔmәl]@@n.@[氣]等距平(線)
isarithm  isarithm⌗@@n.@等值線@@[網絡]@等數線
isaurore  isaurore⌗[ai'sɔ:rɔ:]@@[地物]極光等頻線

「⌗」是關鍵,必須原字典中的 code 和 comment 翻譯中不存在該符號 方案 easy_en 中:

speller:
  algebra:
    - xform/⌗.*$//

主方案中,同之前作法,只是 easy_en 自己濾鏡(反查)自己:

e_reverse_lookup:
  tags: [ easy_en ]
  dictionary: easy_en
  comment_format:
    - xform/^.+⌗//

这个方法我试了下,关键字符我用的是“::”,在生成ECDICT.reverse.bin的时候像是遇到一些问题,好久都没生成出来,也没有log信息更新。换回ECDICT.dict.yaml和ECDICT_reverse.dict.yaml分开的方案,就很快配置完成。

oniondelta commented 2 years ago

這邊實作可以成功,老 Mac 部屬近一分鐘,1百25萬條目字典(40萬翻譯詞條)。

這方法對字典 code(英漢翻譯)內容要求較高,實作修了好幾天! 字典中「\t」「\n」「\r」「空白」「#」等有特殊涵意符號要完全去除,想要再用 comment_format: 正則轉。 好處是可減少一個 comment 專用方案。

能達成想要目標的方法就是好方法,作法五花八門,僅供參考!

shewer commented 2 years ago

用opencc https://github.com/LEOYoon-Tsaw/Rime_collections/blob/master/Rime_description.md#%E4%BA%94simplifier comment_format: 過濾轉換 comment show_in_comment: true 也可以

用rime 的字典在英文字典上有個問題就是: rime dict 是tree 結構 , 候選字排序: "短字串"優先於"長字串" ,同字長的再排序權重。 在使用 enable_completeion: true時 ex : ther 後接着 會是 there ther ther[a-z] ther[a-z][a-z] (加黑字是排不上去的會在很後面) ther
-->ther: abbr. therapy 治療, 療法; thermometer 溫度計t1 therapeutic: [.θerә'pju:tik] a. 治療的, 有益於健康的 [醫] 治療的; 治療學的 ««1 therapeutically: [,θerə'pju:tikli] [醫] adv. 在治療上t1 therapeutics: [.θerә'pju:tiks] n. 治療學 [醫] 治療學; 療法, 治療t1 therapist: ['θerәpist] n. 治療學家 [醫] 治療學家t1 therapy: ['θerәpi] n. 治療 [醫] 療法, 治療t1 there: [ðєә] adv. 在那裡t1 thereabouts: ['ðeәrәbauts] adv. 在那附近, 大約, 上下, 左右t1

oniondelta commented 2 years ago

先感謝 shewer 大大的貢獻! 在寫 rime.lua 時,參考閱讀了許多你的程式碼和留言帖子。

確實有"短字串"優先於"長字串" ,無法像英漢字典一樣排序的問題, 原預想先掛上去,再寫 lua 去排序。 後來改用1百25萬條目(40萬翻譯詞條)字典, 在老 Mac 上感到已經很肥,故沒去折騰 😆

另 opencc 早前嘗試過, 遇到原已有注釋後面會再接注釋情形,如短英文單字:ing ing---abbr. 慣性導航與制導(Inertial Navigation and Guidance) ; 強中子發生器(Intense Neutron Generator) 試著調整 rime 設定檔、 opencc 的 .json 檔和 .text 檔, 這邊還是搞不定 😣

shewer commented 2 years ago

可以寄給我 字典檔嗎 shewer@gmail.com 試試看如何提前預排序, 另外我好像找到重覆初始化的問題了, 英文字典初始化掛錯地方,造成重覆初始化 ,我用原始詞條件50K 載入約1S

oniondelta commented 2 years ago

英文單字:code+comment(檔案太大,故上傳 GitHub 分兩個檔) https://github.com/oniondelta/Onion_Rime_Files/blob/master/allfiles/easy_en_super.dict.yaml https://github.com/oniondelta/Onion_Rime_Files/blob/master/allfiles/easy_en_super_one.dict.yaml https://github.com/oniondelta/Onion_Rime_Files/blob/master/allfiles/easy_en_super_two.dict.yaml

以⌗分界,前面 code ,後面 comment 英文翻譯:

speller:
  algebra:
    - xform/⌗.*$//
    - derive/(.)[;']$/$1/   # 編碼加上 enable_completion: true,全大寫和開頭大寫可在打小寫時顯示,依照原字典沒併到全小寫下。增加此正則,校正排序。
e_reverse_lookup:
  tags: [ abc ]
  overwrite_comment: true
  dictionary: easy_en_super
  comment_format:
    - xform/^.+⌗//  #刪除前面 code
    - xform|^[ a-z;/.'-]+||  #刪除沒有英文翻譯單字
    - xform/@@/\n          /  #換行,mac 用,win 下會有問題
    - xform/@/ /  #轉換空格
shewer commented 2 years ago

己改善好了 載入時間 380k 1S 50k 0.1S (Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz ,ssd ) 1 自動生成固態字典,以固態字典載入優先 txt --> txtl 2 共用字典table , 減少記憶體佔用及載入時間

lotem commented 2 years ago

这个功能有点儿用处。预计在Rime 2里给他设计上。

shewer commented 2 years ago

是加入 字元排序字典結構還是 dict.yaml 的comment

shewer commented 2 years ago

發覺用leveldb也不錯,可以降低載入內存用量,只是不曉得用 leveldb.iterator().seek(string) 是不是有序的把資料調出 目前是將有序的ecdict (key : 單字 or 字句 value: line of csv format)依順序put to leveldb 使用 iterator.seek( str) 看起來是有序的 測試環境 lua + luarocks + lualeveldb 請問: 如果要在libirme-lua 加入 leveldb 要用那一個class 較合適

shewer commented 2 years ago

使用 rime/dict/level_db.h class LevelDb & *DbAccessor 打開ecdict data 10ms

LawssssCat commented 2 years ago

https://github.com/oniondelta/Onion_Rime_Files/commit/4d106957b46fb5a890706640ea44adb2b5dae668

这里comment太长会导致程序崩溃的现象我也遇到了,请问的原因有找到吗?是什么?

win10系统 distribution_code_name: Weasel distribution_version: 0.14.3 rime_version: 1.5.3

hyaray commented 2 years ago

这个功能有点儿用处。预计在Rime 2里给他设计上。

什么情况,还会有rime 2吗?请问哪里有相关介绍么?

hyaray commented 1 year ago

这个功能,分享自己用脚本临时过渡的思路,顺带每次部署后自动删除无效文件。

  1. 想直接显示 comment,目前rime没有这个机制,得用反查实现
  2. 制作反查 xxx.schema.yaml(只为了能生成xxx.reverse.bin文件)
  3. 重新部署用脚本实现:
    1. 获取所有相关dict文件的 comment 行并写入xxx.dict.yaml(一般把带 comment信息的放到文件后面,上一行内容末尾弄个标识,用正则删除即可,否则需要遍历每行,提取有用的信息)
    2. 运行命令行WeaselDeployer.exe /depoly重新部署,并等待结束
    3. 可以判断%temp%目录下是否有error文件,知晓是否有错误
    4. 删除build下xxx的其他无关文件(反查的方案,只有xxx.reverse.bin才是有用的)
    5. 有强迫症,还可以删除build下其他文件,比如五笔方案的临时拼音,那么拼音的.reverse.bin.schema.yaml也是没用的

附上AutoHotkey v2的代码供参考

Rime.rebuild()
class Rime {

    static dirSoft := "c:\soft\rime\weasel-0.14.3"
    static dirUser := "d:\TC\hy\rime"
    static fpServer := this.dirSoft . "\WeaselServer.exe"
    static fpDeployer := this.dirSoft . "\WeaselDeployer.exe"

    static ready(bRun:=false) {
        if (bRun || !ProcessExist("WeaselServer.exe"))
            run(this.fpServer)
    }

    static rebuild() {
        this.ready()
        ;合并多文件的备注到 fpTip
        fpTip := Rime.dirUser . "\tip_hy.dict.yaml"
        FileCopy(Rime.dirUser . "\tip_hy1.dict.yaml", fpTip, true) ;本人是在`tip_hy1`的基础上再叠加其他文件的备注内容
        arrFn := [
            "dict\z_hy.dict.yaml",
            "cmd_work.dict.yaml",
        ]
        sTip := ""
        for fn in arrFn
            sTip .= getComment(format("{1}\{2}", Rime.dirUser,fn))
        FileAppend(sTip, fpTip, "UTF-8")
        ;重新部署并等待完成
        RunWait(format("{1} /deploy", this.fpDeployer))
        ;核实有无错误
        if (FileExist(A_LocalAppdata . "\Temp\rime.weasel.*.ERROR.*")) { ;这个变量仍不是 v2 自带的,需自行调整
            msgbox("有错误文件",,0x40000)
            return
        }
        ;删除无效文件
        FileDelete(fpTip) ;也可以不删
        ;    示例:临时方案的无效文件
        FileDelete(this.dirUser . "\build\english.reverse.bin")
        FileDelete(this.dirUser . "\build\english.schema.yaml")
        ;    示例:反查方案的无效文件
        FileDelete(this.dirUser . "\build\tip_*.schema.yaml")
        FileDelete(this.dirUser . "\build\tip_*.prism.bin")
        FileDelete(this.dirUser . "\build\tip_*.table.bin")
        getComment(fp) {
            sFile := fileread(fp, "utf-8")
            s := RegExReplace(sFile, "s).*eeee`n", "") ;NOTE 不要的内容用 eeee 结尾
            s := RegExReplace(s, "`t.*`t", A_Tab)
            return s
        }
    }

}