是否可以在 ASP.NET MVC 中本地化 URL/路由?
我正在與希望我們的 Web 應用程序中的 URL 使用法語的客戶合作。我是一名英語開發人員,我們也有英語客戶。這是一個有趣的問題,但我認為 ASP.NET MVC 框架不會支持它。
這是場景。路線…
具體範例
英文 URL
www.stackoverflow.com/questions/ask
也會支持
法語網址
www.stackoverflow.com/problème/poser
通用範例
英文 URL
http://clientA.product.com/AreaNameEnglish/ControllerNameEnglish/ActionNameEnglish/params
也需要支持
法語 URL
http://clientB.product.com/AreaNameFrench/ControllerNameFrench/ActionNameFrench/params
所以在 MVC 中,我的 Area、Controller 和 Actions 都需要有英文和法文的翻譯。
顯然,如果我將所有控制器、視圖和操作名稱硬編碼為法語,可維護性將是一個巨大的問題。有沒有辦法在不這樣做的情況下本地化瀏覽器中顯示的路線?請記住,應用程序中有許多不同的路線。幾個區域,每個區域都有幾個控制器,每個區域都有很多動作?
謝謝,
賈斯汀
編輯
感謝@womp,這是我迄今為止想出的……儘管最後我採用了我發布的方法作為答案。
public class LocalizedControllerFactory : DefaultControllerFactory { public override IController CreateController(RequestContext requestContext, string controllerName) { if (string.IsNullOrEmpty(controllerName)) throw new ArgumentNullException("controllerName"); if (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "fr") { controllerName = this.ReplaceControllerName(requestContext, controllerName); this.ReplaceActionName(requestContext); this.ReplaceAreaName(requestContext); } return base.CreateController(requestContext, controllerName); } private string ReplaceControllerName(RequestContext requestContext, string controllerName) { // would use the language above to pick the propery controllerMapper. For now just have french Dictionary<string, string> controllerMapper = new Dictionary<string, string>() { {"frenchControllerA", "englishControllerA"}, {"frenchControllerB", "englishControllerB"} }; return this.ReplaceRouteValue(requestContext, "controller", controllerMapper); } private void ReplaceAreaName(RequestContext requestContext) { // would use the language above to pick the propery areaMapper. For now just have french Dictionary<string, string> areaMapper = new Dictionary<string, string>() { {"frenchAreaX", "englishAreaX"}, {"frenchAreaY", "englishAreaY"} }; this.ReplaceRouteValue(requestContext, "area", areaMapper); } private void ReplaceActionName(RequestContext requestContext) { // would use the language above to pick the propery actionMapper. For now just have french Dictionary<string, string> actionMapper = new Dictionary<string, string>() { {"frenchAction1", "englishAction1"}, {"frenchAction2", "englishAction2"} }; this.ReplaceRouteValue(requestContext, "action", actionMapper); } private string ReplaceRouteValue(RequestContext requestContext, string paramName, Dictionary<string, string> translationLookup) { if (requestContext.RouteData.Values[paramName] == null) { return null; } string srcRouteValue = requestContext.RouteData.Values[paramName] as string; if (srcRouteValue != null && translationLookup.ContainsKey(srcRouteValue)) { requestContext.RouteData.Values[paramName] = translationLookup[srcRouteValue]; } return requestContext.RouteData.Values[paramName] as string; } }一個體面的開始。如果我僅本地化 URL 中的 ControllerName 和 ActionName,它將找到並呈現正確的視圖。但是我有以下問題。
區域名稱無法翻譯
本地化區域意味著 Controller.View() 方法無法找到視圖。即使我已經替換了請求上下文中的區域名稱, ViewEngineCollection.Find() 方法似乎也沒有選擇它。在我的 Controller 類中執行“return View()”的任何地方都無法找到其操作的預設視圖。如果我不本地化該區域,那麼其他步驟將起作用。
RedirectToAction 或 Html.ActionLink
任何時候應用程序呼叫 RedirectToAction 或者如果我使用 Html.ActionLink 幫助程序或類似的 Urls 生成的東西都是英文的。看起來我將不得不在多個位置的某個地方添加邏輯,以將英語 URL 轉換為法語(或其他語言)。
以下部落格包含這個確切問題的完整解決方案。它實際上是一個非常優雅的解決方案,我強烈推薦。
https://blog.maartenballiauw.be/post/2010/01/26/translating-routes-(aspnet-mvc-and-webforms).html
請注意,要使其適用於 AREA,我必須將以下擴展方法添加到他的“TranslatedRouteCollectionExtensions.cs”類中:
public static Route MapTranslatedRoute(this AreaRegistrationContext areaContext, string name, string url, object defaults, object routeValueTranslationProviders, bool setDetectedCulture) { TranslatedRoute route = new TranslatedRoute( url, new RouteValueDictionary(defaults), new RouteValueDictionary(routeValueTranslationProviders), setDetectedCulture, new MvcRouteHandler()); route.DataTokens["area"] = areaContext.AreaName; // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up // controllers belonging to other areas bool useNamespaceFallback = (areaContext.Namespaces == null || areaContext.Namespaces.Count == 0); route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback; areaContext.Routes.Add(route); return route; }然而,即使這樣,可以讀取和解釋帶有 AREA 的翻譯路線,生成的路線似乎總是包含英文 AREA 名稱,但其他所有內容都本地化。
我通過 ASP.NET MVC論壇上提出的相同問題被定向到部落格