Deploying Localized Satellite Assemblies with SharePoint 2010
Localizing web parts in a SharePoint 2010 project is pretty straight forward. Add resource files to your project, set the Deployment Type to AppGlobalResource, and then access them with GetGlobalResourceObject or with the <%$Resources> tag. Unfortunately this only works where you have the HttpContext – so great for web parts, but useless for Timer jobs and event receivers.
In order to access the localized resources when there is no HttpContext you’ll need to access the embedded resource files. If the resource file build action is “Embedded Resource”, Visual Studio will generate a satellite assembly for each locale that you have a resource file for. If you check your build output folder, you should see something like this:
Great! So now that we have the resources embedded in our satellite assemblies, we can just access them with Resources.MyResource.Key or ResourceManager.GetString, right? That’s what I thought, but whenever I went to retrieve the resource i’d only ever get the default value, i’d never get the localized value. After snooping through the WSP file I realized that although the satellite assemblies are built automatically, they are not automatically packaged in the WSP.
In order to access the localized resources, the satellite assemblies need to be manually added to the package:
- Open the Package in the SharePoint solution
- Select the Advanced Tab
- Click Add and select Add Existing Assembly… (Add Existing Assembly from Project Output… does not work)
- For the Source Path find and select the satellite assembly you’d like to add
- Leave the Deployment Target set to Global Assembly Cache
- The location will be automatically set to the name of your satellite assembly. The locale folder needs to be appended to the location name. For example the fr-FR satellite assembly would read fr-FR\MyProject.resources.dll.
- Click OK (Safe Controls and Satellite Resources do not need to be added)
- Repeat for each Satellite Assembly in your project
After deploying the modified package, you should now be able to access your localized resources.
One problem with this solution is that the path to the satellite assemblies is hard coded. So when you switch from a Debug to Release configuration (or vice-versa), you now have to modify each of the satellite assembly entries to point to the new location. Microsoft suggests that if you will be changing configurations often, you should add a post-build step that copies all of the satellite assemblies to a specified folder and then references that copy of the assemblies in the package.