summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2014-08-12 16:45:05 +0200
committerSimon Rettberg2014-08-12 16:45:05 +0200
commite9518cdb81eff6b59049709c8cbc74df14660f53 (patch)
tree8f417d12d89c7d43383a2acc101f67a9e03502f8
parentSome sanity checks; start making detection of available languages dynamic; pu... (diff)
parent[i18n] removed .json files and corrected the menu links (diff)
downloadslx-admin-e9518cdb81eff6b59049709c8cbc74df14660f53.tar.gz
slx-admin-e9518cdb81eff6b59049709c8cbc74df14660f53.tar.xz
slx-admin-e9518cdb81eff6b59049709c8cbc74df14660f53.zip
Merge branch 'i18n' of https://gitlab.c3sl.ufpr.br/cdn/slx-admin into i18n
Conflicts: lang/i18n.php modules/translation.inc.php
-rw-r--r--inc/dictionary.inc.php5
-rw-r--r--inc/up_json_encode.php170
-rw-r--r--lang/de/.json1
-rw-r--r--lang/de/administration/_page.json1
-rw-r--r--lang/de/administration/messages.json1
-rw-r--r--lang/de/administration/template.json1
-rw-r--r--lang/de/dialog-generic.json2
-rw-r--r--lang/de/main-menu-login.json2
-rw-r--r--lang/de/main-menu-logout.json2
-rw-r--r--lang/de/messages.json2
-rw-r--r--lang/de/page-minilinux.json4
-rw-r--r--lang/de/translation/_page.json1
-rw-r--r--lang/de/translation/messages.json1
-rw-r--r--lang/de/translation/template.json1
-rw-r--r--lang/en/.json1
-rw-r--r--lang/en/administration/_page.json1
-rw-r--r--lang/en/administration/messages.json1
-rw-r--r--lang/en/administration/template.json1
-rw-r--r--lang/en/dialog-generic.json2
-rw-r--r--lang/en/main-menu-login.json2
-rw-r--r--lang/en/main-menu-logout.json2
-rw-r--r--lang/en/messages.json2
-rw-r--r--lang/en/page-minilinux.json4
-rw-r--r--lang/en/translation/_page.json1
-rw-r--r--lang/en/translation/messages.json1
-rw-r--r--lang/en/translation/template.json1
-rw-r--r--lang/pt/.json1
-rw-r--r--lang/pt/administration/template.json1
-rw-r--r--lang/pt/dialog-generic.json2
-rw-r--r--lang/pt/main-menu-login.json2
-rw-r--r--lang/pt/main-menu-logout.json2
-rw-r--r--lang/pt/messages.json2
-rw-r--r--lang/pt/page-minilinux.json4
-rw-r--r--lang/pt/translation/_page.json (renamed from lang/pt/administration/_page.json)0
-rw-r--r--lang/pt/translation/messages.json (renamed from lang/pt/administration/messages.json)2
-rw-r--r--lang/pt/translation/template.json1
-rw-r--r--modules/admin.inc.php295
-rw-r--r--modules/translation.inc.php389
-rw-r--r--templates/main-menu-login.html2
-rw-r--r--templates/main-menu-logout.html2
-rw-r--r--templates/translation/_page.html (renamed from templates/administration/_page.html)10
-rw-r--r--templates/translation/messages.html (renamed from templates/administration/messages.html)21
-rw-r--r--templates/translation/template.html (renamed from templates/administration/template.html)15
43 files changed, 614 insertions, 350 deletions
diff --git a/inc/dictionary.inc.php b/inc/dictionary.inc.php
index 58127c18..b8a888d5 100644
--- a/inc/dictionary.inc.php
+++ b/inc/dictionary.inc.php
@@ -58,7 +58,10 @@ class Dictionary
if ($content === false)
Util::traceError("Could not find language file $template for language $lang");
$language = array('lang' => $lang);
- return array_merge($language, json_decode($content, true));
+ $json = json_decode($content, true);
+ if (!is_array($json))
+ return $language;
+ return array_merge($language, $json);
}
public static function translate($string)
diff --git a/inc/up_json_encode.php b/inc/up_json_encode.php
new file mode 100644
index 00000000..b3b843c1
--- /dev/null
+++ b/inc/up_json_encode.php
@@ -0,0 +1,170 @@
+<?php
+
+/**
+ * api: php
+ * title: upgrade.php
+ * description: Emulates functions from new PHP versions on older interpreters.
+ * version: 19
+ * license: Public Domain
+ * url: http://freshmeat.net/projects/upgradephp
+ * type: functions
+ * category: library
+ * priority: auto
+ * load_if: (PHP_VERSION<5.2)
+ * sort: -255
+ * provides: upgrade-php, api:php5, json
+ *
+ *
+ * By loading this library you get PHP version independence. It provides
+ * downwards compatibility to older PHP interpreters by emulating missing
+ * functions or constants using IDENTICAL NAMES. So this doesn't slow down
+ * script execution on setups where the native functions already exist. It
+ * is meant as quick drop-in solution. It spares you from rewriting code or
+ * using cumbersome workarounds instead of the more powerful v5 functions.
+ *
+ * It cannot mirror PHP5s extended OO-semantics and functionality into PHP4
+ * however. A few features are added here that weren't part of PHP yet. And
+ * some other function collections are separated out into the ext/ directory.
+ * It doesn't produce many custom error messages (YAGNI), and instead leaves
+ * reporting to invoked functions or for native PHP execution.
+ *
+ * And further this is PUBLIC DOMAIN (no copyright, no license, no warranty)
+ * so therefore compatible to ALL open source licenses. You could rip this
+ * paragraph out to republish this instead only under more restrictive terms
+ * or your favorite license (GNU LGPL/GPL, BSDL, MPL/CDDL, Artistic/PHPL, ..)
+ *
+ * Any contribution is appreciated. <milky*users#sf#net>
+ *
+ */
+/**
+ * -------------------------- FUTURE ---
+ * @group SVN
+ * @since future
+ *
+ * Following functions aren't implemented in current PHP versions, but
+ * might already be in CVS/SVN.
+ *
+ * @removed
+ * setcookie2
+ *
+ */
+/**
+ * Converts PHP variable or array into a "JSON" (JavaScript value expression
+ * or "object notation") string.
+ *
+ * @compat
+ * Output seems identical to PECL versions. "Only" 20x slower than PECL version.
+ * @bugs
+ * Doesn't take care with unicode too much - leaves UTF-8 sequences alone.
+ *
+ * @param $var mixed PHP variable/array/object
+ * @return string transformed into JSON equivalent
+ */
+if (!defined("JSON_HEX_TAG")) {
+ define("JSON_HEX_TAG", 1);
+ define("JSON_HEX_AMP", 2);
+ define("JSON_HEX_APOS", 4);
+ define("JSON_HEX_QUOT", 8);
+ define("JSON_FORCE_OBJECT", 16);
+}
+if (!defined("JSON_NUMERIC_CHECK")) {
+ define("JSON_NUMERIC_CHECK", 32); // 5.3.3
+}
+if (!defined("JSON_UNESCAPED_SLASHES")) {
+ define("JSON_UNESCAPED_SLASHES", 64); // 5.4.0
+ define("JSON_PRETTY_PRINT", 128); // 5.4.0
+ define("JSON_UNESCAPED_UNICODE", 256); // 5.4.0
+}
+
+function up_json_encode($var, $options = 0, $_indent = "")
+{
+ global ${'.json_last_error'};
+ ${'.json_last_error'} = JSON_ERROR_NONE;
+
+ #-- prepare JSON string
+ $obj = ($options & JSON_FORCE_OBJECT);
+ list($_space, $_tab, $_nl) = ($options & JSON_PRETTY_PRINT) ? array(" ", " $_indent", "\n") : array("", "", "");
+ $json = "$_indent";
+
+ if ($options & JSON_NUMERIC_CHECK and is_string($var) and is_numeric($var)) {
+ $var = (strpos($var, ".") || strpos($var, "e")) ? floatval($var) : intval($var);
+ }
+
+ #-- add array entries
+ if (is_array($var) || ($obj = is_object($var))) {
+
+ #-- check if array is associative
+ if (!$obj) {
+ $keys = array_keys((array) $var);
+ $obj = !($keys == array_keys($keys)); // keys must be in 0,1,2,3, ordering, but PHP treats integers==strings otherwise
+ }
+
+ #-- concat individual entries
+ $empty = 0;
+ $json = "";
+ foreach ((array) $var as $i => $v) {
+ $json .= ($empty++ ? ",$_nl" : "") // comma separators
+ . $_tab . ($obj ? (up_json_encode($i, $options & ~JSON_NUMERIC_CHECK, $_tab) . ":$_space") : "") // assoc prefix
+ . (up_json_encode($v, $options, $_tab)); // value
+ }
+
+ #-- enclose into braces or brackets
+ $json = $obj ? "{" . "$_nl$json$_nl$_indent}" : "[$_nl$json$_nl$_indent]";
+ }
+
+ #-- strings need some care
+ elseif (is_string($var)) {
+
+ if (!empty($var) && mb_detect_encoding($var, 'UTF-8', true) === false) {
+ trigger_error("up_json_encode: invalid UTF-8 encoding in string '$var', cannot proceed.", E_USER_WARNING);
+ $var = NULL;
+ }
+ $rewrite = array(
+ "\\" => "\\\\",
+ "\"" => "\\\"",
+ "\010" => "\\b",
+ "\f" => "\\f",
+ "\n" => "\\n",
+ "\r" => "\\r",
+ "\t" => "\\t",
+ "/" => $options & JSON_UNESCAPED_SLASHES ? "/" : "\\/",
+ "<" => $options & JSON_HEX_TAG ? "\\u003C" : "<",
+ ">" => $options & JSON_HEX_TAG ? "\\u003E" : ">",
+ "'" => $options & JSON_HEX_APOS ? "\\u0027" : "'",
+ "\"" => $options & JSON_HEX_QUOT ? "\\u0022" : "\"",
+ "&" => $options & JSON_HEX_AMP ? "\\u0026" : "&",
+ );
+ $var = strtr($var, $rewrite);
+ //@COMPAT control chars should probably be stripped beforehand, not escaped as here
+ if (function_exists("iconv") && ($options & JSON_UNESCAPED_UNICODE) == 0) {
+ $var = preg_replace("/[^\\x{0020}-\\x{007F}]/ue", "'\\u'.current(unpack('H*', iconv('UTF-8', 'UCS-2BE', '$0')))", $var);
+ }
+ $json = '"' . $var . '"';
+ }
+
+ #-- basic types
+ elseif (is_bool($var)) {
+ $json = $var ? "true" : "false";
+ } elseif ($var === NULL) {
+ $json = "null";
+ } elseif (is_int($var)) {
+ $json = "$var";
+ } elseif (is_float($var)) {
+ if (is_nan($var) || is_infinite($var)) {
+ ${'.json_last_error'} = JSON_ERROR_INF_OR_NAN;
+ return;
+ } else {
+ $json = "$var";
+ }
+ }
+
+ #-- something went wrong
+ else {
+ trigger_error("up_json_encode: don't know what a '" . gettype($var) . "' is.", E_USER_WARNING);
+ ${'.json_last_error'} = JSON_ERROR_UNSUPPORTED_TYPE;
+ return;
+ }
+
+ #-- done
+ return($json);
+}
diff --git a/lang/de/.json b/lang/de/.json
deleted file mode 100644
index 9bc301f1..00000000
--- a/lang/de/.json
+++ /dev/null
@@ -1 +0,0 @@
-{"loginfail":"Benutzername oder Kennwort falsch","token":"Ung\u00fcltiges Token. CSRF Angriff?","adduser":"Benutzer erfolgreich hinzugef\u00fcgt","password":"Passwort und Passwortbest\u00e4tigung stimmen nicht \u00fcberein","empty":"Das Archiv enth\u00e4lt keine Dateien oder Verzeichnisse","no":"Keine ausreichenden Rechte, um auf diese Seite zuzugreifen","settings":"Einstellungen wurden aktualisiert","debug":"Der Debug-Modus ist aktiv!","value":"Der Wert {{1}} ist ung\u00fcltig f\u00fcr die Option {{0}} und wurde ignoriert","invalid":"Ausgew\u00e4hlte Template ist nicht g\u00fcltig","remote":"Parsen der empfangenen Daten fehlgeschlagen ({{0}})","missing":"Es wurde keine Datei ausgew\u00e4hlt!","upload":"Upload schlug fehl: {{0}}","config":"Konfiguration mit ID {{0}} existiert nicht","error":"Konnte Archiv nicht nach {{0}} entpacken - {{1}}","module":"Modul {{0}} wird noch durch Konfiguration {{1}} verwendet","taskmanager":"Taskmanager hat ung\u00fcltige Daten zur\u00fcckgeliefert","task":"Ausf\u00fchrung fehlgeschlagen: {{0}}","news":"News gel\u00f6scht","reboot":"Sicherheitsabfrage zum Reboot nicht best\u00e4tigt","lang_unknwonTaskManager":"Unbekannter Taskmanager-Fehler","lang_configurationCompilation":"Konfiguration zusammenstellen","lang_moduleAdd":"Modul hinzuf\u00fcgen","lang_adAuthentication":"Active Directory Authentifizierung","lang_adModule":"Mit diesem Modul ist die Anmeldung an den Client PCs mit den Benutzerkonten eines Active Directory m\u00f6glich. Je nach Konfiguration ist auch die Nutzung eines Benutzerverzeichnisses auf dem Client m\u00f6glich.","lang_authentication":"Authentifizierung","lang_generic":"Generisch","lang_addCustomModuleInfo":"Mit einem Erweiterten Modul ist es m\u00f6glich, beliebige Dateien zum Grundsystem hinzuzuf\u00fcgen Nutzen Sie dieses Modul, um z.B. spezielle Konfigurationsdateien auf den Client PCs zu verwenden, die sich nicht mit einem der anderen Wizards erstellen l\u00e4sst. Das Hinzuf\u00fcgen eines Erweiterten Moduls erfordert in der Regel zumindest grundlegende Systemkenntnisse im Linuxbereich.","lang_days":"Tag(e)","lang_hours":"Stunde(n)","lang_specificLogo":"Einrichtungsspezifisches Logo","lang_institutionLogo":"Logo der Einrichtung","lang_infoLogo":"Dieses Modul dient dem Hinzuf\u00fcgen eines Logos der Hochschule\/Universit\u00e4t, welches dann z.B. auf dem Anmeldebildschirm angezeigt wird.","lang_location":"Lokalisierung","lang_contentOf":"Inhalt von \"","lang_serverConfiguration":"Serverseitige Konfiguration","lang_login":"Anmelden","lang_createUser":"Benutzer anlegen"} \ No newline at end of file
diff --git a/lang/de/administration/_page.json b/lang/de/administration/_page.json
deleted file mode 100644
index 90abe51c..00000000
--- a/lang/de/administration/_page.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_langAdministration":"Sprache Verwaltung","lang_adminInfo":"","lang_editMessages":"Nachrichten bearbeiten","lang_german":"Deutsch","lang_english":"Englisch","lang_portuguese":"Portuguiesisch"} \ No newline at end of file
diff --git a/lang/de/administration/messages.json b/lang/de/administration/messages.json
deleted file mode 100644
index 03049639..00000000
--- a/lang/de/administration/messages.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_messages":"","lang_templateMessagesHelp":"","lang_germanJSON":"","lang_englishJSON":"","lang_portugueseJSON":"","lang_germanTAG":"","lang_englishTAG":"","lang_portugueseTAG":"","lang_back":"","lang_newTag":"","lang_update":"Hochladen","lang_messagesHardcoded":"","lang_newTAG":"","lang_deleteTAG":"L\u00f6schen"} \ No newline at end of file
diff --git a/lang/de/administration/template.json b/lang/de/administration/template.json
deleted file mode 100644
index 2debb41d..00000000
--- a/lang/de/administration/template.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_templateAdminHelp":"","lang_germanJSON":"","lang_englishJSON":"Englisch JSON","lang_portugueseJSON":"Portugiesisch JSON","lang_germanTAG":"","lang_englishTAG":"","lang_portugueseTAG":"Portugiesisch TAG","lang_back":"Z\u00fcruck","lang_update":"Hochladen","lang_createTag":"","lang_newTAG":"","lang_deleteTAG":"L\u00f6schen"} \ No newline at end of file
diff --git a/lang/de/dialog-generic.json b/lang/de/dialog-generic.json
index a033a102..d739a493 100644
--- a/lang/de/dialog-generic.json
+++ b/lang/de/dialog-generic.json
@@ -1 +1 @@
-{"lang_notUsed":"","lang_next":"Weiter"} \ No newline at end of file
+{"lang_next":"Weiter"} \ No newline at end of file
diff --git a/lang/de/main-menu-login.json b/lang/de/main-menu-login.json
index adb2d053..398b8b6c 100644
--- a/lang/de/main-menu-login.json
+++ b/lang/de/main-menu-login.json
@@ -1 +1 @@
-{"lang_clientLog":"Client Log","lang_settings":"Einstellungen","lang_client":"Client","lang_localization":"Lokalisierung","lang_configurationVariables":"KonfigurationsVariablen","lang_administration":"Verwaltung","lang_server":"Server","lang_configurationBasic":"Grundkonfiguration","lang_vmLocation":"VM Speicherort","lang_news":"News","lang_language":"Sprachen","lang_login":"Anmelden"} \ No newline at end of file
+{"lang_clientLog":"Client Log","lang_settings":"Einstellungen","lang_client":"Client","lang_localization":"Lokalisierung","lang_configurationVariables":"KonfigurationsVariablen","lang_administration":"\u00dcbersetzungen","lang_server":"Server","lang_configurationBasic":"Grundkonfiguration","lang_vmLocation":"VM Speicherort","lang_news":"News","lang_language":"Sprachen","lang_login":"Anmelden"} \ No newline at end of file
diff --git a/lang/de/main-menu-logout.json b/lang/de/main-menu-logout.json
index 2b1088b8..4e3bcf90 100644
--- a/lang/de/main-menu-logout.json
+++ b/lang/de/main-menu-logout.json
@@ -1 +1 @@
-{"lang_clientLog":"Client Log","lang_settings":"Einstellungen","lang_client":"Client","lang_localization":"Lokalisierung","lang_configurationVariables":"KonfigurationsVariablen","lang_administration":"Verwaltung","lang_server":"Server","lang_configurationBasic":"Grundkonfiguration","lang_vmLocation":"VM Speicherort","lang_news":"News","lang_language":"Sprachen","lang_logout":"Abmelden"} \ No newline at end of file
+{"lang_clientLog":"Client Log","lang_settings":"Einstellungen","lang_client":"Client","lang_localization":"Lokalisierung","lang_configurationVariables":"KonfigurationsVariablen","lang_administration":"\u00dcbersetzungen","lang_server":"Server","lang_configurationBasic":"Grundkonfiguration","lang_vmLocation":"VM Speicherort","lang_news":"News","lang_language":"Sprachen","lang_logout":"Abmelden"} \ No newline at end of file
diff --git a/lang/de/messages.json b/lang/de/messages.json
index c01b2a72..0221ad8e 100644
--- a/lang/de/messages.json
+++ b/lang/de/messages.json
@@ -1 +1 @@
-{"loginfail":"Benutzername oder Kennwort falsch","token":"Ung\u00fcltiges Token. CSRF Angriff?","adduser-disabled":"Keine ausreichenden Rechte, um weitere Benutzer hinzuzuf\u00fcgen","password-mismatch":"Passwort und Passwortbest\u00e4tigung stimmen nicht \u00fcberein","empty-field":"Ein Feld wurde nicht ausgef\u00fcllt","adduser-success":"Benutzer erfolgreich hinzugef\u00fcgt","no-permission":"Keine ausreichenden Rechte, um auf diese Seite zuzugreifen","settings-updated":"Einstellungen wurden aktualisiert","debug-mode":"Der Debug-Modus ist aktiv!","value-invalid":"Der Wert {{1}} ist ung\u00fcltig f\u00fcr die Option {{0}} und wurde ignoriert","invalid-action":"Ung\u00fcltige Aktion: {{0}}","remote-timeout":"Konnte Ressource {{0}} nicht herunterladen ({{1}})","remote-parse-failed":"Parsen der empfangenen Daten fehlgeschlagen ({{0}})","missing-file":"Es wurde keine Datei ausgew\u00e4hlt!","invalid-file":"Die Datei {{0}} existiert nicht!","upload-complete":"Upload von {{0}} war erfolgreich","upload-failed":"Upload schlug fehl: {{0}}","config-activated":"Konfiguration {{0}} wurde aktiviert","config-invalid":"Konfiguration mit ID {{0}} existiert nicht","error-write":"Fehler beim Schreiben von {{0}}","error-read":"Fehler beim Lesen von {{0}}","error-archive":"Korruptes Archiv oder nicht unterst\u00fctztes Format","error-rename":"Konnte {{0}} nicht in {{1}} umbenennen","error-nodir":"Das Verzeichnis {{0}} existiert nicht.","empty-archive":"Das Archiv enth\u00e4lt keine Dateien oder Verzeichnisse","error-extract":"Konnte Archiv nicht nach {{0}} entpacken - {{1}}","module-added":"Modul erfolgreich hinzugef\u00fcgt","module-deleted":"Modul {{0}} wurde gel\u00f6scht","module-in-use":"Modul {{0}} wird noch durch Konfiguration {{1}} verwendet","taskmanager-error":"Verbindung zum Taskmanager fehlgeschlagen","taskmanager-format":"Taskmanager hat ung\u00fcltige Daten zur\u00fcckgeliefert","task-error":"Ausf\u00fchrung fehlgeschlagen: {{0}}","invalid-ip":"Kein Interface ist auf die Adresse {{0}} konfiguriert","news-save-success":"News erfolgreich aktualisiert","news-empty":"Es wurde keine News in der Datenbank gefunden","news-del-success":"News gel\u00f6scht","reboot-unconfirmed":"Sicherheitsabfrage zum Reboot nicht best\u00e4tigt","invalid-template":"Ausgew\u00e4hlte Template ist nicht g\u00fcltig","deleted-tag":"","updated-tags":""} \ No newline at end of file
+{"loginfail":"Benutzername oder Kennwort falsch","token":"Ung\u00fcltiges Token. CSRF Angriff?","adduser-disabled":"Keine ausreichenden Rechte, um weitere Benutzer hinzuzuf\u00fcgen","password-mismatch":"Passwort und Passwortbest\u00e4tigung stimmen nicht \u00fcberein","empty-field":"Ein Feld wurde nicht ausgef\u00fcllt","adduser-success":"Benutzer erfolgreich hinzugef\u00fcgt","no-permission":"Keine ausreichenden Rechte, um auf diese Seite zuzugreifen","settings-updated":"Einstellungen wurden aktualisiert","debug-mode":"Der Debug-Modus ist aktiv!","value-invalid":"Der Wert {{1}} ist ung\u00fcltig f\u00fcr die Option {{0}} und wurde ignoriert","invalid-action":"Ung\u00fcltige Aktion: {{0}}","remote-timeout":"Konnte Ressource {{0}} nicht herunterladen ({{1}})","remote-parse-failed":"Parsen der empfangenen Daten fehlgeschlagen ({{0}})","missing-file":"Es wurde keine Datei ausgew\u00e4hlt!","invalid-file":"Die Datei {{0}} existiert nicht!","upload-complete":"Upload von {{0}} war erfolgreich","upload-failed":"Upload schlug fehl: {{0}}","config-activated":"Konfiguration {{0}} wurde aktiviert","config-invalid":"Konfiguration mit ID {{0}} existiert nicht","error-write":"Fehler beim Schreiben von {{0}}","error-read":"Fehler beim Lesen von {{0}}","error-archive":"Korruptes Archiv oder nicht unterst\u00fctztes Format","error-rename":"Konnte {{0}} nicht in {{1}} umbenennen","error-nodir":"Das Verzeichnis {{0}} existiert nicht.","empty-archive":"Das Archiv enth\u00e4lt keine Dateien oder Verzeichnisse","error-extract":"Konnte Archiv nicht nach {{0}} entpacken - {{1}}","module-added":"Modul erfolgreich hinzugef\u00fcgt","module-deleted":"Modul {{0}} wurde gel\u00f6scht","module-in-use":"Modul {{0}} wird noch durch Konfiguration {{1}} verwendet","taskmanager-error":"Verbindung zum Taskmanager fehlgeschlagen","taskmanager-format":"Taskmanager hat ung\u00fcltige Daten zur\u00fcckgeliefert","task-error":"Ausf\u00fchrung fehlgeschlagen: {{0}}","invalid-ip":"Kein Interface ist auf die Adresse {{0}} konfiguriert","news-save-success":"News erfolgreich aktualisiert","news-empty":"Es wurde keine News in der Datenbank gefunden","news-del-success":"News gel\u00f6scht","reboot-unconfirmed":"Sicherheitsabfrage zum Reboot nicht best\u00e4tigt","invalid-template":"Ausgew\u00e4hlte Template ist nicht g\u00fcltig","deleted-tag":"","updated-tags":"","unsuccessful-action":""} \ No newline at end of file
diff --git a/lang/de/page-minilinux.json b/lang/de/page-minilinux.json
index c8a965b1..015cf4c7 100644
--- a/lang/de/page-minilinux.json
+++ b/lang/de/page-minilinux.json
@@ -1,3 +1 @@
-{
- "lang_listObtained":"Liste wird abgerufen..."
-}
+{"lang_listObtained":"Liste wird abgerufen...","lang_errorGetting":""} \ No newline at end of file
diff --git a/lang/de/translation/_page.json b/lang/de/translation/_page.json
new file mode 100644
index 00000000..da3733cb
--- /dev/null
+++ b/lang/de/translation/_page.json
@@ -0,0 +1 @@
+{"lang_langAdministration":"Sprache Verwaltung","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_editMessages":"Nachrichten bearbeiten","lang_german":"Deutsch","lang_english":"Englisch","lang_portuguese":"Portuguiesisch"} \ No newline at end of file
diff --git a/lang/de/translation/messages.json b/lang/de/translation/messages.json
new file mode 100644
index 00000000..231f3a98
--- /dev/null
+++ b/lang/de/translation/messages.json
@@ -0,0 +1 @@
+{"lang_messages":"Nachrichten","lang_templateMessagesHelp":"","lang_germanJSON":"Deutsch JSON","lang_englishJSON":"Englisch JSON","lang_portugueseJSON":"Portugiesisch JSON","lang_germanTAG":"Deutsch TAG","lang_englishTAG":"Englisch TAG","lang_portugueseTAG":"Portugiesisch TAG","lang_back":"Z\u00fcruck","lang_newTag":"Neue Nachricht","lang_messagesHardcoded":"Hardcoded Nachrichten","lang_newTAG":"Neuer Tag","lang_deleteTAG":"L\u00f6schen","lang_templateHint":"Hinweis: Gelbe Linien zeigen eine \u00dcbersetzung fehlt und roten Linien zeigen ein Tag wird nicht von der Vorlage verwendet.","lang_save":"Speichern"} \ No newline at end of file
diff --git a/lang/de/translation/template.json b/lang/de/translation/template.json
new file mode 100644
index 00000000..ceb292e8
--- /dev/null
+++ b/lang/de/translation/template.json
@@ -0,0 +1 @@
+{"lang_templateAdminHelp":"","lang_germanJSON":"Deutsch JSON","lang_englishJSON":"Englisch JSON","lang_portugueseJSON":"Portugiesisch JSON","lang_germanTAG":"Deutsch TAG","lang_englishTAG":"Englisch TAG","lang_portugueseTAG":"Portugiesisch TAG","lang_back":"Z\u00fcruck","lang_createTag":"TAG schafen","lang_newTAG":"Neue Tag","lang_deleteTAG":"L\u00f6schen","lang_templateHint":"Hinweis: Gelbe Linie zeigt eine \u00dcbersetzung fehlt und roten Linien zeigen ein Tag wird nicht von das Template verwendet.","lang_save":"Speichern"} \ No newline at end of file
diff --git a/lang/en/.json b/lang/en/.json
deleted file mode 100644
index fa92867d..00000000
--- a/lang/en/.json
+++ /dev/null
@@ -1 +0,0 @@
-{"loginfail":"Username or Password incorrect","token":"Invalid token. CSRF attack?","adduser":"User successfully added","password":"Password and password confirmation do not match","empty":"The archive contains no files or directories","no":"No sufficient privileges to access this page","settings":"Settings have been updated","debug":"The debug mode is active!","value":"The value {{1}} is invalid for option {{0}} and has been ignored","invalid":"Selected template is not valid","remote":"Parsing the received data failed ({{0}})","missing":"There was no file selected!","upload":"Upload failed: {{0}}","config":"Configuration with id {{0}} does not exist","error":"Could not unpack archive {{0}} to {{1}}","module":"Module {{0}} is still used by Configuration {{1}}","taskmanager":"Task Manager has returned invalid data","task":"Execution failed: {{0}}","news":"News deleted","reboot":"Confirmation prompt to reboot not confirmed","lang_unknwonTaskManager":"Unknown Task Manager error","lang_configurationCompilation":"Compile configuration","lang_moduleAdd":"Add Module","lang_adAuthentication":"Active Directory Authentication","lang_adModule":"This module makes possible the application to the client PCs with the user accounts of an Active Directory. Depending on the configuration, the use of a user directory on the client is possible.","lang_authentication":"Authentication","lang_generic":"Generic","lang_addCustomModuleInfo":"With an extended module it is possible to add any files to the basic system that uses this module, for example to use specific configuration files, which can not be created with one of the other Wizards. Adding an Extended module usually requires at least basic knowledge of the Linux system.","lang_days":"Day(s)","lang_hours":"Hour(s)","lang_specificLogo":"Institution Specific Logo","lang_institutionLogo":"Institution Logo","lang_infoLogo":"This module is used to add the logo of a College \/ University, which then, for example, is displayed on the login screen.","lang_location":"Location","lang_contentOf":"Content of \"","lang_serverConfiguration":"Server-side Configuration","lang_login":"Login","lang_createUser":"Create User"} \ No newline at end of file
diff --git a/lang/en/administration/_page.json b/lang/en/administration/_page.json
deleted file mode 100644
index 41a2d901..00000000
--- a/lang/en/administration/_page.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_langAdministration":"Language Administration","lang_adminInfo":"","lang_editMessages":"Edit Messages","lang_german":"German","lang_english":"English","lang_portuguese":"Portuguese"} \ No newline at end of file
diff --git a/lang/en/administration/messages.json b/lang/en/administration/messages.json
deleted file mode 100644
index 1b89873a..00000000
--- a/lang/en/administration/messages.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_messages":"Messages","lang_templateMessagesHelp":"","lang_germanJSON":"German JSON","lang_englishJSON":"","lang_portugueseJSON":"","lang_germanTAG":"","lang_englishTAG":"","lang_portugueseTAG":"","lang_back":"","lang_newTag":"","lang_update":"Upload","lang_messagesHardcoded":"","lang_newTAG":"","lang_deleteTAG":"Delete"} \ No newline at end of file
diff --git a/lang/en/administration/template.json b/lang/en/administration/template.json
deleted file mode 100644
index 6ed52450..00000000
--- a/lang/en/administration/template.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_templateAdminHelp":"","lang_germanJSON":"German JSON","lang_englishJSON":"","lang_portugueseJSON":"German JSON","lang_germanTAG":"German TAG","lang_englishTAG":"English TAG","lang_portugueseTAG":"Portuguese TAG","lang_back":"Back","lang_update":"Update","lang_createTag":"","lang_newTAG":"","lang_deleteTAG":"Delete"} \ No newline at end of file
diff --git a/lang/en/dialog-generic.json b/lang/en/dialog-generic.json
index 094fe1a1..c44e40a5 100644
--- a/lang/en/dialog-generic.json
+++ b/lang/en/dialog-generic.json
@@ -1 +1 @@
-{"lang_notUsed":"","lang_next":"Next"} \ No newline at end of file
+{"lang_next":"Next"} \ No newline at end of file
diff --git a/lang/en/main-menu-login.json b/lang/en/main-menu-login.json
index 0bb870f0..099cfe54 100644
--- a/lang/en/main-menu-login.json
+++ b/lang/en/main-menu-login.json
@@ -1 +1 @@
-{"lang_clientLog":"Client Log","lang_settings":"Settings","lang_client":"Client","lang_localization":"Localization","lang_configurationVariables":"Configuration Variables","lang_administration":"Administration","lang_server":"Server","lang_configurationBasic":"Basic Configuration","lang_vmLocation":"VM Location","lang_news":"News","lang_language":"Language","lang_login":"Login"} \ No newline at end of file
+{"lang_clientLog":"Client Log","lang_settings":"Settings","lang_client":"Client","lang_localization":"Localization","lang_configurationVariables":"Configuration Variables","lang_administration":"Translations","lang_server":"Server","lang_configurationBasic":"Basic Configuration","lang_vmLocation":"VM Location","lang_news":"News","lang_language":"Language","lang_login":"Login"} \ No newline at end of file
diff --git a/lang/en/main-menu-logout.json b/lang/en/main-menu-logout.json
index 41e6c426..94e99d90 100644
--- a/lang/en/main-menu-logout.json
+++ b/lang/en/main-menu-logout.json
@@ -1 +1 @@
-{"lang_clientLog":"Client Log","lang_settings":"Settings","lang_client":"Client","lang_localization":"Localization","lang_configurationVariables":"Configuration Variables","lang_administration":"Administration","lang_server":"Server","lang_configurationBasic":"Basic Configuration","lang_vmLocation":"VM Location","lang_news":"News","lang_language":"Language","lang_logout":"Logout"} \ No newline at end of file
+{"lang_clientLog":"Client Log","lang_settings":"Settings","lang_client":"Client","lang_localization":"Localization","lang_configurationVariables":"Configuration Variables","lang_administration":"Translations","lang_server":"Server","lang_configurationBasic":"Basic Configuration","lang_vmLocation":"VM Location","lang_news":"News","lang_language":"Language","lang_logout":"Logout"} \ No newline at end of file
diff --git a/lang/en/messages.json b/lang/en/messages.json
index 0d80283c..353f94c1 100644
--- a/lang/en/messages.json
+++ b/lang/en/messages.json
@@ -1 +1 @@
-{"loginfail":"Username or Password incorrect","token":"Invalid token. CSRF attack?","adduser-disabled":"Insufficient privileges to add more users","password-mismatch":"Password and password confirmation do not match","empty-field":"A field was not filled","adduser-success":"User successfully added","no-permission":"No sufficient privileges to access this page","settings-updated":"Settings have been updated","debug-mode":"The debug mode is active!","value-invalid":"The value {{1}} is invalid for option {{0}} and has been ignored","invalid-action":"Invalid action: {{0}}","remote-timeout":"Could not download resource {{0}} ({{1}})","remote-parse-failed":"Parsing the received data failed ({{0}})","missing-file":"There was no file selected!","invalid-file":"The file {{0}} does not exist!","upload-complete":"Upload of {{0}} was successful","upload-failed":"Upload failed: {{0}}","config-activated":"Configuration {{0}} has been activated","config-invalid":"Configuration with id {{0}} does not exist","error-write":"Failed to write {{0}}","error-read":"Error reading {{0}}","error-archive":"Corrupted archive or unsupported format","error-rename":"Could not rename {{0}} into {{1}}","error-nodir":"The directory {{0}} does not exist.","empty-archive":"The archive contains no files or directories","error-extract":"Could not unpack archive {{0}} to {{1}}","module-added":"Module successfully added","module-deleted":"Module {{0}} was deleted","module-in-use":"Module {{0}} is still used by Configuration {{1}}","taskmanager-error":"Failed to connect to the Task Manager","taskmanager-format":"Task Manager has returned invalid data","task-error":"Execution failed: {{0}}","invalid-ip":"No interface is configured with the address {{0}}","news-save-success":"News updated successfully","news-empty":"There was no news found in the database","news-del-success":"News deleted","reboot-unconfirmed":"Confirmation prompt to reboot not confirmed","invalid-template":"Selected template is not valid","deleted-tag":"","updated-tags":""} \ No newline at end of file
+{"loginfail":"Username or Password incorrect","token":"Invalid token. CSRF attack?","adduser-disabled":"Insufficient privileges to add more users","password-mismatch":"Password and password confirmation do not match","empty-field":"A field was not filled","adduser-success":"User successfully added","no-permission":"No sufficient privileges to access this page","settings-updated":"Settings have been updated","debug-mode":"The debug mode is active!","value-invalid":"The value {{1}} is invalid for option {{0}} and has been ignored","invalid-action":"Invalid action: {{0}}","remote-timeout":"Could not download resource {{0}} ({{1}})","remote-parse-failed":"Parsing the received data failed ({{0}})","missing-file":"There was no file selected!","invalid-file":"The file {{0}} does not exist!","upload-complete":"Upload of {{0}} was successful","upload-failed":"Upload failed: {{0}}","config-activated":"Configuration {{0}} has been activated","config-invalid":"Configuration with id {{0}} does not exist","error-write":"Failed to write {{0}}","error-read":"Error reading {{0}}","error-archive":"Corrupted archive or unsupported format","error-rename":"Could not rename {{0}} into {{1}}","error-nodir":"The directory {{0}} does not exist.","empty-archive":"The archive contains no files or directories","error-extract":"Could not unpack archive {{0}} to {{1}}","module-added":"Module successfully added","module-deleted":"Module {{0}} was deleted","module-in-use":"Module {{0}} is still used by Configuration {{1}}","taskmanager-error":"Failed to connect to the Task Manager","taskmanager-format":"Task Manager has returned invalid data","task-error":"Execution failed: {{0}}","invalid-ip":"No interface is configured with the address {{0}}","news-save-success":"News updated successfully","news-empty":"There was no news found in the database","news-del-success":"News deleted","reboot-unconfirmed":"Confirmation prompt to reboot not confirmed","invalid-template":"Selected template is not valid","deleted-tag":"Tag was successfully removed","updated-tags":"","unsuccessful-action":""} \ No newline at end of file
diff --git a/lang/en/page-minilinux.json b/lang/en/page-minilinux.json
index 2841f528..2ec6123c 100644
--- a/lang/en/page-minilinux.json
+++ b/lang/en/page-minilinux.json
@@ -1,3 +1 @@
-{
- "lang_listObtained":"List is being obtained..."
-}
+{"lang_listObtained":"List is being obtained...","lang_errorGetting":""} \ No newline at end of file
diff --git a/lang/en/translation/_page.json b/lang/en/translation/_page.json
new file mode 100644
index 00000000..f2b82119
--- /dev/null
+++ b/lang/en/translation/_page.json
@@ -0,0 +1 @@
+{"lang_langAdministration":"Language Administration","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_editMessages":"Edit Messages","lang_german":"German","lang_english":"English","lang_portuguese":"Portuguese"} \ No newline at end of file
diff --git a/lang/en/translation/messages.json b/lang/en/translation/messages.json
new file mode 100644
index 00000000..4762d6d6
--- /dev/null
+++ b/lang/en/translation/messages.json
@@ -0,0 +1 @@
+{"lang_messages":"Messages","lang_templateMessagesHelp":"","lang_germanJSON":"German JSON","lang_englishJSON":"English JSON","lang_portugueseJSON":"German JSON","lang_germanTAG":"German TAG","lang_englishTAG":"English TAG","lang_portugueseTAG":"Portuguese TAG","lang_back":"Back","lang_newTag":"New Tag","lang_messagesHardcoded":"Hardcoded Messages","lang_newTAG":"New TAG","lang_deleteTAG":"Delete","lang_templateHint":"Hint: Yellow lines indicate a translation is missing and red lines indicate a tag is not being used by the template.","lang_save":"Save"} \ No newline at end of file
diff --git a/lang/en/translation/template.json b/lang/en/translation/template.json
new file mode 100644
index 00000000..cf707b5f
--- /dev/null
+++ b/lang/en/translation/template.json
@@ -0,0 +1 @@
+{"lang_templateAdminHelp":"","lang_germanJSON":"German JSON","lang_englishJSON":"English JSON","lang_portugueseJSON":"German JSON","lang_germanTAG":"German TAG","lang_englishTAG":"English TAG","lang_portugueseTAG":"Portuguese TAG","lang_back":"Back","lang_createTag":"Create TAG","lang_newTAG":"New TAG","lang_deleteTAG":"Delete","lang_templateHint":"Hint: Yellow lines indicate a translation is missing and red lines indicate a tag is not being used by the template.","lang_save":"Save"} \ No newline at end of file
diff --git a/lang/pt/.json b/lang/pt/.json
deleted file mode 100644
index d21fc0f5..00000000
--- a/lang/pt/.json
+++ /dev/null
@@ -1 +0,0 @@
-{"loginfail":"Nome de usu\u00e1rio ou senha incorreta","token":"Token inv\u00e1lido. Ataque CSRF?","adduser":"Usu\u00e1rio adicionado com sucesso","password":"Senha e confirma\u00e7\u00e3o de senha n\u00e3o s\u00e3o iguais","empty":"O arquivo n\u00e3o cont\u00e9m arquivos ou diret\u00f3rios","no":"N\u00e3o h\u00e1 privil\u00e9gios suficientes para acessar essa p\u00e1gina","settings":"As configura\u00e7\u00f5es foram atualizadas","debug":"O modo de depura\u00e7\u00e3o est\u00e1 ativo!","value":"O valor {{1}} \u00e9 inv\u00e1lido para op\u00e7\u00e3o {{0}} e foi ignorado","invalid":"Template selecionado n\u00e3o \u00e9 v\u00e1lido","remote":"An\u00e1lise dos dados recebidos falhou ({{0}})","missing":"N\u00e3o havia nenhum arquivo selecionado!","upload":"Envio falhou: {{0}}","config":"Configura\u00e7\u00e3o com id {{0}} n\u00e3o existe","error":"N\u00e3o foi poss\u00edvel descompactar arquivo {{0}} para {{1}}","module":"M\u00f3dulo {{0}} ainda \u00e9 usado pela configura\u00e7\u00e3o {{1}}","taskmanager":"Gerenciador de Tarefas retornou dados inv\u00e1lidos","task":"Falha na execu\u00e7\u00e3o: {{0}}","news":"Not\u00edcia exclu\u00edda","reboot":"Confirma\u00e7\u00e3o para reinicializar n\u00e3o foi confirmada","lang_unknwonTaskManager":"Erro desconhecido do Gerenciador de Tarefas","lang_configurationCompilation":"Compilar configura\u00e7\u00e3o","lang_moduleAdd":"Adicionar M\u00f3dulo","lang_adAuthentication":"Autentica\u00e7\u00e3o do Active Directory","lang_adModule":"Este m\u00f3dulo possibilita a aplica\u00e7\u00e3o para os computadores clientes com as contas de usu\u00e1rio de um Active Directory. Dependendo da configura\u00e7\u00e3o, o uso de um diret\u00f3rio de usu\u00e1rio no cliente \u00e9 poss\u00edvel.","lang_authentication":"Autentica\u00e7\u00e3o","lang_generic":"Gen\u00e9rico","lang_addCustomModuleInfo":"Com um m\u00f3dulo estendido, \u00e9 poss\u00edvel adicionar os arquivos para o sistema b\u00e1sico que usa este m\u00f3dulo, por exemplo, para usar arquivos de configura\u00e7\u00e3o espec\u00edficas, que n\u00e3o podem ser criados com um dos outros assistentes. Adicionar um m\u00f3dulo estendido normalmente exige pelo menos um conhecimento b\u00e1sico do sistema Linux.","lang_days":"Dia(s)","lang_hours":"Hora(s)","lang_specificLogo":"Logotipo Espec\u00edfico da Institui\u00e7\u00e3o","lang_institutionLogo":"Logotipo da Institui\u00e7\u00e3o","lang_infoLogo":"Este m\u00f3dulo \u00e9 usado para adicionar o logotipo de uma faculdade \/ universidade, que ent\u00e3o, por exemplo, \u00e9 exibido na tela de login.","lang_location":"Localiza\u00e7\u00e3o","lang_contentOf":"Conte\u00fado de \"","lang_serverConfiguration":"Configura\u00e7\u00e3o do servidor","lang_login":"Entrar","lang_createUser":"Criar Usu\u00e1rio"} \ No newline at end of file
diff --git a/lang/pt/administration/template.json b/lang/pt/administration/template.json
deleted file mode 100644
index 8042342f..00000000
--- a/lang/pt/administration/template.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lang_templateAdminHelp":"","lang_germanJSON":"JSON Alem\u00e3o","lang_englishJSON":"JSON Ingl\u00eas","lang_portugueseJSON":"JSON Portugu\u00eas","lang_germanTAG":"TAG em Alem\u00e3o","lang_englishTAG":"TAG em Ingl\u00eas","lang_portugueseTAG":"TAG em Portugu\u00eas","lang_back":"Voltar","lang_update":"Carregar","lang_createTag":"Criar TAG","lang_newTAG":"Nova TAG","lang_deleteTAG":"Excluir"} \ No newline at end of file
diff --git a/lang/pt/dialog-generic.json b/lang/pt/dialog-generic.json
index e6b73911..4bfb1624 100644
--- a/lang/pt/dialog-generic.json
+++ b/lang/pt/dialog-generic.json
@@ -1 +1 @@
-{"lang_notUsed":"","lang_next":"Pr\u00f3ximo"} \ No newline at end of file
+{"lang_next":"Pr\u00f3ximo"} \ No newline at end of file
diff --git a/lang/pt/main-menu-login.json b/lang/pt/main-menu-login.json
index feab29f1..0d539c6a 100644
--- a/lang/pt/main-menu-login.json
+++ b/lang/pt/main-menu-login.json
@@ -1 +1 @@
-{"lang_clientLog":"Log dos Clientes","lang_settings":"Op\u00e7\u00f5es","lang_client":"Cliente","lang_localization":"Localiza\u00e7\u00e3o","lang_configurationVariables":"Vari\u00e1veis de Configura\u00e7\u00e3o","lang_administration":"Administra\u00e7\u00e3o","lang_server":"Servidor","lang_configurationBasic":"Comfigura\u00e7\u00e3o B\u00e1sica","lang_vmLocation":"Localiza\u00e7\u00e3o da VM","lang_news":"Novidades","lang_language":"L\u00edngua","lang_login":"Entrar"} \ No newline at end of file
+{"lang_clientLog":"Log dos Clientes","lang_settings":"Op\u00e7\u00f5es","lang_client":"Cliente","lang_localization":"Localiza\u00e7\u00e3o","lang_configurationVariables":"Vari\u00e1veis de Configura\u00e7\u00e3o","lang_administration":"Tradu\u00e7\u00f5es","lang_server":"Servidor","lang_configurationBasic":"Comfigura\u00e7\u00e3o B\u00e1sica","lang_vmLocation":"Localiza\u00e7\u00e3o da VM","lang_news":"Novidades","lang_language":"L\u00edngua","lang_login":"Entrar"} \ No newline at end of file
diff --git a/lang/pt/main-menu-logout.json b/lang/pt/main-menu-logout.json
index 13ddfa15..9b2d985a 100644
--- a/lang/pt/main-menu-logout.json
+++ b/lang/pt/main-menu-logout.json
@@ -1 +1 @@
-{"lang_clientLog":"Log dos Clientes","lang_settings":"Op\u00e7\u00f5es","lang_client":"Cliente","lang_localization":"Localiza\u00e7\u00e3o","lang_configurationVariables":"Vari\u00e1veis de Configura\u00e7\u00e3o","lang_administration":"Administra\u00e7\u00e3o","lang_server":"Servidor","lang_configurationBasic":"Comfigura\u00e7\u00e3o B\u00e1sica","lang_vmLocation":"Localiza\u00e7\u00e3o da VM","lang_news":"Novidades","lang_language":"L\u00edngua","lang_logout":"Sair"} \ No newline at end of file
+{"lang_clientLog":"Log dos Clientes","lang_settings":"Op\u00e7\u00f5es","lang_client":"Cliente","lang_localization":"Localiza\u00e7\u00e3o","lang_configurationVariables":"Vari\u00e1veis de Configura\u00e7\u00e3o","lang_administration":"Tradu\u00e7\u00f5es","lang_server":"Servidor","lang_configurationBasic":"Comfigura\u00e7\u00e3o B\u00e1sica","lang_vmLocation":"Localiza\u00e7\u00e3o da VM","lang_news":"Novidades","lang_language":"L\u00edngua","lang_logout":"Sair"} \ No newline at end of file
diff --git a/lang/pt/messages.json b/lang/pt/messages.json
index 3033fdb8..44224bc5 100644
--- a/lang/pt/messages.json
+++ b/lang/pt/messages.json
@@ -1 +1 @@
-{"loginfail":"Nome de usu\u00e1rio ou senha incorreta","token":"Token inv\u00e1lido. Ataque CSRF?","adduser-disabled":"Privil\u00e9gios insuficientes para adicionar mais usu\u00e1rios","password-mismatch":"Senha e confirma\u00e7\u00e3o de senha n\u00e3o s\u00e3o iguais","empty-field":"Um campo n\u00e3o foi preenchido","adduser-success":"Usu\u00e1rio adicionado com sucesso","no-permission":"N\u00e3o h\u00e1 privil\u00e9gios suficientes para acessar essa p\u00e1gina","settings-updated":"As configura\u00e7\u00f5es foram atualizadas","debug-mode":"O modo de depura\u00e7\u00e3o est\u00e1 ativo!","value-invalid":"O valor {{1}} \u00e9 inv\u00e1lido para op\u00e7\u00e3o {{0}} e foi ignorado","invalid-action":"A\u00e7\u00e3o inv\u00e1lida: {{0}}","remote-timeout":"N\u00e3o foi poss\u00edvel baixar o recurso {{0}} ({{1}})","remote-parse-failed":"An\u00e1lise dos dados recebidos falhou ({{0}})","missing-file":"N\u00e3o havia nenhum arquivo selecionado!","invalid-file":"O arquivo {{0}} n\u00e3o existe!","upload-complete":"Envio de {{0}} foi bem sucedido","upload-failed":"Envio falhou: {{0}}","config-activated":"Configura\u00e7\u00e3o {{0}} foi ativada","config-invalid":"Configura\u00e7\u00e3o com id {{0}} n\u00e3o existe","error-write":"Erro ao escrever {{0}}","error-read":"Erro ao ler {{0}}","error-archive":"Arquivo corrompido ou formato n\u00e3o suportado","error-rename":"N\u00e3o foi poss\u00edvel renomear {{0}} em {{1}}","error-nodir":"O diret\u00f3rio {{0}} n\u00e3o existe.","empty-archive":"O arquivo n\u00e3o cont\u00e9m arquivos ou diret\u00f3rios","error-extract":"N\u00e3o foi poss\u00edvel descompactar arquivo {{0}} para {{1}}","module-added":"M\u00f3dulo adicionado com sucesso","module-deleted":"M\u00f3dulo {{0}} foi exclu\u00eddo","module-in-use":"M\u00f3dulo {{0}} ainda \u00e9 usado pela configura\u00e7\u00e3o {{1}}","taskmanager-error":"Falha ao conectar-se ao Gerenciador de Tarefas","taskmanager-format":"Gerenciador de Tarefas retornou dados inv\u00e1lidos","task-error":"Falha na execu\u00e7\u00e3o: {{0}}","invalid-ip":"Nenhuma interface est\u00e1 configurada com o endere\u00e7o {{0}}","news-save-success":"Not\u00edcia atualizada com sucesso","news-empty":"N\u00e3o havia not\u00edcias no banco de dados","news-del-success":"Not\u00edcia exclu\u00edda","reboot-unconfirmed":"Confirma\u00e7\u00e3o para reinicializar n\u00e3o foi confirmada","invalid-template":"Template selecionado n\u00e3o \u00e9 v\u00e1lido","deleted-tag":"Tag foi removida com sucesso","updated-tags":"Tags foram atualizadas com sucesso"} \ No newline at end of file
+{"loginfail":"Nome de usu\u00e1rio ou senha incorreta","token":"Token inv\u00e1lido. Ataque CSRF?","adduser-disabled":"Privil\u00e9gios insuficientes para adicionar mais usu\u00e1rios","password-mismatch":"Senha e confirma\u00e7\u00e3o de senha n\u00e3o s\u00e3o iguais","empty-field":"Um campo n\u00e3o foi preenchido","adduser-success":"Usu\u00e1rio adicionado com sucesso","no-permission":"N\u00e3o h\u00e1 privil\u00e9gios suficientes para acessar essa p\u00e1gina","settings-updated":"As configura\u00e7\u00f5es foram atualizadas","debug-mode":"O modo de depura\u00e7\u00e3o est\u00e1 ativo!","value-invalid":"O valor {{1}} \u00e9 inv\u00e1lido para op\u00e7\u00e3o {{0}} e foi ignorado","invalid-action":"A\u00e7\u00e3o inv\u00e1lida: {{0}}","remote-timeout":"N\u00e3o foi poss\u00edvel baixar o recurso {{0}} ({{1}})","remote-parse-failed":"An\u00e1lise dos dados recebidos falhou ({{0}})","missing-file":"N\u00e3o havia nenhum arquivo selecionado!","invalid-file":"O arquivo {{0}} n\u00e3o existe!","upload-complete":"Envio de {{0}} foi bem sucedido","upload-failed":"Envio falhou: {{0}}","config-activated":"Configura\u00e7\u00e3o {{0}} foi ativada","config-invalid":"Configura\u00e7\u00e3o com id {{0}} n\u00e3o existe","error-write":"Erro ao escrever {{0}}","error-read":"Erro ao ler {{0}}","error-archive":"Arquivo corrompido ou formato n\u00e3o suportado","error-rename":"N\u00e3o foi poss\u00edvel renomear {{0}} em {{1}}","error-nodir":"O diret\u00f3rio {{0}} n\u00e3o existe.","empty-archive":"O arquivo n\u00e3o cont\u00e9m arquivos ou diret\u00f3rios","error-extract":"N\u00e3o foi poss\u00edvel descompactar arquivo {{0}} para {{1}}","module-added":"M\u00f3dulo adicionado com sucesso","module-deleted":"M\u00f3dulo {{0}} foi exclu\u00eddo","module-in-use":"M\u00f3dulo {{0}} ainda \u00e9 usado pela configura\u00e7\u00e3o {{1}}","taskmanager-error":"Falha ao conectar-se ao Gerenciador de Tarefas","taskmanager-format":"Gerenciador de Tarefas retornou dados inv\u00e1lidos","task-error":"Falha na execu\u00e7\u00e3o: {{0}}","invalid-ip":"Nenhuma interface est\u00e1 configurada com o endere\u00e7o {{0}}","news-save-success":"Not\u00edcia atualizada com sucesso","news-empty":"N\u00e3o havia not\u00edcias no banco de dados","news-del-success":"Not\u00edcia exclu\u00edda","reboot-unconfirmed":"Confirma\u00e7\u00e3o para reinicializar n\u00e3o foi confirmada","invalid-template":"Template selecionado n\u00e3o \u00e9 v\u00e1lido","deleted-tag":"Tag foi removida com sucesso","updated-tags":"Tags foram atualizadas com sucesso","unsuccessful-action":"A a\u00e7\u00e3o n\u00e3o foi bem sucedida"} \ No newline at end of file
diff --git a/lang/pt/page-minilinux.json b/lang/pt/page-minilinux.json
index 0f5aa3d1..c873855b 100644
--- a/lang/pt/page-minilinux.json
+++ b/lang/pt/page-minilinux.json
@@ -1,3 +1 @@
-{
- "lang_listObtained":"A lista está sendo obtida..."
-}
+{"lang_listObtained":"A lista est\u00e1 sendo obtida...","lang_errorGetting":""} \ No newline at end of file
diff --git a/lang/pt/administration/_page.json b/lang/pt/translation/_page.json
index 7a9fee55..7a9fee55 100644
--- a/lang/pt/administration/_page.json
+++ b/lang/pt/translation/_page.json
diff --git a/lang/pt/administration/messages.json b/lang/pt/translation/messages.json
index b4897277..b8da3765 100644
--- a/lang/pt/administration/messages.json
+++ b/lang/pt/translation/messages.json
@@ -1 +1 @@
-{"lang_messages":"Mensagens","lang_templateMessagesHelp":"Aqui \u00e9 poss\u00edvel alterar as mensagens exibidas no site.","lang_germanJSON":"JSON Alem\u00e3o","lang_englishJSON":"JSON Ingl\u00eas","lang_portugueseJSON":"JSON Portugu\u00eas","lang_germanTAG":"Mensagem em Alem\u00e3o","lang_englishTAG":"Mensagem em Ingl\u00eas","lang_portugueseTAG":"Mensagem em Portugu\u00eas","lang_back":"Voltar","lang_newTag":"Nova Mensagem","lang_update":"Carregar","lang_messagesHardcoded":"Mensagens Hardcoded","lang_newTAG":"Nova TAG","lang_deleteTAG":"Excluir"} \ No newline at end of file
+{"lang_messages":"Mensagens","lang_templateMessagesHelp":"Aqui \u00e9 poss\u00edvel alterar as mensagens exibidas no site.","lang_germanJSON":"JSON Alem\u00e3o","lang_englishJSON":"JSON Ingl\u00eas","lang_portugueseJSON":"JSON Portugu\u00eas","lang_germanTAG":"Mensagem em Alem\u00e3o","lang_englishTAG":"Mensagem em Ingl\u00eas","lang_portugueseTAG":"Mensagem em Portugu\u00eas","lang_back":"Voltar","lang_newTag":"Nova Mensagem","lang_messagesHardcoded":"Mensagens Hardcoded","lang_newTAG":"Nova TAG","lang_deleteTAG":"Excluir","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_save":"Salvar"} \ No newline at end of file
diff --git a/lang/pt/translation/template.json b/lang/pt/translation/template.json
new file mode 100644
index 00000000..2db9a9af
--- /dev/null
+++ b/lang/pt/translation/template.json
@@ -0,0 +1 @@
+{"lang_templateAdminHelp":"","lang_germanJSON":"JSON Alem\u00e3o","lang_englishJSON":"JSON Ingl\u00eas","lang_portugueseJSON":"JSON Portugu\u00eas","lang_germanTAG":"TAG em Alem\u00e3o","lang_englishTAG":"TAG em Ingl\u00eas","lang_portugueseTAG":"TAG em Portugu\u00eas","lang_back":"Voltar","lang_createTag":"Criar TAG","lang_newTAG":"Nova TAG","lang_deleteTAG":"Excluir","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_save":"Salvar"} \ No newline at end of file
diff --git a/modules/admin.inc.php b/modules/admin.inc.php
deleted file mode 100644
index 97a47819..00000000
--- a/modules/admin.inc.php
+++ /dev/null
@@ -1,295 +0,0 @@
-<?php
-
-class Page_Admin extends Page
-{
-
- private $template = false;
- private $path = false;
- private $page = false;
- private $update = false;
- private $files = false;
- private $table = false;
- private $delete = false;
- private $tags = false;
- private $unusedTags = false;
- private $message = false;
-
- protected function doPreprocess()
- {
- User::load();
-
- if (!User::hasPermission('superadmin')) {
- Message::addError('no-permission');
- Util::redirect('?do=Main');
- }
-
- if (Request::get('template')) {
- $this->template = Request::get('template');
- }
-
- if (Request::get('page')) {
- $this->page = Request::get('page');
- }
-
- if (Request::get('delete')) {
- $this->delete = Request::get('delete');
- }
-
- if (Request::post('update')) {
- $this->update = Request::post('update');
- }
- }
-
- protected function doRender()
- {
- if ($this->update)
- $this->updateJson();
- if ($this->delete && $this->template)
- $this->deleteTag($this->template, $this->delete);
-
- switch ($this->page) {
- case 'messages':
- Render::addTemplate('administration/messages', array(
- 'token' => Session::get('token'),
- 'msgs' => $this->initMsg(false),
- 'msgsHC' => $this->initMsg(true)
- ));
- break;
- case 'templates':
- if ($this->templateAnalysis($this->template)) {
- Render::addTemplate('administration/template', array(
- 'token' => Session::get('token'),
- 'template' => $this->template,
- 'path' => $this->path,
- 'tags' => $this->tags
- ));
- break;
- }
- default:
- $this->initTable();
- Render::addTemplate('administration/_page', array(
- 'token' => Session::get('token'),
- 'adminMessage' => $this->message,
- 'table' => $this->table
- ));
- }
- }
-
- private function initTable()
- {
- $this->listTemplates();
- $de = $this->listJson('de/');
- $en = $this->listJson('en/');
- $pt = $this->listJson('pt/');
-
- foreach ($this->files as $key => $value) {
-
- $this->table[] = array(
- 'template' => $value,
- 'link' => $key,
- 'de' => $this->checkJson($de[$key], 'de'),
- 'en' => $this->checkJson($en[$key], 'en'),
- 'pt' => $this->checkJson($pt[$key], 'pt')
- );
- }
-
- sort($this->table);
- }
-
- private function listTemplates()
- {
- $this->files = array();
- $dir = 'templates/';
- $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
- foreach ($objects as $name => $object) {
- if (array_pop(explode('.', $name)) === 'html') {
- $key = str_replace($dir, '', $name);
- $key = str_replace('.html', '', $key);
- $this->files[$key] = $name;
- }
- }
- }
-
- private function listJson($lang)
- {
- $json = array();
- $dir = 'lang/' . $lang;
- $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
- foreach ($objects as $name => $object) {
- if (array_pop(explode('.', $name)) === 'json') {
- $key = str_replace($dir, '', $name);
- $key = str_replace('.json', '', $key);
- $json[$key] = $key;
- }
- }
- return $json;
- }
-
- private function checkJson($path, $lang)
- {
- if (!$path) {
- return "JSON file is missing";
- } else {
- $htmlTemplate = file_get_contents('templates/' . $path . '.html');
- $json = Dictionary::getArrayTemplate($path, $lang);
- preg_match_all('/{{lang_(.*?)}}/s', $htmlTemplate, $matches);
- $htmlCount = count(array_unique($matches[1]));
- $matchCount = 0;
-
- foreach ($json as $key => $value) {
- if ($key != 'lang') {
- if (!in_array(preg_replace('/^lang_/', '', $key), $matches[1])) {
- $matchCount++;
- } else if ($value != '') {
- $matchCount++;
- }
- }
- }
-
- $diff = $htmlCount - $matchCount;
- if ($diff == 0)
- return "OK";
- if ($diff > 0)
- return $diff . " JSON tag(s) are missing";
- if ($diff < 0)
- return ($diff * -1) . " JSON tag(s) are not being used";
- }
- }
-
- private function templateAnalysis($path)
- {
- if (!file_exists('templates/' . $path . '.html')) {
- Message::addError('invalid-template');
- return false;
- }
- $htmlTemplate = file_get_contents('templates/' . $path . '.html');
- preg_match_all('/{{lang_(.*?)}}/s', $htmlTemplate, $matches);
- $tags = $matches[1];
- $tags = array_flip($tags);
- foreach ($tags as $key => $value) {
- $tags['lang_' . $key] = $value;
- unset($tags[$key]);
- }
-
- $langArray = array('en');
- $json = array();
- foreach ($langArray as $lang) {
- $jsonTags = Dictionary::getArrayTemplate($path, $lang);
- $json = array_merge($json, $jsonTags);
- }
-
- unset($json['lang']);
- $test = array_merge($json, $tags);
-
- foreach ($test as $tag => $value) {
- $this->tags[] = array(
- 'tag' => $tag,
- 'de' => $this->checkJsonTag($path, $tag, 'de/'),
- 'en' => $this->checkJsonTag($path, $tag, 'en/'),
- 'pt' => $this->checkJsonTag($path, $tag, 'pt/'),
- 'class' => $this->checkJsonTags($path, $tag)
- );
- }
-
- $this->path = $path;
-
- return true;
- }
-
- private function checkJsonTag($path, $tag, $lang)
- {
- if ($json = Dictionary::getArrayTemplate($path, $lang)) {
- return $json[$tag];
- }
- return '';
- }
-
- private function checkJsonTags($path, $tag)
- {
- $htmlTemplate = file_get_contents('templates/' . $path . '.html');
- $htmlCount = substr_count($htmlTemplate, $tag);
- if ($htmlCount < 1)
- return "danger";
-
- $langArray = array('de/', 'en/', 'pt/');
- foreach ($langArray as $lang) {
- if ($json = Dictionary::getArrayTemplate($path, $lang)) {
- if (!isset($json[$tag]) || $json[$tag] == '')
- return 'warning';
- }
- }
- return '';
- }
-
- private function updateJson()
- {
- $langArray = Dictionary::getLanguages();
- $json = array();
- foreach ($langArray as $lang) {
- $json[$lang] = array();
- }
-
- foreach ($_REQUEST as $key => $value) {
- $str = explode('#', $key, 3);
- if (count($str) !== 3)
- continue;
- $pre = $str[0];
- $lang = $str[1];
- $tag = $str[2];
- if ($pre === 'lang') {
- if (in_array($lang, $langArray)) {
- if ($tag !== 'newtag')
- $json[$lang][$tag] = $value;
- else {
- $json[$lang][$_REQUEST['newtag']] = $value;
- }
- }
- }
- }
-
- foreach ($json as $key => $array) {
- $path = 'lang/' . $key . '/' . $_POST['path'] . '.json'; // TODO: Wtf? Unvalidated user input -> filesystem access!
- $json = json_encode($array, JSON_PRETTY_PRINT);
- if (@file_put_contents($path, $json) === false) {
- Message::addError('invalid-template');
- return false;
- }
- }
- Message::addSuccess('updated-tags');
- }
-
- private function initMsg($isHardcoded)
- {
- $msgs = array();
- $path = 'messages';
- if ($isHardcoded) {
- $path = 'messages-hardcoded';
- }
- $json = Dictionary::getArrayTemplate($path, $lang);
- foreach ($json as $key => $array) {
- if ($key != 'lang')
- $msgs[] = array(
- 'tag' => $key,
- 'de' => $this->checkJsonTag($path, $key, 'de/'), // TODO: Hardcoded language list, use Dictionary::getLanguages()
- 'en' => $this->checkJsonTag($path, $key, 'en/'),
- 'pt' => $this->checkJsonTag($path, $key, 'pt/')
- );
- }
-
- return $msgs;
- }
-
- private function deleteTag($path, $tag)
- {
- $langArray = unserialize(SITE_LANGUAGES);
- foreach ($langArray as $lang) {
- $json = Dictionary::getArrayTemplate($path, $lang);
- unset($json[$tag]);
- unset($json['lang']);
- //file_put_contents('test.txt','lang/' . $lang . '/' . $path . '.json');
- file_put_contents('lang/' . $lang . '/' . $path . '.json', json_encode($json)); // TODO: Check return code, show error if not writable
- }
- Message::addSuccess('deleted-tag');
- }
-
-}
diff --git a/modules/translation.inc.php b/modules/translation.inc.php
new file mode 100644
index 00000000..fccde7cf
--- /dev/null
+++ b/modules/translation.inc.php
@@ -0,0 +1,389 @@
+<?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;
+ private $update = false;
+ private $delete = false;
+ private $tags = false;
+
+ protected function doPreprocess()
+ {
+ User::load();
+
+ if (!User::hasPermission('superadmin')) {
+ Message::addError('no-permission');
+ Util::redirect('?do=Main');
+ }
+
+ if (Request::get('template')) {
+ $this->template = Request::get('template');
+ }
+
+ if (Request::get('page')) {
+ $this->page = Request::get('page');
+ }
+
+ if (Request::get('delete')) {
+ $this->delete = Request::get('delete');
+ }
+
+ if (Request::post('update')) {
+ $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);
+
+ //load the page accordingly to the link
+ switch ($this->page) {
+ case 'messages':
+ //renders the message edition page
+ Render::addTemplate('translation/messages', array(
+ 'token' => Session::get('token'),
+ 'msgs' => $this->initMsg(false),
+ 'msgsHC' => $this->initMsg(true)
+ ));
+ break;
+ case 'templates':
+ //renders the tag edition page
+ if ($this->templateAnalysis($this->template)) {
+ Render::addTemplate('translation/template', array(
+ 'token' => Session::get('token'),
+ 'template' => $this->template,
+ 'tags' => $this->tags
+ ));
+ break;
+ }
+ default:
+ //renders the template selection page
+ Render::addTemplate('translation/_page', array(
+ 'token' => Session::get('token'),
+ 'table' => $this->initTable(),
+ ));
+ }
+ }
+
+ /**
+ * Load the main table with all the website's templates and it's informations
+ * @return array with the templates' information
+ */
+ private function initTable()
+ {
+ $table = array();
+
+ //loads every template
+ $files = $this->listTemplates();
+ //loads every json from each language
+ $de = $this->listJson('de/');
+ $en = $this->listJson('en/');
+ $pt = $this->listJson('pt/');
+
+ //checks the JSON tags from every language
+ foreach ($files as $key => $value) {
+ $table[] = array(
+ 'template' => $value,
+ 'link' => $key,
+ 'de' => $this->checkJson($de[$key], 'de'),
+ 'en' => $this->checkJson($en[$key], 'en'),
+ 'pt' => $this->checkJson($pt[$key], 'pt')
+ );
+ }
+ sort($table);
+ return $table;
+ }
+
+ /**
+ * Finds and returns all the website's templates
+ * @return array
+ */
+ private function listTemplates()
+ {
+ $files = array();
+ $dir = 'templates/';
+ $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
+ foreach ($objects as $name => $object) {
+ if (array_pop(explode('.', $name)) === 'html') {
+ $key = str_replace($dir, '', $name);
+ $key = str_replace('.html', '', $key);
+ $files[$key] = $name;
+ }
+ }
+ 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 (array_pop(explode('.', $name)) === 'json') {
+ $key = str_replace($dir, '', $name);
+ $key = str_replace('.json', '', $key);
+ $json[$key] = $key;
+ }
+ }
+ return $json;
+ }
+
+ /**
+ * Checks the JSON tags from a template
+ * @param string the template's path
+ * @param string the selected language
+ * @return string the information about the JSON tags
+ */
+ private function checkJson($path, $lang)
+ {
+ //if there was not a valid template's path
+ if (!$path) {
+ return "JSON file is missing";
+ }
+ //loads a template and find all its tags
+ $htmlTemplate = file_get_contents('templates/' . $path . '.html');
+ preg_match_all('/{{lang_(.*?)}}/s', $htmlTemplate, $matches);
+ $htmlCount = count(array_unique($matches[1]));
+
+ //initialize the count variables
+ $matchCount = 0;
+ $unusedCount = 0;
+
+ //loads the JSON tags and count the matches
+ $json = Dictionary::getArrayTemplate($path, $lang);
+ foreach ($json as $key => $value) {
+ if ($key != 'lang') {
+ if (!in_array(preg_replace('/^lang_/', '', $key), $matches[1])) {
+ $unusedCount++;
+ } else if ($value != '') {
+ $matchCount++;
+ }
+ }
+ }
+ $diff = $htmlCount - $matchCount;
+
+ //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)
+ $str .= "<br>";
+ if ($unusedCount > 0)
+ $str .= $unusedCount . " JSON tag(s) are not being used";
+ return $str;
+ }
+
+ /**
+ * 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
+ */
+ private function templateAnalysis($path)
+ {
+ //checks if the template is valid
+ if (!file_exists('templates/' . $path . '.html')) {
+ Message::addError('invalid-template');
+ return false;
+ }
+
+ //finds every mustache tag within the html template
+ $htmlTemplate = file_get_contents('templates/' . $path . '.html');
+ preg_match_all('/{{lang_(.*?)}}/s', $htmlTemplate, $matches);
+ $tags = $matches[1];
+ $tags = array_flip($tags);
+ foreach ($tags as $key => $value) {
+ $tags['lang_' . $key] = $value;
+ unset($tags[$key]);
+ }
+
+ //finds every JSON tag withing the JSON language files
+ $langArray = Dictionary::getLanguages();
+ $json = array();
+ foreach ($langArray as $lang) {
+ $jsonTags = Dictionary::getArrayTemplate($path, $lang);
+ if (is_array($jsonTags))
+ $json = array_merge($json, $jsonTags);
+ }
+ //remove unused tag
+ unset($json['lang']);
+ //merges the arrays to keep the unique tags
+ $test = array_merge($json, $tags);
+
+ //loads the content of every JSON tag from the specified language
+ foreach ($test as $tag => $value) {
+ $this->tags[] = array(
+ 'tag' => $tag,
+ 'de' => $this->checkJsonTag($path, $tag, 'de/'),
+ 'en' => $this->checkJsonTag($path, $tag, 'en/'),
+ 'pt' => $this->checkJsonTag($path, $tag, 'pt/'),
+ 'class' => $this->checkJsonTags($path, $tag)
+ );
+ }
+
+ 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 checkJsonTag($path, $tag, $lang)
+ {
+ $json = Dictionary::getArrayTemplate($path, $lang);
+ if (is_array($json) && isset($json[$tag])) {
+ return $json[$tag];
+ }
+ return '';
+ }
+
+ /**
+ * 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 checkJsonTags($path, $tag)
+ {
+ //return danger in case the tag is not found in the template
+ $htmlTemplate = file_get_contents('templates/' . $path . '.html');
+ $htmlCount = substr_count($htmlTemplate, $tag);
+ if ($htmlCount < 1)
+ return "danger";
+
+ //return warning in case at least one of the tag's values is empty
+ $langArray = array('de/', 'en/', 'pt/');
+ foreach ($langArray as $lang) {
+ if (($json = Dictionary::getArrayTemplate($path, $lang))) {
+ if (!isset($json[$tag]) || $json[$tag] == '')
+ 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 ($_REQUEST as $key => $value) {
+ $str = explode('#', $key, 3);
+ if (count($str) !== 3)
+ continue;
+ $pre = $str[0];
+ $lang = $str[1];
+ $tag = $str[2];
+ if ($pre !== 'lang')
+ continue;
+ if (in_array($lang, $langArray)) {
+ if ($tag !== 'newtag')
+ $json[$lang][$tag] = $value;
+ else {
+ $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 = 'lang/' . $key . '/' . $_POST['path'] . '.json'; // TODO: Wtf? Unvalidated user input -> filesystem access!
+ 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');
+ }
+
+ /**
+ * 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();
+ //chooses the path
+ $path = 'messages';
+ if ($isHardcoded) {
+ $path = 'messages-hardcoded';
+ }
+ //loads the content of every JSON tag from the message file
+ $json = Dictionary::getArrayTemplate($path, LANG);
+ foreach ($json as $key => $array) {
+ if ($key != 'lang')
+ $msgs[] = array(
+ 'tag' => $key,
+ 'de' => $this->checkJsonTag($path, $key, 'de/'), // TODO: Hardcoded language list, use Dictionary::getLanguages()
+ 'en' => $this->checkJsonTag($path, $key, 'en/'),
+ 'pt' => $this->checkJsonTag($path, $key, '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
+ * @return boolean if the action was not successful
+ */
+ private function deleteTag($path, $tag)
+ {
+ //delete the tag from every language file
+ $langArray = unserialize(SITE_LANGUAGES);
+ foreach ($langArray as $lang) {
+ $json = Dictionary::getArrayTemplate($path, $lang);
+ unset($json[$tag]);
+ unset($json['lang']);
+ $result = file_put_contents('lang/' . $lang . '/' . $path . '.json', json_encode($json));
+ //add warning and exit in case the action was unsuccessful
+ if ($result === false) {
+ Message::addWarning('unsuccessful-action');
+ return false;
+ }
+ }
+ Message::addSuccess('deleted-tag');
+ }
+
+}
diff --git a/templates/main-menu-login.html b/templates/main-menu-login.html
index 71e10b0e..81aef288 100644
--- a/templates/main-menu-login.html
+++ b/templates/main-menu-login.html
@@ -19,7 +19,7 @@
<li><a href="?do=SysConfig">{{lang_localization}}</a></li>
<li><a href="?do=MiniLinux">bwLehrpool Mini-Linux</a></li>
<li><a href="?do=BaseConfig">{{lang_configurationVariables}}</a></li>
- <li><a href="?do=Admin">{{lang_administration}}</a></li>
+ <li><a href="?do=Translation">{{lang_administration}}</a></li>
<li class="divider"></li>
<li class="dropdown-header">{{lang_server}}</li>
<li><a href="?do=ServerSetup">{{lang_configurationBasic}}</a></li>
diff --git a/templates/main-menu-logout.html b/templates/main-menu-logout.html
index 1721161e..d5671fef 100644
--- a/templates/main-menu-logout.html
+++ b/templates/main-menu-logout.html
@@ -19,7 +19,7 @@
<li><a href="?do=SysConfig">{{lang_localization}}</a></li>
<li><a href="?do=MiniLinux">bwLehrpool Mini-Linux</a></li>
<li><a href="?do=BaseConfig">{{lang_configurationVariables}}</a></li>
- <li><a href="?do=Admin">{{lang_administration}}</a></li>
+ <li><a href="?do=Translation">{{lang_administration}}</a></li>
<li class="divider"></li>
<li class="dropdown-header">{{lang_server}}</li>
<li><a href="?do=ServerSetup">{{lang_configurationBasic}}</a></li>
diff --git a/templates/administration/_page.html b/templates/translation/_page.html
index ac24ed71..8e5e4bab 100644
--- a/templates/administration/_page.html
+++ b/templates/translation/_page.html
@@ -7,7 +7,7 @@
<p>{{lang_adminInfo}}</p>
</div>
<ul class="list-group">
- <a href="?do=Admin&page=messages" class="list-group-item active">{{lang_editMessages}}</a>
+ <a href="?do=Translation&page=messages" class="list-group-item active">{{lang_editMessages}}</a>
</ul>
</div>
<div class="panel panel-default">
@@ -24,9 +24,9 @@
{{#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>
+ <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>
@@ -35,6 +35,6 @@
</div>
<script>
function goTo(link){
- window.location.href = "?do=Admin&page=templates&template=" + link;
+ window.location.href = "?do=Translation&page=templates&template=" + link;
}
</script>
diff --git a/templates/administration/messages.html b/templates/translation/messages.html
index 7cf042e8..c065c7f7 100644
--- a/templates/administration/messages.html
+++ b/templates/translation/messages.html
@@ -4,9 +4,12 @@
{{lang_messages}}
</div>
<div class="panel-body">
- <p>{{lang_templateMessagesHelp}}
+ <p>{{lang_templateMessagesHelp}}</p>
+ <div class="alert alert-info">
+ {{lang_templateHint}}
+ </div>
</div>
- <form action="?do=Admin" method="post">
+ <form action="?do=Translation" method="post">
<table class="table table-hover">
<thead>
<tr>
@@ -31,7 +34,7 @@
<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=Admin&template=messages&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a>
+ <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}}
@@ -40,15 +43,15 @@
</tbody>
</table>
<div class="panel-body">
- <a class="btn btn-primary" href='?do=Admin' >{{lang_back}}</a>
+ <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_update}}">
+ <input type="submit" class="btn btn-primary" value="{{lang_save}}">
</form>
</div>
- <form action="?do=Admin" method="post">
+ <form action="?do=Translation" method="post">
<table class="table table-hover">
<thead>
<tr>
@@ -73,7 +76,7 @@
<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=Admin&template=messages-hardcoded&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a>
+ <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}}
@@ -82,12 +85,12 @@
</tbody>
</table>
<div class="panel-body">
- <a class="btn btn-primary" href='?do=Admin' >{{lang_back}}</a>
+ <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_update}}">
+ <input type="submit" class="btn btn-primary" value="{{lang_save}}">
</form>
</div>
</div>
diff --git a/templates/administration/template.html b/templates/translation/template.html
index 5a89bb3d..11d4e4e7 100644
--- a/templates/administration/template.html
+++ b/templates/translation/template.html
@@ -4,8 +4,11 @@
{{template}}
</div>
<div class="panel-body">
- <p>{{lang_templateAdminHelp}}
- <form action="?do=Admin" method="post">
+ <p>{{lang_templateAdminHelp}}</p>
+ <div class="alert alert-info">
+ {{lang_templateHint}}
+ </div>
+ <form action="?do=Translation" method="post">
<table class="table table-hover">
<thead>
<tr>
@@ -30,7 +33,7 @@
<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=Admin&template={{path}}&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a>
+ <a class="btn btn-danger btn-xs" href="?do=Translation&template={{template}}&delete={{tag}}"><span class="glyphicon glyphicon-remove"></span> {{lang_deleteTAG}}</a>
</td>
</tr>
{{/tags}}
@@ -38,12 +41,12 @@
</tr>
</tbody>
</table>
- <a class="btn btn-primary" href='?do=Admin' >{{lang_back}}</a>
+ <a class="btn btn-primary" href='?do=Translation' >{{lang_back}}</a>
<button class="btn btn-primary" type="button" onclick="addTag(true);" >{{lang_createTag}}</button>
<input type="hidden" name="update" value="true">
- <input type="hidden" name="path" value="{{path}}">
+ <input type="hidden" name="path" value="{{template}}">
<input type="hidden" name="token" value="{{token}}">
- <input type="submit" class="btn btn-primary" value="{{lang_update}}">
+ <input type="submit" class="btn btn-primary" value="{{lang_save}}">
</form>
</div>
</div>