czaks
11 years ago
6 changed files with 334 additions and 0 deletions
@ -0,0 +1,94 @@ |
|||
<?php |
|||
|
|||
class JSParser { |
|||
|
|||
protected $content; |
|||
protected $keywords; |
|||
protected $regs = array(); |
|||
protected $regsCounter = 0; |
|||
protected $strings = array(); |
|||
protected $stringsCounter = 0; |
|||
|
|||
protected function _extractRegs($match) { |
|||
$this->regs[$this->regsCounter] = $match[1]; |
|||
$id = "<<reg{$this->regsCounter}>>"; |
|||
$this->regsCounter++; |
|||
return $id; |
|||
} |
|||
protected function _extractStrings($match) { |
|||
$this->strings[$this->stringsCounter] = $this->importRegExps($match[0]); |
|||
$id = "<<s{$this->stringsCounter}>>"; |
|||
$this->stringsCounter++; |
|||
return $id; |
|||
} |
|||
protected function importRegExps($input) { |
|||
$regs = $this->regs; |
|||
return preg_replace_callback("#<<reg(\d+)>>#", function ($match) use($regs) { |
|||
return $regs[$match[1]]; |
|||
}, $input); |
|||
} |
|||
|
|||
protected function importStrings($input) { |
|||
$strings = $this->strings; |
|||
return preg_replace_callback("#<<s(\d+)>>#", function ($match) use($strings) { |
|||
return $strings[$match[1]]; |
|||
}, $input); |
|||
} |
|||
|
|||
public function __construct($file, $keywords = '_') { |
|||
$this->content = file_get_contents($file); |
|||
$this->keywords = (array)$keywords; |
|||
} |
|||
|
|||
public function parse() { |
|||
$output = htmlspecialchars($this->content, ENT_NOQUOTES); |
|||
|
|||
// extract reg exps |
|||
$output = preg_replace_callback( |
|||
'# ( / (?: (?>[^/\\\\]++) | \\\\\\\\ | (?<!\\\\)\\\\(?!\\\\) | \\\\/ )+ (?<!\\\\)/ ) [a-z]* \b #ix', |
|||
array($this, '_extractRegs'), $output |
|||
); |
|||
|
|||
// extract strings |
|||
$output = preg_replace_callback( |
|||
array( |
|||
'# " ( (?: (?>[^"\\\\]++) | \\\\\\\\ | (?<!\\\\)\\\\(?!\\\\) | \\\\" )* ) (?<!\\\\)" #ix', |
|||
"# ' ( (?: (?>[^'\\\\]++) | \\\\\\\\ | (?<!\\\\)\\\\(?!\\\\) | \\\\' )* ) (?<!\\\\)' #ix" |
|||
), array($this, '_extractStrings'), $output |
|||
); |
|||
|
|||
// delete line comments |
|||
$output = preg_replace("#(//.*?)$#m", '', $output); |
|||
|
|||
// delete multiline comments |
|||
$output = preg_replace('#/\*(.*?)\*/#is', '', $output); |
|||
|
|||
$strings = $this->strings; |
|||
$output = preg_replace_callback("#<<s(\d+)>>#", function($match) use($strings) { |
|||
return $strings[$match[1]]; |
|||
}, $output); |
|||
|
|||
$keywords = implode('|', $this->keywords); |
|||
|
|||
$strings = array(); |
|||
|
|||
// extract func calls |
|||
preg_match_all( |
|||
'# (?:'.$keywords.') \(\\ *" ( (?: (?>[^"\\\\]++) | \\\\\\\\ | (?<!\\\\)\\\\(?!\\\\) | \\\\" )* ) (?<!\\\\)"\\ *\) #ix', |
|||
$output, $matches, PREG_SET_ORDER |
|||
); |
|||
|
|||
foreach ($matches as $m) $strings[] = stripslashes($m[1]); |
|||
|
|||
$matches = array(); |
|||
preg_match_all( |
|||
"# (?:$keywords) \(\\ *' ( (?: (?>[^'\\\\]++) | \\\\\\\\ | (?<!\\\\)\\\\(?!\\\\) | \\\\' )* ) (?<!\\\\)'\\ *\) #ix", |
|||
$output, $matches, PREG_SET_ORDER |
|||
); |
|||
|
|||
foreach ($matches as $m) $strings[] = stripslashes($m[1]); |
|||
|
|||
return $strings; |
|||
} |
|||
} |
|||
?> |
@ -0,0 +1,83 @@ |
|||
<?php |
|||
|
|||
require_once 'PoeditString.php'; |
|||
|
|||
class PoeditParser { |
|||
|
|||
protected $file; |
|||
protected $header = ''; |
|||
protected $strings = array(); |
|||
|
|||
protected function _fixQuotes($str) { |
|||
return stripslashes($str); |
|||
} |
|||
|
|||
public function __construct($file) { |
|||
$this->file = $file; |
|||
} |
|||
|
|||
public function parse() { |
|||
$contents = file_get_contents($this->file); |
|||
|
|||
$parts = preg_split('#(\r\n|\n){2}#', $contents, -1, PREG_SPLIT_NO_EMPTY); |
|||
|
|||
$this->header = array_shift($parts); |
|||
|
|||
foreach ($parts as $part) { |
|||
|
|||
// parse comments |
|||
$comments = array(); |
|||
preg_match_all('#^\\#: (.*?)$#m', $part, $matches, PREG_SET_ORDER); |
|||
foreach ($matches as $m) $comments[] = $m[1]; |
|||
|
|||
$isFuzzy = preg_match('#^\\#, fuzzy$#im', $part) ? true : false; |
|||
|
|||
preg_match_all('# ^ (msgid|msgstr)\ " ( (?: (?>[^"\\\\]++) | \\\\\\\\ | (?<!\\\\)\\\\(?!\\\\) | \\\\" )* ) (?<!\\\\)" $ #ixm', $part, $matches2, PREG_SET_ORDER); |
|||
|
|||
$k = $this->_fixQuotes($matches2[0][2]); |
|||
$v = !empty($matches2[1][2]) ? $this->_fixQuotes($matches2[1][2]) : ''; |
|||
|
|||
$this->strings[$k] = new PoeditString($k, $v, $isFuzzy, $comments); |
|||
} |
|||
} |
|||
|
|||
public function merge($strings) { |
|||
foreach ((array)$strings as $str) { |
|||
if (!in_array($str, array_keys($this->strings))) { |
|||
$this->strings[$str] = new PoeditString($str); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public function getHeader() { |
|||
return $this->header; |
|||
} |
|||
|
|||
public function getStrings() { |
|||
return $this->strings; |
|||
} |
|||
|
|||
public function getJSON() { |
|||
$str = array(); |
|||
foreach ($this->strings as $s) { |
|||
if ($s->value) $str[$s->key] = $s->value; |
|||
} |
|||
return json_encode($str); |
|||
} |
|||
|
|||
public function toJSON($outputFilename, $varName = 'l10n') { |
|||
$str = "$varName = " . $this->getJSON(); |
|||
return file_put_contents($outputFilename, $str) !== false; |
|||
} |
|||
|
|||
public function save($filename = null) { |
|||
$data = $this->header . "\n\n"; |
|||
foreach ($this->strings as $str) { |
|||
$data .= $str; |
|||
} |
|||
return file_put_contents($filename ? $filename : $this->file, $data) !== false; |
|||
} |
|||
} |
|||
|
|||
|
|||
?> |
@ -0,0 +1,29 @@ |
|||
<?php |
|||
|
|||
class PoeditString { |
|||
public $key; |
|||
public $value; |
|||
public $fuzzy; |
|||
public $comments; |
|||
|
|||
function __construct($key, $value = '', $fuzzy = false, $comments = array()) { |
|||
$this->key = $key; |
|||
$this->value = $value; |
|||
$this->fuzzy = $fuzzy; |
|||
$this->comments = (array)$comments; |
|||
} |
|||
|
|||
public function __toString() { |
|||
$str =''; |
|||
foreach ($this->comments as $c) { |
|||
$str .= "#: $c\n"; |
|||
} |
|||
if ($this->fuzzy) $str .= "#, fuzzy\n"; |
|||
$str .= 'msgid "'.str_replace('"', '\\"', $this->key).'"' . "\n"; |
|||
$str .= 'msgstr "'.str_replace('"', '\\"', $this->value).'"' . "\n"; |
|||
$str .= "\n"; |
|||
return $str; |
|||
} |
|||
} |
|||
|
|||
?> |
@ -0,0 +1,59 @@ |
|||
<?php |
|||
|
|||
require_once 'JSParser.php'; |
|||
require_once 'PoeditParser.php'; |
|||
|
|||
function buildOptions($args) { |
|||
$options = array( |
|||
'files' => array(), |
|||
'-o' => null, |
|||
'-k' => '_' |
|||
); |
|||
$len = count($args); |
|||
$i = 0; |
|||
while ($i < $len) { |
|||
if (preg_match('#^-[a-z]$#i', $args[$i])) { |
|||
$options[$args[$i]] = isset($args[$i+1]) ? trim($args[$i+1]) : true; |
|||
$i += 2; |
|||
} |
|||
else { |
|||
$options['files'][] = $args[$i]; |
|||
$i++; |
|||
} |
|||
} |
|||
return $options; |
|||
} |
|||
|
|||
$options = buildOptions($argv); |
|||
|
|||
if (!file_exists($options['-o']) || !is_writable($options['-o'])) { |
|||
die("Invalid output file name. Make sure it exists and is writable."); |
|||
} |
|||
|
|||
$inputFiles = $options['files']; |
|||
|
|||
if (empty($inputFiles)) { |
|||
die("You did not provide any input file."); |
|||
} |
|||
|
|||
$poeditParser = new PoeditParser($options['-o']); |
|||
$poeditParser->parse(); |
|||
|
|||
$errors = array(); |
|||
|
|||
foreach ($inputFiles as $f) { |
|||
if (!is_readable($f) || !preg_match('#\.js$#', $f)) { |
|||
$errors[] = ("$f is not a valid javascript file."); |
|||
continue; |
|||
} |
|||
$jsparser = new JSParser($f, explode(' ', $options['-k'])); |
|||
$jsStrings = $jsparser->parse(); |
|||
$poeditParser->merge($jsStrings); |
|||
} |
|||
|
|||
if (!empty($errors)) { |
|||
echo "\nThe following errors occured:\n" . implode("\n", $errors) . "\n"; |
|||
} |
|||
|
|||
$poeditParser->save(); |
|||
?> |
@ -0,0 +1,42 @@ |
|||
<?php |
|||
|
|||
require_once 'PoeditParser.php'; |
|||
|
|||
function buildOptions($args) { |
|||
$options = array( |
|||
'-o' => null, |
|||
'-i' => null, |
|||
'-n' => 'l10n' |
|||
); |
|||
$len = count($args); |
|||
$i = 0; |
|||
while ($i < $len) { |
|||
if (preg_match('#^-[a-z]$#i', $args[$i])) { |
|||
$options[$args[$i]] = isset($args[$i+1]) ? trim($args[$i+1]) : true; |
|||
$i += 2; |
|||
} |
|||
else { |
|||
$options[] = $args[$i]; |
|||
$i++; |
|||
} |
|||
} |
|||
return $options; |
|||
} |
|||
|
|||
$options = buildOptions($argv); |
|||
|
|||
if (!file_exists($options['-i']) || !is_readable($options['-i'])) { |
|||
die("Invalid input file. Make sure it exists and is readable."); |
|||
} |
|||
|
|||
$poeditParser = new PoeditParser($options['-i']); |
|||
$poeditParser->parse(); |
|||
|
|||
if ($poeditParser->toJSON($options['-o'], $options['-n'])) { |
|||
$strings = count($poeditParser->getStrings()); |
|||
echo "Successfully exported " . count($strings) . " strings.\n"; |
|||
} |
|||
else { |
|||
echo "Cannor write to file '{$options['-o']}'.\n"; |
|||
} |
|||
?> |
@ -0,0 +1,27 @@ |
|||
function _(s) { |
|||
return typeof l10n[s] != 'undefined' ? l10n[s] : s; |
|||
} |
|||
function test(param) { |
|||
var a = _("Hello world, testing jsgettext"); |
|||
func(_('Test string')); |
|||
var reg1 = /"[a-z]+"/i; |
|||
var reg2 = /[a-z]+\+\/"aa"/i; |
|||
var s1 = _('string 1: single quotes'); |
|||
var s2 = _("string 2: double quotes"); |
|||
var s3 = _("/* comment in string */"); |
|||
var s4 = _("regexp in string: /[a-z]+/i"); |
|||
var s5 = jsgettext( "another function" ); |
|||
var s6 = avoidme("should not see me!"); |
|||
var s7 = _("string 2: \"escaped double quotes\""); |
|||
var s8 = _('string 2: \'escaped single quotes\''); |
|||
|
|||
// "string in comment"
|
|||
//;
|
|||
|
|||
/** |
|||
* multiple |
|||
* lines |
|||
* comment |
|||
* _("Hello world from comment") |
|||
*/ |
|||
} |
Loading…
Reference in new issue