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.
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.
Well I am working on web portal, which has a master page and content pages.
In master page, I am selecting language like fr, de, es and ar i.e. arabic.
I did exactly what you mentioned in your sample code, however I could see any changes in the screen.
Text, from English to French or German didnt change. Currencies, Date format, numeric values as per the culture and uiculture changed.
Would it possible for you to explain bit more in details, why same thing may not be working in my situation?
<div>The same for me </div> <div>i'll try this code and didn't seems to works.</div> <div> </div> <div>i'll try some response.write
to understand.</div> <div> </div> <div>System.Threading.Thread.CurrentThread.CurrentCulture.ToString()=fr-FR</div> <div>and after affectation the Culture
System.Threading.Thread.CurrentThread.CurrentCulture.ToString()=en-US</div> <div> </div> <div>so the lang have switch but my ressources is not use in the good language.</div> <div> </div>
<div>I've try the change my navigator language and all works good.</div> <div> </div> <div>I think the Application_BeginRequest append to late?</div> <div> </div>
<div>If anyone could help please. </div>
<div>I have some help from rmprimo now it's working very good.</div> <div>Even better than the tutorials in asp.net website (the tutorials the save the language must be submitted 2 times for the change to be applied)</div> <div> </div> <div>I used query string
for language switching : </div>
You can use a virtual directory in the iis and point it to an common folder for all langauge depend pages.
e.g
/en/yourPage.aspx
/es/yourPage.aspx
the directory structur could be :
\bin
\common\yourPage.aspx
\controls\.....
to switch the language read the current page, create some links to the current page and prepend the
different langauge codes to the links.
- for a first-time visitor, read whose language from the request
- to redirect a visitor to the last visited language, use a coockie
- if a user type an unavailable languagecode in the url, implement a mehtod to
define a default system language.
- then set the language to the current thread
protected void Application_BeginRequest(Object sender, EventArgs e)
{
String language = Request.UserLanguages[0];
if (language.Length > 1) language = language.Substring(0, 2);
HttpCookie cookie = Request.Cookies["ReBuy"];
if (cookie != null && cookie["language"] != null)
{
language = (String)cookie["language"];
}
if (splitPath.Length > 1)
{
if (splitPath[0].Length == 2)
{
language = splitPath[0];
}
else if (splitPath[1].Length == 2)
{
language = splitPath[1];
}
}
language = Bll.Language.Language.GetSystemLanguage(language);
if (cookie == null)
{
cookie = new HttpCookie("myappname");
}
if (cookie["language"] == null || cookie["language"].ToString() != language)
{
cookie["language"] = language;
cookie.Expires = DateTime.Now.AddYears(1);
Response.Cookies.Add(cookie);
}
I would not recommend overriding the global.asax begin_Request event because this is not a encapsulated solution
My advise is to create a base page that will have the logic of language switching (by using the previous solution that
joschua wrote) or if you don't like base pages you can use the aggregation solution by creating an utility (static) class.
So changing the language will only require you to call a method on the base page that will handle everything (saving the language needed to the session / cookie, validating, etc).
The final solution will be clean and reusable
Hope this helps (If you need a sample code tell me - although its relatively simple)
Ran Davidovitz http://davidovitz.blogspot.com
Check this basepage i've made, hope it helps .. ctl00$ddlLanguage is a dropdown that the user uses to switch cultures (this can be tweaked a bit).
It should work with pages that use or don't a master page.
If a culture change is detected OnCultureChange event is raised
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Globalization;
using System.Threading;
public delegate void CultureChanged(object Sender, string CurrentCulture);
public class Base: Page
{
public event CultureChanged OnCultureChanged;
public string LastCultureName
{
get
{
string lastCultureName = (string)Session["_lastCulture"];
if (lastCultureName == null)
Session["_lastCulture"] = Thread.CurrentThread.CurrentCulture.Name;
return lastCultureName;
}
set
{
Session["_lastCulture"] = value;
}
}
protected override void InitializeCulture()
{
//TODO: make this prettier
string lang = Request["ctl00$ddlLanguage"];
if (lang == null || lang == String.Empty)
lang = LastCultureName;
Thread.CurrentThread.CurrentCulture = new CultureInfo(lang);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang);
}
protected override void OnLoadComplete(EventArgs e)
{
base.OnLoadComplete(e);
if (LastCultureName != Thread.CurrentThread.CurrentCulture.Name)
{
LastCultureName = Thread.CurrentThread.CurrentCulture.Name;
if ( this.OnCultureChanged != null)
this.OnCultureChanged(this, LastCultureName);
}
}
}
rmprimo
Contributor
3639 Points
738 Posts
How to do a language switch in a master page.
Mar 08, 2006 03:49 AM|LINK
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");
cookie.Value=DropDownList1.UniqueID;
Response.SetCookie(cookie);
}
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.
Enjoy
Rob
aspnet20begi...
Member
10 Points
2 Posts
Re: How to do a language switch in a master page.
Mar 16, 2006 12:08 PM|LINK
rmprimo,
Well I am working on web portal, which has a master page and content pages.
In master page, I am selecting language like fr, de, es and ar i.e. arabic.
I did exactly what you mentioned in your sample code, however I could see any changes in the screen.
Text, from English to French or German didnt change. Currencies, Date format, numeric values as per the culture and uiculture changed.
Would it possible for you to explain bit more in details, why same thing may not be working in my situation?
Hritesh.
ludo018
Member
10 Points
2 Posts
Re: How to do a language switch in a master page.
Apr 11, 2006 03:38 PM|LINK
System.Threading.Thread.CurrentThread.CurrentCulture.ToString()=en-US</div> <div> </div> <div>so the lang have switch but my ressources is not use in the good language.</div> <div> </div> <div>I've try the change my navigator language and all works good.</div> <div> </div> <div>I think the Application_BeginRequest append to late?</div> <div> </div> <div>If anyone could help please. </div>
ludo018
Member
10 Points
2 Posts
Re: How to do a language switch in a master page.
Apr 12, 2006 04:00 PM|LINK
string sLang = string.Empty; HttpCookie oCookie = Request.Cookies["LANGUAGE"]; if (Request.QueryString["lang"] != null) { sLang = Request.QueryString["lang"]; HttpCookie oCookieSet = new HttpCookie("LANGUAGE"); oCookieSet.Value = Request.QueryString["lang"]; Response.SetCookie(oCookieSet); } else if (oCookie != null && oCookie.Value != null) sLang = oCookie.Value; Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(sLang); Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(sLang);<div> </div> <div>and all work fine </div> <div>thnaks for your help</div>marmot74
Member
45 Points
9 Posts
Re: How to do a language switch in a master page.
Apr 19, 2006 09:40 PM|LINK
joschua
Member
40 Points
8 Posts
Re: How to do a language switch in a master page.
May 05, 2006 08:58 AM|LINK
e.g
/en/yourPage.aspx
/es/yourPage.aspx
the directory structur could be :
\bin
\common\yourPage.aspx
\controls\.....
to switch the language read the current page, create some links to the current page and prepend the
different langauge codes to the links.
- for a first-time visitor, read whose language from the request
- to redirect a visitor to the last visited language, use a coockie
- if a user type an unavailable languagecode in the url, implement a mehtod to
define a default system language.
- then set the language to the current thread
protected void Application_BeginRequest(Object sender, EventArgs e)
{
String language = Request.UserLanguages[0];
if (language.Length > 1) language = language.Substring(0, 2);
HttpCookie cookie = Request.Cookies["ReBuy"];
if (cookie != null && cookie["language"] != null)
{
language = (String)cookie["language"];
}
String appName = Request.ApplicationPath.Length > 1 ? Request.ApplicationPath : "";
String path = this.Request.FilePath.Substring(appName.Length);
String[] splitPath = path.Split('/');
if (splitPath.Length > 1)
{
if (splitPath[0].Length == 2)
{
language = splitPath[0];
}
else if (splitPath[1].Length == 2)
{
language = splitPath[1];
}
}
language = Bll.Language.Language.GetSystemLanguage(language);
if (cookie == null)
{
cookie = new HttpCookie("myappname");
}
if (cookie["language"] == null || cookie["language"].ToString() != language)
{
cookie["language"] = language;
cookie.Expires = DateTime.Now.AddYears(1);
Response.Cookies.Add(cookie);
}
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(language);
}
I hope it helps you.
Ran Davidovi...
Member
64 Points
12 Posts
Re: How to do a language switch in a master page.
May 05, 2006 02:52 PM|LINK
Hi,
I would not recommend overriding the global.asax begin_Request event because this is not a encapsulated solution
My advise is to create a base page that will have the logic of language switching (by using the previous solution that joschua wrote) or if you don't like base pages you can use the aggregation solution by creating an utility (static) class.
So changing the language will only require you to call a method on the base page that will handle everything (saving the language needed to the session / cookie, validating, etc).
The final solution will be clean and reusable
Hope this helps (If you need a sample code tell me - although its relatively simple)
Ran Davidovitz http://davidovitz.blogspot.com
http://davidovitz.blogspot.com
Husain
Member
10 Points
2 Posts
Re: How to do a language switch in a master page.
May 06, 2006 09:58 AM|LINK
sebastian.pi...
Member
52 Points
8 Posts
Re: How to do a language switch in a master page.
May 31, 2006 01:15 AM|LINK
Check this basepage i've made, hope it helps .. ctl00$ddlLanguage is a dropdown that the user uses to switch cultures (this can be tweaked a bit).
It should work with pages that use or don't a master page.
If a culture change is detected OnCultureChange event is raised
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Globalization; using System.Threading; public delegate void CultureChanged(object Sender, string CurrentCulture); public class Base: Page { public event CultureChanged OnCultureChanged; public string LastCultureName { get { string lastCultureName = (string)Session["_lastCulture"]; if (lastCultureName == null) Session["_lastCulture"] = Thread.CurrentThread.CurrentCulture.Name; return lastCultureName; } set { Session["_lastCulture"] = value; } } protected override void InitializeCulture() { //TODO: make this prettier string lang = Request["ctl00$ddlLanguage"]; if (lang == null || lang == String.Empty) lang = LastCultureName; Thread.CurrentThread.CurrentCulture = new CultureInfo(lang); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang); } protected override void OnLoadComplete(EventArgs e) { base.OnLoadComplete(e); if (LastCultureName != Thread.CurrentThread.CurrentCulture.Name) { LastCultureName = Thread.CurrentThread.CurrentCulture.Name; if ( this.OnCultureChanged != null) this.OnCultureChanged(this, LastCultureName); } } }Thanksquasa
Member
21 Points
6 Posts
Re: How to do a language switch in a master page.
Jun 28, 2006 08:43 AM|LINK
LastCultureName prop needs following small change, othewise first time "null" gets returned, which throws an exception at the CurrentCulture setting.:
public string LastCultureName
{
get
{
string lastCultureName = (string)Session["_lastCulture"];
if (lastCultureName == null){
Session["_lastCulture"] = Thread.CurrentThread.CurrentCulture.Name;
lastCultureName = Thread.CurrentThread.CurrentCulture.Name;
}
return lastCultureName;
}
set
{
Session["_lastCulture"] = value;
}
}