save_path = $save_path ? $save_path : _PS_ROOT_DIR_.'/trans/'; $this->debug = $debug; } public function dump($options = array()) { $theme = $options['theme'] ? $options['theme'] : ''; $locale = $options['locale'] ? $options['locale'] : 'en-US'; $theme_module = $options['theme_module'] ? $options['theme_module'] : false; $modules = $options['modules'] ? $options['modules'] : array(); $type = $options['type'] ? $options['type'] : 0; $tpl_path = isset($options['tpl_path']) ? $options['tpl_path'] : ''; $this->check_missing = $options['check_missing'] ? $options['check_missing'] : 0; $this->theme = $theme; $translations = array(); if ($theme && is_dir(_PS_ROOT_DIR_.'/themes/'.$theme)) { if ($result = $this->dumpFront($theme, $theme_module)) { $translations = array_merge_recursive($translations, $result); } } if (!is_array($modules)) { $modules = (array)$modules; } foreach($modules as $module) { if ($result = $this->dumpModule($module)) { $translations = array_merge_recursive($translations, $result); } } if ($this->check_missing) { if ($this->missing) { echo 'The following phrases missed in the domain:
'; echo implode("
\r\n", $this->missing); die; } else { die('All are okay !'); } } $catalogue = new MessageCatalogue($locale, array()); foreach($translations AS $domain => &$messages) { // Skip global domain. if ($this->need_skip($domain, $theme, $modules, $type)) { continue; } $messages = array_map(function($val){ if (is_array($val)){ return array_pop($val); } else { return $val; } }, $messages); if (strtolower($domain) == 'shop.theme.'.$theme) { $this->createTranslationFile($messages, $domain, $tpl_path); } $domain = str_replace('.', '', $domain); $catalogue->add($messages, $domain); $messages = array(); } if (!is_dir($this->save_path)) { (new Filesystem())->mkdir($this->save_path); } $dumper = new dumper; $dumper->dump($catalogue, array( 'path' => $this->save_path, 'default_locale' => 'en-US' )); if ($this->debug) { die('Done'); } return true; } protected function dumpModule($module) { if (!$module) { return false; } $translations = array(); if (is_dir($path = _PS_MODULE_DIR_.$module)) { foreach(array('php','tpl') AS $ext) { if($files = $this->getFiles($path, $ext)) { foreach($files AS $file) { if (strrpos($file, 'index.php') !== false) { continue; } $content = file_get_contents($file); if ($this->debug) { echo $file."
\r\n"; } $result = $this->userParseFile($content, 'module', $ext); $this->checkMissing($file, $result); if ($result) { if ($this->debug) { print_r($result)."
\r\n"; } $translations = array_merge_recursive($translations, $result); } } } } } return $translations; } protected function dumpFront($theme, $theme_module=false) { if (!$theme) { return false; } $translations = array(); if (is_dir(_PS_ROOT_DIR_.'/themes/'.$theme)) { if ($theme_module) { $path = _PS_ROOT_DIR_.'/themes/'.$theme; } else { $path = _PS_ROOT_DIR_.'/themes/'.$theme.'/templates'; } $ext = 'tpl'; if($files = $this->getFiles($path, $ext)) { foreach($files AS $file) { $content = file_get_contents($file); if ($this->debug) { echo $file."
\r\n"; } $result = $this->userParseFile($content, 'front', $ext); $this->checkMissing($file, $result); if ($result) { if ($this->debug) { print_r($result)."
\r\n"; } $translations = array_merge_recursive($translations, $result); } } } } return $translations; } public function getFiles($path, $ext='tpl') { if (!is_dir($path)) { return false; } if (!$ext) { $ext = 'tpl'; } $files = array(); $finder = Finder::create() ->files() ->filter(function (\SplFileInfo $file) use($ext) { return $ext == $file->getExtension(); }) ->in($path) ; foreach ($finder as $file) { $files[] = $file->getPath().'/'.$file->getBasename(); } return $files; } protected function userParseFile($content, $type_translation, $type_file = 'php') { switch ($type_translation) { case 'front': // Parsing file in Front office if ($type_file == 'php') { $regex = '/->trans\(([\'\"])' . _PS_TRANS_PATTERN_ . '([\'\"])(,\s*?[\[|array\(](.*)[\]|\)])(,\s*?([\'\"])(.*)([\'\"]))?\)/Us'; } else { $regex = '/\{l\s*s=\s*([\'\"])'._PS_TRANS_PATTERN_.'([\'\"])?(\s*sprintf=\s*\[.*\])?\s+d\s*=\s*[\'\"](.+)[\'\"]\}?/Us'; } break; case 'module': if ($type_file == 'php') { $regex = '/->trans\(([\'\"])' . _PS_TRANS_PATTERN_ . '([\'\"])(,\s*?[\[|array\(](.*)[\]|\)])(,\s*?([\'\"])(.*)([\'\"]))?\)/Us'; } else { $regex = '/\{l\s*s=\s*([\'\"])'._PS_TRANS_PATTERN_.'([\'\"])?(\s*sprintf=\s*\[.*\])?\s+d\s*=\s*[\'\"](.+)[\'\"]\}?/Us'; } break; } if (!is_array($regex)) { $regex = array($regex); } $strings = array(); foreach ($regex as $regex_row) { $matches = array(); $n = preg_match_all($regex_row, $content, $matches); if ($type_file == 'php') { foreach ($matches[0] as $key => $match) { if (strpos($match, 'trans(') !== false) { $stringToTranslate = trim($matches[2][$key]); if (!$stringToTranslate || $stringToTranslate == '\'' || $stringToTranslate == '"') { continue; } $prefix_key = trim($matches[8][$key]); $strings[$prefix_key][$stringToTranslate] = $stringToTranslate; } } } else { foreach ($matches[0] as $key => $match) { if ($match) { $stringToTranslate = trim($matches[2][$key]); if (!$stringToTranslate || $stringToTranslate == '\'' || $stringToTranslate == '"') { continue; } $prefix_key = trim($matches[5][$key]); $strings[$prefix_key][$stringToTranslate] = $stringToTranslate; } } } } return $strings; } protected function need_skip($domain, $theme, $modules, $type=1) { if (!$domain) { return true; } // Front only. if (!$type && strpos(strtolower($domain), 'shop.theme.'.$theme) === false) { return true; } if (strpos(strtolower($domain), $theme) !== false) { return false; } foreach($modules AS $module) { if (strpos(strtolower($domain), $module) !== false) { return false; } } return true; } public function renameXliffFile($locale='en-US', $ext = 'xlf') { $extension = $locale.'.'.$ext; foreach($files = $this->getFiles($this->save_path, $ext) AS $file) { $path = dirname($file); $filename = str_replace($extension,'', basename($file)); $filename = str_replace('.','', $filename); @rename($file, $path.'/'.$filename.'.'.$extension); } } public function clearFiles($path, $filter='') { if (!is_dir($path)) { return false; } $finder = Finder::create() ->files() ->filter(function (\SplFileInfo $file) use($filter) { if ($filter) { return strpos($file->getBasename(), $filter) !== false; } return true; }) ->depth(0) ->in($path) ; foreach ($finder as $file) { @unlink(rtrim($file->getPath(), '/').'/'.$file->getBasename()); } return true; } public function CopyFiles($src, $des, $filter='', $locale='en-US', $trim=true) { if (!is_dir($src) || !is_dir($des)) { return false; } $finder = Finder::create() ->files() ->filter(function (\SplFileInfo $file) use($filter) { if ($filter) { return strpos($file->getBasename(), $filter) !== false; } return true; }) ->depth(0) ->in($src) ; foreach ($finder as $file) { $file_src = rtrim($file->getPath(), '/').'/'.$file->getBasename(); if ($trim) { $file_name = str_replace('.'.$locale, '', $file->getBasename()); } else { $file_name = $file->getBasename(); } @copy($file_src, $des.$file_name); } return true; } public function checkMissing($file, $translations=array()) { if (!$this->check_missing || !$file || !$translations) { return false; } $file = str_replace(_PS_ROOT_DIR_, '', $file); foreach($translations AS $domain => &$messages) { $domain2 = str_replace('.', '', $domain); if (strpos(strtolower($domain2), $this->theme) !== false || strpos($domain2, 'ModulesSt') !== false) { continue; } $messages = array_map(function($val){ if (is_array($val)){ return array_pop($val); } else { return $val; } }, $messages); $message_all = Context::getContext()->getTranslator()->getCatalogue('en-US')->all($domain2); foreach($messages AS $message) { $message = stripslashes($message); if (!key_exists($message, $message_all)) { $this->missing[] = '['.$domain.']=>['.$message. '] in file: '.$file; } } } } public function createTranslationFile($translations = array(), $domain, $save_path) { if (!$domain || !$save_path) { return false; } $html = '{* Generated by the theme, don\'t modify it manually. *}'."\r\n"; foreach($translations as $translation) { $html .= '{l s=\''.$translation.'\' d=\''.$domain.'\'}'."\r\n"; } @file_put_contents($save_path.'translation.tpl', $html); } }