The current versions of DotNetNuke support localizing any static text within a module. Although full content localization is not yet supported, it is still important to localize your module so that the module can be used for non-English-speaking sites. Imagine the frustration of your users if all the content for their site is written in Spanish, yet all of the static text in your module is written in English.
Though the localization API is very powerful, it would add a lot of work for module developers if it was the only mechanism for localization. To simplify the job for developers, DotNetNuke includes a localization framework that applies localization using declarative markup in the ASCX or ASPX files. This approach provides a couple of benefits:
It simplifies the programming model because the developer adds a single attribute/value pair to the server control markup, and the framework handles calling the appropriate localization APIs.
It allows localization to be applied or changed without recompiling the application.
So look at what it takes to declaratively provide localization for your module.
After all static strings have been identified, you must determine the best approach for localizing each individual string. Each string should be categorized into one of four cases depending on how the string is used within a module:
Text placed directly into the HTML in the ASCX files.
Text declaratively set in a server control in the ASCX files.
Text modified or set in the source code for the module.
Text embedded in images.
The following sections show you how to use the localization framework and localization API to correct each of these potential problem areas.
The key to resolving the problem of text placed directly into the HTML in the ASCX files is to understand that localization is handled programmatically. Whether it is your code or framework code, you need to have the string in a format that is easily accessed programmatically. This means that you must make sure that the code-behind file — and thus the DotNetNuke framework — is aware of the string's existence. This is actually quite easy to fix — just wrap the string in an HTML control. Essentially, this step transforms the problem into Case 2 and enables you to use a common approach for all strings in the ascx file. Table 11-2 shows an example of applying this step to a simple string located in a table cell.
Before | After |
---|---|
<TD > Title: </TD> |
<TD > <asp:Label runat="server"> Title: </asp:Label> </TD> |
At this point, your strings are ready to be localized.
After all of your static strings are encapsulated in server controls, it is easy to tell the localization framework how to localize your strings. To localize a control, add a resourcekey attribute with a value that tells the framework which string resource to use for this control. Table 11-3 takes the previous example and makes this additional change.
Before | After |
---|---|
<TD > <asp:Label runat="server" Title: </asp:Label> </TD> |
<TD > <asp:Label runat="server" resourcekey="TestLabel"> Title: </asp:Label> </TD> |
Now the framework has all the information it needs to find your string resources and localize this content.
As mentioned earlier in the chapter, your module should include the App_LocalResources directory with a resource file named after the user control that is being localized. When you first localize a module, it's best to leave the resource file empty. That will let you know if you have missed localizing strings. Figure 11-1 shows the sample, the Title: string, before it has been localized.
Figure 11-1
To verify that you have applied the localization settings correctly, ensure that the web.config file's AppSettings section includes the following line:
<add key="ShowMissingKeys" value="true" />
If you have applied the resourcekey and set ShowMissingKeys correctly, you should see the image in Figure 11-2, the localized string with a missing value.
Figure 11-2
Notice that the text shows you that it is looking for TestLabel.Text. This makes it easy to see where you have localized a control, and where you still need to create the localized version of the string. If you were to create the TestLabel.Text resource string with a Localized Title; value in your resource file, you'd get the localized content shown in Figure 11-3.
Figure 11-3
When you localize content, keep in mind that different cultures may use different punctuation. In this example, the colon (:) from the original string was changed to a semicolon (;) when it was localized.
A Label control shows how easy it can be to localize a web control. But each control is different and contains different attributes that might need to be localized. Table 11-4 shows which attribute will be localized using the default behavior.
Control Type | Localized Attribute |
---|---|
System.Web.UI.WebControls | |
| Text |
| Text |
| Text |
| AlternateText |
| Text |
| AlternateText |
| Text |
| ErrorMessage |
| Items(i).Text |
| Items(i).Text |
System.Web.UI.HtmlControls | |
| Alt |
If the web control you are localizing is not listed in Table 11-4, you need to localize a different attribute, or if you need to localize multiple attributes for the same control, you must use the localization techniques shown in Case 3.
You will find several cases where text cannot be localized using a declarative approach. This will require programmatically setting the text using the localization API. The API section outlines the most frequently used methods of the API.
Continuing with the same example, take a look at how to handle localizing the Tooltip attribute for the label you created. Notice that this attribute is not the default attribute for the Label control listed in Table 11-4. To localize the attribute, add the following line of code to the code-behind:
lblTitle.Tooltip = Localization.GetString("TestLabel.ToolTip", _ Me.LocalResourceFile)
Because this is a new control, you are safe adding it to the Page_Load event. As you will see shortly, this is not always the appropriate spot for localizing strings. Now that you have the code, the only step left is to add the localized value to the resource file. This example uses LocalResourceFile because it is specific to the module. Also note that although the key is named TestLabel.ToolTip, you are free to use whatever key makes sense to you. Because you're using the API, you have much more control over how the keys are named.
If your key does not include a period (.), the framework will automatically add .text to your key and use that as the key for looking up the localized value. Keep this in mind when creating your keys. Assuming that you have named your key appropriately, you should see something like the localized tooltip shown in Figure 11-4 when you compile and navigate to a page with your module.
Figure 11-4
There are many instances where you might have embedded strings in your code that are changed depending on the application state. A good example of this is the Login skin object. This skin object changes between Login and Logout depending on the authentication state of the current user. To localize this control, just replace all the references to the static text with a call to one of the GetString methods described earlier.
The DotNetNuke localization API includes a few helper methods to simplify localizing complex controls like datagrids. Although you could use the standard programmatic techniques, a helper method makes it trivial to localize the HeaderText values. To localize column headers, include a key in the local resource file for each column in the datagrid. This key should be the same as the HeaderText value for the column with .Header appended. For example, say your grid looks something like this:
<asp:datagrid runat="server" > <Columns> <asp:TemplateColumn HeaderText="Title"> ... </asp:TemplateColumn> </asp:datagrid>
In this case, your resource key would be Title.Header. After you have the keys defined, just add the following method call to your code:
Localization.LocalizeDataGrid(dgSample, LocalResourceFile)
This method automatically iterates through the datagrid and localizes each of the column headers.
Images are a special case. It is recommended that you never include text in your images because it complicates localization and can usually be avoided through the use of background images and CSS. If your design requires you to embed text in an image, you need to make a few changes to make it easier to localize the image.
No module will ever include localized resources for every language supported by DotNetNuke — the effort to maintain the resource files would greatly exceed the cost for all other development. Most module developers will include resource files for their native language and maybe one or two other languages depending on the language skills of the module development staff. This means that many users will be forced to create the resource files for their own language. That's not usually a significant problem.
If an image file contains embedded text, though, the user is forced to re-create the image with a localized version of the text. To ease the burden for the user, include the base image without text, so that the user can easily create the text label in his language. Keep in mind that different languages have different space requirements. Just because a word or phrase is short in one language does not mean that it will be equally short in another language. That's one of the reasons for avoiding embedded text.
When your user has the image file with the localized text, he or she can use the standard GetString methods to set the ImageUrl attribute to the appropriate image filename, depending on the language they select.