diff --git a/assets/src/css/style.css b/assets/src/css/style.css
index 19141ae042..88ab38aaaf 100755
--- a/assets/src/css/style.css
+++ b/assets/src/css/style.css
@@ -216,6 +216,192 @@ input[type=file] {
box-shadow: 0 1px 3px rgba(255, 193, 7, 0.3);
}
+.login-page .osm-login {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ min-height: 100vh;
+ padding: 32px 16px;
+ background:
+ linear-gradient(135deg, rgba(15, 23, 42, 0.04), rgba(14, 165, 233, 0.08)),
+ #f5f7fb;
+}
+
+.login-page .osm-login__panel {
+ width: min(100%, 430px);
+}
+
+.login-page .osm-login__brand {
+ margin-bottom: 18px;
+ text-align: center;
+}
+
+.login-page .osm-login__logo {
+ width: min(100%, 310px);
+ max-height: 86px;
+ object-fit: contain;
+}
+
+.login-page .osm-login__locale {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 8px;
+ margin-bottom: 12px;
+}
+
+.login-page .osm-login__locale-label {
+ margin-bottom: 0;
+ color: #4b5563;
+ font-size: 0.9rem;
+ font-weight: 600;
+}
+
+.login-page .osm-login__locale-select {
+ width: auto;
+ min-width: 180px;
+}
+
+.login-page .osm-login__form {
+ padding: 32px;
+ background: #fff;
+ border: 1px solid #dbe3ef;
+ border-radius: 8px;
+ box-shadow: 0 18px 45px rgba(15, 23, 42, 0.12);
+}
+
+.login-page .osm-login__title {
+ margin: 0;
+ color: #111827;
+ font-size: 1.75rem;
+ font-weight: 700;
+ letter-spacing: 0;
+ line-height: 1.2;
+}
+
+.login-page .osm-login__subtitle {
+ margin: 8px 0 24px;
+ color: #64748b;
+}
+
+.login-page .osm-login__notice,
+.login-page .osm-login__error {
+ border-radius: 8px;
+}
+
+.login-page .osm-login__brute {
+ display: block;
+ margin-top: 8px;
+}
+
+.login-page .osm-login__field {
+ margin-bottom: 18px;
+}
+
+.login-page .osm-login__field label {
+ color: #334155;
+ font-weight: 600;
+}
+
+.login-page .osm-login__field .form-control {
+ min-height: 46px;
+ border-color: #cbd5e1;
+ border-radius: 6px 0 0 6px;
+}
+
+.login-page .osm-login__field .input-group-text,
+.login-page .osm-login__password-toggle {
+ min-width: 46px;
+ border-color: #cbd5e1;
+ background: #f8fafc;
+ color: #475569;
+}
+
+.login-page .osm-login__password-toggle {
+ border-radius: 0 6px 6px 0;
+}
+
+.login-page .osm-login__submit {
+ min-height: 48px;
+ border-radius: 6px;
+ font-weight: 700;
+}
+
+.login-page .osm-login__links {
+ margin-top: 18px;
+ text-align: center;
+}
+
+.login-page .osm-login__links a {
+ color: #475569;
+ font-weight: 600;
+}
+
+.login-page .osm-login__links a:hover {
+ color: #0f766e;
+}
+
+.login-page .osm-login__divider {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ margin: 24px 0 16px;
+ color: #64748b;
+ font-size: 0.9rem;
+}
+
+.login-page .osm-login__divider::before,
+.login-page .osm-login__divider::after {
+ content: "";
+ flex: 1;
+ height: 1px;
+ background: #e2e8f0;
+}
+
+.login-page .osm-login__oauth-button {
+ border-radius: 6px;
+ font-weight: 700;
+}
+
+.login-page .osm-login :focus-visible {
+ outline: 3px solid rgba(14, 165, 233, 0.35);
+ outline-offset: 2px;
+}
+
+@media (max-width: 575.98px) {
+ .login-page .osm-login {
+ align-items: flex-start;
+ padding: 22px 12px;
+ }
+
+ .login-page .osm-login__brand {
+ margin-bottom: 14px;
+ }
+
+ .login-page .osm-login__logo {
+ width: min(100%, 250px);
+ max-height: 72px;
+ }
+
+ .login-page .osm-login__locale {
+ justify-content: stretch;
+ }
+
+ .login-page .osm-login__locale-select {
+ flex: 1;
+ min-width: 0;
+ }
+
+ .login-page .osm-login__form {
+ padding: 24px 18px;
+ }
+
+ .login-page .osm-login__title {
+ font-size: 1.45rem;
+ }
+}
+
/* Disabilita il widget sidebar-search di AdminLTE */
[data-widget-disabled="true"] .sidebar-search-results,
.sidebar-search-results,
diff --git a/include/login.php b/include/login.php
new file mode 100644
index 0000000000..6300b38b07
--- /dev/null
+++ b/include/login.php
@@ -0,0 +1,211 @@
+.
+ */
+
+$escape = static fn ($value) => htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
+
+$username = $username ?? '';
+$error_message = $error_message ?? null;
+$available_login_locales = $available_login_locales ?? [];
+$selected_login_locale = $selected_login_locale ?? trans_osm()->getCurrentLocale();
+$oauth_providers = $oauth_providers ?? [];
+
+$provider_icon = static function ($provider_name) {
+ $provider_name = strtolower((string) $provider_name);
+
+ if (str_contains($provider_name, 'microsoft')) {
+ return 'fa-windows';
+ }
+ if (str_contains($provider_name, 'keycloak')) {
+ return 'fa-key';
+ }
+ if (str_contains($provider_name, 'google')) {
+ return 'fa-google';
+ }
+
+ return 'fa-sign-in';
+};
+
+echo '
+
+
+
+
.')
+
';
+
+if (count($available_login_locales) > 1) {
+ echo '
+ ';
+}
+
+if (Update::isBeta()) {
+ echo '
+
+
+ '.$escape(tr('Attenzione!')).' '.tr('Stai utilizzando una versione non stabile di OSM.').'
+
+
';
+}
+
+if (AuthOSM::isBrute()) {
+ echo '
+
+ '.$escape(tr('Attenzione')).'
+ '.$escape(tr('Sono stati effettuati troppi tentativi di accesso consecutivi!')).'
+
+ '.$escape(tr('Tempo rimanente')).':
+ '.(AuthOSM::getBruteTimeout() + 1).'
+ '.$escape(tr('secondi')).'
+
+
';
+}
+
+echo '
+
+
+
+
+';
diff --git a/index.php b/index.php
index 53e55b8088..20b3fa88f6 100755
--- a/index.php
+++ b/index.php
@@ -27,12 +27,53 @@
$op = filter('op');
$token = filter('token');
-$microsoft = null;
-$keycloack = null;
-if ($dbo->isConnected()) {
+// Lingua pre-login: solo sessione/richiesta corrente, senza modificare l'impostazione globale.
+$available_login_locales = [];
+$selected_login_locale = trans_osm()->getCurrentLocale();
+if ($dbo->isConnected() && $dbo->isInstalled() && !AuthOSM::check()) {
try {
- $microsoft = $dbo->selectOne('zz_oauth2', '*', ['name' => 'Microsoft', 'enabled' => 1, 'is_login' => 1]);
- $keycloack = $dbo->selectOne('zz_oauth2', '*', ['name' => 'Keycloak', 'enabled' => 1, 'is_login' => 1]);
+ $catalog_locales = trans_osm()->getAvailableLocales();
+ $enabled_locales = $dbo->fetchArray('SELECT `id`, `name`, `iso_code`, `language_code`, `date`, `time`, `timestamp`, `decimals`, `thousands`, `predefined` FROM `zz_langs` WHERE `enabled` = 1 ORDER BY `predefined` DESC, `name` ASC');
+
+ foreach ($enabled_locales as $enabled_locale) {
+ if (!empty($enabled_locale['predefined']) || trans_osm()->isLocaleAvailable($enabled_locale['language_code']) || in_array($enabled_locale['language_code'], $catalog_locales)) {
+ $available_login_locales[] = $enabled_locale;
+ }
+ }
+
+ $requested_login_locale = null;
+ $has_requested_login_locale = array_key_exists('login_locale', $_POST) || array_key_exists('login_locale', $_GET);
+ if ($has_requested_login_locale) {
+ $requested_login_locale = post('login_locale') ?: get('login_locale');
+ } elseif (!empty($_SESSION['login_locale'])) {
+ $requested_login_locale = $_SESSION['login_locale'];
+ }
+
+ $login_locale = null;
+ foreach ($available_login_locales as $available_login_locale) {
+ if ($available_login_locale['language_code'] === $requested_login_locale) {
+ $login_locale = $available_login_locale;
+ break;
+ }
+ }
+
+ if (!empty($login_locale)) {
+ $_SESSION['login_locale'] = $login_locale['language_code'];
+ $selected_login_locale = $login_locale['language_code'];
+ $lang = $selected_login_locale;
+
+ trans_osm()->setLocale($selected_login_locale, [
+ 'timestamp' => $login_locale['timestamp'],
+ 'date' => $login_locale['date'],
+ 'time' => $login_locale['time'],
+ 'number' => [
+ 'decimals' => $login_locale['decimals'],
+ 'thousands' => $login_locale['thousands'],
+ ],
+ ]);
+ } elseif ($has_requested_login_locale) {
+ unset($_SESSION['login_locale']);
+ }
} catch (QueryException $e) {
}
}
@@ -140,80 +181,11 @@
include_once App::filepath('include|custom|', 'top.php');
-// Controllo se è una beta e in caso mostro un warning
-if (Update::isBeta()) {
- echo '
-
-
- '.tr('Attenzione!').' '.tr('Stai utilizzando una versione non stabile di OSM.').'
-
-
';
-}
-
-// Controllo se è una beta e in caso mostro un warning
-if (AuthOSM::isBrute()) {
- echo '
-
-
-
-
'.tr('Sono stati effettuati troppi tentativi di accesso consecutivi!').'
-
-
'.tr('Tempo rimanente').':
-
'.(AuthOSM::getBruteTimeout() + 1).' '.tr('secondi').'
-
-
-
-
- ';
-}
// Recupera il messaggio di errore dalla variabile di sessione
$error_message = $_SESSION['login_error'] ?? null;
if (!empty($error_message)) {
// Rimuovi il messaggio dalla sessione dopo averlo recuperato
unset($_SESSION['login_error']);
-
- echo '
- ';
}
$login_logo = App::getPaths()['img'].'/logo_completo.png';
@@ -229,100 +201,17 @@ function brute() {
}
}
+$oauth_providers = [];
if ($dbo->isInstalled() && $dbo->isConnected() && !Update::isUpdateAvailable()) {
- echo '
-
-
-
- ';
+if ($dbo->isInstalled() && $dbo->isConnected() && !Update::isUpdateAvailable()) {
+ include_once App::filepath('include|custom|', 'login.php');
}
$custom_css = $dbo->isInstalled() ? html_entity_decode(setting('CSS Personalizzato')) : '';
diff --git a/locale/de_DE/de_DE.mo b/locale/de_DE/de_DE.mo
index 5e14ef7f7d..1c5803807b 100644
Binary files a/locale/de_DE/de_DE.mo and b/locale/de_DE/de_DE.mo differ
diff --git a/locale/de_DE/de_DE.po b/locale/de_DE/de_DE.po
index 7dee567392..3afd0c9d50 100644
--- a/locale/de_DE/de_DE.po
+++ b/locale/de_DE/de_DE.po
@@ -10726,3 +10726,19 @@ msgid ""
"Il browser non supporta i contenuti iframe: clicca qui per raggiungere il "
"file originale"
msgstr ""
+
+#: include/login.php
+msgid "Selezione lingua"
+msgstr "Sprachauswahl"
+
+#: include/login.php
+msgid "Lingua"
+msgstr "Sprache"
+
+#: include/login.php
+msgid "Accessi alternativi"
+msgstr "Alternative Anmeldungen"
+
+#: include/login.php
+msgid "Accedi con"
+msgstr "Anmelden mit"
diff --git a/locale/en_GB/en_GB.mo b/locale/en_GB/en_GB.mo
index d291a6b6ad..6d70f840a8 100755
Binary files a/locale/en_GB/en_GB.mo and b/locale/en_GB/en_GB.mo differ
diff --git a/locale/en_GB/en_GB.po b/locale/en_GB/en_GB.po
index fb07812f19..a7a3cbda64 100755
--- a/locale/en_GB/en_GB.po
+++ b/locale/en_GB/en_GB.po
@@ -20181,6 +20181,22 @@ msgid ""
"l'amministratore del sistema."
msgstr ""
+#: include/login.php
+msgid "Selezione lingua"
+msgstr "Language selection"
+
+#: include/login.php
+msgid "Lingua"
+msgstr "Language"
+
+#: include/login.php
+msgid "Accessi alternativi"
+msgstr "Alternative sign-ins"
+
+#: include/login.php
+msgid "Accedi con"
+msgstr "Sign in with"
+
#~ msgid "Il gestionale open source per l'assistenza tecnica e la fatturazione"
#~ msgstr ""
#~ "The open source management software for technical assistance and billing"