/gallery2/lib/tools/po/extract.php
PHP | 288 lines | 208 code | 16 blank | 64 comment | 93 complexity | 8bdcecf10408905cf35c1d59d45a9030 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MIT, LGPL-3.0
- #!/usr/bin/php -f
- <?php
- /*
- * PHP script to extract strings from all the files and print
- * to stdout for use with xgettext.
- *
- * This script is based on the perl script provided with the Horde project
- * http://www.horde.org/. As such, it inherits the license from the
- * original version. You can find that license here:
- *
- * http://cvs.horde.org/co.php/horde/COPYING?r=2.1
- *
- * I'm not exactly sure what the license restrictions are in this case,
- * but I want to give full credit to the original authors:
- *
- * Copyright 2000-2002 Joris Braakman <jbraakman@yahoo.com>
- * Copyright 2001-2002 Chuck Hagenbuch <chuck@horde.org>
- * Copyright 2001-2002 Jan Schneider <jan@horde.org>
- *
- * We've modified the script somewhat to make it work cleanly with the
- * way that Gallery embeds internationalized text, so let's tack on our
- * own copyrights.
- *
- * Copyright (C) 2002-2008 Bharat Mediratta <bharat@menalto.com>
- *
- * $Id: extract.php 17580 2008-04-13 00:38:13Z tnalmdal $
- */
- if (!empty($_SERVER['SERVER_NAME'])) {
- errorExit("You must run this from the command line\n");
- }
- if (!function_exists('token_get_all')) {
- errorExit("PHP tokenizer required.\n"
- . "Must use a PHP binary that is NOT built with --disable-tokenizer\n");
- }
- $exts = '(class|php|inc|css|html|tpl)';
- $idEmitted = false;
- $strings = array();
- array_shift($_SERVER['argv']);
- foreach ($_SERVER['argv'] as $moduleDir) {
- if (preg_match('#^/cygdrive/(\w+)/(.*)$#', trim($moduleDir), $matches)) {
- /* Cygwin and Window PHP filesystem function don't play nice together. */
- $moduleDir = $matches[1] . ':\\' . str_replace('/', '\\', $matches[2]);
- }
- if (!is_dir($moduleDir)) {
- continue;
- }
- chdir($moduleDir);
- find('.');
- $oldStringsRaw = "$moduleDir/po/strings.raw";
- if (file_exists($oldStringsRaw)) {
- $lines = file($oldStringsRaw);
- if (preg_match('/^#.*Id/', $lines[0])) {
- print $lines[0];
- $idEmitted = true;
- }
- }
- }
- if (!$idEmitted) {
- print '# $' . 'Id$' . "\n";
- }
- foreach ($strings as $string => $otherFiles) {
- print $string;
- if (!empty($otherFiles)) {
- print ' /* also in: ' . implode(' ', $otherFiles) . ' */';
- }
- print "\n";
- }
- /**
- * Recursive go through subdirectories
- */
- function find($dir) {
- if ($dh = opendir($dir)) {
- $listing = $subdirs = array();
- while (($file = readdir($dh)) !== false) {
- if ($file == '.' || $file == '..') {
- continue;
- }
- $listing[] = $file;
- }
- closedir($dh);
- sort($listing);
- global $exts;
- $dir = ($dir == '.') ? '' : ($dir . '/');
- foreach ($listing as $file) {
- $filename = $dir . $file;
- if (is_dir($filename)) {
- /* Don't parse unit tests */
- if ($file != 'test') {
- $subdirs[] = $filename;
- }
- } else if (preg_match('/\.' . $exts . '$/', $file)) {
- extractStrings($filename);
- }
- }
- foreach ($subdirs as $dir) {
- find($dir);
- }
- }
- }
- /**
- * Grab all translatable strings in a file into $strings array
- */
- function extractStrings($filename) {
- global $strings;
- $strings["\n/* $filename */"] = array();
- $startSize = count($strings);
- $localStrings = array();
- $data = file_get_contents($filename);
- /*
- * class|inc|php are module and core PHP files.
- * Parse .html as PHP for installer/upgrader templates/*.html files.
- * Parse .css as PHP for modules/colorpack/packs/{name}/color.css files.
- */
- if (preg_match('/\.(class|inc|php|css|html)$/', $filename)) {
- /* Tokenize PHP code and process to find translate( or i18n( or _( calls */
- $tokens = token_get_all($data);
- for ($i = 0; $i < count($tokens); $i++) {
- if (is_array($tokens[$i]) && $tokens[$i][0] == T_STRING
- && in_array($tokens[$i][1], array('translate', '_translate', 'i18n', '_'))
- && $tokens[$i + 1] === '(') {
- /* Found a function call for translation, process the contents */
- for ($i += 2; is_array($tokens[$i]) && $tokens[$i][0] == T_WHITESPACE; $i++) { }
- if (is_array($tokens[$i]) && $tokens[$i][0] == T_VARIABLE) {
- /* Skip translate($variable) */
- continue;
- }
- for ($buf = '', $parenCount = $ignore = 0; $i < count($tokens); $i++) {
- /* Fill $buf with translation params; so end at , or ) not in a nested () */
- if (!$parenCount && ($tokens[$i] === ')' || $tokens[$i] === ',')) {
- break;
- }
- if ($ignore && $parenCount == $ignore
- && ($tokens[$i] === ',' || $tokens[$i] === ')')) {
- $ignore = false;
- }
- if ($tokens[$i] === '(') {
- $parenCount++;
- } else if ($tokens[$i] === ')') {
- $parenCount--;
- }
- if (is_array($tokens[$i]) && $tokens[$i][0] == T_CONSTANT_ENCAPSED_STRING) {
- $lastString = $tokens[$i][1];
- }
- if (!$ignore) {
- $buf .= is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i];
- }
- if (is_array($tokens[$i]) && $tokens[$i][0] == T_DOUBLE_ARROW
- && (substr($lastString, 1, 3) === 'arg'
- || substr($lastString, 1, 5) === 'count')) {
- /*
- * Convert 'argN' => code to 'argN' => null so we don't eval that code.
- * Add 'null' to $buf now, then ignore content until next , or ) not in
- * a deeper nested ().
- */
- $buf .= 'null';
- $ignore = $parenCount;
- }
- }
- $param = eval('return ' . $buf . ';');
- if (is_string($param)) {
- /* Escape double quotes and newlines */
- $text = strtr($param, array('"' => '\"', "\r\n" => '\n', "\n" => '\n'));
- $string = 'gettext("' . $text . '")';
- if (!isset($strings[$string])) {
- $strings[$string] = array();
- } else if (!isset($localStrings[$string])) {
- $strings[$string][] = $filename;
- }
- $localStrings[$string] = true;
- } else if (is_array($param)) {
- foreach (array('text', 'one', 'many') as $key) {
- if (isset($param[$key])) {
- /* Escape double quotes and newlines */
- $param[$key] = strtr($param[$key],
- array('"' => '\\"', "\r\n" => '\n', "\n" => '\n'));
- }
- }
- if (isset($param['one'])) {
- $string = 'ngettext("' . $param['one'] . '", "' . $param['many'] . '")';
- } else {
- $string = 'gettext("' . $param['text'] . '")';
- }
- if (isset($param['cFormat'])) {
- $string = '/* xgettext:'
- . ($param['cFormat'] ? '' : 'no-') . "c-format */\n$string";
- }
- if (!empty($param['hint'])) {
- $string = '// HINT: ' . str_replace("\n", "\n// ", $param['hint'])
- . "\n$string";
- }
- if (!isset($strings[$string])) {
- $strings[$string] = array();
- } else if (!isset($localStrings[$string])) {
- $strings[$string][] = $filename;
- }
- $localStrings[$string] = true;
- }
- }
- }
- } else if (preg_match_all('/{\s*g->(?:text|changeInDescendents)\s+.*?[^\\\\]}/s',
- $data, $matches)) {
- /* Use regexp to process tpl files for {g->text ..} and {g->changeInDescendents ..} */
- foreach ($matches[0] as $string) {
- $text = $one = $many = null;
- /*
- * Ignore translations of the form:
- * text=$foo
- * as we expect those to be variables containing values that
- * have been marked elsewhere with the i18n() function.
- */
- if (preg_match('/\stext=\$/', $string)) {
- continue;
- }
- /* text=..... */
- if (preg_match('/\stext="(.*?[^\\\\])"/s', $string, $matches)) {
- $text = $matches[1];
- } else if (preg_match("/text='(.*?)'/s", $string, $matches)) {
- $text = str_replace('"', '\"', $matches[1]); /* Escape double quotes */
- }
- /* one=..... */
- if (preg_match('/\sone="(.*?[^\\\\])"/s', $string, $matches)) {
- $one = $matches[1];
- } else if (preg_match("/\sone='(.*?)'/s", $string, $matches)) {
- $one = str_replace('"', '\"', $matches[1]); /* Escape double quotes */
- }
- /* many=..... */
- if (preg_match('/\smany="(.*?[^\\\\])"/s', $string, $matches)) {
- $many = $matches[1];
- } else if (preg_match("/\smany='(.*?)'/s", $string, $matches)) {
- $many = str_replace('"', '\"', $matches[1]); /* Escape double quotes */
- }
- /* Hint for translators */
- $translatorHint = preg_match('/\shint=((["\']).*?[^\\\\]\2)/s', $string, $matches)
- ? eval('return ' . $matches[1] . ';') : '';
- /* c-format hint for xgettext */
- $cFormatHint = preg_match('/\sc[Ff]ormat=(true|false)/s', $string, $matches)
- ? '/* xgettext:' . ($matches[1] == 'false' ? 'no-' : '') . "c-format */\n" : '';
- /* Pick gettext() or ngettext() and escape newlines */
- if (isset($text)) {
- $string = 'gettext("' . strtr($text, array("\r\n" => '\n', "\n" => '\n')) . '")';
- } else if (isset($one) && isset($many)) {
- $string = 'ngettext("' . strtr($one, array("\r\n" => '\n', "\n" => '\n')) . '", "'
- . strtr($many, array("\r\n" => '\n', "\n" => '\n')) . '")';
- } else {
- /* Parse error */
- $string = str_replace("\n", '\n> ', $string);
- errorExit("extract.php parse error: $filename:\n> $string\n");
- }
- if ($cFormatHint) {
- $string = $cFormatHint . $string;
- }
- if ($translatorHint) {
- $string = "// HINT: $translatorHint\n$string";
- }
- if (!isset($strings[$string])) {
- $strings[$string] = array();
- } else if (!isset($localStrings[$string])) {
- $strings[$string][] = $filename;
- }
- $localStrings[$string] = true;
- }
- }
- if (count($strings) == $startSize) {
- unset($strings["\n/* $filename */"]);
- }
- }
- function errorExit($message) {
- $stderr = fopen('php://stderr', 'w');
- fwrite($stderr, $message);
- exit(1);
- }
- ?>