Problem when I switch language

Last post 07-17-2007 12:39 PM by rstrahl. 6 replies.

Sort Posts:

  • Problem when I switch language

    07-13-2007, 3:06 PM
    • Loading...
    • MSchumacher
    • Joined on 07-13-2007, 7:00 PM
    • Montreal, Quebec, Canada
    • Posts 18

    Hi,

    This is my first post here. If my subject is not in the good forum, please appology and tell me where I should put it. Thanks.


    Im experiencing 2 problems with the language (Globalization - Localization). First, I explain you what I did :

    I use a LinkButton to switch between english (en-CA) and french (fr-CA) (I do that because I dont want that the user have to go in the IE tools to switch the language). I do the change in InitializeCulture() by trapping __EVENTTARGET. If it is my LinkButton who fire the postback, then I switch the language.

    The code goes like this :

       if (Language == English)
       {
          Thread.CurrentThread.CurrentUICulture = new CultureInfo(English);
          Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(English);
       }
       else
       {
          Thread.CurrentThread.CurrentUICulture = new CultureInfo(French);
          Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(French);
       }
       base.InitializeCulture();


    Also, I use App_GlobalResources directory to put my resources files : one generic (ex : test.resx), one for english (ex : test.en-CA.resx and one for french (ex: test.fr-CA.resx).

    Finaly, in the aspx file, I associate the text with the resource file like this :

    <asp:LinkButton  ... Text="<%$ Resources:Global, DeleteLinkButton_Text %>"></asp:LinkButton>


    Now, here are the problems I encounter :

    Problem one :

    - I start the page and it display it in french. That's what I want.
    - I click the LinkButton "English" and all the text switch to englixh; the result is still good.
    - I click the same LinkButton "Français" and then, I have my first mistake. The LinkButton that I use to display "Détruire"/"Delete" does not change to french. It display "Delete" instead of "Détruire". Everything else is good in the page.
    - I click several time and evething is fine, except the DeleteLinkButton that always display "Delete", no matter what language is selected.
    - I click another LinkButton : SearchLinkButton. Before it, it was displaying well, alternating between "Recherche" and "Search". But, after I did it, it get stick on one language, refusing to switch.
    - Also, sometime (Im not sure what made the change), the DeleteLinkButton display "Détruire" again. But after I switch in english, the old problem return.

    Problem two :

    - With the DeleteLinkButton, I use OnClick and the OnClientClick event. With the OnclientClick event, I asked the user to confirm the delete. A cancel return false and a OK return true. The false cancel the OnClick; the page stay on the client with no postback, and this is what I want. With the true, the page do a postback and the OnClick event do the delete. This is also good. But, I like to trap another situation. To do a delete, the user must select the row by checking a CheckBox. If the user select some rows, click Delete and confirm it, everything goes well. Finaly, when the user did no selection before calling the DeleteLinkButton, I warn him after he confirm the delete. Idealy, I like to warn the user before, like "No row has been selected. Please select a row before clicking Delete", but I dont figure how to loop in the gridview on the client side in a javascript.... So I do the warning by a literal control that I fill at the end of the page with an alert() message.

    Now the problems I encounter :

    - The text of the confirm message is in the good language. My problem are with the buttons. They always display "OK" and "Cancel"; they never display in it in french ("OK" and "Annuler"). I tried to put both language in the IE Tools/Internet Options/Languages, but nothing change. I though that the IE page should switch language when I do it in InitializeCulture() Here the code I use :

       if (Language == French)
       {
          DeleteLinkButton.OnClientClick = "return confirm('Confirmez la destruction')";
       }
       else
       {
          DeleteLinkButton.OnClientClick = "return confirm('Confirm Delete')";
       }

    Finaly, I dont know why, the warning message I use to warn the user that no data has been deleted does not always display the same way... Some time, it is display normaly : a popup window in front of the GridView window. But, some time, the popup box display in front of a white page. I did loop many time clicking the delete button follow by a confirmation and the display was not regular. Sometime I have 3 good pages, after 1 blank, after 5 good pages, after 3 blank, etc.

    Well, this is all. I know this is a lot and I dont expect to solve all problem here. But if someone can help me, it will be greatly appreciate :)
    Thanks

    M. Schumacher
  • Re: Problem when I switch language

    07-14-2007, 6:39 AM
    • Loading...
    • Biser
    • Joined on 11-01-2006, 11:24 AM
    • Bulgaria
    • Posts 93

    HI

    I have few question:

    1. Where are you store Selected Language: Session,Cookie, Cache.

    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"

    if (Language == English)
       {
          Thread.CurrentThread.CurrentUICulture = new CultureInfo(English);
          Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(English);
       }
       else
       {
          Thread.CurrentThread.CurrentUICulture = new CultureInfo(French);
          Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(French);
       }

    3. Can you give your Event Handler  fot your LinkButtons to see how you change Language.

     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.

     

    Please remember to click "Mark as Answer" on this post if it helped you.
  • Re: Problem when I switch language

    07-16-2007, 2:18 PM
    Answer
    • Loading...
    • rstrahl
    • Joined on 08-20-2003, 1:08 PM
    • Paia, Hawaii
    • Posts 249
    • TrustedFriends-MVPs

    There are many issues with switching the language in the context of a page and switch to that language and properly display that same page as part of a Postback. Specifically localization is applied at load time of the page, but potentially ViewState or POST data can override those settings. If you make an explicit assignment anywhere on a ViewState holding control ViewState will override any initial values. I suspect something along those lines is happening for you.

    Typically the better approach is to have a separate page that lets the Application change languages. You switch the language and then Redirect to a new page or even the same one, but you force a full reload rather than a PostBack.

    It can be done with PostBack, but you have to be really careful about what gets updated on the page.

    +++ Rick ---

     

    Rick Strahl [MVP]
    West Wind Technologies
    Making waves on the Web
    www.west-wind.com/weblog
  • Re: Problem when I switch language

    07-16-2007, 3:41 PM
    • Loading...
    • MSchumacher
    • Joined on 07-13-2007, 7:00 PM
    • Montreal, Quebec, Canada
    • Posts 18

    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
  • Re: Problem when I switch language

    07-16-2007, 3:51 PM
    • Loading...
    • MSchumacher
    • Joined on 07-13-2007, 7:00 PM
    • Montreal, Quebec, Canada
    • Posts 18

    Hi Rick,

    I dont manipulate the ViewState. For the POST data, im not 100% about what do you mean. By the way, I find your approche very interesting. If there's many issue related to switching language in a postback (that's exactly what Im doing), your solution is interesting, but have some inconveniant. Exemple, I show the LanguageLinkButton in every page. Suppose that the user is in an update page, if I simply redirect to a page who have the job to switch language and then do a postback, I will loose the data that may have been entered before switching language. Anyway, I will test that solution and see the same code, in another page, work then well. If it is the case, I will know this is the good direction to go.

    Thanks

    M. Schumacher
  • Re: Problem when I switch language

    07-17-2007, 8:39 AM
    • Loading...
    • MSchumacher
    • Joined on 07-13-2007, 7:00 PM
    • Montreal, Quebec, Canada
    • Posts 18

    Also, I dont know if its a part of the problem, but the properties  :

       Thread.CurrentThread.CurrentUICulture
       Thread.CurrentThread.CurrentCulture

    does not maintain the switch of language I do. The browser defaults are :

       Thread.CurrentThread.CurrentUICulture = "en-US"
       Thread.CurrentThread.CurrentCulture = "fr-CA"

    I have to reset those value at every load, because if I dont, they will return to those default value. Maybe its normal, but I thought that the change could be for the browser session, and not only for the active page (a postback return to the default value if those properties are not set).

    M. Schumacher
  • Re: Problem when I switch language

    07-17-2007, 12:39 PM
    Answer
    • Loading...
    • rstrahl
    • Joined on 08-20-2003, 1:08 PM
    • Paia, Hawaii
    • Posts 249
    • TrustedFriends-MVPs

    Localization is applied per thread and it's normal that threads always start with the default locale set (ie. whatever your server is set up). If you manually set this you have to do on every hit. If you let ASP.NET do (with Culture="Auto") then ASP.NET does it for you on every hit, but something always needs to set the culture.

     

    +++ Rick ---      

    Rick Strahl [MVP]
    West Wind Technologies
    Making waves on the Web
    www.west-wind.com/weblog
Page 1 of 1 (7 items)
Microsoft Communities
Page view counter