Lorenzo Alberton

London, UK   ·   Contact me   ·  

« Articles

PEAR::Translation2 tutorials - "frontend" usage

Abstract: This first Translation2 tutorial shows how to deal with translated strings: how to fetch them one by one or in groups, and how to transform, cache and decorate them.


This first Translation2 tutorial shows how to deal with translated strings: how to fetch them one by one or in groups, and how to transform, cache and decorate them.

Creating a Translation2 object

Before using the class, you have to create an instance and connect it to the storage container. This is the only part that differs in the various storage drivers. Here's how you might connect to PEAR::MDB2:

<?php
// set the parameters to connect to your db
$dbinfo = array(
    'hostspec' => 'host',
    'database' => 'dbname',
    'phptype'  => 'mysql',
    'username' => 'user',
    'password' => 'pwd'
);
define('TABLE_PREFIX', 'mytable_');

// tell Translation2 about your db-tables structure,
// if it's different from the default one.
$params = array(
    'langs_avail_table' => TABLE_PREFIX.'langs_avail',
    'string_text_col'    => '%s'  //'%s' will be replaced by the lang code
);

$driver = 'MDB2';

require_once 'Translation2.php';
$tr =& Translation2::factory($driver, $dbinfo, $params);
?>

Here's how you can connect to the XML driver:

<?php
$driver = 'XML';
$options = array(
    'filename'         => 'i18n.xml',
    'save_on_shutdown' => true, //set to FALSE to save in real time
);
require_once 'Translation2.php';
$tr =& Translation2::factory($driver, $options);
?>

The gettext driver requires two .ini files containing the language and domain settings.

; langs.ini example:
; If one does not specify the source encoding, ISO-8859-1 is assumed
; Beware that gettext can choke on bad encodings!
 
[en]
name = English
encoding = iso-8859-1
 
[de]
name = Deutsch
encoding = iso-8859-1
 
[it]
name = italiano
encoding = iso-8859-1
;domains.ini example:
 
messages = /path/to/locale
2nddomain = /path/to/locale
3rddomain = /path/to/locale

Once you have them, you can connect with this code:

<?php
require_once 'Translation2.php';

$params = array(
    'prefetch'          => false,
    'langs_avail_file'  => 'path/to/langs.ini',
    'domains_path_file' => 'path/to/domains.ini',
    'default_domain'    => 'messages',
    //'file_type'       => 'po',
);

$tr =& Translation2::factory('gettext', $params);
?>

Connecting was the hardest part. From now on, you're ready to use Translation2 in a consistent way, regardless of the actual storage container used.

Fetching the translations

The get() method is used to fetch the translated string identified by (for instance) 'hour' from the 'time' group:

$hours = array(
    'en' => $tr->get('hour', 'time', 'en'),
    'de' => $tr->get('hour', 'time', 'de'),
    'de' => $tr->get('hour', 'time', 'fr'),
    'it' => $tr->get('hour', 'time', 'it'),
);

$hours will now contain

array(
  'en' => 'hour',
  'de' => 'Stunden',
  'fr' => 'heure',
  'it' => 'ora',
);

If you need the translations for one language only and/or from one group only, you can set it once for all:

$tr->setLang('fr');
$tr->setPageID('time');

echo $tr->get('hour');   // prints 'heure'
echo $tr->get('second'); // prints 'seconde'

Of course you can override the defaults any time, or reset them:

$tr->setLang('fr');
$tr->setPageID('time');

echo $tr->get('hour'); // prints 'heure', from the 'time' group
echo $tr->get('second', 'numerals'); // prints 'deuxième', from the 'numerals' group

$tr->setPageID('numerals');
echo $tr->get('second'); // prints 'deuxième', from the 'numerals' group

Fetching all the translations of a certain group of strings in one shot is often more convenient:

$strings = $tr->getPage('time', 'it');
//strings will now contain:
// [hour] => 'ora', [minute] => 'minuto', [second] => 'secondo', ...

Using Decorators

The main idea behind Translation2 is to have a lean core, and a simple way to extend the basic functionality. This is achieved thanks to decorators. They act as layers upon the base class and can be anything from filters to caching or logging modules.
A few of them are already included in the official package, but you can write new ones easily. To use them, all you have to do is calling getDecorator('DecoratorName') and eventually set some options. Here's an example of the Lang decorator, used to provide a fallback language for the strings that are not translated in the requested language:

// $tr is a Translation2 object
// english is the main language
$tr->setLang('en');

// add a fallback language layer
$tr =& $tr->getDecorator('Lang');
$tr->setOption('fallbackLang', 'it')

// now use Translation2 as usual...

If you are using the database container and want to lighten the load on your db, you can add a cache layer. Translation2 has two cache decorators, one memory-based (useful to prefetch a larger group of translations in memory and reduce the number of queries) and one file-based:

// add a memory-based cache layer:
$tr =& $tr->getDecorator('CacheMemory');
$tr->setOption('prefetch', true); //prefetch is on by default

// add a file-based cache layer:
$tr =& $tr->getDecorator('CacheLiteFunction');
$cacheLiteOptions = array(
    'cacheDir' => '/tmp/',
    'caching'  => true,       // enable or disable caching
    'lifeTime' => 3600,       // in seconds
    'cleaningFrequency' => 0, // never clean cached files (set 1 to clean at every request)
);
$tr->setOptions($cacheLiteOptions);

// now use Translation2 as usual...

NB: you can have as many decorators as you need, even of the same type. For instance, you can have two fallback languages, or a cache layer after each fallback language decorator.

Using parameters

Sometimes you need to place some parameters in the translations, and replace them at runtime. This makes maintaining the translations immensely easier. For instance, if you want to greet the logged user with a personalized message, you can use a placeholder in the message itself, and replace it with the user name. Let's say the translation strings for the message are "Hello &&user&&, welcome back!" for English, and "Ciao &&user&&, ben tornato!" for Italian (you can set the placeholder delimiters with the 'ParameterPrefix' and 'ParameterPostfix' options):

$logged_username = 'John Doe';

$tr->setParams(array('user' => $logged_username));

echo $tr->get('greeting_message', 'messages', 'en');
// Hello John Doe, welcome back!

echo $tr->get('greeting_message', 'messages', 'it');
// Ciao John Doe, ben tornato!

Recap

As you can see, working with Translation2 is very easy. Next time we'll see how to add new languages and translations to the storage container, i.e. the "Administration mode" usage. Stay tuned!

« Go back to PEAR::Translation2 tutorials index.




Related articles

Latest articles

Filter articles by topic

AJAX, Apache, Book Review, Charset, Cheat Sheet, Data structures, Database, Firebird SQL, Hadoop, Imagick, INFORMATION_SCHEMA, JavaScript, Kafka, Linux, Message Queues, mod_rewrite, Monitoring, MySQL, NoSQL, Oracle, PDO, PEAR, Performance, PHP, PostgreSQL, Profiling, Scalability, Security, SPL, SQL Server, SQLite, Testing, Tutorial, TYPO3, Windows, Zend Framework


Back