Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC6 localizable DisplayAttribute

I wonder if there is possibility to use IHtmlLocalizer from ASP.NET MVC6 directly with POCO classes? Currently I have few viewmodels that uses DisplayAttribute in order to display translated string in views and validator, but it requires to create additional static class with each static property defined (unfortunately the static indexers are not possible in C#). Is there any better way to get this done?

My current code:

[Display(Name = "TrackingDevice", ResourceType = typeof(TestResource))]
public string TrackingDevice { get; set; }

public class TestResource
{
    public static string TrackingDevice
    {
        get
        {
            //Here I call IHtmlLocalizer via IServiceLocator
            return "Field name";
        }
    }
}
like image 628
Kamil Sokołowski Avatar asked Nov 20 '25 18:11

Kamil Sokołowski


1 Answers

I have struggled a bit and finally succeeded in compiling a working solution to this question. Thanks to @Szymon Sasin for his answer, although it is not working against the latest version and his configuration is partial, it helped me build this solution.

First, configure localization at Startup.cs:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        //...
        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services
            .AddMvc(mvcOptions =>
            {
                IServiceProvider provider = services.BuildServiceProvider();
                IStringLocalizer localizer = provider.GetService<IStringLocalizer<DisplayResources>>();
                mvcOptions.ModelMetadataDetailsProviders.Add(new DisplayAttributeLocalizationProvider(localizer));
            });
        //...
    }
}

Second, verify your folder structure against the configured ResourcePath. The important thing here is that the path to the custom resource type and the path to its resx files should be relative. Example:

<root_proj_dir>/Resources/Resources_Common/DisplayResources.en.resx
<root_proj_dir>/Resources/Resources_Common/DisplayResources.bg.resx
<root_proj_dir>/Resources_Common/DisplayResources.cs

Third, define your custom metadata provider:

public sealed class DisplayAttributeLocalizationProvider : IDisplayMetadataProvider
{
    private IStringLocalizer _localizer;

    public DisplayAttributeLocalizationProvider(IStringLocalizer localizer)
    {
        _localizer = localizer;
    }

    public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
    {
        context.PropertyAttributes?
            .Where(attribute => attribute is DisplayAttribute)
            .Cast<DisplayAttribute>().ToList().ForEach(display =>
            {
                display.Name = _localizer[display.Name].Value;
            });
    }
}

Fourth, use all this in your view model just like this:

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

The "Email" value will be the key to look-up for in the DisplayResources.xx.resx files.

Hope that many others will find this info helpful!

like image 93
Vladislav Avatar answered Nov 22 '25 09:11

Vladislav



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!