本部分介绍开发世界就绪应用程序时要遵循的最佳做法。
全球化最佳做法
将您的应用程序在内部转换为 Unicode。
使用 System.Globalization 命名空间提供的区域性识别类来操作和格式化数据。
- 若要排序,请使用 SortKey 类和 CompareInfo 类。
- 对于字符串比较,请使用 CompareInfo 类。
- 对于日期和时间格式,请使用类 DateTimeFormatInfo 。
- 对于数字格式设置,请使用 NumberFormatInfo 类。
- 对于公历和非公历日历,请使用 Calendar 类或特定日历实现之一。
在适当的情况下,使用 System.Globalization.CultureInfo 类提供的区域性属性设置。 使用 CultureInfo.CurrentCulture 属性设置任务的格式,例如日期和时间或数字格式。 使用CultureInfo.CurrentUICulture属性来检索资源。 请注意,可以为每个线程设置
CurrentCulture
属性和CurrentUICulture
属性。使用命名空间中的 System.Text 编码类,使应用程序能够读取和写入各种编码数据。 不要假定 ASCII 数据。 假设在用户可以输入文本的任何地方都支持国际字符。 例如,应用程序应接受服务器名称、目录、文件名、用户名和 URL 中的国际字符。
使用 UTF8Encoding 类时,出于安全原因,应使用此类提供的错误检测功能。 若要启用错误检测功能,请使用包含
throwOnInvalidBytes
参数的构造函数来创建类的实例,并将该参数的值设置为true
。尽可能将字符串作为整个字符串处理,而不是作为一系列单独的字符处理。 在对子字符串进行排序或搜索时,这一点尤其重要。 这可以防止与分析组合字符相关的问题。 也可以使用类处理文本单元而不是单个字符 System.Globalization.StringInfo 。
使用命名空间提供的 System.Drawing 类显示文本。
为保持操作系统间的一致性,不要允许用户设置重写 CultureInfo。 使用接受
CultureInfo
参数的useUserOverride
构造函数,并将其设置为false
。在国际操作系统版本上测试应用程序功能,并使用国际数据。
如果安全决策基于字符串比较或大小写更改操作的结果,请使用不区分区域性的字符串操作。 这种做法可确保结果不受
CultureInfo.CurrentCulture
的值的影响。 请参阅“使用字符串的最佳实践”中“使用当前文化的字符串比较”部分,以了解一个演示如何文化敏感的字符串比较可能导致不一致结果的示例。对于用于交换或存储的任何元素(例如 API 调用中的 JSON 文档中的字段),请使用 CultureInfo;此外,应该明确指定往返格式(例如
"O"
"o"
日期时间格式说明符)。 尽管不变文化的格式字符串是稳定的且不太可能更改,指定一个明确的格式字符串可以帮助阐明您的代码意图。全球化数据 不稳定,应考虑到这一点编写应用程序及其测试。 它每年通过主机 OS 通道在所有受支持的平台上更新几次。 此数据通常不会随运行时一起分发。
本地化最佳做法
将所有可本地化的资源移动到单独的资源专用 DLL 中。 可本地化的资源包括用户界面元素,如字符串、错误消息、对话框、菜单和嵌入式对象资源。
不要硬编码字符串或用户界面资源。
不要将不可本地化的资源放入仅限资源的 DLL 中。 这会使翻译者感到困惑。
不要使用从串联短语在运行时生成的复合字符串。 复合字符串很难本地化,因为它们通常假定英语语法顺序不适用于所有语言。
避免诸如“空文件夹”之类的不明确构造,其中字符串可以根据字符串组件的语法角色以不同的方式翻译。 例如,“empty”可以是动词或形容词,这可能会导致以意大利语或法语等语言进行不同的翻译。
避免使用应用程序中包含文本的图像和图标。 本地化成本高昂。
需要在用户界面中留出足够的空间以适应字符串长度的扩展。 在某些语言中,短语可能需要比其他语言所需的空间多 50-75%。
使用 System.Resources.ResourceManager 类根据文化检索资源。
使用 Visual Studio 创建 Windows 窗体对话框,以便可以使用 Windows 窗体资源编辑器(Winres.exe)进行本地化。 不要手动编写 Windows 窗体对话框的代码。
安排专业本地化(翻译)。
有关创建和本地化资源的完整说明,请参阅 .NET 应用中的资源。
ASP.NET 和其他服务器应用程序的全球化最佳做法
小窍门
以下最佳做法适用于 ASP.NET Framework 应用。 有关 ASP.NET Core 应用,请参阅 ASP.NET Core 中的全球化和本地化。
在应用程序中显式设置 CurrentUICulture 和 CurrentCulture 属性。 不要依赖于默认值。
请注意,ASP.NET 应用程序是托管应用程序,因此可以使用与其他托管应用程序相同的类,以根据区域性检索、显示和操作信息。
请注意,可以在 ASP.NET 中指定以下三种类型的编码:
requestEncoding
指定从客户端浏览器接收的编码。responseEncoding
指定要发送到客户端浏览器的编码。 在大多数情况下,此编码应与指定的requestEncoding
编码相同。- fileEncoding 指定 .aspx、 .asmx 和 .asax 文件分析的默认编码。
在 ASP.NET 应用程序中,将
requestEncoding
、responseEncoding
、fileEncoding
、culture
和uiCulture
属性分别指定在以下三个位置的值:- 在 Web.config 文件的全球化部分中。 此文件在 ASP.NET 应用程序外部。 有关详细信息,请参阅 <全球化> 元素。
- 在页面指令中。 请注意,当应用程序位于页面中时,文件已读取。 因此,指定 fileEncoding 和 requestEncoding 太晚了。 只能在页面指令中指定
uiCulture
、culture
和responseEncoding
。 - 在应用程序代码中以编程方式指定。 此设置可能因请求而异。 在应用程序代码到达时,像页面指令一样,指定
fileEncoding
和requestEncoding
为时已晚。 只能在应用程序代码中指定uiCulture
、culture
和responseEncoding
。
请注意,uiCulture 值可以设置为浏览器接受语言。
对于分布式应用程序,例如允许零停机更新的 Azure 容器应用,或类似情况,你必须规划可能出现的情况,其中应用程序存在多个实例,而这些实例具有不同的格式规则或其他文化数据,尤其是时区规则。
- 如果应用程序部署包含数据库,请记住该数据库将有自己的全球化规则。 在大多数情况下,应避免在数据库中执行任何与全球化相关的函数。
- 如果应用程序部署包含使用客户端全球化资源的客户端应用程序或 Web 前端,则假定客户端资源不同于服务器可用的资源。 考虑在客户端上专门执行全球化功能。
可靠测试的建议
若要使依赖项更加明确,使测试更加容易和可并行化,应考虑显式传递区域性相关的设置,例如将 参数传递给执行格式设置的方法,以及将
CultureInfo
传递给处理日期和时间的方法TimeZoneInfo
。 检索时间时,还应使用 或类似类型TimeProvider。对于大多数测试,不应 显式验证格式化操作的确切输出或时区的确切偏移量。 格式和时区数据可能会随时改变,且在相同操作系统的两个实例之间可能会有所不同(在同一台计算机上甚至可能有不同的进程)。 依赖确切值会使测试变得脆弱。
- 通常,验证是否收到某些输出就足够了(例如,格式化时出现非空字符串)。
- 对于某些数据元素和格式,可能会改为验证数据是否解析为输入值(往返)。 对于删除字段(例如,某些与日期相关的字段的年份)或者截断或舍入值(例如浮点输出)的情况,需要加以注意。
- 如果你有验证所有本地化格式输出的显式要求,应考虑在测试设置过程中创建和使用自定义区域性。 对于大多数简单情况,可以通过使用
CultureInfo
构造函数来实例化new CultureInfo(..)
对象,并设置DateTimeFormat
和NumberFormat
属性来完成。 对于更复杂的情况,子类化类型可以重写其他属性。 这项功能可能有潜在的额外好处,例如使用资源文件启用 伪本地化。 - 如果您有明确要求来验证所有日期/时间操作的结果,应考虑 在测试设置期间创建和使用自定义
TimeZoneInfo
实例。 这有潜在的其他好处,例如稳定测试某些边缘情况(例如,对夏令时规则的更改)。