Deliver localized auth app with verification and go_router

Integrate themed login/signup, EN/RU localization, shared dummy providers, verification recovery screens and named URL routes. Store frontend guidelines, workflow skills, validation and delivery documentation. Related to #2, #3, #5 and #6.
This commit is contained in:
Stephan D committed 2026-09-11 15:37:07 +02:00
1 parent 27424ed886
commit 10a278c65a
44 files changed
+4128 -28

No files matched your search

@@ -0,0 +1,530 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart' as intl;
import 'app_localizations_en.dart';
import 'app_localizations_ru.dart';
// ignore_for_file: type=lint
/// Callers can lookup localized strings with an instance of AppLocalizations
/// returned by `AppLocalizations.of(context)`.
///
/// Applications need to include `AppLocalizations.delegate()` in their app's
/// `localizationDelegates` list, and the locales they support in the app's
/// `supportedLocales` list. For example:
///
/// ```dart
/// import 'i18n/app_localizations.dart';
///
/// return MaterialApp(
/// localizationsDelegates: AppLocalizations.localizationsDelegates,
/// supportedLocales: AppLocalizations.supportedLocales,
/// home: MyApplicationHome(),
/// );
/// ```
///
/// ## Update pubspec.yaml
///
/// Please make sure to update your pubspec.yaml to include the following
/// packages:
///
/// ```yaml
/// dependencies:
/// # Internationalization support.
/// flutter_localizations:
/// sdk: flutter
/// intl: any # Use the pinned version from flutter_localizations
///
/// # Rest of dependencies
/// ```
///
/// ## iOS Applications
///
/// iOS applications define key application metadata, including supported
/// locales, in an Info.plist file that is built into the application bundle.
/// To configure the locales supported by your app, you’ll need to edit this
/// file.
///
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
/// Then, in the Project Navigator, open the Info.plist file under the Runner
/// project’s Runner folder.
///
/// Next, select the Information Property List item, select Add Item from the
/// Editor menu, then select Localizations from the pop-up menu.
///
/// Select and expand the newly-created Localizations item then, for each
/// locale your application supports, add a new item and select the locale
/// you wish to add from the pop-up menu in the Value field. This list should
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property.
abstract class AppLocalizations {
AppLocalizations(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
///
/// Returns a list of localizations delegates containing this delegate along with
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
/// and GlobalWidgetsLocalizations.delegate.
///
/// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
<LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
/// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[
Locale('en'),
Locale('ru'),
];
/// No description provided for @appTitle.
///
/// In en, this message translates to:
/// **'SXCHNGE · Your next move'**
String get appTitle;
/// No description provided for @nextChapter.
///
/// In en, this message translates to:
/// **'YOUR NEXT CHAPTER'**
String get nextChapter;
/// No description provided for @loginHeading.
///
/// In en, this message translates to:
/// **'Hey, welcome\nback.'**
String get loginHeading;
/// No description provided for @signupHeading.
///
/// In en, this message translates to:
/// **'Make your\nfirst move.'**
String get signupHeading;
/// No description provided for @loginIntro.
///
/// In en, this message translates to:
/// **'Your next move is just a login away.'**
String get loginIntro;
/// No description provided for @signupIntro.
///
/// In en, this message translates to:
/// **'A new account. A world of possibility.'**
String get signupIntro;
/// No description provided for @login.
///
/// In en, this message translates to:
/// **'Log in'**
String get login;
/// No description provided for @signup.
///
/// In en, this message translates to:
/// **'Sign up'**
String get signup;
/// No description provided for @name.
///
/// In en, this message translates to:
/// **'Your name'**
String get name;
/// No description provided for @email.
///
/// In en, this message translates to:
/// **'Email address'**
String get email;
/// No description provided for @emailHint.
///
/// In en, this message translates to:
/// **'you@example.com'**
String get emailHint;
/// No description provided for @password.
///
/// In en, this message translates to:
/// **'Password'**
String get password;
/// No description provided for @confirmPassword.
///
/// In en, this message translates to:
/// **'Confirm password'**
String get confirmPassword;
/// No description provided for @passwordHint.
///
/// In en, this message translates to:
/// **'Use at least 12 characters.'**
String get passwordHint;
/// No description provided for @showPassword.
///
/// In en, this message translates to:
/// **'Show password'**
String get showPassword;
/// No description provided for @hidePassword.
///
/// In en, this message translates to:
/// **'Hide password'**
String get hidePassword;
/// No description provided for @showConfirmation.
///
/// In en, this message translates to:
/// **'Show confirmation'**
String get showConfirmation;
/// No description provided for @hideConfirmation.
///
/// In en, this message translates to:
/// **'Hide confirmation'**
String get hideConfirmation;
/// No description provided for @createAccount.
///
/// In en, this message translates to:
/// **'Create account'**
String get createAccount;
/// No description provided for @letsGo.
///
/// In en, this message translates to:
/// **'Let’s go'**
String get letsGo;
/// No description provided for @loginPreview.
///
/// In en, this message translates to:
/// **'Demo login completed. No real session was created. Your credentials have not been sent or saved.'**
String get loginPreview;
/// No description provided for @signupPreview.
///
/// In en, this message translates to:
/// **'Demo sign-up completed. No real account was created. Your credentials have not been sent or saved.'**
String get signupPreview;
/// No description provided for @alreadyMember.
///
/// In en, this message translates to:
/// **'Already part of sxchnge?'**
String get alreadyMember;
/// No description provided for @newHere.
///
/// In en, this message translates to:
/// **'New around here?'**
String get newHere;
/// No description provided for @loginInstead.
///
/// In en, this message translates to:
/// **'Log in instead'**
String get loginInstead;
/// No description provided for @createAnAccount.
///
/// In en, this message translates to:
/// **'Create an account'**
String get createAnAccount;
/// No description provided for @earlyPreview.
///
/// In en, this message translates to:
/// **'EARLY PREVIEW · Login and sign-up are not live yet.'**
String get earlyPreview;
/// No description provided for @brandEyebrow.
///
/// In en, this message translates to:
/// **'A LITTLE CHANGE. A BIG NEXT STEP.'**
String get brandEyebrow;
/// No description provided for @brandHeading.
///
/// In en, this message translates to:
/// **'Good moves.\nStart here.'**
String get brandHeading;
/// No description provided for @brandIntro.
///
/// In en, this message translates to:
/// **'A fresh way forward.\nMake it yours with sxchnge.'**
String get brandIntro;
/// No description provided for @brandCard.
///
/// In en, this message translates to:
/// **'Less friction.\nMore possibility.'**
String get brandCard;
/// No description provided for @brandFooter.
///
/// In en, this message translates to:
/// **'YOUR NEXT MOVE STARTS WITH YOU.'**
String get brandFooter;
/// No description provided for @emailRequired.
///
/// In en, this message translates to:
/// **'Enter your email address.'**
String get emailRequired;
/// No description provided for @emailInvalid.
///
/// In en, this message translates to:
/// **'Enter a valid email address.'**
String get emailInvalid;
/// No description provided for @nameRequired.
///
/// In en, this message translates to:
/// **'Enter your name.'**
String get nameRequired;
/// No description provided for @passwordRequired.
///
/// In en, this message translates to:
/// **'Enter your password.'**
String get passwordRequired;
/// No description provided for @confirmationRequired.
///
/// In en, this message translates to:
/// **'Confirm your password.'**
String get confirmationRequired;
/// No description provided for @passwordMismatch.
///
/// In en, this message translates to:
/// **'Passwords do not match.'**
String get passwordMismatch;
/// No description provided for @language.
///
/// In en, this message translates to:
/// **'Language'**
String get language;
/// No description provided for @preferenceNotSaved.
///
/// In en, this message translates to:
/// **'Language changed for this session. Your preference could not be saved.'**
String get preferenceNotSaved;
/// No description provided for @authWorking.
///
/// In en, this message translates to:
/// **'Please wait…'**
String get authWorking;
/// No description provided for @authCompleted.
///
/// In en, this message translates to:
/// **'Request completed.'**
String get authCompleted;
/// No description provided for @authInvalidCredentials.
///
/// In en, this message translates to:
/// **'Email or password is incorrect. Please try again.'**
String get authInvalidCredentials;
/// No description provided for @authEmailInUse.
///
/// In en, this message translates to:
/// **'This email is already registered. Try logging in.'**
String get authEmailInUse;
/// No description provided for @authUnavailable.
///
/// In en, this message translates to:
/// **'The service is unavailable. Please try again.'**
String get authUnavailable;
/// No description provided for @authUnexpected.
///
/// In en, this message translates to:
/// **'Something went wrong. Please try again.'**
String get authUnexpected;
/// No description provided for @checkInbox.
///
/// In en, this message translates to:
/// **'Check your inbox.'**
String get checkInbox;
/// No description provided for @verificationSent.
///
/// In en, this message translates to:
/// **'We’ve sent you a verification email. Open the link in your inbox to confirm your email address.'**
String get verificationSent;
/// No description provided for @verificationSending.
///
/// In en, this message translates to:
/// **'Preparing your verification email…'**
String get verificationSending;
/// No description provided for @verificationChecking.
///
/// In en, this message translates to:
/// **'Verifying your email…'**
String get verificationChecking;
/// No description provided for @verificationVerified.
///
/// In en, this message translates to:
/// **'Your email\nis verified.'**
String get verificationVerified;
/// No description provided for @verificationVerifiedBody.
///
/// In en, this message translates to:
/// **'One step done. You can now return to login. Identity verification is a separate step.'**
String get verificationVerifiedBody;
/// No description provided for @verificationExpired.
///
/// In en, this message translates to:
/// **'This link has expired.'**
String get verificationExpired;
/// No description provided for @verificationExpiredBody.
///
/// In en, this message translates to:
/// **'Request a new verification email and use the latest link.'**
String get verificationExpiredBody;
/// No description provided for @verificationInvalid.
///
/// In en, this message translates to:
/// **'This link isn’t valid.'**
String get verificationInvalid;
/// No description provided for @verificationInvalidBody.
///
/// In en, this message translates to:
/// **'The confirmation link is missing or invalid. Open the complete link from your email, or request a new one.'**
String get verificationInvalidBody;
/// No description provided for @verificationInternal.
///
/// In en, this message translates to:
/// **'Something went wrong.'**
String get verificationInternal;
/// No description provided for @verificationInternalBody.
///
/// In en, this message translates to:
/// **'We couldn’t complete your request because of an internal error. Please try again.'**
String get verificationInternalBody;
/// No description provided for @verificationResend.
///
/// In en, this message translates to:
/// **'Resend verification email'**
String get verificationResend;
/// No description provided for @verificationRequest.
///
/// In en, this message translates to:
/// **'Send a new verification email'**
String get verificationRequest;
/// No description provided for @verificationRetry.
///
/// In en, this message translates to:
/// **'Try again'**
String get verificationRetry;
/// No description provided for @verificationBack.
///
/// In en, this message translates to:
/// **'Back to login'**
String get verificationBack;
/// No description provided for @verificationHint.
///
/// In en, this message translates to:
/// **'No email? Check your spam folder or request another below.'**
String get verificationHint;
/// No description provided for @verificationDemo.
///
/// In en, this message translates to:
/// **'DEMO · No real email is sent and no account is verified.'**
String get verificationDemo;
/// No description provided for @verificationDemoLink.
///
/// In en, this message translates to:
/// **'Open demo confirmation link'**
String get verificationDemoLink;
/// No description provided for @verificationStep.
///
/// In en, this message translates to:
/// **'CONFIRM YOUR EMAIL'**
String get verificationStep;
}
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
Future<AppLocalizations> load(Locale locale) {
return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
}
@override
bool isSupported(Locale locale) =>
<String>['en', 'ru'].contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified.
switch (locale.languageCode) {
case 'en':
return AppLocalizationsEn();
case 'ru':
return AppLocalizationsRu();
}
throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.',
);
}