import type { Translations } from './en'; const ru: Translations = { nav: { library: 'Библиотека', search: 'Поиск и загрузка', downloads: 'Загрузки', upload: 'Загрузить', storage: 'Хранилище', playlists: 'Плейлисты', newPlaylist: 'Новый плейлист', admin: 'Администрирование', settings: 'Настройки', administration: 'Администрирование', }, conn: { connected: 'Подключено', connecting: 'Подключение…', disconnected: 'Нет связи', error: 'Недоступно', manage: 'Соединение — управление экземплярами', cached: 'Показаны последние данные', }, user: { online: 'онлайн', offline: 'офлайн', signOut: 'Выйти', }, connect: { domains: { title: 'Сохранённые серверы', addPlaceholder: 'https://your-server.example.com', addButton: 'Добавить сервер', selected: 'Выбран', use: 'Выбрать', forgetTitle: 'Удалить этот сервер', }, removeDialog: { title: 'Удалить локальные данные?', description: 'Сервер «{{name}}» будет удалён из сохранённых, а его данные на этом устройстве — очищены.', cancel: 'Отмена', logout: 'Просто выйти', removeAndLogout: 'Удалить данные и выйти', }, login: { title: 'Вход в {{name}}', registerTitle: 'Регистрация на {{name}}', username: 'Имя пользователя', password: 'Пароль', passwordHint: 'Не менее 8 символов.', submit: 'Войти', submitting: 'Вход…', registerSubmit: 'Зарегистрироваться', registering: 'Регистрация…', noAccount: 'Нет аккаунта?', registerLink: 'Зарегистрироваться', haveAccount: 'Уже есть аккаунт?', signInLink: 'Войти', }, errors: { unreachable: 'Не удаётся подключиться к серверу. Проверьте URL и доступность.', badCredentials: 'Неверное имя пользователя или пароль.', generic: 'Не удалось войти. Попробуйте ещё раз.', usernameTaken: 'Это имя пользователя уже занято.', passwordTooShort: 'Пароль должен содержать не менее 8 символов.', registrationDisabled: 'Регистрация на этом сервере отключена.', registerFailed: 'Не удалось создать аккаунт. Попробуйте ещё раз.', }, }, library: { title: 'Библиотека', searchPlaceholder: 'Поиск в библиотеке…', tabs: { tracks: 'Треки', albums: 'Альбомы', artists: 'Исполнители', }, playAll: '▶ Воспроизвести все ({{count}})', empty: { tracks: { title: 'Нет треков', description: 'Библиотека пуста. Начните с загрузки музыки.', }, albums: { title: 'Нет альбомов', description: 'В библиотеке нет альбомов.', }, artists: { title: 'Нет исполнителей', description: 'В библиотеке нет исполнителей.', }, }, albumCard: { tracks: '{{count}} треков', tracksDuration: '{{count}} треков · {{duration}}', }, artistRow: { meta: '{{albumCount}} альб. · {{trackCount}} треков', }, offline: { banner: 'Нет связи с сервером — показана локально доступная библиотека. Она может быть неполной и доступна только для чтения, пока сервер недоступен.', emptyTitle: 'Офлайн ничего нет', emptyDesc: 'На этом устройстве ещё нет кэша библиотеки. Подключитесь к серверу хотя бы раз, чтобы просматривать офлайн.', }, }, album: { type: 'Альбом', play: '▶ Слушать', error: 'Не удалось загрузить альбом', tracksError: 'Не удалось загрузить треки', empty: { title: 'Нет треков', description: 'В этом альбоме нет треков.', }, offline: { title: 'Альбом недоступен офлайн', description: 'Нет связи, а этот альбом не сохранён на устройстве.', }, }, artist: { type: 'Исполнитель', play: '▶ Слушать всё', error: 'Не удалось загрузить исполнителя', meta: '{{albumCount}} альбомов · {{trackCount}} треков', albums: 'Альбомы', tracks: 'Треки', noAlbums: 'Пока нет альбомов.', empty: { title: 'Нет треков', description: 'У этого исполнителя нет треков.', }, offline: { title: 'Исполнитель недоступен офлайн', description: 'Нет связи, а этот исполнитель не сохранён на устройстве.', }, }, playlist: { type: 'Плейлист', play: '▶ Слушать', error: 'Не удалось загрузить плейлист', tracksError: 'Не удалось загрузить треки', empty: { title: 'Плейлист пуст', description: 'В этом плейлисте пока нет треков.', }, menu: { rename: 'Переименовать', delete: 'Удалить', }, }, player: { nothingPlaying: 'Ничего не играет', previous: 'Назад', next: 'Вперёд', pause: 'Пауза', play: 'Воспроизвести', streaming: 'Стриминг', local: 'Локально', queue: 'Очередь', mute: 'Выключить звук', unmute: 'Включить звук', }, nowPlaying: { expand: 'Сейчас играет', collapse: 'Свернуть', artwork: 'Обложка', lyrics: 'Текст', }, lyrics: { none: 'Текст для этого трека не найден.', refetch: 'Искать снова', }, queue: { title: 'Очередь воспроизведения', shuffle: 'Перемешать очередь', loop: 'Повторять текущий трек', clear: 'Очистить очередь', close: 'Закрыть', from: 'Из: {{source}}', radio: 'Радио · {{source}}', nextUp: 'Далее', empty: 'Очередь пуста', radioActive: 'Радио активно', mixing: '∞ микс', familiar: 'Знакомое', new: 'Новое', loadingMore: 'Загрузка радио…', doubleClickPlay: 'Двойной клик для воспроизведения', removeFromQueue: 'Убрать из очереди', menu: { options: 'Параметры трека', playNow: 'Воспроизвести сейчас', moveNext: 'Сделать следующим', info: 'Информация о треке', remove: 'Убрать из очереди', }, }, track: { menu: { options: 'Действия с треком', playNow: 'Играть сейчас', playNext: 'Следующим', addToQueue: 'Добавить в очередь', info: 'Информация о треке', addToPlaylist: 'Добавить в плейлист…', removeFromPlaylist: 'Убрать из плейлиста', editMetadata: 'Редактировать метаданные', download: 'Скачать', delete: 'Удалить', }, }, addToPlaylist: { title: 'Добавить в плейлист', empty: 'У вас пока нет плейлистов.', newPlaylist: 'Новый плейлист', newPlaceholder: 'Название плейлиста', create: 'Создать и добавить', added: 'Добавлено в «{{name}}».', error: 'Не удалось добавить трек в этот плейлист. Попробуйте ещё раз.', createError: 'Не удалось создать плейлист. Попробуйте ещё раз.', }, playlists: { newDialog: { title: 'Новый плейлист', placeholder: 'Название плейлиста', cancel: 'Отмена', create: 'Создать', }, empty: { title: 'Пока нет плейлистов', description: 'Создайте первый плейлист, чтобы начать организовывать треки.', }, trackCount: '{{count}} треков', menu: { options: 'Действия с плейлистом', rename: 'Переименовать', delete: 'Удалить', }, renameDialog: { title: 'Переименовать плейлист', save: 'Сохранить', }, deleteDialog: { title: 'Удалить плейлист?', description: 'Плейлист «{{name}}» будет удалён навсегда. Треки останутся в библиотеке.', cancel: 'Отмена', confirm: 'Удалить', }, }, trackInfo: { title: 'О треке', open: 'Информация о треке', close: 'Закрыть', notFound: 'Трек не найден', play: 'Играть', addToQueue: 'В очередь', editMetadata: 'Метаданные', liked: 'В избранном', trackOf: '№ {{n}} из {{total}}', kbps: '{{n}} кбит/с', sections: { status: 'Статус', general: 'Основное', file: 'Файл', identifiers: 'Идентификаторы', }, fields: { artist: 'Исполнитель', album: 'Альбом', trackNumber: 'Трек', disc: 'Диск', year: 'Год', genre: 'Жанр', duration: 'Длительность', format: 'Формат', bitrate: 'Битрейт', size: 'Размер', source: 'Источник', added: 'Добавлен', enriched: 'Обогащён', trackId: 'ID трека', albumId: 'ID альбома', artistId: 'ID исполнителя', }, }, common: { error: 'Что-то пошло не так', retry: 'Повторить', comingSoon: 'Скоро', back: 'Назад', offlineBanner: 'Нет связи с сервером — показаны локально доступные данные, только для чтения.', }, storage: { subtitle: 'Всё, что хранит этот инстанс', maintenance: { subtitle: 'Найдите дубликаты, треки с ошибкой обогащения и файлы без метаданных — и уберите осиротевшие записи.', tabs: { duplicates: 'Дубликаты', broken: 'С ошибкой', missing: 'Без метаданных', }, cleanup: { title: 'Очистить осиротевшие файлы', description: 'Сверить каталог и удалить записи, у которых пропал файл на диске. Выполняется в фоне.', button: 'Запустить очистку', enqueued: 'Очистка поставлена в очередь', }, duplicates: { empty: 'Дубликатов не найдено.', groupTitle: '{{count}} треков с одним отпечатком', }, broken: { empty: 'Треков с ошибкой нет.', }, missing: { empty: 'У всех треков есть метаданные.', }, pagination: '{{from}}–{{to}} из {{total}}', prev: 'Назад', next: 'Вперёд', editBatch: 'Редактировать массово', }, device: 'На этом устройстве', server: 'На сервере', audioCache: 'Кэш аудио', audioCacheUsage: 'Занято {{used}} из {{max}}', cachedTracks: '{{n}} треков сохранено офлайн', audioCacheUnavailable: 'Офлайн-кэш аудио недоступен (service worker не активен).', offlineLibrary: 'Офлайн-библиотека', offlineLibraryMeta: '{{tracks}} треков · {{albums}} альбомов · {{artists}} исполнителей доступно офлайн', serverUnreachable: 'Сервер недоступен — показано только это устройство.', emptyTitle: 'Пока ничего не сохранено', emptyDesc: 'Загрузите немного музыки — и здесь появится статистика вашей библиотеки.', disk: 'Диск', diskUsage: 'Занято {{used}} из {{total}}', diskFree: 'Свободно {{free}}', diskLibraryShare: 'Библиотека занимает {{percent}}% всего диска', diskUnknown: 'Объектное хранилище — фиксированного диска нет', footprint: 'Объём библиотеки', tracks: 'Треки', artists: 'Исполнители', albums: 'Альбомы', playtime: 'Общая длительность', avgTrackSize: 'Средний размер трека', largestTrack: 'Самый большой трек', formats: 'Форматы', sources: 'Откуда взято', metadataHealth: 'Состояние метаданных', topGenres: 'Топ жанров', noGenres: 'Жанры пока не указаны', funFacts: 'Интересные факты', factPlaytime: 'Нажмите play и уходите — библиотека играет {{duration}} без остановки.', factFootprint: '{{size}} музыки в {{tracks}} треках.', factGenre: 'Чаще всего встречается жанр {{genre}} ({{count}} треков).', factAvg: 'Средний трек весит {{size}}.', factSince: 'Коллекция собирается с {{date}}.', status: { enriched: 'Обогащено', manual: 'Вручную', pending: 'В ожидании', failed: 'Ошибка', }, }, pages: { admin: 'Администрирование', settings: 'Настройки', downloads: 'Загрузки', search: 'Поиск и загрузка', storage: 'Хранилище', login: 'Вход', artist: 'Артист', playlists: 'Плейлисты', upload: 'Загрузка файлов', metadata: 'Редактирование метаданных', metadataBatch: 'Редактирование метаданных (массово)', storageMaintenance: 'Обслуживание хранилища', queue: 'Очередь воспроизведения', }, settings: { language: 'Язык', theme: 'Тема', themeDark: 'Тёмная', themeLight: 'Светлая', tabs: { profile: 'Профиль', playback: 'Воспроизведение', scrobbling: 'Скробблинг', instance: 'Сервер', }, common: { save: 'Сохранить', saving: 'Сохранение…', }, instance: { current: 'Текущий инстанс', none: 'Инстанс не выбран.', manage: 'Управление инстансами', signOut: 'Выйти', }, playback: { streamQuality: 'Качество потока', streamQualityHint: 'Качество звука при стриминге с сервера. «Оригинал» отдаёт файл как есть.', quality: { original: 'Оригинал', high: 'Высокое', medium: 'Среднее', low: 'Низкое', }, }, scrobbling: { description: 'Отправляйте свои прослушивания в Last.fm или ListenBrainz.', configured: 'Подключено', notConfigured: 'Не подключено', enabled: 'Скробблинг', on: 'Вкл', off: 'Выкл', provider: 'Сервис', lastfm: 'Last.fm', listenbrainz: 'ListenBrainz', username: 'Имя пользователя', usernamePlaceholder: 'ваш логин', sessionKey: 'Ключ сессии / токен', sessionKeyPlaceholder: 'вставьте токен', sessionKeyKeep: 'оставьте пустым, чтобы сохранить текущий токен', sessionKeyHint: 'Хранится на сервере в зашифрованном виде и больше не показывается.', saved: 'Настройки скробблинга сохранены.', error: 'Не удалось сохранить. Попробуйте ещё раз.', }, }, admin: { userDetail: 'Пользователь', tabs: { users: 'Пользователи', sources: 'Источники', instance: 'Сервер', }, users: { add: 'Добавить', empty: 'Пользователей пока нет.', you: '(вы)', added: 'Добавлен {{date}}', role: { admin: 'Админ', user: 'Пользователь', }, status: { blocked: 'Заблокирован', }, newDialog: { title: 'Новый пользователь', username: 'Логин', password: 'Пароль', create: 'Создать', cancel: 'Отмена', error: 'Не удалось создать пользователя — возможно, логин занят.', }, menu: { options: 'Действия', makeAdmin: 'Сделать админом', makeUser: 'Снять админа', resetPassword: 'Сбросить пароль', activate: 'Разблокировать', deactivate: 'Заблокировать', }, resetDialog: { title: 'Сброс пароля — {{name}}', newPassword: 'Новый пароль', submit: 'Задать пароль', cancel: 'Отмена', done: 'Пароль обновлён.', }, deactivateDialog: { title: 'Заблокировать пользователя?', description: '{{name}} будет разлогинен и не сможет войти. Позже можно разблокировать.', confirm: 'Заблокировать', cancel: 'Отмена', }, }, instance: { status: { ok: 'Работает', down: 'Недоступен', skipped: 'Не настроен', }, services: { title: 'Сервисы', database: 'База данных', redis: 'Redis', ml: 'ML-сервис', }, sources: { title: 'Источники', envNote: 'Источники настраиваются через переменные окружения.', empty: 'Источники не настроены.', available: 'Доступен', unavailable: 'Недоступен', }, reindex: { title: 'Переиндексация библиотеки', description: 'Пересканировать все индексируемые источники. Выполняется в фоне, идемпотентно.', button: 'Переиндексировать', enqueued: 'Переиндексация запущена ({{count}} источников).', noSource: 'Индексируемые источники не настроены.', }, }, }, notFound: { title: 'Страница не найдена', description: 'Этого экрана пока нет.', backToLibrary: 'Вернуться в библиотеку', }, upload: { title: 'Загрузка файлов', dropzone: { title: 'Перетащите аудиофайлы сюда', hint: 'или нажмите, чтобы выбрать файлы — по одному или сразу несколько', button: 'Выбрать файлы', }, queueTitle: 'Загрузки ({{completed}}/{{total}})', clearCompleted: 'Убрать завершённые', retry: 'Повторить', editMetadata: 'Изменить метаданные', recent: { title: 'Недавно загруженные', empty: 'Пока ничего не загружено.', }, metadataPending: 'Загруженные треки появляются как «Unknown Artist» с метаданными в ожидании — дозаполните их позже.', unknownArtist: 'Unknown Artist · метаданные в ожидании', status: { queued: 'В очереди', uploading: 'Загрузка', done: 'Загружено', duplicate: 'Уже в библиотеке', error: 'Ошибка', }, }, discover: { title: 'Поиск и скачивание', subtitle: 'Находите музыку в подключённых источниках и добавляйте в библиотеку.', searchPlaceholder: 'Найти трек, исполнителя или альбом…', searchButton: 'Найти', allSources: 'Все источники', noSources: 'Источники скачивания не настроены. Включите источник (например, YouTube Music) на сервере, чтобы искать и скачивать.', startTitle: 'Начните с поиска', startDesc: 'Здесь появятся результаты из подключённых источников.', emptyTitle: 'Ничего не найдено', emptyDesc: 'Попробуйте другой запрос или другой источник.', searchError: 'Не удалось выполнить поиск. Попробуйте ещё раз.', download: 'Скачать', retryDownload: 'Повторить', queued: 'В очереди', inLibrary: 'В библиотеке', viewDownloads: 'К загрузкам', }, downloads: { title: 'Загрузки', subtitle: 'Активные, завершённые и неуспешные скачивания.', activeCount: 'Активных: {{count}}', sectionActive: 'В процессе', sectionHistory: 'История', emptyTitle: 'Пока нет загрузок', emptyDesc: 'Найдите музыку в разделе «Поиск и скачивание».', loadError: 'Не удалось загрузить список.', failedBanner: 'Неуспешных скачиваний: {{count}}. Повторите их или проверьте источник на сервере.', attempt: 'Попытка {{count}}', open: 'Открыть', retry: 'Повторить', cancel: 'Отменить', status: { queued: 'В очереди', downloading: 'Скачивание', enriching: 'Обработка', done: 'Готово', failed: 'Ошибка', }, }, metadata: { status: { pending: 'Обработка…', enriched: 'Готово', failed: 'Нет совпадения', manual: 'Вручную', }, statusHint: { pending: 'Определяем метаданные…', enriched: 'Метаданные определены', failed: 'Не удалось определить метаданные', manual: 'Изменено вручную — не обновляется автоматически', }, }, metadataBatch: { selectedCount: 'Выбрано {{selected}} из {{total}}', status: { pending: 'Без метаданных', failed: 'С ошибкой', }, result: 'Обновлено {{ok}}, ошибок {{fail}}', reEnrich: { title: 'Повторное авто-обогащение', hint: 'Поставить в очередь идентификацию AcoustID/MusicBrainz для выбранных треков.', button: 'Переобогатить выбранные', }, common: { title: 'Применить общие поля', hint: 'Заполненные поля запишутся всем выбранным трекам; пустые останутся без изменений.', apply: 'Применить к выбранным', }, empty: 'В этой категории пусто.', }, metadataEditor: { optimize: { title: 'Оптимизировать формат', hint: 'Перекодировать в компактный Opus + HLS в фоне.', button: 'Оптимизировать', enqueued: 'Оптимизация поставлена в очередь — выполнится в фоне.', }, error: 'Не удалось загрузить трек', saved: 'Метаданные сохранены.', saveError: 'Не удалось сохранить метаданные.', save: 'Сохранить', fields: { title: 'Название', artist: 'Исполнитель', album: 'Альбом', year: 'Год', genre: 'Жанр', trackNumber: 'Номер трека', }, autoEnrich: { title: 'Поиск по AcoustID', hint: 'Определить трек по аудио-отпечатку.', findMatches: 'Найти совпадения', reEnrich: 'Повторить обогащение', enqueued: 'Обогащение запущено — обновите через момент.', error: 'Не удалось найти совпадения.', noMatches: 'Совпадений не найдено.', }, matches: { use: 'Использовать', unknownTitle: 'Неизвестное название', }, diff: { title: 'Применить это совпадение?', noChanges: 'Нет изменений относительно текущих значений.', cancel: 'Отмена', apply: 'Применить', }, }, }; export default ru;