ASP.NET MVC 多語言實現——URL路由

考慮實現一個完整的基於asp.net mvc的多語言解決方案,從路由到model再到view最後到數據庫設計(先挖好坑,後面看能填多少)。css

我所見過的多語言作得最好的網站莫過於微軟的msdn了,就先從模仿它的路由開始html

僅實現相同的url格式很簡單,只要將默認的路由加上一個表示語言的變量就能夠了jquery

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代碼:bootstrap

    [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 = 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 選擇語言部分代碼:cookie

@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...mvc

附上Artech大神的另外一種實現方式,http://www.cnblogs.com/artech/archive/2012/05/04/localization-via-url-routing.htmlapp

相關文章
相關標籤/搜索