fygul
新手上路
新手上路
阅读:6048回复:6

字、碼互相轉譯功能

楼主#
更多 发布于:2012-12-31 17:41
【簡介】
之前有人提過這篇 ,裡面有提過的這裡就不再贅言,其中的11樓稍提了一下有提供這功能的輸入法與適用條件

以自己用的中文輸入法拆碼方式為例,簡單舉個例子:
「小小輸入法」幾個字轉譯為字碼:「sa sa cai bp wu 」
「sa sa cai bp wu 」則可轉譯成文字:「小小輸入法」
※以下所提的內容,均以自己用的輸入法拆碼方式為例做說明

這功能較適合於選字率低的輸入法,否則選字率過高,轉譯出來結果可能很奇怪,也沒什意義可言
也許有人覺得這功能只是噱頭,無實際用途,不過當初做出這功能的輸入法是有他的考量
因該輸入法不是系統內建,為方便使用者萬一在沒有該輸入法的環境時,可以暫時先將想輸入的東西,以英文代碼存下
等到回到有該輸入法的環境後,即可用此功能轉成中文
其主要目的並不是當加密文,讓人家看不懂用的,加密的軟體已太多,不須再用這個來插一腳。何況這也不是很好的加密方式,很容易解密
自己過去倒是有幾個時機使用此功能,現在使用的時機很少了,因用小小這平台可四處帶著走
這類時機像剛好沒有可用的輸入法,網路連線也不方便,無法用線上版的輸入法。只好暫時先用英文代碼,之後再轉譯成中文;或要寄中文訊息給朋友,卻無法輸入中文,而朋友也使用相同輸入法,懂得如何轉譯成中文

以下利用小小的「命令直達車」功能,模擬此「字、碼互相轉譯功能」
這個做法的條件、限制,及使用環境大致與這篇 所提相同的

這裡再補充三點限制,也就是這裡所用碼表的條件:
第一是拆碼方式的選字率要低,結果才會理想;否則結果可能讓你無法接受,而不想用此功能
第二是目前僅適用於一行中只含一組字碼對應一文字的碼表
也就是要像這種的

a 對
aa 寸
aaa 鑫
aaa 龘
aaa 鑆
aaar 鑆
...

不能像這種的

a 對
aa 寸
aaa 鑫 龘 鑆
aaar 鑆
...

第二項限制是因為目前自己做的程式只處理像第一種的格式
(為方便說明,上述碼表片段範例中,將空白前面的英文代碼稱為「字碼」,簡稱為「碼」;空白後的中文字或符號稱為「字符」,簡稱為「字」)
字符最好是單一字元的文字或符號

第三是碼表中要出現[data]這個分隔指示。最好是乾淨格式的碼表,以免引發錯誤
碼表最好已按照字的使用頻率排列過,即常用字排在前,效果會較好
自己的碼表是用utf-8編碼,若用GBK編碼,主程式要調整

【設置方法】
以上交代過基本的需知,再來說明設置方法
一、在分詞庫中加入命令直通車的指令
xmode $GO(碼字轉譯,tw\plugin\xmode.pyw)
ymode $GO(字碼轉譯,tw\plugin\ymode.pyw)

二、做好xmode.pyw與ymode.pyw
取名為xmode與ymode是源自原始設計此功能的輸入法用來啟用解譯功能的按鍵方式,且官方說明文件沒公開此功能,所以自己就私底下將其稱為X模式,反向的解譯則稱為Y模式

利用二支python小程式執行下述的主程式,將自己的檔案名稱傳入,當成是執行參數
二支程式的內容完全一樣,只有檔案名稱不一樣

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
  
import os
import sys
  
def main():
    path, filename = os.path.split(sys.argv[0])
    basename, ext = os.path.splitext(filename)
    os.chdir('tw/plugin/')
    os.system('translate.pyw ' + basename)
  
if __name__ == '__main__':
    main()

三、主程式:translate.pyw

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
import sys
##import os
import win32clipboard
import win32con
import win32gui
 
code_table = '../wushiamy.txt'
 
def copy_from_clipboard():
    '''從剪貼簿複製文字,但排除沒有實質內容者'''
    win32clipboard.OpenClipboard()
    t = win32clipboard.GetClipboardData(win32con.CF_UNICODETEXT)
    win32clipboard.CloseClipboard()
    if t.strip('\n ') != '':
        return t
 
def copy_to_clipboard(text):
    '''文字複製到剪貼簿'''
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardData(win32con.CF_UNICODETEXT, text)
    win32clipboard.CloseClipboard()
 
def prepare_dict(code_table):
    '''準備兩個轉譯用的字典,其中一個屬僅中介的暫時性字典
       及組字鍵之字元串列'''
    global dict_code, dict_cword, keys_lst
    with open(code_table, encoding='utf-8') as f:
        start = False
        for line in f:
            line = line.strip('\n').lower()
            if not start:
                if line.startswith('[data]'):
                    start = True
                elif line.startswith('key='):
                    s, keys = line.split('=')
                else:
                    continue
            else:
                if line.startswith('#') or line == '':
                    continue
                code, cword = line.split(' ', 1)
                if not dict_cword.get(cword):
                    dict_cword[cword] = {}
                if not dict_code.get(code):
                    dict_code[code] = cword
                    dict_cword[cword][code] = False
                else:
                    dict_cword[cword][code] = True  #表示要選字的碼
    keys_lst = [c for c in keys]
 
def get_best_code():
    '''轉譯用最佳短碼字典'''
    global dict_cword_best
    for k in dict_cword.keys():
        cand = dict_cword.get(k) #取出其中的候選
        lst_t = []
        lst_f = []
        for code in cand.keys():
            if cand[code] == True:
                lst_t.append('{}:{}'.format(len(code), code))
            else:
                lst_f.append('{}:{}'.format(len(code), code))
        if lst_f:   #不用選字的碼,優先採用
            lst_f.sort()
            n, dict_cword_best[k] = lst_f[0].split(':', 1)
        elif lst_t:
            lst_t.sort()
            n, dict_cword_best[k] = lst_t[0].split(':')
 
def translate(dic, key):
    '''轉譯。若無法轉譯,傳回原值'''
    value = dic.get(key)
    if value:
        return value
    else:
        return key
 
def try_translate(jam):
    '''嘗試轉譯可能是中文混雜的字串;不能轉換的部分照原字串傳回'''
    output = cw = ''    #cw: candidate word
    pos = -1
    for i in jam:
        pos += 1
        if i in keys_lst:
            cw += i
        else:
            if cw:
                output += translate(dict_code, cw)
                cw = ''
            output += i
        if pos == len(jam) - 1:
            if cw:
                output += translate(dict_code, cw)
    return output
 
def xmode():
    '''X模式:組字碼轉成字符(指文字、符號等的統稱)'''
    text = copy_from_clipboard()
    if text:
        code_lst = text.split(' ')
        cword_lst = []
        for c in code_lst:
            w = dict_code.get(c)
            if w:
                cword_lst.append(w)
            else:
                cword_lst.append(try_translate(c))
        copy_to_clipboard(''.join(cword_lst))
 
def ymode():
    '''Y模式:字符轉成組字碼'''
    text = copy_from_clipboard()
    if text:
        cword_lst = [w for w in text]
        code_lst = []
        for w in cword_lst:
            c = dict_cword_best.get(w)
            if c:
                code_lst.append(c + ' ')
            else:
                code_lst.append(w)
        copy_to_clipboard(''.join(code_lst))
 
def main():
    if len(sys.argv) > 1:
        prepare_dict(code_table)
        get_best_code()
        if sys.argv[1] == 'xmode':
            xmode()
        elif sys.argv[1] == 'ymode':
            ymode()
 
if __name__ == '__main__':
    dict_code = {}          #{code: cword},記錄組字碼第一次出現時的字
    dict_cword = {}         #{cword: code},中介的暫時性字典,用來產生dict_cword_best用
    dict_cword_best = {}    #{cword: code},字符的最佳短碼:不須選字的最短碼;若無此類碼,則放排序後排在前面的最短碼。
    keys_lst = []           #放組字鍵之字元
    main()

【使用方法】
以一篇《千字文》做轉譯的範例
這篇內容只是拿來當範例,不同版本,文字有些許差異,這非關本主題

天地玄黃 宇宙洪荒 日月盈昃 辰宿列張 寒來暑往
秋收冬藏 閏餘成歲 律呂調陽 雲騰致雨 露結為霜
金生麗水 玉出崑崗 劍號巨闕 珠稱夜光 果珍李柰
菜重芥薑 海鹹河淡 鱗潛羽翔 龍師火帝 鳥官人皇
始制文字 乃服衣裳 推位讓國 有虞陶唐 吊民伐罪
周發殷湯 坐朝問道 垂拱平章 愛育黎首 臣伏戎羌
遐邇壹體 率賓歸王 鳴鳳在樹 白駒食場 化被草木
賴及萬方 蓋此身髮 四大五常 恭惟鞠養 豈敢毀傷
女慕貞絜 男效才良 知過必改 得能莫忘 罔談彼短
靡恃己長 信使可覆 器欲難量 墨悲絲染 詩讚羔羊
景行維賢 剋念作聖 德建名立 形端表正 空谷傳聲
虛堂習聽 禍因惡積 福緣善慶 尺璧非寶 寸陰是競
資父事君 曰嚴與敬 孝當竭力 忠則盡命 臨深履薄
夙興溫清 似蘭斯馨 如松之盛 川流不息 淵澄取映
容止若思 言辭安定 篤初誠美 慎終宜令 榮業所基
藉甚無竟 學優登仕 攝職從政 存以甘棠 去而益詠
樂殊貴賤 禮別尊卑 上和下睦 夫唱婦隨 外受傅訓
入奉母儀 諸姑伯叔 猶子比兒 孔懷兄弟 同氣連枝
交友投分 切磨箴規 仁慈隱惻 造次弗離 節義廉退
顛沛匪虧 性靜情逸 心動神疲 守真志滿 逐物意移
堅持雅操 好爵自縻 都邑華夏 東西二京 背邙面洛
浮渭據涇 宮殿盤鬱 樓觀飛驚 圖寫禽獸 畫彩仙靈
丙舍傍啟 甲帳對楹 肆筵設席 鼓瑟吹笙 升階納陛
弁轉疑星 右通廣內 左達承明 既集墳典 亦聚群英
杜稾鍾隸 漆書壁經 府羅將相 路俠槐卿 戶封八縣
家給千兵 高冠陪輦 驅轂振纓 世祿侈富 車駕肥輕
策功茂實 勒碑刻銘 磻溪伊尹 佐時阿衡 奄宅曲阜
微旦孰營 桓公匡合 濟弱扶傾 綺迴漢惠 說感武丁
俊乂密勿 多士寔寧 晉楚更霸 趙魏困橫 假途滅虢
踐土會盟 何遵約法 韓弊煩刑 起翦頗牧 用軍最精
宣威沙漠 馳譽丹青 九州禹跡 百郡秦并 嶽宗泰岱
禪主雲亭 雁門紫塞 雞田赤城 昆池碣石 鉅野洞庭
曠遠綿邈 巖岫杳冥 治本於農 務資稼穡 俶載南畝
我藝黍稷 稅熟貢新 勸賞黜陟 孟軻敦素 史魚秉直
庶幾中庸 勞謙謹敕 聆音察理 鑑貌辯色 貽厥嘉猷
勉其祗植 省躬譏誡 寵增抗極 殆辱近恥 林皋幸即
兩疏見機 解組誰逼 索居閑處 沉默寂寥 求古尋論
散慮逍遙 欣奏累遣 慼謝歡招 渠荷的歷 園莽抽條
枇杷晚翠 梧桐早凋 陳根委翳 落葉飄颻 遊鵾獨運
淩摩絳霄 耽讀翫市 寓目囊箱 易輶攸畏 屬耳垣牆
具膳餐飯 適口充腸 飽飫烹宰 饑厭糟糠 親戚故舊
老少異糧 妾御績紡 侍巾帷房 紈扇圓潔 銀燭煒煌
晝眠夕寐 藍筍象床 弦歌酒讌 接杯舉觴 矯手頓足
悅豫且康 嫡後嗣續 祭祀烝嘗 稽顙再拜 悚懼恐惶
牋牒簡要 顧答審詳 骸垢想浴 執熱願涼 驢騾犢特
駭躍超驤 誅斬賊盜 捕獲叛亡 布射僚丸 嵇琴阮嘯
恬筆倫紙 鈞巧任釣 釋紛利俗 並皆佳妙 毛施淑姿
工顰妍笑 年矢每催 曦暉朗曜 璇璣懸斡 晦魄環照
指薪修祜 永綏吉劭 矩步引領 俯仰廊廟 束帶矜莊
徘徊瞻眺 孤陋寡聞 愚蒙等誚 謂語助者 焉哉乎也

先將《千字文》內容複製到剪貼板
用命令直通車執行ymode,將結果貼出來

edn yal lwa ka  nuj niq wrb rfs  do ue ruf dlb  fkn nptd dri qek  njb ln dho mk
hfn gpx pba rrv  mke xat ay zs  mie opo ino bm  uta ubnf ppx ua  ulo syo bf utm
ae se la wn  kaa eei edb enx  acr ol ffe mbei  ksb hy lx ser  qtn kbm tzj trsv
ret gq rbr reqe  wm zoxk wto wff  ufmc kd eee bhee  akp ren fn lnn  nfa nbo bn pdk
guo snr wx nzj  rp uu lkn snok  jve ple ik ohe  x zoed bni leo  onj oxx paq us
no fx feyu wep  bby jue moo hwn  ge jrb pj ldj  hx tue hw ho  re pad aqj bkr
offw nsw ,de qd  ljj nbv pq ke  onf rnf xy tua  pdo mfno xn yep  pfl vpx rdj tn
vb pux ru fy  rce zfl sx vax  f dn w sn  rbf hv rcnm kx  ede irp gu pvd
gx rddf zmb fds  qdx lxd up an  vdo qow hp flp  dd ul rdd fha  nbf iff mip vdd
ltte hya gg kn  pio pc to cv  om win rcv deq  qfy qt ssa wkt  iya iq bkf bhj
ds mv sve rumb  jorrv ayh pvf rok  mh ewn coo le  kmp ldi vk ez  nbi wo pqa yc
zfe sy ed rh  ct od oha hb  rq sq bv ldn  cnn pka rs nka  aa bue jn lr
bb bxx jce eoo  dov ox ea nx  ypz so ldlv dx  cha mbr cnb aop  rv wnn cg xr
rda seb wdf whu  pub bse kbk yhd  goo tbu az afe  si wl ba pmh  whi wjd rux dcn
nwo ze roo qha  io ej ng nz  zmf vdp iay bkd  hjb spb nme api  ft fr fki ky
xd kl vf ldr  snz pyx jde pyv  jrv rob mz ezp  xz u go snot  yua ri y iun
rn dsb qa mbk  rsl odr bea pqg  fe hoo fa mqu  qnn odd gej xw  cpa enu pia isi
bp fnq oma pbx  xg gjo ppd fsu  qak zj bl grl  zll hk orl tp  neo km cwn tju
lxx xux jru bdp  cdp ltto zko ql  pre bav bh hmbr  sow bin vj lav  rpi bx lpq dkw
jbt wln fs zk  hse hz hhu nw  ha gd rsi lbp  naa jba yha m  eqw snm ldh hcc
ruy jya xve xt  gz efaa pm lttsr  yb oclv aj tmp  csa co r los  ffu fbiv tj wpo
wez wquv jzn wsi  nov cu zf twum  tg rmr fj hls  ot nf bla odv  eqe em pei ef
enb bgo pgy fop  qi nek a truf  ,df zpzw iru lrn  yuv kkhp oin zse  xj bd snb bbyv
urj cqa fz dse  xoo t lka nbn  xie ywn wsj due  dl vt yja fba  lfa ruq eh rcn
tye qhn agq twv  wgw asj cy ssi  lpa fsv gea tm  lo pgn tvav dgi  fp yya b ms
neq sao gj kv  q kc blo qaqc  mxv yncu jfk ssg  sl rscw pcc fq  cj dfv ucl csi
zjn idx rpv nbd  ry lopg lhr aco  lomq ce pex ex  pxi h bto ut  xl ngl fo pbjv
rz dev lzz ff  tede bua fke aoo  wwh qb jqn pft  svo ohw wrc jh  ir ah we ti
phx xxv xe nm  cca ye ndez nti  efed tz tx uuv  yzsu hgv otn tka  pox bhw efn eazr
ozk yv ad duf  pto bw sna wu  jwj brj fta kri  yl beer pta spx  nqj ncj dru mhu
cf ag wsp wdv  mav eio nae hue  k yy pcnu if  tdo eob fnh bkj  eqid ns fnw paxe
rso ake uta lnt  lpv mi zfs ny  evv qo yfa yay  dbl wal lod loo  aff qui wneo lkw
dlk yw spj eqgw  eop eiq tdov ndl  wuo tej fbb ffk  mpd bb hneq hwoo  pfsu jc n lqo
ix rt hbw hqbp  hr lf imb li  rdx kt qfee bzs  zfev ctov lzp hsa  cx ufa ges je
lrf gb ci lenq  rnd iqn irc vsd  rap ldo nja kq  af erv lil dcl  mbuo lbei yq bead
edx kba rsxe tje  sm sqk irl irv  nal ybo jlr tk  duo fka kwn rha  ttn pddj yj gi
eb ysv mrl g  nbh sme ive ew  jns cjo mtv zv  wnr qf nuv nem  na joo eaa iam
rup zh suw uw  kin fnv qsa uc  aqphv isa rin jdo  wfft rpto d ldx  ok rdr jiq pn
tbl tcl dr eejj  two tneo djj bno  bcs tdk hgx fvder  ro rst ccv unc  fwn dbnf qc ncw
wybp lhv sps usu  rkl ib eepr ni  nqnu mo vkv ztm  ep cber pip qkn  cc rj yede gwoo
meb ubho zn xlu  gow oo tl uep  xnl xgn lwf nlj  xwb yn mrfd mlew  ll as jx rg
ypf sp qrb man  lgx mpv sg sfy  pya nj nve ffy  ska fee ob wyo  adk fca fwj fpdk
cnde mox ca ngqb  rrf zex nn ltn  qlw tiv weo irff  jlg tba eq nvd  vdg hj eta ozn
hf unn me lew  gxo i ome sb  ja rsol wefr snt  hakd uuub ey hfj  hvs qv ih hpdk
pkxr pst zmd v  fb zao nii ibh  qulh yfo th wwo  yz yf yt bls  mffr mfqs sjmv sya
mflh ovv yo mflk  isb cki mjv bif  jij qu blu fl  xni saa pla zx  hake kyv brr oeh
hgo zej pam sxx  anr ikk pke ana  mg sbd hri pwo  be bpd ve gsp  ml fva su big
ie zstg gkj zed  vsj vdn vm pev  dbkk dncv aue dvv  kzv krz muh jbdv  dvom pdv kk df
jfd rli pp rsjo  un seg yoo dod  vfv zsp qii apt  pav pfp lab liq  jcs fnn may rgy
mirs mioo mvo mra  zg bel ntdd mrj  qh qq zya isu  iqu iwo mdx hov  ezkf jaqo hjv al

將上述字碼複製到剪貼板
用命令直通車執行xmode,將結果貼出來,因與前述《千字文》內容一樣,這裡就不再貼一次

【補充說明】
對這個執行結果做一些補充說明
一、如果純中文的文章轉成字碼,再轉回中文文章,若出現與原來不一樣的字,大概就是那些字輸入時需要選字,而轉譯的過程中,選了順序在前的不同字
二、這裡看到轉來又轉去,兩份中文的內容都一樣,似乎這千字都不需選字?這是因輸入法的碼表將選字碼也設計進去了,對於熟悉的人,是好像不選字般。若去掉這層,這千字中有22個需要選字,選字率為2.2%。這可利用「偽.蝦米」較為精細的解譯功能看出來,但我裝給它用的二進制碼表是較早的版本,並不是目前最新的版本
三、選字率要多低,效果才會好?這點自己沒去研究,也沒切確的數字,可能直接試試轉譯結果滿不滿意,若不滿意大概也代表了選字率較為偏高。上述文章有一些現代不常用到的字,若是常用字,選字率應該還會更低
四、要轉譯的內容若為中英文混雜,可能會導致非預期結果
五、這範列中雖沒一般的標點符號,但所用輸入法碼表中也含有標點符號,故也可轉譯


以上的作法可能有些狀況沒有考慮到,不見得是週全嚴謹的作法,只是權充需要的人參考
程式碼也是粗略撰寫,要用在不同環境,要做適度調整
游客

返回顶部