+ translate->refreshPage, 'onclick=location.href=location.href', 'btn btn-primary');?> +
+ translate->refreshPage, 'onclick=location.href=location.href', 'btn btn-primary');?> +
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 @@
+
+
+