Skip to content

[Blazor] Data annotations localization support #12158

@qw-34

Description

@qw-34

In my case, I have custom localization service (like IStringLocalizer), that retrieve localization from database for user-specific culture. User culture configures in user settings, that may changes in application runtime, i.e. without page reload.

ILocalizationService
{
	string this[string key] { get; }
	string GetString(string key);
	void ChangeLanguage(CultureInfo culture);
}

Service registers as scoped, i.e. each user have own ILocalizationService with own specific culture settings.

services.AddScoped<ILocalizationService, LocalizationService>();

In components this works great, just inject service.

@page "/some-page"
@inject ILocalizationService T
<h1>@T["SomeText"]</h1>

Of course, this does not work in standard case of using data annotation attributes. For example:

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

Data annotation attributes can be provided with custom type with localized strings. Something like this:

User
{
	[Required(ErrorMessageResourceName = "Validation_Required", ErrorMessageResourceType = typeof(LocalizationResources))]
	[Display(Name = "Name", ResourceType = typeof(LocalizationResources))]
	string Name { get; set; }
	
	[Display(Name = "Email", ResourceType = typeof(LocalizationResources))]
	string Email { get; set; }
}

LocalizationResources
{
	public static string Name => GetString();
	public static string Email => GetString();
	public static string Validation_Required => GetString();
	
	public static Func<ILocalizationService> LocalizationServiceProvider { get; set; }

	public static string GetString([CallerMemberName] string key = null)
	{
		return LocalizationServiceProvider().GetString(key);
	}
}

Main problem of this approach is that localized strings in LocalizationResources must be as static properties. So we cant directly inject user-specific ILocalizationService. But we can try get user-specific ILocalizationService via Func<ILocalizationService> LocalizationServiceProvider that can be configured, for example, in Configure() method:

public void Configure(IServiceProvider serviceProvider)
{
	LocalizationResources.LocalizationServiceProvider = () => serviceProvider.GetRequiredService<ILocalizationService>();
}

Of course, this does not work, because of scope of serviceProvider in Configure() method differs from user-specific scopes. In order for this approach to work it is necessary in LocalizationResources.LocalizationServiceProvider uses some kind of context that will provide user-scoped IServiceProvider to resolve user-specific ILocalizationService.

So, at this moment, in server-side Blazor is exists any method to localize the data annotation attributes in non-resx scenarios? Have a plan to implement its in future?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Pillar: Technical DebtPriority:2Work that is important, but not critical for the releaseaffected-fewThis issue impacts only small number of customersarea-blazorIncludes: Blazor, Razor ComponentsenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-blazor-serverfeature-localizationseverity-majorThis label is used by an internal tooltriaged

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions