原以為可以使用之前的多國語言方案進行編程了,沒想到第一個正式點的頁面就卡了,為什麼呢,因為通過HtmlHelper只能找到當前請求的View是哪個,如果這個View使用了Layout或是Partial就歇菜了。通過一番嘗試,發現使用HtmlHelper.ViewDataContainer屬性可以獲得一個WebViewPage對象,這個對象中的VirtualPath對象代表當前正在Excute的頁面屬於哪個物理檔案(.cshtml),於是修改代碼如下:
public static class LocalizationHelper { public static string Lang(this HtmlHelper htmlhelper, string key) { var viewPath = (htmlhelper.ViewDataContainer as WebViewPage).VirtualPath; var viewName = viewPath.Substring(viewPath.LastIndexOf('/'), viewPath.Length - viewPath.LastIndexOf('/')).TrimStart('/'); var filePath = htmlhelper.ViewContext.HttpContext.Server.MapPath(viewPath.Substring(0, viewPath.LastIndexOf('/') + 1)) + "App_LocalResources"; var langs = htmlhelper.ViewContext.HttpContext.Request.UserLanguages.Union<string>(new string[] { "" }); IEnumerable<DictionaryEntry> resxs = null; foreach (var lang in langs) { var resxKey = string.IsNullOrWhiteSpace(lang) ? string.Format(@"{0}\{1}.resx", filePath, viewName) : string.Format(@"{0}\{1}.{2}.resx", filePath, viewName, lang); resxs = GetResx(resxKey); if (resxs != null) { break; } } return (string)resxs.FirstOrDefault<DictionaryEntry>(x => x.Key.ToString() == key).Value; } private static IEnumerable<DictionaryEntry> GetResx(string resxKey) { ObjectCache cache = MemoryCache.Default; IEnumerable<DictionaryEntry> resxs = null; if (cache.Contains(resxKey)) { resxs = cache.GetCacheItem(resxKey).Value as IEnumerable<DictionaryEntry>; } else { if (File.Exists(resxKey)) { resxs = new ResXResourceReader(resxKey).Cast<DictionaryEntry>(); cache.Add(resxKey, resxs, new CacheItemPolicy() { Priority = CacheItemPriority.NotRemovable }); } } return resxs; } }