Saturday, June 09, 2007

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.