Pragmatic.Internationalization
Comprehensive internationalization (i18n) and localization (l10n) for .NET 10: async-safe culture context, money & currency value types, culture-aware formatting, compile-time-checked translations with plural support, and humanizers.
The Problem
Section titled “The Problem”.NET gives you low-level globalization primitives (CultureInfo, .resx), but a real multilingual app
hits the same gaps:
- Thread culture is fragile —
CurrentCultureis thread-local; after anawaityour continuation may run on a different thread, andDefaultThreadCurrentCultureis a process-wide, multi-tenant trap. - No multi-scope culture — a request may need Italian UI, English API responses, German invoices. .NET gives you two slots; beyond that you’re on your own.
- Money is not a type — every app reinvents a
Moneystruct, silently adds USD to EUR, and formats inconsistently. - Plurals are language-specific — English has 2 forms, Russian 3, Arabic 6;
count == 1 ? a : bis wrong for most of the world. .resxdoesn’t compose — translations scatter across XML with no build-time completeness check; you can ship with half a language missing.
The Solution — five pillars
Section titled “The Solution — five pillars”I18NContext— anAsyncLocalambient context that flows acrossawait, supports multiple culture scopes (UI, Data, custom), and syncs with .NET thread cultures.Money&CurrencyCode— value types enforcing same-currency arithmetic, ISO 4217 metadata, and culture-aware formatting.- Formatting — extension methods + an injectable
GlobalizationFormatterfor numbers, dates, money, percentages, and file sizes. - Translation keys (SG) — a generator reads JSON at compile time and produces a static
Tclass of strongly-typedLocalizedStringproperties; missing translations are build warnings (PRAG1802). - Humanizers — duration, ordinal, quantity, and relative-time formatters for 17+ languages.
var price = Money.From(99.99m, CurrencyCode.EUR);price.Format(); // "99,99 €" (it-IT) / "€99.99" (en-US)
return new NotFoundError(T.Errors.OrderNotFound.Value); // compile-time-safe translationThe middleware sets I18NContext from Accept-Language / query string / a provider chain, and it
flows across every await automatically.
Quick Start — translations
Section titled “Quick Start — translations”- Add JSON files under
translations/(one per culture:en.json,it.json, …). - Include them in your
.csproj:<AdditionalFiles Include="translations/*.json" />. - Reference
Pragmatic.SourceGenerator. - Use the generated
Tclass:
var text = T.Welcome.Value; // current culturevar italian = T.Errors.NotFound["it"]; // a specific cultureFull walkthrough: Getting Started.
Packages
Section titled “Packages”| Package | Description |
|---|---|
Pragmatic.Internationalization | Core: context, Money/CurrencyCode, formatting, humanizers, generated T |
Pragmatic.Internationalization.AspNetCore | Culture middleware, ProblemDetails localization, frontend endpoint |
Pragmatic.Internationalization.EFCore | LocalizedString entity storage |
Installation
Section titled “Installation”dotnet add package Pragmatic.Internationalizationdotnet add package Pragmatic.SourceGenerator # generates the strongly-typed T classFeatures at a glance
Section titled “Features at a glance”- Async-safe, multi-scope culture context (UI / Data / custom).
Moneywith same-currency-enforced arithmetic + ISO 4217CurrencyCode.- Culture-aware formatters for numbers, dates, money, percent, file sizes.
- Compile-time-checked translations with CLDR plural rules.
- Humanizers for duration, ordinals, quantities, relative time (17+ languages).
- ASP.NET Core middleware + EF Core
LocalizedStringstorage.
Status
Section titled “Status”Stable within the 0.8 preview — the five pillars, the translation generator, and the ASP.NET Core / EF Core integrations are settled. See the roadmap.
| Concepts | The five pillars in depth: culture context, Money/Currency, formatting, plural rules, humanizers, integrations |
| Getting Started | Translations, Money, formatting, and humanizers from zero |
| Translation Keys | JSON layout, the generated T class, plural forms, completeness warnings |
| Common Mistakes | The most frequent i18n pitfalls |
| Troubleshooting | Problem/solution guide with diagnostics |
Requirements
Section titled “Requirements”- .NET 10.0+
Pragmatic.SourceGeneratoranalyzer (for the translationTclass)
License
Section titled “License”Part of the Pragmatic.Design ecosystem — see Licensing. Pragmatic.Internationalization is MIT-licensed.