Change culture based on a link MVC4
Asked Answered
M

2

12

I have a curiosity related to culture change in MVC. I tried in 2 ways, but apparently I was wrong somewhere.

In my Web.config I have :

 <globalization uiCulture="auto" culture="auto" />

This is how I tried to change the thread culture :

 <li>@Html.ActionLink("Eng", "ChangeCulture", "Home", new { lang="en-US"}, new { @class = "languageSelectorEnglish" })</li>

First method

I have the following controller :

    public void ChangeCulture(string lang)
    {
        Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(lang);
        Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);

        Response.Cookies.Remove("Language");
        var langCookie = new HttpCookie("Language");
        langCookie["Language"] = lang;
        langCookie.Value = lang;
        langCookie.Expires = System.DateTime.Now.AddDays(21);
        Response.Cookies.Add(langCookie);

        Response.Redirect(Request.UrlReferrer.ToString());
    }

Second method

    public ActionResult ChangeCulture(string lang)
    {
        Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(lang);
        Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);

        // Split the url to url + query string
        var fullUrl= Request.UrlReferrer.ToString();
        var questionMarkIndex = fullUrl.IndexOf('?');
        string queryString = null;
        string url = fullUrl;
        if (questionMarkIndex != -1) // There is a QueryString
        {
            url = fullUrl.Substring(0, questionMarkIndex);
            queryString = fullUrl.Substring(questionMarkIndex + 1);
        }

        // Arranges
        var request = new HttpRequest(null, url, queryString);
        var response = new HttpResponse(new StringWriter());
        var httpContext = new HttpContext(request, response);

        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));

        // Extract the data    
        var values = routeData.Values;
        var controllerName = values["controller"];
        var actionName = values["action"];
        var areaName = values["area"];

        return RedirectToAction(actionName.ToString());
    }

Where am I wrong ? Thank you.

Morava answered 27/2, 2013 at 9:31 Comment(2)
What's the issue you facing?Misplay
Culture did not want to change even if I've changed Thread current culture. I'll post my answer soon because I find a way to do it without setting a cookie.Morava
M
8

It's seems I need to override the culture for my resource strings and not the thread. So my final method is this :

    public void ChangeCulture(string lang)
    {
         Resources.Resources.Culture = new CultureInfo(lang);

         Response.Redirect(Request.UrlReferrer.ToString());
    }

Hope this helps.

UPDATE :

The code above is not good when your application is used by multiple users, because it sets same culture for every user, no matter what browser they are using.

The good way to do it is to make a method which sets a cookie in your browser :

    public void ChangeCulture(string lang)
    {
        Response.Cookies.Remove("Language");

        HttpCookie languageCookie = System.Web.HttpContext.Current.Request.Cookies["Language"];

        if (languageCookie == null) languageCookie = new HttpCookie("Language");

        languageCookie.Value = lang;

        languageCookie.Expires = DateTime.Now.AddDays(10);

        Response.SetCookie(languageCookie);

        Response.Redirect(Request.UrlReferrer.ToString());
    }

After this ( the tricky way ) you need to make every controller to inherit from one BaseController. It is tricky because you need to override Initialize.

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
    {


        HttpCookie languageCookie = System.Web.HttpContext.Current.Request.Cookies["Language"];
        if (languageCookie != null)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(languageCookie.Value);
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(languageCookie.Value);
        }
        else
        {
        //other code here
        }


        base.Initialize(requestContext);
    }
Morava answered 27/2, 2013 at 10:20 Comment(1)
Thanks! Wow this was from 2013 :)Morava
H
4

Remove the line in your web.config:

<globalization uiCulture="auto" culture="auto" />

Setting these to auto will default the language to the user's language set on the browser. This is overriding your Thread setting.

Horsemint answered 27/2, 2013 at 9:41 Comment(2)
Hello. It didn't work, but I found a way to do it. I'll post my answer as soon as I can. Thank you very much .Morava
In my case, just by having the line in the config file regardless of culture setting already overrides the thread settings.Barye

© 2022 - 2024 — McMap. All rights reserved.