<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[25003] trunk: Import internationalization tools from i18n.svn.wordpress.org.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/25003">25003</a></dd>
<dt>Author</dt> <dd>nacin</dd>
<dt>Date</dt> <dd>2013-08-07 06:44:08 +0000 (Wed, 07 Aug 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Import internationalization tools from i18n.svn.wordpress.org.

Imported from https://i18n.svn.wordpress.org/tools/trunk@22088.

see <a href="http://core.trac.wordpress.org/ticket/24976">#24976</a>.</pre>

<h3>Added Paths</h3>
<ul>
<li>trunk/tools/</li>
<li>trunk/tools/i18n/</li>
<li><a href="#trunktoolsi18naddtextdomainphp">trunk/tools/i18n/add-textdomain.php</a></li>
<li><a href="#trunktoolsi18nextractphp">trunk/tools/i18n/extract.php</a></li>
<li><a href="#trunktoolsi18nmakepotphp">trunk/tools/i18n/makepot.php</a></li>
<li><a href="#trunktoolsi18nnotgettextedphp">trunk/tools/i18n/not-gettexted.php</a></li>
<li><a href="#trunktoolsi18npotextmetaphp">trunk/tools/i18n/pot-ext-meta.php</a></li>
<li>trunk/tools/i18n/t/</li>
<li><a href="#trunktoolsi18ntExtractTestphp">trunk/tools/i18n/t/ExtractTest.php</a></li>
<li><a href="#trunktoolsi18ntNotGettextedTestphp">trunk/tools/i18n/t/NotGettextedTest.php</a></li>
<li>trunk/tools/i18n/t/data/</li>
<li><a href="#trunktoolsi18ntdatanotgettexted0resultphp">trunk/tools/i18n/t/data/not-gettexted-0-result.php</a></li>
<li><a href="#trunktoolsi18ntdatanotgettexted0workphp">trunk/tools/i18n/t/data/not-gettexted-0-work.php</a></li>
<li><a href="#trunktoolsi18ntdatanotgettexted0mo">trunk/tools/i18n/t/data/not-gettexted-0.mo</a></li>
<li><a href="#trunktoolsi18ntdatanotgettexted0php">trunk/tools/i18n/t/data/not-gettexted-0.php</a></li>
<li><a href="#trunktoolsi18ntdatanotgettexted0po">trunk/tools/i18n/t/data/not-gettexted-0.po</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktoolsi18naddtextdomainphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/add-textdomain.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/add-textdomain.php                              (rev 0)
+++ trunk/tools/i18n/add-textdomain.php 2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,108 @@
</span><ins>+<?php
+/**
+ * Console application, which adds textdomain argument
+ * to all i18n function calls
+ *
+ * @package wordpress-i18n
+ */
+error_reporting(E_ALL);
+
+require_once dirname( __FILE__ ) . '/makepot.php';
+
+class AddTextdomain {
+
+       var $modified_contents = '';
+       var $funcs;
+
+       function AddTextdomain() {
+               $makepot = new MakePOT;
+               $this->funcs = array_keys( $makepot->rules );
+       }
+
+       function usage() {
+               $usage = "Usage: php add-textdomain.php [-i] <domain> <file>\n\nAdds the string <domain> as a last argument to all i18n function calls in <file>\nand prints the modified php file on standard output.\n\nOptions:\n    -i    Modifies the PHP file in place, instead of printing it to standard output.\n";
+               fwrite(STDERR, $usage);
+               exit(1);
+       }
+
+       function process_token($token_text, $inplace) {
+               if ($inplace)
+                       $this->modified_contents .= $token_text;
+               else
+                       echo $token_text;
+       }
+
+
+       function process_file($domain, $source_filename, $inplace) {
+
+               $this->modified_contents = '';
+               $domain = addslashes($domain);
+
+               $source = file_get_contents($source_filename);
+               $tokens = token_get_all($source);
+
+               $in_func = false;
+               $args_started = false;
+               $parens_balance = 0;
+               $found_domain = false;
+
+               foreach($tokens as $token) {
+                       $string_success = false;
+                       if (is_array($token)) {
+                               list($id, $text) = $token;
+                               if (T_STRING == $id && in_array($text, $this->funcs)) {
+                                       $in_func = true;
+                                       $parens_balance = 0;
+                                       $args_started = false;
+                                       $found_domain = false;
+                               } elseif (T_CONSTANT_ENCAPSED_STRING == $id && ("'$domain'" == $text || "\"$domain\"" == $text)) {
+                                       if ($in_func && $args_started) {
+                                               $found_domain = true;
+                                       }
+                               }
+                               $token = $text;
+                       } elseif ('(' == $token){
+                               $args_started = true;
+                               ++$parens_balance;
+                       } elseif (')' == $token) {
+                               --$parens_balance;
+                               if ($in_func && 0 == $parens_balance) {
+                                       $token = $found_domain? ')' : ", '$domain')";
+                                       $in_func = false;
+                                       $args_started = false;
+                                       $found_domain = false;
+                               }
+                       }
+                       $this->process_token($token, $inplace);
+               }
+
+               if ($inplace) {
+                       $f = fopen($source_filename, 'w');
+                       fwrite($f, $this->modified_contents);
+                       fclose($f);
+               }
+       }
+}
+
+
+// run the CLI only if the file
+// wasn't included
+$included_files = get_included_files();
+if ($included_files[0] == __FILE__) {
+       $adddomain = new AddTextdomain;
+
+       if (!isset($argv[1]) || !isset($argv[2])) {
+               $adddomain->usage();
+       }
+
+       $inplace = false;
+       if ('-i' == $argv[1]) {
+               $inplace = true;
+               if (!isset($argv[3])) $adddomain->usage();
+               array_shift($argv);     
+       }
+
+       $adddomain->process_file($argv[1], $argv[2], $inplace);
+}
+
+?>
</ins></span></pre></div>
<a id="trunktoolsi18nextractphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/extract.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/extract.php                             (rev 0)
+++ trunk/tools/i18n/extract.php        2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,210 @@
</span><ins>+<?php
+$pomo = dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/src/wp-includes/pomo';
+require_once "$pomo/entry.php";
+require_once "$pomo/translations.php";
+
+class StringExtractor {
+
+       var $rules = array();
+       var $comment_prefix = 'translators:';
+
+       function __construct( $rules = array() ) {
+               $this->rules = $rules;
+       }
+
+       function extract_from_directory( $dir, $excludes = array(), $includes = array(), $prefix = '' ) {
+               $old_cwd = getcwd();
+               chdir( $dir );
+               $translations = new Translations;
+               $file_names = (array) scandir( '.' );
+               foreach ( $file_names as $file_name ) {
+                       if ( '.' == $file_name || '..' == $file_name ) continue;
+                       if ( preg_match( '/\.php$/', $file_name ) && $this->does_file_name_match( $prefix . $file_name, $excludes, $includes ) ) {
+                               $translations->merge_originals_with( $this->extract_from_file( $file_name, $prefix ) );
+                       }
+                       if ( is_dir( $file_name ) ) {
+                               $translations->merge_originals_with( $this->extract_from_directory( $file_name, $excludes, $includes, $prefix . $file_name . '/' ) );
+                       }
+               }
+               chdir( $old_cwd );
+               return $translations;
+       }
+
+       function extract_from_file( $file_name, $prefix ) {
+               $code = file_get_contents( $file_name );
+               return $this->extract_entries( $code, $prefix . $file_name );
+       }
+
+       function does_file_name_match( $path, $excludes, $includes ) {
+               if ( $includes ) {
+                       $matched_any_include = false;
+                       foreach( $includes as $include ) {
+                               if ( preg_match( '|^'.$include.'$|', $path ) ) {
+                                       $matched_any_include = true;
+                                       break;
+                               }
+                       }
+                       if ( !$matched_any_include ) return false;
+               }
+               if ( $excludes ) {
+                       foreach( $excludes as $exclude ) {
+                               if ( preg_match( '|^'.$exclude.'$|', $path ) ) {
+                                       return false;
+                               }
+                       }
+               }
+               return true;
+       }
+
+       function entry_from_call( $call, $file_name ) {
+               $rule = isset( $this->rules[$call['name']] )? $this->rules[$call['name']] : null;
+               if ( !$rule ) return null;
+               $entry = new Translation_Entry;
+               $multiple = array();
+               $complete = false;
+               for( $i = 0; $i < count( $rule ); ++$i ) {
+                       if ( $rule[$i] && ( !isset( $call['args'][$i] ) || !is_string( $call['args'][$i] ) || '' == $call['args'][$i] ) ) return false;
+                       switch( $rule[$i] ) {
+                       case 'string':
+                               if ( $complete ) {
+                                       $multiple[] = $entry;
+                                       $entry = new Translation_Entry;
+                                       $complete = false;
+                               }
+                               $entry->singular = $call['args'][$i];
+                               $complete = true;
+                               break;
+                       case 'singular':
+                               if ( $complete ) {
+                                       $multiple[] = $entry;
+                                       $entry = new Translation_Entry;
+                                       $complete = false;
+                               }
+                               $entry->singular = $call['args'][$i];
+                               $entry->is_plural = true;
+                               break;
+                       case 'plural':
+                               $entry->plural = $call['args'][$i];
+                               $entry->is_plural = true;
+                               $complete = true;
+                               break;
+                       case 'context':
+                               $entry->context = $call['args'][$i];
+                               foreach( $multiple as &$single_entry ) {
+                                       $single_entry->context = $entry->context;
+                               }
+                               break;
+                       }
+               }
+               if ( isset( $call['line'] ) && $call['line'] ) {
+                       $references = array( $file_name . ':' . $call['line'] );
+                       $entry->references = $references;
+                       foreach( $multiple as &$single_entry ) {
+                               $single_entry->references = $references;
+                       }
+               }
+               if ( isset( $call['comment'] ) && $call['comment'] ) {
+                       $comments = rtrim( $call['comment'] ) . "\n";
+                       $entry->extracted_comments = $comments;
+                       foreach( $multiple as &$single_entry ) {
+                               $single_entry->extracted_comments = $comments;
+                       }
+               }
+               if ( $multiple && $entry ) {
+                       $multiple[] = $entry;
+                       return $multiple;
+               }
+
+               return $entry;
+       }
+
+       function extract_entries( $code, $file_name ) {
+               $translations = new Translations;
+               $function_calls = $this->find_function_calls( array_keys( $this->rules ), $code );
+               foreach( $function_calls as $call ) {
+                       $entry = $this->entry_from_call( $call, $file_name );
+                       if ( is_array( $entry ) )
+                               foreach( $entry as $single_entry )
+                                       $translations->add_entry_or_merge( $single_entry );
+                       elseif ( $entry)
+                               $translations->add_entry_or_merge( $entry );
+               }
+               return $translations;
+       }
+
+       /**
+        * Finds all function calls in $code and returns an array with an associative array for each function:
+        *      - name - name of the function
+        *      - args - array for the function arguments. Each string literal is represented by itself, other arguments are represented by null.
+        *  - line - line number
+        */
+       function find_function_calls( $function_names, $code ) {
+               $tokens = token_get_all( $code );
+               $function_calls = array();
+               $latest_comment = false;
+               $in_func = false;
+               foreach( $tokens as $token ) {
+                       $id = $text = null;
+                       if ( is_array( $token ) ) list( $id, $text, $line ) = $token;
+                       if ( T_WHITESPACE == $id ) continue;
+                       if ( T_STRING == $id && in_array( $text, $function_names ) && !$in_func ) {
+                               $in_func = true;
+                               $paren_level = -1;
+                               $args = array();
+                               $func_name = $text;
+                               $func_line = $line;
+                               $func_comment = $latest_comment? $latest_comment : '';
+
+                               $just_got_into_func = true;
+                               $latest_comment = false;
+                               continue;
+                       }
+                       if ( T_COMMENT == $id ) {
+                               $text = trim( preg_replace( '%^/\*|//%', '', preg_replace( '%\*/$%', '', $text ) ) );
+                               if ( 0 === stripos( $text, $this->comment_prefix ) ) {
+                                       $latest_comment = $text;
+                               }
+                       }
+                       if ( !$in_func ) continue;
+                       if ( '(' == $token ) {
+                               $paren_level++;
+                               if ( 0 == $paren_level ) { // start of first argument
+                                       $just_got_into_func = false;
+                                       $current_argument = null;
+                                       $current_argument_is_just_literal = true;
+                               }
+                               continue;
+                       }
+                       if ( $just_got_into_func ) {
+                               // there wasn't a opening paren just after the function name -- this means it is not a function
+                               $in_func = false;
+                               $just_got_into_func = false;
+                       }
+                       if ( ')' == $token ) {
+                               if ( 0 == $paren_level ) {
+                                       $in_func = false;
+                                       $args[] = $current_argument;
+                                       $call = array( 'name' => $func_name, 'args' => $args, 'line' => $func_line );
+                                       if ( $func_comment ) $call['comment'] = $func_comment;
+                                       $function_calls[] = $call;
+                               }
+                               $paren_level--;
+                               continue;
+                       }
+                       if ( ',' == $token && 0 == $paren_level ) {
+                               $args[] = $current_argument;
+                               $current_argument = null;
+                               $current_argument_is_just_literal = true;
+                               continue;
+                       }
+                       if ( T_CONSTANT_ENCAPSED_STRING == $id && $current_argument_is_just_literal ) {
+                               // we can use eval safely, because we are sure $text is just a string literal
+                               eval('$current_argument = '.$text.';' );
+                               continue;
+                       }
+                       $current_argument_is_just_literal = false;
+                       $current_argument = null;
+               }
+               return $function_calls;
+       }
+}
</ins></span></pre></div>
<a id="trunktoolsi18nmakepotphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/makepot.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/makepot.php                             (rev 0)
+++ trunk/tools/i18n/makepot.php        2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,571 @@
</span><ins>+<?php
+require_once dirname( __FILE__ ) . '/not-gettexted.php';
+require_once dirname( __FILE__ ) . '/pot-ext-meta.php';
+require_once dirname( __FILE__ ) . '/extract.php';
+
+if ( !defined( 'STDERR' ) ) {
+       define( 'STDERR', fopen( 'php://stderr', 'w' ) );
+}
+
+class MakePOT {
+       var $max_header_lines = 30;
+
+       var $projects = array(
+               'generic',
+               'wp-frontend',
+               'wp-admin',
+               'wp-network-admin',
+               'wp-core',
+               'wp-ms',
+               'wp-tz',
+               'wp-plugin',
+               'wp-theme',
+               'bb',
+               'mu',
+               'bp',
+               'rosetta',
+               'wporg-bb-forums',
+       );
+
+       var $rules = array(
+               '_' => array('string'),
+               '__' => array('string'),
+               '_e' => array('string'),
+               '_c' => array('string'),
+               '_n' => array('singular', 'plural'),
+               '_n_noop' => array('singular', 'plural'),
+               '_nc' => array('singular', 'plural'),
+               '__ngettext' => array('singular', 'plural'),
+               '__ngettext_noop' => array('singular', 'plural'),
+               '_x' => array('string', 'context'),
+               '_ex' => array('string', 'context'),
+               '_nx' => array('singular', 'plural', null, 'context'),
+               '_nx_noop' => array('singular', 'plural', 'context'),
+               '_n_js' => array('singular', 'plural'),
+               '_nx_js' => array('singular', 'plural', 'context'),
+               'esc_attr__' => array('string'),
+               'esc_html__' => array('string'),
+               'esc_attr_e' => array('string'),
+               'esc_html_e' => array('string'),
+               'esc_attr_x' => array('string', 'context'),
+               'esc_html_x' => array('string', 'context'),
+               'comments_number_link' => array('string', 'singular', 'plural'),
+       );
+
+       var $ms_files = array( 'ms-.*', '.*/ms-.*', '.*/my-.*', 'wp-activate\.php', 'wp-signup\.php', 'wp-admin/network\.php', 'wp-admin/includes/ms\.php', 'wp-admin/network/.*\.php', 'wp-admin/includes/class-wp-ms.*' );
+
+       var $temp_files = array();
+
+       var $meta = array(
+               'default' => array(
+                       'from-code' => 'utf-8',
+                       'msgid-bugs-address' => 'http://wppolyglots.wordpress.com',
+                       'language' => 'php',
+                       'add-comments' => 'translators',
+                       'comments' => "Copyright (C) {year} {package-name}\nThis file is distributed under the same license as the {package-name} package.",
+               ),
+               'generic' => array(),
+               'wp-frontend' => array(
+                       'description' => 'Translation of frontend strings in WordPress {version}',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress',
+                       'package-version' => '{version}',
+               ),
+               'wp-admin' => array(
+                       'description' => 'Translation of site admin strings in WordPress {version}',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress',
+                       'package-version' => '{version}',
+               ),
+               'wp-network-admin' => array(
+                       'description' => 'Translation of network admin strings in WordPress {version}',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress',
+                       'package-version' => '{version}',
+               ),
+               'wp-core' => array(
+                       'description' => 'Translation of WordPress {version}',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress',
+                       'package-version' => '{version}',
+               ),
+               'wp-ms' => array(
+                       'description' => 'Translation of multisite strings in WordPress {version}',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress',
+                       'package-version' => '{version}',
+               ),
+               'wp-tz' => array(
+                       'description' => 'Translation of timezone strings in WordPress {version}',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress',
+                       'package-version' => '{version}',
+               ),
+               'bb' => array(
+                       'description' => 'Translation of bbPress',
+                       'copyright-holder' => 'bbPress',
+                       'package-name' => 'bbPress',
+               ),
+               'wp-plugin' => array(
+                       'description' => 'Translation of the WordPress plugin {name} {version} by {author}',
+                       'msgid-bugs-address' => 'http://wordpress.org/tag/{slug}',
+                       'copyright-holder' => '{author}',
+                       'package-name' => '{name}',
+                       'package-version' => '{version}',
+               ),
+               'wp-theme' => array(
+                       'description' => 'Translation of the WordPress theme {name} {version} by {author}',
+                       'msgid-bugs-address' => 'http://wordpress.org/tags/{slug}',
+                       'copyright-holder' => '{author}',
+                       'package-name' => '{name}',
+                       'package-version' => '{version}',
+                       'comments' => 'Copyright (C) {year} {author}\nThis file is distributed under the same license as the {package-name} package.',
+               ),
+               'bp' => array(
+                       'description' => 'Translation of BuddyPress',
+                       'copyright-holder' => 'BuddyPress',
+                       'package-name' => 'BuddyPress',
+               ),
+               'glotpress' => array(
+                       'description' => 'Translation of GlotPress',
+                       'copyright-holder' => 'GlotPress',
+                       'package-name' => 'GlotPress',
+               ),
+               'wporg-bb-forums' => array(
+                       'description' => 'WordPress.org International Forums',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'WordPress.org International Forums',
+               ),
+               'rosetta' => array(
+                       'description' => 'Rosetta (.wordpress.org locale sites)',
+                       'copyright-holder' => 'WordPress',
+                       'package-name' => 'Rosetta',
+               ),
+       );
+
+       function __construct($deprecated = true) {
+               $this->extractor = new StringExtractor( $this->rules );
+       }
+
+       function __destruct() {
+               foreach ( $this->temp_files as $temp_file )
+                       unlink( $temp_file );
+       }
+
+       function tempnam( $file ) {
+               $tempnam = tempnam( sys_get_temp_dir(), $file );
+               $this->temp_files[] = $tempnam;
+               return $tempnam;
+       }
+
+       function realpath_missing($path) {
+               return realpath(dirname($path)).DIRECTORY_SEPARATOR.basename($path);
+       }
+
+       function xgettext($project, $dir, $output_file, $placeholders = array(), $excludes = array(), $includes = array()) {
+               $meta = array_merge( $this->meta['default'], $this->meta[$project] );
+               $placeholders = array_merge( $meta, $placeholders );
+               $meta['output'] = $this->realpath_missing( $output_file );
+               $placeholders['year'] = date( 'Y' );
+               $placeholder_keys = array_map( create_function( '$x', 'return "{".$x."}";' ), array_keys( $placeholders ) );
+               $placeholder_values = array_values( $placeholders );
+               foreach($meta as $key => $value) {
+                       $meta[$key] = str_replace($placeholder_keys, $placeholder_values, $value);
+               }
+
+               $originals = $this->extractor->extract_from_directory( $dir, $excludes, $includes );
+               $pot = new PO;
+               $pot->entries = $originals->entries;
+
+               $pot->set_header( 'Project-Id-Version', $meta['package-name'].' '.$meta['package-version'] );
+               $pot->set_header( 'Report-Msgid-Bugs-To', $meta['msgid-bugs-address'] );
+               $pot->set_header( 'POT-Creation-Date', gmdate( 'Y-m-d H:i:s+00:00' ) );
+               $pot->set_header( 'MIME-Version', '1.0' );
+               $pot->set_header( 'Content-Type', 'text/plain; charset=UTF-8' );
+               $pot->set_header( 'Content-Transfer-Encoding', '8bit' );
+               $pot->set_header( 'PO-Revision-Date', date( 'Y') . '-MO-DA HO:MI+ZONE' );
+               $pot->set_header( 'Last-Translator', 'FULL NAME <EMAIL@ADDRESS>' );
+               $pot->set_header( 'Language-Team', 'LANGUAGE <LL@li.org>' );
+               $pot->set_comment_before_headers( $meta['comments'] );
+               $pot->export_to_file( $output_file );
+               return true;
+       }
+
+       function wp_generic($dir, $args) {
+               $defaults = array(
+                       'project' => 'wp-core',
+                       'output' => null,
+                       'default_output' => 'wordpress.pot',
+                       'includes' => array(),
+                       'excludes' => array_merge(
+                               array('wp-admin/includes/continents-cities\.php', 'wp-content/themes/twenty.*', ),
+                               $this->ms_files
+                       ),
+                       'extract_not_gettexted' => false,
+                       'not_gettexted_files_filter' => false,
+               );
+               $args = array_merge( $defaults, $args );
+               extract( $args );
+               $placeholders = array();
+               if ( $wp_version = $this->wp_version( $dir ) )
+                       $placeholders['version'] = $wp_version;
+               else
+                       return false;
+               $output = is_null( $output )? $default_output : $output;
+               $res = $this->xgettext( $project, $dir, $output, $placeholders, $excludes, $includes );
+               if ( !$res ) return false;
+
+               if ( $extract_not_gettexted ) {
+                       $old_dir = getcwd();
+                       $output = realpath( $output );
+                       chdir( $dir );
+                       $php_files = NotGettexted::list_php_files('.');
+                       $php_files = array_filter( $php_files, $not_gettexted_files_filter );
+                       $not_gettexted = new NotGettexted;
+                       $res = $not_gettexted->command_extract( $output, $php_files );
+                       chdir( $old_dir );
+                       /* Adding non-gettexted strings can repeat some phrases */
+                       $output_shell = escapeshellarg( $output );
+                       system( "msguniq --use-first $output_shell -o $output_shell" );
+               }
+               return $res;
+       }
+
+       function wp_core($dir, $output) {
+               if ( file_exists( "$dir/wp-admin/user/about.php" ) ) return false;
+
+               return $this->wp_generic( $dir, array(
+                       'project' => 'wp-core', 'output' => $output,
+                       'extract_not_gettexted' => true,
+                        'not_gettexted_files_filter' => array( &$this, 'is_not_ms_file' ),
+               ) );
+       }
+
+       function wp_frontend($dir, $output) {
+               if ( ! file_exists( "$dir/wp-admin/user/about.php" ) ) return false;
+
+               return $this->wp_generic( $dir, array(
+                       'project' => 'wp-frontend', 'output' => $output,
+                       'includes' => array(), 'excludes' => array( 'wp-admin/.*', 'wp-content/themes/.*' ),
+                       'default_output' => 'wordpress.pot',
+               ) );
+       }
+
+       function wp_admin($dir, $output) {
+               if ( ! file_exists( "$dir/wp-admin/user/about.php" ) ) return false;
+
+               $frontend_pot = $this->tempnam( 'frontend.pot' );
+               if ( false === $frontend_pot ) return false;
+
+               $frontend_result = $this->wp_frontend( $dir, $frontend_pot );
+               if ( ! $frontend_result )
+                       return false;
+
+               $result = $this->wp_generic( $dir, array(
+                       'project' => 'wp-admin', 'output' => $output,
+                       'includes' => array( 'wp-admin/.*' ), 'excludes' => array( 'wp-admin/includes/continents-cities\.php', 'wp-admin/network/.*', 'wp-admin/network.php' ),
+                       'default_output' => 'wordpress-admin.pot',
+               ) );
+
+               if ( ! $result )
+                       return false;
+
+                $potextmeta = new PotExtMeta;
+                $result = $potextmeta->append( "$dir/wp-content/plugins/akismet/akismet.php", $output );
+               if ( ! $result )
+                       return false;
+               $result = $potextmeta->append( "$dir/wp-content/plugins/hello.php", $output );
+               if ( ! $result )
+                       return false;
+                /* Adding non-gettexted strings can repeat some phrases */
+                $output_shell = escapeshellarg($output);
+                system("msguniq $output_shell -o $output_shell");
+
+               $common_pot = $this->tempnam( 'common.pot' );
+               if ( ! $common_pot )
+                       return false;
+               $admin_pot = realpath( is_null( $output ) ? 'wordpress-admin.pot' : $output );
+               system( "msgcat --more-than=1 --use-first $frontend_pot $admin_pot > $common_pot" );
+               system( "msgcat -u --use-first $admin_pot $common_pot -o $admin_pot" );
+               return true;
+       }
+
+       function wp_network_admin($dir, $output) {
+               if ( ! file_exists( "$dir/wp-admin/user/about.php" ) ) return false;
+
+               $frontend_pot = $this->tempnam( 'frontend.pot' );
+               if ( false === $frontend_pot ) return false;
+
+               $frontend_result = $this->wp_frontend( $dir, $frontend_pot );
+               if ( ! $frontend_result )
+                       return false;
+
+               $admin_pot = $this->tempnam( 'admin.pot' );
+               if ( false === $admin_pot ) return false;
+
+               $admin_result = $this->wp_admin( $dir, $admin_pot );
+               if ( ! $admin_result )
+                       return false;
+
+               $result = $this->wp_generic( $dir, array(
+                       'project' => 'wp-network-admin', 'output' => $output,
+                       'includes' => array( 'wp-admin/network/.*', 'wp-admin/network.php' ), 'excludes' => array(),
+                       'default_output' => 'wordpress-admin-network.pot',
+               ) );
+
+               if ( ! $result ) {
+                       return false;
+               }
+
+               $common_pot = $this->tempnam( 'common.pot' );
+               if ( ! $common_pot )
+                       return false;
+
+               $net_admin_pot = realpath( is_null( $output ) ? 'wordpress-network-admin.pot' : $output );
+               system( "msgcat --more-than=1 --use-first $frontend_pot $admin_pot $net_admin_pot > $common_pot" );
+               system( "msgcat -u --use-first $net_admin_pot $common_pot -o $net_admin_pot" );
+               return true;
+       }
+
+       function wp_ms($dir, $output) {
+               if ( file_exists( "$dir/wp-admin/user/about.php" ) ) return false;
+               if ( !is_file("$dir/wp-admin/ms-users.php") ) return false;
+               $core_pot = $this->tempnam( 'wordpress.pot' );
+               if ( false === $core_pot ) return false;
+               $core_result = $this->wp_core( $dir, $core_pot );
+               if ( ! $core_result )
+                       return false;
+               $ms_result = $this->wp_generic( $dir, array(
+                       'project' => 'wp-ms', 'output' => $output,
+                       'includes' => $this->ms_files, 'excludes' => array(),
+                       'default_output' => 'wordpress-ms.pot',
+                       'extract_not_gettexted' => true,
+                       'not_gettexted_files_filter' => array( &$this, 'is_ms_file' ),
+               ) );
+               if ( !$ms_result ) {
+                       return false;
+               }
+               $common_pot = $this->tempnam( 'common.pot' );
+               if ( ! $common_pot )
+                       return false;
+               $ms_pot = realpath( is_null( $output )? 'wordpress-ms.pot' : $output );
+               system( "msgcat --more-than=1 --use-first $core_pot $ms_pot > $common_pot" );
+               system( "msgcat -u --use-first $ms_pot $common_pot -o $ms_pot" );
+               return true;
+       }
+
+       function wp_tz($dir, $output) {
+               $continents_path = 'wp-admin/includes/continents-cities.php';
+               if ( !file_exists( "$dir/$continents_path" ) ) return false;
+               return $this->wp_generic( $dir, array(
+                       'project' => 'wp-tz', 'output' => $output,
+                       'includes' => array($continents_path), 'excludes' => array(),
+                       'default_output' => 'wordpress-continents-cities.pot',
+               ) );
+       }
+
+       function wp_version($dir) {
+               $version_php = $dir.'/wp-includes/version.php';
+               if ( !is_readable( $version_php ) ) return false;
+               return preg_match( '/\$wp_version\s*=\s*\'(.*?)\';/', file_get_contents( $version_php ), $matches )? $matches[1] : false;
+       }
+
+
+       function mu($dir, $output) {
+               $placeholders = array();
+               if (preg_match('/\$wpmu_version\s*=\s*\'(.*?)\';/', file_get_contents($dir.'/wp-includes/version.php'), $matches)) {
+                       $placeholders['version'] = $matches[1];
+               }
+               $output = is_null($output)? 'wordpress.pot' : $output;
+               return $this->xgettext('wp', $dir, $output, $placeholders);
+       }
+
+
+       function bb($dir, $output) {
+               $placeholders = array();
+               $output = is_null($output)? 'bbpress.pot' : $output;
+               return $this->xgettext('bb', $dir, $output, $placeholders);
+
+       }
+
+       function get_first_lines($filename, $lines = 30) {
+               $extf = fopen($filename, 'r');
+               if (!$extf) return false;
+               $first_lines = '';
+               foreach(range(1, $lines) as $x) {
+                       $line = fgets($extf);
+                       if (feof($extf)) break;
+                       if (false === $line) {
+                               return false;
+                       }
+                       $first_lines .= $line;
+               }
+               return $first_lines;
+       }
+
+
+       function get_addon_header($header, &$source) {
+               if (preg_match('|'.$header.':(.*)$|mi', $source, $matches))
+                       return trim($matches[1]);
+               else
+                       return false;
+       }
+
+       function generic($dir, $output) {
+               $output = is_null($output)? "generic.pot" : $output;
+               return $this->xgettext('generic', $dir, $output, array());
+       }
+
+       function guess_plugin_slug($dir) {
+               if ('trunk' == basename($dir)) {
+                       $slug = basename(dirname($dir));
+               } elseif (in_array(basename(dirname($dir)), array('branches', 'tags'))) {
+                       $slug = basename(dirname(dirname($dir)));
+               } else {
+                       $slug = basename($dir);
+               }
+               return $slug;
+       }
+
+       function wp_plugin($dir, $output, $slug = null) {
+               $placeholders = array();
+               // guess plugin slug
+               if (is_null($slug)) {
+                       $slug = $this->guess_plugin_slug($dir);
+               }
+               $main_file = $dir.'/'.$slug.'.php';
+               $source = $this->get_first_lines($main_file, $this->max_header_lines);
+
+               $placeholders['version'] = $this->get_addon_header('Version', $source);
+               $placeholders['author'] = $this->get_addon_header('Author', $source);
+               $placeholders['name'] = $this->get_addon_header('Plugin Name', $source);
+               $placeholders['slug'] = $slug;
+
+               $output = is_null($output)? "$slug.pot" : $output;
+               $res = $this->xgettext('wp-plugin', $dir, $output, $placeholders);
+               if (!$res) return false;
+               $potextmeta = new PotExtMeta;
+               $res = $potextmeta->append($main_file, $output);
+               /* Adding non-gettexted strings can repeat some phrases */
+               $output_shell = escapeshellarg($output);
+               system("msguniq $output_shell -o $output_shell");
+               return $res;
+       }
+
+       function wp_theme($dir, $output, $slug = null) {
+               $placeholders = array();
+               // guess plugin slug
+               if (is_null($slug)) {
+                       $slug = $this->guess_plugin_slug($dir);
+               }
+               $main_file = $dir.'/style.css';
+               $source = $this->get_first_lines($main_file, $this->max_header_lines);
+
+               $placeholders['version'] = $this->get_addon_header('Version', $source);
+               $placeholders['author'] = $this->get_addon_header('Author', $source);
+               $placeholders['name'] = $this->get_addon_header('Theme Name', $source);
+               $placeholders['slug'] = $slug;
+
+               $license = $this->get_addon_header( 'License', $source );
+               if ( $license )
+                       $this->meta['wp-theme']['comments'] = "Copyright (C) {year} {author}\nThis file is distributed under the {$license}.";
+               else
+                       $this->meta['wp-theme']['comments'] = "Copyright (C) {year} {author}\nThis file is distributed under the same license as the {package-name} package.";
+
+               $output = is_null($output)? "$slug.pot" : $output;
+               $res = $this->xgettext('wp-theme', $dir, $output, $placeholders);
+               if (! $res )
+                       return false;
+               $potextmeta = new PotExtMeta;
+               $res = $potextmeta->append( $main_file, $output, array( 'Theme Name', 'Theme URI', 'Description', 'Author', 'Author URI' ) );
+               if ( ! $res )
+                       return false;
+               // If we're dealing with a pre-3.4 default theme, don't extract page templates before 3.4.
+               $extract_templates = ! in_array( $slug, array( 'twentyten', 'twentyeleven', 'default', 'classic' ) );
+               if ( ! $extract_templates ) {
+                       $wp_dir = dirname( dirname( dirname( $dir ) ) );
+                       $extract_templates = file_exists( "$wp_dir/wp-admin/user/about.php" ) || ! file_exists( "$wp_dir/wp-load.php" );
+               }
+               if ( $extract_templates ) {
+                       $res = $potextmeta->append( $dir, $output, array( 'Template Name' ) );
+                       if ( ! $res )
+                               return false;
+                       $files = scandir( $dir );
+                       foreach ( $files as $file ) {
+                               if ( '.' == $file[0] || 'CVS' == $file )
+                                       continue;
+                               if ( is_dir( $dir . '/' . $file ) ) {
+                                       $res = $potextmeta->append( $dir . '/' . $file, $output, array( 'Template Name' ) );
+                                       if ( ! $res )
+                                               return false;
+                               }
+                       }
+               }
+               /* Adding non-gettexted strings can repeat some phrases */
+               $output_shell = escapeshellarg($output);
+               system("msguniq $output_shell -o $output_shell");
+               return $res;
+       }
+
+       function bp($dir, $output) {
+               $output = is_null($output)? "buddypress.pot" : $output;
+               return $this->xgettext('bp', $dir, $output, array(), array('bp-forums/bbpress/.*'));
+       }
+
+       function glotpress( $dir, $output ) {
+               $output = is_null( $output ) ? "glotpress.pot" : $output;
+               return $this->xgettext( 'glotpress', $dir, $output );
+       }
+
+       function wporg_bb_forums( $dir, $output ) {
+               $output = is_null( $output ) ? 'wporg.pot' : $output;
+               return $this->xgettext( 'wporg-bb-forums', $dir, $output, array(), array(
+                       'bb-plugins/elfakismet/.*',
+                       'bb-plugins/support-forum/.*',
+               ) );
+       }
+
+       function rosetta( $dir, $output ) {
+               $output = is_null( $output )? 'rosetta.pot' : $output;
+               return $this->xgettext( 'rosetta', $dir, $output, array(), array(), array(
+                       'mu-plugins/rosetta.*\.php',
+                       'mu-plugins/rosetta/[^/]+\.php',
+                       'mu-plugins/rosetta/tmpl/.*\.php',
+                       'themes/rosetta/.*\.php',
+               ) );
+       }
+
+       function is_ms_file( $file_name ) {
+               $is_ms_file = false;
+               $prefix = substr( $file_name, 0, 2 ) === './'? '\./' : '';
+               foreach( $this->ms_files as $ms_file )
+                       if ( preg_match( '|^'.$prefix.$ms_file.'$|', $file_name ) ) {
+                               $is_ms_file = true;
+                               break;
+                       }
+               return $is_ms_file;
+       }
+
+       function is_not_ms_file( $file_name ) {
+               return !$this->is_ms_file( $file_name );
+       }
+}
+
+// run the CLI only if the file
+// wasn't included
+$included_files = get_included_files();
+if ($included_files[0] == __FILE__) {
+       $makepot = new MakePOT;
+       if ((3 == count($argv) || 4 == count($argv)) && in_array($method = str_replace('-', '_', $argv[1]), get_class_methods($makepot))) {
+               $res = call_user_func(array(&$makepot, $method), realpath($argv[2]), isset($argv[3])? $argv[3] : null);
+               if (false === $res) {
+                       fwrite(STDERR, "Couldn't generate POT file!\n");
+               }
+       } else {
+               $usage  = "Usage: php makepot.php PROJECT DIRECTORY [OUTPUT]\n\n";
+               $usage .= "Generate POT file from the files in DIRECTORY [OUTPUT]\n";
+               $usage .= "Available projects: ".implode(', ', $makepot->projects)."\n";
+               fwrite(STDERR, $usage);
+               exit(1);
+       }
+}
</ins></span></pre></div>
<a id="trunktoolsi18nnotgettextedphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/not-gettexted.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/not-gettexted.php                               (rev 0)
+++ trunk/tools/i18n/not-gettexted.php  2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,234 @@
</span><ins>+<?php
+/**
+ * Console application, which extracts or replaces strings for
+ * translation, which cannot be gettexted
+ *
+ * @package wordpress-i18n
+ * @subpackage tools
+ */
+// see: http://php.net/tokenizer
+if ( ! 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();
+}
+
+?>
</ins></span></pre></div>
<a id="trunktoolsi18npotextmetaphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/pot-ext-meta.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/pot-ext-meta.php                                (rev 0)
+++ trunk/tools/i18n/pot-ext-meta.php   2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+<?php
+/**
+ * Console application, which adds metadata strings from
+ * a WordPress extension to a POT file
+ *
+ * @package wordpress-i18n
+ * @subpackage tools
+ */
+
+$pomo = dirname( dirname( dirname( __FILE__ ) ) ) . '/src/wp-includes/pomo';
+require_once "$pomo/po.php";
+require_once dirname( __FILE__ ) . '/makepot.php';
+
+class PotExtMeta {
+
+       var $headers = array(
+               'Plugin Name',
+               'Theme Name',
+               'Plugin URI',
+               'Theme URI',
+               'Description',
+               'Author',
+               'Author URI',
+               'Tags',
+       );
+
+
+       function usage() {
+               fwrite(STDERR, "Usage: php pot-ext-meta.php EXT POT\n");
+               fwrite(STDERR, "Adds metadata from a WordPress theme or plugin file EXT to POT file\n");
+               exit(1);
+       }
+
+       function load_from_file($ext_filename) {
+               $source = MakePOT::get_first_lines($ext_filename);
+               $pot = '';
+               foreach($this->headers as $header) {
+                       $string = MakePOT::get_addon_header($header, $source);
+                       if (!$string) continue;
+                       $args = array(
+                               'singular' => $string,
+                               'extracted_comments' => $header.' of the plugin/theme',
+                       );
+                       $entry = new Translation_Entry($args);
+                       $pot .= "\n".PO::export_entry($entry)."\n";
+               }
+               return $pot;
+       }
+
+       function append( $ext_filename, $pot_filename, $headers = null ) {
+               if ( $headers )
+                       $this->headers = (array) $headers;
+               if ( is_dir( $ext_filename ) ) {
+                       $pot = implode('', array_map(array(&$this, 'load_from_file'), glob("$ext_filename/*.php")));
+               } else {
+                       $pot = $this->load_from_file($ext_filename);
+               }
+               $potf = '-' == $pot_filename? STDOUT : fopen($pot_filename, 'a');
+               if (!$potf) return false;
+               fwrite($potf, $pot);
+               if ('-' != $pot_filename) fclose($potf);
+               return true;
+       }
+}
+
+$included_files = get_included_files();
+if ($included_files[0] == __FILE__) {
+       ini_set('display_errors', 1);
+       $potextmeta = new PotExtMeta;
+       if (!isset($argv[1])) {
+               $potextmeta->usage();
+       }
+       $potextmeta->append( $argv[1], isset( $argv[2] ) ? $argv[2] : '-', isset( $argv[3] ) ? $argv[3] : null );
+}
+
+?>
</ins></span></pre></div>
<a id="trunktoolsi18ntExtractTestphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/t/ExtractTest.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/t/ExtractTest.php                               (rev 0)
+++ trunk/tools/i18n/t/ExtractTest.php  2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,160 @@
</span><ins>+<?php
+
+require_once dirname( dirname( __FILE__ ) ) . '/extract.php';
+
+class ExtractTest extends PHPUnit_Framework_TestCase {
+
+       function setUp() {
+               $this->extractor = new StringExtractor;
+               $this->extractor->rules = array(
+                       '__' => array('string'),
+               );
+       }
+
+       function test_with_just_a_string() {
+               $expected = new Translation_Entry( array( 'singular' => 'baba', 'references' => array('baba.php:1') ) );
+               $result = $this->extractor->extract_entries('<?php __("baba"); ?>', 'baba.php' );
+               $this->assertEquals( $expected, $result->entries['baba'] );
+       }
+
+       function test_entry_from_call_simple() {
+               $entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba') ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba' ) ) );
+       }
+
+       function test_entry_from_call_nonexisting_function() {
+               $entry = $this->extractor->entry_from_call( array( 'name' => 'f', 'args' => array('baba') ), 'baba.php' );
+               $this->assertEquals( $entry, null );
+       }
+
+       function test_entry_from_call_too_few_args() {
+               $entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array() ), 'baba.php' );
+               $this->assertEquals( $entry, null );
+       }
+
+       function test_entry_from_call_non_expected_null_arg() {
+               $this->extractor->rules = array( '_nx' => array( 'singular', 'plural', 'context' ) );
+               $entry = $this->extractor->entry_from_call( array( 'name' => '_nx', 'args' => array('%s baba', null, 'noun') ), 'baba.php' );
+               $this->assertEquals( $entry, null );
+       }
+
+       function test_entry_from_call_more_args_should_be_ok() {
+               $this->extractor->rules = array( '__' => array('string') );
+               $entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba', 5, 'pijo', null) ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba' ) ) );
+       }
+
+
+       function test_entry_from_call_context() {
+               $this->extractor->rules = array( '_x' => array( 'string', 'context' ) );
+               $entry = $this->extractor->entry_from_call( array( 'name' => '_x', 'args' => array('baba', 'noun') ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba', 'context' => 'noun' ) ) );
+       }
+
+       function test_entry_from_call_plural() {
+               $this->extractor->rules = array( '_n' => array( 'singular', 'plural' ) );
+               $entry = $this->extractor->entry_from_call( array( 'name' => '_n', 'args' => array('%s baba', '%s babas') ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => '%s baba', 'plural' => '%s babas' ) ) );
+       }
+
+       function test_entry_from_call_plural_and_context() {
+               $this->extractor->rules = array( '_nx' => array( 'singular', 'plural', 'context' ) );
+               $entry = $this->extractor->entry_from_call( array( 'name' => '_nx', 'args' => array('%s baba', '%s babas', 'noun') ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => '%s baba', 'plural' => '%s babas', 'context' => 'noun' ) ) );
+       }
+
+       function test_entry_from_call_extracted_comment() {
+               $entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba'), 'comment' => 'translators: give me back my pants!' ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba', 'extracted_comments' => "translators: give me back my pants!\n" ) ) );
+       }
+
+       function test_entry_from_call_line_number() {
+               $entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba'), 'line' => 10 ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba', 'references' => array('baba.php:10') ) ) );
+       }
+
+       function test_entry_from_call_zero() {
+               $entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('0') ), 'baba.php' );
+               $this->assertEquals( $entry, new Translation_Entry( array( 'singular' => '0' ) ) );
+       }
+
+       function test_entry_from_call_multiple() {
+               $this->extractor->rules = array( 'c' => array( 'string', 'singular', 'plural' ) );
+               $entries = $this->extractor->entry_from_call( array( 'name' => 'c', 'args' => array('baba', 'dyado', 'dyados') ), 'baba.php' );
+               $this->assertEquals( array(
+                               new Translation_Entry( array( 'singular' => 'baba' ) ), new Translation_Entry( array( 'singular' => 'dyado', 'plural' => 'dyados' ) ) ), $entries );
+       }
+
+       function test_entry_from_call_multiple_first_plural_then_two_strings() {
+               $this->extractor->rules = array( 'c' => array( 'singular', 'plural', null, 'string', 'string' ) );
+               $entries = $this->extractor->entry_from_call( array( 'name' => 'c', 'args' => array('dyado', 'dyados', 'baba', 'foo', 'bar') ), 'baba.php' );
+               $this->assertEquals( array(
+                               new Translation_Entry( array( 'singular' => 'dyado', 'plural' => 'dyados' ) ),
+                               new Translation_Entry( array( 'singular' => 'foo' ) ),
+                               new Translation_Entry( array( 'singular' => 'bar' ) ) ), $entries );
+       }
+
+       function test_find_function_calls_one_arg_literal() {
+               $this->assertEquals( array( array( 'name' => '__', 'args' => array( 'baba' ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('__'), '<?php __("baba"); ?>' ) );
+       }
+
+       function test_find_function_calls_one_arg_zero() {
+               $this->assertEquals( array( array( 'name' => '__', 'args' => array( '0' ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('__'), '<?php __("0"); ?>' ) );
+       }
+
+       function test_find_function_calls_one_arg_non_literal() {
+               $this->assertEquals( array( array( 'name' => '__', 'args' => array( null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('__'), '<?php __("baba" . "dudu"); ?>' ) );
+       }
+
+       function test_find_function_calls_shouldnt_be_mistaken_by_a_class() {
+               $this->assertEquals( array(), $this->extractor->find_function_calls( array('__'), '<?php class __ { }; ("dyado");' ) );
+       }
+
+       function test_find_function_calls_2_args_bad_literal() {
+               $this->assertEquals( array( array( 'name' => 'f', 'args' => array( null, "baba" ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f(5, "baba" ); ' ) );
+       }
+
+       function test_find_function_calls_2_args_bad_literal_bad() {
+               $this->assertEquals( array( array( 'name' => 'f', 'args' => array( null, "baba", null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f(5, "baba", 5 ); ' ) );
+       }
+
+       function test_find_function_calls_1_arg_bad_concat() {
+               $this->assertEquals( array( array( 'name' => 'f', 'args' => array( null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( "baba" . "baba" ); ' ) );
+       }
+
+       function test_find_function_calls_1_arg_bad_function_call() {
+               $this->assertEquals( array( array( 'name' => 'f', 'args' => array( null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( g( "baba" ) ); ' ) );
+       }
+
+       function test_find_function_calls_2_arg_literal_bad() {
+               $this->assertEquals( array( array( 'name' => 'f', 'args' => array( "baba", null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( "baba", null ); ' ) );
+       }
+
+       function test_find_function_calls_2_arg_bad_with_parens_literal() {
+               $this->assertEquals( array( array( 'name' => 'f', 'args' => array( null, "baba" ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( g( "dyado", "chicho", "lelya "), "baba" ); ' ) );
+       }
+
+       function test_find_function_calls_with_comment() {
+               $this->assertEquals(
+                       array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'translators: let your ears fly!' ) ),
+                       $this->extractor->find_function_calls( array('f'), '<?php /* translators: let your ears fly! */ f( "baba" ); ' ) );
+       }
+
+       function test_find_function_calls_with_not_immediate_comment() {
+               $this->assertEquals(
+                       array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'translators: let your ears fly!' ) ),
+                       $this->extractor->find_function_calls( array('f'), '<?php /* translators: let your ears fly! */ $foo = g ( f( "baba" ) ); ' ) );
+       }
+
+       function test_find_function_calls_with_not_immediate_comment_include_only_latest() {
+               $this->assertEquals(
+                       array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'translators: let your ears fly!' ) ),
+                       $this->extractor->find_function_calls( array('f'), '<?php /* translators: boo */ /* translators: let your ears fly! */ /* baba */ $foo = g ( f( "baba" ) ); ' ) );
+       }
+
+       function test_comment_prefix_should_be_case_insensitive() {
+               $this->assertEquals(
+                       array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'Translators: let your ears fly!' ) ),
+                       $this->extractor->find_function_calls( array('f'), '<?php /* Translators: let your ears fly! */ f( "baba" ); ' ) );
+       }
+}
</ins></span></pre></div>
<a id="trunktoolsi18ntNotGettextedTestphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/t/NotGettextedTest.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/t/NotGettextedTest.php                          (rev 0)
+++ trunk/tools/i18n/t/NotGettextedTest.php     2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+<?php
+/**
+ * Tests for not-gettexted.php
+ *
+ * @package wordpress-i18n
+ * @subpackage tools
+ */
+error_reporting( E_ALL );
+require_once dirname( dirname( __FILE__ ) ) . '/not-gettexted.php';
+
+class NotGettextedTest extends PHPUnit_Framework_TestCase {
+       
+       function __construct() {
+               $this->ng = new NotGettexted;
+       }
+       
+       function test_make_string_aggregator() {
+               global $baba;
+               $f = $this->ng->make_string_aggregator( 'baba', 'baba.php' );
+               call_user_func( $f, 'x', 'y', 'z' );
+               call_user_func( $f, 'a', 'b', 'c' );
+               $this->assertEquals( array( array( 'x', 'y', 'baba.php', 'z'), array( 'a', 'b', 'baba.php', 'c' ) ), $baba );
+       }
+
+       function test_walk() {
+               $code = '
+<?php
+       $s = 8;
+echo /* WP_I18N_GUGU*/         "yes" /* /WP_I18N_UGU         */;
+       if ($x == "18181") { wp_die(sprintf(/*WP_I18N_DIE*/\'We died %d times!\'/*WP_I18N_DIE*/)); }
+?>';
+               $tokens = token_get_all($code); 
+               $this->assertEquals( '', $this->ng->walk_tokens( $tokens, array(&$this->ng, 'ignore_token'), array(&$this->ng, 'ignore_token') ) );
+               $this->assertEquals( '"yes"\'We died %d times!\'', $this->ng->walk_tokens( $tokens, array(&$this->ng, 'unchanged_token'), array(&$this->ng, 'ignore_token') ) );
+               $this->assertEquals( $code, $this->ng->walk_tokens( $tokens, array(&$this->ng, 'unchanged_token'), array(&$this->ng, 'unchanged_token') ) );
+               $this->assertEquals( $code, $this->ng->walk_tokens( $tokens, array(&$this->ng, 'unchanged_token'), array(&$this->ng, 'unchanged_token') ) );
+       }
+
+       function test_replace() {
+               # copy to a new file, so that we don't corrupt the old one
+               copy( 'data/not-gettexted-0.php', 'data/not-gettexted-0-work.php' );
+               $this->ng->command_replace( 'data/not-gettexted-0.mo', 'data/not-gettexted-0-work.php' );
+               $this->assertEquals( file_get_contents( 'data/not-gettexted-0-result.php' ), file_get_contents( 'data/not-gettexted-0-work.php' ) );
+               unlink( 'data/not-gettexted-0-work.php' );
+       }
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunktoolsi18ntdatanotgettexted0resultphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/t/data/not-gettexted-0-result.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/t/data/not-gettexted-0-result.php                               (rev 0)
+++ trunk/tools/i18n/t/data/not-gettexted-0-result.php  2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+<?php
+
+if (! isset($wp_did_header)):
+if ( !file_exists( dirname(__FILE__) . '/wp-config.php') ) {
+       if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) $path = '';
+       else $path = 'wp-admin/';
+
+       require_once( dirname(__FILE__) . '/wp-includes/classes.php');
+       require_once( dirname(__FILE__) . '/wp-includes/functions.php');
+       require_once( dirname(__FILE__) . '/wp-includes/plugin.php');
+       wp_die( sprintf(/*WP_I18N_CONFIG*/'Translation: There doesn\'t seem to be a <code>wp-config.php</code> file. I need this before we can get started. Need more help? <a href=\'http://codex.wordpress.org/Editing_wp-config.php\'>We got it</a>. You can create a <code>wp-config.php</code> file through a web interface, but this doesn\'t work for all server setups. The safest way is to manually create the file.</p><p><a href=\'%s\' class=\'button\'>Create a Configuration File</a>' /*/WP_I18N_CONFIG*/, $path.'setup-config.php'), /*WP_I18N_ERROR*/ 'Translation: WordPress &rsaquo; Error' /*/WP_I18N_ERROR*/);
+}
+
+$wp_did_header = true;
+
+require_once( dirname(__FILE__) . '/wp-config.php');
+
+wp();
+
+require_once(ABSPATH . WPINC . '/template-loader.php');
+
+endif;
+
+?>
</ins></span></pre></div>
<a id="trunktoolsi18ntdatanotgettexted0workphp"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/t/data/not-gettexted-0-work.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/t/data/not-gettexted-0-work.php                         (rev 0)
+++ trunk/tools/i18n/t/data/not-gettexted-0-work.php    2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+<?php
+
+if (! isset($wp_did_header)):
+if ( !file_exists( dirname(__FILE__) . '/wp-config.php') ) {
+       if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) $path = '';
+       else $path = 'wp-admin/';
+
+       require_once( dirname(__FILE__) . '/wp-includes/classes.php');
+       require_once( dirname(__FILE__) . '/wp-includes/functions.php');
+       require_once( dirname(__FILE__) . '/wp-includes/plugin.php');
+       wp_die( sprintf(/*WP_I18N_CONFIG*/'Translation: There doesn\'t seem to be a <code>wp-config.php</code> file. I need this before we can get started. Need more help? <a href=\'http://codex.wordpress.org/Editing_wp-config.php\'>We got it</a>. You can create a <code>wp-config.php</code> file through a web interface, but this doesn\'t work for all server setups. The safest way is to manually create the file.</p><p><a href=\'%s\' class=\'button\'>Create a Configuration File</a>' /*/WP_I18N_CONFIG*/, $path.'setup-config.php'), /*WP_I18N_ERROR*/ 'Translation: WordPress &rsaquo; Error' /*/WP_I18N_ERROR*/);
+}
+
+$wp_did_header = true;
+
+require_once( dirname(__FILE__) . '/wp-config.php');
+
+wp();
+
+require_once(ABSPATH . WPINC . '/template-loader.php');
+
+endif;
+
+?>
</ins></span></pre></div>
<a id="trunktoolsi18ntdatanotgettexted0mo"></a>
<div class="binary"><h4>Added: trunk/tools/i18n/t/data/not-gettexted-0.mo</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Index: trunk/tools/i18n/t/data/not-gettexted-0.mo
</span><span class="cx">===================================================================
</span><del>--- trunk/tools/i18n/t/data/not-gettexted-0.mo  2013-08-07 06:38:38 UTC (rev 25002)
</del><ins>+++ trunk/tools/i18n/t/data/not-gettexted-0.mo   2013-08-07 06:44:08 UTC (rev 25003)
</ins><span class="cx">Property changes on: trunk/tools/i18n/t/data/not-gettexted-0.mo
</span><span class="cx">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<ins>+application/octet-stream
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktoolsi18ntdatanotgettexted0php"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/t/data/not-gettexted-0.php (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/t/data/not-gettexted-0.php                              (rev 0)
+++ trunk/tools/i18n/t/data/not-gettexted-0.php 2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+<?php
+
+if (! isset($wp_did_header)):
+if ( !file_exists( dirname(__FILE__) . '/wp-config.php') ) {
+       if (strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false) $path = '';
+       else $path = 'wp-admin/';
+
+       require_once( dirname(__FILE__) . '/wp-includes/classes.php');
+       require_once( dirname(__FILE__) . '/wp-includes/functions.php');
+       require_once( dirname(__FILE__) . '/wp-includes/plugin.php');
+       wp_die( sprintf(/*WP_I18N_CONFIG*/" There doesn't seem to be a <code>wp-config.php</code> file. I need this before we can get started. Need more help? <a href='http://codex.wordpress.org/Editing_wp-config.php'>We got it</a>. You can create a <code>wp-config.php</code> file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file.</p><p><a href='%s' class='button'>Create a Configuration File</a>" /*/WP_I18N_CONFIG*/, $path.'setup-config.php'), /*WP_I18N_ERROR*/ "WordPress &rsaquo; Error" /*/WP_I18N_ERROR*/);
+}
+
+$wp_did_header = true;
+
+require_once( dirname(__FILE__) . '/wp-config.php');
+
+wp();
+
+require_once(ABSPATH . WPINC . '/template-loader.php');
+
+endif;
+
+?>
</ins></span></pre></div>
<a id="trunktoolsi18ntdatanotgettexted0po"></a>
<div class="addfile"><h4>Added: trunk/tools/i18n/t/data/not-gettexted-0.po (0 => 25003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tools/i18n/t/data/not-gettexted-0.po                               (rev 0)
+++ trunk/tools/i18n/t/data/not-gettexted-0.po  2013-08-07 06:44:08 UTC (rev 25003)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2008-04-22 19:23+0200\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Not gettexted string WP_I18N_CONFIG
+#: not-gettext-0.php:11
+msgid " There doesn't seem to be a <code>wp-config.php</code> file. I need this before we can get started. Need more help? <a href='http://codex.wordpress.org/Editing_wp-config.php'>We got it</a>. You can create a <code>wp-config.php</code> file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file.</p><p><a href='%s' class='button'>Create a Configuration File</a>"
+msgstr "Translation: There doesn't seem to be a <code>wp-config.php</code> file. I need this before we can get started. Need more help? <a href='http://codex.wordpress.org/Editing_wp-config.php'>We got it</a>. You can create a <code>wp-config.php</code> file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file.</p><p><a href='%s' class='button'>Create a Configuration File</a>"
+
+#. Not gettexted string WP_I18N_ERROR
+#: not-gettext-0.php:11
+msgid "WordPress &rsaquo; Error"
+msgstr "Translation: WordPress &rsaquo; Error"
+
</ins></span></pre>
</div>
</div>

</body>
</html>