Walkthrough: Localizing Columns, Content Types, and Lists

Applies to: SharePoint Foundation 2010

This walkthrough shows you how to provide and consume localization resources for the columns, content types, and lists that you create and deploy. Tasks illustrated in the walkthrough include:

  • Using resource expressions in XML definitions for columns, content types, and lists.

  • Deploying localization resources that are specific to a single Feature.

  • Deploying localization resources that can be shared by many Features.

Prerequisites

For general requirements, see Requirements for Developing SharePoint Solutions. In addition, specific requirements to complete this walkthrough include:

Scenario

In this walkthrough, you create a SharePoint project in Microsoft Visual Studio 2010 named WingtipReports. The project includes two Features, one with site scope so that it can be activated for an entire site collection, and the other with web scope so that it can be activated for individual websites in the collection.

The first Feature adds several new elements to the site collection, including several custom site columns; a custom site content type called Weekly Status Report; and a custom list template called Weekly Status Reports. All of these items are localized by replacing hard-coded display strings with Microsoft ASP.NET resource expressions that retrieve localized string values from language resource (.resx) files. The language resource files are installed as global resources so that they can be shared by other Features that have been created in separate deployments by developers at Wingtip.

A second, web-scoped Feature provisions an instance of the Weekly Status Reports list. Much of the display text for this instance of the list is provided by the site columns and the site content types that are provisioned when the first Feature is activated. (For this reason, the second Feature is defined as having an activation dependency on the first Feature.) However, the list instance does have its own title and description, and this text is localized by retrieving translations from another set of resource files. Because these resources localize only a single list instance, they are installed as local resources, which are available only to the Feature that installs them.

Creating a SharePoint Project

First, create a SharePoint project in Visual Studio 2010, and name the project WingtipReports.

To create a SharePoint project

  1. Start Visual Studio 2010 as an administrator.

  2. Display the New Project dialog box by pointing to New on the File menu, and then clicking New Project.

  3. Expand the SharePoint node under either Visual C# or Visual Basic, and then click 2010.

  4. In the Templates pane, click Empty SharePoint Project, change the name of the project to WingtipReports, and then click OK.

    The SharePoint Customization Wizard appears.

  5. On the Specify the site and security level for debugging page, enter the URL for the SharePoint site to which you want to add the new custom field item, or use the default location (http://< system name>/).

  6. In the What is the trust level for this SharePoint solution? section, select Deploy as a farm solution.

  7. Click Finish.

    The project appears in Solution Explorer.

  8. In Solution Explorer, click the project node, and then press F4.

    The Properties window appears.

  9. Set the Include Assembly In Package property to False.

    The project has no code and does not need to deploy an assembly.

  10. Press Ctrl+Shift+S to save all.

Creating a Feature with Site Collection Scope

The first major element that you must add to this project is a Feature that can be used to provision XML definitions for site columns, a site content type, and a list template, in addition to localization resources to support each of those items. This Feature will have site collection scope so that the elements that the Feature provisions are available to all websites in the site collection.

To create a Feature with site collection scope

  1. In Solution Explorer, right-click the Features folder, and then click Add Feature.

    A folder named Feature1 is added, and the Feature Designer opens.

  2. Right-click the Feature1 folder, select Rename, and type WeeklyStatusReport.

  3. In the Feature Designer, replace the automatically generated value for the Title field with the following string:

    $Resources:WeeklyStatusFeature
    

    This string is an ASP.NET expression. The dollar sign ($) indicates that an expression follows. The prefix Resources indicates the type of expression. The suffix after the colon (:) is the expression value that will be resolved. In this case, WeeklyStatusFeature is the name of a key in a resource file. SharePoint Foundation evaluates the expression and replaces it with the localized value that it finds in a resource file. Later in the walkthrough, you create a resource file that contains the correct key/value pair.

    You might sometimes see resource expressions like this one:

    $Resources:wingtip,WeeklyStatusFeature
    

    The value before the comma (,) specifies a base file name for the resource file, wingtip. You could use the same syntax for the resource expression in this step, but in step 8, you set a property that makes it unnecessary to specify a base file name.

  4. In the Description field, paste the following string:

    $Resources:WeeklyStatusFeatureDesc
    
  5. In the Scope list, select Site.

  6. If the Packaging Explorer window is not open, on the View menu, point to Other Windows, and then click Packaging Explorer.

  7. In the Packaging Explorer, click the node for $Resources:WeeklyStatusFeature, and then press F4 to display the Properties window.

  8. In the Properties window, set the value of the Default Resource File property to wingtip.

  9. Change the value of the Deployment Path property to WingtipReports.

  10. Press Ctrl+Shift+S to save all.

Adding Global Resources to the Project

The next step is to add localization resource files to the SharePoint solution. The files that you add in this step are deployed as global resources. Global resources are installed in the %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\Resources folder on all servers in the farm, where they can be shared by many Features, including Features that other users deploy. The working assumption for this walkthrough is that you want to use the site columns and content types that you are creating now in other Features that you develop in future projects.

In this phase of the project, you create two resource files. First, you create a resource file to support the default language of the website. Then you create a second resource file for one of the alternate languages that are supported by the website. In a production environment, you might create and deploy many other language-specific resource files.

To add global resource files

  1. In Solution Explorer, click the project node. Then, on the Project menu, click Add SharePoint Mapped Folder.

  2. In the Add SharePoint Mapped Folder dialog box, select Resources, and then click OK.

    A Resources folder is added to the project. Check the properties of this folder. Notice that the DeploymentLocation property is set to {SharePointRoot}\Resources.

  3. In Solution Explorer, select the Resources folder. On the Project menu, click Add New Item.

  4. In the Add New Item dialog box, expand the node for Visual C# if your development language is C#, or Common Items if you are working in Visual Basic. Select General. In the template pane, select Resources File. Name the file Wingtip.resx, and then click Add.

    The resource file is added to the project and opened in the Managed Resources Editor.

    Tip

    Whenever you provision files in the global Resources folder, it is a good practice to choose unique file names to avoid naming conflicts with resources that are provisioned by other applications. One convention is to prefix the file name with your company name. For example, if your company is Wingtip Toys, the names of resource files that you deploy can all begin with "Wingtip."

  5. In Solution Explorer, right-click the resource file that you just created, and then select Open With.

  6. In the Open With dialog box, under Choose the program you want to use to open this file, select XML (Text) Editor. Then click OK.

    The resource opens in the XML editor.

  7. In the XML editor, scroll to the bottom of the file, and insert a blank line just above the final </root> tag. Place the insertion point on the blank line, and then paste the following XML into the file.

    <data name="Accomplishments" xml:space="preserve">
        <value>Accomplishments (invariant)</value>
      </data>
      <data name="BlockingIssues" xml:space="preserve">
        <value>Blocking Issues (invariant)</value>
      </data>
      <data name="Direction" xml:space="preserve">
        <value>LTR</value>
        <comment>Can be LTR, RTL, or none</comment>
      </data>
      <data name="FromDate" xml:space="preserve">
        <value>From (invariant)</value>
      </data>
      <data name="PlanForNextWeek" xml:space="preserve">
        <value>Plan For Next Week (invariant)</value>
      </data>
      <data name="SubmittedBy" xml:space="preserve">
        <value>Submitted By (invariant)</value>
      </data>
      <data name="ToDate" xml:space="preserve">
        <value>To (invariant)</value>
      </data>
      <data name="WeeklyStatusFeature" xml:space="preserve">
        <value>Weekly Status Reports (invariant)</value>
      </data>
      <data name="WeeklyStatusFeatureDesc" xml:space="preserve">
        <value>Provides support for weekly status report lists. (invariant)</value>
      </data>
      <data name="WeeklyStatusListTemplate" xml:space="preserve">
        <value>Weekly Status Reports List (invariant)</value>
      </data>
      <data name="WeeklyStatusListTemplateDesc" xml:space="preserve">
        <value>A list of weekly progress reports. (invariant)</value>
      </data>
      <data name="WeeklyStatusReportCT" xml:space="preserve">
        <value>Weekly Status Report (invariant)</value>
      </data>
      <data name="WeeklyStatusReportCTDesc" xml:space="preserve">
        <value>Add a new weekly status report. (invariant)</value>
      </data>
    
  8. Press Ctrl+S to save the file. Then on the File menu, click Close to close the file.

  9. In Solution Explorer, select the file Wingtip.resx. On the Edit menu, click Copy. Then click Paste.

    A file that is named Copy of Wingtip.resx is added to the Resources folder.

  10. Right-click the file that is named Copy of Wingtip.resx, and then click Rename. Rename the file to Wingtip.language-COUNTRY/REGION.resx where language is a two-letter code for the default language of your website and COUNTRY/REGION is a two-letter code for the subculture.

    For example, if the default language is English (United States), the resource file name is Wingtip**.en-US**.resx.

    For more information about language identifiers, see the System.Globalization.CultureInfo class.

    Important

    In resource expressions, you reference a resource file by using its base file name, such as "Wingtip". When SharePoint Foundation retrieves a resource value, it looks for a resource file that has this base file name followed by a language identifier that corresponds to the value of the CurrentUICulture property of the currently executing thread. SharePoint Foundation expects to find an exact match. For example, if the language identifier on the current thread is "pt-BR", SharePoint Foundation looks for a resource file that has the name "BaseFilename.pt-BR.resx". It ignores files that have the same language code but not the same subculture code, such as "BaseFilename.pt.resx" and "BaseFilename.pt-PT.resx".

    If SharePoint Foundation does not find a resource file to match the language identifier on the executing thread, it looks for a fallback resource file. The first choice for a fallback is a resource file for the invariant culture--that is, a resource file that has no language identifier at the end of the file name. For example, in the current project the resource file for the invariant culture is Wingtip.resx. If SharePoint Foundation cannot find a resource file for the invariant culture, it tries to fall back to the default language. If it does not find a resource file for the default language, it displays the resource name.

  11. Repeat steps 9 and 10, this time appending the culture-specific identifier for an alternate language that is enabled on your website.

  12. Open both of the culture-specific language resources files that you have just created, and replace the word "invariant" with the language identifier for the file. For example, in Wingtip.en-US.resx, "Accomplishments (invariant)" becomes " Accomplishments (en-US)".

    For this walkthrough, it is not necessary to translate string values. Instead, it should be sufficient to append a language identifier to an untranslated string. When you test the Web Part, the language identifier indicates the language that is displayed.

  13. Press Ctrl+Shift+S to save all.

Creating Site Columns, a Content Type, and a List Definition

Now it is time to consume the global resources that you have just created. In this phase of the project, you create several custom site columns and then define a content type that uses the columns. Finally, you create a list definition that is based on the content type.

To create the site columns, content type, and list definition

  1. In Solution Explorer, click the project node. Then, on the Project menu, click Add New Item.

  2. Expand the SharePoint node under either Visual C# or Visual Basic, and then click 2010.

  3. In the Templates pane, click Empty Element, change the name of the element to Fields, and then click Add.

    A Fields folder appears in Solution Explorer. Under the folder is a file named Elements.xml.

  4. If Elements.xml is not open in the editor, open it.

  5. In Elements.xml, add the following field definitions between the opening <Elements> and the closing </Elements> tags.

      <Field ID="{fcc46300-de6e-481e-ac2c-5bc369946712}"
             Name="SubmittedBy"
             DisplayName="$Resources:SubmittedBy"
             Type="User" List="UserInfo" ShowField="NameWithPicture"
             UserSelectionMode="PeopleOnly" UserSelectionScope="0"
             Required="TRUE" />
      <Field ID="{ab597cd8-5392-4c9a-bf99-51de026408d0}"
             Name="FromDate" 
             DisplayName="$Resources:FromDate"
             Type="DateTime" Format="DateOnly"
             Required="TRUE" >
        <Default>[today]</Default>
      </Field>
      <Field ID="{a69582b1-6756-40af-ab7a-7beab306afc9}"
             Name="ToDate" 
             DisplayName="$Resources:ToDate"
             Type="Calculated" Format="DateOnly" ResultType="DateTime" 
             ReadOnly="TRUE" Required="FALSE">
        <Formula>=StartDate+7</Formula>
        <FieldRefs>
          <FieldRef Name="FromDate"/>
        </FieldRefs>
      </Field>
      <Field ID="{3aaad916-127b-48ad-9c07-9b20d5c82aea}"
             Name="Accomplishments"
             DisplayName="$Resources:Accomplishments"
             Type="Note" NumLines="10" RichText="TRUE" RichTextMode="FullHtml"
             Required="TRUE"/>
      <Field ID="{300423a8-5cd6-43de-be09-58318aebe443}"
             Name="PlanForNextWeek"
             DisplayName="$Resources:PlanForNextWeek"
             Type="Note" NumLines="6" RichText="TRUE" RichTextMode="FullHtml"
             Required="FALSE" />   
      <Field ID="{a757c55d-85de-40ca-9cc9-b2ba31a0221d}"
             Name="BlockingIssues"
             DisplayName="$Resources:BlockingIssues"
             Type="Note" NumLines="4" RichText="TRUE" RichTextMode="FullHtml"
             Required="FALSE" />
    
  6. Press Ctrl+S to save Elements.xml, andthen close the file.

  7. In Solution Explorer, click the project node. Then, on the Project menu, click Add New Item.

  8. In the Templates pane, click Content Type, change the name of the element to ContentTypes, and then click Add.

  9. In the SharePoint Customization Wizard, under Which base content type should this content type inherit from? select Item. Then click Finish.

    A ContentTypes folder appears in Solution Explorer. Under the folder is another file named Elements.xml.

  10. In the new Elements.xml, delete everything between the opening <Elements> and the closing </Elements> tags. Then insert the following content type definition.

    <!-- Parent ContentType: Item (0x01) -->
      <ContentType ID="0x010013573845130047cdb90148d52e593cef"
                   Name="$Resources:WeeklyStatusReportCT"
                   Group="Custom Content Types"
                   Description="$Resources:WeeklyStatusReportCTDesc"
                   Inherits="TRUE"
                   Version="0">
        <FieldRefs>
          <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
          <FieldRef ID="{fcc46300-de6e-481e-ac2c-5bc369946712}" Name="SubmittedBy" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
          <FieldRef ID="{ab597cd8-5392-4c9a-bf99-51de026408d0}" Name="FromDate" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
          <FieldRef ID="{a69582b1-6756-40af-ab7a-7beab306afc9}" Name="ToDate" Required="FALSE" ShowInNewForm="FALSE" ShowInEditForm="FALSE"/>
          <FieldRef ID="{3aaad916-127b-48ad-9c07-9b20d5c82aea}" Name="Accomplishments" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
          <FieldRef ID="{300423a8-5cd6-43de-be09-58318aebe443}" Name="PlanForNextWeek" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
          <FieldRef ID="{a757c55d-85de-40ca-9cc9-b2ba31a0221d}" Name="BlockingIssues" Required="FALSE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
        </FieldRefs>
      </ContentType>
    
  11. Press Ctrl+S to save Elements.xml. Then close the file.

  12. In Solution Explorer, click the project node. Then, on the Project menu, click Add New Item.

  13. In the Templates pane, click List Definition From Content Type, change the name of the element to ListDefinitions, and then click Add.

  14. In the SharePoint Customization Wizard, under What is the display name of the list definition? paste the following resource expression:

    $Resources:WeeklyStatusListTemplate
    
  15. Be sure that the value for What content type would you like for your list definition? is $Resources:WeeklyStatusReportCT (WingtipReports\ContentTypes).

  16. Clear the Add a list instance for this list definition check box, and then click Finish.

    A ListDefinitions folder appears in Solution Explorer. Under the folder is another file named Elements.xml and also a file named Schema.xml.

  17. In the new Elements.xml file, replace the value of the Description attribute with the following resource expression:

    $Resources:WeeklyStatusListTemplateDesc"
    
  18. Press Ctrl+S to save Elements.xml. Then close the file.

  19. In Solution Explorer, double-click WeeklyStatusReport.feature to open it in the designer.

  20. In the Feature Designer, verify that the list under Items in the Feature includes these items:

    • Resources

    • Fields

    • ContentTypes

    • ListDefinitions

  21. Click Manifest (near the bottom). Verify that the manifest is identical (except for the Id attribute value) to the following XML:

    <Feature xmlns="https://schemas.microsoft.com/sharepoint/" 
             DefaultResourceFile="wingtip" 
             Description="$Resources:WeeklyStatusFeatureDesc" 
             Id="e18a0885-083e-43f6-94fe-b6d378a2468c" 
             Scope="Site" 
             Title="$Resources:WeeklyStatusFeature">
      <ElementManifests>
        <ElementManifest Location="Resources\Elements.xml" />
        <ElementManifest Location="Fields\Elements.xml" />
        <ElementManifest Location="ContentTypes\Elements.xml" />
        <ElementManifest Location="ListDefinitions\Elements.xml" />
        <ElementFile Location="ListDefinitions\Schema.xml" />
      </ElementManifests>
    </Feature>
    

Creating a Feature to Provision a List Instance

The next task is to add a second, web-scoped Feature to the project, and then add the definition for a list instance to the Feature. Both the Feature element that defines the Feature and the ListInstance element that defines the list instance use resource expressions for key attributes. The final task in the project is to create the resource files that provide values for those expressions.

Because this Feature depends on elements that are deployed by the first Feature that you created, you will define an activation dependency for the new Feature. It cannot be activated unless the Feature that it depends upon is activated first.

To create a Feature that provisions a list instance

  1. In Solution Explorer, right-click the Features folder, and then click Add Feature.

    A folder named Feature1 is added, and the Feature Designer opens.

  2. Right-click the Feature1 folder, select Rename, and type WeeklyStatusList.

  3. In the Feature Designer, replace the automatically generated value for the Title field with the following string:

    $Resources:WeeklyStatusListFeature
    
  4. In the Description field, paste the following string:

    $Resources:WeeklyStatusListFeatureDesc
    
  5. Verify that the value in the Scope list is Web.

  6. Click Feature Activation Dependencies (near the bottom) to expand the dependencies pane. Then click Add.

    The Add Feature Activation Dependencies dialog box appears.

  7. Click $Resources:WeeklyStatusFeature, and then click Add.

  8. In Solution Explorer, click the project node. Then, on the Project menu, click Add New Item.

    The Add New Item dialog box appears.

  9. Expand the SharePoint node under either Visual C# or Visual Basic, and then click 2010.

  10. In the Templates pane, click List Instance. Accept the default name, and then click Add.

  11. In the SharePoint Customization Wizard, replace the value for What is the display name of the list? with the following string:

    $Resources:WeeklyStatusList
    
  12. Verify that the value for Which list do you want to instantiate? is $Resources:WeeklyStatusListTemplate (WingtipReports\ListDefinitions).

  13. Replace the value for Description with the following string:

    $Resources:WeeklyStatusListDesc
    
  14. Verify that the Add this list instance to quick launch bar check box is selected, and then click Finish.

    A folder named ListInstance1 appears in Solution Explorer, and the Elements.xml file appears in the folder and is opened in the editor. Notice that resource expressions are the values for the Title and Description attributes of the ListInstance element.

  15. Press Ctrl+Shift+S to save all.

Adding Feature Resources

The last task is to create localization resources for the list instance and the Feature that deploys it. Because these resources are specific to one Feature, they can be created as local rather than global resources.

To add resources that are local to a Feature

  1. In Solution Explorer, right-click the WeeklyStatusList folder, and then click Add Feature Resource.

  2. In the Add Resource dialog box, for Select the culture of the resource file, select Invariant Language (Invariant Country). Then click OK.

    The resource file is added to the WeeklyStatusList folder. Note that the base file name is Resources. Resources that are local to a Feature always use this base file name. When the Feature is deployed, local resource files are placed in a Resources folder under the Feature's folder on the file system.

  3. In Solution Explorer, right-click the resource file that you just created, then select Open With.

  4. In the Open With dialog box, under Choose the program you want to use to open this file, select XML (Text) Editor. Then click OK.

    The resource opens in the XML editor.

  5. In the XML editor, scroll to the bottom of the file, and insert a blank line just above the final </root> tag. Place the insertion point on the blank line, and then paste the following XML into the file.

      <data name="WeeklyStatusList" xml:space="preserve">
        <value>Weekly Status Reports (invariant)</value>
      </data>
      <data name="WeeklyStatusListDesc" xml:space="preserve">
        <value>Use the Weekly Status Reports list to submit progress reports. (invariant)</value>
      </data>
      <data name="WeeklyStatusListFeature" xml:space="preserve">
        <value>Weekly Status Report List (invariant)</value>
      </data>
      <data name="WeeklyStatusListFeatureDesc" xml:space="preserve">
        <value>Creates a weekly status report list. (invariant)</value>
      </data>
    
  6. Press Ctrl+S to save the resource file, and then close it.

  7. Repeat steps 1–6, this time creating a resource file for the default language of your website. In step 5, replace the word "invariant" with the code for the default language (for example, "en-US").

  8. Repeat steps 1–6, this time creating a resource file for an alternate language supported by your website. In step 5, replace the word "invariant" with the code for the alternate language (for example, "es-ES").

  9. In Solution Explorer, double-click WeeklyStatusList.feature to open the Feature in the designer.

  10. Verify that the only item below Items in the Feature is ListInstance1 (WingtipReports).

  11. In the Feature Designer, click Manifest (near the bottom). Verify that the manifest is similar to the following XML:

    <Feature xmlns="https://schemas.microsoft.com/sharepoint/" 
             Title="$Resources:WeeklyStatusListFeature" 
             Description="$Resources:WeeklyStatusListFeatureDesc" 
             Id="30444f12-2c40-4d2a-92dd-68a30192f0ae" Scope="Web">
      <ActivationDependencies>
        <ActivationDependency FeatureDescription="$Resources:WeeklyStatusFeatureDesc" 
                              FeatureId="e18a0885-083e-43f6-94fe-b6d378a2468c"
                              FeatureTitle="$Resources:WeeklyStatusFeature" />
      </ActivationDependencies>
      <ElementManifests>
        <ElementManifest Location="ListInstance1\Elements.xml" />
        <ElementFile Location="Resources\Resources.en-US.resx" />
        <ElementFile Location="Resources\Resources.es-ES.resx" />
      </ElementManifests>
    </Feature>
    

    Your manifest will have a different value for the Id attribute. The culture names on the resource files might also be different.

  12. Press Ctrl+Shift+S to save all.

Test the Project

Test the project to make sure it works correctly.

To test the project

  1. In Visual Studio, press F5 to start debugging.

    The Output pane reports the build and deployment process. Eventually the website appears in the browser.

  2. In Quick Launch, look for a navigation link to the Weekly Status Reports list. The link title should display the title of the list in the default display language for the site.

  3. Click the arrow next to your user name in the upper-right corner of the page. Click Display Language, and then click the name of the alternate language that you used in the walkthrough. Verify that the link title for the Weekly Status Reports list changes to the alternate language.

  4. Click the link to the Weekly Status Reports list. Then click Add new item or the equivalent in the alternate language.

    The New item form appears.

  5. Verify that all the fields on the form have display text in the alternate language.

  6. Proceeding in similar fashion, verify that the site columns, content type, and list template all consume localization resources correctly.

  7. Verify that Weekly Status Reports is a site collection Feature and that Weekly Status Report List is a site Feature.

See Also

Tasks

Walkthrough: Localizing a Web Part

Concepts

Understanding the Multilingual User Interface (MUI)