Chapter 15
Localization
What's in this chapter?
Understanding culture types
Getting culture settings from a thread
Declaring culture in ASP.NET
Understanding differences in dates
Understanding differences in currency and numbers
Understanding differences in sorting
Using culture specific resource files
As the audience for an application expands, businesses often realize they need to globalize the application. Of course, the ideal solution is to build the application to handle an international audience right from the start, but in most cases this may not be feasible because building for localized versions requires extra work and cost.
The core of any localization effort is the translation of resources and user interface changes. Such changes are application specific and, therefore, not really open to generic implementation across the multitude of potential cultures for which you might choose to target an application. However, some common elements of localization, such as date support or numeric and currency formats, can be implemented by .NET Framework classes.
The .NET Framework has made a considerable effort to support the internationalization of .NET applications. API support, server controls, and even Visual Studio itself equip you to do the extra work required to bring your application to an international audience. This chapter looks at some of the important items to consider when building your applications for the world.
Culture Code | Description |
en-US | English language; United States |
en-GB | English language; United Kingdom (Great Britain) |
en-AU | English language; Australia |
en-CA | English language; Canada |
fr-CA | French language; Canada |
The examples in this table define five distinct cultures. These five cultures have some similarities and some differences. Four of the cultures speak the same language (English), so the language code of “en” is used in these culture settings. Following the language setting is the region setting. Even though most of these cultures speak the same language, it is important to distinguish them further by setting their region (such as US for the United States, GB for the United Kingdom, AU for Australia, and CA for Canada). These settings reflect the fact that the English used in the United States is slightly different from the English used in the United Kingdom, and so forth. Beyond language, differences exist in how dates and numerical values are represented. This is why a culture's language and region are presented together.
The differences between the cultures in the table do not break down by region only. Many countries contain more than a single language, and each may have its own preference for notation of dates and other items. For example, en-CA specifies English speakers in Canada. Because Canada is not only an English-speaking country, it also includes the culture setting of fr-CA for French-speaking Canadians.
The culture definition just given is called a specific culture definition. This definition is as detailed as you can possibly get, defining both the language and the region. The other type of culture definition is a neutral culture definition. Each specific culture has a specified neutral culture with which it is associated. For instance, the English language cultures shown in the previous table are separate, but they also belong to one neutral culture: EN (English). The diagram presented in illustrates how these culture types relate to one another.
From this diagram, you can see that many specific cultures belong to a neutral culture. Higher in the hierarchy than the neutral culture is an invariant culture, which is an agnostic culture setting that should be utilized when passing items (such as dates and numbers) around a network. When performing these kinds of operations, you should make your back-end data flows devoid of user-specific culture settings. Instead, apply these settings in the business and presentation layers of your applications.
In addition, pay attention to neutral culture when working with your applications. In most cases, you are going to build applications with views that are more dependent on a neutral culture than on a specific culture. For instance, if you have a Spanish version of your application, you'll probably make this version available to all Spanish speakers regardless of where they live. In many applications, it won't matter whether the Spanish speaker is from Spain, Mexico, or Argentina. In cases where it does make a difference, use the specific culture settings.
When the end user requests an ASP.NET page or runs a Windows Forms dialog, the item is executed on a thread from the thread pool. That thread has a culture associated with it. You can get information about the culture of the thread programmatically and then check for particular details about that culture.
To see an example of working with a thread and reading the culture information of that thread, start with the basic WPF application created in Chapter 1. To reproduce this, create a new project called ProVB2012_Localization, and add the appropriate button and text box controls.
Add a new Sub DisplayCultureInfo and have it called by the Click event handler for the test button on the form. When the TestButton_Click event is fired, the user's culture information is retrieved and displayed in the TextBox control. The code for the new Sub is as follows (code file: MainWindow.xaml.vb):
Private Sub DisplayCultureInfo() Dim ci As New System.Globalization.CultureInfo( System.Threading.Thread.CurrentThread.CurrentCulture.ToString()) TextBoxResult.Text = "CURRENT CULTURE'S INFO" & Environment.NewLine TextBoxResult.Text += "Name: " & ci.Name & Environment.NewLine TextBoxResult.Text += "Parent Name: " & ci.Parent.Name & Environment.NewLine TextBoxResult.Text += "Display Name: " & ci.DisplayName & Environment.NewLine TextBoxResult.Text += "English Name: " & ci.EnglishName & Environment.NewLine TextBoxResult.Text += "Native Name: " & ci.NativeName & Environment.NewLine TextBoxResult.Text += "Three Letter ISO Name: " & ci.ThreeLetterISOLanguageName & Environment.NewLine TextBoxResult.Text += "Calendar Type: " & ci.Calendar.ToString() & Environment.NewLineEnd Sub
This simple form creates a CultureInfo object from the System.Globalization namespace and assigns the culture from the current thread that is running using the System.Threading.Thread .CurrentThread.CurrentCulture.ToString call. Once the CultureInfo object is populated with the end user's culture, details about that culture can be retrieved using a number of available properties that the CultureInfo object offers. Example results of running the form are shown in .
Note that in the code download there is an additional button on the form based on additional changes that are made to this sample project.
The CultureInfo object contains a number of properties that provide you with specific culture information. The items displayed are only a small sampling of what is available from this object. From this figure, you can see that the en-US culture is the default setting in which the thread executes. In addition to this, you can use the CultureInfo object to get at a lot of other descriptive information about the culture. You can always change a thread's culture on the overloads provided via a new instantiation of the CultureInfo object. The following code illustrates commenting out the original default line of code and replacing it with an explicit change of the current culture to Thailand (code file: MainWindow.xaml.vb):
Private Sub DisplayCultureInfo() System.Threading.Thread.CurrentThread.CurrentCulture = New Globalization.CultureInfo("th-TH") Dim ci As Globalization.CultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture ' Dim ci As New System.Globalization.CultureInfo( ' System.Threading.Thread.CurrentThread.CurrentCulture.ToString()) TextBoxResult.Text = "CURRENT CULTURE'S INFO" & Environment.NewLine TextBoxResult.Text += "Name: " & ci.Name & Environment.NewLine TextBoxResult.Text += "Parent Name: " & ci.Parent.Name & Environment.NewLine TextBoxResult.Text += "Display Name: " & ci.DisplayName & Environment.NewLine TextBoxResult.Text += "English Name: " & ci.EnglishName & Environment.NewLine TextBoxResult.Text += "Native Name: " & ci.NativeName & Environment.NewLine TextBoxResult.Text += "Three Letter ISO Name: " & ci.ThreeLetterISOLanguageName & Environment.NewLine TextBoxResult.Text += "Calendar Type: " & ci.Calendar.ToString() & Environment.NewLineEnd Sub
In this example, only a couple of lines of code are changed to assign a new instance of the CultureInfo object to the CurrentCulture property of the thread being executed by the application. The culture setting enables the CultureInfo object to define the culture you want to utilize. In this case, the Thai language of Thailand is assigned. The results produced in the TextBox control are illustrated in .
From this figure, you can see that the .NET Framework provides the native name of the language used even if it is not a Latin-based letter style. In this case, the results are presented for the Thai language in Thailand, including some of the properties associated with this culture (such as an entirely different calendar than the one used in Western Europe and the United States).
ASP.NET enables you to easily define the culture that is used either by your entire ASP.NET application or by a specific page within your Web application, using what are termed server-side culture declarations. You can specify the culture for any of your ASP.NET applications by means of the appropriate configuration files. To demonstrate this, close the ProVB2010_Localization application you started with and create a new ASP.NET Empty Web Site called ProVB_Russian. Alternatively, you can open this download folder as a website in Visual Studio 2012. Once the site has been created add a default.aspx page. On this blank page add a new Calendar control from the toolbox, following the text: Welcome to ASP.NET!
To change the default language used by this control, you can specify culture settings in the web.config file of the application itself, as illustrated here (code file: web.config):
<configuration> <system.web> <globalization culture="ru-RU" uiCulture="ru-RU" /> </system.web> </configuration>
Only the <globalization> line will need to be added to your default web.config file; it should also be noted that based on the following page-specific settings, this line has been commented out in the code download.
Note the two attributes represented: culture and uiCulture. The culture attribute enables you to define the culture to use for processing incoming requests, whereas the uiCulture attribute enables you to define the default culture needed to process any resource files in the application (use of these attributes is covered later in the chapter).
Note that one additional option you have when specifying a culture on the server is to define this culture in the root web.config file for the server. Thus, if you are setting up a web server that will be used with only a single culture, you can specify that culture at the server level, instead of needing to specify it as part of the settings for each application running on the server. This can be useful if you are installing Web applications created outside of your native culture, but where you want date, currency, sorting, and similar formats to default appropriately.
In the preceding snippet, the culture established for this ASP.NET application is the Russian language in the country of Russia. In addition to setting the culture at either the server-wide or the application-wide level, another option is to set the culture at the page level, as shown in the following snippet.
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" UICulture="ru-RU" Culture="ru-RU"%> %>
This example specifies that the Russian language and culture settings are used for everything on the page. You can see this in action by using this @Page directive and a simple Calendar control on the page. shows the output. Notice that marking the page as using Russian settings does not automatically translate text within the page; it only updates the embedded control added to the page.
In addition to using server-side settings to define the culture for your ASP.NET pages, you also have the option to define the culture according to what the client has set as his or her preference in a browser instance.
When end users install Microsoft's Internet Explorer or some other browser, they have the option to select their preferred cultures in a particular order (if they have selected more than a single culture preference). To see this in action in IE, select Tools ⇒ Internet Options from the IE menu. On the first tab provided (General) is a Languages button at the bottom of the dialog. Select this button and you are provided with the Language Preference dialog shown in .
To add any additional cultures to the list, click the Add button and select the appropriate culture from the list. After you have selected any cultures present in the list, you can select the order in which you prefer to use them. Thus, a user with multiple settings in this list will have a version of the application with their first language choice before anything else; if a version that supports that language is not available, their second and then consecutive versions are checked. The first available language matching one of their preferences will be presented.
Making language selections, the end user can leverage the automatic culture recognition feature provided in ASP.NET. Instead of specifying a distinct culture in any of the configuration files or from the @Page directive, you can also state that ASP.NET should automatically select the culture provided by the end user requesting the page. This is done using the auto keyword, as illustrated here:
<%@ Page UICulture="auto" Culture="auto" %>
With this construction in your page, the dates, calendars, and numbers appear in the preferred culture of the requester. What happens if you have translated resources in resource files (shown later in the chapter) that depend on a culture specification? Or what if you have only specific translations and therefore can't handle every possible culture that might be returned to your ASP.NET page? In this case, you can specify the auto option with an additional fallback option if ASP.NET cannot find any of the culture settings of the user (such as culture-specific resource files). This usage is illustrated in the following code:
<%@ Page UICulture="auto:en-US" Culture="auto:en-US" %>
In this case, the automatic detection is utilized; but if the culture preferred by the end user is not present, then en-US is used.
Clearly, the formats used to represent a date/time value can be dramatically different between cultures—some, such as Saudi Arabia (ar-SA) and Thailand, (th-TH) use entirely different calendar baselines.
In addition to date/time values, numbers are displayed quite differently from one culture to the next. How can a number be represented differently in different cultures? Well, it has less to do with the actual number (although certain cultures use different number symbols) and more to do with how the number separators are used for decimals or for showing amounts such as thousands, millions, and more. For instance, in the English culture of the United States (en-US), numbers are represented in the following fashion:
5,123,456.00
From this example, you can see that the en-US culture uses a comma as a separator for thousands and a period for signifying the start of any decimals that might appear after the number is presented. It is quite different when working with other cultures. The following snippet shows an example of representing numbers in other cultures (code file: MainWindow.xaml.vb):
Private Sub Numbers() Dim myNumber As Double = 5123456.0 Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("n") & Environment.NewLine Thread.CurrentThread.CurrentCulture = New CultureInfo("vi-VN") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("n") & Environment.NewLine Thread.CurrentThread.CurrentCulture = New CultureInfo("fi-FI") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("n") & Environment.NewLine Thread.CurrentThread.CurrentCulture = New CultureInfo("fr-CH") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("n") & Environment.NewLine End Sub
Adding this code to your project and running it from the click event produces the results shown in .
As you can see, cultures show numbers in numerous different formats. The second culture listed in the figure, vi-VN (Vietnamese in Vietnam), constructs a number exactly the opposite from the way it is constructed in en-US. The Vietnamese culture uses periods for the thousand separators and a comma for signifying decimals, a somewhat common format around the world. Finnish uses spaces for the thousand separators and a comma for the decimal separator, whereas the French-speaking Swiss use an apostrophe for separating thousands, and a period for the decimal separator. This demonstrates that not only do you need to consider dates and language constructs, but that it is also important to “translate” numbers to the proper format so that users of your application can properly understand the numbers represented.
Another scenario in which you represent numbers is when working with currencies. It is one thing to convert currencies so that end users understand the proper value of an item; it is another to translate the construction of the currency just as you would a basic number.
Each culture has a distinct currency symbol used to signify that a number represented is an actual currency value. For instance, the en-US culture represents currency in the following format:
$5,123,456.00
The en-US culture uses a U.S. dollar symbol ($), and the location of this symbol is just as important as the symbol itself. For en-US, the $ symbol directly precedes the currency value (with no space in between the symbol and the first character of the number). Other cultures use different symbols to represent currency and often place those currency symbols in different locations.
Create another Sub that can be called from the button's click event handler, and this time format the same numbers using the built-in .NET currency formatting shown here (code file: MainWindow.xaml.vb):
Private Sub Currency() Dim myNumber As Double = 5123456.0 Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("c") & Environment.NewLine Thread.CurrentThread.CurrentCulture = New CultureInfo("vi-VN") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("c") & Environment.NewLine Thread.CurrentThread.CurrentCulture = New CultureInfo("fi-FI") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("c") & Environment.NewLine Thread.CurrentThread.CurrentCulture = New CultureInfo("fr-CH") TextBoxResult.Text += Thread.CurrentThread.CurrentCulture.EnglishName & " : " & myNumber.ToString("c") & Environment.NewLine End Sub
Executing this code displays the output shown in .
Not only are the numbers constructed quite differently from one another, but the currency symbol and the location of the symbol in regard to the number are quite different as well.
Note that when you are using currencies on an ASP.NET page and you have provided an automatic culture setting for the page as a whole (such as setting the culture in the @Page directive), you need to specify a specific culture for the currency that is the same in all cases. Unlike dates, for which the differences are primarily display oriented, with a currency there is an expectation of value conversion. Thus, reformatting a currency can cause expensive errors unless you are actually doing a currency conversion.
For instance, if you are specifying a U.S. dollar currency value in your data, you do not want your ASP.NET page to display that value as something else (for example, the euro) based on translating the remainder of the page information to another language. Of course, if you actually performed a currency conversion and showed the appropriate euro value along with the culture specification of the currency, that makes sense and is the best solution.
Therefore, if you are using an automatic culture setting on your ASP.NET page and you are not converting the currency, you should perform something similar to the following code for currency values:
Dim myNumber As Double = 5123456.00 Dim usCurr As CultureInfo = New CultureInfo("en-US") Response.Write(myNumber.ToString("c", usCurr))
You have learned to translate textual values and alter the construction of the numbers, date/time values, currencies, and more when you are globalizing an application. You should also take care when applying culture settings to some of the programmatic behaviors that you establish for values in your applications. One operation that can change based upon the culture setting applied is how .NET sorts strings. You might think that all cultures sort strings in the same way (and generally they do), but sometimes differences exist. For example, the following snippet shows a sorting operation occurring in the en-US culture (code file: MainWindow.xaml.vb):
Private Sub Sorting() Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") 'Thread.CurrentThread.CurrentCulture = New CultureInfo("fi-FI") Dim myList As List(Of String) = New List(Of String) myList.Add("Washington D.C.") myList.Add("Helsinki") myList.Add("Moscow") myList.Add("Warsaw") myList.Add("Vienna") myList.Add("Tokyo") myList.Sort() For Each item As String In myList TextBoxResult.Text += item.ToString() & Environment.NewLine Next End Sub
For this example to work, you have to reference the System.Collections and the System.Collections.Generic namespaces, because this example makes use of the List(Of String) object.
In this example, a generic list of capitals from various countries of the world is created in random order. Then the Sort method of the generic List(Of String) object is invoked. This sorting operation sorts the strings according to how sorting is done for the defined culture in which the application thread is running. The preceding code shows the sorting as it is done for the en-US culture. The result of this operation when used within the ProVB2012_Localization form is shown in .
This is pretty much what you would expect. Now, however, change the previous example so that the culture is set to the Finnish culture. Do this by uncommenting the second line of the Sub Sorting and commenting out the first line of the Sub Sorting which sets the “en-US” culture settings, in the preceding snippet.
If you run the same bit of code under the Finnish culture setting, you get the results presented in .
Comparing the Finnish culture sorting shown in and the U.S. English culture sorting done in , you can see that the city of Vienna is in a different place in the Finnish version. This is because in the Finnish language, there is no difference between the letter V and the letter W. Therefore, if you are sorting using the Finnish culture setting, Vi comes after Wa, and thus Vienna appears last in the list of strings in the sorting operation.
Selecting Generate Local Resource from the Tools menu causes Visual Studio to create an App_LocalResources folder in your project if you don't have one already. A .resx file based upon this ASP.NET page is then placed in the folder. For instance, if you are working with the Default.aspx page, then the resource file is named Default.aspx.resx (see ).
Right-click on the .resx file; select View Code. If View Code isn't present on your default menu, select Open With; you'll get a dialog with a list of editor options. From the Open With dialog, select the XML (Text) Editor as the program to open this file using the OK button. After doing this, you should find the View Code option on the context menu for this file. When the .resx file opens, you'll notice that the .resx file is nothing more than an XML file with an associated schema at the beginning of the document. The resource file that is generated for you takes every possible property of every translatable control on the page and gives each item a key value that can be referenced in your ASP.NET page. Looking at the page's code, note that all the text values you placed in the page have been retained, but they have also been placed inside the resource file. Visual Studio changed the code of the Default.aspx page in two places as follows (code file: Default.aspx):
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="ProVB_Localization._Default" culture="auto" meta:resourcekey="PageResource1" uiculture="auto" %> <div> <asp:Label ID="Label1" runat="server" Text="What is your name?" meta:resourcekey="Label1Resource1"> </asp:Label><br /> <br /> <asp:TextBox ID="TextBox1" runat="server" meta:resourcekey="TextBox1Resource1"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Submit Name" meta:resourcekey="Button1Resource1" /><br /> <br /> <asp:Label ID="Label2" runat="server" meta:resourcekey="Label2Resource1"> </asp:Label> </div>
From this bit of code, you can see that the Culture and UICulture attributes have been added to the @Page directive with a value of auto, thus, enabling this application to be localized. In addition, the attribute meta:resourcekey has been added to each of the controls, along with an associated value. This is the key from the .resx file that was created on your behalf. Double-clicking on the Default.aspx.resx file opens the resource file in the Resource Editor, shown in , built into Visual Studio. Keep in mind the code download will have additional settings not shown if you are working along with the chapter.
Note that a few properties from each of the server controls have been defined in the resource file. For instance, the Button server control has its Text and ToolTip properties exposed in this resource file, and the Visual Studio localization tool has pulled the default Text property value from the control based on what you placed there. Looking more closely at the Button server control constructions in this file, you can see that both the Text and ToolTip properties have a defining Button1Resource1 value preceding the property name. This is the key that is used in the Button server control shown earlier.
<asp:Button ID="Button1" runat="server" Text="Submit Name" meta:resourcekey="Button1Resource1" />
In the following aspx source, a meta:resourcekey attribute has been added to a Button control. In this case it references Button1Resource1. All the properties using this key in the resource file (for example, the Text and ToolTip properties) are applied to this Button server control at run time.
The Default.aspx.resx file created in the last section is used by the application as the default or invariant culture. No specific culture is assigned to this resource file. If for a given request no culture can be determined, then this is the resource file that is utilized. To add another resource file for the Default.aspx page that handles another language altogether, right click the App_LocalResources folder and select Add Í Resources File from the context menu. Use the name Default.aspx.fi-FI .resx for your new file. Next click on the top left corner of your original .resx file, which will select all, then right-click and select copy. Now return to your newly created file and paste the contents into your file. Finally give the following keys the values shown to make a Finnish-language resource file:
Button1Resource1.Text Lähetä Nimi Label1Resource1.Text Mikä sinun nimi on?
Once you have created this file, take an additional step and assign a value to the Label2Resource1 .Text entry. The Default.aspx.resx file should have the following key value pair:
Label2Resource1.Text Hello
You can add a value to the same key in the Default.aspx.fi-FI.resx file as shown here:
Label2Resource1.Text Hei
You now have resources for specific controls, and a resource that you can access later programmatically.
Finalizing the Default.aspx page, you want to add a Button1_Click event so that when the end user enters a name into the text box and clicks the Submit button, the Label2 server control provides a greeting pulled from the local resource files. When all is said and done, your default page should have a code-behind element that matches the following snippet:
Label2.Text = GetLocalResourceObject("Label2Resource1.Text") & " " & TextBox1.Text
In addition to pulling local resources using the meta:resourcekey attribute in the server controls on the page to access the exposed attributes, you can also access any property value contained in the local resource file by using the GetLocalResourceObject. When using GetLocalResourceObject, you simply use the name of the key as a parameter, as shown here:
GetLocalResourceObject("Label2Resource1.Text")
With the code from the Default.aspx page in place and the resource files completed, you can run the page, entering a name in the text box and then clicking the Submit Name button to get a response, as shown in .
What happened behind the scenes that caused this page to be constructed in this manner? First, only two resource files—Default.aspx.resx and Default.aspx.fi-FI.resx—are available. The Default.aspx.resx resource file is the invariant culture resource file, whereas the Default.aspx.fi-FI.resx resource file is for a specific culture (fi-FI). Because the browser requesting the Default.aspx page was set to en-US as the preferred culture, ASP.NET found the local resources for the Default.aspx page. From there, ASP.NET checked for an en-US-specific version of the Default.aspx page. Because there isn't a specific page for the en-US culture, ASP.NET checked for an EN-(neutral culture)-specific page. Not finding a page for the EN neutral culture, ASP.NET was then forced to use the invariant culture resource file of Default.aspx.resx, producing the page shown in .
If you now set your IE language preference as fi-FI and rerun the Default.aspx page, you'll see a Finnish version of the page, as shown in .
In this case, having set the IE language preference to fi-FI, you are presented with this culture's page instead of the invariant culture page presented earlier. ASP.NET found this specific culture through use of the Default.aspx.fi-FI.resx resource file.
You can see that all the control properties that were translated and placed within the resource file are utilized automatically by ASP.NET, including the page title presented in the title bar of IE.
When you are working with the resource files from this example, note that one of the resources is for a specific culture. The Default.aspx.fi-FI.resx file is for a specific culture—the Finnish language as spoken in Finland. Another option would be to make this file work not for a specific culture, but instead for a neutral culture. To do so, simply name the file Default.aspx.FI.resx. In this case, it doesn't make any difference because no other countries speak Finnish; but it would make sense for languages such as German, Spanish, or French, which are spoken in multiple countries.
For instance, if you are going to have a Spanish version of the Default.aspx page, you could definitely build it for a specific culture, such as Default.aspx.es-MX.resx. This construction is for the Spanish language as spoken in Mexico. With this in place, if someone requests the Default.aspx page with the language setting of es-MX, that user is provided with the contents of this resource file. If the requester has a setting of es-ES, he or she will not get the Default.aspx.es-MX.resx resource file, but the invariant culture resource file of Default.aspx.resx. If you are going to make only a single translation for your site or any of your pages, construct the resource files to be for neutral cultures, not specific cultures.
If you have the resource file Default.aspx.ES.resx, then it won't matter if the end user's preferred setting is set to es-MX, es-ES, or even es-AR—that user gets the appropriate ES neutral-culture version of the page.
Rather than having just a generic set of tools, when working with Visual Studio 2012 on Windows 8 Microsoft has created a separate set of language-specific tool kits. Called the “Multilingual App Toolkit for Visual Studio 2012” these kits (which vary by language) provide you the tools to help you localize your Windows Store application. They provide translation support, management of resource files and editor tools.
Before you work at localizing a Windows Store application, you need to install a copy of this toolkit on your Windows 8 development machine. Next load the solution containing the project you want to localize and select that project in the Solution Explorer. With the project selected you'll find that the top option on the Tools menu for Visual Studio is “Enable Multilingual App Toolkit.”
Selecting that option will add a new folder to your solution called MultilingualResources. By default within this folder you will see a newly created Pseudo Language file. This .xlf file is used to hold a series of test strings associated with your custom localization efforts. If in a brand new application you double-click on this file you'll find that the Multilingual Editor opens as shown in .
Windows Store applications use a combination of .xlf file extensions for the language resources and .resw files to define the resources. The .xlf file extension relates to the industry standard XLIFF localization interchange file format. This format, which is defined on the www.oasis-open .org website, describes a standard extensible XML vocabulary that allows for easy interchange of translation files.
These files are assigned a default source and target language. Then they apply xml tags within a trans-unit structure to define the source and target strings for translation. Each trans-unit is named and has the potential to include additional alternative language definitions that essentially allow you to provide multiple target translations for each source string.
Unlike the previously described .resx files, Windows Store applications use .resw files. The good news is that these file formats are very similar, so similar, in fact, that the easiest way to transfer a .resx file to a Windows application is to create the necessary folders in your application and then copy in the .resx file and rename it as an .resw file. That will transfer your resource mappings. However, you will place only a single .resw file in your project, because you'll leverage the .xlf files and language editors to handle your translations.
Once you've added a .resw file to your project, you can then choose to add additional language. Right-click on the project file that you are looking to localize. Within the context menu you will find a new option to “Add Translation Languages.” Selecting this option will open the dialog shown in , from which you can select the languages you would like to support.
As shown in , there is the option to select the neutral language (es) or to specify a culture and language that you would like to target. Each language you add will create a separate .xlf file to your multilingual resources folder in your project. You can then use the Multilingual Editor to create and maintain your translations.
This chapter looked at some of the localization tools available to you. It started with a review of the culture types and how to determine the preferred culture for either a thread or Web request. It looked at understanding how different cultures may treat the same date or number differently for display and, just as important, how .NET can automate this handling for you. It also examined differences with currency with a warning about the need to convert a value and not just swap the display formatting when dealing with currency. The chapter then looked at how .NET supports the use of multiple resource files to provide support for different languages and cultures.
While .NET has provided many tools to help you with this process, you should keep in mind that these tools only make the process easier when looking at the built-in features of controls, not the application specific text and layout; when you want to localize an application, you need to plan to work with someone familiar with the language, and ideally the culture, you will target.
In addition to making many of the changes described in this chapter, localization is a process that requires consideration of multiple different time zones, consideration for information that reads Left to Right versus cultures that expect information to flow Right to Left, and other issues that are outside the scope of the tools you use. While that seems like a lot, you'll note that the same concepts for using resource files exist across the different .NET solution templates.
The next chapter takes you from the topics in this chapter, which focused on how to make your application user interface work with different cultures, to writing service applications that have little or no user interface.