From e4ca8efe7b04e500783967e2419cb8904d4ed99f Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 21 Jun 2019 16:12:00 +0800 Subject: [PATCH] * finish task #5827. --- config/filter.php | 3 + module/translate/control.php | 20 +- module/translate/css/module.css | 3 + module/translate/js/module.js | 20 ++ module/translate/lang/zh-cn.php | 2 +- module/translate/model.php | 275 +++++++++++++------------- module/translate/view/module.html.php | 107 ++++++++++ 7 files changed, 289 insertions(+), 141 deletions(-) create mode 100644 module/translate/css/module.css create mode 100644 module/translate/js/module.js create mode 100644 module/translate/view/module.html.php diff --git a/config/filter.php b/config/filter.php index 9f30f178a0..980cd5ac6d 100644 --- a/config/filter.php +++ b/config/filter.php @@ -45,6 +45,7 @@ $filter->mail = new stdclass(); $filter->user = new stdclass(); $filter->block = new stdclass(); $filter->file = new stdclass(); +$filter->translate = new stdclass(); $filter->block->default = new stdclass(); $filter->block->main = new stdclass(); @@ -210,3 +211,5 @@ $filter->git->cat->get['repoUrl'] = 'reg::base64'; $filter->git->diff->get['repoUrl'] = 'reg::base64'; $filter->svn->cat->get['repoUrl'] = 'reg::base64'; $filter->svn->diff->get['repoUrl'] = 'reg::base64'; + +$filter->translate->module->cookie['translateView'] = 'equal::split'; diff --git a/module/translate/control.php b/module/translate/control.php index b82d07ff7e..0f6a15f45b 100644 --- a/module/translate/control.php +++ b/module/translate/control.php @@ -143,14 +143,23 @@ class translate extends control } if(empty($referLang)) { - $langs = json_decode($this->config->global->langs, true); - $referLang = $langs[$language]['reference']; + $langs = json_decode($this->config->global->langs, true); + if(isset($langs[$language])) + { + $referLang = $langs[$language]['reference']; + } + else + { + $referLang = $language == 'zh-cn' ? 'en' : 'zh-cn'; + } } + $this->view->cmd = $this->translate->checkDirPriv($module); + if($_POST) { - $this->translate->addTranslation($zentaoVersion, $language, $module); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate(inlink('showLang', "zentaoVersion=$zentaoVersion&language=$language&module=$module&consultLang=$consultLang"), 'parent')); + $this->translate->addTranslation($language, $module, $referLang); + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload')); } $this->view->referItems = $this->translate->getModuleLangs($module, $referLang); @@ -159,6 +168,7 @@ class translate extends control $this->view->currentModule = $module; $this->view->currentGroup = $group; $this->view->language = $language; + $this->view->referLang = $referLang; $this->display(); } diff --git a/module/translate/css/module.css b/module/translate/css/module.css new file mode 100644 index 0000000000..62e7911992 --- /dev/null +++ b/module/translate/css/module.css @@ -0,0 +1,3 @@ +.table-data tbody>tr>td{border:1px solid #cbd0db !important; padding-right:8px !important;} +.table-data tbody>tr>td.translated{padding:0px !important;} +.translated input, .translated textarea{border:0px;} diff --git a/module/translate/js/module.js b/module/translate/js/module.js new file mode 100644 index 0000000000..6ebb88cdd7 --- /dev/null +++ b/module/translate/js/module.js @@ -0,0 +1,20 @@ +function setTranslateView(view) +{ + $.cookie('translateView', view, {expires:config.cookieLife, path:config.webRoot}); + location.reload(); +} + +function adjustKeyWidth() +{ + var maxWidth = 0; + $('.table-data tbody tr').each(function() + { + keyWidth = $(this).find('td').eq(1).find('nobr').width(); + if(maxWidth < keyWidth) maxWidth = keyWidth; + }); + $('.table-data thead tr:first th').eq(1).width(maxWidth); +} +$(function() +{ + adjustKeyWidth(); +}); diff --git a/module/translate/lang/zh-cn.php b/module/translate/lang/zh-cn.php index a4fb830a39..25d27c0144 100644 --- a/module/translate/lang/zh-cn.php +++ b/module/translate/lang/zh-cn.php @@ -20,7 +20,7 @@ $lang->translate->reference = '参考语言'; $lang->translate->status = '状态'; $lang->translate->refreshPage = '刷新'; -$lang->translate->builtIn = '内置语音'; +$lang->translate->builtIn = '内置语言'; $lang->translate->finished = '翻译完成'; $lang->translate->progress = '完成 %s'; diff --git a/module/translate/model.php b/module/translate/model.php index dc7e91cdd3..5147e9a208 100644 --- a/module/translate/model.php +++ b/module/translate/model.php @@ -103,7 +103,7 @@ class translateModel extends model if(strpos($line, '$lang->menuOrder') === 0) continue; if(strpos($line, 'include') === 0 or strpos($line, 'global') === 0) continue; if(strpos($line, 'unset(') !== false) continue; - if(strpos($line, '/*') === 0 or strpos($line, '//') === 0 or strpos($line, ' $value) + { + /* Remove Notes. */ + if(preg_match( '/; *\/\//', $value)) $value = preg_replace('/; *\/\/.*/', '', $value); + $value = trim($value, ';'); + /* Trim ['] or ["] when not [.] . */ + if(preg_match('/["\'] *\./', $value) == 0 and preg_match('/\. *[\'"]/', $value) == 0) + { + if($value{0} == '"' or $value{0} == "'") $value = trim($value, $value{0}); + } + $items[$key] = $value; + } return $items; } - public function checkDirPriv() + public function checkDirPriv($moduleName = '') { - $cmd = ''; - $modules = glob($this->app->getModuleRoot() . '*'); + $cmd = ''; + $moduleRoot = $this->app->getModuleRoot(); + $modules = empty($moduleName) ? array($moduleRoot . $moduleName) : glob($moduleRoot . '*'); foreach($modules as $modulePath) { if(is_dir($modulePath . '/lang') and !is_writable($modulePath . '/lang')) $cmd .= "chmod 777 {$modulePath}/lang
"; @@ -203,8 +217,9 @@ class translateModel extends model */ public function getTranslations($language, $module = '', $langKeys = array()) { - return $this->dao->select('id,lang,`key`,`value`,status')->from(TABLE_TRANSLATION) + return $this->dao->select('*')->from(TABLE_TRANSLATION) ->where('lang')->eq($language) + ->andWhere('mode')->eq($this->config->global->flow) ->beginIF(!empty($module))->andWhere('module')->eq($module)->fi() ->beginIF(!empty($langKeys))->andWhere('langKey')->in($langKeys)->fi() ->orderBy('id asc') @@ -220,158 +235,148 @@ class translateModel extends model * @access public * @return void */ - public function addTranslation($zentaoVersion, $language, $module) + public function addTranslation($language, $module, $referLang) { - $addData = ''; - $allWords = ''; //Use to stat word count. - $account = $this->app->user->account; - $postData = $this->untieModuleLang($_POST); - $allEntry = count($postData); - $translateData = $this->getTranslations($zentaoVersion, $language, $module, array_keys($postData)); - $translated = count(array_keys($translateData)); - - foreach($postData as $langKey => $translation) + $referItems = $this->getModuleLangs($module, $referLang); + $dbItems = $this->getTranslations($language, $module); + $translations = array(); + $flow = $this->config->global->flow; + foreach($this->post->keys as $i => $key) { - if(empty($translation)) + $dbItem = zget($dbItems, $key, ''); + $value = $referItems[$key]; + $now = helper::now(); + if(!empty($_POST['values'][$i])) $value = $this->post->values[$i]; + if($dbItem) { - unset($postData[$langKey]); - continue; - } - - /* Check duplicate translation.*/ - if(isset($translateData[$langKey]) and in_array($translation, array_keys($translateData[$langKey]))) - { - unset($postData[$langKey]); - continue; - } - - if(!isset($translateData[$langKey])) $translated++; - if(get_magic_quotes_gpc()) $translation = stripslashes($translation); - $allWords[$langKey] = $translation; - - $translation = $this->dbh->quote($translation); - $addData .= "('" . $account . "', '$zentaoVersion', '$module', '$language', '$langKey', $translation, '" . helper::now() . "'),"; - } - - if($addData) - { - /* Delete old translation when user edit these.*/ - $havingTranslate = $this->dao->select('id, translation')->from(TABLE_TRANSLATE) - ->where('account')->eq($account) - ->andWhere('version')->eq($zentaoVersion) - ->andWhere('module')->eq($module) - ->andWhere('language')->eq($language) - ->andWhere('langKey')->in(array_keys($allWords)) - ->fetchPairs('id', 'translation', false); - if($havingTranslate) - { - $this->dao->delete()->from(TABLE_TRANSLATE)->where('id')->in(array_keys($havingTranslate))->exec(false); - $addedScores = $this->countWords(join(' ', $havingTranslate)); - } - - /* Add translate content*/ - $addTranslateData = "INSERT INTO `" . TABLE_TRANSLATE . "` (`account`, `version`, `module`, `language`, `langKey`, `translation`, `time`) VALUES" . rtrim($addData, ','); - $this->dbh->exec($addTranslateData); - - /* Add translate log*/ - if(get_magic_quotes_gpc()) $postData = stripslashes(json_encode($postData)); - $postData = $this->dbh->quote($postData); - $addLogData = "INSERT INTO `" . TABLE_TRANSLATELOG . "` (`account`, `version`, `module`, `language`, `content`, `time`) VALUES('" . $account . "', '$zentaoVersion', '$module', '$language', " . $postData . ", '" . helper::now() . "')"; - $this->dbh->exec($addLogData); - - /* Count words as scores*/ - $scores = $this->countWords(join(' ', $allWords)); - if(empty($addedScores)) - { - $this->loadModel('score')->log($account, 'translate', 'in', $scores, 'TRANSLATE'); + unset($dbItem->id); + $translation = $dbItem; + $translation->version = $this->config->version; + if($dbItem->value != $value) + { + $translation->value = $value; + $translation->status = 'translated'; + $translation->translator = $this->app->user->account; + $translation->translationTime = $now; + if($translation->reason) $translation->reason = ''; + } + elseif(!$this->checkNeedTranslate($value) and !empty($_POST['values'][$i]) and strpos("waiting|changed", $translation->status) !== false) + { + $translation->status = 'translated'; + } } else { - $scores = $scores - $addedScores; - $scoreType = $scores >= 0 ? 'in' : 'out'; - $this->loadModel('score')->log($account, 'edittranslate', $scoreType, abs($scores), 'TRANSLATE'); - } - - /* compute percent of translation and save.*/ - $percent = round($translated / $allEntry * 100, 1) . '%'; - $languageLog = $this->dao->select('*')->from(TABLE_LANGUAGELOG)->where('version')->eq($zentaoVersion) - ->andWhere('language')->eq($language) - ->andWhere('module')->eq($module) - ->fetch('', false); - - if($languageLog) - { - $this->dao->update(TABLE_LANGUAGELOG)->set('translated')->eq($translated)->set('percent')->eq($percent)->where('id')->eq($languageLog->id)->exec(false); - } - else - { - $languageLog->version = $zentaoVersion; - $languageLog->language = $language; - $languageLog->module = $module; - $languageLog->allEntry = $allEntry; - $languageLog->translated = $translated; - $languageLog->percent = $percent; - $this->dao->insert(TABLE_LANGUAGELOG)->data($languageLog, false)->exec(); + $translation = new stdclass(); + $translation->lang = $language; + $translation->module = $module; + $translation->key = $key; + $translation->value = $value; + $translation->status = 'translated'; + $translation->translator = $this->app->user->account; + $translation->translationTime = $now; + $translation->version = $this->config->version; + $translation->mode = $flow; } + $translations[$key] = $translation; } + + $this->dao->delete()->from(TABLE_TRANSLATION)->where('lang')->eq($language)->andWhere('module')->eq($module)->andWhere('mode')->eq($flow)->exec(); + foreach($translations as $translation) $this->dao->replace(TABLE_TRANSLATION)->data($translation)->exec(); + if(!dao::isError()) $this->buildLangFile($language, $module, $translations, $referLang); } - /** - * untieModuleLang - * - * @param string $moduleLangs - * @param string $key - * @access public - * @return void - */ - public function untieModuleLang($moduleLangs = '', $key = '') + public function buildLangFile($language, $module, $translations, $referLang) { - $untieLang = array(); - if(is_object($moduleLangs)) + $moduleRoot = $this->app->getModuleRoot(); + $newLangFile = $moduleRoot . $module . "/lang/{$language}.php"; + $newContent = "getTranslatedLang($mainReferLangFile, $translations) . "\n"; + if(is_dir($moduleRoot . $module . "/ext/lang/$referLang")) { - foreach($moduleLangs as $langKey => $moduleLang) + $extLangFiles = glob($moduleRoot . $module . "/ext/lang/{$referLang}/*.php"); + foreach($extLangFiles as $extLangFile) $newContent .= $this->getTranslatedLang($extLangFile, $translations) . "\n"; + } + file_put_contents($newLangFile, $newContent); + } + + public function getTranslatedLang($referLang, $translations) + { + $lines = file($referLang); + $flow = $this->config->global->flow; + $inFlow = true; + $level = 0; + $content = ''; + foreach($lines as $i => $line) + { + $line = trim($line); + if(strpos($line, '/*') === 0 or strpos($line, '//') === 0 or strpos($line, '$langKey"; - if(is_array($moduleLang) or is_object($moduleLang)) + $content .= "\n"; + continue; + } + if(strpos($line, '$lang->menuOrder') === 0 or strpos($line, 'include') === 0 or strpos($line, 'global') === 0 or strpos($line, 'unset(') !== false) + { + $content .= $line . "\n"; + continue; + } + if(strpos($line, 'if') !== false and trim($lines[$i + 1]) == '{') + { + $inCondition = true; + $level ++; + if(strpos($line, 'config->global->flow') !== false and strpos($line, $flow) === false) $inFlow = false; + } + if($line == '}' and $inCondition) + { + $level --; + if($level == 0) { - $untieLang += $this->untieModuleLang($moduleLang, $nextKey); + $inCondition = false; + $inFlow = true; + } + } + if($line == '{' or $line == '}' or strpos($line, 'if') === 0 or strpos($line, 'else') === 0) + { + $content .= $line . "\n"; + continue; + } + if(!$inFlow and $inCondition) + { + $content .= $line . "\n"; + } + elseif($inFlow and strpos($line, '$lang') === 0 and strpos($line, '=') !== false) + { + $position = strpos($line, '='); + $key = trim(substr($line, 0, $position)); + if(isset($translations[$key])) + { + $translation = $translations[$key]; + $value = $translation->value; + if($this->checkNeedTranslate($value) and strpos($value, 'array(') === false) + { + $value = '"' . addslashes($value) . '"'; + } + $content .= $key . " = $value;\n"; } else { - $untieLang[$nextKey] = $moduleLang; + $content .= $line . "\n"; } } } - elseif(is_array($moduleLangs)) - { - foreach($moduleLangs as $arrayKey => $moduleLang) - { - /* Init key for delete '"'*/ - if(strpos($arrayKey, '\"') !== false) $arrayKey = str_replace(array('\"', '\"'), '', $arrayKey); - $arrayKey = !$arrayKey ? '' : (is_string($arrayKey) and !empty($key)) ? '"' . $arrayKey . '"' : $arrayKey; - $nextKey = empty($key) ? $arrayKey : $key . '[' . $arrayKey . ']'; - if(is_array($moduleLang) or is_object($moduleLang)) - { - $untieLang += $this->untieModuleLang($moduleLang, $nextKey); - } - else - { - $untieLang[$nextKey] = $moduleLang; - } - } - } - return $untieLang; + return $content; } - public function countWords($allWords) + public function checkNeedTranslate($value) { - $scores = 0; + $result = true; + if($value == 'new stdclass()') $result = false; + if(strpos($value, '$') === 0 and strpos($value, '$lang->productCommon') === false and strpos($value, '$lang->projectCommon') === false and preg_match('/["\'] *\./', $value) == 0 and preg_match('/\. *["\']/', $value) == 0) $result = false; + if($value == '$lang->productCommon' or $value == '$lang->projectCommon') $result = false; - $allWords = trim($allWords); - $allWords = preg_replace('/<[a-z\/]+.*>/Ui', '', $allWords); - - $allWords = preg_replace('/[\x80-\xff]{1,3}/', '', $allWords, -1, $scores); //Count chinese. - $scores += str_word_count($allWords); - return $scores; + return $result; } } diff --git a/module/translate/view/module.html.php b/module/translate/view/module.html.php new file mode 100644 index 0000000000..278fe69a07 --- /dev/null +++ b/module/translate/view/module.html.php @@ -0,0 +1,107 @@ + + +
+
+
translate->notice->failDirPriv, $cmd);?>
+
+ translate->refreshPage, 'onclick=location.href=location.href', 'btn btn-primary');?> +
+
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + $item):?> + translate->checkNeedTranslate($item) ? '' : "class='hidden'"; + if(empty($hideClass)) $i++; + + $hiddenKey = "value='{$key}'"; + if(strpos($key, "'") !== false) $hiddenKey = 'value="' . $key . '"'; + $hiddenKey = ''; + ?> + + > + + + + + + + + + > + + + + + + + > + + + + + + + + + + +
translate->key;?>langs[$referLang];?>langs[$language];?>langs[$referLang] . ' / ' . $config->langs[$language];?>translate->status;?>
$key" . $hiddenKey;?> + value != $item) ? htmlspecialchars($translation->value) : '', "class='form-control'"); + ?> + translate->statusList, $translation->status) : '';?>
$key" . $hiddenKey;?>translate->statusList, $translation->status) : '';?>
+ value != $item) ? htmlspecialchars($translation->value) : '', "class='form-control'"); + ?> +
+
+
+
+ +