平台化項目多語言架構實現


項目為什么要平台化

一、易維護

封裝可以大大的減少耦合,當發生變更的時候只需要修改一處地方。平台化項目和封裝是有區別的,平台化項目是將項目所有組件、事件等制定一個標准,將這些組件基於標准進行高度封裝,實現配置界面,通過配置大大的減少編碼量。

當需要整體變更的時候只需要更改這個標准便可,維護點更加的明確。

二、可擴展

1、首先有一點我要糾正,好多人都說封裝性太強的東西只能做一些定性的項目,不能滿足復雜的需求。這個觀點是錯誤的,只能說你在使用別人高度封裝的框架,而沒有自已的框架 或者 沒有掌握別人的框架 在或者 那個框架太LOW了。優秀的框架都是可以滿足開發需求的,因為他們都留有很多自定義的地方。

2、當項目需求不能滿足的時候,可以按照標准去擴展現有組件或者創建新的組件。

3、即使組件代碼太垃圾也沒關系,只要保證調用處是規范的,以后隨時都可以對組件進行重構。

三、成長性

隨着項目越來越多,標准會越來越完善,組件也會越來越多 

 

多語言傳統實現方式

拋開數據庫部分

一、資源文件

通過Cookie的值來決定到底調用哪個資源文件,我用的是.NET,我就來吐嘈下.NET資源文件的多么不方便

1、需要定義N多的Key。

2、為什么要把中文和英文分成兩個文件,來回切換有多麻煩,而實際上我們需要的是這樣的資源文件。

3、性能差笨重

二、XML

1、需要自已設計代碼

2、無法在靜態文件中使用,做不到前后分離

3、查看不方便,沒有EXCEL直觀

 

三、多個頁面

 使用多個頁面來實現多語言有兩個缺點:

1、當一個頁面HTML結構發現變動的時候其它頁面也需要變更

2、沒有現成的文件給專門的部門去翻譯,要自已整理或者翻譯者就在程序員身邊

 

基於平台化的實現方式

一、設計資源文件

如下圖我們選擇了EXCEL作為資源文件,根據功能的不同把EXCEL划分為多個文件,和傳統的資源文件划分方式是不同的。

 

根據頁面定義了多個Sheet,有幾種語言就定義幾列,而不是有幾種言語就定義多少文件和傳統方式是質變。

只要找個小弟把CN整理好,就不需要我們開發部門出任何體力了,也許會有人問為什么沒有key,對!我們就是不需要用到key這個累贅,下面會講到如何實現。

 

二、如何解析EXCEL

.NET可以使用Aspose.cell或者NOPI等組件把將EXCEL轉為對象,可以將這個對象存進Cache減少IO操作

存儲的結構為List<T>

public class T{

目錄

模塊

頁面

語言A

語言B

語言C ...

}

這種結構可以很容易的篩選出當前頁面所需要的語言

 

三、實現1:模版解析引擎里面作手腳實現全局替換

拿.NET MVC來舉例子:

使用RazorEngine.dll自已實現CSHTML轉HTML

public ActionResult Index(){

string templateObj = GetViewByFilePath("~/Home/index.cshtml");  

var model=new { id = xxx };

string html = Razor.Parse(templateObj ,model ); 

//根據Excel轉成的List<T>,篩選出當前頁面的語言List<T>,對這個html 進行遍歷替換處理 
//代碼並無封裝可言,我只是為了讓大家看的更明白些
foreach(var it in List<T>){
  html=html.Replace(it.默認語言,it.當前語言);
}

return View((new HtmlString(html),"~/Home/Shared/Language.cshtml");
}

  

 

//所有頁面最后都使用Language.CSHTML文件  

@model HtmlString


@Model

 

上面的替換代碼只是最簡單的例子更細節的地方我會在下面講到  

缺點: 

即使使用了緩存也會有點點性能影響,至少不會比資源文件差。

 

四、實現2:生成靜態文件方式

只需要開發默認語言的所有頁面,然后通過工具的方式去生成其他頁面

如圖: index_en.cshtml是通過工具生成出來的頁面

 

重寫視圖引擎根據Cookie自動調用相應的View文件

{
    /// <summary>
    /// 自定義MVC視圖引擎
    /// </summary>
    public sealed class BestViewEngine : RazorViewEngine
    {
 
        public BestViewEngine()
        {
        }
        /// <summary>
        /// 重寫FindView
        /// </summary>
        /// <param name="controllerContext"></param>
        /// <param name="viewName"></param>
        /// <param name="masterName"></param>
        /// <param name="useCache"></param>
        /// <returns></returns>
        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            var key ="languageKey";//COOKIE KEY
            var cm = CookiesManager<string>.GetInstance();
            if (cm.ContainsKey(key))//驗證多語言COOKIE是否有值
            {
                var cacheVal = cm[key]; //獲取多語言后綴 (例如: en)
                if (cacheVal.IsValuable())
                    viewName += "_{0}".ToFormat(cm[key]);//將原視圖名添加后綴   比如 index 添加后綴之后就是 index_en
            }
            return base.FindView(controllerContext, viewName, masterName, useCache);//參數處理后調用BASE的FindView方法
        }
 
    }
}

 

工具的邏輯很簡單  讀取文件index.cshtml HTML =》獲取語言List<T>=>篩選語言List<T>=>遍歷替換成新的HTML 寫入Index_en.cshtml 

 

缺點

 使用的是工具,總感覺少了點什么。

 

五、實現3:我們平台的實現方式

1、頁面所有的菜單是通過平台配置生成的

 

通過后台配置生成出來的導航地圖

 

2、將多語言工具集成到平台配置界面,點擊生成自動創建相應的VIEW文件

 

生成后的目錄

 

3、數據庫因為有 語言表和菜單表,Excel里面的Sheet就更容易篩選了,只要在列里面添加一個菜單ID便可,算法也更加精簡,EXCEL的結構也支持更多花樣

 

六、替換的小技巧

1、JS代碼中文的提取

 

JS使用頁面的定義

 

2、根據上圖整理出來的Sheet,把JS部分和頁面部分的中文都整理進去了,並且把當前菜單ID也加進去了方便篩選

 

3、拿EXCEL里面的第一行和第二行來說吧,如果就這么單純的替換會出現問題

頁面里面的【必填數字】,會變成 【Required數字】

 

(1)、我們可以通過先替換長的,在替換短的來解決這個問題

(2)、先替換當前頁面的在替換公共的

(3)、按上面2種替換方式可以保證99%頁面替換是正確定的了,針對特殊情況們可以 【^移動】通過符號添加優先級  只要以^符號的開頭的最先替換=》然后按長度=》按當前頁和通用頁,這樣就能保證99.9%,以此類推(說白了就是在優先級上面做手腳)。

 

 

您不給個贊嗎?


免責聲明!

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



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