This document describes how to build administrative modules that can present a localized GUI. By following these guidelines your modules will be able to change language in accordance with the rest of the administrative GUI.
Most modules are based on the LLCPropertyDef plug-in (Composite Property Definitions) or the DataMapper plug-in (Database Applications), both configured via the Datamap fan.
Common for both plug-ins are that the majority of configuration regarding GUI is done by writing XSL and therefore a XSL aware approach has been taken to introduce localization.
The two plug-ins has been extended with a XSL Entension that you can reference from your XSL document and use to fetch strings located in XML files. The XSL Extension can automatically detect the language of the administrative GUI and deliver the correct string from the XML files to your XSL.
When installing Composite a folder called “Localization” is placed in the Composite install folder. This folder contains a number of existing XML files, used by Composite, plug-ins and standard modules. The folder also contains a XML schema that defines the structure of the XML files.
The overall structure of the XML files looks as follows:
<?xml version="1.0" encoding="iso-8859-1"?> <ss:StringSet name="Ajax.myModule" xmlns:ss="http://composite.net/Localization/StringSet.xsd"> <ss:String id="heading"> <ss:English>Hello world!</ss:English> <ss:Danish>Hej verden!</ss:Danish> </ss:String> <ss:String id="label.name"> <ss:English>Please write your name</ss:English> <ss:Danish>Angiv venligst dit navn</ss:Danish> </ss:String> </ss:StringSet>
The name attribute on the StringSet element defines the namespace for your strings. You should define a namespace that won’t clash with other people’s namespaces, i.e. “mycompany.mymodule”.
The id attribute of the string identifies your string elements. This value helps you differentiate the strings within your namespace.
The namespace and id together defines a string identifier that works across all XML files. Your strings can be uniquely identified using the format <namespace>.<string id> - in the above example Ajax.myModule.heading identifies a unique string.
The elements within the String element define localized versions of your string. In the above example Danish and English localized versions has been defined.
When IIS launches the administrative module the content of the XML files will be loaded into memory and stay there for as long as the application is running. This makes the localization mechanism extremely fast, but does require some configuration if you wish to see changes made to the XML files appear immediately. Please see technical details below.
If the loading of the XML should fail information regarding the problem will be written to the local server’s event log. Points of failure can be malformed XML, XML that does not conform to the schema or strings that are defined multiple times.
To utilize the localization mechanism in your XSL you need to do the following:
You can signal that you want to use the localization mechanism by adding the following namespace declaration to your xsl:stylesheet element in your XSL
xmlns:str="http://www.composite.net/Localization"
With the above declaration in place, you can request a string from the XML files by using the following function:
str:GetStringWithConfig( <sting identifier> )
The <string identifier> is a concatenation of your string set name and your string id, separated by a dot. In the XML example above you would reference the “Hello world!” string using the following function call:
<xsl:value-of select=”str:GetStringWithConfig(‘Ajax.myModule.heading’)” />
The XSL extension will figure out what language is running and return the correct string.
If you wish to control what language implementation is returned you can use the following function:
str:GetString ( <sting identifier>, <language> )
<xsl:stylesheet version="1.0" xmlns:str="http://www.composite.net/Localization" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml"/> <xsl:template match="/"> <FormelementsCollection> <Formelement label="{str:GetStringWithConfig('Ajax.myModule.heading')}"/> <Formelement label="{str:GetStringWithConfig('Ajax.myModule.label.name')}"> <INPUT type="text" name="theName"> </Formelement> </FormelementsCollection> </xsl:template> </xsl:stylesheet>
Below is a walk through of some of the technical details of the localization mechanism – the intended audience are developers that needs to work intensely with the facility and curious people.
The XML files are loaded and parsed by a COM+ pooled component that lives in a COM+ library package. This component is created when it is instantiated and will stay in memory while the process that has called it runs.
This means that changes to the XML will not show up automatically.
You can “flush the pool”, thereby force a reload of all XML, by shutting down the CompositeAdmin COM+ package and unload/recycle the application in which the IIS site runs. This approach works if you are deploying a new set of XML files on a server.
If you disable object pooling, the XML files will be loaded and parsed with every instantiation of the component. This makes things slower, but in a development/debug phase this approach works great. To disable object pooling, locate the CompositeLocalization.StringProxy class in the CompositrAdminLib package, and configure it to not use object pooling.
The Localization folder is scanned for XML files by the localization mechanism – adding a file to this folder will make the localization mechanism load it at the next scan. You can create a arbitrary folder structure (the scanning will include any subdirectories).
You are encouraged to name your files in accordance with the string set name, i.e. “Ajax.myModule.xml” for the above XML example.
You can partition a string set across multiple files – a second file could contain “new strings” or a “new language”. Of course, new information can be added to the existing XML file at your discretion.