Knickers: Change your underwear!
Messages, Labels, and Template Text

Overview

This document outlines how text and translations work within Knickers and your application.

One of the most overriding ideas in Knickers is that it should be as easily translatable as possible. This means that all displayed text should be centralized so that it's not necessary to hunt through code or templates to find translatable text. The result of this is that there are very few places to look for text that needs to be translated either for development purposes or for clients.

Additionally, we want to offer the ability for individual systems and subsystems to have customized versions of the text displayed, whether it's in the "default" language or in a translated one.

Locale

The Locale object is your friend. This is where you tell everything which localization you want to use. A locale consists of two parts: the language and the country. For example, to display American English you would set your language to "en" and your country to "US". For British English, you would use "en" and "UK". The combination of these two parts tells the system which language dictionaries to load.

Within the Knickers config you can set your default language and country using SYSTEM_DEFAULT_LANGUAGE and SYSTEM_DEFAULT_COUNTRY constants (which are "en" and "US" if you do not set them), which will control what locale is used if none is specified. It will also control the "fallback" locale used if translations cannot be found for a desired locale.

The locale, once initialized, is passed to the OutputGenerator. The OutputGenerator is in charge of finding the correct text to display. You don't need to worry about how that works. It's magic!

Types of Text

There are three types of text: Messages, Template Text, and Labels. Combined, these consitute all text displayed to both developers and end users.

Messages are "code generated" strings. This doesn't mean that your code is actually generating the content of a Message, but that the Message is not connected to any particular template and its display is controlled by your code opting to show it. The best example of these are error messages. Messages are shared globally throughout the system.

Template Text is contained within templates, connected to a particular page or widget. Template Text is specific to the template it's contained within but is shared across different formats of the same template.

Labels are shared globally like Messages but are *very* simple. They are single words, without formatting, and are designed to lend consistency to the system and minimize the need to translate commonly-used words. An example of this would be the word "Score" that might be shown on several pages if you are creating a suite of reports. You would not want to have to translate "Score" for every report that it's displayed on and its meaning is simple and consistent regardless of context. In this case, you would use a label. It should be understood that labels cannot contain formatting or tags and should not be used as part of larger messages. Labels may be used both in templates and in code.

Locations of Text

In Knickers, the message dictionary files are stored in

KNICKERS_ROOT/dicts/common/{LOCALE}/Messages.php

For Applications using Knickers, the location is:

KNICKERS_APP_ROOT/dicts/common/{LOCALE}/Messages.php

Customized versions (for different "systems" or "subsystems") of messages are here:

KNICKERS_APP_ROOT/dicts/custom/{SYSTEM}/{LOCALE}/Messages.php
KNICKERS_APP_ROOT/dicts/custom/{SYSTEM}/ss/{SUBSYSTEM}/{LOCALE}/Messages.php (not sure this works yet)

Template text is stored in dictionary files whose names and locations mirror those of the templates themselves, with a few differences. Templates are stored according to their template formats (cli, html, xml, etc) and without regard to language. Dictionaries, however, are unconcerned with template formats but are concerned with languages. They are stored in a "dicts" directory that contains a "common" and a "custom" directory, with locale subdirectories.

For exmaple, you may have two templates, KNICKERS_ROOT/common/tpl/cli/unit_test.tpl and KNICKERS_ROOT/common/tpl/html/unit_test.tpl. The English dictionary for these two templates will be in KNICKERS_ROOT/common/dicts/en_US/unit_test.tpl.dict.php. The French dictionary will be in KNICKERS_ROOT/common/dicts/fr_FR/unit_test.tpl.dict.php.

Customized templates are contained within
custom/{SYSTEM}/tpl 
or
custom/{SYSTEM}/ss/{SUBSYSTEM}/tpl. 
Customized dictionary files are contained within
dicts/custom/{SYSTEM}/[locale] 
or 
dicts/custom/{SYSTEM}/ss/{SUBSYSTEM}/locale.

Labels are in

KNICKERS_ROOT/dicts/common/{LOCALE}/Labels.php
KNICKERS_APP_ROOT/dicts/common/{LOCALE}/Labels.php
KNICKERS_APP_ROOT/dicts/custom/{SYSTEM}/{LOCALE}/Labels.php
KNICKERS_APP_ROOT/dicts/custom/{SYSTEM}/ss/{SUBSYSTEM}/{LOCALE}/Labels.php

Usage

To create a new Message, add the string to your Messages.php file in your default locale. Make sure your message's key is not already in use by another Message. Error messages should be prefixed with 'ERR_' and generic messages with 'MSG_'. Add the key and your text to the MESSAGES array.

Template text should be edited in your templates for your default locale. Distinct parts of text should be surrounded with {|TXT|SOME_IDENTIFIER}{/|TXT|SOME_IDENTIFIER}, where SOME_IDENTIFIER is a template-unique string used to identify your particular text. Note that template text may contain tags, but may not be contained *within* conditional tags (though template text can be located *between* conditional tags).

To have your template text tags and dictionaries generated automatically, run the text_tagger script (in knickers/scripts) on your file (./text_tagger.php [filename]).

To create a new Label, follow the instructions for Messages but put your text in the appropriate Labels.php file.

If you have text that is customized for a system or subsystem, be SURE to send your Config object to your Locale on construction. The Config is what tells the Locale how to look for custom files. Without that, you're going to be stuck wondering why your custom dictionary won't load.

Example:

$cfg = new Config('system_name');
$l = new Locale('en', 'US', $cfg);
$msg = new Message(TEST_APP_CUSTOM_CONSTANT);
$msg->getTranslatedString($l); // gets unparsed message from dictionary