Showing posts with label alias. Show all posts
Showing posts with label alias. Show all posts

Sitecore Multilingual Item Alias

Sitecore by default provides Item Aliases for single language, refer my earlier post regarding Sitecore Aliases. One good request came to Sitecore SDN Forums for achieving aliases for multiple languages in Sitecore so thought to post about it.

What we want to achieve is, when a request come for an alias, the content of the Linked Item should come with selected language.

How to achieve?

  1. In the Alias template (/sitecore/templates/System/Alias), add a new field Linked Language with DropLink field.
    So, when a request comes like http://domain/idioma/, it should serve the Products page with es-ES language.


  2. Override the AliasResolver like below:
    namespace SitecoreTactics.HttpRequestPipeline
    {
        public class MultilingualAliasResolver : HttpRequestProcessor
        {
            public override void Process(HttpRequestArgs args)
            {
                Assert.ArgumentNotNull((object)args, "args");
                if (!Settings.AliasesActive)
                {
                    Tracer.Warning((object)"Aliases are not active.");
                }
                else
                {
                    Database database = Context.Database;
                    if (database == null)
                    {
                        Tracer.Warning((object)"There is no context database in AliasResover.");
                    }
                    else
                    {
                        Profiler.StartOperation("Resolve alias.");
                        if (database.Aliases.Exists(args.LocalPath) && !this.ProcessItem(args))
                            this.ProcessExternalUrl(args);
                        Profiler.EndOperation();
                    }
                }
            }
    
            private void ProcessExternalUrl(HttpRequestArgs args)
            {
                string targetUrl = Context.Database.Aliases.GetTargetUrl(args.LocalPath);
                if (targetUrl.Length <= 0)
                    return;
                this.ProcessExternalUrl(targetUrl);
            }
    
            private void ProcessExternalUrl(string path)
            {
                if (Context.Page.FilePath.Length > 0)
                    return;
                Context.Page.FilePath = path;
            }
    
            private bool ProcessItem(HttpRequestArgs args)
            {
                bool aliasFound = false;
                string alias = args.LocalPath;
                if (alias.Length > 0)
                {
                    Item obj = ItemManager.GetItem(FileUtil.MakePath("/sitecore/system/aliases", alias, '/'), Language.Invariant, 
                        Version.First, Sitecore.Context.Database, SecurityCheck.Disable);
                    if (obj != null)
                    {
                        LinkField itemField = (LinkField)obj.Fields["linked item"];
                        string language = obj["linked language"];
                        if (!string.IsNullOrEmpty(language) && itemField!= null)
                        {
                            Item langItem = Sitecore.Context.Database.GetItem(new ID(language));
                            if (langItem != null)
                            {
                                Language lang = Language.Parse(langItem.Name);
                                Item item = Sitecore.Context.Database.GetItem(itemField.TargetID, lang);
                                if (item != null)
                                {
                                    this.ProcessItem(args, item);
                                    aliasFound = true;
                                }
                            }
                        }
                        else if (itemField!=null)
                        {
                            Item item = Sitecore.Context.Database.GetItem(itemField.TargetID);
                            if (item != null)
                            {
                                this.ProcessItem(args, item);
                                aliasFound = true;
                            }
                        }
                    }
                }
    
                return aliasFound;
            }
    
            private void ProcessItem(HttpRequestArgs args, Item target)
            {
                if (Context.Item != null)
                    return;
                Context.Item = target;
                Context.Language = target.Language;
            }
        }
    }
    
  3. In Web.config, replace the Sitecore's AliasResolver and add our custom overridden MultilingualAliasResolver as below:
    <!--<processor type="Sitecore.Pipelines.HttpRequest.AliasResolver, Sitecore.Kernel" />-->
    <processor type="SitecoreTactics.HttpRequestPipeline.MultilingualAliasResolver, SitecoreTactics" />
    

Finally we are able to use multilingual aliases.

Note:Above code works only for Linked Items which are Sitecore Internal Links.

Sitecore Item alias - Alternate URL

An Alias is an alternate path for an item when browsing the web site. In other terms we can have URL alias in Sitecore.

Suppose, you have an item's URL as:
http://mysite.com/news/2013/cricket/

Now, you want the same page to be opened using some alternate URLs like:
http://mysite.com/cricket-news/
OR
http://mysite.com/news-cricket/

This is quite possible using AliasResolver in Sitecore.

How to configure

We will create two different aliases cricket-news and news-cricket under /sitecore/system/aliases/. Both items will have same configuration, means both will point to content item /sitecore/content/Home/News/2013/Cricket/ So, AliasResolver read these settings and work accordingly.

See below image how alias can be set for this item.

How can we know URL of alternate URL or Alias?

To see if an alias exists, use the database.Aliases.Exists() method. This will check if both the alias exists and the target item exists sd below:
    // Code from Sitecore.Pipelines.HttpRequest.AliasResolver class
    Database database = Context.Database;
    if (database == null)
    {
        Tracer.Warning("There is no context database in AliasResover.");
    }
    else
    {
        if (database.Aliases.Exists(args.LocalPath) && !this.ProcessItem(args))
        {
            this.ProcessExternalUrl(args);
        }
        Profiler.EndOperation();
    }

    private void ProcessExternalUrl(HttpRequestArgs args)
    {
        string targetUrl = Context.Database.Aliases.GetTargetUrl(args.LocalPath);
        if (targetUrl.Length > 0)
        {
            this.ProcessExternalUrl(targetUrl);
        }
    }

    private void ProcessExternalUrl(string path)
    {
        if (Context.Page.FilePath.Length <= 0)
        {
            Context.Page.FilePath = path;
        }
    }


What to do in multisite environment?

In multisite environment, we can still use this functionality. We can customize the AliasResolver processor in HttpRequestBegin pipeline, where the alias items will be stored in Site specific folder, so, the Custom AliasResolver will search aliases in site folder only. We can create a alias folder structure site-wise, something like,
/Sitecore/System/Aliases/Site-A/Alias1
/Sitecore/System/Aliases/Site-A/Alias2
/Sitecore/System/Aliases/Site-B/Alias1
/Sitecore/System/Aliases/Site-B/Alias2

See below snap:

This structure might change depending on what folder structure you follow. See how code will go for Custom AliasResolver:
namespace SitecoreTactics.Pipelines.HttpRequestBegin
{
class CustomAliasResolver : AliasResolver
{
    public new void Process(HttpRequestArgs args)
    {
        Assert.ArgumentNotNull(args, "args");

        if (!Settings.AliasesActive)
        {
            Tracer.Warning("Aliases are not active.");
        } 
        else 
        {
            Sitecore.Data.Database database = Sitecore.Context.Database;
            if (database == null)
            {
                Tracer.Warning("There is no context database in AliasResover.");
            }

            Item aliasItem = getAliasItem(args);
            if (aliasItem != null)
            {
                LinkField linkField = aliasItem.Fields["Linked item"];
                if (linkField != null)
                {
                    Item AliasLinkedTo = Sitecore.Context.Database.GetItem(linkField.TargetID);

                    if (AliasLinkedTo != null)
                    {
                        Sitecore.Context.Item = AliasLinkedTo;
                    }
                }
                else
                {
                    base.Process(args);
                }
            }
        }            
    }

    /// 
    /// Gets the alias item.
    /// 
    /// The args.
    /// 
    private Item getAliasItem(HttpRequestArgs args) 
    {
        string siteName = Sitecore.Context.Site.RootPath.ToLower();

        if (args.LocalPath.Length > 1)
        {
            Item aliasItem = Sitecore.Context.Database.GetItem("/sitecore/system/Aliases/" + siteName + "/" + args.LocalPath);
            if (aliasItem != null)
            {
                return aliasItem;
            }                
        }

        return null;
    }
}
}

Read more about Sitecore alias:

- Sitecore language based Alias
- Sitecore Alias for multisite solution - Marketplace Module