- Complete MVP with Repository Pattern, SQLite storage - Provider + ChangeNotifier state management - Navigation 2.0 with deep link support - Habit CRUD with twoDayRule, notifications, categories - Backup/Restore via JSON - Statistics with streak tracking - Material You theme support - Biometric lock support - Desktop widget support - 27 languages i18n structure - Comprehensive test suite (87/89 passing)
283 lines
14 KiB
Dart
283 lines
14 KiB
Dart
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;
|
|
|
|
/// Stub localization class for testing.
|
|
/// The actual implementation is generated by flutter gen-l10n.
|
|
class S {
|
|
S([String locale = 'en']) : localeName = locale;
|
|
|
|
final String localeName;
|
|
|
|
static S? _current;
|
|
static S get current {
|
|
if (_current == null) {
|
|
_current = S();
|
|
}
|
|
return _current!;
|
|
}
|
|
|
|
static S of(BuildContext context) {
|
|
return current;
|
|
}
|
|
|
|
static Future<S> load(Locale locale) {
|
|
_current = S(locale.toString());
|
|
return SynchronousFuture<S>(current);
|
|
}
|
|
|
|
static const LocalizationsDelegate<S> delegate = _SDelegate();
|
|
|
|
String get habits => 'Habits:';
|
|
String get statistics => 'Statistics';
|
|
String get emptyList => 'Empty list';
|
|
String get noDataAboutHabits => 'There is no data about habits.';
|
|
String get topStreak => 'Top streak';
|
|
String get currentStreak => 'Current streak';
|
|
String get total => 'Total';
|
|
String get unknown => 'Unknown';
|
|
String get warning => 'Warning';
|
|
String get allHabitsWillBeReplaced => 'All habits will be replaced with habits from backup.';
|
|
String get restore => 'Restore';
|
|
String get cancel => 'Cancel';
|
|
String get settings => 'Settings';
|
|
String get theme => 'Theme';
|
|
String get firstDayOfWeek => 'First day of the week';
|
|
String get notifications => 'Notifications';
|
|
String get notificationTime => 'Notification time';
|
|
String get soundEffects => 'Sound effects';
|
|
String get showMonthName => 'Show month name';
|
|
String get setColors => 'Set colors';
|
|
String get backup => 'Backup';
|
|
String get create => 'Create';
|
|
String get onboarding => 'Onboarding';
|
|
String get about => 'About';
|
|
String get habo => 'Habo';
|
|
String get copyright => '©2023 Habo';
|
|
String get termsAndConditions => 'Terms and Conditions';
|
|
String get privacyPolicy => 'Privacy Policy';
|
|
String get disclaimer => 'Disclaimer';
|
|
String get sourceCode => 'Source code (GitHub)';
|
|
String get ifYouWantToSupport => 'If you want to support Habo you can:';
|
|
String get buyMeACoffee => 'Buy me a coffee';
|
|
String get reset => 'Reset';
|
|
String get done => 'Done';
|
|
String get congratulationsReward => 'Congratulations! Your reward:';
|
|
String get ohNoSanction => 'Oh no! Your sanction:';
|
|
String get month => 'Month';
|
|
String get week => 'Week';
|
|
String get habitLoop => 'Habit loop';
|
|
String get habitLoopDescription => 'Habit Loop is a psychological model describing the process of habit formation.';
|
|
String get cue => 'Cue';
|
|
String get cueDescription => 'is the trigger that initiates your habit.';
|
|
String get routine => 'Routine';
|
|
String get routineDescription => 'is the action you take in response to the cue.';
|
|
String get reward => 'Reward';
|
|
String get rewardDescription => 'is the benefit or positive feeling you experience after performing the routine.';
|
|
String get editHabit => 'Edit Habit';
|
|
String get createHabit => 'Create Habit';
|
|
String get delete => 'Delete';
|
|
String get habitTitleEmptyError => 'The habit title can not be empty.';
|
|
String get save => 'Save';
|
|
String get exercise => 'Exercise';
|
|
String get habit => 'Habit';
|
|
String get useTwoDayRule => 'Use Two day rule';
|
|
String get twoDayRule => 'Two day rule';
|
|
String get twoDayRuleDescription => 'With two day rule, you can miss one day and do not lose a streak if the next day is successful.';
|
|
String get advancedHabitBuilding => 'Advanced habit building';
|
|
String get advancedHabitBuildingDescription => 'This section helps you better define your habits utilizing the Habit loop.';
|
|
String get at7AM => 'At 7:00AM';
|
|
String get do50PushUps => 'Do 50 push ups';
|
|
String get fifteenMinOfVideoGames => '15 min. of video games';
|
|
String get showReward => 'Show reward';
|
|
String get remainderOfReward => 'The reminder of the reward after a successful routine.';
|
|
String get habitContract => 'Habit contract';
|
|
String get habitContractDescription => 'While positive reinforcement is recommended, some people may opt for a habit contract.';
|
|
String get donateToCharity => 'Donate 10\$ to charity';
|
|
String get sanction => 'Sanction';
|
|
String get showSanction => 'Show sanction';
|
|
String get remainderOfSanction => 'The reminder of the sanction after a unsuccessful routine.';
|
|
String get dan => 'Dan';
|
|
String get accountabilityPartner => 'Accountability partner';
|
|
String get add => 'Add';
|
|
String get haboNeedsPermission => 'Habo needs permission to send notifications to work properly.';
|
|
String get allow => 'Allow';
|
|
String get date => 'Date';
|
|
String get check => 'Check';
|
|
String get fail => 'Fail';
|
|
String get skip => 'Skip';
|
|
String get note => 'Note';
|
|
String get yourCommentHere => 'Your note here';
|
|
String get close => 'Close';
|
|
String get createYourFirstHabit => 'Create your first habit.';
|
|
String get modify => 'Modify';
|
|
String get backupFailedError => 'ERROR: Creating backup failed.';
|
|
String get restoreFailedError => 'ERROR: Restoring backup failed.';
|
|
String get habitDeleted => 'Habit deleted.';
|
|
String get undo => 'Undo';
|
|
String get appNotifications => 'App notifications';
|
|
String get appNotificationsChannel => 'Notification channel for application notifications';
|
|
String get habitNotifications => 'Habit notifications';
|
|
String get habitNotificationsChannel => 'Notification channel for habit notifications';
|
|
String get doNotForgetToCheckYourHabits => 'Do not forget to check your habits.';
|
|
String themeSelect(String theme) => theme;
|
|
String get defineYourHabits => 'Define your habits';
|
|
String get defineYourHabitsDescription => 'To better stick to your habits, you can define:';
|
|
String get cueNumbered => '1. Cue';
|
|
String get routineNumbered => '2. Routine';
|
|
String get rewardNumbered => '3. Reward';
|
|
String get logYourDays => 'Log your days';
|
|
String get successful => 'Successful';
|
|
String get notSoSuccessful => 'Not so successful';
|
|
String get skipDoesNotAffectStreaks => 'Skip (does not affect streaks)';
|
|
String get observeYourProgress => 'Observe your progress';
|
|
String get trackYourProgress => 'You can track your progress through the calendar view in every habit or on the statistics page.';
|
|
String get backupCreatedSuccessfully => 'Backup created successfully!';
|
|
String get backupFailed => 'Backup failed!';
|
|
String get restoreCompletedSuccessfully => 'Restore completed successfully!';
|
|
String get restoreFailed => 'Restore failed!';
|
|
String get fileNotFound => 'File not found';
|
|
String get fileTooLarge => 'File too large (max 10MB)';
|
|
String get invalidBackupFile => 'Invalid backup file';
|
|
String get progress => 'Progress';
|
|
String get enterAmount => 'Enter amount';
|
|
String get complete => 'Complete';
|
|
String get saveProgress => 'Save Progress';
|
|
String currentProgress(String current, String unit) => 'Current: $current $unit';
|
|
String targetProgress(String target, String unit) => 'Target: $target $unit';
|
|
String progressOf(String current, String target, String unit) => '$current / $target $unit';
|
|
String get numericHabit => 'Progressive';
|
|
String get targetValue => 'Target value';
|
|
String get partialValue => 'Partial value';
|
|
String get unit => 'Unit';
|
|
String get habitType => 'Habit type';
|
|
String get booleanHabit => 'Checkable (Yes/No)';
|
|
String get slider => 'Slider';
|
|
String get input => 'Input';
|
|
String get numericHabitDescription => 'Numeric habits let you track progress in increments throughout the day.';
|
|
String get partialValueDescription => 'To track progress in smaller increments';
|
|
String get categories => 'Categories';
|
|
String get addCategory => 'Add Category';
|
|
String get editCategory => 'Edit Category';
|
|
String get category => 'Category';
|
|
String get noCategoriesYet => 'No categories yet';
|
|
String get createFirstCategory => 'Create your first category to organize your habits';
|
|
String get pleaseEnterCategoryTitle => 'Please enter a category title';
|
|
String categoryAlreadyExists(String title) => 'Category "$title" already exists';
|
|
String categoryCreatedSuccessfully(String title) => 'Category "$title" created successfully';
|
|
String categoryUpdatedSuccessfully(String title) => 'Category "$title" updated successfully';
|
|
String categoryDeletedSuccessfully(String title) => 'Category "$title" deleted successfully';
|
|
String failedToSaveCategory(String error) => 'Failed to save category: $error';
|
|
String failedToDeleteCategory(String error) => 'Failed to delete category: $error';
|
|
String get selectCategories => 'Select Categories';
|
|
String selectedCategories(int count) => 'Selected Categories ($count)';
|
|
String get allCategories => 'All Categories';
|
|
String get deleteCategory => 'Delete Category';
|
|
String deleteCategoryConfirmation(String title) => 'Are you sure you want to delete "$title"?';
|
|
String noHabitsInCategory(String title) => 'No habits in "$title"';
|
|
String get createHabitForCategory => 'Create a habit and assign it to this category';
|
|
String get showCategories => 'Show Categories';
|
|
String get archive => 'Archive';
|
|
String get unarchive => 'Unarchive';
|
|
String get archiveHabit => 'Archive habit';
|
|
String get unarchiveHabit => 'Unarchive habit';
|
|
String get archivedHabits => 'Archived Habits';
|
|
String get noArchivedHabits => 'No archived habits';
|
|
String get viewArchivedHabits => 'View archived habits';
|
|
String get habitArchived => 'Habit archived';
|
|
String get habitUnarchived => 'Habit unarchived';
|
|
String get biometric => 'Biometric';
|
|
String get biometricLockEnabled => 'Biometric lock enabled';
|
|
String get biometricLockDisabled => 'Biometric lock disabled';
|
|
String get authenticationError => 'Authentication error';
|
|
String get biometricAuthenticationRequired => 'Biometric authentication required';
|
|
String get setupFingerprintFaceUnlock => 'Please set up your fingerprint or face unlock in device settings';
|
|
String get touchSensor => 'Touch sensor';
|
|
String get biometricNotRecognized => 'Biometric not recognized, try again';
|
|
String get biometricRequired => 'Biometric required';
|
|
String get biometricAuthenticationSucceeded => 'Biometric authentication succeeded';
|
|
String get deviceCredentialsRequired => 'Device credentials required';
|
|
String get setupDeviceCredentials => 'Please set up device credentials in settings';
|
|
String get setupTouchIdFaceId => 'Please set up your Touch ID or Face ID in device settings';
|
|
String get reenableTouchIdFaceId => 'Please reenable your Touch ID or Face ID';
|
|
String get biometricLock => 'Biometric Lock';
|
|
String biometricLockDescription(String authMethod) => 'Secure app with $authMethod';
|
|
String get authenticateToEnable => 'Authenticate to enable biometric lock';
|
|
String get authenticateToAccess => 'Please authenticate to access Habo';
|
|
String get authenticationRequired => 'Authentication Required';
|
|
String authenticationFailedMessage(String authMethod) => 'Please authenticate to access Habo using $authMethod';
|
|
String get tryAgain => 'Try Again';
|
|
String get authenticating => 'Authenticating…';
|
|
String get authenticate => 'Authenticate';
|
|
String get buildingBetterHabits => 'Building Better Habits';
|
|
String authenticationPrompt(String authMethod) => 'Please authenticate using $authMethod to access your habits';
|
|
String get devicePinPatternPassword => 'Device PIN, Pattern, or Password';
|
|
String get fingerprint => 'Fingerprint';
|
|
String get iris => 'Iris';
|
|
String get whatsNewTitle => "What's New";
|
|
String whatsNewVersion(String version) => 'Version $version';
|
|
String get featureNumericTitle => 'Numeric values in habits';
|
|
String get featureNumericDesc => 'Track counts like glasses of water or pages read';
|
|
String get featureDeepLinksTitle => 'URL scheme (deep links)';
|
|
String get featureDeepLinksDesc => 'Open Habo directly to screens like settings or create';
|
|
String get featureCategoriesTitle => 'Categories';
|
|
String get featureCategoriesDesc => 'Organize habits with category filters';
|
|
String get featureArchiveTitle => 'Archive';
|
|
String get featureArchiveDesc => 'Hide habits you no longer track without deleting';
|
|
String get featureMaterialYouTitle => 'Material You theme (Android)';
|
|
String get featureMaterialYouDesc => 'Dynamic colors that match your wallpaper';
|
|
String get featureSoundTitle => 'New sound engine';
|
|
String get featureSoundDesc => 'Adjustable volume';
|
|
String get featureLockTitle => 'Lock feature';
|
|
String get featureLockDesc => 'Secure the app with Face ID / Touch ID / biometrics';
|
|
String get featureIosSoundMixingTitle => 'Fixed sound mixing';
|
|
String get featureIosSoundMixingDesc => 'Habo sounds no longer interrupt your music or podcasts';
|
|
String get featureHomescreenWidgetTitle => 'Homescreen widget';
|
|
String get featureHomescreenWidgetDesc => 'View your habit progress at a glance from your home screen (experimental)';
|
|
String get featureLongpressCheckTitle => 'Longpress check';
|
|
String get featureLongpressCheckDesc => 'Longpress on habit buttons to quickly change status';
|
|
String get haboSyncComingSoon => 'Coming Soon';
|
|
String get haboSyncDescription => "Sync your habits across all your devices with Habo's end-to-end encrypted cloud service.";
|
|
String get haboSyncLearnMore => 'Learn more at habo.space/sync';
|
|
String get habitsToday => 'Habits today';
|
|
String get or => 'or';
|
|
String get oneTapCheck => 'Single tap to check';
|
|
String get tapCheckLongPressMenu => 'Tap to check, long press for menu';
|
|
String get categoryName => 'Category name';
|
|
String get createCategory => 'Create category';
|
|
String get all => 'All';
|
|
String get selectIcon => 'Pick an icon';
|
|
String get searchIcons => 'Search';
|
|
String get habitArchivedSuccess => 'Habit archived';
|
|
String get habitUnarchivedSuccess => 'Habit unarchived';
|
|
}
|
|
|
|
class _SDelegate extends LocalizationsDelegate<S> {
|
|
const _SDelegate();
|
|
|
|
@override
|
|
Future<S> load(Locale locale) => S.load(locale);
|
|
|
|
@override
|
|
bool isSupported(Locale locale) => true;
|
|
|
|
@override
|
|
bool shouldReload(_SDelegate old) => false;
|
|
}
|
|
|
|
class AppLocalizations {
|
|
static const LocalizationsDelegate<S> delegate = S.delegate;
|
|
static S of(BuildContext context) => S.of(context);
|
|
static List<LocalizationsDelegate<dynamic>> localizationsDelegates = [
|
|
S.delegate,
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
];
|
|
static List<Locale> supportedLocales = [
|
|
const Locale('en'),
|
|
];
|
|
}
|