<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Contains the Translation2 base class
*
* PHP versions 4 and 5
*
* LICENSE: Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Internationalization
* @package Translation2
* @author Lorenzo Alberton <l.alberton@quipo.it>
* @copyright 2004-2008 Lorenzo Alberton
* @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
* @version CVS: $Id: Translation2.php 268999 2008-11-14 16:18:50Z quipo $
* @link http://pear.php.net/package/Translation2
*/
/**
* require PEAR base class
*/
require_once 'PEAR.php';
/**
* Allows redefinition of the default pageID.
* This constant is needed to allow both NULL and EMPTY pageID values
* and to have them match
*/
if (!defined('TRANSLATION2_DEFAULT_PAGEID')) {
define('TRANSLATION2_DEFAULT_PAGEID', 'translation2_default_pageID');
}
/**
* Class Error codes
*/
define('TRANSLATION2_ERROR', -1);
define('TRANSLATION2_ERROR_METHOD_NOT_SUPPORTED', -2);
define('TRANSLATION2_ERROR_CANNOT_CONNECT', -3);
define('TRANSLATION2_ERROR_CANNOT_FIND_FILE', -4);
define('TRANSLATION2_ERROR_DOMAIN_NOT_SET', -5);
define('TRANSLATION2_ERROR_INVALID_PATH', -6);
define('TRANSLATION2_ERROR_CANNOT_CREATE_DIR', -7);
define('TRANSLATION2_ERROR_CANNOT_WRITE_FILE', -8);
define('TRANSLATION2_ERROR_UNKNOWN_LANG', -9);
define('TRANSLATION2_ERROR_ENCODING_CONVERSION', -10);
define('TRANSLATION2_ERROR_UNSUPPORTED', -11);
/**
* Translation2 base class
*
* This class provides an easy way to retrieve all the strings
* for a multilingual site or application from a data source
* (i.e. a db, an xml file or a gettext file).
*
* @category Internationalization
* @package Translation2
* @author Lorenzo Alberton <l.alberton@quipo.it>
* @copyright 2004-2008 Lorenzo Alberton
* @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
* @link http://pear.php.net/package/Translation2
*/
class Translation2
{
// {{{ class vars
/**
* Storage object
* @var object
* @access protected
*/
var $storage = '';
/**
* Class options
* @var array
*/
var $options = array();
/**
* Default lang
* @var array
* @access protected
*/
var $lang = array();
/**
* Current pageID
* @var string
* @access protected
*/
var $currentPageID = null;
/**
* Array of parameters for the adapter class
* @var array
* @access protected
*/
var $params = array();
// }}}
// {{{ Constructor
/**
* Constructor
*/
function Translation2()
{
if (func_num_args()) {
$msg = '<b>Translation2 error:</b>'
.' Don\'t use the constructor - use factory()';
trigger_error($msg, E_USER_ERROR);
}
}
// }}}
// {{{ factory()
/**
* Return a Translation2 instance already initialized
*
* @param string $driver Type of the storage driver
* @param mixed $options Additional options for the storage driver
* (example: if you are using DB as the storage
* driver, you have to pass the dsn string here)
* @param array $params Array of parameters for the adapter class
* (i.e. you can set here the mappings between your
* table/field names and the ones used by this class)
*
* @return object Translation2 instance or PEAR_Error on failure
* @static
*/
function & factory($driver, $options = '', $params = array())
{
$tr = new Translation2;
$tr->storage = Translation2::_storageFactory($driver, $options);
if (PEAR::isError($tr->storage)) {
return $tr->storage;
}
$tr->_setDefaultOptions();
$tr->_parseOptions($params);
$tr->storage->_parseOptions($params);
return $tr;
}
// }}}
// {{{ _storageFactory()
/**
* Return a storage driver based on $driver and $options
*
* @param string $driver Type of storage class to return
* @param string $options Optional parameters for the storage class
*
* @return object Object Storage object
* @static
* @access private
*/
function & _storageFactory($driver, $options = '')
{
$storage_path = 'Translation2/Container/'.strtolower($driver).'.php';
$storage_class = 'Translation2_Container_'.strtolower($driver);
include_once $storage_path;
$storage = new $storage_class;
$err = $storage->init($options);
if (PEAR::isError($err)) {
return $err;
}
return $storage;
}
// }}}
// {{{ setContainerOptions()
/**
* Set some storage driver options
*
* @param array $options array of options
*
* @return void
* @access protected
*/
function setContainerOptions($options)
{
$this->storage->_parseOptions($options);
}
// }}}
// {{{ _setDefaultOptions()
/**
* Set some default options
*
* @return void
* @access private
*/
function _setDefaultOptions()
{
$this->options['ParameterPrefix'] = '&&';
$this->options['ParameterPostfix'] = '&&';
$this->options['ParameterAutoFree'] = true;
$this->options['prefetch'] = true;
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the base class
*
* @param array $array options
*
* @return void
* @access private
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
// {{{ getDecorator()
/**
* Return an instance of a decorator
*
* This method is used to get a decorator instance.
* A decorator can be seen as a filter, i.e. something that can change
* or handle the values of the objects/vars that pass through.
*
* @param string $decorator Name of the decorator
*
* @return object Decorator object reference
*/
function & getDecorator($decorator)
{
$decorator_path = 'Translation2/Decorator/'.$decorator.'.php';
$decorator_class = 'Translation2_Decorator_'.$decorator;
include_once $decorator_path;
if (func_num_args() > 1) {
$obj = func_get_arg(1);
$new_decorator = new $decorator_class($obj);
} else {
$new_decorator = new $decorator_class($this);
}
return $new_decorator;
}
// }}}
// {{{ setCharset()
/**
* Set charset used to read/store the translations
*
* @param string $charset character set (encoding)
*
* @return void|PEAR_Error
*/
function setCharset($charset)
{
$res = $this->storage->setCharset($charset);
if (PEAR::isError($res)) {
return $res;
}
}
// }}}
// {{{ setLang()
/**
* Set default lang
*
* Set the language that shall be used when retrieving strings.
*
* @param string $langID language code (for instance, 'en' or 'it')
*
* @return true|PEAR_Error
*/
function setLang($langID)
{
$res = $this->storage->setLang($langID);
if (PEAR::isError($res)) {
return $res;
}
$this->lang = $res;
return true;
}
// }}}
// {{{ setPageID($pageID)
/**
* Set default page
*
* Set the page (aka "group of strings") that shall be used when retrieving strings.
* If you set it, you don't have to state it in each get() call.
*
* @param string $pageID ID of the default page
*
* @return self
*/
function setPageID($pageID = null)
{
$this->currentPageID = $pageID;
return $this;
}
// }}}
// {{{ getLang()
/**
* get lang info
*
* Get some extra information about the language (its full name,
* the localized error text, ...)
*
* @param string $langID language ID
* @param string $format ['name', 'meta', 'error_text', 'array']
*
* @return mixed [string | array], depending on $format
*/
function getLang($langID = null, $format = 'name')
{
if (is_null($langID)) {
if (!isset($this->lang['id'])) {
$msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
.' Use Translation2::setLang() to set a default language.';
return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
}
$langID = $this->lang['id'];
}
$lang = $this->storage->getLangData($langID);
if ($format == 'array') {
return $lang;
} elseif (isset($lang[$format])) {
return $lang[$format];
} elseif (isset($lang['name'])) {
return $lang['name'];
}
$msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
.' Use Translation2::setLang() to set a default language.';
return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
}
// }}}
// {{{ getLangs()
/**
* get langs
*
* Get some extra information about the languages (their full names,
* the localized error text, their codes, ...)
*
* @param string $format ['ids', 'names', 'array']
*
* @return array|PEAR_Error
*/
function getLangs($format = 'name')
{
return $this->storage->getLangs($format);
}
// }}}
// {{{ setParams()
/**
* Set parameters for next string
*
* Set the replacement for the parameters in the string(s).
* Parameter delimiters are customizable.
*
* @param array $params array of replacement parameters
*
* @return self
*/
function setParams($params = null)
{
if (empty($params)) {
$this->params = array();
} elseif (is_array($params)) {
$this->params = $params;
} else {
$this->params = array($params);
}
return $this;
}
// }}}
// {{{ _replaceParams()
/**
* Replace parameters in strings
*
* @param mixed $strings strings where the replacements must occur
*
* @return mixed
* @access protected
*/
function _replaceParams($strings)
{
if (empty($strings) || is_object($strings) || !count($this->params)) {
return $strings;
}
if (is_array($strings)) {
foreach ($strings as $key => $string) {
$strings[$key] = $this->_replaceParams($string);
}
} else {
if (strpos($strings, $this->options['ParameterPrefix']) !== false) {
foreach ($this->params as $name => $value) {
$strings = str_replace($this->options['ParameterPrefix']
. $name . $this->options['ParameterPostfix'],
$value,
$strings);
}
if ($this->options['ParameterAutoFree']) {
$this->params = array();
}
}
}
return $strings;
}
// }}}
// {{{ replaceEmptyStringsWithKeys()
/**
* Replace empty strings with their stringID
*
* @param array $strings array of strings to be replaced if empty
*
* @return array
* @static
*/
function replaceEmptyStringsWithKeys($strings)
{
if (!is_array($strings)) {
return $strings;
}
foreach ($strings as $key => $string) {
if (empty($string)) {
$strings[$key] = $key;
}
}
return $strings;
}
// }}}
// {{{ getRaw()
/**
* Get translated string (as-is)
*
* @param string $stringID ID of the string to be translated
* @param string $pageID ID of the page/group containing the string
* @param string $langID ID of the language
* @param string $defaultText Text to display when the string is empty
*
* @return string|PEAR_Error
*/
function getRaw($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
{
$pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
$str = $this->storage->getOne($stringID, $pageID, $langID);
if (empty($str)) {
$str = $defaultText;
}
return $str;
}
// }}}
// {{{ get()
/**
* Get translated string
*
* First check if the string is cached, if not => fetch the page
* from the container and cache it for later use.
* If the string is empty, check the fallback language; if
* the latter is empty too, then return the $defaultText.
*
* @param string $stringID ID of the string
* @param string $pageID ID of the page/group containing the string
* @param string $langID ID of the language
* @param string $defaultText Text to display when the string is empty
* NB: This parameter is only used in the DefaultText decorator
*
* @return string
*/
function get($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
{
$str = $this->getRaw($stringID, $pageID, $langID);
if (PEAR::isError($str)) {
return $str;
}
return $this->_replaceParams($str);
}
// }}}
// {{{ getRawPage()
/**
* Get the array of strings in a page
*
* Fetch the page (aka "group of strings) from the container,
* without applying any formatting and without replacing the parameters
*
* @param string $pageID ID of the page/group containing the string
* @param string $langID ID of the language
*
* @return array
*/
function getRawPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
{
$pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
return $this->storage->getPage($pageID, $langID);
}
// }}}
// {{{ getPage()
/**
* Get an entire group of strings
*
* Same as getRawPage, but resort to fallback language and
* replace parameters when needed
*
* @param string $pageID ID of the page/group containing the string
* @param string $langID ID of the language
*
* @return array
*/
function getPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
{
$pageData = $this->getRawPage($pageID, $langID);
return $this->_replaceParams($pageData);
}
// }}}
// {{{ getStringID()
/**
* Get the stringID for the given string. This method is the reverse of get().
*
* @param string $string This is NOT the stringID, this is a real string.
* The method will search for its matching stringID, and then
* it will return the associate string in the selected language.
* @param string $pageID ID of the page/group containing the string
*
* @return string
*/
function getStringID($string, $pageID = TRANSLATION2_DEFAULT_PAGEID)
{
$pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
return $this->storage->getStringID($string, $pageID);
}
// }}}
// {{{ __clone()
/**
* Clone internal object references
*
* This method is called automatically by PHP5
*
* @return void
* @access protected
*/
function __clone()
{
$this->storage = clone($this->storage);
}
// }}}
}
?>
Copyright 2K16 - 2K18 Indonesian Hacker Rulez