摘要
在实际项目中,经常遇到,开发的项目要提供给不同的国家使用,如果根据国家来开发不同的站点,肯定是非常耗时又耗成本的。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{ ////// 默认 资源文件 中文 /// 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_cultures = new List { "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();}Index @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/jqueryval") @using (Html.BeginForm()) { @Html.AntiForgeryToken()@Html.ValidationSummary(true, "", new { @class = "text-danger" })}@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })@Html.LabelFor(model => model.Gender, htmlAttributes: new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Gender, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Gender, "", new { @class = "text-danger" })@Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md-2" })@Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" })@Html.ActionLink("Back to List", "Index")
测试
通过切换cookie中lang的值进行语言的切换
切换英文
修改cookie中lang字段对应的值为en-US
总结
之前,国际化都是通过angularjs的方式在前端实现的,今天尝试下mvc中的实现方式。这里需要注意的,在使用特性Display的ResourceType参数时,需要指定Languages是public的,默认是interval,需要修改可访问性。