Friday, August 31, 2007

C# Programming(Globalizing Your ASP.NET Applications)

Taking Advantage of the System.Globalization Namespace

This is the first article of a two-part series on the globalization and localization features that are implemented in the Microsoft .NET Framework and available for ASP.NET developers. In this first part, I will look at the globalization features implemented in the System.Globalization namespace through different classes and enumerations. I also will create several example programs that show how to use these features in ASP.NET.

The second part of this article will deal with localization. I will explore how cultural information corresponds to language selections and how to create resource-based ASP.NET applications. I will create several examples to show you how to use the ResourceManager class to manage resources stored in resources files and how to use satellite assemblies.

Overview

Before I jump into the details, let me define some terms. Globalization is the process of developing a Web application core whose features and code design aren't based on a single language or locale and whose source-code base makes it easier to create editions of the application in different languages. Localization is the process of adapting a Web application so it is appropriate for the area, or locale, for which it is used. In an international market, this means translating the user interface and the content, customizing features (if necessary), and testing the results to ensure the site or program still functions correctly. A localizable application is an application that is ready for translation - all the strings and images are separated from the code.

A good localization and globalization solution is an essential part of any multilingual project, and it should be considered during the early stages of the project design. There may be different approaches to technical implementation. For example, I could create a fixed set of Web pages for different languages and store them in separate directories, or I could use online translation software. I also could use in-memory dictionaries (e.g., the Dictionary object that is part of the Microsoft Scripting Engine, the Lookup Table object, or the MessageManager object that is part of the Microsoft Commerce Server 2000) that will be accessed on a per-term basis.

Another option is to use the XML-based dictionaries. They serve the same purpose but are more flexible in terms of multilingual support. As for globalization, I can use some limited support available in the ASP object model and create COM objects. That would provide the access to National Language Support functionality of the Microsoft Windows platform and its API.

.NET Platform Features

To simplify development of multilingual applications, the .NET platform uses the concepts of culture and region. These concepts, supported by appropriate classes, define the information that contains cultural conventions and regional settings. This information is very useful for the globalization of Web applications.

To help Web developers localize their applications, the .NET platform extends the concept of resources to Web applications. Resources in .NET can be stored in files with the resources extension or in satellite assemblies and can be managed through the new ResourceManager class. Resources can be used with normal Windows applications as well as in Web applications. Using Visual Studio .NET allows developers to create all the files required for localization. By simply attaching XML-based resources (resx files) to my project, I easily can create applications that support different languages and provide a fallback for the neutral resource (default language), if the resource for a particular language cannot be found.

Globalization

The globalization features available in the .NET Framework are implemented in the System.Globalization namespace through different classes and enumerations.

The two main classes for globalization in this namespace are CultureInfo and RegionInfo. The CultureInfo class contains country-specific cultural information, such as language, calendar, sorting, and so on. Note that culture is the client-defined "value." You specify it as the locale when you install your operating system. The RegionInfo class contains region-specific information, such as region name, currency symbol, metric-system indicator, and other information. FIGURE 1 shows the members of the System.Globalization namespace.


FIGURE 1: The System.Globalization namespace members.

System.Globalization classes include Calendar, which represents time in divisions such as weeks, months, and years. There are different calendars for different cultures: GregorianCalendar, HebrewCalendar, HijriCalendar, JapaneseCalendar, JulianCalendar, KoreanCalendar, TaiwanCalendar, and ThaiBuddhistCalendar. The DateTimeFormatInfo class defines how the selected culture affects the values of the DateTime structure, NumberFormatInfo defines how the selected culture affects numeric values, StringInfo is used to iterate string values, and TextInfo defines code pages and other functions to work with text.

Language Negotiation

Language negotiation occurs when the user sets his or her preferred language, in order of preference, in the browser. Then, the browser negotiates with the server to attempt to find a page in a suitable language. For example, in Internet Explorer, you can specify a set of preferred languages by selecting Tools | Internet Options and clicking on the Languages button as shown in FIGURE 2.


FIGURE 2: Specifying language prioritization in Internet Explorer.

The server code can extract this information later because it's sent as part of the HTTP request and stored in the HTTP_ACCEPT_LANGUAGE variable. (The HTTP_ACCEPT_LANGUAGE variable is supported by most HTTP 1.1 browsers.) Sometimes language negotiation can produce results that aren't suitable for the user. For example, although the default language may be specified as French, the user may prefer to browse the English version of the site. In this case, you might provide a language-selection menu on the start page.

Some Web sites use another scenario: They try to guess a user's language preference by looking up the country extension in the IP address. For example, if the user is surfing from proxy.myprovider.co.uk (a provider based in the United Kingdom), the sites assume the user speaks English. This is often a convenient strategy, but is not necessarily the most accurate. For example, many users browse from .com, .net, or similar address suffixes that do not have any obvious relationship to a particular language.

To access a user's language preferences in ASP.NET, you can use the UserLanguages property of the HTTPRequest class that contains a weighted string array of client language preferences. The fact that they're weighted means that if the user has specified more than one language, the first one will be the default language, and others will have numeric weights indicating how far the particular language is from the default one. For example, the languages shown in FIGURE 2 have the weighted string array shown in FIGURE 3.


FIGURE 3: Language preference weights for the languages specified in FIGURE 2.

The source code for the page shown in FIGURE 3 (langpref.aspx) is provided in the download files accompanying this article (see end of article for details).

I'll use this feature to create a menu based on client languages that will be used in later examples of this article. Note that although I easily could specify the default language as the main language for an application, it is always better to give the user a chance to change the default language. FIGURE 4 contains the Visual Basic .NET code that populates a list box with the region names, extracted from the list of languages.

Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)

Dim UserLangs() As String

Dim Count As Integer

Dim Pos As Integer

Dim Lang As String

If Not IsPostBack Then

UserLangs = Request.UserLanguages

For Count = 0 To UserLangs.GetUpperBound(0)

Pos = InStr(1, UserLangs(Count), ";")

If Pos > 0 Then

Lang = Left(UserLangs(Count).ToUpper, Pos-1)

Else

Lang = UserLangs(Count).ToUpper

End If

Pos = InStr(1, Lang, "-")

If Pos > 0 Then

Lang = Lang.Substring(Pos, Lang.Length-Pos)

End If

LangList.Items.Add(Lang)

Next Count

End If

End Sub

FIGURE 4: Populating the list box with region names.

Using RegionInfo Class

Now I am ready to use the RegionInfo class. I'll create an application that will allow me to check various region settings for specified regions. To do this, I need to implement the OnSelectedIndexChanged event handler for my list box that was populated with the code from FIGURE 4. The code for the event handler is shown in FIGURE 5.

Sub Index_Changed(sender As Object, e As EventArgs)

Dim Region As RegionInfo

Region = New RegionInfo(LangList.SelectedItem.Text)

AddRow(RegTable, "Name", Region.Name)

AddRow(RegTable, "EnglishName", _

Region.EnglishName)

AddRow(RegTable, "DisplayName", _

Region.DisplayName)

AddRow(RegTable, "CurrencySymbol", _

Region.CurrencySymbol)

AddRow(RegTable, "ISOCurrencySymbol", _

Region.ISOCurrencySymbol)

AddRow(RegTable, "IsMetric", Region.IsMetric)

AddRow(RegTable, "TwoLetterISORegionName", _

Region.TwoLetterISORegionName)

AddRow(RegTable, "ThreeLetterISORegionName", _

Region.ThreeLetterISORegionName)

AddRow(RegTable, "ThreeLetterWindowsRegionName", _

Region.ThreeLetterWindowsRegionName)

End Sub

FIGURE 5: This code populates a table with RegionInfo information.

On each list-box click, I create a new RegionInfo object with the specified region name and show its attributes. For example, information for the United States is shown in FIGURE 6.

No comments: