Tuesday, April 23, 2013

SharePoint 2013 Multilingual User Interface (MUI) Switcher

In SharePoint Foundation 2010, when someone navigates to a multilingual website, the website uses the Accept-Language header that the client browser sends with the HTTP request to determine the language in which to render the user interface. If the website does not support any of the languages specified by the browser, the default language is used as the display language
A multilingual website also displays a drop-down menu in the upper-right corner of the page, next to the user's name, where users can select a display language. When someone selects a language that is different from the current display language, the website switches to the new language. The user's preference is persisted in a cookie that is dropped on the client computer. The website gets the user's language preference from the cookie on subsequent visits to the site.



But In SharePoint 2013  the language switcher drop down is removed ... So We have tried to implement our own switcher with same concept in SharePoint 2010 - Reference the Changing the Display Language  - But trying to add the JavaScript was useless.

So we tried another approach ... Using an HTTP Module which interrupts the request in a very early stage - Reference this Page to see how to create and apply an HTTPModule to SharePoint  - .

The trick is the new SharePoint model for changing the display language  is by checking the user's language preferences ... Then adding those languages to the request header in the Accept-Language tag i.e. ar-SA,en-US or buy the language preferences the user configures in his SharePoint user profile. 
  
English Preference Only

Arabic then English Preference 

OK ... we will not reinvent the wheel ... The game plan is to interrupt the request and check for the cookies value - Assuming we have a cookie  preserving the current selected language - Adding the selected language at the to the request header using an HTTP Handler , Then setting the current thread culture to the selected language, By implementing the PreSendRequestHeaders event handler.

UPDATE: Thanks to Suleman, many people was facing some issues in this approach, He found using the PreRequestHandlerExecute event handler solves all issues

e.g context.PreRequestHandlerExecute +=context_PreRequestHandlerExecute;


Following is the code we used for achieving the above scenario by setting the language to arabic:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading.Tasks;
using System.Threading;
 
namespace MUISwitcher
{
    class HTTPSwitcherModule : IHttpModule
    {
        #region IHttpModule Members
 
        public void Dispose()
        {
        }
 
        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute +=context_PreRequestHandlerExecute;
        }
 
        void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpApplication httpApp = sender as HttpApplication;
            HttpContext context = httpApp.Context;
            string httpUrl = context.Request.Url.ToString();
 
            //TODO:Get the selected value for the current culture form the cookie i.e. ar-SA and 
            //set the Header and the CurrentCulture to the aquired value
 
            var lang = context.Request.Headers["Accept-Language"];
 
            if (!lang.Contains("ar-SA"))
                context.Request.Headers["Accept-Language"] = "ar-SA," + context.Request.Headers["Accept-Language"];
 
 
            var culture = new System.Globalization.CultureInfo("ar-SA");
 
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
        }
 
        #endregion
    }
}

6 comments:

  1. Can you please share full code ? i tried this but it is not working.

    ReplyDelete
    Replies
    1. This already the full code, The Key point is to create new empty SharePoint project, Ensure you are on .Net Framework 4.5 add a new class with the above code. Deploy your solution make, Then make sure to add the following to your web.config at section:

      <add name="<YOURHTTPMODULENAME>" type="<FULL CLASS NAMESPACE>, <PROJECT NAMESPACE>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<PUBLICK KEY TOKEN>" />

      i.e.<add name="HTTPSwitcherModule " type="MUISwitcher.HTTPSwitcherModule , MUISwitcher, Version=1.0.0.0, Culture=neutral, PublicKeyToken=51d3e9841465c1e3" />

      To make sure you have correctly configured everything, At the first line of PreSendRequestHeaders put a System.Diagnostics.Debbuger.Lanch() method and find out if the debugger launches in any page request.

      Sorry for the late reply

      Delete
  2. I can't seem to get this to work either... Everything is set up and running as you describe, but I can't seem to force the language to change. Regardless of what values I put in the code, it always loads with the language preferences set in the user's profile or in the browser setting... Is this working for you? Any other tips you can provide? I am able to debug and step through the HTTP module code, so I know it is set up correctly.

    ReplyDelete
  3. Thanks Islam for this great article!

    If any of you still have issues with Language switcher... you actually need to implement PreRequestHandlerExecute event handler and it will start working for you guys. e.g.

    context.PreRequestHandlerExecute +=context_PreRequestHandlerExecute;

    -Suleman

    ReplyDelete
  4. Nice work Suleman. By using the PreRequestHandlerExecute event instead of the PreSendRequestHeaders handler I got this to work as well. It's a shame we have to develop this "hack" to implement such a common functionality.

    -Wade

    ReplyDelete