Configuring URLs for multilingual websites -- Live URL for each page does not show proper assigned d

Ethan Smith asked on June 21, 2018 17:34

I am working on creating hreflang alternate tags for SEO purposes on each page on a multilingual Kentico 9 powered site. I have 4 different domain names (not subdomains) assigned as aliases.

For each Domain Alias, I have the proper Visitor Culture.

When I edit a page that is in multiple languages, the Live URL shows as my primary domain rather than the specific domain alias for that culture. This becomes a problem when I use this Macro code to output proper hreflang tags as needed for SEO:

{% foreach (page in CurrentDocument.CultureVersions) {
  if (page.DocumentCulture != CurrentDocument.DocumentCulture) {
    ""
  }
}
#%}

The tags ARE generated, but EACH one uses the main domain name and does not use the correct culture specific domain alias as required.

I can access the page at the proper domain alias by navigating directly to it myself, but nothing done through Macros or programmatically seems to recognize the proper domain alias for that culture version.

Recent Answers


Brenden Kehren answered on June 21, 2018 17:49

I have a method I used based on a field (WebLocals) a user can select 1 from.

    public string GetLanguageUrls()
    {
        string returnValue = "";
        string[] locals = ValidationHelper.GetString(Eval("WebLocales"), "").Split('|');
        foreach (var s in locals)
        {
            CMS.Localization.CultureInfo ci = CMS.Localization.CultureInfoProvider.GetCultureInfo(s);
            string link = "";
            if (ci != null)
            {
                string cultureUrl = CMS.SiteProvider.SiteInfoProvider.GetDomainForCulture(CMS.SiteProvider.SiteContext.CurrentSiteName, ci.CultureCode);
                if (!string.IsNullOrEmpty(cultureUrl))
                {
                    cultureUrl = URLHelper.GetAbsoluteUrl(Eval<string>("NodeAliasPath") + ".aspx", cultureUrl);
                    link = string.Format("<li><a href='{0}' lang='{1}'>{2}</a></li>", cultureUrl, ci.CultureCode, ci.CultureShortName);
                }                
            }
            returnValue = string.Concat(returnValue, link);
        }
        return "<ul>" + returnValue + "</ul>";
    }

I use a foreach loop because its better at error handling even though there is only ever 1 culture code in the WebLocals field

0 votesVote for this answer Mark as a Correct answer

Ethan Smith answered on June 21, 2018 18:33

Brenden Kehren how would I implement this?

I'm brand new to .NET development environment and trying to get up to speed on Kentico CMS.

I'm guessing this needs to go in my Master Page (SiteMasterUS.master.cs) code behind file and then be called somehow in the Master Page (SiteMasterUS.master) ?

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 21, 2018 22:40

Unfortunately, it sounds like you're using ASPX development mode in Kentico. We don't use that method so I can't provide exact steps but typically you'd create a class with a public static method in it returning a string.

From there you can optionally create a custom macro method as well as a custom transformation method and then simply call that custom static method you created in the first class. This allows that one static method to be available all via all the methods Kentico will allow you to call it; API, Macro, Transformation.

0 votesVote for this answer Mark as a Correct answer

Ethan Smith answered on June 22, 2018 16:28 (last edited on December 10, 2019 02:31)

Any idea how I can get something like this working?

The logic is that I know I only have 4 languages with corresponding domain aliases -- Since this original code from Milan Lund IS working but just not when I have separate domains set (it works great IF I use the subdirectory language approach like domain.com/en-US/ instead of englishdomain.com etc.) I figured I could try and just CHECK the returned language code and then use that to set a culture domain variable myself that I could then print into the <'link rel'> tag as needed.

The code below is not outputting anything, it's silently erroring out -- any ideas?


{% foreach (page in CurrentDocument.CultureVersions) {
  
  string CultureDomain = "https://NoSet.com";
  
  if (page.DocumentCulture == "en-GB"){
    string CultureDomain = "https://GreatBritain.com";
  }
  else if (page.DocumentCulture == "en-AU"){
    string CultureDomain = "https://Australia.com";
  }
  else if (page.DocumentCulture == "en-US"){
    string CultureDomain = "https://USA.com";
  }
  else if (page.DocumentCulture == "en-IN"){
    string CultureDomain = "https://India.com";
  }
  else {
    string CultureDomain = "https://NoSet.com";
  }
  

  "<#link rel=\"alternate\" href=\""+ CultureDomain + "\" hreflang=\""+ page.DocumentCulture +"\" />"

}
|(identity)GlobalAdministrator%} 

(Please note that Extra "#" at the beginning of the LINK REL tag is NOT there in my code, I just had to add it so this editor would stop hiding it from my response).

0 votesVote for this answer Mark as a Correct answer

Ethan Smith answered on June 22, 2018 16:31

Forgot to include this link, but this is what I've started with originally:

https://www.milanlund.com/blog/get-urls-of-a-pages-culture-versions-in-kentico

This is being placed into the HEAD part of my page templates. And yes I didn't know much about the various development methods or patterns previously but I believe with our doing ASPX + Portal method for this site.

0 votesVote for this answer Mark as a Correct answer

Ethan Smith answered on July 5, 2018 16:04 (last edited on December 10, 2019 02:31)

I am updating this in case anyone else runs across this through Google or Kentico site search -- I did not know previously that an ELSE IF statement would not work within the FOREACH loop within K# Syntax. (Maybe it works normally in regular C# -- I'm not sure? I'm coming from a design and more front-end background). Either way I was able to get a solution that worked for me using nested IF ELSE statements.

Code sample below (modified slightly for general example):

{% foreach (page in CurrentDocument.CultureVersions) {

if (page.DocumentCulture != CurrentDocument.DocumentCulture) {

  if (page.DocumentCulture == "en-AU") {
    "<link rel=\"alternate\" href=\"https://website.com.au"+ page.NodeAliasPath + ".aspx" + "\" hreflang=\""+ page.DocumentCulture +"\" />";
  }

  else {
    if (page.DocumentCulture == "en-GB") {
      "<link rel=\"alternate\" href=\"https://website.co.uk"+ page.NodeAliasPath + ".aspx" + "\" hreflang=\""+ page.DocumentCulture +"\" />";
    }

    else {
      if (page.DocumentCulture == "en-US") {
        "<link rel=\"alternate\" href=\"https://website.com"+ page.NodeAliasPath + ".aspx" + "\" hreflang=\""+ page.DocumentCulture +"\" />";
      }

      else {
        if (page.DocumentCulture == "en-IN") {
          "<link rel=\"alternate\" href=\"https://website.co.in"+ page.NodeAliasPath + ".aspx" + "\" hreflang=\""+ page.DocumentCulture +"\" />";
        }
      }
    }
  }

}

}
|(identity)GlobalAdministrator%}

The logic for this returns a collection of documents in all cultures for the current page. That is our FOREACH loop primary condition. The first IF statement checks to see if the page in the loop has the same culture set as the page we're currently viewing, ELSE we start running through the series of nested IF/ELSE statements as needed to set the proper tag relevant for the culture version and language code of each page in the loop.

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.