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

标签 asp.net-mvc url localization asp.net-mvc-routing

我正在与一位客户合作,该客户希望我们的 Web 应用程序中的 URL 为法语。我是一名英语开发人员,我们也有英语客户。这是一个有趣的问题,但我认为 ASP.NET MVC 框架不会支持它。

这是场景。路线...

具体示例
英文网址
www.stackoverflow.com/questions/ask

也支持

法语网址
www.stackoverflow.com/problème/poser

通用示例
英文网址
http://clientA.product.com/AreaNameEnglish/ControllerNameEnglish/ActionNameEnglish/params

还需要支持

法语网址
http://clientB.product.com/AreaNameFrench/ControllerNameFrench/ActionNameFrench/params

因此,在 MVC 中,我的区域、 Controller 和操作都需要有英语和法语翻译。

如果我将所有 Controller 、 View 和操作名称硬编码为法语,显然可维护性将是一个巨大的问题。无论如何,是否可以本地化浏览器中显示的路线而不执行此操作?请记住,应用程序中有许多不同的路线。几个区域,每个区域都有一些 Controller ,每个区域都有许多操作?

谢谢,
贾斯汀

编辑
感谢@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,它将找到并呈现正确的 View 。但是我有以下问题。

区域名称无法翻译
本地化区域意味着 Controller.View() 方法无法找到 View 。 尽管我已经替换了请求上下文中的区域名称,但 ViewEngineCollection.Find() 方法似乎没有选择它。在我的 Controller 类中任何执行“return View()”的地方都无法找到其操作的默认 View 。如果我不本地化该区域,则其他步骤将起作用。

RedirectToAction 或 Html.ActionLink
每当应用程序调用 RedirectToAction 或者我使用 Html.ActionLink 帮助程序或类似的东西时,生成的 URL 都是英文的。看来我必须在多个位置的某个地方添加逻辑,才能将英语 URL 转换为法语(或其他语言)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 上提出的相同问题,我被引导至博客 Forums

关于asp.net-mvc - 是否可以在 ASP.NET MVC 中本地化 URL/路由?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3935768/

相关文章:

Java 的 equalsIgnoreCase 失败,德语字母表中使用 ß ("Sharp S")

asp.net-mvc - 良好的 WiX 编辑器

asp.net-mvc - 什么是可用于 ASP.NET MVC 应用程序的良好轻量级数据库?

ios - 使用 UIWebView 时让 POST 始终通过 NSUrlCache 的问题

javascript - RegEx 使用 Javascript 匹配多个 URL 模式

ios - NSLocalizedString 数组

ios:本地化表情符号名称(kCFStringTransformToUnicodeName)

c# - MVC 项目 - 两个站点相同的 Controller

asp.net-mvc - 部分 View 提交返回 null

php - 如何获取完整的 URL 以在 Laravel 中显示