Localization of Webform applications in multiple languages

Usually, web applications should be available in multiple languages other than English. In this blogpost, I am going to walk over creating a sample application that will be localized in French and Dutch. Usually, the preferred language is picked from the user’s browser settings. To make it a little tougher, we will allow the user to switch languages at runtime. To enable runtime switching of languages, we will add three link buttons in the master page.

<asp:LinkButton ID="btnEn" runat="server" Text="en" 
    CommandArgument="en" OnCommand="SetCulture"></asp:LinkButton> | 
<asp:LinkButton ID="btnFr" runat="server" Text="fr" 
    CommandArgument="fr" OnCommand="SetCulture"></asp:LinkButton> | 
<asp:LinkButton ID="btnNl" runat="server" Text="nl" 
    CommandArgument="nl" OnCommand="SetCulture"></asp:LinkButton>

Localization allows text for the page controls to be displayed in multiple languages. The text for the controls comes from a resource file. ASP.NET provides multiple ways of doing localization: implicit and explicit.

In the sample application, there are two pages – Default.aspx and About.aspx. In Default.aspx, we will do implicit localization. In About.aspx, we will do explicit localization.

Implicit Localization

Implicit localization involves creating resource files for each page and each language in the App_LocalResources folder. It is called implicit because the name of the resource file  is based on conventions. The resource file has the convention of <FileName>.aspx.<language>.resx. The default resource file for the home page is default.aspx.resx. The resource file for french language is default.aspx.fr.resx. For each supported language, resource files are created.

In Default.aspx, we enable implicit localization. We allow the text within a label with ID lblImplicit to come from resource files. The label has a meta:resourcekey attribute attached to it:

<asp:Label ID="lblImplicit" runat="server" 
    meta:resourcekey="lblImplicit" Text="Implicit Localization">
    
</asp:Label>

Within the resource file, use the convention <ResourceKey>.<Property> to define the text for the label. The french resource file looks like:

ImplicitLocalization

Explicit Localization

Explicit Localization allows multiple resource  files to be created under App_GlobalResources folder. In explicit localization, resource files are not organized by page names. So, the resource files can have any name. Usually resource files defined by Explicit Localization are characterized by module or sub-system names.

We can set explicit localization for About.aspx. The default resource file is Messages.resx. In the About page, the label uses the text from Message1 from the Messages resource file as follows:

<asp:Label ID="lblExplicit" runat="server" 
    Text="<%$ Resources: Messages, Message1 %>">
    
</asp:Label>

The Resource file name for French language is Messages.fr.resx. The Resource file name for Dutch is Messages.nl.resx. The dutch resource file looks like:

ExplicitLocalization

Now, we are ready to write some code to make all of this work. When we are clicking the link button in the master page, the SetCulture event handler is called. All we do in the below code is set the Session[“Culture”] variable to the selected language. Also, the page is redirected to. This will ensure that the selected culture will set in the reload.

protected void SetCulture(object sender, CommandEventArgs e)
{
    Session["Culture"] = e.CommandArgument.ToString();
    Response.Redirect(Request.RawUrl);
}

Every page has a method – InitializeCulture(). This method is triggered in the Page lifecycle ahead of all events including Page_PreInit(). This is one reason that the page is reloaded again. In InitializeCulture(), we pick the language setting from the Session variable. Then, we set the UICulture for the current thread. This will ensure that the right resource files are picked for the current request.

protected override void InitializeCulture()
{
    // When the user comes to the page for the first time
    if (Session["Culture"] == null)
    {
        Session["Culture"] = "en";
        Session["OldCulture"] = "en";
    }

    // Set the UI Culture here
    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo((string)Session["Culture"]);
    UICulture = (string)Session["Culture"];
    base.InitializeCulture();
}

Finally, there is some code to enable / disable the link buttons in the Page_load of the master page:

protected void Page_Load(object sender, EventArgs e)
{
          
    string culture = (string)Session["Culture"];
    string oldCulture = (string)Session["OldCulture"];

    // Disable the button in current culture
    // This is required if user goes to some other page
    // Page is populated with controls.
    LinkButton newBtn = FindControl("btn" + culture) as LinkButton;
    if (newBtn != null)
        newBtn.Enabled = false;

    // if old culture is different
    // This happens when the user clicks on any of the link buttons
    if (culture != oldCulture)
    {
        // enable the old button and reset oldculture  
        LinkButton oldBtn = FindControl("btn" + oldCulture) as LinkButton;
        if (oldBtn != null)
            oldBtn.Enabled = true;
        Session["OldCulture"] = culture;
    }
}

I have used a base class for all pages – CultureDemo.MainPage. This class overrides the InitializeCulture method. All pages in the CultureDemo application derive from CultureDemo.MainPage instead of System.Web.UI.Page. This ensures that all page and all requests have the right language setting. The complete application is available in the zip file: CultureDemo

Related Posts

Leave a Reply

Your email address will not be published.