What is the best place to set the Culture/UI Culture in an ASP.net MVC app
Currently I have a CultureController class which looks like this:
public class CultureController : Controller { public ActionResult SetSpanishCulture() { HttpContext.Session["culture"] = "es-ES"; return RedirectToAction("Index", "Home"); } public ActionResult SetFrenchCulture() { HttpContext.Session["culture"] = "fr-FR"; return RedirectToAction("Index", "Home"); } }
and a hyperlink for each language on the homepage with a link such as this:
<li><%= Html.ActionLink("French", "SetFrenchCulture", "Culture")%></li> <li><%= Html.ActionLink("Spanish", "SetSpanishCulture", "Culture")%></li>
which works fine but I am thinking there is a more appropriate way to do this.
I am reading the Culture using the following ActionFilter http://www.iansuttle.com/blog/post/ASPNET-MVC-Action-Filter-for-Localized-Sites.aspx. I am a bit of an MVC noob so am not confident I am setting this in the correct place. I don't want to do it at the web.config level, it has to be based on a user's choice. I also don't want to check their http-headers to get the culture from their browser settings.
Edit:
Just to be clear - I am not trying to decide whether to use session or not. I am happy with that bit. What I am trying to work out is if it is best to do this in a Culture controller that has an action method for each Culture to be set, or is there is a better place in the MVC pipeline to do this?
In an ASP.NET Web page, you can set to two culture values, the Culture and UICulture properties. The Culture value determines the results of culture-dependent functions, such as the date, number, and currency formatting, and so on. The UICulture value determines which resources are loaded for the page.
CurrentCulture = New CultureInfo("th-TH", False) Console. WriteLine("CurrentCulture is now {0}.", CultureInfo.CurrentCulture.Name) ' Display the name of the current UI culture. Console. WriteLine("CurrentUICulture is {0}.", CultureInfo.CurrentUICulture.Name) ' Change the current UI culture to ja-JP.
Explicitly Setting the Current UI Culture NET Framework 4.6, you can change the current UI culture by assigning a CultureInfo object that represents the new culture to the CultureInfo. CurrentUICulture property.
I'm using this localization method and added a route parameter that sets the culture and language whenever a user visits example.com/xx-xx/
Example:
routes.MapRoute("DefaultLocalized", "{language}-{culture}/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "", language = "nl", culture = "NL" });
I have a filter that does the actual culture/language setting:
using System.Globalization; using System.Threading; using System.Web.Mvc; public class InternationalizationAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { string language = (string)filterContext.RouteData.Values["language"] ?? "nl"; string culture = (string)filterContext.RouteData.Values["culture"] ?? "NL"; Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture)); Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture)); } }
To activate the Internationalization attribute, simply add it to your class:
[Internationalization] public class HomeController : Controller { ...
Now whenever a visitor goes to http://example.com/de-DE/Home/Index the German site is displayed.
I hope this answers points you in the right direction.
I also made a small MVC 5 example project which you can find here
Just go to http://{yourhost}:{port}/en-us/home/index to see the current date in English (US), or change it to http://{yourhost}:{port}/de-de/home/index for German etcetera.
I know this is an old question, but if you really would like to have this working with your ModelBinder (in respect to DefaultModelBinder.ResourceClassKey = "MyResource";
as well as the resources indicated in the data annotations of the viewmodel classes), the controller or even an ActionFilter
is too late to set the culture.
The culture could be set in Application_AcquireRequestState
, for example:
protected void Application_AcquireRequestState(object sender, EventArgs e) { // For example a cookie, but better extract it from the url string culture = HttpContext.Current.Request.Cookies["culture"].Value; Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture); Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture); }
EDIT
Actually there is a better way using a custom routehandler which sets the culture according to the url, perfectly described by Alex Adamyan on his blog.
All there is to do is to override the GetHttpHandler
method and set the culture there.
public class MultiCultureMvcRouteHandler : MvcRouteHandler { protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { // get culture from route data 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); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With