Skip to content

Commit

Permalink
Merge pull request #40492 from Clockwork-Muse/globalization-recommend…
Browse files Browse the repository at this point in the history
…ations

Add some globalization recommendations for best practices.
  • Loading branch information
tarekgh committed Apr 28, 2024
2 parents 3990433 + 92013ef commit be2836e
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ This section describes the best practices to follow when developing world-ready

1. If a security decision is based on the result of a string comparison or case change operation, use a culture-insensitive string operation. This practice ensures that the result is not affected by the value of `CultureInfo.CurrentCulture`. See the ["String Comparisons that Use the Current Culture"](../../standard/base-types/best-practices-strings.md#string-comparisons-that-use-the-current-culture) section of [Best Practices for Using Strings](../../standard/base-types/best-practices-strings.md) for an example that demonstrates how culture-sensitive string comparisons can produce inconsistent results.

1. For any element being used for interchange (for example, a field in a JSON document in an API call) or storage, use the <xref:System.Globalization.CultureInfo?displayProperty=InvariantCulture>; additionally, you should explicitly specify a roundtrip format (such as the [`"O"`, `"o"` date-time format specifier](../../standard/base-types/standard-date-and-time-format-strings.md#the-round-trip-o-o-format-specifier)). Although the format strings for the invariant culture are stable and unlikely to change, specifying an explicit format string helps to clarify the intent of your code.
- For date/time elements, consider the advice and observations of Noda Time author Jon Skeet, who shares valuable insights. For more information, see [Jon Skeet: _Storing UTC is not a silver bullet_](https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/).

1. Globalization data [is not stable](https://devblogs.microsoft.com/i18n/culture-data-shouldnt-be-considered-stable/), and you should write your application and its tests with this in mind. It's updated several times a year through host OS channels on all supported platforms. This data is typically not distributed with the runtime.

## Localization best practices

1. Move all localizable resources to separate resource-only DLLs. Localizable resources include user interface elements, such as strings, error messages, dialog boxes, menus, and embedded object resources.
Expand All @@ -66,7 +71,7 @@ This section describes the best practices to follow when developing world-ready

1. For a complete description of creating and localizing resources, see [Resources in .NET apps](resources.md).

## Globalization best practices for ASP.NET applications
## Globalization best practices for ASP.NET and other server applications

> [!TIP]
> The following best practices are for ASP.NET Framework apps. For ASP.NET Core apps, see [Globalization and localization in ASP.NET Core](/aspnet/core/fundamentals/localization).
Expand All @@ -89,6 +94,20 @@ This section describes the best practices to follow when developing world-ready

1. Note that the uiCulture value can be set to the browser accept language.

1. For applications that are distributed, allow zero-downtime updates (for example, Azure Container Apps), or similar you must plan for situations where there may be multiple instances of the application with different format rules or other culture data, most relevantly time zone rules.
- If your application deployment includes a database, remember that the database will have its own globalization rules. In most cases you should avoid performing any globalization-related functions in the database.
- If your application deployment includes a client application or web frontend using client globalization resources, assume that the client resources differ from the resources available to your server. Consider exclusively performing globalization functions on the client.

## Recommendations for robust testing

1. To make dependencies more explicit and testing potentially easier and parallelizable, you _should consider_ explicitly passing culture-relevant settings, such as `CultureInfo` parameters, to methods that perform formatting, and `TimeZoneInfo` to methods that work with dates and times. You _should also_ use <xref:System.TimeProvider> or a similar type when retrieving the time.

1. For most tests, you _shouldn't_ explicitly validate the exact output of a given formatting operation or the exact offset of a time zone. Formatting and time zone data may change at any time and may differ between two otherwise identical instances of an operating system (and potentially different processes on the same machine). Relying on an exact value makes tests brittle.
- Generally, validating that some output was received will be sufficient (for example, non-empty strings when formatting).
- For some data elements and formats, validating that the data parses to the input value may be used instead (roundtripping). Care needs to be taken for cases where fields are dropped (for example, year for some date-related fields) or the value truncated or rounded (such as for floating-point output).
- If you have explicit requirements to validate all localized format output, you _should consider_ creating and using a custom culture during test setup. For most simple cases this can be done by instantiating a `CultureInfo` object with its constructor `new CultureInfo(..)` and setting the `DateTimeFormat` and `NumberFormat` properties. For more complicated cases, subclassing the type allows overriding additional properties. There are potential additional benefits to this, such as enabling [pseudolocalization](/globalization/methodology/pseudolocalization) with resource files.
- If you have explicit requirements to validate the results of all date/time operations, you _should consider_ creating and using a custom `TimeZoneInfo` instance during test setup. There are potential additional benefits to this, such as enabling stable testing of certain edge cases (for example, changes to DST rules).

## See also

- [Globalization and Localization](globalization-and-localization.md)
Expand Down
3 changes: 3 additions & 0 deletions docs/core/extensions/globalization-icu.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Before .NET 5, the .NET globalization APIs used different underlying libraries o

Starting with .NET 5, developers have more control over which underlying library is used, enabling applications to avoid differences across platforms.

> [!NOTE]
> The culture data that drives the behavior of the ICU library is usually maintained by the [Common Locale Data Repository (CLDR)](https://cldr.unicode.org/), not the runtime.
## ICU on Windows

Windows now incorporates a preinstalled [icu.dll](/windows/win32/intl/international-components-for-unicode--icu-) version as part of its features that's automatically employed for globalization tasks. This modification allows .NET to leverage this ICU library for its globalization support. In cases where the ICU library is unavailable or cannot be loaded, as is the case with older Windows versions, .NET 5 and subsequent versions revert to using the NLS-based implementation.
Expand Down

0 comments on commit be2836e

Please sign in to comment.