* @license PHP License * @package WB * @subpackage base */ WBClass::load('WBCli'); /** * Command Line Interface class: Event Queue Processor * * Run event queue * * @version 0.1.0 * @package WB * @subpackage base */ class WBCli_Translator extends WBCli { /** * locale configuration * @var WBConfig */ private $locale; /** * text importer * @var array patI18n_Importer */ private $imp = array(); /** * config Loader * @var WBCoonfig_Loader */ private $configLoader; /** * markup scanner * @var WBMarkup_Scanner */ private $scanner; /** * markup handler * @var WBMarkup_Handler_I18nExtractor */ private $handler; /** * list of errors * @var array */ private $errors = array(); /** * 2nd constructor * * load config and setup importer */ protected function init() { WBClass::load('patI18n'); $this->locale = WBClass::create('WBConfig'); $this->locale->load('locale'); $trans = $this->locale->get('translators', array()); if (empty($trans) || !isset($trans['modules'])) { $trans['modules'] = array(); } foreach ($trans['modules'] as $mod) { if (isset($mod['defaultdomain'])) { $mod['domain'] = $mod['defaultdomain']; } $this->imp = patI18n::createImporter($mod['module'], $mod); } } /** * execute programme * * Use observer and execute event queue */ protected function execute() { $this->commands = array('extract'); foreach ($this->commands as $c) { call_user_func(array($this, 'execute'. ucfirst($c))); } $this->pvl('done'); } /** * extract all the meesages * * */ private function executeExtract() { $this->extractPhp(); $this->extractXmlConfig(); $this->extractTemplate(); } private function extractPhp() { $sys = WBParam::get('wb/dir/system'); $this->pv('Extract messages from Wombat\'s PHP files ... '); $cnt = $this->extractPhpDir($sys . '/include/WB'); $this->pvl($cnt); if (!empty($this->errors)) { $this->pl('There where errors.'); $this->pvl(implode("\n", $this->errors)); $this->errors = array(); } $base = WBParam::get('wb/dir/base'); if ($base == $sys) { return; } $this->pv('Extract messages from custom PHP files ... '); $cnt = $this->extractPhpDir($base . '/include'); $this->pvl($cnt); if (!empty($this->errors)) { $this->pl('There where errors.'); $this->pvl(implode("\n", $this->errors)); $this->errors = array(); } } private function extractPhpDir($dir) { $cnt = 0; $dh = new DirectoryIterator($dir); foreach ($dh as $i) { $name = $i->getFilename(); if ($i->isDot() || '.' == $name[0]) { continue; } if ($i->isDir()) { $cnt += $this->extractPhpDir($i->getRealPath()); continue; } $name = explode('.', $name); if ('php' != end($name)) { continue; } $this->extractPhpFile($i->getRealPath()); ++$cnt; } return $cnt; } public function extractPhpFile($realpath) { $string = file_get_contents($realpath); $tokens = token_get_all($string); for ($i = 0; $i < count($tokens); ++$i) { $t = $tokens[$i]; if (!is_array($t)) { continue; } if ($t[0] == T_DOUBLE_COLON) { $left = $tokens[($i - 1)]; if ($left[0] != T_STRING || strtolower($left[1]) != 'pati18n' ) { continue; } $right = $tokens[($i + 1)]; if ($right[0] != T_STRING) { continue; } ++$i; $domain = null; switch (strtolower($right[1])) { case 'dgettext': $d = $this->getNextString($i, $tokens); $domain = $d[1]; // fall through case 'gettext': $t = $this->getNextString($i, $tokens); try { $this->imp->addMsg($t[1], null, $domain); } catch(Exception $e) { $this->errors[] = $e->getMessage(); } break; case 'dngettext': $d = $this->getNextString($i, $tokens); $domain = $d[1]; // fall through case 'ngettext': $s = $this->getNextString($i, $tokens); $p = $this->getNextString($i, $tokens); try { $id = $this->imp->addMsg($t[1], null, $domain); $this->imp->addMsg($p[1], $id, $domain); } catch(Exception $e) { $this->errors[] = $e->getMessage(); } break; default: continue 2; break; } } } } private function getNextString(&$i, $tokens) { ++$i; while(true) { $t = $tokens[$i]; // skip "(" if (!is_array($t) && $t == '(') { ++$i; continue; } // skip blanks if (is_array($t) && $t[0] != T_WHITESPACE ) { break; } ++$i; } $t[1] = stripslashes(trim($t[1], '\'"')); return $t; } private function extractTemplate() { $this->scanner = WBClass::create('WBMarkup_Scanner'); $this->handler = WBClass::create('WBMarkup_Handler_I18nExtractor_HtmlTemplate'); $this->handler->setImporter($this->imp); $this->scanner->setHandler($this->handler); $dir = WBParam::get('wb/dir/base') . '/template'; $this->pv('Extract messages from HTML template files ... '); $cnt = $this->extractTemplateFile($dir); $this->pvl($cnt); } private function extractTemplateFile($dir) { $cnt = 0; $dh = new DirectoryIterator($dir); foreach ($dh as $i) { $name = $i->getFilename(); if ($i->isDot() || '.' == $name[0]) { continue; } $path = $i->getRealpath(); // recursion if ($i->isDir()) { $cnt += $this->extractTemplateFile($path); continue; } $name = explode('.', $name); if ('tmpl' != end($name)) { continue; } $this->scanner->scanFile($path); ++$cnt; } return $cnt; } /** * extract messages from XML config * */ private function extractXmlConfig() { $this->scanner = WBClass::create('WBMarkup_Scanner'); $this->handler = WBClass::create('WBMarkup_Handler_I18nExtractor_XmlConfig'); $this->handler->setImporter($this->imp); $this->scanner->setHandler($this->handler); // file baseed config $this->pv('Extract messages from XML config stored files ... '); $this->configLoader = WBClass::create('WBConfig_Loader_File'); $cnt = $this->extractXmlConfigDir(''); $this->pvl($cnt); // config in tables $this->pv('Extract messages from XML config stored in database ... '); $this->configLoader = WBClass::create('WBConfig_Loader_ConfigTable'); $cnt = $this->extractXmlConfigDir(''); $this->pvl($cnt); } /** * extract messages from XML config * * Use config loader to list and fetch XML config (e.g. from file or database) * scan config and listrecursively. * * * @param string $dir * @return int */ private function extractXmlConfigDir($dir) { $d = $dir; if (!empty($d)) { $d .= '/'; } $data = ''; $exp = null; if ($this->configLoader->load($dir, $data, $exp, true)) { $this->scanner->scan($data); $cnt = $this->handler->getParsedContent(); } $list = $this->configLoader->ls($dir); $cnt = count($list); foreach ($list as $l) { $cnt += $this->extractXmlConfigDir($d . $l); } return $cnt; } private function executeXgettext() { $this->pvl('Xgettext'); } private function executeMsgfmt() { $this->pvl('Msgfmt'); $sysDir = WBParam::get('wb/dir/system'); $this->pvl('sysdir ' . $sysDir); $file = WBClass::create('WBFile'); /** @var $file WBFile */ $available = $this->locale->get('locale/languages/available'); foreach ($available as $a) { // solve problem with 5 letter language codes $lang = substr($a, 0, 2); if ($lang == 'en') { continue; } $file->mkDir('var/lang/' . $lang . '/LC_MESSAGES'); // wombat $cmd = sprintf('msgfmt -v -o %s/wombat.mo %s/resource/gettext/wombat/%s.po', $file->realpath(), $sysDir, $lang); exec($cmd, $out, $ret); if ($ret) { break; } // patForms $cmd = sprintf('msgfmt -v -o %s/patForms.mo %s/lib/patForms/data/gettext/patForms/%s.po', $file->realpath(), $sysDir, $lang); exec($cmd, $out, $ret); if ($ret) { break; } } } } ?>