Skip to content

Ability to translate all DataAnnotations without having to specify ErrorMessage #4848

Description

@tbolon

Currently, ValidationAttributeAdapterOfTAttribute.GetErrorMessage uses IStringLocalizer only when ErrorMessage is set:

protected virtual string GetErrorMessage(ModelMetadata modelMetadata, params object[] arguments)
{
    if (modelMetadata == null)
    {
        throw new ArgumentNullException(nameof(modelMetadata));
    }

    if (_stringLocalizer != null &&
        !string.IsNullOrEmpty(Attribute.ErrorMessage) &&
        string.IsNullOrEmpty(Attribute.ErrorMessageResourceName) &&
        Attribute.ErrorMessageResourceType == null)
    {
        return _stringLocalizer[Attribute.ErrorMessage, arguments];
    }

    return Attribute.FormatErrorMessage(modelMetadata.GetDisplayName());
}

The consequence is that you have to set the ErrorMessage property each time you want to translate an error message.

Suppose you just want to translate the default RequiredAttribute ErrorMessageString, which is The {0} field is required. for all your Model classes.

  1. You must override the default DataAnnotationLocalizerProvider to return a shared resource.
  2. You add a generic entry named, for example, "DataAnnotations_Required" with the translated value format: Le champ {0} doit être renseigné.
  3. You must replace all the [Required] attributes with [Required(ErrorMessage = "DataAnnotations_Required")]

More generally, there is no way to just adapt the generic DataAnnotation validation messages to your language. (the ones in System.ComponentModel.Annotations.SR.resources) without having to replace all your data annotations.

The documentation only provide a sample where the messages are customized for each property (despite the fact that only the property name change).

There is no easy workaround either:

  • You can't inherit from RequiredAttribute to fix the ErrorMessage property, since the framework uses strict type comparison
  • Replacing the default ValidationAttributeAdapterProvider is not trivial, because you have to replace all adapters with custom ones to override the GetErrorMessage method.

Is there a better way to achieve localization for all default data annotation error messages ?
Or room for improvement in asp.net core mvc to reduce the burden of writing all this custom code ?

Activity

  1. changed the title [-]Ability to localize all DataAnnotations without specifiing ErrorMessage[/-] [+]Ability to translate all DataAnnotations without specifiing ErrorMessage[/+] on Aug 22, 2017
  2. Eilon commented on Aug 24, 2017

    @Eilon
    Contributor

    @tbolon unfortunately the problem is that the built-in data annotations will return already-localized resources if the right resources are installed on the system (via NuGet, or in .NET Framework). Because of that, ASP.NET Core's localization system won't know what to translate off of because it will get "random" text depending on what's installed. That's why ASP.NET Core requires that you specify a specific error message so that it knows exactly what to key off of.

  3. tbolon commented on Aug 25, 2017

    @tbolon
    Author

    You are right. In my case there was no satellite resource assembly loaded, so resources were always returned in English. Despite that, perhaps the ValidationAttributeAdapterProvider could, at least, be enhanced to match sub-classes. So we could create a custom LocRequiredAttribute : RequiredAttribute class with a fixed ErrorMessage set.

    One additional point to take into consideration: some validation messages are obtained through DefaultModelBindingMessageProvider, and there is an opportunity to translate them using MvcOptions and Set...Accessor() methods. eg. SetValueMustBeANumberAccessor used to display validation error for numbers.

    This part is never addressed in the documentation and I discovered it only by chance.

    It seems there are some inconsistencies or, at least, some rough edges regarding localization & model binding in asp.net core for now. I don't know how exactly they could be solved...

  4. Eilon commented on Sep 7, 2017

    @Eilon
    Contributor

    Crazy idea time:

    If the system sees that ErrorMessage isn't set, it can try to call into the loc system with some well-known key (such as System.ComponentModel.DataAnnotations.Required.Message) to see if the loc system returns a value not equal to that key. If it returns the key, clearly it has not been localized and so it should fall back to getting the data annotation attribute's intrinsic error message. If it returns some other value, it can assume it was localized and use that as the error message.

    @DamianEdwards @ryanbrandenburg @hishamco - does this sound like it might work?

  5. ryanbrandenburg commented on Sep 11, 2017

    @ryanbrandenburg
    Contributor

    I can't think of any technical reason why that wouldn't work, but I'm kind of wary of adding magic keys which do specific things.

  6. mkArtakMSFT commented on Jan 10, 2018

    @mkArtakMSFT
    Contributor

    We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

  7. effyteva commented on Aug 16, 2018

    @effyteva

    Any updates on this one?
    It's very critical for large applications...

  8. iamdroppy commented on Sep 8, 2018

    @iamdroppy

    I agree with OP, this should be enhanced.

  9. alexandrejobin commented on Nov 6, 2018

    @alexandrejobin

    In MVC5 and lower, it was really easy to make the validation work in other language. Just publish your website with the right resources files that came from Microsoft and you were good.

    • \fr\System.ComponentModel.DataAnnotations.resources.dll
    • \fr\System.Web.Mvc.resources.dll
    • \fr\EntityFramework.resources.dll

    With MVC Core 2.1, if i want to localize the error messages from DataAnnotations and MVC libraries, i need to:

    • Use the ErrorMessage property on each DataAnnotations validation attribute to tell them the resource key to use. By doing this, it also require me to create an english resource file and define all validation error messages that is already present in original library (weird).
    • Change all ModelBindingMessageProvider properties to support my languages like so:
    services.AddMvc(options =>
        {
            options.ModelBindingMessageProvider.SetValueIsInvalidAccessor(x => $"The value '{x}' is invalid.");
            options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor(x => $"The field {x} must be a number.");
            options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor(x => $"A value for the '{x}' property was not provided.");
            options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, y) => $"The value '{x}' is not valid for {y}.");
            options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => "A value is required.");
            options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor(x => $"The supplied value is invalid for {x}.");
            options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(x => $"The value '{x}' is invalid.");
            options.ModelBindingMessageProvider.SetMissingRequestBodyRequiredValueAccessor(() => "A non-empty request body is required.");
            options.ModelBindingMessageProvider.SetNonPropertyAttemptedValueIsInvalidAccessor(x => $"The value '{x}' is not valid.");
            options.ModelBindingMessageProvider.SetNonPropertyUnknownValueIsInvalidAccessor(() => "The supplied value is invalid.");
            options.ModelBindingMessageProvider.SetNonPropertyValueMustBeANumberAccessor(() => "The field must be a number.");
        })
    

    The problem with that?

    • When Core 2.0 came out, 4 new validation messages were added to the framework (MissingRequestBodyRequiredValueAccessor, NonPropertyAttemptedValueIsInvalidAccessor, NonPropertyUnknownValueIsInvalidAccessor and NonPropertyValueMustBeANumberAccessor) . We have to be very careful and search for new strings to localize by our own each time we upgrade the framework.

    My thought on this is if the library has messages that is intended to be used in UI like the RequiredAttribute, RangeAttribute, etc, the library should come localized by the owner (Microsoft). If i want to override the messages, i can do it with my own resource files.

  10. changed the title [-]Ability to translate all DataAnnotations without specifiing ErrorMessage[/-] [+]Ability to translate all DataAnnotations without having to specify ErrorMessage[/+] on Nov 6, 2018
  11. transferred this issue fromaspnet/Mvcon Dec 13, 2018
  12. added this to the Backlog milestone on Dec 13, 2018
  13. 28 remaining items

  14. added
    area-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templates
    and removed
    old-area-web-frameworks-do-not-use*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels
    on Jun 20, 2023
  15. omarceloribeiro commented on Oct 10, 2023

    @omarceloribeiro

    This is a huge problem because it impact even some small hello world project that is not made inside the USA.
    if you are in any country that don't speak english and you create a simple mvc web project, you get all the messages in english wihout any easy way to provide translations. nothing works. no nuget packages, no resx files to download, to install, no classes to implement. nothing works. and it is just the start of hello world project. How this is not solved yet?

  16. Erwinvandervalk commented on Nov 2, 2023

    @Erwinvandervalk

    Data Annotations can be used independently from MVC (for example if you're using console apps or minimal api's).

    You want to be able to plugin a translation mechanism directly into Data Annotations. Whatever will be done for this (once it eventually get's picked up), please don't just limit it to MVC only.

  17. cactusoft commented on Nov 28, 2023

    @cactusoft

    Best I have found is Toolbelt.Blazor.LocalizedDataAnnotationsValidator in nuget. I have a custom resources provider set up in my db (so I can change text values through my admin section without having to restart the app). But I think it should work fine with a regular resource file too.

    [Required(ErrorMessage = "core.errors.dataannotations.required")]

    Problem is that not all the .net core validation seems to be exposed. I am getting "The XXX field must be a number." on InputNumber elements, but since I don't have any validation explicitly set, there doesn't seem to be any obvious way to override it.

  18. ips219 commented on Feb 3, 2024

    @ips219

    For the records...

    As a workaround I found this solution in https://stackoverflow.com/a/57428328/7731148

    It is working correctly in my project just by adding an small static initialization and the original Strings comming from github translated...

    I cannot aunderstand why DA does not allow to override default messages by configuration for five years...

  19. Tridus commented on Jan 23, 2025

    @Tridus

    unfortunately the problem is that the built-in data annotations will return already-localized resources if the right resources are installed on the system (via NuGet, or in .NET Framework).

    Where do you get these in NuGet? That seems the easiest solution since then the default case will work in whatever language you install, since it is supposed to already support that.

    Barring that, add an option to specify a resource type for all these messages to look in instead of the default, if set, so we can set that and then supply the sources. This is what DataAnnotationLocalizerProvider seems like it should do, except due to how these work it still winds up only working in English if you don't specify ErrorMessage on each attribute.

    It baffles me that it's been this many years for something that impacts basically every multilingual application and the suggested fix is still "specify ErrorMessage on every annotation".

    In the mean time, @ips219 posted a solution that still works in .net 8.

  20. added
    feature-validationIssues related to model validation in minimal and controller-based APIs
    on Feb 10, 2026
  21. added theissue type on May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    affected-mediumThis issue impacts approximately half of our customersarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-model-bindingfeature-validationIssues related to model validation in minimal and controller-based APIsseverity-minorThis label is used by an internal tool

    Projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions