C# 实现多语言支持的本地化(System.Globalization名称空间)
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
❝ System.Globalization名称空间System.Globalization 名称空间包含了所有的区域性类和区域类,以支持不同的日期格式、不同 的数字格式,甚至如GregorianCalendar 类、HebrewCalendar 类和JapaneseCalendar 类等表示的不同 日历。使用这些类可以根据不同的地区显示不同的表示法。 Unicode问题因为一个Unicode 字符有16 位,所以共有65536 个Unicode 字符。这对于当前在信息技术中使 用的所有语言够用吗?例如,汉语就需要80 000 多个字符。但是,Unicode 可以解决这个问题。使 用Unicode 必须区分基本字符和组合字符。可以给一个基本字符添加若干个组合字符,组成一个可 显示的字符或一个文本元素。 例如,冰岛的字符Ogonek,就可以使用基本字符0x006F(拉丁小字母o)、组合字符0x0328(组 合Ogonek)和0x0304(组合Macron)组合而成,组合字符在0x0300~0x0345 之间定 义,对于美国和欧洲市场,预定义字符有助于处理特殊的字符。字符Ogonek 也可以用预定义字符 0x01ED 来定义。 StringInfo 类的静态方法 一个显示字符可以包含多个Unicode 字符。要解决这个问题,如果编写的应用程 序要在国际市场销售,就不应使用数据类型char,而应使用string。string 可以包含由 基本字符和组合字符组成的文本元素,但char 不能。 区域性和区域世界分为多个区域性和区域,应用程序必须知道这些区域性和区域的差异。区域性是基于用户 的语言和区域性习惯的一组偏爱特性。RFC 1766(www.ietf.org/rfc/rfc1766.txt)定义了区域性的名称, 这些名称根据语言和国家或区域的不同在世界各地使用。例如en-AU、en-CA、en-GB 和en-US 分 别用于表示澳大利亚、加拿大、英国和美国的英语。 在 System.Globalization 名称空间中,最重要的类是CultureInfo。这个类表示区域性,定义了日 历、数字和日期的格式,以及和区域性一起使用的排序字符串。 RegionInfo 类表示区域设置(如货币),说明该区域是否使用米制系统。在某些区域中,可以使用 多种语言。例如,西班牙区域就有Basque(eu-ES)、Catalan(ca-ES)、Spanish(es-ES)和Galician(gl-ES) 区域性。类似于一个区域可以有多种语言,一种语言也可以在多个区域使用,例如,墨西哥、西班 牙、危地马拉、阿根廷和秘鲁等都使用西班牙语。 特定、中立和不变的区域性在.NET Framework 中使用区域性,必须区分3 种类型:特定、中立和不变的区域性。 特定的区域性与真正存在的区域性相关,这种区域性用上一节介绍的RFC 1766 定义。特定的 区域性可以映射到中立的区域性。例如,de 是特定区域性de-AT、de-DE、de-CH 等的中立区域性, de 是德语(German【Deutsch】)的简写,AT、DE 和CH 分别是奥地利(Austria)、德国(Germany)和瑞 士(Switzerland)等国家的简写。 在翻译应用程序时,通常不需要为每个区域翻译,因为奥地利和瑞士等国使用的德语没有太大 的区别。所以可以使用中立的区域性来本地化应用程序,而不需要使用特定的区域性。 不变的区域性独立于真正的区域性。在文件中存储格式化的数字或日期,或通过网络把它们发 送到服务器上时,最好使用独立于任何用户设置的区域性。 下图显示了区域性类型的相互关系。 CurrentCulture和CurrentUICulture设置区域性时,必须区分用户界面的区域性和数字及日期格式的区域性。区域性与线程相关, 并且通过这两种区域性类型,就可以把两种区域性设置应用于线程。Thread 类提供了CurrentCulture 和CurrentUICulture 属性。CurrentCulture 属性用于设置与格式化和排序选项一起使用的区域性,而 CurrentUICulture 属性用于设置用户界面的语言。 使用 Windows 控制面板中的“区域和语言”选项,就可以改变CurrentCulture 的默认设置,如 下图 所示。使用这个配置,还可以改变区域性的默认数字、时间和日期格式。 CurrentUICulture 属性不依赖于这个配置,而依赖于操作系统的语言。这有一个例外:如果 Windows 7、Windows Vista 或Windows XP 安装了多语言用户界面(Multi-language User Interface, MUI),就可以用区域配置改变用户界面的语言,这会影响CurrentUICulture 属性。 这些设置都使用默认值,在许多情况下,不需要改变默认值。如果需要改变区域性,只需把线 程的两个区域性改为Spanish 区域性,如下面的代码段所示:
前面已学习了区域性的设置,下面讨论CurrentCulture 设置对数字和日期格式的影响。 数字格式System 名称空间中的数字结构Int16、Int32 和Int64 等都有一个重载的ToString()方法。这个方 法可以根据地域创建不同的数字表示法。对于Int32 结构,ToString()方法有下述4 个重载版本:
不带参数的ToString()方法返回一个没有格式化选项的字符串,也可以给ToString()方法传递一 个字符串和一个实现IFormatProvider 接口的类。 该字符串指定表示法的格式。而这个格式可以是标准数字格式化字符串或者图形数字格式化字 符串。对于标准数字格式化,字符串是预定义的,其中C 表示货币符号,D 表示输出为小数,E 表 示输出用科学计数法表示,F 表示定点输出,G 表示一般输出,N 表示输出为数字,X 表示输出为 十六进制数。对于图形数字格式化字符串,可以指定位数、节和组分隔符、百分号等。图形数字格 式字符串###, ###表示两个3 位数块被一个组分隔符分开。 IFormatProvider 接口由NumberFormatInfo、DateTimeFormatInfo 和CultureInfo 类实现。这个接 口定义了GetFormat()方法,它返回一个格式对象。 NumberFormatInfo 类可以为数字定义自定义格式。使用NumberFormatInfo 类的默认构造函数, 可以创建独立于区域性的对象或不变的对象。使用这个类的属性,可以改变所有格式选项,如正号、 百分号、数字组分隔符和货币符号等。从静态属性InvariantInfo 返回一个与区域性无关的只读 NumberFormatInfo 对象。NumberFormatInfo 对象的格式化值取决于当前线程的CultureInfo 类,该线 程从静态属性CurrentInfo 返回。 下一个示例使用一个简单的控制台项目。在这段代码中,第一个示例显示了在当前线程的区域 性格式中所显示的数字(这里是English-US,是操作系统的设置)。第二个示例使用了带有 IFormatProvider 参数的ToString()方法。CultureInfo 类实现IFormatProvider 接口,所以创建一个使用 法国区域性的CultureInfo 对象。第3 个示例改变了当前线程的区域性。使用Thread 实例的 CurrentCulture 属性,把区域性改为德国区域性:
结果如下所示。可以把这个结果与前面列举的美国、英国、法国和德国区域性的结果进行比较。
对于日期,也提供了与数字相同的支持。DateTime 结构有一些把日期转换为字符串的方法。公 共实例的ToLongDateString()、ToLongTimeString()、ToShortDateString()和ToShortTimeString()方法都使用当前区域性来创建字符串表示法。使用ToString()方法,可以指定另一种区域性:
使用ToString()方法的字符串参数,可以指定预定义格式字符或自定义格式字符串,把日期转换 为字符串。DateTimeFormatInfo 类指定了可能的值。DateTimeFormatInfo 类指定的格式字符串有不同 的含义。例如,D 表示长日期格式,d 表示短日期格式, ddd 表示星期的缩写,dddd 表示星期的全 称,yyyy 表示年份,T 表示长时间格式,t 表示短时间格式。使用IFormatProvider 参数可以指定区 域性。使用不带IFormatProvider 参数的重载方法,表示所使用的是当前线程的区域性:
这个示例程序的结果说明了使用线程的当前区域性的ToLongDateString()方法,其中给ToString() 方法传递一个CultureInfo 实例,则显示其法国版本,把线程的CurrentCulture 属性改为es-ES,则显 示其西班牙版本,如下所示。
使用区域性为了全面介绍区域性,下面使用一个WPF 应用程序示例,该应用程序列出所有的区域性,描 述区域性属性的不同特征。下图 显示了该应用程序在Visual Studio 2010 WPF 设计器中的用户界 面。 在应用程序的初始化阶段,所有可用的区域性都添加到应用程序左边的树形视图控件中。这个初 始化在AddCulturesToTree()方法中进行,该方法在Window类CultureDemoWindow的构造函数中调用:
在AddCulturesToTree()方法中,从通过静态方法CultureInfo.GetCultures()中获取所有区域性。给 这个方法传递CultureTypes.AllCultures,就会返回所有可用区域性的未排序数组。该数组用一个 Lambda 表达式排序,这个Lambda 表达式要传递给Array.Sort()方法的第二个参数的Comparison 委 托。在foreach 循环中,把每个区域性添加到树形视图中。为每种区域性创建一个TreeViewItem 对 象,因为WPF 的TreeView 类使用TreeViewItem 对象来显示。将TreeViewItem 对象的Tag 属性设置 为CultureInfo 对象,以便以后访问这个树型视图中的CultureInfo 对象。 TreeViewItem 对象添加到树中的什么地方取决于区域性类型。如果区域性没有父区域性,它就 会添加到树的根节点上。要查找父区域性,必须把所有区域性保存到一个字典中。相关内容参见前 面章节,其中第10 章介绍了字典,第8 章介绍了Lambda 表达式。
在用户选择树中的一个节点时,就会调用TreeView 类的SelectedItemChanged 事件的处理程序。 在这里,这个处理程序在TreeCultures_SelectedItemChanged()方法中实现。在这个方法中,先调用 ClearTextFields()方法清除所有字段,再选择TreeViewItem 对象的Tag 属性,从树中获取CultureInfo 对象。接着使用CultureInfo 对象的属性Name、NativeName 和EnglishName 设置一些文本字段。如果 CultureInfo 对象是一个可以使用IsNeutralCulture 属性进行查询的中立区域性,就设置相应的复选框。
然后获取区域性的日历信息。CultureInfo 类的Calendar 属性返回特定区域性的默认Calendar 对 象。因为Calendar 类没有对应的名称属性,所以需要使用基类的ToString()方法获取类的名称,并删 除要在文本字段textCalendar 中显示的这个字符串的名称空间。 因为一种区域性可能支持多种日历,所以OptionalCalendars 属性返回额外支持的Calendar 对象 数组。这些可选的日历显示在列表框listCalendars 中。派生自Calendar 的GregorianCalendar 类还有 一个CalendarType 属性,它列出了Gregorian 日历的类型。这个类型可以是GregorianCalendarTypes 枚举的一个值:Arabic、MiddleEastFrench、TransliteratedFrench、USEnglish 或Localized,这取决于 区域性。使用Gregorian 日历,类型还可以显示在列表框中。
接着,在if 语句中使用“!ci.IsNeutralCulture”,以检查区域性是否为特定区域性(不是中立区域 性)。使用ShowSamples()方法显示数字和日期示例。这个方法将在下一段代码中实现。使用 ShowRegionInformation()方法显示区域的一些信息。对于不变的区域性,只能显示数字和日期示例, 不能显示区域信息。因为不变的文件与实际的语言无关,所以它与区域也无关。
为了显示一些本地化的数字和日期,把CultureInfo 类型的选中对象传递给ToString()方法的 IFormatProvider 参数。
为了显示与RegionInfo 对象相关的信息,通过在ShowRegionInformation()方法中传递选中的区域性标识符,构造一个RegionInfo 对象,然后访问DisplayName、CurrencySymbol、ISOCurrencySymbol 和IsMetric 属性,以显示这些信息。
启动应用程序,在树形视图中就会看到所有的区域性,选择一个区域性后,就会列出该区域性 的特征。 排序排序字符串取决于区域性。一些区域性有不同的排列顺序。例如在芬兰,字符V 和W 就是相 同的。在默认情况下,为排序而比较字符串的算法要使用与区分区域性的排序方式,其中排序依赖 于区域性。 为了说明芬兰的排序方式,下面的代码创建一个控制台应用程序小示例,其中对数组中尚未排 序的美国州名进行排序。因为我们将使用System.Collections.Generic 、System.Threading 和 System.Globalization 名称空间中的类,所以必须声明这些名称空间。下面的DisplayNames()方法用 于在控制台上显示数组或集合中的所有元素:
在Main()方法中,在创建了包含一些美国州名的数组后,就把线程的CurrentCulture 属性设置 为Finnish 区域性,这样,下面的Array.Sort()方法就使用芬兰的排列顺序。调用DisplayNames()方法 在控制台上显示所有的州名:
在以芬兰排列顺序第一次显示美国州名后,数组将再次排序。如果希望排序独立于用户的区域 性,就可以使用不变的区域性。在已排序的数组要发送到服务器上,或存储到某个地方时,就可以 采用这种方式。
这个程序的输出显示了用Finnish 区域性进行排岸的结果和独立于区域性的排序结果。在使用独 立于文件的排序方式时,Virginia 排在Washington 的前面。用Finnish 区域性进行排序时,Virginia 排在Washington 的后面。
如果对集合进行的排序应独立于区域性,该集合就必须用不变的区域性进行排 序。在把排序结果发送给服务器或存储在文件中时,这种方法尤其有效。 除了依赖地域的格式化和测量系统之外,文本和图片也可能因区域性的不同而不同。此时就需要使用资源。 阅读原文:原文链接 该文章在 2025/3/24 13:20:49 编辑过 |
关键字查询
相关文章
正在查询... |