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

- 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:
mrleo1nidandClaude Opus 5.5 committed 2026-10-20 17:46:18 +03:00
1 parent ca106e8eb1
commit a3f212d253
19 files changed
+2144 -14

No files matched your search

+144
View File
@@ -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"
}
}
}