开发全球通用应用程序的最佳做法

本节描述在开发全球通用的应用程序时应遵循的最佳做法。

全球化最佳做法

  1. 在内部使应用程序代码成为 Unicode。

  2. 使用 System.Globalization 命名空间提供的区域性识别类来操作和格式化数据。

  3. 在适当的情况下,使用 System.Globalization.CultureInfo 类提供的区域性属性设置。 使用 CultureInfo.CurrentCulture 属性来执行格式化任务,如日期和时间或数字的格式化。 使用 CultureInfo.CurrentUICulture 属性来检索资源。 请注意,CurrentCultureCurrentUICulture 属性可以通过线程进行设置。

  4. 通过使用 System.Text 命名空间中的编码类,使应用程序能够与各种编码相互进行数据读写。 不要采用 ASCII 数据。 假定在用户可以输入文本的任何位置都将提供国际字符。 例如,应用程序应接受服务器名、目录、文件名、用户名和 URL 中的国际字符。

  5. 使用 UTF8Encoding 类时,出于安全原因,应使用此类提供的错误检测功能。 为了打开错误检测功能,请使用具有一个 throwOnInvalidBytes 参数的构造函数来创建该类的一个实例,并将该参数的值设置为 true

  6. 尽可能将字符串按整个字符串处理,而不是按一系列个别字符处理。 这在排序或搜索子字符串时尤为重要。 这可以防止与分析组合字符有关的问题。 还可以通过 System.Globalization.StringInfo 类使用文本单元而不是单个字符。

  7. 使用 System.Drawing 命名空间提供的类来显示文本。

  8. 为保持操作系统间的一致性,不要允许用户设置重写 CultureInfo。 使用接受 CultureInfo 参数的 useUserOverride 构造函数并将此参数设置为 false

  9. 在国际操作系统版本上使用国际数据来测试应用程序功能。

  10. 如果安全决策基于字符串比较或大小写更改操作的结果,请使用不区分区域性的字符串操作。 这种做法可确保结果不会受 CultureInfo.CurrentCulture 值的影响。 有关展示了区分区域性字符串比较如何产生不一致结果的示例,请参阅字符串使用最佳做法“使用当前区域性的字符串比较”部分。

  11. 对于任何用于交换(例如,API 调用中的 JSON 文档中的字段)或存储的元素,请使用 CultureInfo;此外,还应显式指定往返格式(例如 "O""o" 日期时间格式说明符)。 尽管固定区域性的格式字符串稳定且不太可能更改,但指定显式格式字符串有助于阐明代码的意图。

  12. 全球化数据不稳定,在编写应用程序及其测试时应考虑到这一点。 它每年通过主机 OS 通道在所有受支持的平台上更新几次。 该数据通常不会随运行时一起分发。

本地化最佳做法

  1. 将所有可本地化的资源移动到单独的纯资源 DLL 中。 可本地化的资源包括用户界面元素,如字符串、错误消息、对话框、菜单以及嵌入的对象资源。

  2. 不要对字符串或用户界面资源进行硬编码。

  3. 不要将不可本地化的资源放在纯资源 DLL 中。 这会让翻译器感到困惑。

  4. 不要使用在运行时从串联词组生成的复合字符串。 复合字符串难以本地化,因为它们往往采用英语语法顺序,而此顺序并不适用于所有语言。

  5. 避免不明确的结构,如“Empty Folder”,因为根据字符串组成部分的语法规则,这些字符串可能产生不同的翻译。 例如,“empty”既可以是一个动词,也可以是一个形容词,因此在诸如意大利语或法语等语言中就可能导致不同的翻译。

  6. 避免在应用程序中使用包含文本的图像和图标。 本地化这些图像和图标的成本是很大的。

  7. 允许在用户界面中为字符串长度的扩展保留足够的空间。 在某些语言中,词组所需的空间可能比在其他语言中多 50-75%。

  8. 使用 System.Resources.ResourceManager 类来根据区域性检索资源。

  9. 使用 Visual Studio 创建 Windows 窗体对话框,以便可以使用 Windows 窗体资源编辑器 (Winres.exe) 对它们进行本地化。 不要对 Windows 窗体对话框进行手动编码。

  10. 安排进行专业本地化工作(翻译)。

  11. 有关创建并本地化资源的完整说明,请参阅.NET 应用中的资源

ASP.NET 和其他服务器应用程序的全球化最佳做法

提示

以下最佳做法适用于 ASP.NET Framework 应用。 有关 ASP.NET Core 应用,请参阅 ASP.NET Core 中的全球化和本地化

  1. 在应用程序中显式设置 CurrentUICultureCurrentCulture 属性。 不要依赖于默认设置。

  2. 请注意,ASP.NET 应用程序是托管应用程序,因此可以使用与其他托管应用程序相同的类,以根据区域性检索、显示和操作信息。

  3. 注意在 ASP.NET 中可以指定以下三种编码类型:

    • requestEncoding 指定了从客户端浏览器接收的编码。
    • responseEncoding 指定了要发送到客户端浏览器的编码。 在大多数情形下,此编码应该与为 requestEncoding 指定的编码相同。
    • fileEncoding 指定了用于 .aspx.asmx.asax 文件分析的默认编码。
  4. 指定 ASP.NET 应用程序内以下三个位置中 requestEncodingresponseEncodingfileEncodingcultureuiCulture 属性的值:

    • Web.config 文件的全球化部分中。 此文件是 ASP.NET 应用程序的外部文件。 有关详细信息,请参阅 <globalization> 元素
    • 在页面指令中。 请注意,当应用程序在页面中时,文件已经被读取。 因此,指定 fileEncoding 和 requestEncoding 为时已晚。 在页面指令中只能指定 uiCulturecultureresponseEncoding
    • 在应用程序代码中以编程方式指定。 该设置可能随请求的不同而不同。 同页面指令一样,如果在访问应用程序的代码时指定 fileEncodingrequestEncoding 就会为时已晚。 在应用程序代码中只能指定 uiCulturecultureresponseEncoding
  5. 请注意,uiCulture 值可以设置为浏览器接受的语言。

  6. 对于分布式的应用程序、允许零停机更新的应用程序(例如 Azure 容器应用)或类似的应用程序,必须考虑到可能存在多个应用程序实例的情况,这些实例具有不同格式规则或其他区域性数据,其中最相关的是时区规则。

    • 如果应用程序部署包含数据库,请记住该数据库将有自己的全球化规则。 在大多数情况下,应避免在数据库中执行任何与全球化相关的功能。
    • 如果应用程序部署包含使用客户端全球化资源的客户端应用程序或 Web 前端,则假定客户端资源不同于服务器可用的资源。 考虑只在客户端执行全球化功能。

可靠测试的建议

  1. 若要使依赖项更加明确,使测试更加容易和可并行化,应考虑显式传递区域性相关的设置,例如将 CultureInfo 参数传递给执行格式设置的方法,以及将 TimeZoneInfo 传递给处理日期和时间的方法。 检索时间时,还应使用 TimeProvider 或类似类型

  2. 对于大多数测试,不应显式验证给定格式设置操作的确切输出或时区的确切偏移。 格式设置和时区数据随时可能更改,在操作系统的两个其他方面相同的实例(可能是同一台计算机上的不同进程)之间可能有所不同。 依赖确切值会让测试变得脆弱。

    • 通常,验证是否收到某些输出就足够了(例如,格式设置时的非空字符串)。
    • 对于某些数据元素和格式,可能会改为验证数据是否解析为输入值(往返)。 对于删除字段(例如,某些与日期相关的字段的年份)或者截断或舍入值(例如浮点输出)的情况,需要加以注意。
    • 如果你有验证所有本地化格式输出的显式要求,应考虑在测试设置过程中创建和使用自定义区域性。 对于大多数简单情况,可以通过使用构造函数 new CultureInfo(..)CultureInfo 对象实例化,并设置 DateTimeFormatNumberFormat 属性来完成此操作。 对于更复杂的情况,子类化类型可以重写其他属性。 它还有潜在的其他好处,例如使用资源文件启用伪本地化
    • 如果明确要求验证所有日期/时间操作的结果,应考虑在测试设置过程中创建和使用自定义 TimeZoneInfo 实例。 它还有潜在的其他好处,例如可以对某些边缘情况进行稳定测试(例如,对 DST 规则的更改)。

另请参阅