DDD開發框架ABP之本地化/多語言支持


      本地化(Localization)也就是多語言功能,借此用戶能夠選擇他的母語或熟悉的語言來使用系統,這顯然非常有利於軟件系統推向國際化。一個應用程序的UI界面至少有一種語言,DDD開發框架ABP就提供了一個彈性的多語言框架,可以簡化我們在多語言方面的開發時間。利用ABP完整實現多語言只需要簡單地完成三個步驟:建立資源、配置資源以及使用資源。

一、建立資源

      本地化的內容主要是文本字符串,ABP提供三種方式存儲本地化資源的方式,分別是ASP.NET自帶的資源文件、XML文件以及自定義的資源獲取方式。ABP是分模塊的,每個模塊可以定義獨立的本地化來源,每個本地化資源必須有一個唯一的名稱。

XML文件
      以XML文件存儲本地化資源時,XML文件必須是unicode(UTF-8),文件格式如下:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <localizationDictionary culture="en">
 3     <texts>
 4        <text name="ZeroSystem" value="Zero System" />
 5        <text name="TaskList" value="Task List" />
 6        <text name="NewTask" value="New Task" />
 7        <text name="Xtasks" value="{0} tasks" />
 8        <text name="CompletedTasks" value="Completed tasks" />
 9        <text name="EmailWelcomeMessage">Hi,
10         Welcome to Simple Task System! This is a sample
11         email content.</text>
12     </texts>
13 </localizationDictionary>

      上面代碼中,文件開頭的culture="en"表明這個XML文件用於英語環境。text節點很簡單地使用了name/value,name是一個代碼,是唯一的,value是其在對應的語言下先是給用戶的信息,可以是一個詞,也可以是一段話。

      我們應該為每種語言創建一個XML文件,比如:

ZeroSystem
    ZeroSystem-zh-CN.xml
    ZeroSytem-zh-TW.xml
    ZeroSytem.xml

      上面的文件列表中,Zero是資源的名稱,沒有帶語言代碼的XML文件用於默認語言。ABP會自動根據當前系統語言Thread.CurrentThread.CurrentUICulture從相應資源文件中獲取文本信息,如果該語言沒有,則自動從默認語言的XML文件中搜索。值得一提的是,在大系統中,我們可以考慮根據模塊分類建立多個資源文件以方便管理,只需要建立多個不同名稱的文件夾和一系列的資源文件即可。

RESX 資源文件

      本地化信息也可以存儲在.NET資源文件中,我們可以為每一種語言建立一個資源文件。.NET資源文件資源文件以.resx為后綴,也是name/value鍵值對。

       

       .NET資源文件中不帶語言后綴的文件用於默認語言。其他方面與XML資源文件方式大同小異,本文不再做詳細說明。

自定義資源

      ABP的本地化框架除了支持XML外,也提供了自定義的資源,可以用其他方式來保存文本,比如數據庫。我們可以直接實現ILocalization接口,或者從DictionaryBasedLocalizationSource類繼承會更加容易些。下一篇將會講述如何存儲資源文件於數據庫中。

 

二、配置資源

 

      首先,我們需要聲明系統支持哪幾種語言。這可以在模塊的PreInitialize事件中完成配置:

 

1 public override void PreInitialize()
2 { 3 Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "us.png", true)); 4 Configuration.Localization.Languages.Add(new LanguageInfo("zh-TW", "繁體中文", "tw.png")); 5 Configuration.Localization.Languages.Add(new LanguageInfo("zh-CN", "簡體中文", "cn.png")); 6 }

 

      上面代碼中,配置了三種語言,英語為默認語言。LanguageInfo參數包括代碼,名稱,圖標和是否默認語言。

注冊XML資源

      XML資源文件在系統發布時,有兩種存儲方式,一種是文件系統,一種是嵌入到程序集。文件系統存儲更靈活,它可以在系統運行中動態變更;嵌入到程序集的方式使用更方便,但編譯后就不能更改。不同方式都需要在初始化是注冊到配置中。
      文件系統方式注冊時指定文件的地址目錄:

1 Configuration.Localization.Sources.Add(
2     new DictionaryBasedLocalizationSource(
3         "ZeroSystem",
4         new XmlFileLocalizationDictionaryProvider(
5            HttpContext.Current.Server.MapPath("~/Localization/Zero")
6         )
7     )
8 );

      預編譯嵌入程序集的方式需要標記所有XML文件為“嵌入資源”(選擇XML文件,打開屬性窗口,修改“Build Action”為“Embedded Resource”)。注冊代碼如下:

1 Configuration.Localization.Sources.Add(
2      new DictionaryBasedLocalizationSource(
3          "ZeroSystem",
4          new XmlEmbeddedFileLocalizationDictionaryProvider(
5              Assembly.GetExecutingAssembly(),
6              "ZeroSystem.Web.Localization.Sources" )
7     )
8 );

      注意:預編譯嵌入程序集的方式時,XML文件不要使用“.”作為分隔符,建議使用“-”,否則可能會出現找不到文件的問題。比如MySource.en.xml 改為 MySource-en.XML。

注冊RESX資源文件

      .NET資源文件在注冊到配置時略有差異:

1 Configuration.Localization.Sources.Add(
2     new ResourceFileLocalizationSource( "ZeroSystem",
3        MyTexts.ResourceManager ));

      其中ZeroSystem是資源文件的唯一名稱,MyTexts.ResourceManager是引用資源文件的命名空間。

三、使用資源

服務器端使用

      在服務器端使用多語言,我們只需要注入ILocalizationManager接口,然后調用其GetString方法,第一個參數為資源來源的名稱,第二個參數為資源字符串的名稱。

var s1 = _localizationManager.GetString("ZeroSystem", "NewTask");

      GetString方法是基於當前線程的UI Culture設置從資源來源中取得字符串,如果沒有找到,則從默認語言中取得字符串。

      為了避免重復,可以先建立對象存儲資源來源,后面調用GetString方法時只需要傳遞一個參數:

1 var source = _localizationManager.GetSource("ZeroSystem");
2 var s1 = source.GetString("NewTask");

      注意:如果我們在特定情況下(比如靜態的上下文中)無法注入ILocalizationManager接口,我們也可以直接使用靜態類LocalizationHelper。

L方法

  在應用服務層(Application Service)、MVC Controller,或者Razor View中,ABP還定義了一個更簡單的方法L,來取得本地語言的字符串。

1 public class HomeController : SimpleTaskSystemControllerBase
2 {
3     public ActionResult Index()
4     {
5         var helloWorldText = L("HelloWorld");
6         return View();
7     }
8 }

Javascript端

      ABP同樣支持的Javascript里面使用多語言。為了實現這個能力,我們首先需要引入Javascript文件:

<script src="/AbpScripts/GetScripts" type="text/javascript"></script>

      ABP自動生成了取得本地化資源的Javascript方法,所以我們可以簡單地取得本地化文本如下:

var s1 = abp.localization.localize('NewTask', 'ZeroSystem');

      本地化文本同樣可以帶參數,比如“ Role {0} will be deleted”,通過下面的方法可以得到“Role Admin will be deleted”。

1 var source = abp.localization.getSource('ZeroSystem');
2 source('RoleDeleteWarningMessage', 'Admin');

多語言切換(基於AngularJS

      首先需要建立一個Angular控制器,比如在header.js文件中,注明語言變量:

1 angular.module('app').controller(controllerId, [
2         '$scope', '$state', function ($scope, $state) {
3             var vm = this;
4             vm.languages = abp.localization.languages;
5             vm.currentLanguage = abp.localization.currentLanguage;
6       }
7 ]);

      其中abp.localization.languages存儲了語言的清單,abp.localization.currentLanguage存儲了當前語言。
      然后在UI界面添加語言選項,以Razor+AngularJS為例,在header.cshtml文件中添加如下代碼:

 1 <li class="dropdown dropdown-language">
 2        <a href="javascript:;" data-toggle="dropdown" class="dropdown-toggle" data-hover="dropdown" data-close-others="true">
 3              <img alt="" src="/assets/global/img/flags/{{vm.currentLanguage.icon}}.png" />
 4              <span>{{vm.currentLanguage.displayName}}</span>
 5               <i class="fa fa-angle-down"></i>
 6       </a>
 7       <ul class="dropdown-menu dropdown-menu-default">
 8              <li ng-repeat="language in vm.languages" ng-hide="vm.currentLanguage.name == language.name">
 9                    <a href="~/AbpLocalization/ChangeCulture?cultureName={{language.name}}">
10                           <img alt="" src="/assets/global/img/flags/{{language.icon}}.png" />
11                           <span> {{language.displayName}}</span>
12                    </a>
13                </li>
14         </ul>
15 </li>

      ABP定義的語言對象包含了三個屬性,分別是:
      name:語言名稱,比如en, cn等
      displayName:顯示的語言文本,比如:英語、日語、簡體中文、繁體中文等。
      icon:顯示的語言圖標名稱,ABP推薦的是國旗圖標
      語言切換時,連接至ABP內置的一個MVC控制器,控制器的名稱為:AbpLocalizationController,控制器定義了一個Action方法ChangeCulture。該控制器完整代碼如下:

 1 namespace Abp.Web.Mvc.Controllers.Localization
 2 {
 3     public class AbpLocalizationController : AbpController
 4     {
 5         [DisableAuditing]
 6         public virtual ActionResult ChangeCulture(string cultureName, string returnUrl = "")
 7         {
 8             if (!GlobalizationHelper.IsValidCultureCode(cultureName))
 9             {
10                 throw new AbpException("Unknown language: " + cultureName + ". It must be a valid culture!");
11             }
12 
13             Response.Cookies.Add(new HttpCookie("Abp.Localization.CultureName", cultureName) { Expires = Clock.Now.AddYears(2) });
14 
15             if (Request.IsAjaxRequest())
16             {
17                 return Json(new MvcAjaxResponse(), JsonRequestBehavior.AllowGet);
18             }
19 
20             if (!string.IsNullOrWhiteSpace(returnUrl))
21             {
22                 return Redirect(returnUrl);
23             }
24 
25             return Redirect(Request.ApplicationPath);
26         }
27     }
28 }

總結

      DDD開發框架ABP就提供了一個彈性的多語言框架,可以靈活的采用XML文件、.NET資源文件或數據庫的方式存儲多語言資源。ABP利用依賴注入提供了快捷的獲取資源的方法,在前端Javascript也封裝了支持多語言的方法。

      具體如何實現在數據庫中存儲多語言資源,在下一篇博客《DDD開發框架ABP之本地化資源的數據庫存儲擴展》中有詳細的實現過程和代碼。當然通常說的多語言指的是軟件系統的菜單、欄位、說明、幫助等開發階段預先定義的內容,這些內容是由開發人員設定,在不同語言環境下不會因為用戶的不同而存在差異。還有一種關鍵數據欄位的多語言,比如用戶姓名、角色名稱、供應商名稱等,或許用戶也希望系統能夠具有多語言能力,ABP框架能否支持,該如何實現呢?


免責聲明!

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



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