feat: multi-module improvements across merchant, store, i18n, and customer systems
All checks were successful
CI / ruff (push) Successful in 12s
CI / pytest (push) Successful in 50m57s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Successful in 40s
CI / deploy (push) Successful in 51s

- Fix platform-grouped merchant sidebar menu with core items at root level
- Add merchant store management (detail page, create store, team page)
- Fix store settings 500 error by removing dead stripe/API tab
- Move onboarding translations to module-owned locale files
- Fix onboarding banner i18n with server-side rendering + context inheritance
- Refactor login language selectors to use languageSelector() function (LANG-002)
- Move HTTPException handling to global exception handler in merchant routes (API-003)
- Add language selector to all login pages and portal headers
- Fix customer module: drop order stats from customer model, add to orders module
- Fix admin menu config visibility for super admin platform context
- Fix storefront auth and layout issues
- Add missing i18n translations for onboarding steps (en/fr/de/lb)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 23:48:25 +01:00
parent f141cc4e6a
commit a77a8a3a98
113 changed files with 3741 additions and 2923 deletions

View File

@@ -111,7 +111,35 @@
"invalid_credentials": "Ungültiger Benutzername oder Passwort",
"session_expired": "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.",
"account_locked": "Ihr Konto wurde gesperrt",
"account_inactive": "Ihr Konto ist inaktiv"
"account_inactive": "Ihr Konto ist inaktiv",
"signing_in": "Anmeldung läuft...",
"sending": "Wird gesendet...",
"send_reset_link": "Link zum Zurücksetzen senden",
"reset_password_desc": "Geben Sie Ihre E-Mail-Adresse ein und wir senden Ihnen einen Link zum Zurücksetzen Ihres Passworts.",
"back_to_login": "Zurück zur Anmeldung",
"back_to_platform": "Zurück zur Plattform",
"no_account": "Noch kein Konto?",
"visit_platform": "Besuchen Sie unsere Plattform",
"already_have_account": "Haben Sie bereits ein Konto?",
"create_account": "Konto erstellen",
"continue_shopping": "Weiter einkaufen",
"admin_login": "Admin-Anmeldung",
"merchant_login": "Händler-Anmeldung",
"store_login": "Shop-Portal-Anmeldung",
"customer_login": "Kunden-Anmeldung",
"create_account_title": "Konto erstellen",
"creating_account": "Konto wird erstellt...",
"sign_in_instead": "Stattdessen anmelden",
"first_name": "Vorname",
"last_name": "Nachname",
"phone_number": "Telefonnummer",
"marketing_consent": "Ich möchte Neuigkeiten und Sonderangebote erhalten",
"password_requirements": "Muss mindestens 8 Zeichen, einen Buchstaben und eine Zahl enthalten",
"check_email": "Überprüfen Sie Ihre E-Mail",
"reset_link_sent": "Wir haben einen Link zum Zurücksetzen des Passworts an Ihre E-Mail-Adresse gesendet. Bitte überprüfen Sie Ihren Posteingang und klicken Sie auf den Link.",
"didnt_receive_email": "E-Mail nicht erhalten? Überprüfen Sie Ihren Spam-Ordner oder",
"try_again": "versuchen Sie es erneut",
"remember_password": "Passwort wieder eingefallen?"
},
"nav": {
"dashboard": "Dashboard",
@@ -191,5 +219,11 @@
"time": "HH:mm",
"datetime": "DD.MM.YYYY HH:mm",
"currency": "{amount} {symbol}"
},
"onboarding": {
"banner": {
"title": "Erste Schritte",
"dismiss": "Ausblenden"
}
}
}

View File

@@ -111,7 +111,35 @@
"invalid_credentials": "Invalid username or password",
"session_expired": "Your session has expired. Please login again.",
"account_locked": "Your account has been locked",
"account_inactive": "Your account is inactive"
"account_inactive": "Your account is inactive",
"signing_in": "Signing in...",
"sending": "Sending...",
"send_reset_link": "Send Reset Link",
"reset_password_desc": "Enter your email address and we'll send you a link to reset your password.",
"back_to_login": "Back to Login",
"back_to_platform": "Back to Platform",
"no_account": "Don't have an account?",
"visit_platform": "Visit our platform",
"already_have_account": "Already have an account?",
"create_account": "Create an account",
"continue_shopping": "Continue shopping",
"admin_login": "Admin Login",
"merchant_login": "Merchant Login",
"store_login": "Store Portal Login",
"customer_login": "Customer Login",
"create_account_title": "Create Account",
"creating_account": "Creating account...",
"sign_in_instead": "Sign in instead",
"first_name": "First Name",
"last_name": "Last Name",
"phone_number": "Phone Number",
"marketing_consent": "I'd like to receive news and special offers",
"password_requirements": "Must contain at least 8 characters, one letter, and one number",
"check_email": "Check Your Email",
"reset_link_sent": "We've sent a password reset link to your email. Please check your inbox and click the link to reset your password.",
"didnt_receive_email": "Didn't receive the email? Check your spam folder or",
"try_again": "try again",
"remember_password": "Remember your password?"
},
"nav": {
"dashboard": "Dashboard",
@@ -195,5 +223,11 @@
"clipboard": {
"copied": "Copied to clipboard",
"failed": "Failed to copy"
},
"onboarding": {
"banner": {
"title": "Get Started",
"dismiss": "Dismiss"
}
}
}

View File

@@ -111,7 +111,35 @@
"invalid_credentials": "Nom d'utilisateur ou mot de passe invalide",
"session_expired": "Votre session a expiré. Veuillez vous reconnecter.",
"account_locked": "Votre compte a été verrouillé",
"account_inactive": "Votre compte est inactif"
"account_inactive": "Votre compte est inactif",
"signing_in": "Connexion en cours...",
"sending": "Envoi en cours...",
"send_reset_link": "Envoyer le lien de réinitialisation",
"reset_password_desc": "Entrez votre adresse e-mail et nous vous enverrons un lien pour réinitialiser votre mot de passe.",
"back_to_login": "Retour à la connexion",
"back_to_platform": "Retour à la plateforme",
"no_account": "Vous n'avez pas de compte ?",
"visit_platform": "Visitez notre plateforme",
"already_have_account": "Vous avez déjà un compte ?",
"create_account": "Créer un compte",
"continue_shopping": "Continuer vos achats",
"admin_login": "Connexion Admin",
"merchant_login": "Connexion Marchand",
"store_login": "Connexion Portail Magasin",
"customer_login": "Connexion Client",
"create_account_title": "Créer un compte",
"creating_account": "Création du compte...",
"sign_in_instead": "Se connecter",
"first_name": "Prénom",
"last_name": "Nom",
"phone_number": "Numéro de téléphone",
"marketing_consent": "Je souhaite recevoir des actualités et offres spéciales",
"password_requirements": "Doit contenir au moins 8 caractères, une lettre et un chiffre",
"check_email": "Vérifiez votre e-mail",
"reset_link_sent": "Nous avons envoyé un lien de réinitialisation à votre adresse e-mail. Veuillez vérifier votre boîte de réception et cliquer sur le lien.",
"didnt_receive_email": "Vous n'avez pas reçu l'e-mail ? Vérifiez votre dossier spam ou",
"try_again": "réessayez",
"remember_password": "Vous vous souvenez de votre mot de passe ?"
},
"nav": {
"dashboard": "Tableau de bord",
@@ -191,5 +219,11 @@
"time": "HH:mm",
"datetime": "DD/MM/YYYY HH:mm",
"currency": "{amount} {symbol}"
},
"onboarding": {
"banner": {
"title": "Premiers pas",
"dismiss": "Masquer"
}
}
}

View File

@@ -111,7 +111,35 @@
"invalid_credentials": "Ongëltege Benotzernumm oder Passwuert",
"session_expired": "Är Sessioun ass ofgelaf. Mellt Iech w.e.g. erëm un.",
"account_locked": "Äre Kont ass gespaart",
"account_inactive": "Äre Kont ass inaktiv"
"account_inactive": "Äre Kont ass inaktiv",
"signing_in": "Umellen...",
"sending": "Gëtt geschéckt...",
"send_reset_link": "Link fir zréckzesetzen schécken",
"reset_password_desc": "Gitt Är E-Mail-Adress an a mir schécken Iech e Link fir Äert Passwuert zréckzesetzen.",
"back_to_login": "Zréck zum Login",
"back_to_platform": "Zréck zur Plattform",
"no_account": "Kee Kont?",
"visit_platform": "Besicht eis Plattform",
"already_have_account": "Hutt Dir schonn e Kont?",
"create_account": "E Kont erstellen",
"continue_shopping": "Weider akafen",
"admin_login": "Admin Login",
"merchant_login": "Händler Login",
"store_login": "Buttek-Portal Login",
"customer_login": "Client Login",
"create_account_title": "Kont erstellen",
"creating_account": "Kont gëtt erstallt...",
"sign_in_instead": "Aloggen amplaz",
"first_name": "Virnumm",
"last_name": "Nonumm",
"phone_number": "Telefonsnummer",
"marketing_consent": "Ech wëll Neiegkeeten an Spezialangebotter kréien",
"password_requirements": "Muss mindestens 8 Zeechen, ee Buschtaf an eng Zuel enthalen",
"check_email": "Kuckt Är E-Mail",
"reset_link_sent": "Mir hunn e Link fir d'Passwuert zréckzesetzen op Är E-Mail-Adress geschéckt. Kuckt w.e.g. Ären Posteingang a klickt op de Link.",
"didnt_receive_email": "E-Mail net kritt? Kuckt Ären Spam-Dossier oder",
"try_again": "probéiert et nach eng Kéier",
"remember_password": "Passwuert erëm agefall?"
},
"nav": {
"dashboard": "Dashboard",
@@ -191,5 +219,11 @@
"time": "HH:mm",
"datetime": "DD.MM.YYYY HH:mm",
"currency": "{amount} {symbol}"
},
"onboarding": {
"banner": {
"title": "Ufänken",
"dismiss": "Verstoppen"
}
}
}

View File

@@ -182,6 +182,12 @@ const Icons = {
'support': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z"/></svg>`,
'emoji-happy': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>`,
// Onboarding & Setup Icons
'rocket': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.59 14.37a6 6 0 01-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 006.16-12.12A14.98 14.98 0 009.631 8.41m5.96 5.96a14.926 14.926 0 01-5.841 2.58m-.119-8.54a6 6 0 00-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 00-2.58 5.84m2.699 2.7c-.103.021-.207.041-.311.06a15.09 15.09 0 01-2.448-2.448 14.9 14.9 0 01.06-.312m-2.24 2.39a4.493 4.493 0 00-6.914 0"/></svg>`,
'settings': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>`,
'plug': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>`,
'package': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/></svg>`,
// Messaging
'chat-bubble-left-right': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12.5c0 2.5-2.015 4.5-4.5 4.5H11l-4 4v-4H4.5C2.015 17 0 15 0 12.5v-5C0 5.015 2.015 3 4.5 3h11C18.015 3 20 5.015 20 7.5v5z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9.5c0-2.485 2.015-4.5 4.5-4.5h3c2.485 0 4.5 2.015 4.5 4.5v5c0 2.485-2.015 4.5-4.5 4.5H17l-3 3v-3h-.5c-2.485 0-4.5-2.015-4.5-4.5v-5z"/></svg>`,
'chat-bubble-left': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/></svg>`