Skip to main content
Version: 3.0.8

Culture and global configuration

Orientation

Humanizer chooses language and grammar from one of three places:

  1. A CultureInfo passed to the operation.
  2. CultureInfo.CurrentCulture or CurrentUICulture, depending on the API.
  3. A configured registry fallback when the requested culture has no matching component.

Per-call culture is the narrowest and safest choice. Ambient culture is useful when a request pipeline already establishes it. Global Configurator changes are process-wide policy.

Example

The example passes French directly to ToWords, establishes French ambient culture for APIs that need it, and keeps the custom transformer local:

Program.cs
using System.Globalization;
using Humanizer;

var french = CultureInfo.GetCultureInfo("fr-FR");
CultureInfo.CurrentCulture = french;
CultureInfo.CurrentUICulture = french;

AssertEqual("quarante-deux", 42.ToWords(french));
AssertEqual("BONJOUR", "bonjour".Transform(french, new LoudTransformer()));

Console.WriteLine("quarante-deux; BONJOUR");

static void AssertEqual(string expected, string actual)
{
if (actual != expected)
throw new InvalidOperationException($"Expected '{expected}', got '{actual}'.");
}

sealed class LoudTransformer : ICulturedStringTransformer
{
public string Transform(string input) =>
Transform(input, CultureInfo.CurrentCulture);

public string Transform(string input, CultureInfo culture) =>
culture.TextInfo.ToUpper(input);
}

That separation is intentional: select language close to the call, and reserve global configuration for behavior that truly applies to the entire application.

Why newer registries freeze

In Humanizer 3.x and current builds, LocaliserRegistry<TLocaliser> resolves and caches components by culture. On first resolution it freezes the registration table, making subsequent reads predictable and safe. A later Register call therefore throws instead of silently changing behavior for only some cultures or requests.

Date humanization strategies are mutable properties rather than registries, but they should still be set once during startup. Enum description-property selection has the same startup boundary: in 3.x, call UseEnumDescriptionPropertyLocator before any enum humanization; in 2.x, assign EnumDescriptionPropertyLocator during startup.

Pitfall

Setting only CurrentCulture is not always enough. Collection and enum localization can depend on CurrentUICulture, while numeric formatting commonly follows CurrentCulture. Set both at a well-defined boundary when you need consistent ambient behavior.

Version notes

Humanizer 2.x keeps localization registries mutable and exposes an assignable Configurator.EnumDescriptionPropertyLocator. Humanizer 3.x freezes registries after first use and replaces direct locator assignment with UseEnumDescriptionPropertyLocator. Treat the selected package and API reference as the authority for a specific release.