summaryrefslogtreecommitdiffstats
path: root/modules/translation/module.inc.php
diff options
context:
space:
mode:
authorSimon Rettberg2016-04-28 21:31:15 +0200
committerSimon Rettberg2016-04-28 21:31:15 +0200
commit95db8e184b378534db0ac08d14ae8500ee5090c3 (patch)
treef39cee8160ef4266e49dbe04d3e8fe6400ce2133 /modules/translation/module.inc.php
parentMerge branch 'master' into modularization (diff)
downloadslx-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.php597
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);
- }
-
-}