Files
maraphon-app/src/Marathon.UI/Resources/SharedResource.ru.resx
T
alexei.dolgolyov 9f090cec1f feat(phase-8-frontend): results loader UI + browsing list + 41 localization keys
* Pages/Results/ResultsList.razor — completed-events list with date range,
  sport/winner filter, search, footer count.
* Pages/Results/ResultsLoader.razor — driver page with two modes (load all
  in range / load selected events), live progress reporting via
  IProgress<PullResultsProgress>, summary line, cancellable.
* Replaces the Phase 5 Pages/Results.razor placeholder.

Service layer:
* IResultsBrowsingService + ResultsBrowsingService (Scoped, mirrors the
  Event/Anomaly browsing-service pattern). Reads IResultRepository +
  IEventRepository, projects to immutable view-model records.
* UiServicesExtensions: registers ResultsBrowsingService; also fixes an
  unrelated localization resolver bug (drop ResourcesPath since
  SharedResource lives in the Marathon.UI.Resources namespace already).

Localization:
* 41 new Results.* keys (RU+EN parity) covering both pages, filter chips,
  loader modes, progress states, and footer copy.

Tests:
* ResultsListTests + ResultsLoaderTests — 22 new bUnit tests covering
  filter narrowing, mode switching, progress aggregation, and empty
  states.
* FakeResultsBrowsingService support type for tests.
* MarathonTestContext registers the fake; TestData adds factories for
  EventResult/EventResultListItem.
2026-05-09 15:10:49 +03:00

318 lines
25 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
<resheader name="version"><value>2.0</value></resheader>
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<!-- App chrome -->
<data name="App.Title"><value>Marathon Odds Lab</value></data>
<data name="App.Tagline"><value>Аналитика коэффициентов marathonbet.by</value></data>
<data name="App.BrandMark"><value>Marathon</value></data>
<data name="App.Dateline"><value>Лаборатория коэффициентов</value></data>
<!-- Navigation -->
<data name="Nav.Section.Analysis"><value>Анализ</value></data>
<data name="Nav.Section.System"><value>Система</value></data>
<data name="Nav.Dashboard"><value>Сводка</value></data>
<data name="Nav.PreMatch"><value>До матча</value></data>
<data name="Nav.Live"><value>Лайв</value></data>
<data name="Nav.Anomalies"><value>Аномалии</value></data>
<data name="Nav.Results"><value>Результаты</value></data>
<data name="Nav.Settings"><value>Настройки</value></data>
<!-- Home / Dashboard -->
<data name="Home.Kicker"><value>Сводка</value></data>
<data name="Home.Title"><value>Поиск аномалий в коэффициентах</value></data>
<data name="Home.Lede"><value>Снимаем линии marathonbet.by по расписанию, ищем разворот фаворита и удерживаем доказательства каждой аномалии.</value></data>
<data name="Home.Stat.Events"><value>Событий в работе</value></data>
<data name="Home.Stat.Snapshots"><value>Снимков сегодня</value></data>
<data name="Home.Stat.Anomalies"><value>Аномалий найдено</value></data>
<data name="Home.Stat.Coverage"><value>Видов спорта</value></data>
<data name="Home.Section.Latest"><value>Свежий поток</value></data>
<data name="Home.Section.Pipeline"><value>Конвейер сбора</value></data>
<data name="Home.Pipeline.Step1"><value>Сбор расписания (`/su`)</value></data>
<data name="Home.Pipeline.Step2"><value>Снимок коэффициентов</value></data>
<data name="Home.Pipeline.Step3"><value>Детектор разворота</value></data>
<data name="Home.Pipeline.Step4"><value>Экспорт XLSX</value></data>
<data name="Home.Empty"><value>Пока пусто. Запустите фоновые сборщики на странице «Настройки», чтобы пошёл поток данных.</value></data>
<!-- Settings — sections -->
<data name="Settings.Kicker"><value>Конфигурация</value></data>
<data name="Settings.Title"><value>Настройки</value></data>
<data name="Settings.Lede"><value>Каждый параметр сборщика, хранилища, детектора и локализации. Изменения сохраняются в appsettings.Local.json и применяются на лету.</value></data>
<data name="Settings.Section.Scraping"><value>Сбор</value></data>
<data name="Settings.Section.Workers"><value>Фоновые задачи</value></data>
<data name="Settings.Section.Storage"><value>Хранилище</value></data>
<data name="Settings.Section.Anomaly"><value>Детектор аномалий</value></data>
<data name="Settings.Section.Localization"><value>Локализация</value></data>
<data name="Settings.Action.Reset"><value>Сбросить раздел</value></data>
<data name="Settings.Action.Save"><value>Сохранить</value></data>
<data name="Settings.Action.SaveAll"><value>Сохранить все</value></data>
<data name="Settings.Confirm.Title"><value>Подтвердите изменения</value></data>
<data name="Settings.Confirm.Body"><value>Параметры будут записаны в appsettings.Local.json и перечитаны службами. Продолжить?</value></data>
<data name="Settings.Saved"><value>Настройки сохранены.</value></data>
<data name="Settings.SaveFailed"><value>Не удалось сохранить настройки.</value></data>
<!-- Settings — Scraping -->
<data name="Settings.Scraping.PollingIntervalSeconds"><value>Интервал опроса (сек)</value></data>
<data name="Settings.Scraping.PollingIntervalSeconds.Hint"><value>Как часто перечитывать список матчей. Минимум 5 секунд.</value></data>
<data name="Settings.Scraping.MaxConcurrentRequests"><value>Параллельных запросов</value></data>
<data name="Settings.Scraping.MaxConcurrentRequests.Hint"><value>Не более 8 — иначе увидим 429.</value></data>
<data name="Settings.Scraping.UserAgents"><value>Пул User-Agent</value></data>
<data name="Settings.Scraping.UserAgents.Hint"><value>По одному значению на строку. Ротируется на запрос.</value></data>
<data name="Settings.Scraping.RetryMaxAttempts"><value>Повторы при сбое</value></data>
<data name="Settings.Scraping.RetryBaseDelayMs"><value>Базовая задержка (мс)</value></data>
<data name="Settings.Scraping.RateLimitRps"><value>Лимит RPS</value></data>
<data name="Settings.Scraping.RateLimitRps.Hint"><value>Запросов в секунду. Рекомендовано 1.</value></data>
<data name="Settings.Scraping.BaseUrl"><value>Базовый URL</value></data>
<data name="Settings.Scraping.RequestTimeoutSeconds"><value>Тайм-аут запроса (сек)</value></data>
<data name="Settings.Scraping.UsePlaywright"><value>Использовать Playwright</value></data>
<!-- Settings — Workers -->
<data name="Settings.Workers.UpcomingScheduleCron"><value>Cron расписания (UPCOMING)</value></data>
<data name="Settings.Workers.UpcomingScheduleCron.Hint"><value>Стандартный cron. По умолчанию каждые 5 минут.</value></data>
<data name="Settings.Workers.LivePollerEnabled"><value>Лайв-сборщик включён</value></data>
<data name="Settings.Workers.UpcomingPollerEnabled"><value>Сборщик расписания включён</value></data>
<data name="Settings.Workers.LivePollIntervalSeconds"><value>Интервал лайв-опроса (сек)</value></data>
<data name="Settings.Workers.LivePollIntervalSeconds.Hint"><value>Пауза между циклами сбора лайв-котировок. По умолчанию 30 с.</value></data>
<data name="Settings.Workers.ResultsPollerEnabled"><value>Сборщик результатов включён</value></data>
<data name="Settings.Workers.ResultsPollerEnabled.Hint"><value>Отключён до Phase 8. Включите только после реализации опроса match-complete.</value></data>
<data name="Settings.Workers.ResultsPollIntervalSeconds"><value>Интервал сборщика результатов (сек)</value></data>
<data name="Settings.Workers.AnomalyDetectionEnabled"><value>Детектор аномалий включён</value></data>
<data name="Settings.Workers.AnomalyDetectionEnabled.Hint"><value>Запускает детектор разворота после паузы на каждом цикле. Отключение приостанавливает анализ без потери накопленных снимков.</value></data>
<!-- Settings — Storage -->
<data name="Settings.Storage.DatabasePath"><value>Путь к SQLite</value></data>
<data name="Settings.Storage.ExportDirectory"><value>Каталог экспорта</value></data>
<data name="Settings.Storage.SnapshotRetentionDays"><value>Хранить снимки (дней)</value></data>
<!-- Settings — Anomaly -->
<data name="Settings.Anomaly.SuspensionGapSeconds"><value>Окно «заморозки» (сек)</value></data>
<data name="Settings.Anomaly.OddsFlipThreshold"><value>Порог флипа (Δ вероятности)</value></data>
<data name="Settings.Anomaly.MinSnapshotCount"><value>Мин. число снимков</value></data>
<data name="Settings.Anomaly.DetectionIntervalSeconds"><value>Интервал детектора (сек)</value></data>
<!-- Settings — Localization -->
<data name="Settings.Localization.DefaultCulture"><value>Язык интерфейса по умолчанию</value></data>
<!-- Locale switcher -->
<data name="Locale.Russian"><value>RU</value></data>
<data name="Locale.English"><value>EN</value></data>
<data name="Locale.Tooltip.Switch"><value>Сменить язык</value></data>
<!-- Theme toggle -->
<data name="Theme.Toggle.Light"><value>Светлая тема</value></data>
<data name="Theme.Toggle.Dark"><value>Тёмная тема</value></data>
<!-- Common -->
<data name="Common.Save"><value>Сохранить</value></data>
<data name="Common.Cancel"><value>Отмена</value></data>
<data name="Common.Reset"><value>Сбросить</value></data>
<data name="Common.Loading"><value>Загрузка…</value></data>
<data name="Common.Empty"><value>Нет данных</value></data>
<data name="Common.Yes"><value>Да</value></data>
<data name="Common.No"><value>Нет</value></data>
<!-- Anomaly (Phase 7 placeholders) -->
<data name="Anomaly.Live"><value>Аномалия</value></data>
<data name="Anomaly.Kind.SuspensionFlip"><value>Разворот после заморозки</value></data>
<data name="Anomaly.Score"><value>Уверенность</value></data>
<!-- Phase 7 — Лента аномалий -->
<data name="Anomaly.Title"><value>Лента аномалий</value></data>
<data name="Anomaly.Lede"><value>Сигнальный журнал «разворотов» в реальном времени. Детектор проходит каждый цикл, считает подразумеваемые вероятности до и после каждой заморозки рынка и ранжирует находки по уверенности.</value></data>
<data name="Anomaly.Severity.Low"><value>Низкая</value></data>
<data name="Anomaly.Severity.Medium"><value>Средняя</value></data>
<data name="Anomaly.Severity.High"><value>Высокая</value></data>
<data name="Anomaly.Filter.AnySeverity"><value>Любая</value></data>
<data name="Anomaly.Filter.Severity"><value>Мин. важность</value></data>
<data name="Anomaly.Filter.Sport"><value>Вид спорта</value></data>
<data name="Anomaly.Filter.From"><value>Обнаружено с</value></data>
<data name="Anomaly.Filter.To"><value>Обнаружено по</value></data>
<data name="Anomaly.Filter.DateRange"><value>Диапазон дат</value></data>
<data name="Anomaly.Filter.MarkRead"><value>Отметить прочитанными</value></data>
<data name="Anomaly.Card.DetectedAt"><value>Обнаружено</value></data>
<data name="Anomaly.Card.Score"><value>Уверенность</value></data>
<data name="Anomaly.Card.Kind"><value>Тип</value></data>
<data name="Anomaly.Card.GapSeconds"><value>Длительность паузы</value></data>
<data name="Anomaly.Evidence.Pre"><value>До паузы</value></data>
<data name="Anomaly.Evidence.Post"><value>После паузы</value></data>
<data name="Anomaly.Evidence.Probability"><value>Подразум. вер.</value></data>
<data name="Anomaly.Evidence.Rate"><value>Кэф</value></data>
<data name="Anomaly.Evidence.SuspensionDuration"><value>Длительность паузы</value></data>
<data name="Anomaly.Evidence.FavouriteSwap"><value>Смена фаворита</value></data>
<data name="Anomaly.Detail.EvidenceTitle"><value>Хроника свидетельств</value></data>
<data name="Anomaly.Detail.LinkBackToEvent"><value>Открыть событие</value></data>
<data name="Anomaly.Detail.BackToFeed"><value>К ленте</value></data>
<data name="Anomaly.Detail.NotFound"><value>Аномалия не найдена — возможно, она была удалена.</value></data>
<data name="Anomaly.Empty.NoneInRange"><value>Под текущие фильтры аномалии не попадают. Снизьте порог важности или расширьте диапазон дат.</value></data>
<data name="Anomaly.Stat.Total"><value>Всего</value></data>
<data name="Anomaly.Nav.UnreadAria"><value>Непрочитанные аномалии</value></data>
<!-- Phase 6 — Список матчей / Лайв / Детали / Экспорт -->
<data name="PreMatch.Title"><value>Расписание до матча</value></data>
<data name="PreMatch.Lede"><value>Предстоящие события с последним предматчевым превью «1 / X / 2». Фильтр по виду спорта, стране, лиге и команде.</value></data>
<data name="PreMatch.Empty"><value>Под текущие фильтры не подпадает ни одно событие. Расширьте диапазон или снимите чипы выше.</value></data>
<data name="PreMatch.Filter.Toolbar"><value>Панель фильтров</value></data>
<data name="PreMatch.Filter.From"><value>С</value></data>
<data name="PreMatch.Filter.To"><value>По</value></data>
<data name="PreMatch.Filter.Sport"><value>Виды спорта</value></data>
<data name="PreMatch.Filter.Country"><value>Страны</value></data>
<data name="PreMatch.Filter.Search"><value>Поиск по лиге или команде</value></data>
<data name="PreMatch.Filter.Search.Placeholder"><value>напр. Реал Мадрид, NBA, Ролан Гаррос…</value></data>
<data name="PreMatch.Column.Time"><value>Время</value></data>
<data name="PreMatch.Column.Country"><value>Страна</value></data>
<data name="PreMatch.Column.League"><value>Лига</value></data>
<data name="PreMatch.Column.Match"><value>Матч</value></data>
<data name="PreMatch.Footer.Events"><value>событий</value></data>
<data name="PreMatch.Footer.Refreshed"><value>обновлено в</value></data>
<data name="Live.Title"><value>Лайв-поток коэффициентов</value></data>
<data name="Live.Lede"><value>Текущие лайв-события с последним сделанным снимком. Список обновляется по настроенному интервалу опроса; строки пульсируют при движении котировки.</value></data>
<data name="Live.AutoRefresh"><value>Автообновление</value></data>
<data name="Detail.Title"><value>Событие</value></data>
<data name="Detail.NotFound"><value>Событие не найдено — возможно, оно убрано из исходного потока.</value></data>
<data name="Detail.BackToList"><value>К расписанию</value></data>
<data name="Detail.Export"><value>Экспорт</value></data>
<data name="Detail.Tabs.Aria"><value>Вкладки разделов ставок</value></data>
<data name="Detail.Tabs.Match"><value>Матч</value></data>
<data name="Detail.Tabs.Period"><value>Период {0}</value></data>
<data name="Detail.NoBoards"><value>Снимков ставок по этому событию ещё нет.</value></data>
<data name="Detail.BetType"><value>Тип</value></data>
<data name="Detail.Side"><value>Сторона</value></data>
<data name="Detail.Threshold"><value>Порог</value></data>
<data name="Detail.Rate"><value>Кэф</value></data>
<data name="Detail.BetType.Win"><value>Победа</value></data>
<data name="Detail.BetType.Draw"><value>Ничья</value></data>
<data name="Detail.BetType.WinFora"><value>Фора</value></data>
<data name="Detail.BetType.Total"><value>Тотал</value></data>
<data name="Detail.Side.Side1"><value>1</value></data>
<data name="Detail.Side.Side2"><value>2</value></data>
<data name="Detail.Side.Draw"><value>X</value></data>
<data name="Detail.Side.Less"><value>Меньше</value></data>
<data name="Detail.Side.More"><value>Больше</value></data>
<data name="Detail.Chart.Title"><value>Динамика коэффициентов</value></data>
<data name="Detail.Chart.Empty"><value>Снимков по этому событию ещё нет.</value></data>
<data name="Detail.Chart.Time"><value>Время</value></data>
<data name="Detail.Chart.Win1"><value>П1</value></data>
<data name="Detail.Chart.Draw"><value>X</value></data>
<data name="Detail.Chart.Win2"><value>П2</value></data>
<data name="Detail.Chart.AccessibleSummary"><value>Показать таблицу значений</value></data>
<data name="Detail.History.Title"><value>История снимков</value></data>
<data name="Detail.History.Source"><value>Источник</value></data>
<data name="Detail.History.BetCount"><value>Ставок</value></data>
<data name="Detail.History.Live"><value>ЛАЙВ</value></data>
<data name="Detail.History.PreMatch"><value>ДО МАТЧА</value></data>
<data name="Export.Kicker"><value>Экспорт</value></data>
<data name="Export.Title"><value>Экспорт в Excel</value></data>
<data name="Export.DateRange.From"><value>Дата начала</value></data>
<data name="Export.DateRange.To"><value>Дата конца</value></data>
<data name="Export.Kind.Label"><value>Тип снимков</value></data>
<data name="Export.Kind.PreMatch"><value>Только до матча</value></data>
<data name="Export.Kind.Live"><value>Только лайв</value></data>
<data name="Export.Kind.Combined"><value>Комбинированный</value></data>
<data name="Export.Submit"><value>Экспорт</value></data>
<data name="Export.Cancel"><value>Отмена</value></data>
<data name="Export.Success"><value>Файл сохранён в {0}</value></data>
<data name="Export.Error.MissingDates"><value>Выберите даты начала и конца.</value></data>
<data name="Export.Error.InvalidRange"><value>Дата конца должна быть не раньше даты начала.</value></data>
<data name="Export.Error.Failed"><value>Экспорт не удался.</value></data>
<data name="Sport.Basketball"><value>Баскетбол</value></data>
<data name="Sport.Football"><value>Футбол</value></data>
<data name="Sport.Tennis"><value>Теннис</value></data>
<data name="Sport.Hockey"><value>Хоккей</value></data>
<data name="Results.Title"><value>Результаты матчей</value></data>
<data name="Results.Lede"><value>Финальные счета загруженных событий. Обходим страницу события, ждём matchIsComplete=true, фиксируем сторону-победителя.</value></data>
<data name="Results.Action.LoadNew"><value>Загрузить результаты</value></data>
<data name="Results.Action.OpenList"><value>К списку</value></data>
<data name="Results.Filter.From"><value>С</value></data>
<data name="Results.Filter.To"><value>По</value></data>
<data name="Results.Filter.Search"><value>Поиск</value></data>
<data name="Results.Filter.Search.Placeholder"><value>Команда, лига, категория…</value></data>
<data name="Results.Filter.Sport"><value>Спорт</value></data>
<data name="Results.Filter.Winner"><value>Победитель</value></data>
<data name="Results.Filter.Winner.All"><value>Любой</value></data>
<data name="Results.Filter.Winner.Side1"><value>Команда 1</value></data>
<data name="Results.Filter.Winner.Side2"><value>Команда 2</value></data>
<data name="Results.Filter.Winner.Draw"><value>Ничья</value></data>
<data name="Results.Column.Time"><value>Время</value></data>
<data name="Results.Column.Country"><value>Страна</value></data>
<data name="Results.Column.League"><value>Лига</value></data>
<data name="Results.Column.Match"><value>Матч</value></data>
<data name="Results.Column.Score"><value>Счёт</value></data>
<data name="Results.Column.Winner"><value>Победитель</value></data>
<data name="Results.Column.CompletedAt"><value>Завершено</value></data>
<data name="Results.Empty"><value>Результатов в выбранном диапазоне ещё нет. Запустите загрузку или подождите завершения матчей.</value></data>
<data name="Results.Footer.Items"><value>результатов</value></data>
<data name="Results.Loader.Kicker"><value>Загрузка</value></data>
<data name="Results.Loader.Title"><value>Загрузить результаты</value></data>
<data name="Results.Loader.Lede"><value>Опросим страницу каждого события, заберём финальный счёт и сторону-победителя. Выберите диапазон или конкретные события.</value></data>
<data name="Results.Loader.Mode"><value>Режим</value></data>
<data name="Results.Loader.Mode.AllInRange"><value>Все в диапазоне</value></data>
<data name="Results.Loader.Mode.Selected"><value>Выбранные события</value></data>
<data name="Results.Loader.Selected.Empty"><value>Все события в этом диапазоне уже имеют результат.</value></data>
<data name="Results.Loader.Selected.CountFormat"><value>{0} выбрано</value></data>
<data name="Results.Loader.Action.Load"><value>Загрузить</value></data>
<data name="Results.Loader.Action.Cancel"><value>Отменить</value></data>
<data name="Results.Loader.Action.Back"><value>Назад</value></data>
<data name="Results.Loader.Progress.Format"><value>{0} / {1}</value></data>
<data name="Results.Loader.Progress.Loaded"><value>Загружено</value></data>
<data name="Results.Loader.Progress.AlreadyLoaded"><value>Уже было</value></data>
<data name="Results.Loader.Progress.NotYetComplete"><value>Не завершено</value></data>
<data name="Results.Loader.Progress.Failed"><value>Ошибка</value></data>
<data name="Results.Loader.Summary.Format"><value>Загружено {0}, пропущено {1}, всего обработано {2}.</value></data>
<data name="Results.Loader.Empty.NoCandidates"><value>Нет событий для загрузки в этом диапазоне.</value></data>
</root>