The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








I heart FeedBurner

Latest Diggs - Programming

Computers Blogs - Blog Top Sites

Site Hits

Total: 2,821,584
since: 19 Jan 2005

Localizing a WPF Application

posted Tue 22 Aug 06
I will try not to get up on the soap box here, but I have been known to get a little rowdy in discussions about localization and globalization. In general (obviously things like budget, time, manpower are concerns) if you are building an application, then it should be ready for localization even if you don't actually have any alternate language translations available. This was a huge, huge concern with Windows Forms applications because the cost of going back into an existing application and retro-fitting it with the plumbing necessary to support multiple languages was pretty painful.

However, if the application was designed up front with localization in mind, and simply only shipped with an en-US culture out of the box, then it was just a matter of hiring a translation service, building a new alternate-culture satellite Assembly and Bob's your Uncle. It was at this point where I tended to get a little upset. I had been told numerous times in the past that it was too much time or effort to pre-fit an application with the ability to be localized in the future. This wasn't the case with Windows Forms and is most certainly not the case with Windows Presentation Foundation applications built on XAML.

This post will show you how to localize a WPF application and hopefully it will convince you that preparing for globalization in a WPF application is so simple that there's no excuse why it shouldn't be done. The first step in preparing the application for localization is setting the UI culture in the csproj file of a WPF application (put this tag in the first <PropertyGroup> tag you've got):

<UICulture>en-US</UICulture>

When you rebuild your application, you should now find a familiar satellite Assembly directory in bin\debug\en-US and obj\debug\en-US called (myapp).resources.dll. This is the language-specific satellite Assembly that now contains the entire GUI of your application, localized to that specific UI culture.

Next, you need to add UIDs to your application. The process of adding UIDs basically assigns a unique identifier for purposes of localization to each UI element within your visual stree. This step is required and is not optional. The only way to get around this step is if you have manually assigned UIDs to your visual elements while writing your XAML. Note that the Expression designers from MS do not create UIDs. To add UIDs to all your visual elements:

msbuild /t:updateuid (your app).csproj

Also, if you need to verify/double-check the status of UIDs within your elements:

msbuild /t:checkuid (your app).csproj

At this point (and this is where I think the process turns from professional to hack) you need to build the LocBaml tool that comes with the SDK samples. This tool takes the bamlall dependent Assemblies of the Assembly that you are extracting must be present. In other words, you need to have access to the root Assembly either in the current directory or in the GAC for LocBaml to create the CSV file. output by your application and turns it into a multi-column CSV file containing the raw data from the UI elements. Also note that when you run LocBaml,

For my sample, I have a simple XAML window that looks like this (after generating UIDs automatically using msbuild):

<Window x:Uid="Window_1" x:Class="LocalizableApplication.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Title="LocalizableApplication" Height="300" Width="300"
    >
    <Grid x:Uid="Grid_1">
      <TextBlock x:Uid="TextBlock_1" xml:lang="en-us"
              Text="Are you an american?" />
     </Grid>
    </Window>

At this point, run LocBaml to produce the CSV file. The command looks like this:

locbaml /parse (input en-US .resources satellite assembly) /out:english.csv

My CSV contained the text shown in the image below:

If you look closely you can see my TextBlock, TextBlock_1 in there with the default English text "Are you an american?". Running the application now looks like this:

At this point, at least this is the party line, you would hand the CSV file off to a translation service. Later, after sprinkling magical translation fairy dust upon your file, they would return with new CSV files like japanese.csv or hindi.csv or klingon.csv (you know you want Klingon, every app needs Klingon...)

So, you then issue the following command to create a second language satellite Assembly from the combination of the original satellite Assembly and the new CSV:

locbaml /generate MyApp.resources.dll /trans:japanese.csv /out:ja-JP /cul:ja-JP

This puts a new MyApp.resources.dll file in the ja-JP directory with the ja-JP culture. Now you can modify your regional setting from the control panel, or you can add the following code to your App.xaml.cs file (note that you can't get away with doing this in the Form constructor like you can in Windows Forms - WPF sets the culture on the thread much earlier than WinForms!):

CultureInfo ci = new CultureInfo("ja-JP");
  Thread.CurrentThread.CurrentCulture = ci;
  Thread.CurrentThread.CurrentUICulture = ci;

When you run the application now, it looks like this:

I didn't do the Unicode because the Japanese IME on my machine is pretty lame and didn't feel like manually entering the unicode for the hiragana, katakana, and kanji characters.

Hopefully this post is a convincing example that preparing an application for globalization is actually pretty easy. Also, if you look back up at the CSV file, you'll note that you can change all numeric values based on culture as well. This means that you can change the location, orientation, even scaling, of UI elements based on the culture so that the UI can be completely adapted to the host culture.

At times it felt as though Microsoft was giving localization the brush-off. Its a first-class citizen in VS 2005 for Windows Forms - you can use that editor to change all aspects of an application's localization, all the way down to switching languages within the IDE so you can visually see the new language's form right within the editor. I don't think it would've been that hard to provide for a similar experience with WPF and I'm a little dissapointed that you have to drop out of Visual Studio to use an SDK sample in order to get the job done.

The Expression Interactive Designer has a language property on the DocumentRoot of the XAML, but I didn't see any other really integrated support for swapping languages on the fly and seeing how each language change affects the XAML's appearance and functionality. That entire experience needs to be improved upon and either Microsoft will do it, or some 3rd party vendor is going to do it. Hopefully that functionality will find its way into "Orcas".

tags:            

links: digg this    del.icio.us    technorati    reddit




1. Denny Huber left...
Fri 10 Nov 06 11:40 am

Hi. Your paragraph that begins with "At this point (and this is where I think the process turns from professional to hack) " seems incomplete.

I cannot get this process to work, and I wonder if it is because I am working with the absolute latest SDK, which I downloaded Nov. 9, 2006.

Thanks, Denny Huber


2. Robin Wang left...
Mon 20 Nov 06 10:06 pm

Hi there,

LocBaml is using BAML localizatin API. I am wondering if there is a plan to enhance this API? I mean, without some work around, I do not seem to be able to get around the requirement that the related assemblies have to be present in teh same folder as LocBaml.exe. Anyone has an idea?


3. Alok left...
Thu 11 Jan 07 7:14 am

This does not work. It creates the csv file and satellite assemblie. But when the appliction is run it never picks up any satellite assembly other than en-US. Am i missing something.


4. Stephanie left...
Mon 15 Jan 07 6:20 am

It doesn't work for me either... Even though I have changed culture, it only picks the en-US assembly... Did someone get it to work? I'm using november 2006 CTP


5. Thomas Hollowy left...
Thu 17 May 07 8:53 am :: http://nyxtom.vox.com

That's cool. I wrote a post recently on a wpf hiragana-katakana chart on my blog. Small application, but localization is very nice.


6. Anima left...
Thu 27 Dec 07 8:20 am

Hi All,

I have a WPF application which supports globalization. But if user tries to enter Chinese numbers using IME pad in a numeric only textbox, the conversion logic to convert this entry to integer is failing.

Code I am using for conversion is:

private bool IsNumeric(char valueToCheck)

  • {

  • int result = new int();

  • return int.TryParse(valueToCheck.ToString(), System.Globalization.NumberStyles.Any, CultureInfo.CurrentCulture, out result);

  • }

I am checking if the entry is numeric or not, but this is returning false for chinese numbers.

I have set the culture of the application to Chinese by executing below lines:

  • string culture = "zh-CN";

  • System.Threading.Thread.CurrentThread.CurrentUICulture =

    • new System.Globalization.CultureInfo(culture);

  • System.Threading.Thread.CurrentThread.CurrentCulture =

    • new System.Globalization.CultureInfo(culture);

Thanks in advance Anima


Tag Related Posts

Smart, Deep Property Notifications in CLINQ v2.0

Tue 07 Oct 08 1:15 P GMT-05
tags:          

Microsoft's Lofty Direction

Sun 05 Oct 08 2:30 P GMT-05

MobileMe vs. Live Mesh Throwdown - Round 1

Wed 16 Jul 08 10:33 A GMT-05

One Framework to Rule them All

Mon 25 Feb 08 6:49 P GMT-05

CLINQ v1 Demo - Network Message Filtering

Wed 09 Jan 08 7:47 P GMT-05
tags:        

Building a Ledger Style for WPF Grids

Tue 21 Aug 07 3:30 P GMT-05
tags:    

My first "Acropolis" Application

Mon 04 Jun 07 1:40 P GMT-05
tags:      

Exploring the Delegate Design Pattern

Mon 14 May 07 6:30 P GMT-05

Will Silverlight be DOA?

Mon 16 Apr 07 8:02 P GMT-05

Exploring the MVC Pattern in WPF

Tue 10 Apr 07 12:51 P GMT-05
tags:                      

My Little Pony .NET Unleashed 2007

Fri 30 Mar 07 1:59 P GMT-05

Authorness

Thu 15 Mar 07 1:44 P GMT-05

WPF Bindings == WTF Bindings?

Mon 12 Mar 07 6:31 P GMT-05

On MUDs

Thu 08 Mar 07 5:00 A GMT-05
tags:                    

Cocoa Programming vs. WPF : NIB vs XAML

Tue 20 Feb 07 2:09 P GMT-05

Cocoa Bindings vs. WPF Binding

Thu 15 Feb 07 5:41 P GMT-05
tags:                

WPF Bumper Stickers

Tue 12 Dec 06 7:32 P GMT-05

Ulysses Agenda Makes Redmond Developer News

Wed 29 Nov 06 7:10 P GMT-05
tags:                

Is the continuous beta the new model for Vista?

Tue 21 Nov 06 8:51 P GMT-05
tags:              

Ulysses Agenda - Network Engine Test 1

Mon 09 Oct 06 2:26 A GMT-05
tags:              

ASP.NET vs Ruby on Rails : Round 2 (Agility)

Thu 05 Oct 06 11:02 A GMT-05
tags:                      

ASP.NET vs Ruby on Rails : Round 1

Wed 04 Oct 06 1:37 P GMT-05
tags:                

Ulysses Agenda : First Cut Networking Design

Thu 14 Sep 06 12:46 A GMT-05
tags:                  

First Impressions of Windows Vista RC1

Thu 07 Sep 06 1:30 P GMT-05
tags:                      

Localizing a WPF Application

Tue 22 Aug 06 11:39 A GMT-05
tags:            

WPF Slide Show and Photo Album

Fri 18 Aug 06 6:48 P GMT-05

Is Windows Workflow Foundation Too Complex?

Fri 18 Aug 06 12:15 P GMT-05

ADO.NET Entity Framework Announced Today!

Wed 16 Aug 06 11:08 A GMT-05