转chromeUI3

国际化

不可否认,Chrome的国际化做的非常优秀,在Chrome中添加一种新的语言支持非常方便。

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<

















  <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>

删除(&R)
此网站的安全证书已过期!
导入
DE<
或者

DE<
<!DOCTYPE translationbundle>

Simsun
84%
default
DE<
两者区别主要是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<

当用户需要使用图片时,可以参考如下代码:

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

include "chrome_exe_version.rc"

endif DE<

posted @ 2016-03-14 18:14 kevinzhwl 阅读(...) 评论(...) 编辑 收藏