摘要
在實際項目中,經常遇到,開發的項目要提供給不同的國家使用,如果根據國家來開發不同的站點,肯定是非常耗時又耗成本的。asp.net中,提供了一種比較方便的方式,可以使用資源文件的方式,使我們的站點,面向國際化。
一個例子
新建一個mvc項目,如下:

其中文件夾App_GlobalResources,為資源文件文件夾。可以通過右鍵添加,如圖:

Languages.resx:默認中文資源文件。
Languages.en.resx:英文資源文件。
資源項包括


注意,添加過之后,你可以對比一下,這兩個文件,其中默認中文資源文件Languages.Designer.cs中有代碼,英文資源的是沒有代碼的(這里不再做分析,之后可以通過反編譯工具進行查看)。
測試
為了測試方便,添加一個UserInfo的實體類
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; namespace Wolfy.Lang.Models { /// <summary> /// 默認 資源文件 中文 /// </summary> public class UserInfo { [Display(Name = "Id", ResourceType = typeof(Resources.Languages))] public int Id { set; get; } [Display(Name = "Name", ResourceType = typeof(Resources.Languages))] public string Name { set; get; } [Display(Name = "Gender", ResourceType = typeof(Resources.Languages))] public string Gender { set; get; } [Display(Name = "Age", ResourceType = typeof(Resources.Languages))] public int Age { set; get; } } }
這里采用默認資源中文的資源文件。
獲取語言的輔助類,用來獲取語言。這里為了設置方便,采用獲取cookie中的lang字段作為測試用,當然你也可以使用url進行傳遞。
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Wolfy.Lang.Utilities { public class LanguageHelper { private static List<string> _cultures = new List<string> { "zh-CN", "en-US" }; public static string FindLanguageName(string name) { if (string.IsNullOrEmpty(name)) { return _cultures[0]; } if (_cultures.Where(l => l.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Any()) { return name; } var partName = GetPartName(name); foreach (var item in _cultures) { if (item.StartsWith(partName)) { return item; } } return _cultures[0]; } private static string GetPartName(string name) { if (!name.Contains("-")) { return name; } else { return name.Split('-')[0]; } } } }
添加BaseController,在需要國際化的視圖對應的控制器,都需要繼承該類。
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; using System.Web.Mvc; using Wolfy.Lang.Utilities; namespace Wolfy.Lang.Controllers { public class BaseController : Controller { protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) { string langName = string.Empty; HttpCookie langCookie = Request.Cookies["lang"]; if (langCookie != null) { langName = langCookie.Value; } else { langName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : string.Empty; } langName = LanguageHelper.FindLanguageName(langName); Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(langName); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; return base.BeginExecuteCore(callback, state); } } }
添加user控制器
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; using System.Web.Mvc; namespace Wolfy.Lang.Controllers { public class UserController : BaseController { // GET: User public ActionResult Index() { ViewBag.submit = Resources.Languages.Submit; HttpCookie cookie = Request.Cookies["lang"]; if (cookie == null) { //默認中文 cookie = new HttpCookie("lang", "zh") { Expires = DateTime.Now.AddDays(1) }; Response.Cookies.Add(cookie); } return View(); } } }
對應的視圖
@model Wolfy.Lang.Models.UserInfo @{ Layout = null; var culture = System.Threading.Thread.CurrentThread.CurrentCulture.Name.ToLowerInvariant(); } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/jqueryval") @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Gender, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Gender, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Gender, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="@ViewBag.submit" class="btn btn-default" /> </div> </div> </div> } <div> @Html.ActionLink("Back to List", "Index") </div> </body> </html>
測試
通過切換cookie中lang的值進行語言的切換

切換英文

修改cookie中lang字段對應的值為en-US
總結
之前,國際化都是通過angularjs的方式在前端實現的,今天嘗試下mvc中的實現方式。這里需要注意的,在使用特性Display的ResourceType參數時,需要指定Languages是public的,默認是interval,需要修改可訪問性。
