chrome UI 學習筆記3--國際化 (轉)

不可否認,Chrome的國際化做的非常優秀,在Chrome中添加一種新的語言支持非常方便。

http://www.chromium.org/developers/design-documents/ui-localization

Locale 項目

如果使用virtual studio 2008打開chrome for windows的工程,可以看到如下的項目:

chrome UI 學習筆記3--國際化 - yolcy - 寫着玩

其中每一個項目對應一種語言支持,所以如果需要添加新的語言支持,只需要新建一個新的語言項目。

實際上,每一個語言項目內的所有文件都是編譯生成的中間文件,在文件夾【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文件。

chrome UI 學習筆記3--國際化 - yolcy - 寫着玩

所有grd文件都是一個xml文件,格式都符合grit的一個規範,下面是【generated_resources.grd】的部分內容:



DE<<?xml version="1.0" encoding="UTF-8"?>

<!-- This file contains definitions of resources that will be translated for
each locale. -->

<grit base_dir="." latest_public_release="0" current_release="1"
      source_lang_id="en" enc_check="m&#246;l">
  <outputs>
    <output filename="grit/generated_resources.h" type="rc_header">
      <emit emit_type='prepend'></emit>
    </output>
    <output filename="generated_resources_zh-CN.rc" type="rc_all" lang="zh-CN" />
    <output filename="generated_resources_zh-TW.rc" type="rc_all" lang="zh-TW" />
    <output filename="generated_resources_zh-CN.pak" type="data_package" lang="zh-CN" />
    <output filename="generated_resources_zh-TW.pak" type="data_package" lang="zh-TW" />
  </outputs>
  <translations>
    <file path="resources/generated_resources_zh-CN.xtb" lang="zh-CN" />
    <file path="resources/generated_resources_zh-TW.xtb" lang="zh-TW" />
  </translations>
  <release seq="1" allow_pseudo="false">
    <messages fallback_to_english="true">
      <!-- TODO add all of your "string table" messages here. Remember to
      change nontranslateable parts of the messages into placeholders (using the
      <ph> element). You can also use the 'grit add' tool to help you identify
      nontranslateable parts and create placeholders for them. -->

      <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>
  </release>
</grit>DE<

說明:

  1. Output節表示輸出文件,例如上面的文件會生成一個 generated_resources.h、若干rc文件(generated_resources_zh-CN.rc)和若干pak文件(generated_resources_zh-CN.pak)。

  2. Translations節表示翻譯文件,一般來說每一種支持的語言都應該有一個翻譯文件。

  3. 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" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zh-CN">
<translation id="6779164083355903755">刪除(&amp;R)</translation>
<translation id="3581034179710640788">此網站的安全證書已過期!</translation>
<translation id="8275038454117074363">導入</translation>
</translationbundle>DE<

或者

DE<<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zh-CN">
<translation id="IDS_WEB_FONT_FAMILY">Simsun</translation>
<translation id="IDS_WEB_FONT_SIZE">84%</translation>
<translation id="IDS_UI_FONT_FAMILY">default</translation> 
</translationbundle>DE<

兩者區別主要是ID的表示方式。後者IDgrd中的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

從上面內容可以發現,chromepython解釋器直接放到源碼【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類型,然後找到對應的Dllload

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文件比較重要:

  1. src\chrome\app\generated_resources.grd :該文件定義了多國語言字符串(string),例如按鈕的文字,窗口的標題等。

  2. 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"?>
<grit latest_public_release="0" current_release="1">
  <outputs>
    <output filename="grit/theme_resources.h" type="rc_header">
      <emit emit_type='prepend'></emit>
    </output>
    <output filename="theme_resources.rc" type="rc_all" />
    <output filename="theme_resources.pak" type="data_package" />
  </outputs>
  <release seq="1">
    <includes>
      <include name="IDR_BACK" file="back.png" type="BINDATA" />
      <include name="IDR_BACK_D" file="back_d.png" type="BINDATA" />
    </includes>
  </release>
</grit>DE<


當用戶需要使用圖片時,可以參考如下代碼:


DE<ResourceBundle &rb = ResourceBundle::GetSharedInstance();
    SkBitmap* img_ = rb.GetBitmapNamed(IDR_ABCDEFG);DE<


其中 IDR_ABCDEFG爲在 theme_resources.grd中每一張圖片分配的name


Chrome的版本信息

如果查看項目生成的chrome.exechrome.dll文件的屬性,可以發現如下:

chrome UI 學習筆記3--國際化 - yolcy - 寫着玩

實際上這些參數通過項目chrome_exechrome_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

#include "chrome_exe_version.rc"
#endif DE<

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章