6

We have a multi language site with English and Thai and I need to change the default language code in URL for the Thai pages.

eg: mysite.com/th-th/about should become mysite.com/th/about

My code works though, but I have 2 questions.

  1. Is this the right/sitecore way to do it
  2. I have replaced the default linkmanager for now. But ours is a multi-site instance. Is there another way to add the Link manager provider, just for a particular site, like from a patch file.

web.config

//replaced the existing property with custom
 <linkManager defaultProvider="sitecore">
  <providers>
   <clear />
    <add name="sitecore" type="MySite.Foundation.Common.Utilities.SitecoreExtensions+MySiteLinkProvider, MySite.Foundation.Common" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" />
    <!--<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" />-->        
 </providers>
</linkManager>

custom.config:

<pipelines>
 <httpRequestBegin>
  <processor type="MySite.Foundation.Common.Utilities.SitecoreExtensions+MySiteHttpRequestProcessor, MySite.Foundation.Common" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" />
      </httpRequestBegin>
</pipelines>

code:

public class MySiteLinkProvider : LinkProvider 
{
  public override string GetItemUrl(Item item, UrlOptions options)
  {
    string returnUrl = base.GetItemUrl(item, options);

    if (Context.Site.Name.ToLower() == "mysite")
    {
      try
      {
        Language currentLanguage = LanguageManager.GetLanguages(Context.Database).Where(x => x.Name == item.Language.Name).FirstOrDefault();

        if (currentLanguage != null)
        {
          options.LanguageEmbedding = LanguageEmbedding.Always;
          options.LanguageLocation = LanguageLocation.FilePath;
          ID languageId = LanguageManager.GetLanguageItemId(item.Language, item.Database);
          var languageItem = item.Database.GetItem(languageId);
          var regionName = item.Language.CultureInfo.TwoLetterISOLanguageName.ToLower() ?? "";
          returnUrl = base.GetItemUrl(item, options).ToLower().ReplaceFirst(item.Language.Name.ToLower(), regionName);
         }
         else
         {
           string defaultLanguageName = Sitecore.Context.Site.Language.ToLower();
           Language defaultLanguage = LanguageManager.GetLanguages(Context.Database).Where(x => x.Name.ToLower() == defaultLanguageName).FirstOrDefault();

           if (defaultLanguage != null)
           {
             returnUrl = base.GetItemUrl(item, options).ToLower().ReplaceFirst(item.Language.Name.ToLower(), defaultLanguage.CultureInfo.TwoLetterISOLanguageName.ToLower());
           }
           else
           {
             returnUrl = base.GetItemUrl(item, options).ToLower().ReplaceFirst(item.Language.Name.ToLower(), defaultLanguageName);
           }
          }
         }
         catch (System.Exception ex)
         {
         }
        }

       return returnUrl;
      }
    }

    public class MySiteHttpRequestProcessor : HttpRequestProcessor
    {
      public override void Process(HttpRequestArgs args)
      {
        if (Context.Site.Name.ToLower() == "mysite")
        {
          Assert.ArgumentNotNull(args, "args");
          string contextLanguageName = Context.Language.Name.ToLower();
          string languageCode = Context.Language.CultureInfo.TwoLetterISOLanguageName.ToLower();

          if (contextLanguageName != languageCode)
          {
            //if url has th-th, then context language will be th-th. In such case, redirect to the same url but with language code
            //eg: if url is /th-th/home, redirect to /th/home
            string url = LinkManager.GetItemUrl(Context.Item).ToLower().Replace(contextLanguageName, languageCode);
            HttpContext.Current.Response.Redirect(url, false);
           }
           else
           {
             //get the correct language and set it to context and the item.
             Language contextLanguage = Context.Language;
             Language sitecoreLanguage = LanguageManager.GetLanguages(Context.Database).Where(x => x.Name == contextLanguageName).FirstOrDefault();
             sitecoreLanguage = sitecoreLanguage ?? LanguageManager.GetLanguages(Context.Database).Where(x => x.CultureInfo.TwoLetterISOLanguageName == contextLanguageName).FirstOrDefault();

             if (sitecoreLanguage != null)
             {
               Context.SetLanguage(sitecoreLanguage, true);
               Context.Item = ItemManager.GetItem(args.Url.ItemPath.ReplaceFirst("/" + languageCode, ""), sitecoreLanguage, Version.Latest, Context.Database);
             }
            }
           }
          }
        }
  • 1
    Wouldn't it be easier to change your language (in system) to "th" instead of "th-th"? That would fix your issue as well without custom code.. – Gatogordo Mar 23 '17 at 12:59
  • We did try that with no effect. Also, I read that renaming a language works well if it is a fresh project and there are no thai versions. But versions are already created now. – Qwerty Mar 23 '17 at 13:18
  • Stephen Pope has answered your question here: stackoverflow.com/questions/8129168/… If I were you, I would skip the "dirty" parts in his answer and use the actual update of the language of your items – Gatogordo Mar 23 '17 at 14:50
6

Best way to do this is by using physicalFolder/virtualFolder parameters in site definitions.

step 1: Add seperate site definitions before "website" site definition as follows

    <site name="th-site" patch:before="site[@name='website']" 
     virtualFolder="/th" physicalFolder="/th" rootPath="/sitecore/content" 
     startItem="/Home" hostName="mysite.com"  database="web" language="th-th" 
     inherits="website" /> 

    <site name="en-site" patch:before="site[@name='website']" 
     virtualFolder="/en" physicalFolder="/en" rootPath="/sitecore/content" 
     startItem="/Home" hostName="mysite.com"  database="web" language="en" 
     inherits="website" />

NOTE: Main things to note is physicalFolder & virtualFolder settings in the site definition.

step 2: In the default link manager, set "languageEmbedding" property to "never".

UPDATE: step 3: Set the Languages.AlwaysStripLanguage setting to false https://sitecorefootsteps.blogspot.com/2014/01/striplanguage-processor-in-pipeline.html

That's it.

  • @scFootsteps. I followed the example and created those two definitions before the default in sitedefiniton.config, but it did not work. When user browses /th-th/home, itsn;t redirecting to /th/home. And when I manually browse /th/home, the content for thai version doesn't load or is empty. – Qwerty Mar 24 '17 at 7:17
  • its not handling redirects. You have to handle redirections from other way/module. regarding empty page when browse /th/home, is your home url is /th or /th/home ? because starting item is determine by rootPath + startItem. So, in the definition i have given, when you browse /th/ , you should see the /sitecore/content/home item. Also, have you setup languages for the site definitions. can you post your site definitions by running the /sitecore/admin/showconfig.aspx ?? – scFootsteps Mar 24 '17 at 8:37
  • also, have you setup both virtualFolder & physicalFolder to /th ?? – scFootsteps Mar 24 '17 at 8:40
  • @Qwerty I have added a step 3 which needs to tell to sitecore not to strip /th when try to resolve site. – scFootsteps Mar 24 '17 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.