Commit e6d5f5a163d3904c67590c0bef79d74882b28e4f

Authored by nbm
1 parent 10a178fb

Add File_Gettext 0.4.0 (BSD-licenced)


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5135 c91229c3-7414-0410-bfa2-8a42b809f60b
thirdparty/pear/File/Gettext.php 0 → 100644
  1 +<?php
  2 +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3 +
  4 +/**
  5 + * File::Gettext
  6 + *
  7 + * PHP versions 4 and 5
  8 + *
  9 + * @category FileFormats
  10 + * @package File_Gettext
  11 + * @author Michael Wallner <mike@php.net>
  12 + * @copyright 2004-2005 Michael Wallner
  13 + * @license BSD, revised
  14 + * @version CVS: $Id$
  15 + * @link http://pear.php.net/package/File_Gettext
  16 + */
  17 +
  18 +/**
  19 + * Use PHPs builtin error messages
  20 + */
  21 +ini_set('track_errors', true);
  22 +
  23 +/**
  24 + * File_Gettext
  25 + *
  26 + * GNU gettext file reader and writer.
  27 + *
  28 + * #################################################################
  29 + * # All protected members of this class are public in its childs. #
  30 + * #################################################################
  31 + *
  32 + * @author Michael Wallner <mike@php.net>
  33 + * @version $Revision$
  34 + * @access public
  35 + */
  36 +class File_Gettext
  37 +{
  38 + /**
  39 + * strings
  40 + *
  41 + * associative array with all [msgid => msgstr] entries
  42 + *
  43 + * @access protected
  44 + * @var array
  45 + */
  46 + var $strings = array();
  47 +
  48 + /**
  49 + * meta
  50 + *
  51 + * associative array containing meta
  52 + * information like project name or content type
  53 + *
  54 + * @access protected
  55 + * @var array
  56 + */
  57 + var $meta = array();
  58 +
  59 + /**
  60 + * file path
  61 + *
  62 + * @access protected
  63 + * @var string
  64 + */
  65 + var $file = '';
  66 +
  67 + /**
  68 + * Factory
  69 + *
  70 + * @static
  71 + * @access public
  72 + * @return object Returns File_Gettext_PO or File_Gettext_MO on success
  73 + * or PEAR_Error on failure.
  74 + * @param string $format MO or PO
  75 + * @param string $file path to GNU gettext file
  76 + */
  77 + function &factory($format, $file = '')
  78 + {
  79 + $format = strToUpper($format);
  80 + if (!@include_once 'File/Gettext/' . $format . '.php') {
  81 + return File_Gettext::raiseError($php_errormsg);
  82 + }
  83 + $class = 'File_Gettext_' . $format;
  84 + $obref = &new $class($file);
  85 + return $obref;
  86 + }
  87 +
  88 + /**
  89 + * poFile2moFile
  90 + *
  91 + * That's a simple fake of the 'msgfmt' console command. It reads the
  92 + * contents of a GNU PO file and saves them to a GNU MO file.
  93 + *
  94 + * @static
  95 + * @access public
  96 + * @return mixed Returns true on success or PEAR_Error on failure.
  97 + * @param string $pofile path to GNU PO file
  98 + * @param string $mofile path to GNU MO file
  99 + */
  100 + function poFile2moFile($pofile, $mofile)
  101 + {
  102 + if (!is_file($pofile)) {
  103 + return File_Gettext::raiseError("File $pofile doesn't exist.");
  104 + }
  105 +
  106 + include_once 'File/Gettext/PO.php';
  107 +
  108 + $PO = &new File_Gettext_PO($pofile);
  109 + if (true !== ($e = $PO->load())) {
  110 + return $e;
  111 + }
  112 +
  113 + $MO = &$PO->toMO();
  114 + if (true !== ($e = $MO->save($mofile))) {
  115 + return $e;
  116 + }
  117 + unset($PO, $MO);
  118 +
  119 + return true;
  120 + }
  121 +
  122 + /**
  123 + * prepare
  124 + *
  125 + * @static
  126 + * @access protected
  127 + * @return string
  128 + * @param string $string
  129 + * @param bool $reverse
  130 + */
  131 + function prepare($string, $reverse = false)
  132 + {
  133 + if ($reverse) {
  134 + $smap = array('"', "\n", "\t", "\r");
  135 + $rmap = array('\\"', '\\n"' . "\n" . '"', '\\t', '\\r');
  136 + return (string) str_replace($smap, $rmap, $string);
  137 + } else {
  138 + $smap = array('/"\s+"/', '/\\\\n/', '/\\\\r/', '/\\\\t/', '/\\\\"/');
  139 + $rmap = array('', "\n", "\r", "\t", '"');
  140 + return (string) preg_replace($smap, $rmap, $string);
  141 + }
  142 + }
  143 +
  144 + /**
  145 + * meta2array
  146 + *
  147 + * @static
  148 + * @access public
  149 + * @return array
  150 + * @param string $meta
  151 + */
  152 + function meta2array($meta)
  153 + {
  154 + $array = array();
  155 + foreach (explode("\n", $meta) as $info) {
  156 + if ($info = trim($info)) {
  157 + list($key, $value) = explode(':', $info, 2);
  158 + $array[trim($key)] = trim($value);
  159 + }
  160 + }
  161 + return $array;
  162 + }
  163 +
  164 + /**
  165 + * toArray
  166 + *
  167 + * Returns meta info and strings as an array of a structure like that:
  168 + * <code>
  169 + * array(
  170 + * 'meta' => array(
  171 + * 'Content-Type' => 'text/plain; charset=iso-8859-1',
  172 + * 'Last-Translator' => 'Michael Wallner <mike@iworks.at>',
  173 + * 'PO-Revision-Date' => '2004-07-21 17:03+0200',
  174 + * 'Language-Team' => 'German <mail@example.com>',
  175 + * ),
  176 + * 'strings' => array(
  177 + * 'All rights reserved' => 'Alle Rechte vorbehalten',
  178 + * 'Welcome' => 'Willkommen',
  179 + * // ...
  180 + * )
  181 + * )
  182 + * </code>
  183 + *
  184 + * @see fromArray()
  185 + * @access protected
  186 + * @return array
  187 + */
  188 + function toArray()
  189 + {
  190 + return array('meta' => $this->meta, 'strings' => $this->strings);
  191 + }
  192 +
  193 + /**
  194 + * fromArray
  195 + *
  196 + * Assigns meta info and strings from an array of a structure like that:
  197 + * <code>
  198 + * array(
  199 + * 'meta' => array(
  200 + * 'Content-Type' => 'text/plain; charset=iso-8859-1',
  201 + * 'Last-Translator' => 'Michael Wallner <mike@iworks.at>',
  202 + * 'PO-Revision-Date' => date('Y-m-d H:iO'),
  203 + * 'Language-Team' => 'German <mail@example.com>',
  204 + * ),
  205 + * 'strings' => array(
  206 + * 'All rights reserved' => 'Alle Rechte vorbehalten',
  207 + * 'Welcome' => 'Willkommen',
  208 + * // ...
  209 + * )
  210 + * )
  211 + * </code>
  212 + *
  213 + * @see toArray()
  214 + * @access protected
  215 + * @return bool
  216 + * @param array $array
  217 + */
  218 + function fromArray($array)
  219 + {
  220 + if (!array_key_exists('strings', $array)) {
  221 + if (count($array) != 2) {
  222 + return false;
  223 + } else {
  224 + list($this->meta, $this->strings) = $array;
  225 + }
  226 + } else {
  227 + $this->meta = @$array['meta'];
  228 + $this->strings = @$array['strings'];
  229 + }
  230 + return true;
  231 + }
  232 +
  233 + /**
  234 + * toMO
  235 + *
  236 + * @access protected
  237 + * @return object File_Gettext_MO
  238 + */
  239 + function &toMO()
  240 + {
  241 + include_once 'File/Gettext/MO.php';
  242 + $MO = &new File_Gettext_MO;
  243 + $MO->fromArray($this->toArray());
  244 + return $MO;
  245 + }
  246 +
  247 + /**
  248 + * toPO
  249 + *
  250 + * @access protected
  251 + * @return object File_Gettext_PO
  252 + */
  253 + function &toPO()
  254 + {
  255 + include_once 'File/Gettext/PO.php';
  256 + $PO = &new File_Gettext_PO;
  257 + $PO->fromArray($this->toArray());
  258 + return $PO;
  259 + }
  260 +
  261 + /**
  262 + * Raise PEAR error
  263 + *
  264 + * @static
  265 + * @access protected
  266 + * @return object
  267 + * @param string $error
  268 + * @param int $code
  269 + */
  270 + function raiseError($error = null, $code = null)
  271 + {
  272 + include_once 'PEAR.php';
  273 + return PEAR::raiseError($error, $code);
  274 + }
  275 +}
  276 +?>
... ...
thirdparty/pear/File/Gettext/MO.php 0 → 100644
  1 +<?php
  2 +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3 +
  4 +/**
  5 + * File::Gettext
  6 + *
  7 + * PHP versions 4 and 5
  8 + *
  9 + * @category FileFormats
  10 + * @package File_Gettext
  11 + * @author Michael Wallner <mike@php.net>
  12 + * @copyright 2004-2005 Michael Wallner
  13 + * @license BSD, revised
  14 + * @version CVS: $Id$
  15 + * @link http://pear.php.net/package/File_Gettext
  16 + */
  17 +
  18 +/**
  19 + * Requires File_Gettext
  20 + */
  21 +require_once 'File/Gettext.php';
  22 +
  23 +/**
  24 + * File_Gettext_MO
  25 + *
  26 + * GNU MO file reader and writer.
  27 + *
  28 + * @author Michael Wallner <mike@php.net>
  29 + * @version $Revision$
  30 + * @access public
  31 + */
  32 +class File_Gettext_MO extends File_Gettext
  33 +{
  34 + /**
  35 + * file handle
  36 + *
  37 + * @access private
  38 + * @var resource
  39 + */
  40 + var $_handle = null;
  41 +
  42 + /**
  43 + * big endianess
  44 + *
  45 + * Whether to write with big endian byte order.
  46 + *
  47 + * @access public
  48 + * @var bool
  49 + */
  50 + var $writeBigEndian = false;
  51 +
  52 + /**
  53 + * Constructor
  54 + *
  55 + * @access public
  56 + * @return object File_Gettext_MO
  57 + * @param string $file path to GNU MO file
  58 + */
  59 + function File_Gettext_MO($file = '')
  60 + {
  61 + $this->file = $file;
  62 + }
  63 +
  64 + /**
  65 + * _read
  66 + *
  67 + * @access private
  68 + * @return mixed
  69 + * @param int $bytes
  70 + */
  71 + function _read($bytes = 1)
  72 + {
  73 + if (0 < $bytes = abs($bytes)) {
  74 + return fread($this->_handle, $bytes);
  75 + }
  76 + return null;
  77 + }
  78 +
  79 + /**
  80 + * _readInt
  81 + *
  82 + * @access private
  83 + * @return int
  84 + * @param bool $bigendian
  85 + */
  86 + function _readInt($bigendian = false)
  87 + {
  88 + return current($array = unpack($bigendian ? 'N' : 'V', $this->_read(4)));
  89 + }
  90 +
  91 + /**
  92 + * _writeInt
  93 + *
  94 + * @access private
  95 + * @return int
  96 + * @param int $int
  97 + */
  98 + function _writeInt($int)
  99 + {
  100 + return $this->_write(pack($this->writeBigEndian ? 'N' : 'V', (int) $int));
  101 + }
  102 +
  103 + /**
  104 + * _write
  105 + *
  106 + * @access private
  107 + * @return int
  108 + * @param string $data
  109 + */
  110 + function _write($data)
  111 + {
  112 + return fwrite($this->_handle, $data);
  113 + }
  114 +
  115 + /**
  116 + * _writeStr
  117 + *
  118 + * @access private
  119 + * @return int
  120 + * @param string $string
  121 + */
  122 + function _writeStr($string)
  123 + {
  124 + return $this->_write($string . "\0");
  125 + }
  126 +
  127 + /**
  128 + * _readStr
  129 + *
  130 + * @access private
  131 + * @return string
  132 + * @param array $params associative array with offset and length
  133 + * of the string
  134 + */
  135 + function _readStr($params)
  136 + {
  137 + fseek($this->_handle, $params['offset']);
  138 + return $this->_read($params['length']);
  139 + }
  140 +
  141 + /**
  142 + * Load MO file
  143 + *
  144 + * @access public
  145 + * @return mixed Returns true on success or PEAR_Error on failure.
  146 + * @param string $file
  147 + */
  148 + function load($file = null)
  149 + {
  150 + if (!isset($file)) {
  151 + $file = $this->file;
  152 + }
  153 +
  154 + // open MO file
  155 + if (!is_resource($this->_handle = @fopen($file, 'rb'))) {
  156 + return parent::raiseError($php_errormsg . ' ' . $file);
  157 + }
  158 + // lock MO file shared
  159 + if (!@flock($this->_handle, LOCK_SH)) {
  160 + @fclose($this->_handle);
  161 + return parent::raiseError($php_errormsg . ' ' . $file);
  162 + }
  163 +
  164 + // read (part of) magic number from MO file header and define endianess
  165 + switch ($magic = current($array = unpack('c', $this->_read(4))))
  166 + {
  167 + case -34:
  168 + $be = false;
  169 + break;
  170 +
  171 + case -107:
  172 + $be = true;
  173 + break;
  174 +
  175 + default:
  176 + return parent::raiseError("No GNU mo file: $file (magic: $magic)");
  177 + }
  178 +
  179 + // check file format revision - we currently only support 0
  180 + if (0 !== ($_rev = $this->_readInt($be))) {
  181 + return parent::raiseError('Invalid file format revision: ' . $_rev);
  182 + }
  183 +
  184 + // count of strings in this file
  185 + $count = $this->_readInt($be);
  186 +
  187 + // offset of hashing table of the msgids
  188 + $offset_original = $this->_readInt($be);
  189 + // offset of hashing table of the msgstrs
  190 + $offset_translat = $this->_readInt($be);
  191 +
  192 + // move to msgid hash table
  193 + fseek($this->_handle, $offset_original);
  194 + // read lengths and offsets of msgids
  195 + $original = array();
  196 + for ($i = 0; $i < $count; $i++) {
  197 + $original[$i] = array(
  198 + 'length' => $this->_readInt($be),
  199 + 'offset' => $this->_readInt($be)
  200 + );
  201 + }
  202 +
  203 + // move to msgstr hash table
  204 + fseek($this->_handle, $offset_translat);
  205 + // read lengths and offsets of msgstrs
  206 + $translat = array();
  207 + for ($i = 0; $i < $count; $i++) {
  208 + $translat[$i] = array(
  209 + 'length' => $this->_readInt($be),
  210 + 'offset' => $this->_readInt($be)
  211 + );
  212 + }
  213 +
  214 + // read all
  215 + for ($i = 0; $i < $count; $i++) {
  216 + $this->strings[$this->_readStr($original[$i])] =
  217 + $this->_readStr($translat[$i]);
  218 + }
  219 +
  220 + // done
  221 + @flock($this->_handle, LOCK_UN);
  222 + @fclose($this->_handle);
  223 + $this->_handle = null;
  224 +
  225 + // check for meta info
  226 + if (isset($this->strings[''])) {
  227 + $this->meta = parent::meta2array($this->strings['']);
  228 + unset($this->strings['']);
  229 + }
  230 +
  231 + return true;
  232 + }
  233 +
  234 + /**
  235 + * Save MO file
  236 + *
  237 + * @access public
  238 + * @return mixed Returns true on success or PEAR_Error on failure.
  239 + * @param string $file
  240 + */
  241 + function save($file = null)
  242 + {
  243 + if (!isset($file)) {
  244 + $file = $this->file;
  245 + }
  246 +
  247 + // open MO file
  248 + if (!is_resource($this->_handle = @fopen($file, 'wb'))) {
  249 + return parent::raiseError($php_errormsg . ' ' . $file);
  250 + }
  251 + // lock MO file exclusively
  252 + if (!@flock($this->_handle, LOCK_EX)) {
  253 + @fclose($this->_handle);
  254 + return parent::raiseError($php_errormsg . ' ' . $file);
  255 + }
  256 +
  257 + // write magic number
  258 + if ($this->writeBigEndian) {
  259 + $this->_write(pack('c*', 0x95, 0x04, 0x12, 0xde));
  260 + } else {
  261 + $this->_write(pack('c*', 0xde, 0x12, 0x04, 0x95));
  262 + }
  263 +
  264 + // write file format revision
  265 + $this->_writeInt(0);
  266 +
  267 + $count = count($this->strings) + ($meta = (count($this->meta) ? 1 : 0));
  268 + // write count of strings
  269 + $this->_writeInt($count);
  270 +
  271 + $offset = 28;
  272 + // write offset of orig. strings hash table
  273 + $this->_writeInt($offset);
  274 +
  275 + $offset += ($count * 8);
  276 + // write offset transl. strings hash table
  277 + $this->_writeInt($offset);
  278 +
  279 + // write size of hash table (we currently ommit the hash table)
  280 + $this->_writeInt(0);
  281 +
  282 + $offset += ($count * 8);
  283 + // write offset of hash table
  284 + $this->_writeInt($offset);
  285 +
  286 + // unshift meta info
  287 + if ($meta) {
  288 + $meta = '';
  289 + foreach ($this->meta as $key => $val) {
  290 + $meta .= $key . ': ' . $val . "\n";
  291 + }
  292 + $strings = array('' => $meta) + $this->strings;
  293 + } else {
  294 + $strings = $this->strings;
  295 + }
  296 +
  297 + // write offsets for original strings
  298 + foreach (array_keys($strings) as $o) {
  299 + $len = strlen($o);
  300 + $this->_writeInt($len);
  301 + $this->_writeInt($offset);
  302 + $offset += $len + 1;
  303 + }
  304 +
  305 + // write offsets for translated strings
  306 + foreach ($strings as $t) {
  307 + $len = strlen($t);
  308 + $this->_writeInt($len);
  309 + $this->_writeInt($offset);
  310 + $offset += $len + 1;
  311 + }
  312 +
  313 + // write original strings
  314 + foreach (array_keys($strings) as $o) {
  315 + $this->_writeStr($o);
  316 + }
  317 +
  318 + // write translated strings
  319 + foreach ($strings as $t) {
  320 + $this->_writeStr($t);
  321 + }
  322 +
  323 + // done
  324 + @flock($this->_handle, LOCK_UN);
  325 + @fclose($this->_handle);
  326 + return true;
  327 + }
  328 +}
  329 +?>
... ...
thirdparty/pear/File/Gettext/PO.php 0 → 100644
  1 +<?php
  2 +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3 +
  4 +/**
  5 + * File::Gettext
  6 + *
  7 + * PHP versions 4 and 5
  8 + *
  9 + * @category FileFormats
  10 + * @package File_Gettext
  11 + * @author Michael Wallner <mike@php.net>
  12 + * @copyright 2004-2005 Michael Wallner
  13 + * @license BSD, revised
  14 + * @version CVS: $Id$
  15 + * @link http://pear.php.net/package/File_Gettext
  16 + */
  17 +
  18 +/**
  19 + * Requires File_Gettext
  20 + */
  21 +require_once 'File/Gettext.php';
  22 +
  23 +/**
  24 + * File_Gettext_PO
  25 + *
  26 + * GNU PO file reader and writer.
  27 + *
  28 + * @author Michael Wallner <mike@php.net>
  29 + * @version $Revision$
  30 + * @access public
  31 + */
  32 +class File_Gettext_PO extends File_Gettext
  33 +{
  34 + /**
  35 + * Constructor
  36 + *
  37 + * @access public
  38 + * @return object File_Gettext_PO
  39 + * @param string path to GNU PO file
  40 + */
  41 + function File_Gettext_PO($file = '')
  42 + {
  43 + $this->file = $file;
  44 + }
  45 +
  46 + /**
  47 + * Load PO file
  48 + *
  49 + * @access public
  50 + * @return mixed Returns true on success or PEAR_Error on failure.
  51 + * @param string $file
  52 + */
  53 + function load($file = null)
  54 + {
  55 + if (!isset($file)) {
  56 + $file = $this->file;
  57 + }
  58 +
  59 + // load file
  60 + if (!$contents = @file($file)) {
  61 + return parent::raiseError($php_errormsg . ' ' . $file);
  62 + }
  63 + $contents = implode('', $contents);
  64 +
  65 + // match all msgid/msgstr entries
  66 + $matched = preg_match_all(
  67 + '/(msgid\s+("([^"]|\\\\")*?"\s*)+)\s+' .
  68 + '(msgstr\s+("([^"]|\\\\")*?"\s*)+)/',
  69 + $contents, $matches
  70 + );
  71 + unset($contents);
  72 +
  73 + if (!$matched) {
  74 + return parent::raiseError('No msgid/msgstr entries found');
  75 + }
  76 +
  77 + // get all msgids and msgtrs
  78 + for ($i = 0; $i < $matched; $i++) {
  79 + $msgid = preg_replace(
  80 + '/\s*msgid\s*"(.*)"\s*/s', '\\1', $matches[1][$i]);
  81 + $msgstr= preg_replace(
  82 + '/\s*msgstr\s*"(.*)"\s*/s', '\\1', $matches[4][$i]);
  83 + $this->strings[parent::prepare($msgid)] = parent::prepare($msgstr);
  84 + }
  85 +
  86 + // check for meta info
  87 + if (isset($this->strings[''])) {
  88 + $this->meta = parent::meta2array($this->strings['']);
  89 + unset($this->strings['']);
  90 + }
  91 +
  92 + return true;
  93 + }
  94 +
  95 + /**
  96 + * Save PO file
  97 + *
  98 + * @access public
  99 + * @return mixed Returns true on success or PEAR_Error on failure.
  100 + * @param string $file
  101 + */
  102 + function save($file = null)
  103 + {
  104 + if (!isset($file)) {
  105 + $file = $this->file;
  106 + }
  107 +
  108 + // open PO file
  109 + if (!is_resource($fh = @fopen($file, 'w'))) {
  110 + return parent::raiseError($php_errormsg . ' ' . $file);
  111 + }
  112 + // lock PO file exclusively
  113 + if (!@flock($fh, LOCK_EX)) {
  114 + @fclose($fh);
  115 + return parent::raiseError($php_errmsg . ' ' . $file);
  116 + }
  117 +
  118 + // write meta info
  119 + if (count($this->meta)) {
  120 + $meta = 'msgid ""' . "\nmsgstr " . '""' . "\n";
  121 + foreach ($this->meta as $k => $v) {
  122 + $meta .= '"' . $k . ': ' . $v . '\n"' . "\n";
  123 + }
  124 + fwrite($fh, $meta . "\n");
  125 + }
  126 + // write strings
  127 + foreach ($this->strings as $o => $t) {
  128 + fwrite($fh,
  129 + 'msgid "' . parent::prepare($o, true) . '"' . "\n" .
  130 + 'msgstr "' . parent::prepare($t, true) . '"' . "\n\n"
  131 + );
  132 + }
  133 +
  134 + //done
  135 + @flock($fh, LOCK_UN);
  136 + @fclose($fh);
  137 + return true;
  138 + }
  139 +}
  140 +?>
... ...