<?php
/**
 * patI18n
 *
 * $Id: patI18n.php 4 2007-06-17 20:13:53Z gerd $
 *
 * Modular translation interface
 *
 * @version     0.1.0
 * @package     patI18n
 * @author      gERD Schaufelberger <gerd@php-tools.net>
 * @license     LGPL
 * @link        http://www.php-tools.net
 */

/*
 * Load module base class
 */
if( !class_exists'patI18n_Module'false ) ) {
    require 
dirname__FILE__ ) . '/patI18n/Module.php';
}

/**
 * patI18n
 *
 * Modular translation interface
 * 
 * Inspired by GNU Gettext {@link http://www.gnu.org/software/gettext/} 
 * and it's PHP implementation, this packages provides an sort of compatible
 * but modular interface for translation.
 * 
 * Both, text domains and plural forms are supported as Gettext does it. The 
 * names of the static functions are the same as in Gettext. This way using
 * it is piece of cake when you are familiar with Gettext. Besides providing
 * the same interface, allows you to use the normal Gettext tools like 
 * "xgettext" to extract to-be-translated strings etc. 
 * 
 * Still, patI18n is not fixed to utilise Gettext at all. The modular design
 * allows to connect any kind of translation tool. Furthermore, you can even 
 * use more than one module at the same time.
 *
 * @version     0.1.0
 * @package     patI18n
 * @author      gERD Schaufelberger <gerd@php-tools.net>
 * @license     LGPL
 * @link        http://www.php-tools.net
 */
class patI18n
{
   
/**
    * complete locale name, e.g. "de_DE@euro" or "de_DE.UTF-8"
    */
    
const LOCALE_TYPE_COMPLETE '1';
    
   
/**
    * just the language name with variant, like "de_DE"
    */
    
const LOCALE_TYPE_LANG '2';
    
   
/**
    * just the short (two) letter language name, like "de"
    */
    
const LOCALE_TYPE_SHORT '4';
    
   
/**
    * List of concrete translation modules
    * @var array
    * @see addModule()
    */
    
static protected $modules    =   array();

   
/**
    * Current locale
    * @var string
    */
    
static protected $locale    =   'C';

   
/**
    * Add localisation module
    * 
    * Append named module into module chain. The module will be loaded 
    * automatically and configured with the given settings.
    * 
    * @param string $name module name
    * @param string $settings list of configuation options
    * @return bool true on success
    * @todo allow class loader to load from custom module folders
    */
    
static public function addModule$name$settings = array() )
    {
        
$class  =   'patI18n_Module_' $name;
        if( !
class_exists$classfalse ) ) {
            include 
dirname__FILE__ ) . '/patI18n/Module/' $name '.php';
        }

        
$m      =   new $class();
        
$m->configure$settings );

        
self::$modules[]    =   $m;
        return 
true;
    }

   
/**
    * Switch to language
    * 
    * This is the replacement for PHP's (@link setLocale()}. This call
    * gets forwared to all modules. 
    * 
    * Each module is expected to return "true". In case one module returns 
    * "false", further processing is canceled. 
    * 
    * @param string $string
    * @return bool true on success
    */
    
static public function setLocale$locale )
    {
        
self::$locale   =   $locale;
        foreach( 
self::$modules as $m ) {
            if( !
$m->setLocale$locale ) ) {                
                return 
false;
            }
        }
        return 
true;
    }
    
   
/**
    * Simple getter
    * 
    * @param int $type, on of: LOCALE_TYPE_COMPLETE, LOCALE_TYPE_LANG or LOCALE_TYPE_SHORT
    * @return string $locale
    * @todo this is just lazy implementation
    */
    
static public function getLocale$type self::LOCALE_TYPE_COMPLETE )
    {
        switch( 
$type ) {
            case 
self::LOCALE_TYPE_COMPLETE:
                return 
self::$locale;
                
            case 
self::LOCALE_TYPE_LANG:
                return 
substrself::$locale0);
                
            case 
self::LOCALE_TYPE_SHORT:
                return 
substrself::$locale0);
                
             default:
                break;
        }
        
        
// this is not suposed to happen
        
throw new Exception'The used type is unknown' );                
    }
    
   
/**
    * Gettext interface
    * 
    * This is the most simple version. It does neithere support domains nor
    * plural forms.
    * 
    * Again, this is just a forward to each module. The modules will
    * will be called in the same order as they were added. The first module
    * that returns "true" - which means the string was translated, ends 
    * the process - the rest of the modules won't be called at all!
    * 
    * @param string $string To be translated string
    * @return string translated string
    */
    
static public function gettext$string )
    {
        foreach( 
self::$modules as $m ) {
            if( 
$m->gettext$string ) ) { 
                return 
$string;
            }
        }
        return 
$string;
    }

   
/**
    * Gettext interface using domain
    * 
    * This is pretty much the same as {@link gettext()}. The only difference
    * is that the "domain" is passed to the module as well.    
    * 
    * @param string $domain name of text domain
    * @param string $string To be translated string
    * @return string translated string
    * @see gettext()
    */
    
static public function dgettext$domain$string )
    {
        foreach( 
self::$modules as $m ) {
            if( 
$m->gettext$string$domain ) ) { 
                return 
$string;
            }
        }
        return 
$string;
    }

   
/**
    * Gettext plural version interface
    * 
    * This is pretty much the same as {@link gettext()}, but there are
    * two strings to be translated. The second one is the plural form.
    * 
    * Some languages have more than one form for plural messages dependent 
    * on the count.
    * 
    * @param string $string To be translated string
    * @param string $stringPlural the plural form of the translated string
    * @param int $count The numnber of items the plural should be applied for
    * @return string translated string
    * @see gettext()
    */
    
static public function ngettext$string$stringPlural$count )
    {
        foreach( 
self::$modules as $m ) {
            if( 
$m->ngettext$string$stringPlural$count ) ) { 
                return 
$string;
            }
        }
        return 
$string;
    }
    
   
/**
    * Gettext plural version interface using domain
    * 
    * Pretty much the same as {@link ngettext()}, but it requires a "domain"
    * 
    * @param string $domain name of text domain
    * @param string $string To be translated string
    * @param string $stringPlural the plural form of the translated string
    * @param int $count The numnber of items the plural should be applied for
    * @return string translated string
    * @see ngettext()
    */
    
static public function dngettext$domain$string$stringPlural$count )
    {
        foreach( 
self::$modules as $m ) {
            if( 
$m->ngettext$string$stringPlural$count$domain ) ) { 
                return 
$string;
            }
        }
        return 
$string;
    }
}
?>