In this section, you create a simple Windows application that shows how to use Visual Studio 2008 or localization. This application does not use complex Windows Forms and does not have any real inner functionality be~ause the key feature it is intended to demonstrate here is localization. In the automatically generated source code, change the namespace to Wrox.ProCSharp .Local i za t ion and the class name to BookOfTheDayForm.The namespace is not only changed in the source file ookOfTheDayForm.cs but also in the project settings, so that all generated resource files will get this namespace, too. Youcan change the n!lmespace for all new items that are created by selecting Common Properties from the Project¢ Properties menu.
To show some issues with localization, this program has a picture, some text, a date, and a number. The picture shows a flag that is also localized. Figure 21-11 shows this form of the application as seen in he Windows Forms Designer The following table lists the values for the Name and Text properties of the Windows Forms elements.
might change depending on the current time of day. This example demonstrates that the localization for dynamically created dialogs must be done differently. In the method WelcomeMessage ( ), display a message box using MessageBox. Show (). Call the method WelcomeMessage () in the constructor of the form class BookOf’:’heDayForm, before the call to Ini tiali zeComponent ( ) . Here is the co.de for the method WelcomeMessage (): p~blic void WelcomeMessage()
The number and date in the form should be set by using formatting options. Add a new method, SetDa teAndNumber ( ), to set the values with the format option. In a real application, these values could be received from a Web service or a database, but this example is just concentrating on localization. The date is formatted using the Doption (to display the long date name). The number is displayed using the picture number format string ## II. II !If , 11I11, where II represents a digit and ” r ” is the group separator.
In the constructor of the BookOfTheDayForm class, both the WelcomeMessage () and SetDateAndNumber () methods are called
A magic feature of the Widows Forms Designer is started when you set the Localize property of the form from false to true. This results in the creation of an XML-based resource file for the dialog box that stores all resource strings, properties (including the location and size of Wmdows Forms elements), embedded pictures, and so on. In addition, the implementation of the Ini tializeComponent () method is changed; an instance of the class System. Resources. ResourceManager is created, and to get to the values and positions of the text fields and pictures, the
GetObj ect () method is used instead of writing the values directly into the code. GetObject () uses the CurrentUICul ture property of the current thread for finding the correct localization of thp resource. Here is part of InitializeComponent () from the file BookOfTheDayForm. Designer. Co before the < Locallization property is set to true, where all properties of textbox textile e are set:
The code for the IntializeComponent () method is automatically changed by setting the Localizable property to true:
Where does the resource manager get the data from? When the Localizable property is set to true, the resource file BookOfTheDay. resX is generated. In this file, you can find the scheme of the XML resource, followed by all elements in the form: Type, Text, Location, Tablndex, and so on. The class ComponentResourceManager is derived from ResourceManager and offers the method ApplyResources ( ) . With ApplyResources ( ), the resources that are defined with the second argument are applied to the object in the first argument. The following XML segment shows a few of the properties of textBoxTi tle: the Location property has a value of 13, 133; the Tablndex property has a value of 2; the Text property is set to Professional C#; and so on. For every value, the type of the value is stored as well. For example, the Location property is of type System. Drawing. Point, and this class can be found in the assembly Sys tern. Drawing. Why are the locations and sizes stored in this XML file? With translations, many strings have completely different sizes and no longer fit into the original positions. When the locations and sizes are all stored inside the resource file, everything that is needed for localizations is stored in these files, separate from the C# code:
When changing some of these resource values, it is not necessary to work directly with the XML code. You can change these resources directly in the Visual Studio 2008 Designer. Whenever you change the Language property of the form and the properties of some form elements, a new resource file is generated for the specified language. Create a German version of the form by setting the Language property to Geitnan, and a French version by setting the Language property to French. For every language, you get a resource file with the changed properties: in this case, BookOfTheDayForm. de. resX and BookOfTheDayForm. fr . resX The following table shows the changes needed for the German version.
The following table lists the changes for the French version.
By default, images are not moved to satellite assemblies. However, in the sample application, the flag should be different depending on the country. Todo this, you have to add the image of the American flag to the file Resources. resx. You can find this file in the Properties section of the Visual Studio Solution Explorer. With the resource editor, select the Images categories as shown in Figure 21-12,and add the file americanflag .bmp.To make localization with images possible, the image must have the same name in all languages. Here the image in the file Resources. resx has the name Flag. Youcan rename the image in the properties editor. Within the properties editor, you can also change whether the image should be linked or embedded. For best performance with resources, images are linked by default. With linked images, the image file must be delivered together with the application. If you want to embed the image within the assembly, you can change the Persistence property to Embedded
The localized versions of the flags can be added by copying the file Resource. resx to Resource de. resx and Resource. fr . resx and replacing the flags with GermanFlag .bmpand FranceFlag. bmp.Because a strongly typed resource class is needed only with the neutral resource, the property CustomTooi’can be cleared with the resource files of all specific languages. Compiling the project now creates a satellite assembly for each language. Inside the debug directory (or the release, depending on your active configuration), language subdirectories like de and fr are created. In such a subdirectory, you ‘will find the file BookOfTheDay. resources. dll. Such a file is a satellite assembly that includes only localized resources. Opening this assembly with ildasm, you see a manifest
with the embedded resources and a defined locale. The assembly has the locale de in the assembly attributes, so it can be found in the de subdirectory. Youcan also see the name of the resource with .mresource; it is prefixed with the namespace name Wrox. ProCSharp. Localization, followed by the class name BookOfTheDayFormand the language code de.
Changing the Culture Programmatically
After translating the resources and building the satellite assemblies, you will get the correct translations ‘1 depending on the configured culture for the user. The welcome message is not translated. at this time. This needs to be done in a different way, as you’ll see shortly.
In addition to the system configuration, it should be possible to send the language code as a commandline argument to your application for testing purposes. The BookOfTheDayForrn constructor is changed
to allow passig a culture string, and setting the culture depending on this string. A Culturelnfo ninstance is created to pass it to the CurrentCulture and CurrentUlCulture properties of the current thread. Remember that the CurrentCul ture is used for formatting, and the CurrentUICul ture is used for loading of resources.
The BookOfTheDayForrn is instantiated in the Main () method, which can be found in the file Program. cs. In this method, you pass the culture string to the BookOfTheDayForrn constructor
Now you can start the application by using command-line options. With the running application, you can see that the formatting options and the resources that were generated from the Windows Forms Designer show up. Figures 21-13 and 21-14 show two localizations in which the application is started with the command-line options de-DE and fr.
There is still a problem with the welcome mess e box: the strings are hard-coded inside the program. Because these strings are not properties of elen uts inside the form, the Forms Designer does not extract XMLresources as it does from the properties for Windows controls when changing the Localizable property of the form. Youhave to change this code yourself.
Using Custom Resource Messages
For the welcome message, you have to translate the hard-coded strings. The following table shows the translations for German and French. You can write custom resource messages directly in the file Resurces. resx and the language-specific derivations. Of course, you can also create a new resource file.
The source code of the method WelcomeMessage () must also be changed to use the resources. With strongly typed resources.jhere is no need to instantiate the ResourceManager class. Instead, the properties of the strongly typed resource can be used:
..vhenthe program is started using English, German, or French, you will get the message boxes shown in i-igures 21-15,21-16,and 21-17, respectively .
Automatic Fallback for Resources
For the French and German versions in the example, all the resources are inside the satellite assemblies. U not, then all the values of labels or text boxes are changed; this is not a problem at all.Youmust have only the values that will change in the satellite assembly; the other values will be taken from the parent assembly.For example, for de-at (~ustria), you could change the value for the GoodAfternoon resource to GrU~ Gott while leaving the other values intact. During runtime, when looking for the value of the resource Good Marning, which is not located in the de-at satellite assembly, the parent assembly would be searched. The parent for de-at is de. In cases where the de assembly does not have this resource either, the value would be searched for in the parent assembly of de, the neutral r ssembly.The neutral assembly does not have a culture code
It is an easy task to outsource translations using resource files. It is not necessary to install Visual Studio for translating resource files; a simple XML editor will suffice. The disadvantage of using an XML editor is that there is no real chance to rearrange Windows Forms elements and change the sizes if e.
translated text does not fit into the original borders of a label or button. Using a Windows Forms Designer to do translations is a natural choice.
Microsoft provides a tool as part of the .NET Framework SDK that fulfills all these requirements: the Windows Resource Localization Editor winres .exe (see Figure 21-18). Users working with this tool do not need access to the C# source files; only binary or XML-based resource files are needed for translations. After these translations are completed, you can import the resource files to the Visual Studio project to build satellite assemblies.
If you don’t want your translation bureau to change the sizes and locations of labels and buttons, and they cannot deal wish XML files, you can send a simple text-based file. With the command-line utility resgen. exe, you can create a text file from an XML file:
resgen myresource.resX myresource.txt
And after you have 1.ceived the translation from the translation bureau, you can create an XML file from the returned text file. Remember to add the culture name to the file name:
resgen myresource.es.txt myresource.es.resX.