Class-Based Modeling
The type name is the key, properties are the placeholders. Rename either and the compiler catches it.
Define a class, and you’ve defined a message. The type name is the key, the properties are the placeholders — rename either and the compiler catches it.
String-based localization keys are fragile. You pick "errors.required_field" by convention, match {0} placeholders by position, and maintain separate resource files that drift out of sync with every refactor.
Bogoware.Localization takes a different approach. The fully-qualified type name becomes the lookup key. Properties become template placeholders. Rename either and the compiler catches it — no conventions to memorize, no resource files to keep aligned by hand. It’s a well-established idea — types as messages — applied to localization.
The library handles the rest: three-tier culture fallback, a four-step provider resolution chain, recursive nested formatting, and seamless ASP.NET Core integration — including automatic JSON response localization and ProblemDetails support.
Class-Based Modeling
The type name is the key, properties are the placeholders. Rename either and the compiler catches it.
Culture Fallback
Three-tier resolution: exact culture, parent culture, then invariant culture.
Provider Resolution Chain
Self-provider, DI provider, registry template, then fallback format — in that order, always.
Nested Localization
ILocalizable properties are formatted recursively through the full resolution chain.
JSON Templates
Load templates from embedded resources, files, or raw JSON strings. JSONC supported.
JSON Serialization
Localize properties during System.Text.Json serialization automatically.
DI Integration
AddLocalization() extension methods with additive, assembly-scanning registration.
ASP.NET Core
Per-request culture resolution, JSON response localization, and ProblemDetails support.
Install from NuGet
dotnet add package Bogoware.LocalizationDefine a localizable type
using Bogoware.Localization;
public class RequiredFieldError(string fieldName) : ILocalizable{ public string FieldName { get; } = fieldName;}Create JSON templates (embedded resources)
{ "MyApp.Errors.RequiredFieldError": "'{FieldName}' is required" }
// localized-messages.it-IT.json{ "MyApp.Errors.RequiredFieldError": "'{FieldName}' è obbligatorio" }Register and format
services.AddLocalization(typeof(RequiredFieldError).Assembly);
var formatter = serviceProvider.GetRequiredService<ILocalizationFormatter>();var message = formatter.Format(new RequiredFieldError("Email"));// → "'Email' is required" (en-US)// → "'Email' è obbligatorio" (it-IT)| Type | Purpose | Key Operations |
|---|---|---|
ILocalizable | Marker interface for localizable types | Implement on any class to make it localizable |
ILocalizationFormatter | Format localizable objects to strings | Format(ILocalizable) with culture support |
ILocalizationRegistry | Store and retrieve templates | TryGetTemplate(type, culture) with fallback |
ILocalizationProvider<T> | DI-based per-type providers | Register via AddLocalization() |
JsonLocalizationRegistry | JSON-backed template storage | Load from embedded resources, files, or strings |