Add PictureTarget entity that bridges PictureSource to output device, separating processing settings from device connection/calibration state. This enables future target types (Art-Net, E1.31) and cleanly decouples "what to stream" from "where to stream." - Add PictureTarget/WledPictureTarget dataclasses and storage - Split ProcessorManager into DeviceState (health) + TargetState (processing) - Add /api/v1/picture-targets endpoints (CRUD, start/stop, settings, metrics) - Simplify device API (remove processing/settings/metrics endpoints) - Auto-migrate existing device settings to picture targets on first startup - Add Targets tab to WebUI with target cards and editor modal - Add en/ru locale keys for targets UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
343 lines
26 KiB
JSON
343 lines
26 KiB
JSON
{
|
||
"app.title": "WLED Grab",
|
||
"app.version": "Версия:",
|
||
"theme.toggle": "Переключить тему",
|
||
"locale.change": "Изменить язык",
|
||
"auth.login": "Войти",
|
||
"auth.logout": "Выйти",
|
||
"auth.authenticated": "● Авторизован",
|
||
"auth.title": "Вход в WLED Grab",
|
||
"auth.message": "Пожалуйста, введите ваш API ключ для аутентификации и доступа к WLED Grab.",
|
||
"auth.label": "API Ключ:",
|
||
"auth.placeholder": "Введите ваш API ключ...",
|
||
"auth.hint": "Ваш API ключ будет безопасно сохранен в локальном хранилище браузера.",
|
||
"auth.button.cancel": "Отмена",
|
||
"auth.button.login": "Войти",
|
||
"auth.error.required": "Пожалуйста, введите API ключ",
|
||
"auth.success": "Вход выполнен успешно!",
|
||
"auth.logout.confirm": "Вы уверены, что хотите выйти?",
|
||
"auth.logout.success": "Выход выполнен успешно",
|
||
"auth.please_login": "Пожалуйста, войдите для просмотра",
|
||
"displays.title": "Доступные Дисплеи",
|
||
"displays.layout": "\uD83D\uDDA5\uFE0F Дисплеи",
|
||
"displays.information": "Информация о Дисплеях",
|
||
"displays.legend.primary": "Основной Дисплей",
|
||
"displays.legend.secondary": "Вторичный Дисплей",
|
||
"displays.badge.primary": "Основной",
|
||
"displays.badge.secondary": "Вторичный",
|
||
"displays.resolution": "Разрешение:",
|
||
"displays.refresh_rate": "Частота Обновления:",
|
||
"displays.position": "Позиция:",
|
||
"displays.index": "Индекс Дисплея:",
|
||
"displays.loading": "Загрузка дисплеев...",
|
||
"displays.none": "Нет доступных дисплеев",
|
||
"displays.failed": "Не удалось загрузить дисплеи",
|
||
"displays.picker.title": "Выберите Дисплей",
|
||
"displays.picker.select": "Выберите дисплей...",
|
||
"displays.picker.click_to_select": "Нажмите, чтобы выбрать этот дисплей",
|
||
"templates.title": "\uD83D\uDCC4 Шаблоны Движков",
|
||
"templates.description": "Шаблоны захвата определяют, как захватывается экран. Каждый шаблон использует определённый движок захвата (MSS, DXcam, WGC) с настраиваемыми параметрами. Назначайте шаблоны устройствам для оптимальной производительности.",
|
||
"templates.loading": "Загрузка шаблонов...",
|
||
"templates.empty": "Шаблоны захвата не настроены",
|
||
"templates.add": "Добавить Шаблон Движка",
|
||
"templates.edit": "Редактировать Шаблон Движка",
|
||
"templates.name": "Имя Шаблона:",
|
||
"templates.name.placeholder": "Мой Пользовательский Шаблон",
|
||
"templates.description.label": "Описание (необязательно):",
|
||
"templates.description.placeholder": "Опишите этот шаблон...",
|
||
"templates.engine": "Движок Захвата:",
|
||
"templates.engine.hint": "Выберите технологию захвата экрана",
|
||
"templates.engine.select": "Выберите движок...",
|
||
"templates.engine.unavailable": "Недоступен",
|
||
"templates.engine.unavailable.hint": "Этот движок недоступен в вашей системе",
|
||
"templates.config": "Конфигурация",
|
||
"templates.config.show": "Показать конфигурацию",
|
||
"templates.config.none": "Нет дополнительных настроек",
|
||
"templates.config.default": "По умолчанию",
|
||
"templates.created": "Шаблон успешно создан",
|
||
"templates.updated": "Шаблон успешно обновлён",
|
||
"templates.deleted": "Шаблон успешно удалён",
|
||
"templates.delete.confirm": "Вы уверены, что хотите удалить этот шаблон?",
|
||
"templates.error.load": "Не удалось загрузить шаблоны",
|
||
"templates.error.engines": "Не удалось загрузить движки",
|
||
"templates.error.required": "Пожалуйста, заполните все обязательные поля",
|
||
"templates.error.delete": "Не удалось удалить шаблон",
|
||
"templates.test.title": "Тест Захвата",
|
||
"templates.test.description": "Протестируйте этот шаблон перед сохранением, чтобы увидеть предпросмотр захвата и метрики производительности.",
|
||
"templates.test.display": "Дисплей:",
|
||
"templates.test.display.select": "Выберите дисплей...",
|
||
"templates.test.duration": "Длительность Захвата (с):",
|
||
"templates.test.border_width": "Ширина Границы (px):",
|
||
"templates.test.run": "\uD83E\uDDEA Запустить",
|
||
"templates.test.running": "Выполняется тест...",
|
||
"templates.test.results.preview": "Полный Предпросмотр Захвата",
|
||
"templates.test.results.borders": "Извлечение Границ",
|
||
"templates.test.results.top": "Сверху",
|
||
"templates.test.results.right": "Справа",
|
||
"templates.test.results.bottom": "Снизу",
|
||
"templates.test.results.left": "Слева",
|
||
"templates.test.results.performance": "Производительность",
|
||
"templates.test.results.capture_time": "Захват",
|
||
"templates.test.results.extraction_time": "Извлечение",
|
||
"templates.test.results.total_time": "Всего",
|
||
"templates.test.results.max_fps": "Макс. FPS",
|
||
"templates.test.results.duration": "Длительность",
|
||
"templates.test.results.frame_count": "Кадры",
|
||
"templates.test.results.actual_fps": "Факт. FPS",
|
||
"templates.test.results.avg_capture_time": "Средн. Захват",
|
||
"templates.test.error.no_engine": "Пожалуйста, выберите движок захвата",
|
||
"templates.test.error.no_display": "Пожалуйста, выберите дисплей",
|
||
"templates.test.error.failed": "Тест не удался",
|
||
"devices.title": "\uD83D\uDCA1 Устройства",
|
||
"devices.add": "Добавить Новое Устройство",
|
||
"devices.loading": "Загрузка устройств...",
|
||
"devices.none": "Устройства не настроены",
|
||
"devices.failed": "Не удалось загрузить устройства",
|
||
"devices.wled_config": "Конфигурация WLED:",
|
||
"devices.wled_note": "Настройте ваше WLED устройство (эффекты, сегменты, порядок цветов, ограничения питания и т.д.) используя",
|
||
"devices.wled_link": "официальное приложение WLED",
|
||
"devices.wled_note_or": "или встроенный",
|
||
"devices.wled_webui_link": "веб-интерфейс WLED",
|
||
"devices.wled_note_webui": "(откройте IP устройства в браузере).",
|
||
"devices.wled_note2": "Этот контроллер отправляет данные о цвете пикселей и управляет яркостью для каждого устройства.",
|
||
"device.name": "Имя Устройства:",
|
||
"device.name.placeholder": "ТВ в Гостиной",
|
||
"device.url": "URL:",
|
||
"device.url.placeholder": "http://192.168.1.100",
|
||
"device.led_count": "Количество Светодиодов:",
|
||
"device.led_count.hint": "Количество светодиодов, настроенных в вашем WLED устройстве",
|
||
"device.led_count.hint.auto": "Автоматически определяется из WLED устройства",
|
||
"device.button.add": "Добавить Устройство",
|
||
"device.button.start": "Запустить",
|
||
"device.button.stop": "Остановить",
|
||
"device.button.settings": "Основные настройки",
|
||
"device.button.capture_settings": "Настройки захвата",
|
||
"device.button.calibrate": "Калибровка",
|
||
"device.button.remove": "Удалить",
|
||
"device.button.webui": "Открыть веб-интерфейс WLED",
|
||
"device.status.connected": "Подключено",
|
||
"device.status.disconnected": "Отключено",
|
||
"device.status.error": "Ошибка",
|
||
"device.status.processing": "Обработка",
|
||
"device.status.idle": "Ожидание",
|
||
"device.fps": "FPS:",
|
||
"device.display": "Дисплей:",
|
||
"device.remove.confirm": "Вы уверены, что хотите удалить это устройство?",
|
||
"device.added": "Устройство успешно добавлено",
|
||
"device.removed": "Устройство успешно удалено",
|
||
"device.started": "Обработка запущена",
|
||
"device.stopped": "Обработка остановлена",
|
||
"device.metrics.actual_fps": "Факт. FPS",
|
||
"device.metrics.target_fps": "Целев. FPS",
|
||
"device.metrics.frames": "Кадры",
|
||
"device.metrics.errors": "Ошибки",
|
||
"device.health.online": "WLED Онлайн",
|
||
"device.health.offline": "WLED Недоступен",
|
||
"device.health.checking": "Проверка...",
|
||
"device.tutorial.start": "Начать обучение",
|
||
"device.tip.metadata": "Информация об устройстве (кол-во LED, тип, цветовые каналы) определяется автоматически из WLED",
|
||
"device.tip.brightness": "Перетащите для регулировки яркости",
|
||
"device.tip.start": "Запуск или остановка захвата экрана",
|
||
"device.tip.settings": "Основные настройки устройства (имя, URL, интервал проверки)",
|
||
"device.tip.capture_settings": "Настройки захвата (дисплей, шаблон захвата)",
|
||
"device.tip.calibrate": "Калибровка позиций LED, направления и зоны покрытия",
|
||
"device.tip.webui": "Открыть встроенный веб-интерфейс WLED для расширенной настройки",
|
||
"device.tip.add": "Нажмите, чтобы добавить новое WLED устройство",
|
||
"settings.title": "Настройки Устройства",
|
||
"settings.general.title": "Основные Настройки",
|
||
"settings.capture.title": "Настройки Захвата",
|
||
"settings.capture.saved": "Настройки захвата обновлены",
|
||
"settings.capture.failed": "Не удалось сохранить настройки захвата",
|
||
"settings.brightness": "Яркость:",
|
||
"settings.brightness.hint": "Общая яркость для этого WLED устройства (0-100%)",
|
||
"settings.url.hint": "IP адрес или имя хоста вашего WLED устройства",
|
||
"settings.display_index": "Дисплей:",
|
||
"settings.display_index.hint": "Какой экран захватывать для этого устройства",
|
||
"settings.fps": "Целевой FPS:",
|
||
"settings.fps.hint": "Целевая частота кадров (10-90)",
|
||
"settings.capture_template": "Шаблон Движка:",
|
||
"settings.capture_template.hint": "Движок захвата экрана и конфигурация для этого устройства",
|
||
"settings.button.cancel": "Отмена",
|
||
"settings.health_interval": "Интервал Проверки (с):",
|
||
"settings.health_interval.hint": "Как часто проверять статус WLED устройства (5-600 секунд)",
|
||
"settings.button.save": "Сохранить Изменения",
|
||
"settings.saved": "Настройки успешно сохранены",
|
||
"settings.failed": "Не удалось сохранить настройки",
|
||
"calibration.title": "Калибровка Светодиодов",
|
||
"calibration.tip.led_count": "Укажите количество LED на каждой стороне",
|
||
"calibration.tip.start_corner": "Нажмите на угол для выбора стартовой позиции",
|
||
"calibration.tip.direction": "Переключение направления ленты (по часовой / против часовой)",
|
||
"calibration.tip.offset": "Смещение LED — расстояние от LED 0 до стартового угла",
|
||
"calibration.tip.span": "Перетащите зелёные полосы для настройки зоны покрытия",
|
||
"calibration.tip.test": "Нажмите на край для теста LED",
|
||
"calibration.tip.toggle_inputs": "Нажмите на общее количество LED для скрытия боковых полей",
|
||
"calibration.tutorial.start": "Начать обучение",
|
||
"calibration.start_position": "Начальная Позиция:",
|
||
"calibration.position.bottom_left": "Нижний Левый",
|
||
"calibration.position.bottom_right": "Нижний Правый",
|
||
"calibration.position.top_left": "Верхний Левый",
|
||
"calibration.position.top_right": "Верхний Правый",
|
||
"calibration.direction": "Направление:",
|
||
"calibration.direction.clockwise": "По Часовой Стрелке",
|
||
"calibration.direction.counterclockwise": "Против Часовой Стрелки",
|
||
"calibration.leds.top": "Светодиодов Сверху:",
|
||
"calibration.leds.right": "Светодиодов Справа:",
|
||
"calibration.leds.bottom": "Светодиодов Снизу:",
|
||
"calibration.leds.left": "Светодиодов Слева:",
|
||
"calibration.button.cancel": "Отмена",
|
||
"calibration.button.save": "Сохранить",
|
||
"calibration.saved": "Калибровка успешно сохранена",
|
||
"calibration.failed": "Не удалось сохранить калибровку",
|
||
"server.healthy": "Сервер онлайн",
|
||
"server.offline": "Сервер офлайн",
|
||
"error.unauthorized": "Не авторизован - пожалуйста, войдите",
|
||
"error.network": "Сетевая ошибка",
|
||
"error.unknown": "Произошла ошибка",
|
||
"modal.discard_changes": "У вас есть несохранённые изменения. Отменить их?",
|
||
"confirm.title": "Подтверждение Действия",
|
||
"confirm.yes": "Да",
|
||
"confirm.no": "Нет",
|
||
"common.delete": "Удалить",
|
||
"common.edit": "Редактировать",
|
||
"streams.title": "\uD83D\uDCFA Источники",
|
||
"streams.description": "Источники определяют конвейер захвата. Сырой источник захватывает экран с помощью шаблона захвата. Обработанный источник применяет постобработку к другому источнику. Назначайте источники устройствам.",
|
||
"streams.group.raw": "Захват Экрана",
|
||
"streams.group.processed": "Обработанные",
|
||
"streams.section.streams": "\uD83D\uDCFA Источники",
|
||
"streams.add": "Добавить Источник",
|
||
"streams.add.raw": "Добавить Захват Экрана",
|
||
"streams.add.processed": "Добавить Обработанный",
|
||
"streams.edit": "Редактировать Источник",
|
||
"streams.edit.raw": "Редактировать Захват Экрана",
|
||
"streams.edit.processed": "Редактировать Обработанный Источник",
|
||
"streams.name": "Имя Источника:",
|
||
"streams.name.placeholder": "Мой Источник",
|
||
"streams.type": "Тип:",
|
||
"streams.type.raw": "Захват экрана",
|
||
"streams.type.processed": "Обработанный",
|
||
"streams.display": "Дисплей:",
|
||
"streams.display.hint": "Какой экран захватывать",
|
||
"streams.capture_template": "Шаблон Движка:",
|
||
"streams.capture_template.hint": "Шаблон движка, определяющий способ захвата экрана",
|
||
"streams.target_fps": "Целевой FPS:",
|
||
"streams.target_fps.hint": "Целевое количество кадров в секунду (10-90)",
|
||
"streams.source": "Источник:",
|
||
"streams.source.hint": "Источник, к которому применяются фильтры обработки",
|
||
"streams.pp_template": "Шаблон Фильтра:",
|
||
"streams.pp_template.hint": "Шаблон фильтра для применения к источнику",
|
||
"streams.description_label": "Описание (необязательно):",
|
||
"streams.description_placeholder": "Опишите этот источник...",
|
||
"streams.created": "Источник успешно создан",
|
||
"streams.updated": "Источник успешно обновлён",
|
||
"streams.deleted": "Источник успешно удалён",
|
||
"streams.delete.confirm": "Вы уверены, что хотите удалить этот источник?",
|
||
"streams.error.load": "Не удалось загрузить источники",
|
||
"streams.error.required": "Пожалуйста, заполните все обязательные поля",
|
||
"streams.error.delete": "Не удалось удалить источник",
|
||
"streams.test.title": "Тест Источника",
|
||
"streams.test.run": "🧪 Запустить",
|
||
"streams.test.running": "Тестирование источника...",
|
||
"streams.test.duration": "Длительность Захвата (с):",
|
||
"streams.test.error.failed": "Тест источника не удался",
|
||
"postprocessing.title": "\uD83D\uDCC4 Шаблоны Фильтров",
|
||
"postprocessing.description": "Шаблоны обработки определяют фильтры изображений и цветокоррекцию. Назначайте их обработанным источникам для единообразной постобработки на всех устройствах.",
|
||
"postprocessing.add": "Добавить Шаблон Фильтра",
|
||
"postprocessing.edit": "Редактировать Шаблон Фильтра",
|
||
"postprocessing.name": "Имя Шаблона:",
|
||
"postprocessing.name.placeholder": "Мой Шаблон Фильтра",
|
||
"filters.select_type": "Выберите тип фильтра...",
|
||
"filters.add": "Добавить фильтр",
|
||
"filters.remove": "Удалить",
|
||
"filters.move_up": "Вверх",
|
||
"filters.move_down": "Вниз",
|
||
"filters.empty": "Фильтры не добавлены. Используйте селектор ниже для добавления.",
|
||
"filters.brightness": "Яркость",
|
||
"filters.saturation": "Насыщенность",
|
||
"filters.gamma": "Гамма",
|
||
"filters.downscaler": "Уменьшение",
|
||
"filters.pixelate": "Пикселизация",
|
||
"filters.auto_crop": "Авто Обрезка",
|
||
"filters.flip": "Отражение",
|
||
"postprocessing.description_label": "Описание (необязательно):",
|
||
"postprocessing.description_placeholder": "Опишите этот шаблон...",
|
||
"postprocessing.created": "Шаблон успешно создан",
|
||
"postprocessing.updated": "Шаблон успешно обновлён",
|
||
"postprocessing.deleted": "Шаблон успешно удалён",
|
||
"postprocessing.delete.confirm": "Вы уверены, что хотите удалить этот шаблон фильтра?",
|
||
"postprocessing.error.load": "Не удалось загрузить шаблоны фильтров",
|
||
"postprocessing.error.required": "Пожалуйста, заполните все обязательные поля",
|
||
"postprocessing.error.delete": "Не удалось удалить шаблон фильтра",
|
||
"postprocessing.config.show": "Показать настройки",
|
||
"postprocessing.test.title": "Тест шаблона фильтра",
|
||
"postprocessing.test.source_stream": "Источник:",
|
||
"postprocessing.test.running": "Тестирование шаблона фильтра...",
|
||
"postprocessing.test.error.no_stream": "Пожалуйста, выберите источник",
|
||
"postprocessing.test.error.failed": "Тест шаблона фильтра не удался",
|
||
"device.button.stream_selector": "Настройки источника",
|
||
"device.stream_settings.title": "📺 Настройки источника",
|
||
"device.stream_selector.label": "Источник:",
|
||
"device.stream_selector.hint": "Выберите источник, определяющий что это устройство захватывает и обрабатывает",
|
||
"device.stream_selector.none": "-- Источник не назначен --",
|
||
"device.stream_selector.saved": "Настройки источника обновлены",
|
||
"device.stream_settings.border_width": "Ширина границы (px):",
|
||
"device.stream_settings.border_width_hint": "Сколько пикселей от края экрана выбирать для цвета LED (1-100)",
|
||
"device.stream_settings.interpolation": "Режим интерполяции:",
|
||
"device.stream_settings.interpolation.average": "Среднее",
|
||
"device.stream_settings.interpolation.median": "Медиана",
|
||
"device.stream_settings.interpolation.dominant": "Доминантный",
|
||
"device.stream_settings.interpolation_hint": "Как вычислять цвет LED из выбранных пикселей",
|
||
"device.stream_settings.smoothing": "Сглаживание:",
|
||
"device.stream_settings.smoothing_hint": "Временное смешивание между кадрами (0=нет, 1=полное). Уменьшает мерцание.",
|
||
"device.tip.stream_selector": "Настройки источника и проекции LED для этого устройства",
|
||
"streams.group.static_image": "Статические",
|
||
"streams.add.static_image": "Добавить статическое изображение (источник)",
|
||
"streams.edit.static_image": "Редактировать статическое изображение (источник)",
|
||
"streams.type.static_image": "Статическое изображение",
|
||
"streams.image_source": "Источник изображения:",
|
||
"streams.image_source.placeholder": "https://example.com/image.jpg или C:\\path\\to\\image.png",
|
||
"streams.image_source.hint": "Введите URL (http/https) или локальный путь к изображению",
|
||
"streams.validate_image.validating": "Проверка...",
|
||
"streams.validate_image.valid": "Изображение доступно",
|
||
"streams.validate_image.invalid": "Изображение недоступно",
|
||
"targets.title": "⚡ Цели",
|
||
"targets.description": "Цели связывают источники изображений с устройствами вывода. Каждая цель ссылается на устройство и источник, с собственными настройками обработки.",
|
||
"targets.add": "Добавить Цель",
|
||
"targets.edit": "Редактировать Цель",
|
||
"targets.loading": "Загрузка целей...",
|
||
"targets.none": "Цели не настроены",
|
||
"targets.failed": "Не удалось загрузить цели",
|
||
"targets.name": "Имя Цели:",
|
||
"targets.name.placeholder": "Моя Цель",
|
||
"targets.device": "Устройство:",
|
||
"targets.device.hint": "На какое WLED устройство отправлять данные LED",
|
||
"targets.device.none": "-- Выберите устройство --",
|
||
"targets.source": "Источник:",
|
||
"targets.source.hint": "Какой источник изображения захватывать и обрабатывать",
|
||
"targets.source.none": "-- Источник не назначен --",
|
||
"targets.border_width": "Ширина границы (px):",
|
||
"targets.border_width.hint": "Сколько пикселей от края экрана выбирать для цвета LED (1-100)",
|
||
"targets.interpolation": "Режим интерполяции:",
|
||
"targets.interpolation.hint": "Как вычислять цвет LED из выбранных пикселей",
|
||
"targets.interpolation.average": "Среднее",
|
||
"targets.interpolation.median": "Медиана",
|
||
"targets.interpolation.dominant": "Доминантный",
|
||
"targets.smoothing": "Сглаживание:",
|
||
"targets.smoothing.hint": "Временное смешивание между кадрами (0=нет, 1=полное). Уменьшает мерцание.",
|
||
"targets.created": "Цель успешно создана",
|
||
"targets.updated": "Цель успешно обновлена",
|
||
"targets.deleted": "Цель успешно удалена",
|
||
"targets.delete.confirm": "Вы уверены, что хотите удалить эту цель?",
|
||
"targets.error.load": "Не удалось загрузить цели",
|
||
"targets.error.required": "Пожалуйста, заполните все обязательные поля",
|
||
"targets.error.delete": "Не удалось удалить цель",
|
||
"targets.button.start": "Запустить",
|
||
"targets.button.stop": "Остановить",
|
||
"targets.status.processing": "Обработка",
|
||
"targets.status.idle": "Ожидание",
|
||
"targets.status.error": "Ошибка",
|
||
"targets.metrics.actual_fps": "Факт. FPS",
|
||
"targets.metrics.target_fps": "Целев. FPS",
|
||
"targets.metrics.frames": "Кадры",
|
||
"targets.metrics.errors": "Ошибки"
|
||
}
|