Search This Blog

Thursday, March 11, 2010

How to do a language switch in a master page.

As the rap song goes: “There’s no champagne in the champagne room...”, there is no page in MasterPage. It derives from UserControl. As such it does not support the InitializeCulture() method for us to override as described in this post. Newbies love master pages, even though half the time they do not understand them, so here is a solution, compounding the misuse, but here it goes.
Declare a dropdown as usual in the master page. Instead of overriding the InitializeCulture() place the same code in the Application_BeginRequest event handler in the global.asax. It is very similar to InitializeCulture() in the sense that it occurs early and no controls are ready yet. We have a little problem though, now the control is declared in a template and its name and id attributes rendered differently. We can't use the control id and cheat like in the other post any more. We cant use the Control.UniqueID property either, remember no controls yet. So now what?
Another collection like the form variables collection that is also not originally server collection is the cookies collection. I use the cookie but it can be any of the ways for cross page communication that do not depend on server controls, like profile, session, querystring etc. We cannot use a cookie to carry the culture name value which comes from the dropdown selected item value, because the culture would always be a step behind. It would be set early on but later the dropdown selection change it but the resources for the previous culture come up. So normally only the page containing the dropdown would be a step behind, but because the dropdown is in the master page it appears that the whole site is ALWAYS ONE STEP BEHIND.
If, however, in the cookie, we pass the control name (which is information that never changes, so we can never be behind), instead of the culture name( which we can never keep up with), and then use that key to get the form variable value, we have pieced ourselves a workaround.
in the master page:
<asp:DropDownList runat="server" ID="DropDownList1" AutoPostBack="true"OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
<asp:ListItem Value="en" Text="English" />      <asp:ListItem Value="fr" Text="French" />
<asp:ListItem Value="de" Text="German" />asp:DropDownList>
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e){
   HttpCookie cookie = new HttpCookie("DropDownName");

in global asax

void Application_BeginRequest(Object sender, EventArgs e){
      string lang = string.Empty;//default to the invariant culture      HttpCookie cookie = Request.Cookies["DropDownName"];

      if (cookie != null && cookie.Value != null)
         lang = Request.Form[cookie.Value];

      Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(lang);

Notice, there is absolutely no code in any of the content pages. Thats it ten lines of code and we are done for the whole site. This is not complete code, just a tip and trick of using master page and the .net event model to globalize code.

The new issue now is what about pages that do not have a master page? Not all pages are strapped in a template like that. This approach can be modified to support both. That is for next post.


Happy Dotnetting... :)

No comments:

Post a Comment

Leave your suggession & comment...