How to handle Localization in Blazorise Validation
In this blog post we'll teach you how to properly localize Blazorise Validation messages by using the inbuilt MessageLocalizer
.
The Problem
Let's start with a simple example. We have a ValidationLocalizationExample
class with a PhoneCountryCode
property that has a DataAnnotations
validation to validate whether the input would be a valid phone country code.
We want to validate this property and display a localized error message if the validation fails. We do so by providing the Feedback
and ValidationError
components in addition to the regular Blazorise Validation components.
<Validations @ref=_validationsRef HandlerType="ValidationHandlerType.DataAnnotation" Model="_model"> <Validation> <Field> <FieldLabel>Phone Country Code</FieldLabel> <TextEdit @bind-Text="@_model.PhoneCountryCode"> <Feedback> <ValidationError /> </Feedback> </TextEdit> </Field> </Validation> </Validations> <Button Clicked="Submit">Submit</Button>
@code { private ValidationLocalizationExample _model = new(); private Validations _validationsRef; public class ValidationLocalizationExample { [RegularExpression( @"^(\+?\d{1,3}|\d{1,4})$" )] public string PhoneCountryCode { get; set; } } private async Task Submit() { if (await _validationsRef.ValidateAll()) { Console.WriteLine( "Validation Success!" ); } } }
As we can see in the screenshot above, by default, the DataAnnotations
validation will display the error message in English, with two arguments that have been inserted in the message
- The name of the field that failed, and
- The regular expression for the validation that failed.
But what if we want to display the error message in another language? Or just change the message to something else? Enter the MessageLocalizer
!
What is & How to use the Message Localizer
The MessageLocalizer
is a parameter that can be set in the Validation
component. It is used to localize the error messages that are displayed when a validation fails.
This parameter is of type Func<string, IEnumerable<string>? arguments, string>
and it receives the error message and corresponding arguments, if any, and returns the localized error message.
So by providing any delegate that adheres to this signature, we can localize the error messages. We'll go one step further and show you an example of how you can create an abstraction that utilizes the .NET IStringLocalizer
to localize the error messages.
Creating a custom Message Localizer
We'll start by creating a helper class that will be used to localize the error messages. Let's call it MessageLocalizerHelper
.
This class will receive a Microsoft.Extensions.Localization.IStringLocalizer<T>
in the constructor and will have a Localize
method that will receive the error message and arguments and return the localized error message.
public class MessageLocalizerHelper<T> { private readonly Microsoft.Extensions.Localization.IStringLocalizer<T> stringLocalizer; public MessageLocalizerHelper( Microsoft.Extensions.Localization.IStringLocalizer<T> stringLocalizer ) { this.stringLocalizer = stringLocalizer; } public string Localize( string message, IEnumerable<string>? arguments ) { try { return arguments?.Count() > 0 ? stringLocalizer[message, LocalizeMessageArguments( arguments )?.ToArray()!] : stringLocalizer[message]; } catch { return stringLocalizer[message]; } } private IEnumerable<string> LocalizeMessageArguments( IEnumerable<string> arguments ) { foreach (var argument in arguments) { // first try to localize with "DisplayName:{Name}" var localization = stringLocalizer[$"DisplayName:{argument}"]; if (localization.ResourceNotFound) { // then try to localize with just "{Name}" localization = stringLocalizer[argument]; yield return localization; } } } }
Applying a custom Message Localizer
All that's left to do is to inject your Message Localizer in your page or component where the validations are being run and set the Localize method as the MessageLocalizer
parameter.
The following shows a full example of how this would work:
NOTE: This example assumes you're using Dependency Injection. Do not forget to register your dependencies!
<Validations @ref=_validationsRef HandlerType="ValidationHandlerType.DataAnnotation" Model="_model"> <Validation MessageLocalizer="MessageLocalizer.Localize"> <Field> <FieldLabel>Phone Country Code</FieldLabel> <TextEdit @bind-Text="@_model.PhoneCountryCode"> <Feedback> <ValidationError /> </Feedback> </TextEdit> </Field> </Validation> </Validations> <Button Clicked="Submit">Submit</Button>
@code { [Inject] public MessageLocalizerHelper<Dashboard> MessageLocalizer { get; set; } private ValidationLocalizationExample _model = new(); private Validations _validationsRef; private async Task Submit() { if (await _validationsRef.ValidateAll()) { Console.WriteLine( "Validation Success!" ); } } public class ValidationLocalizationExample { [RegularExpression( @"^(\+?\d{1,3}|\d{1,4})$" )] public string PhoneCountryCode { get; set; } } public class MessageLocalizerHelper<T> { private readonly Microsoft.Extensions.Localization.IStringLocalizer<T> stringLocalizer; public MessageLocalizerHelper( Microsoft.Extensions.Localization.IStringLocalizer<T> stringLocalizer ) { this.stringLocalizer = stringLocalizer; } public string Localize( string message, IEnumerable<string>? arguments ) { try { return arguments?.Count() > 0 ? stringLocalizer[message, LocalizeMessageArguments( arguments )?.ToArray()!] : stringLocalizer[message]; } catch { return stringLocalizer[message]; } } private IEnumerable<string> LocalizeMessageArguments( IEnumerable<string> arguments ) { foreach (var argument in arguments) { // first try to localize with "DisplayName:{Name}" var localization = stringLocalizer[$"DisplayName:{argument}"]; if (localization.ResourceNotFound) { // then try to localize with just "{Name}" localization = stringLocalizer[argument]; yield return localization; } } } } }
Conclusion
We've looked at a simple example of how to localize the error messages that are displayed when a validation fails. We've also shown how to create a custom Message Localizer that utilizes the .NET IStringLocalizer
to localize the error messages.
With this knowledge you should be able to localize the error messages in your Blazorise Validation components. We hope this blog post was helpful and that you've learned something new about Blazorise!