|
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".
Hi. Your paragraph that begins with "At this point (and this is where I
think the process turns from professional to hack) " seems incomplete.
Hi there,
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.
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
That's cool. I wrote a post recently on a wpf hiragana-katakana chart on my
blog. Small application, but localization is very nice.
Hi All,
{
int result = new int();
return int.TryParse(valueToCheck.ToString(), System.Globalization.NumberStyles.Any, CultureInfo.CurrentCulture, out result);
}
string culture = "zh-CN";
System.Threading.Thread.CurrentThread.CurrentUICulture =
new System.Globalization.CultureInfo(culture);
System.Threading.Thread.CurrentThread.CurrentCulture =
new System.Globalization.CultureInfo(culture);