Repository navigation
Description
In my case, I have custom localization service (like IStringLocalizer), that retrieve localization from database for user-specific culture. User culture configures in user settings, that may changes in application runtime, i.e. without page reload.
ILocalizationService
{
string this[string key] { get; }
string GetString(string key);
void ChangeLanguage(CultureInfo culture);
}
Service registers as scoped, i.e. each user have own ILocalizationService with own specific culture settings.
services.AddScoped<ILocalizationService, LocalizationService>();
In components this works great, just inject service.
@page "/some-page"
@inject ILocalizationService T
<h1>@T["SomeText"]</h1>
Of course, this does not work in standard case of using data annotation attributes. For example:
User
{
[Required]
[Display(Name = "Name")]
string Name { get; set; }
[Display(Name = "Email")]
string Email { get; set; }
}
Data annotation attributes can be provided with custom type with localized strings. Something like this:
User
{
[Required(ErrorMessageResourceName = "Validation_Required", ErrorMessageResourceType = typeof(LocalizationResources))]
[Display(Name = "Name", ResourceType = typeof(LocalizationResources))]
string Name { get; set; }
[Display(Name = "Email", ResourceType = typeof(LocalizationResources))]
string Email { get; set; }
}
LocalizationResources
{
public static string Name => GetString();
public static string Email => GetString();
public static string Validation_Required => GetString();
public static Func<ILocalizationService> LocalizationServiceProvider { get; set; }
public static string GetString([CallerMemberName] string key = null)
{
return LocalizationServiceProvider().GetString(key);
}
}
Main problem of this approach is that localized strings in LocalizationResources must be as static properties. So we cant directly inject user-specific ILocalizationService. But we can try get user-specific ILocalizationService via Func<ILocalizationService> LocalizationServiceProvider that can be configured, for example, in Configure() method:
public void Configure(IServiceProvider serviceProvider)
{
LocalizationResources.LocalizationServiceProvider = () => serviceProvider.GetRequiredService<ILocalizationService>();
}
Of course, this does not work, because of scope of serviceProvider in Configure() method differs from user-specific scopes. In order for this approach to work it is necessary in LocalizationResources.LocalizationServiceProvider uses some kind of context that will provide user-scoped IServiceProvider to resolve user-specific ILocalizationService.
So, at this moment, in server-side Blazor is exists any method to localize the data annotation attributes in non-resx scenarios? Have a plan to implement its in future?
Activity
mkArtakMSFT commentedon Jul 16, 2019
Thanks for contacting us, @qw-34.
We don't have any plans to support this in 3.0, but we'll look to bring support for the in the future.
sven5 commentedon Sep 2, 2019
Please also add support for
DataAnnotationLocalizerProviderin Blazor - we already have this in MVC.agonzalezm commentedon Oct 3, 2019
will this be supported in 3.1? we also need full multi-language support for server-side application texts, data annotations validations, etc
marinasundstrom commentedon Apr 20, 2020
Localization is now supported in Blazor, using
Microsoft.AspNetCore.Localization:DataAnnotations are not really supported though.
After some quick investigation, my conclusion is that the
DataAnnotationsValidatoris the class that should be responsible for resolving the string from the preferred .resx file.It could be implemented there by injecting
StringLocalizer<T>(where T is the Component) into the ``DataAnnotationsValidatorand then pass it toEditContextDataAnnotationsExtensions .AddDataAnnotationsValidation```.https://github.com/dotnet/aspnetcore/blob/057ec9cfae1831f91f1a0e01397059b20431db7b/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs
But you need to create adapters to handle the localization of specific data annotations, like in MVC:
https://github.com/dotnet/aspnetcore/tree/c565386a3ed135560bc2e9017aa54a950b4e35dd/src/Mvc/Mvc.DataAnnotations/src
It might be a bigger task than expected.
There is also an experimental
ObjectGraphDataAnnotationsValidatorthat validates not only top-level properties. Maybe that will replace theDataAnnotationsValidatorin the future.fededim commentedon Mar 30, 2021
Is there any schedule to support Data Annotations localization in Blazor ? Without them Blazor apps are fully localized in a language, but the standard data annotation errors remain still in English....this "double language" is not great from the user perspective. Think about this feature, it's important for every application.
[-][Blazor] Problems with localization of data annotation attributes in server-side Blazor[/-][+][Blazor] Data annotations localization support[/+]62 remaining items
oroztocil commentedon Feb 27, 2026
I submitted a design proposal for localization support in
Microsoft.Extensions.Validation: #65539This would cover all the localization features requested in this thread to Blazor form validation.
mrpmorris commentedon Mar 11, 2026
This is how I solved the problem.
Set the Build Tool property of your resx file to
PublicResXFileCodeGeneratorThen add the code needed to localize a Blazor app...
Now when you access the static property MyResx.PropertyName it will use the relevant translation based on the user's browser request. No need for IStringLocalizer, just use the static properties.
As for the ValidationAttribute descendants, if you are willing to use a Fody weaver then I created AutoLocalize which lets you do this
It will automatically set the ErrorMessageResourceType on all validation attributes (that you've not already set it on) and set the ErrorMessageResourceName to AutoLocalize_{ShortAttributeName}
For example
Note, you can change the AutoLocalize_ prefix in the assembly-level attribute.
mrpmorris commentedon Mar 13, 2026
I really disliked the
IStringLocalizer<T>approach. Being able to use magic strings was not a good experience. In my client's app they use multiple resx files (one per page) and I saw many examples ofTinIStringLocalizer<T>.nameof(SomeResource.SomeProperty)but using the wrongSomeResourceclass (which has a same or similar looking property name).Once I realised that literally putting
@SomeGeneratedStaticClassForResx.SomePropertyin razor cs code would use the current user's locale, I was not only very surprised (magic) but also relieved that I could dump all thoseIStringLocalizer<T>injections in my app. But that only solved the text I wanted to show in the UI, not error messages from Microsoft.What about having a static
ValidationAttribute.DefaultErrorMessageResourceTypeproperty that is used whenever theErrorMessageResourceTypeinstance property is null? You could use the defaultValidatorAttribute_{ClassShortName}for theErrorMessageResourceNametoo.Would that not solve the problem very easily? It would just need two static members added, and the getter for the two instance properties changed to return a default value when none is present. Perhaps have a protected
bool UseDefaultErrorMessageResourceTypeAndNameinstance method onValidatorAttributeso descendants have to set it to True to opt in. You could then enable it in MS code to opt-in without affecting other people's code.Benefits
mrpmorris commentedon May 18, 2026
@oroztocil I see you have closed this as completed, but there are no PR's associated with it for us to look at the source code.
oroztocil commentedon May 18, 2026
@mrpmorris I apologize, that was a mistake I made in my PR description. See #66646
Note that the PR description is not completely up to date after few changes we settled on during review (including offline review).
[release/11.0] Add message template formatting to DataAnnotations val…