|
|
|||||||||||||||||||||||||||||
|
Дополнение к локализации ASP.NET MVC - Используем маршрутизациюИсточник: habrahabr
Сейчас я опишу очень простой и при этом очень мощный метод локализации, расположив ее в URL-адресе, используя механизм маршрутизации. Также этот метод локализации не потребует трюк с OutputCache, как было описано в предыдущем посте. Цель этого поста - возможность показать, как получить из URL-адреса вида /{culture}/{Controller}/{Action}... в Вашем приложении, URL-адрес вида /ru/Home/About. Собственные Обработчики Маршрутов Прежде всего, нам придется расширить стандартный класс MvcRouteHandler. Класс MultiCultureMvcRouteHandler будет предназначен для маршрутов, которые будут брать значение культуры из параметров и класс SingleCultureMvcRouteHandler (будет использоваться как маркер, без дополнительной имплементации). public class MultiCultureMvcRouteHandler : MvcRouteHandler { protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { var culture = requestContext.RouteData.Values["culture"].ToString(); var ci = new CultureInfo(culture); Thread.CurrentThread.CurrentUICulture = ci; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); return base.GetHttpHandler(requestContext); } } В переопределенном методе GetHttpHandler перед вызовом его базовой имплементации мы просто получаем параметр "культуры" из массива RouteData, создаем объект CultureInfo и задаем его как текущую культуру текущего потока. Именно здесь мы устанавливаем культуру и не будем использовать метод Application_AcquireRequestState в Global.asax. public class SingleCultureMvcRouteHandler : MvcRouteHandler {} Как я заметил, данный класс будет использоваться только для выделения тех маршрутов, когда Вам потребуется, чтобы они были независимы от культуры. Регистрируем маршруты Теперь перейдем к файлу Global.asax, где мы имеем метод RegisterRoutes(), регистрирующий маршруты. Сразу же после последней привязки маршрута добавьте конструкцию foreach как в следующем примере. { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults );
foreach (Route r in routes) { if (!(r.RouteHandler is SingleCultureMvcRouteHandler)) { r.RouteHandler = new MultiCultureMvcRouteHandler(); r.Url = "{culture}/" + r.Url; //Adding default culture if (r.Defaults == null) { r.Defaults = new RouteValueDictionary(); } r.Defaults.Add("culture", Culture.ru.ToString());
//Adding constraint for culture param if (r.Constraints == null) { r.Constraints = new RouteValueDictionary(); } r.Constraints.Add("culture", new CultureConstraint(Culture.en.ToString(), Culture.ru.ToString())); } }
} Отлично, давайте пройдемся по этому коду. Итак, для каждого маршрута мы, прежде всего, проверяем, является ли тип обработчика SingleCultureMvcRouteHandler, или нет. Так что, если мы поменяем свойство RouteHandler текущего маршрута на MultiCulture, то должны будем добавить префикс к URL-адресу, добавить культуру по-умолчанию и, наконец, добавить обработчик для проверки значения параметра культуры. { private string[] _values; public CultureConstraint(params string[] values) { this._values = values; }
public bool Match(HttpContextBase httpContext,Route route,string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
// Get the value called "parameterName" from the // RouteValueDictionary called "value" string value = values[parameterName].ToString(); // Return true is the list of allowed values contains // this value. return _values.Contains(value);
}
} И перечисление культур { ru = 1, en = 2 } Простой механизм переключения культур Для изменения культур нам потребуется простое действие, которое я поместил в AccountController. { if (returnUrl.Length >= 3) { returnUrl = returnUrl.Substring(3); } return Redirect("/" + lang.ToString() + returnUrl); } и частичное представление со ссылками - CultureSwitchControl.ascx
<%= Html.ActionLink("eng", "ChangeCulture", "Account", new { lang = (int)MvcLocalization.Helpers.Culture.en, returnUrl = this.Request.RawUrl }, new { @class = "culture-link" })%>
<%= Html.ActionLink("рус", "ChangeCulture", "Account", new { lang = (int)MvcLocalization.Helpers.Culture.ru, returnUrl = this.Request.RawUrl }, new { @class = "culture-link" })%> Простой пример использования культуры И наконец, если нам потребуется какой-либо маршрут независимый от культуры, все что нам нужно сделать - это задать свойство RouteHandler как SingleCultureMvcRouteHandler, например: "AboutRoute", "About", new { controller = "Home", action = "About"} ).RouteHandler = new SingleCultureMvcRouteHandler(); Итак, все :) Локализация без использования сессии, без проблем с OutputCache (будет рассмотрен в моем следующем посте) и с использованием маршрутизации. Ссылки по теме
|
|