标签:程序 ade code 哈希表 original 位置 完成 研究 根据
.mo
文件是.po
文件经msgfmt
编译后生成的翻译文件, 便于程序阅读. 我这段时间折腾了下i18n, 根据Gettext的文档研究了一下Mo文件的结构, 在C#上实现了mo文件的解析和浏览, 现把.mo的结构和基于Winform实现的Mo查看器分享给大家.
整型均为4字节(Int32), 下面不再标注
位置 | 标识 | 说明 |
---|---|---|
0 | Magic | 用于识别Mo文件, 值为0x950412de 或0xde120495 |
4 | Major&Minor Revision | 两个16位整型组成的版本号. |
8 | N | 文本数量 |
12 | O (Original) | 源文本信息位置 |
16 | T (Translation) | 译文信息位置 |
20 | S (hashtable Size) | 哈希表大小 |
24 | H (hashtable Offset) | 哈希表位置 |
... | ... | 这里以后可能会有更多的头部信息... |
O | string 0 - Len&Offset | (4字节+4字节, 下同)第一条源文本的长度和位置 |
O + 8 | string 1 - Len&Offset | 第二条源文本的长度和位置 |
... | ... | ... |
O+(N-1)*8 | string (N-1) - Len&Offset | 第N条源文本的长度和位置 |
T | translation 0 - Len&Offset | 第一条翻译的长度和位置 |
T + 8 | translation 1 - Len&Offset | 第二条翻译的长度和位置 |
... | ... | ... |
T + (N-1)*8 | translation (N-1) - Len&Offset | 第N条翻译的长度和位置 |
H | hash table | 哈希表区(H ~ H+S*4) |
* | * | 文本区 |
开头的Magic用作Mo格式文件的标记, 值为固定的0x950412de
或0xde120495
(大端小端的区别), 如果检测到起始4字节不是这两个值的话就可以报error了;
之后的2字节+2字节是主次版本号, 目前主版本号为1或0, 次版本号为1或0;
接下来便可以读到文本数量N
, 源文本信息起始位置O
和译文信息起始位置T
. 这里可以获取到每串文本的长度和位置, 进而跳转到指定位置, 读指定长度的字节流, 然后转成字符串即可.
msgfmt
生成Mo文件时, 会把文本串的顺序按照ASCII重新排序. (这样也保证了头部信息是第一条文本)--no-hash
, 不指定它的话, msgfmt
会生成由源文本得到的哈希表. 这有利于实际使用时的查找. 指定--no-hash
可以减小.mo
文件体积, 此时S
的值为0.? 每一条文本串以‘\0‘结尾, 文本信息的Len不包含这个‘\0‘. 如果没有复数文本串的话, 可以通过‘\0‘来完成字符串的读取. 但是有复数的话就不可以了, 复数文本串以‘\0‘分隔, 放在一个文本串里.
? 举个例子, 源文本 File removed
, 复数Files removed
. 那么这个源文本串在文件中的格式:
File removed\0Files removed\0
^ ^ ^
Offset NUL Offset+Len
? 于是就可以从Offset位置读Len长度的字节, 如果字节串里有‘\0‘就说明是复数文本. 然后就可以用相同方式处理译文串了.
? 这个是研究i18n的时候顺手做的, 用C#实现了Mo的解析和查看, 丢到Github上了 刚开始做的时候以为指定了--no-hash
就可以按照Po的文本顺序生成Mo的...后来发现并不会, 所以无法还原出原有的文本串顺序. 不过排序后的字符串方便定位和查找, 如果你的电脑没安装Poedit, 又只想查看Mo的话可以试试: Github
标签:程序 ade code 哈希表 original 位置 完成 研究 根据
原文地址:https://www.cnblogs.com/zaevi/p/mo-structure.html