我有一个网站需要本地化为多种不同的语言。 为实现这一点,我在这里遵循了教程 https://www.ryadel.com/en/setup-a-multi-language-website-using-asp-net-mvc/ 在我的路线配置中,我有:
routes.MapRoute(
name: "DefaultLocalized",
url: "{lang}/{controller}/{action}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" }, // en or en-US
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
目前我的语言切换器的工作原理如下,对于每种可用的语言,我都会使用当前的URL并使用相应的语言段创建一个链接,即en-US
或ru-RU
等
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
@foreach (CultureViewModel culture in Global.EnabledCultures)
{
<li><span class="Language dropdown-item" title="@culture.DisplayName">@Html.Raw(Url.LangSwitcher(culture.DisplayName, ViewContext.RouteData, culture.Name))</span></li>
}
</div>
Url.LangSwitcher是UrlHelper的扩展名
public static string LangSwitcher(this UrlHelper url, string name, RouteData routeData, string lang, bool isMainMenu = false)
{
var action = (routeData.Values["action"] ?? "").ToString().ToLower();
var controller = (routeData.Values["controller"] ?? "").ToString().ToLower();
var requestContext = HttpContext.Current.Request.RequestContext;
string link = "";
// We need to create a unique URL for the current page for each of the enabled languages for this portal
// If the lang variable is specified for current URL we need to substitute with the incoming lang variable
//we need to duplicate the RouteData object and use the duplicate for URL creation as
//changing the value of lang in RouteData object passed to this function changes the current culture of the request
RouteData localValues = new RouteData();
foreach (KeyValuePair<string, object> var in routeData.Values)
{
if (var.Key != "lang")
{
localValues.Values.Add(var.Key, var.Value);
}
}
localValues.Values.Add("lang", lang);
link = "<a href = \"" + new UrlHelper(requestContext).Action(action, controller, localValues.Values) + "\" >";
string img = "<img src=\"/Content/images/Flags/" + lang + ".gif\" alt = \"" + lang + "\"> " + name;
string closeTags = "</a>";
return link + img + closeTags;
}
所以它需要当前的URL并切换语言slug并输出我们正在创建的菜单的链接。
这一切都适用于遵循标准{lang}/{controller}/{action}/{id}
模式
但是,我希望能够在控制器上创建带有属性的自定义链接,如下所示:
[Route("brokers/this/is/a/custom/url")]
public ActionResult CompareBrokers(int page = 1)
{
所以当我尝试从这样的视图访问这条路线时:
@Url.Action("CompareBrokers", "Brokers")
生成的URL如下所示:
https://localhost:44342/brokers/this/is/a/custom/url?lang=en-US
我希望它像这样
https://localhost:44342/en-US/brokers/this/is/a/custom/url
关于如何根据我目前的设置实现我想要的任何建议?
更新
将[Route("{lang}/brokers/this/is/a/custom/url")]
作为我的属性取得了一些有限的成功,只要当前网址中有lang变量,它就会起作用,所以如果我在http://site.url/en-US上,那么链接会正确创建,但如果我我在http://site.url他们没有。
我尝试在控制器中放置2个属性:
[Route("brokers/this/is/a/custom/url")]
[Route("{lang}/brokers/this/is/a/custom/url")]
但它只使用第一个
更新2
根据评论中的建议我使用了属性:
[Route("{lang=en-GB}/brokers/this/is/a/custom/url")]
它运行正常,我的链接生成正确,但我需要能够适应默认本地化而不需要URL中的lang var
答案 0 :(得分:2)
如果您使用订单参数放置两个属性,路由将首先尝试将第一个路由与lang参数匹配,如果未提供lang参数,则它将在第二个路径上回退。
[Route("{lang}/brokers/this/is/a/custom/url", Order = 1)]
[Route("brokers/this/is/a/custom/url", Order = 2)]
public ActionResult CompareBrokers(int page = 1)
{
}
更新: 要在lang是默认语言时使用第二个路由,您可以通过添加actionFilter或controllerActivator从routedata中删除lang:
if (filterContext.RouteData.Values["lang"]?.ToString() == _DefaultLanguage)
{
filterContext.RouteData.Values.Remove("lang");
}
答案 1 :(得分:0)
这是一个月后我放弃使用常规路由/路由配置文件后为我工作的功能,请注意,我正在使用Areas,此处的区域名称为“ Merchant”
普通链接:
https://localhost:44364/En/Merchant/Financial/TransactionDetails/55
要将其作为“自定义”链接打开,例如:
https://localhost:44364/En/Merchant/Financial/Transactions/Transaction/Details/55
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace GHLogistics.Areas.Merchant.Controllers
{
[RouteArea("{lang}")]
[RoutePrefix("Merchant")]
public class FinancialController : MerchantBaseController
{
[Route("Financial/Transactions/Transaction/Details/{Id}")]
public ActionResult TransactionDetails(long Id)
{
return Content("TransactionDetails" + " " + Id.ToString());
// or
//pass relative path of view file, pass model
//return View("~/Areas/Merchant/Views/Financial/TransactionDetails.cshtml",transactions);
}
}
}
MerchantAreaRegistration.cs文件
context.MapRoute(
"Merchant_default",
url: "{lang}/Merchant/{controller}/{action}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" },
defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "GHLogistics.Areas.Merchant.Controllers" }
);
RouteConfig.cs文件
namespace GHLogistics
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
AreaRegistration.RegisterAllAreas();
routes.MapRoute(
name: "Default",
url: "{lang}/{controller}/{action}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" },
defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "GHLogistics.Controllers" }
);
}
}
}