MULTIMEDIA

Application Patterns and Tips : Localize a WPF Application

8/21/2012 4:10:40 PM
There are two methods of localizing a WPF application: using XAML and using resources and data binding. Unfortunately, either way, compared to Windows Forms applications, doing localization in WPF is currently a real chore. Table 1 highlights some of the pros and cons of the two approaches. Table 1. Pros and Cons of WPF Localization techniques ProsConsXAMLLocalization completely separate from development processMore efficient than data bindingEasy to modify CSV filesNo easy way to repeat process with UI updates, unless you are extremely good at version controlThe tool is unsupportedHard to integrate with resource filesNo Visual Studio supportResources and data bindingData-binding is easy and well-understood by WPF developersBindings are strongly typed and checked by the compilerResources are relatively easy to manage, and are similar to the other .Net platformsNo type conversionYou must manually map each UI element to a resourceOnly works on dependency propertiesSome tools, such as Blend, do not load resources from satellite assemblies (yet) XAML Localization To localize your WPF application using the XAML method, follow these steps: 1. Manually edit the project file and add <UICulture>en-US</UICulture> under the <PropertyGroup> section.2. Add this line to your AssemblyInfo.cs file: [assembly: NeutralResourcesLanguageAttribute("en-US", UltimateResourceFallbackLocation.Satellite)] 3. Open a command prompt and navigate to your project’s directory. Run the command: msbuild /t:updateuid This will generate a UID for every WPF element, modifying your XAML files in the process. You should never manually edit these UIDs. Note msbuild is located with the .Net framework files, and the easiest way to run it is to start the command prompt with the shortcut that Visual Studio installs; this will initialize the correct environment settings to access the .NET Framework binaries. 4. Rebuild the project. A directory called en-US will appear in the output directory. This contains the resource DLL.5. Obtain the LocBaml tool from the Windows SDK. On my computer, it was packaged in C:\Program Files\Microsoft SDKs\windows\v7.0\Samples\WPFSamples.zip. To get it to work in .Net 4, I had to recreate the project from scratch and change the target framework to .Net 4.0. By the time you read this, the tool may work out of the box. However, the tool is not officially supported by Microsoft. (Are you starting to get nervous about this method yet?)6. Copy LocBaml.exe, the generated resource DLL, and your application executable to the same folder and run this command from a prompt: locbaml.exe /parse myapp.resources.dll /out:translate_en-US.csv7. Copy the file translate_en-US.csv to files with different names, depending on your target cultures, e.g., translate_it-IT.csv, translate_fr-CA.csv.8. Open the csv files in a program that can edit them (such as any text editor or Excel) and translate the text into the target language. You can also modify things like file paths (in the case that you have different images for cultures, for example). Note It’s important to realize that other fields besides UI text will be present. When giving the files to translator, you may want to specify which fields need translating. 9. Create a new directory for the localized DLL, e.g. “it-IT.”10. Create a localized resource DLL by running: locbaml.exe /generate myapp.resources.dll /trans: translate_it-IT.csv /out :.\it-IT /cul:it-IT  Copy the resource directory to the output directory, next to the existing en-US directory. If you want to easily see the differences, you can add some code to the application startup that will set the UI culture to be to the region specified in Control Panel. public App() { //set UI to have whatever be same as non-UI, //which is what is in Control Panel Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; } As you can see, this method is a little complex and tedious, especially if you need to make changes after localization has begun (make sure you have excellent version control practices). It’s recommended that you build your own set of tools to manage this process, even if it’s just a set of batch files. Figures 1 and 2 show a localized WPF app running in English and Italian, with translated text and different resources. Figure 1. The localized app running in the default culture. Figure 2. Changing the system’s region to Italy causes the app to pick the localized DLL. If Windows were using the Italian language pack, then the Yes and No on the message box would also be in Italian. See the LocWPFXAML project in the sample code for a full example. Resource File Localization Rather than go through all of that, you can use resource files just like with Windows Forms. 1. Create a global resource file and add strings, images, etc. to it.2. Copy and rename it with the desired culture, e.g., Resources.it-IT.resx. (Make sure that this file is in the same directory as the original Resources.resx) Building the project should result in culture-specific directory being created under the output directory.3. Create an XML namespace Properties in the Window where you want to use the localized resource: xmlns:props="clr-namespace:LocWPFResources.Properties"4. Use data binding to attach the resources to XAML controls: <Label x:Name="labelName" Grid.Row="0" Grid.Column="0" Content="{x:Static props:Resources.labelName}" /> This is much simpler, but it does require more thought as you develop the UI of your application. Also, you can’t directly bind very much other than strings. For example, to use an image from resources in a XAML Image control, you can do something like this: public MainWindow() { InitializeComponent(); //set the image imageFlag.BeginInit(); imageFlag.Source = CreateImageSource(Properties.Resources.flag); imageFlag.EndInit(); } private ImageSource CreateImageSource(System.Drawing.Bitmap bitmap) { using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); stream.Position = 0; //the OnLoad option uses the stream immediately //so that we can dispose it return BitmapFrame.Create(stream,BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } } Note Given the complexities of localization, you should definitely give the topic a lot of thought before deciding on a strategy. I encourage you to read the whitepaper and look at the samples located at http://wpflocalization.codeplex.com/. See the LocWPFResources project in the sample code for a full example.
 Other

 Most View
 -  Building and Deploying Applications for Windows Azure : Creating a Demo Project
 -  Group Test: Integrated Valve Amps $2,175-$3,000 (Part 3)
 -  Algorithms for Compiler Design: STRAIGHTFORWARD CODE GENERATION
 -  Corel Painter X : Working with Layers - More Furniture
 -  Three Recent Arrivals Are Welcome Additions To The Market (Part 3)
 -  How To Disable The Windows 8 Lock Screen
 -  ASUS Eee Pad MeMO 171 - Got The MeMO?
 -  Rig Builder – May 2012 (Part 3)
 -  The ASP.NET AJAX Control Toolkit (part 1) - Installing
 Top 10
 -  Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 6)
 -  Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 5)
 -  Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 4)
 -  Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 3)
 -  Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 2)
 -  Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 1)
 -  Nook HD - A High-Definition Tablet With The Heart Of A Reader (Part 4)
 -  Nook HD - A High-Definition Tablet With The Heart Of A Reader (Part 3)
 -  Nook HD - A High-Definition Tablet With The Heart Of A Reader (Part 2)
 -  Nook HD - A High-Definition Tablet With The Heart Of A Reader (Part 1)