Recipe 14.2 Providing Multiple Language Support

     

14.2.1 Problem

You want to support multiple languages in your application without developing multiple versions of each page.

14.2.2 Solution

Use resource files to provide the text for each user interface element in the languages you wish to support, and then set the text to use at runtime based on the language setting in the browser.

You don't need to make any changes to the .aspx files of your application for them to output text in multiple languages.

In the code-behind class for each page that needs to support multiple languages, use the .NET language of your choice to:

  1. Determine the user's preferred language from the collection of acceptable languages returned with the page request.

  2. Create a CultureInfo object from the user's language.

  3. Set the CurrentCulture and the CurrentUICulture to the user's culture object (for controlling the formatting of dates and numbers and locating the appropriate resource file for the selected culture, respectively).

  4. Create a ResourceManager object that will be used to obtain the strings to be displayed in the user's language.

  5. Set the text for the individual controls using the GetString method of the ResourceManager .

  6. Set the values of the language, current date, and sample currency.

Example 14-1 through Example 14-3 show the .aspx file and VB and C# code-behind files for an application we've written to demonstrate this solution. The output is shown in Figure 14-1 (English) and Figure 14-2 (German).

Figure 14-1. Multiple language output ”English
figs/ancb_1401.gif

Figure 14-2. Multiple language support ”German
figs/ancb_1402.gif

14.2.3 Discussion

ASP.NET provides extensive support for internationalizing applications. With just a few lines of code and the appropriate resource files, an application can display text in the language set in the browser and can format dates, times, and currency as the user would expect to see them.

In the example we have provided to demonstrate multiple language support, the code determines the user's preferred language when the page is requested . Using the preferred language, a welcome message, the language setting, the current date, and a currency sample are displayed.

The .aspx file in our example contains nothing specific to support outputting text in multiple languages. Several ASP literal controls are used to display the information in the user's preferred language.

The Page_Load method in the code-behind provides all of the code required to display the form data in the user's preferred language. Our first step is to get the user's preferred language from the collection of acceptable languages returned with the page request. The language collection can contain zero or more languages, so we must make sure there is at least one language in the collection. Because the language collection usually lists the languages in the order preferred by the user, selecting the first language in the list is generally acceptable.

In a production application, you may want to verify that your application supports the first language in the collection, and if it does not, continue through the collection looking for a supported language.


Your next step is to create a CultureInfo object whose culture value is set to the user's language. You'll use this information to set the CurrentCulture and CurrentUICulture properties of the CurrentThread . CurrentCulture cannot be set to a neutral culture value (one without the subculture specified), so the CreateSpecificCulture method is used to add the subculture information as required. This is necessary because Internet Explorer and other browsers allow the user to select a language, such as German, without specifying the specific country or locale in which the user resides.

Now we set the CurrentCulture and the CurrentUICulture to the user's culture object. The CurrentCulture is used to format dates and numbers, while the CurrentUICulture is used by the resource manager to locate the appropriate resource file for the selected culture.

Next, you must create a ResourceManager object to gather the strings to be displayed in the user's language. The constructor for the ResourceManager requires you to pass it the root name of the resource files for the application (resource file naming is described later) and a reference to the main assembly for the resources. The root name must be fully qualified with the default namespace name you use for the project. In our example, the default namespace in the project properties has been left blank so only the root name of the resource file "Strings" is used. In this example, the root resource file is compiled into the main assembly, so a reference to the currently executing assembly can be obtained using the GetExecutingAssembly method.

Now that you have set the current culture and UI culture and a ResourceManager is available, you can set the text for the individual controls using the GetString method of the ResourceManager . The values you pass to the GetString method are the keys you use identify the desired text strings in the resource files.

The last thing to do is to set the values of the language, current date, and sample currency. These are done in exactly the same manner as a single-language application.

The ResourceManager handles all of the dirty work of finding the resource file for the user's language, as well as defaulting to the root resource file if a language is requested that is not supported by your application. It is able to find the appropriate resource file because of a very strict naming convention used for the files.

The root resource file can be named most anything, but it is best to keep it simple and avoid using names that include additional periods and dashes. In our example, the root filename is Strings .

The names for additional language files must include the root name combined with the culture and subculture information in the format shown next, where Rootname is the root filename, <languagecode> defines the two-letter language code derived from ISO-639-1, and <country/regioncode> defines the two-letter country or region code from ISO-3166. The languagecode should be in lowercase and the country/regioncode in uppercase.

   Rootname.<languagecode>-<country/regioncode>   

For instance, the resource file containing text in German for our example is named Strings.de-DE , where de indicates the German language and DE designates the German localization of the language (as opposed to Austrian, Swiss, and others).

To find the required resource file, the resource manager uses the root name of the resource file then appends the UI Culture name to create the name of the resource file applicable to the user's language. The resource manager then attempts to locate the resource file using a fairly complex set of rules. For our example, let's keep it simple and just say that if the specific resource file is not found on a first attempt, then the root resource file will be used instead. (Refer to "Packaging and Deploying Resources" in the MSDN documentation for the full set of rules defining where the .NET runtime looks for resource files.)

Resource files can be created in many different ways. If you are using Visual Studio .NET, you can simply add a new "Assembly Resource File" to your project. Visual Studio will create an empty XML file ( .resx ) to contain your resources. You can double-click on the file in your project and start typing the names of the keys and the values (text to display). Visual Studio will take care of the creation and placement of the compiled resource files in the bin directory. The English (root) resource file for our example is shown here, with the in-line schema deleted for clarity:

 <?xml version="1.0" encoding="utf-8"?> <root>    ...  <data name="txtWelcome">   <value>Welcome to Localization</value>   </data>   <data name="txtLanguageSetting">   <value>Language Setting</value>   </data>   <data name="txtCurrencySample">   <value>Currency Sample</value>   </data>   <data name="txtDateSample" mimetype=" ">   <value>Date Sample</value>   </data>  </root> 

If you are not using Visual Studio, you can create text files containing the names of the keys and the required values. The root text file and the German text file for our example are shown here:


English (root)
 txtLanguageSetting=Language Setting txtWelcome=Welcome to Localization txtDateSample=Date Sample txtCurrencySample=Currency Sample 


German
 txtLanguageSetting=SprachencEinstellung txtWelcome=Willkommen zur Lokalisation txtDate=Datum-Probe txtCurrencySample=Whrung-Probe 

After creating text resource files, you need to compile them into .NET resource files by entering the following in a command prompt:


English (root)
 resgen Strings.txt 


German
 resgen Strings.de-DE.txt 

The resulting Strings.resources and Strings.de-DE.resources files must be copied to the bin directory of our application.

Testing your application for the supported languages can be performed by changing the preferred language in Internet Explorer. You can change the language by selecting Tools Internet Options from the IE menu. Next, click the Languages button and the Language Preference dialog box will be displayed, as shown in Figure 14-3. Add the languages you need to test your application. To test a specific language, move it to the top of the list of languages.

Figure 14-3. Setting language preference in IE
figs/ancb_1403.gif

Using resource files in an international application provides a very cost-effective method of implementing the needed support for multiple languages. One thing to keep in mind when designing your application is the performance impact caused by "looking up" every string at runtime. This will result in longer rendering times for the pages. Your international application may require a more powerful web server than you would generally specify for a domestic application.


14.2.4 See Also

"Packaging and Deploying Resources" in the MSDN documentation for the full set of rules defining where the .NET runtime looks for resource files

Example 14-1. Multiple language support (.aspx)
 <%@ Page Language="vb" AutoEventWireup="false"           Codebehind="CH14InternationalCultureVB.aspx.vb"           Inherits="ASPNetCookbook.VBExamples.CH14InternationalCultureVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>   <head>     <title>Internationalization - Culture and UI Culture</title>     <link rel="stylesheet" href="css/ASPNetCookbook.css">   </head>   <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">     <form id="frmInternationalization" method="post" runat="server">       <table width="100%" cellpadding="0" cellspacing="0" border="0">         <tr>           <td align="center">             <img src="images/ASPNETCookbookHeading_blue.gif">           </td>         </tr>         <tr>           <td class="dividerLine">             <img src="images/spacer.gif" height="6" border="0"></td>         </tr>       </table>       <table width="90%" align="center" border="0">         <tr>           <td align="center">&nbsp;</td>         </tr>         <tr>           <td align="center" class="PageHeading">             Internationalization - Culture and UI Culture (VB)           </td>         </tr>         <tr>           <td><img src="images/spacer.gif" height="10" border="0"></td>         </tr>         <tr>           <td>             <table width="60%" align="center" border="0">               <tr>                 <td align="center" colspan="2">  <asp:Literal id="litWelcome" Runat="server" />  </td>               </tr>               <tr>                 <td align="right" width="50%">  <asp:Literal id="litLanguageSettingLabel" Runat="server" />  :&nbsp;                 </td>                 <td width="50%">  <asp:Literal id="litLanguageSetting" Runat="server" />  </td>               </tr>               <tr>                 <td align="right" width="50%">  <asp:Literal id="litDateLabel" Runat="server" />:&nbsp;  </td>                 <td width="50%">  <asp:Literal id="litDate" Runat="server" />  </td>               </tr>               <tr>                 <td align="right" width="50%">  <asp:Literal id="litCostLabel" Runat="server" />:&nbsp;  </td>                 <td width="50%">  <asp:Literal id="litCost" Runat="server" />  </td>               </tr>             </table>           </td>         </tr>       </table>     </form>   </body> </html> 

Example 14-2. Multiple language support code-behind (.vb)
 Option Explicit On  Option Strict On '----------------------------------------------------------------------------- ' '   Module Name: CH14InternationalCultureVB.aspx.vb ' '   Description: This module provides the code behind for the  '                CH14InternationalCultureVB.aspx page ' '***************************************************************************** Imports System.Resources Imports System.Globalization Imports System.Reflection Imports System.Threading Namespace ASPNetCookbook.VBExamples   Public Class CH14InternationalCultureVB     Inherits System.Web.UI.Page     'controls on the form     Protected litWelcome As System.Web.UI.WebControls.Literal     Protected litLanguageSettingLabel As System.Web.UI.WebControls.Literal     Protected litLanguageSetting As System.Web.UI.WebControls.Literal     Protected litCostLabel As System.Web.UI.WebControls.Literal     Protected litCost As System.Web.UI.WebControls.Literal     Protected litDateLabel As System.Web.UI.WebControls.Literal     Protected litDate As System.Web.UI.WebControls.Literal     '*************************************************************************     '     '   ROUTINE: Page_Load     '     '   DESCRIPTION: This routine provides the event handler for the page load     '                event.  It is responsible for initializing the controls      '                on the page.     '-------------------------------------------------------------------------  Private Sub Page_Load(ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles MyBase.Load   Const sampleValue As Single = 12345.67   Dim locRM As ResourceManager   Dim userLanguage As String   Dim culture As CultureInfo   'make sure at least one language is set in the browser   If (Request.UserLanguages.Length > 0) Then   'select the first language in browser's accept language list   userLanguage = Request.UserLanguages(0)   'create a culture object from the user's language by using the   'CreateSpecificCulture method to ensure subculture information   'is included.  Culture cannot be set to a neutral culture.   culture = CultureInfo.CreateSpecificCulture(userLanguage)   'set the culture and UICulture   Thread.CurrentThread.CurrentCulture = culture   Thread.CurrentThread.CurrentUICulture = culture   End If   'create a new resource manager from the currently executing assembly   locRM = New ResourceManager("Strings", _   System.Reflection.Assembly.GetExecutingAssembly())   'set the labels on the form with the strings obtained through the   'resource manager from the applicable resource file   litWelcome.Text = locRM.GetString("txtWelcome")   litLanguageSettingLabel.Text = locRM.GetString("txtLanguageSetting")   litDateLabel.Text = locRM.GetString("txtDateSample")   litCostLabel.Text = locRM.GetString("txtCurrencySample")   'set the control displaying the browser culture setting   litLanguageSetting.Text = userLanguage   'set the sample date to the current date   litDate.Text = Date.Now.ToShortDateString()   'set the sample currency value   litCost.Text = sampleValue.ToString("C")   End Sub  'Page_Load  End Class  'CH14InternationalCultureVB End Namespace 

Example 14-3. Multiple language support code-behind (.cs)
 //---------------------------------------------------------------------------- // //   Module Name: CH14InternationalCultureCS.aspx.cs // //   Description: This module provides the code behind for the  //                CH14InternationalCultureCS.aspx page // //**************************************************************************** using System; using System.Resources; using System.Globalization; using System.Reflection; using System.Threading; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples {   public class CH14InternationalCultureCS : System.Web.UI.Page   {     protected System.Web.UI.WebControls.Literal litWelcome;     protected System.Web.UI.WebControls.Literal litLanguageSettingLabel;     protected System.Web.UI.WebControls.Literal litLanguageSetting;     protected System.Web.UI.WebControls.Literal litCostLabel;     protected System.Web.UI.WebControls.Literal litCost;     protected System.Web.UI.WebControls.Literal litDateLabel;     protected System.Web.UI.WebControls.Literal litDate;     //************************************************************************     //     //   ROUTINE: Page_Load     //     //   DESCRIPTION: This routine provides the event handler for the page      //                load event.  It is responsible for initializing the      //                controls on the page.     //------------------------------------------------------------------------  private void Page_Load(object sender, System.EventArgs e)   {   const double sampleValue = 12345.67;   ResourceManager locRM =null;   String userLanguage = null;   CultureInfo culture = null;   // make sure at least one language is set in the browser   if (Request.UserLanguages.Length > 0)   {   // select the first language in browser's accept language list   userLanguage = Request.UserLanguages[0];   // create a culture object from the user's language by using the   // CreateSpecificCulture method to ensure subculture information   // is included.  Culture cannot be set to a neutral culture.   culture = CultureInfo.CreateSpecificCulture(userLanguage);   // set the culture and UICulture   Thread.CurrentThread.CurrentCulture = culture;   Thread.CurrentThread.CurrentUICulture = culture;   }  // if (Request.UserLanguages.Length > 0)   // create a new resource manager from the currently executing assembly   locRM = new ResourceManager("Strings",   System.Reflection.Assembly.GetExecutingAssembly());     // set the labels on the form with the strings obtained through the   // resource manager from the applicable resource file   litWelcome.Text = locRM.GetString("txtWelcome");   litLanguageSettingLabel.Text = locRM.GetString("txtLanguageSetting");   litDateLabel.Text = locRM.GetString("txtDateSample");   litCostLabel.Text = locRM.GetString("txtCurrencySample");   // set the control displaying the browser culture setting   litLanguageSetting.Text = userLanguage;   // set the sample date to the current date   litDate.Text = DateTime.Now.ToShortDateString();   // set the sample currency value   litCost.Text = sampleValue.ToString("C");   }  // Page_Load  }  // CH14InternationalCultureCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2006
Pages: 179

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net