Localization is fun when it works, but pain when it does not. I have experienced this pain first hand in the form of cryptic MissingManifestResourceException errors and want to share with you when they can occur and also to have a reminder if I hit this problem again.
Sharing resources – RESX!
UWP applications have added a new format for resource management – RESW. Basically it is almost exactly the same as RESX, but has a different extension. The truth is, that cross-platform mobile developers usually prefer having shared string resources across all platforms and for this purpose a Portable Class Library is used.
Such resource sharing infrastructure is quite easy to set up. First you create a new PCL, add in a RESX resource file, set its code generation to public and then add more localized resource files with the same name but additional culture-tag extension – e.g. LocalizedStrings.resx (neutral), LocalizedStrings.de.resx (German), LocalizedStrings.cs.resx (Czech).
At runtime the CultureInfo.CurrentUICulture is checked and references to your resource class are directed at the proper localized version of the resources.
This works almost 100 % of the time. Until you get a MissingManifestResourceException .
The two forms of MissingManifestResourceException
In my case the exception started up when I tried to simply access a localized string resource:
System.Resources.MissingManifestResourceException: 'MissingManifestResource_ResWFileNotLoaded, ResourceLibraryApp.Resources.ResxInResources'
I have noticed the reference to RESW files in the description so I decided to add “dummy” RESW files to the UWP app project for all supported languages. Note that this is necessary anyway! If you don’t include the RESW files in the UWP project, the packaging process will not notice the non-neutral translations and your app will not be available in the languages you intend. This comes down to the <Resource Language="x-generate"/> which can be found in the Package.appxmanifest file.
After rebuild and relaunch, the exception persisted. After a bit more fiddling around with ResourceManager , the exception description got even more “helpful”:
An exception of type 'System.Resources.MissingManifestResourceException' occurred in mscorlib.ni.dll but was not handled in user code
Additional information: Unable to load resources for resource file "ResourceLibraryApp.Resources.LocalizedStrings" in package "9b09bfd8-2a50-4a1f-baae-e90b760e48c7".
I was completely lost until I tried something counterintuitive and it worked – I changed the name of the PCL assembly.
Do NOT end the name of your PCL with “.Resources”!
The heading says the whole story. If you end the name of your PCL with .Resources your app will crash with MissingManifestResourceException at runtime. Everything will otherwise work, compilation will go through flawlessly. Also, to make things more “Sherlocky”, the exception will appear only when the localized resources are used and will not show up with the neutral culture.
When I renamed the assembly to end with .Localization (or anything else for that matter), the app no longer crashed and the resources have loaded well.
Example project with both .Resources PCL and .Localization PCL is available on my GitHub. You can verify yourself that retrieving the resource from the first mentioned library will crash.
This RESX + PCL bug is hard to track down mainly because it causes problems only at runtime and only with the right culture configuration. However, it can be created quite easily, because Resources suffix is a fitting name for a PCL containing your Resources 🙂 .