| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 | <?php/** * Console application, which extracts or replaces strings for * translation, which cannot be gettexted * * @package wordpress-i18n * @subpackage tools */// see: http://php.net/tokenizerif ( ! defined( 'T_ML_COMMENT' ) )	    define( 'T_ML_COMMENT', T_COMMENT );else	    define( 'T_DOC_COMMENT', T_ML_COMMENT );$pomo = dirname( dirname( dirname( __FILE__ ) ) ) . '/src/wp-includes/pomo';require_once "$pomo/po.php";require_once "$pomo/mo.php";class NotGettexted {	var $enable_logging = false;	var $STAGE_OUTSIDE = 0;	var $STAGE_START_COMMENT = 1;	var $STAGE_WHITESPACE_BEFORE = 2;	var $STAGE_STRING = 3;	var $STAGE_WHITESPACE_AFTER = 4;	var $STAGE_END_COMMENT = 4;	var $commands = array('extract' => 'command_extract', 'replace' => 'command_replace' );	function logmsg() {		$args = func_get_args();		if ($this->enable_logging) error_log(implode(' ', $args));	}	function stderr($msg, $nl=true) {		fwrite(STDERR, $msg.($nl? "\n" : ""));	}	function cli_die($msg) {		$this->stderr($msg);		exit(1);	}	function unchanged_token($token, $s='') {		return is_array($token)? $token[1] : $token;	}	function ignore_token($token, $s='') {		return '';	}	function list_php_files($dir) {		$files = array();		$items = scandir( $dir );		foreach ( (array) $items as $item ) {			$full_item = $dir . '/' . $item;			if ('.' == $item || '..' == $item)				continue;			if ('.php' == substr($item, -4))				$files[] = $full_item;			if (is_dir($full_item))				$files += array_merge($files, NotGettexted::list_php_files($full_item, $files));		}		return $files;	}	function make_string_aggregator($global_array_name, $filename) {		$a = $global_array_name;		return create_function('$string, $comment_id, $line_number', 'global $'.$a.'; $'.$a.'[] = array($string, $comment_id, '.var_export($filename, true).', $line_number);');	}	function make_mo_replacer($global_mo_name) {		$m = $global_mo_name;		return create_function('$token, $string', 'global $'.$m.'; return var_export($'.$m.'->translate($string), true);');	}	function walk_tokens(&$tokens, $string_action, $other_action, $register_action=null) {		$current_comment_id = '';		$current_string = '';		$current_string_line = 0;		$result = '';		$line = 1;		foreach($tokens as $token) {			if (is_array($token)) {				list($id, $text) = $token;				$line += substr_count($text, "\n");				if ((T_ML_COMMENT == $id || T_COMMENT == $id) && preg_match('|/\*\s*(/?WP_I18N_[a-z_]+)\s*\*/|i', $text, $matches)) {					if ($this->STAGE_OUTSIDE == $stage) {						$stage = $this->STAGE_START_COMMENT;						$current_comment_id = $matches[1];						$this->logmsg('start comment', $current_comment_id);						$result .= call_user_func($other_action, $token);						continue;					}					if ($this->STAGE_START_COMMENT <= $stage && $stage <= $this->STAGE_WHITESPACE_AFTER && '/'.$current_comment_id == $matches[1]) {						$stage = $this->STAGE_END_COMMENT;						$this->logmsg('end comment', $current_comment_id);						$result .= call_user_func($other_action, $token);						if (!is_null($register_action)) call_user_func($register_action, $current_string, $current_comment_id, $current_string_line);						continue;					}				} else if (T_CONSTANT_ENCAPSED_STRING == $id) {					if ($this->STAGE_START_COMMENT <= $stage && $stage < $this->STAGE_WHITESPACE_AFTER) {						eval('$current_string='.$text.';');						$this->logmsg('string', $current_string);						$current_string_line = $line;						$result .= call_user_func($string_action, $token, $current_string);						continue;					}				} else if (T_WHITESPACE == $id) {					if ($this->STAGE_START_COMMENT <= $stage && $stage < $this->STAGE_STRING) {						$stage = $this->STAGE_WHITESPACE_BEFORE;						$this->logmsg('whitespace before');						$result .= call_user_func($other_action, $token);						continue;					}					if ($this->STAGE_STRING < $stage && $stage < $this->STAGE_END_COMMENT) {						$stage = $this->STAGE_WHITESPACE_AFTER;						$this->logmsg('whitespace after');						$result .= call_user_func($other_action, $token);						continue;					}				}			}			$result .= call_user_func($other_action, $token);			$stage = $this->STAGE_OUTSIDE;			$current_comment_id = '';			$current_string = '';			$current_string_line = 0;		}		return $result;	}	function command_extract() {		$args = func_get_args();		$pot_filename = $args[0];		if (isset($args[1]) && is_array($args[1]))			$filenames = $args[1];		else			$filenames = array_slice($args, 1);		$global_name = '__entries_'.mt_rand(1, 1000);		$GLOBALS[$global_name] = array();		foreach($filenames as $filename) {			$tokens = token_get_all(file_get_contents($filename));			$aggregator = $this->make_string_aggregator($global_name, $filename);			$this->walk_tokens($tokens, array($this, 'ignore_token'), array($this, 'ignore_token'), $aggregator);		}		$potf = '-' == $pot_filename? STDOUT : @fopen($pot_filename, 'a');		if (false === $potf) {			$this->cli_die("Couldn't open pot file: $pot_filename");		}		foreach($GLOBALS[$global_name] as $item) {			@list($string, $comment_id, $filename, $line_number) = $item;			$filename = isset($filename)? preg_replace('|^\./|', '', $filename) : '';			$ref_line_number = isset($line_number)? ":$line_number" : '';			$args = array(				'singular' => $string,				'extracted_comments' => "Not gettexted string $comment_id",				'references' => array("$filename$ref_line_number"),			);			$entry = new Translation_Entry($args);			fwrite($potf, "\n".PO::export_entry($entry)."\n");		}		if ('-' != $pot_filename) fclose($potf);		return true;	}	function command_replace() {		$args = func_get_args();		$mo_filename = $args[0];		if (isset($args[1]) && is_array($args[1]))			$filenames = $args[1];		else			$filenames = array_slice($args, 1);		$global_name = '__mo_'.mt_rand(1, 1000);		$GLOBALS[$global_name] = new MO();		$replacer = $this->make_mo_replacer($global_name);		$res = $GLOBALS[$global_name]->import_from_file($mo_filename);		if (false === $res) {			$this->cli_die("Couldn't read MO file '$mo_filename'!");		}		foreach($filenames as $filename) {			$source = file_get_contents($filename);			if ( strlen($source) > 150000 ) continue;			$tokens = token_get_all($source);			$new_file = $this->walk_tokens($tokens, $replacer, array($this, 'unchanged_token'));			$f = fopen($filename, 'w');			fwrite($f, $new_file);			fclose($f);		}		return true;	}	function usage() {		$this->stderr('php i18n-comments.php COMMAND OUTPUTFILE INPUTFILES');		$this->stderr('Extracts and replaces strings, which cannot be gettexted');		$this->stderr('Commands:');		$this->stderr('	extract POTFILE PHPFILES appends the strings to POTFILE');		$this->stderr('	replace MOFILE PHPFILES replaces strings in PHPFILES with translations from MOFILE');	}	function cli() {		global $argv, $commands;		if (count($argv) < 4 || !in_array($argv[1], array_keys($this->commands))) {			$this->usage();			exit(1);		}		call_user_func_array(array($this, $this->commands[$argv[1]]), array_slice($argv, 2));	}}// run the CLI only if the file// wasn't included$included_files = get_included_files();if ($included_files[0] == __FILE__) {	error_reporting(E_ALL);	$not_gettexted = new NotGettexted;	$not_gettexted->cli();}?>
 |