diff options
author | Simon Rettberg | 2014-09-02 18:46:24 +0200 |
---|---|---|
committer | Simon Rettberg | 2014-09-02 18:46:24 +0200 |
commit | 32f22e10ff63a555e5b80207dc524390aa4bc6c1 (patch) | |
tree | 702a01c3ba1dc2a5ca6ebc4a7810005a8c76a16f | |
parent | [Render] Show untranslated tags in rendered output (diff) | |
download | slx-admin-32f22e10ff63a555e5b80207dc524390aa4bc6c1.tar.gz slx-admin-32f22e10ff63a555e5b80207dc524390aa4bc6c1.tar.xz slx-admin-32f22e10ff63a555e5b80207dc524390aa4bc6c1.zip |
[i18n] Language handling is now completely dynamic, no more hardcoded de,en,pt
25 files changed, 283 insertions, 425 deletions
diff --git a/inc/dictionary.inc.php b/inc/dictionary.inc.php index 6efd8fde..fc509112 100644 --- a/inc/dictionary.inc.php +++ b/inc/dictionary.inc.php @@ -4,7 +4,8 @@ class Dictionary { private static $messageArray = false; - private static $languages; + private static $languages = false; + private static $languagesLong = false; private static $stringCache = array(); private static $hardcodedMessages = false; @@ -62,14 +63,13 @@ class Dictionary $file = Util::safePath("lang/" . $lang . "/" . $section . ".json"); if (isset(self::$stringCache[$file])) return self::$stringCache[$file]; - $language = array('lang' => $lang); $content = @file_get_contents($file); if ($content === false) // File does not exist for language - return $language; + return array(); $json = json_decode($content, true); if (!is_array($json)) - return $language; - return self::$stringCache[$file] = array_merge($language, $json); + return array(); + return self::$stringCache[$file] = $json; } public static function translate($section, $string = false) @@ -100,11 +100,29 @@ class Dictionary /** * Get all supported languages as array - * @return array List of languages (2 char id) + * @param boolean $withName true = return assoc array containinc cc and name of all languages; + * false = regular array containing only the ccs + * @return array List of languages */ - public static function getLanguages() + public static function getLanguages($withName = false) { - return self::$languages; + if (!$withName) + return self::$languages; + if (self::$languagesLong === false) { + self::$languagesLong = array(); + foreach (self::$languages as $lang) { + if (file_exists("lang/$lang/name.txt")) { + $name = @file_get_contents("lang/$lang/name.txt"); + } else { + $name = $lang; + } + self::$languagesLong[] = array( + 'cc' => $lang, + 'name' => $name + ); + } + } + return self::$languagesLong; } } diff --git a/inc/menu.inc.php b/inc/menu.inc.php deleted file mode 100644 index fdec08c3..00000000 --- a/inc/menu.inc.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -require_once('inc/render.inc.php'); -require_once('inc/user.inc.php'); - -class Menu -{ - - public function loginPanel() - { - if (User::getName() === false) return Render::parse('menu-login'); - return Render::parse('menu-logout', array( - 'user' => User::getName() - )); - } - -} - @@ -117,11 +117,13 @@ Page::preprocess(); //$menu = new Menu; if (User::getName() === false) { Render::addTemplate('main-menu-login', array( - 'url' => urlencode($_SERVER['REQUEST_URI']) + 'url' => urlencode($_SERVER['REQUEST_URI']), + 'langs' => Dictionary::getLanguages(true) )); } else { Render::addTemplate('main-menu-logout', array( 'url' => urlencode($_SERVER['REQUEST_URI']), + 'langs' => Dictionary::getLanguages(true), 'user' => User::getName() )); } diff --git a/lang/de/messages.json b/lang/de/messages.json index db10fbad..9ffbc24e 100644 --- a/lang/de/messages.json +++ b/lang/de/messages.json @@ -18,6 +18,7 @@ "invalid-action": "Ung\u00fcltige Aktion: {{0}}", "invalid-file": "Die Datei {{0}} existiert nicht!", "invalid-ip": "Kein Interface ist auf die Adresse {{0}} konfiguriert", + "invalid-path": "", "invalid-template": "Ausgew\u00e4hlte Template ist nicht g\u00fcltig", "loginfail": "Benutzername oder Kennwort falsch", "missing-file": "Es wurde keine Datei ausgew\u00e4hlt!", diff --git a/lang/de/name.txt b/lang/de/name.txt new file mode 100644 index 00000000..176e5370 --- /dev/null +++ b/lang/de/name.txt @@ -0,0 +1 @@ +Deutsch
\ No newline at end of file diff --git a/lang/de/templates/translation/_page.json b/lang/de/templates/translation/_page.json index 94e448c2..1e59df52 100644 --- a/lang/de/templates/translation/_page.json +++ b/lang/de/templates/translation/_page.json @@ -1,8 +1,8 @@ { "lang_adminInfo": "In diesem Abschnitt k\u00f6nnen Sie die JSON-Tags, die \u00fcbersetzten Texte durch die Website verwendet wird, enth\u00e4lt zu \u00e4ndern. Um dies zu tun, w\u00e4hlen Sie eine Vorlage aus, um ihre jeweiligen Tags \u00e4ndern. Alternativ klicken Sie auf den Link unten, um die Nachrichten der Website \u00e4ndern.", + "lang_editHardcoded": "Hardcoded-Texte bearbeiten", "lang_editMessages": "Nachrichten bearbeiten", - "lang_english": "Englisch", - "lang_german": "Deutsch", - "lang_langAdministration": "Sprache Verwaltung", - "lang_portuguese": "Portuguiesisch" + "lang_editSettings": "Einstellungs-Texte bearbeiten", + "lang_editTemplates": "Template-Texte bearbeiten", + "lang_langAdministration": "Sprache Verwaltung" }
\ No newline at end of file diff --git a/lang/de/templates/translation/template.json b/lang/de/templates/translation/edit.json index 8f3dfb66..c2c6b755 100644 --- a/lang/de/templates/translation/template.json +++ b/lang/de/templates/translation/edit.json @@ -2,12 +2,9 @@ "lang_back": "Z\u00fcruck", "lang_createTag": "TAG schafen", "lang_deleteTAG": "L\u00f6schen", - "lang_englishJSON": "Englisch JSON", "lang_englishTAG": "Englisch TAG", - "lang_germanJSON": "Deutsch JSON", "lang_germanTAG": "Deutsch TAG", "lang_newTAG": "Neue Tag", - "lang_portugueseJSON": "Portugiesisch JSON", "lang_portugueseTAG": "Portugiesisch TAG", "lang_save": "Speichern", "lang_templateAdminHelp": "", diff --git a/lang/de/templates/translation/messages.json b/lang/de/templates/translation/messages.json deleted file mode 100644 index 656c7e15..00000000 --- a/lang/de/templates/translation/messages.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "lang_back": "Z\u00fcruck", - "lang_deleteTAG": "L\u00f6schen", - "lang_englishJSON": "Englisch JSON", - "lang_englishTAG": "Englisch TAG", - "lang_germanJSON": "Deutsch JSON", - "lang_germanTAG": "Deutsch TAG", - "lang_messages": "Nachrichten", - "lang_messagesHardcoded": "Hardcoded Nachrichten", - "lang_newTAG": "Neuer Tag", - "lang_newTag": "Neue Nachricht", - "lang_portugueseJSON": "Portugiesisch JSON", - "lang_portugueseTAG": "Portugiesisch TAG", - "lang_save": "Speichern", - "lang_templateHint": "Hinweis: Gelbe Linien zeigen eine \u00dcbersetzung fehlt und roten Linien zeigen ein Tag wird nicht von der Vorlage verwendet.", - "lang_templateMessagesHelp": "" -}
\ No newline at end of file diff --git a/lang/en/messages.json b/lang/en/messages.json index a300cff7..3302545c 100644 --- a/lang/en/messages.json +++ b/lang/en/messages.json @@ -18,6 +18,7 @@ "invalid-action": "Invalid action: {{0}}", "invalid-file": "The file {{0}} does not exist!", "invalid-ip": "No interface is configured with the address {{0}}", + "invalid-path": "", "invalid-template": "Selected template is not valid", "loginfail": "Username or Password incorrect", "missing-file": "There was no file selected!", diff --git a/lang/en/name.txt b/lang/en/name.txt new file mode 100644 index 00000000..3d38949d --- /dev/null +++ b/lang/en/name.txt @@ -0,0 +1 @@ +English
\ No newline at end of file diff --git a/lang/en/templates/translation/_page.json b/lang/en/templates/translation/_page.json index 1c84d34c..c9c6020d 100644 --- a/lang/en/templates/translation/_page.json +++ b/lang/en/templates/translation/_page.json @@ -1,8 +1,8 @@ { "lang_adminInfo": "In this section you can change the JSON tags that contains the translated texts used by the site. To do this, select a template below to modify their respective tags. Alternatively, click the link below to change the messages of the site.", + "lang_editHardcoded": "Edit hardcoded strings", "lang_editMessages": "Edit Messages", - "lang_english": "English", - "lang_german": "German", - "lang_langAdministration": "Language Administration", - "lang_portuguese": "Portuguese" + "lang_editSettings": "Edit configuration variables related strings", + "lang_editTemplates": "Edit template strings", + "lang_langAdministration": "Language Administration" }
\ No newline at end of file diff --git a/lang/en/templates/translation/template.json b/lang/en/templates/translation/edit.json index ad07a8b6..ff3f44ca 100644 --- a/lang/en/templates/translation/template.json +++ b/lang/en/templates/translation/edit.json @@ -2,12 +2,9 @@ "lang_back": "Back", "lang_createTag": "Create TAG", "lang_deleteTAG": "Delete", - "lang_englishJSON": "English JSON", "lang_englishTAG": "English TAG", - "lang_germanJSON": "German JSON", "lang_germanTAG": "German TAG", "lang_newTAG": "New TAG", - "lang_portugueseJSON": "German JSON", "lang_portugueseTAG": "Portuguese TAG", "lang_save": "Save", "lang_templateAdminHelp": "", diff --git a/lang/en/templates/translation/messages.json b/lang/en/templates/translation/messages.json deleted file mode 100644 index 433e9cdf..00000000 --- a/lang/en/templates/translation/messages.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "lang_back": "Back", - "lang_deleteTAG": "Delete", - "lang_englishJSON": "English JSON", - "lang_englishTAG": "English TAG", - "lang_germanJSON": "German JSON", - "lang_germanTAG": "German TAG", - "lang_messages": "Messages", - "lang_messagesHardcoded": "Hardcoded Messages", - "lang_newTAG": "New TAG", - "lang_newTag": "New Tag", - "lang_portugueseJSON": "German JSON", - "lang_portugueseTAG": "Portuguese TAG", - "lang_save": "Save", - "lang_templateHint": "Hint: Yellow lines indicate a translation is missing and red lines indicate a tag is not being used by the template.", - "lang_templateMessagesHelp": "" -}
\ No newline at end of file diff --git a/lang/pt/messages.json b/lang/pt/messages.json index c11497b0..e02f9a1a 100644 --- a/lang/pt/messages.json +++ b/lang/pt/messages.json @@ -18,6 +18,7 @@ "invalid-action": "A\u00e7\u00e3o inv\u00e1lida: {{0}}", "invalid-file": "O arquivo {{0}} n\u00e3o existe!", "invalid-ip": "Nenhuma interface est\u00e1 configurada com o endere\u00e7o {{0}}", + "invalid-path": "", "invalid-template": "Template selecionado n\u00e3o \u00e9 v\u00e1lido", "loginfail": "Nome de usu\u00e1rio ou senha incorreta", "missing-file": "N\u00e3o havia nenhum arquivo selecionado!", diff --git a/lang/pt/name.txt b/lang/pt/name.txt new file mode 100644 index 00000000..811b10b4 --- /dev/null +++ b/lang/pt/name.txt @@ -0,0 +1 @@ +Português
\ No newline at end of file diff --git a/lang/pt/templates/translation/_page.json b/lang/pt/templates/translation/_page.json index af575a4d..68043805 100644 --- a/lang/pt/templates/translation/_page.json +++ b/lang/pt/templates/translation/_page.json @@ -1,8 +1,8 @@ { "lang_adminInfo": "Nesta se\u00e7\u00e3o \u00e9 poss\u00edvel alterar as TAGs de JSON que cont\u00e9m os textos traduzidos utilizados no site. Para fazer isto, selecione um template abaixo para modificar suas respectivas TAGs. Alternativamente, clique no link abaixo para alterar as mensagens do site.", + "lang_editHardcoded": "", "lang_editMessages": "Editar Mensagens", - "lang_english": "Ingl\u00eas", - "lang_german": "Alem\u00e3o", - "lang_langAdministration": "Administra\u00e7\u00e3o da L\u00edngua", - "lang_portuguese": "Portugu\u00eas" + "lang_editSettings": "", + "lang_editTemplates": "", + "lang_langAdministration": "Administra\u00e7\u00e3o da L\u00edngua" }
\ No newline at end of file diff --git a/lang/pt/templates/translation/template.json b/lang/pt/templates/translation/edit.json index 008da819..42eb5b28 100644 --- a/lang/pt/templates/translation/template.json +++ b/lang/pt/templates/translation/edit.json @@ -2,12 +2,9 @@ "lang_back": "Voltar", "lang_createTag": "Criar TAG", "lang_deleteTAG": "Excluir", - "lang_englishJSON": "JSON Ingl\u00eas", "lang_englishTAG": "TAG em Ingl\u00eas", - "lang_germanJSON": "JSON Alem\u00e3o", "lang_germanTAG": "TAG em Alem\u00e3o", "lang_newTAG": "Nova TAG", - "lang_portugueseJSON": "JSON Portugu\u00eas", "lang_portugueseTAG": "TAG em Portugu\u00eas", "lang_save": "Salvar", "lang_templateAdminHelp": "", diff --git a/lang/pt/templates/translation/messages.json b/lang/pt/templates/translation/messages.json deleted file mode 100644 index cb5fc59b..00000000 --- a/lang/pt/templates/translation/messages.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "lang_back": "Voltar", - "lang_deleteTAG": "Excluir", - "lang_englishJSON": "JSON Ingl\u00eas", - "lang_englishTAG": "Mensagem em Ingl\u00eas", - "lang_germanJSON": "JSON Alem\u00e3o", - "lang_germanTAG": "Mensagem em Alem\u00e3o", - "lang_messages": "Mensagens", - "lang_messagesHardcoded": "Mensagens Hardcoded", - "lang_newTAG": "Nova TAG", - "lang_newTag": "Nova Mensagem", - "lang_portugueseJSON": "JSON Portugu\u00eas", - "lang_portugueseTAG": "Mensagem em Portugu\u00eas", - "lang_save": "Salvar", - "lang_templateHint": "Dica: linhas amarelas indicam que uma tradu\u00e7\u00e3o est\u00e1 faltando e linhas vermelhas indicam que uma tag n\u00e3o \u00e9 utilizada pelo template.", - "lang_templateMessagesHelp": "Aqui \u00e9 poss\u00edvel alterar as mensagens exibidas no site." -}
\ No newline at end of file diff --git a/modules/translation.inc.php b/modules/translation.inc.php index d946357a..fc04fc52 100644 --- a/modules/translation.inc.php +++ b/modules/translation.inc.php @@ -26,54 +26,76 @@ class Page_Translation extends Page 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'); - $this->delete = Request::get('delete'); - $this->update = Request::post('update'); } protected function doRender() { - //calls the update function - if ($this->update) - $this->updateJson(); - //calls the tag deletion function - if ($this->delete && $this->template) - $this->deleteTag($this->template, $this->delete); + $langs = Dictionary::getLanguages(true); //load the page accordingly to the link switch ($this->page) { case 'messages': - //renders the message edition page - Render::addTemplate('translation/messages', array( - 'msgs' => $this->initMsg(false), - 'msgsHC' => $this->initMsg(true) + //renders the message edit page + Render::addTemplate('translation/edit', array( + 'path' => 'messages', + 'langs' => $langs, + 'tags' => $this->loadMessageEditArray() )); break; - case 'templates': + case 'hardcoded': + //renders the hardcoded messages edit page + Render::addTemplate('translation/edit', array( + 'path' => 'messages-hardcoded', + 'langs' => $langs, + 'tags' => $this->loadHardcodedStringEditArray() + )); + break; + case 'settings': + //renders the settings related edit page + Render::addTemplate('translation/edit', array( + 'path' => 'settings/cat_setting', + 'langs' => $langs, + 'tags' => $this->buildTranslationTable('settings/cat_setting') + )); + Render::addTemplate('translation/edit', array( + 'path' => 'settings/setting', + 'langs' => $langs, + 'tags' => $this->buildTranslationTable('settings/setting') + )); + 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 - if ($this->templateAnalysis($this->template)) { - $langs = array(); - foreach (Dictionary::getLanguages() as $lang) { - $langs[] = array('lang' => $lang); - } - Render::addTemplate('translation/template', array( - 'template' => 'templates/' . $this->template, - 'langs' => $langs, - 'tags' => $this->tags - )); - break; - } - default: + Render::addTemplate('translation/edit', array( + 'path' => 'templates/' . $this->template, + 'langs' => $langs, + 'tags' => $this->loadTemplateEditArray($this->template) + )); + break; + case 'templates': //renders the template selection page - Render::addTemplate('translation/_page', array( - 'table' => $this->initTable(), + Render::addTemplate('translation/template-list', array( + 'table' => $this->loadTemplatesList(), )); + break; + default: + //renders main page with selection of what part to edit + Render::addTemplate('translation/_page'); } } @@ -81,29 +103,32 @@ class Page_Translation extends Page * Load the main table with all the website's templates and it's informations * @return array with the templates' information */ - private function initTable() + private function loadTemplatesList() { $table = array(); //loads every template $files = $this->listTemplates(); - //loads every json from each language - $de = $this->listJson('de/templates/'); - $en = $this->listJson('en/templates/'); - $pt = $this->listJson('pt/templates/'); + $langs = Dictionary::getLanguages(true); //checks the JSON tags from every language - foreach ($files as $key => $value) { + foreach ($files as $file) { + $tags = $this->loadTemplateTags($file['path']); // Don't list templates without lang tags - $tmp = $this->checkJson($de[$key], 'de'); - if ($tmp === false) // TODO: Pretty solution + 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' => $value, - 'link' => $key, - 'de' => $tmp, - 'en' => $this->checkJson($en[$key], 'en'), - 'pt' => $this->checkJson($pt[$key], 'pt') + 'template' => $file['name'], + 'link' => $file['name'], + 'status' => $msgs ); } sort($table); @@ -120,35 +145,17 @@ class Page_Translation extends Page $dir = 'templates/'; $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); foreach ($objects as $name => $object) { - if (substr($name, -5) === '.html') { - $key = substr($name, strlen($dir), -5); - $files[$key] = substr($name, strlen($dir)); + if (substr($name, -5) === '.html') { + $files[] = array( + 'path' => substr($name, 0, -5), + 'name' => substr($name, strlen($dir), -5) + ); } } return $files; } /** - * Finds and returns all the JSON files from a selected language - * @param string the selected language (abbreviated) - * @return array all the JSON files from the language - */ - private function listJson($lang) - { - $json = array(); - $dir = 'lang/' . $lang; - $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); - foreach ($objects as $name => $object) { - if (substr($name, -5) === '.json') { - $key = str_replace($dir, '', $name); - $key = substr($key, 0, -5); - $json[$key] = $key; - } - } - return $json; - } - - /** * Finds and returns all PHP files of slxadmin * @return array of all php files */ @@ -169,41 +176,38 @@ class Page_Translation extends Page * 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) + private function checkJson($path, $lang, $expectedTags) { //if there was not a valid template's path if (!$path) { - return "JSON file is missing"; + return "Translation missing"; } - //loads a template and find all its tags - $htmlTemplate = @file_get_contents("templates/$path.html"); - if (preg_match_all('/{{lang_(.*?)}}/s', $htmlTemplate, $matches) == 0) - return false; - $htmlCount = count(array_unique($matches[1])); + // 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::getArrayTemplate($path, $lang); + $json = Dictionary::getArray($path, $lang); + //return print_r($json) . "\nvs\n" . print_r($expectedTags); foreach ($json as $key => $value) { - if ($key != 'lang') { - if (!in_array(preg_replace('/^lang_/', '', $key), $matches[1])) { - $unusedCount++; - } else if ($value != '') { - $matchCount++; - } + 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 && $unusedCount == 0) - $str .= "OK"; if ($diff > 0) $str .= $diff . " JSON tag(s) are missing"; if ($diff > 0 && $unusedCount > 0) @@ -214,14 +218,26 @@ class Page_Translation extends Page } /** - * Builds the template page with the tags from its template and its JSON file - * @param string the template's path - * @param string the selected language - * @return string the information about the JSON tags + * 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 templateAnalysis($path) + private function loadTemplateEditArray($path) { $path = "templates/$path"; + $tags = $this->loadTemplateTags($path); + if ($tags === false) + return false; + return $this->buildTranslationTable($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)) { @@ -229,18 +245,74 @@ class Page_Translation extends Page return false; } - // All languages - $langArray = Dictionary::getLanguages(); - //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(); - foreach ($matches[1] as $tagName) { - $tags[$tagName] = array('tag' => $tagName); - foreach ($langArray as $lang) { - $tags[$tagName]['langs'][$lang]['lang'] = $lang; - $tags[$tagName]['missing'] = count($langArray); + 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); + } } } @@ -250,40 +322,22 @@ class Page_Translation extends Page if (!is_array($jsonTags)) continue; foreach ($jsonTags as $tag => $translation) { - if (substr($tag, 0, 5) === 'lang_') { - $tags[$tag]['langs'][$lang]['translation'] = $translation; - $tags[$tag]['tag'] = $tag; - if (!isset($tags[$tag]['missing'])) - $tags[$tag]['missing'] = 0; - if (!empty($translation)) - $tags[$tag]['missing']--; - } + $tags[$tag]['langs'][$lang]['translation'] = $translation; + $tags[$tag]['langs'][$lang]['lang'] = $lang; + $tags[$tag]['tag'] = $tag; + if (!isset($tags[$tag]['missing'])) + $tags[$tag]['missing'] = 0; + if (!empty($translation)) + $tags[$tag]['missing'] --; } } // Finally remove $lang from the keys so mustache will iterate over them via {{#..}} foreach ($tags as &$tag) { $tag['langs'] = array_values($tag['langs']); - $tag['class'] = $this->getTagColor($tag['missing']); - } - $this->tags = array_values($tags); - - return true; - } - - /** - * Loads the content of a JSON tag - * @param string the JSON's path - * @param string the selected tag - * @param string the specified language - * @return string the tag's content - */ - private function getJsonTag($path, $tag, $lang) - { - $json = Dictionary::getArray($path, $lang); - if (is_array($json) && isset($json[$tag])) { - return $json[$tag]; + if ($requiredTags !== false) + $tag['class'] = $this->getTagColor($tag['missing']); } - return ''; + return array_values($tags); } /** @@ -316,15 +370,12 @@ class Page_Translation extends Page } //find the tag requests to change the file - foreach ($_REQUEST as $key => $value) { + foreach ($_POST as $key => $value) { $str = explode('#', $key, 3); - if (count($str) !== 3) + if (count($str) !== 3 || $str[0] !== 'lang') continue; - $pre = $str[0]; $lang = $str[1]; - $tag = $str[2]; - if ($pre !== 'lang') - continue; + $tag = trim($str[2]); if (!isset($json[$lang])) { Message::addWarning('i18n-invalid-lang', $lang); continue; @@ -351,9 +402,7 @@ class Page_Translation extends Page Util::redirect('?do=Translation'); } ksort($array); // Sort by key, so the diff on the output is cleaner - error_log("Converting " . print_r($array, true)); $json = up_json_encode($array, JSON_PRETTY_PRINT); // Also for better diffability of the json files, we pretty print - error_log("Result: $json"); //exits the function in case the action was unsuccessful if (@file_put_contents($path, $json) === false) { Message::addError('invalid-template'); @@ -364,48 +413,6 @@ class Page_Translation extends Page } /** - * Load the main table with all the website's messages or hardcoded messages - * @var boolean choose between hardcoded and non-hardcoded messages - * @return array with the selected messages - */ - private function initMsg($isHardcoded) - { - $msgs = array(); - // Get all php files, so we can find all strings that need to be translated - $php = $this->listPhp(); - $tags = array(); - //chooses the path and regex - if ($isHardcoded) { - $path = 'messages-hardcoded'; - $expr = '/Dictionary\s*::\s*translate\s*\(\s*[\'"](.*?)[\'"]\s*[\)\,]/i'; - } else { - $path = 'messages'; - $expr = '/Message\s*::\s*add\w+\s*\(\s*[\'"](.*?)[\'"]\s*[\)\,]/i'; - } - // 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($expr, $content, $out) < 1) - continue; - foreach ($out[1] as $id) { - if (!isset($tags[$id])) - $tags[$id] = 0; // TODO: Display usage count next to it, even better would be list of php files it appears in, so a translator can get context - $tags[$id]++; - } - } - ksort($tags); - foreach ($tags as $tag => $usageCount) { - $msgs[] = array( - 'tag' => $tag, - 'de' => $this->getJsonTag($path, $tag, 'de/'), // TODO: Hardcoded language list, use Dictionary::getLanguages() - 'en' => $this->getJsonTag($path, $tag, 'en/'), - 'pt' => $this->getJsonTag($path, $tag, 'pt/') - ); - } - return $msgs; - } - - /** * Delete a specific JSON tag from a JSON files * @var string the JSON's file path * @var the JSON tag to be deleted @@ -413,13 +420,15 @@ class Page_Translation extends Page */ 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::getArrayTemplate($path, $lang); + $json = Dictionary::getArray($path, $lang); unset($json[$tag]); - unset($json['lang']); - $result = file_put_contents('lang/' . $lang . '/' . $path . '.json', json_encode($json)); + $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'); diff --git a/templates/main-menu-login.html b/templates/main-menu-login.html index 81aef288..3f06e40b 100644 --- a/templates/main-menu-login.html +++ b/templates/main-menu-login.html @@ -29,12 +29,12 @@ <li><a href="?do=News">{{lang_news}}</a></li> <li><a href="?do=SystemStatus">Status</a></li> <li class="dropdown"> - <a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="lang/{{lang}}/flag.png"><b class="caret"></b></a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="lang/{{current_lang}}/flag.png"><b class="caret"></b></a> <ul class="dropdown-menu"> <li class="dropdown-header">{{lang_language}}</li> - <li><a href="?lang=de&url={{url}}"><img src="lang/de/flag.png"> Deutsch</a></li> - <li><a href="?lang=en&url={{url}}"><img src="lang/en/flag.png"> English</a></li> - <li><a href="?lang=pt&url={{url}}"><img src="lang/pt/flag.png"> Português</a></li> + {{#langs}} + <li><a href="?lang={{cc}}&url={{url}}"><img src="lang/{{cc}}/flag.png" alt="{{name}}"> {{name}}</a></li> + {{/langs}} </ul> </li> </ul> diff --git a/templates/main-menu-logout.html b/templates/main-menu-logout.html index d5671fef..149e0369 100644 --- a/templates/main-menu-logout.html +++ b/templates/main-menu-logout.html @@ -29,12 +29,12 @@ <li><a href="?do=News">{{lang_news}}</a></li> <li><a href="?do=SystemStatus">Status</a></li> <li class="dropdown"> - <a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="lang/{{lang}}/flag.png"><b class="caret"></b></a> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="lang/{{current_lang}}/flag.png"><b class="caret"></b></a> <ul class="dropdown-menu"> <li class="dropdown-header">{{lang_language}}</li> - <li><a href="?lang=de&url={{url}}"><img src="lang/de/flag.png"> Deutsch</a></li> - <li><a href="?lang=en&url={{url}}"><img src="lang/en/flag.png"> English</a></li> - <li><a href="?lang=pt&url={{url}}"><img src="lang/pt/flag.png"> Português</a></li> + {{#langs}} + <li><a href="?lang={{cc}}&url={{url}}"><img src="lang/{{cc}}/flag.png" alt="{{name}}"> {{name}}</a></li> + {{/langs}} </ul> </li> </ul> diff --git a/templates/translation/_page.html b/templates/translation/_page.html index 8e5e4bab..dee651a7 100644 --- a/templates/translation/_page.html +++ b/templates/translation/_page.html @@ -5,36 +5,12 @@ </div> <div class="panel-body"> <p>{{lang_adminInfo}}</p> + <ul class="nav nav-pills nav-stacked"> + <li><a href="?do=Translation&page=templates">{{lang_editTemplates}}</a></li> + <li><a href="?do=Translation&page=messages">{{lang_editMessages}}</a></li> + <li><a href="?do=Translation&page=hardcoded">{{lang_editHardcoded}}</a></li> + <li><a href="?do=Translation&page=settings">{{lang_editSettings}}</a></li> + </ul> </div> - <ul class="list-group"> - <a href="?do=Translation&page=messages" class="list-group-item active">{{lang_editMessages}}</a> - </ul> - </div> - <div class="panel panel-default"> - <table class="table table-hover"> - <thead> - <tr> - <th>Template</th> - <th style='text-align:center;'>{{lang_german}}</th> - <th style='text-align:center;'>{{lang_english}}</th> - <th style='text-align:center;'>{{lang_portuguese}}</th> - <tr> - </thead> - <tbody> - {{#table}} - <tr onclick="goTo('{{link}}');"> - <td>{{template}}</td> - <td style='width:230px;text-align:center;'>{{{de}}}</td> - <td style='width:230px;text-align:center;'>{{{en}}}</td> - <td style='width:230px;text-align:center;'>{{{pt}}}</td> - </tr> - {{/table}} - </tbody> - </table> </div> </div> -<script> -function goTo(link){ - window.location.href = "?do=Translation&page=templates&template=" + link; -} -</script> diff --git a/templates/translation/template.html b/templates/translation/edit.html index 87c0f01b..049be6cb 100644 --- a/templates/translation/template.html +++ b/templates/translation/edit.html @@ -1,7 +1,7 @@ <div class="container"> <div class="panel panel-default"> <div class="panel-heading"> - {{template}} + {{path}} </div> <div class="panel-body"> <p>{{lang_templateAdminHelp}}</p> @@ -24,12 +24,12 @@ <tr class="{{class}}" id="{{tag}}"> <td>{{tag}}</td> {{#langs}} - <td style="text-align:center"> + <td> <input type="text" class="form-control" placeholder="{{placeholder}}" value="{{translation}}" name="lang#{{lang}}#{{tag}}"> </td> {{/langs}} - <td style="text-align:center"> - <a class="btn btn-danger btn-xs" href="?do=Translation&template={{template}}&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a> + <td> + <button type="submit" class="btn btn-danger btn-xs" name="delete" value="{{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</button> </td> </tr> {{/tags}} @@ -39,10 +39,9 @@ </table> <a class="btn btn-primary" href='?do=Translation' >{{lang_back}}</a> <button class="btn btn-primary" type="button" onclick="addTag()" >{{lang_createTag}}</button> - <input type="hidden" name="update" value="true"> - <input type="hidden" name="path" value="{{template}}"> + <input type="hidden" name="path" value="{{path}}"> <input type="hidden" name="token" value="{{token}}"> - <input type="submit" class="btn btn-primary" value="{{lang_save}}"> + <button type="submit" class="btn btn-primary" name="update" value="true">{{lang_save}}</button> </form> </div> </div> diff --git a/templates/translation/messages.html b/templates/translation/messages.html deleted file mode 100644 index c065c7f7..00000000 --- a/templates/translation/messages.html +++ /dev/null @@ -1,107 +0,0 @@ -<div class="container"> - <div class="panel panel-default"> - <div class="panel-heading"> - {{lang_messages}} - </div> - <div class="panel-body"> - <p>{{lang_templateMessagesHelp}}</p> - <div class="alert alert-info"> - {{lang_templateHint}} - </div> - </div> - <form action="?do=Translation" method="post"> - <table class="table table-hover"> - <thead> - <tr> - <th>{{lang_messages}}</th> - <th style='text-align:center;width:260px;'>{{lang_germanJSON}}</th> - <th style='text-align:center;width:260px;'>{{lang_englishJSON}}</th> - <th style='text-align:center;width:260px;'>{{lang_portugueseJSON}}</th> - <th style='width:100px;text-align:center;'></th> - </tr> - </thead> - <tbody> - {{#msgs}} - <tr> - <td>{{tag}}</td> - <td style='width:250px;text-align:center;'> - <input type="text" class="form-control" placeholder="{{lang_germanTAG}}" value="{{de}}" name="lang#de#{{tag}}"> - </td> - <td style='width:250px;text-align:center;'> - <input type="text" class="form-control" placeholder="{{lang_englishTAG}}" value="{{en}}" name="lang#en#{{tag}}"> - </td> - <td style='width:250px;text-align:center;'> - <input type="text" class="form-control" placeholder="{{lang_portugueseTAG}}" value="{{pt}}" name="lang#pt#{{tag}}"> - </td> - <td style='text-align:center;'> - <a class="btn btn-danger btn-xs" href="?do=Translation&template=messages&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a> - </td> - </tr> - {{/msgs}} - <tr id="newTag"> - </tr> - </tbody> - </table> - <div class="panel-body"> - <a class="btn btn-primary" href='?do=Translation' >{{lang_back}}</a> - <button class="btn btn-primary" type="button" onclick="addTag(false);" >{{lang_newTag}}</button> - <input type="hidden" name="update" value="true"> - <input type="hidden" name="path" value="messages"> - <input type="hidden" name="token" value="{{token}}"> - <input type="submit" class="btn btn-primary" value="{{lang_save}}"> - </form> - </div> - <form action="?do=Translation" method="post"> - <table class="table table-hover"> - <thead> - <tr> - <th>{{lang_messagesHardcoded}}</th> - <th style='text-align:center;width:260px;'>{{lang_germanJSON}}</th> - <th style='text-align:center;width:260px;'>{{lang_englishJSON}}</th> - <th style='text-align:center;width:260px;'>{{lang_portugueseJSON}}</th> - <th style='width:100px;text-align:center;'></th> - </tr> - </thead> - <tbody> - {{#msgsHC}} - <tr> - <td>{{tag}}</td> - <td style='width:250px;text-align:center;'> - <input type="text" class="form-control" placeholder="{{lang_germanTAG}}" value="{{de}}" name="lang#de#{{tag}}"> - </td> - <td style='width:250px;text-align:center;'> - <input type="text" class="form-control" placeholder="{{lang_englishTAG}}" value="{{en}}" name="lang#en#{{tag}}"> - </td> - <td style='width:250px;text-align:center;'> - <input type="text" class="form-control" placeholder="{{lang_portugueseTAG}}" value="{{pt}}" name="lang#pt#{{tag}}"> - </td> - <td style='text-align:center;'> - <a class="btn btn-danger btn-xs" href="?do=Translation&template=messages-hardcoded&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a> - </td> - </tr> - {{/msgsHC}} - <tr id="newTagCoded"> - </tr> - </tbody> - </table> - <div class="panel-body"> - <a class="btn btn-primary" href='?do=Translation' >{{lang_back}}</a> - <button class="btn btn-primary" type="button" onclick="addTag(true);" >{{lang_newTag}}</button> - <input type="hidden" name="update" value="true"> - <input type="hidden" name="path" value="messages-hardcoded"> - <input type="hidden" name="token" value="{{token}}"> - <input type="submit" class="btn btn-primary" value="{{lang_save}}"> - </form> - </div> - </div> -</div> -<script> -function addTag(isHardcoded){ - var target; - if(isHardcoded) - target = document.getElementById('newTagCoded'); - else - target = document.getElementById('newTag'); - target.innerHTML = "<td> <input type='text' class='form-control' placeholder='{{lang_newTAG}}' name='newtag'> </td> <td style='width:250px;text-align:center;'> <input type='text' class='form-control' placeholder='{{lang_germanTAG}}' name='lang#de#newtag'> </td> <td style='width:250px;text-align:center;'> <input type='text' class='form-control' placeholder='{{lang_englishTAG}}' name='lang#en#newtag'> </td> <td style='width:250px;text-align:center;'> <input type='text' class='form-control' placeholder='{{lang_portugueseTAG}}' name='lang#pt#newtag'> </td>"; -} -</script> diff --git a/templates/translation/template-list.html b/templates/translation/template-list.html new file mode 100644 index 00000000..1449cef0 --- /dev/null +++ b/templates/translation/template-list.html @@ -0,0 +1,33 @@ +<div class="container"> + <div class="panel panel-default"> + <div class="panel-heading"> + {{lang_langAdministration}} + </div> + <div class="panel-body"> + <p>{{lang_adminInfo}}</p> + </div> + </div> + <div class="panel panel-default"> + <table class="table table-hover"> + <thead> + <tr> + <th>Template</th> + <th>{{lang_status}}</th> + <tr> + </thead> + <tbody> + {{#table}} + <tr onclick="goTo('{{link}}');"> + <td>{{template}}</td> + <td>{{{status}}}</td> + </tr> + {{/table}} + </tbody> + </table> + </div> +</div> +<script> +function goTo(link){ + window.location.href = "?do=Translation&page=template&template=" + link; +} +</script> |