问题 使URL语言特定(通过路线)


很难找到这个具体问题的答案,所以生病了:

我们希望建立完全语言特定的网址

www.mysite.com/EN

www.mysite.com/DE

这是在RouteConfig中完成的

url: "{language}/{controller}/{action}/{id}"

但接下来是棘手的部分:

www.mysite.com/EN/Categories

www.mysite.com/DE/Kategorien

即使控制器名称以多种语言显示,但指向同一个控制器。这有可能吗?


11948
2018-02-21 15:53


起源

看到 ASP.NET MVC 5在路由和url中的文化 寻求完整的解决方案。 - NightOwl888


答案:


嗯,这部分是可能的(仅限语言部分)。使用不同语言的控制器名称绝对是一个有趣的点,但我认为很难实现这一点。想想像阿拉伯语和希伯来语这样的Bidi语言会是什么样子。在不同的语言中使用控制器可能是一个好主意,但是你会为自己造成破坏,我相信你必须改变底层的MVC结构来实现这一点。

语言变化部分很简单,可以像下面这样完成。

您可能想要看的是全球化。基本上语言部分对应于当前线程UI文化。您需要的是以下内容:

  1. 定义一个路线,如下所示:

    var lang = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
    
    routes.MapRoute(
        name: "Default",
        url: "{language}/{controller}/{action}/{id}",
        defaults: new { language = lang, controller = "Home", 
                        action = "Index", id = UrlParameter.Optional }
     );
    
  2. 寄存器 Application_AcquireRequestState 并定义如下:

    protected void Application_AcquireRequestState()
    {
        var routes = RouteTable.Routes;
    
        var httpContext = Request.RequestContext.HttpContext;
        if (httpContext == null) return;
    
        var routeData = routes.GetRouteData(httpContext);
    
        var language = routeData.Values["language"] as string;
        var cultureInfo = new CultureInfo(language);
    
        System.Threading.Thread.CurrentThread.CurrentCulture = cultureInfo;
        System.Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo;
    }
    

    虽然 CurrentUICulture 你需要切换语言从资源文件加载信息,你也应该改变 CurrentCulture 同样的 CultureInfo;

  3. 最后,确保您具有相应的资源文件和回退资源文件。

我用了 Name 的财产 CultureInfo 所以你德语将是de-DE,英语en-US等。 这应该可以解决问题。

如果您需要更多信息,我可以上传一个示例MVC项目供您检查。

更新:一种做你想做的事情的粗略方法是将路段的顺序反转为这样的:

routes.MapRoute(
    name: "NewDefault",
    url: "{language}/{id}/{action}/{controller}",
    defaults: new { language = lang, controller = "Home", action = "Index", id = "Category"}
);

这样您就可以提出以下请求 http://www.your_url.com/de/Kategorien。在这种情况下,Kategorien映射到 id 而不是一个控制器。您的控制器保留英语或德语(取决于您的命名方式),但用户可以看到不同的语言。在后台,您的视图可能是这样的:

public ActionResult Index(string id, string categoryName)
{
    // Fetch data based on category name (categoryName)
    return View();
}

您可以将其他信息作为参数传递,但您需要调整路线,使其类似于:{language} / {category} / {subcategory} / {action} / {controller}

只要知道从长远来看这可能会导致颈部疼痛,如果你试试这个,那么一定要记录好。


14
2018-02-21 16:36



嗨Husein,谢谢你的回复。那种语言实现看起来不错,我会像那样实现它。但真正的(棘手的)问题是5种不同语言之间的区别。 / EN / Categories / NL / Categorieen / DE / Kategorien / FR /CatégoriesPL/ Kategorie ......都应该指向同一个控制器。我不确定这是否可能,也许只有这5个文本字符串的约束... - stefjnl
我已经用我想到的想法更新了我的答案。希望能帮助到你。 - Husein Roncevic
嗨,罗恩,只是一个抬头,我最终实现了或多或少你更新的答案,使类别变量。 routes.MapRoute(name:“CategoryOverview”,url:“{language} / {category}”,默认值:new {language = lang,controller =“Categories”,action =“Index”}); - stefjnl
太好了,@ stefjnl,我希望我能帮到你。问候! - Husein Roncevic
嘿我在url中键入奇怪的语言时遇到错误,你可以更新帖子来处理它,重定向到错误控制器的消息或某些。 - Senad Meškin