Skip to content
This repository has been archived by the owner on Feb 23, 2021. It is now read-only.

Localization of data annotation attributes in Localization.StarterWeb #187

Closed
xps opened this issue Jan 4, 2017 · 5 comments
Closed

Localization of data annotation attributes in Localization.StarterWeb #187

xps opened this issue Jan 4, 2017 · 5 comments
Labels
Milestone

Comments

@xps
Copy link

xps commented Jan 4, 2017

I am looking for an example showing how to localize data annotation attributes. I feel like this should belong in the Localization.StarterWeb sample, but unfortunately it is not implemented. Here you can see English field names and validation messages when the French language is selected:

image

There are mostly 4 things that I would like to see:

  1. Localization of messages of ValidationAttributes (e.g. [Required], "The {0} field is required.")
  2. Localization of display names ([Display(Name = "Email Address")])
  3. Localization of built-in validation messages ("The field {0} must be a number.")
  4. Display of numbers and dates in a format matching the current culture, and properly taking that format into account in the built-in front-end validation (jquery.validate)

Ideally, in a way that is compatible with implementing a custom IStringLocalizer to retrieve the translations...

I would be willing to submit a PR given some pointers.

Any help appreciated.

@xps xps changed the title Localization of validation of data annotation attributes in Localization.StarterWeb Localization of data annotation attributes in Localization.StarterWeb Jan 4, 2017
@dougbu
Copy link
Member

dougbu commented Jan 4, 2017

This sample might not use enough of the MVC support for it to be visible. Look at samples/Mvc.LocalizationSample.Web instead.

@xps
Copy link
Author

xps commented Jan 5, 2017

Thanks, I had a look and indeed it shows how to address some of my points, namely:

  • Localization of ValidationAttributes with explicit messages (e.g. [Required(ErrorMessage = "This field is required")])
  • Localization of display names (e.g. [Display(Name = "Email Address")])

However, it does not show (and I don't know how to):

  • Localize ValidationAttributes that use the default message (e.g. [Required] or [MaxLength(20)])
  • Localize validation messages that appear automatically when there are no attributes. For instance, having a numeric property will cause the field to be required and the value will have to match a numeric format. When the value is invalid you will see a message like "The value '{0}' is not valid for {1}.". When the value is blank the message that is shown is "The value '' is invalid." which is different from the [Required] message and cannot seem to be overridden by adding a [Required] attribute.

Also there is the problem of the compatibility with the front-end validation, which I think should be supported since it is implemented in the default project templates, but let's leave that aside for now as it seems like a different subject.

@dougbu
Copy link
Member

dougbu commented Jan 6, 2017

Localize ValidationAttributes that use the default message (e.g. [Required] or [MaxLength(20)])

The IStringLocalizer-based approach is explicitly opt-in. One of the reasons is ValidationAttributes are already localized in .NET.

If you're seeing .NET ValidationAttribute messages only in your system's default language, you either need to install .NET Framework (desktop) language packs or you need to wait for .NET Core language packs. (I'm not sure of the .NET Core language pack status but don't think they're available yet. @ryanbrandenburg is this correct?)

Localize validation messages that appear automatically when there are no attributes.

These messages are all retrieved from Funcs in ModelMetadata.ModelBindingMessageProvider. To override defaults, you can:

  1. Make MvcOptions updates in your Startup class e.g.
services.AddMvc(options => options.ModelBindingMessageProvider.AttemptedValueIsInvalidAccessor =
    (value, name) => $"Hmm, '{value}' is not a valid value for '{name}'."));
  1. Make similar updates in an IConfigureOptions<MvcOptions> implementation, perhaps using an IStringLocalizerFactory e.g.
var stringLocalizer = _stringLocalizerFactory.Create(typeof(MvcDataAnnotationsLocalizationOptionsSetup));
options.ModelBindingMessageProvider.AttemptedValueIsInvalidAccessor =
    (value, name) => stringLocalizer["The value '{0}' is not valid for {1}.", value, name];
  1. Make type-specific changes in an IBindingMetadataProvider implementation e.g.
if (context.Key.MetadataKind == ModelMetadataKind.Property)
{
    var stringLocalizer = _stringLocalizerFactory.Create(typeof(DataAnnotationsMetadataProvider));
    context.BindingMetadata.ModelBindingMessageProvider.AttemptedValueIsInvalidAccessor =
        (value, name) => stringLocalizer[
            $"The value '{{0}}' is not valid for properties of type '{context.Key.ModelType.FullName}' like {context.Key.Name}.",
            value];
}

(Thought we had samples using at least one of these. But I'm not finding anything.)

@xps
Copy link
Author

xps commented Jan 9, 2017

Thanks for the detailed info! With your help I managed to get everything localized.
Let me know if you'd like me to make some changes to the samples for the next guy.

@Eilon Eilon added this to the Backlog milestone Mar 27, 2017
@Eilon Eilon added the wontfix label Apr 18, 2017
@Eilon
Copy link
Member

Eilon commented Apr 18, 2017

Closing because there are no plans to make this sample change.

@Eilon Eilon closed this as completed Apr 18, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants