问题
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