最近在学习chromium过程中遇到了chromium的资源,由于chromium对其资源文件进行封装的处理,比较繁琐,特此整理了一下。chromium是一个跨平台的开源项目,所以对资源进行封装的主要目的就是为了摆脱对平台的依赖。
本文主要是针对本地化字符串的翻译和使用方法。
在本人这次学习过程中,主要是针对chromium的本地化,也就是chromium支持多种语言,对于语言的翻译使用了我自己添加的语言文件,这次就是从这些翻译文件的添加和使用来介绍一下过程。
首先,需要创建2个文件:strings.grd,strings.gyp,和一个文件夹:translations/
一、grd文件
strings.grd:其格式是xml,里面使用了几个标签,如下 代码:
<?xml version="1.0" encoding="UTF-8"?> <grit base_dir="." current_release="1" source_lang_id="en"> <outputs> <output filename="grit/strings.h" type="rc_header"> </output> <output filename="strings_ar.pak" type="data_package" lang="ar"/> <output filename="strings_bg.pak" type="data_package" lang="bg"/> ... </outputs> <translations> <file path="translations/strings_ar.xtb" lang="ar" /> <file path="translations/strings_bg.xtb" lang="bg" /> ... </translations> <release seq="1"> <messages fallback_to_english="true"> <message name="IDS_XXX" desc="DESC_xxxxx"> xxxxxx </message> ... </messages> </release> </grit>
在以上的XML文件中,最主要的有三个节点:outputs、translations和messages
outputs:用来配置输出的文件,在将xtb文件解析后,输出到哪个文件中,这个文件名需要我们来指定,生成的文件文件就是我们在chromium需要用到的.pak文件;
translations:用来指定要翻译的各种语言的xtb文件,也就是ouputs的输入文件,xtb文件与pak文件就是一以 lang这个属性对应起来的;
messages:这个下面有一个或者多个message节点,每一个节点表示要翻译的一个字符串内容,每一个字符串有一个唯一的ID,描述,也就是以上的message name,和desc,这个有开发者来指定,必须保证是唯一的。
二、GYP文件
strings.gyp,这个文件是chromium GYP编译文件,其内容格式为json,用来指定编译的环境,其内容如下:
{ 'targets': [ { 'target_name': 'strings','type': 'none','variables': { 'grit_out_dir': 'xxxxxxx',},'actions': [ { 'action_name': 'grenerate_strings','variables': { 'grit_grd_file': 'strings.grd','includes': [ '../../../../build/grit_action.gypi' ],],'direct_dependent_settings': { 'includes_dirs': [ '<(SHARED_INTERMEDIATE_DIR)',] }
以上文件指定了当前的一个模块名字,target_name,以及输出目录等等。
三、XTB文件
然后,在translates文件夹下面,就是我们的一系列xtb文件,文件格式为XML,以某一个语言的xtb文件为例:
<?xml version="1.0" ?> <!DOCTYPE translationbundle> <translationbundle lang="pt"> <translation id="xxxxxxxxxx">Menu</translation> ... </translation>
如以上文件,语言是pt,也就是葡萄牙语,translationbundle这个节点中的子节点,就是一个个需要翻译的字符串,这些都是以当前语言显示的。
在translation节点中,有一个id="xxxxxxxxxxx",这个id是由chromium中的grit工具来生成的,生成过程如下:
首先进入目录src/tools/grit/,然后运行python命令,进入python命令行,然后执行一下命令:
>>> from grit.extern.tclib import GenerateMessageId >>> GenerateMessageId("Menu") '3897092660631435901'
生成的一串数字就是这个Menu的Id,chromium的字符串都是以英语为基础来生成的。
四、ResourceId
到现在还不能编译,chromium会为每一个字符串生成一个唯一的Id,在字符串资源中,而这个id的生成标准是以strings.grd中的message name来生成的,这就是为什么message name要唯一的原因,字符串资源生成id的方式如下:
在src/tools/gritsettings/ 下,有一个叫做resource_ids的名字,我们在末尾指定grd文件,以及一个第一个message的id,然后grd中后续的字符串id就是从第一个id逐个加1:
"content/browser//strings/strings.grd": { "messages": [45020],}
从文件中能看到指定的grd文件,和起始id,这个id值必须在31000之后,31000之前都是chromium中供自己使用的。
chromium的资源文件是在编译之前就会生成的,过程如下:
2.根据grd文件中的message节点,获取各个message的name 和 id,id由resource_ids文件中得到;
3.根据translation节点中指定的xtb文件,对每个message的翻译进行匹配,匹配的依据是上文通过字符串生成的id,如果id与字符串不匹配是不会读入的(本人犯的错);另外,chromium会以英语为默认语言,所以xtb文件中是没有lang="en"的文件的,否则,解析时会报错(本人犯的错);
4.在解析完成一个xtb文件时,会同时根据lang生成output中指定的pak文件。
使用语言本地化的正常流程是,chromium会进行一个系统调用getlocales来获取当前系统的语言,但是我使用的是嵌入式linux系统,没有locale支持,所以我只能使用chromium中的DataPack类来对pak文件进行读取,然后通过字符串的name来获取相应的字符串。