不可否認,Chrome的國際化做的非常優秀,在Chrome中添加一種新的語言支持非常方便。
http://www.chromium.org/developers/design-documents/ui-localization
Locale 項目
如果使用virtual studio 2008打開chrome for windows的工程,可以看到如下的項目:
其中每一個項目對應一種語言支持,所以如果需要添加新的語言支持,只需要新建一個新的語言項目。
實際上,每一個語言項目內的所有文件都是編譯生成的中間文件,在文件夾【src\chrome\app\locales】中存放了這所有的項目文件,但每一個項目僅僅存在一個vcproj文件,例如zh-CN.vcproj,項目中包含的文件實際存在於【src\chrome\Debug/Release\grit_derived_sources】目錄下。那這些文件怎麼生成的呢,這需要了解一下google自己開發的一個python項目。
GRIT 軟件
該項目的源碼在目錄【src\tools\grit】下,全部使用python語言。該目錄下的readme是這麼說的:
GRIT (Google Resource and Internationalization Tool) is a tool for Windows projects to manage resources and simplify the localization workflow. |
在命令行輸入命令【python grit.py】(該文件是整個grit的入口)有如下輸出
GRIT - the Google Resource and Internationalization Tool Copyright (c) Google Inc. 2009
Usage: grit [GLOBALOPTIONS] TOOL [args to tool]
Global options:
-i INPUT Specifies the INPUT file to use (a .grd file). If this is not specified, GRIT will look for the environment variable GRIT_INPUT. If it is not present either, GRIT will try to find an input file named 'resource.grd' in the current working directory.
-v Print more verbose runtime information.
-x Print extremely verbose runtime information. Implies -v
-p FNAME Specifies that GRIT should profile its execution and output the results to the file FNAME.
Tools:
TOOL can be one of the following: build A tool that builds RC files for compilation. newgrd Create a new empty .grd file. rc2grd A tool for converting .rc source files to .grd files. transl2tc Import existing translations in RC format into the TC sdiff View differences without regard for translateable portions. resize Generate a file where you can resize a given dialog. unit Use this tool to run all the unit tests for GRIT. count Exports all translateable messages into an XMB file.
For more information on how to use a particular tool, and the specific arguments you can send to that tool, execute 'grit help TOOL' |
有興趣可以研究一下代碼,python還是很有趣的東東!!!
grit接收一個輸入文件,然後生成項目所需的.h和.rc等文件。當然輸出什麼文件需要用戶在輸入文件中指定。
Grd文件
grit接收grd類型的文件作爲輸入,然後根據輸入文件中的指定輸出匹配的文件。locale相關的輸入文件存放在目錄【src\chrome\app\resources】下,最關鍵的幾個文件是【locale_settings.grd】和【generated_resources.grd】(此文件放在目錄src\chrome\app下,個人覺得放那很詭異)。在chrome中有若干項目僅僅包含grd文件並將其生成目標文件,而其他一些項目則依賴這些文件。chrome_strings項目就如此。它就將相關的grd文件生成locale下各種語言項目依賴的.h和.rc文件。
所有grd文件都是一個xml文件,格式都符合grit的一個規範,下面是【generated_resources.grd】的部分內容:
DE<<?xml version="1.0" encoding="UTF-8"?> |
說明:
-
Output節表示輸出文件,例如上面的文件會生成一個 generated_resources.h、若干rc文件(generated_resources_zh-CN.rc)和若干pak文件(generated_resources_zh-CN.pak)。
-
Translations節表示翻譯文件,一般來說每一種支持的語言都應該有一個翻譯文件。
-
Messages節表示定義的默認字符串(不同的grd文件有不同的作用,其他文件的message節裏面的內容不一定是字符串,也可能是其他類型。),
當grit解析收到locate 相關的grd文件時,首先生成默認的資源文件,這裏默認的資源文件是“en-US”。當發現Output節有其他語言的輸出時,則查找對應的xtb翻譯文件,如果grd文件中的message選項指定需要翻譯,則通過message中的name屬性查找xtb中對應的record,然後將替換之。
在grd文件中有很多可選的選項,具體可以參考chrome自帶的grd文件或者grit源代碼。目前本人未找到google官方的幫助文檔。
Xtb文件也是一個xml文件,典型的內容格式如下:
DE<<?xml version="1.0" ?> |
DE<<?xml version="1.0" ?> |
兩者區別主要是ID的表示方式。後者ID和grd中的name是一致的,而前者則通過某種算法將grd中的name轉換爲由數字組成的ID。
Grd文件的編譯
chrome通過添加“自定義編譯規則(Custom Build Rules)”來通過vs2008自動編譯所有自定義格式文件。例如grd文件的規則如下:
如圖所示,grd使用一個bat文件編譯,並且提供兩個參數。正如前面提到的,第二個參數就是目標文件的輸出路徑。
該bat文件的內容如下:
:: Batch file run as build command for .grd files :: The custom build rule is set to expect (inputfile).h and (inputfile).rc :: our grd files must generate files with the same basename. @echo off
setlocal
… 忽略 …
:: Put cygwin in the path call %SolutionDir%\..\third_party\cygwin\setup_env.bat
%SolutionDir%\..\third_party\python_24\python.exe %SolutionDir%\..\tools\grit\grit.py -i %InFile% build -o %OutDir% %PreProc1% %PreProc2% %PreProc3% %PreProc4% %PreProc5 |
從上面內容可以發現,chrome將python解釋器直接放到源碼【src\third_party\python_24】裏。然後通過它調用grit.py文件實現文件的編譯。
關於grd的自定義編譯規則文件可以查看文件【src\tools\grit\build\grit_resources.rules】。 msdn上【http://msdn.microsoft.com/en-us/library/03t8bzzy.aspx 】也許有些幫助。
Locale初始化
當通過grd文件生成locale下語言項目依賴的文件後,Chrome將這些項目打包生成一個語言Dll,這些Dll可以在目錄【src\chrome\Debug/Release\locales】下找到。當Chrome啓動時,它會通過某種途徑查找locale類型,然後找到對應的Dll來load。
Chrome查找locale類型通過【src\chrome\common\l10n_util.h】的GetApplicationLocale函數實現。
該函數首先檢查命令行有沒有通過“--lang”指定locale,如果沒有,則檢查當前的配置文件中是否指定locale。如果未指定,則獲取操作系統的locale,如果再獲取失敗,則使用默認的en-US。當然在返回之前,Chrome總會檢查當前的語言文件目錄是否存在該語言的Dll。
chrome自己弄了一套本地配置系統,下面是一個典型的配置文件格式,內容爲語言選項
{ "intl": { "app_locale": "zh-CN" } } |
當找到locale後,chrome通過【src\chrome\common\resource_bundle_win.cc】中的LoadResources函數加載對應的Dll。
國際化小結
當程序中需要使用多國語言的字符串時,可以參考下面的代碼
DE<ResourceBundle &rb = ResourceBundle::GetSharedInstance(); |
其中 IDS_ABCDEFG就是定義在grd中的name 。
Chrome中有兩個grd文件比較重要:
-
src\chrome\app\generated_resources.grd :該文件定義了多國語言字符串(string),例如按鈕的文字,窗口的標題等。
-
src\chrome\app\resources\locale_settings.grd :該文件定義了多語言配置,例如窗口的大小,某些控件的尺寸。考慮到不同語言的字符串差異,同一個窗口在不同語言下要求的寬度等參數可能不一樣。此外還包含字體的大小、名稱等。
UI主題
UI主題和國際化一樣,同樣適用grit 將grd翻譯成目標文件,然後再生成主題Dll。生成主題的grd文件是【src\chrome\app\theme\theme_resources.grd】。該文件在項目chrome_resources中。該項目生成的rc文件被項目theme_dll使用並生成一個主題Dll。
主題Dll在目錄【src\chrome\Debug/Release\themes】下。在我這個chrome源碼版本中,只有一個主題Dll。名字爲“default.dll”。這個Dll在【src\chrome\common\resource_bundle_win.cc】中的函數LoadThemeResources()被load。
主題通常都由一些圖片組成,這些圖片存放在目錄【src\chrome\app\theme】下,基本上時png圖片格式。
這些圖片通過theme_resources.grd 來生成dll。這個文件的部分格式如下:
DE<<?xml version="1.0" encoding="UTF-8"?> |
當用戶需要使用圖片時,可以參考如下代碼:
DE<ResourceBundle &rb = ResourceBundle::GetSharedInstance(); |
其中 IDR_ABCDEFG爲在 theme_resources.grd中每一張圖片分配的name。
Chrome的版本信息
如果查看項目生成的chrome.exe、chrome.dll文件的屬性,可以發現如下:
實際上這些參數通過項目chrome_exe、chrome_dll中的一個.rc.version文件來獲取,之所以講這些是因爲.rc.version的處理和前面提到的grd文件有異曲同工之妙。version文件典型的內容如下:
///////////////////////////////////////////////////////////////////////////// // // Version // ... 省略 ... BEGIN VALUE "CompanyName", "@COMPANY_FULLNAME@" VALUE "FileDescription", "@PRODUCT_FULLNAME@" VALUE "FileVersion", "0.0.0.0" VALUE "InternalName", "chrome_exe" VALUE "LegalCopyright", "@COPYRIGHT@" ... 省略 ... END END ... 省略 ... END
|
version文件的編譯
Version文件的編譯命令如下:
D:\chrometrunk\chrometrunk\src\chrome\/../chrome/tools/build/win/version.bat "D:\chrometrunk\chrometrunk\src\chrome\/../chrome/" "D:\chrometrunk\chrometrunk\src\chrome\Debug\obj\chrome_exe" "D:\chrometrunk\chrometrunk\src\chrome\Debug\obj\chrome_exe/chrome_exe_version.rc" |
此類型的編譯規則文件見【src\chrome\tools\build\win\version.rules】。該規則的核心就是version.bat文件。
version.bat的內容如下:
:: Batch file run as build command for vers.vcproj @echo off
setlocal
set InFile=%~1 set SolutionDir=%~2 set IntDir=%~3 set OutFile=%~4 set VarsBat=%IntDir%/vers-vars.bat
:: Put cygwin in the path call %SolutionDir%\..\third_party\cygwin\setup_env.bat
:: Load version digits as environment variables cat %SolutionDir%\VERSION | sed "s/\(.*\)/set \1/" > %VarsBat%
:: Load branding strings as environment variables set Distribution="chromium" if "%CHROMIUM_BUILD%" == "_google_chrome" set Distribution="google_chrome" cat %SolutionDir%app\theme\%Distribution%\BRANDING | sed "s/\(.*\)/set \1/" >> %VarsBat%
set OFFICIAL_BUILD=0 if "%CHROME_BUILD_TYPE%" == "_official" set OFFICIAL_BUILD=1
:: Determine the current repository revision number set PATH=%~dp0..\..\..\..\third_party\svn;%PATH% svn.exe info | grep.exe "Revision:" | cut -d" " -f2- | sed "s/\(.*\)/set LASTCHANGE=\1/" >> %VarsBat% call %VarsBat%
::echo LastChange: %LASTCHANGE%
:: output file cat %InFile% | sed "s/@MAJOR@/%MAJOR%/" ^ | sed "s/@MINOR@/%MINOR%/" ^ | sed "s/@BUILD@/%BUILD%/" ^ | sed "s/@PATCH@/%PATCH%/" ^ | sed "s/@COMPANY_FULLNAME@/%COMPANY_FULLNAME%/" ^ | sed "s/@COMPANY_SHORTNAME@/%COMPANY_SHORTNAME%/" ^ | sed "s/@PRODUCT_FULLNAME@/%PRODUCT_FULLNAME%/" ^ | sed "s/@PRODUCT_SHORTNAME@/%PRODUCT_SHORTNAME%/" ^ | sed "s/@PRODUCT_EXE@/%PRODUCT_EXE%/" ^ | sed "s/@COPYRIGHT@/%COPYRIGHT%/" ^ | sed "s/@OFFICIAL_BUILD@/%OFFICIAL_BUILD%/" ^ | sed "s/@LASTCHANGE@/%LASTCHANGE%/" > %OutFile%
endlocal |
注意上述紅色標示的部分
VERSION 部分是獲取Chrome預先寫好的版本參數文件【src\chrome\VERSION】,內容如下
MAJOR=2 MINOR=0 BUILD=175 PATCH=0 |
BRANDING 部分是獲取Chrome預先寫好的公司參數文件【src\chrome\app\theme\chromium\BRANDING】,內容如下
COMPANY_FULLNAME=The Chromium Authors COMPANY_SHORTNAME=The Chromium Authors PRODUCT_FULLNAME=Chromium PRODUCT_SHORTNAME=Chromium COPYRIGHT=Copyright (C) 2006-2009 The Chromium Authors. All Rights Reserved. |
如果熟悉Linux的話,估計不會對sed這條命令陌生。這條命令存在與目錄【src\third_party\cygwin】中。sed命令將上述兩個文件的內容經過處理,在每一行之前加入set。然後輸出到%VarsBat%文件【src\chrome\Debug\obj\chrome_exe\vers-vars.bat】中。最終 vers-vars.bat文件的格式類似【set MAJOR=2】。很顯然,當執行這個bat,即把所有的參數添加的環境變量了。
最後一條命令將version文件中【%***%】替換成同名環境變量的值,並輸出到一個rc文件【src\chrome\Debug\obj\chrome_exe/chrome_exe_version.rc"】中。
最後在chrome_exe項目的rc文件【src\chrome\app\chrome_exe.rc】中,【chrome_exe_version.rc】被include進去。源碼如下:
DE<#else // APSTUDIO_INVOKED |