Procházet zdrojové kódy

Neo-style install footer language switcher

Footer language control on every install step. Native names (English / Русский), same ?lang= cookie, current action preserved. No flags, no System locale.
Andrey Yasko před 2 měsíci
rodič
revize
90a882fc38

+ 14 - 2
install/classes/BxDolInstallLang.php

@@ -53,16 +53,28 @@ class BxDolInstallLang
         return $sKey;
     }
 
+    public function getLang()
+    {
+        return $this->_sLang;
+    }
+
     public function getAvailableLanguages ()
     {
         $aRet = array();
         $aModules = $this->_oModulesTools->getModules('language');
-        foreach ($aModules as $aModuleConfig)
+        foreach ($aModules as $aModuleConfig) {
+            $sStudioTitle = $aModuleConfig['title'];
+            $sTitle = $sStudioTitle;
+            $aOwnStrings = $this->_oModulesTools->readLanguage($aModuleConfig);
+            if (!empty($aOwnStrings['__' . $sStudioTitle]))
+                $sTitle = $aOwnStrings['__' . $sStudioTitle];
+
             $aRet[$aModuleConfig['home_uri']] = array(
                 'code' => $aModuleConfig['home_uri'],
-                'title' => $aModuleConfig['title'],
+                'title' => $sTitle,
                 'icon' => BX_INSTALL_URL_MODULES . $aModuleConfig['home_dir'] . 'template/images/icons/' . (file_exists(BX_INSTALL_DIR_MODULES .  $aModuleConfig['home_dir'] . 'template/images/icons/std-pi.png') ? 'std-pi.png' : 'std-icon.svg'),
             );
+        }
         return $aRet;
     }
 

+ 5 - 0
install/classes/BxDolInstallView.php

@@ -57,6 +57,11 @@ class BxDolInstallView
 
     function pageEnd ($sTitle)
     {
+        $oLang = BxDolInstallLang::getInstance();
+        $aLangs = $oLang->getAvailableLanguages();
+        $sLang = $oLang->getLang();
+        $sLangTitle = (isset($aLangs[$sLang]) && !empty($aLangs[$sLang]['title'])) ? $aLangs[$sLang]['title'] : $sLang;
+
         $aToolbarItem = $this->_aToolbarItem;
         $sInlineCSS = $this->_getInlineCSS();
         $sFilesCSS = $this->_getFilesCSS();

+ 96 - 6
install/css/styles.css

@@ -106,21 +106,33 @@ body.bx-install-body,
 
 .bx-install-footer {
     flex: 0 0 auto;
-    text-align: center;
-    padding: 20px;
+    display: grid;
+    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
+    align-items: center;
+    gap: 12px;
+    padding: 16px 20px;
     font-size: 12px;
     color: var(--bx-inst-muted);
+}
+.bx-install-footer-lang {
+    justify-self: start;
+    position: relative;
+}
+.bx-install-footer-links {
+    justify-self: center;
     display: flex;
     flex-wrap: wrap;
-    justify-content: center;
     align-items: center;
-    gap: 0 4px;
+    justify-content: center;
 }
-.bx-install-footer a {
+.bx-install-footer-spacer {
+    justify-self: end;
+}
+.bx-install-footer-links a {
     color: var(--bx-inst-muted);
     text-decoration: none;
 }
-.bx-install-footer a:hover {
+.bx-install-footer-links a:hover {
     color: var(--bx-inst-text);
     text-decoration: underline;
 }
@@ -133,6 +145,84 @@ body.bx-install-body,
     vertical-align: middle;
 }
 
+.bx-install-lang {
+    position: relative;
+}
+.bx-install-lang-trigger {
+    list-style: none;
+    display: inline-flex;
+    align-items: center;
+    gap: 6px;
+    padding: 4px 2px;
+    cursor: pointer;
+    color: var(--bx-inst-muted);
+    font-size: 13px;
+    font-weight: 500;
+    user-select: none;
+}
+.bx-install-lang-trigger::-webkit-details-marker {
+    display: none;
+}
+.bx-install-lang-trigger::marker {
+    content: "";
+}
+.bx-install-lang[open] .bx-install-lang-trigger,
+.bx-install-lang-trigger:hover {
+    color: var(--bx-inst-accent);
+    text-decoration: underline;
+}
+.bx-install-lang-current {
+    line-height: 1.2;
+}
+.bx-install-lang-icon {
+    display: block;
+    flex: 0 0 auto;
+}
+.bx-install-lang-menu {
+    position: absolute;
+    left: 0;
+    bottom: calc(100% + 8px);
+    min-width: 220px;
+    padding: 6px;
+    background: #fff;
+    border: 1px solid var(--bx-inst-border);
+    border-radius: 12px;
+    box-shadow: var(--bx-inst-shadow);
+    z-index: 30;
+}
+.bx-install-lang-item {
+    display: flex !important;
+    align-items: center;
+    gap: 10px;
+    padding: 8px 10px;
+    border-radius: 8px;
+    color: var(--bx-inst-text) !important;
+    font-size: 13px;
+    text-decoration: none !important;
+}
+.bx-install-lang-item:hover {
+    background: #f3f4f6;
+}
+.bx-install-lang-item.is-selected {
+    background: #eff6ff;
+    color: var(--bx-inst-accent) !important;
+}
+.bx-install-lang-badge {
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    width: 28px;
+    height: 28px;
+    border-radius: 999px;
+    background: #f3f4f6;
+    color: var(--bx-inst-text);
+    flex: 0 0 auto;
+}
+.bx-install-lang-item.is-selected .bx-install-lang-badge {
+    background: #dbeafe;
+    color: var(--bx-inst-accent);
+}
+
 /* Kill the old teal header if any leftover classes still render */
 .bx-header.bx-def-color-bg-header,
 #bx-toolbar {

+ 12 - 6
install/templates/_page.php

@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="<?=bx_html_attribute($sLang); ?>">
 <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -32,11 +32,17 @@
     </main>
 
     <footer class="bx-install-footer">
-        <a href="https://unacms.com" target="_blank" rel="noopener"><?php echo _t('_sys_inst_footer_product'); ?></a>
-        <span class="bx-install-footer-sep" aria-hidden="true"></span>
-        <a href="https://unacms.com/docs" target="_blank" rel="noopener"><?php echo _t('_sys_inst_footer_docs'); ?></a>
-        <span class="bx-install-footer-sep" aria-hidden="true"></span>
-        <a href="https://unacms.com/contact" target="_blank" rel="noopener"><?php echo _t('_sys_inst_footer_contact'); ?></a>
+        <div class="bx-install-footer-lang">
+            <?php include('lang_swither.php'); ?>
+        </div>
+        <div class="bx-install-footer-links">
+            <a href="https://unacms.com" target="_blank" rel="noopener"><?php echo _t('_sys_inst_footer_product'); ?></a>
+            <span class="bx-install-footer-sep" aria-hidden="true"></span>
+            <a href="https://unacms.com/docs" target="_blank" rel="noopener"><?php echo _t('_sys_inst_footer_docs'); ?></a>
+            <span class="bx-install-footer-sep" aria-hidden="true"></span>
+            <a href="https://unacms.com/contact" target="_blank" rel="noopener"><?php echo _t('_sys_inst_footer_contact'); ?></a>
+        </div>
+        <div class="bx-install-footer-spacer" aria-hidden="true"></div>
     </footer>
 </div>
 

+ 0 - 2
install/templates/initial.php

@@ -2,8 +2,6 @@
 
     <img class="bx-def-margin-bottom bx-install-img" src="img/logo.svg" alt="UNA" />
 
-    <?php include('lang_swither.php'); ?>
-
     <div class="bx-install-actions">
         <a href="?action=permissions" class="bx-btn bx-btn-primary"><?php echo _t('_sys_inst_start_installation'); ?></a>
         <a href="?action=audit" class="bx-btn"><?php echo _t('_sys_inst_server_audit'); ?></a>

+ 0 - 2
install/templates/initial_fail.php

@@ -1,7 +1,5 @@
 <div class="bx-install-initial-fail">
 
-    <?php include('lang_swither.php'); ?>
-
     <?php echo _t('_sys_inst_hosting_fails'); ?>
     <ul>
     <?php foreach ($aErrors as $sMsg): ?>

+ 45 - 5
install/templates/lang_swither.php

@@ -1,8 +1,48 @@
+<?php
+/**
+ * Footer language switcher. Hidden when fewer than two language modules exist.
+ */
+if (empty($aLangs) || count($aLangs) < 2)
+    return;
 
-    <div class="bx-install-initial-langs bx-def-margin-bottom">
-    <?php foreach ($aLangs as $aLang): ?>
-        <a title="<?php echo bx_html_attribute($aLang['title']); ?>" href="?lang=<?=$aLang['code']; ?>">
-            <img src="<?php echo bx_html_attribute($aLang['icon']); ?>" alt="<?php echo bx_html_attribute($aLang['title']); ?>" />
+if (!function_exists('bx_install_lang_url')) {
+    function bx_install_lang_url($sCode)
+    {
+        $a = array();
+        if (!empty($_GET['action']))
+            $a['action'] = $_GET['action'];
+        $a['lang'] = $sCode;
+        return '?' . http_build_query($a);
+    }
+}
+
+$sTranslateSvg = '<svg class="bx-install-lang-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5 8 6 6"/><path d="m4 14 6-6 2-3"/><path d="M2 5h12"/><path d="M7 2h1"/><path d="m22 22-5-10-5 10"/><path d="M14 18h6"/></svg>';
+?>
+<details class="bx-install-lang">
+    <summary class="bx-install-lang-trigger">
+        <?php echo $sTranslateSvg; ?>
+        <span class="bx-install-lang-current"><?php echo bx_html_attribute($sLangTitle); ?></span>
+    </summary>
+    <div class="bx-install-lang-menu" role="menu">
+        <?php foreach ($aLangs as $aLang): ?>
+        <a role="menuitem" class="bx-install-lang-item<?php echo ($aLang['code'] === $sLang) ? ' is-selected' : ''; ?>" href="<?php echo bx_html_attribute(bx_install_lang_url($aLang['code'])); ?>">
+            <span class="bx-install-lang-badge"><?php echo $sTranslateSvg; ?></span>
+            <span><?php echo bx_html_attribute($aLang['title']); ?></span>
         </a>
-    <?php endforeach; ?>
+        <?php endforeach; ?>
     </div>
+</details>
+<script>
+(function () {
+    var d = document.querySelector('.bx-install-lang');
+    if (!d) return;
+    document.addEventListener('click', function (e) {
+        if (!d.contains(e.target))
+            d.removeAttribute('open');
+    });
+    document.addEventListener('keydown', function (e) {
+        if (e.key === 'Escape')
+            d.removeAttribute('open');
+    });
+})();
+</script>