diff --git a/src/locales/ar/translation.json b/src/locales/ar/translation.json index 034d0cbd2..3de926679 100644 --- a/src/locales/ar/translation.json +++ b/src/locales/ar/translation.json @@ -273,6 +273,13 @@ "added_download_source": "تمت إضافة مصدر التنزيل", "download_sources_synced": "تمت مزامنة جميع مصادر التنزيل", "insert_valid_json_url": "أدخل عنوان JSON صالح", + "download_source_urls": "عناوين مصادر التنزيل", + "single_source": "واحد", + "bulk_add_sources": "إضافة مجمعة", + "insert_urls_one_per_line": "أدخل عناوين JSON صالحة، واحد في كل سطر", + "must_be_valid_urls": "يجب أن تكون عناوين صالحة", + "add_download_sources": "إضافة مصادر", + "bulk_add_results": "تمت إضافة {{success}} مصدر(مصادر) بنجاح. فشل {{failed}}.", "found_download_option_zero": "لم يتم العثور على خيارات تنزيل", "found_download_option_one": "تم العثور على {{countFormatted}} خيار تنزيل", "found_download_option_other": "تم العثور على {{countFormatted}} خيارات تنزيل", diff --git a/src/locales/be/translation.json b/src/locales/be/translation.json index 8d67e693e..415cff805 100644 --- a/src/locales/be/translation.json +++ b/src/locales/be/translation.json @@ -108,6 +108,17 @@ "title_confirmation_delete_all_sources": "Выдаліць усе крыніцы сцягвання", "removed_download_sources": "Крыніцы сцягвання выдалены", "button_delete_all_sources": "Премахнете всички източници на изтегляне", + "added_download_source": "Крыніца сцягвання дададзена", + "download_sources_synced": "Усе крыніцы сцягвання сінхранізаваны", + "download_source_url": "URL крыніцы сцягвання", + "download_source_urls": "URL-адрасы крыніц сцягвання", + "single_source": "Адзін", + "bulk_add_sources": "Масавае даданне", + "insert_valid_json_url": "Увядзіце сапраўдны JSON URL", + "insert_urls_one_per_line": "Увядзіце сапраўдныя JSON URL-адрасы, па адным на радок", + "must_be_valid_urls": "Павінны быць сапраўдныя URL-адрасы", + "add_download_sources": "Дадаць крыніцы", + "bulk_add_results": "Дададзена {{success}} крыніца(крыніц) паспяхова. {{failed}} не ўдалося.", "behavior": "Паводзіны", "quit_app_instead_hiding": "Закрываць праграму замест таго, каб хаваць яе ў трэй", "launch_with_system": "Запускаць праграму пры запуску сыстэмы" diff --git a/src/locales/bg/translation.json b/src/locales/bg/translation.json index 3e2897006..f8f266fa2 100644 --- a/src/locales/bg/translation.json +++ b/src/locales/bg/translation.json @@ -288,6 +288,13 @@ "added_download_source": "Източникът е добавен", "download_sources_synced": "Всички източници са синхронизирани", "insert_valid_json_url": "Въведете валиден JSON url", + "download_source_urls": "URL адреси на източници за изтегляне", + "single_source": "Един", + "bulk_add_sources": "Масово добавяне", + "insert_urls_one_per_line": "Въведете валидни JSON URL адреси, по един на ред", + "must_be_valid_urls": "Трябва да са валидни URL адреси", + "add_download_sources": "Добави източници", + "bulk_add_results": "Добавени {{success}} източник(а) успешно. {{failed}} не успяха.", "found_download_option_zero": "Не е намерена опция за изтегляне", "found_download_option_one": "Намерена е {{countFormatted}} опция за изтегляне", "found_download_option_other": "Намерени са {{countFormatted}} опции за изтегляне", diff --git a/src/locales/ca/translation.json b/src/locales/ca/translation.json index 96eb67e29..f7b6f58ad 100644 --- a/src/locales/ca/translation.json +++ b/src/locales/ca/translation.json @@ -189,6 +189,13 @@ "added_download_source": "Added download source", "download_sources_synced": "Totes les fonts de descàrrega estan sincronitzades", "insert_valid_json_url": "Insereix una URL JSON vàlida", + "download_source_urls": "URLs de fonts de descàrrega", + "single_source": "Únic", + "bulk_add_sources": "Afegir en massa", + "insert_urls_one_per_line": "Insereix URLs JSON vàlides, una per línia", + "must_be_valid_urls": "Han de ser URLs vàlides", + "add_download_sources": "Afegir fonts", + "bulk_add_results": "Afegit {{success}} font(s) amb èxit. {{failed}} han fallat.", "found_download_option_zero": "No s'ha trobat cap opció de descàrrega", "found_download_option_one": "S'ha trobat l'opció de baixada de {{countFormatted}}", "found_download_option_other": "S'han trobat {{countFormatted}} opcions de baixada", diff --git a/src/locales/cs/translation.json b/src/locales/cs/translation.json index 6bcc89444..a9efa0eaa 100644 --- a/src/locales/cs/translation.json +++ b/src/locales/cs/translation.json @@ -281,6 +281,13 @@ "added_download_source": "Zdroj přidán", "download_sources_synced": "Všechny zdroje jsou synchronizovány", "insert_valid_json_url": "Zadej platnou JSON adresu", + "download_source_urls": "URL adresy zdrojů stahování", + "single_source": "Jeden", + "bulk_add_sources": "Hromadné přidání", + "insert_urls_one_per_line": "Zadej platné JSON URL adresy, jednu na řádek", + "must_be_valid_urls": "Musí být platné URL adresy", + "add_download_sources": "Přidat zdroje", + "bulk_add_results": "Přidáno {{success}} zdroj(ů) úspěšně. {{failed}} selhalo.", "found_download_option_zero": "Nenalezena žádná možnost stahování", "found_download_option_one": "Nalezena {{countFormatted}} možnost stahování", "found_download_option_other": "Nalezeny {{countFormatted}} možnosti stahování", diff --git a/src/locales/da/translation.json b/src/locales/da/translation.json index 21a92f72c..58b508565 100644 --- a/src/locales/da/translation.json +++ b/src/locales/da/translation.json @@ -205,6 +205,13 @@ "added_download_source": "Tilføjede download kilde", "download_sources_synced": "Alle download kilder er synkroniserede", "insert_valid_json_url": "Indsæt en gyldig JSON url", + "download_source_urls": "Download kilde URL'er", + "single_source": "Enkelt", + "bulk_add_sources": "Tilføj i bulk", + "insert_urls_one_per_line": "Indsæt gyldige JSON URL'er, én per linje", + "must_be_valid_urls": "Skal være gyldige URL'er", + "add_download_sources": "Tilføj kilder", + "bulk_add_results": "Tilføjet {{success}} kilde(r) med succes. {{failed}} fejlede.", "found_download_option_zero": "Ingen download mulighed fundet", "found_download_option_one": "Fandt {{countFormatted}} download mulighed", "found_download_option_other": "Fandt {{countFormatted}} download mulighed", diff --git a/src/locales/de/translation.json b/src/locales/de/translation.json index fb285ee0d..954064da4 100644 --- a/src/locales/de/translation.json +++ b/src/locales/de/translation.json @@ -289,6 +289,13 @@ "added_download_source": "Download-Quelle hinzugefügt", "download_sources_synced": "Alle Download-Quellen sind synchronisiert", "insert_valid_json_url": "Füge eine gültige JSON URL ein", + "download_source_urls": "Download-Quellen-URLs", + "single_source": "Einzel", + "bulk_add_sources": "Massenhinzufügen", + "insert_urls_one_per_line": "Füge gültige JSON-URLs ein, eine pro Zeile", + "must_be_valid_urls": "Müssen gültige URLs sein", + "add_download_sources": "Quellen hinzufügen", + "bulk_add_results": "{{success}} Quelle(n) erfolgreich hinzugefügt. {{failed}} fehlgeschlagen.", "found_download_option_zero": "Keine Download-Option gefunden", "found_download_option_one": "{{countFormatted}} Download-Option gefunden", "found_download_option_other": "{{countFormatted}} Download-Optionen gefunden", diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5084a4a0c..9d8f1d5a1 100755 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -443,7 +443,14 @@ "download_count_one": "{{countFormatted}} download option", "download_count_other": "{{countFormatted}} download options", "download_source_url": "Download source URL", + "download_source_urls": "Download source URLs", "add_download_source_description": "Insert the URL of the .json file", + "single_source": "Single", + "bulk_add_sources": "Bulk Add", + "insert_urls_one_per_line": "Insert valid JSON URLs, one per line", + "must_be_valid_urls": "Must be valid URLs", + "add_download_sources": "Add sources", + "bulk_add_results": "Added {{success}} source(s) successfully. {{failed}} failed.", "download_source_up_to_date": "Up-to-date", "download_source_errored": "Errored", "download_source_pending_matching": "Updating soon", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 5a65d3cf6..3af506ba8 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -452,6 +452,13 @@ "added_download_source": "Añadir fuente de descarga", "download_sources_synced": "Todas las fuentes de descarga están sincronizadas", "insert_valid_json_url": "Introducí una URL de json válida", + "download_source_urls": "URLs de fuentes de descarga", + "single_source": "Único", + "bulk_add_sources": "Agregar en masa", + "insert_urls_one_per_line": "Introduce URLs JSON válidas, una por línea", + "must_be_valid_urls": "Deben ser URLs válidas", + "add_download_sources": "Agregar fuentes", + "bulk_add_results": "Agregado {{success}} fuente(s) exitosamente. {{failed}} fallaron.", "found_download_option_zero": "Sin opciones de descargas encontrada", "found_download_option_one": "Encontrada {{countFormatted}} fuente de descarga", "found_download_option_other": "Encontradas {{countFormatted}} opciones de descargas", diff --git a/src/locales/et/translation.json b/src/locales/et/translation.json index c5566eeb9..0528ca249 100644 --- a/src/locales/et/translation.json +++ b/src/locales/et/translation.json @@ -241,6 +241,13 @@ "added_download_source": "Allalaadimise allikas lisatud", "download_sources_synced": "Kõik allalaadimise allikad on sünkroniseeritud", "insert_valid_json_url": "Sisesta kehtiv JSON url", + "download_source_urls": "Allalaadimise allika URL-id", + "single_source": "Üks", + "bulk_add_sources": "Hulgi lisamine", + "insert_urls_one_per_line": "Sisesta kehtivad JSON URL-id, üks reale", + "must_be_valid_urls": "Peavad olema kehtivad URL-id", + "add_download_sources": "Lisa allikad", + "bulk_add_results": "Lisatud {{success}} allikas(t) edukalt. {{failed}} ebaõnnestus.", "found_download_option_zero": "Allalaadimise valikuid ei leitud", "found_download_option_one": "Leitud {{countFormatted}} allalaadimise valik", "found_download_option_other": "Leitud {{countFormatted}} allalaadimise valikut", diff --git a/src/locales/fa/translation.json b/src/locales/fa/translation.json index 69a49b79e..4fb204a1b 100644 --- a/src/locales/fa/translation.json +++ b/src/locales/fa/translation.json @@ -112,6 +112,17 @@ "title_confirmation_delete_all_sources": "تمام منابع دانلود را حذف کنید", "removed_download_sources": "منابع دانلود حذف شد", "button_delete_all_sources": "تمام منابع دانلود را حذف کنید", + "added_download_source": "منبع دانلود اضافه شد", + "download_sources_synced": "همه منابع دانلود همگام‌سازی شده‌اند", + "download_source_url": "URL منبع دانلود", + "download_source_urls": "URLهای منابع دانلود", + "single_source": "تک", + "bulk_add_sources": "افزودن دسته‌ای", + "insert_valid_json_url": "یک URL JSON معتبر وارد کنید", + "insert_urls_one_per_line": "URLهای JSON معتبر را وارد کنید، هر خط یک URL", + "must_be_valid_urls": "باید URLهای معتبر باشند", + "add_download_sources": "افزودن منابع", + "bulk_add_results": "{{success}} منبع(منابع) با موفقیت اضافه شد. {{failed}} ناموفق بود.", "enable_real_debrid": "فعال‌سازی Real-Debrid", "debrid_api_token_hint": "کلید API خود را از <ب0>اینجا بگیرید.", "save_changes": "ذخیره تغییرات" diff --git a/src/locales/fi/translation.json b/src/locales/fi/translation.json index fee3ff225..54d4cba8e 100644 --- a/src/locales/fi/translation.json +++ b/src/locales/fi/translation.json @@ -445,6 +445,13 @@ "added_download_source": "Lähde lisätty", "download_sources_synced": "Kaikki lähteet päivitetty", "insert_valid_json_url": "Liitä kelvollinen JSON-tiedoston URL-osoite", + "download_source_urls": "Latauslähde-URL-osoitteet", + "single_source": "Yksi", + "bulk_add_sources": "Lisää joukolla", + "insert_urls_one_per_line": "Liitä kelvollisia JSON-URL-osoitteita, yksi per rivi", + "must_be_valid_urls": "Täytyy olla kelvollisia URL-osoitteita", + "add_download_sources": "Lisää lähteet", + "bulk_add_results": "Lisätty {{success}} lähde(t) onnistuneesti. {{failed}} epäonnistui.", "found_download_option_zero": "Ei latausvaihtoehtoja löytynyt", "found_download_option_one": "Löytyi {{countFormatted}} latausvaihtoehto", "found_download_option_other": "Löytyi {{countFormatted}} latausvaihtoehtoa", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 8fc077225..666681399 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -283,6 +283,13 @@ "added_download_source": "Source de téléchargement ajoutée", "download_sources_synced": "Toutes les sources de téléchargement sont synchronisées", "insert_valid_json_url": "Insérez une URL JSON valide", + "download_source_urls": "URLs des sources de téléchargement", + "single_source": "Unique", + "bulk_add_sources": "Ajout en masse", + "insert_urls_one_per_line": "Insérez des URLs JSON valides, une par ligne", + "must_be_valid_urls": "Doit être des URLs valides", + "add_download_sources": "Ajouter des sources", + "bulk_add_results": "Ajouté {{success}} source(s) avec succès. {{failed}} ont échoué.", "found_download_option_zero": "Aucune option de téléchargement trouvée", "found_download_option_one": "{{countFormatted}} option trouvée", "found_download_option_other": "{{countFormatted}} options trouvées", diff --git a/src/locales/hu/translation.json b/src/locales/hu/translation.json index c2a598731..031d5fd15 100644 --- a/src/locales/hu/translation.json +++ b/src/locales/hu/translation.json @@ -464,6 +464,13 @@ "added_download_source": "Letöltési forrás hozzáadva", "download_sources_synced": "Az összes letöltési forrás szinkronizálva", "insert_valid_json_url": "Adj meg egy érvényes JSON url-t", + "download_source_urls": "Letöltési forrás URL-ek", + "single_source": "Egyetlen", + "bulk_add_sources": "Tömeges hozzáadás", + "insert_urls_one_per_line": "Adj meg érvényes JSON URL-eket, soronként egyet", + "must_be_valid_urls": "Érvényes URL-eknek kell lenniük", + "add_download_sources": "Források hozzáadása", + "bulk_add_results": "{{success}} forrás sikeresen hozzáadva. {{failed}} sikertelen.", "found_download_option_zero": "Nincs letöltési opció", "found_download_option_one": "{{countFormatted}} Letöltési opció találva", "found_download_option_other": "{{countFormatted}} Letöltési opciók találva", diff --git a/src/locales/id/translation.json b/src/locales/id/translation.json index b782da211..9ad1874e8 100644 --- a/src/locales/id/translation.json +++ b/src/locales/id/translation.json @@ -188,6 +188,13 @@ "added_download_source": "Sumber unduhan ditambahkan", "download_sources_synced": "Semua sumber unduhan disinkronkan", "insert_valid_json_url": "Masukkan URL JSON yang valid", + "download_source_urls": "URL sumber unduhan", + "single_source": "Tunggal", + "bulk_add_sources": "Tambah massal", + "insert_urls_one_per_line": "Masukkan URL JSON yang valid, satu per baris", + "must_be_valid_urls": "Harus berupa URL yang valid", + "add_download_sources": "Tambah sumber", + "bulk_add_results": "Ditambahkan {{success}} sumber berhasil. {{failed}} gagal.", "found_download_option_zero": "Tidak ada opsi unduhan ditemukan", "found_download_option_one": "Ditemukan {{countFormatted}} opsi unduhan", "found_download_option_other": "Ditemukan {{countFormatted}} opsi unduhan", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index ac37ffe97..1bc70b44f 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -122,6 +122,17 @@ "title_confirmation_delete_all_sources": "Elimina tutte le fonti di download", "removed_download_sources": "Fonti di download rimosse", "button_delete_all_sources": "Rimuovi tutte le fonti di download", + "added_download_source": "Fonte di download aggiunta", + "download_sources_synced": "Tutte le fonti di download sono sincronizzate", + "download_source_url": "URL fonte di download", + "download_source_urls": "URL fonti di download", + "single_source": "Singolo", + "bulk_add_sources": "Aggiungi in blocco", + "insert_valid_json_url": "Inserisci un URL JSON valido", + "insert_urls_one_per_line": "Inserisci URL JSON validi, uno per riga", + "must_be_valid_urls": "Devono essere URL validi", + "add_download_sources": "Aggiungi fonti", + "bulk_add_results": "Aggiunto {{success}} fonte(i) con successo. {{failed}} non riusciti.", "debrid_api_token_hint": "Puoi trovare la tua chiave API <0>here", "save_changes": "Salva modifiche" }, diff --git a/src/locales/kk/translation.json b/src/locales/kk/translation.json index 48fb8181a..d88ea45dd 100644 --- a/src/locales/kk/translation.json +++ b/src/locales/kk/translation.json @@ -187,6 +187,13 @@ "added_download_source": "Жүктеу көзі қосылды", "download_sources_synced": "Барлық жүктеу көздері синхрондалды", "insert_valid_json_url": "Жарамды JSON URL енгізіңіз", + "download_source_urls": "Жүктеу көздерінің URL мекенжайлары", + "single_source": "Бір", + "bulk_add_sources": "Жалпылама қосу", + "insert_urls_one_per_line": "Жарамды JSON URL мекенжайларын енгізіңіз, әр жолға біреу", + "must_be_valid_urls": "Жарамды URL мекенжайлары болуы керек", + "add_download_sources": "Көздерді қосу", + "bulk_add_results": "{{success}} көз(дер) сәтті қосылды. {{failed}} сәтсіз аяқталды.", "found_download_option_zero": "Жүктеу нұсқалары табылмады", "found_download_option_one": "{{countFormatted}} жүктеу нұсқасы табылды", "found_download_option_other": "{{countFormatted}} жүктеу нұсқалары табылды", diff --git a/src/locales/ko/translation.json b/src/locales/ko/translation.json index a9b9c0e55..32c46b28a 100644 --- a/src/locales/ko/translation.json +++ b/src/locales/ko/translation.json @@ -112,6 +112,17 @@ "title_confirmation_delete_all_sources": "모든 다운로드 소스 삭제", "removed_download_sources": "제거된 글꼴", "button_delete_all_sources": "모든 다운로드 소스 제거", + "added_download_source": "다운로드 소스 추가됨", + "download_sources_synced": "모든 다운로드 소스가 동기화됨", + "download_source_url": "다운로드 소스 URL", + "download_source_urls": "다운로드 소스 URL", + "single_source": "단일", + "bulk_add_sources": "일괄 추가", + "insert_valid_json_url": "유효한 JSON URL을 입력하세요", + "insert_urls_one_per_line": "유효한 JSON URL을 입력하세요, 한 줄에 하나씩", + "must_be_valid_urls": "유효한 URL이어야 합니다", + "add_download_sources": "소스 추가", + "bulk_add_results": "{{success}}개 소스가 성공적으로 추가되었습니다. {{failed}}개 실패했습니다.", "enable_real_debrid": "Real-Debrid 활성화", "debrid_api_token_hint": "API 키를 <0>이곳에서 얻으세요.", "save_changes": "변경 사항 저장" diff --git a/src/locales/lv/translation.json b/src/locales/lv/translation.json index 26aacb74e..5ec989763 100644 --- a/src/locales/lv/translation.json +++ b/src/locales/lv/translation.json @@ -445,6 +445,13 @@ "added_download_source": "Avots pievienots", "download_sources_synced": "Visi avoti atjaunināti", "insert_valid_json_url": "Ievietojiet derīgu JSON faila URL", + "download_source_urls": "Lejupielādes avotu URL adreses", + "single_source": "Viens", + "bulk_add_sources": "Masveida pievienošana", + "insert_urls_one_per_line": "Ievietojiet derīgas JSON URL adreses, vienu katrā rindā", + "must_be_valid_urls": "Jābūt derīgām URL adresēm", + "add_download_sources": "Pievienot avotus", + "bulk_add_results": "Pievienots {{success}} avots(i) veiksmīgi. {{failed}} neizdevās.", "found_download_option_zero": "Nav atrasts lejupielādes variantu", "found_download_option_one": "Atrasts {{countFormatted}} lejupielādes variants", "found_download_option_other": "Atrasti {{countFormatted}} lejupielādes varianti", diff --git a/src/locales/nb/translation.json b/src/locales/nb/translation.json index 95bda8fe1..79af5d150 100644 --- a/src/locales/nb/translation.json +++ b/src/locales/nb/translation.json @@ -205,6 +205,13 @@ "added_download_source": "La til Nedlastingskilde", "download_sources_synced": "Alle nedlastingskilder er synkroniserte", "insert_valid_json_url": "Innsett en gyldig JSON url", + "download_source_urls": "Nedlastingskilde-URL-er", + "single_source": "Enkelt", + "bulk_add_sources": "Legg til i bulk", + "insert_urls_one_per_line": "Innsett gyldige JSON URL-er, én per linje", + "must_be_valid_urls": "Må være gyldige URL-er", + "add_download_sources": "Legg til kilder", + "bulk_add_results": "Lagt til {{success}} kilde(r) med suksess. {{failed}} feilet.", "found_download_option_zero": "Ingen nedlastingsmulighet funnet", "found_download_option_one": "Fant {{countFormatted}} nedlastingsmulighet", "found_download_option_other": "Fant {{countFormatted}} nedlastingsmuligheter", diff --git a/src/locales/nl/translation.json b/src/locales/nl/translation.json index baa6df6e1..af41593df 100644 --- a/src/locales/nl/translation.json +++ b/src/locales/nl/translation.json @@ -113,6 +113,17 @@ "title_confirmation_delete_all_sources": "Verwijder alle downloadbronnen", "removed_download_sources": "Downloadbronnen verwijderd", "button_delete_all_sources": "Verwijder alle downloadbronnen", + "added_download_source": "Downloadbron toegevoegd", + "download_sources_synced": "Alle downloadbronnen zijn gesynchroniseerd", + "download_source_url": "Downloadbron URL", + "download_source_urls": "Downloadbron URL's", + "single_source": "Enkele", + "bulk_add_sources": "Bulk toevoegen", + "insert_valid_json_url": "Voer een geldige JSON URL in", + "insert_urls_one_per_line": "Voer geldige JSON URL's in, één per regel", + "must_be_valid_urls": "Moeten geldige URL's zijn", + "add_download_sources": "Bronnen toevoegen", + "bulk_add_results": "{{success}} bron(nen) succesvol toegevoegd. {{failed}} mislukt.", "enable_real_debrid": "Enable Real-Debrid", "debrid_api_token_hint": "U kunt uw API-sleutel <0>hier verkrijgen.", "save_changes": "Wijzigingen opslaan" diff --git a/src/locales/pl/translation.json b/src/locales/pl/translation.json index 2e0d16964..45fd9ac54 100644 --- a/src/locales/pl/translation.json +++ b/src/locales/pl/translation.json @@ -121,6 +121,18 @@ "description_confirmation_delete_all_sources": "Usuniesz wszystkie źródła pobierania", "title_confirmation_delete_all_sources": "Usuń wszystkie źródła pobierania", "button_delete_all_sources": "Usuń wszystkie źródła pobierania", + "removed_download_sources": "Źródła pobierania usunięte", + "added_download_source": "Źródło pobierania dodane", + "download_sources_synced": "Wszystkie źródła pobierania są zsynchronizowane", + "download_source_url": "URL źródła pobierania", + "download_source_urls": "URL źródła pobierania", + "single_source": "Pojedyncze", + "bulk_add_sources": "Dodaj masowo", + "insert_valid_json_url": "Wprowadź prawidłowy URL JSON", + "insert_urls_one_per_line": "Wprowadź prawidłowe URL JSON, jeden na linię", + "must_be_valid_urls": "Muszą być prawidłowe URL", + "add_download_sources": "Dodaj źródła", + "bulk_add_results": "Dodano {{success}} źródło(źródeł) pomyślnie. {{failed}} nie powiodło się.", "enable_real_debrid": "Włącz Real-Debrid", "debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj", "save_changes": "Zapisz zmiany" diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 73d5e8fb2..ee005eeed 100755 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -449,6 +449,13 @@ "added_download_source": "Fonte adicionada", "download_sources_synced": "As fontes foram sincronizadas", "insert_valid_json_url": "Insira a url de um JSON válido", + "download_source_urls": "URLs de fontes de download", + "single_source": "Único", + "bulk_add_sources": "Adicionar em massa", + "insert_urls_one_per_line": "Insira URLs JSON válidas, uma por linha", + "must_be_valid_urls": "Devem ser URLs válidas", + "add_download_sources": "Adicionar fontes", + "bulk_add_results": "Adicionado {{success}} fonte(s) com sucesso. {{failed}} falharam.", "found_download_option_zero": "Nenhuma opção de download encontrada", "found_download_option_one": "{{countFormatted}} opção de download encontrada", "found_download_option_other": "{{countFormatted}} opções de download encontradas", diff --git a/src/locales/pt-PT/translation.json b/src/locales/pt-PT/translation.json index c8e4586d8..8b9d54952 100644 --- a/src/locales/pt-PT/translation.json +++ b/src/locales/pt-PT/translation.json @@ -273,6 +273,13 @@ "added_download_source": "Fonte adicionada", "download_sources_synced": "As fontes foram sincronizadas", "insert_valid_json_url": "Insere o URL de um JSON válido", + "download_source_urls": "URLs de fontes de descarga", + "single_source": "Único", + "bulk_add_sources": "Adicionar em massa", + "insert_urls_one_per_line": "Insere URLs JSON válidas, uma por linha", + "must_be_valid_urls": "Devem ser URLs válidas", + "add_download_sources": "Adicionar fontes", + "bulk_add_results": "Adicionado {{success}} fonte(s) com sucesso. {{failed}} falharam.", "found_download_option_zero": "Nenhuma opção de transferência encontrada", "found_download_option_one": "{{countFormatted}} opção de transferência encontrada", "found_download_option_other": "{{countFormatted}} opções de transferência encontradas", diff --git a/src/locales/ro/translation.json b/src/locales/ro/translation.json index 8ed6fd39d..22804d336 100644 --- a/src/locales/ro/translation.json +++ b/src/locales/ro/translation.json @@ -128,6 +128,17 @@ "title_confirmation_delete_all_sources": "Ștergeți toate sursele de descărcare", "removed_download_sources": "Sursele de descărcare au fost eliminate", "button_delete_all_sources": "Eliminați toate sursele de descărcare", + "added_download_source": "Sursă de descărcare adăugată", + "download_sources_synced": "Toate sursele de descărcare sunt sincronizate", + "download_source_url": "URL sursă de descărcare", + "download_source_urls": "URL-uri surse de descărcare", + "single_source": "Unul", + "bulk_add_sources": "Adăugare în masă", + "insert_valid_json_url": "Inserează un URL JSON valid", + "insert_urls_one_per_line": "Inserează URL-uri JSON valide, unul pe linie", + "must_be_valid_urls": "Trebuie să fie URL-uri valide", + "add_download_sources": "Adaugă surse", + "bulk_add_results": "Adăugat {{success}} sursă(e) cu succes. {{failed}} au eșuat.", "enable_real_debrid": "Activează Real-Debrid", "real_debrid_description": "Real-Debrid este un descărcător fără restricții care îți permite să descarci fișiere instantaneu și la cea mai bună viteză a internetului tău.", "debrid_invalid_token": "Token API invalid", diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json index b831ff2e4..f381cebc6 100644 --- a/src/locales/ru/translation.json +++ b/src/locales/ru/translation.json @@ -462,6 +462,13 @@ "added_download_source": "Источник добавлен", "download_sources_synced": "Все источники обновлены", "insert_valid_json_url": "Вставьте действительный URL JSON-файла", + "download_source_urls": "URL-адреса источников загрузки", + "single_source": "Один", + "bulk_add_sources": "Массовое добавление", + "insert_urls_one_per_line": "Вставьте действительные URL JSON-файлов, по одному на строку", + "must_be_valid_urls": "Должны быть действительные URL", + "add_download_sources": "Добавить источники", + "bulk_add_results": "Добавлено {{success}} источник(ов) успешно. {{failed}} не удалось.", "found_download_option_zero": "Не найдено вариантов загрузки", "found_download_option_one": "Найден {{countFormatted}} вариант загрузки", "found_download_option_other": "Найдено {{countFormatted}} вариантов загрузки", diff --git a/src/locales/sv/translation.json b/src/locales/sv/translation.json index 901e4ca76..3d6d8ff5d 100644 --- a/src/locales/sv/translation.json +++ b/src/locales/sv/translation.json @@ -288,6 +288,13 @@ "added_download_source": "Nedladdningskälla tillagd", "download_sources_synced": "Alla nedladdningskällor är synkroniserade", "insert_valid_json_url": "Ange en giltig JSON-URL", + "download_source_urls": "Nedladdningskäll-URL:er", + "single_source": "Enskild", + "bulk_add_sources": "Masslägg till", + "insert_urls_one_per_line": "Ange giltiga JSON-URL:er, en per rad", + "must_be_valid_urls": "Måste vara giltiga URL:er", + "add_download_sources": "Lägg till källor", + "bulk_add_results": "Lade till {{success}} källa(r) framgångsrikt. {{failed}} misslyckades.", "found_download_option_zero": "Inga nedladdningsalternativ hittades", "found_download_option_one": "Hittade {{countFormatted}} nedladdningsalternativ", "found_download_option_other": "Hittade {{countFormatted}} nedladdningsalternativ", diff --git a/src/locales/tr/translation.json b/src/locales/tr/translation.json index 52e1f10f9..f73a5c758 100644 --- a/src/locales/tr/translation.json +++ b/src/locales/tr/translation.json @@ -453,7 +453,14 @@ "button_delete_all_sources": "Tümünü kaldır", "added_download_source": "İndirme kaynağı eklendi", "download_sources_synced": "Tüm indirme kaynakları eşitlendi", - "insert_valid_json_url": "Geçerli bir JSON URL’si girin", + "insert_valid_json_url": "Geçerli bir JSON URL'si girin", + "download_source_urls": "İndirme kaynağı URL'leri", + "single_source": "Tek", + "bulk_add_sources": "Toplu ekle", + "insert_urls_one_per_line": "Geçerli JSON URL'lerini girin, her satıra bir tane", + "must_be_valid_urls": "Geçerli URL'ler olmalı", + "add_download_sources": "Kaynak ekle", + "bulk_add_results": "{{success}} kaynak başarıyla eklendi. {{failed}} başarısız.", "found_download_option_zero": "İndirme seçeneği bulunamadı", "found_download_option_one": "{{countFormatted}} indirme seçeneği bulundu", "found_download_option_other": "{{countFormatted}} indirme seçeneği bulundu", diff --git a/src/locales/uk/translation.json b/src/locales/uk/translation.json index 323d8ad5c..3d862af93 100644 --- a/src/locales/uk/translation.json +++ b/src/locales/uk/translation.json @@ -426,6 +426,13 @@ "general": "Основні", "import": "Імпортувати", "insert_valid_json_url": "Вставте дійсний URL JSON-файлу", + "download_source_urls": "URL-адреси джерел завантаження", + "single_source": "Один", + "bulk_add_sources": "Масове додавання", + "insert_urls_one_per_line": "Вставте дійсні URL JSON-файлів, по одному на рядок", + "must_be_valid_urls": "Повинні бути дійсні URL", + "add_download_sources": "Додати джерела", + "bulk_add_results": "Додано {{success}} джерело(джерел) успішно. {{failed}} не вдалося.", "language": "Мова", "cancel_button_confirmation_delete_all_sources": "немає", "confirm_button_confirmation_delete_all_sources": "Так, видалити все", diff --git a/src/locales/uz/translation.json b/src/locales/uz/translation.json index 24e508af3..213ce47a5 100644 --- a/src/locales/uz/translation.json +++ b/src/locales/uz/translation.json @@ -255,6 +255,13 @@ "added_download_source": "Manba qo'shildi", "download_sources_synced": "Barcha manbalar yangilandi", "insert_valid_json_url": "Amaldagi JSON-fayl URL'ini kiriting", + "download_source_urls": "Yuklab olish manbalari URL manzillari", + "single_source": "Bitta", + "bulk_add_sources": "Ommaviy qo'shish", + "insert_urls_one_per_line": "Amaldagi JSON URL manzillarini kiriting, har bir qatorga bittadan", + "must_be_valid_urls": "Amaldagi URL manzillar bo'lishi kerak", + "add_download_sources": "Manbalarni qo'shish", + "bulk_add_results": "{{success}} manba(lar) muvaffaqiyatli qo'shildi. {{failed}} muvaffaqiyatsiz.", "found_download_option_zero": "Yuklab olish variantlari topilmadi", "found_download_option_one": "{{countFormatted}} yuklab olish varianti topildi", "found_download_option_other": "{{countFormatted}} yuklab olish varianti topildi", diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index bfc353d9b..910281068 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -450,6 +450,13 @@ "added_download_source": "已添加下载源", "download_sources_synced": "所有下载源已同步", "insert_valid_json_url": "插入有效的 JSON 网址", + "download_source_urls": "下载源网址", + "single_source": "单个", + "bulk_add_sources": "批量添加", + "insert_urls_one_per_line": "插入有效的 JSON 网址,每行一个", + "must_be_valid_urls": "必须是有效的网址", + "add_download_sources": "添加源", + "bulk_add_results": "成功添加 {{success}} 个源。{{failed}} 个失败。", "found_download_option_zero": "未找到下载选项", "found_download_option_one": "找到 {{countFormatted}} 个下载选项", "found_download_option_other": "找到 {{countFormatted}} 个下载选项", diff --git a/src/main/events/download-sources/add-download-sources-bulk.ts b/src/main/events/download-sources/add-download-sources-bulk.ts new file mode 100644 index 000000000..57f9919b8 --- /dev/null +++ b/src/main/events/download-sources/add-download-sources-bulk.ts @@ -0,0 +1,100 @@ +import { registerEvent } from "../register-event"; +import { HydraApi } from "@main/services/hydra-api"; +import { downloadSourcesSublevel } from "@main/level"; +import type { DownloadSource } from "@types"; +import { logger } from "@main/services"; + +interface BulkAddResult { + success: number; + failed: number; + errors: string[]; +} + +const getErrorMessage = (error: unknown): string => { + if (error instanceof Error) { + if (error.message.includes("already exists")) { + return "Already exists"; + } + return error.message; + } + return "Unknown error"; +}; + +const addSingleDownloadSource = async ( + url: string, + existingUrls: Set, + result: BulkAddResult +): Promise => { + if (existingUrls.has(url)) { + result.failed++; + result.errors.push(`"${url}" - Already exists`); + return false; + } + + try { + const downloadSource = await HydraApi.post( + "/download-sources", + { + url, + }, + { needsAuth: false } + ); + + await downloadSourcesSublevel.put(downloadSource.id, { + ...downloadSource, + isRemote: true, + createdAt: new Date().toISOString(), + }); + + result.success++; + return true; + } catch (error) { + result.failed++; + const errorMessage = getErrorMessage(error); + result.errors.push(`"${url}" - ${errorMessage}`); + logger.error(`Failed to add download source "${url}":`, error); + return false; + } +}; + +const addDownloadSourcesBulk = async ( + _event: Electron.IpcMainInvokeEvent, + urls: string[] +): Promise => { + const result: BulkAddResult = { + success: 0, + failed: 0, + errors: [], + }; + + const existingSources = await downloadSourcesSublevel.values().all(); + const existingUrls = new Set(existingSources.map((source) => source.url)); + + const uniqueUrls = Array.from(new Set(urls)); + const profileUrls: string[] = []; + + for (const url of uniqueUrls) { + const added = await addSingleDownloadSource(url, existingUrls, result); + if (added && HydraApi.isLoggedIn() && HydraApi.hasActiveSubscription()) { + profileUrls.push(url); + } + } + + if ( + profileUrls.length > 0 && + HydraApi.isLoggedIn() && + HydraApi.hasActiveSubscription() + ) { + try { + await HydraApi.post("/profile/download-sources", { + urls: profileUrls, + }); + } catch (error) { + logger.error("Failed to add download sources to profile:", error); + } + } + + return result; +}; + +registerEvent("addDownloadSourcesBulk", addDownloadSourcesBulk); diff --git a/src/main/events/index.ts b/src/main/events/index.ts index 2720d3ceb..4919f7bee 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -65,6 +65,7 @@ import "./autoupdater/restart-and-install-update"; import "./user-preferences/authenticate-real-debrid"; import "./user-preferences/authenticate-torbox"; import "./download-sources/add-download-source"; +import "./download-sources/add-download-sources-bulk"; import "./download-sources/sync-download-sources"; import "./download-sources/get-download-sources-check-baseline"; import "./download-sources/get-download-sources-since-value"; diff --git a/src/preload/index.ts b/src/preload/index.ts index a29655321..16f3cf9cc 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -99,6 +99,8 @@ contextBridge.exposeInMainWorld("electron", { /* Download sources */ addDownloadSource: (url: string) => ipcRenderer.invoke("addDownloadSource", url), + addDownloadSourcesBulk: (urls: string[]) => + ipcRenderer.invoke("addDownloadSourcesBulk", urls), removeDownloadSource: (url: string, removeAll?: boolean) => ipcRenderer.invoke("removeDownloadSource", url, removeAll), getDownloadSources: () => ipcRenderer.invoke("getDownloadSources"), diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index e35ed57bb..f1ee9ed67 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -213,6 +213,9 @@ declare global { /* Download sources */ addDownloadSource: (url: string) => Promise; + addDownloadSourcesBulk: ( + urls: string[] + ) => Promise<{ success: number; failed: number; errors: string[] }>; removeDownloadSource: ( removeAll = false, downloadSourceId?: string diff --git a/src/renderer/src/pages/settings/add-download-source-modal.scss b/src/renderer/src/pages/settings/add-download-source-modal.scss index d938f7f0d..00d733e9e 100644 --- a/src/renderer/src/pages/settings/add-download-source-modal.scss +++ b/src/renderer/src/pages/settings/add-download-source-modal.scss @@ -45,4 +45,72 @@ gap: globals.$spacing-unit; margin-top: calc(globals.$spacing-unit * 2); } + + &__mode-toggle { + display: flex; + gap: globals.$spacing-unit; + margin-bottom: calc(globals.$spacing-unit * 2); + } + + &__textarea-container { + display: flex; + flex-direction: column; + gap: calc(globals.$spacing-unit / 2); + + label { + color: globals.$body-color; + font-size: 14px; + font-weight: 500; + } + } + + &__textarea { + background-color: globals.$dark-background-color; + border: solid 1px globals.$border-color; + border-radius: 8px; + padding: globals.$spacing-unit; + color: #dadbe1; + font-family: inherit; + font-size: 14px; + resize: vertical; + min-height: 200px; + outline: none; + transition: border-color ease 0.2s; + + &:hover { + border-color: rgba(255, 255, 255, 0.5); + } + + &:focus { + border-color: #dadbe1; + cursor: text; + } + } + + &__error { + color: globals.$error-color; + font-size: 12px; + margin-top: calc(globals.$spacing-unit / 2); + } + + &__results { + margin-top: calc(globals.$spacing-unit * 2); + padding: globals.$spacing-unit; + background-color: globals.$dark-background-color; + border-radius: 8px; + border: solid 1px globals.$border-color; + + p { + margin: 0; + color: globals.$body-color; + font-size: 14px; + } + } + + &__errors { + display: flex; + flex-direction: column; + gap: calc(globals.$spacing-unit / 2); + margin-top: calc(globals.$spacing-unit / 2); + } } diff --git a/src/renderer/src/pages/settings/add-download-source-modal.tsx b/src/renderer/src/pages/settings/add-download-source-modal.tsx index af6f8b4d4..f7da11322 100644 --- a/src/renderer/src/pages/settings/add-download-source-modal.tsx +++ b/src/renderer/src/pages/settings/add-download-source-modal.tsx @@ -1,4 +1,4 @@ -import { useContext, useEffect, useState } from "react"; +import { useContext, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Button, Modal, TextField } from "@renderer/components"; @@ -18,7 +18,8 @@ interface AddDownloadSourceModalProps { } interface FormValues { - url: string; + url?: string; + urls?: string; } export function AddDownloadSourceModal({ @@ -27,12 +28,48 @@ export function AddDownloadSourceModal({ onAddDownloadSource, }: Readonly) { const [isLoading, setIsLoading] = useState(false); + const [isBulkMode, setIsBulkMode] = useState(false); + const [bulkResults, setBulkResults] = useState<{ + success: number; + failed: number; + errors: string[]; + } | null>(null); const { t } = useTranslation("settings"); - const schema = yup.object().shape({ - url: yup.string().required(t("required_field")).url(t("must_be_valid_url")), - }); + const schema = useMemo( + () => + yup.object().shape({ + url: isBulkMode + ? yup.string() + : yup + .string() + .required(t("required_field")) + .url(t("must_be_valid_url")), + urls: isBulkMode + ? yup + .string() + .required(t("required_field")) + .test("valid-urls", t("must_be_valid_urls"), (value) => { + if (!value) return false; + const urlList = value + .split("\n") + .map((url) => url.trim()) + .filter((url) => url.length > 0); + if (urlList.length === 0) return false; + try { + for (const url of urlList) { + new URL(url); + } + return true; + } catch { + return false; + } + }) + : yup.string(), + }), + [isBulkMode, t] + ); const { register, @@ -40,21 +77,54 @@ export function AddDownloadSourceModal({ setValue, setError, clearErrors, + watch, formState: { errors, isSubmitting }, } = useForm({ - resolver: yupResolver(schema), + resolver: yupResolver(schema) as any, }); + const watchedUrls = watch("urls"); + const { sourceUrl } = useContext(settingsContext); const onSubmit = async (values: FormValues) => { setIsLoading(true); + setBulkResults(null); try { - await window.electron.addDownloadSource(values.url); + if (isBulkMode) { + const urlList = (values.urls || "") + .split("\n") + .map((url) => url.trim()) + .filter((url) => url.length > 0); + + const results = + await globalThis.electron.addDownloadSourcesBulk(urlList); + + setBulkResults({ + success: results.success, + failed: results.failed, + errors: results.errors, + }); + + if (results.success > 0) { + onAddDownloadSource(); + } - onClose(); - onAddDownloadSource(); + if (results.failed === 0) { + setTimeout(() => { + onClose(); + }, 2000); + } + } else { + if (!values.url) { + setIsLoading(false); + return; + } + await window.electron.addDownloadSource(values.url); + onClose(); + onAddDownloadSource(); + } } catch (error) { logger.error("Failed to add download source:", error); const errorMessage = @@ -62,22 +132,34 @@ export function AddDownloadSourceModal({ ? t("download_source_already_exists") : t("failed_add_download_source"); - setError("url", { - type: "server", - message: errorMessage, - }); + if (isBulkMode) { + setError("urls", { + type: "server", + message: errorMessage, + }); + } else { + setError("url", { + type: "server", + message: errorMessage, + }); + } } finally { setIsLoading(false); } }; useEffect(() => { - setValue("url", ""); - clearErrors(); - setIsLoading(false); + if (visible) { + setValue("url", ""); + setValue("urls", ""); + clearErrors(); + setIsLoading(false); + setBulkResults(null); + setIsBulkMode(false); - if (sourceUrl) { - setValue("url", sourceUrl); + if (sourceUrl) { + setValue("url", sourceUrl); + } } }, [visible, clearErrors, setValue, sourceUrl]); @@ -86,6 +168,13 @@ export function AddDownloadSourceModal({ onClose(); }; + const urlCount = isBulkMode + ? ((watchedUrls || "") + .split("\n") + .map((url) => url.trim()) + .filter((url) => url.length > 0).length ?? 0) + : 0; + return (
+
+ + +
+
- + {isBulkMode ? ( +
+ +