如何使用MVC路由多语言URL

Ham*_*mid 20 c# model-view-controller asp.net-mvc routing url-rewriting

我需要现有控制器的多语言URL路由.让我解释一下:

我有一个名为"Product"的控制器和名为"Software"的View; 因此,默认情况下,如果用户输入" http://example.com/en/Product/Software ",请获取正确的内容(实际存在于http://example.com/Product/Software中),

但是,如果另一个用户 - 法国用户 - 键入" http://example.com/fr/Produits/logiciels ",则必须获得控制器并显示正确的内容(同样http://example.com/Product/软件,但有法语文本).

注意:我使用"{language}/{controller}/{action}/{id}"设置路由表

任何其他无效的网址都必须显示404页面.

可能吗?

Jay*_*y1b 9

在Dan的帖子的基础上,我使用底层来翻译我的控制器和动作名称.

我创建了一个表来存储值,这可能并且可能应该保存在资源文件中以保持所有内容; 但是我使用了数据库表,因为它可以更好地与我公司的流程配合使用

CREATE TABLE [dbo].[RoutingTranslations](
[RouteId] [int] IDENTITY(1,1) NOT NULL,
[ControllerName] [nvarchar](50) NOT NULL,
[ActionName] [nvarchar](50) NOT NULL,
[ControllerDisplayName] [nvarchar](50) NOT NULL,
[ActionDisplayName] [nvarchar](50) NOT NULL,
[LanguageCode] [varchar](10) NOT NULL)
Run Code Online (Sandbox Code Playgroud)

然后将RouteConfig.cs文件更改为:

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

        //Build up routing table based from the database.  
        //This will stop us from having to create shedloads of these statements each time a new language, controller or action is added
        using (GeneralEntities db = new GeneralEntities())
        {
            List<RoutingTranslation> rt = db.RoutingTranslations.ToList();
            foreach (var r in rt)
            {
                routes.MapRoute(
                    name: r.LanguageCode + r.ControllerDisplayName + r.ActionDisplayName,
                    url: r.LanguageCode + "/" + r.ControllerDisplayName + "/" + r.ActionDisplayName + "/{id}",
                    defaults: new { culture = r.LanguageCode, controller = r.ControllerName, action = r.ActionName, id = UrlParameter.Optional },
                    constraints: new { culture = r.LanguageCode }
                );
            }                
        }

        //Global catchall
        routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new {culture = CultureHelper.GetDefaultCulture(), controller = "Default", action = "Index", id = UrlParameter.Optional }
            //defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

    }
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,它将始终使用英语控制器和操作名称,但允许您通过在表中输入值来提供覆盖.

(我的国际化代码主要基于这篇伟大的博客文章 .http://afana.me/post/aspnet-mvc-internationalization-part-2.aspx)


Dan*_*son 5

如前所述,这确实与网站网址(和路线)使用英语的约定背道而驰。

尽管如此,这是可能的,但是要做到这一点,您可能必须考虑为每种外语在每个动作中生成一条路线。因此,对于具有20种操作和三种语言(英语,法语和德语)的网站,您需要41条路线(20种法语,20种德语和1种英语)。我承认,这不是最高效的系统,但它可以按您的意愿工作。

//You'll only need one of these, which is the default.
routes.MapRoute(
  "English route",
  "en/{controller}/{action}/{id}"
  new { controller = "Home", action = "Index", language = "en" },
);

routes.MapRoute(
  "FrenchHome",
  "fr/Demarrer/Index/{id}",
  new { controller = "Home", action = "Index", language = "fr" }
);

routes.MapRoute(
  "GermanHome",
  "de/Heim/Index/{id}", //'Heim' is, I believe the correct usage of Home in German.
  new { controller = "Home", action = "Index", language = "de" }
);

//Some more routes...

routes.MapRoute(
  "FrenchSoftware",
  "fr/Produit/Logiciels/{id}",
  new { controller = "Product", action = "Software", language = "fr" }
);

routes.MapRoute(
  "GermanSoftware",
  "de/Produkt/Software/{id}", //In this instance, Software should be the same in German and English.
  new { controller = "Product", action = "Software", language = "de" }
);

//And finally, the 404 action.
routes.MapRoute(
  "Catchall",
  "{language}/{*catchall}",
  new { controller = "Home", action = "PageNotFound", language = "en" },
  new { language = "^(en|fr|de)$" }
);

//This is for the folks who didn't put a language in their url.
routes.MapRoute(
  "Catchall",
  "{*catchall}",
  new { controller = "Home", action = "PageNotFound", language = "en" }
);
Run Code Online (Sandbox Code Playgroud)

在您的操作中,例如产品/软件...

public ActionResult Software(string language, int id)
{
  //This would go off to the DAL and get the content in whatever language you want.
  ProductModel model = ProductService.GetSoftware(language, id);

  return View(model);
}
Run Code Online (Sandbox Code Playgroud)

如果有人说我有一种更好的方法,我会喜欢的,因为我同意以外语提供url不好,并且考虑到Internet本身正朝着允许非罗马字符输入的方向发展。网址,我们越早寻找解决方案越好。

不仅如此,而且我知道骄傲的法国人不喜欢看到他们的网站网址包含英语。:)