Choose explicit and ambient cultures
August 2, 2026 ยท View on GitHub
Pass a CultureInfo directly when an overload accepts one. It makes the
language choice visible, keeps concurrent requests isolated, and is easy to
test. Set CurrentCulture and CurrentUICulture together at a request,
message, or job boundary for APIs that use ambient culture.
Culture names are .NET culture identifiers. A specific culture such as
fr-FR can map to neutral fr locale data when that exact regional name is in
Humanizer's generated accepted-culture inventory. Built-in registries use this
generated map and do not walk arbitrary .NET parents. A caller-created
LocaliserRegistry<TLocaliser> retains parent-chain fallback and uses its
default only when no registered parent matches.
Example
using System.Globalization;
using Humanizer;
var french = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(42.ToWords(french));
The output is quarante-deux.
Keep using explicit overloads inside shared services where possible; this prevents one concurrent operation from changing another operation's output.
Establish ambient culture at a boundary
Some APIs use the ambient culture:
using System.Globalization;
using Humanizer;
var french = CultureInfo.GetCultureInfo("fr-FR");
CultureInfo.CurrentCulture = french;
CultureInfo.CurrentUICulture = french;
Console.WriteLine(42.ToWords());
The output is again quarante-deux.
Keep both ambient cultures consistent
CurrentCulture and CurrentUICulture serve different .NET concerns, and
Humanizer APIs can use either one. Setting only one can produce mixed-language
output. Avoid changing ambient culture in a shared request path when an
explicit overload exists.
Profile reuse is resolution, not parity proof. If an accepted fr-CA mapping
reaches fr, that only identifies where the data came from. It does not
establish that French Canadian wording matches every neutral-French choice.
Choose an application fallback
Use Configurator.IsCultureSupported(culture) before choosing an application
fallback. It checks the exact culture name against Humanizer's generated
accepted-culture inventory and does not return true merely because an
arbitrary parent or the default English localizers could produce output:
var requested = CultureInfo.GetCultureInfo("fr-FR");
var culture = Configurator.IsCultureSupported(requested)
? requested
: CultureInfo.GetCultureInfo("en");
If inherited or direct output is wrong, follow the language correction guide or open a prefilled locale issue.