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)
var subject = T.Emails.OrderShipped.Value; // compile-time-safe translation, current cultureThe 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.Common.Welcome["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 (JSON column) and CurrencyCode (varchar(3)) 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”Functional within 1.0.0-alpha: the five pillars, the translation generator, and the ASP.NET Core and EF Core integrations; the surface may still change before 1.0. See the roadmap and the CHANGELOG.
| Concepts | The five pillars in depth: culture context, Money/Currency, formatting, plural rules, humanizers, integrations |
| Getting Started | Translations, Money, formatting, and humanizers from zero |
| Integration | ASP.NET Core middleware, I18NBuilder/UseI18N, translation endpoint, localized ProblemDetails, EF Core |
| 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.
