I was tasked at work with making my client’s Blazor Web Server app internationalized. It was quite an easy task; that is, until I had to localize the error messages from validation attributes (which are used a LOT throughout the app).
I looked for an answer for ages, because I just couldn’t accept what was evidently true – you have to manually add ErrorMessageResourceType and ErrorMessageResourceName to every single validation attribute.
This would have taken me a week at least, likely longer, and doing it manually meant I was sure to mess something up and present the wrong message for an attribute.
It would have been nice if it were possible to set ErrorMessageResourceType and ErrorMessageResourceName globally. So, I wrote a library that does it…
https://github.com/mrpmorris/AutoLocalize
- Add a Nuget reference to Fody to your project.
- Add a Nuget reference to Morris.AutoLocalize.Fody too.
- Build (this will add FodyWeavers.xml to the project).
- Edit FodyWeavers.xml and add
<Morris.AutoLocalize /> - Finally, add this attribute to your assembly
using Morris.AutoLocalize; [assembly: AutoLocalizeValidationAttributes(typeof(YourResourceType))]
Note: To get auto generated classes for resx files, inspect the file’s properties and set the Build Tool to PublicResXFileCodeGenerator.
When you build you will see a new CSV file in your project folder showing you which ErrorMessageResourceName entries need to be in your resx file.
Your already internationalized app will now also look for localized error messages for validation attributes!
I hope you’ll find this interesting/useful.
PS: There is a PowerShell script in the repo root you can run which will use chat GPT to translate any modified resx files into a target language.
PPS: If you don’t already know how to add Internationalization support to your Blazor app, this is the code you need around the builder.Build() line. It picks up the user’s supported language that is sent by the browser (in priority order) and then uses the first matching one as the current culture.
builder.Services.AddLocalization();
// This is the line that already exists in your Program.cs file
var app = builder.Build();
// Localisation
var supportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("fr"),
// etc
};
var requestLocalizationOptions = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures,
};
requestLocalizationOptions.RequestCultureProviders =
[
new AcceptLanguageHeaderRequestCultureProvider(),
];
app.UseRequestLocalization(requestLocalizationOptions); 
Comments