Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs
Contact   •   Articles   •   Products   •   Support   •   Search
Ad-free experience sponsored by:
ASPOSE - the market leader of .NET and Java APIs for file formats – natively work with DOCX, XLSX, PPT, PDF, images and more

Resx and BAML Resources in WPF


:P
On this page:

If there’s one thing that’s confusing as heck about Localization in WPF it’s how resources are loaded. The two major approaches for localization in WPF – using LocBaml BAML resource localization or standard Resx Localization with MarkupExtensions  – stand at odds in what they expect for their resource loading requirements.

BAML Resources

When using the LocBaml approach that creates localized BAML resources it’s necessary to specify the <UICulture> key in the project file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <UICulture>en-US</UICulture>

You also need to specify at the assembly level what the neutral culture is and that ALL resources need to be stored in external satellite resources including the neutral culture:

[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]

This setting tells the runtime to look for the final fallback not in the MainAssembly, but in a satellite assembly.For BAML localization both of these settings must be made or localized BAML content won’t load. Effectively these two settings result in no resources being stored in the main assembly.

When both settings are made the compiler emits the default BAML resources – basically those XAML documents you’ve created – into an en-US folder in the target output folder. When enabled WPF will expect resources to be loaded from these resource directories including the default ‘neutral’ resources.

If localization is enabled and you try to set the UltimateFallbackLocation.MainAssembly you’ll run into the unfortunate result that your BAML Resources could not be found even for the neutral/default language. MainAssembly is the default setting for the flag, but it will only work if localization is not enabled and the <UICulture> flag is not set in the project file.

Bottom line: If you are localizing BAML resources  both settings are required and you have to use satellite assemblies for everything including the neutral culture.

Resx Resources and BAML Resources in the same Project: Resource Hell

LocBaml is a pretty unstable solution that has lots of issues, but fortunately Resx resources also still work in WPF. You can use Resx resources through code, by binding static resource values ( Content=”{x:static res:Resources.HelloWorld}”) to strongly typed resources or by using one of the many custom localization markup extensions that are available.

Here’s where things get confusing though – if you are mixing approaches with BAML and Resx localization you need to be real careful how to set up your Resx resources because of the  required UltimateResourceFallbackLocation.Satellite setting used.

Specifically at design time you need to create a non-culture specific .resx file like Resources.resx. You can then create your culture specific versions as well (Resources.de.resx). Normally you’d expect that’s enough, but because of the Satellite export of resources even the neutral culture gets exported to an external resource assembly in the en-US folder. This means in addition to Resources.resx you also need to have Resources.en-US.resx in your project! At runtime .NET only looks for the en-US version for that particular culture as well as the fallback culture when a specific or non-specific culture can’t be mapped.

Assuming my neutral culture is en-US here’s what this looks like in the VS Project:

Resources

Notice both ResxResources.resx and ResxResource.en-US.resx. The former is never used at runtime, but required in order to provide the strongly typed class.

You might think that why can’t we just skip the ResxResource.resx file and JUST create the the ResxResource.en-US.resx file. While that works just fine for compilation at runtime, if you want strongly typed resources the non-culture version of the resources is the only one that generates the strongly typed resource class.

Bottom Line: You’ll want to work with Resource.resx and then also copy that file to Resources.en-US.resx when keys change or use a build task to automate this process.

That’s pretty annoying, but it gets even worse: Microsoft Blend doesn’t load resources from satellite assemblies and since this approach effectively requires that resources are loaded from satellite assemblies any binding against resources or use of markup extensions that retrieve even neutral resources in Blend will fail with an error that Resources could not be loaded. Now that’s a big bummer especially after building a markup extension and having it work in the Visual Studio Cider designer.

NOTE: This tedious copy process is required only if you use both localized BAML and Resx resources in the same project and you have the <UICulture> key set in your project file.

Running only Resx Resources

Things are much easier if you don’t localize BAML resources and only work with Resx resources. In this scenario don’t specify the <UICulture> key in your project file or remove it if it was there before. Then set your assembly NeutralResourcesLanguage attribute to compile the neutral resources into the main assembly:

[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)]

In this set up you can work with resources the way you always have in WinForms and classlibrary projects where neutral resources are retrieved from the main assembly and any localized resources are retrieved from satellite assemblies. This means you just create your neutral resources in Resources.resx (or whatever other file) and create only your translated cultures in Resources.de.resx and so on. No copying for the explicitly fallback culture. Nice and logical the way you would expect it to work.

With the neutral fallback resources stored in the main assembly Expression Blend is also happy and  now loads static resources and markup extension bound resources without issues.

Confused?

If you think all of this sounds confusing as hell you’re not alone. While working on this I found dozens of questions regarding resource load failures. This stuff isn’t real obvious and worst of all the behavior that BAML resources introduces are partially incompatible with the standard Resx resources. It also doesn’t help that Microsoft has practically no guidance on this matter. Oh wait – I’m supposed to be writing that :-}

Hopefully this will help some of you out. I know I wish had seen something along these lines a couple of weeks back when I was ramming my head against the wall wondering why BAML resources were working and Resx Resources continued to fail. The more I see the more I wonder who should be strapped to a wheel for throwing LocBaml into the localization mix for WPF. I’ll have more on that in my next post.

Posted in WPF  Localization  

The Voices of Reason


 

RoundRobin
August 13, 2009

# re: Resx and BAML Resources in WPF

Just came across this writing while looking for a BAML editor.

I personally work in software localization quite extensively. I appreciate your thoughts, but I have to admit that I do not think either one of the 2 approaches you discussed is ideal, let alone the problems and confusions those approaches will bring.

As a developer, one should not set aside too much effort to make the applciation internationalized (it is not that it is not important). I think Microsoft has provided quite a good set of guideline along with Visual Studio to help developers write code and support more than one language - especially so in WPF. Th eproblem is the lack of tools that are based on well documented specifications, for example, there is no such public spec from Microsoft on how to render and edit BAML directly.

In regard to your points,

- LocBAML does not necessarily require netural resources to be separated from main assembly
- Resx with XAML extension is too complicated, especially with custom WPF controls and is not supported by standard VS XAML editor

Here is the streamlined approach to WPF localizaztion that I think will simplify the process.

- Developer writes the code as normal, using standard tools in Visual Studio (XAML editor etc)
- Make the XAML localizable
- Compile the application. The localizable resources will be embedded in main assembly as culture neutral
- Localization process uses a tool like LocBAML (more advanced) to extract resources, translate them, generate satellite assemblies
- Package the main asssembly and satellite assemblies. Done.

Your thoughts?

What I set out to do is to find (or create) a resource editor for BAML. Remember those days when one can open an executable or DLL in Visual Studio in "Resouce" mode so all the resources can be seen? I am just wondering why Microsoft does not provide a feature like that for BAML resources, or better yet, publish BAML spec so someone esle can create a tool to accomplish that.

Nic
May 17, 2010

# re: Resx and BAML Resources in WPF

The approach using LocBaml does not cater for all scenarios, even from the context of the xaml.
Some control vendors (Telerik for instance) rely on RESX files for parts of there localisation.
Also in the business layer (remember localisation is not just language - tax, and other business rules are a part of localization) workflows may need to be localized. If workflows are composed of Commands these may need to be localized as well. There are many other scenarios that fall under the banner of localization that are not handled by the LocBaml approach (solely). Good work Rick, your article has real value.

Rick Strahl
November 06, 2010

# re: Resx and BAML Resources in WPF

FWIW the WPF Localization whitepaper is located here: http://wpflocalization.codeplex.com/releases/view/29389

Tejas Sharma
January 23, 2013

# re: Resx and BAML Resources in WPF

This is a great article. I'm surprised at the lack of documentation about <UICulture> and that it only pertains to BAML related localization. Thank you for putting this up.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2020