I have a site which requires localization into a number of different languages. To achieve this I followed the tutorial here https://www.ryadel.com/en/setup-a-multi-language-website-using-asp-net-mvc/ In my route config I have :
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 }
);
Currently my language switcher works like this, for every available language I take the current URL and create a link with the appropriate language slug i.e. en-US
or ru-RU
etc
<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>
Where Url.LangSwitcher is an Extension of 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;
}
so it takes the current URL and switches out the language slug and outputs a link for the menu we are creating.
This all works fine on links that follow the standard {lang}/{controller}/{action}/{id}
pattern
however, I want to be able to create custom links with attributes on the controllers like so:
[Route("brokers/this/is/a/custom/url")]
public ActionResult CompareBrokers(int page = 1)
{
so when I try to access this route from a view like so:
@Url.Action("CompareBrokers", "Brokers")
the URL that is generated is like this:
https://localhost:44342/brokers/this/is/a/custom/url?lang=en-US
where I want it to be like this
https://localhost:44342/en-US/brokers/this/is/a/custom/url
Any advice on how I can achieve what I want given my current set up?
UPDATE
putting [Route("{lang}/brokers/this/is/a/custom/url")]
as my attribute has some limited success, it will work as long as there is a lang variable in the current URL, so if I am on http://site.url/en-US then the links get created correctly, but if I am on http://site.url they do not.
Ive tried putting 2 attributes in my controller:
[Route("brokers/this/is/a/custom/url")]
[Route("{lang}/brokers/this/is/a/custom/url")]
but it just uses the first one
UPDATE 2
Following advice in the comments I used the attribute:
[Route("{lang=en-GB}/brokers/this/is/a/custom/url")]
and it works perfectly, my links get generated correctly, however I need to be able to accommodate the default localization without the lang var in the URL