在ASP.NET MVC中本地化/转换路由

时间:2011-06-03 14:28:11

标签: asp.net-mvc-3 localization internationalization asp.net-mvc-routing

任何人都知道一个很好的解决方案来本地化ASP.NET MVC中的路由?我想要实现的是这两个网址指向相同的行动/资源:

此外,应该有可能根据当前文化生成路线(如果没有可用的翻译,则默认生成路线)。或者,如果我能够只指定一种文化,以便上面两个链接中只有一个能够起作用,那么这也是可行的。

我尝试了very nice approach by Maarten Balliauw,但遗憾的是,他的解决方案不适用于Html.RenderAction(...)

当然,我可以为所有翻译添加路线,例如

routes.MapRoute(
    "Products_Categories",
    "Produkte/Kategorien",
    new { controller = "Products", action = "Categories" }
);

但这将最终导致大量路线,而且非常不灵活。任何更好的解决方案将不胜感激:-)越灵活越好。

6 个答案:

答案 0 :(得分:2)

这可能是一种管理所有路由的可行方法 - 或者它的一些变体,例如在XML文件中定义路由

http://www.iansuttle.com/blog/post/ASPNET-MVC-Store-Routes-in-the-Database.aspx

你仍然会有大量的路线,但管理它们会更容易了

答案 1 :(得分:2)

您可以尝试我刚刚找到的令人敬畏的AttributeRouting项目!你可以通过NuGet获得它。

答案 2 :(得分:1)

可以在https://github.com/boudinov/mvc-5-routing-localization

上找到属性路由和基于常规路由的简单解决方案

您可以使用/ de前缀来使用它们,因为它是首选方案。您需要在资源文件中将“产品”和“类别”翻译成德语:

或者是原始问题的有效答案,没有语言前缀,您可以像这样:

答案 3 :(得分:0)

我不确定这是否是正确的方法,至少不是你发布的方式。 网址中应该有一些定义文化的内容,例如:

否则,您最终可能会得到两种或多种语言/文化之间不明确的网址。

答案 4 :(得分:0)

MvcCodeRouting可以选择格式化或翻译路线,请参阅this page

答案 5 :(得分:0)

尝试使用自定义路线。这比这里介绍的替代方案更灵活。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using System.Web;
using System.Web.Mvc;

public class ProductRoute : RouteBase
{

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        RouteData result = null;

        string virutalPath = httpContext.Request.Url.AbsolutePath.Substring(1).ToLowerInvariant();

        // Call the database here to retrieve the productId based off of the virtualPath
        var productId = Product.GetProductIdFromVirtualPath(virutalPath);
        if (productId != Guid.Empty)
        {
            result = new RouteData(this, new MvcRouteHandler());
            result.Values["controller"] = "Product";
            result.Values["action"] = "Details";
            result.Values["id"] = productId;
        }

        return result;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        VirtualPathData result = null;
        string controller = Convert.ToString(values["controller"]);
        string action = Convert.ToString(values["action"]);

        if (controller == "Product")
        {
            string path = string.Empty;
            if (action == "Details")
            {
                Guid productId = (Guid)values["id"];

                // Call the database here to get the Virtual Path
                var virtualPath = Product.GetVirtualPathFromProductId(productId);
            }

            if (!String.IsNullOrEmpty(virtualPath))
            {
                result = new VirtualPathData(this, virtualPath);
            }
        }


        return result;
    }

}

您可以通过将路径直接添加到Global.asax中的路由表来使用该路由,如下所示:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "home", // Route name
            "", // URL with parameters
            new { controller = "Home", action = "Index" } // Parameter defaults
        );


        // Add your custom route like so
        routes.Add(new ProductRoute());


        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

    }

然后在您的本地化产品表上,只需要一个包含查找路径的字段(不带前导斜杠)。当然,您没有提到如何存储数据,所以您必须自己提出。

此外,您需要通过将其解析出virtualPath来处理本地化。根据谷歌的说法,它应该在那里。您应该根据传递的标题处理初始文化,并将其重定向(302)到所选文化的URL。然后用户应该能够切换语言,在这种情况下,您可以将其放入cookie中,以便记住他们的偏好。但是,搜索引擎应该能够通过URL告知文化而不传递任何标题。

这将通过GetVirtualPath()方法处理@ Html.RenderAction()的情况,如果需要,您可以更改逻辑。我建议你添加缓存,因为这会使每个请求按原样命中数据库。路径表在应用启动时填充,但每个路由都在每个请求上执行。

还有一件事 - 要处理“路由不匹配”的情况,只需返回null,路由器将继续前进到下一个配置的路由。这允许您根据需要配置任意数量的自定义路由,而无需混合逻辑。