國際化python
不能否認,Chrome的國際化作的很是優秀,在Chrome中添加一種新的語言支持很是方便。git
Locale 項目算法
若是使用virtual studio 2008打開chrome for windows的工程,能夠看到以下的項目:
chrome UI 學習筆記3--國際化 - yolcy - 寫着玩chrome
其中每個項目對應一種語言支持,因此若是須要添加新的語言支持,只須要新建一個新的語言項目。
實際上,每個語言項目內的全部文件都是編譯生成的中間文件,在文件夾【src\chrome\app\locales】中存放了這全部的項目文件,但每個項目僅僅存在一個vcproj文件,例如zh-CN.vcproj,項目中包含的文件實際存在於【src\chrome\Debug/Release\grit_derived_sources】目錄下。那這些文件怎麼生成的呢,這須要瞭解一下google本身開發的一個python項目。windows
GRIT 軟件安全
該項目的源碼在目錄【src\tools\grit】下,所有使用python語言。該目錄下的readme是這麼說的:app
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 Toolide
Copyright (c) Google Inc. 2009svn
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文件。
chrome UI 學習筆記3--國際化 - yolcy - 寫着玩
全部grd文件都是一個xml文件,格式都符合grit的一個規範,下面是【generated_resources.grd】的部份內容:
DE<
<message name="IDS_SHOWFULLHISTORY_LINK" desc="The label of the Show Full History link at the bottom of the back/forward menu."> Show Full History </message> </messages>
DE<
說明:
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<
<!DOCTYPE translationbundle>
或者
DE<
<!DOCTYPE translationbundle>
二者區別主要是ID的表示方式。後者ID和grd中的name是一致的,而前者則經過某種算法將grd中的name轉換爲由數字組成的ID。
Grd文件的編譯
chrome經過添加「自定義編譯規則(Custom Build Rules)」來經過vs2008自動編譯全部自定義格式文件。例如grd文件的規則以下:
chrome UI 學習筆記3--國際化 - yolcy - 寫着玩
如圖所示,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();
std::wstring str = l10n_util::GetString( IDS_ABCDEFG )DE<
其中 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<
當用戶須要使用圖片時,能夠參考以下代碼:
DE<ResourceBundle &rb = ResourceBundle::GetSharedInstance();
SkBitmap* img_ = rb.GetBitmapNamed(IDR_ABCDEFG);DE<
其中 IDR_ABCDEFG爲在 theme_resources.grd中每一張圖片分配的name。
Chrome的版本信息
若是查看項目生成的chrome.exe、chrome.dll文件的屬性,能夠發現以下:
chrome UI 學習筆記3--國際化 - yolcy - 寫着玩
實際上這些參數經過項目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