ASP.NET MVC之國際化(十一)


前言

在項目中遇到國際化語言的問題是常有的事情,之前在做關於MVC國際化語言時,剛開始打算全部利用AngularJS來實現,但是漸漸發現對於頁面Title難以去控制其語言轉換,於是對於頁面Tiltle利用后台的資源文件來實現而前台利用AngularJS來實現,這樣更好簡潔和方便,本節我們來講講MVC中的國際化問題。

話題引入

為了效率的問題全部利用前端腳本實現是個不錯的選擇,但是有時候也稍顯麻煩一點,本文只討論利用MVC來實現,下面我們首先來看一個例子。

我們在項目新建一個il8n文件夾在此下面新建一個資源文件【注意:將訪問修飾符修改為public】

接下來我們新建一個【 InternationalizationController 控制器】 ,在此下面獲取其資源文件的鍵對應的值

            Assembly myAssem = Assembly.GetExecutingAssembly();
            ResourceManager rm = new ResourceManager("ASP.NET_MVC_7.il8n.Resource.zh-cn", myAssem);
          
            ViewBag.title = rm.GetString("Cnblogs");
            ViewBag.blog = rm.GetString("BlogName");
            ViewBag.sign = rm.GetString("MySignature");

我們首先調試來看看是否已經獲取到值。

錯誤詳細如下:

其他信息: 未能找到任何適合於指定的區域性或非特定區域性的資源。請確保在編譯時已將“ASP.NET_MVC_7.il8n.Resource.zh-cn.resources”正確嵌入或鏈接到程序集“ASP.NET MVC_7”,或者確保所有需要的附屬程序集都可加載並已進行了完全簽名。

出現此錯誤時不知所以然,經查資料有說,查看在項目的obj/debug(看項目運行模式選擇對應模式即可)下是否有有對應的一擴展名 .resources 結尾的文件,若有則復制除開以擴展名的字符串,先看是否有相應的文件吧,如下:

看到這里復制這里的內容和代碼里寫的是一致的,還是無解。思前想后,看看這個  ResourceManager 類的參數具體是指的什么意思,第一個是basename,提示也說的不是太明確,還是看看msdn上的說明是否有注意的地方。果不其然。看看如下:

資源文件名稱不能有任何擴展名,看之前我們的名稱,我在第一次演示創建資源文件時就已經在左上角明確標出,其創建的資源名稱為 Resource.zh-cn.resx ,上述注意本意就是說只能有一個.結尾的資源名稱,我們現在將Resource.去掉再看看,代碼也進行相應的修改如下。

ResourceManager rm = new ResourceManager("ASP.NET_MVC_7.il8n.zh-cn", myAssem);

之前為如下,對比一下:

 ResourceManager rm = new ResourceManager("ASP.NET_MVC_7.il8n.Resource.zh-cn", myAssem);

我們在對應的視圖給出如下代碼:

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.title</title>
</head>
<body>
    <h1>@ViewBag.blog</h1>
    <h3>@ViewBag.sign</h3>
</body>
</html>

我們完整來看看最終效果:

 

注意:在創建資源文件命名時必須以一個擴展名命名,要么以下划線來命名。 

當然為了方便管理可以將資源文件單獨建立成一個項目,此時只需要加載對應的項目程序集即可,例如 :

            var il8mAssem = Assembly.Load("Il8nResource");
            ResourceManager rm = new ResourceManager("Il8nResource.zh-cn", il8nAssem);
            var blog = rm.GetString("BlogName");

MVC實現國際化 

實現國際化選擇語言無非兩種形式:

(1)通過下拉框自己選擇語言。

(2)根據用戶的pc或者phone的語言來選擇對應的語言進行翻譯。

本文以下拉框來展示。在此之前我們首先需要了解下國際化,國際化是什么,不就是不同國家之間的語言么,恩,是的,如果你不是干計算機的,我會馬上認同你,否則就有點鄙視你了。我們接下來來看看。

國際化

國際化被縮寫為i18n,i18n又是代表什么鬼玩意,它代表從i到n的18中字母。國際化用來開發產品或者軟件,在這種情況下它們很容易被本地化為語言和文化,它又分為全球化和本地化。

(1)Globalization:全球化被縮寫為G11n,代表以G到n的11的字母,在開發產品或者軟件時使得它們可以支持不同的文化的方式處理。

(2)Localization:本地化被縮寫為L10n,代表從L到n的10的字母,在開發產品或者軟件時可以定制為特定的文化。

在ASP.NET Framework中的文化 

在ASP.NET中有兩種文化: Culture 和 UICulture ,用兩個小寫字母來定義語言,兩個大寫字母來定義區域。例如,en代表英語,而GB和US分別代表Britain(英國)和American (美國),所以在這種情況下,在英國則被定義為en-GB,在美國定義為en-US。

Culture:代表相關文化的功能,如日期、數字、貨幣等。

UICulture:被用來定位正確的資源文件, 並通過ResourceManager類來在網頁上呈現。

這兩種文化屬性在.NET中的每個線程中都有,當需要呈現時通過ASP.NET 框架來處理。

國際化在MVC中 

大概思路:將語言存儲在Session中,通過下拉框讀取資源文件更改語言。接下來我們開始實現。

(1)新建一個項目 InternationalizationResources 並在其下創建中文和英文資源文件。

(2)創建用戶注冊類,並利用DataAnnotations中的 ResourceType 來對應其默認資源類型(中文)

    public class UserViewModel
    {
        [Display(Name = "UserName", ResourceType = typeof(InternationalizationResources.Resource))]
        [Required(ErrorMessageResourceName = "UserNameRequired", ErrorMessageResourceType = typeof(InternationalizationResources.Resource))]
        public string UserName { get; set; }

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

        [Display(Name = "Password", ResourceType = typeof(InternationalizationResources.Resource))]
        [Required(ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(InternationalizationResources.Resource))]
        public string Password { get; set; }

        [Display(Name = "ConfirmPassword", ResourceType = typeof(InternationalizationResources.Resource))]
        [Required(ErrorMessageResourceName = "ConfirmPasswordRequired", ErrorMessageResourceType = typeof(InternationalizationResources.Resource))]
        [Compare("Password", ErrorMessageResourceName = "ConfirmPasswordCompare", ErrorMessageResourceType = typeof(InternationalizationResources.Resource))]
        public string ConfirmPassword { get; set; }

        [Display(Name = "Address", ResourceType = typeof(InternationalizationResources.Resource))]
        [Required(ErrorMessageResourceName = "AddressRequired", ErrorMessageResourceType = typeof(InternationalizationResources.Resource))]
        public string Address { get; set; }
    }

(3)在初始化時設置文化。

        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);
            if (Session["CurrentCulture"] != null)
            {
                Thread.CurrentThread.CurrentCulture = new CultureInfo(Session["CurrentCulture"].ToString());
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(Session["CurrentCulture"].ToString());
            }
        }

(4)通過下拉框存儲語言。

        public ActionResult ChangeCulture(string ddlCulture)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo(ddlCulture);
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(ddlCulture);

            Session["CurrentCulture"] = ddlCulture;
            return View("Index");
        }

(5)用戶注冊並驗證。

        [HttpPost]
        public ActionResult Index(UserViewModel user)
        {
            if (ModelState.IsValid)
            {
               
            }
            return View();
        }

(6)利用強類型視圖首先獲取頁面標題。

@model ASP.NET_MVC_7.Models.UserViewModel
@{
    ViewBag.Title = InternationalizationResources.Resource.Title;
}

(7)讀取資源文件中語言並設置到下拉框並給其選擇語言更換語言事件。

 <div class="col-md-4">
        @using (Html.BeginForm("ChangeCulture", "Internationalization"))
        {
            <p>
                @InternationalizationResources.Resource.SelectLanuage : @Html.DropDownList("ddlCulture", new SelectList(new[]
 {
 new{value="zh-CN",text= InternationalizationResources.Resource.Chinese},
 new{value="en-Us",text= InternationalizationResources.Resource.English}

 }, "value", "text", Session["CurrentCulture"]), new { onchange = "this.form.submit();" })
            </p>
        }
    </div>

(8)進行注冊並驗證。

<br />
@using (Html.BeginForm("Index", "Internationalization"))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">

        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.FullName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FullName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.FullName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.PasswordFor(model => model.Password, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextAreaFor(model => model.Address, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="@InternationalizationResources.Resource.Save" class=" btn btn-default" />
            </div>
        </div>
    </div>
}

下面我們來完整看看演示效果:

總結

這一節我們學習了如何在MVC中如何實現國際化,注意:一般我們可以設置一個默認的語言如上述的Resource.Resx(中文),而英文必須以Resource以開頭后面緊跟語言如(Resource.en-US.resx)才行。當頁面中需要的翻譯的不多時可以直接通過 ResourceManager 類來實現,但是上述也講了需要注意的地方。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM