When introducing the item type multiple-choice field into the application, we defined the following values:
<?xml version="1.0"?> <type> <type-enum value="(Not selected)"/> <type-enum value="Important"/> <type-enum value="Not important"/> <type-enum value="Personal"/> </type>
For simple applications with a limited audience, it is often acceptable to
use values which are then presented unchanged such that the value
Personal
is known both inside the application and is also shown to
the user as the textual string Personal
. However, for other
applications there may be good reasons not to show values directly in this
way:
123
representing the same concept as Personal
.Personal
may not be understood by users who do
not speak or otherwise use the English language.We must therefore consider introducing additional label information in order to remedy the first case, at least. Consequently, we may modify the defined values as follows:
?xml version="1.0"?> <type> <type-enum value="0">(Not selected)</type-enum> <type-enum value="I">Important</type-enum> <type-enum value="N">Not important</type-enum> <type-enum value="P">Personal</type-enum> </type>
Here, we have provided user-visible labels which can now be used by the template. A single change to the item type choices list is required to include these labels as the visible text in that particular form control whilst maintaining the usage of the internal values:
<p>
Item type:
<select template:multiple-choice-list-field="type,type-enum,value" name="..." multiple="multiple"
onchange="requestUpdate(
'comments',
'{template:list-attribute('type-enum', 'value')}',
'{template:other-elements(../options)}',
'{template:child-attribute('value', template:child-element('comment', 1, template:other-elements(../options)))}',
'/structure/item/options')">
<option template:multiple-choice-list-value="type-enum,value,selected,text()" value="..." />
</select>
</p>
The addition, as described in the template:multiple-choice-value
and template:multiple-choice-list-value
sections of the "Template Attribute Reference"
document, selects the text inside the appropriate type-enum
elements and inserts it as a label into each choice in the item type list.
To update the special WebStack resource, we now need to modify a few of the class attributes:
template_resources = { "structure" : ("structure_multivalue_label_template.xhtml", "structure_output.xsl") } init_resources = { "structure" : ("structure_multivalue_label_template.xhtml", "structure_input.xsl") } document_resources = { "types" : "structure_types_label.xml" }
With these adjustments, it should now be possible to see the original labels
and yet have the application manipulate a separate set of internal values.
Note that it may be necessary to remove the old stylesheet for producing
output, structure_output.xsl
, so that the updated version of the
template is taken into use.
Whilst the above work made it possible to satisfy the first motivation of the use of labels - to hide internal values - it did not permit us to provide translations for different languages. In fact, there are at least two approaches which could provide labels in multiple languages:
types
and type-enum
elements for each language.The former approach might work in situations where multiple-choice values are obtained from a repository, such as a database, which contains the labels for items in each supported language. One can envisage a product database, for example, containing product descriptions for each language or market, and such information could be extracted in such a way that it could be convenient to use many different data files (or to extract the information dynamically, insert it into the form data document, and to provide a reference to the form data document as a source of value information).
Let us concentrate, however, on the latter, more convenient approach for our
example application. In order to produce translated labels, we must first
define a translations file
as described in the "Internationalisation"
document; this file can be saved alongside our other resources with the name
translations.xml
, and its contents can be defined as follows:
<?xml version="1.0" encoding="iso-8859-1"?> <translations> <locale> <code value="nb"/> <code value="nb_NO"/> <translation value="(Not selected)">(Ikke valgt)</translation> <translation value="Important">Viktig</translation> <translation value="Not important">Ikke viktig</translation> <translation value="Personal">Personlig</translation> </locale> </translations>
To make use of this file, we must add additional references in the Web resource's attributes:
document_resources = {
"types" : "structure_types_label.xml",
"translations" : "translations.xml"
}
And to introduce the translation mechanisms into the output production, we must modify the resource further:
# Complete the response. stylesheet_parameters["locale"] = trans.get_content_languages()[0] self.send_output(trans, [trans_xsl], structure, stylesheet_parameters, references={"translations" : self.prepare_document("translations")})
Here, we define a locale
parameter for the output stylesheet
using the first language specified in each user's browser's language
preferences. Then, we add a reference to the translations document specified
above.
Finally, we have to change the template to make use of the translations:
<p>
Item type:
<select name="..." template:multiple-choice-list-field="type,type-enum,value" multiple="multiple">
<option template:multiple-choice-list-value="type-enum,value,selected,template:i18n(text())" value="..." />
</select>
</p>
Note that we use the template:i18n
extension function to modify the text found in each type-enum
element in the types document. The usage of this function is described in the
extension function API
documentation.
Now, upon adding items in the application, if the
browser is set up appropriately - in this case using Norwegian
Bokmål [nb]
as the first choice of language - the item types will
appear translated in the final output.
Despite offering translations of labels, our work may not be complete. For long lists of values, it may be desirable to sort the choices in an order that is meaningful to the user, and it might not be possible to rely on a suitable ordering of values from the source which provides them. Consider a list of countries where the underlying multiple-choice value is a two letter country code. If such a list were presented sorted by the country codes, yet were to employ labels which gave the translated names of the countries, the ordering would seem almost arbitrary and difficult to navigate for the user.
To resolve such matters, we have to introduce an additional annotation in order to control the ordering of choices:
<p>
Item type:
<select name="..." template:multiple-choice-list-field="type,type-enum,value" multiple="multiple">
<option template:multiple-choice-list-value="type-enum,value,selected,template:i18n(text())" template:sort="template:i18n(text())" value="..." />
</select>
</p>
By requesting that the choices be sorted according to the translated label, they should have an ordering that the user can relate to and navigate more easily.
Now that we have designed and implemented a simple application, it may be worth reading some recommendations about developing your own applications.