diff options
author | Simon Rettberg | 2016-05-10 16:57:06 +0200 |
---|---|---|
committer | Simon Rettberg | 2016-05-10 16:57:06 +0200 |
commit | 2fa2bb665d8ca5e837147f85267f865f1b8b0503 (patch) | |
tree | b2e49bb825e1cc421597a681351d04b97c91834c | |
parent | Message string editing works now (diff) | |
download | slx-admin-2fa2bb665d8ca5e837147f85267f865f1b8b0503.tar.gz slx-admin-2fa2bb665d8ca5e837147f85267f865f1b8b0503.tar.xz slx-admin-2fa2bb665d8ca5e837147f85267f865f1b8b0503.zip |
Translating module strings and custom sections works
54 files changed, 490 insertions, 588 deletions
diff --git a/config.php.example b/config.php.example index fcab800a..eece978d 100644 --- a/config.php.example +++ b/config.php.example @@ -25,3 +25,11 @@ define('CONFIG_IPXE_DIR', '/opt/openslx/ipxe'); define('CONFIG_VMSTORE_DIR', '/srv/openslx/nfs'); define('CONFIG_PROXY_CONF', '/opt/openslx/proxy/config'); + +// Sort order for menu +$MENU_CAT_SORT_ORDER = array('main.content' => 0, 'main.settings' => 1, 'main.status' => 2, 'main.users' => 3); +$MENU_SETTING_SORT_ORDER = array( + 'news' => 0, 'sysconfig' => 1, 'baseconfig' => 2, 'locations' => 3, // main.content + 'serversetup' => 0, 'internetaccess' => 1, 'vmstore' => 2, 'webinterface' => 3, 'backup' => 4, // main.settings + 'systemstatus' => 0, 'eventlog' => 1, 'syslog' => 2, 'statistics' => 3 // main.status +);
\ No newline at end of file diff --git a/inc/dashboard.inc.php b/inc/dashboard.inc.php index ef8be110..13d713bb 100644 --- a/inc/dashboard.inc.php +++ b/inc/dashboard.inc.php @@ -7,32 +7,48 @@ class Dashboard public static function createMenu() { - $modulesAssoc = array(); + global $MENU_SETTING_SORT_ORDER, $MENU_CAT_SORT_ORDER; + $modByCategory = array(); $all = Module::getEnabled(); foreach ($all as $module) { $cat = $module->getCategory(); if ($cat === false) continue; - $modulesAssoc[$cat][] = $module; + $modByCategory[$cat][] = $module; } - $modulesArray = array(); - foreach ($modulesAssoc as $id => $list) { - $momomo = array(); - foreach ($list as $module) { - $momomo[] = array( + $categories = array(); + $catSort = array(); + foreach ($modByCategory as $catId => $modList) { + $modules = array(); + $sectionSort = array(); + foreach ($modList as $module) { + $modId = $module->getIdentifier(); + $modules[] = array( 'displayName' => $module->getDisplayName(), 'identifier' => $module->getIdentifier(), 'className' => ($module->getIdentifier() === Page::getModule()->getIdentifier()) ? 'active' : '' ); + if (isset($MENU_SETTING_SORT_ORDER[$modId])) { + $sectionSort[] = (string)($MENU_SETTING_SORT_ORDER[$modId] + 1000); + } else { + $sectionSort[] = '9999' . $modId; + } } - $modulesArray[] = array( - 'icon' => self::getCategoryIcon($id), - 'displayName' => Dictionary::getCategoryName($id), - 'modules' => $momomo + array_multisort($sectionSort, SORT_ASC, $modules); + $categories[] = array( + 'icon' => self::getCategoryIcon($catId), + 'displayName' => Dictionary::getCategoryName($catId), + 'modules' => $modules ); + if (isset($MENU_CAT_SORT_ORDER[$catId])) { + $catSort[] = (string)($MENU_CAT_SORT_ORDER[$catId] + 1000); + } else { + $catSort[] = '9999' . $catId; + } } + array_multisort($catSort, SORT_ASC, $categories); Render::setDashboard(array( - 'categories' => $modulesArray, + 'categories' => $categories, 'url' => urlencode($_SERVER['REQUEST_URI']), 'langs' => Dictionary::getLanguages(true), 'dbupdate' => Database::needSchemaUpdate(), diff --git a/inc/dictionary.inc.php b/inc/dictionary.inc.php index 72139601..0dafe9d9 100644 --- a/inc/dictionary.inc.php +++ b/inc/dictionary.inc.php @@ -68,13 +68,26 @@ class Dictionary return self::$stringCache[$file] = $json; } - public static function translate($module, $path, $string) + public static function translateFileModule($moduleId, $path, $tag) { - $strings = self::getArray($module, $path); - if (!isset($strings[$string])) { + $strings = self::getArray($moduleId, $path); + if (!isset($strings[$tag])) { return false; } - return $strings[$string]; + return $strings[$tag]; + } + + public static function translateFile($path, $tag) + { + return self::translateFileModule(Page::getModule()->getIdentifier(), $path, $tag); + } + + public static function translate($tag) + { + $string = self::translateFile('module', $tag); + if ($string !== false) + return $string; + return self::translateFileModule('main', 'global-tags', $tag); } public static function getMessage($id) @@ -82,7 +95,7 @@ class Dictionary if (!preg_match('/^(\w+)\.(.+)$/', $id, $out)) { return 'Invalid Message ID format: ' . $id; } - $string = self::translate($out[1], 'messages', $out[2]); + $string = self::translateFileModule($out[1], 'messages', $out[2]); if ($string === false) { return "($id) ({{0}}, {{1}}, {{2}}, {{3}})"; } @@ -97,15 +110,16 @@ class Dictionary if (!preg_match('/^(\w+)\.(\w+)$/', $category, $out)) { return 'Invalid Category ID format: ' . $category; } - $string = self::translate($out[1], 'categories', $out[2]); + $string = self::translateFileModule($out[1], 'categories', $out[2]); if ($string === false) { - return '!!' . $category . '!!'; + return "!!{$category}!!"; } return $string; } /** - * Get all supported languages as array + * Get all supported languages as array. + * * @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 diff --git a/inc/module.inc.php b/inc/module.inc.php index 292c744a..261c2990 100644 --- a/inc/module.inc.php +++ b/inc/module.inc.php @@ -156,7 +156,7 @@ class Module public function getDisplayName() { - $string = Dictionary::translate($this->name, 'module', 'module_name'); + $string = Dictionary::translateFileModule($this->name, 'module', 'module_name'); if ($string === false) { return '!!' . $this->name . '!!'; } @@ -165,7 +165,7 @@ class Module public function getPageTitle() { - return Dictionary::translate($this->name, 'module', 'page_title'); + return Dictionary::translateFileModule($this->name, 'module', 'page_title'); } public function getCategory() @@ -177,18 +177,5 @@ class Module { return Dictionary::getCategoryName($this->category); } - - public function translate($tag, $section = 'module') - { - $string = Dictionary::translate($this->name, $section, $tag); - if ($string === false) { - $string = Dictionary::translate('core', $section, $tag); - } - if ($string === false) { - error_log('Translation not found. Module: ' . $this->name . ', section: ' . $section . ', tag: ' . $tag); - $string = '!!' . $tag . '!!'; - } - return $string; - } } diff --git a/inc/render.inc.php b/inc/render.inc.php index 6a2872f7..e3a23f23 100644 --- a/inc/render.inc.php +++ b/inc/render.inc.php @@ -191,7 +191,7 @@ class Render // Add untranslated strings to the dictionary, so their tag is seen in the rendered page if ($fallback === false && empty($dictionary[$tag])) { $fallback = true; // Fallback to general dictionary of module - $dictionary = $dictionary + Dictionary::getArray('main', 'global-template-tags'); + $dictionary = $dictionary + Dictionary::getArray('main', 'global-tags'); } if (empty($dictionary[$tag])) { $dictionary[$tag] = '{{' . $tag . '}}'; @@ -52,11 +52,6 @@ abstract class Page self::$instance->doAjax(); } - public static function translate($tag, $section = 'module') - { - return self::$module->translate($tag, $section); - } - public static function getModule() { return self::$module; diff --git a/modules-available/backup/lang/de/messages.json b/modules-available/backup/lang/de/messages.json new file mode 100644 index 00000000..a1237539 --- /dev/null +++ b/modules-available/backup/lang/de/messages.json @@ -0,0 +1,3 @@ +{ + "backup-failed": "Erstellen des Backups fehlgeschlagen" +}
\ No newline at end of file diff --git a/modules-available/backup/lang/de/module.json b/modules-available/backup/lang/de/module.json index a08ad617..8b32a289 100644 --- a/modules-available/backup/lang/de/module.json +++ b/modules-available/backup/lang/de/module.json @@ -1,4 +1,4 @@ { "module_name": "Sichern\/Wiederherstellen", - "page_title": "Sichern und wiederherstellen" + "page_title": "Sichern und Wiederherstellen" }
\ No newline at end of file diff --git a/modules-available/baseconfig/hooks/translation.inc.php b/modules-available/baseconfig/hooks/translation.inc.php index 84a6d33a..4f2cd8f7 100644 --- a/modules-available/baseconfig/hooks/translation.inc.php +++ b/modules-available/baseconfig/hooks/translation.inc.php @@ -6,7 +6,7 @@ $HANDLER = array(); * List of valid subsections */ $HANDLER['subsections'] = array( - 'categories', 'settings' + 'config-variable-categories', 'config-variables' ); /* @@ -17,11 +17,11 @@ $HANDLER['subsections'] = array( /** * Configuration categories */ -$HANDLER['grep']['categories'] = function($module) { +$HANDLER['grep_config-variable-categories'] = function($module) { $want = array(); $res = Database::simpleQuery("SELECT catid FROM cat_setting ORDER BY catid ASC"); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $want[] = 'cat_' . $row['catid']; + $want['cat_' . $row['catid']] = true; } return $want; }; @@ -29,11 +29,11 @@ $HANDLER['grep']['categories'] = function($module) { /** * Configuration variables */ -$HANDLER['grep']['settings'] = function($module) { +$HANDLER['grep_config-variables'] = function($module) { $want = array(); $res = Database::simpleQuery("SELECT setting FROM setting ORDER BY setting ASC"); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $want[] = $row['setting']; + $want[$row['setting']] = true; } return $want; }; diff --git a/modules-available/baseconfig/lang/de/cat_setting.json b/modules-available/baseconfig/lang/de/config-variable-categories.json index b8cb6935..b8cb6935 100644 --- a/modules-available/baseconfig/lang/de/cat_setting.json +++ b/modules-available/baseconfig/lang/de/config-variable-categories.json diff --git a/modules-available/baseconfig/lang/de/setting.json b/modules-available/baseconfig/lang/de/config-variables.json index af1007be..af1007be 100644 --- a/modules-available/baseconfig/lang/de/setting.json +++ b/modules-available/baseconfig/lang/de/config-variables.json diff --git a/modules-available/baseconfig/lang/de/module.json b/modules-available/baseconfig/lang/de/module.json new file mode 100644 index 00000000..461bebdb --- /dev/null +++ b/modules-available/baseconfig/lang/de/module.json @@ -0,0 +1,3 @@ +{ + "module_name": "KonfigurationsVariablen" +}
\ No newline at end of file diff --git a/modules-available/baseconfig/lang/en/cat_setting.json b/modules-available/baseconfig/lang/en/config-variable-categories.json index 7c0ab654..7c0ab654 100644 --- a/modules-available/baseconfig/lang/en/cat_setting.json +++ b/modules-available/baseconfig/lang/en/config-variable-categories.json diff --git a/modules-available/baseconfig/lang/en/setting.json b/modules-available/baseconfig/lang/en/config-variables.json index 36ac6e8c..36ac6e8c 100644 --- a/modules-available/baseconfig/lang/en/setting.json +++ b/modules-available/baseconfig/lang/en/config-variables.json diff --git a/lang/pt/settings/cat_setting.json b/modules-available/baseconfig/lang/pt/config-variable-categories.json index b04839e8..b04839e8 100644 --- a/lang/pt/settings/cat_setting.json +++ b/modules-available/baseconfig/lang/pt/config-variable-categories.json diff --git a/lang/pt/settings/setting.json b/modules-available/baseconfig/lang/pt/config-variables.json index 66ec3b1c..66ec3b1c 100644 --- a/lang/pt/settings/setting.json +++ b/modules-available/baseconfig/lang/pt/config-variables.json diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php index 8f914376..e741dd2e 100644 --- a/modules-available/baseconfig/page.inc.php +++ b/modules-available/baseconfig/page.inc.php @@ -82,12 +82,12 @@ class Page_BaseConfig extends Page LEFT JOIN setting_global AS tbl USING (setting) ORDER BY cat_setting.sortval ASC, setting.setting ASC'); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $row['description'] = Util::markup(Page::translate($row['setting'], 'setting')); + $row['description'] = Util::markup(Dictionary::translateFile('config-variables', $row['setting'])); if (is_null($row['displayvalue'])) $row['displayvalue'] = $row['defaultvalue']; $row['item'] = $this->makeInput($row['validator'], $row['setting'], $row['displayvalue']); $settings[$row['catid']]['settings'][] = $row; if (!isset($settings[$row['catid']]['category_id'])) { - $settings[$row['catid']]['category_name'] = Page::translate('cat_' . $row['catid'], 'cat_setting'); + $settings[$row['catid']]['category_name'] = Dictionary::translateFile('config-variable-categories', 'cat_' . $row['catid']); $settings[$row['catid']]['category_id'] = $row['catid']; } } diff --git a/modules-available/baseconfig/templates/_page.html b/modules-available/baseconfig/templates/_page.html index 273ee50c..da155ad2 100644 --- a/modules-available/baseconfig/templates/_page.html +++ b/modules-available/baseconfig/templates/_page.html @@ -17,14 +17,11 @@ {{#settings}} <div class="list-group-item {{class}}"> <div class="row"> - <div class="col-md-1" style="width:118px;"> - <input type="checkbox" name="switch[{{setting}}]" {{checked}}> - </div> - <div class="col-md-4"> + <div class="col-md-5"> {{setting}} <div class="slx-default">{{defaultvalue}}</div> </div> - <div class="col-md-4"> + <div class="col-md-5"> {{{item}}} </div> <div class="col-md-2"> diff --git a/modules-available/dozmod/lang/de/module.json b/modules-available/dozmod/lang/de/module.json new file mode 100644 index 00000000..fd4c6aff --- /dev/null +++ b/modules-available/dozmod/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "Dozentenmodul", + "page_title": "Verwalten des Dozentenmoduls" +}
\ No newline at end of file diff --git a/modules-available/eventlog/lang/de/module.json b/modules-available/eventlog/lang/de/module.json new file mode 100644 index 00000000..8217fc02 --- /dev/null +++ b/modules-available/eventlog/lang/de/module.json @@ -0,0 +1,3 @@ +{ + "module_name": "Server-Log" +}
\ No newline at end of file diff --git a/modules-available/eventlog/lang/en/module.json b/modules-available/eventlog/lang/en/module.json index bf1d01f0..0fc536f3 100644 --- a/modules-available/eventlog/lang/en/module.json +++ b/modules-available/eventlog/lang/en/module.json @@ -1,3 +1,3 @@ { - "module_name": "Client Log" + "module_name": "Server Log" }
\ No newline at end of file diff --git a/modules-available/locations/lang/de/module.json b/modules-available/locations/lang/de/module.json new file mode 100644 index 00000000..b38fa89c --- /dev/null +++ b/modules-available/locations/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "R\u00e4ume\/Orte", + "page_title": "R\u00e4ume und Orte verwalten" +}
\ No newline at end of file diff --git a/modules-available/main/hooks/translation.inc.php b/modules-available/main/hooks/translation.inc.php new file mode 100644 index 00000000..8c0e4b51 --- /dev/null +++ b/modules-available/main/hooks/translation.inc.php @@ -0,0 +1,30 @@ +<?php + +$HANDLER = array(); + +/** + * List of valid subsections + */ +$HANDLER['subsections'] = array( + 'categories' +); + +/* + * Handlers for the subsections that will return an array of expected tags. + * This is optional, if you don't want to define expected tags, don't create a function. + */ + +/** + * Configuration categories + */ +$HANDLER['grep_categories'] = function($module) { + $skip = strlen($module->getIdentifier()) + 1; + $want = array(); + foreach (Module::getAll() as $module) { + $cat = $module->getCategory(); + if (is_string($cat)) { + $want[substr($cat, $skip)] = true; + } + } + return $want; +}; diff --git a/modules-available/main/lang/de/categories.json b/modules-available/main/lang/de/categories.json new file mode 100644 index 00000000..3d9b50a3 --- /dev/null +++ b/modules-available/main/lang/de/categories.json @@ -0,0 +1,6 @@ +{ + "content": "Inhalt", + "settings": "Einstellungen", + "status": "Status", + "users": "Benutzer" +}
\ No newline at end of file diff --git a/modules-available/main/lang/de/template-tags.json b/modules-available/main/lang/de/template-tags.json index d31fb64d..e9b829e8 100644 --- a/modules-available/main/lang/de/template-tags.json +++ b/modules-available/main/lang/de/template-tags.json @@ -1,35 +1,24 @@ { "lang_bootMenuWarning": "Das Bootmen\u00fc ist veraltet oder wurde noch nicht generiert.", - "lang_configurationBasic": "PXE\/Boot", - "lang_configurationVariables": "KonfigurationsVariablen", "lang_configure": "Konfigurieren", - "lang_dozmod": "Dozentenmodul", - "lang_eventLog": "Server Log", - "lang_internetAccess": "Internetzugriff", "lang_intro": "Dies ist die bwLehrpool Konfigurationsoberfl\u00e4che.", "lang_introGuest": "Dies ist das Administrations-Interface der lokalen bwLehrpool-Installation. Bitte authentifizieren Sie sich, um Einstellungen vorzunehmen.", "lang_language": "Sprachen", - "lang_localization": "Lokalisierung + Integration", - "lang_locations": "R\u00e4ume\/Orte", + "lang_loggedInPrefix": "Angemeldet als", + "lang_loggedInSuffix": " ", "lang_login": "Anmelden", "lang_logout": "Abmelden", "lang_minilinuxMissing": "Wichtige Dateien der MiniLinux-Installation fehlen.", "lang_needsSetup": "Einrichtung unvollst\u00e4ndig", - "lang_news": "vmChooser News", "lang_next": "Weiter", "lang_noExistingAccount": "Es existiert noch kein Administrator-Zugang f\u00fcr diesen Satelliten-Server.", "lang_numerOfImagesMarkedForDeletion": "Zur L\u00f6schung markierte Abbilder", "lang_register": "Registrieren", - "lang_server": "Server", - "lang_serverStatus": "Server Status", - "lang_settings": "Einstellungen", - "lang_status": "Status", "lang_systemConfiguration": "Systemkonfiguration", "lang_systemConfigurationNotChosen": "Es wurde noch keine Systemkonfiguration ausgew\u00e4hlt.", + "lang_toggleNavigation": "Navigation ein\/ausblenden", "lang_translations": "\u00dcbersetzungen", - "lang_vmLocation": "VM Speicherort", "lang_vmLocationNotSet": "Es ist noch kein Speicherort f\u00fcr die Virtuellen Maschinen festgelegt.", "lang_warning": "Warnung", - "lang_webInterface": "Web-Schnittstelle", "lang_welcome": "Willkommen" }
\ No newline at end of file diff --git a/modules-available/main/lang/en/template-tags.json b/modules-available/main/lang/en/template-tags.json index f368e8b8..3483bcfe 100644 --- a/modules-available/main/lang/en/template-tags.json +++ b/modules-available/main/lang/en/template-tags.json @@ -1,41 +1,24 @@ { - "lang_backup": "Backup\/Restore", "lang_bootMenuWarning": "The boot menu is outdated or has not been generated.", - "lang_client": "Client", - "lang_clientLog": "Client Log", - "lang_clientStats": "Client statistics", - "lang_configurationBasic": "PXE\/Boot", - "lang_configurationVariables": "Configuration Variables", "lang_configure": "Configure", - "lang_dozmod": "Tutor module", - "lang_eventLog": "Server Log", - "lang_internetAccess": "Internet access", "lang_intro": "This is the bwLehrpool configuration interface.", "lang_introGuest": "This is the administration interface of the local bwLehrpool intallation. Please authenticate yourself to adjust settings.", "lang_language": "Language", - "lang_localization": "Localization", - "lang_locations": "Rooms\/Locations", "lang_loggedInPrefix": "Logged in as", "lang_loggedInSuffix": " ", "lang_login": "Login", "lang_logout": "Logout", "lang_minilinuxMissing": "Important files from the mini Linux installation are missing.", "lang_needsSetup": "Setup incomplete", - "lang_news": "vmChooser news", "lang_next": "Next", "lang_noExistingAccount": "No account has been created yet. Sign up to become the administrator.", "lang_numerOfImagesMarkedForDeletion": "Images marked for deletion", "lang_register": "Register", - "lang_server": "Server", - "lang_serverStatus": "Server status", - "lang_settings": "Settings", - "lang_status": "Status", "lang_systemConfiguration": "System Configuration", "lang_systemConfigurationNotChosen": "A system configuration has not been chosen yet.", + "lang_toggleNavigation": "toggle navigation", "lang_translations": "Translations", - "lang_vmLocation": "VM Location", "lang_vmLocationNotSet": "A location for the virtual machine is not set yet.", "lang_warning": "Warning", - "lang_webInterface": "Web interface", "lang_welcome": "Welcome" }
\ No newline at end of file diff --git a/modules-available/main/lang/pt/categories.json b/modules-available/main/lang/pt/categories.json new file mode 100644 index 00000000..4b6ed82f --- /dev/null +++ b/modules-available/main/lang/pt/categories.json @@ -0,0 +1,6 @@ +{ + "content": "Conte\u00fado", + "settings": "Configura\u00e7\u00f5es", + "status": "Status", + "users": "Usu\u00e1rios" +} diff --git a/modules-available/main/page.inc.php b/modules-available/main/page.inc.php index 369d4b54..0a9acd81 100644 --- a/modules-available/main/page.inc.php +++ b/modules-available/main/page.inc.php @@ -25,8 +25,6 @@ class Page_Main extends Page protected function doRender() { - // Render::setTitle('abc'); - if (!User::isLoggedIn()) { Render::addTemplate('page-main-guest', array( 'register' => (Database::queryFirst('SELECT userid FROM user LIMIT 1') === false) diff --git a/modules-available/main/templates/page-login.html b/modules-available/main/templates/page-login.html deleted file mode 100644 index 247e9a55..00000000 --- a/modules-available/main/templates/page-login.html +++ /dev/null @@ -1,11 +0,0 @@ -<form class="form-signin" action="?do=Session" method="post"> - <h2 class="form-signin-heading">{{lang_enter}}</h2> - <input type="text" name="user" class="form-control" placeholder="{{lang_username}}" autofocus> - <input type="password" name="pass" class="form-control" placeholder="{{lang_password}}"> - <!--label class="checkbox"> - <input type="checkbox" name="remember" value="remember-me"> {{lang_rememberID}} - </label--> - <button class="btn btn-lg btn-primary btn-block" type="submit">{{lang_login}}</button> - <a class="btn btn-lg btn-primary btn-block" href="?do=AddUser">{{lang_register}}</a> - <input type="hidden" name="action" value="login"> -</form>
\ No newline at end of file diff --git a/modules-available/main/templates/page-minilinux.html b/modules-available/main/templates/page-minilinux.html deleted file mode 100644 index dc13e6b0..00000000 --- a/modules-available/main/templates/page-minilinux.html +++ /dev/null @@ -1,14 +0,0 @@ -<div id="systemlist"> - <div class="panel panel-default">{{lang_listObtained}}</div> -</div> - -<script type="text/javascript"><!-- - function loadSystemList(version) { - $('#systemlist').load('{{{listurl}}}', { token: TOKEN, version: version }, function( response, status, xhr ) { - if ( status === "error" ) { - var msg = "{{lang_errorGetting}}"; - $( "#systemlist" ).html( msg + xhr.status + " " + xhr.statusText ); - } - }); - } -// --></script>
\ No newline at end of file diff --git a/modules-available/main/templates/page-news.html b/modules-available/main/templates/page-news.html deleted file mode 100644 index 8e400498..00000000 --- a/modules-available/main/templates/page-news.html +++ /dev/null @@ -1,57 +0,0 @@ -<div class="panel panel-default"> - <div class="panel-heading"> - {{lang_editNews}} - </div> - <div class="panel-body"> - <p>{{lang_newsIntro}}</p> - <form action="?do=News&action=save" method="post"> - <div class="form-group"> - <label for="news-title-id">{{lang_title}}</label> - <input type="text" name="news-title" id ="news-title-id" class="form-control" placeholder="{{welcome}}" value="{{latestTitle}}"> - </div> - <div class="form-group"> - <label for="news-content-id">{{lang_content}}</label> - <textarea name="news-content" id ="news-content-id" class="form-control" rows="5" cols="30" placeholder="">{{latestContent}}</textarea> - </div> - <p>{{lang_latestUpdate}}: {{latestDate}}</p> - <button class="btn btn-primary btn-sm" type="submit">{{lang_save}}</button> - <input type="hidden" name="token" value="{{token}}"> - </form> - </div> -</div> - -<div class="panel panel-default"> - <div class="panel-heading"> - {{lang_newsOld}} - </div> - <div class="panel-body"> - <div class="table-responsive"> - <form method="post" action="?do=News&action=delete"> - <input type="hidden" name="token" value="{{token}}"> - <table class="table table-stripped table-condensed"> - <thead> - <tr> - <th>{{lang_date}}</th> - <th>{{lang_title}}</th> - <th>{{lang_content}}</th> - <th></th> - </tr> - </thead> - <tbody> - {{#list}} - <tr {{#active}}class="active"{{/active}}> - <td class="text-left nowrap">{{date}}</td> - <td class="slx-ellipsis">{{title}}</td> - <td class="slx-ellipsis">{{content}}</td> - <td> - <a class="btn btn-primary btn-xs" href="?do=news&newsid={{newsid}}&action=show"><span class="glyphicon glyphicon-share-alt"></span> {{lang_show}}</a> - <button class="btn btn-danger btn-xs" type="submit" name="newsid" value="{{newsid}}"><span class="glyphicon glyphicon-remove"></span> {{lang_delete}}</button> - </td> - </tr> - {{/list}} - </tbody> - </table> - </form> - </div> - </div> -</div> diff --git a/modules-available/main/templates/page-syslog.html b/modules-available/main/templates/page-syslog.html deleted file mode 100644 index 98e94291..00000000 --- a/modules-available/main/templates/page-syslog.html +++ /dev/null @@ -1,58 +0,0 @@ -<h1>{{lang_clientLog}}</h1> -<form method="post" action="?do=SysLog"> - <input type="hidden" name="token" value="{{token}}"> - <div class="input-group"> - <span class="input-group-addon">{{lang_filter}}</span> - <input id="filterstring" type="text" placeholder="id" value="{{filter}}" name="filter" data-role="tagsinput" /> - <span class="input-group-addon"> - <input type="checkbox" name="not" {{#not}}checked="checked"{{/not}}> {{lang_not}} - </span> - <span class="input-group-btn"> - <button class="btn btn-default" type="submit">{{lang_go}}</button> - </span> - </div> -</form> -{{{pagenav}}} -<table class="table table-striped table-condensed"> - <thead> - <th width="1"></th> - <th>{{lang_when}}</th> - <th>{{lang_client}}</th> - <th>{{lang_event}}</th> - <th width="1">{{lang_details}}</th> - </thead> - <tbody> - {{#list}} - <tr> - <td><span class="glyphicon {{icon}}" title="{{logtypeid}}" onclick="$('#filterstring').tagsinput('add', '{{logtypeid}}')"></span></td> - <td class="text-right" nowrap="nowrap">{{date}}</td> - <td>{{clientip}}</td> - <td>{{description}}</td> - <td>{{#extra}} - <a class="btn btn-default btn-xs pull-left" onclick="$('#details-body').html($('#extra-{{logid}}').html())" data-toggle="modal" data-target="#myModal">»</a> - <div class="hidden" id="extra-{{logid}}">{{extra}}</div> - {{/extra}}</td> - </tr> - {{/list}} - </tbody> -</table> -{{{pagenav}}} - -<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> - <div class="modal-dialog modal-lg"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> - <h4 class="modal-title" id="myModalLabel">{{lang_details}}</h4> - </div> - <div class="modal-body"> - <pre id="details-body"></pre> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> - </div> - </div> - </div> -</div> - - diff --git a/modules-available/main/templates/page-vmstore.html b/modules-available/main/templates/page-vmstore.html deleted file mode 100644 index fe2c5225..00000000 --- a/modules-available/main/templates/page-vmstore.html +++ /dev/null @@ -1,111 +0,0 @@ -<form role="form" method="post" action="?do=VmStore"> - <input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="display:none;"> - <input type="password" name="password_fake" id="password_fake" value="" style="display:none;"> - <input type="hidden" name="token" value="{{token}}"> - <input type="hidden" name="action" value="setstore"> - <div class="panel panel-default"> - <div class="panel-heading"> - {{lang_vmLocation}} <a class="btn btn-default" data-toggle="modal" data-target="#help-store"><span class="glyphicon glyphicon-question-sign"></span></a> - </div> - <div class="panel-body slx-md-width"> - <p>{{lang_vmLocationChoose}}</p> - <div class="panel panel-default"> - <div class="panel-heading"> - <input type="radio" name="storetype" value="internal" {{pre-internal}}> {{lang_intern}} - </div> - <div class="panel-body"> - {{lang_noAdditionalInformation}} - </div> - </div> - <div class="panel panel-default"> - <div class="panel-heading"> - <input type="radio" name="storetype" value="nfs" {{pre-nfs}}> NFS - <a class="btn btn-default btn-sm" data-toggle="modal" data-target="#help-nfs"><span class="glyphicon glyphicon-question-sign"></span></a> - </div> - <div class="panel-body"> - <label for="nfsaddr">NFS-Export</label> - <input type="text" class="form-control" name="nfsaddr" value="{{nfsaddr}}" placeholder="1.2.3.4:/export/bwlp" id="nfsaddr"> - </div> - </div> - <div class="panel panel-default"> - <div class="panel-heading"> - <input type="radio" name="storetype" value="cifs" {{pre-cifs}}> CIFS - </div> - <div class="panel-body"> - <label for="cifsaddr">UNC-Pfad</label> - <input type="text" class="form-control" name="cifsaddr" value="{{cifsaddr}}" placeholder="\\samba.server.example.com\bwlp" id="cifsaddr"> - <br> - <label for="cifsuser">{{lang_readWrite}}</label> - <div class="input-group"> - <span class="input-group-addon slx-ga"> - {{lang_username}} - </span> - <input type="text" class="form-control" name="cifsuser" value="{{cifsuser}}" placeholder="{{lang_username}}" id="cifsuser"> - <span class="input-group-addon"> - {{lang_password}} - </span> - <input type="{{password_type}}" class="form-control" name="cifspasswd" value="{{cifspasswd}}" placeholder="{{lang_password}}"> - </div> - <br> - <label for="cifsuserro">{{lang_readOnly}}</label> - <div class="input-group"> - <span class="input-group-addon slx-ga"> - {{lang_username}} - </span> - <input type="text" class="form-control" name="cifsuserro" value="{{cifsuserro}}" placeholder="{{lang_username}}" id="cifsuserro"> - <span class="input-group-addon"> - {{lang_password}} - </span> - <input type="{{password_type}}" class="form-control" name="cifspasswdro" value="{{cifspasswdro}}" placeholder="{{lang_password}}"> - </div> - </div> - </div> - <button class="btn btn-primary" type="submit">{{lang_save}}</button> - </div> - </div> -</form> - -<div class="modal fade" id="help-store" tabindex="-1" role="dialog"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header">{{lang_vmLocation}}</div> - <div class="modal-body"> - <p> - {{lang_vmLocationHelp1}} - </p> - <p> - {{lang_vmLocationHelp2}} - </p> - <p> - {{lang_vmLocationHelp3}} - </p> - </div> - <div class="modal-footer"><a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a></div> - </div> - </div> -</div> - -<div class="modal fade" id="help-nfs" tabindex="-1" role="dialog"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header">NFS</div> - <div class="modal-body"> - <p> - {{lang_nfsHelp1}} - </p> - <pre> -/mnt/images 1.2.3.4(rw,no_root_squash,async) -/mnt/images *(ro,async,nolock) - </pre> - <p> - {{lang_nfsHelp2}} - </p> - <pre> -/mnt/images 1.2.3.4(rw,all_squash,anon_uid=1234,async) -/mnt/images *(ro,async,nolock) - </pre> - </div> - <div class="modal-footer"><a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a></div> - </div> - </div> -</div> diff --git a/modules-available/minilinux/lang/de/module.json b/modules-available/minilinux/lang/de/module.json new file mode 100644 index 00000000..e5284ac0 --- /dev/null +++ b/modules-available/minilinux/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "bwLehrpool MiniLinux", + "page_title": "MiniLinux verwalten und aktualisieren" +}
\ No newline at end of file diff --git a/modules-available/news/lang/de/module.json b/modules-available/news/lang/de/module.json new file mode 100644 index 00000000..f44a64e5 --- /dev/null +++ b/modules-available/news/lang/de/module.json @@ -0,0 +1,3 @@ +{ + "module_name": "vmChooser News" +}
\ No newline at end of file diff --git a/modules-available/serversetup/lang/de/module.json b/modules-available/serversetup/lang/de/module.json new file mode 100644 index 00000000..eb777343 --- /dev/null +++ b/modules-available/serversetup/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "PXE\/Boot", + "page_title": "PXE- und Boot-Einstellungen" +}
\ No newline at end of file diff --git a/modules-available/support/lang/de/module.json b/modules-available/support/lang/de/module.json new file mode 100644 index 00000000..13b2b8f0 --- /dev/null +++ b/modules-available/support/lang/de/module.json @@ -0,0 +1,3 @@ +{ + "module_name": "Support" +}
\ No newline at end of file diff --git a/modules-available/sysconfig/lang/de/module.json b/modules-available/sysconfig/lang/de/module.json new file mode 100644 index 00000000..dfd47099 --- /dev/null +++ b/modules-available/sysconfig/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "Lokalisierung + Integration", + "page_title": "Lokalisierung + Integration" +}
\ No newline at end of file diff --git a/modules-available/sysconfig/lang/en/module.json b/modules-available/sysconfig/lang/en/module.json index f6454e24..9125fb13 100644 --- a/modules-available/sysconfig/lang/en/module.json +++ b/modules-available/sysconfig/lang/en/module.json @@ -1,3 +1,4 @@ { - "module_name": "Modules" + "module_name": "Localization", + "page_title": "Localize and integrate" }
\ No newline at end of file diff --git a/modules-available/syslog/lang/en/module.json b/modules-available/syslog/lang/en/module.json index 0fc536f3..bbe80ee1 100644 --- a/modules-available/syslog/lang/en/module.json +++ b/modules-available/syslog/lang/en/module.json @@ -1,3 +1,4 @@ { - "module_name": "Server Log" + "module_name": "Client Log", + "page_title": "Log messages \u2013 Clients" }
\ No newline at end of file diff --git a/modules-available/systemstatus/lang/de/module.json b/modules-available/systemstatus/lang/de/module.json new file mode 100644 index 00000000..e69c3fb0 --- /dev/null +++ b/modules-available/systemstatus/lang/de/module.json @@ -0,0 +1,3 @@ +{ + "module_name": "System-Status" +}
\ No newline at end of file diff --git a/modules-available/systemstatus/lang/en/module.json b/modules-available/systemstatus/lang/en/module.json index 126d6bb8..bb201773 100644 --- a/modules-available/systemstatus/lang/en/module.json +++ b/modules-available/systemstatus/lang/en/module.json @@ -1,3 +1,3 @@ { - "module_name": "Server" + "module_name": "System Status" }
\ No newline at end of file diff --git a/modules-available/translation/lang/de/messages.json b/modules-available/translation/lang/de/messages.json new file mode 100644 index 00000000..645d678b --- /dev/null +++ b/modules-available/translation/lang/de/messages.json @@ -0,0 +1,3 @@ +{ + "i18n-invalid-lang": "Ung\u00fcltige Sprache: {{0}}" +}
\ No newline at end of file diff --git a/modules-available/translation/lang/de/module.json b/modules-available/translation/lang/de/module.json new file mode 100644 index 00000000..c3bf2f78 --- /dev/null +++ b/modules-available/translation/lang/de/module.json @@ -0,0 +1,3 @@ +{ + "module_name": "\u00dcbersetzungen" +}
\ No newline at end of file diff --git a/modules-available/translation/lang/de/template-tags.json b/modules-available/translation/lang/de/template-tags.json index f84bb0af..613a8fa1 100644 --- a/modules-available/translation/lang/de/template-tags.json +++ b/modules-available/translation/lang/de/template-tags.json @@ -9,9 +9,13 @@ "lang_editModules": "Modul bearbeiten", "lang_editSettings": "Einstellungstexte bearbeiten", "lang_editTemplates": "Template-Texte bearbeiten", + "lang_hint": "Hinweis", "lang_langAdministration": "Templates", - "lang_missing": "Fehlt", + "lang_mainHeading": "\u00dcbersetzungen verwalten", + "lang_messages": "Benachrichtigungen", + "lang_missing": "Fehlend", "lang_module": "Modul", + "lang_otherStrings": "Andere Texte", "lang_sample": "Beispiel", "lang_save": "Speichern", "lang_status": "Status", @@ -21,5 +25,6 @@ "lang_templateHint": "Hinweis: Gelbe Linie zeigt eine \u00dcbersetzung fehlt und roten Linien zeigen ein Tag wird nicht von das Template verwendet.", "lang_templates": "Templates", "lang_translation": "\u00dcbersetzung", - "lang_unused": "Ungenutzt" + "lang_unused": "Ungenutzt", + "lang_unusedUnreliableHint": "Die Erkennung von ungenutzten Tags bezieht nur aktivierte Module mit ein. Es k\u00f6nnte sein, dass ein ungenutzt gemeldeter Tag in einem nicht aktivierten Modul verwendet wird." }
\ No newline at end of file diff --git a/modules-available/translation/lang/en/template-tags.json b/modules-available/translation/lang/en/template-tags.json index 48389f9b..84b3ba26 100644 --- a/modules-available/translation/lang/en/template-tags.json +++ b/modules-available/translation/lang/en/template-tags.json @@ -9,9 +9,13 @@ "lang_editModules": "Edit Module Translations", "lang_editSettings": "Edit configuration variables related strings", "lang_editTemplates": "Edit template strings", + "lang_hint": "Notice", "lang_langAdministration": "Templates", + "lang_mainHeading": "Translation management", + "lang_messages": "Messages", "lang_missing": "Missing", "lang_module": "Module", + "lang_otherStrings": "Other strings", "lang_sample": "Sample", "lang_save": "Save", "lang_status": "Status", @@ -21,5 +25,6 @@ "lang_templateHint": "Hint: Yellow lines indicate a translation is missing and red lines indicate a tag is not being used by the template.", "lang_templates": "Templates", "lang_translation": "Translation", - "lang_unused": "Unused" + "lang_unused": "Unused", + "lang_unusedUnreliableHint": "Detection of unused tags only includes currently activated modules. It's possible that a tag marked \"unused\" is actually refered to in a module not activated." }
\ No newline at end of file diff --git a/modules-available/translation/page.inc.php b/modules-available/translation/page.inc.php index 674756a2..1713efe9 100644 --- a/modules-available/translation/page.inc.php +++ b/modules-available/translation/page.inc.php @@ -42,7 +42,7 @@ class Page_Translation extends Page public function __construct() { - $this->builtInSections = array('template', 'messages', 'custom'); + $this->builtInSections = array('template', 'messages', 'module', 'custom'); } private function isValidSection($section) @@ -159,50 +159,22 @@ class Page_Translation extends Page $this->showMessagesEdit(); return; } + + // Module + if ($this->section === 'module') { + $this->ensureValidDestLanguage(); + $this->showModuleEdit(); + return; + } - //load the page accordingly to the link - switch ($this->section) { - case 'messages': - //renders the message edit page - Render::addTemplate('edit', array( - 'path' => 'messages', - 'langs' => $langs, - 'tags' => $this->loadMessageEditArray() - )); - break; - case 'hardcoded': - //renders the hardcoded messages edit page - Render::addTemplate('edit', array( - 'path' => 'messages-hardcoded', - 'langs' => $langs, - 'tags' => $this->loadHardcodedStringEditArray() - )); - break; - case 'settings': - //renders the settings related edit page - Render::addTemplate('edit', array( - 'path' => 'cat_setting', - 'langs' => $langs, - 'tags' => $this->loadCategoriesArray() - )); - Render::addTemplate('edit', array( - 'path' => 'setting', - 'langs' => $langs, - 'tags' => $this->loadSettingsArray() - )); - break; - case 'config-module': - //renders the hardcoded messages edit page - Render::addTemplate('edit', array( - 'path' => 'config-module', - 'langs' => $langs, - 'tags' => $this->buildTranslationTable('config-module') - )); - break; - default: - //renders main page with selection of what part to edit - Render::addTemplate('_page'); + // Custom + if ($this->section === 'custom') { + $this->ensureValidDestLanguage(); + $this->showCustomEdit(); + return; } + + $this->redirect(); } private function showListOfModules() @@ -237,16 +209,20 @@ class Page_Translation extends Page $this->showModuleTemplates(); // Messages $this->showModuleMessages(); + // Other/hardcoded strings + $this->showModuleStrings(); + // Module specific + $this->showModuleCustom(); } private function showModuleTemplates() { $templateTags = $this->loadUsedTemplateTags(); $data = array('module' => $this->module->getIdentifier()); - $list = array(); + $templateNames = array(); $data['tagcount'] = 0; foreach ($templateTags as $templates) { - $list = array_merge($list, $templates); + $templateNames = array_merge($templateNames, $templates); $data['tagcount']++; } foreach (Dictionary::getLanguages(true) as $lang) { @@ -259,7 +235,7 @@ class Page_Translation extends Page ); } $data['templates'] = array(); - foreach (array_unique($list) as $template) { + foreach (array_unique($templateNames) as $template) { $data['templates'][] = array('template' => $template); } Render::addTemplate('template-list', $data); @@ -269,14 +245,14 @@ class Page_Translation extends Page { $messageTags = $this->loadUsedMessageTags(); $data = array('module' => $this->module->getIdentifier()); - $list = array(); + $phpFiles = array(); $data['messagecount'] = 0; foreach ($messageTags as $templates) { - $list = array_merge($list, array_keys($templates['files'])); + $phpFiles = array_merge($phpFiles, array_keys($templates['files'])); $data['messagecount']++; } foreach (Dictionary::getLanguages(true) as $lang) { - list($missing, $unused) = $this->getModuleTranslationStatus($lang['cc'], 'messages', $messageTags); + list($missing, $unused) = $this->getModuleTranslationStatus($lang['cc'], 'messages', false, $messageTags); $data['langs'][] = array( 'cc' => $lang['cc'], 'name' => $lang['name'], @@ -285,11 +261,57 @@ class Page_Translation extends Page ); } $data['files'] = array(); - foreach (array_unique($list) as $template) { + foreach (array_unique($phpFiles) as $template) { $data['files'][] = array('file' => $template); } Render::addTemplate('message-list', $data); } + + private function showModuleStrings() + { + $moduleTags = $this->loadUsedModuleTags(); + $data = array('module' => $this->module->getIdentifier()); + $data['tagcount'] = count($moduleTags); + foreach (Dictionary::getLanguages(true) as $lang) { + list($missing, $unused) = $this->getModuleTranslationStatus($lang['cc'], 'module', true, $moduleTags); + $data['langs'][] = array( + 'cc' => $lang['cc'], + 'name' => $lang['name'], + 'missing' => $missing, + 'unused' => $unused + ); + } + Render::addTemplate('string-list', $data); + } + + private function showModuleCustom() + { + if ($this->customHandler === false) + return; + foreach ($this->customHandler['subsections'] as $subsection) { + $this->showModuleCustomSubsection($subsection); + } + } + + private function showModuleCustomSubsection($subsection) + { + $moduleTags = $this->loadUsedCustomTags($subsection); + $data = array( + 'subsection' => $subsection, + 'module' => $this->module->getIdentifier(), + 'tagcount' => count($moduleTags), + ); + foreach (Dictionary::getLanguages(true) as $lang) { + list($missing, $unused) = $this->getModuleTranslationStatus($lang['cc'], $subsection, false, $moduleTags); + $data['langs'][] = array( + 'cc' => $lang['cc'], + 'name' => $lang['name'], + 'missing' => $missing, + 'unused' => $unused + ); + } + Render::addTemplate('custom-list', $data); + } private function showTemplateEdit() { @@ -313,10 +335,34 @@ class Page_Translation extends Page )); } + private function showModuleEdit() + { + Render::addTemplate('edit', array( + 'destlang' => $this->destLang, + 'language' => Dictionary::getLanguageName($this->destLang), + 'tags' => $this->loadModuleEditArray(), + 'module' => $this->module->getIdentifier(), + 'section' => $this->section + )); + } + + private function showCustomEdit() + { + Render::addTemplate('edit', array( + 'destlang' => $this->destLang, + 'language' => Dictionary::getLanguageName($this->destLang), + 'tags' => $this->loadCustomEditArray(), + 'module' => $this->module->getIdentifier(), + 'section' => $this->section, + 'subsection' => $this->subsection + )); + } + /** * Get all tags used by templates of the given module. - * @param \Module $module module in question, false to use the one being edited - * @return array index is tag, value is array of templates using that tag + * @param \Module $module module in question, false to use the one being edited. + * + * @return array of array(tag => array of templates using that tag) */ private function loadUsedTemplateTags($module = false) { @@ -368,6 +414,41 @@ class Page_Translation extends Page $this->getModulePhpFiles($module)); return $tags; } + + /** + * Get all module tags used/required. + * + * @param type $module + * @return array of array(tagname => (bool)required) + */ + private function loadUsedModuleTags($module = false) + { + if ($module === false) { + $module = $this->module; + } + $tags = $this->loadTagsFromPhp('/Dictionary\s*::\s*translate\s*\(\s*[\'"](?<tag>[^\'"\.]*)[\'"]\s*\)/i', + $this->getModulePhpFiles($module)); + foreach ($tags as &$tag) { + $tag = true; + } + unset($tag); + // Fixup special tags + if ($module->getCategory() === false) { + unset($tags['module_name']); + unset($tags['page_title']); + } else { + $tags['module_name'] = true; + $tags['page_title'] = false; + } + return $tags; + } + + private function loadUsedCustomTags($subsection) + { + if (!isset($this->customHandler['grep_'.$subsection])) + return array(); + return $this->customHandler['grep_'.$subsection]($this->module); + } private function getTagsFromTemplate($templateFile) { @@ -395,53 +476,49 @@ class Page_Translation extends Page */ private function getModuleTemplateStatus($lang, $tags = false, $module = false) { - if ($module === false) { - $module = $this->module; - } - if ($tags === false) { - $tags = $this->loadUsedTemplateTags(); - } - $globalTranslation = Dictionary::getArray('main', 'global-template-tags', $lang); - $translation = Dictionary::getArray($module->getIdentifier(), 'template-tags', $lang) + $globalTranslation; - $matches = 0; - $unused = 0; - $expected = count($tags); - foreach ($translation as $key => $value) { - if(!isset($tags[$key])) { - if (!in_array($key, $globalTranslation)) { - $unused++; - } - } else { - $matches++; - } - - } - $missing = $expected - $matches; - return array($missing, $unused); + return $this->getModuleTranslationStatus($lang, 'template-tags', true, $tags, $module); } /** - * Get missing and unused counters for given module's templates. + * Get missing and unused counters for given translation unit. + * This is a more general version of the getModuleTemplateStatus function, + * which is special since it uses fallback to global translations. * - * @param type $lang lang to use - * @param type $tags - * @param type $module + * @param string $lang lang cc to use + * @param string $file the name of the translation file to load for checking + * @param boolean $fallback whether to check the global-tags of the main module as fallback + * @param array $tags list of tags that are expected to exist. Tags are the array keys! + * @param \Module $module the module to work with, defaults to the currently edited module * @return array list(missingCount, unusedCount) */ - private function getModuleTranslationStatus($lang, $file, $tags, $module = false) + private function getModuleTranslationStatus($lang, $file, $fallback, $tags, $module = false) { if ($module === false) { $module = $this->module; } - $translation = Dictionary::getArray($module->getIdentifier(), $file, $lang); + if ($fallback) { + $globalTranslation = Dictionary::getArray('main', 'global-tags', $lang); + } else { + $globalTranslation = array(); + } + $translation = Dictionary::getArray($module->getIdentifier(), $file, $lang) + $globalTranslation; $matches = 0; $unused = 0; - $expected = count($tags); - foreach ($translation as $key => $value) { + $expected = 0; + foreach ($tags as $v) { + if ($v !== false) { + $expected++; + } + } + foreach (array_keys($translation) as $key) { if(!isset($tags[$key])) { - $unused++; + if (!in_array($key, $globalTranslation)) { + $unused++; + } } else { - $matches++; + if ($tags[$key] !== false) { + $matches++; + } } } @@ -507,51 +584,6 @@ 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, $expectedTags) - { - //if there was not a valid template's path - if (!$path) { - return "Translation missing"; - } - // How many tags do we expect in the translation - $htmlCount = count($expectedTags); - - //initialize the count variables - $matchCount = 0; - $unusedCount = 0; - - //loads the JSON tags and count the matches - $json = Dictionary::getArray(substr($path, strlen("modules/")), $lang); - //return print_r($json) . "\nvs\n" . print_r($expectedTags); - foreach ($json as $key => $value) { - if (!in_array($key, $expectedTags)) { - $unusedCount++; - } else if (!empty($value)) { - $matchCount++; - } - } - $diff = $htmlCount - $matchCount; - - if ($diff == 0 && $unusedCount == 0) - return ''; - //build the return string - $str = ""; - if ($diff > 0) - $str .= $diff . " JSON tag(s) are missing"; - if ($diff > 0 && $unusedCount > 0) - $str .= "<br>"; - if ($unusedCount > 0) - $str .= $unusedCount . " JSON tag(s) are not being used"; - return $str; - } - - /** * Get array to pass to edit page with all the tags and translations. * * @param string $path the template's path @@ -563,7 +595,7 @@ class Page_Translation extends Page if ($tags === false) return false; $table = $this->buildTranslationTable('template-tags', array_keys($tags), true); - $global = Dictionary::getArray($this->module->getIdentifier(), 'global-template-tags', $this->destLang); + $global = Dictionary::getArray($this->module->getIdentifier(), 'global-tags', $this->destLang); foreach ($table as &$entry) { if (empty($entry['translation']) && isset($global[$entry['tag']])) { $entry['placeholder'] = $global[$entry['tag']]; @@ -602,6 +634,41 @@ class Page_Translation extends Page return $table; } + /** + * Get array to pass to edit page with all the message ids. + * + * @param string $path the template's path + * @return array structure to pass to the tags list in the edit template + */ + private function loadModuleEditArray() + { + $tags = $this->loadUsedModuleTags(); + $table = $this->buildTranslationTable('module', array_keys($tags), true); + return $table; + } + + /** + * Get array to pass to edit page with all the message ids. + * + * @param string $path the template's path + * @return array structure to pass to the tags list in the edit template + */ + private function loadCustomEditArray() + { + $tags = $this->loadUsedCustomTags($this->subsection); + $table = $this->buildTranslationTable($this->subsection, array_keys($tags), true); + return $table; + } + + /** + * Quick and dirty method to count the parameters of a message/translate invocation. + * Expects the rest of an invocation, so e.g. addMessage('foo-foo', 'hi'); becomes + * , 'hi'); or addMessage('foo'); becomes just ); + * This obviously fails if the call is spread over multiple lines. + * + * @param string $str the partial method call + * @return int number of arguments to the method, minus the message id + */ private function countMessageParams($str) { $quote = false; @@ -611,28 +678,36 @@ class Page_Translation extends Page $depth = 0; for ($i = 0; $i < $len; ++$i) { $char = $str{$i}; + // Last char was backslash? Ignore this char if ($escape) { $escape = false; continue; } - if ($quote === false) { - if ($char === ',') { - if ($depth === 0) { - $count++; - } - } elseif ($char === '"' || $char === "'") { - $quote = $char; - } elseif ($char === '{' || $char === '(' || $char === '[') { - $depth++; - } elseif ($char === '}' || $char === ')' || $char === ']') { - $depth--; - } - } else { + // We're inside quotes, watch for end or backslash + if ($quote !== false) { if ($char === $quote) { $quote = false; } elseif ($char === '\\') { $escape = true; } + continue; + } + // We're not inside quotes + // Check if we have a parameter delimiter + if ($char === ',') { + // Check we're not in a nested method call + if ($depth === 0) { + $count++; // Increase parameter counter + } + } elseif ($char === '"' || $char === "'") { + // Start of string + $quote = $char; + } elseif ($char === '{' || $char === '(' || $char === '[') { + // Nested method etc. + $depth++; + } elseif ($char === '}' || $char === ')' || $char === ']') { + // End nested method + $depth--; } } return $count; @@ -659,7 +734,7 @@ class Page_Translation extends Page $tags = array(); // Now find all tags in all php files. Only works for literal usage, not something like $foo = 'bar'; Dictionary::translate($foo); foreach ($files as $file) { - $content = @file_get_contents($file); + $content = file_get_contents($file); if ($content === false || preg_match_all($regexp, $content, $out, PREG_SET_ORDER) < 1) continue; foreach ($out as $set) { @@ -701,30 +776,8 @@ class Page_Translation extends Page } } if ($findAlreadyTranslated) { - $srcLangs = array_merge(array(LANG), array('en'), Dictionary::getLanguages()); - $srcLangs = array_unique($srcLangs); - $key = array_search($this->destLang, $srcLangs); - if ($key !== false) { - unset($srcLangs[$key]); - } - foreach ($srcLangs as $lang) { - $otherLang = Dictionary::getArray($this->module->getIdentifier(), $file, $lang); - if (!is_array($otherLang)) - continue; - $missing = false; - foreach (array_keys($tags) as $tag) { - if (isset($tags[$tag]['samplelang'])) - continue; - if (!isset($otherLang[$tag])) { - $missing = true; - } else { - $tags[$tag]['samplelang'] = $lang; - $tags[$tag]['sampletext'] = $otherLang[$tag]; - } - } - if (!$missing) - break; - } + // For each tag, include a translated string from another language as reference + $this->findTranslationSamples($file, $tags); } $tagid = 0; foreach ($tags as &$tag) { @@ -738,27 +791,42 @@ class Page_Translation extends Page } } } - // Finally remove $lang from the keys so mustache will iterate over them via {{#..}} + // Finally remove tagname from the keys so mustache will iterate over them via {{#..}} return array_values($tags); } /** - * Change the color of the table line according to the tag status - * @param string the JSON's path - * @param string the selected tag - * @return string the css class of the line + * Finds translation samples for the given tags in the given file, looking in all + * languages except the one currently being translated to. Prefers the language the + * user selected, then english, then everything else. + * + * @param string $file translation unit + * @param type $tags list of tags, formatted as used in buildTranslationTable() */ - private function getTagColor($missingCount) + private function findTranslationSamples($file, &$tags) { - //return danger in case the tag is not found in the template - if ($missingCount < 0) - return 'danger'; - - //return warning in case at least one of the tag's values is empty - if ($missingCount > 0) - return 'warning'; - //if it's ok don't change the class - return ''; + $srcLangs = array_unique(array_merge(array(LANG), array('en'), Dictionary::getLanguages())); + if (($key = array_search($this->destLang, $srcLangs)) !== false) { + unset($srcLangs[$key]); + } + foreach ($srcLangs as $lang) { + $otherLang = Dictionary::getArray($this->module->getIdentifier(), $file, $lang); + if (!is_array($otherLang)) + continue; + $missing = false; + foreach (array_keys($tags) as $tag) { + if (isset($tags[$tag]['samplelang'])) + continue; + if (!isset($otherLang[$tag])) { + $missing = true; + } else { + $tags[$tag]['samplelang'] = $lang; + $tags[$tag]['sampletext'] = $otherLang[$tag]; + } + } + if (!$missing) + break; + } } private function getJsonFile() @@ -771,6 +839,9 @@ class Page_Translation extends Page if ($this->section === 'template') { return $prefix . '/template-tags.json'; } + if ($this->section === 'module') { + return $prefix . '/module.json'; + } // Custom submodule if ($this->section === 'custom') { if ($this->customHandler === false || !isset($this->customHandler['subsections'])) { @@ -781,7 +852,7 @@ class Page_Translation extends Page Message::addError('invalid-custom-handler', $this->subsection); $this->redirect(1); } - return $prefix . '/' . $this->subsection; + return $prefix . '/' . $this->subsection . '.json'; } Message::addError('invalid-section', $this->section); $this->redirect(1); @@ -851,35 +922,5 @@ class Page_Translation extends Page Message::addSuccess('updated-tags'); } - - /** - * Load all settings categories for editing. - * - * @return array - */ - private function loadCategoriesArray() - { - $want = array(); - $res = Database::simpleQuery("SELECT catid FROM cat_setting ORDER BY catid ASC"); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $want[] = 'cat_' . $row['catid']; - } - return $this->buildTranslationTable('settings/cat_setting', $want); - } - - /** - * Load all settings categories for editing. - * - * @return array - */ - private function loadSettingsArray() - { - $want = array(); - $res = Database::simpleQuery("SELECT setting FROM setting ORDER BY setting ASC"); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $want[] = $row['setting']; - } - return $this->buildTranslationTable('settings/setting', $want); - } } diff --git a/modules-available/translation/templates/_page.html b/modules-available/translation/templates/_page.html deleted file mode 100644 index 45732c5b..00000000 --- a/modules-available/translation/templates/_page.html +++ /dev/null @@ -1,18 +0,0 @@ -<h1>{{lang_mainHeading}}</h1> -<div class="panel panel-default"> - <div class="panel-heading"> - {{lang_langAdministration}} - </div> - <div class="panel-body"> - <p>{{lang_adminInfo}}</p> - <ul class="nav nav-pills nav-stacked"> - <!-- new modules page ??? --> - <li><a href="?do=Translation&page=modules">{{lang_editModules}}</a></li> - <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> - <li><a href="?do=Translation&page=config-module">{{lang_editConfigModule}}</a></li> - </ul> - </div> -</div> diff --git a/modules-available/translation/templates/custom-list.html b/modules-available/translation/templates/custom-list.html new file mode 100644 index 00000000..42ee98ad --- /dev/null +++ b/modules-available/translation/templates/custom-list.html @@ -0,0 +1,21 @@ +<div class="panel panel-default"> + <div class="panel-heading"> + {{subsection}} + </div> + <div class="panel-body"> + <div class="row"> + <div class="col-sm-6"> + {{#langs}} + <a href="?do=Translation&module={{module}}&section=custom&subsection={{subsection}}&destlang={{cc}}">{{name}} »</a> + <ul> + <li>{{lang_missing}}: {{missing}}</li> + <li>{{lang_unused}}: {{unused}}</li> + </ul> + {{/langs}} + </div> + <div class="col-sm-6"> + {{lang_tags}}: {{tagcount}} + </div> + </div> + </div> +</div> diff --git a/modules-available/translation/templates/module-list.html b/modules-available/translation/templates/module-list.html index 589fa0d4..81dc741c 100644 --- a/modules-available/translation/templates/module-list.html +++ b/modules-available/translation/templates/module-list.html @@ -1,11 +1,5 @@ -<div class="panel panel-default"> - <div class="panel-heading"> - {{lang_langAdministration}} - </div> - <div class="panel-body"> - <p>{{lang_adminInfo}}</p> - </div> -</div> +<h1>{{lang_translationHeading}}</h1> + <div class="panel panel-default"> <table class="table"> <thead> diff --git a/modules-available/translation/templates/string-list.html b/modules-available/translation/templates/string-list.html new file mode 100644 index 00000000..f1301494 --- /dev/null +++ b/modules-available/translation/templates/string-list.html @@ -0,0 +1,21 @@ +<div class="panel panel-default"> + <div class="panel-heading"> + {{lang_otherStrings}} + </div> + <div class="panel-body"> + <div class="row"> + <div class="col-sm-6"> + {{#langs}} + <a href="?do=Translation&module={{module}}&section=module&destlang={{cc}}">{{name}} »</a> + <ul> + <li>{{lang_missing}}: {{missing}}</li> + <li>{{lang_unused}}: {{unused}}</li> + </ul> + {{/langs}} + </div> + <div class="col-sm-6"> + {{lang_tags}}: {{tagcount}} + </div> + </div> + </div> +</div> diff --git a/modules-available/vmstore/lang/de/module.json b/modules-available/vmstore/lang/de/module.json new file mode 100644 index 00000000..87be6cae --- /dev/null +++ b/modules-available/vmstore/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "VM Speicherort", + "page_title": "Speicherort f\u00fcr VMs festlegen" +}
\ No newline at end of file diff --git a/modules-available/vmstore/lang/en/module.json b/modules-available/vmstore/lang/en/module.json index 67e63451..95b2e66d 100644 --- a/modules-available/vmstore/lang/en/module.json +++ b/modules-available/vmstore/lang/en/module.json @@ -1,3 +1,4 @@ { - "module_name": "Virtual Machine" + "module_name": "VM storage location", + "page_title": "Setting VM storage location" }
\ No newline at end of file diff --git a/modules-available/webinterface/lang/de/module.json b/modules-available/webinterface/lang/de/module.json new file mode 100644 index 00000000..4b96a1fe --- /dev/null +++ b/modules-available/webinterface/lang/de/module.json @@ -0,0 +1,4 @@ +{ + "module_name": "Web-Schnittstelle", + "page_title": "Web-Schnittstelle konfigurieren" +}
\ No newline at end of file |