Monday, March 23, 2009

Localized WPF Applications

Have you every worried about how you were going to localize your WPF applications?

The WinForms localization model is fairly mature, built into the designer, and utilizes satellite assemblies, that allow for post-build extension of your application. This has many advantages, including being able to farm the localization off to third parties, without requiring them to recompile the original application.

The WinForms model also lead to concise class wrappers and tags for your localized data. That made it easy to access both in the designer, and in the code-behind.

WPF doesn't seem to have the whole localization concept fully baked at the moment. In my opinion LocBaml is to oppresive. Requiring you to spread UID's throughout every XAML document you have, then manually edit every one of them to fit into the planned language.

I just want to localize the words. Can't I use the old satellite assembly approach, for string tables instead of the embedded pages (i.e., BAML resources)?

Yes you can. First decide if you even want the XAML to even be in your satellite resource assemblies. Microsoft says to add the tag into the project file. But, you can localize string tables without doing this.
  • In your project, add a .resx - "Resources File" (I prefer doing this instead of using the existing Settings file - for separation).
       [example: Properties\Resources.resx]
  • Open the resource file, and change the access modifier to "Public".
  • Add additional "Resources Files" at the same level, in the same folder. Inserting the appropriate localization code into the name.
       [example: Properties\Resources.de-DE.resx]
  • Clear the Custom Tool field in the Properties window for each of these files.
  • Open your XAML file and add a reference to the class wrapper namespace.
       [In this case WPFTest.Properties]
  • Then you can go ahead and use elements from the resource string table directly in you XAML
XAML:

<Window x:Class="WPFTest.Window1"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:res="clr-namespace:WPFTest.Properties"

   Title="Window1" SizeToContent="WidthAndHeight">

    <StackPanel>

        <Button Name="button1" Click="button1_Click">Button</Button>

        <Label Name="label1" Content="{x:Static res:Resources.TestString}" />

    </StackPanel>

</Window>

CS Code:

        private void button1_Click(object sender, RoutedEventArgs e)

        {

            Properties.Resources.Culture = new System.Globalization.CultureInfo("de-DE");

            Window1 wnd = new Window1();

            wnd.Show();

        }

Note: You need to set the culture for the resources (if you wish to override the current system settings), before you show the WPF window.

No comments: