Search This Blog

Friday, February 4, 2011

Redirect user on preferred language

If you are working on SharePoint multi lingual portal and want to redirect the user on his preferred language, you need to customize the variationRoot.aspx page. This page is created by SharePoint when the variation labels created in the site. it's available on the pages library of the root site.
variationRoot.aspx internally refers the "VariationsRootLanding.ascx" control which contains the logic of redirecting user on source variation language site. To customize this, you need to
  • Create a copy of VariationsRootLanding.ascx control available in the 14 hive folder. (14\TEMPLATE\CONTROLTEMPLATES).
  • Assign a code behind file to the control.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="XYZVariationRootLanding.ascx.cs"
Inherits="XYZ.XYZ.Web.XYZVariationRootLanding" %>
<%@Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@Assembly Name="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@Register TagPrefix="CMS" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Publishing.WebControls"%>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Collections.Specialized" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Collections.ObjectModel" %>
<%@ Import Namespace="System.Globalization" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %>
<%@ Import Namespace="Microsoft.SharePoint.WebControls" %>
<%@ Import Namespace="Microsoft.SharePoint.Publishing" %>

  • Add the following code in the code behind
public partial class XYZVariationRootLanding : System.Web.UI.UserControl
{
private const string QualityValuePrefix = ";q=";
private enum PropertiesOnLabelToUse
{
Language,
Locale
}
private enum MatchingPreference
{
ImpreciseOrderFirst,
PreciseMatch
}
private PropertiesOnLabelToUse PropertyOnLabelToUse
{
get { return this.propertyOnLabelToUse; }
set { this.propertyOnLabelToUse = value; }
}
private PropertiesOnLabelToUse propertyOnLabelToUse = PropertiesOnLabelToUse.Locale;
private MatchingPreference PreferenceOrder
{
get { return this.preferenceOrder; }
set { this.preferenceOrder = value; }
}
private MatchingPreference preferenceOrder = MatchingPreference.ImpreciseOrderFirst;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string targetUrl = this.GetRedirectTargetUrl();
if (!string.IsNullOrEmpty(targetUrl))
{
SPUtility.Redirect(targetUrl, SPRedirectFlags.Default, Context);
}
}
private string GetRedirectTargetUrl()
{
try
{
ReadOnlyCollection spawnedLabels = Variations.Current.UserAccessibleLabels;
LoggedInUser loggedInUser = new LoggedInUser();
string ReturnURL = string.Empty;
string XYZURL = string.Empty;
loggedInUser.LoginName = SPContext.Current.Web.CurrentUser.LoginName;
if (spawnedLabels.Count > 0)
{
string sourceLabelUrl = string.Empty;
Dictionary cultureCodeToUrlMapping = new Dictionary();
Dictionary cultureCodeStrippedToUrlMapping = new Dictionary();
foreach (VariationLabel label in spawnedLabels)
{
if (label.IsSource)
{
sourceLabelUrl = label.TopWebUrl;
}
CultureInfo labelCultureInfo = this.GetLabelCultureInfo(label);
string labelCultureInfoName = labelCultureInfo.Name.ToUpperInvariant();
if (!cultureCodeToUrlMapping.ContainsKey(labelCultureInfoName) || label.IsSource)
{
cultureCodeToUrlMapping.Remove(labelCultureInfoName);
cultureCodeToUrlMapping.Add(labelCultureInfoName, label.TopWebUrl);
string strippedCode = labelCultureInfoName.Split('-')[0];
if (!cultureCodeStrippedToUrlMapping.ContainsKey(strippedCode) || label.IsSource)
{
cultureCodeStrippedToUrlMapping.Remove(strippedCode);
cultureCodeStrippedToUrlMapping.Add(strippedCode, label.TopWebUrl);
}
}
}
string matchedUrl;
if (MatchingPreference.ImpreciseOrderFirst == this.preferenceOrder)
{
matchedUrl = this.GetRedirectTargetUrlImpreciseOrderFirst(
cultureCodeToUrlMapping, cultureCodeStrippedToUrlMapping);
}
else
{
matchedUrl = this.GetRedirectTargetUrlPreciseMatch(
cultureCodeToUrlMapping, cultureCodeStrippedToUrlMapping);
}
ReturnURL = (string.IsNullOrEmpty(matchedUrl) ? sourceLabelUrl : matchedUrl);
XYZURL = GetXYZLanguageURL();
if (string.IsNullOrEmpty(XYZURL))
{
return ReturnURL;
}
else
{
return XYZURL;
}
}
}
catch (Exception ex)
{
LogUtility logUtility = new LogUtility();
logUtility.ManageException(ex.Message, ex);
Response.Redirect(SPContext.Current.Site.RootWeb.Url + "/Pages/Exception.aspx");
}
return null;
}
private string GetXYZLanguageURL()
{
// Logic for creating the redirection URL
}
private CultureInfo GetLabelCultureInfo(VariationLabel label)
{
if (PropertiesOnLabelToUse.Locale == this.propertyOnLabelToUse)
{
return new CultureInfo(Convert.ToInt32(label.Locale, CultureInfo.InvariantCulture));
}
else
{
return new CultureInfo(label.Language);
}
}
private string GetRedirectTargetUrlImpreciseOrderFirst(Dictionary cultureCodeToUrlMapping, Dictionary cultureCodeStrippedToUrlMapping)
{
string[] browserPrefLanguages = this.GetUserLanguages();
if (null == browserPrefLanguages)
return null;
string browserPrefLang;
string browserPrefLangStripped;
for (int i = 0; i <>
{
browserPrefLang = browserPrefLanguages[i].ToUpperInvariant();
if (cultureCodeToUrlMapping.ContainsKey(browserPrefLang))
{
return cultureCodeToUrlMapping[browserPrefLang];
}
browserPrefLangStripped = browserPrefLang.Split('-')[0];
if ((browserPrefLang != browserPrefLangStripped) &&
(cultureCodeToUrlMapping.ContainsKey(browserPrefLangStripped)))
{
return cultureCodeToUrlMapping[browserPrefLangStripped];
}
if (cultureCodeStrippedToUrlMapping.ContainsKey(browserPrefLangStripped))
{
return cultureCodeStrippedToUrlMapping[browserPrefLangStripped];
}
}
return null;
}
private string GetRedirectTargetUrlPreciseMatch(Dictionary cultureCodeToUrlMapping, Dictionary cultureCodeStrippedToUrlMapping)
{
string[] browserPrefLanguages = this.GetUserLanguages();
if (null == browserPrefLanguages)
return null;
for (int i = 0; i <>
{
string browserPrefLanguageName = browserPrefLanguages[i].ToUpperInvariant();
if (cultureCodeToUrlMapping.ContainsKey(browserPrefLanguageName))
{
return cultureCodeToUrlMapping[browserPrefLanguageName];
}
}
for (int i = 0; i <>
{
string browserPrefLanguageName = browserPrefLanguages[i].ToUpperInvariant();
if (cultureCodeStrippedToUrlMapping.ContainsKey(browserPrefLanguageName))
{
return cultureCodeStrippedToUrlMapping[browserPrefLanguageName];
}
}
string browserPrefLangStripped;
for (int i = 0; i <>
{
browserPrefLangStripped = browserPrefLanguages[i].Split('-')[0].ToUpperInvariant();
if (cultureCodeToUrlMapping.ContainsKey(browserPrefLangStripped))
{
return cultureCodeToUrlMapping[browserPrefLangStripped];
}
}
for (int i = 0; i <>
{
browserPrefLangStripped = browserPrefLanguages[i].Split('-')[0].ToUpperInvariant();
if (cultureCodeStrippedToUrlMapping.ContainsKey(browserPrefLangStripped))
{
return cultureCodeStrippedToUrlMapping[browserPrefLangStripped];
}
}
return null;
}
private string[] GetUserLanguages()
{
string[] browserPrefLanguages = Page.Request.UserLanguages;
if (null != browserPrefLanguages)
{
int qualityIndexPos = -1;
for (int i = 0; i <>
{
qualityIndexPos = browserPrefLanguages[i].IndexOf(QualityValuePrefix, StringComparison.Ordinal);
if (qualityIndexPos > 0)
{
browserPrefLanguages[i] = browserPrefLanguages[i].Substring(0, qualityIndexPos);
}
}
}
return browserPrefLanguages;
}
private string ConcatUrls(string firstPart, string secondPart)
{
if (firstPart.EndsWith("/"))
{
if (secondPart.StartsWith("/"))
{
firstPart = firstPart.TrimEnd('/');
}
return firstPart + secondPart;
}
else
{
if (secondPart.StartsWith("/"))
return firstPart + secondPart;
else
return firstPart + "/" + secondPart;
}
}
}
  • Compile the control and deploy DLL in the bin/GAC fodler.
at this point, we are done with the control customization and remaining part is to integrate the custom control with variationRoot.aspx page so user will redirect on preferred language.
for the integration of the control, download the variationrootlayout.aspx file available in the master pages folder "_catalogs/masterpage/Forms/AllItems.aspx" of the site and add the following code at the start of the page.
<%@ Register TagPrefix="Publishing" TagName="VariationsRootLanding" src="~/_controltemplates/XYZVariationRootLanding.ascx"%>
this registration will integrate the custom control with the default page. Now when you access the site, SharePoint will call control you have created and redirect based on the logic implemented in custom control.

2 comments:

  1. Hi Sourabh,

    Nice article .. If i include inherits in the page directive and add the code in ascx.cs variation is not working. It is telling could not load the assembly.. Any help pls

    My requirement is i need to get the preferred language from the user profile webservice and redirect the user based on it..


    thanks in advance

    ReplyDelete
  2. Hi,

    I am not sure but probably control’s DLL is not deployed in the GAC/Bin file. You can make sure that, solution package has deployed the DLL in the required location and safe control entry is available in web.config file. Please share your code. It would be helpful to analyze the problem in detail.

    ReplyDelete