Introduction
This article describes a quick and easy way to implement localization through the use of resource strings within an ASP.NET 2.0 application (Visual Basic 2005). The article and code sample are not at all representative of everything that can be accomplished in terms of application localization using the tools and constructs supplied within the .NET framework, however, if you have never been exposed to localization, this article is meant as an introduction to the topic.
Localization support in 2005 is impressive; with the support provided it is possible to automatically detect the user�s culture and to respond to that detection with properly formatted dates, currency and other numeric values, properly configured controls (e.g., a calendar control with the correct month and day text shown for the current and detected culture) and so forth.
This application is focused solely upon the use of localized strings to replace text on a web page based upon a user selected culture. Even though this is certainly not the be-all, end-all solution to localization, it is a good starting point and using the approach defined in this article, the reader will have an adequate method for translating web pages based upon a user�s selection of a specific culture.
The demonstration application will attempt to show the reader how to replace strings used within a web application with strings from alternative cultures; this is handled entirely through the use of managed resources and user selected culture information. This demonstration translates six different nonsense strings contained in label controls to either English, French, German, or Spanish on the fly. Examine figures 1 and 2 for examples screen shots of the web application in use.
Figure 1: Sample Web Application (English Strings)
Figure 2: Sample Web Application (German Strings)
Getting Started
In order to begin, unzip the downloaded files and open the project provided. Within the project you will find a simple ASP.NET 2.0 application written in VB.NET; the web application contains a single web page (Default.aspx). The web page serves no purpose other than to demonstrate the use of the resource based localization. Aside from the Default.aspx page, you will note that a couple of folders have been added to the project template; one is the App_GlobalResources folder and the other is the graphics folder.
The graphics folder contains four icons: a German flag GIF, a Spanish flag GIF, a French flag GIF, and a US flag GIF. These icons are used within the application as the image associated with an image button which is in turn used to set the culture information associated with the page to the correct culture. The flag icons were obtained from a public web site. The icons are the work of Mark James of Birmingham (a developer residing in the UK) and he offers a terrific collection of very high quality icons at no charge (which certainly does not make any less attractive in my book). If you are in need of flag icons or other icons, I would certainly recommend a visit to this gentleman�s site.
The App_GlobalResources folder is used to contains the resource files which in turn contain the localized strings. The naming of the file is specific and intentional; in order to capture the correct strings from the correct resource files, the naming of the files should adhere to the format shown. If, for example, you wished to add Canadian French strings to the file, you should plan on creating a Strings.fr-CA.resx file to go along with those shown in figure 3.
Figure 3: Project in the IDE�s Solution Explorer
At this point, create a virtual directory in IIS and point it at this web application, then open up the project in Visual Studio 2005.
The Code: Default.aspx
Open up the default.aspx page within the 2005 IDE, at the beginning of the file, you will note that a few imports have been added:
Imports System
Imports System.Globalization
Imports System.Threading
Imports System.Resources
Imports System.Reflection
The added imports are necessary to support the culture information and resource file used within the application. Actually, the System import is not really necessary but the others are essential to the task and you will note their use during the examination of the balance of the code contained within the default class.
The declaration of the class is per the default configuration; it has not been modified and you will note that the class inherits from the page class.
Partial Class _Default
Inherits System.Web.UI.Page
Private rm As ResourceManager
Immediately following the class declaration, an instance of the ResourceManager
class is made. It is through the resource manager that the application is provided with the means to interact with the contents of the application resources (the resource string files contained in the App_GlobalResources folder). The declaration of the ResourceManager
is included at this point merely to provide form wide scope to the object; you will note that it is not declared as �New
� in this location.
Next up is the Page Load event handler; that code is as follows:
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim ci As CultureInfo
If Not Page.IsPostBack Then
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
rm = New ResourceManager("Resources.Strings", _
System.Reflection.Assembly.Load("App_GlobalResources"))
ci = Thread.CurrentThread.CurrentCulture
LoadStrings(ci)
Else
rm = New ResourceManager("Resources.Strings", _
System.Reflection.Assembly.Load("App_GlobalResources"))
ci = Thread.CurrentThread.CurrentCulture
LoadStrings(ci)
End If
End Sub
You will note that during the page load event, the first item of business is to declare an instance of the CultureInfo
class. The culture information class instance is used to contain the current user�s culture. This value may be set up to be populated through auto detection but since I am not prepared to handle all possible languages I have chosen to manually set the initial culture to American English which is defined as �en-US�; I have selected this as the default merely because I live in the US; for pages likely to be used more in other locations, or in instances where I am unsure as to the appropriate culture to apply, I would be more likely to auto select the value and/or apply a more suitable default culture. The if statement merely checks to see if the page is a post back, and if it is not, it manually sets the culture information object to represent American English.
The default culture selection is managed in the if statement immediately following the declaration of the instance of the culture information class. The first line within the if statement sets the current culture thread to be configured for American English.
The next item to attend to is the resource manager; here a new instance of the resource manager is declared and, through reflection, it is permitted to load the string resources contained in the App_GlobalResources folder.
Next up, the culture information object is set to match the current culture thread (which was previously set to American English).
Last, with all of the culture information declared and configured, the culture information is passed to a subroutine called �LoadStrings
� and this subroutine gathers the string values from the appropriate resource string file (based upon the culture information) and sets the text of the six labels used within the demonstration.
If the page has been previously loaded, the current culture is left intact, the culture information variable is set to the current culture thread, and the strings are loaded based upon the current culture. This portion of the if statement is necessary to permit the user to alter the culture information without overriding it upon page load.
Following the page load event handler, the next item in the class is used to capture the correct strings from the appropriate resource file. This is managed through a subroutine called �LoadStrings
�. This subroutine is passed the current culture information as an argument and that culture information is used to instruct the resource manager as to which string resource file to gather the requested strings from when the page is loading. The subroutine uses the resource manager to capture each string and the returned string is then used to populate the Text
property for each of the six labels contained in the demonstration application. The code for �LoadStrings
� subroutine is as follows:
Private Sub LoadStrings(ByVal ci As CultureInfo)
lbl1.Text = rm.GetString("BirdInfo", ci)
lbl2.Text = rm.GetString("CatInfo", ci)
lbl3.Text = rm.GetString("DogInfo", ci)
lbl4.Text = rm.GetString("TravelInfo", ci)
lbl5.Text = rm.GetString("WaterInfo", ci)
lbl6.Text = rm.GetString("WeatherInfo", ci)
End Sub
The last bit of code in the demonstration is used to support the image button click event handlers used to manually set the culture information. There are four click event handlers in this demonstration, one each for American English, German, French, and Spanish. As they are all basically the same, I will only show one here in the article and you may examine the others to note the differences between them.
This is the code for the French image button click event handler:
Protected Sub ibtFrance_Click(ByVal sender As Object, _
ByVal e As System.Web.UI.ImageClickEventArgs) _
Handles ibtFrance.Click
Thread.CurrentThread.CurrentCulture = New CultureInfo("fr-FR")
LoadStrings(Thread.CurrentThread.CurrentCulture)
End Sub
You will note that the click event handler (represented by the icon of a French flag in the demonstration web application) sets the current culture thread to �fr-FR� (French French as opposed to something like fr-CA for Canadian French). Once the culture is set, the �LoadStrings� subroutine is called again and is passed the current culture, now set to fr-FR.
Resource Files
The resource string files each contain the same list of string identities but for each identified string, the value changes depending upon the language.
The English strings used are listed as per figure 4 and, for an example, the Spanish strings equivalents are shown in figure 5. If you compare the two resource files you will note that the name property for each string is identical but the value property is different. When the culture information is set to English, the strings contained in the first file will be collected and used to set the label text. If the culture information is set to Spanish, the strings in the second file shown (figure 5) will be collected and used to set the label text.
It has nothing to do with the coding the application but there are many useful software packages and web sites that will translate strings from one language into another. Once such web site is the Alta Vista Babel fish web site (figure 6). This web site is free to use and I have asked speakers of other languages as to the accuracy of the translations from English and have been told that they are generally pretty good. Naturally, if you are developing something professionally, you may wish to hire a translator to make sure that your translations are accurate and acceptable to the users.
Figure 4: English Strings
Figure 5: Spanish String Equivalents
Figure 6: The Alta Vista Babel Fish Translation Web Site (Lots of fun really)
By the way, if any of the translations in the demonstration project are offensive or incorrect, please take it out Babel Fish as I did in fact use it to translate all of the strings used in the demonstration from English into the other languages.
Summary
The purpose of this demonstration and article was to give a brief introduction into localization through the use of string resource files built to support several languages. As was mentioned in the introduction, this example is not by an means a complete and thorough discussion of the topic but it is a good introduction into one of the most important aspects of localization. This demonstration only showed the text of a few labels; the same approach could be applied to setting the text in button controls, the contents of list boxes or drop down lists, page titles, and whatever other controls might be used to display some sort of text.