[Asp.net mvc]国际化

摘要

在实际项目中,经常遇到,开发的项目要提供给不同的国家使用,如果根据国家来开发不同的站点,肯定是非常耗时又耗成本的。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,需要修改可访问性。

posted @ 2017-10-18 16:44  wolfy  阅读(1900)  评论(0编辑  收藏  举报