Tuesday, August 29, 2006

XForms Tip: Dynamic Language Switching



Recently, I was booking a flight on an airline's web site, when the application asked for my departing country (Switzerland). As soon as I performed my selection, the page reloaded in German. Since my 10 years of studying German did not quite make me fluent, I looked for a way to switch back to English or French and surely I found reassuring "en" and "fr" links at the top of the page. I chose "en", which took me to an English page all right, but with all my booking information cleared! The browser's back button at that point resulted in an error message and I had to start over.

This anecdote leads right to this post's topic! With XForms, you can implement language switching very quickly and at the same time provide a user experience that I don't remember having seen in any web application so far. So let's look at the basic ideas:

  • The key is to store your text resources in separate XML files, one for each language. Name the files with suffixes such as _en or _fr using the standard language codes. The English resources can look like this:

    <resources>
      <titles>
        <main-title>Notice of Change of Address</main-title>
        ...
      </titles>
      <labels>
        <last-name>Last Name</last-name>
        ...
      </labels>
      <alerts>
        <last-name>Must contain letters...</last-name>
        ...
      </alerts>
    </resources>
    

  • Store the current language in a special XForms instance called language-instance.

    <xforms:instance id="language-instance">
        <language xmlns="">en</language>
    </xforms:instance>
    
  • Load the appropriate text resource into an instance called resources-instance using an XForms submission during the page's initialization, by reacting to the xforms-ready event. You can also provide a default, in this case English:

    <xforms:instance id="resources-instance" src="resources_en.xml"/>
    
  • Refer to resources using xforms:output, xforms:label, etc.:

    <xforms:output value="instance('resources-instance')/titles/main-title"/>
    <xforms:input id="dmv-last-name-control" ref="dmv:name/dmv:last-name">
        <xforms:label ref="instance('resources-instance')/labels/last-name"/>
        <xforms:alert ref="instance('resources-instance')/alerts/last-name"/>
    </xforms:input>
    

    At this point, your application is internationalized with all your text resources are now separate from the form itself.

  • Now, to make things really cool, provide a dropdown menu with the list of available languages, for example:

    <xforms:select1 ref="instance('language-instance')">
        <xforms:label ref="instance('resources-instance')/labels/language-choice"/>
        <xforms:item>
            <xforms:label>en</xforms:label>
            <xforms:value>en</xforms:value>
        </xforms:item>
        <xforms:item>
            <xforms:label>fr</xforms:label>
            <xforms:value>fr</xforms:value>
        </xforms:item>
        <xforms:send ev:event="xforms-value-changed" submission="update-language-submission"/>
    </xforms:select1>
    
  • Finally, here is the submission that updates the language resource:

    <xforms:submission id="update-language-submission" ref="instance('language-instance')"
            action="/forms/service/resources/{{.}}" validate="false"
            method="get" replace="instance" instance="resources-instance"/>
    

With this simple mechanism to update text resources, no page reload or data loss occurs when users change the page's language: they will probably love it ;-)

You can see the example live in the online DMV Forms example

No comments:

Post a Comment