home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Translation2.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  17.6 KB  |  595 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5.  * Contains the Translation2 base class
  6.  *
  7.  * PHP versions 4 and 5
  8.  *
  9.  * LICENSE: Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. The name of the author may not be used to endorse or promote products
  17.  *    derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
  20.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
  23.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * @category  Internationalization
  31.  * @package   Translation2
  32.  * @author    Lorenzo Alberton <l.alberton@quipo.it>
  33.  * @copyright 2004-2008 Lorenzo Alberton
  34.  * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
  35.  * @version   CVS: $Id: Translation2.php,v 1.40 2008/02/02 18:02:26 quipo Exp $
  36.  * @link      http://pear.php.net/package/Translation2
  37.  */
  38.  
  39. /**
  40.  * require PEAR base class
  41.  */
  42. require_once 'PEAR.php';
  43.  
  44. /**
  45.  * Allows redefinition of the default pageID.
  46.  * This constant is needed to allow both NULL and EMPTY pageID values
  47.  * and to have them match
  48.  */
  49. if (!defined('TRANSLATION2_DEFAULT_PAGEID')) {
  50.     define('TRANSLATION2_DEFAULT_PAGEID', 'translation2_default_pageID');
  51. }
  52. /**
  53.  * Class Error codes
  54.  */
  55. define('TRANSLATION2_ERROR',                      -1);
  56. define('TRANSLATION2_ERROR_METHOD_NOT_SUPPORTED', -2);
  57. define('TRANSLATION2_ERROR_CANNOT_CONNECT',       -3);
  58. define('TRANSLATION2_ERROR_CANNOT_FIND_FILE',     -4);
  59. define('TRANSLATION2_ERROR_DOMAIN_NOT_SET',       -5);
  60. define('TRANSLATION2_ERROR_INVALID_PATH',         -6);
  61. define('TRANSLATION2_ERROR_CANNOT_CREATE_DIR',    -7);
  62. define('TRANSLATION2_ERROR_CANNOT_WRITE_FILE',    -8);
  63. define('TRANSLATION2_ERROR_UNKNOWN_LANG',         -9);
  64. define('TRANSLATION2_ERROR_ENCODING_CONVERSION', -10);
  65. define('TRANSLATION2_ERROR_UNSUPPORTED',         -11);
  66.  
  67. /**
  68.  * Translation2 base class
  69.  *
  70.  * This class provides an easy way to retrieve all the strings
  71.  * for a multilingual site or application from a data source
  72.  * (i.e. a db, an xml file or a gettext file).
  73.  *
  74.  * @category  Internationalization
  75.  * @package   Translation2
  76.  * @author    Lorenzo Alberton <l.alberton@quipo.it>
  77.  * @copyright 2004-2008 Lorenzo Alberton
  78.  * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
  79.  * @link      http://pear.php.net/package/Translation2
  80.  */
  81. class Translation2
  82. {
  83.     // {{{ class vars
  84.  
  85.     /**
  86.      * Storage object
  87.      * @var object
  88.      * @access protected
  89.      */
  90.     var $storage = '';
  91.  
  92.     /**
  93.      * Class options
  94.      * @var array
  95.      */
  96.     var $options = array();
  97.  
  98.     /**
  99.      * Default lang
  100.      * @var array
  101.      * @access protected
  102.      */
  103.     var $lang = array();
  104.  
  105.     /**
  106.      * Current pageID
  107.      * @var string
  108.      * @access protected
  109.      */
  110.     var $currentPageID = null;
  111.  
  112.     /**
  113.      * Array of parameters for the adapter class
  114.      * @var array
  115.      * @access protected
  116.      */
  117.     var $params = array();
  118.  
  119.     // }}}
  120.     // {{{ Constructor
  121.  
  122.     /**
  123.      * Constructor
  124.      */
  125.     function Translation2()
  126.     {
  127.         if (func_num_args()) {
  128.             $msg = '<b>Translation2 error:</b>'
  129.                   .' Don\'t use the constructor - use factory()';
  130.             trigger_error($msg, E_USER_ERROR);
  131.         }
  132.     }
  133.  
  134.     // }}}
  135.     // {{{ factory()
  136.  
  137.     /**
  138.      * Return a Translation2 instance already initialized
  139.      *
  140.      * @param string $driver  Type of the storage driver
  141.      * @param mixed  $options Additional options for the storage driver
  142.      *                        (example: if you are using DB as the storage
  143.      *                        driver, you have to pass the dsn string here)
  144.      * @param array  $params  Array of parameters for the adapter class
  145.      *                        (i.e. you can set here the mappings between your
  146.      *                        table/field names and the ones used by this class)
  147.      *
  148.      * @return object Translation2 instance or PEAR_Error on failure
  149.      * @static
  150.      */
  151.     function & factory($driver, $options = '', $params = array())
  152.     {
  153.         $tr = new Translation2;
  154.         $tr->storage = Translation2::_storageFactory($driver, $options);
  155.         if (PEAR::isError($tr->storage)) {
  156.             return $tr->storage;
  157.         }
  158.         $tr->_setDefaultOptions();
  159.         $tr->_parseOptions($params);
  160.         $tr->storage->_parseOptions($params);
  161.         return $tr;
  162.     }
  163.  
  164.     // }}}
  165.     // {{{ _storageFactory()
  166.  
  167.     /**
  168.      * Return a storage driver based on $driver and $options
  169.      *
  170.      * @param string $driver  Type of storage class to return
  171.      * @param string $options Optional parameters for the storage class
  172.      *
  173.      * @return object Object   Storage object
  174.      * @static
  175.      * @access private
  176.      */
  177.     function & _storageFactory($driver, $options = '')
  178.     {
  179.         $storage_path  = 'Translation2/Container/'.strtolower($driver).'.php';
  180.         $storage_class = 'Translation2_Container_'.strtolower($driver);
  181.         include_once $storage_path;
  182.         $storage = new $storage_class;
  183.         $err = $storage->init($options);
  184.         if (PEAR::isError($err)) {
  185.             return $err;
  186.         }
  187.         return $storage;
  188.     }
  189.  
  190.     // }}}
  191.     // {{{ setContainerOptions()
  192.  
  193.     /**
  194.      * Set some storage driver options
  195.      *
  196.      * @param array $options array of options
  197.      *
  198.      * @return void
  199.      * @access protected
  200.      */
  201.     function setContainerOptions($options)
  202.     {
  203.         $this->storage->_parseOptions($options);
  204.     }
  205.  
  206.     // }}}
  207.     // {{{ _setDefaultOptions()
  208.  
  209.     /**
  210.      * Set some default options
  211.      *
  212.      * @return void
  213.      * @access private
  214.      */
  215.     function _setDefaultOptions()
  216.     {
  217.         $this->options['ParameterPrefix']   = '&&';
  218.         $this->options['ParameterPostfix']  = '&&';
  219.         $this->options['ParameterAutoFree'] = true;
  220.         $this->options['prefetch']          = true;
  221.     }
  222.  
  223.     // }}}
  224.     // {{{ _parseOptions()
  225.  
  226.     /**
  227.      * Parse options passed to the base class
  228.      *
  229.      * @param array $array options
  230.      *
  231.      * @return void
  232.      * @access private
  233.      */
  234.     function _parseOptions($array)
  235.     {
  236.         foreach ($array as $key => $value) {
  237.             if (isset($this->options[$key])) {
  238.                 $this->options[$key] = $value;
  239.             }
  240.         }
  241.     }
  242.  
  243.     // }}}
  244.     // {{{ getDecorator()
  245.  
  246.     /**
  247.      * Return an instance of a decorator
  248.      *
  249.      * This method is used to get a decorator instance.
  250.      * A decorator can be seen as a filter, i.e. something that can change
  251.      * or handle the values of the objects/vars that pass through.
  252.      *
  253.      * @param string $decorator Name of the decorator
  254.      *
  255.      * @return object Decorator object reference
  256.      */
  257.     function & getDecorator($decorator)
  258.     {
  259.         $decorator_path  = 'Translation2/Decorator/'.$decorator.'.php';
  260.         $decorator_class = 'Translation2_Decorator_'.$decorator;
  261.         include_once $decorator_path;
  262.         if (func_num_args() > 1) {
  263.             $obj = func_get_arg(1);
  264.             $new_decorator = new $decorator_class($obj);
  265.         } else {
  266.             $new_decorator = new $decorator_class($this);
  267.         }
  268.         return $new_decorator;
  269.     }
  270.  
  271.     // }}}
  272.     // {{{ setCharset()
  273.  
  274.     /**
  275.      * Set charset used to read/store the translations
  276.      *
  277.      * @param string $charset character set (encoding)
  278.      *
  279.      * @return void|PEAR_Error
  280.      */
  281.     function setCharset($charset)
  282.     {
  283.         $res = $this->storage->setCharset($charset);
  284.         if (PEAR::isError($res)) {
  285.             return $res;
  286.         }
  287.     }
  288.  
  289.     // }}}
  290.     // {{{ setLang()
  291.  
  292.     /**
  293.      * Set default lang
  294.      *
  295.      * Set the language that shall be used when retrieving strings.
  296.      *
  297.      * @param string $langID language code (for instance, 'en' or 'it')
  298.      *
  299.      * @return void|PEAR_Error
  300.      */
  301.     function setLang($langID)
  302.     {
  303.         $res = $this->storage->setLang($langID);
  304.         if (PEAR::isError($res)) {
  305.             return $res;
  306.         }
  307.         $this->lang = $res;
  308.     }
  309.  
  310.     // }}}
  311.     // {{{ setPageID($pageID)
  312.  
  313.     /**
  314.      * Set default page
  315.      *
  316.      * Set the page (aka "group of strings") that shall be used when retrieving strings.
  317.      * If you set it, you don't have to state it in each get() call.
  318.      *
  319.      * @param string $pageID ID of the default page
  320.      *
  321.      * @return void
  322.      */
  323.     function setPageID($pageID = null)
  324.     {
  325.         $this->currentPageID = $pageID;
  326.     }
  327.  
  328.     // }}}
  329.     // {{{ getLang()
  330.  
  331.     /**
  332.      * get lang info
  333.      *
  334.      * Get some extra information about the language (its full name,
  335.      * the localized error text, ...)
  336.      *
  337.      * @param string $langID language ID
  338.      * @param string $format ['name', 'meta', 'error_text', 'array']
  339.      *
  340.      * @return mixed [string | array], depending on $format
  341.      */
  342.     function getLang($langID = null, $format = 'name')
  343.     {
  344.         if (is_null($langID)) {
  345.             if (!isset($this->lang['id'])) {
  346.                 $msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
  347.                       .' Use Translation2::setLang() to set a default language.';
  348.                 return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
  349.             }
  350.             $langID = $this->lang['id'];
  351.         }
  352.         $lang = $this->storage->getLangData($langID);
  353.         if ($format == 'array') {
  354.             return $lang;
  355.         } elseif (isset($lang[$format])) {
  356.             return $lang[$format];
  357.         } elseif (isset($lang['name'])) {
  358.             return $lang['name'];
  359.         }
  360.         $msg = 'Translation2::getLang(): unknown language "'.$langID.'".'
  361.               .' Use Translation2::setLang() to set a default language.';
  362.         return $this->storage->raiseError($msg, TRANSLATION2_ERROR_UNKNOWN_LANG);
  363.     }
  364.  
  365.     // }}}
  366.     // {{{ getLangs()
  367.  
  368.     /**
  369.      * get langs
  370.      *
  371.      * Get some extra information about the languages (their full names,
  372.      * the localized error text, their codes, ...)
  373.      *
  374.      * @param string $format ['ids', 'names', 'array']
  375.      *
  376.      * @return array
  377.      */
  378.     function getLangs($format = 'name')
  379.     {
  380.         return $this->storage->getLangs($format);
  381.     }
  382.  
  383.     // }}}
  384.     // {{{ setParams()
  385.  
  386.     /**
  387.      * Set parameters for next string
  388.      *
  389.      * Set the replacement for the parameters in the string(s).
  390.      * Parameter delimiters are customizable.
  391.      *
  392.      * @param array $params array of replacement parameters
  393.      *
  394.      * @return void
  395.      */
  396.     function setParams($params = null)
  397.     {
  398.         if (empty($params)) {
  399.             $this->params = array();
  400.         } elseif (is_array($params)) {
  401.             $this->params = $params;
  402.         } else {
  403.             $this->params = array($params);
  404.         }
  405.     }
  406.  
  407.     // }}}
  408.     // {{{ _replaceParams()
  409.  
  410.     /**
  411.      * Replace parameters in strings
  412.      *
  413.      * @param mixed $strings strings where the replacements must occur
  414.      *
  415.      * @return mixed
  416.      * @access protected
  417.      */
  418.     function _replaceParams($strings)
  419.     {
  420.         if (empty($strings) || is_object($strings) || !count($this->params)) {
  421.             return $strings;
  422.         }
  423.         if (is_array($strings)) {
  424.             foreach ($strings as $key => $string) {
  425.                 $strings[$key] = $this->_replaceParams($string);
  426.             }
  427.         } else {
  428.             if (strpos($strings, $this->options['ParameterPrefix']) !== false) {
  429.                 foreach ($this->params as $name => $value) {
  430.                     $strings = str_replace($this->options['ParameterPrefix']
  431.                                            . $name . $this->options['ParameterPostfix'],
  432.                                            $value,
  433.                                            $strings);
  434.                 }
  435.                 if ($this->options['ParameterAutoFree']) {
  436.                     $this->params = array();
  437.                 }
  438.             }
  439.         }
  440.         return $strings;
  441.     }
  442.  
  443.     // }}}
  444.     // {{{ replaceEmptyStringsWithKeys()
  445.  
  446.     /**
  447.      * Replace empty strings with their stringID
  448.      *
  449.      * @param array $strings array of strings to be replaced if empty
  450.      *
  451.      * @return array
  452.      * @static
  453.      */
  454.     function replaceEmptyStringsWithKeys($strings)
  455.     {
  456.         if (!is_array($strings)) {
  457.             return $strings;
  458.         }
  459.         foreach ($strings as $key => $string) {
  460.             if (empty($string)) {
  461.                 $strings[$key] = $key;
  462.             }
  463.         }
  464.         return $strings;
  465.     }
  466.  
  467.     // }}}
  468.     // {{{ getRaw()
  469.  
  470.     /**
  471.      * Get translated string (as-is)
  472.      *
  473.      * @param string $stringID    ID of the string to be translated
  474.      * @param string $pageID      ID of the page/group containing the string
  475.      * @param string $langID      ID of the language
  476.      * @param string $defaultText Text to display when the string is empty
  477.      *
  478.      * @return string|PEAR_Error
  479.      */
  480.     function getRaw($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
  481.     {
  482.         $pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
  483.         $str = $this->storage->getOne($stringID, $pageID, $langID);
  484.         if (empty($str)) {
  485.             $str = $defaultText;
  486.         }
  487.         return $str;
  488.     }
  489.  
  490.     // }}}
  491.     // {{{ get()
  492.  
  493.     /**
  494.      * Get translated string
  495.      *
  496.      * First check if the string is cached, if not => fetch the page
  497.      * from the container and cache it for later use.
  498.      * If the string is empty, check the fallback language; if
  499.      * the latter is empty too, then return the $defaultText.
  500.      *
  501.      * @param string $stringID    ID of the string
  502.      * @param string $pageID      ID of the page/group containing the string
  503.      * @param string $langID      ID of the language
  504.      * @param string $defaultText Text to display when the string is empty
  505.      *               NB: This parameter is only used in the DefaultText decorator
  506.      *
  507.      * @return string
  508.      */
  509.     function get($stringID, $pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null, $defaultText = '')
  510.     {
  511.         $str = $this->getRaw($stringID, $pageID, $langID);
  512.         if (PEAR::isError($str)) {
  513.             return $str;
  514.         }
  515.         return $this->_replaceParams($str);
  516.     }
  517.  
  518.     // }}}
  519.     // {{{ getRawPage()
  520.  
  521.     /**
  522.      * Get the array of strings in a page
  523.      *
  524.      * Fetch the page (aka "group of strings) from the container,
  525.      * without applying any formatting and without replacing the parameters
  526.      *
  527.      * @param string $pageID ID of the page/group containing the string
  528.      * @param string $langID ID of the language
  529.      *
  530.      * @return array
  531.      */
  532.     function getRawPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
  533.     {
  534.         $pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
  535.         return $this->storage->getPage($pageID, $langID);
  536.     }
  537.  
  538.     // }}}
  539.     // {{{ getPage()
  540.  
  541.     /**
  542.      * Get an entire group of strings
  543.      *
  544.      * Same as getRawPage, but resort to fallback language and
  545.      * replace parameters when needed
  546.      *
  547.      * @param string $pageID ID of the page/group containing the string
  548.      * @param string $langID ID of the language
  549.      *
  550.      * @return array
  551.      */
  552.     function getPage($pageID = TRANSLATION2_DEFAULT_PAGEID, $langID = null)
  553.     {
  554.         $pageData = $this->getRawPage($pageID, $langID);
  555.         return $this->_replaceParams($pageData);
  556.     }
  557.  
  558.     // }}}
  559.     // {{{ getStringID()
  560.  
  561.     /**
  562.      * Get the stringID for the given string. This method is the reverse of get().
  563.      *
  564.      * @param string $string This is NOT the stringID, this is a real string.
  565.      *               The method will search for its matching stringID, and then
  566.      *               it will return the associate string in the selected language.
  567.      * @param string $pageID ID of the page/group containing the string
  568.      *
  569.      * @return string
  570.      */
  571.     function getStringID($string, $pageID = TRANSLATION2_DEFAULT_PAGEID)
  572.     {
  573.         $pageID = ($pageID == TRANSLATION2_DEFAULT_PAGEID ? $this->currentPageID : $pageID);
  574.         return $this->storage->getStringID($string, $pageID);
  575.     }
  576.  
  577.     // }}}
  578.     // {{{ __clone()
  579.  
  580.     /**
  581.      * Clone internal object references
  582.      *
  583.      * This method is called automatically by PHP5
  584.      *
  585.      * @return void
  586.      * @access protected
  587.      */
  588.     function __clone()
  589.     {
  590.         $this->storage = clone($this->storage);
  591.     }
  592.  
  593.     // }}}
  594. }
  595. ?>