主题插件汉化 如何将po文件编译成(转换)mo文件呢?

po文件简介

po文件本来是用来翻译程序源代码里的字符串的。先来稍微解释一下它本来的用途,需要一点点C语言的基础才能完全理解。如果理解有困难,可以忽略这段内容,不会对我们使用po来翻译造成任何影响。

目前大部分自由软件实现国际化使用的是gettext。国际化就是让程序可以使用多国语言来显示程序里的字符串。程序里一般都有很多字符串,菜单名也好,错误信息也好,都是字符串。假设字符串为string,非国际化的程序里都是直接写"string"。如果用了gettext来实现国际化的话,就要写成gettext("string")。有时也会看到_("string"),那实际上也是gettext,只不过通过宏的定义把gettext改头换面了。这个string就是msgid。然后使用xgettext来从程序源代码文件产生po文件。然后交给专门的翻译人员来翻译po。翻译人员根本不需要懂编程。翻译完毕后,使用msgfmt来把po转化成mo文件,并安装到系统里合适的位置。程序运行时,到底显示什么字符串就是由gettext函数来决定的了。主要有两个决定因素,一个是系统的locale及相关环境变量(LANGUAGE,LC_ALL,LC_MESSAGES和LANG),一个是相关的mo文件。具体可以看我的这篇文章。

随着程序版本的升级,程序里的字符串的数量和内容都会发生变化,但变化不会很大,以前翻译过的po里大部分msgid都能被重复利用。所以维护po 的翻译人员在每次得到从新的程序源代码产生的po时,都用msgmerge来根据旧的已翻译过的po来先处理一下新的未翻译的po。处理过后,大部分情况下新po就翻译的差不多了。翻译人员的工作量被大幅度减轻了。

po文件格式解析

po文件都是由一对对的msgid和msgstr组成的。msgid就是原文。msgstr就是译文。原文译文相互对照,所以非常适于翻译。

  1. msgid"FlashPlayer9released"
  2. msgstr"Flash Player9发布"

有的msgid前面一行有fuzzy的字样。这说明,第一这个po是被msgmerge处理过的;第二,已翻译的po里没有和这个msgid完全等同的msgid,只有非常相似的。这种情况下,msgmerge仍然会用那个相似的msgid来翻译此msgid。不过会给这个msgid标记为 fuzzy,表示翻译人员仍然要翻译这个msgid,并在翻译后去掉上面带fuzzy的这一行。

  1. #,fuzzy
  2. msgid"GentooLinuxPPCHandbook"
  3. msgstr"GentooLinuxAlpha手册"

po文件翻译的好处

1.原文译文相互对照,适于翻译

2.一篇文章里同一个msgid不管出现多少次,都只需要翻译一次

3.旧有的已翻译过的po,可以重复利用,不必再次翻译,且利于统一风格

4.有非常好的翻译工具,熟练使用后可大幅度提高工作效率

应用实例

我们在使用WordPress及其插件时,经常可以找到汉化的版本,一般是通过一个汉化过(翻译过)的mo文件来实现(WordPress仅可识别 mo文件),实际上不单WordPress,包括很多桌面应用程序都是是依靠po文件或mo文件来实现多语言版本。如果原作者提供了一个po文件或mo文件,那么我们就可以通过相关工具来自行汉化,或者翻译成其他语言版本。因为mo文件不能直接编辑,所以我们得编辑po文件,若仅有mo文件,那么就应该先把它转换成po文件后再进行编辑翻译。

至于编辑工具,由于po文件本身就是一个文本文件,所以任何文本编辑器都可以使用。除了专门编辑po文件的poEdit,还推荐使用poEdit、EditPlus、UltraEdit或者你喜欢的vi或vim。

我们来看一个po文件,这是yskin制作的WordPress2.11中文版po文件中的一部分

  1. msgid“”
  2. msgstr“”
  3. “Project-Id-Version:WordPress2.1-1.0\n”
  4. “PO-Revision-Date:2007-02-2212:35+0800\n”
  5. “Last-Translator:yskin\n”
  6. “MIME-Version:1.0\n”
  7. “Content-Type:text/plain;charset=utf-8\n”
  8. “Content-Transfer-Encoding:8bit\n”
  9. “X-Poedit-Basepath:d:/wordpress\n”
  10. “X-Poedit-Language:SimplifiedChinese\n”
  11. “X-Poedit-Country:China\n”
  12. “X-Poedit-SourceCharset:utf-8\n”
  13. “X-Poedit-KeywordsList:_e;__;__ngettext:1,2\n”
  14. “Language-Team:\n”
  15. “POT-Creation-Date:\n”
  16. “Plural-Forms:nplurals=1;plural=0;\n”
  17. “X-Poedit-SearchPath-0:.\n”
  18. #第一条要翻译的字符串。
  19. #:wp-comments-post.php:15
  20. msgid“Sorry,commentsareclosedforthisitem.”
  21. msgstr“对不起,这篇文章禁止评论。”
  22. 上面是这个po文件的最初部分,各行意思一目了然,注意编码尽可能采用UTF-8。
  23. #第一条要翻译的字符串。
  24. #:wp-comments-post.php:15
  25. msgid“Sorry,commentsareclosedforthisitem.”
  26. msgstr“对不起,这篇文章禁止评论。”

这段就是po文件的主体结构了,每一个翻译项占一段。#:wp-comments-post.php:15说明字符串相应的位置;msgid“Sorry,commentsareclosedforthisitem.”翻译前的原文;msgstr“对不起,这篇文章禁止评论。” 翻译后的字符串。以此类推,即可完成所有资源的翻译。非常简单。

那么如何将po文件编译成(转换)mo文件呢?

如果你使用的是poEdit,按Ctrl+s保存就会自动生成相应的po文件和mo文件;

或者在命令提示符界面,使用msgfmtdemo.po命令将po文件编译为可用的demo.mo文件,用msgunfmtdemo.mo命令转回 demo.po文件,这些命令在poEdit的安裝目录下有,可以拷贝msgunfmt.exe、msgfmt.exe及相关链接库文件 gettextlib.dll、gettextsrc.dll、iconv.dll、intl.dll到c:/windows/system32目录下,或者安装.Net2.0环境。

另外推荐一款GUI界面的转化程序po2mo.exe,作者的说明:该程序是调用msgfmt.exe和msgunfmt.exe文件,从而进行po、mo文件互转。文件是用C#写的,需要.Net2.0环境。

[root@bogon~]#msgfmtaaa.po;mvmessages.moaaa.mo;chmod700aaa.mo;chownapache.apacheaaa.mo;restoreconaaa.mo

[root@bogon~]#servicehttpdrestart

++++++++++++++++++++++++++++++++++++++++++

当我在服务器和测试机上都成功部署并能够编译*.po文件后,发现对某些的修改并不能生效例如

  1. #.TRANS:Mainmenuoptionwhenloggedintologoutthecurrentuser
  2. #:lib/action.php:477
  3. #,fuzzy
  4. msgctxt"MENU"
  5. msgid"Logout"
  6. msgstr"登出"

无论我怎么修改,都是显示Logout并没有进行中文的翻译,不知道为什么。找到gettext官网,查看它的文档,发现这么一段话:

fuzzyThisflagcanbegeneratedbythemsgmergeprogramoritcanbeinsertedbythetranslatorherself.Itshowsthatthemsgstrstringmightnotbeacorrecttranslation(anymore).Onlythetranslatorcanjudgeifthetranslationrequiresfurthermodification,orisacceptableasis.Oncesatisfiedwiththetranslation,shethenremovesthisfuzzyattribute.Themsgmergeprograminsertsthiswhenitcombinedthemsgidandmsgstrentriesafterfuzzysearchonly.SeeFuzzyEntries。大概意思:这个标签是由msgmerge这个程序或者翻译人自己所创建。它表示msgstr这个字符串里的内容可能不是正确的翻译。只有翻译者自己能够判断这条记录是否需要做进一步的修改,或者就是正确的翻译。一旦发现这个翻译是正确的,就将fuzzy标签属性删掉。也就是说如果用户你觉得这条翻译是对的,去掉fuzzy那行记录就行了

  1. #:lib/action.php:477
  2. msgctxt"MENU"
  3. msgid"Logout"
  4. msgstr"登出"

就这样,OK终于把这个国际化给搞定啦!