diff options
| author | Simon Rettberg | 2016-04-28 21:31:15 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2016-04-28 21:31:15 +0200 |
| commit | 95db8e184b378534db0ac08d14ae8500ee5090c3 (patch) | |
| tree | f39cee8160ef4266e49dbe04d3e8fe6400ce2133 /modules/translation/module.inc.php | |
| parent | Merge branch 'master' into modularization (diff) | |
| download | slx-admin-95db8e184b378534db0ac08d14ae8500ee5090c3.tar.gz slx-admin-95db8e184b378534db0ac08d14ae8500ee5090c3.tar.xz slx-admin-95db8e184b378534db0ac08d14ae8500ee5090c3.zip | |
Implemented new menu, added logic for defining dependencies, move translation files around
Diffstat (limited to 'modules/translation/module.inc.php')
| -rw-r--r-- | modules/translation/module.inc.php | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/modules/translation/module.inc.php b/modules/translation/module.inc.php deleted file mode 100644 index 3548f727..00000000 --- a/modules/translation/module.inc.php +++ /dev/null @@ -1,597 +0,0 @@ -<?php - -class Page_Translation extends Page -{ - - /** - * The pages where you can administrate the website translations - * @var string|boolean holds the target template - * @var string|boolean used to choose which page to load - * @var string|boolean used check if there should be an update - * @var string|boolean used check if there should be a deletion - * @var array|boolean holds the tags of the selected template - */ - private $template = false; - private $page = false; - - protected function doPreprocess() - { - User::load(); - - if (!User::hasPermission('superadmin')) { - Message::addError('no-permission'); - Util::redirect('?do=Main'); - } - - if (Request::post('update')) { - $this->updateJson(); - Util::redirect('?do=Translation'); - } - if (Request::post('delete')) { - $this->deleteTag(Request::post('path'), Request::post('delete')); - Util::redirect('?do=Translation'); // TODO: Ajax post for delete so we stay on the page - } - - $this->template = Request::get('template'); - $this->page = Request::get('page'); - } - - protected function doRender() - { - $langs = Dictionary::getLanguages(true); - - //load the page accordingly to the link - switch ($this->page) { - case 'messages': - //renders the message edit page - Render::addTemplate('edit', array( - 'path' => 'messages', - 'langs' => $langs, - 'tags' => $this->loadMessageEditArray() - )); - break; - case 'hardcoded': - //renders the hardcoded messages edit page - Render::addTemplate('edit', array( - 'path' => 'messages-hardcoded', - 'langs' => $langs, - 'tags' => $this->loadHardcodedStringEditArray() - )); - break; - case 'settings': - //renders the settings related edit page - Render::addTemplate('edit', array( - 'path' => 'cat_setting', - 'langs' => $langs, - 'tags' => $this->loadCategoriesArray() - )); - Render::addTemplate('edit', array( - 'path' => 'setting', - 'langs' => $langs, - 'tags' => $this->loadSettingsArray() - )); - break; - case 'config-module': - //renders the hardcoded messages edit page - Render::addTemplate('edit', array( - 'path' => 'config-module', - 'langs' => $langs, - 'tags' => $this->buildTranslationTable('config-module') - )); - break; - case 'template': - $this->template = Util::safePath($this->template); - if ($this->template === false) { - Message::addError('invalid-path'); - Util::redirect('?do=Translation'); - } - //renders the tag edition page - Render::addTemplate('edit', array( - 'path' => 'modules/' . $this->template, - 'langs' => $langs, - 'tags' => $this->loadTemplateEditArray($this->template) - )); - break; - case 'templates': - //renders the template selection page - Render::addTemplate('template-list', array( - 'table' => $this->loadTemplatesList(), - )); - break; - case 'modules': - Render::addTemplate('module-list', array( - 'table' => $this->loadModuleTable() - )); - break; - default: - //renders main page with selection of what part to edit - Render::addTemplate('_page'); - } - } - - private function loadModuleTable(){ - $table = array(); - - $modules = $this->loadModuleList(); - - foreach ($modules as $module) { - $msgs = $this->checkModuleTranslation($module); - $table[] = array( - 'module' => $module, - 'status' => $msgs - ); - } - - sort($table); - return $table; - } - - private function loadModuleEdit(){ - $table = array(); - $tags = array_flip($this->loadModuleTags($this->module)); - foreach ($this->langs as $lang) { - $tags = array_merge($tags, Dictionary::getArray($this->module,$lang['cc'])); - } - foreach ($tags as $tag => $value) { - $langArray = array(); - $class = ''; - foreach ($this->langs as $lang) { - $translations = Dictionary::getArray($this->module,$lang['cc']); - $langArray[] = array( - 'lang' => $lang['cc'], - 'placeholder' => 'TAG - ' . $lang['name'], - 'translation' => $translations[$tag] - ); - if(!in_array($tag, $this->loadModuleTags($this->module))) - $class = 'danger'; - else if(!$translations[$tag]) - $class = 'warning'; - } - $table[] = array( - 'tag' => $tag, - 'class' => $class, - 'langs' => $langArray - ); - } - - return $table; - } - - private function loadModuleList(){ - // Return an array with the modules and the tags data - $list = array(); - $list = array_diff(scandir('modules/'), array('..', '.')); - return $list; - } - - private function loadModuleTags($module){ - // Return an array with the module language tags - $path = "modules/" . $module . "templates/"; - $files = array_diff(scandir($path), array('..', '.')); - $tags = array(); - foreach ($files as $file) { - $content = file_get_contents($path . $file); - preg_match_all('/{{(lang_.*?)}}/s', $content, $matches); - if (isset($matches[1]) && is_array($matches[1])){ - $tags = array_merge($tags,array_unique($matches[1])); - } - } - return array_unique($tags); - } - - private function checkModuleTranslation($module){ - $tags = $this->loadModuleTags($module); - $translation = array(); - $msgs = ''; - foreach ($this->langs as $key => $lang) { - $translation = Dictionary::getArray($module,$lang['cc']); - $matches = 0; - $unused = 0; - $expected = count($tags); - foreach ($translation as $key => $value) { - if(!in_array($key, $tags)) - $unused ++; - else if(!empty($value)) - $matches ++; - - } - - $diff = $expected - $matches; - $msg = ""; - if ($diff > 0) - $msg .= $diff . " JSON tag(s) are missing"; - if ($diff > 0 && $unused > 0) - $msg .= "<br>"; - if ($unused > 0) - $msg .= $unused . " JSON tag(s) are not being used"; - if(!empty($msg)) - $msgs .= "<div><span class='badge'>{$lang['name']}:</span> $msg</div>"; - } - if(empty($msgs)) - $msgs = 'OK'; - return $msgs; - } - /** - * Load the main table with all the website's templates and it's informations - * @return array with the templates' information - */ - private function loadTemplatesList() - { - $table = array(); - - //loads every template - $files = $this->listTemplates(); - $langs = Dictionary::getLanguages(true); - - //checks the JSON tags from every language - foreach ($files as $file) { - $tags = $this->loadTemplateTags($file['path']); - // Don't list templates without lang tags - if (empty($tags)) - continue; - $msgs = ''; - foreach ($langs as $lang) { - $msg = $this->checkJson($file['path'], $lang['cc'], $tags); - if (!empty($msg)) - $msgs .= "<div><span class='badge'>{$lang['name']}:</span>$msg</div>"; - } - if (empty($msgs)) - $msgs = 'OK'; - $table[] = array( - 'template' => $file['name'], - 'link' => $file['name'], - 'status' => $msgs - ); - } - sort($table); - return $table; - } - - /** - * Finds and returns all the website's templates - * @return array - */ - private function listTemplates() - { - $files = array(); - $dir = 'modules/'; - $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); - foreach ($objects as $name => $object) { - if (substr($name, -5) === '.html') { - $files[] = array( - 'path' => substr($name, 0, -5), - 'name' => substr($name, strlen($dir), -5) - ); - } - } - return $files; - } - - /** - * Finds and returns all PHP files of slxadmin - * @return array of all php files - */ - private function listPhp() - { - $php = array(); - $dir = '.'; - $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); - foreach ($objects as $name => $object) { - if (substr($name, -4) === '.php') { - $php[] = $name; - } - } - return $php; - } - - /** - * Checks the JSON tags from a template - * @param string the template's path - * @param string the selected language - * @param string tags that should be in the json file - * @return string|boolean the information about the JSON tags, false if template has no lang-tags - */ - private function checkJson($path, $lang, $expectedTags) - { - //if there was not a valid template's path - if (!$path) { - return "Translation missing"; - } - // How many tags do we expect in the translation - $htmlCount = count($expectedTags); - - //initialize the count variables - $matchCount = 0; - $unusedCount = 0; - - //loads the JSON tags and count the matches - $json = Dictionary::getArray(substr($path, strlen("modules/")), $lang); - //return print_r($json) . "\nvs\n" . print_r($expectedTags); - foreach ($json as $key => $value) { - if (!in_array($key, $expectedTags)) { - $unusedCount++; - } else if (!empty($value)) { - $matchCount++; - } - } - $diff = $htmlCount - $matchCount; - - if ($diff == 0 && $unusedCount == 0) - return ''; - //build the return string - $str = ""; - if ($diff > 0) - $str .= $diff . " JSON tag(s) are missing"; - if ($diff > 0 && $unusedCount > 0) - $str .= "<br>"; - if ($unusedCount > 0) - $str .= $unusedCount . " JSON tag(s) are not being used"; - return $str; - } - - /** - * Get array to pass to edit page with all the tags and translations for the given template - * @param string $path the template's path - * @return array the information about the JSON tags - */ - private function loadTemplateEditArray($path) - { - $tags = $this->loadTemplateTags($path); - if ($tags === false) - return false; - return $this->buildTranslationTable("modules/" . $path, $tags); - } - - /** - * Load array of tags used in given template. - * @param string $path the path of the template, relative to templates/, without .html extension. - * @return array all tags in template - */ - private function loadTemplateTags($path) - { - $templateFile = "$path.html"; - //checks if the template is valid - if (!file_exists($templateFile)) { - Message::addError('invalid-template', $templateFile); - return false; - } - - //finds every mustache tag within the html template - $htmlTemplate = file_get_contents($templateFile); - preg_match_all('/{{(lang_.*?)}}/s', $htmlTemplate, $matches); - if (!isset($matches[1]) || !is_array($matches[1])) - return array(); - return array_unique($matches[1]); - } - - /** - * Load array of tags and translations of all messages - * @return array the information about the JSON tags - */ - private function loadMessageEditArray() - { - $tags = $this->loadTagsFromPhp('/Message\s*::\s*add\w+\s*\(\s*[\'"](.*?)[\'"]\s*[\)\,]/i'); - if ($tags === false) - return false; - return $this->buildTranslationTable('messages', $tags); - } - - /** - * Load array of tags and translations of all strings found in the php files. - * @return array the information about the JSON tags - */ - private function loadHardcodedStringEditArray() - { - $tags = $this->loadTagsFromPhp('/Dictionary\s*::\s*translate\s*\(\s*[\'"]([^\'"]*?)[\'"]\s*\)/i'); - if ($tags === false) - return false; - return $this->buildTranslationTable('messages-hardcoded', $tags); - } - - /** - * Load array of tags used in all the php files, by given regexp. Capture group 1 should return - * the exact tag name. - * @param string $regexp regular expression matching all tags in capture group 1 - * @return array of all tags found - */ - private function loadTagsFromPhp($regexp) - { - // Get all php files, so we can find all strings that need to be translated - $php = $this->listPhp(); - $tags = array(); - // Now find all tags in all php files. Only works for literal usage, not something like $foo = 'bar'; Dictionary::translate($foo); - foreach ($php as $file) { - $content = @file_get_contents($file); - if ($content === false || preg_match_all($regexp, $content, $out) < 1) - continue; - foreach ($out[1] as $id) { - $tags[$id] = true; - } - } - return array_keys($tags); - } - - private function buildTranslationTable($path, $requiredTags = false) - { - // All languages - $langArray = Dictionary::getLanguages(); - - $tags = array(); - if ($requiredTags !== false) { - foreach ($requiredTags as $tagName) { - $tags[$tagName] = array('tag' => $tagName); - foreach ($langArray as $lang) { - $tags[$tagName]['langs'][$lang]['lang'] = $lang; - $tags[$tagName]['missing'] = count($langArray); - } - } - } - // Finds every JSON tag within the JSON language files - foreach ($langArray as $lang) { - $jsonTags = Dictionary::getArray($path, $lang, true); - if (!is_array($jsonTags)) - continue; - foreach ($jsonTags as $tag => $translation) { - $tags[$tag]['langs'][$lang]['translation'] = $translation; - $tags[$tag]['langs'][$lang]['lang'] = $lang; - if (strpos($translation, "\n") !== false) - $tags[$tag]['langs'][$lang]['big'] = true; - $tags[$tag]['tag'] = $tag; - if (!isset($tags[$tag]['missing'])) - $tags[$tag]['missing'] = 0; - if (!empty($translation)) - $tags[$tag]['missing'] --; - } - } - // Fill the blanks - foreach ($langArray as $lang) { - foreach (array_keys($tags) as $tagName) { - if (!isset($tags[$tagName]['langs'][$lang])) - $tags[$tagName]['langs'][$lang]['lang'] = $lang; - } - } - // Finally remove $lang from the keys so mustache will iterate over them via {{#..}} - foreach ($tags as &$tag) { - $tag['langs'] = array_values($tag['langs']); - if ($requiredTags !== false) - $tag['class'] = $this->getTagColor($tag['missing']); - } - return array_values($tags); - } - - /** - * Change the color of the table line according to the tag status - * @param string the JSON's path - * @param string the selected tag - * @return string the css class of the line - */ - private function getTagColor($missingCount) - { - //return danger in case the tag is not found in the template - if ($missingCount < 0) - return 'danger'; - - //return warning in case at least one of the tag's values is empty - if ($missingCount > 0) - return 'warning'; - //if it's ok don't change the class - return ''; - } - - /** - * Updates a JSON file with it's new tags or/and tags values - */ - private function updateJson() - { - $langArray = Dictionary::getLanguages(); - foreach ($langArray as $lang) { - $json[$lang] = array(); - } - - //find the tag requests to change the file - foreach ($_POST as $key => $value) { - $str = explode('#', $key, 3); - if (count($str) !== 3 || $str[0] !== 'lang') - continue; - $lang = $str[1]; - $tag = trim($str[2]); - if (!isset($json[$lang])) { - Message::addWarning('i18n-invalid-lang', $lang); - continue; - } - if (empty($tag)) { - Message::addWarning('i18n-empty-tag'); - continue; - } - $value = trim($value); - if ($tag !== 'newtag') { - if (empty($value)) { - unset($json[$lang][$tag]); - } else { - $json[$lang][$tag] = $value; - } - } else { - if (!empty($value)) // TODO: Error message if new tag's name collides with existing - $json[$lang][$_REQUEST['newtag']] = $value; - } - } - - // JSON_PRETTY_PRINT is only available starting with php 5.4.0.... Use upgradephp's json_encode - require_once('inc/up_json_encode.php'); - - //saves the new values on the file - foreach ($json as $key => $array) { - $path = Util::safePath('lang/' . $key . '/' . Request::post('path') . '.json'); - if ($path === false) { - Message::addError('invalid-path'); - Util::redirect('?do=Translation'); - } - @mkdir(dirname($path), 0755, true); - ksort($array); // Sort by key, so the diff on the output is cleaner - $json = up_json_encode($array, JSON_PRETTY_PRINT); // Also for better diffability of the json files, we pretty print - //exits the function in case the action was unsuccessful - if (@file_put_contents($path, $json) === false) { - Message::addError('invalid-template'); - return; - } - } - Message::addSuccess('updated-tags'); - } - - /** - * Delete a specific JSON tag from a JSON files - * @var string the JSON's file path - * @var the JSON tag to be deleted - * @return boolean if the action was not successful - */ - private function deleteTag($path, $tag) - { - // JSON_PRETTY_PRINT is only available starting with php 5.4.0.... Use upgradephp's json_encode - require_once('inc/up_json_encode.php'); - - //delete the tag from every language file - $langArray = Dictionary::getLanguages(); - foreach ($langArray as $lang) { - $json = Dictionary::getArray($path, $lang); - unset($json[$tag]); - $result = file_put_contents('lang/' . $lang . '/' . $path . '.json', up_json_encode($json, JSON_PRETTY_PRINT)); - //add warning and exit in case the action was unsuccessful - if ($result === false) { - Message::addWarning('unsuccessful-action'); - return false; - } - } - Message::addSuccess('deleted-tag'); - } - - /** - * Load all settings categories for editing. - * - * @return array - */ - private function loadCategoriesArray() - { - $want = array(); - $res = Database::simpleQuery("SELECT catid FROM cat_setting ORDER BY catid ASC"); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $want[] = 'cat_' . $row['catid']; - } - return $this->buildTranslationTable('settings/cat_setting', $want); - } - - /** - * Load all settings categories for editing. - * - * @return array - */ - private function loadSettingsArray() - { - $want = array(); - $res = Database::simpleQuery("SELECT setting FROM setting ORDER BY setting ASC"); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $want[] = $row['setting']; - } - return $this->buildTranslationTable('settings/setting', $want); - } - -} |
