Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
В предыдущем параграфе мы создали проект, добавив в него модель и ресурсы, которые затем будем использовать при локализации. Теперь создадим минималистичную логику приложения.
Существуют различные способы определения культуры и непосредственной локализации, например, можно переопределять класс контроллера, доопределяя
в нем OnActionExecuted
и ExecuteCore
. Но в данном случае мы поступим по-другому и создадим свой фильтр действий,
который будет срабатывать при обращении к действиям контроллера и производить локализацию.
Создадим в проекте папку Filters и добавим в нее класс CultureAttribute со следующим содержанием:
using System; using System.Collections.Generic; using System.Globalization; using System.Threading; using System.Web; using System.Web.Mvc; namespace MultilingualSite.Filters { public class CultureAttribute : FilterAttribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext filterContext) { string cultureName = null; // Получаем куки из контекста, которые могут содержать установленную культуру HttpCookie cultureCookie = filterContext.HttpContext.Request.Cookies["lang"]; if (cultureCookie != null) cultureName = cultureCookie.Value; else cultureName = "ru"; // Список культур List<string> cultures = new List<string>() {"ru", "en", "de"}; if (!cultures.Contains(cultureName)) { cultureName = "ru"; } Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName); } public void OnActionExecuting(ActionExecutingContext filterContext) { //не реализован } } }
Метод OnActionExecuted
срабатывает после вызова действия контроллера. В начале он получает установленную культуру из куков.
Затем мы смотрим, есть ли такая культура в списке. Обратите внимание, что строковые значения культур в списке соответствуют суффиксам культур
в названиях файлов ресурсов (за исключением русского языка, для которого используется культура по умолчанию).
Сама же установка культуры производится в следующих строках:
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName);
После этого для локализации система будет выбирать нужный файл ресурсов.
Теперь создадим собственно само приложение: контроллер и представления. Добавим в папку Controllers контроллер HomeController:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MultilingualSite.Filters; using MultilingualSite.Models; namespace MultilingualSite.Controllers { [Culture] public class HomeController : Controller { PersonContext db = new PersonContext(); public ActionResult Index() { return View(db.Persons); } public ActionResult ChangeCulture(string lang) { string returnUrl = Request.UrlReferrer.AbsolutePath; // Список культур List<string> cultures = new List<string>() {"ru", "en", "de"}; if (!cultures.Contains(lang)) { lang = "ru"; } // Сохраняем выбранную культуру в куки HttpCookie cookie = Request.Cookies["lang"]; if (cookie != null) cookie.Value = lang; // если куки уже установлено, то обновляем значение else { cookie = new HttpCookie("lang"); cookie.HttpOnly = false; cookie.Value = lang; cookie.Expires = DateTime.Now.AddYears(1); } Response.Cookies.Add(cookie); return Redirect(returnUrl); } } }
По сути контроллер от обычного отличается только тем, что к нему применен ранее созданный атрибут. И практически всю логику по локализации выполняет этот атрибут.
Также в контроллере определено действие ChangeCulture
, которое меняет язык с помощью установки нужных куков и затем перенаправляет на
ту же страницу.
Теперь добавим представление Index.cshtml, которое будет выглядеть так:
@model IEnumerable<MultilingualSite.Models.Person> @{ ViewBag.Title = @Resources.Resource.IndexHeader; } <h2>@Resources.Resource.IndexHeader</h2> <p> @Html.ActionLink(@Resources.Resource.CreateLink, "Create") </p> <table> <tr> <th> @Html.DisplayNameFor(model => model.Name) </th> <th> @Html.DisplayNameFor(model => model.State) </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.State) </td> </tr> } </table>
Это обычное представление, только вместо прямых вставок текста используются ресурсы: @Resources.Resource.IndexHeader
.
И изменим стандартную мастер-страницу _Layout.cshtml, добавив на нее функционал переключения языков:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div> @using (Html.BeginForm("ChangeCulture", "Home")) { <select name="lang"> <option disabled selected>@Resources.Resource.ChooseLang</option> <option value="ru">Русский</option> <option value="en">English</option> <option value="de">Deutsch</option> </select> <input type="submit" name="submit" value="@Resources.Resource.ChooseLang"> } </div> @RenderBody() @Scripts.Render("~/bundles/jquery") @RenderSection("scripts", required: false) </body> </html>
Здесь мы добавили простую форму с выпадающим списком, которая будет отсылать выбор пользователя на сервер вышеопределенному методу
ChangeCulture
.
Запустим, и у нас отобразится страница на русском языке:
Выбрав в выпадающем списке другой язык и нажав Enter, мы получим локализацию уже на другой язык.
Также мы можем создать и другие представления, например, для создания пользователей. Но общие принципы останутся те же.