SharePoint Gear

Projects & Solutions from a SharePoint Geek

70-541: Localize a feature using a resource file April 11, 2009

Short & Sweet

Resource files allow you to expose strings used by you applications. WSS supports two types of rerource files: provisioning and run-time. The former is used by features and solutions. The latter is used by ASP.Net. Provisioning resource files are stored in your feature’s Resources folder (by default) unless you either specify a DefaultResource file in feature.xml or reference the resource file with a three-part reference. Run-time resource files are stored in App_GlobalResources for the application and they’re copied there from ~12CONFIGRESOURCES when the web application is first deployed. Run-time resources are always referenced with their three-part name.

Detailed Information

Well-designed solutions will make use of resource files. Resource files allow you to expose strings used by you applications. These strings can describe:

  • Descriptions for fields, lists, sites
  • Options in a SharePoint Choice Field (SPFieldChoice)
  • The name of files used in th soluton (e.g. images, templates)
  • Anything else that might be referenced by a string

Resource files are implemented as XML files. I guess their major reason for existing is they support three  major software engineering principles:

  1. Encapsulation and abstraction: When you use a resource in your code, you call the resource, without caring for what value the resource holds. e.g. I might reference a resource called myLibraryName. The actual value of myLibraryName is not known to me and I don’t care. Likewise, someone else can change the value to another valid string and the solution will continue to operate correctly.
  2. Reuse: Resources can be shared amongst solutions. If we have two, very similar solutions, SolutionTwo might use all the resources of SolutionOne and create new resources for its specific resources. This reduces our development time and also makes it easier to conceptualise and architect our new solution (and should reduce our error rate).

Resource files also support a .Net feature that Microsoft has pushed since .Net 1.1 (maybe earlier): Localisation. The idea is that you can write an application and use Resource references for the text (strings) in the application. You can then create a separate resources file for each language (or culture) and the application will work seamlessly when it’s deployed internationally.

There are two types of resource files supporting in WSS:

  1. Provisioning: Used during the provisioning of sites and features.
  2. Run-time: Used by ASPX pages and by assemblies.

The default provisioning resource file is ~12TEMPLATEcore.resx. If you open this file in a text editor, you’ll get a real grasp of what resource files are all about. They operate on a KeyValue pair fomat of storing information and are very readable. There’s plenty of CDATAreferences throughout the file. If you’re not familiar with this tag, see the CDATA reference at the bottom of this article, though it’s probably not too important test.

Run-time resources are stored separately to provisioning resources and are more closely tied to the web application than to WSS. They are stored in the web application’s App_GlobalResources folder:

  • C:InetpubwwwrootwssVirtualDirectories<port_number>App_GlobalResources

If you browse to this folder an open wss.resxyou’ll notice a pile of strings that you’re probably familiar with. As with most defaultcore WSS files, it’s best not to modify the existing ones if at all possible to keep your installation in a supportable state.

So, we’ve looked at what resource files are and where they’re stored. Now we need to actually use them in our feature. I’m going to show you two examples of using provisioning resources.

In the first example we’ll create the most basic of features and provision it as a site collection feature. The feature won’t actually do anything, but its Title and Description will be populated from a resource file. By default, WSS looks within your feature’s folder for a resources file. It looks for the following file:

  • ~12TEMPLATEFeatures<your_feature_folder>ResourcesResources.<culture>.resx

We’re going to create a feature, then a resources.<culture>.resx file and provision it to our site collection. Here goes:

  1. Create a folder named ResourcesFeature within ~12TEMPLATESFeatures. This folder will house our feature.
  2. Open this folder and create a new text document. Call it feature.xml. Open this file with your favourite text editor and enter the following lines:
    <Feature xmlns=”http://schemas.microsoft.com/sharepoint/”
             Id=”dae19050-2648-11de-8c30-0800200c9a66″
             Description=”$Resources:ResourceFilesDescription”
             Title=”$Resources:ResourceFilesTitle”
             Scope=”Site”
             />
  3. You should recognise the above as a very simple feature definition file. It defines the feature’s Id, Description, Title and Scope. The Description and Title fields will be populated by our resources file. You’ll notice the syntax for referencing feautures is $Resources:<resource_key>. WSS will lookup that resource key and substitute its value in our Feature.xml during the provisioning process. Save the feature.xml file and exit the text editor.
  4. Within the ~12TEMPLATESFeaturesResourcesFeature folder you created above, create another folder named Resources. This folder will house our resources file.
  5. Within the Resources folder, create a new text document. Call it Resources.en-US.resx(I’m assuming your server’s culture is set to English-US. If not, you’ll need to enter the appropriate culture. I’ll include a link to a cultures list at the end of this document). Open this file and enter the following lines:
    <?xml version=”1.0″ encoding=”utf-8″?>
    <root>
      <data name=”ResourceFilesDescription”>
        <value>An example of using Resource Files in WSS</value>
      </data>
      <data name=”ResourceFilesTitle”>
        <value>My Feature Uses Resource Files</value>
      </data>
    </root>
  6. That’s the format of a resources file. Each resource has a data tag witha name and an associated value. The names match up with the names we used in our feature.xml file. Save the resources file annd exit the text editor.
  7. Now it’s time to install the feature. For this we’ll use stsadm. Open command prompt and change to the following directory:
    C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12BIN
  8. Run the following command:
    stsadm -o installfeature -name ResourcesFeature
  9. Now just open the Site Settings page of your site and view the Site Collections Features page. You will have a feature named My Feature Uses Resource Files with the correct description.

Pretty easy. The one limitation of using resources in this manner is that they can’t be shared across features. This is because they’re stored within the feature folder itself. The solution is to move the resources file outside the feature folder to a location that’s accessible by all features. This is achieved by using the DefaultResourceFile attribute within feature.xml to specify a resources file name. Once you activate this attribute, WSS will not look within your feature’s folder for the resources file; instead it will search within:

  • ~12Resources<filename>.<Culture>.resx

Just like the earlier example, we’re going to create a feature, then a resources file and provision it to our site collection. Follow me:

  1. Create a folder named GlobalResourcesFeature within ~12TEMPLATESFeatures. This folder will house our feature.
  2. Open this folder and create a new text document. Call it feature.xml. Open this file with your favourite text editor and enter the following lines:
    <Feature xmlns=”http://schemas.microsoft.com/sharepoint/
             Id=”3d089b99-2041-4729-872d-79891b5163a3″
             Description=”$Resources:ResourceFilesDescription”
             Title=”$Resources:ResourceFilesTitle”
             Scope=”Site”
             DefaultResourceFile=”GlobalResourcesFeature”
             />
  3. You should recognise the above as a very simple feature definition file. It defines the feature’s Id, Description, Title and Scope. The Description and Title fields will be populated by our resources file. You’ll notice the syntax for referencing features is $Resources:<resource_key>. WSS will lookup that resource key and substitute its value in our Feature.xml during the provisioning process. Save the feature.xml file and exit the text editor. Nothing has changed from the previous example (so I cut & paste the text).
  4. Withing the ~12Resources folder create a text document and rename it to GlobalResourcesFeature.en-US.resx. Open this file and enter the following lines:
    <?xml version=”1.0″ encoding=”utf-8″?>
    <root>
      <data name=”ResourceFilesDescription”>
        <value>An example of using GLOBAL Resource Files in WSS</value>
      </data>
      <data name=”ResourceFilesTitle”>
        <value>My Feature Uses GLOBAL Resource Files</value>
      </data>
    </root>
  5. That’s the format of a resources file. Each resource has a data tag witha name and an associated value. The names match up with the names we used in our feature.xml file. Save the resources file annd exit the text editor.
  6. Now it’s time to install the feature. For this we’ll use stsadm. Open command prompt and change to the following directory:
    C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12BIN
  7. Run the following command:
    stsadm -o installfeature -name GlobalResourcesFeature
  8. Now just open the Site Settings page of your site and view the Site Collections Features page. You will have a feature named My Feature Uses GLOBAL Resource Files with the correct description.

So, now you could reuse those resources on a number of features. So, what if you wanted to reference resources from a number of different resource files? Well you can achieve that too. You can reference any resource from the ~12Resources folder by including its file prefix in the reference.

As an example, let’s take the Description field of our feature above. That reference had two parts, the $Resources: declaration, followed by the resource_key. We can also add a third, file, part to the declaration to force it to look for a certain file in ~12Resources. To reference our GlobalResourcesFeature.en-US.resx file’s ResourceFilesDescription key use:

  • $Resources:GlobalResourcesFeature,ResourceFilesDescription

So, in essence, we could remove the DefaultResourceFile attribute from feature.xml (in the second example above) and change it to:
<Feature xmlns=”http://schemas.microsoft.com/sharepoint/
         Id=”3d089b99-2041-4729-872d-79891b5163a3″
         Description=”$Resources:GlobalResourcesFeature,ResourceFilesDescription”
         Title=”$Resources:GlobalResourcesFeature,ResourceFilesTitle”
         Scope=”Site”
         />

Both approaches would achieve the same result. The latter has the advantage of using multiple resource files, where as the former requriesless typing. You can, of course, specify a DefaultResourceFile and only use the file reference for cases that access resources outside the default file.

There’s one last think to note when using provisioning resources. There’s another attribute in feature.xml that corresponds to resources: The RequireResources attribute takes “TRUE” or “FALSE” as input. If you choose to specify TRUE for this attribute, WSS will check that a resource file exists for your server’s culture when the feature is installed. If it does not exist, the feature will be hidden from the GUI. In this way, you won’t be able to activate your feature from the GUI. This will not prevent someone activating the feature from stsadm.

That’s it for provisioning resources. They’re probably the ones most important to WSS development. We’ll take a quick look at run-time resources. These are the standard type of resources you’re used to if you have an ASP.Net background. These are necessary in WSS solutions, because provisioning resource files are not available from within ASP.Net. Instead, you must use run-time resources.

As mentioned earlier, run-time resources are stored within the web application’s App_GlobalResources folder. The default run-time resource file is called wss.resx and you’ll find it in the same folder. You might want to look through it to see what kind of string are stored there. Referencing run-time resources always uses a three-part name:

  1. In code: Resources.<file_prefix>,<resource_key>
  2. In ASPX pages: <% $Resources:<file_prefix>,<resource_key> %>

If you look within the App_GlobalResources folder, you’ll note there’s a pile of resource files in there already. Resource files are originally stored in:

  • ~12CONFIGResources

When you provision a web application they are all copied to its App_GlobalResources folder and accessed from there. If you’ve created global run-time resource files, you can deploy them to ~12CONFIGResources and then push them out to all the web applications’ App_GlobalResources folder. This is done via the following stsadm command:

  • stsadm -o copyappbincontent

I think that’s about it… phew!

References

 

Leave a Reply