- expose legal links to screen readers on web - allow only http(s) legal URLs, prevent double submit - detect transport errors without runtimeType, keep extra in memory - ship third-party license text, document decisions Refs #1 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
14 KiB
Auth-Screens: Layout-Skizzen und Texte (Spec #1, Task U1)
Grundlage: docs/specs/1-auth-registrierung-anmeldung.md (§ 4.4 Meldungen, § 5.4 Screens, § 6 Plattform).
Komponenten: app/lib/core/widgets/ (siehe docs/design-system.md). Alle Texte unten sind
Vorschläge und gehen über l10n (ARB); die ARB-Dateien pflegt der flutter-dev (A1/A2).
Schlüssel sind lowerCamelCase mit Präfix auth.
1. Gemeinsames Layout
- Alle sechs Screens nutzen
AppFormScaffold. Kompakt (< 600 dp): Vollbild, scrollbar, Seitenrand 16 dp. Ab 600 dp: zentrierte Karte, max. 480 dp breit (AppBreakpoints.authCardMaxWidth), Innenabstand 24 dp. - Inhalt in einer Spalte, Abstand zwischen Feldern 16 dp, zwischen Gruppen 24 dp.
- Reihenfolge = Lesereihenfolge = Tab-Reihenfolge: Titel, Banner (falls vorhanden), Felder, Checkboxen, Primärknopf, Sekundärlinks.
- Titel:
headlineSmall, darunter optional ein Einleitungssatz inbodyMedium. Titel als Semantics-Überschrift (Semantics(header: true)). - Banner (
AppBanner) stehen über den Feldern, direkt unter dem Titel. Fehler am Feld stehen unter dem Feld. - Genau ein Primärknopf (
AppPrimaryButton, volle Breite). Sekundäraktionen sindTextButtons (48 dp). - Eingaben bleiben bei jedem Fehler erhalten. Während
submittingsind Knopf und Felder gesperrt, der Knopf zeigt den Spinner und den gesprochenen TextauthSubmitting. - Nach einem Fehler setzt der Screen den Fokus auf das erste fehlerhafte Feld; bei Banner-Fehlern bleibt der Fokus am Knopf, das Banner wird als Live-Region angesagt.
- Enter im letzten Feld sendet ab (
TextInputAction.done), sonstnext.
Legende der Skizzen: [ ] Feld, [x] Checkbox, ( ) Primärknopf, <…> Link/TextButton, ! Banner.
2. Skizzen
RegisterScreen (/register)
Konto erstellen (Titel)
! Fehler-Banner (nur bei registrationRejected / network / rateLimited / unexpected)
E-Mail
[ name@example.com ] Fehler: authEmailInvalid
Passwort
[ •••••••••• (Auge) ] Hinweis: authPasswordRule / Fehler je Regel
Anzeigename
[ Alex 4/30 ] Fehler: authDisplayNameEmpty | TooLong | Invalid
[x] Ich bin mindestens 16 Jahre alt Fehler: authAgeNotConfirmed
[x] Ich habe die <Datenschutzerklärung> gelesen und stimme den <Nutzungsbedingungen> zu
Fehler: authTermsNotAccepted
( Konto erstellen )
<Schon ein Konto? Anmelden>
CheckEmailScreen (/register/check-email, Modus Bestätigung bzw. Reset)
Prüfe dein Postfach (Titel)
Wir haben dir eine E-Mail geschickt, falls ... (Text, bodyLarge)
Der Link ist 1 Stunde gültig. Die E-Mail kann einige Minuten dauern. Schau auch im Spam-Ordner nach.
! Info-Banner "E-Mail wurde erneut gesendet" (nach Resend, auch bei emailSendLimited)
! Fehler-Banner bei rateLimited / network
(nur wenn E-Mail fehlt, z. B. nach Reload:) E-Mail [ ]
( E-Mail erneut senden ) -> nur Modus Bestätigung, gesperrt solange Anfrage läuft
<Zurück zur Anmeldung> (Modus Reset: <Andere E-Mail-Adresse eingeben> -> /forgot-password)
LoginScreen (/login)
Anmelden
! Fehler-Banner: authInvalidCredentials | rateLimited | network (über dem Formular, nie am Feld)
! Info-Banner emailNotConfirmed + Aktion "Bestätigungs-E-Mail erneut senden"
E-Mail [ ]
Passwort [ ••••• (Auge) ]
( Anmelden )
<Passwort vergessen?>
<Konto erstellen>
ForgotPasswordScreen (/forgot-password)
Passwort zurücksetzen
Gib die E-Mail-Adresse deines Kontos ein. Wir senden dir einen Link zum Zurücksetzen.
E-Mail [ ] Fehler: authEmailInvalid
( Link senden )
<Zurück zur Anmeldung>
EmailLinkScreen (/auth/confirm)
Zustände: idle (Knopf), submitting, success (nur Bestätigung), error (Link ungültig).
E-Mail-Adresse bestätigen | Neues Passwort festlegen (Titel je Typ)
Ein Klick genügt, um fortzufahren.
( E-Mail-Adresse bestätigen ) | ( Weiter zum neuen Passwort )
Erfolg: ! Info-Banner "E-Mail bestätigt" (+ Mobile-Web: "Du kannst dich jetzt auch in der App anmelden.")
Fehler: ! Fehler-Banner "Der Link ist abgelaufen ..." ( Neuen Link anfordern )
ResetPasswordScreen (/reset-password)
Neues Passwort festlegen
Neues Passwort
[ ••••••••• (Auge) ] Live-Regeln: authPasswordRule, Fehler je Regel / samePassword
( Passwort speichern )
<Abbrechen> -> signOut
Erfolg: Hinweis authPasswordChanged, dann Weiterleitung nach /
3. Textvorschläge
Ton: du-Form, kurz, sachlich-freundlich, keine Schuldzuweisung. Platzhalter in ICU-Syntax ({n}).
Neutrale Texte (Krit. 4, F12) verraten nie, ob eine Adresse registriert ist.
3.1 Meldungen aus § 4.4 (Fehlerabbildung)
| Schlüssel | de | en |
|---|---|---|
authErrorInvalidCredentials |
E-Mail-Adresse oder Passwort ist nicht korrekt. | Email address or password is incorrect. |
authErrorEmailNotConfirmed |
Bestätige zuerst deine E-Mail-Adresse. Wir haben dir dazu eine E-Mail geschickt. | Please confirm your email address first. We sent you an email for this. |
authActionResendConfirmation |
Bestätigungs-E-Mail erneut senden | Resend confirmation email |
authErrorRateLimited |
Zu viele Versuche. Bitte warte einige Minuten und versuche es erneut. | Too many attempts. Please wait a few minutes and try again. |
authErrorWeakPasswordLength |
Das Passwort ist zu kurz. | The password is too short. |
authErrorWeakPasswordCharacters |
Das Passwort ist zu einfach. Wähle ein anderes. | The password is too simple. Choose a different one. |
authErrorWeakPasswordPwned |
Dieses Passwort ist sehr verbreitet und leicht zu erraten. Wähle ein anderes. | This password is very common and easy to guess. Choose a different one. |
authErrorSamePassword |
Wähle ein anderes als dein bisheriges Passwort. | Choose a password different from your current one. |
authErrorLinkInvalidOrExpired |
Der Link ist abgelaufen oder wurde schon benutzt. | The link has expired or has already been used. |
authActionRequestNewLink |
Neuen Link anfordern | Request a new link |
authErrorEmailInvalid |
Gib eine gültige E-Mail-Adresse ein. | Enter a valid email address. |
authErrorRegistrationRejected |
Registrierung nicht möglich. Bitte prüfe deine Angaben. | Registration is not possible. Please check your details. |
authErrorNetwork |
Keine Verbindung. Für diesen Schritt brauchst du Internet. | No connection. You need internet access for this step. |
authErrorUnexpected |
Etwas ist schiefgelaufen. Bitte versuche es erneut. | Something went wrong. Please try again. |
authActionRetry |
Erneut versuchen | Try again |
emailSendLimited hat bewusst keinen eigenen Text: Register/Forgot/CheckEmail zeigen den neutralen Erfolgstext
(§ 3.3), nur der Resend im LoginScreen zeigt authErrorRateLimited.
3.2 Meldungen aus § 5.4 (Felder, Banner, Hinweise)
| Schlüssel | de | en |
|---|---|---|
authPasswordTooShort |
Mindestens 10 Zeichen – {missing, plural, =1{es fehlt noch 1 Zeichen} other{es fehlen noch {missing} Zeichen}}. | At least 10 characters – {missing, plural, =1{1 more character needed} other{{missing} more characters needed}}. |
authPasswordCommon |
Dieses Passwort ist sehr verbreitet und leicht zu erraten. Wähle ein anderes. | This password is very common and easy to guess. Choose a different one. |
authPasswordRule |
Mindestens 10 Zeichen. Kein sehr verbreitetes Passwort. | At least 10 characters. Not a very common password. |
authPasswordRequired |
Gib ein Passwort ein. | Enter a password. |
authDisplayNameEmpty |
Gib einen Anzeigenamen ein. | Enter a display name. |
authDisplayNameTooLong |
Der Anzeigename darf höchstens {max} Zeichen lang sein. | The display name can be at most {max} characters long. |
authDisplayNameInvalid |
Dieser Anzeigename ist nicht erlaubt. Verwende sichtbare Zeichen. | This display name is not allowed. Use visible characters. |
authAgeNotConfirmed |
Shuffle ist erst ab 16 Jahren nutzbar. | Shuffle can only be used from age 16. |
authTermsNotAccepted |
Bitte stimme Datenschutzerklärung und Nutzungsbedingungen zu. | Please agree to the privacy policy and the terms of use. |
authFieldEmailLabel |
E-Mail-Adresse | Email address |
authFieldPasswordLabel |
Passwort | Password |
authFieldNewPasswordLabel |
Neues Passwort | New password |
authFieldDisplayNameLabel |
Anzeigename | Display name |
authPasswordShow |
Passwort anzeigen | Show password |
authPasswordHide |
Passwort verbergen | Hide password |
authCheckboxAgeLabel |
Ich bin mindestens 16 Jahre alt | I am at least 16 years old |
authCheckboxTermsPrefix |
Ich habe die | I have read the |
authCheckboxTermsPrivacyLink |
Datenschutzerklärung | privacy policy |
authCheckboxTermsMiddle |
gelesen und stimme den | and agree to the |
authCheckboxTermsTermsLink |
Nutzungsbedingungen | terms of use |
authCheckboxTermsSuffix |
zu | (leer) |
authBannerTypeError |
Fehler | Error |
authBannerTypeInfo |
Hinweis | Note |
authSubmitting |
Bitte warten … | Please wait … |
Hinweis zur Checkbox „Nutzungsbedingungen“: Satzbau ist je Sprache verschieden. Der Satz wird deshalb aus den
Segmenten Prefix, PrivacyLink, Middle, TermsLink, Suffix zusammengesetzt (AppCheckboxField.rich);
im Englischen bleibt Suffix leer. Alternativ ein ICU-Satz mit Platzhaltern, den der Screen an den Linkstellen
teilt – Entscheidung beim flutter-dev (A2).
3.3 Screen-Texte
| Schlüssel | de | en |
|---|---|---|
authRegisterTitle |
Konto erstellen | Create account |
authRegisterSubmit |
Konto erstellen | Create account |
authRegisterHaveAccount |
Schon ein Konto? Anmelden | Already have an account? Sign in |
authCheckEmailTitle |
Prüfe dein Postfach | Check your inbox |
authCheckEmailBody |
Wir haben dir eine E-Mail geschickt, falls die Adresse noch nicht registriert ist. Folge dem Link darin, um fortzufahren. | We sent you an email if the address is not registered yet. Follow the link in it to continue. |
authCheckEmailBodyReset |
Wir haben dir eine E-Mail mit einem Link zum Zurücksetzen geschickt, falls zu dieser Adresse ein Konto besteht. | We sent you an email with a reset link if an account exists for this address. |
authCheckEmailDelayHint |
Die E-Mail kann einige Minuten dauern. Schau auch im Spam-Ordner nach. | The email can take a few minutes. Also check your spam folder. |
authCheckEmailValidity |
Der Link ist {duration} gültig. | The link is valid for {duration}. |
authCheckEmailValidityOneHour |
1 Stunde | 1 hour |
authCheckEmailResend |
E-Mail erneut senden | Resend email |
authCheckEmailResent |
Wir haben die E-Mail erneut gesendet, falls es zu dieser Adresse etwas zu senden gibt. | We resent the email, if there is something to send for this address. |
authCheckEmailDifferentAddress |
Andere E-Mail-Adresse eingeben | Enter a different email address |
authBackToLogin |
Zurück zur Anmeldung | Back to sign in |
authLoginTitle |
Anmelden | Sign in |
authLoginSubmit |
Anmelden | Sign in |
authLoginForgotPassword |
Passwort vergessen? | Forgot password? |
authLoginCreateAccount |
Konto erstellen | Create account |
authForgotTitle |
Passwort zurücksetzen | Reset password |
authForgotBody |
Gib die E-Mail-Adresse deines Kontos ein. Wir senden dir einen Link zum Zurücksetzen. | Enter the email address of your account. We will send you a reset link. |
authForgotSubmit |
Link senden | Send link |
authConfirmTitle |
E-Mail-Adresse bestätigen | Confirm email address |
authConfirmBody |
Ein Klick genügt, um deine E-Mail-Adresse zu bestätigen. | One click is enough to confirm your email address. |
authConfirmSubmit |
E-Mail-Adresse bestätigen | Confirm email address |
authConfirmSuccess |
E-Mail bestätigt. | Email confirmed. |
authConfirmSuccessMobileWeb |
Du kannst dich jetzt auch in der App anmelden. | You can now also sign in in the app. |
authRecoveryTitle |
Neues Passwort festlegen | Set a new password |
authRecoveryBody |
Ein Klick genügt, um ein neues Passwort festzulegen. | One click is enough to set a new password. |
authRecoverySubmit |
Weiter zum neuen Passwort | Continue to new password |
authResetTitle |
Neues Passwort festlegen | Set a new password |
authResetSubmit |
Passwort speichern | Save password |
authResetCancel |
Abbrechen | Cancel |
authPasswordChanged |
Passwort geändert. Andere Geräte werden abgemeldet; das kann bis zu einer Stunde dauern. | Password changed. Other devices will be signed out; this can take up to an hour. |
4. Barrierefreiheit pro Screen (Checkliste für A2–A4 und T2)
- Jedes Feld hat ein sichtbares Label (kein Platzhalter-Label); Fehler per
errorText(Icon + Text + Live-Region). - Banner und Fehler werden beim Erscheinen vorgelesen (Live-Region); keine reinen Farb-Signale.
- Passwortfelder:
AppPasswordFieldmitisNewPassword: truebei Register/Reset, sonstfalse; E-Mail mitAutofillHints.email(Login:AutofillHints.username/email),TextInputType.emailAddress. - Links in Checkbox-Sätzen (
AppCheckboxField.rich) sind eigene Semantics-Knoten (link: true, Label = Linktext, Tap), keine Custom Actions (Flutter-Web setzt diese nicht in ARIA um). Der Checkbox-Knoten trägt den ganzen Satz. - Meldungen, die sich bei jedem Tastendruck ändern („es fehlen noch n“), sind während des Tippens keine Live-Region
(
liveError: false) und werden beim Verlassen des Feldes angesagt; der sichtbare Text bleibt. - Alle interaktiven Elemente >= 48 dp, Tab-Reihenfolge wie Lesereihenfolge, Fokus sichtbar.
- Test je Screen mit
textScaler2.0 (Android 320 x 640),androidTapTargetGuideline,labeledTapTargetGuideline,textContrastGuideline, Hell und Dunkel (T2).