正确使用gettext来翻译Wordpress主题

来源:互联网 发布:软件质量模型 编辑:程序博客网 时间:2024/05/17 22:55

Wordpress是一个非常不错的blog系统,使用方便,且能更换不同的主题。在国外的网站上,有很多免费的主题,这些主题不但表现形式漂亮、简洁,而且代码也非常精炼。

但我们国人在使用这些主题的时候,都不免要碰到一个汉化的问题。最直接的办法,当然是打开文本编辑器,将这些主题的模板文件进行修改,将英文的地方 替换成中文。但这样的做法,虽然直接,存在的缺点也是很明显的:首先,我们需要了解我们文本编辑器最后保存文件时的编码,并且要符合Wordpress生 成页面时产生的charset属性,如果你的文本编辑器保存文件为GB2312,而Wordpress设置成了UTF-8,那么页面显示出来就是乱码。其 次,我们直接改动了原来的主题代码,增加了程序和相应语言的耦合度,不便于维护,以后如果主题的作者对主题代码进行了升级,我们就需要重新进行修改了。最 后,对于那些追求完美的程序员来说,更趋向于低耦合度的东西。

其实,Wordpress利用了GNU gettext模块,已经完美地支持了多语言。而很多国外的优秀主题,也是遵循这样的规范进行开发的,我们所需要做的就是,生成一张翻译列表,然后填上我 们的汉语对应语句就可以了。当然,你的主题如果不准备更新,或者追求快速(毕竟翻译的步骤还是比直接修改来的麻烦一点),你也可以跳过本文。

在开始本文的实验以前,请确保你已经知道以下事情:

  • 安装Wordpress 2.5 (本文在2.5版本上测试通过)
  • 大致明白GNU gettext的工作原理。GNU gettext利用两个文件:po和mo,其中po是一个翻译列表,列举了所以需要翻译的词组,并提供翻译。mo则是由po文件进行编译过后的文件,更加适合机器阅读。
  • 会设置Wordpress为中文,也就是将wp-config.php文件里的WPLANG定义为’zh_CN’,其中zh代表中文,CN代表中国大陆。然后下载安装Wordpress的mo文件到wp-content/language目录下。
  • 会安装并且切换主题,并大致明白主题模板文件的作用,比如边框内容对应于sidebar.php文件。

好了,首先,我们到这里下载一个用于测试的主题。这个主题叫做Barthelme,是一个符合Wordpress 2.5规范的主题,非常简洁的主题,下面是它的预览:

barthelme v3 screenshot

另外插句话,http://www.plaintxt.org/ 这个网站里面提供了几个非常简洁的主题,而且都支持Wordpress 2.5,喜欢这种风格的朋友可以自行选择。

好了,我们按照常规办法安装好 Barthelme 主题。由于我们已经将Wordpress切换到了中文,所以我们可以看到这样的模样:

只有词条'页面'被翻译了

我们看看这个主题截图,其中少部分被正常翻译了,比如“页面”,然而更多的词条还没有被翻译,比如“CATEGORIES“和”Comments“ 等。这是怎么回事呢?原来我们由于安装过Wordpress的汉化mo文件,并且将站点切换到了zh_CN,所以这些词条首先从Wordpress的汉化 mo文件里寻找,这样,它找到了“页面”词条的翻译,但却没有找到“CATEGORIES“词条的翻译,于是产生了这样奇怪的现象。

到这里,我们应该看到一个问题,那就是,新的模板(符合多语言开发规范的模板)会自动进入Wordpress的汉化包里进行词条翻译搜索,这样,就 和Wordpress的翻译混杂在了一起。我们知道,Wordpress的中文汉化主要应该集中于后台管理的汉化,而对于主题,理想的状况是每个主题有自 己的汉化包。

为了解决这个问题,Wordpress提出了文字域的概念。用过C++语言的朋友可以将其对应于namespace概念。这个概念解决了作用域的冲突。好,那么我们首先为Barthelme主题添加其独自的文字域。

我们进入wp-content/themes/barthelme目录,打开functions.php文件。functions.php文件是wordpress主题的一个标准文件,主要用来定义一些该主题的php函数以及进行一些环境的设置。我们在该文件的最后部分发现了这样的代码:

load_theme_textdomain('barthelme')

load_theme_textdomain函数用来设置主题的域。我们看到,Barthelme主题是严格按照多语言标准进行开发的,它已经为我们设置好了域名:barthelme。在汉化其他主题时,如果我们没有发现这条语句,可以在functions.php文件里添加这条语句,并定义自己的域名。

既然定义了域名,那么为什么词条“页面”能够正确翻译,而“Categories“就不能了呢?让我们打开sidebar.php文件,找到以下部分:

<?php wp_list_pages('title_li=<h3>'.__('Pages').'</h3>&sort_column=menu_order') ?>
<li id="categories">
<h3><?php _e('Categories', 'barthelme'); ?></h3>
<ul>
<?php wp_list_cats('sort_column=name&hierarchical=1') ?>
</ul>
</li>

原来,在显示词条”页面“时,用的是__('Pages'),而显示词条“分类”时,用的是_e('Categories', 'bathelme'); 我们知道,php里主要通过__(key,domain)_e(key,domain)来进行词条翻译,而当我们不提供第二个参数时,则在全局域里进行搜索,这就是为什么我们的“页面”词条可以正常显示的原因,因为这里遗漏了域名,wordpress进入全局域里为其搜索去了。看来,这里是bug了,对其进行修改:__('Pages', 'barthelme')。然后保存后,刷新下页面:

由于没有提供域翻译,所以都没有被翻译

这样,词条“页面”就不会被翻译了,因为我们还没有提供该域的翻译文件。

接下来要进行翻译了,我们首先需要产生一个翻译词条的列表,也就是po文件(或者pot文件,pot的意思是po文件的模板template)。当然,我们如果手工产生这个列表的话,工作量是非常巨大的,这里我们借助GNU gettext的工具来产生:

] cd wp-content/themes/barthelme
] find . -iname "*.php" > files.tmp
] xgettext --language=PHP --indent --keyword=__ --keyword=_e
--keyword=__ngettext:1,2 -s -n --from-code=UTF-8 -f files.tmp
] rm files.tmp

我们首先进入主题目录,通过find命令产生一个php文件名列表,并将这个文件名列表保存为一个临时文件files.tmp。接着,我们用xgettext文件来扫描php文件,自动产生po文件。你可以通过 info xgettext 来获取详细的使用帮助,其中--indent选项指定使用缩进模式,-s选项指定对词条进行排序,-n选项则将每个词条所处的位置添加到该词条的注释里。

运行完xgettext后,会产生一个messages.po文件,这就是我们需要工作的翻译文件。它主要由两部分组成:头信息和翻译词条列表。我们打开这个文件,它的开始部分是一个头信息部分:

msgid   ""
msgstr "Project-Id-Version: PACKAGE VERSION/n"
"Report-Msgid-Bugs-To: /n"
"POT-Creation-Date: 2008-04-09 18:51+0800/n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE/n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>/n"
"Language-Team: LANGUAGE <LL@li.org>/n"
"MIME-Version: 1.0/n"
"Content-Type: text/plain; charset=CHARSET/n"
"Content-Transfer-Encoding: 8bit/n"

我们首先需要对这个头信息进行改造,改造有两个部分:一,设置charset,这个一般设置为UTF-8;二来要为其添加关于汉语的一些细节。关于 语言的细节主要包括nplurals和plural的设置,其实它包括了该语言如何处理单数和复数的情况,当然,我们汉语没有这个问题,我们简单地将 nplurals设置为2,plural设置为1就可以了。下面是修改好的头信息(注意红色部分):

msgstr  "Project-Id-Version: PACKAGE VERSION/n"
"Report-Msgid-Bugs-To: /n"
"POT-Creation-Date: 2008-04-09 18:51+0800/n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE/n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>/n"
"Language-Team: LANGUAGE <LL@li.org>/n"
"MIME-Version: 1.0/n"
"Content-Type: text/plain; charset=UTF-8/n"
"Content-Transfer-Encoding: 8bit/n"
"Plural-Forms: nplurals=2; plural=1 != 1;/n"

接下来,该翻译了,我们搜索以下词条,并将其翻译:

#: sidebar.php:11
msgid "Pages"
msgstr "页面"

#: sidebar.php:14
msgid "Categories"
msgstr "分类"

保存文件的时候,我们要注意,因为我们已经设置编码为UTF-8,所以我们需要将文件保存为UTF-8编码,常用的编辑器,比如UtralEdit和Emacs都支持的。保存好后我们需要将messages.po文件重新命名为zh_CN.po:

] mv messages.po zh_CN.po

接下来编译这个po文件为mo文件:

] msgfmt -o zh_CN.mo zh_CN.po

好了,检查以下我们的主题目录,是否有一个名为zh_CN.mo文件,如果有,说明一切正常,我们刷新一下页面:

翻译成功

翻译成功!接下来要做的就是,继续修改po文件,翻译词条,然后用msgfmt工具对其进行编译即可。

总结

一个符合gettext规范的主题需要注意以下内容(针对Wordpress 2.5):

  • 确定一个主题使用的域名: mydomain;
  • functions.php文件里设置文字域 load_theme_textdomai('mydomain')
  • 主题模板里使用__('key','mydomain')或者_e('key','mydomain')
  • 用xgettext自动产生po文件,并且修改信息头,编码设置为UTF-8,并设置汉语细节;
  • 将po文件改名为你的语言区域,如zh_CN.po
  • 用UTF-8编码编辑zh_CN.po文件,翻译各个词条;
  • 用msgfmt命令对po文件进行编译,生成mo文件;
  • 刷新网页,搞定!
原创粉丝点击