Provider Chain
The ILocalizationFormatter resolves localized strings through a chain of providers, stopping at the first one that returns a result.
Resolution Order
-
Self-provider — If the type implements
ILocalizationProvider, itsLocalize(culture)method is called directly -
DI provider — If an
ILocalizationProvider<T>for the specific type is registered in the DI container, it is used -
Registry template — The
ILocalizationRegistryis queried using the type’sFullNameas key -
Default format —
TypeName(Prop1=val1, Prop2=val2)— a diagnostic representation
Self-Provider
The highest priority. Implement ILocalizationProvider directly on your type:
public class SpecialError : ILocalizable, ILocalizationProvider{ public string Localize(CultureInfo culture) => "Special error message";}DI Provider
Register a provider for a specific type in the DI container:
public class OrderErrorProvider : ILocalizationProvider<OrderError>{ public string? Localize(OrderError instance, CultureInfo culture) { // Custom localization logic return $"Order {instance.OrderId} failed: {instance.Reason}"; }}
// Registrationservices.AddSingleton<ILocalizationProvider<OrderError>, OrderErrorProvider>();Registry Template
The standard approach. Templates are loaded from JSON files into the ILocalizationRegistry:
{ "MyApp.Errors.OrderError": "Order #{OrderId} failed: {Reason}"}Default Format
When no other provider returns a result, the formatter produces a diagnostic string:
OrderError(OrderId=12345, Reason=Payment declined)This ensures that the formatter always returns a meaningful string, even without configured templates.
Recursive Resolution
When a template placeholder or fallback property resolves to an ILocalizable value, the entire chain is applied recursively. The culture is propagated through all nesting levels. See the Nested Localization guide for details and examples.