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