ASP.NET MVC language change link

前端 未结 4 1728
伪装坚强ぢ
伪装坚强ぢ 2020-12-24 05:12

I have an ASP.NET MVC site that it\'s in two languages using Resources. To allow the server to present the site in the apropiate language (depending on the one that\'s confi

相关标签:
4条回答
  • 2020-12-24 05:38

    If you use the App_GloabalResources to store your resx language files, all you have to do is add a drop down which changes the current thread's UI Culture and this will automatically select the right resx language file to display.

    0 讨论(0)
  • 2020-12-24 05:41

    You may take a look at the following guide. It uses Session to store the current user language preference but the code could be very easily tweaked in order to use a cookie. The idea is that you will have a controller action:

    public ActionResult ChangeCulture(string lang, string returnUrl)
    {
        var langCookie = new HttpCookie("lang", lang)
        {
            HttpOnly = true
        };
        Response.AppendCookie(langCookie);
        return Redirect(returnUrl);
    }
    

    and then in Global.asax you could subscribe for the Application_AcquireRequestState event in order to set the current thread culture based on the value of the cookie:

    protected void Application_AcquireRequestState(object sender, EventArgs e)
    {
        var langCookie = HttpContext.Current.Request.Cookies["lang"];
        if (langCookie != null)
        {
            var ci = new CultureInfo(langCookie.Value);
            //Checking first if there is no value in session 
            //and set default language 
            //this can happen for first user's request
            if (ci == null)
            {
                //Sets default culture to english invariant
                string langName = "en";
    
                //Try to get values from Accept lang HTTP header
                if (HttpContext.Current.Request.UserLanguages != null && HttpContext.Current.Request.UserLanguages.Length != 0)
                {
                    //Gets accepted list 
                    langName = HttpContext.Current.Request.UserLanguages[0].Substring(0, 2);
                }
    
                langCookie = new HttpCookie("lang", langName)
                {
                    HttpOnly = true
                };
    
    
                HttpContext.Current.Response.AppendCookie(langCookie);
            }
    
            //Finally setting culture for each request
            Thread.CurrentThread.CurrentUICulture = ci;
            Thread.CurrentThread.CurrentCulture = ci;
    
            //The line below creates issue when using default culture values for other
            //cultures for ex: NumericSepratore.
            //Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
        }
    }
    

    Now this being said using cookies and session to store current language is not SEO friendly. What I prefer doing when I need a localized application is to use a special route which will contain the language:

    routes.MapRoute(
        "Default",
        "{lang}/{controller}/{action}/{id}",
        new 
        { 
            lang = "en-US",   
            controller = "Home", 
            action = "Index", 
            id = UrlParameter.Optional 
        }
    );
    

    and then prefix all my urls with the language. This provides unique urls for different languages so that robots can properly index all content. Now all that's left is to modify the Application_AcquireRequestState method so that it uses the lang token of the url and based on its value set the proper Thread.CurrentThread.CurrentUICulture and Thread.CurrentThread.CurrentCulture.

    And now when you wanted to change the language you would simply generate the proper link:

    @Html.ActionLink("Page index en français", "index", new { lang = "fr-FR" })
    
    0 讨论(0)
  • 2020-12-24 05:44

    App_GloabalResources is not the right place the resources when it comes to MVC programmering. See http://buildingwebapps.blogspot.no/2012/05/right-way-to-use-resource-files-for.html

    0 讨论(0)
  • 2020-12-24 05:50

    An alternative and I feel it is more flexible

     protected override void ExecuteCore()
        {
            if (RouteData.Values["lang"] != null && !string.IsNullOrWhiteSpace(RouteData.Values["lang"].ToString()))
            {
                SetCulture(RouteData.Values["lang"].ToString());
            }
            else
            {
                var cookie = HttpContext.Request.Cookies["myappculture"];
                if (cookie != null)
                { SetCulture(cookie.Value); }
                else
                { SetCulture(HttpContext.Request.UserLanguages[0]);}
            }
            base.ExecuteCore();
        }
    
    public ActionResult ChangeCulture(string lang, string returnUrl)
        {
    
            SetCulture(lang);
            // Little house keeping
            Regex re = new Regex("^/\\w{2,3}(-\\w{2})?");
            returnUrl = re.Replace(returnUrl,"/" + lang.ToLower());
            return Redirect(returnUrl);
        }
    
    private void SetCulture(string lang)
        {
            CultureInfo ci = new CultureInfo(lang);
            System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
            System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
    
            // Force a valid culture in the URL
            RouteData.Values["lang"] = lang;
    
            // save the location into cookie
            HttpCookie _cookie = new HttpCookie("myappculture", Thread.CurrentThread.CurrentUICulture.Name);
            _cookie.Expires = DateTime.Now.AddYears(1);
            HttpContext.Response.SetCookie(_cookie);
        }
    

    In the view

    Multilingual setup in view

    I kept the resource in a different project as follows

    Resources in a different project and Its usage

    0 讨论(0)
提交回复
热议问题