turquoiseowl / i18n

Smart internationalization for ASP.NET
Other
556 stars 156 forks source link

Generating hreflang link elements #251

Closed ajbeaven closed 8 years ago

ajbeaven commented 8 years ago

Short version: In Scheme2 when viewing a page with a localized URL, i18n tries to localize URLs that don't have a langtag in them (ie. URLs pointing to the default language version). This makes it impossible to generate correct hreflang link elements under Scheme2.

Long version: In order to improve indexing of the different languages supported on my site I'm trying to generate some hreflang link elements. I'd hope to have something like this in the end:

<link rel="alternate" hreflang="en" href="https://mysite.com">
<link rel="alternate" hreflang="es" href="https://mysite.com/es">
<link rel="alternate" hreflang="ru" href="https://mysite.com/ru">

Note that I'm using Scheme2 with en as the default language.

This is what I've got so far:

@foreach (var language in LanguageHelpers.GetAppLanguages())
{
    var languageKey = language.Key == LocalizedApplication.Current.DefaultLanguage ? null : language.Key;
    <link rel="alternate" hreflang="@language.Key" href="@LanguageTag.SetLangTagInUrlPath(Url.Action(action, controller, new {area = area}, "https"), UriKind.Absolute, languageKey)"/>
}

This works perfectly fine when running under localhost, however in production, when I'm on a version that is not the default language, the href of the hreflang tag that points to the default language is changed to the current language.

Is there a way to ignore this behaviour just while generating this one URL? Alternatively, if there is a better way to generate these hreflang tags, then I'm all ears.

turquoiseowl commented 8 years ago

I don't follow exactly the meaning of your penultimate paragraph, but will not the following work:

@foreach (var language in LanguageHelpers.GetAppLanguages())
{
    if (language == LocalizedApplication.Current) {
        <link rel="alternate" 
            hreflang="@language.Key" 
            href="@Url.Action(action, controller, new {area = area}, "https")"/>
    }
    else {
        <link rel="alternate" 
            hreflang="@language.Key" 
            href="@LanguageTag.SetLangTagInUrlPath(
                Url.Action(action, controller, new {area = area}, "https"), 
                UriKind.Absolute, 
                languageKey)"/>
    }
}
ajbeaven commented 8 years ago

To explain that paragraph and to continue the first example I used above, if I was on the page https://mysite.com/ru the hreflang="en" tag's URL is changed to https://mysite.com/ru when rendered instead of https://mysite.com.

From what I was seeing, even if I hard coded the correct URL in the hreflang attribute, the URL is changed when it's rendered on the page. Thus, the code you supplied would have the same problem (albeit a bit cleaner).

I've hacked around this in the meantime by adding an outgoing filter (don't localise if the url is the same as the currentRequestUrl) but it doesn't seem like the right approach and is likely to cause other bugs.

What would be awesome is if there was an HTML helper that you could use to render these tags as this should be a very common use case. That said, this issue would also affect an html helper so that'll still need to be addressed.

turquoiseowl commented 8 years ago

Yes, of course, the URL will get localized when you don't want it to be, to the current language.

So what's needed is a 'DO NOT LOCALIZE ME' flag with the URL string?

I recall this same issue was brought up a while back, but not the specific solution. First thought is a hack like a ^^^^ prefix to the URL string to indicate DO NOT LOCALIZE. The UrlLocalizer can then strip that and act accordingly.