Setting and Recognizing the Culture


Users need a means of specifying what culture they would like the application to use. You can provide support for this in several ways. You could detect the user's culture from the browser; you could provide an option to set the culture in your application; or you could provide a combination of both, in which you detect the initial setting from the browser and let the user change the setting in the application. Over the next few sections, we look at different options for allowing users to set the culture and recognizing the culture that they have set.

Setting the Culture in Internet Explorer

In this section, we look at allowing the user to specify the culture in Internet Explorer.

A small switch of terminology occurs here because what the .NET Framework refers to as a culture, HTTP refers to as a language.


The user's language preference is set in the HTTP_ACCEPT_LANGUAGES request header. This value is reflected in the Request.UserLanguages property, which is an array of strings. The HTTP request header doesn't make a distinction between a language used for globalization and a language used for retrieving resources for the user interface, so its single setting is typically used for both purposes. A user sets the language preference in Internet Explorer by selecting Tools, Internet Options... and clicking on the Languages... button (see Figure 5.3).

Figure 5.3. Setting the Culture in Internet Explorer


The user can set any number of language settings here. The implication is that the first language (i.e., the language at the top of the list) is the most preferred language, and subsequent languages are acceptable, but each is less preferable.

Recognizing the User Culture

The next step is to recognize and use the user's language setting. Several ways exist for achieving this, and we examine each. The first and simplest is to set the culture in the page's Load event:

 private void Page_Load(object sender, System.EventArgs e) {     if (Request.UserLanguages != null &&         Request.UserLanguages.GetLength(0) > 0)     {         CultureInfo cultureInfo =             new CultureInfo(Request.UserLanguages[0]);         Thread.CurrentThread.CurrentUICulture = cultureInfo;         Thread.CurrentThread.CurrentCulture =             CultureInfo.CreateSpecificCulture(cultureInfo.Name);     }     etc. etc. 


This code gets the user's language preference from the first element of the Request.UserLanguages array. If the user's settings are those shown in Figure 5.3, Request.UserLanguages[0] will be "en-US". We create a new CultureInfo object and assign it to CurrentUICulture. The next line uses CultureInfo.CreateSpecificCulture to create a specific culture from a potentially neutral culture. In this example the culture will be no different (i.e., it will be "en-US"), but if the original language preference was "en", the specific culture would be "en-US". Recall that this step is necessary because CurrentCulture must be culture-specific. Later in this chapter, we implement a more sophisticated version of this first attempt that iterates through each of the language preferences looking for a language that matches the application's supported languages.

Of course, the implementation given here is very trusting. It makes the assumption that the language chosen by the user is one that the .NET Framework recognizes. Users are free to enter a language that is not supported by the .NET Framework (e.g., Bengali is not supported by the .NET Framework 1.1), or users can enter a custom language that they type in (e.g., "xx"). In these circumstances, the CultureInfo constructor will throw an exception and the application will stop. A sensible enhancement to the previous code, therefore, is to trap exceptions:

 private void Page_Load(object sender, System.EventArgs e) {     if (Request.UserLanguages != null &&         Request.UserLanguages.GetLength(0) > 0)     {         try         {             CultureInfo cultureInfo =                 new CultureInfo(Request.UserLanguages[0]);             Thread.CurrentThread.CurrentUICulture = cultureInfo;             Thread.CurrentThread.CurrentCulture =                 CultureInfo.CreateSpecificCulture(cultureInfo.Name);         }         catch (ArgumentException)         {         }     }     etc. etc. 


This solution works fine for the example that we have been working with, but it suffers from two problems. First, the solution is a page-wide solution and not an application-wide solution. Second, the solution occurs a little too late in the request pipeline for some code. The first problem could be solved easily by putting the code in a page base class and ensuring that all pages inherit from the page base class; this is not a difficult problem to solve. But the second problem requires moving the code out of the page class altogether. The HttpApplication.BeginRequest method is the first application method to be called in the ASP.NET pipeline, and setting the culture here ensures that all subsequent code uses the correct culture. Open Global.asax.cs and add the following code. (If you don't have a Global Application Class, then in Solution Explorer, right-click the project; select Add, Add New Item...; select Global Application Class; and click Open):

 protected void Application_BeginRequest(Object sender, EventArgs e) {     SetCultureFromUserLanguage(); } private void SetCultureFromUserLanguage() {     if (Request.UserLanguages != null &&         Request.UserLanguages.GetLength(0) > 0)     {         try         {             CultureInfo cultureInfo =                 new CultureInfo(Request.UserLanguages[0]);             Thread.CurrentThread.CurrentUICulture = cultureInfo;             Thread.CurrentThread.CurrentCulture =                 CultureInfo.CreateSpecificCulture(cultureInfo.Name);         }         catch (ArgumentException)         {         }     } } 


Unfortunately, this solution is not without its own problems. The BeginRequest method occurs too early in the pipeline for the Session variable to be available. This means that if you allow users to set their own preferences independently of the browser's language preference and you store their preference in the Session variable, the BeginRequest method occurs too early to make use of the setting. A compromise is to use the HttpApplication.AcquireRequestState event, which occurs after the Session variable has been initialized but before the Page.Load event. Assuming that you have a page that sets Session["Culture"] to a culture string, change the Global HttpApplication constructor to this:

 public Global() {     InitializeComponent();     AcquireRequestState +=         new EventHandler(Global_AcquireRequestState); } 


Now add the Global_AcquireRequestState method:

 private void Global_AcquireRequestState(object sender, EventArgs e) {     if (Session["Culture"] != null)     {         Thread.CurrentThread.CurrentCulture =             new CultureInfo(Session["Culture"].ToString());         Thread.CurrentThread.CurrentUICulture =             Thread.CurrentThread.CurrentCulture;     }     else         SetCultureFromUserLanguage(); } 


This solution has the following benefits:

  • It can be applied to all requests in the application.

  • It occurs earlier in the pipeline than Page.Load.

  • It respects the user's preference if any has been set in the Session variable.

  • It defaults the culture to the user's browser setting if there is no preference in the Session variable.

Setting the Culture in Configuration Files

You can, of course, ignore the user's language preference altogether and hard-code the culture. Both machine.config (which applies to all Web sites on the machine) and web.config (which applies to a single Web site) have a globalization element that allows the Culture and UICulture to be specified. The following globalization element sets the CurrentCulture to French (France) and CurrentUI Culture to French:

 <globalization culture="fr-FR" uiCulture="fr"/> 


This setting initializes the culture for the Web site but does not prevent it from being changed subsequently. You might want to use this setting to provide a default for users who do not have a language preference set in their browser. This is preferable to relying on the default values of CurrentCulture and CurrentUICulture because these values are set in the operating system under the user account under which ASP.NET is running and apply to all Web sites that run under the same user account. As such, you might not have control over these settings. In this scenario, you would set the default culture in web.config and attempt to get the user's language preference in either the Page or HttpApplication class.




.NET Internationalization(c) The Developer's Guide to Building Global Windows and Web Applications
.NET Internationalization: The Developers Guide to Building Global Windows and Web Applications
ISBN: 0321341384
EAN: 2147483647
Year: 2006
Pages: 213

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