注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

itoedr的it学苑

记录从IT文盲学到专家的历程

 
 
 

日志

 
 

PHP系统中的多语言自适应方案:gettext(收录)  

2014-07-22 10:54:18|  分类: 多语言平台 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

**********************
关于po文件系统
**********************
po系统属于L10n方案。“po”是: Portable Object(可跨平台对象)的缩写。
      po与mo模式的转变过程PO是 Portable Object (可移植对象)的缩写形式;MO是 Machine Object (机器对象,可理解为二进制文件) 的缩写形式。
      :po系统的升级:
       PO 文件是面向翻译人员的、提取于源代码的一种资源文件。当软件升级的时候,通过使用 gettext 软件包处理 PO 文件,可以在一定程度上使翻译成果得以继承,减轻翻译人员的负担。
        MO 文件是面向计算机的、由 PO 文件通过 gettext 软件包编译而成的二进制文件。程序通过读取 MO 文件使自身的界面转换成用户使用的语言。 GNUgettext 是一个软件包,是为了使软件实现国际化支持而产生的。 I18N是 internationalization 的缩写形式,意即在 i 和 n 之间有 18 个字母,本意是指软件的“国际化”. L10N是 localization 的缩写形式,意即在 l 和 n 之间有 10 个字母,本意是指软件的“本地化”。
       按照软件开发的惯例,最初的软件只有英文版本,根据需要,作者再把软件界面和文档翻译成不同国家、地区的语言版本。但是由于实现翻译的途径、翻译的工作效率、翻译的可重用性等因素各不相同,使翻译工作面临很大困境,也阻碍了软件的推广和应用。为了方便地将软件翻译成不同语言的版本,就需要一套翻译规范和通用工具,这就导致了“国际化”机制的出现。仅仅翻译是不够的,同一种语言在不同国家、地区可能存在多个支系,它们在表达习惯、语法结构甚至文字种类和编码上都有不同,方言更是千奇百怪,通用的翻译其质量肯定是不高的。涉及到计算机领域,还存在操作习惯上的差别,而且对某种语言提供完美的输入、显示、打印、保存、传输并非一件轻而易举的事,这就导致了“本地化”机制的出现。简而言之,“国际化”是“本地化”的一部分,主要是指国际化的实现机制和翻译工作, “本地化”包含“国际化”,是对“国际化”的补充和完善,它还包括为实现对某种特定语言良好的支持而进行的有针对性的翻译调整以及对软件进行的打补丁工作。 I18N 和 L10N 的国际组织是 Openi18n 组织,其前身是 li18nux 组织。它原来是制定GNU/Linux 自由操作系统上软件全球化标准的国际计划,后来扩充到GNU/Linux 之外所有开放源代码的技术领域,因而更名为 Open Internationalization Initiative,由非营利组织 Free Standards Group 赞助,并为世界各大厂商所支持,对于GNU/Linux 系统上的多国语言文字处理技术和环境有决定性的影响。各个开源软件开发组织通常都有负责“国际化”和“本地化”工作的分支机构。
       ajax I18N 主要使用 gettext 软件包使软件实现国际化支持。
**********************
           PHP中如何实现i18n?如果你和我一样,最近也在集中精力解决一个多语种的站点的建设问题,那么也许你已经在考虑这个问题的解决方法了,或者已经有了自己的解决方案。那么就来看看我的吧。
         PHP手册中,有一个关于gettext函数的说明,是这样说的:

      The gettext functions implement an NLS (Native Language Support) API which can be used to internationalize your PHP applications.

gettext函数实施了一个NLS(本地语言支持)API,可以用来国际化你的PHP应用。

  我编程的一个原则是,如果有系统本身的函数,我是一定不会开发自己的函数的。所以我决定使用这个gettext函数来对我的站点进行i18n。

       这是一个多语种的站点,因此根据用户的偏好(主要是语种设置)在界面上将显示相同内容但是不同语种的信息(缺省为英文)。例如:

//用户选择英文

Hello, today is July 29th, 2007.

//用户选择中文

你好,今天是2007年7月29日。

作为实施过程中最关键的一个环节,我们先集中在纯“静态”的内容之上。比如在英文语境下显示“Hello”而在中文语境下显示“你好”。

第一步,创建各语种对应的目录结构。

假定你的站点根目录为f: emp(或/home/apple),那么先创建一个locale目录,然后对于你要支持的每个语种(除了缺省的“英语”)都要创建一个语种目录,并在该 目录下创建一个LC_MESSAGES的目录。至于“语种”目录的命名,需要参考国际标准,例如:中文是zh-CN,加拿大英语是en-CA等。在Linux下,请将-替换为下划线(_)。

因此,如果我们要为中文、加拿大英文创建NLS内容,那么目录结构看起来应该差不多是这样的:

F:/temp/LOCALE

├─en_CA
│ └─LC_MESSAGES
└─zh_CN
└─LC_MESSAGES

第二步,编写一个所谓的PO文件,并将其编译为MO文件。你可以用专门的工具写PO文件并同时编译为MO文件,也可以用任何文本编辑器编辑PO文件,然后用专门的工具编译PO文件到MO文件。这个专门的工具我推荐poEdit。一般而言,一个PO文件的格式如下:

msgid “”
msgstr “”
“Project-Id-Version: Apple

“POT-Creation-Date:

“PO-Revision-Date: 2007-07-29 17:01+0800

“Last-Translator: Taylor Ren <taylor.ren@gmail.com>

“Language-Team: 516′ Studio

“MIME-Version: 1.0

“Content-Type: text/plain; charset=utf-8

“Content-Transfer-Encoding: 8bit

“X-Poedit-Language: English

“X-Poedit-Country: UNITED STATES

“X-Poedit-SourceCharset: utf-8

msgid “Hello”
msgstr “你好!”

msgid “Good”
msgstr “好”

我们可以很少关注最开始的几行代码。而我们真正要输入的是一个msgid-msgstr对,对于每个需要翻译的词组、短语,我们都应该给出对应的翻译。而且,这里的msgid-msgstr是可以嵌入参数的。例如:“今天是$y年$m月$日”。这样在真正输出时,就可以被当时赋值的变量替换。

       如果我们在poEdit中编辑这些东西,那么在我们保存PO文件时,就会自动生成MO文件。只有MO文件可以被PHP使用。将这个MO文件保存到对应语种的LC_MESSAGES目录中去。

第三步,编写PHP脚本进行测试。

在测试前,我们必须保证在PHP中打开了gettext这个扩展。

在笔者的实践中,Windows和Linux的实现不同。假定这个index.php放在locale目录下。我们先看Windows的脚本:

<?php

putenv(”LANG=en_CA”);
setlocale(LC_ALL, ”);
//setlocale(LC_ALL, ‘en_CA’); //用这个在Windows下不起作用

// 指定翻译表的位置
bindtextdomain(”default”, “../locale”);

// 选择域
textdomain(”default”);

// NLS的翻译会寻找../locale/en_CA/LC_MESSAGES/default.mo文件

// 打印一个测试消息
echo _(”Hello”).” “; // _()是gettext()的快捷方式
echo _(”Good”).”<br/>”;

// 来测试中文
putenv(”LANG=zh_CN”);
setlocale(LC_ALL, ”);

bindtextdomain(”default”, “../locale”);

textdomain(”default”);

// NLS的翻译会寻找../locale/zh_cn/LC_MESSAGES/default.mo文件

// 打印一个测试消息
echo _(”Hello”).” “;
echo _(”Good”).”<br/>”;
?>

测试文件的地址在这里。(en_CA的翻译是随便乱写的,只是为了演示而已。)

Linux的脚本基本同上。

但是要注意两点:

第一,Linux下推荐使用setlocale(LC_ALL, ‘en_CA’);,此时不用putenv(”LANG=en_CA.”);setlocale(LC_ALL, ”);

第二,Linux下的语种名必须是Linux支持的语种。支持的语种列表可以在/usr/lib/locale中找到,或者用locale -a命令列出。而且,必须使用utf8后缀。所以,完整的写法是setlocale(LC_ALL, “zh_CN.utf8″);

测试文件的地址就不列出来了。用户可以自己测试。

用这个方法进行i18n的工作,我个人觉得还是很直观、很快捷的。



  评论这张
 
阅读(141)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017