ASP.NET MVC6 localizable DisplayAttribute

随声附和 提交于 2019-12-23 16:42:31

问题


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";
        }
    }
}

回答1:


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!




回答2:


First of all in the latest version of ASP.NET 5 beta8 you can find new features and the newest one is localisation in DataAnnotations.

1.Enable it in your Setup class

services.AddMvc()  
   .AddViewLocalization()  
   .AddDataAnnotationsLocalization();

2.Mark your model with appropriate configured data annotation

using System.ComponentModel.DataAnnotations;
using AspNet5Localization.Resources;

namespace AspNet5Localization.Model
{
    public class Box
    {
        public long Id { get; set; }

        public double Height { get; set; }

        public double Width { get; set; }

        [Required(ErrorMessageResourceName = "BoxLengthRequired", ErrorMessageResourceType = typeof(AmazingResource))]
        [Range(1.0, 100.0, ErrorMessageResourceName = "BoxLengthRange", ErrorMessageResourceType = typeof(AmazingResource))]
        public double Length { get; set; }
    }
}

Data annotation example:

[Required(ErrorMessageResourceName = "SomeResourcePropertyName", ErrorMessageResourceType = typeof(SomeResourceType))]



回答3:


ASP.NET Core 1.0 does not support out-of-the-box localization based on the new introduced localization approach for the Display attribute. One way to go is to use the prior to ASP.NET Core 1.0 approach for localization with resource files. I have implemented a simple demo project which shows how to localize the display attribute here https://github.com/feradz/ASPNetCoreLocalization/wiki DataAnnotations.resx is used for localizing the Display attribute.




回答4:


try to use something like that:

public sealed class DisplayAttributeLocalisationProvider : IDisplayMetadataProvider {
    private IHtmlLocalizer localiser;

    public DisplayAttributeLocalisationProvider(IHtmlLocalizer localiser) {
        this.localiser = localiser;
    }

    public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
        => context
            .PropertyAttributes
            .Where(attribute => attribute is DisplayAttribute)
            .Cast<DisplayAttribute>()
            .ToList()
            .ForEach(x =>
                x.Name = this
                    .localiser
                    .Html(x?.Name)
                    .Value);

To add it to configuration use:

private void ConfigureMvcOptions(MvcOptions options)
    {
        options
            .ModelMetadataDetailsProviders
                .Add(new DisplayAttributeLocalisationProvider(this.localiser));

I am not sure how it will work with an errors but works fine with DisplayAttributes

Edited: updated to MVC6



来源:https://stackoverflow.com/questions/33463166/asp-net-mvc6-localizable-displayattribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!