应用程序的国际化

 

谢列文章:应用程序的国际化,第一部分
周融,2008 年 5 月
版权所有 (C) 2001-2008, 保留所有权利。

现代应用程序框架设计中常常需要考虑到国际因素。例如,一个具备规模的企业要求其在各个国家的分支机构使用对应国家/地区语言版本的应用程序以方便 员工。这个需求就是最简单的国际化需求。往往在这种大规模的应用程序设计上,国际化是必须而且非常重要的。本文讨论基于 Microsoft .NET Framework 框架下的国际化和本地化应用程序的方法、指引和实例,以便给开发人员提供入门性指导。

本文适用于:Microsoft .NET Framework 2.0, 3.0, 3.5, Microsoft Windows.

作为本系列文章中的第一部分,我们主要介绍一些基础知识和一些方法,在接下来的文章中,会深入到各种不同的应用平台详细说明国际化和本地化需求如何实现。

在本文中:
· 全球化的应用程序
· 什么是国际化和本地化
· 全球化支持的设计方法
· 结论

全球化的应用程序

我们很容易理解什么是“全球化”应用程序,最直观的例子莫过于 Microsoft Windows 操作系统。我们在市场上能够买到的 Windows 副本,包含英语版本和各个国家/地区的特定语言版本(如果这些国家/地区被 Microsoft 本地化小组支持),特定语言版本的 Windows 使得能够认知该语言的用户能轻松使用和控制操作系统;除此之外,在某些特定的国家/地区,Microsoft Windows 中包含的某些服务可能也会跟随语言版本的变化而变化。例如在 Windows Vista 中的天气服务,在美国,它使用美国特定的天气 Web 服务提供数据源,而在中国,这项天气服务无法运行,因为中国队天气服务的提供商有严格的控制。Microsoft Windows 在不同的语言版本上,不仅显示文字是基于特定语言的,而且日历、项目排列方式、姓名显示规则、日期格式、数字货币显示样式等都不同,在美国英语版本的 Windows Vista 上,日期被显示为 Wednesday, May 28, 2008,而在中国简体中文版本上则显示为 2008 年 5 月 28 日星期三。

大体上说,全球化应用程序具备如下特征:
1、能支持超过一种以上的特定区域语言。
2、在特定区域,应用程序和服务会有不同的表现(例如天气、购物服务可能都会从本地供应商获取数据源)。
3、符合本地居民使用习惯,如日期、时间格式、货币符号、历法、等等。

如果一个应用程序支持这些特性(或已经准备好支持这些特性),则这个应用程序称为可本地化应用程序 (Internationalizable Application)。

国际化和本地化

国际化 (Globalization): 将一个解决方案或者应用程序进行某些修改,使其能支持特定区域语言,包括显示、使用习惯、历法、本地化的服务等,我们将这个过程称之为国际化 (Globalize)。

本地化 (Localization): 将可国际化的应用程序进行某些更改,使其实现在一种或多种特定区域上的语言,实现基于该语言的界面文本显示、时间日期格式转化、历法更改、服务数据源的变更等的过程,我们称之为本地化 (Localize)

注意,请正确理解这两个概念,国际化是用来对应用程序进行改造使其能被本地化的过程;本地化则是基于一种特定区域语言上的对应用程序的更改,是实现 全球化应用程序的关键部分。先将应用程序变得可国际化,然后针对不同的国家/地区在进行单独的本地化进程,最后,基于各个本地化语言版本之上的应用程序实 施测试。

有一些人可能认为,本地化工作就是单纯的翻译。其实不然。因为根据国际化的三大特性,显示文本的翻译只是其中的一部分内容,而且,在一个没有经过改 造的应用程序中,到处充满着被硬编码的字符串,要做翻译,是非常困难的;另外,即使有可能基于几种语言进行文本翻译,但对于翻译完成后的“本地化”版本进 行功能测试,又是一件非常头疼的事情,所以,要做好本地化,首先要改造应用程序,使其支持国际化特性。

对于一个支持国际化特性的应用程序,本地化非常简单,国际化应用程序已经不再包含硬编码的字符串,只需要修改或增加特定的资源文件(在下一篇文章中 讨论),就可以实现显示文本的“翻译”工作;利用一些测试手段,如伪本地化(Pseudo Localization),可集中规模化对待本地化应用程序进行测试;另外,改造过的应用程序代码在多语言支持环境下变得更加容易维护,因为没有了“母 语言”假设,所有语言版本的应用程序都是平等对待的,可以解决很多实际问题,如多字节编码(MBCS)语言的转换和显示等。

本地化支持的设计方法

为了支持本地化,应用程序在设计上必须进行一些调整。一般说来,这些调整发证在两个阶段,一个是在软件工程的概要设计上,需要预留本地化支持的开发 过程、设计、日程和时间表;二是在详细设计/编码过程,需要开发人员遵照某些要求和规范编写需要本地化的应用程序部分。此外,还应增加本地化小组,以及相 应的项目日程表;在测试阶段,增加本地化测试环节和日程。最后还需要在部署阶段和相应的阶段中增加本地化版本支持。

下面的表格说明了国际化应用程序设计的一般步骤。

 

软件工程阶段 说明
需求分析包含国际化需求分析,例如是否需要进行国际化、本地化语言的种类,国家/地区语言和文化信息等等。
市场分析针对需求分析中的本地化需求,根据市场战略、形式和发展,制定对于包括每一个需要支持的国家/地区的指引文档。
财务增加对本地化进程中的开支预算。
人力资源准备本地化小组的人事工作,基于需要支持的各个国家/地区的本地员工招聘工作等。
概要设计制定国际化工作项目的基础结构、日程表、资源分配等;根据需求分析和市场分析中对于本地化支持的结果,进行 Specification 的制定工作;制定编码规范,使应用程序准备好进行国际化支持。
详细设计开发人员(SDE)、测试开发人员(SDET)根据 Spec 和规范进行应用程序代码、测试用例/代码设计。
测试进行伪本地化测试、然后进行本地化测试。
部署针对于不同的本地化版本需求独立进行部署。

很显然,上面列出的本地化进程只是一种概念模型,它需要在不同的需求环境中作更进一步细化。

针对开发人员和测试开发人员来说,形成良好的编码习惯是提高本地化效率的最好方式,我们在此列举了一些在编写代码过程中的建议,供大家参考。这些条目将在以后的文章中进行详细介绍。

(1)不要使用硬编码字符串。

硬编码字符串就是类似于如下形式的常量性字符串引用。例如,当需要输出一段服务器异常错误提示文本时,硬编码经常会出现,看下面的例子。

  1. public   static   void  Main( string [] args)  
  2. {  
  3.     var operand1 = 5;  
  4.     var opreand2 = 0;  
  5.     try   
  6.     {  
  7.         var result = operand1 / operand2;  
  8.         return ;  
  9.     } catch (DividedByZeroException ex)   
  10.     {  
  11.         MessageBox.Show(<font color="#800000" > "Cannot divided by zero./n" </font>);  
  12.     }  
  13. }  
public static void Main(string[] args)
{
    var operand1 = 5;
    var opreand2 = 0;
    try
    {
        var result = operand1 / operand2;
        return;
    } catch(DividedByZeroException ex) 
    {
        MessageBox.Show("Cannot divided by zero./n"
);
    }
}

代码中加颜色的字符串,就是硬编码字符串,它导致在进行本地化时必须修改改字符串为相应的语言版本,这会对大量源代码进行修改,并有可能影响源代码编码格式,并且没有一种系统的方法找到这些字符串,因此,在本地化时会经常漏掉。

正确的处理方法,是把这些字符串存放到资源文件(或外部文件)中,或将它们集中存放到一个静态类只读字段中,以方便日后本地化。这段代码展示如何处理这些更改。

  1. namespace  Mark.Resources  
  2. {  
  3.     public   static   class  Constants  
  4.     {  
  5.         public   static   readonly   string  DividedByZeroErrorMessage =  "Cannot divided by zero." ;  
  6.     }  
  7. }  
  8.   
  9. namespace  Mark  
  10. {  
  11.     public   static   void  Main()  
  12.     {  
  13.         Console.WriteLine(Mark.Resources.Constants.DividedByZeroErrorMessage);  
  14.     }  
  15. }  
namespace Mark.Resources
{
    public static class Constants
    {
        public static readonly string DividedByZeroErrorMessage = "Cannot divided by zero.";
    }
}

namespace Mark
{
    public static void Main()
    {
        Console.WriteLine(Mark.Resources.Constants.DividedByZeroErrorMessage);
    }
}

(2)使用 string.Format() 方法格式化字符串

本地化过程中我们经常遇到一些与特定语言有关的 描述性文本的处理。例如显示从数据库中获 取的结果集中包含多少页数据,在英语版本中,我们可以表示为 Page: 1 of 10,这表示结果总共有 10 页,当前在第 1 页。但我们用简体中文表示时,我们表示成:第 1 页,共 10 页。这里的 1 和 10 是随时可变的,而其他描述性文本则根据本地化语言不同而不同。因此,使用格式化字符串很容易解决这一类问题。请参考下面的代码。

  1. readonly   string  PageIndicatorMessageEnUs =  "{0} of {1}" ;  
  2. readonly   string  PageIndicatorMessageZhCn =  "第 {0} 页,共 {1} 页。" ;  
  3.   
  4. public   static   void  Main()  
  5. {  
  6.     var pageCount = GetPageCount();  
  7.     var currentPageIndex = GetCurrentPageIndex();  
  8.   
  9.     Console.WriteLine(string .Format(PageIndicatorMessageEnUs, currentPageIndex, pageCount)); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值