首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

国际化、本地化和Unicode

i18n, L10n, and Unicode

在现代Web应用程序开发领域中,国际化、本地化和Unicode都是热门话题。如果你建立的应用程序不支持多种语言,就很有可能遗漏潜在用户基础中极大的一部分。目前的研究表明,世界上大约有5亿1千万人说英语。如果您的应用程序只迎合英语用户,就会将全世界的92%的潜在用户拒之门外。当然这些数据很不精确,通常是一种恐吓战术,实际上你得从考虑世界上60亿人中有多少人上网开始。但即使考虑到这个因素,我们仍然有64%的非英语在线用户,大约6.8亿人(该统计数据来自global reach站点:http://global-reach.biz/)。显然,被你拒之门外的潜在用户的数目仍然很庞大。

历史上,对这个问题的处理曾经很麻烦。开发人员要有关于字符集和文本处理的高级知识,语言相关的特定数据需要被分别存储,并且一个用户群组的数据不能和另一组的共享。但在一个互联网越来越无所不在的世界里,这些问题都需要解决。最终达成的解决方案为开发人员砍掉了很多困难工作,现在创建多语言应用几乎是轻而易举的,开发人员只需要一些简单的知识即可。

本章会让你快速了解国际化和本地化所涉及的问题,并给出解决它们的简单方案。然后我们会深入研究Unicode,解释它是什么,如何起作用,以及你如何能够快速简易地实现全Unicode的应用程序。我们会略微谈到在Web应用程序的数据操作中,Unicode会起作用的一些关键地方,并且指出它们潜在的一些问题。

国际化和本地化

Internationalization and Localization

国际化和本地化是Web应用程序领域的专业术语。一部分是因为它们都是挺长的单词,容易让人眩晕,也因为它们在当今世界确实变得越来越重要了。国际化和本地化通常一起被提起,但它们指代的内容很不相同,而了解这种不同很重要。

l          国际化是为应用程序添加输入、处理、输出国际文本的能力

l          本地化是为特定地区(locale)提供定制的应用程序的过程

国际化常简写为i18n(“18”代表了省略的18个字母),本地化简写为L10n(同样的原因,但使用大写的“L”,让人看得更清楚些),从现在起我们就用这种形式来指代它们,至少可以省些墨水。和其他很多热门话题一样,人们也为i18n和L10n关联了很多其他术语,为了避免以后可能产生混淆,在这里就简单进行说明:globalization(g11n)指的是i18n和L10n的集合,而personalization(p13n)和reach(r3h)仅仅指L10n。

Web应用程序中的国际化

Internationalization in Web Applications

让我们回顾一下不远的过去(有时也称之为20世纪90年代),那时要支持国际化,意味着应用程序能够用许多不同的字符集和编码输入、存储和输出数据。说英语的用户用Latin-1字符集和你交流,说俄语的使用KOI8-R,日语用户则是Shift_JIS等。其他的也都是这样,除非你想要在一个页面上同时展现来自不同用户集合的数据。这些字符集和编码中的每个代码都能够展现和编码定义好的一组字符,通常介于100和250之间。有时这些字符会有重叠,因此你可能会以两种形式存储和显示字符Ю(西里尔字母中的大写字母Yu),在KOI8-Ukrainian中它是字节0xE0,在Apple Cyrillic中则是字节0x9E。但一般情况下,一个字符集中的字符不能使用另一个字符集来显示。字符ね(平假名字母E)可以用IBM-971-Korean来表示,字符Ų(带有欧格内克附加符号的拉丁大写字母U)可以用IBM-914-Baltic来表示,而反过来就不行了。

虽然这些不同的字符集或许还挺可爱的,但它们问题很多,远远不只是可以表示其他字符集的字符。每段存储数据都需要贴上相应的字符集标签。任何对字符串的操作都得考虑相关的字符集,如你不能对shift-JIS字符串执行基于字节的子串操作。当你要输出页面时,HTML和所有的内容都必须使用正确的字符集输出。

这样到了一定程度后,终于有人说“我受够了,受够了”,他再也不能忍受这样的事情了。后续的解决方案看起来很清楚,用一种字符集和编码来表示所有想要存放和显示的字符。这样就不再需要给字符串加上字符集的标签了,也不再需要各种不同的字符串函数了,并且能够以单独的一种格式输出页面了。这个主意听起来挺简洁的。于是在1991年,Unicode产生了。带着涵盖了所有已知的可写语言的所有字符的字符集合(包括来自所有现存字符集合的区别音符和符号)和一组精彩的新编码,它的诞生必然会根本性地改变这个世界。在默默耕耘了大约10年之后,它实现了自己的目标。

在本章中,我们将只涉及用于国际化的Unicode字符集和UTF-8编码。你当然也可以选择另外的路线,使用另一种Unicode编码或者回去使用多个字符集的集合,但对于主要存放英语数据的程序而言,UTF-8往往是最合理的。有些应用程序需要存放大量CJKV数据,或者任何含有许多较大码点的数据——这时UTF-16是合理的选择。除了在码点的相应表示长度上可能不一致之外,本章其他部分对UTF-16和UTF-8都是同样有效的。

Web应用程序中的本地化

Localization in Web Applications

将Web应用程序本地化和将它国际化很不相同,尽管后者是先决条件。当我们谈论对Web应用进行本地化时,我们指的是基于用户首选的locale,为他们提供了一个不同的界面(通常是文本)。

到底什么是Locale?

Locale这个词可用来形容一组本地化的偏好。 这通常要包括语言和地区,往往还含有关于时区、日期和时间格式、数字显示、货币的其他设定等。 一个独立的locale通常是关联在用户的账号上,使应用程序的各部分可为用户而剪裁:根据用户自己的时区显示时间,根据用户自己的语言展示文本,显示用户特定的千位分隔符等。

有几个方法能将网站本地化,但都不那么简单。本章主要以国际化为主,因此不会在本地

化的细节上投入太多精力。在我们回顾国际化的基础知识之前,我们先看一下本地化的三种方法。

字符串替换

在最低的层次,你可以使用类似于GNU的gettext的类库 (http://www.gnu.org/software/ gettext/),它可以在字符串这个层级替换语言。举例来说,下面这种简单的PHP代码,它会输出一次问候:

printf("Hello %s!", $username);

它使用了gettext封装函数,我们在这儿可以用任意语言代替它:

printf(_("Hello %s!"), $username);

代码中惟一的改变是调用gettext函数,其调用方法是用_( )把英文字符串传给它。然后,gettext的配置文件包含短语的映射,将它们翻译成不同的语言,如示例4-1和示例4-2所示。

示例4-1:my_app.fr.po

msgid "Hello %s!"

msgstr "Bonjour %s!"

示例4-2:my_app.ja.po

msgid "Hello %s!"

msgstr "%s!"

根据用户所要的locale,gettext在运行时返回正确的字符串,然后由应用程序输出。

字符串替换存在的问题是:任何时候,如果你要改变应用程序的任何视觉结构(改变流程、加入解释等),都需要立即更新每一个翻译。如果你有一支由专职翻译人员组成的团队,这都是很好办的,但对任何变化进行部署之前,都不得不进行完整的翻译,这和快速Web应用开发不怎么合拍。

多个模板集合

在标记完全脱离任何页面逻辑的应用中,模板是无需进行处理的文件(除了其中的条件语句和迭代语句)。如果您创建多套模板,对每个你想支持的locale都准备一个,那么其中一套的发展无需和另一套同步。对于主locale,你可以进行多次变更,然后定期地分批地将这些变化应用到其他locale上。但这种方法有它自身的问题。虽然标记层的变化可以独立于页面逻辑的任何变化, 但任何页面逻辑的功能性改变,都必须反映到标记层并且进行复制。比如, 如果在你的应用程序中的一个页面展示了5个最新条目,但被改为随机显示

5个故事,然后其他所有语言都必须一次性的按照这个范本进行更新。另一种方法是在页面逻辑这一层同时支持多种功能,这样可以不用去修改不同locale使用的功能,而提供给模板选择。这种方法会在一开始就变得非常复杂,因为它把多种相互竞争的流程一起放在了页面逻辑层中。

多个前端

要避免把多种逻辑流程一股脑儿地放在页面逻辑层,有一个替代方案,即创建多个页面逻辑层(包括标记和其上的展现层)。这实际上在单个共同存储和商务逻辑层之上,有效地建立了多个站点。

通过基于分层模型建立应用程序和通过API暴露业务逻辑功能(可以跳到第11章了解更多信息),你可以在一开始只支持一种locale,然后依着自己的节奏建立其他locale的前端。 这样一个国际化的业务逻辑层和存储层,能够在不同locale之间共享数据——基于日本locale的前端添加的数据,能使用基于西班牙locale的前端来看。

想要更多更普遍的关于i18n和L10n的网站,你可以访问W3C的i18n门户 http://www.w3. org/International/

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论