Hi,

I started yesterday with a ezlupdate.php script. I attached what I came up with until today. Replace "require_once 'init.php';" with your ezcComponents Setup.

The script reads all templates in a directory and extracts the language strings. I used the existing functionality of the translation component for manipulating translation files. Therefore it's not possible to delete strings. Maybe there should be a new status "DELETED" that makes storeContext() delete the string from the file.
I mark obsolete strings but only if the filename properties match.
This is not perfect as the filename is an absolute path at the moment and not relative to the template dir. I'd recommend to change this.

For normal strings this works fine. But if you use HTML or double quotes, you run into the following problems:

a) xpath for finding messages in 'ts_backend.php', line 436

The xpath query for finding the messages is not working properly if there are the same strings in different contexts. Fix: don't use '//' in the xpath query which forces the search to start at the root element and not within the given context $result = $xpath->query( 'message/source[text()="' . htmlspecialchars( $info->original ) . '"]', $contextNode );

b) the same xpath doesn't work if there is HTML in the string

Within the DOM tree all reserved characters seem to be decoded.
Result: The xpath search for the encoded string fails. Therefore there shouldn't be a htmlspecialchars() call for building the query.

$result = $xpath->query( 'message/source[text()="' . $info->original . '"]', $contextNode );

HTML is working then.

c) double quotes in translation strings

This doesn't work: {tr "This is the \"root\" element!"}

First problem: String extractor doesn't strip slashes.
stripslashes() needs to be added to visitTranslationTstNode in ezcTemplateTranslationStringExtracter.

Second problem: All quotes are decoded in the xpath query call (see b)) and therefore it's impossible to have both quote types in one string. All xpath queries containing double quotes fail.

The only solution I found is to use concat(). The xpath needs to be changed again: $result = $xpath->query( 'message/source[text()=concat("'.str_replace( '"', '",\'"\',"', $info->original ).'","")]', $contextNode );

The concat() function needs at least two parameters. In order to meet this requirement there is an empty string at the end of every concat() call.

I hope this is what you were looking for.

Regards,
Andi

Derick Rethans schrieb:
On Wed, 2 Apr 2008, Andreas Schamberger wrote:

I've got a question regarding the new TemplateTranslationTiein:
For ezPublish templates there is the ezlupdate program. What are the
plans for ezcTemplate? Update of ezlupdate or plain PHP solution?

There is some code that extracts the translations from templates already, but it has not been converted into a full blown script yet. For the eZ Publish version that will use the new template and translation components there will most likely be a PHP-only solution as replacement for ezlupdate.

What's the schedule for this missing part of the TemplateTranslationTiein?

We hope to get it done before the release, but there are some slightly more importent things to be done first. If you are interested in helping out a bit, that would be most welcome. I attached a script that shows how to extract strings from a template.

Another thing I would recommend to add to the TemplateTranslationTiein
is a developer mode for the TemplateTranslationTieIn. I'd like to see a
development property in ezcTemplateTranslationConfiguration that makes
the ezcTemplateTranslationProvider catch the Exceptions for missing
translations/translation files and just return the string from the
template. This solution makes it possible to develop with a template
that doesn't have a valid translation file yet.

Hmm, I see your point here; however, I don't quite think that this is an elegant solution. I don't always want to catch the exception, and rethrow it when the configure option is not set, nor having two bits of code here for each case. Could you file a feature request for this please?

regards,

setOptions( array ( 'format' => '[LOCALE].xml' ) ); // create ts file if it does not exist yet createMissingTsFile( $backend->buildTranslationFileName( $locale ) ); $backend->initWriter( $locale ); foreach ( $it as $item ) { $pathname = realpath( $item->getPathname() ); echo $pathname. "\n"; $contexts = getTranslationsFromTemplate( $item->getPathname() ); foreach ( $contexts AS $contextName => $translations ) { try { // get the original context $context = $backend->getContext( $locale, $contextName ); } catch ( ezcTranslationContextNotAvailableException $e ) { // create empty context $context = array(); } // store all existing translations in associative array $translationMapOriginal = array(); foreach ( $context as $translationElement ) { $translationMapOriginal[$translationElement->original] = $translationElement; } $translationMapNew = array(); foreach ( $translations as $translationElement ) { $translationMapNew[$translationElement->original] = $translationElement; } // create empty context $context = array(); // insert new translations foreach ( $translations AS $translationElement ) { // insert new strings if ( !isset( $translationMapOriginal[$translationElement->original] ) ) { $context[] = $translationElement; } } // update translations foreach ( $translationMapOriginal AS $translationElement ) { // update data if ( isset( $translationMapNew[$translationElement->original] ) ) { $new = $translationMapNew[$translationElement->original]; $translationElement->comment = $new->comment; $translationElement->filename = $new->filename; $translationElement->line = $new->line; $translationElement->column = $new->column; $context[] = $translationElement; } // flag obsolete strings (only if filename is equal, because the context // could be used in different files) elseif ( $translationElement->filename == $pathname ) { $translationElement->status = ezcTranslationData::OBSOLETE; $context[] = $translationElement; } } //var_dump( $context ); $backend->storeContext( $contextName, $context ); } } // write translation data to file $backend->deinitWriter(); // format the xml to be readable $file = str_replace( '\\', '/', $backend->buildTranslationFileName( $locale ) ); $xmllintPath = "C:/Program Files/gnuwin32/bin/"; $cmd = '"'.$xmllintPath.'xmllint" --format ' . $file; file_put_contents( $file, shell_exec( $cmd ) ); /** * Create missing ts file * * @param string $filename */ function createMissingTsFile( $filename ) { if ( !is_file( $filename ) ) { $content = ''; file_put_contents( $filename, $content ); echo 'New Ts file created: ' . $file . "\n"; } } /** * get translation array with translation data for each context from tpl * * @param string $filename * @return @var array(string=>array(ezcTranslationData)) */ function getTranslationsFromTemplate( $filename ) { $source = new ezcTemplateSourceCode( $filename, $filename ); $source->load(); $parser = new ezcTemplateParser( $source, new ezcTemplate() ); $tst = $parser->parseIntoNodeTree(); $et = new ezcTemplateTranslationStringExtracter( $parser ); $eted = $tst->accept( $et ); return $et->strings; } /** * RecursivFilterIterator that ignores '.svn' directories * */ class IgnoreSvnDirIterator extends RecursiveFilterIterator { public function accept() { if ( $this->current()->getFilename() == '.svn' ) { return false; } return true; } }
-- 
Components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/components

Reply via email to