Replace the OpenRouter HTTP client with a DeepSeek client: - data/openrouter/ -> data/deepseek/; OpenRouterClient -> DeepSeekClient (+ DeepSeekCompletion / DeepSeek*Exception) - base URL api.deepseek.com, drop OpenRouter-only headers - DeepSeek has no strict json_schema: use response_format json_object and rely on the prompt for shape (ai_schema.dart removed) - secure-storage key openrouter_api_key -> deepseek_api_key - default model deepseek/deepseek-v4-flash -> deepseek-chat - l10n strings, test dart-defines (DEEPSEEK_API_KEY/_TEST_MODEL), docs Also bundles in-progress findBodyIgnoreRule (body-level ignore rules applied before the AI call) already present in the working tree. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1039 lines
22 KiB
Dart
1039 lines
22 KiB
Dart
// ignore: unused_import
|
|
import 'package:intl/intl.dart' as intl;
|
|
import 'app_localizations.dart';
|
|
|
|
// ignore_for_file: type=lint
|
|
|
|
/// The translations for English (`en`).
|
|
class AppLocalizationsEn extends AppLocalizations {
|
|
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
|
|
|
@override
|
|
String get appTitle => 'NewBudget';
|
|
|
|
@override
|
|
String get navHome => 'Home';
|
|
|
|
@override
|
|
String get navAnalytics => 'Analytics';
|
|
|
|
@override
|
|
String get navAccounts => 'Accounts';
|
|
|
|
@override
|
|
String get navProfile => 'Profile';
|
|
|
|
@override
|
|
String get allAccounts => 'All';
|
|
|
|
@override
|
|
String get comingSoon => 'Coming soon';
|
|
|
|
@override
|
|
String get budget => 'BUDGET';
|
|
|
|
@override
|
|
String get balance => 'BALANCE';
|
|
|
|
@override
|
|
String get income => 'INCOME';
|
|
|
|
@override
|
|
String get expenses => 'EXPENSES';
|
|
|
|
@override
|
|
String get transactions => 'Transactions';
|
|
|
|
@override
|
|
String transactionCount(int count) {
|
|
String _temp0 = intl.Intl.pluralLogic(
|
|
count,
|
|
locale: localeName,
|
|
other: '$count transactions',
|
|
one: '$count transaction',
|
|
);
|
|
return '$_temp0';
|
|
}
|
|
|
|
@override
|
|
String get allCategoriesFilter => 'All categories · all types';
|
|
|
|
@override
|
|
String get filterByCategories => 'Filter by category';
|
|
|
|
@override
|
|
String get clearFilter => 'Clear';
|
|
|
|
@override
|
|
String get selectAll => 'Select all';
|
|
|
|
@override
|
|
String categoriesSelectedCount(int count) {
|
|
String _temp0 = intl.Intl.pluralLogic(
|
|
count,
|
|
locale: localeName,
|
|
other: '$count categories',
|
|
one: '$count category',
|
|
);
|
|
return '$_temp0';
|
|
}
|
|
|
|
@override
|
|
String moreCategories(int count) {
|
|
String _temp0 = intl.Intl.pluralLogic(
|
|
count,
|
|
locale: localeName,
|
|
other: '+ $count more →',
|
|
one: '+ $count more →',
|
|
);
|
|
return '$_temp0';
|
|
}
|
|
|
|
@override
|
|
String todayWithDate(String date) {
|
|
return 'Today · $date';
|
|
}
|
|
|
|
@override
|
|
String yesterdayWithDate(String date) {
|
|
return 'Yesterday · $date';
|
|
}
|
|
|
|
@override
|
|
String get analyticsTitle => 'Reports';
|
|
|
|
@override
|
|
String get analyticsSubtitle => 'Analytics';
|
|
|
|
@override
|
|
String get accountsSubtitle => 'Management';
|
|
|
|
@override
|
|
String get profileSubtitle => 'Settings';
|
|
|
|
@override
|
|
String get darkTheme => 'Dark theme';
|
|
|
|
@override
|
|
String get profileLanguageTile => 'Language';
|
|
|
|
@override
|
|
String get langEnglish => 'English';
|
|
|
|
@override
|
|
String get langRussian => 'Russian';
|
|
|
|
@override
|
|
String get profileHint =>
|
|
'User profile, currency, locale and other settings will appear here.';
|
|
|
|
@override
|
|
String get onboardingTitle => 'Welcome';
|
|
|
|
@override
|
|
String get onboardingSubtitle => 'Tell us your name to get started.';
|
|
|
|
@override
|
|
String get onboardingNameLabel => 'Your name';
|
|
|
|
@override
|
|
String get onboardingNameHint => 'How should we address you?';
|
|
|
|
@override
|
|
String get onboardingContinue => 'Continue';
|
|
|
|
@override
|
|
String get txNewTitle => 'New transaction';
|
|
|
|
@override
|
|
String get txEditTitle => 'Edit transaction';
|
|
|
|
@override
|
|
String get txTypeExpense => 'Expense';
|
|
|
|
@override
|
|
String get txTypeIncome => 'Income';
|
|
|
|
@override
|
|
String get txTypeTransfer => 'Transfer';
|
|
|
|
@override
|
|
String get txAmountHint => '0';
|
|
|
|
@override
|
|
String get txCategoryLabel => 'Category';
|
|
|
|
@override
|
|
String get txAccountLabel => 'Account';
|
|
|
|
@override
|
|
String get txAccountFromLabel => 'From';
|
|
|
|
@override
|
|
String get txAccountToLabel => 'To';
|
|
|
|
@override
|
|
String get txDateTimeLabel => 'Date & time';
|
|
|
|
@override
|
|
String get txBalanceAfter => 'Balance after';
|
|
|
|
@override
|
|
String get txTransferAfter => 'After transfer';
|
|
|
|
@override
|
|
String get txNoteLabel => 'Merchant';
|
|
|
|
@override
|
|
String get txNoteHint => 'e.g. Amazon…';
|
|
|
|
@override
|
|
String get txExtraInfoLabel => 'Additional info';
|
|
|
|
@override
|
|
String get txExtraInfoHint => 'e.g. Groceries for the week…';
|
|
|
|
@override
|
|
String get txSaveButton => 'Add transaction';
|
|
|
|
@override
|
|
String get txSaveEditButton => 'Save changes';
|
|
|
|
@override
|
|
String txTransferButton(String amount) {
|
|
return 'Transfer $amount';
|
|
}
|
|
|
|
@override
|
|
String get txDeleteButton => 'Delete';
|
|
|
|
@override
|
|
String get txDeleteConfirmTitle => 'Delete transaction?';
|
|
|
|
@override
|
|
String get txDeleteConfirmMessage => 'This action cannot be undone.';
|
|
|
|
@override
|
|
String get txDeleteConfirmYes => 'Delete';
|
|
|
|
@override
|
|
String get txDeleteConfirmNo => 'Cancel';
|
|
|
|
@override
|
|
String get txPickCategory => 'Pick a category';
|
|
|
|
@override
|
|
String get txPickAccount => 'Pick an account';
|
|
|
|
@override
|
|
String get pickerAccountTitle => 'Account';
|
|
|
|
@override
|
|
String pickerAccountSubtitle(int count) {
|
|
String _temp0 = intl.Intl.pluralLogic(
|
|
count,
|
|
locale: localeName,
|
|
other: '$count accounts',
|
|
one: '$count account',
|
|
);
|
|
return '$_temp0';
|
|
}
|
|
|
|
@override
|
|
String get pickerCategoryTitle => 'Category';
|
|
|
|
@override
|
|
String pickerCategorySubtitle(int count) {
|
|
String _temp0 = intl.Intl.pluralLogic(
|
|
count,
|
|
locale: localeName,
|
|
other: '$count categories',
|
|
one: '$count category',
|
|
);
|
|
return '$_temp0';
|
|
}
|
|
|
|
@override
|
|
String get pickerAddAccount => 'Add account';
|
|
|
|
@override
|
|
String get pickerCreateCategory => 'Create category';
|
|
|
|
@override
|
|
String get comingSoonShort => 'Coming soon';
|
|
|
|
@override
|
|
String get txValidationAmountRequired => 'Enter an amount';
|
|
|
|
@override
|
|
String get txValidationAccountRequired => 'Pick an account';
|
|
|
|
@override
|
|
String get txValidationCategoryRequired => 'Pick a category';
|
|
|
|
@override
|
|
String get txValidationTransferSameAccount =>
|
|
'Source and destination must differ';
|
|
|
|
@override
|
|
String get txValidationTransferDestRequired => 'Pick a destination account';
|
|
|
|
@override
|
|
String get categoriesScreenTitle => 'Categories';
|
|
|
|
@override
|
|
String get categoriesEmpty =>
|
|
'No categories yet. Tap + to create your first one.';
|
|
|
|
@override
|
|
String get categoryNewTitle => 'New category';
|
|
|
|
@override
|
|
String get categoryEditTitle => 'Edit category';
|
|
|
|
@override
|
|
String get categoryNameLabel => 'Name';
|
|
|
|
@override
|
|
String get categoryNameHint => 'e.g. Groceries';
|
|
|
|
@override
|
|
String get categoryIconLabel => 'Icon';
|
|
|
|
@override
|
|
String get categoryColorLabel => 'Color';
|
|
|
|
@override
|
|
String get categorySaveButton => 'Create category';
|
|
|
|
@override
|
|
String get categoryArchiveButton => 'Archive';
|
|
|
|
@override
|
|
String get categoryArchiveConfirmTitle => 'Archive category?';
|
|
|
|
@override
|
|
String get categoryArchiveConfirmMessage =>
|
|
'Archived categories disappear from pickers and lists. Existing transactions keep their reference.';
|
|
|
|
@override
|
|
String get categoryValidationNameRequired => 'Enter a name';
|
|
|
|
@override
|
|
String get categoryValidationNameTooLong => 'Name is too long (max 50 chars)';
|
|
|
|
@override
|
|
String get iconPickerTitle => 'Pick an icon';
|
|
|
|
@override
|
|
String get colorPickerTitle => 'Pick a color';
|
|
|
|
@override
|
|
String get currencyPickerTitle => 'Pick a currency';
|
|
|
|
@override
|
|
String get currencyPickerSearchHint => 'Search…';
|
|
|
|
@override
|
|
String get colorPickerAllUsed =>
|
|
'All palette colors are already in use by other categories.';
|
|
|
|
@override
|
|
String get iconGroupFood => 'Food';
|
|
|
|
@override
|
|
String get iconGroupTransport => 'Transport';
|
|
|
|
@override
|
|
String get iconGroupShopping => 'Shopping';
|
|
|
|
@override
|
|
String get iconGroupHome => 'Home';
|
|
|
|
@override
|
|
String get iconGroupHealth => 'Health';
|
|
|
|
@override
|
|
String get iconGroupEntertainment => 'Leisure';
|
|
|
|
@override
|
|
String get iconGroupWork => 'Work';
|
|
|
|
@override
|
|
String get iconGroupTravel => 'Travel';
|
|
|
|
@override
|
|
String get iconGroupFinance => 'Finance';
|
|
|
|
@override
|
|
String get iconGroupOther => 'Other';
|
|
|
|
@override
|
|
String get profileCategoriesTile => 'Categories';
|
|
|
|
@override
|
|
String get profileAccountsTile => 'Accounts';
|
|
|
|
@override
|
|
String get accountsEmpty => 'No accounts yet. Tap + to add one.';
|
|
|
|
@override
|
|
String get accountNewTitle => 'New account';
|
|
|
|
@override
|
|
String get accountEditTitle => 'Edit account';
|
|
|
|
@override
|
|
String get accountNameLabel => 'Name';
|
|
|
|
@override
|
|
String get accountNameHint => 'e.g. Cash wallet';
|
|
|
|
@override
|
|
String get accountTypeLabel => 'Type';
|
|
|
|
@override
|
|
String get accountTypeCash => 'Cash';
|
|
|
|
@override
|
|
String get accountTypeCard => 'Card';
|
|
|
|
@override
|
|
String get accountTypeBank => 'Bank';
|
|
|
|
@override
|
|
String get accountTypeSavings => 'Savings';
|
|
|
|
@override
|
|
String get accountCurrencyLabel => 'Currency';
|
|
|
|
@override
|
|
String get accountInitialBalanceLabel => 'Initial balance';
|
|
|
|
@override
|
|
String get accountIconLabel => 'Icon';
|
|
|
|
@override
|
|
String get accountColorLabel => 'Color';
|
|
|
|
@override
|
|
String get accountIsDefaultLabel => 'Default account';
|
|
|
|
@override
|
|
String get accountIsDefaultHint => 'Used when creating new transactions';
|
|
|
|
@override
|
|
String get accountSaveButton => 'Create account';
|
|
|
|
@override
|
|
String get accountSaveEditButton => 'Save changes';
|
|
|
|
@override
|
|
String get accountArchiveButton => 'Archive';
|
|
|
|
@override
|
|
String get accountArchiveConfirmTitle => 'Archive account?';
|
|
|
|
@override
|
|
String get accountArchiveConfirmMessage =>
|
|
'Archived accounts disappear from pickers and lists. Existing transactions keep their reference.';
|
|
|
|
@override
|
|
String get accountValidationNameRequired => 'Enter a name';
|
|
|
|
@override
|
|
String get accountValidationNameTooLong => 'Name is too long (max 50 chars)';
|
|
|
|
@override
|
|
String get accountSaveError =>
|
|
'Failed to save the account. Please try again.';
|
|
|
|
@override
|
|
String get accountArchiveError =>
|
|
'Failed to archive the account. Please try again.';
|
|
|
|
@override
|
|
String get accountSetDefaultError =>
|
|
'Account saved, but couldn\'t mark it as default.';
|
|
|
|
@override
|
|
String get profileParsingTile => 'Notification parsing';
|
|
|
|
@override
|
|
String get parsingSettingsTitle => 'Notification parsing';
|
|
|
|
@override
|
|
String get parsingSettingsSubtitle => 'Settings';
|
|
|
|
@override
|
|
String get parsingEnableLabel => 'Recognize notifications';
|
|
|
|
@override
|
|
String get parsingAutoApplyLabel => 'Auto-add transactions';
|
|
|
|
@override
|
|
String get parsingAutoApplyHint =>
|
|
'Add without confirmation when a rule exists, the amount is found in the message text and the account is trusted.';
|
|
|
|
@override
|
|
String inboxWhyNotAuto(String reasons) {
|
|
return 'Why not automatic: $reasons';
|
|
}
|
|
|
|
@override
|
|
String get gateCheckRuleMatched => 'no rule for this merchant';
|
|
|
|
@override
|
|
String get gateCheckAmountVerifiedInBody =>
|
|
'amount not found in the message text';
|
|
|
|
@override
|
|
String get gateCheckCurrencyKnown => 'currency not recognized';
|
|
|
|
@override
|
|
String get gateCheckTypeMatchesRule =>
|
|
'transaction type differs from the rule';
|
|
|
|
@override
|
|
String get gateCheckAccountResolved => 'account not resolved';
|
|
|
|
@override
|
|
String get gateCheckAccountTrusted => 'ambiguous account';
|
|
|
|
@override
|
|
String get gateCheckAmountUnderCap => 'amount is too large';
|
|
|
|
@override
|
|
String get parsingRulesTile => 'Parsing rules';
|
|
|
|
@override
|
|
String parsingRulesCreatedCount(int count) {
|
|
return 'Rules created: $count';
|
|
}
|
|
|
|
@override
|
|
String get parsingAiSectionTitle => 'AI (DeepSeek)';
|
|
|
|
@override
|
|
String get parsingAiComingSoon =>
|
|
'AI recognition is coming in a future version.';
|
|
|
|
@override
|
|
String get parsingNotifAccessTitle => 'Notification access';
|
|
|
|
@override
|
|
String get parsingNotifAccessGranted =>
|
|
'Granted — notifications are being read';
|
|
|
|
@override
|
|
String get parsingNotifAccessDenied => 'Not granted — tap to open settings';
|
|
|
|
@override
|
|
String get parsingNotifAccessOpenSettings => 'Open settings';
|
|
|
|
@override
|
|
String get parsingDebugSectionTitle => 'Debug';
|
|
|
|
@override
|
|
String get parsingDebugInjectTile => 'Inject a test notification';
|
|
|
|
@override
|
|
String get parsingLogTile => 'Parsing log';
|
|
|
|
@override
|
|
String get parsingLogTitle => 'Parsing log';
|
|
|
|
@override
|
|
String get parsingLogEmpty =>
|
|
'No messages yet. Incoming notifications will appear here.';
|
|
|
|
@override
|
|
String get parsingLogError => 'Failed to load the log.';
|
|
|
|
@override
|
|
String get parsingLogFilterAll => 'All';
|
|
|
|
@override
|
|
String get parsingLogFilterInbox => 'Inbox';
|
|
|
|
@override
|
|
String get parsingLogFilterApplied => 'Applied';
|
|
|
|
@override
|
|
String get parsingLogFilterIgnored => 'Ignored';
|
|
|
|
@override
|
|
String get parsingLogFilterFailed => 'Failed';
|
|
|
|
@override
|
|
String get parsingStatusPending => 'Pending';
|
|
|
|
@override
|
|
String get parsingStatusInbox => 'Inbox';
|
|
|
|
@override
|
|
String get parsingStatusApplied => 'Applied';
|
|
|
|
@override
|
|
String get parsingStatusIgnored => 'Ignored';
|
|
|
|
@override
|
|
String get parsingStatusFailed => 'Failed';
|
|
|
|
@override
|
|
String get parsingStatusPendingAi => 'Waiting for AI';
|
|
|
|
@override
|
|
String get parsingStatusParsedPartial => 'Partial';
|
|
|
|
@override
|
|
String get parsingLogOnline => 'Online';
|
|
|
|
@override
|
|
String get parsingLogOffline => 'Offline';
|
|
|
|
@override
|
|
String get parsingLogFilterWaiting => 'Waiting';
|
|
|
|
@override
|
|
String get parsingDetailConfidence => 'Confidence';
|
|
|
|
@override
|
|
String get parsingDetailPipeline => 'Pipeline';
|
|
|
|
@override
|
|
String get parsingDetailMessage => 'Message';
|
|
|
|
@override
|
|
String get parsingDetailDraft => 'Draft';
|
|
|
|
@override
|
|
String get parsingDetailRule => 'Rule suggestion';
|
|
|
|
@override
|
|
String get parsingDetailMeta => 'Meta';
|
|
|
|
@override
|
|
String parsingDetailAttempt(int count, int max) {
|
|
return 'Attempt $count/$max';
|
|
}
|
|
|
|
@override
|
|
String get parsingDetailSource => 'Source';
|
|
|
|
@override
|
|
String get parsingDetailFailedChecks => 'Why not automatic';
|
|
|
|
@override
|
|
String get parsingDetailAmountScore => 'Amount';
|
|
|
|
@override
|
|
String get parsingDetailAccountScore => 'Account';
|
|
|
|
@override
|
|
String get parsingDetailTypeScore => 'Type';
|
|
|
|
@override
|
|
String get parsingDetailMerchantScore => 'Merchant';
|
|
|
|
@override
|
|
String get parsingDetailCategoryScore => 'Category';
|
|
|
|
@override
|
|
String get parsingDetailTitle => 'Title';
|
|
|
|
@override
|
|
String get parsingDetailBody => 'Body';
|
|
|
|
@override
|
|
String get parsingDetailCard => 'Card';
|
|
|
|
@override
|
|
String get parsingDetailCurrency => 'Currency';
|
|
|
|
@override
|
|
String get parsingDetailKind => 'Kind';
|
|
|
|
@override
|
|
String get parsingDetailDate => 'Date';
|
|
|
|
@override
|
|
String get parsingDetailMerchantRaw => 'Merchant (raw)';
|
|
|
|
@override
|
|
String get parsingDetailMerchantCanonical => 'Merchant (canonical)';
|
|
|
|
@override
|
|
String get parsingDetailCounterparty => 'Counterparty';
|
|
|
|
@override
|
|
String get parsingDetailCategorySuggestion => 'Category hint';
|
|
|
|
@override
|
|
String get parsingDetailAccountId => 'Account ID';
|
|
|
|
@override
|
|
String get parsingDetailCategoryId => 'Category ID';
|
|
|
|
@override
|
|
String get parsingDetailTransferTo => 'Transfer to';
|
|
|
|
@override
|
|
String get parsingDetailRuleCategory => 'Category';
|
|
|
|
@override
|
|
String get parsingDetailTransactionId => 'Transaction ID';
|
|
|
|
@override
|
|
String get parsingDetailDedupHash => 'Dedup hash';
|
|
|
|
@override
|
|
String get parsingDetailReceivedAt => 'Received at';
|
|
|
|
@override
|
|
String get parsingDetailCreatedAt => 'Created at';
|
|
|
|
@override
|
|
String get inboxTitle => 'From notifications';
|
|
|
|
@override
|
|
String get inboxSubtitle =>
|
|
'A rule is learned on the first tap: similar messages will be confirmed automatically.';
|
|
|
|
@override
|
|
String get inboxEmpty =>
|
|
'Inbox is empty. New notifications will appear here.';
|
|
|
|
@override
|
|
String inboxCreateRule(String merchant, String category) {
|
|
return 'Create rule “$merchant → $category”';
|
|
}
|
|
|
|
@override
|
|
String inboxCreateRuleNoCategory(String merchant) {
|
|
return 'Create rule for “$merchant”';
|
|
}
|
|
|
|
@override
|
|
String get inboxConfirmOnce => 'Confirm once';
|
|
|
|
@override
|
|
String get inboxIgnore => 'Ignore';
|
|
|
|
@override
|
|
String get inboxApplyAll => 'Apply all';
|
|
|
|
@override
|
|
String get inboxHideAll => 'Hide all';
|
|
|
|
@override
|
|
String get inboxUnrecognized => 'Not recognized';
|
|
|
|
@override
|
|
String get inboxParseErrorTitle => 'Recognition error';
|
|
|
|
@override
|
|
String get inboxRetry => 'Try again';
|
|
|
|
@override
|
|
String get inboxAddManually => 'Add manually';
|
|
|
|
@override
|
|
String get inboxNoCategory => 'No category';
|
|
|
|
@override
|
|
String get inboxAccountUnknown => 'Account unknown';
|
|
|
|
@override
|
|
String get inboxEditRuleTooltip => 'Edit before saving';
|
|
|
|
@override
|
|
String get rulesTitle => 'Parsing rules';
|
|
|
|
@override
|
|
String get rulesSubtitle => 'Settings';
|
|
|
|
@override
|
|
String get rulesFilterAll => 'All';
|
|
|
|
@override
|
|
String get rulesFilterMerchants => 'Merchants';
|
|
|
|
@override
|
|
String get rulesFilterAccounts => 'Accounts';
|
|
|
|
@override
|
|
String get rulesFilterIgnore => 'Ignore';
|
|
|
|
@override
|
|
String get rulesEmpty =>
|
|
'No rules yet. Create them from the Inbox in one tap.';
|
|
|
|
@override
|
|
String ruleMatchesCount(int count) {
|
|
String _temp0 = intl.Intl.pluralLogic(
|
|
count,
|
|
locale: localeName,
|
|
other: '$count matches',
|
|
one: '$count match',
|
|
);
|
|
return '$_temp0';
|
|
}
|
|
|
|
@override
|
|
String get ruleDisabled => 'Disabled';
|
|
|
|
@override
|
|
String get ruleEditorNewTitle => 'New rule';
|
|
|
|
@override
|
|
String get ruleEditorEditTitle => 'Rule';
|
|
|
|
@override
|
|
String get ruleEditorIfContains => 'If the notification contains';
|
|
|
|
@override
|
|
String get ruleEditorPatternHint => 'e.g. WBSPB';
|
|
|
|
@override
|
|
String get ruleEditorModeContains => 'Contains';
|
|
|
|
@override
|
|
String get ruleEditorModeExact => 'Exact';
|
|
|
|
@override
|
|
String get ruleEditorModeRegex => 'Regex';
|
|
|
|
@override
|
|
String get ruleEditorThen => 'Then it is:';
|
|
|
|
@override
|
|
String get ruleEditorMerchant => 'Merchant';
|
|
|
|
@override
|
|
String get ruleEditorMerchantHint => 'e.g. Wildberries';
|
|
|
|
@override
|
|
String get ruleEditorCategory => 'Category';
|
|
|
|
@override
|
|
String get ruleEditorAccount => 'Account';
|
|
|
|
@override
|
|
String get ruleEditorAccountUnchanged => '— keep unchanged —';
|
|
|
|
@override
|
|
String get ruleEditorAdvanced => 'Advanced';
|
|
|
|
@override
|
|
String get ruleEditorPriority => 'Priority';
|
|
|
|
@override
|
|
String get ruleEditorMatchesTitle => 'Matches (last 30 days)';
|
|
|
|
@override
|
|
String get ruleEditorNoMatches => 'No matches in the last 30 days';
|
|
|
|
@override
|
|
String get ruleEditorSave => 'Save';
|
|
|
|
@override
|
|
String get ruleEditorDelete => 'Delete';
|
|
|
|
@override
|
|
String get ruleEditorEnabledLabel => 'Enabled';
|
|
|
|
@override
|
|
String get debugInjectTitle => 'Test notification';
|
|
|
|
@override
|
|
String get debugInjectSubtitle => 'Debug';
|
|
|
|
@override
|
|
String get debugInjectPackageLabel => 'App package';
|
|
|
|
@override
|
|
String get debugInjectTitleLabel => 'Title (optional)';
|
|
|
|
@override
|
|
String get debugInjectBodyLabel => 'Notification text';
|
|
|
|
@override
|
|
String get debugInjectSend => 'Send to pipeline';
|
|
|
|
@override
|
|
String get debugInjectSent => 'Sent';
|
|
|
|
@override
|
|
String get debugInjectFillSample => 'Sample: purchase';
|
|
|
|
@override
|
|
String get aiConsentKeyMissing => 'API Key is missing';
|
|
|
|
@override
|
|
String get aiConsentSaved => 'Settings saved';
|
|
|
|
@override
|
|
String get aiConsentTitle => 'AI Parsing';
|
|
|
|
@override
|
|
String get aiConsentBody =>
|
|
'We use the DeepSeek API to parse notifications with AI. Your data is sent to the selected model. You need your own API key. Tokens are used.';
|
|
|
|
@override
|
|
String get aiConsentKeyLabel => 'DeepSeek API Key';
|
|
|
|
@override
|
|
String get aiConsentKeyHint => 'sk-...';
|
|
|
|
@override
|
|
String get aiConsentModelLabel => 'AI Model';
|
|
|
|
@override
|
|
String get aiConsentAllow => 'Allow AI Parsing';
|
|
|
|
@override
|
|
String get aiConsentRegexOnly => 'Use Regex Only (Local)';
|
|
|
|
@override
|
|
String get parsingAiConfigure => 'Configure AI';
|
|
|
|
@override
|
|
String parsingAiTokensToday(int tokens) {
|
|
return 'Tokens used today: $tokens';
|
|
}
|
|
|
|
@override
|
|
String parsingAiTokensTodayLimited(int tokens, int limit) {
|
|
return 'Tokens today: $tokens / $limit';
|
|
}
|
|
|
|
@override
|
|
String get habitTrackingTile => 'Spending habit analysis';
|
|
|
|
@override
|
|
String get habitObligationRequired => 'Necessary';
|
|
|
|
@override
|
|
String get habitObligationOptional => 'Optional';
|
|
|
|
@override
|
|
String get habitObligationUnnecessary => 'Unnecessary';
|
|
|
|
@override
|
|
String get habitObligationOptionalShort => 'Optional';
|
|
|
|
@override
|
|
String get habitImpulseImpulsive => 'Impulse';
|
|
|
|
@override
|
|
String get habitImpulseConsidered => 'Considered';
|
|
|
|
@override
|
|
String get habitNotMarked => 'not marked';
|
|
|
|
@override
|
|
String get habitFilterAll => 'All';
|
|
|
|
@override
|
|
String get habitScaleImpulseCaps => 'IMPULSIVENESS';
|
|
|
|
@override
|
|
String get habitScaleObligationCaps => 'OBLIGATION';
|
|
|
|
@override
|
|
String get habitAnalysisTitle => 'Transactions';
|
|
|
|
@override
|
|
String get habitAnalysisTile => 'Habit analysis';
|
|
|
|
@override
|
|
String get profileSeedDemoTile => 'Fill with demo transactions';
|
|
|
|
@override
|
|
String get profileSeedDemoSuccess => 'Demo transactions added';
|
|
|
|
@override
|
|
String get commonAdd => 'Add';
|
|
|
|
@override
|
|
String get commonCancel => 'Cancel';
|
|
|
|
@override
|
|
String get commonDelete => 'Delete';
|
|
|
|
@override
|
|
String get parsingAppsTile => 'Source apps';
|
|
|
|
@override
|
|
String get sourceAppsTitle => 'Source apps';
|
|
|
|
@override
|
|
String get sourceAppsAddedSection => 'Monitored';
|
|
|
|
@override
|
|
String get sourceAppsAvailableSection => 'Available';
|
|
|
|
@override
|
|
String get sourceAppsEmpty =>
|
|
'No apps added yet. Pick a bank below or add one manually.';
|
|
|
|
@override
|
|
String get sourceAppsAddManual => 'Add manually';
|
|
|
|
@override
|
|
String get sourceAppsPackageLabel => 'Package name';
|
|
|
|
@override
|
|
String get sourceAppsNameLabel => 'Display name (optional)';
|
|
|
|
@override
|
|
String get sourceAppsPickFromInstalled => 'Choose from installed apps';
|
|
|
|
@override
|
|
String get sourceAppsPickerTitle => 'Installed apps';
|
|
|
|
@override
|
|
String get sourceAppsSearchHint => 'Search';
|
|
|
|
@override
|
|
String get sourceAppsPickerEmpty => 'No apps found';
|
|
|
|
@override
|
|
String get sourceAppsAlreadyAdded => 'Already added';
|
|
|
|
@override
|
|
String get appBindingsTitle => 'Account bindings';
|
|
|
|
@override
|
|
String get appBindingsEmpty =>
|
|
'No bindings yet. Add one to map a card to an account.';
|
|
|
|
@override
|
|
String get appBindingsAnyCard => 'Any card (default)';
|
|
|
|
@override
|
|
String get appBindingsSetDefault => 'Set as default for this app';
|
|
|
|
@override
|
|
String get appBindingsAddTitle => 'New binding';
|
|
|
|
@override
|
|
String get appBindingsCardLabel => 'Card last 4 digits';
|
|
|
|
@override
|
|
String get appBindingsCardHelper => 'Leave empty to match any card';
|
|
|
|
@override
|
|
String get appBindingsDefaultLabel => 'Default for this app';
|
|
|
|
@override
|
|
String get ruleKindMerchant => 'Merchant → category';
|
|
|
|
@override
|
|
String get ruleKindAccount => 'Sender → account';
|
|
|
|
@override
|
|
String get ruleEditorAccountPick => 'Select account';
|
|
}
|