3

I've set up my application so that the contents are read from different RESX files, according to the pattern that the router recognizes. Every page is accessible in a certain language depending on the first part of the URL.

routes.MapRoute(
  name: "Localization",
  url: "{lang}/{controller}/{action}/{id}", ...
);

When I'm testing with no specification, I get to the English version of my Lingo.REXS and when I put in se, I get to the Swedish version, i.e. Lingo.se.RESX. Everything's fine this far.

However, I'm not sure how to let the user control the setting of the language. I don't want it to be automatic nor assumed based on the browser's settings, geo-data etc. I basically want three flags (img controls) that somehow magically set that user (or at least that browser session) to be routable with the prefix corresponding to the language of the flag clicked.

So, we have /se/Home/About and /ge/Home/About. The user clicks on the German flag - how do we route them to the latter? And if they click on the Swedish flag - how do we route them to the former?

I've verified with this blog but it doesn't address the actual issue with how to route into a certain language depending on the clicked flag image. I've also found this blog but I simply don't understand how they do it. I see a bunch of calls to a DB so I suspect that it's not based on RESX files (and my understanding is that it's the proper way to go), although there's also some reference to @TestResource.

Right now I'm confused and uncertain. Any suggestions or clarifications?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438

1 Answers1

3

There is a somewhat non-intuitive feature of MVC that makes this really easy. MVC automatically reuses any route values from the request. So all of your URLs will automatically "inherit" the culture - there is no need to specify it explicitly in ActionLink.

The one exception is during language selection. But you can take advantage of this same routing behavior to build a common header or footer in your _Layout.cshtml. Whatever route values the current page has will be inherited - all you need to do is specify controller, action, and culture.

@{ 
    var routeValues = this.ViewContext.RouteData.Values;
    var controller = routeValues["controller"] as string;
    var action = routeValues["action"] as string;
}
<ul>
    <li>@Html.ActionLink("Swedish", @action, @controller, new { lang = "se" }, new { rel = "alternate", hreflang = "se" })</li>
    <li>@Html.ActionLink("English", @action, @controller, new { lang = "en" }, new { rel = "alternate", hreflang = "en" })</li>
</ul>

As mentioned previously, all other links on the page will automatically be passed a culture from the current context, so they will automatically stay within the same culture. There is no reason to pass the culture explicitly in those cases.

@ActionLink("About", "About", "Home")

With the above link, if the current URL is /Home/Contact, the link that is generated will be /Home/About. If the current URL is /en/Home/Contact, the link will be generated as /en/Home/About.

Reference: ASP.NET MVC 5 culture in route and url

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Hmm... I recognize the insightfulness of your replies, so (now, that the sucking-up is delivered) I wonder if you mean that I've done way too much by implementing the special route and localization attribute. Are you saying that I only need to place a link with culture for the three languages somewhere in *_Layout.cshtml* and once the user click there (hence selecting the culture), it will live on? It **can't** be that easy... Can it? – Konrad Viltersten Apr 09 '16 at 23:01
  • Yes, that is correct. It is that easy. But, it does depend on there being a route to match the route value (which you have shown in your question). See my linked answer for how to handle the "default" language. – NightOwl888 Apr 10 '16 at 00:00
  • It's freaking awesome. It feels like a bug (that in this case is extremely helpful, though) but the stupid re-routing only handles the suffix **after** the second slash. That's great! Thanks. – Konrad Viltersten Apr 10 '16 at 13:12
  • But does this work for multiple concurent sessions of different languages? Surely changing the global culture affects them all ? – userSteve Feb 14 '22 at 08:37
  • The above code isn't dealing with the culture, it is simply building a hyperlink with the culture string in it. If you follow through to [ASP.NET MVC 5 culture in route and url](https://stackoverflow.com/questions/32764989/asp-net-mvc-5-culture-in-route-and-url), there is a `CultureFilter` which sets the culture based on the URL. This culture is not global, it is associated with the current thread, and will not affect other users of the application. – NightOwl888 Feb 14 '22 at 15:35