Replace the Inbox badge button in MonthHeader with a bottom-nav tab (hidden when notification parsing is disabled). Redirect /inbox → /home when parsing is off, register the Inbox shell branch unconditionally, and add a settings action to the Inbox screen. Move the parsing tile to the top of the profile screen so settings stay reachable when the tab is hidden. Add tests for the nav tab visibility and inbox routing, plus a release-install PowerShell helper that preserves app data. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1146 lines
31 KiB
Dart
1146 lines
31 KiB
Dart
// ignore: unused_import
|
||
import 'package:intl/intl.dart' as intl;
|
||
import 'app_localizations.dart';
|
||
|
||
// ignore_for_file: type=lint
|
||
|
||
/// The translations for Russian (`ru`).
|
||
class AppLocalizationsRu extends AppLocalizations {
|
||
AppLocalizationsRu([String locale = 'ru']) : super(locale);
|
||
|
||
@override
|
||
String get appTitle => 'Kitty finances';
|
||
|
||
@override
|
||
String get navHome => 'Главная';
|
||
|
||
@override
|
||
String get navInbox => 'Входящие';
|
||
|
||
@override
|
||
String get navAnalytics => 'Аналитика';
|
||
|
||
@override
|
||
String get navAccounts => 'Счета';
|
||
|
||
@override
|
||
String get navProfile => 'Профиль';
|
||
|
||
@override
|
||
String get allAccounts => 'Все';
|
||
|
||
@override
|
||
String get comingSoon => 'Скоро';
|
||
|
||
@override
|
||
String get budget => 'БЮДЖЕТ';
|
||
|
||
@override
|
||
String get balance => 'БАЛАНС';
|
||
|
||
@override
|
||
String get income => 'ДОХОДЫ';
|
||
|
||
@override
|
||
String get expenses => 'РАСХОДЫ';
|
||
|
||
@override
|
||
String get transactions => 'Транзакции';
|
||
|
||
@override
|
||
String transactionCount(int count) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
count,
|
||
locale: localeName,
|
||
other: '$count операций',
|
||
many: '$count операций',
|
||
few: '$count операции',
|
||
one: '$count операция',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String get allCategoriesFilter => 'Все категории · все типы';
|
||
|
||
@override
|
||
String get filterByCategories => 'Фильтр по категориям';
|
||
|
||
@override
|
||
String get clearFilter => 'Сбросить';
|
||
|
||
@override
|
||
String get selectAll => 'Выбрать все';
|
||
|
||
@override
|
||
String categoriesSelectedCount(int count) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
count,
|
||
locale: localeName,
|
||
other: '$count категорий',
|
||
many: '$count категорий',
|
||
few: '$count категории',
|
||
one: '$count категория',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String moreCategories(int count) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
count,
|
||
locale: localeName,
|
||
other: '+ ещё $count категорий →',
|
||
many: '+ ещё $count категорий →',
|
||
few: '+ ещё $count категории →',
|
||
one: '+ ещё $count категория →',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String todayWithDate(String date) {
|
||
return 'Сегодня · $date';
|
||
}
|
||
|
||
@override
|
||
String yesterdayWithDate(String date) {
|
||
return 'Вчера · $date';
|
||
}
|
||
|
||
@override
|
||
String get analyticsTitle => 'Отчёты';
|
||
|
||
@override
|
||
String get analyticsSubtitle => 'Аналитика';
|
||
|
||
@override
|
||
String get analyticsNoData => 'Нет данных за этот месяц';
|
||
|
||
@override
|
||
String get accountsSubtitle => 'Управление';
|
||
|
||
@override
|
||
String get profileSubtitle => 'Настройки';
|
||
|
||
@override
|
||
String get darkTheme => 'Тёмная тема';
|
||
|
||
@override
|
||
String get profileLanguageTile => 'Язык';
|
||
|
||
@override
|
||
String get langEnglish => 'English';
|
||
|
||
@override
|
||
String get langRussian => 'Русский';
|
||
|
||
@override
|
||
String get profileHint =>
|
||
'Здесь появится профиль пользователя, валюта, локаль и другие настройки.';
|
||
|
||
@override
|
||
String get onboardingTitle => 'Добро пожаловать';
|
||
|
||
@override
|
||
String get onboardingSubtitle => 'Расскажите, как к вам обращаться.';
|
||
|
||
@override
|
||
String get onboardingNameLabel => 'Ваше имя';
|
||
|
||
@override
|
||
String get onboardingNameHint => 'Например, Алекс';
|
||
|
||
@override
|
||
String get onboardingContinue => 'Продолжить';
|
||
|
||
@override
|
||
String get onboardingAccountTitle => 'Ваш первый счёт';
|
||
|
||
@override
|
||
String get onboardingAccountSubtitle =>
|
||
'Добавьте счёт, чтобы учитывать деньги. Другие счета можно добавить позже.';
|
||
|
||
@override
|
||
String get txNewTitle => 'Новая операция';
|
||
|
||
@override
|
||
String get txEditTitle => 'Редактировать операцию';
|
||
|
||
@override
|
||
String get txTypeExpense => 'Расход';
|
||
|
||
@override
|
||
String get txTypeIncome => 'Доход';
|
||
|
||
@override
|
||
String get txTypeTransfer => 'Перевод';
|
||
|
||
@override
|
||
String get txAmountHint => '0';
|
||
|
||
@override
|
||
String get txCategoryLabel => 'Категория';
|
||
|
||
@override
|
||
String get txAccountLabel => 'Счёт списания';
|
||
|
||
@override
|
||
String get txAccountFromLabel => 'Откуда';
|
||
|
||
@override
|
||
String get txAccountToLabel => 'Куда';
|
||
|
||
@override
|
||
String get txDateTimeLabel => 'Дата и время';
|
||
|
||
@override
|
||
String get txBalanceAfter => 'Остаток после';
|
||
|
||
@override
|
||
String get txTransferAfter => 'После перевода';
|
||
|
||
@override
|
||
String get txNoteLabel => 'Мерчант';
|
||
|
||
@override
|
||
String get txNoteHint => 'Например, Пятерочка…';
|
||
|
||
@override
|
||
String get txExtraInfoLabel => 'Доп. информация';
|
||
|
||
@override
|
||
String get txExtraInfoHint => 'Например, продукты на неделю…';
|
||
|
||
@override
|
||
String get txSaveButton => 'Добавить транзакцию';
|
||
|
||
@override
|
||
String get txSaveEditButton => 'Сохранить';
|
||
|
||
@override
|
||
String txTransferButton(String amount) {
|
||
return 'Перевести $amount';
|
||
}
|
||
|
||
@override
|
||
String get txDeleteButton => 'Удалить';
|
||
|
||
@override
|
||
String get txDeleteConfirmTitle => 'Удалить транзакцию?';
|
||
|
||
@override
|
||
String get txDeleteConfirmMessage => 'Действие нельзя отменить.';
|
||
|
||
@override
|
||
String get txDeleteConfirmYes => 'Удалить';
|
||
|
||
@override
|
||
String get txDeleteConfirmNo => 'Отмена';
|
||
|
||
@override
|
||
String get txPickCategory => 'Выберите категорию';
|
||
|
||
@override
|
||
String get txPickAccount => 'Выберите счёт';
|
||
|
||
@override
|
||
String get pickerAccountTitle => 'Счёт';
|
||
|
||
@override
|
||
String pickerAccountSubtitle(int count) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
count,
|
||
locale: localeName,
|
||
other: '$count счетов',
|
||
many: '$count счетов',
|
||
few: '$count счёта',
|
||
one: '$count счёт',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String get pickerCategoryTitle => 'Категория';
|
||
|
||
@override
|
||
String pickerCategorySubtitle(int count) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
count,
|
||
locale: localeName,
|
||
other: '$count категорий',
|
||
many: '$count категорий',
|
||
few: '$count категории',
|
||
one: '$count категория',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String get pickerAddAccount => 'Добавить счёт';
|
||
|
||
@override
|
||
String get pickerCreateCategory => 'Создать категорию';
|
||
|
||
@override
|
||
String get comingSoonShort => 'Скоро';
|
||
|
||
@override
|
||
String get txValidationAmountRequired => 'Введите сумму';
|
||
|
||
@override
|
||
String get txValidationAccountRequired => 'Выберите счёт';
|
||
|
||
@override
|
||
String get txValidationCategoryRequired => 'Выберите категорию';
|
||
|
||
@override
|
||
String get txValidationTransferSameAccount =>
|
||
'Счёт-источник и счёт-получатель должны отличаться';
|
||
|
||
@override
|
||
String get txValidationTransferDestRequired => 'Выберите счёт получателя';
|
||
|
||
@override
|
||
String get categoriesScreenTitle => 'Категории';
|
||
|
||
@override
|
||
String get categoriesEmpty =>
|
||
'Пока нет категорий. Нажмите +, чтобы создать первую.';
|
||
|
||
@override
|
||
String get categoryNewTitle => 'Новая категория';
|
||
|
||
@override
|
||
String get categoryEditTitle => 'Редактировать категорию';
|
||
|
||
@override
|
||
String get categoryNameLabel => 'Название';
|
||
|
||
@override
|
||
String get categoryNameHint => 'Например, Продукты';
|
||
|
||
@override
|
||
String get categoryIconLabel => 'Иконка';
|
||
|
||
@override
|
||
String get categoryColorLabel => 'Цвет';
|
||
|
||
@override
|
||
String get categorySaveButton => 'Создать категорию';
|
||
|
||
@override
|
||
String get categoryArchiveButton => 'В архив';
|
||
|
||
@override
|
||
String get categoryArchiveConfirmTitle => 'Архивировать категорию?';
|
||
|
||
@override
|
||
String get categoryArchiveConfirmMessage =>
|
||
'Архивные категории исчезают из пикеров и списков. Существующие транзакции сохранят ссылку на неё.';
|
||
|
||
@override
|
||
String get categoryValidationNameRequired => 'Введите название';
|
||
|
||
@override
|
||
String get categoryValidationNameTooLong =>
|
||
'Слишком длинное название (не больше 50 символов)';
|
||
|
||
@override
|
||
String get iconPickerTitle => 'Выберите иконку';
|
||
|
||
@override
|
||
String get colorPickerTitle => 'Выберите цвет';
|
||
|
||
@override
|
||
String get currencyPickerTitle => 'Выберите валюту';
|
||
|
||
@override
|
||
String get currencyPickerSearchHint => 'Поиск…';
|
||
|
||
@override
|
||
String get colorPickerAllUsed =>
|
||
'Все цвета палитры уже заняты другими категориями.';
|
||
|
||
@override
|
||
String get iconGroupFood => 'Еда';
|
||
|
||
@override
|
||
String get iconGroupTransport => 'Транспорт';
|
||
|
||
@override
|
||
String get iconGroupShopping => 'Покупки';
|
||
|
||
@override
|
||
String get iconGroupHome => 'Дом';
|
||
|
||
@override
|
||
String get iconGroupHealth => 'Здоровье';
|
||
|
||
@override
|
||
String get iconGroupEntertainment => 'Досуг';
|
||
|
||
@override
|
||
String get iconGroupWork => 'Работа';
|
||
|
||
@override
|
||
String get iconGroupTravel => 'Путешествия';
|
||
|
||
@override
|
||
String get iconGroupFinance => 'Финансы';
|
||
|
||
@override
|
||
String get iconGroupOther => 'Прочее';
|
||
|
||
@override
|
||
String get profileCategoriesTile => 'Категории';
|
||
|
||
@override
|
||
String get profileAccountsTile => 'Счета';
|
||
|
||
@override
|
||
String get accountsEmpty => 'Счетов нет. Нажмите +, чтобы добавить.';
|
||
|
||
@override
|
||
String get accountNewTitle => 'Новый счёт';
|
||
|
||
@override
|
||
String get accountEditTitle => 'Редактировать счёт';
|
||
|
||
@override
|
||
String get accountNameLabel => 'Название';
|
||
|
||
@override
|
||
String get accountNameHint => 'напр. Кошелёк';
|
||
|
||
@override
|
||
String get accountTypeLabel => 'Тип';
|
||
|
||
@override
|
||
String get accountTypeCash => 'Наличные';
|
||
|
||
@override
|
||
String get accountTypeCard => 'Карта';
|
||
|
||
@override
|
||
String get accountTypeBank => 'Банк';
|
||
|
||
@override
|
||
String get accountTypeSavings => 'Накопления';
|
||
|
||
@override
|
||
String get accountCurrencyLabel => 'Валюта';
|
||
|
||
@override
|
||
String get accountInitialBalanceLabel => 'Начальный баланс';
|
||
|
||
@override
|
||
String get accountIconLabel => 'Иконка';
|
||
|
||
@override
|
||
String get accountColorLabel => 'Цвет';
|
||
|
||
@override
|
||
String get accountIsDefaultLabel => 'Счёт по умолчанию';
|
||
|
||
@override
|
||
String get accountIsDefaultHint => 'Подставляется при создании транзакций';
|
||
|
||
@override
|
||
String get accountSaveButton => 'Создать счёт';
|
||
|
||
@override
|
||
String get accountSaveEditButton => 'Сохранить';
|
||
|
||
@override
|
||
String get accountArchiveButton => 'Архивировать';
|
||
|
||
@override
|
||
String get accountArchiveConfirmTitle => 'Архивировать счёт?';
|
||
|
||
@override
|
||
String get accountArchiveConfirmMessage =>
|
||
'Архивные счета исчезают из списков и пикеров. Существующие транзакции сохранят ссылку.';
|
||
|
||
@override
|
||
String get accountValidationNameRequired => 'Введите название';
|
||
|
||
@override
|
||
String get accountValidationNameTooLong =>
|
||
'Слишком длинное название (макс. 50 символов)';
|
||
|
||
@override
|
||
String get accountSaveError =>
|
||
'Не удалось сохранить счёт. Попробуйте ещё раз.';
|
||
|
||
@override
|
||
String get accountArchiveError =>
|
||
'Не удалось архивировать счёт. Попробуйте ещё раз.';
|
||
|
||
@override
|
||
String get accountSetDefaultError =>
|
||
'Счёт сохранён, но не удалось сделать его умолчательным.';
|
||
|
||
@override
|
||
String get profileParsingTile => 'Парсинг уведомлений';
|
||
|
||
@override
|
||
String get parsingSettingsTitle => 'Парсинг уведомлений';
|
||
|
||
@override
|
||
String get parsingSettingsSubtitle => 'Настройки';
|
||
|
||
@override
|
||
String get parsingEnableLabel => 'Распознавать уведомления';
|
||
|
||
@override
|
||
String get parsingAutoApplyLabel => 'Авто-добавление транзакций';
|
||
|
||
@override
|
||
String get parsingAutoApplyHint =>
|
||
'Добавлять без подтверждения, когда есть правило, сумма найдена в тексте сообщения и счёт определён надёжно.';
|
||
|
||
@override
|
||
String get parsingTransferPairingLabel => 'Склеивать переводы между счетами';
|
||
|
||
@override
|
||
String get parsingTransferPairingHint =>
|
||
'Два уведомления об одном переводе (списание + зачисление) объединяются в одну транзакцию-перевод на подтверждение.';
|
||
|
||
@override
|
||
String get parsingDiagnosticModeLabel => 'Режим диагностики';
|
||
|
||
@override
|
||
String get parsingDiagnosticModeHint =>
|
||
'Ловить каждое уведомление от мониторимых приложений (включая пустые/повторные) с полным дампом всех полей. Временно — для отладки, добавляет шум в журнал парсинга.';
|
||
|
||
@override
|
||
String inboxWhyNotAuto(String reasons) {
|
||
return 'Почему не автоматически: $reasons';
|
||
}
|
||
|
||
@override
|
||
String get gateCheckRuleMatched => 'нет правила для мерчанта';
|
||
|
||
@override
|
||
String get gateCheckAmountVerifiedInBody =>
|
||
'сумма не найдена в тексте сообщения';
|
||
|
||
@override
|
||
String get gateCheckCurrencyKnown => 'валюта не распознана';
|
||
|
||
@override
|
||
String get gateCheckTypeMatchesRule => 'тип операции отличается от правила';
|
||
|
||
@override
|
||
String get gateCheckAccountResolved => 'счёт не определён';
|
||
|
||
@override
|
||
String get gateCheckAccountTrusted => 'счёт не подтверждён для приложения';
|
||
|
||
@override
|
||
String get gateCheckAmountUnderCap => 'слишком крупная сумма';
|
||
|
||
@override
|
||
String get parsingRulesTile => 'Правила парсинга';
|
||
|
||
@override
|
||
String parsingRulesCreatedCount(int count) {
|
||
return 'Правил создано: $count';
|
||
}
|
||
|
||
@override
|
||
String get parsingAiSectionTitle => 'AI (DeepSeek)';
|
||
|
||
@override
|
||
String get parsingAiComingSoon =>
|
||
'ИИ-распознавание появится в следующей версии.';
|
||
|
||
@override
|
||
String get parsingNotifAccessTitle => 'Доступ к уведомлениям';
|
||
|
||
@override
|
||
String get parsingNotifAccessGranted => 'Выдан — уведомления читаются';
|
||
|
||
@override
|
||
String get parsingNotifAccessDenied =>
|
||
'Не выдан — нажмите, чтобы открыть настройки';
|
||
|
||
@override
|
||
String get parsingNotifAccessOpenSettings => 'Открыть настройки';
|
||
|
||
@override
|
||
String get parsingDebugSectionTitle => 'Отладка';
|
||
|
||
@override
|
||
String get parsingDebugInjectTile => 'Вставить тестовое уведомление';
|
||
|
||
@override
|
||
String get parsingLogTile => 'Журнал парсинга';
|
||
|
||
@override
|
||
String get parsingLogTitle => 'Журнал парсинга';
|
||
|
||
@override
|
||
String get parsingLogEmpty =>
|
||
'Сообщений пока нет. Входящие уведомления появятся здесь.';
|
||
|
||
@override
|
||
String get parsingLogError => 'Не удалось загрузить журнал.';
|
||
|
||
@override
|
||
String get parsingLogFilterAll => 'Все';
|
||
|
||
@override
|
||
String get parsingLogFilterInbox => 'Inbox';
|
||
|
||
@override
|
||
String get parsingLogFilterApplied => 'Применённые';
|
||
|
||
@override
|
||
String get parsingLogFilterIgnored => 'Игнорированные';
|
||
|
||
@override
|
||
String get parsingLogFilterFailed => 'Ошибки';
|
||
|
||
@override
|
||
String get parsingStatusPending => 'В очереди';
|
||
|
||
@override
|
||
String get parsingStatusInbox => 'Inbox';
|
||
|
||
@override
|
||
String get parsingStatusApplied => 'Применено';
|
||
|
||
@override
|
||
String get parsingStatusIgnored => 'Игнорировано';
|
||
|
||
@override
|
||
String get parsingStatusFailed => 'Ошибка';
|
||
|
||
@override
|
||
String get parsingStatusPendingAi => 'Ждёт AI';
|
||
|
||
@override
|
||
String get parsingStatusParsedPartial => 'Частично';
|
||
|
||
@override
|
||
String get parsingStatusWaitingPair => 'Ждёт пару';
|
||
|
||
@override
|
||
String get parsingStatusPaired => 'Объединено в перевод';
|
||
|
||
@override
|
||
String get parsingUnmergeTransfer => 'Расклеить перевод';
|
||
|
||
@override
|
||
String get parsingLogOnline => 'Онлайн';
|
||
|
||
@override
|
||
String get parsingLogOffline => 'Офлайн';
|
||
|
||
@override
|
||
String get parsingLogFilterWaiting => 'Ждёт сети';
|
||
|
||
@override
|
||
String get parsingDetailConfidence => 'Уверенность';
|
||
|
||
@override
|
||
String get parsingDetailPipeline => 'Pipeline';
|
||
|
||
@override
|
||
String get parsingDetailMessage => 'Сообщение';
|
||
|
||
@override
|
||
String get parsingDetailDraft => 'Черновик';
|
||
|
||
@override
|
||
String get parsingDetailRule => 'Предложение правила';
|
||
|
||
@override
|
||
String get parsingDetailMeta => 'Мета';
|
||
|
||
@override
|
||
String get parsingDetailDiagnostics => 'Диагностика';
|
||
|
||
@override
|
||
String parsingDetailAttempt(int count, int max) {
|
||
return 'Попытка $count/$max';
|
||
}
|
||
|
||
@override
|
||
String get parsingDetailSource => 'Источник';
|
||
|
||
@override
|
||
String get parsingDetailFailedChecks => 'Почему не автоматически';
|
||
|
||
@override
|
||
String get parsingDetailAmountScore => 'Сумма';
|
||
|
||
@override
|
||
String get parsingDetailAccountScore => 'Счёт';
|
||
|
||
@override
|
||
String get parsingDetailTypeScore => 'Тип';
|
||
|
||
@override
|
||
String get parsingDetailMerchantScore => 'Мерчант';
|
||
|
||
@override
|
||
String get parsingDetailCategoryScore => 'Категория';
|
||
|
||
@override
|
||
String get parsingDetailTitle => 'Заголовок';
|
||
|
||
@override
|
||
String get parsingDetailBody => 'Текст';
|
||
|
||
@override
|
||
String get parsingDetailCard => 'Карта';
|
||
|
||
@override
|
||
String get parsingDetailCurrency => 'Валюта';
|
||
|
||
@override
|
||
String get parsingDetailKind => 'Вид';
|
||
|
||
@override
|
||
String get parsingDetailDate => 'Дата';
|
||
|
||
@override
|
||
String get parsingDetailMerchantRaw => 'Мерчант (сырой)';
|
||
|
||
@override
|
||
String get parsingDetailMerchantCanonical => 'Мерчант (норм.)';
|
||
|
||
@override
|
||
String get parsingDetailCounterparty => 'Контрагент';
|
||
|
||
@override
|
||
String get parsingDetailCategorySuggestion => 'Подсказка категории';
|
||
|
||
@override
|
||
String get parsingDetailAccountId => 'ID счёта';
|
||
|
||
@override
|
||
String get parsingDetailCategoryId => 'ID категории';
|
||
|
||
@override
|
||
String get parsingDetailTransferTo => 'Перевод на';
|
||
|
||
@override
|
||
String get parsingDetailRuleCategory => 'Категория';
|
||
|
||
@override
|
||
String get parsingDetailTransactionId => 'ID транзакции';
|
||
|
||
@override
|
||
String get parsingDetailDedupHash => 'Dedup-хеш';
|
||
|
||
@override
|
||
String get parsingDetailReceivedAt => 'Получено';
|
||
|
||
@override
|
||
String get parsingDetailCreatedAt => 'Создано';
|
||
|
||
@override
|
||
String get inboxTitle => 'Из уведомлений';
|
||
|
||
@override
|
||
String get inboxSubtitle =>
|
||
'Правило обучится с первого раза: следующие похожие сообщения подтвердятся автоматически.';
|
||
|
||
@override
|
||
String get inboxEmpty => 'Inbox пуст. Новые уведомления появятся здесь.';
|
||
|
||
@override
|
||
String inboxCreateRule(String merchant, String category) {
|
||
return 'Создать правило «$merchant → $category»';
|
||
}
|
||
|
||
@override
|
||
String inboxCreateRuleNoCategory(String merchant) {
|
||
return 'Создать правило для «$merchant»';
|
||
}
|
||
|
||
@override
|
||
String get inboxConfirm => 'Подтвердить';
|
||
|
||
@override
|
||
String get inboxCategoryRequiredHint =>
|
||
'Выберите категорию, чтобы подтвердить';
|
||
|
||
@override
|
||
String get inboxIgnore => 'Игнорировать';
|
||
|
||
@override
|
||
String get inboxApplyAll => 'Учесть все';
|
||
|
||
@override
|
||
String get inboxTransferPairTitle => 'Перевод между счетами';
|
||
|
||
@override
|
||
String get inboxTransferFrom => 'Счёт списания';
|
||
|
||
@override
|
||
String get inboxTransferTo => 'Счёт зачисления';
|
||
|
||
@override
|
||
String get inboxTransferPickAccount => 'Выбрать…';
|
||
|
||
@override
|
||
String get inboxUnpair => 'Расклеить';
|
||
|
||
@override
|
||
String get inboxUnrecognized => 'Не распознано';
|
||
|
||
@override
|
||
String get inboxParseErrorTitle => 'Ошибка распознавания';
|
||
|
||
@override
|
||
String get inboxRetry => 'Попробовать снова';
|
||
|
||
@override
|
||
String get inboxAddManually => 'Добавить вручную';
|
||
|
||
@override
|
||
String get inboxNoCategory => 'Без категории';
|
||
|
||
@override
|
||
String get inboxAccountUnknown => 'Счёт не определён';
|
||
|
||
@override
|
||
String get inboxEditRuleTooltip => 'Изменить перед сохранением';
|
||
|
||
@override
|
||
String get inboxWaitingNetworkTitle => 'Ждёт сети';
|
||
|
||
@override
|
||
String get inboxStuckOffline =>
|
||
'Нет подключения к интернету. Разбор продолжится, когда появится сеть.';
|
||
|
||
@override
|
||
String get inboxStuckNetwork =>
|
||
'Сеть есть, но запрос к AI не прошёл. Повторим автоматически.';
|
||
|
||
@override
|
||
String get parseErrorOffline => 'Не было соединения с интернетом';
|
||
|
||
@override
|
||
String get parseErrorNetwork => 'Запрос к AI не прошёл (ошибка сети)';
|
||
|
||
@override
|
||
String get parseErrorRetryLimit => 'Лимит AI-попыток исчерпан';
|
||
|
||
@override
|
||
String get rulesTitle => 'Правила парсинга';
|
||
|
||
@override
|
||
String get rulesSubtitle => 'Настройки';
|
||
|
||
@override
|
||
String get rulesFilterAll => 'Все';
|
||
|
||
@override
|
||
String get rulesFilterMerchants => 'Мерчанты';
|
||
|
||
@override
|
||
String get rulesFilterAccounts => 'Счета';
|
||
|
||
@override
|
||
String get rulesFilterIgnore => 'Игнор';
|
||
|
||
@override
|
||
String get rulesEmpty =>
|
||
'Правил пока нет. Создавайте их из Inbox в один тап.';
|
||
|
||
@override
|
||
String ruleMatchesCount(int count) {
|
||
String _temp0 = intl.Intl.pluralLogic(
|
||
count,
|
||
locale: localeName,
|
||
other: '$count совпадений',
|
||
many: '$count совпадений',
|
||
few: '$count совпадения',
|
||
one: '$count совпадение',
|
||
);
|
||
return '$_temp0';
|
||
}
|
||
|
||
@override
|
||
String get ruleDisabled => 'Выключено';
|
||
|
||
@override
|
||
String get ruleEditorNewTitle => 'Новое правило';
|
||
|
||
@override
|
||
String get ruleEditorEditTitle => 'Правило';
|
||
|
||
@override
|
||
String get ruleEditorIfContains => 'Если уведомление содержит';
|
||
|
||
@override
|
||
String get ruleEditorPatternHint => 'напр. WBSPB';
|
||
|
||
@override
|
||
String get ruleEditorModeContains => 'Содержит';
|
||
|
||
@override
|
||
String get ruleEditorModeExact => 'Точно';
|
||
|
||
@override
|
||
String get ruleEditorModeRegex => 'Regex';
|
||
|
||
@override
|
||
String get ruleEditorThen => 'То это:';
|
||
|
||
@override
|
||
String get ruleEditorMerchant => 'Мерчант';
|
||
|
||
@override
|
||
String get ruleEditorMerchantHint => 'Напр. Wildberries';
|
||
|
||
@override
|
||
String get ruleEditorCategory => 'Категория';
|
||
|
||
@override
|
||
String get ruleEditorAccount => 'Счёт';
|
||
|
||
@override
|
||
String get ruleEditorAccountUnchanged => '— не менять —';
|
||
|
||
@override
|
||
String get ruleEditorApp => 'Приложение';
|
||
|
||
@override
|
||
String get ruleEditorAppPick => 'Выберите приложение';
|
||
|
||
@override
|
||
String get ruleEditorNoApps => 'Сначала добавьте приложение-источник';
|
||
|
||
@override
|
||
String get rulesUnknownApp => 'Неизвестное приложение';
|
||
|
||
@override
|
||
String get ruleEditorAdvanced => 'Дополнительно';
|
||
|
||
@override
|
||
String get ruleEditorPriority => 'Приоритет';
|
||
|
||
@override
|
||
String get ruleEditorMatchesTitle => 'Совпадает с (последние 30 дней)';
|
||
|
||
@override
|
||
String get ruleEditorNoMatches => 'Нет совпадений за 30 дней';
|
||
|
||
@override
|
||
String get ruleEditorSave => 'Сохранить';
|
||
|
||
@override
|
||
String get ruleEditorDelete => 'Удалить';
|
||
|
||
@override
|
||
String get ruleEditorEnabledLabel => 'Активно';
|
||
|
||
@override
|
||
String get debugInjectTitle => 'Тестовое уведомление';
|
||
|
||
@override
|
||
String get debugInjectSubtitle => 'Отладка';
|
||
|
||
@override
|
||
String get debugInjectPackageLabel => 'Пакет приложения';
|
||
|
||
@override
|
||
String get debugInjectTitleLabel => 'Заголовок (необязательно)';
|
||
|
||
@override
|
||
String get debugInjectBodyLabel => 'Текст уведомления';
|
||
|
||
@override
|
||
String get debugInjectSend => 'Отправить в обработку';
|
||
|
||
@override
|
||
String get debugInjectSent => 'Отправлено';
|
||
|
||
@override
|
||
String get debugInjectFillSample => 'Пример: покупка';
|
||
|
||
@override
|
||
String get aiConsentKeyMissing => 'API-ключ не указан';
|
||
|
||
@override
|
||
String get aiConsentSaved => 'Настройки сохранены';
|
||
|
||
@override
|
||
String get aiConsentTitle => 'Парсинг с ИИ';
|
||
|
||
@override
|
||
String get aiConsentBody =>
|
||
'Мы используем DeepSeek API для парсинга уведомлений с помощью ИИ. Ваши данные отправляются выбранной модели. Вам понадобится свой API-ключ. Расходуются токены.';
|
||
|
||
@override
|
||
String get aiConsentKeyLabel => 'API-ключ DeepSeek';
|
||
|
||
@override
|
||
String get aiConsentKeyHint => 'sk-...';
|
||
|
||
@override
|
||
String get aiConsentModelLabel => 'Модель ИИ';
|
||
|
||
@override
|
||
String get aiConsentAllow => 'Разрешить ИИ-парсинг';
|
||
|
||
@override
|
||
String get aiConsentRegexOnly => 'Только Regex (Локально)';
|
||
|
||
@override
|
||
String get parsingAiConfigure => 'Настроить ИИ';
|
||
|
||
@override
|
||
String parsingAiTokensToday(int tokens) {
|
||
return 'Токенов за сегодня: $tokens';
|
||
}
|
||
|
||
@override
|
||
String parsingAiTokensTodayLimited(int tokens, int limit) {
|
||
return 'Токенов за сегодня: $tokens / $limit';
|
||
}
|
||
|
||
@override
|
||
String get habitTrackingTile => 'Анализ привычек трат';
|
||
|
||
@override
|
||
String get habitObligationRequired => 'Обязательно';
|
||
|
||
@override
|
||
String get habitObligationOptional => 'Не обязательно';
|
||
|
||
@override
|
||
String get habitObligationUnnecessary => 'Не нужно';
|
||
|
||
@override
|
||
String get habitObligationOptionalShort => 'Можно без';
|
||
|
||
@override
|
||
String get habitImpulseImpulsive => 'Импульсивно';
|
||
|
||
@override
|
||
String get habitImpulseConsidered => 'Обдуманно';
|
||
|
||
@override
|
||
String get habitNotMarked => 'не отмечено';
|
||
|
||
@override
|
||
String get habitFilterAll => 'Все';
|
||
|
||
@override
|
||
String get habitScaleImpulseCaps => 'ИМПУЛЬСИВНОСТЬ';
|
||
|
||
@override
|
||
String get habitScaleObligationCaps => 'ОБЯЗАТЕЛЬНОСТЬ';
|
||
|
||
@override
|
||
String get habitAnalysisTitle => 'Транзакции';
|
||
|
||
@override
|
||
String get habitAnalysisTile => 'Анализ привычек';
|
||
|
||
@override
|
||
String get profileSeedDemoTile => 'Заполнить демо транзакциями';
|
||
|
||
@override
|
||
String get profileSeedDemoSuccess => 'Демо транзакции добавлены';
|
||
|
||
@override
|
||
String get commonAdd => 'Добавить';
|
||
|
||
@override
|
||
String get commonCancel => 'Отмена';
|
||
|
||
@override
|
||
String get commonDelete => 'Удалить';
|
||
|
||
@override
|
||
String get parsingAppsTile => 'Приложения-источники';
|
||
|
||
@override
|
||
String get sourceAppsTitle => 'Приложения-источники';
|
||
|
||
@override
|
||
String get sourceAppsAddedSection => 'Отслеживаются';
|
||
|
||
@override
|
||
String get sourceAppsAvailableSection => 'Доступные';
|
||
|
||
@override
|
||
String get sourceAppsEmpty =>
|
||
'Пока нет приложений. Выберите банк ниже или добавьте вручную.';
|
||
|
||
@override
|
||
String get sourceAppsAddManual => 'Добавить вручную';
|
||
|
||
@override
|
||
String get sourceAppsPackageLabel => 'Имя пакета';
|
||
|
||
@override
|
||
String get sourceAppsNameLabel => 'Отображаемое имя (необязательно)';
|
||
|
||
@override
|
||
String get sourceAppsPickFromInstalled => 'Выбрать из установленных';
|
||
|
||
@override
|
||
String get sourceAppsPickerTitle => 'Установленные приложения';
|
||
|
||
@override
|
||
String get sourceAppsSearchHint => 'Поиск';
|
||
|
||
@override
|
||
String get sourceAppsPickerEmpty => 'Приложения не найдены';
|
||
|
||
@override
|
||
String get sourceAppsAlreadyAdded => 'Уже добавлено';
|
||
|
||
@override
|
||
String get sourceAppsSelfMerchantLabel => 'Мерчант — само приложение';
|
||
|
||
@override
|
||
String get sourceAppsSelfMerchantHint =>
|
||
'Уведомления не называют продавца: категория выбирается вручную, правила не предлагаются';
|
||
|
||
@override
|
||
String get appDetailEnabled => 'Отслеживать уведомления';
|
||
|
||
@override
|
||
String get appDetailDefaultAccount => 'Счёт по умолчанию';
|
||
|
||
@override
|
||
String get appDetailDefaultAccountNone => 'Не задан';
|
||
|
||
@override
|
||
String get appDetailDefaultAccountHint =>
|
||
'Новые операции из этого приложения записываются на этот счёт. Запоминается автоматически при первом «Подтвердить» во Входящих.';
|
||
|
||
@override
|
||
String get appDetailRoutingRules => 'Правила выбора счёта';
|
||
|
||
@override
|
||
String get appDetailRoutingRulesEmpty =>
|
||
'Если приложение пишет о нескольких счетах (карта, вклад), добавьте правило: паттерн в тексте → счёт. Правила важнее счёта по умолчанию.';
|
||
|
||
@override
|
||
String get appDetailAddRule => 'Добавить';
|
||
|
||
@override
|
||
String get inboxAppDefaultSet => 'Счёт сохранён как основной для приложения';
|
||
|
||
@override
|
||
String get ruleKindMerchant => 'Мерчант → категория';
|
||
|
||
@override
|
||
String get ruleKindAccount => 'Отправитель → счёт';
|
||
|
||
@override
|
||
String get ruleEditorAccountPick => 'Выбрать счёт';
|
||
}
|