首页 > 代码库 > ASP.NET MVC 多语言实现——URL路由

ASP.NET MVC 多语言实现——URL路由

考虑实现一个完整的基于asp.net mvc的多语言解决方案,从路由到model再到view最后到数据库设计(先挖好坑,后面看能填多少)。

我所见过的多语言做得最好的网站莫过于微软的msdn了,就先从模仿它的路由开始

仅实现相同的url格式很简单,只要将默认的路由加上一个表示语言的变量就可以了

public static void RegisterRoutes(RouteCollection routes)        {
       //other routes
routes.MapRoute( name: "Default", url: "{culture}/{controller}/{action}/{id}", constraints: new { culture = "zh-cn|en-us" }, defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }

然后就可以通过类似 /zh-cn/home/index或/en-us/home/index 的url访问相应页面。然而仅是这样肯定没什么实际性的作用,之前浏览过很多多语言站点,发现url里面有代表语言的都是基本都是以zh或zh-cn代表中文,en或en-us代表English,这一定有什么联系;C#有一个表示区域信息的class CultureInfo,通过设置线程的区域信息来调整某些内容的默认展示方式,最常见的就是日期格式的显示。culture的值可参照 http://www1.cs.columbia.edu/~lok/csharp/refdocs/System.Globalization/types/CultureInfo.html,当然一个Website没人有精力去支持所有语言,可以通过mvc的路由去限制,上面限制了仅中文简体(zh-cn)和美式英语(en-us)。mvc执行过程中与culture有关的步骤大概有Controller激活(不确定)->Action的Model绑定->Action执行->View呈现,因此只要在asp.net为一个客户端请求调用一个线程到使用该线程执行Controller Action的这段过程中加入设置culture的操作就能达到目的,我用的则是ActionFilter:

using System;using System.Globalization;using System.Threading;using System.Web.Mvc;/************************************************************************************************************************************************ * Class Name : InternationalizationAttribute.cs * Create Date: Tue, ‎Jan ‎12, ‎2016 * Last Update: Thur, ‎Jan 12, ‎2016 * Description: Set Culture. learn from http://stackoverflow.com/questions/1560796/set-culture-in-an-asp-net-mvc-app. * Author     : Cameron ************************************************************************************************************************************************/[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]public sealed class InternationalizationAttribute : ActionFilterAttribute{    public override void OnActionExecuting(ActionExecutingContext filterContext)    {        bool isSkipInternationalize = filterContext.ActionDescriptor.IsDefined(typeof(WithoutInternationalizationAttribute), inherit: true)                                        || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(WithoutInternationalizationAttribute), inherit: true);        if (!isSkipInternationalize)        {            string culture = (string)filterContext.RouteData.Values["culture"];            //if (string.IsNullOrEmpty(culture))            //{            //    System.Web.HttpCookie cookieCulture = filterContext.HttpContext.Request.Cookies["culture"];            //    if (cookieCulture == null)            //        filterContext.RouteData.Values.Add("culture", "zh-cn");            //    else            //        filterContext.RouteData.Values.Add("culture", cookieCulture.Value);            //    filterContext.HttpContext.Response.RedirectToRoute("Default");            //}            //else {            //filterContext.RequestContext.HttpContext.User            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);            Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);            //}        }    }}/// <summary>/// Actions and controllers with the WithoutInternationalization attribute are skipped by the InternationalizationAttribute./// </summary>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]public sealed class WithoutInternationalizationAttribute : Attribute{}

 相应controller代码:

    [Internationalization]    public class HomeController : Controller    {        public ActionResult Index()        {            return View();        }        public ActionResult Login()        {            return View();        }        [HttpPost]        public ActionResult Login(LoginViewModel loginModel)        {            return View();        }        [WithoutInternationalization]        public ActionResult ChooseCulture(string culture, string returnUrl)        {            //string url = GetApplicationPath(HttpContext.Request) + "/aaaa/bbb?c=5";            //var request = new HttpRequest(null, Request.Url.AbsoluteUri, "");            //var response = new HttpResponse(new System.IO.StringWriter());            //var httpContext = new HttpContext(request, response);            //var routeData = http://www.mamicode.com/System.Web.Routing.RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));>//var values = routeData.Values;            //HttpCookie cookieCulture = Request.Cookies["culture"];            //var originalCulture = RouteData.Values["culture"];            //if (cookieCulture == null)            //{            //    RouteData.Values.Add("culture", "zh-cn");            //}            //else {            //}            //写得有点死,有待改进            if (!returnUrl.EndsWith("/"))                returnUrl += "/";            if (!string.IsNullOrEmpty(returnUrl) && returnUrl.Length > 3 && returnUrl.StartsWith("/") && returnUrl.IndexOf("/", 1) > 0 && new string[] { "zh-cn", "en-us" }.Contains(returnUrl.Substring(1, returnUrl.IndexOf("/", 1) - 1)))                returnUrl = $"/{culture}{returnUrl.Substring(returnUrl.IndexOf("/", 1))}";            else                returnUrl = $"/{culture}{returnUrl}";            return Redirect(returnUrl);        }    }

 Layout View 选择语言部分代码:

技术分享
@using Resources<!DOCTYPE html><html><head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>@ViewBag.Title - @Resource1.my_app</title>    @Styles.Render("~/Content/css")    @Scripts.Render("~/bundles/modernizr")</head><body>    <div class="navbar navbar-inverse navbar-fixed-top">        <div class="container">            <div class="navbar-header">                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">                    <span class="icon-bar"></span>                    <span class="icon-bar"></span>                    <span class="icon-bar"></span>                </button>                @Html.ActionLink(Resource1.app_name, "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })            </div>            <div class="navbar-collapse collapse">                <ul class="nav navbar-nav">                    <li>@Html.ActionLink(Resource1.home, "Index", "Home")</li>                    <li>@Html.ActionLink("中文", "ChooseCulture", new { culture = "zh-cn", returnUrl = Request.RawUrl })</li>                    <li>@Html.ActionLink("English", "ChooseCulture", new { culture = "en-us", returnUrl = Request.RawUrl })</li>                </ul>                <ul class="nav navbar-nav navbar-right">                    <li>@Html.ActionLink(Resource1.Login, "Login", "Home")</li>                </ul>            </div>        </div>    </div>    <div class="container body-content">        @RenderBody()        <hr />        <footer>            <p>&copy; @DateTime.Now.Year - @Resource1.my_app</p>        </footer>    </div>    @Scripts.Render("~/bundles/jquery")    @Scripts.Render("~/bundles/bootstrap")    @RenderSection("scripts", required: false)</body></html>
View Code

This is my first bolg...

附上Artech大神的另一种实现方式,http://www.cnblogs.com/artech/archive/2012/05/04/localization-via-url-routing.html

ASP.NET MVC 多语言实现——URL路由