2015-11-01 2 views
3

Интересно, есть ли возможность использовать IHtmlLocalizer из ASP.NET MVC6 непосредственно с классами POCO? В настоящее время у меня мало моделей просмотра, которые используют DisplayAttribute, чтобы отображать переведенную строку в представлениях и валидаторе, но для этого требуется создать дополнительный статический класс с каждым заданным статическим свойством (к сожалению, статические индексы не возможны на C#). Есть ли лучший способ сделать это?ASP.NET MVC6 localizable DisplayAttribute

Мой текущий код:

[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"; 
     } 
    } 
} 
+0

Вы должны взглянуть на эту статью: ИСПОЛЬЗОВАНИЕ ДАННЫХ И ЛОКАЛИЗАЦИЯ В ASP.NET 5 MVC 6 annotatiohttp: //damienbod.com/2015/10/24/using-dataannotations-and-localization-in-asp-net -5-mvc-6/ –

+0

Этот пример не работает для меня в веб-приложении MVC. – feradz

+0

У меня такая же проблема. Я решил не использовать DisplayAttribute. И я предоставляю локализацию для метки в представлении. Пример: . Не забудьте добавить LocString: @inject IViewLocalizer LocString –

ответ

0

Прежде всего, в последней версии ASP.NET 5 beta8 вы можете найти новые возможности и новейший локализация в DataAnnotations.

1.Enable это в классе настройки

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

2.Mark ваша модель с соответствующей сконфигурированной аннотирования данных

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

Пример данных аннотаций:

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

Спасибо, но как насчет атрибута Display? Я хочу, чтобы переведенное имя поля отображалось в метке. Текущий aproach требует, чтобы я создал ресурс, который не поддерживается в VS2015. Есть идеи? –

+0

Вам удалось заставить его работать для атрибута Display? – feradz

+0

@ Andrii Tsok, согласно документации ASP.NET DisplayAttribute не является частью локализации DataAnnotation, поэтому ваш ответ, похоже, не связан с вопросом. См. Здесь: https://docs.asp.net/ru/latest/fundamentals/localization.html?highlight=istringlocalizerfactory#dataannotations-localization – Vladislav

0

попытаться использовать что-то вроде этого:

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); 

Чтобы добавить его в использовании конфигурации:

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

Я не знаю, как он будет работать с ошибками, но прекрасно работает с DisplayAttributes

Отредактировано: обновлен до MVC6

+0

В текущей версии .Net Core (1.0.0) GetDisplayMetadata, похоже, был переименован в CreateDisplayMetadata. Кроме того, ExecuteAction не определен для IEnumerable . Есть ли у вас более свежий пример? – Vladislav

+0

Метод настройки запускается только один раз для жизненного цикла приложения, поэтому в многоязычном приложении атрибуты будут переведены на язык первого клиента для подключения и останутся таким образом для всех клиентов до тех пор, пока пул приложений не будет переработан. –

1

I немного боролись и, наконец, удалось составить рабочее решение по этому вопросу. Спасибо @Szymon Sasin за его ответ, хотя он не работает против последней версии, и его конфигурация является частичной, и это помогло мне построить это решение.

Во-первых, настроить локализацию на 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)); 
      }); 
     //... 
    } 
} 

Во-вторых, проверьте структуру папок с сконфигурированной ResourcePath. Важно то, что путь к типу пользовательского ресурса и путь к его файлам resx должен быть относительным. Пример:

<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 

В-третьих, определить пользовательский метаданных поставщика:

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

В-четвертых, использовать все это в вашей модели представления так же, как это:

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

Значение «Email» станет ключом к поиску в файлах DisplayResources.xx.resx.

Надеюсь, что многие другие найдут эту информацию полезной!

+0

Я только узнал, что у этого решения есть ошибка. Атрибуты отображения инициализируются только один раз, а затем, если культура изменяется, их значения не изменяются. Однако на данный момент нет очевидного решения ... ищет его – Vladislav

+0

Большое спасибо. Кажется, ОК, разве что я не нашел решение ошибки, описанной выше? – Vladislav

+1

С некоторыми настройками workz как шарм. Спасибо за этот пример. –

0

ASP.NET Core 1.0 не поддерживает локальную локализацию на основе нового внедренного подхода к локализации для атрибута Display. Один из способов - использовать подход ASP.NET Core 1.0 до локализации с файлами ресурсов. Я реализовал простой демонстрационный проект, который показывает, как локализовать атрибут отображения здесь https://github.com/feradz/ASPNetCoreLocalization/wikiDataAnnotations.resx используется для локализации атрибута Display.