Локализация аннотаций данных

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 18.12.2019

Для локализации аннотаций данных применяется ранее рассмотренный в прошлых темах сервис IStringLocalizer<T>. И также все необходимые ресурсы локализации определяются с помощью файлов ресурсов. Посмотрим на примере.

Пусть в проекте для моделей будет определена папка ViewModels, в которой будет расположена модель ProductViewModel:

using System.ComponentModel.DataAnnotations;

namespace LocalizationApp.ViewModels
{
    public class ProductViewModel
    {
        [Required(ErrorMessage = "NameRequired")]
        [StringLength(20, ErrorMessage = "NameLength", MinimumLength = 6)]
        [Display(Name = "Name")]
        public string Name { get; set; }
        [Required(ErrorMessage = "PriceRequired")]
        [Range(10, 100, ErrorMessage = "PriceRange")]
        [Display(Name = "Price")]
        public int Price { get; set; }
    }
}

Это вполне обычная модель, к которой применяются аннотации данных. Но в данном случае значение ErrorMessage в атрибутах Required/Range/StringLength рассматривается не только как сообщение об ошибке, но и как название ресурса, который содержит нужное значение. То же самое касается и свойства Name в атрибуте Display. То есть в данном случае применяются 6 атрибутов, которые фактически используют шесть ресурсов: Name, Price, NameLength, NameRequired, PriceRange и PriceRequired. И через эти ресурсы мы можем управлять локализацией аннотаций.

Теперь собственно определим файлы ресурсов. К наименованию файлов ресурсов для моделей применяются те же правила, что и к наименованию файлов ресурсов для контроллеров и представлений. То есть название файла ресурсов должно отражать полный путь к модели в рамках проекта. Например, в нашем случае модель находится по пути ViewModels/ProductViewModel.cs, поэтому файлы ресурсов для нее могут располагаться по следующим путям:

  • [папка_ресурсов]/ViewModels.ProductViewModel.[код_культры].resx

  • [папка_ресурсов]/ViewModels/ProductViewModel.[код_культры].resx

Выберем второй способ. Определим в проекте в папке Resources подкаталог ViewModels, а в него добавим файлы ресурсов для различных локалей:

Локализация аннотаций данных в ASP.NET Core

В данном случае я определил три файла ресурсов:

  • Resources/ViewModels/ProductViewModel.ru.resx

  • Resources/ViewModels/ProductViewModel.en.resx

  • Resources/ViewModels/ProductViewModel.de.resx

Каждый файл ресурсов содержит те ресурсы, которые применяются в атрибутах модели ProductViewModel. Например, файл для русскоязычной локали:

Аннотации данных и файлы ресурсов в ASP.NET Core

И файл ресурсов для англоязычной локали:

Аннотации данных и локализация в ASP.NET Core MVC

Далее для подключения локализации аннотаций в классе Startup необходимо вызвать метод AddDataAnnotationsLocalization() в методе ConfigureServices:

using System.Globalization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;

namespace LocalizationApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLocalization(options => options.ResourcesPath = "Resources");
            services.AddControllersWithViews()
                .AddDataAnnotationsLocalization() // добавляем локализацию аннотаций;
                .AddViewLocalization();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseDeveloperExceptionPage();

            var supportedCultures = new[]
            {
                new CultureInfo("en"),
                new CultureInfo("ru"),
                new CultureInfo("de")
            };
            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("ru"),
                SupportedCultures = supportedCultures,
                SupportedUICultures = supportedCultures
            });

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Для тестирования определим в контроллере HomeController действие Create:

public IActionResult Create()
{
	return View();
}
[HttpPost]
public IActionResult Create(ProductViewModel model)
{
	if(ModelState.IsValid)
	{
		return Content("модель добавлена");
	}
	return View(model);
}

И для действия создадим представление Create.cshtml с формой для добавления объекта ProductViewModel:

@model LocalizationApp.ViewModels.ProductViewModel

<form asp-antiforgery="true" asp-action="Create" asp-controller="Home">
    <div>
        <div class="validation" asp-validation-summary="All"></div>
        <div>

            <label asp-for="Name"></label><br />
            <input type="text" asp-for="Name" />
            <span asp-validation-for="Name"></span>
        </div>

        <div>
            <label asp-for="Price"></label><br />
            <input asp-for="Price" />
            <span asp-validation-for="Price"></span>
        </div>
        <div>
            <input type="submit" value="Save" />
        </div>
    </div>
</form>

@section scripts{

<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
}

Запустим приложение и установим русскоязычную культуру. Попробуем отправить заведомо некорректные данные:

Теперь установим англоязычную локаль:

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850