Username Password
Bookmark and Share


A major feature of WebGUI is the Internationalization (i18n) of the interface. By storing English strings in a data structure with a key, you can use the same key to store strings in Dutch, German, Spanish, and other languages. Using a combination of WebGUI::International objects in your asset, and ^International(); macros in your templates, you can make easily translatable interfaces. This example will make an i18n for the InfoCard asset created in the Assets chapter.


To use internationalization in your code, first make an i18n namespace in lib/WebGUI/i18n/English/. You can call yours Asset_InfoCard to follow with convention (assets start with Asset_, form controls start with Form_, macros with Macro_, etc...).


package WebGUI::i18n::English::Asset_InfoCard;

use strict;

our $I18N = {

'assetName' => {

message => q{InfoCard},

lastUpdated => 0,

context => q{The name of the InfoCard asset},





I18n modules are just Perl modules with a single “our” variable called $I18N. This variable is a hash reference of hash references, as outlined above. The key will be used to access your message in line 5, which is the internationalized text. I18n also provides for keeping track of the time lastUpdated, which is used by the i18n utility at, and the context in line 7, which is how the message will be used. Sometimes the translator won't be able to figure out what he's translating from the message, which is why the context can be useful.


Once you have a shell of an i18n module, you need a way to get at it from your asset. For this, make an i18n method in your asset class.


sub i18n {

my $class = shift;

my $session = shift;

return WebGUI::International->new( $session, "Asset_InfoCard" );



Notice that this is a class method, because you'll need to be able to use it from other class methods. It takes a single argument, a WebGUI::Session object, and returns a WebGUI::International object with your i18n namespace. Now that you have a way to get at your i18n, you need to use it.


To start, revisit the definition. Remember your label and hoverHelp keys? Now you can internationalize them instead of hard-coding English, like so:


sub definition {

my $class = shift;

my $session = shift;

my $definition = shift;

my $i18n = __PACKAGE__->i18n( $session );


tie my %properties, 'Tie::IxHash', (

templateIdView => {

tab => 'display',

fieldType => 'template',

label => $i18n->get('property templateIdView label'),

hoverHelp => $i18n->get('property templateIdView description'),

namespace => 'InfoCard',



First, get your WebGUI::International object. Then, in place of literal strings, use the get method to get the appropriate string from your Asset_InfoCard i18n file (lines 11-12). Notice the key used. Property templateIdView label is descriptive and follows the general<->specific rules outlined by Perl Best Practices. “property” because it's an Asset property, templateIdView'is the property, and “label” is what's being displayed. Now, when these keys are alphabetized (by the application) they will follow a logical pattern and be easier to translate.


Once you've changed all of your labels and hoverHelp to be i18n values, you can go back and add your English translation to your i18n module.


'assetName' => {

message => q{InfoCard},

lastUpdated => 0,

context => q{The name of the InfoCard asset},


'property templateIdView label' => {

message => q{View Template},

lastUpdated => 0,

context => q{Label for asset property},


'property templateIdView description' => {

message => q{The template to view the InfoCard},

lastUpdated => 0,

context => q{Description of asset property},



Now you can do this for other English text inside of your module, and you're left with only your template having plain English labels. To make those translatable, you can use the International macro inside of your template.


The International macro allows you to perform i18n lookups anywhere a macro can be used. Like the WebGUI::International->get method, the International macro is quite easy to use.


<h2><tmpl_var name></h2>


<dt>^International('property name label','Asset_InfoCard');</dt>

<dd><tmpl_var name></dd>


<dt>^International('property address label','Asset_InfoCard');</dt>

<dd><tmpl_var address> <br /> <tmpl_var city>, <tmpl_var state></dd>



Notice in the sample template above, international labels are reused from your asset's edit form. This is a good idea in most cases, but sometimes you'll want to use a different label. Take your address above. In the InfoCard edit form, Address refers only to the person's street address, but in your template, you bunch the entire address together: street, city, and state. So instead, give it a different i18n label.


<dt>^International('template address label', 'Asset_InfoCard');</dt>

<dd><tmpl_var address> <br /> <tmpl_var city>, <tmpl_var state></dd>


And, of course, add your new label to your English i18n translation.


'template address label' => {

message => q{Full Address},

lastUpdated => 0,

context => q{Label for the address, city, and state in the template.},



Placeholders and i18n

Most i18n values just work in all languages. You can translate words, phrases, or paragraphs and things come out just fine. Sometimes, however, the order of things must be reversed. This is most readily apparent when translating labels for numbers. How can you make i18n for, “Viewing results 1-10 of 30 total,” when those numbers are given in template variables?


Perl already has a method of dealing with such things: formats. Since formats are just strings with special parts (placeholders), you can store the format as an i18n value and use Perl's sprintf() function to replace the placeholders with the correct values.


my $currentPage = “1-10”;

my $total = “50”;

sprintf “Viewing results %s of %s total”, $currentPage, $totalResults;


Now, the string, “Viewing results %s of %s total,” will be translated into, “Viewing results 1-10 of 50 total.” All you need to do is move the string out to one of your i18n modules.


If you're in a template and you need to fill in a placeholder, all you need to do is pass it as another argument to the ^International; macro.


^International(“search title”, “Asset_Search”, “1-10”, “50”);

<!-- or more usefully -->

^International(“search title”, “Asset_Search”, <tmpl_var currentPage>, <tmpl_var total>);

Keywords: asset i18n translation

Search | Most Popular | Recent Changes | Wiki Home
© 2022 Plain Black Corporation | All Rights Reserved