i18n icon indicating copy to clipboard operation
i18n copied to clipboard

Certain methods of generating URLs fail to be localized

Open ajbeaven opened this issue 9 years ago • 11 comments

I've found some issues with certain methods of generating URLs in MVC where the URLs fail to be localized correctly. Here are some crude examples that show the strange behaviour:

No additional parameters<br/>
1 - <a href="@Url.Action("Index", "Home")">link</a> - works<br />
2 - @Html.ActionLink("link", "Index", "Home") - works<br /><br />

Querystring parameter<br />
3 - <a href="@Url.Action("Index", "Home", new { thing = 123 })">link</a> - works<br />
4 - <a href="@Url.Action("Index", "Home")?thing=123">link</a> - works<br />
5 - <a href="?thing[0]=123">link</a> - works<br />
6 - <a href="http://localhost:8082?thing[0]=123">link</a> - works<br />
7 - @Html.ActionLink("link", "Index", "Home", new RouteValueDictionary { { "thing[0]", 123 } }, null) - works<br />
8 - <a href="@Url.Action("Index", "Home")?thing[0]=123">link</a> - doesn't work<br /><br />

Anchors<br />
9 - <a href="http://localhost:8082#thing">link</a> - works<br />
10 - <a href="#thing">link</a> - works<br />
11 - <a href="@Url.Action("Index", "Home")#thing">link</a> - doesn't work<br />
12 - @Html.ActionLink("link", "Index", "Home", null, null, "thing", null, null) - doesn't work<br />

I'm using Scheme2, a default language of en and am testing with a Content-Language set to ru.

I would have added some tests to ResponseFilterTests but I'd need to update them so they supported Url.Action and Html.ActionLink (where it seems the problems lie). I wanted to get your thoughts before doing something drastic like that.

As the examples show above, 8 can be supported by passing the parameter in as an Url.Action / Html.ActionLink argument, so that's not too much of a problem. When it comes to the anchors in 11 and 12 though, even passing it in as a Html.ActionLink argument doesn't work (Url.Action doesn't have an overload that takes an archor/fragment). I'd prefer not to hardcode all URLs that point to an anchor on a different page.

ajbeaven avatar Sep 28 '16 00:09 ajbeaven

Cancel that last point. An acceptable workaround for the anchor issue would be to specify the protocol:

13 - <a href="@Url.Action("Index", "Home", null, Request.Url.Scheme)#thing">link</a> - works<br />

ajbeaven avatar Sep 28 '16 03:09 ajbeaven

What do you mean by 'doesn't work'?

turquoiseowl avatar Sep 28 '16 08:09 turquoiseowl

Oops, sorry forgot to add that part :/

The examples I gave above were rendered on a page at http://localhost:8082/ru. I would expect all the generated URLs to include the ru langtag in them. The cases above that 'didn't work' were the ones that did not.

ajbeaven avatar Sep 28 '16 11:09 ajbeaven

Can I close this issue? Thanks.

turquoiseowl avatar Nov 25 '16 14:11 turquoiseowl

Unless something has changed with how the URLs are generated, I think this would still be an issue. I'll check when I'm back near a computer next week.

ajbeaven avatar Nov 25 '16 18:11 ajbeaven

Just confirmed that this is still an issue.

To clarify, when on a localized URL (eg. http://localhost/ru) the following methods of generating URLs will not be localized correctly (ie. http://localhost?test=a instead of http://localhost/ru?test=a):

Querystring

<a href="@Url.Action("Index", "Home")?test=a">link</a>

Anchor

<a href="@Url.Action("Index", "Home")#test">link</a>
@Html.ActionLink("link", "Index", "Home", null, null, "test", null, null)

Is this making any sense?

ajbeaven avatar Nov 28 '16 06:11 ajbeaven

Same problem here. If I use @Url.Action inside a Javascript, it does not put the localization part of URL.

Example: var url = '@Url.Action("Action", "Controller")';

Actual result: /Controller/Action

Expected result: /pt/Controller/Action

chgsantos avatar Jan 25 '17 20:01 chgsantos

I don't think you're experiencing this bug sorry. i18n doesn't indiscriminately localise every URL - check out EarlyUrlLocalizer.cs. There might be a more efficient way, but you can use LanguageTag.SetLangTagInUrlPath and LanguageTag.ExtractLangTagFromUrl for your purposes.

ajbeaven avatar Jan 25 '17 20:01 ajbeaven

@ajbeaven I'll take a look. Thanks!

chgsantos avatar Jan 25 '17 22:01 chgsantos

Yes, during processing and patching of the HTTP response, i18n does its best to locate and then localize any URLs in the response. However, it does this based on the HTML spec.: looking in any/all attributes where URLs are expected e.g. hrefs. Which means if you are putting a URL into the response somewhere else, like some Javascript, then the URL isn't going to be detected.

So for these arbitrarily-located URLs we need a means to explicitly localize a URL. In fact, there is such a method: EarlyUrlLocalizer.LocalizeUrl, although it's currently inaccessible. I'm thinking it should be made accessible...

turquoiseowl avatar Jan 25 '17 23:01 turquoiseowl

It'd be nice if EarlyUrlLocalizer.LocalizeUrl had an optional langtag parameter and when not supplied it uses the current request's language/default language.

ajbeaven avatar Jan 25 '17 23:01 ajbeaven