Using satellite assemblies in SharePoint applications (with a twist)
What I like about the way SharePoint stores localization resource files is that all strings are stored in central location. This makes the maintenance a bit easier (you don't need to hunt down all files that need translation) and allows ad-hoc changes without the need to recompile. On the other hand it's kind of hard to make strongly-typed notation (Resources.[file prefix].[resource name].) work and the time when the resources are auto-compiled can be a bit unpredictable.
To find a solution, which allows me to create centralized language assembly for all strings and still be able to use strongly-typed notation I looked at another feature of the .Net framework - the satellite assemblies.
Create a resource file in an assembly (e.g. Strings.resx), then add language specific version (Strings.en-us.resx), and in the build folder the compiler will create a sub folder with the locale id to store language a specific extension of the assembly. The limitation of this approach is that the automatically generated class is declared as private thus we cannot reference the resources from different modules in our SharePoint application.
Trying to find a solution to this limitation I noticed one feature of the tool ResGen.exe, which compiles the resources. The command line parameter /publicClass allows us to generate the resources class as a public class.
To make this work I added the following line to my pre-build commands:
ResGen.exe /str:cs,<namespace> /publicClass "$(ProjectDir)Strings.resx"
Then I added the main assembly and all satellite assemblies to the SharePoint solution manifest. In addition the rest of the application modules can use the localization assembly simply by adding a reference to it.
<Assembly DeploymentTarget="WebApplication" Location="Localization.dll" />
<Assembly DeploymentTarget="WebApplication" Location="en-USLocalization.resources.dll" />
Compared to the use of global resources this approach does not allow the use of explicit expressions <%$ Resources:[filename prefix,]resource-key %> in ASPX pages, but I found that this is not a big limitation, especially if the development style of your team is more server side oriented.
Dovizhdane!
Comments
Assuming that maybe the base path here isn't bin\debug but bin\debug\solution, I tried ..\de\MyAssembly.resources.dll, which yielded the same error. Since bin\debug\solution is being recreated during a build\deploy, no use trying to manually copy the resource assembly there either.
I won't switch to a WebApplication deployment target here, the presence of the assemblies in the GAC is crucial in this instance.
The only other content on this topic I found was on http://my.safaribooksonline.com/9780735623200/ch09lev1sec6 where they suggest that another way of deploying resource DLLs is to created another solution package acting as a "language pack" and only containing the localized additions to the base, language-neutral solution package. Will give it a go.
The issue in your case might be that you are putting the satellite assembly in the wrong sub folder. It should go in sub folder "de-De" not "de" if you deploy in the bin. However I am not sure how this works with GAC deployment.
Given the fact that apparently a .resources.dll file apparently can be gac-installed just like any other assembly, that's sufficient now for my needs. At some point, I might create a "language pack" WSP, for now, telling people where to stick the .resources.dll will be sufficient.