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 is 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 2.0 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 that is 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. A global resource contains 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 is used to specify 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 http://www.IETF.org.
Here 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)
Notice that 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—then you have specified something called a neutral culture. If you provide both a language code and a country/region code—for example, en-US—then you have specified something called a specific culture.
You can view the culture names supported by the .NET Framework by looking up the entry for the CultureInfo
class in the Microsoft .NET Framework SDK 2.0 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 are creating an online store then 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 United State currency amounts.
You can set either the UICulture
or Culture
properties by using the <%@ Page %>
directive. For example, the page in Listing 24.1 sets both properties to the value id-ID
(Indonesian).
Example 24.1. Bagus.aspx
<%@ Page Language="VB" Culture="id-ID" UICulture="id-ID" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub Page_Load() lblDate.Text = DateTime.Now.ToString("D") lblPrice.Text = (512.33D).ToString("c") End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Bagus</title> </head> <body> <form id="form1" runat="server"> <div> Today's date is: <br /> <asp:Label id="lblDate" Runat="server" /> <hr /> The price of the product is: <br /> <asp:Label id="lblPrice" Runat="server" /> </div> </form> </body> </html>
The page in Listing 24.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 24.1).
The date is displayed like this:
05 Nopember 2005
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 only formats the currency as appropriate for a particular culture. If you need to convert currency amounts, then you need to use a Web service: Conversion rates change minute by minute. See, for example, http://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 24.2 enables you to select a particular culture from a drop-down list of cultures (see Figure 24.2).
Example 24.2. SelectCulture.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub btnSelect_Click(ByVal sender As Object, ByVal e As EventArgs) Culture = ddlCulture.SelectedValue End Sub Sub Page_PreRender() lblDate.Text = DateTime.Now.ToString("D") lblPrice.Text = (512.33D).ToString("c") End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Select Culture</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label id="lblCulture" Text="Culture:" AssociatedControlID="ddlCulture" Runat="server" /> <asp:DropDownList id="ddlCulture" DataTextField="DisplayName" DataValueField="Name" DataSourceID="srcCultures" Runat="server" /> <asp:Button id="btnSelect" Text="Select" Runat="server" OnClick="btnSelect_Click" /> <asp:ObjectDataSource id="srcCultures" TypeName="System.Globalization.CultureInfo" SelectMethod="GetCultures" Runat="server"> <SelectParameters> <asp:Parameter Name="types" DefaultValue="SpecificCultures" /> </SelectParameters> </asp:ObjectDataSource> <hr /> Today's date is: <br /> <asp:Label id="lblDate" Runat="server" /> <br /><br /> The price of the product is: <br /> <asp:Label id="lblPrice" Runat="server" /> </div> </form> </body> </html>
The DropDownList
control in Listing 24.2 is bound to an ObjectDataSource
control, which retrieves a list of all the culture names supported by the .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 24.3 illustrates this approach.
Example 24.3. SelectCultureProfile.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Protected Overrides Sub InitializeCulture() Culture = Profile.UserCulture UICulture = Profile.UserUICulture End Sub Protected Sub btnSelect_Click(ByVal sender As Object, ByVal e As EventArgs) Profile.UserCulture = ddlCulture.SelectedValue Profile.UserUICulture = ddlCulture.SelectedValue Response.Redirect(Request.Path) End Sub Private Sub Page_PreRender() lblDate.Text = DateTime.Now.ToString("D") lblPrice.Text = (512.33D).ToString("c") End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Select Culture Profile</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label id="lblCulture" Text="Culture:" AssociatedControlID="ddlCulture" Runat="server" /> <asp:DropDownList id="ddlCulture" DataTextField="DisplayName" DataValueField="Name" DataSourceID="srcCultures" Runat="server" /> <asp:Button id="btnSelect" Text="Select" Runat="server" OnClick="btnSelect_Click" /> <asp:ObjectDataSource id="srcCultures" TypeName="System.Globalization.CultureInfo" SelectMethod="GetCultures" Runat="server"> <SelectParameters> <asp:Parameter Name="types" DefaultValue="SpecificCultures" /> </SelectParameters> </asp:ObjectDataSource> <hr /> Today's date is: <br /> <asp:Label id="lblDate" Runat="server" /> <br /><br /> The price of the product is: <br /> <asp:Label id="lblPrice" Runat="server" /> </div> </form> </body> </html>
You should notice two things about the page in Listing 24.3. First, notice that the culture is set in the InitializeCulture()
method. This method overrides the InitializeCulture()
method of the base Page
class and sets the UICulture
and Culture
properties by using the Profile
object.
Second, notice that the btnSelect_Click()
handler updates the properties of the Profile
object and redirects the page back to itself. This is done so that the InitializeCulture()
method executes after a user changes the selected culture.
The page in Listing 24.3 uses the Profile
defined in the web configuration file contained in Listing 24.4.
Example 24.4. Web.Config
<?xml version="1.0"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <anonymousIdentification enabled="true"/> <profile> <properties> <add name="UserCulture" defaultValue="en-US" /> <add name="UserUICulture" defaultValue="en"/> </properties> </profile> </system.web> </configuration>
Notice that the web configuration file in Listing 24.4 includes a 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. The Accept-Language header 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 the menu option Tools, Internet Options and clicking the Languages button. You can then create an ordered list of your preferred languages (see Figure 24.3). When using Opera, select the menu option Tools, Preferences and click the Details button (see Figure 24.4).
You can retrieve the value of the Accept-Language header by using the Request.UserLanguages
property. For example, the page in Listing 24.5 displays a list of the languages retrieved from a browser’s Accept-Language header (see Figure 24.5).
Example 24.5. ShowAcceptLanguages.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub Page_Load() bltAcceptLanguages.DataSource = Request.UserLanguages bltAcceptLanguages.DataBind() End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show Accept Languages</title> </head> <body> <form id="form1" runat="server"> <div> <asp:BulletedList id="bltAcceptLanguages" Runat="server" /> </div> </form> </body> </html>
If you want to set the Culture
or UICulture
properties automatically by detecting the browser’s Accept-Language header, then you can set either of these properties to the value auto
. For example, the page in Listing 24.6 automatically displays the date and currency amount according to the user’s preferred language.
Example 24.6. SelectCultureAuto.aspx
<%@ Page Language="VB" Culture="auto:en-US" UICulture="auto:en-US"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub Page_PreRender() lblDate.Text = DateTime.Now.ToString("D") lblPrice.Text = (512.33D).ToString("c") End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Select Culture Auto</title> </head> <body> <form id="form1" runat="server"> <div> Today's date is: <br /> <asp:Label id="lblDate" Runat="server" /> <br /><br /> The price of the product is: <br /> <asp:Label id="lblPrice" Runat="server" /> </div> </form> </body> </html>
In the <%@ Page %>
directive in Listing 24.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.
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 24.7 sets both the Culture
and UICulture
properties to the value de-DE
(German).
The web configuration file in Listing 24.7 sets the Culture
and UICulture
for all pages to the value de-DE
(German).
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, then you can simply set the Culture
and UICulture
properties in the page.
The 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 24.8 uses the ASP.NET Calendar
controll to display a calendar (see Figure 24.6).
Example 24.8. ShowCalendar.aspx
<%@ Page Language="VB" Culture="id-ID" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show Calendar</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Calendar id="Calendar1" Runat="server" /> </div> </form> </body> </html>
The Culture
attribute in the <%@ Page %>
directive is set to the value id-ID
(Indonesian). When the calendar is rendered, Indonesian month names are displayed in the calendar.
The 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.
To 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 24.9 formats two sets of date and time values.
Example 24.9. ToStringCulture.aspx
<%@ Page Language="VB" %> <%@ Import Namespace="System.Globalization" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Private Sub Page_Load() ' Get German Culture Info Dim gCulture As New CultureInfo("de-DE") ' Use culture when formatting strings lblGermanDate.Text = DateTime.Now.ToString("D", gCulture) lblGermanPrice.Text = (512.33D).ToString("c", gCulture) ' Get Indonesian Culture Info Dim iCulture As New CultureInfo("id-ID") ' Use culture when formatting strings lblIndonesianDate.Text = DateTime.Now.ToString("D", iCulture) lblIndonesianPrice.Text = (512.33D).ToString("c", iCulture) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>ToString Culture</title> </head> <body> <form id="form1" runat="server"> <div> <h1>German</h1> Today's date is: <br /> <asp:Label id="lblGermanDate" Runat="server" /> <br /><br /> The price of the product is: <br /> <asp:Label id="lblGermanPrice" Runat="server" /> <h1>Indonesian</h1> Today's date is: <br /> <asp:Label id="lblIndonesianDate" Runat="server" /> <br /><br /> The price of the product is: <br /> <asp:Label id="lblIndonesianPrice" Runat="server" /> </div> </form> </body> </html>
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 24.7). Notice that two CultureInfo
objects, corresponding to two cultures, are created in the Page_Load()
method.
Different cultures follow different conventions when comparing and sorting string values. If you need to compare or sort string values in your code, then 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 Then lblResult.Text = "The strings are the same!" End If
The following conditional uses a specific culture to perform a string comparison:
If String.Compare("Hello", "Hello", True, New CultureInfo("de-DE")) = 0 Then lblResult.Text = "The strings are the same!" End If
In this case, the first two parameters passed to the String.Compare()
method are the strings being compared. The third parameter indicates whether the comparison performed should be case sensitive or not. 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, then 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 resources. 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 24.10 is a very simple page. It contains a button labeled "Click Here!" and displays the text "Thank You!" after you click the button.
Example 24.10. SimplePage.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) lblMessage.Visible = True End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Simple Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button id="btnSubmit" Text="Click Here!" OnClick="btnSubmit_Click" Runat="server" /> <br /><br /> <asp:Label id="lblMessage" Text="Thank You!" Visible="false" Runat="server" /> </div> </form> </body> </html>
The page in Listing 24.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, then you need to make a few modifications to the page.
The page in Listing 24.11 is a localizable version of the same page.
Example 24.11. LocalizablePage.aspx
<%@ Page Language="VB" UICulture="auto" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) lblMessage.Visible = True End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Localizable Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button id="btnSubmit" Text="<%$ Resources:ClickHere %>" OnClick="btnSubmit_Click" Runat="server" /> <br /><br /> <asp:Label id="lblMessage" Text="<%$ Resources:ThankYou %>" Visible="false" Runat="server" /> </div> </form> </body> </html>
Two types of changes were made to the page in Listing 24.11. First, notice that 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 is loaded automatically.
Don’t confuse the Page UICulture
property with the Page Culture
property. The UICulture
property determines which resource files are loaded for the page. The Culture
property, on the other hand, determines how date, number, and currency values are formatted.
Second, notice that both the Button
and Label
controls have been modified. The Button control is declared like this:
<asp:Button id="btnSubmit" Text="<%$ Resources:ClickHere %>" OnClick="btnSubmit_Click" Runat="server" />
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, then 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, then the contents of the default resource file are used.
The second resource file name includes the specific culture name es-PR (Puerto Rican Spanish). If a user’s browser is set to Puerto Rican Spanish, then the contents of this resource file are loaded.
Finally, the third resource file name includes the neutral culture name es (Spanish). If a user’s preferred language is Spanish, but not Puerto Rican Spanish, then 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 selecting 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 24.12.
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 24.13 uses implicit localization expressions.
Example 24.13. LocalizablePageImplicit.aspx
<%@ Page Language="VB" UICulture="auto" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub btnSubmit_Click(ByVal s As Object, ByVal e As EventArgs) lblMessage.Visible = True End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Localizable Page Implicit</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button id="btnSubmit" meta:resourceKey="btnSubmit" Text="Click Me!" ToolTip="Click to show message" OnClick="btnSubmit_Click" Runat="server" /> <br /><br /> <asp:Label id="lblMessage" meta:resourceKey="lblMessage" Text="Thank You!" Visible="false" Runat="server" /> </div> </form> </body> </html>
Notice that 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 24.14 contains three entries.
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 over 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 more 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 24.15 uses an explicit resource expression to set the page title.
Example 24.15. PageExplicit.aspx
<%@ Page Language="VB" UICulture="auto" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title><asp:Literal Text="<%$ Resources:Title %>" runat="Server" /></title> </head> <body> <form id="form1" runat="server"> <div> <h1>Page Explicit Localization</h1> </div> </form> </body> </html>
In Listing 24.15, the page title is created with a Literal
control. The Literal
control 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 24.16.
Example 24.16. PageImplicit.aspx
<%@ Page Language="VB" UICulture="auto" meta:resourceKey="page" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Page Title</title> </head> <body> <form id="form1" runat="server"> <div> <h1>Page Implicit Localization</h1> </div> </form> </body> </html>
Notice that the <%@ Page %>
directive includes a meta:resourceKey
attribute. If a local resource includes a page.Title
entry, then 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, then you can use the GetLocalResourceObject()
method. For example, the page in Listing 24.17 grabs a welcome message from a resource file. The welcome message is used to format some text, and then the formatted text is displayed in a Label
control.
Example 24.17. ProgramLocal.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> sub Page_Load() Dim welcomeMessage As String = CType(GetLocalResourceObject("welcomeMessage"), String) lblMessage.Text = String.Format(welcomeMessage, "Steve") end Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Program Local Resource</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label id="lblMessage" Runat="server" /> </div> </form> </body> </html>
Notice that the result returned from the 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 24.17, named ProgramLocal.aspx.es.resx
, is contained in Listing 24.18.
If someone’s browser is set to Spanish as the preferred language, and the user requests the page, then the welcome message is retrieved from this resource file, the name Steve is added to the string, and the result is displayed in the browser (see Figure 24.8).
You also can retrieve local resources in a component. Within a component, use the shared HttpContext.GetLocalResourceObject()
method. For example, the component in Listing 24.19 grabs the entry named ClickHere
from the local resource file that corresponds to the page named LocalizablePage.aspx
.
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 24.20 is a global resource file.
The page in Listing 24.21 uses the entries from the global resource file (see Figure 24.9).
Example 24.21. ShowGlobalPage.aspx
<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title> <asp:Literal id="ltlTitle" Text="<%$ Resources:Site,Title %>" Runat="Server" /> </title> </head> <body> <form id="form1" runat="server"> <div> <br />Page Content <br />Page Content <br />Page Content <br />Page Content <hr /> <asp:Literal id="ltlCopyright" Text="<%$ Resources:Site,Copyright %>" Runat="Server" /> </div> </form> </body> </html>
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 24.22 is localized to Spanish.
If you modify the UICulture
attribute contained in the <%@ Page %>
directive in Listing 24.21 to the value es
, then the resource file in Listing 24.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 24.23 grabs the Title entry from the Site resource file and displays the value of the entry in a Label control.
Example 24.23. ProgramGlobal.aspx
<%@ Page Language="VB" UICulture="auto" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> Sub Page_Load() lblMessage.Text = CType(GetGlobalResourceObject("Site", "Title"), String) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Program Global</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label id="lblMessage" Runat="server" /> </div> </form> </body> </html>
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 24.24 retrieves the Title entry from the Site global resource file (Site.resx
and its culture-specific variations).
Example 24.24. ProgramGlobalTyped.aspx
<%@ Page Language="VB" UICulture="auto" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> sub Page_Load() lblMessage.Text = Resources.Site.Title end sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Program Global Typed</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label id="lblMessage" Runat="server" /> </div> </form> </body> </html>
Notice that you can use the following expression magically to refer to the Title entry in the Site resource file:
lblMessage.Text = Resources.Site.Title
The ASP.NET Framework includes a control named the Localize
control. This control is included in the Framework to make it easier to localize big chunks of text in a page.
For example, the page in Listing 24.25 uses the Localize
control in the body of the page.
Example 24.25. ShowLocalizeControl.aspx
<%@ Page Language="VB" UICulture="auto" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show Localize Control</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Localize ID="locBodyText" meta:resourceKey="locBodyText" Runat="server"> Here is the page body text </asp:Localize> <br /><br /> <asp:Literal ID="ltlBodyText" runat="server"> Here is some literal text </asp:Literal> </div> </form> </body> </html>
The Localize
control is very 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 24.10).
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.