Asp.net-Mvc

是否可以在 ASP.NET MVC 中本地化 URL/路由?

  • September 3, 2016

我正在與希望我們的 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論壇上提出的相同問題被定向到部落格

引用自:https://stackoverflow.com/questions/3935768