Main assembly versus Satellite assembly problems when fetching both XAML and RESX resources in C# .Net Main assembly versus Satellite assembly problems when fetching both XAML and RESX resources in C# .Net wpf wpf

Main assembly versus Satellite assembly problems when fetching both XAML and RESX resources in C# .Net


Localization with WPF is very troublesome due to the bad documentation. I spent hours for some insights.

The MainWindow.xaml file always builds into the en-US satellite assembly. If the UltimateResourceFallbackLocation is set to MainAssembly, it will never find the Window's BAML and I get an exception in the InitializeComponent() call. So I feel forced to set UltimateResourceFallbackLocation to "Satellite".

This is due to the fact that your project.vcproj file probably contains <UICulture>en-US</UICulture>. This essentially tells VS to generate stellite assemblies (you see the folder en-US is being created with the according satellite in it).

UltimateResourceFallbackLocation.MainAssembly now tells .net to speed up finding the localization info by using the embedded one instead of the one in the matching directory. If your systems culture is en-US it would explain this behaviour perfectly.

quoting Kim Hamilton:

... then the ResourceManager looks for "en-US" resources directly in the main assembly, instead of searching first in an “en-US” folder. Since resource probes can be expensive, this attribute can help improve perf.

Since you've found a solution for your second bulletpoint there is only one left:

If I remove the UICulture and NeutralResourcesLanguage entirely – which forces the XAML and RESX data to both build into the MainAssembly, then my culture-specific strings don't work.

Actually WPF still does localization: When you don't have an entry like <UICulture>en-US</UICulture> in the .vcproj file wpf still tries to find a satellite in a directory having a name matching to System.Threading.Thread.CurrentThread.CurrentUICulture. It it is found, it is being used. Except, of course, if your neutrallanguage is set to your system language and you use the main assembly fallback strategy. For you to test the localization on your en-US system you should pick some other culture, e.g. ja-JP as the neutral language. Then provide the en-US folder with the according satellite in it.

So what I am using for localization and recommend is:

  1. dont have <UICulture>en-US</UICulture> in the .vcproj file
  2. use [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)]
  3. provide all target-culture directories with matching satellites.


I believe an arbitrary "smarter" alternative is to use the Assembly Linker (Al.exe) to compile .resources files into satellite assemblies as outlined in this article.

** Update **

Examples used in that article:

This Assembly Linker (Al.exe) command creates a satellite assembly for the application MyApp from the file strings.de.resources.

al /t:lib /embed:strings.de.resources /culture:de /out:MyApp.resources.dll

This Assembly Linker (Al.exe) command also creates a satellite assembly for the application MyApp from the file strings.de.resources. The /template option causes the satellite assembly to inherit assembly metadata from the parent assembly MyApp.dll.

al /t:lib /embed:strings.de.resources /culture:de /out:MyApp.resources.dll/template:MyApp.dll