• Summary
You can localize an ASP.NET website so that it supports multiple languages and cultures. For example, you might need to create both an English language and Spanish language version of the same website.
One approach to localization is to simply create multiple copies of the same website and translate each copy into a different language. This was a common approach when building ASP Classic (or even ASP.NET 1.1) websites. The problem with this approach is it creates a website maintenance nightmare. Whenever you need to make a change to the website—no matter how simple—you must make the change in each copy of the website.
When building ASP.NET applications, you do not need to create multiple copies of a website to support multiple languages. Instead, you can take advantage of resource files. A resource file contains language-specific content. For example, one resource file might contain a Spanish version of all the text in your website, and a second resource file might contain the Indonesian version of all the text in your website.
In this chapter, you learn how to localize ASP.NET applications. First, you learn how to set the culture of the current page. You learn how to use both the Culture
and UICulture
properties. You also learn how to detect users’ preferred languages automatically through their browser settings.
Next, local resources are explored. A local resource contains content scoped to a particular file such as an ASP.NET page. You learn how to use both implicit and explicit resource expressions.
This chapter also examines global resources, which contain content that can be used in any page within an application. For example, you can place the title of your website in a global resource file.
Finally, the ASP.NET Localize
control is discussed. You learn how to use this control in your pages to localize big chunks of page text.
Two main properties of the Page
class have an effect on localization:
• UICulture
• Culture
The UICulture
property specifies which resource files are loaded for the page. The resource files can contain all the text content of your pages translated into a particular language. You can set this property to any standard culture name. This property is discussed in detail during the discussion of using local and global resources later in this chapter.
The Culture
property, on the other hand, determines how strings such as dates, numerals, and currency amounts are formatted. It also determines how values are compared and sorted. For example, by modifying the Culture
property, you can display dates with language-specific month names such as January (English), Januar (German), or Enero (Spanish).
Both the UICulture
and Culture
properties accept standard culture names for their values. Culture names follow the RFC 1766 and RFC 3066 standards maintained by the Internet Engineering Task Force (IETF). The IETF website is located at www.IETF.org.
Following are some common culture names:
• de-DE = German (Germany)
• en-US = English (United States)
• en-GB = English (United Kingdom)
• es-MX = Spanish (Mexico)
• id-ID = Indonesian (Indonesia)
• zh-CN = Chinese (China)
Each culture name consists of two parts. The first part represents the language code, and the second part represents the country/region code. If you specify a culture name and do not provide a country/region code—for example, en—you have specified something called a neutral culture. If you provide both a language code and a country/region code—for example, en-US—you have specified something called a specific culture.
You can view the culture names supported by .NET Framework by looking up the entry for the CultureInfo
class in the Microsoft .NET Framework SDK documentation. It’s a really long list.
The Culture
property must always be set to a specific culture. This makes sense because, for example, different English speakers use different currency symbols. The UICulture
property, on the other hand, can be set to either a neutral or specific culture name. Text written in Canadian English is pretty much the same as text written in U.S. English.
You can set the UICulture
and Culture
properties to the same value or different values. For example, if you create an online store, you might want to set the UICulture
property to the value de-DE
to display German product descriptions. However, you might want to set the Culture
property to the value en-US to display product prices in U.S. currency amounts.
You can set either the UICulture
or Culture
properties by using the <%@ Page %>
directive. For example, the page in Listing 30.1 sets both properties to the value id-ID
(Indonesian).
Listing 30.1. Bagus.aspx
The page in Listing 30.1 displays a date and a currency amount. Because the Culture
property is set to the value id-ID
in the <%@ Page %>
directive, both the date and currency amount are formatted with Indonesian cultural conventions (see Figure 30.1).
Figure 30.1. Displaying a localized date and price.
The date is displayed like this:
05 March 2010
The currency amount is displayed as an Indonesian Rupiah amount like this:
Rp512
Setting the Culture does not actually convert a currency amount. Setting a particular culture formats only the currency as appropriate for a particular culture. If you need to convert currency amounts, you need to use a Web service: Conversion rates change minute by minute. See, for example, www.xmethods.com.
Instead of using the <%@ Page %>
directive to set the Culture
or UICulture
properties, you can set these properties programmatically. For example, the page in Listing 30.2 enables you to select a particular culture from a drop-down list of cultures (see Figure 30.2).
Figure 30.2. Selecting a culture from a DropDownList
control.
Listing 30.2. SelectCulture.aspx
The DropDownList
control in Listing 30.2 is bound to an ObjectDataSource
control, which retrieves a list of all the culture names supported by .NET Framework. The culture names are retrieved during a call to the GetCultures()
method of the CultureInfo
class.
When you click the button to select a culture, the btnSelect_Click()
method executes and assigns the name of the selected culture to the page’s Culture
property. When you select a new culture, the formatting applied to the date and currency amount changes.
Several websites on the Internet display a page that requires the user to select a language before entering the main website. For example, the Federal Express website (www.FedEx.com) requires you to select a country before entering the website.
You can take advantage of the Profile
object to store a user’s preferred culture. That way, a user needs to select a culture only once, and the culture is then used any time the user returns to your website in the future. The page in Listing 30.3 illustrates this approach.
Listing 30.3. SelectCultureProfile.aspx
Consider two things about the page in Listing 30.3. First, the culture is set in the InitializeCulture()
method, which overrides the InitializeCulture()
method of the base Page
class and sets the UICulture
and Culture
properties by using the Profile
object.
Second, the btnSelect_Click()
handler updates the properties of the Profile
object and redirects the page back to itself, which is done so that the InitializeCulture()
method executes after a user changes the selected culture.
The page in Listing 30.3 uses the Profile
defined in the web configuration file contained in Listing 30.4.
Listing 30.4. Web.Config
The web configuration file in Listing 30.4 includes an anonymousIdentification
element. Including this element causes a profile to be created for a user even if the user has not been authenticated.
In the previous section, you learned how to set the UICulture
and Culture
properties by allowing the user to select a particular culture from a DropDownList
control. Instead of requiring users to select their culture, you can automatically detect users’ cultures through their browser settings.
Whenever a browser makes a request for a web page, the browser sends an Accept-Language header, which contains a list of the user’s preferred languages.
You can set your preferred languages when using Microsoft Internet Explorer or Mozilla Firefox by selecting Tools, Internet Options and clicking the Languages button. You can then create an ordered list of your preferred languages (see Figure 30.3). When using Opera, select Tools, Preferences and click the Details button (see Figure 30.4).
Figure 30.3. Setting your preferred language with Internet Explorer.
Figure 30.4. Setting your preferred language with Opera.
You can retrieve the value of the Accept-Language header by using the Request.UserLanguages
property. For example, the page in Listing 30.5 displays a list of the languages retrieved from a browser’s Accept-Language header (see Figure 30.5).
Figure 30.5. Displaying a browser’s language settings.
Listing 30.5. ShowAcceptLanguages.aspx
If you want to set the Culture
or UICulture
properties automatically by detecting the browser’s Accept-Language header, you can set either of these properties to the value auto
. For example, the page in Listing 30.6 automatically displays the date and currency amount according to the user’s preferred language.
Listing 30.6. SelectCultureAuto.aspx
In the <%@ Page %>
directive in Listing 30.6, both the Culture
and UICulture
attributes are set to the value auto:en-US
. The culture name that appears after the colon enables you to specify a default culture when a language preference cannot be detected from the browser.
Don’t assume that all values of the Accept-Language header retrieved from a browser are valid culture names. Most browsers enable users to enter a “user-defined” language, which might not be valid.
Rather than set the Culture
and UICulture
properties in each page, you can set these properties once in the web configuration file. Typically, you should take this approach because it makes your website easier to maintain.
The web configuration file in Listing 30.7 sets the Culture
and UICulture
properties to the value de-DE
(German).
Listing 30.7. Web.Config
If you prefer, you can use the value auto
in the web configuration file if you want the culture to be automatically detected based on the value of the browser Accept-Language header. If you need to override the configuration settings in the web configuration file in a particular page, you can simply set the Culture
and UICulture
properties in the page.
Culture
and ASP.NET ControlsThe value of the Culture
property automatically has an effect on the rendering behavior of ASP.NET controls such as the Calendar
control. For example, Listing 30.8 uses the ASP.NET Calendar
control to display a calendar (see Figure 30.6).
Figure 30.6. Displaying a localized Calendar
control.
Listing 30.8. ShowCalendar.aspx
The Culture
attribute in the <%@ Page %>
directive is set to the value id-ID
(Indonesian). When the calendar is rendered, Indonesian month names display in the calendar.
CultureInfo
ClassThe CultureInfo
class contains information about more than 150 different cultures. You can use the methods of this class in your code to retrieve information about a specific culture and use the information when formatting values such as dates, numbers, and currency amounts.
To represent a culture with the CultureInfo
class, you can instantiate the class by passing a culture name to the class constructor like this:
Dim culture As New CultureInfo("de-DE")
You can also use any of the following methods of the CultureInfo
class to retrieve information about a culture or cultures:
• CreateSpecificCulture
—Enables you to create a CultureInfo
object by supplying the name of a specific culture.
• GetCultureInfo
—Enables you to create a CultureInfo
object by supplying an identifier, culture name, or CompareInfo
and TextInfo
object.
• GetCultureInfoByIetfLanguageTag
—Enables you to create a CultureInfo
object efficiently by supplying a culture name.
• GetCultures
—Enables you to retrieve an array of cultures.
The CultureInfo
class lives in the System.Globalization
namespace. Before you can use the CultureInfo
class, you need to import this namespace.
CultureInfo
Class to Format String ValuesTo this point, the culture has been set at the level of an individual ASP.NET page or the level of an entire ASP.NET application. However, you might need to take advantage of locale-specific formatting at a more granular level. You can use the CultureInfo
class to format a particular value independent of the Culture
set for the page.
When you use the ToString()
method to format dates, times, numbers, and currency amounts, you can supply an additional parameter that formats the value in accordance with a specific culture. For example, the page in Listing 30.9 formats two sets of date and time values.
Listing 30.9. ToStringCulture.aspx
The first date and time is formatted with German cultural conventions, and the second date and time is formatted with Indonesian cultural conventions (see Figure 30.7). Two CultureInfo
objects, corresponding to two cultures, are created in the Page_Load()
method.
Figure 30.7. Formatting with the ToString()
method.
Different cultures follow different conventions when comparing and sorting string values. If you need to compare or sort string values in your code, you should use the String.Compare()
method and optionally supply the method with an instance of the CultureInfo
object.
The String.Compare()
method returns one of the following values:
• Negative Integer—The first string is less than the second string.
• Zero—The first string is equal to the second string.
• Positive Integer—The first string is greater than the second string.
For example, the following conditional compares two strings, using the current culture set for the page:
if (String.Compare("Hello", "Hello") == 0)
lblResult.Text = "The strings are the same!";
The following conditional uses a specific culture to perform a string comparison:
if (String.Compare("Hello", "Hello", true, new CultureInfo("de-DE")) == 0)
lblResult.Text = "The strings are the same!";
In this case, the first two parameters passed to the String.Compare()
method are the strings compared. The third parameter indicates whether the comparison performed should be case-sensitive. Finally, the last parameter represents a CultureInfo
object.
If you need to modify the text (or other content) in a page depending on a user’s language, you can take advantage of resource files. Each resource file can contain page text translated into a particular language.
The ASP.NET Framework supports two types of resource files: local and global. In this section, you learn how to use local resources. A local resource is scoped to a particular file such as an ASP.NET page.
The page in Listing 30.10 is a simple page. It contains a button labeled Click Here! and displays the text Thank You! after you click the button.
Listing 30.10. SimplePage.aspx
The page in Listing 30.10 displays the same text regardless of the language of the user visiting the page. If you want to display text in different languages for different users, you need to make a few modifications to the page.
The page in Listing 30.11 is a localizable version of the same page.
Listing 30.11. LocalizablePage.aspx
Two types of changes were made to the page in Listing 30.11. First, the <%@ Page %>
directive includes a UICulture
attribute that is set to the value auto
. When a user requests the page, a resource file that matches the user’s preferred browser language loads automatically.
Don’t confuse the Page UICulture
property with the Page Culture
property. The UICulture
property determines which resource files load for the page. The Culture
property, on the other hand, determines how date, number, and currency values are formatted.
Second, both the Button and Label controls have been modified. The Button control is declared like this:
The value of the Text
property is a resource expression. This resource expression retrieves the value of an entry named ClickHere
from the loaded resource file. This resource expression is considered to be an explicit resource expression because the property is explicitly set to the value of a particular resource entry.
After you localize a page, you can associate a resource file with the page. All the resource files that you want to associate with a page must be added to a special folder named App_LocalResources. You create the App_LocalResources folder in the same folder as the page that you want to localize. For example, if the page is located in the root of your application, you would add the App_LocalResources folder to the root folder.
You associate a resource file in the App_LocalResources folder with a particular page by using the following file-naming convention:
page name.[culture name].resx
For example, all the following resource files are associated with the LocalizablePage.aspx
page:
LocalizablePage.aspx.resx
LocalizablePage.aspx.es-PR.resx
LocalizablePage.aspx.es.resx
The first resource file is the default resource file. If none of the other resource files match the user’s language settings, the contents of the default resource file are used.
The second resource filename includes the specific culture name es-PR (Puerto Rican Spanish). If a user’s browser is set to Puerto Rican Spanish, the contents of this resource file are loaded.
Finally, the third resource filename includes the neutral culture name es (Spanish). If a user’s preferred language is Spanish, but not Puerto Rican Spanish, the contents of this resource file are loaded.
You create a resource file when using Visual Web Developing by right-clicking an App_LocalResources folder, selecting Add New Item, and Assembly Resource file. Visual Web Developer automatically displays an editor for the resource file. The editor enables you to enter name and value pairs. For example, the LocalizablePage.aspx.es.resx
resource file contains the two name/value pairs in Listing 30.12.
Listing 30.12. App_LocalResourcesLocalizablePage.aspx.es.resx
Behind the scenes, resource files are XML files. You can open a resource file in Notepad and edit its contents. The ASP.NET Framework dynamically compiles resource files into assemblies in the background.
As an alternative to using explicit localization expressions, you can use an implicit localization expression. An implicit localization expression enables you to localize multiple control properties with one resource key.
The page in Listing 30.13 uses implicit localization expressions.
Listing 30.13. LocalizablePageImplicit.aspx
Both the Button and Label control include a meta:resourceKey
property. The value of this property represents a resource key in a local resource file. For example, the resource file in Listing 30.14 contains three entries.
Listing 30.14. App_LocalResourcesLocalizablePageImplicit.aspx.es.resx
The first two entries set the Text
and ToolTip
properties of the btnSubmit
control. The third entry sets the value of the Text
property of the lblMessage
property.
When you are ready to start localizing a page, always create a default localization file (for example, LocalizablePageImplicit.aspx.resx
). If you don’t create a default localization file, other culture-specific localization files are ignored.
There are two advantages to using implicit localization expressions instead of using explicit localization expressions. First, implicit expressions enable you to override multiple control properties by associating a single resource key with the control.
Second, by taking advantage of implicit localization expressions, you can easily localize an existing website. You simply need to add the meta:resourceKey
attribute to any control that you need to localize.
You can use resource expressions when setting page properties such as the page title. For example, the page in Listing 30.15 uses an explicit resource expression to set the page title.
Listing 30.15. PageExplicit.aspx
In Listing 30.15, the page title is created with a Literal
control, which contains an explicit resource expression for the value of its Text
property. You also can use implicit resource expressions when setting the page title. This approach is illustrated by the page in Listing 30.16.
Listing 30.16. PageImplicit.aspx
The <%@ Page %>
directive includes a meta:resourceKey
attribute. If a local resource includes a page.Title
entry, the value of this entry is used for the title displayed by the page.
If you need to retrieve a local resource in your page code, you can use the GetLocalResourceObject()
method. For example, the page in Listing 30.17 grabs a welcome message from a resource file. The welcome message is used to format some text, and then the formatted text displays in a Label
control.
Listing 30.17. ProgramLocal.aspx
The result returned from GetLocalResourceObject()
must be cast to a string value. As the method name implies, the method returns an object and not a string value. The resource file associated with the page in Listing 30.17, named ProgramLocal.aspx.es.resx
, is contained in Listing 30.18.
Listing 30.18. App_LocalResourcesProgramLocal.aspx.es.resx
If someone’s browser is set to Spanish as the preferred language, and the user requests the page, the welcome message is retrieved from this resource file, the name Steve is added to the string, and the result displays in the browser (see Figure 30.8).
Figure 30.8. Retrieving a local resource programmatically.
You also can retrieve local resources in a component. Within a component, use the shared HttpContext.GetLocalResourceObject()
method. For example, the component in Listing 30.19 grabs the entry named ClickHere
from the local resource file that corresponds to the page named LocalizablePage.aspx
.
Listing 30.19. LocalComponent.cs
A local resource is scoped to a particular page. A global resource, on the other hand, can be used by any page in an application. Any localized content that you need to share among multiple pages in your website should be added to a global resource file.
You create global resource files by adding the files to a special folder named App_GlobalResources
. This folder must be located in the root of your application.
For example, the file in Listing 30.20 is a global resource file.
Listing 30.20. App_GlobalResourcesSite.resx
The page in Listing 30.21 uses the entries from the global resource file (see Figure 30.9).
Figure 30.9. Displaying global resource entries.
Listing 30.21. ShowGlobalPage.aspx
Just as you can with a local resource file, you can localize a global resource file by adding culture names to the file name. For example, the page in Listing 30.22 is localized to Spanish.
Listing 30.22. App_GlobalResourcesSite.es.resx
If you modify the UICulture
attribute contained in the <%@ Page %>
directive in Listing 30.21 to the value es
, the resource file in Listing 30.22 will be used with the page. Alternatively, you can set UICulture
to the value auto
and change your browser’s language settings.
You can retrieve a global resource entry programmatically from any page by using the GetGlobalResourceObject()
method. For example, the page in Listing 30.23 grabs the Title entry from the Site resource file and displays the value of the entry in a Label control.
Listing 30.23. ProgramGlobal.aspx
The GetGlobalResourceObject()
method requires two parameters: the name of the resource class and the name of an entry. The resource class corresponds to the global resource filename.
The ASP.NET Framework automatically converts global resources into compiled classes behind the scenes. This enables you to use strongly typed expressions when working with global resources in your code. When you create a resource, a new class is added automatically to the Resources namespace. The class exposes all the entries of the resource file as properties.
For example, the page in Listing 30.24 retrieves the Title entry from the Site global resource file (Site.resx
and its culture-specific variations).
Listing 30.24. ProgramGlobalTyped.aspx
You can use the following expression magically to refer to the Title entry in the Site resource file:
lblMessage.Text = Resources.Site.Title
Localize
ControlThe ASP.NET Framework includes a control named the Localize
control, which is included in Framework to make it easier to localize big chunks of text in a page.
For example, the page in Listing 30.25 uses the Localize
control in the body of the page.
Listing 30.25. ShowLocalizeControl.aspx
The Localize
control is similar to the Literal
control (it derives from the Literal
control). In Source View, there is nothing that distinguishes the two controls. The difference between the Localize
control and Literal
control is apparent only in Design View. Unlike the Literal control, the contents of the Localize
control can be edited directly on the Designer surface in Design View (see Figure 30.10).
Figure 30.10. Using the Localize
control in Design View.
In this chapter, you learned how to localize websites for different languages and culture. In the first section, you learned how to use the Culture
and UICulture
properties to set the current culture for the page. You also learned how to set these properties automatically by detecting a browser’s preferred language settings.
Next, you learned how to create local resource files that you can apply to particular pages (and other files). You learned how to use both explicit and implicit localization expressions. You also saw how you can programmatically retrieve local resource entries in your code.
You then studied the topic of global resource files, which contain entries that can be used within any page in a website. You learned to use explicit resource expressions with global resources and how to retrieve global resource entries programmatically.
Finally, you had a brief look at the ASP.NET Localize
control. You learned how to use this control to localize big chunks of text in a page.