Moved the mediaPreviewUrl function to the media API for better organization and clarity. Updated the MediaPanel component to include a preview feature for media assets, allowing users to view processed clips. Enhanced the UI to include a dialog for media previews and added corresponding localization strings in both English and Russian for the new preview functionality.
1043 lines
62 KiB
TypeScript
1043 lines
62 KiB
TypeScript
/** Словарь локали «ru». Плоская правка: ключи обеих локалей обязаны совпадать. */
|
||
export const ru = {
|
||
appName: 'TeleWave',
|
||
nav: {
|
||
dashboard: 'Эфир',
|
||
admin: 'Админка',
|
||
settings: 'Настройки',
|
||
login: 'Войти',
|
||
register: 'Регистрация',
|
||
logout: 'Выйти',
|
||
},
|
||
theme: { light: 'Светлая', dark: 'Тёмная', system: 'Системная' },
|
||
lang: { ru: 'RU', en: 'EN' },
|
||
common: {
|
||
save: 'Сохранить',
|
||
cancel: 'Отмена',
|
||
retry: 'Повторить',
|
||
close: 'Закрыть',
|
||
delete: 'Удалить',
|
||
create: 'Создать',
|
||
loading: 'Загрузка…',
|
||
error: 'Что-то пошло не так',
|
||
search: 'Поиск',
|
||
actions: 'Действия',
|
||
prevPage: 'Предыдущая страница',
|
||
nextPage: 'Следующая страница',
|
||
yes: 'Да',
|
||
no: 'Нет',
|
||
},
|
||
home: {
|
||
title: 'TELEWAVE',
|
||
subtitle: 'ЭФИРНАЯ СЕТКА КАНАЛОВ',
|
||
tagline: 'Твои каналы. Твой эфир. В любое время.',
|
||
cta: 'Войти в эфир',
|
||
ctaRegister: 'Создать аккаунт',
|
||
},
|
||
auth: {
|
||
userName: 'Имя пользователя',
|
||
password: 'Пароль',
|
||
loginTitle: 'Вход в эфир',
|
||
loginSubtitle: 'Введите учётные данные для доступа к сетке каналов',
|
||
registerTitle: 'Новый зритель',
|
||
registerSubtitle: 'Создайте аккаунт, чтобы настроить свою сетку каналов',
|
||
submitLogin: 'Войти',
|
||
submitRegister: 'Зарегистрироваться',
|
||
noAccount: 'Нет аккаунта?',
|
||
haveAccount: 'Уже есть аккаунт?',
|
||
registrationClosed: 'Регистрация закрыта',
|
||
registrationClosedHint:
|
||
'Открытая регистрация отключена. Учётную запись может завести администратор.',
|
||
invalidCredentials: 'Неверное имя пользователя или пароль',
|
||
userNameTaken: 'Это имя пользователя уже занято',
|
||
blocked: 'Аккаунт заблокирован администратором',
|
||
genericError: 'Не удалось выполнить вход. Попробуйте ещё раз',
|
||
},
|
||
air: {
|
||
now: 'Сейчас',
|
||
next: 'Далее',
|
||
ad: 'Реклама',
|
||
bumper: 'Заставка',
|
||
fallback: 'Аварийный запас',
|
||
signOff: 'Конец вещания',
|
||
episode: 'Серия',
|
||
collectionPart: 'часть {{part}} из {{total}}',
|
||
live: 'В эфире',
|
||
volume: 'Громкость',
|
||
noChannels: 'Пока нет доступных каналов. Загляните позже.',
|
||
offline: 'Канал сейчас не в эфире',
|
||
offlineHint: 'Нет расписания или контента. Загляните позже.',
|
||
numbersHint: '↑ / ↓ — переключение каналов по номерам',
|
||
iptv: 'Плейлист IPTV',
|
||
iptvHint:
|
||
'M3U со всеми каналами и программой передач — для VLC, TiviMate и подобных. Доступ к эфиру зашит в сам файл: делиться им нельзя.',
|
||
iptvDone: 'Плейлист скачан. Файл открывает доступ к эфиру — не передавайте его никому.',
|
||
iptvFailed: 'Не удалось собрать плейлист',
|
||
retry: 'Повторить',
|
||
},
|
||
settings: {
|
||
title: 'Настройки аккаунта',
|
||
changeUserName: 'Смена имени пользователя',
|
||
newUserName: 'Новое имя пользователя',
|
||
changePassword: 'Смена пароля',
|
||
currentPassword: 'Текущий пароль',
|
||
newPassword: 'Новый пароль',
|
||
dangerZone: 'Опасная зона',
|
||
deleteAccount: 'Удалить аккаунт',
|
||
deleteAccountConfirm: 'Аккаунт и все данные будут удалены безвозвратно. Продолжить?',
|
||
saved: 'Сохранено',
|
||
},
|
||
admin: {
|
||
groups: {
|
||
title: 'Группы',
|
||
createTitle: 'Создать группу',
|
||
hint: 'Группа — что может попасть в эфир. На неё ссылается слот сетки, из неё стратегия выбирает элемент.',
|
||
name: 'Название',
|
||
description: 'Описание',
|
||
items: 'Позиций',
|
||
units: 'Единиц',
|
||
duration: 'Объём',
|
||
hoursShort: 'ч',
|
||
minutesShort: 'мин',
|
||
hasFilter: 'с правилом',
|
||
composition: 'Состав',
|
||
empty: 'Группа пуста',
|
||
orderHint: 'Порядок задаётся перетаскиванием — по нему идут последовательные стратегии.',
|
||
showAdvanced: 'Дополнительно',
|
||
hideAdvanced: 'Скрыть',
|
||
find: 'Подобрать',
|
||
addFound: 'Добавить найденное',
|
||
found: 'Найдено: {{total}}, новых: {{fresh}}',
|
||
added: 'Добавлено позиций: {{count}}',
|
||
alreadyIn: 'уже в группе',
|
||
mode: {
|
||
label: 'Состав',
|
||
Static: 'Явный список',
|
||
Dynamic: 'По правилу',
|
||
StaticHint: 'Позиции добавляются вручную; правило только помогает их найти.',
|
||
DynamicHint:
|
||
'Состав считается правилом при каждом обращении — новое из библиотеки попадает в эфир само.',
|
||
},
|
||
pinned: 'закреплено',
|
||
byRule: 'по правилу',
|
||
excluded: 'Исключено',
|
||
excludeHint: 'Исключить из состава — правило больше не будет его подставлять',
|
||
restore: 'Вернуть',
|
||
dynamicOrderHint:
|
||
'Порядок: сначала закреплённое (перетаскиванием), затем найденное правилом по алфавиту.',
|
||
previewComposition: 'При этом правиле в составе будет: {{count}}',
|
||
pendingFound: 'Под правило группы подходит нового: {{count}} —',
|
||
pendingAdd: 'Добавить все ({{count}})',
|
||
elementKinds: { Show: 'Шоу', Collection: 'Коллекция' },
|
||
suggestions: {
|
||
title: 'Предложения',
|
||
hint: 'Собрано по текущей библиотеке. Кнопка создаёт группу с этим составом и сохраняет правило набора — новое из библиотеки потом добавится в один клик.',
|
||
stats: '{{shows}} шоу · {{units}} ед.',
|
||
exists: 'уже есть',
|
||
created: 'Группа создана',
|
||
allCreated: 'Все предложения уже созданы.',
|
||
showExisting: 'Показать уже созданные ({{count}})',
|
||
hideExisting: 'Скрыть уже созданные',
|
||
kinds: {
|
||
Genre: 'жанр',
|
||
ShowKind: 'тип',
|
||
Audience: 'рейтинг',
|
||
BigSeries: 'крупный сериал',
|
||
},
|
||
},
|
||
filter: {
|
||
title: 'Правило набора',
|
||
hint: 'В явном списке правило только ищет кандидатов; в группе «по правилу» оно и есть состав.',
|
||
elementKinds: 'Что искать',
|
||
showKinds: 'Тип шоу',
|
||
showKindsHint:
|
||
'Не отмечено — кино и сериалы. Ролики живут отдельной библиотекой и попадают в набор, только если отметить их явно.',
|
||
genres: 'Жанры',
|
||
genresHint: 'Любой из отмеченных.',
|
||
maxAudience: 'Возраст не строже',
|
||
minAudience: 'Возраст не мягче',
|
||
minAudienceHint:
|
||
'Для ночных слотов. В отличие от верхней границы, шоу без рейтинга сюда не попадают — иначе в «взрослое» просочились бы непроставленные мультики.',
|
||
audienceHint:
|
||
'Рейтинги упорядочены по строгости: G → PG → PG-13 → R → NC-17. Шоу без рейтинга остаются в выборке.',
|
||
year: 'Год',
|
||
unitMinutes: 'Длительность единицы, мин',
|
||
unitMinutesHint:
|
||
'Средняя длина серии или фильма. Позиции без готовых ассетов фильтр не отбрасывает.',
|
||
from: 'от',
|
||
to: 'до',
|
||
any: 'любой',
|
||
},
|
||
},
|
||
collections: {
|
||
posters: 'Проставить постеры',
|
||
postersHint:
|
||
'Берёт обложку первой части у коллекций, у которых постера ещё нет. Выбранный руками не трогает.',
|
||
postersDone: 'Постеры проставлены: {{count}}',
|
||
title: 'Коллекции',
|
||
createTitle: 'Создать коллекцию',
|
||
hint: 'Франшиза — упорядоченный набор фильмов, который играется как одно целое.',
|
||
name: 'Название',
|
||
description: 'Описание',
|
||
parts: 'Части',
|
||
units: 'Единиц',
|
||
addShow: 'Добавить шоу',
|
||
pickShow: 'Выберите шоу',
|
||
empty: 'Коллекция пуста',
|
||
orderHint: 'Порядок частей задаётся перетаскиванием — в нём они и пойдут в эфир.',
|
||
suggestions: {
|
||
title: 'Предложения франшиз',
|
||
hint: 'Собрано из полнометражек, не входящих ни в одну коллекцию: что собрать в новую франшизу и чем дополнить уже собранную. Проверьте состав — по названиям догадка иногда промахивается.',
|
||
parts: '{{count}} частей',
|
||
exists: 'уже есть',
|
||
additionBadge: 'дополнение',
|
||
add: 'Добавить',
|
||
added: 'Добавлено в коллекцию: {{count}}',
|
||
created: 'Коллекция создана',
|
||
allCreated: 'Все предложения уже созданы.',
|
||
showExisting: 'Показать уже созданные ({{count}})',
|
||
hideExisting: 'Скрыть уже созданные',
|
||
sources: { Metadata: 'из метаданных', NameGuess: 'по названиям' },
|
||
},
|
||
},
|
||
interstitials: {
|
||
title: 'Ролики',
|
||
hint: 'Реклама, промо и джинглы. Перетащите ролики в сборку блока или в группу справа — блок сохранится коллекцией и пойдёт в эфир целиком.',
|
||
upload: 'Загрузить ролики',
|
||
name: 'Название',
|
||
duration: 'Длительность',
|
||
empty: 'Роликов пока нет',
|
||
noAsset: 'Без файла',
|
||
blocks: 'Блоки',
|
||
noBlocks: 'Блоков пока нет',
|
||
clipsCount: '{{count}} рол.',
|
||
blockBuilder: 'Сборка блока',
|
||
blockName: 'Название блока',
|
||
blockTotal: 'Длительность блока',
|
||
dropHint: 'Перетащите сюда ролики',
|
||
groups: 'Группы роликов',
|
||
pickGroup: 'Выберите группу',
|
||
pickGroupFirst: 'Сначала выберите группу',
|
||
dropToGroup: 'Перетащите сюда ролик или блок',
|
||
openGroup: 'Открыть группу',
|
||
newGroupName: 'Название группы',
|
||
createGroupTitle: 'Создать группу роликов',
|
||
},
|
||
genres: {
|
||
title: 'Жанры',
|
||
hint: 'Справочник жанров: по нему собираются группы контента, в него сводятся жанры из метаданных.',
|
||
name: 'Название',
|
||
slug: 'Ключ',
|
||
slugHint: 'Латиницей, без пробелов — по нему жанр опознаётся при обновлении справочника.',
|
||
aliases: 'Варианты написания',
|
||
aliasesHint:
|
||
'Через запятую. Так жанры провайдеров сводятся к вашему: tmdb:28, action, боевик.',
|
||
order: 'Порядок',
|
||
usage: 'Шоу',
|
||
system: 'Системный',
|
||
create: 'Новый жанр',
|
||
edit: 'Изменить жанр',
|
||
},
|
||
roles: {
|
||
title: 'Роли',
|
||
name: 'Название',
|
||
system: 'Системная',
|
||
create: 'Новая роль',
|
||
rename: 'Переименовать',
|
||
},
|
||
users: {
|
||
title: 'Пользователи',
|
||
userName: 'Имя пользователя',
|
||
role: 'Роль',
|
||
status: 'Статус',
|
||
createdAt: 'Регистрация',
|
||
blocked: 'Заблокирован',
|
||
active: 'Активен',
|
||
block: 'Заблокировать',
|
||
unblock: 'Разблокировать',
|
||
resetPassword: 'Пароль',
|
||
resetPasswordFor: 'Сменить пароль: {{name}}',
|
||
newPassword: 'Новый пароль',
|
||
passwordReset: 'Пароль изменён',
|
||
filterAll: 'Все роли',
|
||
createTitle: 'Создать пользователя',
|
||
password: 'Пароль',
|
||
passwordHint: 'Минимум 8 символов, хотя бы одна цифра и заглавная буква.',
|
||
create: 'Создать',
|
||
created: 'Пользователь создан',
|
||
},
|
||
movies: {
|
||
title: 'Разбор фильмов',
|
||
hint: 'Имя файла разбирается на название и год, по ним ищется фильм в источнике метаданных. Каждый файл становится отдельным шоу; строки, где совпадение неточное, поправьте руками.',
|
||
sources: { manual: 'Из папки manual', disk: 'С моего диска' },
|
||
pickFiles: 'Выбрать файлы',
|
||
scan: 'Разобрать ({{count}})',
|
||
scanning: 'Ищем в источнике…',
|
||
nothingYet: 'Выберите источник и нажмите «Разобрать».',
|
||
noProvider: 'Источник метаданных не настроен — без него искать нечем.',
|
||
file: 'Файл',
|
||
parsed: 'Название и год',
|
||
candidate: 'Кандидат',
|
||
toggleAll: 'Отметить все / снять все',
|
||
year: 'Год',
|
||
research: 'Искать заново',
|
||
empty: 'ничего не нашлось',
|
||
noCandidate: 'без метаданных',
|
||
import: 'Завести ({{count}})',
|
||
imported: 'Заведено фильмов: {{created}}, с метаданными: {{enriched}}',
|
||
uploadStarted: 'Файлы пошли на загрузку — фильмы заведутся по мере готовности',
|
||
collectionsHint:
|
||
'Франшизы после импорта соберутся в коллекции — предложения ждут на вкладке «Коллекции».',
|
||
statuses: {
|
||
Confident: 'совпадение точное',
|
||
Uncertain: 'проверьте',
|
||
NotFound: 'не найдено — впишите название',
|
||
AlreadyInLibrary: 'уже в библиотеке',
|
||
},
|
||
},
|
||
media: {
|
||
title: 'Медиа',
|
||
upload: 'Загрузить',
|
||
preview: 'Просмотр',
|
||
manualButton: 'Из папки manual',
|
||
importButton: 'Импорт',
|
||
importTitle: 'Импорт медиа',
|
||
importHint:
|
||
'Три способа пополнить библиотеку: серии из папки manual в шоу, фильмы пачкой и загрузка выбранных файлов в шоу.',
|
||
importTabs: { movies: 'Фильмы', manual: 'Серии из manual', toShow: 'Файлы в шоу' },
|
||
moviesButton: 'Фильмы',
|
||
manualTitle: 'Ручной разбор папки manual',
|
||
manualHint:
|
||
'Файлы из manual/ не разбираются сканером — выберите нужные и укажите шоу. Импортированные файлы уходят из папки, как и из inbox.',
|
||
manualSelectAll: 'Выбрать все',
|
||
manualSelected: 'Выбрано: {{count}}',
|
||
manualEmpty: 'В папке manual пусто',
|
||
regexPickHint: 'Кликните число в имени файла — по нему соберётся правило для всех файлов:',
|
||
regexPickTitle: 'Это номер серии',
|
||
regexPresets: 'Готовые:',
|
||
regexPresetNames: {
|
||
seriesWord: 'Серия N',
|
||
episodeWord: 'Эпизод N',
|
||
seasonEpisode: 'SxxEyy',
|
||
productionCode: '2ACV01',
|
||
afterDash: 'после тире',
|
||
firstNumber: 'первое число',
|
||
},
|
||
regexClear: 'сбросить',
|
||
manualAlready: 'уже в библиотеке',
|
||
manualRoot: 'корень manual/',
|
||
manualRecognized: 'Распознано: {{count}} из {{total}}',
|
||
manualCleanupHint:
|
||
'Файлы уйдут из папки, спутники (субтитры, nfo) и опустевший каталог будут удалены.',
|
||
manualTruncated: 'Показаны первые 500 файлов — в папке есть ещё.',
|
||
manualShow: 'Шоу',
|
||
manualDetected: 'Определено по имени релиза — проверьте и поправьте, если не то.',
|
||
manualPickShow: 'Выберите шоу',
|
||
manualImport: 'Забрать в шоу',
|
||
manualImported: 'Импортировано файлов: {{count}}',
|
||
uploadToShow: 'Загрузить в шоу',
|
||
toShowTitle: 'Загрузить и добавить в шоу',
|
||
toShowPick: 'Выбрать файлы',
|
||
toShowEmpty: 'Файлы не выбраны',
|
||
toShowPicked: 'Выбрано файлов: {{count}}',
|
||
autoDetectHint:
|
||
'Каждый файл привяжется к шоу, чьё оригинальное (или отображаемое) название есть в имени релиза, напр. «The.Simpsons.S33E01…» → The Simpsons.',
|
||
toShowLibrary: 'В библиотеку',
|
||
toShowSeason: 'Сезон (вручную)',
|
||
toShowAuto: 'авто',
|
||
toShowRegex: 'Regex серии',
|
||
toShowRegexInvalid: 'некорректный regex',
|
||
toShowHint: String.raw`Сезон и regex — необязательны: обычно номера распознаются сами (см. ниже). Regex: 1 группа = серия, 2 группы = сезон и серия. Пример: ^(\d+) для «01. Название.mkv».`,
|
||
toShowPreview: 'Что распознаем',
|
||
toShowMatched: 'шоу распознано у {{matched}} из {{total}}',
|
||
applyToAll: 'Задать всем…',
|
||
toShowUnknown: '—',
|
||
toShowConfirm: 'Загрузить и добавить',
|
||
uploadedCount: 'Загружено файлов: {{count}}',
|
||
uploadingCount: 'Загрузка {{done}}/{{total}}',
|
||
cancelAll: 'Отменить все загрузки',
|
||
skippedDuplicates: 'Пропущено дубликатов: {{count}}',
|
||
queueDrained: 'Обработка завершена — очередь пуста',
|
||
filterActive: 'Активные',
|
||
filterAll: 'Все',
|
||
name: 'Файл',
|
||
status: 'Статус',
|
||
duration: 'Длительность',
|
||
resolution: 'Разрешение',
|
||
processingTime: 'Время обработки',
|
||
empty: 'Пока нет загруженных файлов',
|
||
statuses: {
|
||
Pending: 'В очереди',
|
||
Processing: 'Обработка',
|
||
Ready: 'Готов',
|
||
Failed: 'Ошибка',
|
||
},
|
||
stats: {
|
||
queued: 'Сейчас в очереди',
|
||
queuedShort: 'В очереди',
|
||
processing: 'Сейчас в обработке',
|
||
processingShort: 'В обработке',
|
||
average: 'Среднее время обработки (по недавним)',
|
||
averageShort: 'Ср. время',
|
||
eta: 'Примерное время до конца очереди: оставшаяся работа по среднему, делённая на число параллельных транскодов',
|
||
etaShort: 'Осталось',
|
||
etaSoon: 'меньше минуты',
|
||
hoursShort: 'ч',
|
||
minutesShort: 'мин',
|
||
},
|
||
},
|
||
gallery: {
|
||
title: 'Галерея',
|
||
upload: 'Загрузить',
|
||
empty: 'В этой категории пока нет изображений',
|
||
pickHint: 'Выберите изображение или загрузите новое',
|
||
browseHint: 'Все изображения приложения по категориям',
|
||
sort: {
|
||
newest: 'Сначала новые',
|
||
oldest: 'Сначала старые',
|
||
nameAsc: 'Имя: А–Я',
|
||
nameDesc: 'Имя: Я–А',
|
||
},
|
||
categories: {
|
||
Library: 'Библиотека',
|
||
ShowPoster: 'Постеры шоу',
|
||
EpisodeStill: 'Кадры серий',
|
||
BumperBackground: 'Фоны заставок',
|
||
},
|
||
},
|
||
shows: {
|
||
title: 'Шоу',
|
||
createTitle: 'Создать шоу',
|
||
name: 'Название',
|
||
originalName: 'Оригинальное название (eng)',
|
||
kind: 'Тип',
|
||
kinds: { Series: 'Сериал', Single: 'Полнометражка', Interstitial: 'Ролик' },
|
||
pickerPlaceholder: 'Выберите шоу',
|
||
pickerSearch: 'Поиск по названию…',
|
||
pickerEmpty: 'Ничего не найдено',
|
||
pickerCreate: 'Создать сериал «{{name}}»',
|
||
pickerCreateSingleHint: 'Создать как полнометражку',
|
||
pickerCreated: 'Шоу создано',
|
||
audience: 'Рейтинг',
|
||
audienceUnset: 'Не проставлен',
|
||
audiences: {
|
||
G: 'G — без ограничений',
|
||
PG: 'PG — с родителями',
|
||
'PG-13': 'PG-13 — с 13 лет',
|
||
R: 'R — с 17 со взрослым',
|
||
'NC-17': 'NC-17 — только взрослым',
|
||
},
|
||
seasons: 'Сезоны',
|
||
loadedSeasons: 'Загружены сезоны',
|
||
genre: 'Жанр',
|
||
allGenres: 'Все жанры',
|
||
allKinds: 'Все типы',
|
||
deleteTitle: 'Удалить шоу?',
|
||
deleteHint: '«{{name}}» будет удалено из библиотеки. Отменить это нельзя.',
|
||
deleteWithMedia: 'Также удалить медиа: файлов {{count}}',
|
||
deleteWithMediaHint:
|
||
'Иначе файлы останутся в списке медиа ничьими и продолжат занимать место.',
|
||
deleteWithSchedule: 'Также вырезать из будущего эфира',
|
||
deleteWithScheduleHint:
|
||
'Без этого удаление отклонят, пока шоу стоит в ленте. На месте вырезанного зритель увидит фон, пока хвост не пересоберут.',
|
||
otherGenres: 'Остальные жанры',
|
||
bulk: {
|
||
selected: 'Отмечено: {{count}}',
|
||
selectPage: 'Отметить все на странице',
|
||
noGenre: 'Жанр не менять',
|
||
keepAudience: 'Рейтинг не менять',
|
||
apply: 'Применить',
|
||
tagged: 'Обновлено шоу: {{count}}',
|
||
clear: 'Снять выбор',
|
||
enrich: 'Метаданные из {{provider}}',
|
||
enrichHint:
|
||
'Найти по названию и применить — только тем, у кого источник ещё не привязан. Неоднозначные совпадения пропускаются.',
|
||
enriching: 'Ищем…',
|
||
enriched: 'Метаданные применены: {{count}}',
|
||
moreSkipped: 'Ещё пропущено: {{count}}',
|
||
toCollection: 'В коллекцию…',
|
||
toCollectionHint:
|
||
'Отмеченные шоу уйдут во франшизу. Порядок частей — по году выпуска; поправить его можно перетаскиванием в карточке коллекции.',
|
||
newCollection: 'Новая коллекция',
|
||
addToCollection: 'Добавить ({{count}})',
|
||
addedToCollection: '«{{name}}» пополнена: {{count}}',
|
||
},
|
||
genresEmpty: 'Жанры не проставлены',
|
||
genresEdit: 'Жанры',
|
||
genresHint:
|
||
'Отметьте жанры шоу. Основной показывается в списке; в отборе контента участвуют все.',
|
||
genrePrimary: 'основной',
|
||
inGroups: 'В группах',
|
||
inChannels: 'В эфире каналов',
|
||
inCollections: 'Входит в коллекции',
|
||
episodes: 'Серии',
|
||
episode: 'Серия',
|
||
noEpisodes: 'Серий пока нет',
|
||
addMedia: 'Добавить медиа',
|
||
addMediaHint: 'Готовые файлы, ещё не добавленные в это шоу. Выбранные добавятся сериями.',
|
||
filterAssets: 'Фильтр по имени, напр. Family.Guy.S16',
|
||
selectAll: 'Выбрать все',
|
||
deselectAll: 'Снять все',
|
||
addSelected: 'Добавить выбранные',
|
||
noMatches: 'Нет подходящих файлов',
|
||
addedCount: 'Добавлено серий: {{count}}',
|
||
candidatesTruncated:
|
||
'Показаны не все файлы (слишком много готовых ассетов) — уточните фильтр, чтобы увидеть остальные.',
|
||
},
|
||
channels: {
|
||
number: 'Номер',
|
||
numberPlaceholder: 'не задан',
|
||
utcOffset: 'Часовой пояс, ч',
|
||
utcOffsetHint:
|
||
'Целыми часами: 3 — Москва, 0 — UTC, −5 — Нью-Йорк. В этом времени задаётся вся сетка и показывается расписание.',
|
||
dayStart: 'Начало вещательных суток',
|
||
dayStartHint: 'Ночной блок до этого времени относится к предыдущему дню.',
|
||
disabled: 'выключен',
|
||
layers: 'Слои',
|
||
layersHint: 'Побеждает слой с большим приоритетом. Фоновый лежит под всеми и закрывает дыры.',
|
||
background: 'фон',
|
||
newLayerName: 'Новый слой',
|
||
addSlotHere: 'Добавить слот',
|
||
newSlot: 'Новый слот',
|
||
/** Автосборка сетки по профилю: предпросмотр плана и его создание. */
|
||
transfer: {
|
||
action: 'Импорт / экспорт',
|
||
title: 'Обмен конфигурацией сетки',
|
||
hint: 'Файл ссылается на группы и стыки по именам, поэтому переносится между каналами и установками. Запрос к ИИ никуда не отправляется — вы копируете его в свою модель и приносите ответ назад вкладкой импорта.',
|
||
tabs: { export: 'Экспорт', import: 'Импорт', ai: 'Запрос к ИИ' },
|
||
exportHint:
|
||
'Выгружает слои, слоты, правила и ссылки на группы и стыки. Годится и как бэкап перед экспериментом, и как образец для модели.',
|
||
exportAction: 'Скачать файл',
|
||
exported: 'Файл выгружен',
|
||
importHint:
|
||
'Загрузите файл или вставьте JSON — например ответ модели. Недостающие группы и коллекции файл может принести с собой; шоу не создаются никогда — их приносит загрузка медиа. Незнакомые ссылки не валят импорт: такие слоты пропускаются, и вы увидите их списком.',
|
||
pickFile: 'Выбрать файл',
|
||
replace: 'Снести существующие слоты',
|
||
pastePlaceholder: 'Вставьте JSON конфигурации сетки',
|
||
importAction: 'Загрузить',
|
||
imported: 'Создано слотов: {{slots}}, пропущено: {{skipped}}',
|
||
importedLibrary: 'Заведено групп: {{groups}}, коллекций: {{collections}}',
|
||
badJson: 'Это не похоже на JSON — проверьте, что скопирован весь ответ целиком.',
|
||
warnings: 'Что не удалось разобрать',
|
||
aiHint:
|
||
'Соберём запрос: параметры канала, ваши группы и библиотека, ваши референсы и пожелания, плюс схема ответа. Модель может собрать нужные ей группы сама — они заведутся при импорте.',
|
||
references: 'Референс-каналы',
|
||
referencesPlaceholder: '2×2, Paramount Comedy',
|
||
referencesHint:
|
||
'Через запятую. На их ритм модель будет равняться — длина блоков, прайм, ночь.',
|
||
notes: 'Пожелания',
|
||
notesPlaceholder: 'Например: утром детское, вечером кино, ночью — взрослый блок',
|
||
buildPrompt: 'Собрать запрос',
|
||
copyPrompt: 'Скопировать',
|
||
copied: 'Запрос скопирован',
|
||
aiNext: 'Отправьте это в свою модель, а полученный JSON вставьте во вкладке «Импорт».',
|
||
},
|
||
generate: {
|
||
action: 'Собрать сетку',
|
||
title: 'Автосборка сетки',
|
||
hint: 'Профиль задаёт ритм суток: длину блоков, что стоит в прайме и чем закрыта ночь. Группы под каждую полосу подбираются из существующих — по рейтингу, типу контента и запасу серий.',
|
||
modes: {
|
||
FillGaps: 'Заполнить дыры',
|
||
Rebuild: 'Собрать неделю с нуля',
|
||
},
|
||
modeHints: {
|
||
FillGaps: 'Существующие слоты не трогаются — застраивается только незакрытое время.',
|
||
Rebuild: 'Все слоты шаблона сносятся; выходные строятся отдельным слоем поверх будних.',
|
||
},
|
||
summary: 'Будет создано слотов: {{slots}} — это {{percent}}% свободного времени недели.',
|
||
willRemove: 'Будет снесено слотов: {{count}}.',
|
||
fallback: 'Аварийной группой станет «{{name}}» — ею закрываются паузы между слотами.',
|
||
nothing: 'Создавать нечего: свободного времени в сетке нет.',
|
||
create: 'Собрать',
|
||
done: 'Создано слотов: {{created}}, снесено: {{removed}}.',
|
||
},
|
||
editSlot: 'Слот',
|
||
slotTitle: 'Название блока',
|
||
slotStart: 'Начало',
|
||
slotDuration: 'Бюджет, мин',
|
||
weekday: 'День недели',
|
||
everyDay: 'каждый день',
|
||
daypart: 'Дейпарт',
|
||
slotKind: 'Тип слота',
|
||
group: 'Группа',
|
||
pickGroup: 'Выберите группу',
|
||
strategy: 'Стратегия',
|
||
cooldownDays: 'Остывание, дней',
|
||
cooldownHint: 'Не брать то, что уже выходило за этот срок.',
|
||
blockMode: 'Блок',
|
||
blockValue: 'Значение',
|
||
overflow: 'Если не помещается',
|
||
overflowHint: 'Как поступить с элементом, который не влезает в бюджет слота.',
|
||
repeatDaysAgo: 'Суток назад',
|
||
repeatTime: 'Время',
|
||
repeatDuration: 'Длительность, мин',
|
||
anchor: 'Якорь',
|
||
anchorHint:
|
||
'Якорь держит старт жёстко: через него не переносят то, что не влезает. Округление мягкое — сдвигает старт до круглого времени, если это укладывается в допуск.',
|
||
maxDrift: 'Допуск, мин',
|
||
snap: 'Округление',
|
||
snapOff: 'нет',
|
||
resizeSlot: 'Потянуть за край — длительность',
|
||
copyDay: 'Копировать день',
|
||
copyDayFrom: 'Копировать {{day}} в:',
|
||
copy: 'Копировать',
|
||
layerVisible: 'Показывать слой',
|
||
layerName: 'Название слоя',
|
||
layerApplicability: 'Когда действует',
|
||
applicabilityHint:
|
||
'Разделы объединяются по ИЛИ: слой действует, если дата подходит хотя бы под одно условие. Ничего не заполнено — действует всегда.',
|
||
applicabilityWeekdays: 'Дни недели',
|
||
applicabilityDateRanges: 'Диапазоны дат',
|
||
applicabilityAnnual: 'Ежегодно (месяц / день)',
|
||
applicabilityDates: 'Конкретные даты',
|
||
applicabilityNone: 'не задано',
|
||
showForDate: 'Сетка на дату',
|
||
allDates: 'Все слои',
|
||
tabs: {
|
||
grid: 'Сетка',
|
||
rules: 'Правила',
|
||
junctions: 'Стыки',
|
||
viewer: 'Зритель',
|
||
settings: 'Настройки',
|
||
air: 'Эфир',
|
||
},
|
||
noTemplate: 'Сетка канала не загрузилась',
|
||
createTemplate: 'Создать сетку',
|
||
createTemplateHint: 'Появится пустая сетка с фоновым слоем — дальше добавляйте слои и слоты.',
|
||
rules: 'Правила отбора',
|
||
rulesHint:
|
||
'Жёсткие фильтры: отсекают неподходящее до жребия. Как и правка сетки, эфир не двигают — нужно применить.',
|
||
audienceWindows: 'Детское время',
|
||
noAudienceWindows: 'Окон нет — возраст ничем не ограничен.',
|
||
audienceWindowsHint:
|
||
'В окне в эфир идёт контент не строже выбранной категории. Окно может переходить через полночь. Контент без категории не отсекается.',
|
||
from: 'С',
|
||
to: 'До',
|
||
maxAudience: 'Не строже',
|
||
repeatLimit: 'Потолок повторов',
|
||
repeatWindowDays: 'Окно, суток',
|
||
repeatMax: 'Не чаще, раз',
|
||
repeatLimitHint:
|
||
'Считается по уже записанной ленте. Если потолка достигли все кандидаты, слот всё равно заполняется: пустой эфир хуже раннего повтора.',
|
||
preview: 'Предпросмотр',
|
||
previewHide: 'Свернуть предпросмотр',
|
||
previewHint: 'Прогон по текущим правилам: ничего не пишется, курсоры слотов не двигаются.',
|
||
previewDays_one: '{{count}} сутки',
|
||
previewDays_few: '{{count}} суток',
|
||
previewDays_many: '{{count}} суток',
|
||
previewTabs: { programme: 'Программа', tape: 'Лента', problems: 'Проблемы' },
|
||
noProblems: 'Проблем нет',
|
||
andMore: 'и ещё {{count}}',
|
||
heatmap: 'Повторы: шоу × сутки',
|
||
heatmapTotal: 'всего',
|
||
issues: 'Проверки: ошибок {{errors}}, предупреждений {{warnings}}',
|
||
goToSlot: 'к слоту',
|
||
issueKinds: {
|
||
GroupEmpty: 'Пустая группа',
|
||
GroupTooSmall: 'Мало контента',
|
||
GridGap: 'Дыра в сетке',
|
||
SlotOverlap: 'Слоты пересекаются',
|
||
CooldownUnreachable: 'Недостижимое остывание',
|
||
AudienceConflict: 'Возрастной конфликт',
|
||
GroupMissing: 'Группа не выбрана',
|
||
},
|
||
viewer: 'Как выглядит у зрителя',
|
||
viewerHint:
|
||
'Оверлеи рисуются поверх картинки на клиенте — видео не перекодируется. Всё по умолчанию выключено.',
|
||
logo: 'Логотип',
|
||
noLogo: 'нет',
|
||
pickLogo: 'Выбрать логотип',
|
||
logoCorner: 'Угол',
|
||
logoOpacity: 'Прозрачность',
|
||
corners: {
|
||
TopLeft: 'Слева вверху',
|
||
TopRight: 'Справа вверху',
|
||
BottomLeft: 'Слева внизу',
|
||
BottomRight: 'Справа внизу',
|
||
},
|
||
showClock: 'Показывать часы',
|
||
analogFilter: 'Аналоговый фильтр',
|
||
analogFilterHint: 'Сила 0..1. Ноль — выключен; переборщить очень легко.',
|
||
whyHere: 'Почему это здесь',
|
||
priority: 'приоритет',
|
||
traceLayer: 'Слой',
|
||
traceSlot: 'Слот',
|
||
traceGroup: 'Группа',
|
||
traceCollection: 'Коллекция',
|
||
traceStrategy: 'Стратегия',
|
||
traceJunction: 'Врезки',
|
||
traceDrift: 'дрейф {{minutes}} мин',
|
||
traceSnapped: 'старт округлён',
|
||
traceCooldown: 'остывание {{days}} дн.',
|
||
traceCandidates: 'кандидатов после остывания: {{count}}',
|
||
diffSummary: 'Затронет {{total}} записей, изменятся {{changed}}',
|
||
diffSoon: 'В ближайшие сутки изменится записей: {{count}}',
|
||
diffNoChanges: 'Эфир не изменится',
|
||
copyTemplate: 'Скопировать сетку с канала',
|
||
pickSourceChannel: 'Выберите канал-источник',
|
||
copyHere: 'Скопировать сюда',
|
||
copyTemplateHint:
|
||
'Слои, слоты, стыки и правила выбранного канала заменят сетку этого канала. Группы общие и не копируются.',
|
||
copyTemplateConfirm:
|
||
'Текущая сетка этого канала будет заменена сеткой выбранного канала. Продолжить?',
|
||
templateCopied: 'Скопировано: слоёв {{layers}}, слотов {{slots}}',
|
||
copyDroppedBumpers: 'Врезок без блока заставки: {{count}} — донастройте руками',
|
||
// Не «Сбросить»: так уже называется откат правок к эфирному состоянию (ключ restore).
|
||
reset: 'Очистить сетку',
|
||
resetConfirm:
|
||
'Сетка канала будет снята полностью — все слои и слоты, — а будущий эфир, собранный по ней, удалён. Прошлое и идущая сейчас запись останутся. Продолжить?',
|
||
resetDone: 'Сброшено: слоёв {{layers}}, слотов {{slots}}, записей эфира {{entries}}',
|
||
resetHint:
|
||
'Пока канал включён, лента отстроится заново по пустой сетке — аварийной группой. Чтобы эфир остался пустым, снимите её в правилах или выключите канал.',
|
||
fallbackGroup: 'Аварийная группа',
|
||
fallbackGroupNone: 'Нет — только филлер канала',
|
||
fallbackGroupHint:
|
||
'Чем закрывается пауза, если пуст и фоновый слой. Её же играет пустая сетка — весь эфир, пока слотов нет. Проставляется автосборкой сетки, если своя не выбрана.',
|
||
postChecks: 'Пост-проверки',
|
||
breakLimit: 'Потолок врезок в час, мин',
|
||
genreShare: 'Потолок доли жанра за сутки, %',
|
||
fallbackShare: 'Потолок доли фона, %',
|
||
postChecksHint:
|
||
'Пост-проверки считаются по готовой ленте и только предупреждают — ничего не переигрывается.',
|
||
previewKinds: {
|
||
Program: 'Программа',
|
||
Fallback: 'Фон',
|
||
SignOff: 'Конец вещания',
|
||
Ad: 'Реклама',
|
||
Promo: 'Анонс',
|
||
Bumper: 'Заставка',
|
||
},
|
||
previewLoad: 'Врезки по часам, пик — {{peak}} мин',
|
||
junctions: 'Стыки',
|
||
junctionsHint:
|
||
'Что играет между программами: реклама, анонсы, заставки. Слот может взять свой стык, иначе берётся стык по умолчанию.',
|
||
defaultJunction: 'Стык по умолчанию',
|
||
noJunction: 'без стыка',
|
||
junctionBetween: 'Стык внутри слота',
|
||
junctionAfter: 'Стык после слота',
|
||
junctionDefault: 'по умолчанию',
|
||
junctionsUsed: 'Используются в этом канале',
|
||
junctionsNoneUsed: 'Канал не ссылается ни на один стык — между программами ничего не играет.',
|
||
openJunctionEditor: 'Редактор стыков',
|
||
pendingChanges: 'Правила изменены — эфир идёт по старым.',
|
||
restore: 'Сбросить изменения',
|
||
restoreConfirm:
|
||
'Вернуть сетку к тому состоянию, по которому идёт эфир? Всё, что изменено после последнего применения, будет потеряно.',
|
||
restored: 'Сетка возвращена к эфирной: слотов — {{count}}.',
|
||
restoreDropped:
|
||
'Ссылок не восстановлено: {{count}} — группа или стык были удалены после применения.',
|
||
apply: 'Применить',
|
||
applied: 'Эфир пересобран, записей: {{count}}',
|
||
applyReport: 'Отчёт о применении',
|
||
applyReportWarnings:
|
||
'Планировщик выполнил не все правила — предупреждений: {{count}}. Эфир собран, но эти места стоит посмотреть.',
|
||
weekdays: {
|
||
0: 'Вс',
|
||
1: 'Пн',
|
||
2: 'Вт',
|
||
3: 'Ср',
|
||
4: 'Чт',
|
||
5: 'Пт',
|
||
6: 'Сб',
|
||
},
|
||
dayparts: { Morning: 'Утро', Day: 'День', Prime: 'Прайм', Night: 'Ночь' },
|
||
slotKinds: { Content: 'Контент', Repeat: 'Повтор', SignOff: 'Конец вещания' },
|
||
blockModes: { Count: 'Единиц', Duration: 'Минут', FillSlot: 'Весь слот' },
|
||
overflows: {
|
||
ContinueNext: 'Доиграть в следующий раз',
|
||
ExtendSlot: 'Растянуть слот',
|
||
SkipIfNotFits: 'Не начинать',
|
||
},
|
||
strategies: {
|
||
Sequential: 'По порядку',
|
||
RandomWithCooldown: 'Случайно с остыванием',
|
||
Fixed: 'Фиксированный элемент',
|
||
},
|
||
warnings: {
|
||
SlotEmpty: 'Слот не дал контента',
|
||
DriftExceeded: 'Старт ушёл за допуск',
|
||
CooldownExhausted: 'Остывание отсекло всех',
|
||
RepeatSourceEmpty: 'Нечего повторять',
|
||
FallbackEmpty: 'Нечем закрыть паузы',
|
||
CandidatesFiltered: 'Возрастной потолок отсёк всех',
|
||
BreakLimitExceeded: 'Врезок в часе больше потолка',
|
||
GenreShareExceeded: 'Доля жанра выше нормы',
|
||
FallbackShareExceeded: 'Аварийного запаса в эфире больше нормы',
|
||
},
|
||
|
||
title: 'Каналы',
|
||
createTitle: 'Создать канал',
|
||
name: 'Название',
|
||
slug: 'Slug',
|
||
state: 'Состояние',
|
||
enabled: 'В эфире',
|
||
enabledLabel: 'Канал в эфире',
|
||
settings: 'Настройки',
|
||
filler: 'Заглушка',
|
||
noFiller: 'Без заглушки',
|
||
noSchedule: 'Расписание ещё не построено',
|
||
airToday: 'Сегодня',
|
||
airCount: 'Записей за сутки: {{count}}',
|
||
airHidePast: 'Скрывать прошедшее',
|
||
airHideBreaks: 'Скрывать врезки',
|
||
},
|
||
junctions: {
|
||
title: 'Стыки',
|
||
hint: 'Что играет между программами: реклама, анонсы, заставки. Стык общий для всех каналов — канал только выбирает, какой поставить в слот.',
|
||
newName: 'Новый стык',
|
||
empty0: 'Стыков пока нет.',
|
||
empty: 'пусто',
|
||
from: 'конец',
|
||
to: 'начало',
|
||
fork: 'развилка',
|
||
addElement: '+ врезка',
|
||
maxTotal: 'Потолок, с',
|
||
usedInChannels: 'в каналах: {{count}}',
|
||
cannotDeleteUsed: 'Стык используется каналами — сначала снимите ссылки.',
|
||
splitOut: 'Вынести из развилки',
|
||
mergeIntoFork: 'Объединить с предыдущей в развилку',
|
||
element: 'Врезка',
|
||
kind: 'Тип',
|
||
kinds: {
|
||
Ad: 'Реклама',
|
||
Promo: 'Анонс',
|
||
Bumper: 'Заставка',
|
||
Filler: 'Заполнитель',
|
||
},
|
||
group: 'Группа',
|
||
pickGroup: 'выберите группу',
|
||
bumperTemplate: 'Блок заставки',
|
||
pickBumper: 'выберите блок',
|
||
bumperVariant: 'Подблок',
|
||
bumperVariantAuto: 'по триггеру и весам',
|
||
bumperVariantHint:
|
||
'Оставьте «по триггеру и весам», чтобы на смене шоу и между сериями играли разные тексты.',
|
||
amountMode: 'Чем меряется',
|
||
amountModes: { Count: 'Единиц', Duration: 'Минут' },
|
||
count: 'Сколько единиц',
|
||
minutes: 'Сколько минут',
|
||
minutesShort: ' мин',
|
||
amountHint:
|
||
'В смешанной группе (ролики и готовые блоки) считайте минутами: одна «единица» там — то ли ролик, то ли блок.',
|
||
required: 'Обязательная',
|
||
requiredHint:
|
||
'Обязательность решает, кого выбросить при нехватке времени. На порядок показа она не влияет — он задаётся местом в цепочке.',
|
||
choiceWeight: 'Вес в развилке',
|
||
choiceWeightHint: 'Чем больше — тем чаще играет именно эта врезка (0 — не выбирается).',
|
||
conditions: 'Условия показа',
|
||
onlyOnChange: 'Только при смене шоу',
|
||
chance: 'Вероятность, %',
|
||
chanceHint:
|
||
'Интервал считается по этой врезке отдельно. У развилки жребий один на всех: бросает выбранный вариант, и его вероятность — вероятность всей развилки. Жребий берётся из seed генерации, поэтому пересборка не тасует врезки.',
|
||
minInterval: 'Не чаще, чем раз в, мин',
|
||
dayparts: 'Дейпарты',
|
||
daypartsHint: 'Ничего не выбрано — врезка идёт в любых дейпартах.',
|
||
timeWindow: 'Окно суток канала',
|
||
clearWindow: 'Сбросить',
|
||
timeWindowHint: 'Пусто — в любое время. Окно может переходить через полночь.',
|
||
nearHour: 'Рядом с круглым часом',
|
||
nearHourUnit: 'мин до и после :00',
|
||
nearHourHint:
|
||
'0 — без привязки. Сигнал точного времени и джингл ставятся так: врезка играет только в окрестности :00, а не когда-нибудь в этом часе.',
|
||
badgeNearHour: '±{{minutes}} мин от часа',
|
||
badgeOnChange: 'на смене',
|
||
badgeInterval: 'раз в {{minutes}} мин',
|
||
},
|
||
bumpers: {
|
||
title: 'Заставки',
|
||
hint: 'Блоки заставок общие для всех каналов: оформление и звук — у блока, текст — у подблоков. В эфир заставка попадает врезкой стыка.',
|
||
empty: 'Блоков заставок пока нет.',
|
||
newName: 'Название блока',
|
||
createTitle: 'Создать блок заставки',
|
||
newNamePlaceholder: 'Название блока',
|
||
newVariantName: 'Новый текст',
|
||
sampleChannel: 'Смотреть глазами канала',
|
||
sampleChannelNone: 'без канала',
|
||
sampleChannelHint: 'Блок общий, но образцы подстановки берутся у выбранного канала.',
|
||
name: 'Название',
|
||
font: 'Шрифт',
|
||
fontSans: 'Гротеск',
|
||
fontSerif: 'Антиква',
|
||
colorBg: 'Фон (цвет 1)',
|
||
colorBg2: 'Фон (цвет 2)',
|
||
colorAccent: 'Акцент',
|
||
colorText: 'Текст',
|
||
saveStyle: 'Сохранить оформление',
|
||
seconds: 'с',
|
||
defaultDuration: '≈8 с (джингл)',
|
||
variantsCount: 'текстов: {{count}}',
|
||
usedInJunctions: 'во врезках: {{count}}',
|
||
cannotDeleteUsed: 'Блок используется во врезках стыков — сначала снимите ссылки.',
|
||
audio: 'Звук',
|
||
audioHint: 'Длина звука задаёт длительность заставки; без него — синтезированный джингл.',
|
||
background: 'Фон',
|
||
backgroundFieldHint: 'Картинка фона блока; иначе — градиент палитры или постер шоу.',
|
||
backgroundPick: 'Выбрать из галереи',
|
||
backgrounds: {
|
||
Template: 'Фон блока',
|
||
NextPoster: 'Постер следующего шоу',
|
||
NowPoster: 'Постер предыдущего шоу',
|
||
Clip: 'Готовый ролик',
|
||
},
|
||
backgroundClip: 'Ролик-подложка',
|
||
pickClip: 'Выберите ролик',
|
||
backgroundClipHint:
|
||
'Текст пишется поверх видео. Длину заставки задаёт сам ролик; звук блока подрезается под неё, а без звука играет оригинальная дорожка ролика.',
|
||
fileLoaded: 'загружено',
|
||
fileDefault: 'по умолчанию',
|
||
upload: 'Загрузить',
|
||
reset: 'Сбросить',
|
||
variants: 'Подблоки (тексты)',
|
||
variantsHint:
|
||
'Разный текст на одной музыке и оформлении. Правило показа и фон — у каждого подблока свои.',
|
||
addVariant: 'Добавить текст',
|
||
variantName: 'Название',
|
||
trigger: 'Показывать',
|
||
triggers: {
|
||
OnShowChange: 'При смене шоу',
|
||
BetweenEpisodes: 'Между сериями',
|
||
Both: 'Оба',
|
||
},
|
||
weight: 'Вес',
|
||
lineStyles: { Label: 'Подпись', Title: 'Название', Caption: 'Мелкая' },
|
||
lineColors: { Accent: 'Акцент', Text: 'Текст' },
|
||
addLine: 'Строка',
|
||
presets: 'Пресеты',
|
||
preset_nowNext: 'Сейчас / Далее',
|
||
preset_nextAt: 'Далее в …',
|
||
preset_channel: 'Логотип канала',
|
||
presetNow: 'СЕЙЧАС',
|
||
presetNext: 'ДАЛЕЕ',
|
||
presetNextAt: 'ДАЛЕЕ В',
|
||
framePreview: 'Кадр',
|
||
framePreviewHint: 'Подстановка образцами: так строка будет выглядеть в эфире.',
|
||
unknownPlaceholder: 'Неизвестный плейсхолдер: {{tokens}}',
|
||
volatileHint: 'каждый показ уникален — кэш рендера не работает',
|
||
render: 'Отрендерить примеры',
|
||
rendering: 'Рендерим…',
|
||
renderHint: 'Настоящий ffmpeg-рендер всех подблоков со звуком — несколько секунд.',
|
||
tokens: {
|
||
channel: 'Название канала',
|
||
'channel.number': 'Номер канала',
|
||
'now.title': 'Текущее шоу',
|
||
'next.title': 'Следующее шоу',
|
||
'now.episode': 'Серия текущего',
|
||
'next.episode': 'Серия следующего',
|
||
'next.year': 'Год следующего',
|
||
'next.genre': 'Жанр следующего',
|
||
'next.time': 'Время старта следующего',
|
||
'tonight.title': 'Вечерняя программа',
|
||
'tonight.time': 'Время вечерней программы',
|
||
'tomorrow.title': 'Программа завтра вечером',
|
||
'tomorrow.time': 'Время программы завтра',
|
||
time: 'Время показа заставки',
|
||
date: 'Дата',
|
||
weekday: 'День недели',
|
||
slot: 'Название слота',
|
||
},
|
||
},
|
||
storage: {
|
||
title: 'Хранилище',
|
||
volume: 'Том хранилища',
|
||
volumeUnknown: 'Файловая система не отдала размер тома — показано только занятое хранилищем.',
|
||
totalVolume: 'Всего на томе',
|
||
ours: 'Занято TeleWave',
|
||
foreign: 'Прочее на томе',
|
||
foreignHint: 'база, система, чужие файлы',
|
||
free: 'Свободно',
|
||
lowSpace:
|
||
'Свободного места меньше порога ({{threshold}}) — загрузка новых файлов отклоняется.',
|
||
recount: 'Пересчитать',
|
||
computedAt: 'посчитано в {{time}}',
|
||
breakdown: 'Из чего складывается',
|
||
filesTotal: 'файлов: {{count}}',
|
||
files: 'файлов: {{count}}',
|
||
empty: 'Хранилище пустое.',
|
||
areas: {
|
||
Assets: 'Сегменты программ',
|
||
BumperAssets: 'Сегменты заставок',
|
||
Originals: 'Исходники',
|
||
Inbox: 'Inbox',
|
||
ManualInbox: 'Ручной inbox',
|
||
Uploads: 'Незавершённые загрузки',
|
||
BumperSources: 'Звук и фоны заставок',
|
||
Images: 'Изображения',
|
||
Other: 'Прочее под корнем',
|
||
},
|
||
areaHints: {
|
||
Assets: 'HLS-нарезка библиотеки — обычно почти весь объём',
|
||
BumperAssets: 'отрендеренные заставки; чистятся вместе с расписанием',
|
||
Originals: 'остаются, только если включён Storage:KeepOriginals',
|
||
Inbox: 'то, что ещё не разобрал сканер',
|
||
ManualInbox: 'то, что забирается в шоу вручную',
|
||
Uploads: 'перевалочный каталог; залежавшееся — след оборванной заливки',
|
||
BumperSources: 'сырые файлы блоков, не нарезка',
|
||
Images: 'постеры, кадры, логотипы',
|
||
Other: 'файлы мимо известных каталогов — обычно ноль',
|
||
},
|
||
},
|
||
maintenance: {
|
||
title: 'Обслуживание',
|
||
warning: 'Операции необратимы — удаляют данные и файлы навсегда.',
|
||
clearMedia: 'Очистить все медиа',
|
||
clearMediaHint: 'Удалит все загруженные файлы и их нарезку, а также расписание каналов.',
|
||
confirmClearMedia: 'Удалить ВСЕ медиа-файлы безвозвратно?',
|
||
clearShowMedia: 'Удалить медиа шоу',
|
||
clearShowMediaHint: 'Удалит файлы всех серий выбранного шоу и очистит его серии.',
|
||
confirmClearShowMedia: 'Удалить все медиа выбранного шоу безвозвратно?',
|
||
pickShow: 'Выберите шоу',
|
||
deleteShows: 'Удалить все шоу',
|
||
deleteShowsHint: 'Удалит все шоу и их серии. Медиа-файлы останутся в библиотеке.',
|
||
confirmDeleteShows: 'Удалить ВСЕ шоу безвозвратно?',
|
||
doneCount: 'Удалено: {{count}}',
|
||
},
|
||
settings: {
|
||
title: 'Настройки',
|
||
registration: 'Регистрация',
|
||
registrationHint:
|
||
'Когда выключено — новые пользователи не могут регистрироваться сами, учётки заводит только администратор.',
|
||
registrationLabel: 'Разрешить регистрацию на сайте',
|
||
preferredAudio: 'Предпочитаемые озвучки',
|
||
channelNumbers: 'Переключение каналов по номерам',
|
||
channelNumbersHint:
|
||
'Зритель переключает каналы стрелками, как на телевизоре. Сетка каналов остаётся всегда.',
|
||
preferredAudioHint:
|
||
'Коды языков через запятую в порядке приоритета (напр. «rus, eng»). Если в файле есть дорожка с таким языком — при обработке выбирается она (по порядку); иначе — выбор ffmpeg по умолчанию. Применяется к новым обработкам.',
|
||
},
|
||
metadata: {
|
||
title: 'Метаданные',
|
||
pickPoster: 'Из галереи',
|
||
name: 'Название',
|
||
originalName: 'Оригинальное название (eng)',
|
||
originalNamePlaceholder: 'Например: Family Guy',
|
||
originalNameHint: 'По нему ищутся метаданные; на экранах показывается обычное название.',
|
||
sourceLabel: 'Источник',
|
||
searchBtn: 'Искать',
|
||
nothingFound: 'Ничего не найдено',
|
||
apply: 'Применить',
|
||
applied: 'Метаданные применены',
|
||
overview: 'Описание',
|
||
year: 'Год',
|
||
clear: 'Очистить',
|
||
noPoster: 'Нет постера',
|
||
refreshEpisodes: 'Обновить серии',
|
||
refreshing: 'Обновляем…',
|
||
refreshedCount: 'Обновлено серий: {{count}}',
|
||
findMissing: 'Найти отсутствующие серии',
|
||
missingTitle: 'Отсутствующие серии',
|
||
missingNoSeasons: 'В шоу нет загруженных серий с распознанными номерами.',
|
||
seasonN: 'Сезон {{n}}',
|
||
loadedOf: 'загружено {{loaded}} из {{total}}',
|
||
missingUnknown: 'Источник не отдал число серий этого сезона.',
|
||
missingNone: 'Все серии на месте.',
|
||
missingList: 'Не хватает',
|
||
findMissingSeasons: 'Найти отсутствующие сезоны',
|
||
missingSeasonsTitle: 'Отсутствующие сезоны',
|
||
missingSeasonsUnknownTotal: 'Источник не отдал список сезонов этого сериала.',
|
||
missingSeasonsNone: 'Все сезоны на месте.',
|
||
missingSeasonsList: 'Не загружено ни одной серии из сезонов',
|
||
missingSeasonsUnknown: 'Источник не знает загруженные сезоны: {{list}}.',
|
||
},
|
||
},
|
||
}
|