diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 4f942868a8..77ac3a9d41 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -375,7 +375,7 @@ $lang->admin->menu->custom = array('link' => '自定义|custom|set', 'subModu
$lang->admin->menu->sso = array('link' => '集成|admin|sso');
$lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension');
$lang->admin->menu->dev = array('link' => '二次开发|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor,entry');
-$lang->admin->menu->translate = array('link' => '翻译|translate|index');
+$lang->admin->menu->translate = array('link' => '翻译|translate|index', 'subModule' => 'translate');
$lang->admin->menu->data = array('link' => '数据|backup|index', 'subModule' => 'backup,action');
$lang->admin->menu->safe = array('link' => '安全|admin|safe', 'alias' => 'checkweak');
$lang->admin->menu->system = array('link' => '系统|cron|index', 'subModule' => 'cron');
diff --git a/module/translate/config.php b/module/translate/config.php
index 8c30cbf1b7..a45a6de829 100644
--- a/module/translate/config.php
+++ b/module/translate/config.php
@@ -1,4 +1,6 @@
translate->columnNum = 2;
$config->translate->defaultLang = array('en', 'zh-cn', 'zh-tw');
-$config->translate->limit = 10;
+$config->translate->needReview = '1';
+
+$config->translate->editor = new stdclass();
+$config->translate->editor->result = array('id' => 'reason', 'tools' => 'simpleTools');
diff --git a/module/translate/control.php b/module/translate/control.php
index 42b3598e8b..2bdef250e3 100644
--- a/module/translate/control.php
+++ b/module/translate/control.php
@@ -33,11 +33,11 @@ class translate extends control
*/
public function index()
{
- $itemCount = $this->translate->getLangItemCount();
- $progress = $this->translate->getProgress();
+ $itemCount = $this->translate->getLangItemCount();
+ $statistics = $this->translate->getLangStatistics();
$finishedLangs = $translatingLangs = array();
foreach($this->config->translate->defaultLang as $defaultLang) $finishedLangs[$defaultLang] = $this->config->langs[$defaultLang];
- foreach($progress as $translateLang => $data)
+ foreach($statistics as $translateLang => $data)
{
if($data->progress == 1)
{
@@ -111,6 +111,7 @@ class translate extends control
$this->view->position[] = html::a($this->createLink('translate', 'index'), $this->lang->translate->common);
$this->view->position[] = $this->lang->translate->chooseModule;
$this->view->modules = $this->translate->getModules();
+ $this->view->statistics = $this->translate->getModuleStatistics($language);
$this->view->language = $language;
$this->display();
@@ -126,20 +127,12 @@ class translate extends control
* @access public
* @return void
*/
- public function module($language, $module = '', $referLang = '')
+ public function module($language, $module, $referLang = '')
{
$moduleGroup = $this->translate->getModules();
- if(empty($module))
+ foreach($moduleGroup as $group => $modules)
{
- $group = current($this->lang->dev->groupList);
- $module = current($moduleGroup[$group]);
- }
- else
- {
- foreach($moduleGroup as $group => $modules)
- {
- if(in_array($module, $modules)) break;
- }
+ if(in_array($module, $modules)) break;
}
if(empty($referLang))
{
@@ -169,111 +162,130 @@ class translate extends control
$this->view->referItems = $this->translate->getModuleLangs($module, $referLang);
$this->view->translations = $this->translate->getTranslations($language, $module);
$this->view->moduleGroup = $moduleGroup;
- $this->view->currentModule = $module;
- $this->view->currentGroup = $group;
+ $this->view->currentModule = $module;
+ $this->view->currentGroup = $group;
$this->view->language = $language;
$this->view->referLang = $referLang;
$this->display();
}
- /**
- * Download selected language.
- *
- * @param string $zentaoVersion
- * @param string $language
- * @access public
- * @return void
- */
- public function download($zentaoVersion = '3.0', $language = 'en', $downloadModule = '')
+ public function review($language, $module, $referLang = '')
{
- $translateDir = $this->app->getBasePath() . "www/data/guard/zentaopms-$language" . date('His') . mt_rand(0, 100);
- $moduleDir = $translateDir . '/module/';
- mkdir($translateDir);
- mkdir($moduleDir);
- $modules = $this->translate->getModules($zentaoVersion);
- foreach ($modules as $module)
+ $moduleGroup = $this->translate->getModules();
+ foreach($moduleGroup as $group => $modules)
{
- if(!empty($downloadModule) and $downloadModule != $module) continue;
- $langPath = $moduleDir . $module . '/lang/';
- mkdir($moduleDir . $module);
- mkdir($langPath);
- $fileName = $langPath . $language . '.php';
- $filePath = $this->translate->getLangFilePath($zentaoVersion, 'en', $module);
- if(in_array($language, $this->config->translate->defaultLang))
+ if(in_array($module, $modules)) break;
+ }
+ if(empty($referLang))
+ {
+ $langs = json_decode($this->config->global->langs, true);
+ if(isset($langs[$language]))
{
- $filePath = $this->translate->getLangFilePath($zentaoVersion, $language, $module);
- copy($filePath, $fileName);
- continue;
+ $referLang = $langs[$language]['reference'];
}
-
- $translations = $this->translate->getTranslations($zentaoVersion, $language, $module);
-
- /* Write content for new lang file*/
- if(file_exists($filePath))
+ else
{
- $langHandle = fopen($filePath, "r");
- $writeHandle = fopen($fileName, 'w');
- while(!feof($langHandle))
+ $referLang = $language == 'zh-cn' ? 'en' : 'zh-cn';
+ }
+ }
+
+ $this->view->title = $this->lang->translate->review;
+ $this->view->position[] = html::a($this->createLink('translate', 'index'), $this->lang->translate->common);
+ $this->view->position[] = $this->lang->translate->review;
+
+ $this->view->referItems = $this->translate->getModuleLangs($module, $referLang);
+ $this->view->translations = $this->translate->getTranslations($language, $module);
+ $this->view->moduleGroup = $moduleGroup;
+ $this->view->currentModule = $module;
+ $this->view->currentGroup = $group;
+ $this->view->language = $language;
+ $this->view->referLang = $referLang;
+ $this->display();
+ }
+
+ public function result($translationID, $result)
+ {
+ if($result == 'pass')
+ {
+ $this->dao->update(TABLE_TRANSLATION)->set('status')->eq('reviewed')->set('reviewer')->eq($this->app->user->account)->set('reviewTime')->eq(helper::now())->where('id')->eq($translationID)->exec();
+ die(js::reload());
+ }
+ if($result == 'reject' and empty($_POST)) die($this->display());
+ if($result == 'reject' and $_POST)
+ {
+ $data = fixer::input('post')->get();
+ if(empty($data->reason)) $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->error->notempty, $this->lang->translate->reason)));
+ $this->dao->update(TABLE_TRANSLATION)->set('status')->eq('rejected')->set('reviewer')->eq($this->app->user->account)->set('reviewTime')->eq(helper::now())->set('reason')->eq($data->reason)->where('id')->eq($translationID)->exec();
+ $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.reloadStatus($translationID)"));
+ }
+ }
+
+ public function batchPass()
+ {
+ $this->dao->update(TABLE_TRANSLATION)->set('status')->eq('reviewed')->set('reviewer')->eq($this->app->user->account)->set('reviewTime')->eq(helper::now())->where('id')->in($this->post->idList)->exec();
+ $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload'));
+ }
+
+ public function setting()
+ {
+ if($_POST)
+ {
+ $data = fixer::input('post')->get();
+ $this->loadModel('setting')->setItem('system.translate.needReview', $data->needReview);
+ die(js::reload('parent.parent'));
+ }
+ $this->display();
+ }
+
+ public function export($language)
+ {
+ if($_POST)
+ {
+ $account = $this->app->user->account;
+ $cacheRoot = $this->app->getCacheRoot();
+
+ $zfile = $this->app->loadClass('zfile');
+ if(is_dir($cacheRoot . "{$account}_lang/")) $zfile->removeDir($cacheRoot . "{$account}_lang/");
+
+ $downloadFile = $cacheRoot . "{$account}_lang/zentao.zip";
+ $downloadPath = $cacheRoot . "{$account}_lang/zentao/";
+ mkdir($downloadPath, 0777, true);
+
+ $langs = json_decode($this->config->global->langs, true);
+ $referLang = isset($langs[$language]) ? $langs[$language]['reference'] : '';
+
+ $moduleRoot = $this->app->getModuleRoot();
+ foreach(glob($moduleRoot . '/*') as $modulePath)
+ {
+ $moduleName = basename($modulePath);
+ if(!is_dir($downloadPath . "module/{$moduleName}/lang/")) mkdir($downloadPath . "module/{$moduleName}/lang/", 0777, true);
+ if(!file_exists($modulePath . "/lang/{$language}.php") and !empty($referLang) and file_exists($modulePath . "/lang/{$referLang}.php"))
{
- $line = fgets($langHandle);
- $position = strpos($line, '=');
- if($position !== false and strrpos(ltrim($line), '$lang->') === 0)
- {
- $leftContent = substr($line, 0, $position);
- $langKey = str_replace(array("'", '$lang->'), array('"', ''), trim($leftContent));
- $write = $line;
- if(isset($translations[$langKey]))
- {
- $translation = current($translations[$langKey]);
- $write = $leftContent . "= '" . $translation->translation . "';\n";
- }
- fwrite($writeHandle, $write);
- }
- else
- {
- fwrite($writeHandle, $line);
- }
+ $translations = $this->dao->select('*')->from(TABLE_TRANSLATION)->where('lang')->eq($language)->andWhere('module')->eq($moduleName)->andWhere('flow')->eq($this->config->global->flow)->fetchAll('key');
+ $this->translate->buildLangFile($language, $moduleName, $translations, $referLang);
}
- fclose($langHandle);
+ if(file_exists($modulePath . "/lang/{$language}.php")) copy($modulePath . "/lang/{$language}.php", $downloadPath . "module/{$moduleName}/lang/{$language}.php");
}
+
+ $this->app->loadClass('pclzip', true);
+ $zip = new pclzip($downloadFile);
+ $zip->create($downloadPath, PCLZIP_OPT_REMOVE_PATH, dirname($downloadPath));
+
+ $content = file_get_contents($downloadFile);
+ if(is_dir($cacheRoot . "{$account}_lang/")) $zfile->removeDir($cacheRoot . "{$account}_lang/");
+
+ $this->loadModel('file')->sendDownHeader($this->post->fileName . '.zip', 'zip', $content);
}
- $downloadDir = dirname($translateDir);
- $fileDir = basename($translateDir);
- $fileName = $fileDir . '.zip';
- $downloadFile = $downloadDir . '/' . $fileName;
- `cd $downloadDir; zip -rm -9 $fileName $fileDir`;
- if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) $fileName = urlencode($fileName);
- header('Content-Description: File Transfer');
- header('Content-type: application/octet-stream');
- header("Content-Disposition: attachment; filename=$fileName");
- header('Content-Length: ' . filesize($downloadFile));
- readfile($downloadFile);
- unlink($downloadFile);
- die();
+ $this->app->loadLang('file');
+ $this->display();
}
- public function ajaxVote($translateID)
+ public function ajaxGetStatus($id)
{
- $this->dao->update(TABLE_TRANSLATE)->set('vote = vote + 1')->where('id')->eq($translateID)->exec(false);
- $userVotes = $this->cookie->votes;
- $userVotes .= $userVotes . "_" . $translateID . "_";
- setCookie('votes', $userVotes, $this->config->cookieLife);
- $translation = $this->dao->findByID($translateID)->from(TABLE_TRANSLATE)->fetch('', false);
- echo $translation->vote;
- }
+ $translation = $this->dao->select('*')->from(TABLE_TRANSLATION)->where('id')->eq($id)->fetch();
- public function delete($translateID, $consultLang, $confirm = 'no')
- {
- if($confirm == 'no')
- {
- die(js::confirm($this->lang->translate->notice->delete, inlink('delete', "translateID=$translateID&consultLang=$consultLang&confirm=yes")));
- }
- $translation = $this->dao->findByID($translateID)->from(TABLE_TRANSLATE)->fetch('', false);
-
- $scores = $this->translate->countWords($translation->translation);
- $this->loadModel('score')->log($translation->account, 'deleteTranslate', 'punish', $scores, 'TRANSLATE');
-
- $this->dao->delete()->from(TABLE_TRANSLATE)->where('id')->eq($translateID)->exec(false);
- die(js::locate(inLink('showLang', "version=$translation->version&language=$translation->language&module=$translation->module&consultLang=$consultLang"), 'parent'));
+ $status = zget($this->lang->translate->statusList, $translation->status);
+ if($translation->status == 'rejected') $status .= " ";
+ die($status);
}
}
diff --git a/module/translate/css/index.css b/module/translate/css/index.css
index 59ce15b6ca..14767e94e8 100644
--- a/module/translate/css/index.css
+++ b/module/translate/css/index.css
@@ -1,7 +1,7 @@
#mainMenu{font-size:16px;padding:5px 0px;}
.panel{margin-bottom:0px; border:0px;}
.panel .panel-body{padding-bottom:5px;}
+#translatingLangs .panel .panel-body{padding-right:0px;}
.panel .text-progress{color:#999;}
.panel p{padding-bottom:5px;}
.item .pull-right{color:#999;}
-.table-condensed td, .table-condensed th{padding:2px !important;}
diff --git a/module/translate/css/review.css b/module/translate/css/review.css
new file mode 100644
index 0000000000..a3584b8bf9
--- /dev/null
+++ b/module/translate/css/review.css
@@ -0,0 +1,3 @@
+.table-data tbody>tr>td{border:1px solid #cbd0db !important; padding-right:8px !important;}
+.main-col .main-form .table-footer{padding-left: 7px; border: 1px solid #cbd0db; border-top: 0px;}
+.main-col .main-form .table thead tr th .check-all{margin-left: -3px;}
diff --git a/module/translate/js/common.js b/module/translate/js/common.js
new file mode 100644
index 0000000000..4964c1d62b
--- /dev/null
+++ b/module/translate/js/common.js
@@ -0,0 +1,10 @@
+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);
+}
diff --git a/module/translate/js/module.js b/module/translate/js/module.js
index 6ebb88cdd7..ff84dfef11 100644
--- a/module/translate/js/module.js
+++ b/module/translate/js/module.js
@@ -4,16 +4,6 @@ function setTranslateView(view)
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/js/review.js b/module/translate/js/review.js
new file mode 100644
index 0000000000..370939425e
--- /dev/null
+++ b/module/translate/js/review.js
@@ -0,0 +1,42 @@
+function reloadStatus(translationID)
+{
+ $.get(createLink('translate', 'ajaxGetStatus', 'id=' + translationID), function(data)
+ {
+ var $td = $('#mainContent table tbody tr .pass[data-id=' + translationID + ']').closest('td');
+ $td.closest('tr').find('.status').html(data)
+ $td.html('');
+ });
+}
+$(function()
+{
+ adjustKeyWidth();
+ $('#mainContent table tbody [id^=idList]').change(function()
+ {
+ setTimeout(function()
+ {
+ var isCheckAll = true;
+ $('#mainContent table tbody [id^=idList]').each(function()
+ {
+ if(!$(this).prop('checked')) isCheckAll = false;
+ })
+ if(isCheckAll) $('.check-all').addClass('checked');
+ if(!isCheckAll) $('.check-all').removeClass('checked');
+ }, 50);
+ })
+
+ $('#mainContent table tbody tr .pass').click(function()
+ {
+ var $td = $(this).closest('td');
+ var $tr = $td.closest('tr');
+ var id = $(this).data('id');
+ $.get($(this).attr('href'), function()
+ {
+ $.get(createLink('translate', 'ajaxGetStatus', 'id=' + id), function(data)
+ {
+ $tr.find('.status').html(data)
+ $td.html('');
+ });
+ });
+ return false;
+ })
+});
diff --git a/module/translate/lang/zh-cn.php b/module/translate/lang/zh-cn.php
index 446453e38c..f2f9d26f5e 100644
--- a/module/translate/lang/zh-cn.php
+++ b/module/translate/lang/zh-cn.php
@@ -12,6 +12,8 @@ $lang->translate->common = '翻译';
$lang->translate->index = '首页';
$lang->translate->addLang = '新增语言';
$lang->translate->module = '翻译模块';
+$lang->translate->review = '审校';
+$lang->translate->setting = '设置';
$lang->translate->chooseModule = '选择翻译模块';
$lang->translate->name = '语言名称';
@@ -20,6 +22,22 @@ $lang->translate->key = '键';
$lang->translate->reference = '参考语言';
$lang->translate->status = '状态';
$lang->translate->refreshPage = '刷新';
+$lang->translate->reason = '拒绝原因';
+
+$lang->translate->reviewTurnon = '评审流程';
+$lang->translate->reviewTurnonList['1'] = '开启';
+$lang->translate->reviewTurnonList['0'] = '关闭';
+
+$lang->translate->resultList['pass'] = '通过';
+$lang->translate->resultList['reject'] = '拒绝';
+
+$lang->translate->group = '分组';
+$lang->translate->allTotal = '总条目';
+$lang->translate->translatedTotal = '已翻译条目数';
+$lang->translate->changedTotal = '已修改条目数';
+$lang->translate->reviewedTotal = '已审校条目数';
+$lang->translate->translatedProgress = '翻译进度';
+$lang->translate->reviewedProgress = '审校进度';
$lang->translate->builtIn = '内置语言';
$lang->translate->finished = '翻译完成';
diff --git a/module/translate/model.php b/module/translate/model.php
index 85ea1772f6..0536362ede 100644
--- a/module/translate/model.php
+++ b/module/translate/model.php
@@ -162,7 +162,7 @@ class translateModel extends model
{
$cmd = '';
$moduleRoot = $this->app->getModuleRoot();
- $modules = empty($moduleName) ? array($moduleRoot . $moduleName) : glob($moduleRoot . '*');
+ $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
";
@@ -205,13 +205,21 @@ class translateModel extends model
return $itemCount;
}
- public function getProgress()
+ public function getLangStatistics()
{
- $langs = $this->dao->select("`lang`,sum(if((status != 'waiting'),1,0)) as waitItems, count(*) as count")->from(TABLE_TRANSLATION)->groupBy('`lang`')->fetchAll('lang');
- foreach($langs as $lang => $data) $data->progress = round($data->waitItems / $data->count, 3);
+ $langs = $this->dao->select("`lang`,sum(if((status = 'translated'),1,0)) as translatedItems,sum(if((status = 'reviewed'),1,0)) as reviewedItems, count(*) as count")->from(TABLE_TRANSLATION)->groupBy('`lang`')->fetchAll('lang');
+ foreach($langs as $lang => $data) $data->progress = round(($data->translatedItems + $data->reviewedItems) / $data->count, 3);
return $langs;
}
+ public function getModuleStatistics($language)
+ {
+ $fields = 'lang,module,';
+ foreach($this->lang->translate->statusList as $status => $title) $fields .= "sum(if((status = '$status'),1,0)) as $status,";
+ $fields .= "count(*) as count";
+ return $this->dao->select($fields)->from(TABLE_TRANSLATION)->where('lang')->eq($language)->groupBy('module')->fetchAll('module');
+ }
+
/**
* Get Translations
*
@@ -256,7 +264,6 @@ class translateModel extends model
if(!empty($_POST['values'][$i])) $value = $this->post->values[$i];
if($dbItem)
{
- unset($dbItem->id);
$translation = $dbItem;
$translation->version = $this->config->version;
if($dbItem->value != $value)
diff --git a/module/translate/view/choosemodule.html.php b/module/translate/view/choosemodule.html.php
index 8ffc7f5d0b..5a04645dff 100644
--- a/module/translate/view/choosemodule.html.php
+++ b/module/translate/view/choosemodule.html.php
@@ -13,23 +13,51 @@
-
dev->moduleList . ' > ' . $lang->translate->chooseModule;?>
+ langs[$language]}] " . $lang->dev->moduleList . ' > ' . $lang->translate->chooseModule;?>
-