Professional Documents
Culture Documents
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
Resources and
Localization
CHAPTER
7
In this chapter, you will
• Implement localizability for the user interface
• Convert existing encodings
• Implement right-to-left and left-to-right mirroring
• Prepare culture-specific formatting
Localization is rapidly becoming a central part of application development, not only for
building applications that can be used in different languages, but that also accurately
mirror the local culture of the client. Localization becomes paramount when you think
of web sites that will potentially be used by clients from all the corners of the world.
Localization is the process of writing software that is able to sense the user’s locale
and change its behavior based on that information. The user can change his or her locale by
making changes to the Regional Settings in the control panel.
The term culture refers to a combination of parameters and methods that allow a pro-
gram to adjust to the geographical location of the user. For example, the program can
correctly display the currency of a region and print it in the proper location (for exam-
ple, $42.00 for the United States and Canada; 42,00 kr for Sweden). The culture also
contains information on how to display dates and numbers.
One part of localization is the use of strings in the language of the region. In this
chapter you will learn how to use strings from many different cultures to write as generic
a program as possible. This will allow you the freedom to define the strings and re-
sources used in a program in a central store that can be maintained for multiple lan-
guages and locales.
All applications contain resources that can be centralized for better management,
such as the string literals used for labels and button controls. The .NET Framework
draws on the ancestry of Windows to provide resources for strings, images, icons, and
custom resources.
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:22 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
String Resources
String resources are language-specific strings that are made available to a program so
that the resource manager can find the properly localized string to use when the applica-
tion is executed on the user’s computer. Using string resources enables you to write code
that has no string literals in it—the literals are defined in either text files or XML-format-
ted resource files.
We will start with our old friend, the Hello World program, and localize it.
Using System;
class Hello
{
public static void Main()
{
Console.WriteLine("Welcome to the Hello Program");
Console.WriteLine("\n\nHello World!");
Console.WriteLine("\n\nSee you Later");
}
}
This program will always display the same thing, irrespective of where in the world it
is executed. To make the program display in German, we would have to create a new ver-
sion for Germany, and yet another version for any other language that might be needed.
This is an almost impossible situation to manage.
The way to start on the road towards localization is to move the strings out from the
program and store them in a separate file. In our example, the file will be named
strings.txt, and it is located in the same directory as the source file for the program.
It has this content:
This text file is not directly usable by itself—it needs to be compiled, and the tool that
is used to compile resource files is the resgen utility. To create a resource file from the
strings.txt file that can be embedded in an assembly, use the following command:
resgen strings.txt
The result is a new file named strings.resources that can be used in our program.
We also need to make some changes to our program to be able to use the new re-
source file. First we need to add some namespaces to support localization:
using System.Globalization;
using System.Resources;
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:22 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
PART II
EXAM TIP The name of the resource in the ResourceManager
constructor is case-sensitive: “string” is different from “String”.
Now we are ready to use the strings in the string resource file. We do that by using the
GetString() method of the Resource Manager:
Console.WriteLine(rm.GetString("txtHello"));
The final program will be as follows. The CultureInfo object is used to retrieve the
current culture with this statement:
CultureInfo ci = Thread.CurrentThread.CurrentCulture;
The current thread of our program uses the culture of the operating system for the UI
(user interface) culture, the current culture is what the user has configured in the Re-
gional Settings. To make the current thread’s UI culture the same as the current culture,
we use this statement:
Thread.CurrentThread.CurrentUICulture = gh.ci;
We also changed the name of the class to GlobalHello to indicate the global nature of
the program, and the file is now called HelloGlobalWorld.cs. Here’s the revised
program:
using System;
using System.Globalization;
using System.Resources;
using System.Reflection;
using System.Threading;
class GlobalHello {
// create the resource manager once only, it is resource heavy
static ResourceManager rm = new ResourceManager("strings",
Assembly.GetExecutingAssembly());
// create a culture information object
CultureInfo ci = Thread.CurrentThread.CurrentCulture;
public static void Main()
{
GlobalHello gh = new GlobalHello();
// ensure the current thread is using the culture
Thread.CurrentThread.CurrentUICulture = gh.ci;
// Display a welcome
Console.WriteLine(rm.GetString("txtGreeting"));
Console.Write("\n\n");
// say hello world
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:23 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
To compile the program use the csc compiler with the /res: switch to indicate the
default (fallback) resource to use:
C:\gc\global\demo>HelloGlobalWorld
Welcome to the Hello Program
Hello World!
If you go in now and change your Regional Setting in the control panel to French, and
you run the program again, there will not be any change to the output—there are no
French resources defined for the program yet. That’s what we need to do next.
To define language-specific resources, you will need to create a subdirectory under
the directory where the executable is located. For the French language, you use the
two-letter code from the RFC 1766 hierarchy to name the directory for French as fr;
other language codes are en for English, de for German, sv for Swedish, and so on. The
electronic documentation that comes along with Visual Studio .NET contains a com-
plete listing of the codes.
Once the directory is created, you need to create a language-specific string resource file
in the new directory. The following is an example of a language-specific string resource:
In order to make the resource available, you must compile it into a resource file (as
we did earlier for the English version) and then create a satellite assembly (for a refresher
on assemblies, see Chapter 6). It is important to remember that the naming of the file is
critical, and it is case-sensitive. The resource file we used as the fallback was called
strings.txt, so we will call the French version strings.fr.txt. When we com-
pile it using the resgen utility, the resulting resource will be called strings.fr
.resources.
To create the satellite assembly, you need to use the assembly-building utility, al,
as follows:
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:23 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
C:\gc\global\demo>HelloGlobalWorld
Bienvenue bonjour au programme
PART II
Bonjour Monde!
The language has changed to the language of the client’s Regional Settings.
Localized Formatting
Once the strings are localized, we need to look at the formatting of data such as cur-
rency, numbers, and the date and time. The localization of these items is done through
the boxing (conversion to objects) of the data.
As an example, the following code segment will create an int variable that is then
printed using the boxing of the int to an Int32, on which we can call the ToString
Figure 7-1
The Regional
Options
dialog box
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:23 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
int i = 420000000;
Console.WriteLine(" " + i.ToString("N"));
The resulting display depends on the client’s locale, as shown in the following examples:
The boxing technique is an elegant way of ensuring that the client’s locale is honored.
The same technique can be used with other data types, like double and long. The spe-
cial treatment of currency formatting takes the currency sign and position (pre or post)
into consideration, as well as the representation of the decimal and thousands separa-
tor. The following code segment will display the double 42.00 as currency using the cli-
ent’s locale:
double d = 42.00;
Console.WriteLine(" " + d.ToString("C"));
EXAM TIP The boxing operation, and the use of the ToString() method
makes the localization of numeric dates seamless.
Date and time values can be treated in the same fashion, and by taking advantage of
the formatting, we can display the date and time in a format familiar to the user. The fol-
lowing code does just that—the key again is to use the ToString() method to perform
the localized action:
DateTime dt = DateTime.Now;
Console.WriteLine(" " + dt.ToString("F"));
The following program is the final version of the HelloGlobalWorld program that is
localized to work with any culture:
using System;
using System.Globalization;
using System.Resources;
using System.Reflection;
using System.Threading;
class GlobalHello {
// create the resource manager once only, it is resource heavy
static ResourceManager rm = new ResourceManager("strings",
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:23 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
PART II
Console.Write("\n\n");
// say hello world
Console.WriteLine(rm.GetString("txtHello"));
Console.Write("\n\n");
// print out some numbers using the culture
// assign the value 420000000 to a variable and display it
int i = 420000000;
Console.Write("{0} " + rm.GetString("txtNumber"), i);
Console.WriteLine(" " + i.ToString("N"));
// print out 42.00 of the default currency for the culture
double d = 42.00;
Console.Write("{0} " + rm.GetString("txtCurrency"), d);
Console.WriteLine(" " + d.ToString("C"));
// print out todays date and week day using the culture
DateTime dt = DateTime.Now;
Console.Write(rm.GetString("txtDate"));
Console.WriteLine(" " + dt.ToString("F"));
// say bye
Console.WriteLine(rm.GetString("txtBye"));
}
}
Running this program with the regional setting for English would produce this output:
C:\gc\global\demo>HelloGlobalWorld
Welcome to the Hello Program
Hello World!
All the strings in this program are localized. There are no string literals used in the code,
nor are the numeric values displayed without using the formatting of the ToString()
method.
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:23 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
Implementing Right-to-Left
Mirroring and Encoding
For locales that use a right-to-left script direction, you will have to implement the proper
interface for direction, which is done by setting the RightToLeft property to
RightToLeft.Yes for all the controls and forms in the application. The controls on a
form all inherit the RightToLeft property of the form. In Figure 7-2 you can see the
property set to Yes, and that the form’s caption has moved to the right side of the win-
dow bar.
When working with ASP.NET pages, you must also work with RightToLeft script
direction as well as allow the UTF-8 encoding (Unicode characters encoded using UCS
Transformation Format, 8-bit form) to be used to send Unicode characters to the client.
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:24 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
PART II
To set the script direction, the element that needs the direction specified must have
the dir attribute set to rtl, as in the following Hebrew text inserted in the div element:
Best Practices
Localization is a State of Mind; it has to be designed into the application from the begin-
ning. There are some things that must be done to successfully implement a localized ap-
plication, and the following list highlights the most important rules:
The resources can be stored in satellite assemblies, as we have seen in this chapter,
or they can be added to a strongly-named assembly that is added to the GAC. The
naming of the resources is very important. The Resource Manager uses the names to
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:24 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
Summary
In this chapter you were introduced to the world of localization, and you used string re-
sources to turn our Hello World program into something that works all over the world.
You were also introduced to the RightToLeft script direction, as well as the encoding
needed to send 16-bit Unicode characters over the 8-bit Internet by using the UTF-8
encoding.
The need for localization will only grow as we continue towards a more integrated
world where software, and especially the Internet, will be global products working in
the culture of the client.
The next step in preparing for the C# exams is to look at how our code can be used to
generate its own documentation in XML format.
Test Questions
1. What is the code for the German language?
A. ge
B. gb
C. de
D. dk
2. What namespace contains the ResourceManager class?
A. System.Localization
B. System.Resources
C. System.Globalization
D. System.Threading
3. What is the process called that converts a primitive to a class?
A. Primary
B. Boxing
C. Conversion
D. Encoding
4. Which of the following code segments will correctly display the string resource
txtHello? (All objects are correctly created.)
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:24 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
PART II
A. Builds only the HelloGlobalWorld program.
B. Builds the HelloGlobalWorld and links the fallback resource.
C. Creates an assembly for the HelloGlobalWorld program.
D. Creates a name resolution report for the HelloGlobalWorld program.
6. When localizing a web application, you find that you need to encode Unicode
characters that are sent to the client. What attribute would you set?
A. ResponseEncoding="UTF-8"
B. Encoding="UTF-8"
C. ResponseCode="UTF-8"
D. EncodedResponse="UTF-8"
7. What happens when the Resource Manager fails to find the localized resource
for a locale?
A. It uses the closest locale.
B. It throws an exception.
C. Nothing, the resource will be blank.
D. It uses the fallback resource.
8. What namespace contains the CultureInfo class?
A. System.Localization
B. System.Resources
C. System.Globalization
D. System.Threading
9. Do you have to produce all the locale-specific assemblies before deploying the
application?
A. Yes, the assemblies must be present for the final compile of the application.
B. Yes, the fallback manifest must be built from all the satellite assemblies.
C. Yes, the .NET Framework must update the registry with all the information
at deployment.
D. No, the satellite assemblies can be deployed at will after initial deployment.
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:24 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:24 PM
Color profile: Generic CMYK printer profile
Composite DefaultAll-In-One
screen / MCAD/MCSD Visual C# .NET Certification All-in-One Exam Guide / Rempel & Lind / 222443-6 / Chapter 7
PART II
5. B.
6. A.
7. D.
8. C.
9. D.
10. B.
11. B.
12. D.
13. C.
14. C.
P:\010Comp\All-in-1\443-6\ch07.vp
Monday, August 26, 2002 12:11:24 PM