• 探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式


    如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网站对多语言的支持。接下来通过一个实例来讲述实践方式。

    首先创建一个ASP.NET MVC5应用程序,命名为Internationalization:

    QQ截图20140619101226QQ截图20140619101450

    然后在Models中添加一个示例的模型类:

    public class Employee
        {
            [Display(Name = "Name", ResourceType = typeof(Resources.Resource))]
            [Required(ErrorMessageResourceType = typeof(Resources.Resource),
                      ErrorMessageResourceName = "NameRequired")]
            public string Name { get; set; }
        }

    这里提到了Resources.Resource命名空间,接下来就创建它:

    QQ截图20140619101924

    这是一个单独的项目,用来存放各种语言的资源文件,我们创建了三个资源文件,分别存放了中文(默认)、英文和阿拉伯文,资源文件中存放了如下资源项:

    QQ截图20140619102127

     QQ截图20140619102229

    QQ截图20140619102213

    注意:这里的资源因为需要在项目外部使用,所以需要将访问修饰符修改为Public

    接下来就是如何来确定访问者要使用的语言了,在每个请求中,都会有一个Accept-language的头,其中定义了可接受的语言类型,但是我们仅可以从它来判断浏览器中设置的语言,而这个语言类型可能并不是访问者实际需要的语言类型,所以,我们将设计一个可供选择的语言列表,然后在服务器端使用发回Cookie的方式保存浏览器端实际需要的语言。

    首先需要创建一个CultureHelper类,这个类的功能就是来判断访问者实际需要的语言类型:

    public class CultureHelper
        {
            private static readonly List<string> validCultures = new List<string>() { "zh-cn", "en-us","ar" };
            private static readonly List<string> cultures = new List<string>() { "zh-cn", "en-us","ar" };
    
            public static bool IsRightToLeft()
            {
                return Thread.CurrentThread.CurrentCulture.TextInfo.IsRightToLeft;
            }
    
            public static string GetImplementedCulture(string name)
            {
                if (string.IsNullOrEmpty(name))
                {
                    return GetDefaultCulture();
                }
                if (!validCultures.Where(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Any())
                {
                    return GetDefaultCulture();
                }
                if (cultures.Where(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Any())
                {
                    return name;
                }
                var n = GetNeutralCulture(name);
                foreach (var c in cultures)
                {
                    if (c.StartsWith(n))
                    {
                        return c;
                    }
                }
                return GetDefaultCulture();
            }
    
            public static string GetDefaultCulture()
            {
                return cultures[0];
            }
    
            public static string GetCurrentCulture()
            {
                return Thread.CurrentThread.CurrentCulture.Name;
            }
    
            public static string GetCurrentNeutralCulture()
            {
                return GetNeutralCulture(Thread.CurrentThread.CurrentCulture.Name);
            }
    
            public static string GetNeutralCulture(string name)
            {
                if (!name.Contains("-"))
                {
                    return name;
                }
                else
                {
                    return name.Split('-')[0];
                }
            }
    
        }

    接下来创建一个BaseController类,并且确保之后创建的所有控制器继承自它:

    public class BaseController : Controller
        {
            protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
            {
                string cultureName = string.Empty;
                HttpCookie cultureCookie = Request.Cookies["_culture"];
                if (cultureCookie != null)
                {
                    cultureName = cultureCookie.Value;
                }
                else
                {
                    cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ?
                        Request.UserLanguages[0] : null;
                }
                cultureName = CultureHelper.GetImplementedCulture(cultureName);
                Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureName);
                Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
                return base.BeginExecuteCore(callback,state);
            }
        }

    创建一个EmployeeController,作为多语言实践的一个示例:

    public class EmployeeController : BaseController
        {
            //
            // GET: /User/
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult SetCulture(string culture)
            {
                culture = CultureHelper.GetImplementedCulture(culture);
                HttpCookie cookie = Request.Cookies["_culture"];
                if (cookie != null)
                {
                    cookie.Value = culture;
                }
                else
                {
                    cookie = new HttpCookie("_culture");
                    cookie.Value = culture;
                    cookie.Expires = DateTime.Now.AddDays(1);
                }
                Response.Cookies.Add(cookie);
                return RedirectToAction("Index");
            }
        }

    在程序包管理控制台中,使用PS命令,安装Bootstrap对RightToLeft文字习惯的支持:

    Install-Package Twitter.Bootstrap.RTL

    然后在App_Start中的BundleConfig.cs中添加两个资源文字的虚拟捆绑路径:

    bundles.Add(new ScriptBundle("~/bundles/bootstrap-rtl").Include(
                         "~/Scripts/bootstrap-rtl.js",
                         "~/Scripts/respond.js"));
    
                bundles.Add(new StyleBundle("~/Content/css-rtl").Include(
                          "~/Content/css/bootstrap-rtl.css",
                          "~/Content/site.css"));

    最后,创建Index视图:

    @model Internationalization.Models.Employee
    
    @{
        ViewBag.Title = "Index";
        var culture = System.Threading.Thread.CurrentThread.CurrentCulture.Name.ToLowerInvariant();
    }
    
    @helper selected(string c, string culture)
    {
        if (c == culture)
        {
            @:checked="checked"
        }
    }
    
    @*选择语言列表*@
    @using (Html.BeginForm("SetCulture", "Employee"))
    {
        <fieldset>
            <legend></legend>
            <div class="control-group">
                <div class="
                     ">
                    <label for="zh-cn">
                        <input name="culture" id="zh-cn" value="zh-cn" type="radio" @selected("zh-cn", culture) /> 中文
                    </label>
                </div>
            </div>
            <div class="control-group">
                <div class="controls">
                    <label for="en-us">
                        <input name="culture" id="en-us" value="en-us" type="radio" @selected("en-us", culture) /> English
                    </label>
                </div>
            </div>
            <div class="control-group">
                <div class="controls">
                    <label for="en-us">
                        <input name="culture" id="ar" value="ar" type="radio" @selected("ar", culture) />  عربي
                    </label>
                </div>
            </div>
    
        </fieldset>
    }
    
    
    @*创建员工表单*@
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
    
        <div class="form-horizontal">
            <h2>@Resources.Resource.AddEmployee</h2>
            <hr />
            @Html.ValidationSummary(true)
    
            <div class="form-group">
                @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Name)
                    @Html.ValidationMessageFor(model => model.Name)
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
    
    @*在选择语言后,自动提交*@
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
        <script type="text/javascript">
            (function ($) {
                $("input[type = 'radio']").click(function () {
                    $(this).parents("form").submit(); // post form
                });
    
            })(jQuery);
        </script>
    }

    还需要更改_Layout.cshtml文件,当文字习惯为右到左时,需要切换bootstrap的样式文件:

    <!DOCTYPE html>
    <html lang="@Internationalization.Helpers.CultureHelper.GetCurrentNeutralCulture()" dir="@(Internationalization.Helpers.CultureHelper.IsRightToLeft() ? "rtl" : "ltr")">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - 我的 ASP.NET 应用程序</title>
        @Styles.Render("~/Content/css" + (Internationalization.Helpers.CultureHelper.IsRightToLeft() ? "-rtl" : ""))
        @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("应用程序名称", "Index", "Home", null, new { @class = "navbar-brand" })
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li>@Html.ActionLink("主页", "Index", "Home")</li>
                        <li>@Html.ActionLink("关于", "About", "Home")</li>
                        <li>@Html.ActionLink("联系方式", "Contact", "Home")</li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="container body-content">
            @RenderBody()
            <hr />
            <footer>
                <p>&copy; @DateTime.Now.Year - 我的 ASP.NET 应用程序</p>
            </footer>
        </div>
    
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap" + (Internationalization.Helpers.CultureHelper.IsRightToLeft() ? "-rtl" : ""))
        @RenderSection("scripts", required: false)
    </body>
    </html>

    演示效果:

    QQ截图20140619104822 

    QQ截图20140619104936

    最终DEMO地址:点击这里,感谢园友支持,这一期会一直进行下去的

    如果您觉得这篇文章对您有用,劳烦给个赞!

    如果您觉得这篇文章可能对别人游泳,劳烦您推荐一个!

    如果您觉得这篇文章真扯淡,那么你又给我刷了个访问量!X@8}U9MLE}EBUE273)]9PGF

  • 相关阅读:
    HDU 3605 Escape
    ZOJ 2587 Unique Attack
    POJ 3686 The Windy's
    POJ 3084 Panic Room
    SGU 206 Roads
    POJ 3189 Steady Cow Assignment
    POJ 2125 Destroying The Graph
    PLS_INTEGER类型与timestamp类型、date、及时间函数
    SDO_Geometry说明
    with与树查询的使用
  • 原文地址:https://www.cnblogs.com/xiaoyaojian/p/3796024.html
Copyright © 2020-2023  润新知