How to localize standard error messages of validation attributes in ASP.NET Core (v2.2)? For Example, [Required] attribute has this error message "The xxx field is required."; [EmailAddress] has "The xxx field is not a valid e-mail address."; [Compare] has "'xxx' and 'yyy' do not match." and so on. In our project we use not English language and I want to find a way how to translate standard error messages without writing them directly in every attribute of every data-model class
Asked
Active
Viewed 3,132 times
5
-
Did you find any solution? – Sam Alekseev Dec 24 '20 at 08:22
2 Answers
2
If you just want to localize the error messages but not to build a multi-language site, you may try this: (the message strings may be in your language.)
- Add a custom
IValidationMetadataProvider
:
public class MyModelMetadataProvider : IValidationMetadataProvider
{
public void CreateValidationMetadata(ValidationMetadataProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException();
}
var validators = context.ValidationMetadata.ValidatorMetadata;
// add [Required] for value-types (int/DateTime etc)
// to set ErrorMessage before asp.net does it
var theType = context.Key.ModelType;
var underlyingType = Nullable.GetUnderlyingType(theType);
if (theType.IsValueType &&
underlyingType == null && // not nullable type
validators.Where(m => m.GetType() == typeof(RequiredAttribute)).Count() == 0)
{
validators.Add(new RequiredAttribute());
}
foreach (var obj in validators)
{
if (!(obj is ValidationAttribute attribute))
{
continue;
}
fillErrorMessage<RequiredAttribute>(attribute,
"You must fill in '{0}'.");
fillErrorMessage<MinLengthAttribute>(attribute,
"Min length of '{0}' is {1}.");
fillErrorMessage<MaxLengthAttribute>(attribute,
"Max length of '{0}' is {1}.");
fillErrorMessage<EmailAddressAttribute>(attribute,
"Invalid email address.", true);
// other attributes like RangeAttribute, CompareAttribute, etc
}
}
private void fillErrorMessage<T>(object attribute, string errorMessage,
bool forceOverriding = false)
where T : ValidationAttribute
{
if (attribute is T validationAttribute)
{
if (forceOverriding ||
(validationAttribute.ErrorMessage == null
&& validationAttribute.ErrorMessageResourceName == null))
{
validationAttribute.ErrorMessage = errorMessage;
}
}
}
}
- add some lines in
Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews()
.AddMvcOptions(m => {
m.ModelMetadataDetailsProviders.Add(new MyModelMetadataProvider());
m.ModelBindingMessageProvider.SetValueMustBeANumberAccessor(
fieldName => string.Format("'{0}' must be a valid number.", fieldName));
// you may check the document of `DefaultModelBindingMessageProvider`
// and add more if needed
})
;
}
see the document of DefaultModelBindingMessageProvider
If you can read in Japanese, see this article for more details.

percyboy
- 51
- 6
-
Thanks! Works fine in ASP.NET Core 7.0. BTW, defining a custom EmailAddressAttribute error message won't have any effect in all major browsers, because ASP.NET Core adds the type="email" to the input, which triggers the browser's validation, and if it doesn't pass, the browser displays its own error message (in the browser's current language) and the form isn't submitted – Dan Z Mar 28 '23 at 18:13
1
This is spelled out in the docs. You can do either:
Use the
ResourcePath
option on the attribute.[Required(ResourcePath = "Resources")]
Then, you'd add the localized message to
Resources/Namespace.To.MyClass.[lang].resx
.Use one resource file for all classes:
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource)); }); }

Chris Pratt
- 232,153
- 36
- 385
- 444
-
3looks like this approach expects ErrorMessage parameter for all attributes in all models to be translated. I want to avoid it – Vitaliy Dec 12 '19 at 11:39