Tags : chromium grit grd pak
1. 关于资源
任何应用都有一些自身持有的资源,如UI上的按钮,特定的页面,或者是针对不同系统语言设置的不同字符串。这些必然需要通过一个通用的方式集成到应用当中。
Chromium,包括android webview或者同名浏览器,它的资源大致包括两个部分
- 图片,CSS,JS,HTML,用于浏览器本身或者辅助浏览
- 多国语言本地化字符串
这些资源统一以*.pak形式的文件存放于apk中(assets文件夹中)。其中
Android SystemWebView中为webviewchromium.pak
ChromiumPublicApk则为chrome_100_percent.pak与resources.pak
为了生成pak文件,我们除了需要需要打包的源文件外,还需要grd配置文件以及grit工具进行打包。
GRIT 全名为 the Google Resource and Internationalization Tool。该工具可以于chromium项目代码的src/tools/grit/该路径下找到。
使用方法如下:
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.
-h MODULE Causes GRIT to use MODULE.UnsignedFingerPrint instead of
grit.extern.FP.UnsignedFingerprint. MODULE must be
available somewhere in the PYTHONPATH search path.
-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.
buildinfo Determine what files will be needed and
output by GRIT with a given input.
count Count the number of times a given message ID is used.
newgrd Create a new empty .grd file.
rc2grd A tool for converting .rc source files to .grd files.
resize Generate a file where you can resize a given dialog.
sdiff View differences without regard for translateable portions.
transl2tc Import existing translations in RC format into the TC
unit Use this tool to run all the unit tests for GRIT.
xmb Exports all translateable messages into an XMB file.
android2grd Converts Android string.xml files into Chrome grd files.
For more information on how to use a particular tool, and the specific
arguments you can send to that tool, execute 'grit help TOOL'
而grd文件则是一个标准xml文档,结构会在下面的内容里详述。
2. 打包多国语言本地化字符串资源
多国语言本地化字符串,首先我们需要准备grd文件作为配置文件。
如果你是需要新建一个grd以及一个新的打包,推荐可以使用下列命令用grit生成一个空的grd文件模板来进行设计。
$ python ./src/tools/grit/grit.py newgrd
a.grd配置文件
这里我们以android_ui_strings.grd为例
grd的基本结构如下
最外层node为
<grit current_release="1" latest_public_release="0">
...
</grit>
多国语言需要在grit的node中添加下列三类
<outputs>
<translations>
<release>
(1).outputs
outputs主要描述输出的文件,一般都为.h头文件用以描述具体id号,以及具体的资源打包文件pak文件。
<outputs>
<output filename="grit/aw_strings.h" type="rc_header">
<emit emit_type='prepend'></emit>
</output>
<output filename="aw_strings_am.pak" type="data_package" lang="am" />
<output filename="aw_strings_ar.pak" type="data_package" lang="ar" />
...
</outputs>
无非就是两类,rc_header和data_package,其中data_package需要描述具体语言
(2).translations
translations主要定义了具体语言的翻译模板
<translations>
<file path="translations/aw_strings_am.xtb" lang="am" />
<file path="translations/aw_strings_ar.xtb" lang="ar" />
...
</translations>
这里指定了grit生成具体pak的输入文件有那些xtb文件。
这些xtb的格式都是固定的,会在下一个小节进行详细说明。
(3).release
release是描述提供的具体字符串
<release seq="1">
<messages fallback_to_english="true">
<message name="IDS_AW_WEBPAGE_NOT_AVAILABLE" desc="The title of the webpage shown when the requested URL in unavailable">
Webpage not available
</message>
...
</messages>
</release>
如上述格式,其中message为具体字符串内容,包含有name和desc两个属性
name为该字符串资源的id,该id也会在之前生成的头文件中体现,一般都以IDS开头然后全大写(因为之后是要在h头文件中进行define作为宏名的)
desc则是描述下该资源是干什么用的
b. xtb文件
xtb(translationbundle)文件是提供每个语言翻译字段的具体输入源
这些文件需要和grd作为输入给grit来生成具体资源文件。
每个xtb文件结构都是一致的如下所示:
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="zh-CN">
<translation id="1555130319947370107">蓝色</translation>
<translation id="161042844686301425">青色</translation>
...shuxie
</translationbundle>
这里有一个问题,每一个翻译具体的id不是之前在grd的name,而是具体的hash值
我们该如何获得这个hash值呢?
现在知道的方法是使用grit的xmb工具来生成具体hash,然后再套用到这个xtb模板。
执行以下命令:
$ python ./tools/grit/grit.py -i YOUR_GRD_FILE xmb OUTPUT_XMB_FILE_PATH
其中GRD_FILE为需要翻译的grd文件路径
OUTPUT_XMB_FILE_PATH指定输出的XMB放的位置
xmb文件本身不参与到最后的打包过程,所以随便放个临时位置都行
其中找到messagebundle node中具体的每个msg
<messagebundle>
<msg desc="Accessibility label for button to select the blue color." id="1555130319947370107">
Blue
</msg>shuxie
<msg desc="Accessibility label for button to select the cyan color." id="161042844686301425">
Cyan
</msg>
...
我们就可以看到具体的id值了,然后按照上述xtb的模板按部就班填写id以及各个语言翻译字段即可
PS: 个人感觉应该不会需要生成XMB然后再手工填写XTB的具体transaction的message id值。
可能会存在直接输出XTB文件的工具,但是grit似乎没有提供。
c.生成翻译文件
准备好了xtb文件和grd配置文件后,就可以执行grit进行构建具体的翻译文件了
$ python ./src/tools/grit/grit.py -i ./src/ui/android/java/strings/android_ui_strings.grd build -o ~/output/
输出到output文件夹下我们就可以看到
├── values
│ └── android_ui_strings.xml
├── values-am
│ └── android_ui_strings.xml
├── values-ar
│ └── android_ui_strings.xml
....
当然我们在chromium中使用的是pak打包好的资源文件。
分析android_ui_string.grd在BUILD.gn中的build我们可以发现,多国语言本地化字符串使用了一个名为"java_strings_grd"的gn template。这一步就只是完成了grit生成xml的过程。
然后通过android_resources的gn template去完成打包的工作。
具体书写可以详细参考android_ui_string的流程。这里不再一一赘述。
3. 打包非语言资源
除了本地化字符串外,grit还提供打包其他诸如图片,css,js,html等资源的功能。
我们以system_webview_apk中实际打包的load_error.html为例说明
首先我们也需要准备一个grd配置文件
与上述本地化字符串的grd文件有区别的地方在于
- 没有translations element,因为不需要指定翻译语言内容
- release中不是message,而是一个个includes或者是structures
关于上述2中,资源文件是BMP,GIF,具体HTML这种资源时使用includes
而结构资源类似HTML模板,菜单,对话框等,则是使用structures
这里我们就是用includes,以下列方式进行书写
<includes>
<include name="IDR_AW_LOAD_ERROR_HTML" file="resources\load_error.html" flattenhtml="true" type="BINDATA" />
</includes>
其中type只要进入rc文件分类的,rc文件是windows MFC的资源文件
name:和之前一样设置该资源名字,当然不能重名,以及以IDS开头并且一般全大写
file:这个资源文件路径,相对于这个grd文件
注意include这个node没有body
都准备妥当后,使用grit的gn template进行打包,一步完成
grit("generate_aw_resources") {
source = "ui/aw_resources.grd"
outputs = [
"grit/aw_resources.h",
"aw_resources.pak",
]
}