2008-10-08 31 views
20

這是一個普遍的問題,對於意見開放。我一直在想出一種設計Windows MFC應用程序和相關實用程序的字符串資源本地化的好方法。我的心願是:設計字符串本地化的最佳方法

  • 必須在代碼中保存字符串(而不是與宏的#define資源ID的替換),以使這些信息仍然可讀的內聯
  • 必須允許本地化的字符串資源(杜)
  • 不得強加額外的運行時環境的限制(例如:依賴於.NET等)
  • 應該有最小的obtrusion到現有的代碼(改動較小越好)
  • 應該是調試的
  • 應該生成可由常用工具編輯的資源文件(例如:通用格式)
  • 不應該使用複製/粘貼註釋塊來保留代碼中的文字字符串或其他任何可能導致不同步的文件
  • 會很高興允許靜態(編譯時)檢查每個「註釋」字符串是否在資源文件中
  • 允許跨語言資源字符串池(適用於各種語言的組件,例如:native C++和.NET)

我有一種方式,除了靜態檢查,在一定程度上滿足我所​​有的願望,但我有h廣告來開發一些自定義代碼來實現它(並且它有侷限性)。我想知道是否有人以特別好的方式解決了這個問題。

編輯: 的解決方案,我目前有看起來像這樣:

ShowMessage(RESTRING(_T("Some string"))); 
ShowMessage(RESTRING(_T("Some string with variable %1"), sNonTranslatedStringVariable)); 

然後我有一個自定義工具從「RESTRING」塊中解析出字符串,把它們放到一個.resx文件本地化以及一個單獨的C#COM對象,以便從具有後備功能的本地化資源文件加載它們。如果C#對象不可用(或無法加載),我將回退到代碼中的字符串。宏展開爲一個模板類,它調用COM對象並進行格式化等。

無論如何,我認爲添加我現在可以參考的內容會很有用。

回答

0

在一個項目中,我已經將其本地化爲10多種語言,我將所有要本地化的資源都放入一個純資源專用的dll中。在安裝的時候,用戶選擇了與他們的應用程序一起安裝的dll。

我只需將英文版dll發送給本地化團隊。他們爲我編譯的每種語言都返回了本地化的dll。

我知道這不是完美的,但它的工作。

+0

你有沒有想辦法做到這一點,而不用代碼中的資源ID替換字符串?你所描述的聽起來像口語方法,這當然可以工作,但並不真正在尋找什麼。 – Nick 2008-10-08 23:19:19

+0

不,我們不會將字符串硬編碼到我們的應用程序中。我們所看到的是一個與資源ID相關的描述性常量。 – BoltBait 2008-10-08 23:26:16

1

我不太瞭解Windows通常如何實現這一功能,但本地化字符串在Apple的Cocoa framework中的處理方式非常有效。他們有一個非常基本的文本格式文件,您可以將其發送給翻譯器,以及一些預處理器宏來從文件中檢索值。

在你的代碼中,你會看到你的母語中的字符串,而不是不透明的ID。

+0

這基本上是我在找的東西,但是在與純C++(沒有框架)協同工作的東西中。 – Nick 2008-10-08 23:29:12

+0

是的,我想它可能就像你要找的東西。不幸的是,我不知道這樣的設計有任何純C++版本,但對我來說似乎並不像寫這樣的程序很困難。關鍵的簡化有一個「生成器」工具來掃描源文件和創建文件。 – 2008-10-08 23:32:49

3

我們使用英文字符串作爲ID。

如果從國際資源對象(從安裝的I18N DLL加載)查找失敗,那麼我們默認爲ID字符串。

代碼如下所示:

doAction(I18N.get("Press OK to continue")); 

作爲構建過程的一部分,我們有一個分析所有源字符串常量Perl腳本。它構建應用程序中所有字符串的臨時文件,然後將這些文件與每個本地資源字符串進行比較,以查看它們是否存在。任何缺少的字符串會生成電子郵件給相應的翻譯團隊。

我們可以爲每個本地有多個dll。 DLL的名稱是基於RFC 3066
語言[_territory] ​​[。代碼集] [@修飾符]

我們嘗試從機器中提取的語言環境和加載國際化DLL時要儘可能具體,但回落如果更具體的版本不存在,則將其應用於較不特定的本地變體。

例子:

在英國:如果本地是en_GB.UTF-8
(我用這個詞鬆散DLL不是在特定的Windows意義上的)。

首先查找I18N.en_GB.UTF-8 dll。如果這個DLL不存在,請回退到I18N.en_GB。如果該DLL不存在回落到I18N.en如果該DLL不存在下跌貝克I18N.default

唯一的例外是: 簡體中國(zh_CN的),其中回退是美國英語(en_US)。如果機器不支持簡體中文,那麼它不太可能支持全中文。

0

既然它是開放的意見,這裏是我如何做到這一點。

我的本地化文本文件是一個簡單的製表符分隔的文本文件,可以在Excel中加載和編輯。 第一列是用於定義和每一列到右邊的是隨後的語言,例如:

ID    ENGLISH  FRENCH GERMAN 
STRING_YES  YES   OUI  YA 
STRING_NO  NO   NON  NEIN 
在我生成文件

然後是一個cusom生成步驟,其生成strings.h文件和一個strings.dat 。在我的情況下,它爲字符串ID構建一個枚舉列表,然後爲文本創建一個帶有偏移量的二進制文件。由於在我的應用程序中,用戶可以隨時更改語言,我可以隨時將它們全部存儲在內存中,但如果需要,您可以輕鬆地讓預處理器爲每種語言生成不同的輸出文件。

我喜歡這個設計的事情是,如果任何字符串丟失,那麼我會得到一個編譯錯誤,而如果在運行時查找字符串,那麼你可能不知道在很少使用的部分代碼,直到後來。

0

你想要一個我一直想寫但從未有過的高級實用程序。 如果你沒有找到這樣的工具,你可能想要回退到我的CMsg()和CFMsg()包裝類,這些類允許非常容易地從資源表中抽取字符串。(CFMsg甚至提供了一個FormatMessage單行包裝 是的,如果沒有你想要的工具,在註釋中保留一個字符串的副本是一個很好的解決方法。關於註釋的不同步,請記住字符串文字都很少改變。

http://www.codeproject.com/KB/string/stringtable.aspx

BTW,原生Win32程序和.NET程序有一個完全不同的資源存儲管理。你將有一個很難找到兩個共同的解決方案。

1

你解決方案與Unix/Linux「gettext」解決方案非常相似,實際上,您不需要編寫提取routi網元。

我不知道你爲什麼要_RESTRING宏來處理多個參數。我的代碼(使用wxWidgets對gettext的支持)如下所示:MyString.Format(_("Some string with variable %ls"), _("variable"));。也就是說,String :: Format(...)獲取兩個單獨轉換的參數。事後看來,升壓::格式會更好,但它也將允許boost::format(_("Some string with variable %1")) % _("variable");

(我們使用_()宏簡潔)

1

最簡單的方法是在你的代碼只使用字符串ID - 沒有字面字符串。 然後,您可以爲每種語言生成不同版本的.rc文件,並創建僅資源DLL或簡單地構建不同的語言版本。

有一對夫婦共享utilstohelp其本地化調整處理與失蹤的翻譯不再言語和語言warnign對話框元素的RC文件。

一個更復雜的問題是語序,如果在printf中有幾個數字,它必須按不同語言的語法順序排​​列。 codeproject上有一些擴展的printf類,可以讓您指定諸如printf(「word%1s和%2s」,var1,var2)之類的東西,以便在必要時切換%1s和%2s。