Enterprise Localization Toolkit

 

Todd Abel
Microsoft Corporation

May 2002

Summary: Covers localization of a Web site's page layout and presentation using resource files by extending the Microsoft .NET Framework foundation and provides code implementing resource string management via a database, localization of complex data types and automatic building of resource files. Includes a technical description of the contents provided in the download. (28 printed pages)

Download the sample code and documentation from the Microsoft Download Center.

Contents

Summary
Web-based Localization Techniques
Localization in ASP.NET
Enterprise Localization Toolkit Features
Toolkit Technical Overview
Performance
Resource Generation Utility
Resource File Viewer
Frequently Asked Questions
Toolkit Reference
Appendix A: .NET Supported Cultures
Appendix B: Web.Config Settings
Appendix C: Installation
Appendix D: Installed Files
Appendix E: Samples

Summary

There are two main aspects to localization within a Web site. One is to localize the page layout and presentation—typically static content—and the other is to localize the data that is presented to the user. This toolkit addresses only the localization of static content and does not provide any solution that addresses the localization of data. Localization of data must be handled at the source of the data, not in the presentation of that data. Microsoft® Commerce Server and Microsoft Content Management Server help to address the localization of content.

Localization of the presentation can be accomplished in many ways, such as by having one page per culture, or by using a database to store the resource on a per culture basis. The Microsoft .NET Framework provides a great implementation based on resource files to make localization easy to do and maintain. This toolkit builds on what is provided in the Resources and Localization Using the .NET Framework SDK topic in the Microsoft .NET Framework SDK.

A number of toolkit features are provided to assist a development team with site localization:

  • Management of the localized resources
  • Management of the keys that identify localized resources
  • Localization of the resources
  • Generation and deployment of the resource files
  • Automatic localization of a page based on a user's culture

We'll start with an overview of localization techniques, tackle localization using the .NET, and then dive into what this toolkit provides, how to use it, how it performs, and what scenarios are best for its use.

This document is organized to be more technical the further you read. If you are only interested in features and a general summary, you need only read the first portion of the document. If you want technical details, the more you read, the deeper you go into the toolkit details.

Web-based Localization Techniques

For Web-based applications there have been two main techniques used for localization: static localization of each page or dynamic localization. Static localization is when a translator makes a copy of a Web page for each locale. Static localization can be used if the Web site has a small number of pages or the site has very high performance requirements and the pages can't be built on demand. Of course the problem with this type of localization is that the manageability and maintenance cost of the site are increased due to the large number of pages that must be maintained.

With the dynamic approach, the page is constructed on the fly using the locale selected by the user when making a request. The localized resources are typically stored in a database, resource files, or XML files, and merged by performing substitutions when the page is constructed. This substitution has an impact on the performance of the site, but improves manageability while decreasing maintenance costs. Both the .NET Framework and the Enterprise Localization Toolkit use this approach to localize applications. The .NET Framework model has the developer write code to perform the substitutions, and this toolkit enables the runtime substitution of resources.

Localization in ASP.NET

In the .NET Framework, culture is the combination of the user's preferred language and locale. This setting is used to set the format of dates and numbers, and to load localized resource files. The culture is set using the Thread class CurrentCulture and CurrentUICulture properties.

CultureInfo ci = new CultureInfo("en-US");

Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;

The difference between these properties is that CurrentCulture sets the culture for formatting of numbers and dates, while CurrentUICulture sets the culture for loading resources. Appendix A provides code to list the cultures that are supported by the .NET Framework. The CultureInfo class is in the System.Globalization namespace and has all the methods and properties that are needed for globalization.

Cultures are arranged in a rooted hierarchy starting with the neutral invariant culture. The invariant culture is the base culture that can be used to format data independently of the actual display culture. For instance, the invariant culture can be used to format dates that need to be stored in a database that can be accessed by different clients using different specific cultures such as en-US and ja-JP. In that case, the conversion to the specific cultures can be done in order to display the information accordingly to the user's culture at the latest moment while still preserving interoperability between clients by using a common, culture-bias-free format for storage.

Beneath the invariant culture, there are the neutral cultures such as English (en) and German (de) which can be used for localization resources but cannot be used to format numbers and dates, for instance, as there are variations within the same culture (date format is different in the US and in the UK, while the language is—arguably—identical).

Finally, there are the specific cultures like US English (en-US) and UK English (en-UK).

If the user's culture is set for en-US, but the resource is not available in the en-US resource file, the .NET Framework uses a fallback mechanism and automatically looks one level up and tries to find en resources. If resources are not available at this level, then the Framework falls back on the neutral resources defined for the application.

Microsoft ASP.NET and the .NET Framework in general recommend the use if dynamic resources and provide a great set of functionality based on resource files. Resource files are constructed using Resgen.exe or by using Microsoft Visual Studio®. They can then be used directly as loose resource files or compiled further into satellite assemblies using the assembly-generation tool Al.exe.

Loose resource files are uncompiled resource files. They are great because they can be used quickly by copying them to a directory and passing the base path to the static function CreateFileBasedResourceManager on the ResourceManager class.

String baseName = "myResourceFile";            // resource ;
String resDirectory = "C:\\MyApplication\\Resources";
         // directory containing resource files;
Type resourceSet = typeof(System.Resources.ResourceSet); 
         // Standard resourceset

ResourceManager rm = ResourceManager(myResourceFile, resDirectory, 
         resourceSet);

The problem with using loose resource files is that when the Resource Manager loads them, it doesn't shadow copy them, interfering with XCOPY deployment and concurrent access. Loose resource files have a specific naming structure:

<resource file basename>.<culture>.resources

A better choice for using resource files is to use satellite assemblies. Satellite assemblies are DLL files that contain only resources. They start out life as loose resource files and are compiled together into separate DLLs based on culture, then placed into a directory structure that corresponds to the culture name. The .NET Framework SDK has specific information on the correct directory structure.

Enterprise Localization Toolkit Features

As stated above, the toolkit provides a number of additional features that are built on top of what is provided in the .NET Framework. The primary features are:

  • Web-based Management application for use by programmers, translators and deployment personal.
  • Microsoft SQL Server™-based repository to store and manage the localized resources across all ASP.NET applications within an organization.
  • Support for the generation of loose resource files or satellite assemblies.
  • LocalizedPage class that performs the automatic localization (this does not imply automatic translation).
  • Monitor-enabled use of WMI events and performance counters.
  • Assignment of localized values to most properties of server-based controls (including collection-based properties like drop-down list items).
  • Ability to reuse localized elements on multiple control types or multiple controls.
  • Ability to automatically populate the localization database based on keys specified by a developer or Web designer.

The overall architecture of the toolkit can be viewed as in Figure 1.

Aa479334.entloctoolkit_01(en-us,MSDN.10).gif

Figure 1. Toolkit architecture

Web-based Management Application

There are 3 main roles in localizing on an application as shown in Table 1.

Table 1. Localization roles

RoleResponsibility
Designer/ProgrammerDesigns and programs Web pages; defines what HTML elements are to be localized, the key to the resource, the controls and properties to be localized.
TranslatorTranslates the strings that have been defined by the designer/programmer role.
Deployment/BuildCreates and deploys resource files.

The workflow moves from the designer/programmer to the translator to the deployment personnel. For more information on how to use the Management application, please consult the Management application documentation. The Management application is also a sample application: it is localized using the Enterprise Localization Toolkit. The definitions of all the resources used in the Management application can be viewed in the Management application, look at the Enterprise Localization Toolkit application. The definitions of all the resourced used in the Enterprise Localization Toolkit Management application can be viewed using the Management application by selecting Localization Toolkit in the current application's drop-down list. By default the Management application is marked as locked to disable inadvertent changes to its resource definitions, which would cause the Management application to function incorrectly. The Management application is localized into a number of languages to illustrate the use of the toolkit.

SQL Server Storage

SQL Server is used as a repository to store and manage the resources and their relationships to HTML elements using the localization key. The database schema for the toolkit consists of the following tables:

Aa479334.entloctoolkit_02(en-us,MSDN.10).gif

Figure 2. Toolkit database schema

Table 2. Enterprise Localization Toolkit resources and relationships

ResourceDefinition
ApplicationsStores information about each application that is defined; primary key is ApplicationID.
ApplicationCulturesTracks what cultures are enabled for an application. Primary key is ApplicationID + Culture. This table is related to the Applications table.
ControlTypesContains the types of controls available and the assembly that contains them. ControlTypes are added using the Admin utility. Primary key is ControlType.
CulturePropertiesHolds the properties associated with a particular control property, one for each culture. Primary key is refID, which maps to the DictionaryProperties table.
DictionaryPropertiesContains one row for each control's property defined using the management application. One row correlates element, controlType and property to a unique identifier, refID. Primary key is refID. This table is related to the Properties, Elements and CultureProperties tables.
ElementsContains one row for each resource element defined by the designer/programmer. A resource element corresponds to one or more localized controls. Primary key is ElementID. This table is related to the DictionaryProperties and Applications tables.
FilesContains one or more rows per ElementID. This is used to track the files where an element is being used. This is only used during auto population.
PropertiesContains one row per control property. All the properties that are defined on a control are stored in this table. Primary key is ControlTypeID + PropertyID. This table is related to the DictionaryProperties and ControlTypes tables. Control properties can be added to this table using the Admin.exe utility program.

Automatic-Populate the Localization Database for an Application

The toolkit allows developers to design and code their Web sites and add a key to each server control that is to be localized and not write any initialization code for that control. The developer then sets the default localized values for each of the properties on the control that is to be localized. Then in the Web.config file, the auto population key is configured to populate a new or existing application. With this key enabled, when a page is executed, the toolkit will store in the database the key and any properties that have been set for all of the server controls on the page. This feature doesn't handle all properties; for instance combo boxes items cannot be automatically populated. Also, if you display different controls based on user role or other business logic, the page will have to be executed for each role or business logic path.

This can be used to add to or update existing keys in an application's localization database, but is never able to delete any keys or properties. This feature is intended to assist in the way the database is populated, allowing an easier population and maintenance of resource keys.

This feature should never be used on production servers; it severely affects performance because it makes a database call for each property on a page. To configure this, add the following line to the Web.config file's appsettings tag:

<add key="AutoPopulate" value="<name application to populate>" />

...where the value is the name of the application to populate. This application must already exist in the database.

Resource File Generation

The Enterprise Localization Toolkit uses the customizable resource format of the .NET Framework to store its localized resources. It requires this because it associates more than one control and property per key, which is outside the normal way of handling localized resources.

The toolkit generates the proper resource files and hierarchy depending on which type of resource files are desired. The deployment personnel, in conjunction with the programmers, must decide on the type of resource file to use. Then the operations person chooses the version of the resource file to generate, names the files, and then generates them by pressing a button. If subdirectories are needed for satellite assemblies, these will also be created automatically. When generating satellite assemblies, the loose file resources are placed in the Resources directory and a batch file called CreateSatellites.cmd is generated in case the satellite files need to be regenerated.

LocalizedPage class

The LocalizedPage class performs the localization of the control properties. When creating the application, the programmer can derive the page from the LocalizedPage class using the directive,

<@Page inherits=
   "Microsoft.ToolkitsEnterpriseLocalizationt.LocalizedPage"> 

...and ensuring that the toolkit assembly is located in the bin directory of the application. For pages using code behind, just derive your code behind class from LocalizedPage,

public class myCodeBehindPage : 
   Microsoft.Toolkits.EnterpriseLocalization.LocalizedPage

...and everything will work the same way.

In applications where derivation from the LocalizedPage class isn't possible, the Enterprise Localization Toolkit can still be used. There are a number of static methods on the LocalizedPage class. One of these methods, Localize, can be used to localize a page in the same manner as if the page was derived from the LocalizedPage class. To support this, the Localize function must be called at the end of the PreRender event handler on the page. Additionally, at the beginning of the Render method, the RemoveKeyAttribute function should be called. This function removes the key attribute, so that is doesn't appear in the generated HTML. Below is sample code for this method of using the Enterprise Localization Toolkit.

   ArrayList affectedControls;
   
   protected override void OnPreRender(EventArgs evt)
   {
      affectedControls = new ArrayList();
      LocalizedPage.Localize(this.Controls, affectedControls, 
         IsPostBack, EnableViewState);
   }

   protected override void Render(HtmlTextWriter writer)
   {
      LocalizedPage.RemoveKeyAttribute(affectedControls);
      base.Render(writer);
   }

In order to properly localize the page, the user's culture must be set for the current thread. The user's desired culture can be obtained by using HTTP header information or by storing some profile information about the user. The current thread's culture is set using the code:

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");

The CultureInfo class can then be cached in session state for the next time the user visits or it can be created each time.

During the page's Render event, the LocalizedPage class iterates through all the controls on a page looking for the key attribute. The actual name of the attribute is configurable using settings in the Web.config file. See Appendix B for more on Web.config configurations. On each control where the attribute is found, the LocalizedPage class asks the ResourceManager if there is a corresponding resource assigned to that key. If a resource is located, each of the specified control properties is set to the proper value for that culture.

Toolkit Technical Overview

Settings class

The Settings class is a general help class that contains access to configuration settings and other helper functions that make using the toolkit easier. The Settings class is able to read the Web.config file and get runtime configuration settings for each of the configurable items defined. It automatically caches these settings to improve performance. The list of configurable items can be found in Appendix B. Other functions provided by this class are helper functions to load drop-down lists with available cultures and applications. The Settings class also contains the function that generates both types of resource files.

The Settings class is mainly used to get access to the configuration and to get an instance of the current ResourceManager class. Please refer to the Toolkit Reference section for a detailed description of the other methods of this class.

LocalizedPage class

As stated above, the LocalizedPage class performs the setting of control properties that represent the localized resources. In order to get this to work, the programmers must derive their pages from the LocalizedPage class. This is accomplished by using the inherits attribute on the @Page directive.

<%@ Page language="C#" inherits=
   "Microsoft.Toolkits.EnterpriseLocalization.LocalizedPage" %>

The LocalizedPage class overrides the PreRender and Render methods of the standard Page class. This allows the LocalizedPage class to perform the localization of the controls automatically. When the page's PreRender method is called, all of the controls in the server hierarchy are iterated through, and if they are derived from System.Web.UI.WebControls, System.Web.UI.HtmlControls, or expose the Attributes property that contains a System.Web.UI.AttributeCollection, they are interrogated using Reflection for the key attribute. (See the .NET Framework documentation for additional information on reflection.) The localized property values are applied during PreRender method. This is done for two reasons: first, the entire server control hierarchy has been created, so elements that are defined in templated control or DataGrids have been expanded allowing each element in the DataGrid to be localized. Second, the ViewState has not yet been saved, so any changes that are made to the controls will be persisted for use during PostBack. ViewState is not required for the toolkit to properly work, it just reduces the number of times that the localization process must be performed, increasing performance.

Additionally, during the Render method, the key attribute is removed from any controls identified during PreRender that had the key attribute. This is done so the HTML output doesn't have erroneous attributes in it. At this stage of processing, ASP.NET doesn't bother remembering the attribute was taken away. If the key was removed during PreRender, the attribute removal would be remembered, breaking the localization going forward.

When the key attribute is located on a control, the LocalizedPage class obtains a reference to the shared ResourceManager using the Settings.CurrentManager method. The first time the Settings.CurrentManager method is called. It will create a shared ResourceManager class and place it into the ASP.NET cache. The cache has a dependency on the Web.config file, in case an operator changes the configuration. Caching the ResourceManager greatly improves performance and should be used regardless of whether the toolkit is used or not. The default variable name of the cached ResourceManager is LocalizationToolkitResourceManager. (The name of this application variable is configurable using attributes in the application's Web.config file.)

The ResourceManager is responsible for finding and loading culture-based resource files. It does this by using custom ResourceSet and ResourceReader implementations to load the culture resources requested by the user. Once the requested culture's resources are loaded, the ResourceManager returns a LocalizationElement object that manages the specific resource strings associated with the control types and properties for the specified resource key.

The LocalizationElement class is able to bundle all the properties associated with a particular resource key into one ResourceManager call, allowing the association of multiple properties for one resource key. Properties are further bundled by control type allowing different control types to share the same resource key. For instance, the Label class and TextBox class both have the Text property defined. This enables the designer to assign one resource key for both the label and the text box, but allows the text property to be set to different values based on the control type. This enables sharing of resource keys for controls that reference the same logical element. A scenario where this can be useful is on a page that allows viewing and editing of the same data. In view mode you would use a label control to display the data, while in edit mode, a TextBox is used. The same resource key can be assigned to both of these controls, whereas in the base .NET Framework, these would have to be different resource keys. This simplifies the management of resource key associations by enabling sharing of logical resource key across different control types. The Web-based management interface can be extended to automatically relate properties of different control types with the same key.

The page then calls LocalizationElement.SetProperties, passing the control to be localized. The LocalizationElement.SetProperties method looks at the control type of the control, finds any properties that are defined for that control type, and uses Reflection to set the properties to their defined values. For collection-based properties, it adds items to the collection. This same process is repeated for each control on a page that has the key attribute defined. Setting the control's properties is done automatically by setting a key attribute, saving a lot of code that must otherwise be written in the PageLoad event of the ASP.NET page.

LocalizedPage also exposes a number of methods that can be called to force localization of controls. This is useful if, during PostBack, either the localization key changes or the control should be reloaded. For more information on LocalizedPage, see the API reference documentation, Toolkit.xml, in the Documentation subdirectory.

ElementResourceSet class

The ElementResourceSet class is derived from the ResourceSet class. Its purpose is to hold a particular culture's resources for the ResourceManager. It uses a HybridDictionary to hold the corresponding key value pairs and LocalizationElement class. This is different than the base ResourceSet class in that its value is a LocalizationElement object, not a string. (ResourceSet is able to hold Objects, but its base functionality is to hold strings.) Since it holds a LocalizationElement, additional methods have been added to allow access to properties. For instance, you can create an ElementResourceManager from a ResourceManager using:

ElementResourceSet rs = 
        Settings.CurrentManager.GetResourceSet
      (Thread.CurrentThread.CurrentUICulture, 
         true, true) as ElementResourceSet;

This returns the ElementResourceSet for a particular culture. Then the GetProperty method can be called on ElementResourceSet to return a specific property value for a specified control type and resource key

rs.GetProperty("link_Edit", "System.Web.UI.WebControls.LinkButton", 
      "Text") as String;

The base ResourceSet.GetString(string key) can also be called. It will assume that you want the default control type and default property, which are set to be a Label's text property. If you have that property set, then you'll get the value, otherwise you'll get an empty string.

LocalizationElement class

This class manages the relationships between the various control type properties and a resource key. It contains a HybridDictionary of control types and their properties. The key is the control type name, like System.Web.UI.Label. The value in the name value pair is another HybridDictionary containing the properties the designer defines. This second HybridDictionary contains the property name and the property value for the specified culture.

There are a few interesting methods on the LocalizationElement class. SetProperties takes a control and based on the control type, sets all the defined properties. GetProperties takes a control type and returns a HybridDictionary containing the defined properties and their values. GetProperty and GetStringProperty can also be used to return property values for specified control type properties. The other methods on LocalizationElement can be used, but really should not be needed.

Reader and Writer class

The Reader and Writer class are used by the ElementResourceSet to read and write the custom format for the resource files. They should not be used for any other purpose.

Performance

There is of course a performance impact in getting automatic localization compared to the normal .NET Framework localization because reflection is being used to load the properties at runtime rather than writing a line of code to set the property. This is shown in the following performance graphs. Therefore, the toolkit should not be used on high-throughput Web sites where performance is paramount and little business logic is executed.

The toolkit is a great choice for sites that have more business logic executed, so the impact of localization is less a part of the overall request. It is also a good choice for sites that did not think about localization until after the site was written, as it can be easily retrofitted into an existing site by adding keys to controls and then using the automatic population feature. Based on reduced maintenance costs and easier management of resource strings, for a number of scenarios this performance impact is negligible, especially if other operations, such as database access or complex business logic, are added.

If the site is primarily HTML and the use of the Enterprise Localization Toolkit is the largest cost, then this cost can be greatly reduced by using ASP.NET OutputCaching. OutputCaching improves performance when using the Enterprise Localization Toolkit or.NET Framework localization, so it should always be used. OutputCaching enables ASP.NET to cache dynamically constructed pages for a certain length of time. Caching is enabled by the user of the @OutputCache directive in this manner:

<%@ OutputCache Duration="60" VaryByParam="None" %>

This would cache the dynamically constructed page for 60 seconds for all user requests. Caching can also take place by having different cached pages based on query string parameters. As you can see from the performance graph in Figures 3, enabling OutputCaching greatly improves performance. See the .NET Framework General Reference for additional information on @OutputCache.

In Figure 3, you can see that using the toolkit has an impact. The standard .NET lines show the performance impact of localization using the standard .NET Framework methods that use a number of ResourceManager.GetString operations to set individual control property values in PageLoad. The toolkit numbers show the performance when using the Enterprise Localization Toolkit for one or five properties per control.

All performance numbers were generated against a dual processor (800MHz) Compaq Proliant DL 360 with 1 GB of RAM. All tests were performed using three client machines simulating 625 concurrent users with no wait times (125 threads with five sockets each). These are not rigorous tests, but should give an idea of performance levels on your Web site.

For tracking performance, four performance counters are installed in the Performance Monitor application. They are under the Enterprise Localization category. They tell the number of substitutions taking place, the number of substitution errors that are taking place, and the average rate of substitutions.

Aa479334.entloctoolkit_03(en-us,MSDN.10).gif

Figure 3. Localization service time

Aa479334.entloctoolkit_04(en-us,MSDN.10).gif

Figure 4. Localization impact on Web throughput

Resource Generation Utility

To generate the resource files, use the LocalizationManagement.exe application located in the Admin tools directory. To generate the files for an application:

  1. On the Tools menu, click Options to configure the Database connection string.
  2. On the Applications menu, click Open Applications … to open the application.
  3. To open the Generate Resource Files dialog box, on the Tools menu, click Generate Resources, and then click Generate Resource Files (or press F9). The Generate Resource Files dialog box opens as shown in Figure 5.

    Aa479334.entloctoolkit_05(en-us,MSDN.10).gif

    Figure 5. The Generate Resource Files dialog box

  4. Under Neutral Language File, type in or browse to find the name of the neutral language resource file.
  5. Select the Resource File Type.
  6. Click Generate Files.

    The files of the desired type for the selected application will be generated in the subdirectory containing the neutral language resource file. If Satellite Assemblies is chosen for the Resource File Type, multiple subdirectories could be created, each containing the satellite assembly for the indicated culture. In addition, a Resource directory is created that contains all the loose file resources required to generate the satellite assemblies along with a batch file that can be used to regenerate them.

Resource File Viewer

Since the Enterprise Localization Toolkit uses a custom resource format, a utility is supplied that enables the viewing of resources in a file. Use the View.exe utility located in the Admin tools subdirectory to view either loose file or satellite assemblies. The viewer displays the file contents in a tree view as shown in Figure 6:

Aa479334.entloctoolkit_06(en-us,MSDN.10).gif

Figure 6. The Resource Viewer tree view

To view multiple files at one time, on the File menu, click Open or drag-and-drop files onto the window.

Frequently Asked Questions

Q.Why isn't the toolkit DLL strongly named?
A. When a strong named assembly attempts to load another assembly, that assembly must also be strongly named using the same private key. Since the Enterprise Localization Toolkit assembly loads satellite assemblies, these must be signed with the same private key that the Enterprise Localization Toolkit assembly is signed with. To make the toolkit strongly named, generate your own private key using the Sn.exe utility. Then sign both the Enterprise Localization Toolkit assembly and the satellite assemblies the –k option of the compiler. To sign the satellite assemblies, the command lines in the GenerateSatellites function in support.cs must be modified.
Q.Can drop-down lists and list boxes be localized?
A.Yes. The Web-based Management application is able to set properties that are collections. This allows the localization of lists of items. Developers only need to mark the list with the key attribute and translators just type in the localized list of items.
Q.Can dynamically loaded pagelets (.ascx) be localized?
A.Yes. Since the automatic localization is performed just before the page is rendered, any control that exists in the server control hierarchy can be localized. The only requirement is that the controls have a key attribute. See the drop-down list sample for details.
Q.How can I localize a user control that will be used in many different places on my site?
A.A user control (.ascx) that will be used in different places with different text can still be localized using the toolkit. The difficulty is that the key cannot be statically defined in the .ascx file, but must be defined on the instance of the user control. To do this, follow these steps:
  1. In the Web-based Management application, define two keys: one for each localized header text for a Label control. For example:
        headerTextOne  en   Hello
        headerTextTwo  en   Goodbye
    
  2. Change your user control Page_Load to be the following, where Header is a Label control that displays the variable text in the user control:
    private void Page_Load(object sender, System.EventArgs e)
    {
        // Put user code to initialize the page here
        Header.Attributes["key"] = Attributes["key"];
    }
    
  3. Declare the user control as follows:
    <%@ Register TagPrefix="uc" TagName="Header" Src="Header.ascx" %>
    <uc:Header id="myHeader" runat="server" key="headerTextOne" />
    

This allows the key attribute to be changed at runtime. You can change the key attribute or any other property on a control (user or otherwise) and still have the Enterprise Localization Toolkit work as long as everything is done before the PreRender method starts—after that it's too late.

See the user control sample for details.

Q.Why do I get an Access Denied error when using satellite assemblies and impersonation?
A.Because ASP.NET is run as a particular NT user that does not have access to most of the file system, but does have access to the temporary directory for compilation of cached files. If you run with impersonation on, the impersonated user must also have access to this temporary directory to allow assembly caching. If impersonation of the user credentials is required, use loose file resources, as they are not cached and won't require permission to this directory.
Q.Is the toolkit supported?
A.The toolkit is not an official Microsoft-supported product. However, you can get support from, and send your feedback to, entloctk@microsoft.com.

Toolkit Reference

All of the following components are in the Microsoft.Toolkits.EnterpriseLocalization namespace. For reference documentation, please see the Toolkit.xml in the Documentation subdirectory.

Appendix A: .NET-supported Cultures

There are lots of different cultures that are supported by the .NET Framework. You can get a complete table of the supported cultures by compiling and running the following program:

using System;
using System.Globalization;
using System.Threading;
 
namespace ConsoleApplication2
{
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      class EnumCulture
      {
static void Main(string[] args)
       {
            CultureInfo[] ciArray = CultureInfo.GetCultures(CultureTypes.AllCultures);
 
 foreach(CultureInfo ci in ciArray)
              Console.WriteLine("{0}\t{1}\t{2}", ci.Name, ci.LCID, 
               ci.DisplayName);
  }
      }
}

Appendix B: Web.Config Settings

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <sectionGroup name="system.web">
         <section name="appsettings" 
            type="System.Configuration.NameValueSectionHandler,
               System" />
      </sectionGroup>
   </configSections>
   <system.web>
      <appsettings>
         <add key="DSN" value="server=myServer;uid=sa;pwd=;
            database=LocalizationToolkit" />
         <add key="ResourceBaseName" value="Framework" />
         <add key="ResourceManagerType" value="LooseFile" />
         <add key="ApplicationPath" value="C:\\Localization Toolkit" 
            />
         <add key="SupportedCultures" values="en;en-us;en-uk;fr;de" 
            />
         <add key="EnableWMI" values="false" />
      </appsettings>
   </system.web>
</configuration>

Table 3. Web.config parameters

ParameterDescription
ApplicationPathContains the string pointing to the root of the application path. Normally this is the root directory of the Web application.
DSNConnection string for the Web-based management application. This is not needed in a production environment because resource files are used directly.
ResourceBaseNameThe base file name for the applications resource files. If the base name if foo, then for loose files, the resource file should be named foo.en-US.resources for the US English resources. For satellite assemblies, there will be a file named foo.dll in the en\en-US subdirectory.
ResourceManagerTypeThe type of ResourceManager to create, either loose files or satellite assemblies. Parameter must be either "LooseFile" or "Satellite".
ApplicationVariableNameName of the application variable in which to store the shared ResourceManager. The default value is LocalizationToolkitResourceManager.
ResourceManagerKeyName of the key attribute that is added to server controls to enable automatic localization. The default attribute name is "key".
SupportedCulturesContains a semi-colon delimited list of the cultures available to the user. Names follow the RFC 1766 standard in the format "<languagecode2>-<country/regioncode2>", where <languagecode2> is a lowercase two-letter code derived from ISO 639-1 and <country/regioncode2> is an uppercase two-letter code derived from ISO 3166. For example, U.S. English is "en-US".
EnableWMIEither "true" or "false". If set to true, then WMI events will be generated for failures during substitution.

Note: If true, permission to fire WMI events must be granted to the ASP.NET process.

Appendix C: Installation

Prerequisites

  • Any version of Microsoft Windows® capable of running ASP.NET and the Microsoft .NET Framework.
  • Microsoft .NET Framework
  • Microsoft SQL Server 2000
  • Microsoft Internet Information Server (IIS)

Install software

  • Run the Setup program. The default installation directory is a virtual directory under your wwwroot called LocalizationToolkit. If you install to a different directory, you will have to adjust the file installation file paths referenced below. This setup program will create a new virtual directory called LocalizationToolkit.

Install the database

There are two options for creating the database. If SQL Server 2000 is being used, then the .mdf and .ldf files can simply be attached to the current database. These instructions work for attaching a database.

  1. To start the Enterprise Manager, click Start, click Programs, click Microsoft SQL Server, and then click Enterprise Manager.
  2. Select the Microsoft SQL Server that you want to install and select the Databases node.
  3. On the Action menu, click All Tasks, and then click Attach Database.
  4. In the Attach Database dialog box, under MDF file of database to attach, enter C:\Inetpub\wwwroot\LocalizationToolkit\Database\LocalizationToolkit.mdf.
  5. Click Verify, click OK, and then click OK again after the database is successfully attached.

As an alternative, scripts are provided that can create the database and text-based DTC extracts are available for import. All these files can be located in the Database subdirectory.

Configure the Database Connection String

  1. In the application directory C:\Inetpub\wwwroot\LocalizationToolkit, the Web.config file contains the database connection string. If SQL Server is not installed on the same machine as the Web server, the connection string must be changed.
  2. To Change the connection string, edit the link that looks like this:
    <add key="DSN" value="server=(local);Integrated 
          Security=false;uid=;pwd=;database=LocalizationToolkit" />

Register Performance Counters

  1. Run the RegisterPerfCounters utility program on each Web server where the Enterprise Localization Toolkit will be run. Administrative privileges are required to add performance counters.
  2. Performance Monitor can be used to verify that the performance counters have been added.

Register WMI events

  1. Run installutil LocalizationToolkit.dll on each Web server where the Enterprise Localization Toolkit will be run. Administrative privileges are required to register the WMI events.
  2. WBEMTest (located in %WINNT%\System32) can be run to ensure that events are being generated.

Appendix D: Installed Files

The following files are installed as part of the Enterprise Localization Toolkit:

<root>   Root application directory (C:\inetpub\wwwroot\LocalizationToolkit)
   Application.aspx   
   ApplicationCultures.aspx
   Default.aspx
   Designer.aspx
   ElementDetail.aspx
   EULA.rtf   License agreement
   LocalizationDetail.aspx
   Localizer.aspx
   Menu.ascx   Left menu on each page
   Operations.aspx   (obsolete) Use the Management application
   PageHeader.ascx   Header associated with each page
   Style.css   Style sheet
   Web.config   Application configuration

<root>\Admin Tool   Administration tools directory
   AddControls.cs
   AddControls.exe      Utility used to add controls to the database
   LocalizationManagement.exe   Tool used to generate resource files
   LocalizationToolkit.dll   
   Makefile
   RegisterPerfCounters.cs
   RegisterPerfCounters.exe      Utility used to register 
               performance counters
   Viewer.exe      Utility that allows viewing of the contents of loose 
               file or satellite assemblies

<root>\Bin   Binary directory containing libraries and resources
   LocalizationToolkit.dll   Main assembly for the localization toolkit
   Toolkit.dll   Invariant resources for the application
      
<root>\Bin\DE   German language resources for the application
   Toolkit.resources.dll
<root>\Bin\EN   English language resources for the application
   Toolkit.resources.dll
<root>\Bin\FR   French language resources for the application
   Toolkit.resources.dll
<root>\Bin\NL   Netherlands language resources for the application
   Toolkit.resources.dll

<root>\Database   Contains database related files
   ApplicationCultures.txt
   Applications.txt
   ControlTypes.txt
   CultureProperties.txt
   databaseScript.sql   T-SQL scripts to create the database
   DictionaryProperties.txt
   Elements.txt
   LocalizationToolkit.mdf   Database file
   LocalizationToolkit.ldf   Database file
   Properties.txt
   SQL 7.0 Compatible Data…   Script file for creating a database for 
               SQL 7.0

<root>\Docs   Documentation about the Toolkit
   doc.css   XSL style sheet to display XML documentation
   doc.xsl   XSL file to transform toolkit.xml
   LocalizationToolkit Interfa…   User Interface document
   LocalizationToolkit.doc   Technical Documentation
   Readme.txt   
   toolkit.xml   XML based documentation about Toolkit APIs

<root>\Samples
      default.aspx   Sample entry page
      PageHeader.ascx   Page header user control
      Styles.css   Stylesheet for samples
      Web.config   Web configuration file for samples

<root>\Samples\Basic   Basic sample
      default.aspx
   
<root>\Samples\Bin   
      LocalizationToolkit.dll   Localization toolkit assembly
      Samples.dll   Neutral language resource assembly

Note: the de, fr and en subdirectories contain additional satellite 
               assemblies, one for each language.

<root>\Samples\Lists   Localized list box sample
      default.aspx   

<root>\Samples\NonDerived   Shows how to use the toolkit without deriving 
               from the LocalizedPage class.
      default.aspx   

<root>\Samples\UserControls   Shows how to localized dynamic properties on 
               user controls.
      default.aspx   

<root>\Src   Source code to the library
      AssemblyInfo.cs   Version, copyright information
      Element.cs   LocalizationElement class
      LocalizationToolkit.reso…   Resource file for the library
      LocalizedPage.cs   Localized page code
      Makefile
      PerformanceCounters.cs   Performance counter class   
      ResourceReader.cs   Custom ResourceReader class
      Resources.txt   Resources for the library
      ResourceSet.cs   Custom ResourceSet class
      ResourceWriter.cs   Custom ResourceWriter class
      Settings.cs   General settings and help functions.
      Wmi.cs   WMI event class

Appendix E: Samples

How to localize DropDownList items

One of the abilities of the Enterprise Localization Toolkit is to allow localization of complex data types such as collections. A good example of this is to localize the items in a DropDownList. To do this first use the Web-based management tool to add the localized list based resources (see the User Interface Document's Element Properties Detail section in the User's Guide in the download for additional information).

<%@ Page language="C#" Inherits="Microsoft.Toolkits.EnterpriseLocalization.LocalizedPage" 
            trace="false" EnableViewState="true" %>
<%@ Import namespace="Microsoft.Toolkits.EnterpriseLocalization" %>

<script language="C#" runat="server">
void CountryChanged(object src, EventArgs evt)
{
   myLabel.Text = String.Format("Selected {0} with value of {1}", 
            countryDropDown.SelectedIndex, 
               countryDropDown.SelectedItem.Value);
   stateDropDown.Attributes[Settings.KeyName] = 
            countryDropDown.SelectedItem.Value;
   Reload(stateDropDown);
}   
</script>

<html>
<body>
<form runat="server">
   <asp:Label key="ApplicationTitle" runat="server" 
            EnableViewState="false" /><br>
   <asp:DropDownList id="countryDropDown" runat="server" 
      key="CountryList" 
      OnSelectedIndexChanged="CountryChanged" 
      AutoPostBack="true" >
   </asp:DropDownList>
   <asp:DropDownList id="stateDropDown"  key="none" runat="server" />
   <br>
   <asp:Label id="myLabel" runat="server" /><br>
   <a href="Test.aspx">Refresh</a>
</form>
</body>
</html>

How to localize without deriving from LocalizedPage

This sample shows how to use the Enterprise Localization Toolkit without deriving from the LocalizedPage class. First declare an ArrayList to hold the controls that are affected by the localization. Then in PreRender, call the static method LocalizedPage.Localize, passing the page's control array, the ArrayList of affected controls, PostBack status and the current ViewState. In the Render method, call the static method LocalizedPage.RemoveKeyAttribute passing the ArrayList of affected controls.

<%@ Page language="C#"  EnableViewState="true" %>
<%@ Import namespace="Microsoft.Toolkits.EnterpriseLocalization" %>
<%@ Import namespace="System.IO" %>
<%@ Import namespace="System.Xml" %>
<%@ Import namespace="System.Xml.Serialization" %>
<%@ Register tagprefix="test" tagname="t" src="test.ascx" %>

<script language="C#" runat="server">

   ArrayList affectedControls;
   
   protected override void OnPreRender(EventArgs evt)
   {
      affectedControls = new ArrayList();
      LocalizedPage.Localize(this.Controls, affectedControls, 
            IsPostBack, EnableViewState);
   }

   protected override void Render(HtmlTextWriter writer)
   {
      LocalizedPage.RemoveKeyAttribute(affectedControls);
      base.Render(writer);
   }
   
   void CountryChanged(object src, EventArgs evt)
   {
      Trace.Write("CountryChanged", "");
      myLabel.Text = String.Format("Selected {0} with value of {1}", 
            countryDropDown.SelectedIndex, 
               countryDropDown.SelectedItem.Value);
      stateDropDown.Attributes[Settings.KeyName] = 
            countryDropDown.SelectedItem.Value;
//      Reload(stateDropDown);
   }
   
</script>

<html>
<body>
<form runat="server">
   <asp:Label key="ApplicationTitle" runat="server" 
            EnableViewState="false" /><br>
   <asp:DropDownList id="countryDropDown" runat="server" 
      key="CountryList" 
      OnSelectedIndexChanged="CountryChanged" 
      AutoPostBack="true" >
   </asp:DropDownList>
   <asp:DropDownList id="stateDropDown"  key="none" runat="server" />
   <br>
   <asp:Label id="myLabel" runat="server" /><br>
   <a href="Test.aspx">Refresh</a>
   <test:t runat="server" />
</form>
</body>
</html>
Show: