Darftagan
Darftagan

Reputation: 73

Blazor WebAssembly Client DataAnnotations Localization

Asp.net core server side localization is well documented and working for me. But how do you localize DataAnnotations on DTO models on the client side of Blazor webassembly?

On server side I've added the code below and DataAnnotations are localized. Everything is working as expected.

...
services
.AddRazorPages()              .AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
                .AddDataAnnotationsLocalization(
                    options =>
                    {
                        options.DataAnnotationLocalizerProvider = (type, factory) =>
                        {
                            return factory.Create(typeof(CommonStrings));
                        };

                    });
...

But how do I do the same thing on Blazor client side (webassembly)? For example I have this model which is on client side:

public class ApplicationUserDTO
    {
        public string Id { get; set; }

        [Required(ErrorMessage ="Field {0} is required")]
        [Display(Name ="First name")]
        public string FirstName { get; set; }

        [Required]
        [Display(Name = "Last name")]
        public string LastName { get; set; }

        [Required]
        [Display(Name = "Email")]
        public string Email { get; set; }

        [Required]
        [Display(Name = "Username")]
        public string Username { get; set; }


    }

I want to post it to backend via <EditForm> component, and before I do that do the validation on client side. I also want to localize it like i would on aspnet.core server - Error/validation messages and display names...

I tried with LocalizedValidator component:

    public class MessageValidatorBase<TValue> : ComponentBase, IDisposable
    {
        private FieldIdentifier _fieldIdentifier;
        private EventHandler<ValidationStateChangedEventArgs> _stateChangedHandler
            => (sender, args) => StateHasChanged();
        [CascadingParameter]
        private EditContext EditContext { get; set; }
        [Parameter]
        public Expression<Func<TValue>> For { get; set; }
        [Parameter]
        public string Class { get; set; }
        protected IEnumerable<string> ValidationMessages =>
            EditContext.GetValidationMessages(_fieldIdentifier);
        protected override void OnInitialized()
        {
            _fieldIdentifier = FieldIdentifier.Create(For);
            EditContext.OnValidationStateChanged += _stateChangedHandler;
        }
        public void Dispose()
        {
            EditContext.OnValidationStateChanged -= _stateChangedHandler;
        }
    }

and then created component:

@typeparam TValue
@inherits MessageValidatorBase<TValue>
@inject StringLocalizationService _localizer
@foreach (var message in ValidationMessages)
{
    <div class="@Class">
        @_localizer[message]
        
    </div>
}

but the problem is I get already expanded string here. For example if I have error message like this "The field {0} is required" I get "The field First name is required" which will not be localized since I don't have the resource with that key and I don't intend to translate the same error message for every property name...

[EDIT] I just want to know if there is something trivial I didn't do instead of implementing it completely on my own

Upvotes: 3

Views: 3516

Answers (1)

Brian Parker
Brian Parker

Reputation: 14553

WebAssembly example.

Example property

[MaxLength(5,  ErrorMessageResourceName = "LengthError", ErrorMessageResourceType = typeof(Resources.App))]
public string Prefix { get; set; }

Create a folder in your client called Resources. Add a `.resx' file for each language plus a default (no language).

enter image description here

Make sure your set the access Modifier to Public enter image description here

Example output in French.

enter image description here

Upvotes: 6

Related Questions