項目為什么要平台化
一、易維護
封裝可以大大的減少耦合,當發生變更的時候只需要修改一處地方。平台化項目和封裝是有區別的,平台化項目是將項目所有組件、事件等制定一個標准,將這些組件基於標准進行高度封裝,實現配置界面,通過配置大大的減少編碼量。
當需要整體變更的時候只需要更改這個標准便可,維護點更加的明確。
二、可擴展
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%,以此類推(說白了就是在優先級上面做手腳)。