Локализация ASP.NET MVC приложений

в 10:42, , рубрики: ASP, asp.net mvc, localization, Веб-разработка, метки: ,

На тему локализации уже было несколько статей на Хабре, например Локализация ASP.NET MVC приложения с помощью БД или MVC 2: Полное руководство по локализации, но все-таки проблема до сих пор актуальна.

Совсем недавно у нас возникла задача локализации (перевода) интерфейса сайта на другой язык. Наш проект разрабатывается на ASP.NET MVC и в проекте достаточно много клиентского кода на JavaScript и шаблонах jQuery. Еще одним важным моментом для нас является возможность интерактивной работы переводчиков, фактически перевода сайта на лету.

В основном все статьи, касающиеся этой темы, предписывают использовать файлы ресурсов, при этом решение получается не гибким, громоздким, и к тому же, никак не учитывается проблема перевода скриптов и шаблонов, которые в любом современном веб-проекте составляют значительную часть. В конечном итоге мы решили написать свою библиотеку Knoema.Localization, которую недавно выложили в открытый доступ. Наш код базируется на замечательной разработке Griffin, но был существенно усовершенствован, включает интерактивный инструмент для перевода, а также средства естественной локализации JS кода и шаблонов.

Возможности

Библиотека позволяет локализовать:

  • Представления (views)
  • Строковые константы в коде
  • Модели и текст в атрибутах валидации данных
  • Текст в коде на JavaScript
  • Шаблоны jQuery

Основная идея заключается в том, что все локализуемые строки определяются именем файла или классом, а затем представляются в таком виде, в котором они находятся в проекте.
Локализация ASP.NET MVC приложений

Подключение и конфигурация

Для подключения библиотеки к проекту достаточно установить Nuget пакет Knoema.Localization.Mvc. Для хранения локализованных данных вам также потребуется реализация репозитория. В простейшем случае достаточно подключить готовую реализацию для EF установив пакет Knoema.Localization.EFProvider. Альтернативным вариантом является разработка своего провайдера путем реализации достаточно простого интерфейса ILocalizationRepository.

В Global.asax в Application_Start() инициализировать созданный репозиторий:

Knoema.Localization.LocalizationManager.Repository = new Knoema.Localization.EFProvider.LocalizationRepository();

и в методе RegisterRoutes прописать:

routes.IgnoreRoute("_localization/{*route}");

Начальная конфигурация готова, теперь подробнее напишу о деталях использования.

Локализация представлений

Для локализации представлений в web.config нужно указать, что в качестве базового класса для страниц будет использоваться LocalizedWebViewPage:

 <system.web.webPages.razor>
    ...
    <pages pageBaseType="Knoema.Localization.Mvc.LocalizedWebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
      ...
      </namespaces>
    </pages>
  </system.web.webPages.razor>

После этого, в коде представления станет доступен Html helper:

public string R(string text, params object[] formatterArguments);

Пример

<p>@R("Hello world!")</p>

Текст можно параметризовать:

<p>@R("Hello {0}!", username)</p>

Локализация строковых констант в коде

Строки в коде локализуются с помощью расширения:

public static string Resource(this string value, object obj)

или, если метод статический, где нет объекта this, можно использовать:

public static string Resource(this string value, Type type)

Пример

"The given input does not refer to a valid Search.".Resource(this)

Локализация модели

Для локализации моделей необходимо переопределить стандартный провайдер валидации и провайдер метаданных. Для этого в Application_Start() в Global.asax добавить:

ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new ValidationLocalizer());
ModelMetadataProviders.Current = new MetadataLocalizer();

Все модели, которые могут быть локализованы, должны быть помечены атрибутом Localized.

Пример

[Localized]
public class SignInViewModel
{
	[Required(ErrorMessage = "Please provide your e-mail")]
	[Display(Name = "E-mail")]
	public string EMail { get; set; }

	[Required(ErrorMessage = "Please type your password")]
	public string Password { get; set; }
}

Свойства и атрибуты отдельно локализовывать не нужно. Все метаданные добавятся автоматически, останется только добавить для них соответсвующий перевод.

Локазиция javascript и html шаблонов

Строковые константы в javascript коде локализуются с помощью расширения JQuery:

$.localize(text, scriptSource);

Расширение можно подключить в любом месте сраницы с помощью хелпера, лучше для всего приложения сразу:

@RenderLocalizationIncludes(User.IsInRole("Admin"))	 

Кроме того, RenderLocalizationIncludes встроит на сайт виджет (при условии, что вы администратор), где вы сможете перевести все, что локализовали.

Пример

$.localize("Layout options", "~/js/shared/site.js");

Примечание

Нам показалось неудобным, что каждый раз необходимо указывать имя файла. В нашем проекте мы используем минификатор ресурсов Cassette, где есть возможность добавить обработчик ресурсов, перед тем как они скомпилируются. Простой пример конфигурации:

public class CassetteConfiguration : ICassetteConfiguration
{
	private void CustomizeScript(ScriptBundle bundle)
	{
		bundle.Processor = new ScriptPipeline().Prepend(new LocalizationResourceProcessor());
	}

	public void Configure(BundleCollection bundles, CassetteSettings settings)
	{
		bundles.AddPerIndividualFile<ScriptBundle>("js/shared/site.js", customizeBundle: CustomizeScript);
	}
}

Теперь длинный вызов $.localize(«Layout options», "~/js/shared/site.js") можно заменить на:

__R("Layout options");

LocalizationResourceProcessor заменит __R на $.localize и добавит вторым параметром имя файла.

Добавление перевода

Виджет для редактирования перевода:
Локализация ASP.NET MVC приложений
Серым цветом выделены те представления или модели, которые полностью переведены.

Редактирование:
Локализация ASP.NET MVC приложений

Можно добавлять новый язык, экспортировать / импортировать уже существующий.
Локализация ASP.NET MVC приложений

В качестве заключения хочу сказать, что библиотека сначала была написана для внутреннего использования, получилось довольно неплохо и поэтому решили опубликовать ее и написать статью.

Ссылки:
Исходный код на GitHub
Knoema.Localization.Core
Knoema.Localization.MVC
Knoema.Localization.Cassette

Автор: polyakova

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js