Two fixes for the notification-parsing pipeline: - CompanionDeviceManager pairing (DEVICE_PROFILE_WATCH -> COMPANION_DEVICE_WATCH role -> RECEIVE_SENSITIVE_NOTIFICATIONS) via a new platform channel in MainActivity.kt, companion_device_channel.dart and companion_access_controller, surfaced as a card in parsing settings. Lifts the system "Confidential" redaction that hid VTB/T-Bank notification text from the listener. - raw_messages.ai_response: the model's raw completion content is now persisted (schema v4 + migration) and shown in the parsing log detail panel. Unlike draftJson it survives inbox sweeps and is filled even for partial/ignored outcomes. flutter analyze: no issues. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1203 lines
33 KiB
Dart
1203 lines
33 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 gateCheckRuleAutoApplyEnabled =>
|
||
'авто-применение выключено у правила';
|
||
|
||
@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 parsingCompanionTitle => 'Полный доступ к уведомлениям';
|
||
|
||
@override
|
||
String get parsingCompanionBound =>
|
||
'Часы привязаны — текст уведомлений приходит целиком';
|
||
|
||
@override
|
||
String get parsingCompanionNotBound =>
|
||
'Android скрывает текст банковских уведомлений. Привяжите часы, чтобы приложение стало доверенным.';
|
||
|
||
@override
|
||
String get parsingCompanionBind => 'Привязать часы';
|
||
|
||
@override
|
||
String parsingCompanionBindFailed(String error) {
|
||
return 'Не удалось привязать: $error';
|
||
}
|
||
|
||
@override
|
||
String get parsingCompanionPickerTitle => 'Выберите ваши часы';
|
||
|
||
@override
|
||
String get parsingCompanionPickerScan =>
|
||
'Другое устройство — системный поиск';
|
||
|
||
@override
|
||
String get parsingCompanionBtDenied =>
|
||
'Нет разрешения Bluetooth — выдайте его в настройках приложения';
|
||
|
||
@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 get parsingDetailAiResponse => 'Ответ ИИ';
|
||
|
||
@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 ruleEditorAccountPick => 'Выбрать счёт';
|
||
|
||
@override
|
||
String get ruleEditorAccountAuto => 'Авто — счёт приложения';
|
||
|
||
@override
|
||
String get ruleEditorIgnoreLabel => 'Игнорировать сообщение';
|
||
|
||
@override
|
||
String get ruleEditorIgnoreHint =>
|
||
'Совпавшие уведомления пропускаются без транзакции';
|
||
|
||
@override
|
||
String get ruleEditorAutoApplyLabel => 'Применять автоматически';
|
||
|
||
@override
|
||
String get ruleEditorAutoApplyHint =>
|
||
'Выкл: совпадения приходят в Инбокс с префиллом на ручной разбор';
|
||
|
||
@override
|
||
String get ruleEditorTxType => 'Тип операции';
|
||
|
||
@override
|
||
String get ruleEditorTxTypeAny => 'Любой';
|
||
|
||
@override
|
||
String get ruleManualBadge => 'вручную';
|
||
}
|