cvs: pear /Translation2 package.xml /Translation2/Admin/Container xml.php /Translation2/Container xml.php
| From: | Lorenzo Alberton | Date: | Sun, 07 Nov 2004 18:21:25 +0000 |
| Subject: | cvs: pear /Translation2 package.xml /Translation2/Admin/Container xml.php /Translation2/Container xml.php | ||
| Groups: | php.pear.cvs | ||
| Request: | Send a blank email to pear-cvs+get-25738@lists.php.net to get a copy of this message | ||
quipo Sun Nov 7 13:21:25 2004 EDT
Added files:
/pear/Translation2/Admin/Container xml.php
/pear/Translation2/Container xml.php
Modified files:
/pear/Translation2 package.xml
Log:
- changelog
- update filelist (new xml container + gettext examples)
- update dependencies
http://cvs.php.net/diff.php/pear/Translation2/package.xml?r1=1.40&r2=1.41&ty=u Index: pear/Translation2/package.xml diff -u pear/Translation2/package.xml:1.40 pear/Translation2/package.xml:1.41 --- pear/Translation2/package.xml:1.40 Tue Nov 2 11:46:40 2004 +++ pear/Translation2/package.xml Sun Nov 7 13:21:24 2004 @@ -42,48 +42,49 @@ </maintainers> <release> <version>2.0.0beta3</version> - <date>2004-11-02</date> + <date>2004-11-07</date> <license>PHP License</license> <state>beta</state> <notes> -- welcome to the new developers, Ian Eure and Michael Wallner -- the last release contained an old gettext driver (bug #2503) (ieure) -- many portability fixes applied to the database containers (thanks to Ian Eure and +- Welcome to the new developers, Ian Eure and Michael Wallner +- The last release contained an old gettext driver (bug #2503) (ieure) +- Many portability fixes applied to the database containers (thanks to Ian Eure and Xavier Lembo for their suggestions and patches) -- minor changes to the table definitions for better portability (lowercase field names, +- Minor changes to the table definitions for better portability (lowercase field names, VARCHAR instead of CHAR, bigger field size) - setLang() now returns an error if called with an unknown $langID (bug #2498). -- added $cleaningFrequency option to the CacheLiteFunction to implement +- Added $cleaningFrequency option to the CacheLiteFunction to implement statistic cache cleaning -- added Translation2_Admin::cleanCache() method to clean the cache on demand. +- Added Translation2_Admin::cleanCache() method to clean the cache on demand. It is automatically triggered after a change if $options['autoCleanCache'] is TRUE. - Big cleanup of the DB and Admin_DB containers. See CVS changelog for details. (ieure) - Added update() method to Translation2_Admin. This is a BC break; you used to be able to update strings with add(). This is no longer possible, use update(). (ieure) -- re-added a check in add() to see if an update() is needed instead of an insert +- Re-added a check in add() to see if an update() is needed instead of an insert - String ID columns are created as type TEXT to support gettext-style string IDs. (ieure) -- reflect the changes made to the DB container into the MDB and MDB2 containers too, +- Reflect the changes made to the DB container into the MDB and MDB2 containers too, plus other minor fixes/optimizations. - strings_default_table may use %s to represent the language name. You may now have one table per language without having to explicitly specify them all. (ieure) - DefaultText decorator has new getStringID() method, which will return the string which was requested if no stringID exists. This mirrors the gettext() semantics. (ieure) -- Add Admin_Decorator class, which allows you to create Decorators for +- Added Admin_Decorator class, which allows you to create Decorators for Translation2_Admin. (ieure) - New 'Autoadd' Admin Decorator, which automatically adds requested strings. (ieure) -- removed translate(), added getStringID(). You can mimic the old behaviour in +- Removed translate(), added getStringID(). You can mimic the old behaviour in two steps: $stringID = $tr->getStringID('mystring', 'mypage'); $translatedString = $tr->get($stringID, 'mypage', $otherLangID); -- major cleanup of the gettext container and added some examples (mike) +- Major cleanup of the gettext container and added some examples (mike) - removeLang() was missing. Fixed. -- the gettext container no longer require the gettext extension (thanks to Sergey Korotkov); +- The gettext container no longer require the gettext extension (thanks to Sergey Korotkov); it is used when loaded, though, since it's faster. -- both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) -- new Iconv decorator based on the one written by Sergey Korotkov -- added a new "encoding" column to the langsAvail table +- Both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) +- New Iconv decorator based on the one written by Sergey Korotkov +- Added a new "encoding" column to the langsAvail table +- New xml container by Olivier Guilyardi </notes> <deps> <dep type="pkg" rel="has" optional="yes">Cache_Lite</dep> @@ -94,6 +95,7 @@ <dep type="ext" rel="has" optional="yes">gettext</dep> <dep type="pkg" rel="has" optional="yes">File_Gettext</dep> <dep type="pkg" rel="ge" optional="yes" version="0.9.1">I18Nv2</dep> + <dep type="pkg" rel="ge" optional="yes" version="0.13.0">XML_Serializer</dep> </deps> <filelist> <file role="php" name="Translation2.php" /> @@ -109,6 +111,7 @@ <file name="gettext.php" /> <file name="mdb.php" /> <file name="mdb2.php" /> + <file name="xml.php" /> </dir> <dir name="Decorator" role="php"> <file name="Autoadd.php" /> @@ -120,11 +123,13 @@ <file name="gettext.php" /> <file name="mdb.php" /> <file name="mdb2.php" /> + <file name="xml.php" /> </dir> <dir name="Decorator" role="php"> <file name="CacheLiteFunction.php" /> <file name="CacheMemory.php" /> <file name="DefaultText.php" /> + <file name="Iconv.php" /> <file name="Lang.php" /> <file name="SpecialChars.php" /> <file name="UTF8.php" /> @@ -132,9 +137,15 @@ <dir name="docs" role="doc"> <file name="gettext_readme.txt" /> <dir name="examples" role="doc"> + <file role="doc" name="gettext_admin.php" /> + <file role="doc" name="gettext_domains.ini" /> + <file role="doc" name="gettext_langs.ini" /> + <file role="doc" name="gettext_prepare.php" /> + <file role="doc" name="gettext_settings.php" /> <file role="doc" name="settings.php" /> <file role="doc" name="Translation2_example.php" /> <file role="doc" name="Translation2_example.sql" /> + <file role="doc" name="Translation2_gettext_example.php" /> </dir> </dir> </dir> @@ -143,48 +154,49 @@ <changelog> <release> <version>2.0.0beta3</version> - <date>2004-11-02</date> + <date>2004-11-07</date> <license>PHP License</license> <state>beta</state> <notes> -- welcome to the new developers, Ian Eure and Michael Wallner -- the last release contained an old gettext driver (bug #2503) (ieure) -- many portability fixes applied to the database containers (thanks to Ian Eure and +- Welcome to the new developers, Ian Eure and Michael Wallner +- The last release contained an old gettext driver (bug #2503) (ieure) +- Many portability fixes applied to the database containers (thanks to Ian Eure and Xavier Lembo for their suggestions and patches) -- minor changes to the table definitions for better portability (lowercase field names, +- Minor changes to the table definitions for better portability (lowercase field names, VARCHAR instead of CHAR, bigger field size) - setLang() now returns an error if called with an unknown $langID (bug #2498). -- added $cleaningFrequency option to the CacheLiteFunction to implement +- Added $cleaningFrequency option to the CacheLiteFunction to implement statistic cache cleaning -- added Translation2_Admin::cleanCache() method to clean the cache on demand. +- Added Translation2_Admin::cleanCache() method to clean the cache on demand. It is automatically triggered after a change if $options['autoCleanCache'] is TRUE. - Big cleanup of the DB and Admin_DB containers. See CVS changelog for details. (ieure) - Added update() method to Translation2_Admin. This is a BC break; you used to be able to update strings with add(). This is no longer possible, use update(). (ieure) -- re-added a check in add() to see if an update() is needed instead of an insert +- Re-added a check in add() to see if an update() is needed instead of an insert - String ID columns are created as type TEXT to support gettext-style string IDs. (ieure) -- reflect the changes made to the DB container into the MDB and MDB2 containers too, +- Reflect the changes made to the DB container into the MDB and MDB2 containers too, plus other minor fixes/optimizations. - strings_default_table may use %s to represent the language name. You may now have one table per language without having to explicitly specify them all. (ieure) - DefaultText decorator has new getStringID() method, which will return the string which was requested if no stringID exists. This mirrors the gettext() semantics. (ieure) -- Add Admin_Decorator class, which allows you to create Decorators for +- Added Admin_Decorator class, which allows you to create Decorators for Translation2_Admin. (ieure) - New 'Autoadd' Admin Decorator, which automatically adds requested strings. (ieure) -- removed translate(), added getStringID(). You can mimic the old behaviour in +- Removed translate(), added getStringID(). You can mimic the old behaviour in two steps: $stringID = $tr->getStringID('mystring', 'mypage'); $translatedString = $tr->get($stringID, 'mypage', $otherLangID); -- major cleanup of the gettext container and added some examples (mike) +- Major cleanup of the gettext container and added some examples (mike) - removeLang() was missing. Fixed. -- the gettext container no longer require the gettext extension (thanks to Sergey Korotkov); +- The gettext container no longer require the gettext extension (thanks to Sergey Korotkov); it is used when loaded, though, since it's faster. -- both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) -- new Iconv decorator based on the one written by Sergey Korotkov -- added a new "encoding" column to the langsAvail table +- Both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) +- New Iconv decorator based on the one written by Sergey Korotkov +- Added a new "encoding" column to the langsAvail table +- New xml container by Olivier Guilyardi </notes> </release> <release> http://cvs.php.net/co.php/pear/Translation2/Admin/Container/xml.php?r=1.1&p=1 Index: pear/Translation2/Admin/Container/xml.php +++ pear/Translation2/Admin/Container/xml.php <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2004 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 3.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/3_0.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: Olivier Guilyardi <olivier at samalyse dot com> | // +----------------------------------------------------------------------+ // // $Id: xml.php,v 1.1 2004/11/07 18:21:25 quipo Exp $ // /** * @package Translation2 * @version $Id: xml.php,v 1.1 2004/11/07 18:21:25 quipo Exp $ */ /** * require Translation2_Container_xml class */ require_once 'Translation2/Container/xml.php'; require_once "XML/Util.php"; /** * Storage driver for storing/fetching data to/from an XML file * * @package Translation2 * @version $Revision $ */ class Translation2_Admin_Container_xml extends Translation2_Container_xml { // {{{ class vars /** * File resource. Opened in write mode when saving is scheduled. * @var resource */ var $_fileRes = null; // }}} // {{{ createNewLang() /** * Does nothing (here for compatibility with the container interface) * * @param array $langData * @return mixed true on success, PEAR_Error on failure */ function createNewLang($langData) { return true; } // }}} // {{{ addLangToAvailList() /** * Creates a new entry in the <languages> section * * @param array $langData array('lang_id' => 'en', * 'name' => 'english', * 'meta' => 'some meta info', * 'error_text' => 'not available'); * @return mixed true on success, PEAR_Error on failure */ function addLangToAvailList($langData) { $validInput = array( 'name' => '', 'meta' => 'iso-8859-1', 'error_text' => '' ); foreach ($validInput as $key => $val) { if (isset($langData[$key])) $validInput[$key] = $langData[$key]; } $this->_data['languages'][$langData['lang_id']] = $validInput; return $this->_scheduleSaving(); } // }}} // {{{ add() /** * Add a new entry in the strings table. * * @param string $stringID * @param string $pageID * @param array $stringArray Associative array with string translations. * Sample format: array('en' => 'sample', 'it' => 'esempio') * @return mixed true on success, PEAR_Error on failure */ function add($stringID, $pageID, $stringArray) { $langs = array_intersect( array_keys($stringArray), $this->getLangs('ids') ); $pageID = is_null($pageID) ? '#NULL' : $pageID; $pageID = empty($pageID) ? '#EMPTY' : $pageID; foreach ($langs as $lang) { $this->_data['pages'][$pageID][$stringID][$lang] = $stringArray[$lang]; } return $this->_scheduleSaving(); } // }}} // {{{ update() /** * Update an existing entry in the strings table. * * @param string $stringID * @param string $pageID * @param array $stringArray Associative array with string translations. * Sample format: array('en' => 'sample', 'it' => 'esempio') * @return mixed true on success, PEAR_Error on failure */ function update($stringID, $pageID, $stringArray) { return $this->add($stringID, $pageID, $stringArray); } // }}} // {{{ remove() /** * Remove an entry from the strings table. * * @param string $stringID * @param string $pageID * @return mixed true on success, PEAR_Error on failure */ function remove($stringID, $pageID) { $pageID = is_null($pageID) ? '#NULL' : $pageID; $pageID = empty($pageID) ? '#EMPTY' : $pageID; unset ($this->_data['pages'][$pageID][$stringID]); return $this->_scheduleSaving(); } // }}} // {{{ _scheduleSaving() /** * Prepare data saving * * This methods registers _saveData() as a PEAR shutdown function. This * is to avoid saving multiple times if the programmer makes several * changes. * * @return mixed true on success or a PEAR_Error on failure * @access private * @see Translation2_Admin_Container_xml::_saveData() */ function _scheduleSaving() { if (is_null($this->_fileRes)) { if (!$this->_fileRes = fopen ($this->_filename, 'w')) { return new PEAR_Error ('Unable to open the XML file for writing : '. $this->_filename); } register_shutdown_function (array(&$this, '_saveData')); } return true; } // }}} // {{{ _saveData() /** * Serialize and save the updated tranlation data to the XML file * * @return void * @access private * @see Translation2_Admin_Container_xml::_scheduleSaving() */ function _saveData() { $this->_convertEncodings('to_xml'); // Serializing $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" . "<!DOCTYPE translation2 [\n" . " <!ELEMENT translation2 (languages,pages)>\n" . " <!ELEMENT languages (lang*)>\n" . " <!ELEMENT lang (name?,meta?,error_text?,encoding?)>\n" . " <!ATTLIST lang id ID #REQUIRED>\n" . " <!ELEMENT name (#PCDATA)>\n" . " <!ELEMENT meta (#PCDATA)>\n" . " <!ELEMENT error_text (#PCDATA)>\n" . " <!ELEMENT encoding (#PCDATA)>\n" . " <!ELEMENT pages (page*)>\n" . " <!ELEMENT page (string*)>\n" . " <!ATTLIST page key CDATA #REQUIRED>\n" . " <!ELEMENT string (tr*)>\n" . " <!ATTLIST string key CDATA #REQUIRED>\n" . " <!ELEMENT tr (#PCDATA)>\n" . " <!ATTLIST tr lang IDREF #REQUIRED>\n" . "]>\n\n" . "<translation2>\n" . " <languages>\n"; foreach ($this->_data['languages'] as $lang => $spec) { extract ($spec); $xml .= " <lang id=\"$lang\">\n" . " <name>" . ($name ? ' ' . XML_Util::replaceEntities($name) . ' ' : '') . "</name>\n" . " <meta>" . ($meta ? ' ' . XML_Util::replaceEntities($meta) . ' ' : "") . "</meta>\n" . " <error_text>" . ($error_text ? ' ' . XML_Util::replaceEntities($error_text) . ' ' : "") . "</error_text>\n" . " <encoding>" . ($encoding ? " $encoding " : "") . "</encoding>\n" . " </lang>\n"; } $xml .= " </languages>\n" . " <pages>\n"; foreach ($this->_data['pages'] as $page => $strings) { $xml .= " <page key=\"" . XML_Util::replaceEntities($page) . "\">\n"; foreach ($strings as $str_id => $translations) { $xml .= " <string key=\"" . XML_Util::replaceEntities($str_id) . "\">\n"; foreach ($translations as $lang => $str) { $xml .= " <tr lang=\"$lang\"> " . XML_Util::replaceEntities($str) . " </tr>\n"; } $xml .= " </string>\n"; } $xml .= " </page>\n"; } $xml .= " </pages>\n" . "</translation2>\n"; // Saving fwrite ($this->_fileRes, $xml); fclose ($this->_fileRes); } // }}} } ?> http://cvs.php.net/co.php/pear/Translation2/Container/xml.php?r=1.1&p=1 Index: pear/Translation2/Container/xml.php +++ pear/Translation2/Container/xml.php <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2004 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 3.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/3_0.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: Olivier Guilyardi <olivier at samalyse dot com> | // +----------------------------------------------------------------------+ // // $Id $ // /** * @package Translation2 * @version $Id $ */ /** * require Translation2_Container class */ require_once 'Translation2/Container.php'; /** * require XML_Unserializer class */ require_once 'XML/Unserializer.php'; /** * Storage driver for fetching data from an xml file * * Example file : * * <?xml version="1.0" encoding="iso-8859-1"?> * <translation2> * <languages> * <lang id='fr_FR'> * <name> English </name> * <meta> Custom meta data</meta> * <error_text> Non disponible en français </error_text> * <encoding> iso-8859-1 </encoding> * </lang> * <!-- some more <lang>...</lang> --> * </languages> * <pages> * <page key='pets'> * <string key='cat'> * <tr lang='fr_FR'> Chat </tr> * <!-- some more <tr>...</tr> --> * </string> * <!-- some more <string>...</string> --> * </page> * <!-- some more <page>...</page> --> * </pages> * </translation2> * * @package Translation2 * @version $Revision $ */ class Translation2_Container_xml extends Translation2_Container { // {{{ class vars /** * Unserialized XML data * @var object */ var $_data = null; /** * XML file name * @var string */ var $_filename; /** * query counter (unused in this driver. Here for compatibility * with Translation2_example.php) * @var integer * @access private */ var $_queries = 0; // }}} // {{{ init /** * Initialize the container * * @param string $filename Path to the XML file * @return boolean|PEAR_Error object if something went wrong */ function init($filename) { $this->_setDefaultOptions(); $this->_filename = $filename; $keyAttr = array ('lang' => 'id', 'page' => 'key', 'string' => 'key', 'tr' => 'lang'); $unserializer = &new XML_Unserializer (array('keyAttribute' => $keyAttr)); if (PEAR::isError($status = $unserializer->unserialize($filename, true))) { return $status; } // Unserialize data $this->_data = $unserializer->getUnserializedData(); // Handle default language settings. // // This allows, for example, to rapidly write the meta data as : // // <lang key="fr"/> // <lang key="en"/> $defaults = array('name' => '', 'meta' => '', 'error_text' => '', 'encoding' => 'iso-8859-1'); foreach ($this->_data['languages'] as $lang_id => $settings) { if ($settings == "") { $this->_data['languages'][$lang_id] = $defaults; } else { $this->_data['languages'][$lang_id] = array_merge($defaults,$this->_data['languages'][$lang_id]); } } // Convert encodings from xml (somehow heavy) return $this->_convertEncodings('from_xml'); } // }}} // {{{ _convertEncodings() /** * Convert strings to/from XML unique charset (UTF-8) * */ function _convertEncodings($direction) { if ($direction == 'from_xml') { $source_encoding = 'UTF-8'; } else { $target_encoding = 'UTF-8'; } foreach ($this->_data['pages'] as $page_id => $page_content) { foreach ($page_content as $str_id => $translations) { foreach ($translations as $lang => $str) { if ($direction == 'from_xml') { $target_encoding = strtoupper($this->_data['languages'][$lang]['encoding']); } else { $source_encoding = strtoupper($this->_data['languages'][$lang]['encoding']); } if ($target_encoding != $source_encoding) { if (($res = iconv ($source_encoding, $target_encoding, $str)) !== FALSE) { $this->_data['pages'][$page_id][$str_id][$lang] = $res; } else { return new PEAR_Error("Encoding conversion error " . "(source encoding : $source_encoding, ". "target encoding : $target_encoding, ". "processed string : \"$str\""); } } } } } return true; } // }}} // {{{ _setDefaultOptions() /** * Set some default options * * @access private * @return void */ function _setDefaultOptions() { } // }}} // {{{ fetchLangs() /** * Fetch the available langs */ function fetchLangs() { $res = array(); foreach ($this->_data['languages'] as $id => $spec) { $spec['id'] = $id; $res[$id] = $spec; } $this->langs = $res; } // }}} // {{{ getPage() /** * Returns an array of the strings in the selected page * * @param string $pageID * @param string $langID * @return array */ function getPage($pageID = null, $langID = null) { $langID = is_null($langID) ? $this->currentLang['id'] : $langID; $pageID = (is_null($pageID)) ? '#NULL' : $pageID; $pageID = (empty($pageID)) ? '#EMPTY' : $pageID; $result = array(); foreach ($this->_data['pages'][$pageID] as $str_id => $translations) { $result[$str_id] = isset($translations[$langID]) ? $translations[$langID] : null; } return $result; } // }}} // {{{ getOne() /** * Get a single item from the container * * @param string $stringID * @param string $pageID * @param string $langID * @return string */ function getOne($stringID, $pageID = null, $langID = null) { $langID = is_null($langID) ? $this->currentLang['id'] : $langID; $pageID = (is_null($pageID)) ? '#NULL' : $pageID; return isset($this->_data['pages'][$pageID][$stringID][$langID]) ? $this->_data['pages'][$pageID][$stringID][$langID] : null; } // }}} // {{{ getStringID() /** * Get the stringID for the given string * * @param string $stringID * @param string $pageID * @return string */ function getStringID($string, $pageID = null) { $pageID = (is_null($pageID)) ? '#NULL' : $pageID; foreach ($this->_data['pages'][$pageID] as $str_id => $translations) { if (array_search($string,$translations) !== false) { return $str_id; } } return ''; } // }}} } ?>
http://cvs.php.net/diff.php/pear/Translation2/package.xml?r1=1.40&r2=1.41&ty=u Index: pear/Translation2/package.xml diff -u pear/Translation2/package.xml:1.40 pear/Translation2/package.xml:1.41 --- pear/Translation2/package.xml:1.40 Tue Nov 2 11:46:40 2004 +++ pear/Translation2/package.xml Sun Nov 7 13:21:24 2004 @@ -42,48 +42,49 @@ </maintainers> <release> <version>2.0.0beta3</version> - <date>2004-11-02</date> + <date>2004-11-07</date> <license>PHP License</license> <state>beta</state> <notes> -- welcome to the new developers, Ian Eure and Michael Wallner -- the last release contained an old gettext driver (bug #2503) (ieure) -- many portability fixes applied to the database containers (thanks to Ian Eure and +- Welcome to the new developers, Ian Eure and Michael Wallner +- The last release contained an old gettext driver (bug #2503) (ieure) +- Many portability fixes applied to the database containers (thanks to Ian Eure and Xavier Lembo for their suggestions and patches) -- minor changes to the table definitions for better portability (lowercase field names, +- Minor changes to the table definitions for better portability (lowercase field names, VARCHAR instead of CHAR, bigger field size) - setLang() now returns an error if called with an unknown $langID (bug #2498). -- added $cleaningFrequency option to the CacheLiteFunction to implement +- Added $cleaningFrequency option to the CacheLiteFunction to implement statistic cache cleaning -- added Translation2_Admin::cleanCache() method to clean the cache on demand. +- Added Translation2_Admin::cleanCache() method to clean the cache on demand. It is automatically triggered after a change if $options['autoCleanCache'] is TRUE. - Big cleanup of the DB and Admin_DB containers. See CVS changelog for details. (ieure) - Added update() method to Translation2_Admin. This is a BC break; you used to be able to update strings with add(). This is no longer possible, use update(). (ieure) -- re-added a check in add() to see if an update() is needed instead of an insert +- Re-added a check in add() to see if an update() is needed instead of an insert - String ID columns are created as type TEXT to support gettext-style string IDs. (ieure) -- reflect the changes made to the DB container into the MDB and MDB2 containers too, +- Reflect the changes made to the DB container into the MDB and MDB2 containers too, plus other minor fixes/optimizations. - strings_default_table may use %s to represent the language name. You may now have one table per language without having to explicitly specify them all. (ieure) - DefaultText decorator has new getStringID() method, which will return the string which was requested if no stringID exists. This mirrors the gettext() semantics. (ieure) -- Add Admin_Decorator class, which allows you to create Decorators for +- Added Admin_Decorator class, which allows you to create Decorators for Translation2_Admin. (ieure) - New 'Autoadd' Admin Decorator, which automatically adds requested strings. (ieure) -- removed translate(), added getStringID(). You can mimic the old behaviour in +- Removed translate(), added getStringID(). You can mimic the old behaviour in two steps: $stringID = $tr->getStringID('mystring', 'mypage'); $translatedString = $tr->get($stringID, 'mypage', $otherLangID); -- major cleanup of the gettext container and added some examples (mike) +- Major cleanup of the gettext container and added some examples (mike) - removeLang() was missing. Fixed. -- the gettext container no longer require the gettext extension (thanks to Sergey Korotkov); +- The gettext container no longer require the gettext extension (thanks to Sergey Korotkov); it is used when loaded, though, since it's faster. -- both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) -- new Iconv decorator based on the one written by Sergey Korotkov -- added a new "encoding" column to the langsAvail table +- Both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) +- New Iconv decorator based on the one written by Sergey Korotkov +- Added a new "encoding" column to the langsAvail table +- New xml container by Olivier Guilyardi </notes> <deps> <dep type="pkg" rel="has" optional="yes">Cache_Lite</dep> @@ -94,6 +95,7 @@ <dep type="ext" rel="has" optional="yes">gettext</dep> <dep type="pkg" rel="has" optional="yes">File_Gettext</dep> <dep type="pkg" rel="ge" optional="yes" version="0.9.1">I18Nv2</dep> + <dep type="pkg" rel="ge" optional="yes" version="0.13.0">XML_Serializer</dep> </deps> <filelist> <file role="php" name="Translation2.php" /> @@ -109,6 +111,7 @@ <file name="gettext.php" /> <file name="mdb.php" /> <file name="mdb2.php" /> + <file name="xml.php" /> </dir> <dir name="Decorator" role="php"> <file name="Autoadd.php" /> @@ -120,11 +123,13 @@ <file name="gettext.php" /> <file name="mdb.php" /> <file name="mdb2.php" /> + <file name="xml.php" /> </dir> <dir name="Decorator" role="php"> <file name="CacheLiteFunction.php" /> <file name="CacheMemory.php" /> <file name="DefaultText.php" /> + <file name="Iconv.php" /> <file name="Lang.php" /> <file name="SpecialChars.php" /> <file name="UTF8.php" /> @@ -132,9 +137,15 @@ <dir name="docs" role="doc"> <file name="gettext_readme.txt" /> <dir name="examples" role="doc"> + <file role="doc" name="gettext_admin.php" /> + <file role="doc" name="gettext_domains.ini" /> + <file role="doc" name="gettext_langs.ini" /> + <file role="doc" name="gettext_prepare.php" /> + <file role="doc" name="gettext_settings.php" /> <file role="doc" name="settings.php" /> <file role="doc" name="Translation2_example.php" /> <file role="doc" name="Translation2_example.sql" /> + <file role="doc" name="Translation2_gettext_example.php" /> </dir> </dir> </dir> @@ -143,48 +154,49 @@ <changelog> <release> <version>2.0.0beta3</version> - <date>2004-11-02</date> + <date>2004-11-07</date> <license>PHP License</license> <state>beta</state> <notes> -- welcome to the new developers, Ian Eure and Michael Wallner -- the last release contained an old gettext driver (bug #2503) (ieure) -- many portability fixes applied to the database containers (thanks to Ian Eure and +- Welcome to the new developers, Ian Eure and Michael Wallner +- The last release contained an old gettext driver (bug #2503) (ieure) +- Many portability fixes applied to the database containers (thanks to Ian Eure and Xavier Lembo for their suggestions and patches) -- minor changes to the table definitions for better portability (lowercase field names, +- Minor changes to the table definitions for better portability (lowercase field names, VARCHAR instead of CHAR, bigger field size) - setLang() now returns an error if called with an unknown $langID (bug #2498). -- added $cleaningFrequency option to the CacheLiteFunction to implement +- Added $cleaningFrequency option to the CacheLiteFunction to implement statistic cache cleaning -- added Translation2_Admin::cleanCache() method to clean the cache on demand. +- Added Translation2_Admin::cleanCache() method to clean the cache on demand. It is automatically triggered after a change if $options['autoCleanCache'] is TRUE. - Big cleanup of the DB and Admin_DB containers. See CVS changelog for details. (ieure) - Added update() method to Translation2_Admin. This is a BC break; you used to be able to update strings with add(). This is no longer possible, use update(). (ieure) -- re-added a check in add() to see if an update() is needed instead of an insert +- Re-added a check in add() to see if an update() is needed instead of an insert - String ID columns are created as type TEXT to support gettext-style string IDs. (ieure) -- reflect the changes made to the DB container into the MDB and MDB2 containers too, +- Reflect the changes made to the DB container into the MDB and MDB2 containers too, plus other minor fixes/optimizations. - strings_default_table may use %s to represent the language name. You may now have one table per language without having to explicitly specify them all. (ieure) - DefaultText decorator has new getStringID() method, which will return the string which was requested if no stringID exists. This mirrors the gettext() semantics. (ieure) -- Add Admin_Decorator class, which allows you to create Decorators for +- Added Admin_Decorator class, which allows you to create Decorators for Translation2_Admin. (ieure) - New 'Autoadd' Admin Decorator, which automatically adds requested strings. (ieure) -- removed translate(), added getStringID(). You can mimic the old behaviour in +- Removed translate(), added getStringID(). You can mimic the old behaviour in two steps: $stringID = $tr->getStringID('mystring', 'mypage'); $translatedString = $tr->get($stringID, 'mypage', $otherLangID); -- major cleanup of the gettext container and added some examples (mike) +- Major cleanup of the gettext container and added some examples (mike) - removeLang() was missing. Fixed. -- the gettext container no longer require the gettext extension (thanks to Sergey Korotkov); +- The gettext container no longer require the gettext extension (thanks to Sergey Korotkov); it is used when loaded, though, since it's faster. -- both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) -- new Iconv decorator based on the one written by Sergey Korotkov -- added a new "encoding" column to the langsAvail table +- Both .mo and .po files are valid data sources for the gettext container (Sergey Korotkov) +- New Iconv decorator based on the one written by Sergey Korotkov +- Added a new "encoding" column to the langsAvail table +- New xml container by Olivier Guilyardi </notes> </release> <release> http://cvs.php.net/co.php/pear/Translation2/Admin/Container/xml.php?r=1.1&p=1 Index: pear/Translation2/Admin/Container/xml.php +++ pear/Translation2/Admin/Container/xml.php <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2004 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 3.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/3_0.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: Olivier Guilyardi <olivier at samalyse dot com> | // +----------------------------------------------------------------------+ // // $Id: xml.php,v 1.1 2004/11/07 18:21:25 quipo Exp $ // /** * @package Translation2 * @version $Id: xml.php,v 1.1 2004/11/07 18:21:25 quipo Exp $ */ /** * require Translation2_Container_xml class */ require_once 'Translation2/Container/xml.php'; require_once "XML/Util.php"; /** * Storage driver for storing/fetching data to/from an XML file * * @package Translation2 * @version $Revision $ */ class Translation2_Admin_Container_xml extends Translation2_Container_xml { // {{{ class vars /** * File resource. Opened in write mode when saving is scheduled. * @var resource */ var $_fileRes = null; // }}} // {{{ createNewLang() /** * Does nothing (here for compatibility with the container interface) * * @param array $langData * @return mixed true on success, PEAR_Error on failure */ function createNewLang($langData) { return true; } // }}} // {{{ addLangToAvailList() /** * Creates a new entry in the <languages> section * * @param array $langData array('lang_id' => 'en', * 'name' => 'english', * 'meta' => 'some meta info', * 'error_text' => 'not available'); * @return mixed true on success, PEAR_Error on failure */ function addLangToAvailList($langData) { $validInput = array( 'name' => '', 'meta' => 'iso-8859-1', 'error_text' => '' ); foreach ($validInput as $key => $val) { if (isset($langData[$key])) $validInput[$key] = $langData[$key]; } $this->_data['languages'][$langData['lang_id']] = $validInput; return $this->_scheduleSaving(); } // }}} // {{{ add() /** * Add a new entry in the strings table. * * @param string $stringID * @param string $pageID * @param array $stringArray Associative array with string translations. * Sample format: array('en' => 'sample', 'it' => 'esempio') * @return mixed true on success, PEAR_Error on failure */ function add($stringID, $pageID, $stringArray) { $langs = array_intersect( array_keys($stringArray), $this->getLangs('ids') ); $pageID = is_null($pageID) ? '#NULL' : $pageID; $pageID = empty($pageID) ? '#EMPTY' : $pageID; foreach ($langs as $lang) { $this->_data['pages'][$pageID][$stringID][$lang] = $stringArray[$lang]; } return $this->_scheduleSaving(); } // }}} // {{{ update() /** * Update an existing entry in the strings table. * * @param string $stringID * @param string $pageID * @param array $stringArray Associative array with string translations. * Sample format: array('en' => 'sample', 'it' => 'esempio') * @return mixed true on success, PEAR_Error on failure */ function update($stringID, $pageID, $stringArray) { return $this->add($stringID, $pageID, $stringArray); } // }}} // {{{ remove() /** * Remove an entry from the strings table. * * @param string $stringID * @param string $pageID * @return mixed true on success, PEAR_Error on failure */ function remove($stringID, $pageID) { $pageID = is_null($pageID) ? '#NULL' : $pageID; $pageID = empty($pageID) ? '#EMPTY' : $pageID; unset ($this->_data['pages'][$pageID][$stringID]); return $this->_scheduleSaving(); } // }}} // {{{ _scheduleSaving() /** * Prepare data saving * * This methods registers _saveData() as a PEAR shutdown function. This * is to avoid saving multiple times if the programmer makes several * changes. * * @return mixed true on success or a PEAR_Error on failure * @access private * @see Translation2_Admin_Container_xml::_saveData() */ function _scheduleSaving() { if (is_null($this->_fileRes)) { if (!$this->_fileRes = fopen ($this->_filename, 'w')) { return new PEAR_Error ('Unable to open the XML file for writing : '. $this->_filename); } register_shutdown_function (array(&$this, '_saveData')); } return true; } // }}} // {{{ _saveData() /** * Serialize and save the updated tranlation data to the XML file * * @return void * @access private * @see Translation2_Admin_Container_xml::_scheduleSaving() */ function _saveData() { $this->_convertEncodings('to_xml'); // Serializing $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" . "<!DOCTYPE translation2 [\n" . " <!ELEMENT translation2 (languages,pages)>\n" . " <!ELEMENT languages (lang*)>\n" . " <!ELEMENT lang (name?,meta?,error_text?,encoding?)>\n" . " <!ATTLIST lang id ID #REQUIRED>\n" . " <!ELEMENT name (#PCDATA)>\n" . " <!ELEMENT meta (#PCDATA)>\n" . " <!ELEMENT error_text (#PCDATA)>\n" . " <!ELEMENT encoding (#PCDATA)>\n" . " <!ELEMENT pages (page*)>\n" . " <!ELEMENT page (string*)>\n" . " <!ATTLIST page key CDATA #REQUIRED>\n" . " <!ELEMENT string (tr*)>\n" . " <!ATTLIST string key CDATA #REQUIRED>\n" . " <!ELEMENT tr (#PCDATA)>\n" . " <!ATTLIST tr lang IDREF #REQUIRED>\n" . "]>\n\n" . "<translation2>\n" . " <languages>\n"; foreach ($this->_data['languages'] as $lang => $spec) { extract ($spec); $xml .= " <lang id=\"$lang\">\n" . " <name>" . ($name ? ' ' . XML_Util::replaceEntities($name) . ' ' : '') . "</name>\n" . " <meta>" . ($meta ? ' ' . XML_Util::replaceEntities($meta) . ' ' : "") . "</meta>\n" . " <error_text>" . ($error_text ? ' ' . XML_Util::replaceEntities($error_text) . ' ' : "") . "</error_text>\n" . " <encoding>" . ($encoding ? " $encoding " : "") . "</encoding>\n" . " </lang>\n"; } $xml .= " </languages>\n" . " <pages>\n"; foreach ($this->_data['pages'] as $page => $strings) { $xml .= " <page key=\"" . XML_Util::replaceEntities($page) . "\">\n"; foreach ($strings as $str_id => $translations) { $xml .= " <string key=\"" . XML_Util::replaceEntities($str_id) . "\">\n"; foreach ($translations as $lang => $str) { $xml .= " <tr lang=\"$lang\"> " . XML_Util::replaceEntities($str) . " </tr>\n"; } $xml .= " </string>\n"; } $xml .= " </page>\n"; } $xml .= " </pages>\n" . "</translation2>\n"; // Saving fwrite ($this->_fileRes, $xml); fclose ($this->_fileRes); } // }}} } ?> http://cvs.php.net/co.php/pear/Translation2/Container/xml.php?r=1.1&p=1 Index: pear/Translation2/Container/xml.php +++ pear/Translation2/Container/xml.php <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2004 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 3.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/3_0.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: Olivier Guilyardi <olivier at samalyse dot com> | // +----------------------------------------------------------------------+ // // $Id $ // /** * @package Translation2 * @version $Id $ */ /** * require Translation2_Container class */ require_once 'Translation2/Container.php'; /** * require XML_Unserializer class */ require_once 'XML/Unserializer.php'; /** * Storage driver for fetching data from an xml file * * Example file : * * <?xml version="1.0" encoding="iso-8859-1"?> * <translation2> * <languages> * <lang id='fr_FR'> * <name> English </name> * <meta> Custom meta data</meta> * <error_text> Non disponible en français </error_text> * <encoding> iso-8859-1 </encoding> * </lang> * <!-- some more <lang>...</lang> --> * </languages> * <pages> * <page key='pets'> * <string key='cat'> * <tr lang='fr_FR'> Chat </tr> * <!-- some more <tr>...</tr> --> * </string> * <!-- some more <string>...</string> --> * </page> * <!-- some more <page>...</page> --> * </pages> * </translation2> * * @package Translation2 * @version $Revision $ */ class Translation2_Container_xml extends Translation2_Container { // {{{ class vars /** * Unserialized XML data * @var object */ var $_data = null; /** * XML file name * @var string */ var $_filename; /** * query counter (unused in this driver. Here for compatibility * with Translation2_example.php) * @var integer * @access private */ var $_queries = 0; // }}} // {{{ init /** * Initialize the container * * @param string $filename Path to the XML file * @return boolean|PEAR_Error object if something went wrong */ function init($filename) { $this->_setDefaultOptions(); $this->_filename = $filename; $keyAttr = array ('lang' => 'id', 'page' => 'key', 'string' => 'key', 'tr' => 'lang'); $unserializer = &new XML_Unserializer (array('keyAttribute' => $keyAttr)); if (PEAR::isError($status = $unserializer->unserialize($filename, true))) { return $status; } // Unserialize data $this->_data = $unserializer->getUnserializedData(); // Handle default language settings. // // This allows, for example, to rapidly write the meta data as : // // <lang key="fr"/> // <lang key="en"/> $defaults = array('name' => '', 'meta' => '', 'error_text' => '', 'encoding' => 'iso-8859-1'); foreach ($this->_data['languages'] as $lang_id => $settings) { if ($settings == "") { $this->_data['languages'][$lang_id] = $defaults; } else { $this->_data['languages'][$lang_id] = array_merge($defaults,$this->_data['languages'][$lang_id]); } } // Convert encodings from xml (somehow heavy) return $this->_convertEncodings('from_xml'); } // }}} // {{{ _convertEncodings() /** * Convert strings to/from XML unique charset (UTF-8) * */ function _convertEncodings($direction) { if ($direction == 'from_xml') { $source_encoding = 'UTF-8'; } else { $target_encoding = 'UTF-8'; } foreach ($this->_data['pages'] as $page_id => $page_content) { foreach ($page_content as $str_id => $translations) { foreach ($translations as $lang => $str) { if ($direction == 'from_xml') { $target_encoding = strtoupper($this->_data['languages'][$lang]['encoding']); } else { $source_encoding = strtoupper($this->_data['languages'][$lang]['encoding']); } if ($target_encoding != $source_encoding) { if (($res = iconv ($source_encoding, $target_encoding, $str)) !== FALSE) { $this->_data['pages'][$page_id][$str_id][$lang] = $res; } else { return new PEAR_Error("Encoding conversion error " . "(source encoding : $source_encoding, ". "target encoding : $target_encoding, ". "processed string : \"$str\""); } } } } } return true; } // }}} // {{{ _setDefaultOptions() /** * Set some default options * * @access private * @return void */ function _setDefaultOptions() { } // }}} // {{{ fetchLangs() /** * Fetch the available langs */ function fetchLangs() { $res = array(); foreach ($this->_data['languages'] as $id => $spec) { $spec['id'] = $id; $res[$id] = $spec; } $this->langs = $res; } // }}} // {{{ getPage() /** * Returns an array of the strings in the selected page * * @param string $pageID * @param string $langID * @return array */ function getPage($pageID = null, $langID = null) { $langID = is_null($langID) ? $this->currentLang['id'] : $langID; $pageID = (is_null($pageID)) ? '#NULL' : $pageID; $pageID = (empty($pageID)) ? '#EMPTY' : $pageID; $result = array(); foreach ($this->_data['pages'][$pageID] as $str_id => $translations) { $result[$str_id] = isset($translations[$langID]) ? $translations[$langID] : null; } return $result; } // }}} // {{{ getOne() /** * Get a single item from the container * * @param string $stringID * @param string $pageID * @param string $langID * @return string */ function getOne($stringID, $pageID = null, $langID = null) { $langID = is_null($langID) ? $this->currentLang['id'] : $langID; $pageID = (is_null($pageID)) ? '#NULL' : $pageID; return isset($this->_data['pages'][$pageID][$stringID][$langID]) ? $this->_data['pages'][$pageID][$stringID][$langID] : null; } // }}} // {{{ getStringID() /** * Get the stringID for the given string * * @param string $stringID * @param string $pageID * @return string */ function getStringID($string, $pageID = null) { $pageID = (is_null($pageID)) ? '#NULL' : $pageID; foreach ($this->_data['pages'][$pageID] as $str_id => $translations) { if (array_search($string,$translations) !== false) { return $str_id; } } return ''; } // }}} } ?>