feat(web): suggest tracks, my uploads and admin upload queue screens (M5.5)
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 3m4s
ci / ts / ts (packages + web) (push) Successful in 1m23s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 52s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m51s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 3m4s
ci / ts / ts (packages + web) (push) Successful in 1m23s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 52s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m51s
- Suggest tracks: drag-and-drop of files and folders with relative paths, streaming SHA-256 in a Web Worker (hash-wasm), duplicate precheck, batch reservation and tus-js-client upload (8 MB chunks, 4 in parallel, token refresh on 401, resume of failed files). - My uploads: statuses, rejection reasons, withdraw, quota meter. - Upload queue (admin): status tabs, possible-duplicate filter, batches, metadata and storage editing, bulk approve / reject with a reason, import retry, and the queue settings form. - Sidebar section for moderators and admins; ru / en strings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ca106e8eb1
commit
a3f212d253
19 files changed
+2144
-14
No files matched your search
@@ -183,5 +183,149 @@
|
||||
"badge": "accepts uploads",
|
||||
"write_ok": "Write: ok",
|
||||
"write_fail": "Write failed: {{message}}"
|
||||
},
|
||||
"uploads": {
|
||||
"suggest_title": "Suggest tracks",
|
||||
"suggest_subtitle": "Files go to the upload queue; an administrator reviews them and places them into a storage",
|
||||
"drop_title": "Drop music files or folders here",
|
||||
"drop_hint": "Formats: {{formats}}. Folder structure helps guess the artist and album.",
|
||||
"pick_files": "Choose files",
|
||||
"pick_folder": "Choose folder",
|
||||
"files": "Files to send",
|
||||
"skipped_one": "{{count}} file skipped — not audio",
|
||||
"skipped_few": "{{count}} files skipped — not audio",
|
||||
"skipped_many": "{{count}} files skipped — not audio",
|
||||
"skipped_other": "{{count}} files skipped — not audio",
|
||||
"comment": "Comment for the administrator",
|
||||
"comment_hint": "For example: “2011 remaster”, “replacing broken files”",
|
||||
"not_enough_space": "The queue is short of space: {{need}} needed, {{free}} free — some files will be refused.",
|
||||
"clear": "Clear list",
|
||||
"hashing_wait": "Checking files…",
|
||||
"send_one": "Send {{count}} file · {{size}}",
|
||||
"send_few": "Send {{count}} files · {{size}}",
|
||||
"send_many": "Send {{count}} files · {{size}}",
|
||||
"send_other": "Send {{count}} files · {{size}}",
|
||||
"sent_one": "Done: {{count}} file is uploaded and being processed. See statuses in “My uploads”.",
|
||||
"sent_few": "Done: {{count}} files are uploaded and being processed. See statuses in “My uploads”.",
|
||||
"sent_many": "Done: {{count}} files are uploaded and being processed. See statuses in “My uploads”.",
|
||||
"sent_other": "Done: {{count}} files are uploaded and being processed. See statuses in “My uploads”.",
|
||||
"failed_some_one": "{{count}} file did not upload — its space is reserved, you can continue.",
|
||||
"failed_some_few": "{{count}} files did not upload — their space is reserved, you can continue.",
|
||||
"failed_some_many": "{{count}} files did not upload — their space is reserved, you can continue.",
|
||||
"failed_some_other": "{{count}} files did not upload — their space is reserved, you can continue.",
|
||||
"retry_failed": "Continue upload",
|
||||
"uploading_now": "Uploading…",
|
||||
"go_mine": "My uploads →",
|
||||
"more": "Upload more",
|
||||
"dup_found": "This track is already in the library or the queue — no need to upload",
|
||||
"possible_dup": "A similar track exists (same artist, title and length) — the administrator will decide",
|
||||
"file_error": "Error: {{message}}",
|
||||
"remove": "Remove {{name}}",
|
||||
"quota": "Queue: {{used}} of {{limit}}",
|
||||
"quota_mine": "yours: {{used}} of {{limit}}",
|
||||
"mine_title": "My uploads",
|
||||
"mine_subtitle": "What you uploaded and what the administrator decided",
|
||||
"mine_empty": "You have not suggested anything yet",
|
||||
"filter": "Filter",
|
||||
"filter_all": "All",
|
||||
"filter_pending": "In progress",
|
||||
"filter_imported": "Added",
|
||||
"filter_declined": "Not accepted",
|
||||
"col_file": "Track",
|
||||
"col_status": "Status",
|
||||
"col_size": "Size",
|
||||
"col_date": "Uploaded",
|
||||
"received": "{{pct}}% received — open “Suggest tracks” in the same tab to continue",
|
||||
"withdraw": "Withdraw",
|
||||
"load_more": "Show more",
|
||||
"queue_title": "Upload queue",
|
||||
"queue_subtitle": "Check the metadata and the storage path, then approve or reject",
|
||||
"queue_empty": "Nothing here",
|
||||
"tab_review": "Awaiting review",
|
||||
"tab_failed": "Import errors",
|
||||
"tab_progress": "In progress",
|
||||
"tab_imported": "Added",
|
||||
"tab_declined": "Not accepted",
|
||||
"only_possible": "Possible duplicates only",
|
||||
"review_failed_one": "Could not apply the decision to {{count}} file: {{reason}}",
|
||||
"review_failed_few": "Could not apply the decision to {{count}} files: {{reason}}",
|
||||
"review_failed_many": "Could not apply the decision to {{count}} files: {{reason}}",
|
||||
"review_failed_other": "Could not apply the decision to {{count}} files: {{reason}}",
|
||||
"bulk": "Actions on selected",
|
||||
"selected_one": "{{count}} file selected",
|
||||
"selected_few": "{{count}} files selected",
|
||||
"selected_many": "{{count}} files selected",
|
||||
"selected_other": "{{count}} files selected",
|
||||
"approve": "Approve",
|
||||
"reject": "Reject",
|
||||
"batch_of": "Batch from {{author}}",
|
||||
"batch_size_one": "{{count}} file · {{size}}",
|
||||
"batch_size_few": "{{count}} files · {{size}}",
|
||||
"batch_size_many": "{{count}} files · {{size}}",
|
||||
"batch_size_other": "{{count}} files · {{size}}",
|
||||
"select_batch": "Select the whole batch",
|
||||
"select_file": "Select {{name}}",
|
||||
"disc": "disc {{n}}",
|
||||
"edited": "edited",
|
||||
"flag_possible": "possible duplicate",
|
||||
"flag_existing_album": "existing album",
|
||||
"flag_new_album": "new album",
|
||||
"dup_level_sha256": "exact copy of a file",
|
||||
"dup_level_fingerprint": "same track by acoustic fingerprint",
|
||||
"dup_level_metadata": "metadata matched",
|
||||
"edit": "Edit {{name}}",
|
||||
"retry": "Retry",
|
||||
"edit_title": "Track metadata",
|
||||
"meta_artist": "Artist",
|
||||
"meta_albumartist": "Album artist",
|
||||
"meta_album": "Album",
|
||||
"meta_title": "Title",
|
||||
"meta_genre": "Genre",
|
||||
"meta_year": "Year",
|
||||
"meta_track": "Track number",
|
||||
"meta_disc": "Disc",
|
||||
"target_source": "Storage",
|
||||
"target_default": "Default",
|
||||
"tags_note": "Edited fields are written into the file tags on import, so path and tags stay consistent.",
|
||||
"save": "Save",
|
||||
"saved": "Saved",
|
||||
"reject_title_one": "Reject {{count}} file",
|
||||
"reject_title_few": "Reject {{count}} files",
|
||||
"reject_title_many": "Reject {{count}} files",
|
||||
"reject_title_other": "Reject {{count}} files",
|
||||
"reject_reason": "Reason (the author will see it)",
|
||||
"settings_title": "Queue settings",
|
||||
"set_queue": "Queue limit, GB",
|
||||
"set_per_user": "Limit per moderator, GB",
|
||||
"set_per_user_hint": "Empty — no limit",
|
||||
"set_max_file": "Maximum file size, GB",
|
||||
"set_source": "Default storage",
|
||||
"set_source_auto": "The only one accepting uploads",
|
||||
"set_note": "Lowering the limit below the used space deletes nothing: new uploads wait until the queue frees up.",
|
||||
"status": {
|
||||
"uploading": "Uploading",
|
||||
"processing": "Processing",
|
||||
"pending_review": "Awaiting review",
|
||||
"approved": "Approved",
|
||||
"importing": "Importing",
|
||||
"imported": "Added",
|
||||
"import_failed": "Import failed",
|
||||
"duplicate": "Duplicate",
|
||||
"invalid": "Not audio",
|
||||
"rejected": "Rejected",
|
||||
"withdrawn": "Withdrawn",
|
||||
"expired": "Expired"
|
||||
},
|
||||
"stage": {
|
||||
"hashing": "Computing checksum",
|
||||
"checking": "Checking for duplicates",
|
||||
"ready": "Ready to send",
|
||||
"duplicate": "Already exists",
|
||||
"too_large": "Too large",
|
||||
"uploading": "Uploading",
|
||||
"done": "Uploaded, processing",
|
||||
"rejected": "Not accepted",
|
||||
"error": "Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,11 @@
|
||||
"collection": "Collection",
|
||||
"history": "History",
|
||||
"likes": "Likes",
|
||||
"dislikes": "Dislikes"
|
||||
"dislikes": "Dislikes",
|
||||
"uploads": "Uploads",
|
||||
"suggest": "Suggest tracks",
|
||||
"my_uploads": "My uploads",
|
||||
"upload_queue": "Upload queue"
|
||||
},
|
||||
"profile": {
|
||||
"menu": "Profile menu",
|
||||
|
||||
@@ -183,5 +183,149 @@
|
||||
"badge": "принимает загрузки",
|
||||
"write_ok": "Запись: ок",
|
||||
"write_fail": "Запись не удалась: {{message}}"
|
||||
},
|
||||
"uploads": {
|
||||
"suggest_title": "Предложить треки",
|
||||
"suggest_subtitle": "Файлы попадут в очередь на добавление; администратор проверит и разложит их в хранилище",
|
||||
"drop_title": "Перетащите сюда файлы или папки с музыкой",
|
||||
"drop_hint": "Форматы: {{formats}}. Структура папок поможет угадать исполнителя и альбом.",
|
||||
"pick_files": "Выбрать файлы",
|
||||
"pick_folder": "Выбрать папку",
|
||||
"files": "Файлы для отправки",
|
||||
"skipped_one": "Пропущен {{count}} файл — не аудио",
|
||||
"skipped_few": "Пропущено {{count}} файла — не аудио",
|
||||
"skipped_many": "Пропущено {{count}} файлов — не аудио",
|
||||
"skipped_other": "Пропущено {{count}} файла — не аудио",
|
||||
"comment": "Комментарий для администратора",
|
||||
"comment_hint": "Например: «ремастер 2011», «замена битых файлов»",
|
||||
"not_enough_space": "В очереди не хватает места: нужно {{need}}, свободно {{free}} — часть файлов не примут.",
|
||||
"clear": "Очистить список",
|
||||
"hashing_wait": "Проверяю файлы…",
|
||||
"send_one": "Отправить {{count}} файл · {{size}}",
|
||||
"send_few": "Отправить {{count}} файла · {{size}}",
|
||||
"send_many": "Отправить {{count}} файлов · {{size}}",
|
||||
"send_other": "Отправить {{count}} файла · {{size}}",
|
||||
"sent_one": "Готово: {{count}} файл загружен и обрабатывается. Статусы — в «Моих предложениях».",
|
||||
"sent_few": "Готово: {{count}} файла загружены и обрабатываются. Статусы — в «Моих предложениях».",
|
||||
"sent_many": "Готово: {{count}} файлов загружены и обрабатываются. Статусы — в «Моих предложениях».",
|
||||
"sent_other": "Готово: {{count}} файла загружены и обрабатываются. Статусы — в «Моих предложениях».",
|
||||
"failed_some_one": "Не загрузился {{count}} файл — место за ним зарезервировано, можно продолжить.",
|
||||
"failed_some_few": "Не загрузились {{count}} файла — место за ними зарезервировано, можно продолжить.",
|
||||
"failed_some_many": "Не загрузились {{count}} файлов — место за ними зарезервировано, можно продолжить.",
|
||||
"failed_some_other": "Не загрузились {{count}} файла — место за ними зарезервировано, можно продолжить.",
|
||||
"retry_failed": "Продолжить загрузку",
|
||||
"uploading_now": "Загружаю…",
|
||||
"go_mine": "Мои предложения →",
|
||||
"more": "Загрузить ещё",
|
||||
"dup_found": "Такой трек уже есть в библиотеке или в очереди — загружать не нужно",
|
||||
"possible_dup": "Похожий трек уже есть (совпали исполнитель, название и длительность) — решит администратор",
|
||||
"file_error": "Ошибка: {{message}}",
|
||||
"remove": "Убрать {{name}}",
|
||||
"quota": "Очередь: {{used}} из {{limit}}",
|
||||
"quota_mine": "ваши: {{used}} из {{limit}}",
|
||||
"mine_title": "Мои предложения",
|
||||
"mine_subtitle": "Что вы загрузили и что решил администратор",
|
||||
"mine_empty": "Вы ещё ничего не предлагали",
|
||||
"filter": "Фильтр",
|
||||
"filter_all": "Все",
|
||||
"filter_pending": "В работе",
|
||||
"filter_imported": "Добавлены",
|
||||
"filter_declined": "Не приняты",
|
||||
"col_file": "Трек",
|
||||
"col_status": "Статус",
|
||||
"col_size": "Размер",
|
||||
"col_date": "Загружен",
|
||||
"received": "принято {{pct}}% — откройте «Предложить треки» в той же вкладке, чтобы продолжить",
|
||||
"withdraw": "Отозвать",
|
||||
"load_more": "Показать ещё",
|
||||
"queue_title": "Очередь на добавление",
|
||||
"queue_subtitle": "Проверьте метаданные и путь в хранилище, затем одобрите или отклоните",
|
||||
"queue_empty": "Здесь пусто",
|
||||
"tab_review": "На рассмотрении",
|
||||
"tab_failed": "Ошибки импорта",
|
||||
"tab_progress": "В работе",
|
||||
"tab_imported": "Добавлены",
|
||||
"tab_declined": "Не приняты",
|
||||
"only_possible": "Только возможные дубли",
|
||||
"review_failed_one": "Не удалось применить решение к {{count}} файлу: {{reason}}",
|
||||
"review_failed_few": "Не удалось применить решение к {{count}} файлам: {{reason}}",
|
||||
"review_failed_many": "Не удалось применить решение к {{count}} файлам: {{reason}}",
|
||||
"review_failed_other": "Не удалось применить решение к {{count}} файлам: {{reason}}",
|
||||
"bulk": "Действия с выбранными",
|
||||
"selected_one": "Выбран {{count}} файл",
|
||||
"selected_few": "Выбрано {{count}} файла",
|
||||
"selected_many": "Выбрано {{count}} файлов",
|
||||
"selected_other": "Выбрано {{count}} файла",
|
||||
"approve": "Одобрить",
|
||||
"reject": "Отклонить",
|
||||
"batch_of": "Пачка от {{author}}",
|
||||
"batch_size_one": "{{count}} файл · {{size}}",
|
||||
"batch_size_few": "{{count}} файла · {{size}}",
|
||||
"batch_size_many": "{{count}} файлов · {{size}}",
|
||||
"batch_size_other": "{{count}} файла · {{size}}",
|
||||
"select_batch": "Выбрать всю пачку",
|
||||
"select_file": "Выбрать {{name}}",
|
||||
"disc": "диск {{n}}",
|
||||
"edited": "правлено",
|
||||
"flag_possible": "возможный дубль",
|
||||
"flag_existing_album": "в существующий альбом",
|
||||
"flag_new_album": "новый альбом",
|
||||
"dup_level_sha256": "точная копия файла",
|
||||
"dup_level_fingerprint": "тот же трек по акустическому отпечатку",
|
||||
"dup_level_metadata": "совпали метаданные",
|
||||
"edit": "Править {{name}}",
|
||||
"retry": "Повторить",
|
||||
"edit_title": "Метаданные трека",
|
||||
"meta_artist": "Исполнитель",
|
||||
"meta_albumartist": "Исполнитель альбома",
|
||||
"meta_album": "Альбом",
|
||||
"meta_title": "Название",
|
||||
"meta_genre": "Жанр",
|
||||
"meta_year": "Год",
|
||||
"meta_track": "Номер трека",
|
||||
"meta_disc": "Диск",
|
||||
"target_source": "Хранилище",
|
||||
"target_default": "По умолчанию",
|
||||
"tags_note": "Правленые поля запишутся в теги файла при импорте — путь и теги не разойдутся.",
|
||||
"save": "Сохранить",
|
||||
"saved": "Сохранено",
|
||||
"reject_title_one": "Отклонить {{count}} файл",
|
||||
"reject_title_few": "Отклонить {{count}} файла",
|
||||
"reject_title_many": "Отклонить {{count}} файлов",
|
||||
"reject_title_other": "Отклонить {{count}} файла",
|
||||
"reject_reason": "Причина (её увидит автор)",
|
||||
"settings_title": "Настройки очереди",
|
||||
"set_queue": "Лимит очереди, ГБ",
|
||||
"set_per_user": "Лимит на одного модератора, ГБ",
|
||||
"set_per_user_hint": "Пусто — без лимита",
|
||||
"set_max_file": "Максимальный размер файла, ГБ",
|
||||
"set_source": "Хранилище по умолчанию",
|
||||
"set_source_auto": "Единственное, принимающее загрузки",
|
||||
"set_note": "Уменьшение лимита ниже занятого ничего не удаляет: новые загрузки подождут, пока очередь освободится.",
|
||||
"status": {
|
||||
"uploading": "Загружается",
|
||||
"processing": "Обработка",
|
||||
"pending_review": "На рассмотрении",
|
||||
"approved": "Одобрен",
|
||||
"importing": "Импорт",
|
||||
"imported": "Добавлен",
|
||||
"import_failed": "Ошибка импорта",
|
||||
"duplicate": "Дубль",
|
||||
"invalid": "Не аудио",
|
||||
"rejected": "Отклонён",
|
||||
"withdrawn": "Отозван",
|
||||
"expired": "Не докачан"
|
||||
},
|
||||
"stage": {
|
||||
"hashing": "Считаю контрольную сумму",
|
||||
"checking": "Проверяю на дубли",
|
||||
"ready": "Готов к отправке",
|
||||
"duplicate": "Уже есть",
|
||||
"too_large": "Слишком большой",
|
||||
"uploading": "Загружается",
|
||||
"done": "Загружен, обрабатывается",
|
||||
"rejected": "Не принят",
|
||||
"error": "Ошибка"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,11 @@
|
||||
"collection": "Коллекция",
|
||||
"history": "История",
|
||||
"likes": "Лайки",
|
||||
"dislikes": "Дизлайки"
|
||||
"dislikes": "Дизлайки",
|
||||
"uploads": "Предложения",
|
||||
"suggest": "Предложить треки",
|
||||
"my_uploads": "Мои предложения",
|
||||
"upload_queue": "Очередь на добавление"
|
||||
},
|
||||
"profile": {
|
||||
"menu": "Меню профиля",
|
||||
|
||||
Reference in new issue
Block a user