天天看點

OEA 中的多國語言實作

多國語言常見實作及原理分析

    而這些方法背後的本質,其實都是在開發期,通過開發人員定義的“鍵(key)”,找到在運作期加載的不同語言包中對應的語言項,而再讓界面呈現出來。即:

開發期定義開發人員使用的 key。

在不同的語言包中,為 key 定義不同的語言項(value)。

運作時,通過 key,尋找并顯示不同語言的詞句。

    這些開發模式中,開發人員都不得不去定義 key、建立語言包,并修改所有顯示的程式。例如,以下代碼:lblusername.text = resources.usernamedisplaylabel; 我們不得不定義一個 usernamedisplaylabel 的 key,并在語言包中去填寫對應的譯文。那麼,能不能讓開發人員不去定義 key,而直接使用開發人員本國語言編寫呢?例如,讓中國的開發人員這樣寫:lblusername.text = “使用者名:",最終則在英文版本中顯示“username:”。oea 中已經實作了這一方法:

oea 中的多國語言架構

    在 oea 中,多國語言的實作原理,其實是一樣的。但是,多國語言的 key,就是開發人員的本國語言,而不需要為其定義單獨的英文鍵。例如,lblusername.text = “使用者名:"; 中,“使用者名:" 就是這個 key,oea 中稱其為開發語言。而某個國家語言的語言包中的每一項,也是一個 key/value 對,key 是開發語言,而 value 則是這個開發語言對應的第三國語言。

    其主要思想就是把開發人員所在國的語言,作為語言包中每一項的鍵。

    在使用時,開發人員在架構基礎上随意在代碼中使用本國語言,并将最終由架構在界面層翻譯為目标國語言。在此設計基礎上,oea 提供了相應的多國語言編輯環境,它是內建在運作時系統中的。由一個 oea.multilanguages 的插件提供:

OEA 中的多國語言實作

也就是說,多國語言中的語言包等資料載體,也使用了 oea 的實體類系統。加載此插件後,并運作系統,會發現在開發工具中添加了兩個相應的子產品:

OEA 中的多國語言實作

分别是開發語言子產品和多國語言子產品。

    在開發語言子產品中,我們可以看到整個程式代碼中使用的所有開發語言,也就是每一個 key。

OEA 中的多國語言實作

這些 key 由 oea 架構自動收集起來,這個過程發生在第一次運作該代碼時。例如,開發人員編寫了:app.messagebox.show("請選擇一行資料。"); 這行代碼,在這行代碼被第一次運作後,oea 會把"請選擇一行資料。"作為開發語言收集起來:

OEA 中的多國語言實作

    在多國語言子產品中,顯示的則是所有已經添加的語言及該語言下所有翻譯的項:

OEA 中的多國語言實作

其中的翻譯引擎是直接使用 baidu、bing 兩個網站的“服務”,可以為把開發語言直接翻譯為目智語言。而“打開所有子產品”功能則是為了友善一次性收集整個應用程式所有子產品界面的開發語言。這兩個子產品中,都有一個“自動更新”的按鈕。它的作用是把目前架構收集到的所有開發語言寫入各語言包中。

    是以,要支援一個新的語言,隻需要簡單、快速的幾步:

在多國語言中添加一個語言,如日文。

點選“自動更新”,把所有開發項添加到日文中。

點選“翻譯引擎”,把日文包中的所有開發項翻譯好。

如果哪些項翻譯得不好,則可以讓專人進行人工翻譯。可以一邊翻譯,一邊檢視效果,不需要重新開機應用程式。

把整個應用程式配置為使用日文。這一步,隻需要在 app.config 配置檔案中使用以下配置:<add key="oea_currentlanguagecode" value="jp"/>

這樣,再次打開應用程式,會發現所有界面都已經是日文的了,除去人工翻譯的整個過程不到3分鐘:

OEA 中的多國語言實作

程式設計接口

     其實,看到這裡,可能很多朋友會問一些問題:

oea 架構是怎麼做到收集開發語言的?

oea 架構是怎麼讓整個界面都自動翻譯的?

如果我沒有調用架構的層面層 api,還想翻譯怎麼辦?

翻譯過程,是在什麼時候發生?

    整個多國語言架構,說白了就是實作字元串的翻譯。是以 oea 為 string 類型添加了擴充方法 translate:

OEA 中的多國語言實作

這樣,就可以随時對于任何一個字元串調用,例如:當配置目智語言為英文時,調用 “中國”.translate(),傳回 “china”。這樣,不論是否使用 oea 的界面層架構,都使用這個方法來翻譯。(其實換湯不換藥,這跟使用資源檔案中定義的 resources.china 發生的過程一緻,通過 key 找到目智語言包的 value,并傳回。)

從這個方法的注釋中可以看到,隻要是被調用了此方法的字元串,架構都認為它是一個開發語言,會被自動收集起來。而 oea 強大的界面生成架構,隻是在适當的地方調用了 translate 方法,是以整個界面都會被翻譯、收集。oea 中,這個方法的調用,是盡量靠近最終的界面顯示,并盡量遠離開發人員代碼,這樣可以保證開發人員在代碼中的各類判斷,還是使用開發語言。

同時,除了這個字元串的程式設計接口,由于 oea 的用戶端使用了 wpf 架構,是以還為 wpf 提供了專門的控件翻譯接口,它是一個文本顯示控件,及一個附加屬性:

OEA 中的多國語言實作

這樣可以在 xaml 中自動翻譯 wpf 中常見的屬性。否則也可以直接調用 translate 方法進行翻譯。

待改進點

    目前,該多國語言架構已經使用了兩個月了。它的不足也慢慢暴露了出來:

開發語言變更造成無用的翻譯項。

如果一個開發語言已經被收錄進各語言包,此時開發人員再在程式中對其修改,則會造成舊的開發語言成為無用項保留在開發語言包中。是以這時需要人工去删除這些無用的項。雖然多國語言的資料是存儲在服務端的資料庫中(使用了用戶端緩存,性能不是問題),再多的項也沒關系,但是這畢竟是一個潛在的問題,後面需要設計一個好的方法來自動找到這些無用項。

動态拼接字元串的情況,也會造成無用的翻譯項。

另外,如果在動态拼接字元串時,不作任何處理,直接交給界面層顯示,則也會導緻收集了過多無用的項。例如,要顯示:”使用者鍵”+ id,則可以收錄”使用者鍵1”、”使用者鍵2”、”使用者鍵3”……這時,我們提供了 ignoretranslation 方法用于忽略最終的動态字元串。開發人員需要為 ”使用者鍵”單獨調用 translate,并對結果調用 ignoretranslation。如:app.messagebox.show((“使用者鍵”.translate() + id).ignoretransation())。

    就目前的體驗上講,該架構的使用是非常舒服的。開發過程中,除了動态拼接時,基本不需要考慮多國語言的存在。開發效率較高。運作時在界面中可随意修改譯文,即時見到效果,靈活性也不錯。:)

希望對多國語言有研究的朋友,對我的待改進點提出建議。謝謝。:)