Skip to main content
Version: 2.14.1

Localization and extensibility

Orientation

Start with culture selection, then choose the narrowest extension point. Pass CultureInfo per call when possible. Establish CurrentCulture and CurrentUICulture at a request or job boundary for ambient APIs. Use a local interface implementation for one operation and reserve Configurator registries or strategies for process-wide application policy.

Example

This verified example produces French number words and supplies a per-call culture-aware transformer:

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);
}

The result is quarante-deux; BONJOUR. A per-call transformer is isolated and easy to test.

Choose an extension point

NeedPreferred extension
One local string operationIStringTransformer or ICulturedStringTransformer
A custom truncation ruleITruncator passed to Truncate
Relative date thresholdsA date/time strategy assigned once
Application-wide locale componentThe matching LocaliserRegistry<T>
Enum metadata propertyassign Configurator.EnumDescriptionPropertyLocator at startup

Registries cover collection formatters, general formatters, number-word converters, ordinalizers, date-ordinal converters, and clock-notation converters. Culture resolution checks the requested culture and its parents before using the registry default.

Pitfall

In Humanizer 3.x and current, localizer registries freeze on first resolution. Register components before any Humanizer call can resolve that registry. Humanizer 2.x registries remain mutable, but startup registration still prevents request-to-request drift. Do not mutate global strategies per request; concurrent callers can observe the change.

Parent-culture fallback identifies where behavior was resolved. It does not prove that inherited wording is correct for every region.

Version notes

The example’s local transformer runs across the supported corpus. Registry immutability and enum metadata configuration change in Humanizer 3. Individual registries and locale capabilities are selected-version behavior; historical snapshots must not present current YAML/generator internals as old package behavior.