Gettext For Flash
I18N(internationalization)在各个领域已经发扬光大了
乖最爱的WP就是使用这种多国语言、国际化的Web应用技术来实现本地化语言支持的
不过乖了解I18N后最想的是怎么在FLASH里实现GNU的基础本地化技术
首先第一个念头就是看WP怎么实现的
WP使用了GNU Gettext PHP外部函数库
根据配置里定义的语言种类,读取相应的语言包MO(Machine Object)文件
如果MO文件存在,则生成一个全局函数提供给应用程序使用,来查找本地化字符
PS:不存在MO文件的时候,也会生成一个相同的全局函数,不过,它的作用就仅仅是返回提供给它的字符串 🙂
MO是二进制文件格式,想到AS3中提供了ByteArray类,乖就激动的一塌呵呵
但是怎么读呢?翻阅了GNU Gettext的技术文档,忽忽,给出一张官方对MO格式的截图,看图说话:)
文档详细请参见:GNU官方文档“GNU gettext utilities – 8 Producing Binary MO Files”的“8.3 The Format of GNU MO Files”节
先别晕呵呵,首先前两个字(32位机1字=4字节)为对MO文件进行鉴别提供依据。
Table of Contents
一、MO格式详解
1、魔术数字
第一个字是魔术数字(为什么叫Magic number呢?)象征本文件为GNU MO files,值为0x950412de或者0xde120495。
这个值为字节存储机制提供依据,目前在各种体系的计算机中通常采用的字节存储机制主要有两种:big-edian和little-endian。 对这两种机制的讨论已经超出了本文的范围,因此简单带过,大家可以自己搜索相关文献:)
读取MO文件发现,前四个字节为0xde、0x12、0x04和0x95(乖使用的平台采用little-endian)
再按照little-endian方式读这个字,则就是0x95 04 12 de,因此我们把0x950412de作为little-endian的标志
把0xde120495作为big-edian的标志,默认以little-endian方式读这个字
读魔术数字时如果等于0x950412de,那么字节存储机制就是little-endian,
若魔术数字等于0xde120495,则说明文件采用的是big-edian。
如果魔术数字为其他数字,恭喜你,读的肯定不是MO文件:)
两种机制对于正确读取其内容至关重要,大家应该已经注意到了,0x950412de和0xde120495,其实四个字节都是一样的,但是排列顺序不同(可以说相反)。
2、文件修订版本号
第二个字是文件修订版本号(file format revision),用来描述当前文件格式的修订版本,目前值是0。
不过官方说未来可能会更改,为了识别文件的新旧版本。 意思就是目前没用罗~~。
3、字符串数量
图中的N字符处存储的是该MO文件中的字符串对总量(原文和译文成一对)。
4、原文表和译文表
图中位置O和T标识出了原文表和译文表在文件中的位置偏移量,在偏移位置上可以找到我们所需的这两个表。
每个表由多个字符串描述符组成,每个字符串描述符由两个32位的整型(总计八个字节)组成,第一个描述字符串的长度,第二个指示该字符串数据在文件中的位置偏移量,注意,读取字符串数据时,应以字节为单位进行读取。
第一个表,即原文表,存储了原文字符串的描述符,它们以词典顺序进行递增排序。
同理,第二个表,即译文表,存储了译文字符串的描述符,但是译文表并行与原文表:要找到相应的译文数据,得访问数组中与译文数组具有相同索引的片段。
对原文字符串进行排序将能方便我们使用简单二进制搜索功能,这对于MO文件不包含有哈希表,或者使用MO文件中的哈希表无实际价值时,是很有用的。因为GNU gettext的PO(Portable Object,通过它生成MO)文件中常包含一个空字符串原文,并将其译文对应为一些系统信息(例如项目名称,语言等等),所以有必要将空字符串和其译文放置在两表起始位置,可以让我们能很方便的立刻找到相关的系统信息。
5、哈希表
图示中的S存储了哈希表的大小,H指示哈希表在文件中的位置偏移量。S值可能为0,此时编译的MO文件中其实并不含有哈希表。表中存储了字符串数组排序的索引。
我们可能更希望MO文件中不存在哈希表,因为它不仅占用额外空间,而且并不能获得很高的运行效率。因此乖在此只对哈希表做下简单的介绍,跳过。
6、复数
复数形式被以复数字符串紧跟在单数字符串后面,使用一个NUL字节分隔它们的方法保存于文件中。
此时,原文表中的字符串描述符的长度为单数和复数字符串长度以及NUL字节之和。当然,只有单数字符串才参与哈希表查找。同时,复数形式的译文,也连续地存储,并以一个NUL字节分隔,译文表中译文的字符串描述符长度也是单数和复数字符串长度以及NUL字节之和。
OK,至此,基础的MO文件格式已经解释完毕,接下来我们开始让FLASH能利用MO文件达到本地化的目的:)
二、Gettext For Flash
注意,本文使用语言为ActionScript 3。
1、准备MO文件
首先,要准备一个MO文件,要有一个MO文件,得要有一个PO文件(Portable Object,别晕)
PO是一个文本格式的文件,格式大致如下(强烈建议使用UTF8编码):
msgid “”
msgstr “”
“Project-Id-Version: Test 简体中文语言包\n”
“POT-Creation-Date: \n”
“PO-Revision-Date: \n”
“Last-Translator: Molay <edwardtsds@126.com>\n”
“Language-Team: Molay’s World <edwardtsds@126.com>\n”
“MIME-Version: 1.0\n”
“Content-Type: text/plain; charset=utf-8\n”
“Content-Transfer-Encoding: 8bit\n”
“X-Poedit-Language: Chinese\n”
“X-Poedit-Country: CHINA\n”
“X-Poedit-SourceCharset: utf-8\n”
msgid “Hello World!”
msgstr “世界,您好!”
msgid “I’m Molay!”
msgstr “我是宇宙超级无敌熊猫眼乖~”
保存为zh_cn.po 下载专门用来编译MO文件的Poedit软件,编译生成MO文件。软件详情和使用方法百度和GOOGLE上N多哈哈,不再累述。
2、读取MO文件
首先使用下列代码将外部MO文件读入并转化为ByteArray实例。
var byteArr:ByteArray;
var url:URLRequest = new URLRequest(“zh_cn.mo”);
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.load(url);
loader.addEventListener(Event.COMPLETE, completeHandler);
function completeHandler(event) {
byteArr = ByteArray(loader.data);
init();
}
到此,解析的准备工作已经完成。
3、解析MO文件
尽管目前我们涉及到的大都是little-endian,但是我们首先还是要判断文件是哪种字节存储机制,先定义两个标识常量
此处我们以0x950412DE作为little-endian标志,并以little-endian作为默认开始读取方式
const littleSign:uint = 0x950412DE;
const bigSign:uint = 0xDE120495;
// 因为默认下byteArr是以big-edian形式读取
// 但是通常情况下大多数使用的是little-endian
// 在此将默认转化为little-endian
byteArr.endian = Endian.LITTLE_ENDIAN;
// 读取第一个字,无符号整型,32bit
var sign = byteArr.readUnsignedInt();
// 如果是big-edian,将byteArr设置回big-edian
if(sign==bigSign){
byteArr.endian = Endian.BIG_ENDIAN;
}
// 读取版本修订号,同样为无符号整型,32bit,当前为0
var revision = byteArr.readUnsignedInt();
// 读取字符串对总数,此处为3,一个空字符串和系统信息对,两个自定义原文和译文对
var total = byteArr.readUnsignedInt();
// 读取原文表位置偏移量
var originalOffset = byteArr.readUnsignedInt();
// 读取译文表位置偏移量
var translationOffset = byteArr.readUnsignedInt();
// 搜索全体原文描述符,首先将ByteArray定位到originalOffset
byteArr.position = originalOffset;
var i, originalTable=[];
for (i=0;i
至此,MO文件中的本地化语言数据已经完全在FLASH中还原,可以做一些事情让它们工作起来了呵呵
三、注意事项
1、首先FLASH默认使用的是big-edian形式
2、如果是网站形式的呈现,请确定您的服务器支持MO文件的下载访问
3、其实同样的功能可以用XML来实现,还更简单,但是XML是以容量来换结构的形式,在大数据容量上XML和MO文件相比就显得太笨拙了
4、下面提供的类中第二个参数是是否缓存,默认下缓存将把全部字符串从字节数组释放至内存的数组中,可以提高查询效率,但是如果是很大的MO文件,建议将其关闭,不然内存耗费量是蛮大的:)
5、版权声明呵呵,转载请注名原出处和作者,谢谢合作:)
最后,乖发布自己弄的Gettext For Flash类库,实现了大部分GNU Gettext的方法,可以供大家方便的使用:)
source here
详细更新请访问:
svn checkout http://gettext-for-flash.googlecode.com/svn/trunk/
如果有任何想法疑问或者BUG,请联系Molay~Enjoy it~ 😉
Filed under: 未分类 - @ 2008年5月1日 上午6:04
这个东西太有用了,学习阿,哈哈
建议写AS用以WP的插件啊,这样看起来太累了。
谢谢分享~~ getText结合做国际化就方便多了.
请教下,flash是否能读取任意二进制格式的文件并还原呢?
hi, 8-t-8
AS3的ByteArray类完全可以做到读取任意二进制文件
至于还原的意思是另存为吧?这点用AIR的FileStream类的相关方法也完全可以做到