9 Jan 2015, last update: 30 Jan 2022
Create a Sitecore LinkProvider to use different LinkManager
A common wish is to have the language in the url on multilingual sites and not on a single language site. For SEO, show the url in the language is a good idea on Multi language sites. A search engine like unique url’s and content based on the Sitecore language cookie is not good indexed by search engines. When there are multiple URL’s to the same page you should use canonicals. The setting languageEmbedding: asNeeded is not aware of multilanguage or not. We can change that behavior and set languageEmbedding to never on single language websites and to always on Multilanguage.
If you have the wish to have a different Link Manager configuration for a specific site in a multisite environment. You can create your own Link Provider.
All internal links in Sitecore are based on the item GUID. The GUID represents the internal item you link to. By using GUIDs internally, Sitecore allows you to move pages without worrying about links being invalid. Even links in the Rich Text Fields are stored as link to a GUID. When rendering the GUID is converted to a valid URL. The conversion use the link manager. The link manager define a link provider and the link provider have Url options defined in the config.
When a site needs to have a different configuration. You can make a switching provider that is descript in this article A Switching Link Provider in Sitecore
Or you can adapt the linkManager. On Marketplace there is a Link Provider Module that does something simulair and more as describe here. maybe too much, this article focuses on multilingual vs single language with minimal adjustments and no more than necessary change the functionality, maximum performance, reduced risk for upgrades. tested with Sitecore 6.5 through 8.0
This is the part in the default Sitecore web.config where the url options for the link manger are define.
<!-- Options (first is default):
addAspxExtension: false | true (If you set this to false,
remember to configure IIS to map all requests (*) to ASP.NET)
alwaysIncludeServerUrl: false | true
encodeNames: true | false
languageEmbedding: asNeeded | always | never
languageLocation: filePath | queryString
lowercaseUrls: true | false
shortenUrls: true | false
useDisplayName: false | true
-->
<linkManager defaultProvider="sitecore">
<providers>
<clear/>
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false"
alwaysIncludeServerUrl="false"
encodeNames="true"
languageEmbedding="asNeeded"
languageLocation="filePath"
lowercaseUrls="false"
shortenUrls="true"
useDisplayName="false"/>
</providers>
</linkManager>
For Example you have some sites running, and you want to add a Multilanguage site with Nice SEO urls in the correct language. For that you want to set the useDisplayName to true and the languageEmbedding to always. But not touch the other websites.
With useDisplayName=true the Linkmanager use the Displayname instead of the item name in the URL. See Tip #5 SEO url for multi language pages.
The Rich text editor and the Sitecore controls use the LinkManager and of course you should always use the Sitecore.Links.LinkManager to generate a link in your own code.
You can implement a solution based on the following prototype that override the link provider to use a modified configuration dependent on the current site. The new link provider use a new propertie multiLanguageSites a comma separated list or websites.
using System.Collections.Generic;
using System.Collections.Specialized;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Links;
namespace Mirabeau.Sitecore
/// <summary>
/// Sitecore Linkprovider for mixed configuration with multilanguage and not multilanguage websites. change the urloptions depends on the current website
/// to use patch te web.config see the example in App_Config/Include/MirabeauLinkProvider.config
/// </summary>
public class MirabeauLinkProvider : LinkProvider
{
private static HashSet<string> multiLanguageSites;
public override void Initialize(string name, NameValueCollection config)
{
var sites = config.Get("multiLanguageSites");
Log.Info("Mirabeau linkprovider Initialize :" + sites, this.GetType());
multiLanguageSites = new HashSet<string>();
if (!string.IsNullOrWhiteSpace(sites))
{
foreach (var site in sites.Split(','))
{
multiLanguageSites.Add(site.Trim().ToLower());
}
}
base.Initialize(name, config);
}
public override string GetItemUrl( Item item, UrlOptions options)
{
var newOptions = options;
//a new interpretation of the LanguageEmbedding.AsNeeded it depend on the site.
if (options.LanguageEmbedding == LanguageEmbedding.AsNeeded)
{
if (multiLanguageSites.Contains(options.Site.Name.ToLower()))
{
newOptions.LanguageEmbedding = LanguageEmbedding.Always;
//newOptions.UseDisplayName = true; this is also a option to set.
} else
{
newOptions.LanguageEmbedding = LanguageEmbedding.Never;
}
}
return base.GetItemUrl(item, newOptions);
}
}
}
To activate the new LinkProvider change the web.config. This can be done by placing the following include file in the App_Config/Include directory. Put the multilanguage website in the property multiLanguageSites.
<!--
Purpose:
-This include file change the linkprovider to change the urloptions for site define in multiLanguageSites
-->
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<linkManager>
<providers>
<add name="sitecore">
<patch:attribute name="type">Mirabeau.Sitecore.MirabeauLinkProvider, Mirabeau.Sitecore</patch:attribute>
<patch:attribute name="multiLanguageSites">website,websitebe</patch:attribute>
</add>
</providers>
</linkManager>
</sitecore>
</configuration>
Related links
https://jammykam.wordpress.com/2015/02/03/site-specific-link-provider-for-multi-site-implementation-in-sitecore/