Author: dr Date: Mon Feb 4 20:56:17 2008 New Revision: 7285 Log: - Implemented issue #10912: Add translation entries. - Added support for the new location element in Linguist version 1.1 files.
Modified: trunk/Translation/ChangeLog trunk/Translation/src/backends/ts_backend.php trunk/Translation/src/structs/translation_data.php trunk/Translation/tests/files/translations/nl-nl.xml trunk/Translation/tests/translation_backend_ts_test.php trunk/Translation/tests/translation_manager_test.php Modified: trunk/Translation/ChangeLog ============================================================================== --- trunk/Translation/ChangeLog [iso-8859-1] (original) +++ trunk/Translation/ChangeLog [iso-8859-1] Mon Feb 4 20:56:17 2008 @@ -5,6 +5,8 @@ the original language, to the translated one without substituting parameters. This is to have translation support for the Template component. +- Implemented issue #10912: Add translation entries. +- Added support for the new location element in Linguist version 1.1 files. 1.1.6 - Wednesday 05 December 2007 Modified: trunk/Translation/src/backends/ts_backend.php ============================================================================== --- trunk/Translation/src/backends/ts_backend.php [iso-8859-1] (original) +++ trunk/Translation/src/backends/ts_backend.php [iso-8859-1] Mon Feb 4 20:56:17 2008 @@ -73,7 +73,7 @@ * @version //autogentag// * @mainclass */ -class ezcTranslationTsBackend implements ezcTranslationBackend, ezcTranslationContextRead +class ezcTranslationTsBackend implements ezcTranslationBackend, ezcTranslationContextRead, ezcTranslationContextWrite { /** * The last read context, as read by next() method. @@ -104,6 +104,20 @@ private $xmlParser = null; /** + * Contains the DOM tree for modifications while writing a new translation file + * + * @var DomDocument + */ + private $dom; + + /** + * Contains the locale used for writing a new translation file + * + * @var string + */ + private $writeLocale = null; + + /** * Container to hold the properties * * @var array(string=>mixed) @@ -190,7 +204,7 @@ } /** - * Creates an SimpleXML parser object for the locale $locale.. + * Creates an SimpleXML parser object for the locale $locale. * * You can set the class of the returned object through the $returnClass * parameter. That class should extend the SimpleXMLElement class. @@ -220,6 +234,39 @@ } /** + * Creates a DOM parser object for the locale $locale. + * + * This function checks if the <i>location</i> setting is made, if the file + * with the filename as returned by buildTranslationFileName() exists and + * creates a DOM parser object for this file. If the setting + * is not made, it throws an exception. IF the file does not exist, a new + * DomDocument is created. + * + * @param string $locale + * @return object The created parser. + */ + public function openTranslationFileForWriting( $locale ) + { + $filename = $this->buildTranslationFileName( $locale ); + if ( !file_exists( $filename ) ) + { + $dom = new DOMDocument( '1.0', 'UTF-8' ); + $dom->formatOutput = true; + $root = $dom->createElement( 'TS' ); + $dom->appendChild( $root ); + } + else + { + $dom = new DOMDocument( '1.0', 'UTF-8' ); + $dom->formatOutput = true; + $dom->load( $filename ); + $root = $dom->getElementsByTagName( 'TS' )->item( 0 ); + } + + return $dom; + } + + /** * Returns the data from the XML element $message as an * ezcTranslationData object. * @@ -246,7 +293,15 @@ $translation = strlen( $translation ) ? $translation : false; $comment = strlen( $comment ) ? $comment : false; - return new ezcTranslationData( $source, $translation, $comment, $status ); + $location = $message->location; + $file = $line = false; + if ( $location ) + { + $file = trim( (string) $location['filename'] ); + $line = trim( (string) $location['line'] ); + } + + return new ezcTranslationData( $source, $translation, $comment, $status, $file, $line ); } @@ -328,6 +383,127 @@ } /** + * Stores a context. + * + * This method stores the context that it received to the backend specified + * storage place. + * + * @throws ezcTranslationWriterNotInitializedException when the writer is + * not initialized with initWriter(). + * @param string $context The context's name + * @param array(ezcTranslationData) $data The context's translation map + * @return void + */ + public function storeContext( $context, array $data ) + { + if ( is_null( $this->dom ) ) + { + throw new ezcTranslationWriterNotInitializedException(); + } + foreach ( $data as $key => $cachedElement ) + { + if ( $cachedElement->status == ezcTranslationData::OBSOLETE ) + { + unset( $data[$key] ); + } + } + + $dom = $this->dom; + $root = $dom->getElementsByTagName( 'TS' )->item( 0 ); + + // find the context element + $xpath = new DOMXPath( $dom ); + $result = $xpath->query( '//context/name[text()="' . htmlspecialchars( $context ) . '"]' ); + + // If the context does not exist, we create a node for it; otherwise we just use it. + if ( !$result->length ) + { + $contextNode = $dom->createElement( 'context' ); + $nameNode = $dom->createElement( 'name', htmlspecialchars( $context ) ); + $contextNode->appendChild( $nameNode ); + $root->appendChild( $contextNode ); + } + else + { + $contextNode = $result->item( 0 )->parentNode; + } + + // for every entry, we add a new message + foreach ( $data as $info ) + { + // check if the string is already there, if so, remove it first + $xpath = new DOMXPath( $dom ); + $result = $xpath->query( '//message/source[text()="' . htmlspecialchars( $info->original ) . '"]', $contextNode ); + if ( $result->length ) + { + $node = $result->item( 0 )->parentNode; + $contextNode->removeChild( $node ); + } + + // create the new element + $message = $dom->createElement( 'message' ); + $source = $dom->createElement( 'source', htmlspecialchars( $info->original ) ); + $message->appendChild( $source ); + + $translation = $dom->createElement( 'translation', htmlspecialchars( $info->translation ) ); + switch ( $info->status ) + { + case ezcTranslationData::UNFINISHED: + $translation->setAttribute( 'type', 'unfinished' ); + break; + case ezcTranslationData::OBSOLETE: + $translation->setAttribute( 'type', 'obsolete' ); + break; + } + $message->appendChild( $translation ); + + if ( $info->comment ) + { + $comment = $dom->createElement( 'comment', htmlspecialchars( $info->comment ) ); + $message->appendChild( $comment ); + } + + if ( $info->filename && $info->line ) + { + $location = $dom->createElement( 'location' ); + $location->setAttribute( 'filename', $info->filename ); + $location->setAttribute( 'line', $info->line ); + $message->appendChild( $location ); + } + + $contextNode->appendChild( $message ); + } + } + + /** + * Initializes the writer to write to locale $locale. + * + * Opens the translation file. + * + * @throws ezcTranslationNotConfiguredException if the option <i>format</i> + * is not set before this method is called. + * + * @param string $locale + * @return void + */ + public function initWriter( $locale ) + { + $this->dom = $this->openTranslationFileForWriting( $locale ); + $this->writeLocale = $locale; + } + + /** + * Deinitializes the writer + * + * @return void + */ + public function deinitWriter() + { + $filename = $this->buildTranslationFileName( $this->writeLocale ); + $this->dom->save( $filename ); + } + + /** * Advanced to the next context. * * This method parses a little bit more of the XML file to be able to Modified: trunk/Translation/src/structs/translation_data.php ============================================================================== --- trunk/Translation/src/structs/translation_data.php [iso-8859-1] (original) +++ trunk/Translation/src/structs/translation_data.php [iso-8859-1] Mon Feb 4 20:56:17 2008 @@ -62,19 +62,46 @@ public $status; /** + * The filename the string was found in + * + * @var string + */ + public $filename; + + /** + * The line where the string is + * + * @var integer + */ + public $line; + + /** + * The column where the string is + * + * @var integer + */ + public $column; + + /** * Constructs an ezcTranslationData object. * * @param string $original * @param string $translation * @param string $comment * @param int $status + * @param string $filename + * @param int $line + * @param int $column */ - function __construct( $original, $translation, $comment, $status ) + function __construct( $original, $translation, $comment, $status, $filename = null, $line = null, $column = null ) { $this->original = $original; $this->translation = $translation; $this->comment = $comment; $this->status = $status; + $this->filename = $filename; + $this->line = $line; + $this->column = $column; } /** @@ -93,7 +120,7 @@ */ static public function __set_state( array $array ) { - return new ezcTranslationData( $array['original'], $array['translation'], $array['comment'], $array['status'] ); + return new ezcTranslationData( $array['original'], $array['translation'], $array['comment'], $array['status'], $array['filename'], $array['line'], $array['column'] ); } } ?> Modified: trunk/Translation/tests/files/translations/nl-nl.xml ============================================================================== --- trunk/Translation/tests/files/translations/nl-nl.xml [iso-8859-1] (original) +++ trunk/Translation/tests/files/translations/nl-nl.xml [iso-8859-1] Mon Feb 4 20:56:17 2008 @@ -4,6 +4,7 @@ <message> <source>Node ID: %node_id Visibility: %visibility</source> <translation>Knoop ID: %node_id Zichtbaar: %visibility</translation> + <location filename="test.ezt" line="85"/> </message> </context> <context> Modified: trunk/Translation/tests/translation_backend_ts_test.php ============================================================================== --- trunk/Translation/tests/translation_backend_ts_test.php [iso-8859-1] (original) +++ trunk/Translation/tests/translation_backend_ts_test.php [iso-8859-1] Mon Feb 4 20:56:17 2008 @@ -188,7 +188,7 @@ $backend->setOptions( array ( 'format' => '[LOCALE].xml' ) ); $context = $backend->getContext( 'nl-nl', 'contentstructuremenu/show_content_structure' ); - $expected = array( new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Knoop ID: %node_id Zichtbaar: %visibility', false, ezcTranslationData::TRANSLATED ) ); + $expected = array( new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Knoop ID: %node_id Zichtbaar: %visibility', false, ezcTranslationData::TRANSLATED, 'test.ezt', 85 ) ); self::assertEquals( $expected, $context ); } @@ -382,6 +382,133 @@ } } + public function testAddTranslation1() + { + $currentDir = dirname( __FILE__ ); + $backend = new ezcTranslationTsBackend( "{$currentDir}/files/translations" ); + $backend->setOptions( array ( 'format' => '[LOCALE].xml' ) ); + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + $context[] = new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ); + + $backend->setOptions( array ( 'format' => '[LOCALE].test.xml' ) ); + $backend->initWriter( 'nb-no' ); + $backend->storeContext( 'contentstructuremenu/show_content_structure', $context ); + $backend->deinitWriter(); + + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + unlink( "{$currentDir}/files/translations/nb-no.test.xml" ); + + $expected = array( + new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Node-ID: %node_id Synlig/skjult: %visibility', false, ezcTranslationData::TRANSLATED ), + new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ), + ); + self::assertEquals( $expected, $context ); + } + + public function testAddTranslation2() + { + $currentDir = dirname( __FILE__ ); + + // cp for test + copy( "{$currentDir}/files/translations/nb-no.xml", "{$currentDir}/files/translations/nb-no.test.xml" ); + + $backend = new ezcTranslationTsBackend( "{$currentDir}/files/translations" ); + $context = array(); + $context[] = new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ); + + $backend->setOptions( array ( 'format' => '[LOCALE].test.xml' ) ); + $backend->initWriter( 'nb-no' ); + $backend->storeContext( 'contentstructuremenu/show_content_structure', $context ); + $backend->deinitWriter(); + + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + unlink( "{$currentDir}/files/translations/nb-no.test.xml" ); + + $expected = array( + new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Node-ID: %node_id Synlig/skjult: %visibility', false, ezcTranslationData::TRANSLATED ), + new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ), + ); + self::assertEquals( $expected, $context ); + } + + public function testAddTranslation3() + { + $currentDir = dirname( __FILE__ ); + + // cp for test + copy( "{$currentDir}/files/translations/nb-no.xml", "{$currentDir}/files/translations/nb-no.test.xml" ); + + $backend = new ezcTranslationTsBackend( "{$currentDir}/files/translations" ); + $context = array(); + $context[] = new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ); + + $backend->setOptions( array ( 'format' => '[LOCALE].test.xml' ) ); + $backend->initWriter( 'nb-no' ); + $backend->storeContext( 'number_two', $context ); + $backend->deinitWriter(); + + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + $expected = array( + new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Node-ID: %node_id Synlig/skjult: %visibility', false, ezcTranslationData::TRANSLATED ), + ); + + $context = $backend->getContext( 'nb-no', 'number_two' ); + $expected = array( + new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ), + ); + unlink( "{$currentDir}/files/translations/nb-no.test.xml" ); + + self::assertEquals( $expected, $context ); + } + + public function testChangeTranslation1() + { + $currentDir = dirname( __FILE__ ); + $backend = new ezcTranslationTsBackend( "{$currentDir}/files/translations" ); + $backend->setOptions( array ( 'format' => '[LOCALE].xml' ) ); + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + $context[] = new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ); + + $backend->setOptions( array ( 'format' => '[LOCALE].test.xml' ) ); + $backend->initWriter( 'nb-no' ); + $backend->storeContext( 'contentstructuremenu/show_content_structure', $context ); + $backend->deinitWriter(); + + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + + unlink( "{$currentDir}/files/translations/nb-no.test.xml" ); + + $expected = array( + new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ), + ); + self::assertEquals( $expected, $context ); + } + + public function testChangeAndAddTranslation1() + { + $currentDir = dirname( __FILE__ ); + $backend = new ezcTranslationTsBackend( "{$currentDir}/files/translations" ); + $backend->setOptions( array ( 'format' => '[LOCALE].xml' ) ); + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + $context[] = new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ); + $context[] = new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 6 ); + + $backend->setOptions( array ( 'format' => '[LOCALE].test.xml' ) ); + $backend->initWriter( 'nb-no' ); + $backend->storeContext( 'contentstructuremenu/show_content_structure', $context ); + $backend->deinitWriter(); + + $context = $backend->getContext( 'nb-no', 'contentstructuremenu/show_content_structure' ); + + unlink( "{$currentDir}/files/translations/nb-no.test.xml" ); + + $expected = array( + new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 5 ), + new ezcTranslationData( 'Test string to be added', 'Test string die wordt toegevoegd', 'comment', ezcTranslationData::TRANSLATED, 'test.ezt', 6 ), + ); + self::assertEquals( $expected, $context ); + } + public static function suite() { return new PHPUnit_Framework_TestSuite( "ezcTranslationTsBackendTest" ); Modified: trunk/Translation/tests/translation_manager_test.php ============================================================================== --- trunk/Translation/tests/translation_manager_test.php [iso-8859-1] (original) +++ trunk/Translation/tests/translation_manager_test.php [iso-8859-1] Mon Feb 4 20:56:17 2008 @@ -23,7 +23,7 @@ $trm = new ezcTranslationManager( $backend ); $context = $trm->getContext( 'nl-nl', 'contentstructuremenu/show_content_structure' ); - $expected = new ezcTranslation( array( new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Knoop ID: %node_id Zichtbaar: %visibility', false, ezcTranslationData::TRANSLATED ) ) ); + $expected = new ezcTranslation( array( new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Knoop ID: %node_id Zichtbaar: %visibility', false, ezcTranslationData::TRANSLATED, 'test.ezt', 85 ) ) ); self::assertEquals( $expected, $context ); } @@ -34,7 +34,7 @@ $backend->setOptions( array ( 'format' => '[LOCALE].xml' ) ); $trm = new ezcTranslationManager( $backend ); - $expected = new ezcTranslation( array( new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Knoop ID: %node_id Zichtbaar: %visibility', false, ezcTranslationData::TRANSLATED ) ) ); + $expected = new ezcTranslation( array( new ezcTranslationData( 'Node ID: %node_id Visibility: %visibility', 'Knoop ID: %node_id Zichtbaar: %visibility', false, ezcTranslationData::TRANSLATED, 'test.ezt', 85 ) ) ); $context1 = $trm->getContext( 'nl-nl', 'contentstructuremenu/show_content_structure' ); self::assertEquals( $expected, $context1 ); -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components