feat(torrents): harden lifecycle and web-seed management

- Enforce generation-safe seed admission and budget tracking.
- Make web-seed RPC, persistence, rollback, and startup attachment lifecycle-safe.
- Keep Torrent progress, DHT, seed-capacity, and web-seed validation covered.
- Ignore local TORRENT_FEATURES.md roadmap notes.
This commit is contained in:
NimBold
2026-08-03 16:56:01 +03:30
parent 79c0e48c43
commit c4d3a2be51
31 changed files with 3398 additions and 258 deletions
+32
View File
@@ -90,6 +90,7 @@ const common = {
downloading: 'Downloading',
processing: 'Processing',
seeding: 'Seeding',
waitingToSeed: 'Waiting to seed',
paused: 'Paused',
completed: 'Completed',
failed: 'Failed',
@@ -260,6 +261,30 @@ const common = {
torrentPeerDiagnosticsUnavailable: 'Peer diagnostics are available while this Torrent is active.',
torrentPeerDiagnosticsFailed: 'Could not read Torrent peer diagnostics.',
torrentPeerDiagnosticsHint: 'Speeds and connection flags only are shown; peer IPs, ports, IDs, and bitfields are not retained.',
torrentFileProgress: 'Torrent file progress',
torrentFileProgressRefresh: 'Refresh',
torrentFileProgressLoading: 'Loading file progress…',
torrentFileProgressUnavailable: 'File progress is available while this Torrent is active or paused.',
torrentFileProgressFailed: 'Could not read Torrent file progress.',
torrentFileProgressHint: 'Validated relative paths and completed bytes are shown; daemon paths and URIs are not exposed.',
torrentFileProgressPath: 'File',
torrentFileProgressCompleted: 'Completed',
torrentFileProgressSelected: 'Selected',
torrentFileProgressUnselected: 'Not selected',
torrentPieceProgress: 'Torrent piece progress',
torrentPieceProgressRefresh: 'Refresh',
torrentPieceProgressLoading: 'Loading piece progress…',
torrentPieceProgressUnavailable: 'Piece progress is available while this Torrent is active or paused.',
torrentPieceProgressFailed: 'Could not read Torrent piece progress.',
torrentPieceProgressHint: 'Each cell summarizes adjacent pieces. Raw bitfields are never exposed.',
torrentPieceProgressSummary: '{{completed}} of {{total}} pieces complete · {{size}} each',
torrentPieceProgressMap: 'Torrent piece completion map',
torrentWebSeeds: 'Torrent web seeds',
torrentWebSeedsHint: 'One line per seed in the form file index|HTTP(S) URI. Firelink expands multi-file paths natively.',
torrentWebSeedsPlaceholder: '0|https://mirror.example/torrent/',
torrentWebSeedsApply: 'Apply web seeds',
torrentWebSeedsLoading: 'Applying…',
torrentWebSeedsFailed: 'Could not validate or apply the Torrent web seeds.',
torrentPeerCount: '{{total}} peers · {{seeders}} seeders',
torrentPeerDownload: 'Download',
torrentPeerUpload: 'Upload',
@@ -800,6 +825,13 @@ const common = {
torrentLpdDescription: 'Discover compatible peers on the local network. This increases local network visibility.',
torrentPeerDiscoveryRestartNote: 'These options are global to Aria2 and take effect after Firelink restarts. Aria2 still disables peer discovery for private torrents.',
torrentNetwork: 'BitTorrent network binding',
torrentAdvanced: 'Advanced Torrent network',
torrentDhtMessageTimeout: 'DHT message timeout',
torrentDhtMessageTimeoutDescription: 'Whole seconds for DHT and UDP message waits. This does not affect remote .torrent HTTP fetches or HTTP tracker requests. Applies after Firelink restarts.',
torrentSeparateSeedSlots: 'Separate seeding capacity',
torrentSeparateSeedSlotsDescription: 'Keep seeding outside the download limit and cap it with a Firelink-managed pool.',
torrentMaxConcurrentSeeds: 'Maximum concurrent seeds',
torrentMaxConcurrentSeedsDescription: 'Maximum number of Torrents Firelink lets seed at once when separate capacity is enabled.',
torrentListenPort: 'TCP peer ports',
torrentListenPortDescription: 'TCP ports for incoming BitTorrent peer connections. Leave blank for Aria2s default range.',
torrentDhtListenPort: 'UDP/DHT ports',
+32
View File
@@ -90,6 +90,7 @@ const fa = {
downloading: 'در حال دانلود',
processing: 'در حال پردازش',
seeding: 'در حال اشتراک‌گذاری',
waitingToSeed: 'در انتظار اشتراک‌گذاری',
paused: 'متوقف‌شده',
completed: 'تکمیل‌شده',
failed: 'ناموفق',
@@ -260,6 +261,30 @@ const fa = {
torrentPeerDiagnosticsUnavailable: 'اطلاعات همتاها هنگام فعال بودن تورنت در دسترس است.',
torrentPeerDiagnosticsFailed: 'خواندن اطلاعات همتاهای تورنت ممکن نیست.',
torrentPeerDiagnosticsHint: 'فقط سرعت و وضعیت اتصال نمایش داده می‌شود؛ IP، پورت، شناسه و بیت‌فیلد همتاها ذخیره نمی‌شود.',
torrentFileProgress: 'پیشرفت فایل‌های تورنت',
torrentFileProgressRefresh: 'تازه‌سازی',
torrentFileProgressLoading: 'در حال دریافت پیشرفت فایل‌ها…',
torrentFileProgressUnavailable: 'پیشرفت فایل هنگام فعال یا متوقف‌بودن تورنت در دسترس است.',
torrentFileProgressFailed: 'خواندن پیشرفت فایل‌های تورنت ممکن نیست.',
torrentFileProgressHint: 'مسیرهای نسبی معتبر و حجم تکمیل‌شده نمایش داده می‌شود؛ مسیرهای داخلی و URIهای daemon نمایش داده نمی‌شوند.',
torrentFileProgressPath: 'فایل',
torrentFileProgressCompleted: 'تکمیل‌شده',
torrentFileProgressSelected: 'انتخاب‌شده',
torrentFileProgressUnselected: 'انتخاب‌نشده',
torrentPieceProgress: 'پیشرفت قطعه‌های تورنت',
torrentPieceProgressRefresh: 'تازه‌سازی',
torrentPieceProgressLoading: 'در حال دریافت پیشرفت قطعه‌ها…',
torrentPieceProgressUnavailable: 'پیشرفت قطعه‌ها هنگام فعال یا متوقف‌بودن تورنت در دسترس است.',
torrentPieceProgressFailed: 'خواندن پیشرفت قطعه‌های تورنت ممکن نیست.',
torrentPieceProgressHint: 'هر خانه خلاصه‌ای از قطعه‌های مجاور است؛ bitfield خام نمایش داده نمی‌شود.',
torrentPieceProgressSummary: '{{completed}} از {{total}} قطعه کامل شده · هرکدام {{size}}',
torrentPieceProgressMap: 'نقشه تکمیل قطعه‌های تورنت',
torrentWebSeeds: 'وب‌سیدهای تورنت',
torrentWebSeedsHint: 'هر خط به‌شکل شماره فایل|نشانی HTTP(S). مسیر فایل‌های چندفایلی را Firelink در بخش native می‌سازد.',
torrentWebSeedsPlaceholder: '۰|https://mirror.example/torrent/',
torrentWebSeedsApply: 'اعمال وب‌سیدها',
torrentWebSeedsLoading: 'در حال اعمال…',
torrentWebSeedsFailed: 'اعتبارسنجی یا اعمال وب‌سیدهای تورنت انجام نشد.',
torrentPeerCount: '{{total}} همتا · {{seeders}} سید',
torrentPeerDownload: 'دریافت',
torrentPeerUpload: 'آپلود',
@@ -800,6 +825,13 @@ const fa = {
torrentLpdDescription: 'همتاهای سازگار در شبکه محلی را پیدا می‌کند و دیده‌شدن ترافیک در شبکه محلی را افزایش می‌دهد.',
torrentPeerDiscoveryRestartNote: 'این گزینه‌ها سراسری و مربوط به Aria2 هستند و پس از راه‌اندازی مجدد Firelink اعمال می‌شوند. Aria2 همچنان کشف همتا را برای تورنت‌های خصوصی خاموش می‌کند.',
torrentNetwork: 'اتصال شبکه بیت‌تورنت',
torrentAdvanced: 'شبکه پیشرفته تورنت',
torrentDhtMessageTimeout: 'مهلت پیام DHT',
torrentDhtMessageTimeoutDescription: 'مدت انتظار پیام‌های DHT و UDP برحسب ثانیه. روی دریافت HTTP فایل .torrent یا درخواست‌های tracker از نوع HTTP اثر ندارد و پس از راه‌اندازی دوباره اعمال می‌شود.',
torrentSeparateSeedSlots: 'ظرفیت جداگانهٔ سید کردن',
torrentSeparateSeedSlotsDescription: 'سید کردن را از سقف دانلود جدا می‌کند و آن را با ظرفیت مدیریت‌شدهٔ Firelink محدود می‌کند.',
torrentMaxConcurrentSeeds: 'حداکثر سید هم‌زمان',
torrentMaxConcurrentSeedsDescription: 'وقتی ظرفیت جداگانه فعال است، حداکثر تعداد تورنت‌هایی که Firelink هم‌زمان سید می‌کند.',
torrentListenPort: 'پورت‌های همتای TCP',
torrentListenPortDescription: 'پورت‌های TCP برای اتصال‌های ورودی همتاهای بیت‌تورنت. برای محدوده پیش‌فرض Aria2 خالی بگذارید.',
torrentDhtListenPort: 'پورت‌های UDP/DHT',
+32
View File
@@ -90,6 +90,7 @@ const he = {
downloading: 'מוריד',
processing: 'מעבד',
seeding: 'משתף',
waitingToSeed: 'ממתין לשיתוף',
paused: 'מושהה',
completed: 'הושלם',
failed: 'נכשל',
@@ -260,6 +261,30 @@ const he = {
torrentPeerDiagnosticsUnavailable: 'אבחון עמיתים זמין כשהטורנט פעיל.',
torrentPeerDiagnosticsFailed: 'לא ניתן לקרוא את אבחון עמיתי הטורנט.',
torrentPeerDiagnosticsHint: 'מוצגים רק מהירויות ודגלי חיבור; כתובות IP, יציאות, מזהים ושדות ביטים אינם נשמרים.',
torrentFileProgress: 'התקדמות קובצי הטורנט',
torrentFileProgressRefresh: 'רענון',
torrentFileProgressLoading: 'טוען את התקדמות הקבצים…',
torrentFileProgressUnavailable: 'התקדמות הקבצים זמינה כשהטורנט פעיל או מושהה.',
torrentFileProgressFailed: 'לא ניתן לקרוא את התקדמות קובצי הטורנט.',
torrentFileProgressHint: 'מוצגים נתיבים יחסיים מאומתים ובייטים שהושלמו; נתיבי daemon וכתובות URI אינם נחשפים.',
torrentFileProgressPath: 'קובץ',
torrentFileProgressCompleted: 'הושלם',
torrentFileProgressSelected: 'נבחר',
torrentFileProgressUnselected: 'לא נבחר',
torrentPieceProgress: 'התקדמות חלקי הטורנט',
torrentPieceProgressRefresh: 'רענון',
torrentPieceProgressLoading: 'טוען את התקדמות החלקים…',
torrentPieceProgressUnavailable: 'התקדמות החלקים זמינה כשהטורנט פעיל או מושהה.',
torrentPieceProgressFailed: 'לא ניתן לקרוא את התקדמות חלקי הטורנט.',
torrentPieceProgressHint: 'כל תא מסכם חלקים סמוכים; מפת הסיביות הגולמית אינה נחשפת.',
torrentPieceProgressSummary: '{{completed}} מתוך {{total}} חלקים הושלמו · {{size}} לכל חלק',
torrentPieceProgressMap: 'מפת השלמת חלקי הטורנט',
torrentWebSeeds: 'זריעות Web של טורנט',
torrentWebSeedsHint: 'שורה אחת לכל זרע בפורמט file index|כתובת HTTP(S). Firelink מרחיב נתיבי קבצים מרובי-קבצים באופן מקורי.',
torrentWebSeedsPlaceholder: '0|https://מראה.example/torrent/',
torrentWebSeedsApply: 'החל זריעות Web',
torrentWebSeedsLoading: 'מיישם…',
torrentWebSeedsFailed: 'לא ניתן לאמת או להחיל את זריעות ה-Web של הטורנט.',
torrentPeerCount: '{{total}} עמיתים · {{seeders}} משתפים',
torrentPeerDownload: 'הורדה',
torrentPeerUpload: 'העלאה',
@@ -800,6 +825,13 @@ const he = {
torrentLpdDescription: 'מאתר עמיתים תואמים ברשת המקומית ומגדיל את החשיפה המקומית של התעבורה.',
torrentPeerDiscoveryRestartNote: 'האפשרויות האלה הן כלליות ל-Aria2 ונכנסות לתוקף לאחר הפעלה מחדש של Firelink. Aria2 עדיין משבית גילוי עמיתים בטורנטים פרטיים.',
torrentNetwork: 'קישור רשת BitTorrent',
torrentAdvanced: 'רשת Torrent מתקדמת',
torrentDhtMessageTimeout: 'זמן קצוב להודעות DHT',
torrentDhtMessageTimeoutDescription: 'משך ההמתנה להודעות DHT ו-UDP בשניות. אינו משפיע על הורדת קובצי ‎.torrent‎ ב-HTTP או על בקשות HTTP למעקבים. חל לאחר הפעלה מחדש של Firelink.',
torrentSeparateSeedSlots: 'קיבולת זריעה נפרדת',
torrentSeparateSeedSlotsDescription: 'הפרד זריעה ממגבלת ההורדות והגבל אותה למאגר בניהול Firelink.',
torrentMaxConcurrentSeeds: 'מקסימום זריעות במקביל',
torrentMaxConcurrentSeedsDescription: 'מספר הטורנטים המרבי ש-Firelink יזריע בו-זמנית כשהקיבולת הנפרדת פעילה.',
torrentListenPort: 'יציאות עמיתי TCP',
torrentListenPortDescription: 'יציאות TCP לחיבורי עמיתים נכנסים של BitTorrent. השאר ריק כדי להשתמש בטווח ברירת המחדל של Aria2.',
torrentDhtListenPort: 'יציאות UDP/DHT',
+32
View File
@@ -90,6 +90,7 @@ const ru = {
downloading: 'Загрузка',
processing: 'Обработка',
seeding: 'Раздача',
waitingToSeed: 'Ожидание раздачи',
paused: 'Приостановлено',
completed: 'Завершено',
failed: 'Ошибка',
@@ -260,6 +261,30 @@ const ru = {
torrentPeerDiagnosticsUnavailable: 'Диагностика пиров доступна, пока торрент активен.',
torrentPeerDiagnosticsFailed: 'Не удалось получить диагностику пиров торрента.',
torrentPeerDiagnosticsHint: 'Показываются только скорости и флаги соединения; IP-адреса, порты, идентификаторы и битовые поля не сохраняются.',
torrentFileProgress: 'Прогресс файлов торрента',
torrentFileProgressRefresh: 'Обновить',
torrentFileProgressLoading: 'Загрузка прогресса файлов…',
torrentFileProgressUnavailable: 'Прогресс файлов доступен, пока торрент активен или приостановлен.',
torrentFileProgressFailed: 'Не удалось получить прогресс файлов торрента.',
torrentFileProgressHint: 'Показываются проверенные относительные пути и загруженные байты; пути демона и URI не раскрываются.',
torrentFileProgressPath: 'Файл',
torrentFileProgressCompleted: 'Завершено',
torrentFileProgressSelected: 'Выбран',
torrentFileProgressUnselected: 'Не выбран',
torrentPieceProgress: 'Прогресс частей торрента',
torrentPieceProgressRefresh: 'Обновить',
torrentPieceProgressLoading: 'Загрузка прогресса частей…',
torrentPieceProgressUnavailable: 'Прогресс частей доступен, пока торрент активен или приостановлен.',
torrentPieceProgressFailed: 'Не удалось получить прогресс частей торрента.',
torrentPieceProgressHint: 'Каждая ячейка объединяет соседние части; исходная битовая карта не раскрывается.',
torrentPieceProgressSummary: '{{completed}} из {{total}} частей завершено · по {{size}} на часть',
torrentPieceProgressMap: 'Карта завершения частей торрента',
torrentWebSeeds: 'Веб-сиды торрента',
torrentWebSeedsHint: 'Одна строка на сид в формате индекс файла|HTTP(S)-URI. Firelink сам расширяет пути многофайловых торрентов.',
torrentWebSeedsPlaceholder: '0|https://зеркало.example/torrent/',
torrentWebSeedsApply: 'Применить веб-сиды',
torrentWebSeedsLoading: 'Применение…',
torrentWebSeedsFailed: 'Не удалось проверить или применить веб-сиды торрента.',
torrentPeerCount: '{{total}} пиров · {{seeders}} сидеров',
torrentPeerDownload: 'Загрузка',
torrentPeerUpload: 'Отдача',
@@ -800,6 +825,13 @@ const ru = {
torrentLpdDescription: 'Ищет подходящие пиры в локальной сети и увеличивает видимость трафика в ней.',
torrentPeerDiscoveryRestartNote: 'Эти параметры являются глобальными для Aria2 и применяются после перезапуска Firelink. Aria2 по-прежнему отключает обнаружение пиров для приватных торрентов.',
torrentNetwork: 'Сетевые параметры BitTorrent',
torrentAdvanced: 'Расширенные параметры Torrent',
torrentDhtMessageTimeout: 'Тайм-аут сообщений DHT',
torrentDhtMessageTimeoutDescription: 'Время ожидания сообщений DHT и UDP в секундах. Не влияет на загрузку .torrent по HTTP или HTTP-запросы к трекерам. Применяется после перезапуска Firelink.',
torrentSeparateSeedSlots: 'Отдельная ёмкость раздачи',
torrentSeparateSeedSlotsDescription: 'Вынести раздачу за пределы лимита загрузок и ограничить её пулом Firelink.',
torrentMaxConcurrentSeeds: 'Максимум одновременных раздач',
torrentMaxConcurrentSeedsDescription: 'Максимальное число торрентов, которые Firelink раздаёт одновременно при включённой отдельной ёмкости.',
torrentListenPort: 'TCP-порты пиров',
torrentListenPortDescription: 'TCP-порты для входящих соединений BitTorrent. Оставьте пустым, чтобы использовать диапазон Aria2 по умолчанию.',
torrentDhtListenPort: 'Порты UDP/DHT',
+32
View File
@@ -90,6 +90,7 @@ const uk = {
downloading: 'Завантаження',
processing: 'Обробка',
seeding: 'Роздача',
waitingToSeed: 'Очікування роздачі',
paused: 'Призупинено',
completed: 'Завершено',
failed: 'Помилка',
@@ -260,6 +261,30 @@ const uk = {
torrentPeerDiagnosticsUnavailable: 'Діагностика пірів доступна, поки торрент активний.',
torrentPeerDiagnosticsFailed: 'Не вдалося отримати діагностику пірів торрента.',
torrentPeerDiagnosticsHint: 'Показуються лише швидкості та прапорці з’єднання; IP-адреси, порти, ідентифікатори й бітові поля не зберігаються.',
torrentFileProgress: 'Прогрес файлів торрента',
torrentFileProgressRefresh: 'Оновити',
torrentFileProgressLoading: 'Завантаження прогресу файлів…',
torrentFileProgressUnavailable: 'Прогрес файлів доступний, коли торрент активний або призупинений.',
torrentFileProgressFailed: 'Не вдалося отримати прогрес файлів торрента.',
torrentFileProgressHint: 'Показуються перевірені відносні шляхи та завантажені байти; шляхи демона й URI не розкриваються.',
torrentFileProgressPath: 'Файл',
torrentFileProgressCompleted: 'Завершено',
torrentFileProgressSelected: 'Вибрано',
torrentFileProgressUnselected: 'Не вибрано',
torrentPieceProgress: 'Прогрес частин торрента',
torrentPieceProgressRefresh: 'Оновити',
torrentPieceProgressLoading: 'Завантаження прогресу частин…',
torrentPieceProgressUnavailable: 'Прогрес частин доступний, коли торрент активний або призупинений.',
torrentPieceProgressFailed: 'Не вдалося отримати прогрес частин торрента.',
torrentPieceProgressHint: 'Кожна клітинка узагальнює сусідні частини; необроблена бітова карта не розкривається.',
torrentPieceProgressSummary: '{{completed}} із {{total}} частин завершено · по {{size}} на частину',
torrentPieceProgressMap: 'Карта завершення частин торрента',
torrentWebSeeds: 'Вебсіди торента',
torrentWebSeedsHint: 'Один рядок на сід у форматі індекс файлу|HTTP(S)-URI. Firelink сам розгортає шляхи багатофайлових торентів.',
torrentWebSeedsPlaceholder: '0|https://дзеркало.example/torrent/',
torrentWebSeedsApply: 'Застосувати вебсіди',
torrentWebSeedsLoading: 'Застосування…',
torrentWebSeedsFailed: 'Не вдалося перевірити або застосувати вебсіди торента.',
torrentPeerCount: '{{total}} пірів · {{seeders}} сідів',
torrentPeerDownload: 'Завантаження',
torrentPeerUpload: 'Віддача',
@@ -800,6 +825,13 @@ const uk = {
torrentLpdDescription: 'Шукає сумісних пірів у локальній мережі та збільшує видимість трафіку в ній.',
torrentPeerDiscoveryRestartNote: 'Ці параметри є глобальними для Aria2 і застосовуються після перезапуску Firelink. Aria2 і надалі вимикає пошук пірів для приватних торрентів.',
torrentNetwork: 'Мережеві параметри BitTorrent',
torrentAdvanced: 'Розширені параметри Torrent',
torrentDhtMessageTimeout: 'Час очікування повідомлень DHT',
torrentDhtMessageTimeoutDescription: 'Час очікування повідомлень DHT і UDP у секундах. Не впливає на завантаження .torrent через HTTP або HTTP-запити до трекерів. Застосовується після перезапуску Firelink.',
torrentSeparateSeedSlots: 'Окрема місткість роздачі',
torrentSeparateSeedSlotsDescription: 'Винести роздачу за межі ліміту завантажень і обмежити її пулом Firelink.',
torrentMaxConcurrentSeeds: 'Максимум одночасних роздач',
torrentMaxConcurrentSeedsDescription: 'Максимальна кількість торентів, які Firelink роздає одночасно за ввімкненої окремої місткості.',
torrentListenPort: 'TCP-порти пірів',
torrentListenPortDescription: 'TCP-порти для вхідних з’єднань BitTorrent. Залиште порожнім, щоб використати типовий діапазон Aria2.',
torrentDhtListenPort: 'Порти UDP/DHT',
+32
View File
@@ -90,6 +90,7 @@ const zhCN = {
downloading: '下载中',
processing: '处理中',
seeding: '做种中',
waitingToSeed: '等待做种',
paused: '已暂停',
completed: '已完成',
failed: '失败',
@@ -260,6 +261,30 @@ const zhCN = {
torrentPeerDiagnosticsUnavailable: 'Torrent 活跃时可查看对等节点诊断。',
torrentPeerDiagnosticsFailed: '无法读取 Torrent 对等节点诊断。',
torrentPeerDiagnosticsHint: '仅显示速度和连接状态;不会保留对等节点 IP、端口、ID 或位域。',
torrentFileProgress: 'Torrent 文件进度',
torrentFileProgressRefresh: '刷新',
torrentFileProgressLoading: '正在加载文件进度…',
torrentFileProgressUnavailable: 'Torrent 活跃或暂停时可查看文件进度。',
torrentFileProgressFailed: '无法读取 Torrent 文件进度。',
torrentFileProgressHint: '仅显示已验证的相对路径和已完成字节数;不会暴露守护进程路径或 URI。',
torrentFileProgressPath: '文件',
torrentFileProgressCompleted: '已完成',
torrentFileProgressSelected: '已选择',
torrentFileProgressUnselected: '未选择',
torrentPieceProgress: 'Torrent 分片进度',
torrentPieceProgressRefresh: '刷新',
torrentPieceProgressLoading: '正在加载分片进度…',
torrentPieceProgressUnavailable: 'Torrent 活跃或暂停时可查看分片进度。',
torrentPieceProgressFailed: '无法读取 Torrent 分片进度。',
torrentPieceProgressHint: '每个单元格汇总相邻分片;不会暴露原始位图。',
torrentPieceProgressSummary: '{{completed}}/{{total}} 个分片已完成 · 每片 {{size}}',
torrentPieceProgressMap: 'Torrent 分片完成度地图',
torrentWebSeeds: 'Torrent Web 做种',
torrentWebSeedsHint: '每行一个做种,格式为文件索引|HTTP(S) URI。多文件路径由 Firelink 原生展开。',
torrentWebSeedsPlaceholder: '0|https://镜像.example/torrent/',
torrentWebSeedsApply: '应用 Web 做种',
torrentWebSeedsLoading: '正在应用…',
torrentWebSeedsFailed: '无法验证或应用 Torrent Web 做种。',
torrentPeerCount: '{{total}} 个节点 · {{seeders}} 个做种节点',
torrentPeerDownload: '下载',
torrentPeerUpload: '上传',
@@ -800,6 +825,13 @@ const zhCN = {
torrentLpdDescription: '在本地网络中发现兼容节点,这会增加本地网络中的流量可见性。',
torrentPeerDiscoveryRestartNote: '这些选项是 Aria2 的全局设置,需要重启 Firelink 后生效。Aria2 仍会对私有 Torrent 禁用节点发现。',
torrentNetwork: 'BitTorrent 网络绑定',
torrentAdvanced: '高级 Torrent 网络设置',
torrentDhtMessageTimeout: 'DHT 消息超时',
torrentDhtMessageTimeoutDescription: 'DHT 和 UDP 消息的等待时间(秒)。不影响通过 HTTP 获取 .torrent 文件,也不影响 HTTP tracker 请求。Firelink 重启后生效。',
torrentSeparateSeedSlots: '独立做种容量',
torrentSeparateSeedSlotsDescription: '将做种从下载上限中分离,并使用 Firelink 管理的容量池限制做种。',
torrentMaxConcurrentSeeds: '最大同时做种数',
torrentMaxConcurrentSeedsDescription: '启用独立容量后,Firelink 同时做种的 Torrent 数量上限。',
torrentListenPort: 'TCP 节点端口',
torrentListenPortDescription: '用于传入 BitTorrent 节点连接的 TCP 端口。留空以使用 Aria2 的默认范围。',
torrentDhtListenPort: 'UDP/DHT 端口',