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:

MyProject.dll Main assembly
fr-FR\MyProject.resources.dll Satellite Assembly
en-US\MyProject.resources.dll Satellite Assembly

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:

  1. Open the Package in the SharePoint solution
  2. Select the Advanced Tab
  3. Click Add and select Add Existing Assembly… (Add Existing Assembly from Project Output… does not work)
  4. For the Source Path find and select the satellite assembly you’d like to add
  5. Leave the Deployment Target set to Global Assembly Cache
  6. 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.
    Adding Satellite Assembly
  7. Click OK (Safe Controls and Satellite Resources do not need to be added)
    Satellite Assembly Added
  8. Repeat for each Satellite Assembly in your project

After deploying the modified package, you should now be able to access your localized resources.

Gotchas

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.

More Info

http://msdn.microsoft.com/en-us/library/gg615453.aspx

Comments

4 responses to “Deploying Localized Satellite Assemblies with SharePoint 2010”

  1. Al Avatar
    Al

    8. Repeat for each Satellite Assembly in your project

    VS2010 gives each locale the same assembly name therefore impossible to add more than one locale to the package?

    en-us/myassembly.resources.dll
    en-gb/myassembly.resources.dll

    1. Chris Coulson Avatar

      It does, but each assembly goes into it’s own separate folder (specified in the location field). This allows for multiple assemblies with the same name.

  2. Manuel Avatar
    Manuel

    Hi guys.

    What about TFS Builds? This kind of approach will never work with a Build. TFS Build drops binary files to a different folder depending on the configuration of the build, so the bin\Release\[language]\MyAssembly.resources.dll is always inaccessible.

    Any idea??

    1. Chris Coulson Avatar

      I haven’t used TFS Builds, but I would assume you could create a post build script that would copy the files to the appropriate location, like mentioned in the Gotcha’s and http://msdn.microsoft.com/en-us/library/gg615453.aspx .

Leave a Reply

Your email address will not be published. Required fields are marked *