Hi Biser,
Following are the answer to your questions. I minimize the code to what is related to the language. Thanks for your help. Also, remember the strangest aspect
of my bug. The language work normaly for most of the field; only some field does not work properly. I have traced the method that change the language and it
look working perfectly.
1. Where are you store Selected Language: Session,Cookie, Cache.
We store the language in a Session variable.
2. Why you put into CultureInfo English and French are this is a string variable? And not use into CultureInfo("en-CA") and "fr-CA"
Your are right, French and English are variables that have respective value of "en-CA" and "fr-CA".
3. Can you give your Event Handler fot your LinkButtons to see how you change Language.
To make it as clear as possible, I will trace you all the code that is involve and put comment to explain what I do.
4. How you generate your resource files it should lie into App_LocalResources and have resources files for all your pages. In my apps only sitemap resource
file lie into GlobalResource folder.
I do not generate the resource files, I always use GlobalResources. Why? Because I want to have a unique source for my language. I use the files
"Global.resx", "Global.en-CA.resx", "Global.fr-CA.resx" to put all my common stuff (the button name for Add, Delete, Update, Copy, etc.). For the other
aspect of the translation, I use a file by page. For exemple, if I have a page name WebPage1, I will have the following files : "WebPage1.resx",
"WebPage1.en-CA.resx", "WebPage1.fr-CA.resx".
What is weard in my problem is that a part of the page work always well. Everything is related to the specific page (in the exemple "WebPage1") work well. My
problems are, still now, related to my "Global" resource file.
So, as I wrote proviously, here is the complete code that is involve in my problem. I will use the fictive name "WebPage1" to put the code relative to a
webpage of my projetc.
//------------------------
// The webpage who display
//------------------------
WebPage.aspx
<!-- This is the LinkButton who initiate the switch of language -->
<asp:LinkButton ID="LanguageSelection" runat="server" OnClick="LanguageSelection_Click"></asp:LinkButton>
<!-- Those buttons are exemple of what work wrong, particulary the Delete and the search. Their translation are put in the Global resource files, see below
-->
<asp:LinkButton ID="AddLinkButton" runat="server" OnClick="AddLinkButton_Click" Text="<%$ Resources:Global, AddLinkButton_Text %>"></asp:LinkButton>
<asp:LinkButton ID="DeleteLinkButton" runat="server" OnClick="DeleteLinkButton_Click" Text="<%$ Resources:Global, DeleteLinkButton_Text %>"></asp:LinkButton>
<asp:LinkButton ID="searchButton" runat="server" OnClick="searchButton_Click" Text="<%$ Resources:Global, searchButton_Text %>"></asp:LinkButton>
<!-- Here some GridView fields. Their header work perfectly. Their translations are store in the WebPage1 resource files, see below -->
<asp:BoundField DataField="Name" HeaderText="<%$ Resources:WebPage1, Name_Text %>" />
<asp:BoundField DataField="Address" HeaderText="<%$ Resources:WebPage1, Address_Text %>" />
<asp:BoundField DataField="City" HeaderText="<%$ Resources:WebPage1, City_Text %>" />
<asp:BoundField DataField="Postalcode" HeaderText="<%$ Resources:WebPage1, Postalcode_Text %>" />
//----------------------------
// The code behind of the page
//----------------------------
WebPage.aspx.cs
//The includes
using System;
using System.Data;
using System.Configuration;
using System.Collections;
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.Threading;
using System.Globalization;
using MyNamespace;
using System.Collections.Generic;
// I do not switch the language directly in the page.
// Because we will have many pages, I decided to put it in a class (MyNamespace.Page.cs).
// I use this class for everything that is general in our application for a page.
// I call the page by passing the page by reference, so it's like working in my page.
// So, what you see here is the passage of the page, calling MyNamespace.Page.InitializeCulture method.
protected override void InitializeCulture()
{
System.Web.UI.Page thispg = this;
MyNamespace.Page MyNamespacepg = new MyNamespace.Page();
MyNamespacepg.InitializeCulture(ref thispg);
}
// I do the same for the general aspect of the method Page_Load().
// I only pass another parameter, the type of page; but this parameter is not involve in the language solution.
protected void Page_Load(object sender, EventArgs e)
{
System.Web.UI.Page thispg = this;
MyNamespace.Page MyNamespacepg = new MyNamespace.Page();
MyNamespace.Page.FormTypes ft = MyNamespace.Page.FormTypes.Browser;
MyNamespacepg.Page_Load(ref thispg, ft);
}
//-----------------------------------------
// Here is the code of the class MyNamespace.Page.
//-----------------------------------------
Page.cs
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.Threading;
using System.Globalization;
namespace MyNamespace
{
public class Page : System.Web.UI.Page
{
// This method is the one who perform the switch of language.
// I trace this method and it work without problem... except the result.
public void InitializeCulture(ref System.Web.UI.Page pg)
{
// I use Session variable "Language" to store the language.
// MyNamespace.Application.Language is the property we use to work with it.
MyNamespace.Application.Language = System.Convert.ToString(HttpContext.Current.Session["Language"]);
if (MyNamespace.Application.Language == null | MyNamespace.Application.Language == "")
{
// Our default value is french.
MyNamespace.Application.Language = MyNamespace.Application.French;
}
else
{
// Because InitializeCulture is called before PageLoad and object are initialized, I need a way to know if I have to switch language or not.
// I choose to use "__EVENTTARGET" because it contain the name of the button who fire the postback.
// So, I only test if its the "LanguageSelection" button who fire the postback and it its true, then I switch the language.
if (pg.Request["__EVENTTARGET"] == "LanguageSelection")
{
// Because we only switch between two languages, I only have to know what is the current language and I switch for the other.
if (MyNamespace.Application.Language == MyNamespace.Application.French)
{
MyNamespace.Application.Language = MyNamespace.Application.English;
}
else
{
MyNamespace.Application.Language = MyNamespace.Application.French;
}
}
}
Thread.CurrentThread.CurrentUICulture = new CultureInfo(MyNamespace.Application.Language);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(MyNamespace.Application.Language);
base.InitializeCulture();
}
public void Page_Load(ref System.Web.UI.Page pg, FormTypes ft)
{
// This method set MyNamespace.Application.Language to the Session variable "Language".
// After, I simply use the value to set the texte of the LinkButton who is use to switch between language.
MyNamespace.Application.Initialize();
LinkButton LanguageSelection = (LinkButton)pg.FindControl("LanguageSelection");
if (MyNamespace.Application.Language == MyNamespace.Application.French)
{
LanguageSelection.Text = "English";
}
else
{
LanguageSelection.Text = "Français";
}
}
}
}
//------------------------------------------------------------------------------
// The class Application is use to set properties specific to the currente page.
//------------------------------------------------------------------------------
Application.cs
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.Collections.Generic;
using MyNamespace;
namespace MyNamespace
{
public static class Application
{
// This is the property to manage the language. Note that everytime I set the language, the Session variable "Language" is also affected.
private static string _language;
public static string Language
{
get
{
return _language;
}
set
{
_language = value;
HttpContext.Current.Session["Language"] = _language;
}
}
// As you can see, French and English are properties set to "fr-CA" and "en-CA".
private static String _french = "fr-CA";
public static String French
{
get { return _french; }
}
private static String _english = "en-CA";
public static String English
{
get { return _english; }
}
// This method is use to set many properties of the current application. You only see the one involve in the language aspect.
public static void Initialize()
{
_language = System.Convert.ToString(HttpContext.Current.Session["Language"]);
}
}
}
//------------------------------------------------------------------------------
// This is the code of the Global resource file
//------------------------------------------------------------------------------
Global.resx
<root>
<data name="AddLinkButton_Text" xml:space="preserve">
<value> Ajouter |</value>
</data>
<data name="DeleteLinkButton_Text" xml:space="preserve">
<value> Détruire |</value>
</data>
<data name="searchButton_Text" xml:space="preserve">
<value> Recherche |</value>
</data>
</root>
Global.fr-CA.resx
<root>
<data name="AddLinkButton_Text" xml:space="preserve">
<value> Ajouter |</value>
</data>
<data name="DeleteLinkButton_Text" xml:space="preserve">
<value> Détruire |</value>
</data>
<data name="searchButton_Text" xml:space="preserve">
<value> Recherche |</value>
</data>
</root>
Global.en-CA.resx
<root>
<data name="AddLinkButton_Text" xml:space="preserve">
<value> Add |</value>
</data>
<data name="DeleteLinkButton_Text" xml:space="preserve">
<value> Delete |</value>
</data>
<data name="searchButton_Text" xml:space="preserve">
<value> Search |</value>
</data>
</root>
//------------------------------------------------------------------------------
// Here are the part of the resource files of my exemple.
//------------------------------------------------------------------------------
WebPage1.resx
<root>
<data name="Address_Text" xml:space="preserve">
<value>Adresse</value>
</data>
<data name="City_Text" xml:space="preserve">
<value>Ville</value>
</data>
<data name="Name_Text" xml:space="preserve">
<value>Nom</value>
</data>
<data name="Postalcode_Text" xml:space="preserve">
<value>Code postal</value>
</data>
</root>
WebPage1.fr-CA.resx
<root>
<data name="Address_Text" xml:space="preserve">
<value>Adresse</value>
</data>
<data name="City_Text" xml:space="preserve">
<value>Ville</value>
</data>
<data name="Name_Text" xml:space="preserve">
<value>Nom</value>
</data>
<data name="Postalcode_Text" xml:space="preserve">
<value>Code postal</value>
</data>
</root>
WebPage1.en-CA.resx
<root>
<data name="Address_Text" xml:space="preserve">
<value>Address</value>
</data>
<data name="City_Text" xml:space="preserve">
<value>City</value>
</data>
<data name="Name_Text" xml:space="preserve">
<value>Name</value>
</data>
<data name="Postalcode_Text" xml:space="preserve">
<value>Postal Code</value>
</data>
</root>
M. Schumacher