2008-05-30 11:40:08 +00:00
< ? php
/**
2009-09-15 03:43:59 +00:00
* Language string extractor
2008-05-30 11:40:08 +00:00
*
2010-10-03 16:38:58 +00:00
* PHP 5
2008-05-30 11:40:08 +00:00
*
2009-11-06 06:46:59 +00:00
* CakePHP ( tm ) : Rapid Development Framework ( http :// cakephp . org )
2011-05-29 21:31:39 +00:00
* Copyright 2005 - 2011 , Cake Software Foundation , Inc . ( http :// cakefoundation . org )
2008-05-30 11:40:08 +00:00
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
2011-05-29 21:31:39 +00:00
* @ copyright Copyright 2005 - 2011 , Cake Software Foundation , Inc . ( http :// cakefoundation . org )
2009-11-06 06:00:11 +00:00
* @ link http :// cakephp . org CakePHP ( tm ) Project
2008-10-30 17:30:26 +00:00
* @ since CakePHP ( tm ) v 1.2 . 0.5012
2009-11-06 06:51:51 +00:00
* @ license MIT License ( http :// www . opensource . org / licenses / mit - license . php )
2008-05-30 11:40:08 +00:00
*/
2010-12-08 00:20:56 +00:00
App :: uses ( 'File' , 'Utility' );
2011-04-17 16:03:43 +00:00
App :: uses ( 'Folder' , 'Utility' );
2008-05-30 11:40:08 +00:00
/**
* Language string extractor
*
2011-07-26 06:16:14 +00:00
* @ package Cake . Console . Command . Task
2008-05-30 11:40:08 +00:00
*/
2009-09-15 03:43:59 +00:00
class ExtractTask extends Shell {
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2009-09-15 03:43:59 +00:00
* Paths to use when looking for strings
2008-05-30 11:40:08 +00:00
*
* @ var string
*/
2011-04-25 20:08:12 +00:00
protected $_paths = array ();
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Files from where to extract
*
* @ var array
*/
2011-04-25 20:08:12 +00:00
protected $_files = array ();
2009-07-24 19:18:37 +00:00
2009-10-29 23:26:59 +00:00
/**
* Merge all domains string into the default . pot file
*
* @ var boolean
*/
2011-04-25 20:08:12 +00:00
protected $_merge = false ;
2009-10-29 23:26:59 +00:00
2008-05-30 11:40:08 +00:00
/**
2009-09-15 03:43:59 +00:00
* Current file being processed
2008-05-30 11:40:08 +00:00
*
2009-09-15 03:43:59 +00:00
* @ var string
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected $_file = null ;
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2009-09-15 03:43:59 +00:00
* Contains all content waiting to be write
2008-05-30 11:40:08 +00:00
*
* @ var string
*/
2011-04-25 20:08:12 +00:00
protected $_storage = array ();
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Extracted tokens
*
* @ var array
*/
2011-04-25 20:08:12 +00:00
protected $_tokens = array ();
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Extracted strings
*
* @ var array
*/
2011-04-25 20:08:12 +00:00
protected $_strings = array ();
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Destination path
*
* @ var string
*/
2011-04-25 20:08:12 +00:00
protected $_output = null ;
2009-07-24 19:18:37 +00:00
2010-10-29 04:40:04 +00:00
/**
* An array of directories to exclude .
*
* @ var array
*/
protected $_exclude = array ();
2011-05-28 02:48:56 +00:00
/**
* Holds whether this call should extract model validation messages
*
* @ var boolean
*/
protected $_extractValidation = true ;
2011-06-20 05:06:31 +00:00
/**
* Holds the validation string domain to use for validation messages when extracting
*
* @ var boolean
*/
protected $_validationDomain = 'default' ;
2008-05-30 11:40:08 +00:00
/**
* Execution method always used for tasks
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 17:39:13 +00:00
public function execute () {
2010-10-29 04:40:04 +00:00
if ( ! empty ( $this -> params [ 'exclude' ])) {
$this -> _exclude = explode ( ',' , $this -> params [ 'exclude' ]);
}
2008-05-30 11:40:08 +00:00
if ( isset ( $this -> params [ 'files' ]) && ! is_array ( $this -> params [ 'files' ])) {
2011-04-25 20:08:12 +00:00
$this -> _files = explode ( ',' , $this -> params [ 'files' ]);
2008-05-30 11:40:08 +00:00
}
2009-09-15 03:43:59 +00:00
if ( isset ( $this -> params [ 'paths' ])) {
2011-04-25 20:08:12 +00:00
$this -> _paths = explode ( ',' , $this -> params [ 'paths' ]);
2011-07-07 06:27:55 +00:00
} else if ( isset ( $this -> params [ 'plugin' ])) {
$plugin = Inflector :: camelize ( $this -> params [ 'plugin' ]);
if ( ! CakePlugin :: loaded ( $plugin )) {
CakePlugin :: load ( $plugin );
}
$this -> _paths = array ( CakePlugin :: path ( $plugin ));
2011-07-07 06:40:27 +00:00
$this -> params [ 'plugin' ] = $plugin ;
2008-05-30 11:40:08 +00:00
} else {
2011-05-27 20:19:15 +00:00
$defaultPath = APP ;
2011-04-17 16:17:25 +00:00
$message = __d ( 'cake_console' , " What is the path you would like to extract? \n [Q]uit [D]one " );
2009-09-15 03:43:59 +00:00
while ( true ) {
$response = $this -> in ( $message , null , $defaultPath );
2008-05-30 11:40:08 +00:00
if ( strtoupper ( $response ) === 'Q' ) {
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , 'Extract Aborted' ));
2008-06-04 19:04:58 +00:00
$this -> _stop ();
2009-09-15 03:43:59 +00:00
} elseif ( strtoupper ( $response ) === 'D' ) {
2009-09-26 21:08:37 +00:00
$this -> out ();
2009-09-15 03:43:59 +00:00
break ;
} elseif ( is_dir ( $response )) {
2011-04-25 20:08:12 +00:00
$this -> _paths [] = $response ;
2009-09-15 03:43:59 +00:00
$defaultPath = 'D' ;
} else {
2011-03-19 17:32:35 +00:00
$this -> err ( __d ( 'cake_console' , 'The directory path you supplied was not found. Please try again.' ));
2008-05-30 11:40:08 +00:00
}
2009-09-26 21:08:37 +00:00
$this -> out ();
2008-05-30 11:40:08 +00:00
}
}
2011-05-27 20:19:15 +00:00
if ( ! empty ( $this -> params [ 'exclude-plugins' ]) && $this -> _isExtractingApp ()) {
$this -> _exclude = array_merge ( $this -> _exclude , App :: path ( 'plugins' ));
}
2011-07-07 06:40:27 +00:00
if ( ! empty ( $this -> params [ 'ignore-model-validation' ]) || ( ! $this -> _isExtractingApp () && empty ( $plugin ))) {
2011-05-28 02:48:56 +00:00
$this -> _extractValidation = false ;
}
2011-06-20 05:06:31 +00:00
if ( ! empty ( $this -> params [ 'validation-domain' ])) {
$this -> _validationDomain = $this -> params [ 'validation-domain' ];
}
2011-05-28 02:48:56 +00:00
2008-05-30 11:40:08 +00:00
if ( isset ( $this -> params [ 'output' ])) {
2011-04-25 20:08:12 +00:00
$this -> _output = $this -> params [ 'output' ];
2011-07-07 06:27:55 +00:00
} else if ( isset ( $this -> params [ 'plugin' ])) {
$this -> _output = $this -> _paths [ 0 ] . DS . 'Locale' ;
2008-05-30 11:40:08 +00:00
} else {
2011-07-07 06:27:55 +00:00
$message = __d ( 'cake_console' , " What is the path you would like to output? \n [Q]uit " , $this -> _paths [ 0 ] . DS . 'Locale' );
2009-09-15 03:43:59 +00:00
while ( true ) {
2011-07-07 06:27:55 +00:00
$response = $this -> in ( $message , null , $this -> _paths [ 0 ] . DS . 'Locale' );
2008-05-30 11:40:08 +00:00
if ( strtoupper ( $response ) === 'Q' ) {
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , 'Extract Aborted' ));
2008-06-04 19:04:58 +00:00
$this -> _stop ();
2009-09-15 03:43:59 +00:00
} elseif ( is_dir ( $response )) {
2011-04-25 20:08:12 +00:00
$this -> _output = $response . DS ;
2009-09-15 03:43:59 +00:00
break ;
} else {
2011-03-19 17:32:35 +00:00
$this -> err ( __d ( 'cake_console' , 'The directory path you supplied was not found. Please try again.' ));
2008-05-30 11:40:08 +00:00
}
2009-09-26 21:08:37 +00:00
$this -> out ();
2008-05-30 11:40:08 +00:00
}
}
2009-10-29 23:26:59 +00:00
if ( isset ( $this -> params [ 'merge' ])) {
2011-04-25 20:08:12 +00:00
$this -> _merge = ! ( strtolower ( $this -> params [ 'merge' ]) === 'no' );
2009-10-29 23:26:59 +00:00
} else {
$this -> out ();
2011-03-19 17:32:35 +00:00
$response = $this -> in ( __d ( 'cake_console' , 'Would you like to merge all domains strings into the default.pot file?' ), array ( 'y' , 'n' ), 'n' );
2011-04-25 20:08:12 +00:00
$this -> _merge = strtolower ( $response ) === 'y' ;
2009-10-29 23:26:59 +00:00
}
2011-04-25 20:08:12 +00:00
if ( empty ( $this -> _files )) {
$this -> _searchFiles ();
2008-05-30 11:40:08 +00:00
}
2011-04-25 20:08:12 +00:00
$this -> _extract ();
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Extract text
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _extract () {
2009-09-26 21:08:37 +00:00
$this -> out ();
$this -> out ();
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , 'Extracting...' ));
2008-05-30 11:40:08 +00:00
$this -> hr ();
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , 'Paths:' ));
2011-04-25 20:08:12 +00:00
foreach ( $this -> _paths as $path ) {
2009-09-15 03:43:59 +00:00
$this -> out ( ' ' . $path );
}
2011-04-25 20:08:12 +00:00
$this -> out ( __d ( 'cake_console' , 'Output Directory: ' ) . $this -> _output );
2008-05-30 11:40:08 +00:00
$this -> hr ();
2011-04-25 20:08:12 +00:00
$this -> _extractTokens ();
2011-05-28 02:48:56 +00:00
$this -> _extractValidationMessages ();
2011-04-25 20:08:12 +00:00
$this -> _buildFiles ();
$this -> _writeFiles ();
$this -> _paths = $this -> _files = $this -> _storage = array ();
$this -> _strings = $this -> _tokens = array ();
2011-05-28 02:48:56 +00:00
$this -> _extractValidation = true ;
2010-02-12 13:20:43 +00:00
$this -> out ();
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , 'Done.' ));
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2010-10-10 05:56:23 +00:00
/**
* Get & configure the option parser
*
* @ return void
*/
public function getOptionParser () {
$parser = parent :: getOptionParser ();
2011-03-19 17:32:35 +00:00
return $parser -> description ( __d ( 'cake_console' , 'CakePHP Language String Extraction:' ))
-> addOption ( 'app' , array ( 'help' => __d ( 'cake_console' , 'Directory where your application is located.' )))
2011-04-25 17:39:13 +00:00
-> addOption ( 'paths' , array ( 'help' => __d ( 'cake_console' , 'Comma separated list of paths.' )))
2010-10-24 19:27:44 +00:00
-> addOption ( 'merge' , array (
2011-03-19 17:32:35 +00:00
'help' => __d ( 'cake_console' , 'Merge all domain strings into the default.po file.' ),
2010-10-24 19:27:44 +00:00
'choices' => array ( 'yes' , 'no' )
))
2011-03-19 17:32:35 +00:00
-> addOption ( 'output' , array ( 'help' => __d ( 'cake_console' , 'Full path to output directory.' )))
2011-04-17 16:08:10 +00:00
-> addOption ( 'files' , array ( 'help' => __d ( 'cake_console' , 'Comma separated list of files.' )))
2011-05-27 20:19:15 +00:00
-> addOption ( 'exclude-plugins' , array (
'boolean' => true ,
'default' => true ,
2011-07-07 06:27:55 +00:00
'help' => __d ( 'cake_console' , 'Ignores all files in plugins if this command is run inside from the same app directory.' )
))
-> addOption ( 'plugin' , array (
'help' => __d ( 'cake_console' , 'Extracts tokens only from the plugin specified and puts the result in the plugin\'s Locale directory.' )
2011-05-27 20:19:15 +00:00
))
-> addOption ( 'ignore-model-validation' , array (
'boolean' => true ,
'default' => false ,
2011-07-07 06:27:55 +00:00
'help' => __d ( 'cake_console' , 'Ignores validation messages in the $validate property. If this flag is not set and the command is run from the same app directory, all messages in model validation rules will be extracted as tokens.' )
2011-05-27 20:19:15 +00:00
))
-> addOption ( 'validation-domain' , array (
2011-07-07 06:27:55 +00:00
'help' => __d ( 'cake_console' , 'If set to a value, the localization domain to be used for model validation messages.' )
2011-05-27 20:19:15 +00:00
))
2010-10-29 04:40:04 +00:00
-> addOption ( 'exclude' , array (
2011-03-19 17:32:35 +00:00
'help' => __d ( 'cake_console' , 'Comma separated list of directories to exclude. Any path containing a path segment with the provided values will be skipped. E.g. test,vendors' )
2010-10-29 04:40:04 +00:00
));
2010-10-10 05:56:23 +00:00
}
2008-05-30 11:40:08 +00:00
/**
* Extract tokens out of all files to be processed
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _extractTokens () {
foreach ( $this -> _files as $file ) {
$this -> _file = $file ;
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , 'Processing %s...' , $file ));
2008-05-30 11:40:08 +00:00
$code = file_get_contents ( $file );
$allTokens = token_get_all ( $code );
2011-04-25 20:08:12 +00:00
$this -> _tokens = array ();
2008-05-30 11:40:08 +00:00
foreach ( $allTokens as $token ) {
2011-04-25 17:39:13 +00:00
if ( ! is_array ( $token ) || ( $token [ 0 ] != T_WHITESPACE && $token [ 0 ] != T_INLINE_HTML )) {
2011-04-25 20:08:12 +00:00
$this -> _tokens [] = $token ;
2008-05-30 11:40:08 +00:00
}
}
unset ( $allTokens );
2011-04-25 20:08:12 +00:00
$this -> _parse ( '__' , array ( 'singular' ));
$this -> _parse ( '__n' , array ( 'singular' , 'plural' ));
$this -> _parse ( '__d' , array ( 'domain' , 'singular' ));
$this -> _parse ( '__c' , array ( 'singular' ));
$this -> _parse ( '__dc' , array ( 'domain' , 'singular' ));
$this -> _parse ( '__dn' , array ( 'domain' , 'singular' , 'plural' ));
$this -> _parse ( '__dcn' , array ( 'domain' , 'singular' , 'plural' ));
2008-05-30 11:40:08 +00:00
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2009-08-06 21:14:25 +00:00
* Parse tokens
2008-05-30 11:40:08 +00:00
*
* @ param string $functionName Function name that indicates translatable string ( e . g : '__' )
2009-08-06 21:14:25 +00:00
* @ param array $map Array containing what variables it will find ( e . g : domain , singular , plural )
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _parse ( $functionName , $map ) {
2008-05-30 11:40:08 +00:00
$count = 0 ;
2011-04-25 20:08:12 +00:00
$tokenCount = count ( $this -> _tokens );
2008-05-30 11:40:08 +00:00
2010-02-12 13:52:58 +00:00
while (( $tokenCount - $count ) > 1 ) {
2011-04-25 20:08:12 +00:00
list ( $countToken , $firstParenthesis ) = array ( $this -> _tokens [ $count ], $this -> _tokens [ $count + 1 ]);
2008-05-30 11:40:08 +00:00
if ( ! is_array ( $countToken )) {
$count ++ ;
continue ;
}
list ( $type , $string , $line ) = $countToken ;
if (( $type == T_STRING ) && ( $string == $functionName ) && ( $firstParenthesis == '(' )) {
$position = $count ;
$depth = 0 ;
while ( $depth == 0 ) {
2011-04-25 20:08:12 +00:00
if ( $this -> _tokens [ $position ] == '(' ) {
2008-05-30 11:40:08 +00:00
$depth ++ ;
2011-04-25 20:08:12 +00:00
} elseif ( $this -> _tokens [ $position ] == ')' ) {
2008-05-30 11:40:08 +00:00
$depth -- ;
}
$position ++ ;
}
2009-08-06 21:14:25 +00:00
$mapCount = count ( $map );
2011-04-25 20:08:12 +00:00
$strings = $this -> _getStrings ( $position , $mapCount );
2008-05-30 11:40:08 +00:00
2009-08-06 21:14:25 +00:00
if ( $mapCount == count ( $strings )) {
extract ( array_combine ( $map , $strings ));
2011-04-25 17:22:14 +00:00
$domain = isset ( $domain ) ? $domain : 'default' ;
$string = isset ( $plural ) ? $singular . " \0 " . $plural : $singular ;
2011-04-25 20:08:12 +00:00
$this -> _strings [ $domain ][ $string ][ $this -> _file ][] = $line ;
2008-05-30 11:40:08 +00:00
} else {
2011-04-25 20:08:12 +00:00
$this -> _markerError ( $this -> _file , $line , $functionName , $count );
2008-05-30 11:40:08 +00:00
}
}
$count ++ ;
}
}
2009-07-24 19:18:37 +00:00
2011-05-28 02:48:56 +00:00
/**
* Looks for models in the application and extracts the validation messages
* to be added to the translation map
*
* @ return void
*/
protected function _extractValidationMessages () {
if ( ! $this -> _extractValidation ) {
return ;
}
App :: uses ( 'AppModel' , 'Model' );
2011-07-07 06:40:27 +00:00
$plugin = null ;
if ( ! empty ( $this -> params [ 'plugin' ])) {
App :: uses ( $this -> params [ 'plugin' ] . 'AppModel' , $this -> params [ 'plugin' ] . '.Model' );
$plugin = $this -> params [ 'plugin' ] . '.' ;
}
$models = App :: objects ( $plugin . 'Model' , null , false );
2011-05-28 02:48:56 +00:00
foreach ( $models as $model ) {
2011-07-07 06:40:27 +00:00
App :: uses ( $model , $plugin . 'Model' );
2011-05-28 02:48:56 +00:00
$reflection = new ReflectionClass ( $model );
$properties = $reflection -> getDefaultProperties ();
$validate = $properties [ 'validate' ];
if ( empty ( $validate )) {
continue ;
}
2011-06-20 05:06:31 +00:00
2011-05-28 02:48:56 +00:00
$file = $reflection -> getFileName ();
2011-06-20 05:06:31 +00:00
$domain = $this -> _validationDomain ;
if ( ! empty ( $properties [ 'validationDomain' ])) {
$domain = $properties [ 'validationDomain' ];
}
2011-05-28 02:48:56 +00:00
foreach ( $validate as $field => $rules ) {
$this -> _processValidationRules ( $field , $rules , $file , $domain );
}
}
}
/**
* Process a validation rule for a field and looks for a message to be added
* to the translation map
*
* @ param string $field the name of the field that is being processed
* @ param array $rules the set of validation rules for the field
* @ param string $file the file name where this validation rule was found
* @ param string domain default domain to bind the validations to
* @ return void
*/
protected function _processValidationRules ( $field , $rules , $file , $domain ) {
if ( is_array ( $rules )) {
$dims = Set :: countDim ( $rules );
if ( $dims == 1 || ( $dims == 2 && isset ( $rules [ 'message' ]))) {
$rules = array ( $rules );
}
foreach ( $rules as $rule => $validateProp ) {
if ( isset ( $validateProp [ 'message' ])) {
$this -> _strings [ $domain ][ $validateProp [ 'message' ]][ $file ][] = 'validation for field ' . $field ;
}
}
}
}
2008-05-30 11:40:08 +00:00
/**
* Build the translate template file contents out of obtained strings
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _buildFiles () {
foreach ( $this -> _strings as $domain => $strings ) {
2009-09-15 03:43:59 +00:00
foreach ( $strings as $string => $files ) {
2010-02-18 00:41:15 +00:00
$occurrences = array ();
2009-09-15 03:43:59 +00:00
foreach ( $files as $file => $lines ) {
2010-02-18 00:41:15 +00:00
$occurrences [] = $file . ':' . implode ( ';' , $lines );
2008-05-30 11:40:08 +00:00
}
2010-02-18 00:41:15 +00:00
$occurrences = implode ( " \n #: " , $occurrences );
2011-04-25 20:08:12 +00:00
$header = '#: ' . str_replace ( $this -> _paths , '' , $occurrences ) . " \n " ;
2009-09-15 03:43:59 +00:00
if ( strpos ( $string , " \0 " ) === false ) {
$sentence = " msgid \" { $string } \" \n " ;
$sentence .= " msgstr \" \" \n \n " ;
2008-05-30 11:40:08 +00:00
} else {
2009-09-15 03:43:59 +00:00
list ( $singular , $plural ) = explode ( " \0 " , $string );
$sentence = " msgid \" { $singular } \" \n " ;
$sentence .= " msgid_plural \" { $plural } \" \n " ;
$sentence .= " msgstr[0] \" \" \n " ;
$sentence .= " msgstr[1] \" \" \n \n " ;
2008-05-30 11:40:08 +00:00
}
2011-04-25 20:08:12 +00:00
$this -> _store ( $domain , $header , $sentence );
if ( $domain != 'default' && $this -> _merge ) {
$this -> _store ( 'default' , $header , $sentence );
2008-05-30 11:40:08 +00:00
}
}
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Prepare a file to be stored
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _store ( $domain , $header , $sentence ) {
if ( ! isset ( $this -> _storage [ $domain ])) {
$this -> _storage [ $domain ] = array ();
2009-09-15 03:43:59 +00:00
}
2011-04-25 20:08:12 +00:00
if ( ! isset ( $this -> _storage [ $domain ][ $sentence ])) {
$this -> _storage [ $domain ][ $sentence ] = $header ;
2008-05-30 11:40:08 +00:00
} else {
2011-04-25 20:08:12 +00:00
$this -> _storage [ $domain ][ $sentence ] .= $header ;
2008-05-30 11:40:08 +00:00
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Write the files that need to be stored
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _writeFiles () {
2010-02-18 00:41:15 +00:00
$overwriteAll = false ;
2011-04-25 20:08:12 +00:00
foreach ( $this -> _storage as $domain => $sentences ) {
$output = $this -> _writeHeader ();
2009-09-15 03:43:59 +00:00
foreach ( $sentences as $sentence => $header ) {
$output .= $header . $sentence ;
2008-05-30 11:40:08 +00:00
}
2009-09-15 03:43:59 +00:00
$filename = $domain . '.pot' ;
2011-04-25 20:08:12 +00:00
$File = new File ( $this -> _output . $filename );
2010-02-18 00:41:15 +00:00
$response = '' ;
while ( $overwriteAll === false && $File -> exists () && strtoupper ( $response ) !== 'Y' ) {
$this -> out ();
2011-03-19 17:32:35 +00:00
$response = $this -> in ( __d ( 'cake_console' , 'Error: %s already exists in this location. Overwrite? [Y]es, [N]o, [A]ll' , $filename ), array ( 'y' , 'n' , 'a' ), 'y' );
2010-02-18 00:41:15 +00:00
if ( strtoupper ( $response ) === 'N' ) {
$response = '' ;
while ( $response == '' ) {
2011-04-17 16:17:25 +00:00
$response = $this -> in ( __d ( 'cake_console' , " What would you like to name this file? " ), null , 'new_' . $filename );
2011-04-25 20:08:12 +00:00
$File = new File ( $this -> _output . $response );
2010-02-18 00:41:15 +00:00
$filename = $response ;
2008-05-30 11:40:08 +00:00
}
2010-02-18 00:41:15 +00:00
} elseif ( strtoupper ( $response ) === 'A' ) {
$overwriteAll = true ;
2008-05-30 11:40:08 +00:00
}
}
2009-09-15 03:43:59 +00:00
$File -> write ( $output );
$File -> close ();
2008-05-30 11:40:08 +00:00
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Build the translation template header
*
* @ return string Translation template header
*/
2011-04-25 20:08:12 +00:00
protected function _writeHeader () {
2008-05-30 11:40:08 +00:00
$output = " # LANGUAGE translation of CakePHP Application \n " ;
$output .= " # Copyright YEAR NAME <EMAIL@ADDRESS> \n " ;
$output .= " # \n " ;
$output .= " #, fuzzy \n " ;
$output .= " msgid \" \" \n " ;
$output .= " msgstr \" \" \n " ;
$output .= " \" Project-Id-Version: PROJECT VERSION \\ n \" \n " ;
$output .= " \" POT-Creation-Date: " . date ( " Y-m-d H:iO " ) . " \\ n \" \n " ;
$output .= " \" PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ \\ n \" \n " ;
$output .= " \" Last-Translator: NAME <EMAIL@ADDRESS> \\ n \" \n " ;
$output .= " \" Language-Team: LANGUAGE <EMAIL@ADDRESS> \\ n \" \n " ;
$output .= " \" MIME-Version: 1.0 \\ n \" \n " ;
$output .= " \" Content-Type: text/plain; charset=utf-8 \\ n \" \n " ;
$output .= " \" Content-Transfer-Encoding: 8bit \\ n \" \n " ;
$output .= " \" Plural-Forms: nplurals=INTEGER; plural=EXPRESSION; \\ n \" \n \n " ;
return $output ;
}
2011-04-25 17:22:14 +00:00
/**
* Get the strings from the position forward
*
* @ param int $position Actual position on tokens array
* @ param int $target Number of strings to extract
* @ return array Strings extracted
*/
2011-04-25 20:08:12 +00:00
protected function _getStrings ( & $position , $target ) {
2011-04-25 17:22:14 +00:00
$strings = array ();
2011-04-25 20:08:12 +00:00
while ( count ( $strings ) < $target && ( $this -> _tokens [ $position ] == ',' || $this -> _tokens [ $position ][ 0 ] == T_CONSTANT_ENCAPSED_STRING )) {
if ( $this -> _tokens [ $position ][ 0 ] == T_CONSTANT_ENCAPSED_STRING && $this -> _tokens [ $position + 1 ] == '.' ) {
2011-04-25 17:22:14 +00:00
$string = '' ;
2011-04-25 20:08:12 +00:00
while ( $this -> _tokens [ $position ][ 0 ] == T_CONSTANT_ENCAPSED_STRING || $this -> _tokens [ $position ] == '.' ) {
if ( $this -> _tokens [ $position ][ 0 ] == T_CONSTANT_ENCAPSED_STRING ) {
$string .= $this -> _formatString ( $this -> _tokens [ $position ][ 1 ]);
2011-04-25 17:22:14 +00:00
}
$position ++ ;
}
$strings [] = $string ;
2011-04-25 20:08:12 +00:00
} else if ( $this -> _tokens [ $position ][ 0 ] == T_CONSTANT_ENCAPSED_STRING ) {
$strings [] = $this -> _formatString ( $this -> _tokens [ $position ][ 1 ]);
2011-04-25 17:22:14 +00:00
}
$position ++ ;
}
return $strings ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2011-04-25 17:39:13 +00:00
* Format a string to be added as a translatable string
2008-05-30 11:40:08 +00:00
*
* @ param string $string String to format
* @ return string Formatted string
*/
2011-04-25 20:08:12 +00:00
protected function _formatString ( $string ) {
2008-05-30 11:40:08 +00:00
$quote = substr ( $string , 0 , 1 );
$string = substr ( $string , 1 , - 1 );
if ( $quote == '"' ) {
$string = stripcslashes ( $string );
} else {
$string = strtr ( $string , array ( " \\ ' " => " ' " , " \\ \\ " => " \\ " ));
}
2008-11-06 22:57:50 +00:00
$string = str_replace ( " \r \n " , " \n " , $string );
2008-05-30 11:40:08 +00:00
return addcslashes ( $string , " \0 .. \37 \\ \" " );
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Indicate an invalid marker on a processed file
*
* @ param string $file File where invalid marker resides
* @ param integer $line Line number
* @ param string $marker Marker found
* @ param integer $count Count
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _markerError ( $file , $line , $marker , $count ) {
2011-03-19 17:32:35 +00:00
$this -> out ( __d ( 'cake_console' , " Invalid marker content in %s:%s \n * %s( " , $file , $line , $marker ), true );
2008-05-30 11:40:08 +00:00
$count += 2 ;
2011-04-25 20:08:12 +00:00
$tokenCount = count ( $this -> _tokens );
2008-05-30 11:40:08 +00:00
$parenthesis = 1 ;
while ((( $tokenCount - $count ) > 0 ) && $parenthesis ) {
2011-04-25 20:08:12 +00:00
if ( is_array ( $this -> _tokens [ $count ])) {
$this -> out ( $this -> _tokens [ $count ][ 1 ], false );
2008-05-30 11:40:08 +00:00
} else {
2011-04-25 20:08:12 +00:00
$this -> out ( $this -> _tokens [ $count ], false );
if ( $this -> _tokens [ $count ] == '(' ) {
2008-05-30 11:40:08 +00:00
$parenthesis ++ ;
}
2011-04-25 20:08:12 +00:00
if ( $this -> _tokens [ $count ] == ')' ) {
2008-05-30 11:40:08 +00:00
$parenthesis -- ;
}
}
$count ++ ;
}
$this -> out ( " \n " , true );
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2011-04-25 17:39:13 +00:00
* Search files that may contain translatable strings
2008-05-30 11:40:08 +00:00
*
2009-09-15 03:43:59 +00:00
* @ return void
2008-05-30 11:40:08 +00:00
*/
2011-04-25 20:08:12 +00:00
protected function _searchFiles () {
2010-10-29 04:40:04 +00:00
$pattern = false ;
if ( ! empty ( $this -> _exclude )) {
2011-05-27 20:19:15 +00:00
$exclude = array ();
foreach ( $this -> _exclude as $e ) {
if ( $e [ 0 ] !== DS ) {
$e = DS . $e ;
}
$exclude [] = preg_quote ( $e , '/' );
}
$pattern = '/' . implode ( '|' , $exclude ) . '/' ;
2010-10-29 04:40:04 +00:00
}
2011-04-25 20:08:12 +00:00
foreach ( $this -> _paths as $path ) {
2009-09-15 03:43:59 +00:00
$Folder = new Folder ( $path );
$files = $Folder -> findRecursive ( '.*\.(php|ctp|thtml|inc|tpl)' , true );
2010-10-29 04:40:04 +00:00
if ( ! empty ( $pattern )) {
foreach ( $files as $i => $file ) {
if ( preg_match ( $pattern , $file )) {
unset ( $files [ $i ]);
}
}
$files = array_values ( $files );
}
2011-04-25 20:08:12 +00:00
$this -> _files = array_merge ( $this -> _files , $files );
2008-05-30 11:40:08 +00:00
}
}
2011-05-27 20:19:15 +00:00
/**
* Returns whether this execution is meant to extract string only from directories in folder represented by the
* APP constant , i . e . this task is extracting strings from same application .
*
* @ return boolean
*/
protected function _isExtractingApp () {
return $this -> _paths === array ( APP );
}
2008-05-30 11:40:08 +00:00
}