Tools: Remove internationalization tools (also known as makepot.php
).
It has been a great pleasure to work with `makepot.php` over the past [https://i18n.trac.wordpress.org/changeset/4169/ 11 years] but now it's time to say goodbye. The tools have been integrated into WP-CLI as [https://developer.wordpress.org/cli/commands/i18n/make-pot/ wp i18n make-pot] and [https://developer.wordpress.org/cli/commands/i18n/make-json/ wp i18n make-json]. The new commands were optimized to support current PHP versions and are more flexible and reliable when extracting strings for PHP, and JavaScript. Access to the old tools continue to exist in previous branches or at https://i18n.svn.wordpress.org/tools/. Fixes #45287. git-svn-id: https://develop.svn.wordpress.org/trunk@45686 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
84b977945c
commit
2f1afbcf79
@ -1,160 +0,0 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$makepot = new MakePOT;
|
||||
$this->funcs = array_keys( $makepot->rules );
|
||||
$this->funcs[] = 'translate_nooped_plural';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints CLI usage.
|
||||
*/
|
||||
public 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds textdomain to a single file.
|
||||
*
|
||||
* @see AddTextdomain::process_string()
|
||||
*
|
||||
* @param string $domain Text domain.
|
||||
* @param string $source_filename Filename with optional path.
|
||||
* @param bool $inplace True to modifies the PHP file in place. False to print to standard output.
|
||||
*/
|
||||
public function process_file( $domain, $source_filename, $inplace ) {
|
||||
$new_source = $this->process_string( $domain, file_get_contents( $source_filename ) );
|
||||
|
||||
if ( $inplace ) {
|
||||
$f = fopen( $source_filename, 'w' );
|
||||
fwrite( $f, $new_source );
|
||||
fclose( $f );
|
||||
} else {
|
||||
echo $new_source;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds textdomain to a string of PHP.
|
||||
*
|
||||
* Functions calls should be wrapped in opening and closing PHP delimiters as usual.
|
||||
*
|
||||
* @see AddTextdomain::process_tokens()
|
||||
*
|
||||
* @param string $domain Text domain.
|
||||
* @param string $string PHP code to parse.
|
||||
* @return string Modified source.
|
||||
*/
|
||||
public function process_string( $domain, $string ) {
|
||||
$tokens = token_get_all( $string );
|
||||
return $this->process_tokens( $domain, $tokens );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds textdomain to a set of PHP tokens.
|
||||
*
|
||||
* @param string $domain Text domain.
|
||||
* @param array $tokens PHP tokens. An array of token identifiers. Each individual token identifier is either a
|
||||
* single character (i.e.: ;, ., >, !, etc.), or a three element array containing the token
|
||||
* index in element 0, the string content of the original token in element 1 and the line
|
||||
* number in element 2.
|
||||
* @return string Modified source.
|
||||
*/
|
||||
public function process_tokens( $domain, $tokens ) {
|
||||
$this->modified_contents = '';
|
||||
$domain = addslashes( $domain );
|
||||
|
||||
$in_func = false;
|
||||
$args_started = false;
|
||||
$parens_balance = 0;
|
||||
$found_domain = false;
|
||||
|
||||
foreach($tokens as $index => $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) {
|
||||
if ( ! $found_domain ) {
|
||||
$token = ", '$domain'";
|
||||
if ( T_WHITESPACE == $tokens[ $index - 1 ][0] ) {
|
||||
$token .= ' '; // Maintain code standards if previously present
|
||||
// Remove previous whitespace token to account for it.
|
||||
$this->modified_contents = trim( $this->modified_contents );
|
||||
}
|
||||
$token .= ')';
|
||||
}
|
||||
$in_func = false;
|
||||
$args_started = false;
|
||||
$found_domain = false;
|
||||
}
|
||||
}
|
||||
$this->modified_contents .= $token;
|
||||
}
|
||||
|
||||
return $this->modified_contents;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if ( is_dir( $argv[2] ) ) {
|
||||
$directory = new RecursiveDirectoryIterator( $argv[2], RecursiveDirectoryIterator::SKIP_DOTS );
|
||||
$files = new RecursiveIteratorIterator( $directory );
|
||||
foreach ( $files as $file ) {
|
||||
if ( 'php' === $file->getExtension() ) {
|
||||
$adddomain->process_file( $argv[1], $file->getPathname(), $inplace );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$adddomain->process_file( $argv[1], $argv[2], $inplace );
|
||||
}
|
||||
}
|
@ -1,222 +0,0 @@
|
||||
<?php
|
||||
$pomo = dirname( dirname( dirname( __FILE__ ) ) ) . '/src/wp-includes/pomo';
|
||||
require_once "$pomo/entry.php";
|
||||
require_once "$pomo/translations.php";
|
||||
|
||||
/**
|
||||
* Responsible for extracting translatable strings from PHP source files
|
||||
* in the form of Translations instances
|
||||
*/
|
||||
class StringExtractor {
|
||||
|
||||
var $rules = array(
|
||||
'__' => array( 'string' ),
|
||||
'_e' => array( 'string' ),
|
||||
'_n' => array( 'singular', 'plural' ),
|
||||
);
|
||||
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 ) ) {
|
||||
$extracted = $this->extract_from_file( $file_name, $prefix );
|
||||
$translations->merge_originals_with( $extracted );
|
||||
}
|
||||
if ( is_dir( $file_name ) ) {
|
||||
$extracted = $this->extract_from_directory( $file_name, $excludes, $includes, $prefix . $file_name . '/' );
|
||||
$translations->merge_originals_with( $extracted );
|
||||
}
|
||||
}
|
||||
chdir( $old_cwd );
|
||||
return $translations;
|
||||
}
|
||||
|
||||
function extract_from_file( $file_name, $prefix ) {
|
||||
$code = file_get_contents( $file_name );
|
||||
return $this->extract_from_code( $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_from_code( $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 = preg_replace( '%^\s+\*\s%m', '', $text );
|
||||
$text = str_replace( array( "\r\n", "\n" ), ' ', $text );;
|
||||
$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;
|
||||
}
|
||||
}
|
@ -1,639 +0,0 @@
|
||||
<?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 to create POT files for
|
||||
* - WordPress 3.4+
|
||||
* - WordPress plugins
|
||||
* - WordPress themes
|
||||
* - GlotPress (standalone)
|
||||
* - WordPress.org projects (Rosetta, forums, directories)
|
||||
* - WordCamp.org
|
||||
*
|
||||
* Support for older projects can be found in the legacy branch:
|
||||
* https://i18n.trac.wordpress.org/browser/tools/branches/legacy
|
||||
*/
|
||||
class MakePOT {
|
||||
private $max_header_lines = 30;
|
||||
|
||||
public $projects = array(
|
||||
'generic',
|
||||
'wp-frontend',
|
||||
'wp-admin',
|
||||
'wp-network-admin',
|
||||
'wp-tz',
|
||||
'wp-plugin',
|
||||
'wp-theme',
|
||||
'glotpress',
|
||||
'rosetta',
|
||||
'wporg-bb-forums',
|
||||
'wporg-themes',
|
||||
'wporg-plugins',
|
||||
'wporg-forums',
|
||||
'wordcamporg',
|
||||
);
|
||||
|
||||
public $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'),
|
||||
);
|
||||
|
||||
private $ms_files = array(
|
||||
'ms-.*', '.*/ms-.*', '.*/my-.*', 'wp-activate\.php', 'wp-signup\.php',
|
||||
'wp-admin/network\.php', 'wp-admin/network/.*\.php', 'wp-admin/includes/ms\.php',
|
||||
'wp-admin/includes/class-wp-ms.*', 'wp-admin/includes/network\.php',
|
||||
);
|
||||
|
||||
private $temp_files = array();
|
||||
|
||||
public $meta = array(
|
||||
'default' => array(
|
||||
'from-code' => 'utf-8',
|
||||
'msgid-bugs-address' => 'https://make.wordpress.org/polyglots/',
|
||||
'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-tz' => array(
|
||||
'description' => 'Translation of timezone strings in WordPress {version}',
|
||||
'copyright-holder' => 'WordPress',
|
||||
'package-name' => 'WordPress',
|
||||
'package-version' => '{version}',
|
||||
),
|
||||
'wp-plugin' => array(
|
||||
'description' => 'Translation of the WordPress plugin {name} {version} by {author}',
|
||||
'msgid-bugs-address' => 'https://wordpress.org/support/plugin/{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' => 'https://wordpress.org/support/theme/{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.',
|
||||
),
|
||||
'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',
|
||||
),
|
||||
'wporg' => array(
|
||||
'description' => 'WordPress.org',
|
||||
'copyright-holder' => 'WordPress',
|
||||
'package-name' => 'WordPress.org',
|
||||
),
|
||||
'wordcamporg' => array(
|
||||
'description' => 'WordCamp.org',
|
||||
'copyright-holder' => 'WordPress',
|
||||
'package-name' => 'WordCamp.org',
|
||||
),
|
||||
'rosetta' => array(
|
||||
'description' => 'Rosetta (.wordpress.org locale sites)',
|
||||
'copyright-holder' => 'WordPress',
|
||||
'package-name' => 'Rosetta',
|
||||
),
|
||||
);
|
||||
|
||||
public function __construct($deprecated = true) {
|
||||
$this->extractor = new StringExtractor( $this->rules );
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
foreach ( $this->temp_files as $temp_file )
|
||||
unlink( $temp_file );
|
||||
}
|
||||
|
||||
private function tempnam( $file ) {
|
||||
$tempnam = tempnam( sys_get_temp_dir(), $file );
|
||||
$this->temp_files[] = $tempnam;
|
||||
return $tempnam;
|
||||
}
|
||||
|
||||
private function realpath_missing($path) {
|
||||
return realpath(dirname($path)).DIRECTORY_SEPARATOR.basename($path);
|
||||
}
|
||||
|
||||
private 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;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public function wp_frontend( $dir, $output ) {
|
||||
if ( ! file_exists( "$dir/wp-admin/user/about.php" ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$excludes = array( 'wp-admin/.*', 'wp-content/themes/.*', 'wp-includes/class-pop3\.php' );
|
||||
|
||||
// Exclude Akismet all together for 3.9+.
|
||||
if ( file_exists( "$dir/wp-admin/css/about.css" ) ) {
|
||||
$excludes[] = 'wp-content/plugins/akismet/.*';
|
||||
}
|
||||
|
||||
return $this->wp_generic( $dir, array(
|
||||
'project' => 'wp-frontend', 'output' => $output,
|
||||
'includes' => array(),
|
||||
'excludes' => $excludes,
|
||||
'default_output' => 'wordpress.pot',
|
||||
) );
|
||||
}
|
||||
|
||||
public function wp_admin($dir, $output) {
|
||||
$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;
|
||||
}
|
||||
|
||||
$network_admin_files = $this->get_wp_network_admin_files( $dir );
|
||||
|
||||
$result = $this->wp_generic( $dir, array(
|
||||
'project' => 'wp-admin', 'output' => $output,
|
||||
'includes' => array( 'wp-admin/.*' ),
|
||||
'excludes' => array_merge( array( 'wp-admin/includes/continents-cities\.php' ), $network_admin_files ),
|
||||
'default_output' => 'wordpress-admin.pot',
|
||||
) );
|
||||
if ( ! $result ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$potextmeta = new PotExtMeta;
|
||||
|
||||
if ( ! file_exists( "$dir/wp-admin/css/about.css" ) ) { // < 3.9
|
||||
$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;
|
||||
}
|
||||
|
||||
public 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' => $this->get_wp_network_admin_files( $dir ),
|
||||
'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;
|
||||
}
|
||||
|
||||
private function get_wp_network_admin_files( $dir ) {
|
||||
$wp_version = $this->wp_version( $dir );
|
||||
|
||||
// https://core.trac.wordpress.org/ticket/19852
|
||||
$files = array( 'wp-admin/network/.*', 'wp-admin/network.php' );
|
||||
|
||||
// https://core.trac.wordpress.org/ticket/34910
|
||||
if ( version_compare( $wp_version, '4.5-beta', '>=' ) ) {
|
||||
$files = array_merge( $files, array(
|
||||
'wp-admin/includes/class-wp-ms.*',
|
||||
'wp-admin/includes/network.php',
|
||||
) );
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
public function wp_tz( $dir, $output ) {
|
||||
return $this->wp_generic( $dir, array(
|
||||
'project' => 'wp-tz', 'output' => $output,
|
||||
'includes' => array( 'wp-admin/includes/continents-cities\.php' ),
|
||||
'excludes' => array(),
|
||||
'default_output' => 'wordpress-continents-cities.pot',
|
||||
) );
|
||||
}
|
||||
|
||||
private 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;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
// PHP will close file handle, but we are good citizens.
|
||||
fclose( $extf );
|
||||
|
||||
// Make sure we catch CR-only line endings.
|
||||
$first_lines = str_replace( "\r", "\n", $first_lines );
|
||||
|
||||
return $first_lines;
|
||||
}
|
||||
|
||||
public function get_addon_header($header, &$source) {
|
||||
/*
|
||||
* A few things this needs to handle:
|
||||
* - 'Header: Value\n'
|
||||
* - '// Header: Value'
|
||||
* - '/* Header: Value * /'
|
||||
* - '<?php // Header: Value ?>'
|
||||
* - '<?php /* Header: Value * / $foo='bar'; ?>'
|
||||
*/
|
||||
if ( preg_match( '/^(?:[ \t]*<\?php)?[ \t\/*#@]*' . preg_quote( $header, '/' ) . ':(.*)$/mi', $source, $matches ) ) {
|
||||
return $this->_cleanup_header_comment( $matches[1] );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any trailing closing comment / PHP tags from the header value
|
||||
*/
|
||||
private function _cleanup_header_comment( $str ) {
|
||||
return trim( preg_replace( '/\s*(?:\*\/|\?>).*/', '', $str ) );
|
||||
}
|
||||
|
||||
public function generic($dir, $output) {
|
||||
$output = is_null($output)? "generic.pot" : $output;
|
||||
return $this->xgettext('generic', $dir, $output, array());
|
||||
}
|
||||
|
||||
private 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;
|
||||
}
|
||||
|
||||
public function wp_plugin( $dir, $output, $slug = null, $args = array() ) {
|
||||
$defaults = array(
|
||||
'excludes' => array(),
|
||||
'includes' => array(),
|
||||
);
|
||||
$args = array_merge( $defaults, $args );
|
||||
$placeholders = array();
|
||||
// guess plugin slug
|
||||
if (is_null($slug)) {
|
||||
$slug = $this->guess_plugin_slug($dir);
|
||||
}
|
||||
|
||||
$plugins_dir = @opendir( $dir );
|
||||
$plugin_files = array();
|
||||
if ( $plugins_dir ) {
|
||||
while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
|
||||
if ( '.' === substr( $file, 0, 1 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( '.php' === substr( $file, -4 ) ) {
|
||||
$plugin_files[] = $file;
|
||||
}
|
||||
}
|
||||
closedir( $plugins_dir );
|
||||
}
|
||||
|
||||
if ( empty( $plugin_files ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$main_file = '';
|
||||
foreach ( $plugin_files as $plugin_file ) {
|
||||
if ( ! is_readable( "$dir/$plugin_file" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$source = $this->get_first_lines( "$dir/$plugin_file", $this->max_header_lines );
|
||||
|
||||
// Stop when we find a file with a plugin name header in it.
|
||||
if ( $this->get_addon_header( 'Plugin Name', $source ) != false ) {
|
||||
$main_file = "$dir/$plugin_file";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $main_file ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$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, $args['excludes'], $args['includes'] );
|
||||
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;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public function glotpress( $dir, $output ) {
|
||||
$output = is_null( $output ) ? "glotpress.pot" : $output;
|
||||
return $this->xgettext( 'glotpress', $dir, $output );
|
||||
}
|
||||
|
||||
public 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/.*',
|
||||
'themes/.*',
|
||||
) );
|
||||
}
|
||||
|
||||
public function wporg_themes( $dir, $output ) {
|
||||
$output = is_null( $output ) ? 'wporg-themes.pot' : $output;
|
||||
return $this->xgettext( 'wporg', $dir, $output, array(), array(), array(
|
||||
'plugins/theme-directory/.*',
|
||||
'themes/pub/wporg-themes/.*'
|
||||
) );
|
||||
}
|
||||
|
||||
public function wporg_plugins( $dir, $output ) {
|
||||
$output = is_null( $output ) ? 'wporg-plugins.pot' : $output;
|
||||
return $this->xgettext( 'wporg', $dir, $output, array(), array(
|
||||
'plugins/svn-track/i18n-tools/.*'
|
||||
), array(
|
||||
'.*\.php',
|
||||
) );
|
||||
}
|
||||
|
||||
public function wporg_forums( $dir, $output ) {
|
||||
$output = is_null( $output ) ? 'wporg-forums.pot' : $output;
|
||||
return $this->xgettext( 'wporg', $dir, $output, array(), array(), array(
|
||||
'.*\.php',
|
||||
) );
|
||||
}
|
||||
|
||||
public function wordcamporg( $dir, $output ) {
|
||||
$output = is_null( $output ) ? 'wordcamporg.pot' : $output;
|
||||
return $this->xgettext( 'wordcamporg', $dir, $output, array(), array(), array(
|
||||
'.*\.php',
|
||||
) );
|
||||
}
|
||||
|
||||
public function rosetta( $dir, $output ) {
|
||||
$output = is_null( $output )? 'rosetta.pot' : $output;
|
||||
return $this->xgettext( 'rosetta', $dir, $output, array(), array(
|
||||
'mu-plugins/rosetta/i18n-tools/.*',
|
||||
'mu-plugins/rosetta/locales/.*',
|
||||
), array(
|
||||
'mu-plugins/(roles|showcase|downloads)/.*\.php',
|
||||
'mu-plugins/jetpack-settings.php',
|
||||
'mu-plugins/rosetta.*\.php',
|
||||
'mu-plugins/rosetta/[^/]+\.php',
|
||||
'mu-plugins/rosetta/tmpl/.*\.php',
|
||||
'themes/rosetta/.*\.php',
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -1,234 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Console application, which extracts or replaces strings for
|
||||
* translation, which cannot be gettexted
|
||||
*
|
||||
* @package wordpress-i18n
|
||||
* @subpackage tools
|
||||
*/
|
||||
// see: https://secure.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();
|
||||
}
|
||||
|
||||
?>
|
@ -1,78 +0,0 @@
|
||||
<?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) {
|
||||
$makepot = new MakePOT;
|
||||
$source = $makepot->get_first_lines($ext_filename);
|
||||
$pot = '';
|
||||
$po = new PO;
|
||||
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 );
|
||||
}
|
||||
|
||||
?>
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for add-textdomain.php
|
||||
*
|
||||
* @package wordpress-i18n
|
||||
* @subpackage tools
|
||||
*/
|
||||
error_reporting( E_ALL );
|
||||
require_once dirname( dirname( __FILE__ ) ) . '/add-textdomain.php';
|
||||
|
||||
class AddTextDomainTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
$this->atd = new AddTextdomain();
|
||||
}
|
||||
|
||||
function test_add() {
|
||||
// Copy to a new file, so that we don't corrupt the old one.
|
||||
copy( 'data/add-textdomain-0.php', 'data/add-textdomain-0-work.php' );
|
||||
$this->atd->process_file( 'test-domain', 'data/add-textdomain-0-work.php', true );
|
||||
$this->assertEquals( file_get_contents( 'data/add-textdomain-0-result.php' ), file_get_contents( 'data/add-textdomain-0-work.php' ) );
|
||||
unlink( 'data/add-textdomain-0-work.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data_textdomain_sources
|
||||
*/
|
||||
function test_basic_add_textdomain( $source, $expected ) {
|
||||
$tokens = token_get_all( $source );
|
||||
$result = $this->atd->process_tokens( 'foo', $tokens );
|
||||
$this->assertEquals( $expected, $result );
|
||||
}
|
||||
|
||||
function data_textdomain_sources() {
|
||||
return array(
|
||||
array( "<?php __('string'); ?>", "<?php __('string', 'foo'); ?>" ), // Simple single quotes
|
||||
array( '<?php __("string"); ?>', "<?php __(\"string\", 'foo'); ?>" ), // Simple double quotes
|
||||
array( "<?php __( 'string' ); ?>", "<?php __( 'string', 'foo' ); ?>" ), // Simple single quotes CS
|
||||
array( '<?php __( "string" ); ?>', "<?php __( \"string\", 'foo' ); ?>" ), // Simple double quotes CS
|
||||
array( "<?php __( 'string', 'string2' ); ?>", "<?php __( 'string', 'string2', 'foo' ); ?>" ), // Multiple string args
|
||||
array( '<?php __( \'string\', $var ); ?>', '<?php __( \'string\', $var, \'foo\' ); ?>' ), // Multiple string / var args
|
||||
array( "<?php __( 'string', 'foo' ); ?>", "<?php __( 'string', 'foo' ); ?>" ), // Existing textdomain
|
||||
);
|
||||
}
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
<?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_from_code('<?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" ); ' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
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" ); ' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
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" ) ); ' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
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" ) ); ' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
function test_find_function_calls_with_multi_line_comment() {
|
||||
$this->assertEquals( array( array(
|
||||
'name' => '__', 'args' => array( 'on' ), 'line' => 6,
|
||||
'comment' => "Translators: If there are characters in your language that are not supported by Lato, translate this to 'off'. Do not translate into your own language."
|
||||
) ),
|
||||
$this->extractor->find_function_calls( array( '__' ),
|
||||
"<?php
|
||||
/*
|
||||
* Translators: If there are characters in your language that are not supported
|
||||
* by Lato, translate this to 'off'. Do not translate into your own language.
|
||||
*/
|
||||
__( 'on' );"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
function test_find_function_calls_with_c_style_comment() {
|
||||
$this->assertEquals( array( array(
|
||||
'name' => '__', 'args' => array( 'on' ), 'line' => 3,
|
||||
'comment' => 'translators: let your ears fly!'
|
||||
) ),
|
||||
$this->extractor->find_function_calls( array( '__' ),
|
||||
"<?php
|
||||
// translators: let your ears fly!
|
||||
__( 'on' );"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
function test_find_function_calls_with_url_in_comment() {
|
||||
$this->assertEquals( array( array(
|
||||
'name' => '__', 'args' => array( 'F j, Y g:i a' ), 'line' => 3,
|
||||
'comment' => 'translators: localized date and time format, see https://secure.php.net/date'
|
||||
) ),
|
||||
$this->extractor->find_function_calls( array( '__' ),
|
||||
"<?php
|
||||
/* translators: localized date and time format, see https://secure.php.net/date */
|
||||
__( 'F j, Y g:i a' );"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comment
|
||||
*/
|
||||
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" ); ' )
|
||||
);
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?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' );
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
function call_some_i18n_methods() {
|
||||
__( 'Hello World', 'test-domain' );
|
||||
_e( 'Hello World', 'test-domain' );
|
||||
_n( 'Single', 'Plural', 1, 'test-domain' );
|
||||
_n_noop( 'Single Noop', 'Plural Noop', 1, 'test-domain' );
|
||||
_x( 'Hello World', 'Testing', 'test-domain' );
|
||||
_ex( 'Hello World', 'Testing', 'test-domain' );
|
||||
_nx( 'Hello World', 'Testing', 'test-domain' );
|
||||
_nx_noop( 'Hello World Noop', 'Testing', 'test-domain' );
|
||||
esc_attr__( 'Attribute', 'test-domain' );
|
||||
esc_html__( 'HTML', 'test-domain' );
|
||||
esc_attr_e( 'Attribute', 'test-domain' );
|
||||
esc_html_e( 'HTML', 'test-domain' );
|
||||
esc_attr_x( 'Attribute', 'Testing', 'test-domain' );
|
||||
esc_html_x( 'HTML', 'Testing', 'test-domain' );
|
||||
translate_nooped_plural( 'Plural Noop', 2, 'test-domain' );
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
function call_some_i18n_methods() {
|
||||
__( 'Hello World' );
|
||||
_e( 'Hello World' );
|
||||
_n( 'Single', 'Plural', 1 );
|
||||
_n_noop( 'Single Noop', 'Plural Noop', 1 );
|
||||
_x( 'Hello World', 'Testing' );
|
||||
_ex( 'Hello World', 'Testing' );
|
||||
_nx( 'Hello World', 'Testing' );
|
||||
_nx_noop( 'Hello World Noop', 'Testing' );
|
||||
esc_attr__( 'Attribute' );
|
||||
esc_html__( 'HTML' );
|
||||
esc_attr_e( 'Attribute' );
|
||||
esc_html_e( 'HTML' );
|
||||
esc_attr_x( 'Attribute', 'Testing' );
|
||||
esc_html_x( 'HTML', 'Testing' );
|
||||
translate_nooped_plural( 'Plural Noop', 2 );
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
<?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=\'https://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 › Error' /*/WP_I18N_ERROR*/);
|
||||
}
|
||||
|
||||
$wp_did_header = true;
|
||||
|
||||
require_once( dirname(__FILE__) . '/wp-config.php');
|
||||
|
||||
wp();
|
||||
|
||||
require_once(ABSPATH . WPINC . '/template-loader.php');
|
||||
|
||||
endif;
|
||||
|
||||
?>
|
Binary file not shown.
@ -1,24 +0,0 @@
|
||||
<?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='https://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 › Error" /*/WP_I18N_ERROR*/);
|
||||
}
|
||||
|
||||
$wp_did_header = true;
|
||||
|
||||
require_once( dirname(__FILE__) . '/wp-config.php');
|
||||
|
||||
wp();
|
||||
|
||||
require_once(ABSPATH . WPINC . '/template-loader.php');
|
||||
|
||||
endif;
|
||||
|
||||
?>
|
@ -1,21 +0,0 @@
|
||||
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 › Error"
|
||||
msgstr "Translation: WordPress › Error"
|
||||
|
Loading…
x
Reference in New Issue
Block a user