In the walkthrough, you create a simple Web Part that can display the text “Hello, world” in several languages. In addition, the walkthrough shows you how to make all display text that is associated with the Web Part ready for localization, including display text for:
- The Feature that provisions the Web Part.
- The Web Part’s entry in the Web Part Gallery.
- The title in the Web Part chrome.
- A custom action on the Web Part menu.
- A custom property in the Web Part editor.
- A child control hosted by the Web Part.
- At least one SharePoint Foundation 2010 Language Pack installed on your development server.
- At least one SharePoint Foundation website that has alternate language support enabled.
![]() |
---|
The Web Part that you create in this walkthrough could deploy as a sandboxed solution. All of the code for the Web Part can run with partial trust. However, in addition to the Web Part, the walkthrough also deploys language resource files to a root folder in the SharePoint installation, and this part of the project requires full trust. In a production environment, you might want to use two separate solutions: a sandboxed solution to deploy the Web Part, and a farm solution to deploy the resource files. For simplicity, the walkthrough uses only one, a farm solution. |
To create an empty SharePoint project
- Start Visual Studio 2010 as an administrator.
- Open the New Project dialog by pointing to New on the File menu, and then clicking New Project.
- Expand the SharePoint node under either Visual C# or Visual Basic, and then click 2010.
- In the Templates pane, click Empty SharePoint Project, change the name of the project to Wingtip.WebParts, and then click OK.
The SharePoint Customization Wizard appears. - 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 Web Part, or use the default location (http://<; system name>/).
- In the What is the trust level for this SharePoint solution? section, select Deploy as a farm solution.
- Click Finish.
The project appears in Solution Explorer.
To add a Web Part to the project
- In Solution Explorer, select the Wingtip.WebParts node. On the Project menu, click Add New Item.
- In the Add New Item dialog box, select Web Part. In the Name field, type LocalizedWebPart. Then click Add.
The LocalizedWebPart class opens in the code editor. - In the code editor, press Ctrl+A to select all. Then copy and paste the following code:
using System; using System.ComponentModel; using System.Globalization; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using Microsoft.SharePoint.WebControls; namespace Wingtip.WebParts.LocalizedWebPart { [ToolboxItemAttribute(false)] public class LocalizedWebPart : WebPart { // Constants for display strings. const string CATEGORY_TEXT = "Text"; const string LABEL_TEXT = "Hello, world!"; const string TOOLPANE_BOLD = "Bold"; const string TOOLPANE_BOLD_DESC = "Make the text bold"; const string VERB_UNDERLINE = "Underline"; const string VERB_UNDERLINE_DESC = "Draw a line under the text"; const string WEB_PART_TITLE = "Localized Web Part"; const string WEB_PART_DESC = "An example localized Web Part"; // Member variable for the child control. private Label m_textLabel; // Instantiates the Web Part. public LocalizedWebPart() { // Add a handler for the PreRender event. PreRender += LocalizedWebPart_PreRender; } // Creates the control tree. protected override void CreateChildControls() { // Add a Label control to display content. m_textLabel = new Label(); m_textLabel.Text = Text; Controls.Add(m_textLabel); } // The PreRender event is raised after the Web Part is edited, // so this is a good time to update the child control. void LocalizedWebPart_PreRender(object sender, EventArgs e) { // Make sure that CreateChildControls has been called. EnsureChildControls(); // Apply current Web Part settings to the child control. m_textLabel.Font.Bold = Bold; } // Indicates whether the text is bold. // This property is exposed in the Web Part Editor. [WebBrowsable] [Personalizable(PersonalizationScope.Shared)] [Category(CATEGORY_TEXT)] [WebDisplayName(TOOLPANE_BOLD)] [WebDescription(TOOLPANE_BOLD_DESC)] public bool Bold { get; set; } // Overrides the Description property. [WebBrowsable(false), Personalizable(false)] public override string Description { get { return WEB_PART_DESC; } set { ; } } // Gets the text to display. private string Text { get { return LABEL_TEXT; } } // Overrides the Title property. [WebBrowsable(false), Personalizable(false)] public override string Title { get { return WEB_PART_TITLE; } set { ; } } // Gets a collection of custom verbs that provide items // on the options menu for the Web Part. public override WebPartVerbCollection Verbs { get { // Add a custom verb to toggle underlining for the text. WebPartVerb verb = new WebPartVerb(this.ID + "_UnderlineVerb", (sender, args) => { EnsureChildControls(); m_textLabel.Font.Underline = !m_textLabel.Font.Underline; }); verb.Checked = m_textLabel.Font.Underline; verb.Text = VERB_UNDERLINE; verb.Description = VERB_UNDERLINE_DESC; WebPartVerb[] newVerbs = new WebPartVerb[] { verb }; return new WebPartVerbCollection(base.Verbs, newVerbs); } } } }
- Press Ctrl+Shift+S to save all.
Adding Language Resources
![]() |
---|
To find out which languages are supported by your development website, open its home page in your browser. Click Site Actions, and then click Site Settings. Under Site Administration, click Language settings. The default language is listed at the top of the page. Alternate languages are listed below the default language. |
- The Feature that activates the Web Part.
- The Web Part Control Description File that provides information for the Web Part Gallery.
- The code that executes in the compiled assembly.
To add resources to the {SharePointRoot}\Resources folder
- In Solution Explorer, select the Wingtip.Webparts project node. On the Project menu, click Add SharePoint Mapped Folder.
- 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. - In Solution Explorer, select the Resources folder. On the Project menu, click Add New Item.
- 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.WebParts.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.” - In Solution Explorer, right-click the resource file that you just created, and then click Open With. In the Open With dialog box, select XML (Text) Editor, and then click OK.
The resource file opens in the editor. - Scroll down to the bottom of the file. Insert a blank line immediately above the tag. Copy the following markup and paste it into the file at the insertion point.
Bold (invariant) Make the text bold (invariant) An example localized Web Part (invariant) Localized Web Part (invariant) Hello, world! (invariant) Text (invariant) Underline (invariant) Draw a line under the text (invariant) An example localized Web Part (invariant) Localized Web Part (invariant)
- Press Ctrl+S to save the file. Then on the File menu, click Close to close the file.
- In Solution Explorer, select the file Wingtip.WebParts.resx. On the Edit menu, click Copy. Then click Paste.
A file that is named Copy of Wingtip.WebParts.resx is added to the Resources folder. - Right-click the file that is named Copy of Wingtip.WebParts.resx, and then click Rename. Rename the file to Wingtip.WebParts.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.WebParts.en-US.resx.
For more information about language identifiers, see the System.Globalization.CultureInfo class.Important
As is demonstrated later in the walkthrough, you reference a resource file by using its base file name, such as “Wingtip.WebParts.” 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 for 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, 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.WebParts.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. - Repeat steps 8 and 9, this time appending the language identifier for an alternate language that is enabled on your website.
- 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.WebParts.en-US.resx, “Bold (invariant)” becomes “Bold (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. - Press Ctrl+Shift+S to save all.
Localizing the Feature and the Web Part Control Description File
![]() |
---|
You might see resource expressions that end with a semicolon (;). This delimiter is acceptable but is not required by SharePoint Foundation 2010. |
To localize the Feature
- In Solution Explorer, expand the Features folder, and then double-click Feature1.
Feature1.feature opens in the Feature Designer. - In the Feature Designer, delete the text in the Title box, and replace it with the following resource expression:
- Paste the following expression in the Description box:
- Press Ctrl+Shift+S to save all.
To localize the Web Part Control Description
- In Solution Explorer, expand the LocalizedWebPart folder, and then double-click LocalizedWebPart.webpart.
LocalizedWebPart.webpart opens in the XML editor. - Delete the value for the Title property (“LocalizedWebPart”), and replace it with the following resource expression:
$Resources:Wingtip.WebParts,WebPartTitle
- Delete the value for the Description property (“My WebPart”), and replace it with the following resource expression:
$Resources:Wingtip.WebParts,WebPartDesc
- Press Ctrl+Shift+S to save all.
Writing Code to Retrieve Localized Strings
To create a method that retrieves resource strings
- In Solution Explorer, select the Wingtip.Webparts project node. On the Project menu, click Add Class.
The Add New Item dialog box appears. - In the Name field, type Utility.cs or Utility.vb, depending on your language. Then click Add.
- Press Ctrl+A to select all. Then copy and paste the following code, replacing the current content of the file.
using Microsoft.SharePoint.Utilities; namespace Wingtip.WebParts.LocalizedWebPart { public static class Utility { // Wraps the SPUtility method of the same name. public static string GetLocalizedString(string resourceName, int LCID) { if (string.IsNullOrEmpty(resourceName)) return string.Empty; // SPUtility.GetLocalized string needs a resource expression as the first argument. string resourceExpression = string.Format("$Resources:{0}", resourceName); string resourceFile = "Wingtip.WebParts"; // Note: If the named resource does not have a value for the specified language, // SPUtility.GetLocalizedString returns the value for the invariant language. // If the named resource does not exist, it returns the original expression. return SPUtility.GetLocalizedString(resourceExpression, resourceFile, (uint)LCID); } } }
- Press Ctrl+Shift+S to save all.
Localizing Web Part Properties
To localize properties of the Web Part
- In Solution Explorer, double-click either LocalizedWebPart.cs or LocalizedWebPart.vb to open the source file.
- At the top of the file, just below the declaration for the LocalizedWebPart class, are declarations for several string constants. Delete these declarations and replace them with the following code:
// Translate resource keys to string constants. const string CATEGORY_TEXT = "TextCategory"; const string LABEL_TEXT = "LabelText"; const string TOOLPANE_BOLD = "Bold"; const string TOOLPANE_BOLD_DESC = "BoldDesc"; const string VERB_UNDERLINE = "Underline"; const string VERB_UNDERLINE_DESC = "UnderlineDesc"; const string WEB_PART_TITLE = "WebPartTitle"; const string WEB_PART_DESC = "WebPartDesc";
- Navigate to the Description property. Replace the code for the get accessor with the following code:
get { return Utility.GetLocalizedString(WEB_PART_DESC, CultureInfo.CurrentUICulture.LCID); }
- Navigate to the Text property. Replace the code for the get accessor with the following code:
get { return Utility.GetLocalizedString(LABEL_TEXT, CultureInfo.CurrentUICulture.LCID); }
- Navigate to the Title property. Replace the code for the get accessor with the following code:
get { return Utility.GetLocalizedString(WEB_PART_TITLE, CultureInfo.CurrentUICulture.LCID); }
- Navigate to the Verbs property. Replace the two lines of code that set the verb.Text and verb.Description properties with the following lines:
verb.Text = Utility.GetLocalizedString(VERB_UNDERLINE, CultureInfo.CurrentUICulture.LCID); verb.Description = Utility.GetLocalizedString(VERB_UNDERLINE_DESC, CultureInfo.CurrentUICulture.LCID);
- Press Ctrl+Shift+S to save all.
Localizing Attributes
[WebBrowsable] [Personalizable(PersonalizationScope.Shared)] [Category(CATEGORY_TEXT)] [WebDisplayName(TOOLPANE_BOLD)] [WebDescription(TOOLPANE_BOLD_DESC)] public bool Bold { get; set; }
- Category
Provides the display name of a custom category for the property. - WebDisplayName
Provides the display name of the property. - WebDescription
Provides the text of the tooltip for the property.
To localize the Category, WebDisplayName, and WebDescription attributes
- In Solution Explorer, double-click either LocalizedWebPart.cs or LocalizedWebPart.vb to open the source file.
- At the bottom of the LocalizedWebPart class, but still within the class, insert code for the following subclasses:
public sealed class LocalizedCategoryAttribute : CategoryAttribute { public LocalizedCategoryAttribute(string category) : base(category) { } // Override this method to return values from the webpart's resource file. protected override string GetLocalizedString(string value) { return Utility.GetLocalizedString(value, CultureInfo.CurrentUICulture.LCID); } } public sealed class LocalizedWebDisplayNameAttribute : WebDisplayNameAttribute { bool m_isLocalized; public LocalizedWebDisplayNameAttribute(string displayName) : base(displayName) { } // Override this property to return values from the webpart's resource file. public override string DisplayName { get { if (!m_isLocalized) { this.DisplayNameValue = Utility.GetLocalizedString(base.DisplayName, CultureInfo.CurrentUICulture.LCID); m_isLocalized = true; } return base.DisplayName; } } } public sealed class LocalizedWebDescriptionAttribute : WebDescriptionAttribute { bool m_isLocalized; public LocalizedWebDescriptionAttribute(string description) : base(description) { } // Override this property to return values from the webpart's resource file. public override string Description { get { if (!m_isLocalized) { this.DescriptionValue = Utility.GetLocalizedString(base.Description, CultureInfo.CurrentUICulture.LCID); m_isLocalized = true; } return base.Description; } } }
- Navigate to the Bold property. Then change the names of the Category, WebDisplayName, and WebDescription attributes to LocalizedCategory, LocalizedWebDisplayName, and LocalizedWebDescription.
Do not change the attribute parameters. The revised code is as follows:[LocalizedCategory(CATEGORY_TEXT)] [LocalizedWebDisplayName(TOOLPANE_BOLD)] [LocalizedWebDescription(TOOLPANE_BOLD_DESC)]
- Press Ctrl+Shift+S to save all.
Testing the Web Part
To test the Web Part
- In Visual Studio, press F5 to start debugging.
The Output pane reports the build and deployment process. Eventually the website appears in the default browser. - Click Site Actions, and then click Site Settings. Under Site Collection Administration, click Site collection features. Verify that the Localized Web Part feature displays the title and description in the default language.
- Click your name in the upper-right corner of the page. Point to Select Display Language, and then click the alternate language that you used for localizing the Web Part. Verify that the title and description of the Localized Web Part feature display in the alternate language.
- (Optional) Repeat step 3, but select a language for which you did not deploy a language resource file. Verify that the title and description of the Localized Web Part feature display in the invariant language.
- Repeat step 3, but return the language to the website default.
- Click Site Actions, and then click Site Settings. Under Galleries, click Web parts. Then click LocalizedWebPart.webpart. Verify that the title, description, and example display in the default language.
- Repeat step 3 and optionally step 4. Verify that the language changes as expected. Then return the display to the default language.
- Click Site Actions, and then click More options. Click Page, select Web Part Page, and then click Create. Type a name for the page. Then click Create.
The new Web Part page appears. - In Middle Column, click Add a Web Part. Under Categories, click Custom. Select LocalizedWebPart, and then click Add.
Note
In this area of the user interface, the Web Part title and example always appear in the website default language. Switching to an alternate language does not affect the text that is displayed by the Web Part. The Web Part is added to the page.
- Click Stop Editing. Switch to the alternate language to verify that the Web Part title and the label text change as expected. Then return to the default language.
- Move the cursor to the far right of the page. When the down arrow appears, click it. Verify that the Underline action appears on the menu in the default language.
- Switch to the alternate language. Then repeat step 11. Verify that the Underline action displays in the alternate language. Return the display to the default language.
- Move the cursor to the far right side of the page. When the down arrow appears, click it. Then click Edit Web Part. At the bottom of the tool pane, look for the Text category. Verify that the name appears in the default language. Expand the category. Verify that the Bold check box and its tooltip appear in the default language.
- Switch to the alternate language. Then repeat step 13. Verify that display text changes to the alternate language.
Be Connected…
Satyendra
THREE QUERIES offers easy access to information about SharePoint and associated technologies, project management, agile and scrum methodologies that helps developers, administrators, architects, technical managers, business analysts and end users. It has grown from there. We provide an important knowledge base for those involved in managing, architecture and developing software projects of all kinds. With weekly/daily exclusive updates, we keep you in touch with the latest business, management, technology thinking.
WE ARE CONNECTED ~ Follow us on social media to get regular updates and opinion on what's happening in the world of SharePoint, front-end, back end web technologies and project management. If you like this article, please share it and follow us at Facebook, Twitter, Instagram, Pinterest and LinkedIn