File indexing completed on 2024-06-16 05:30:32

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Translate
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @version    $Id$
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  */
0021 
0022 /** Zend_Locale */
0023 // require_once 'Zend/Locale.php';
0024 
0025 /** Zend_Translate_Adapter */
0026 // require_once 'Zend/Translate/Adapter.php';
0027 
0028 /**
0029  * @category   Zend
0030  * @package    Zend_Translate
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_Translate_Adapter_Gettext extends Zend_Translate_Adapter {
0035     // Internal variables
0036     private $_bigEndian   = false;
0037     private $_file        = false;
0038     private $_adapterInfo = array();
0039     private $_data        = array();
0040 
0041     /**
0042      * Read values from the MO file
0043      *
0044      * @param  string  $bytes
0045      */
0046     private function _readMOData($bytes)
0047     {
0048         if ($this->_bigEndian === false) {
0049             return unpack('V' . $bytes, fread($this->_file, 4 * $bytes));
0050         } else {
0051             return unpack('N' . $bytes, fread($this->_file, 4 * $bytes));
0052         }
0053     }
0054 
0055     /**
0056      * Load translation data (MO file reader)
0057      *
0058      * @param  string  $filename  MO file to add, full path must be given for access
0059      * @param  string  $locale    New Locale/Language to set, identical with locale identifier,
0060      *                            see Zend_Locale for more information
0061      * @param  array   $option    OPTIONAL Options to use
0062      * @throws Zend_Translation_Exception
0063      * @return array
0064      */
0065     protected function _loadTranslationData($filename, $locale, array $options = array())
0066     {
0067         $this->_data      = array();
0068         $this->_bigEndian = false;
0069         $this->_file      = @fopen($filename, 'rb');
0070         if (!$this->_file) {
0071             // require_once 'Zend/Translate/Exception.php';
0072             throw new Zend_Translate_Exception('Error opening translation file \'' . $filename . '\'.');
0073         }
0074         if (@filesize($filename) < 10) {
0075             @fclose($this->_file);
0076             // require_once 'Zend/Translate/Exception.php';
0077             throw new Zend_Translate_Exception('\'' . $filename . '\' is not a gettext file');
0078         }
0079 
0080         // get Endian
0081         $input = $this->_readMOData(1);
0082         if (strtolower(substr(dechex($input[1]), -8)) == "950412de") {
0083             $this->_bigEndian = false;
0084         } else if (strtolower(substr(dechex($input[1]), -8)) == "de120495") {
0085             $this->_bigEndian = true;
0086         } else {
0087             @fclose($this->_file);
0088             // require_once 'Zend/Translate/Exception.php';
0089             throw new Zend_Translate_Exception('\'' . $filename . '\' is not a gettext file');
0090         }
0091         // read revision - not supported for now
0092         $input = $this->_readMOData(1);
0093 
0094         // number of bytes
0095         $input = $this->_readMOData(1);
0096         $total = $input[1];
0097 
0098         // number of original strings
0099         $input = $this->_readMOData(1);
0100         $OOffset = $input[1];
0101 
0102         // number of translation strings
0103         $input = $this->_readMOData(1);
0104         $TOffset = $input[1];
0105 
0106         // fill the original table
0107         fseek($this->_file, $OOffset);
0108         $origtemp = $this->_readMOData(2 * $total);
0109         fseek($this->_file, $TOffset);
0110         $transtemp = $this->_readMOData(2 * $total);
0111 
0112         for($count = 0; $count < $total; ++$count) {
0113             if ($origtemp[$count * 2 + 1] != 0) {
0114                 fseek($this->_file, $origtemp[$count * 2 + 2]);
0115                 $original = @fread($this->_file, $origtemp[$count * 2 + 1]);
0116                 $original = explode("\0", $original);
0117             } else {
0118                 $original[0] = '';
0119             }
0120 
0121             if ($transtemp[$count * 2 + 1] != 0) {
0122                 fseek($this->_file, $transtemp[$count * 2 + 2]);
0123                 $translate = fread($this->_file, $transtemp[$count * 2 + 1]);
0124                 $translate = explode("\0", $translate);
0125                 if ((count($original) > 1)) {
0126                     $this->_data[$locale][$original[0]] = $translate;
0127                     array_shift($original);
0128                     foreach ($original as $orig) {
0129                         $this->_data[$locale][$orig] = '';
0130                     }
0131                 } else {
0132                     $this->_data[$locale][$original[0]] = $translate[0];
0133                 }
0134             }
0135         }
0136         
0137         @fclose($this->_file);
0138 
0139         $this->_data[$locale][''] = trim($this->_data[$locale]['']);
0140         if (empty($this->_data[$locale][''])) {
0141             $this->_adapterInfo[$filename] = 'No adapter information available';
0142         } else {
0143             $this->_adapterInfo[$filename] = $this->_data[$locale][''];
0144         }
0145 
0146         unset($this->_data[$locale]['']);
0147         return $this->_data;
0148     }
0149 
0150     /**
0151      * Returns the adapter informations
0152      *
0153      * @return array Each loaded adapter information as array value
0154      */
0155     public function getAdapterInfo()
0156     {
0157         return $this->_adapterInfo;
0158     }
0159 
0160     /**
0161      * Returns the adapter name
0162      *
0163      * @return string
0164      */
0165     public function toString()
0166     {
0167         return "Gettext";
0168     }
0169 }