diff --git a/.github/workflows/publish-rolling.yml b/.github/workflows/publish-rolling.yml index c43ed9271..d526b50a7 100644 --- a/.github/workflows/publish-rolling.yml +++ b/.github/workflows/publish-rolling.yml @@ -125,14 +125,12 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} registry-url: 'https://registry.npmjs.org' - cache: 'pnpm' - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/client/src/javascript/i18n/strings/he.json b/client/src/javascript/i18n/strings/he.json index 0967ef424..7016602fe 100644 --- a/client/src/javascript/i18n/strings/he.json +++ b/client/src/javascript/i18n/strings/he.json @@ -1 +1,394 @@ -{} +{ + "actionbar.button.add.torrent": "הוספת טורנט", + "actionbar.button.remove.torrent": "הסרת טורנט", + "actionbar.button.start.torrent": "התחלת Torrent", + "actionbar.button.stop.torrent": "עצירת טורנט", + "alert.settings.saved": "ההגדרות נשמרו בהצלחה.", + "alert.torrent.add": "הוספת {countElement} {count, plural, =1 {טורנט} other {טורנטים}} הצליחה.", + "alert.torrent.add.failed": "הוספת {countElement} {count, plural, =1 {טורנט} other {טורנטים}} נכשלה.", + "alert.torrent.add.sent": "{countElement} {count, plural,=1 {בקשה נשלחה} other {בקשות נשלחו}} ללקוח הטורנטים.", + "alert.torrent.move": "הזזת {countElement} {count, plural,=1 {טורנט} other {טורנטים}} הצליחה.", + "alert.torrent.move.failed": "הזזת {countElement} {count, plural,=1 {טורנט} other {טורנטים}} נכשלה.", + "alert.torrent.remove": "הסרת {countElement} {count, plural,=1 {טורנט} other {טורנטים}} הצליחה.", + "alert.torrent.remove.failed": "הסרת {countElement} {count, plural,=1 {טורנט} other {טורנטים}} נכשלה.", + "auth.add.user": "הוספת משתמש", + "auth.admin": "מנהל", + "auth.create.account": "יצירת חשבון", + "auth.create.an.account": "יצירת חשבון", + "auth.create.an.account.intro": "ברוכים הבאים ל-Flood!", + "auth.current.user": "משתמש נוכחי", + "auth.error.password.empty": "הסיסמה לא יכולה להיות ריקה.", + "auth.error.username.empty": "שם המשתמש אינו יכול להיות ריק.", + "auth.input.clear": "ניקוי", + "auth.log.in": "התחברות", + "auth.login": "התחברות", + "auth.login.intro": "התחבר לחשבונך.", + "auth.message.not.admin": "המשתמש אינו מנהל", + "auth.password": "ססמה", + "auth.user.accounts": "חשבונות משתמשים", + "auth.username": "שם משתמש", + "button.add": "הוספה", + "button.cancel": "ביטול", + "button.close": "סגירה", + "button.download": "הורדה", + "button.new": "חדש", + "button.no": "לא", + "button.ok": "אישור", + "button.retry": "ניסיון חוזר", + "button.save": "שמירת הגדרות", + "button.save.feed": "שמירה", + "button.yes": "כן", + "connection-interruption.action.selection.config": "עדכון הגדרות חיבור הלקוח", + "connection-interruption.action.selection.retry": "ניסיון נוסף עם הגדרות חיבור הלקוח הנוכחיות", + "connection-interruption.heading": "לא ניתן להתחבר ללקוח", + "connection-interruption.not.admin": "נא ליצור קשר עם מנהל Flood אם בעיה זו ממשיכה.", + "connection-interruption.verification-error": "לא ניתן לאמת את החיבור.", + "connection.settings.client.select": "לקוח", + "connection.settings.error.empty": "הגדרות החיבור לא יכולות להיות ריקות.", + "connection.settings.deluge": "Deluge", + "connection.settings.deluge.host": "מארח", + "connection.settings.deluge.host.input.placeholder": "למשל localhost", + "connection.settings.deluge.password": "סיסמה", + "connection.settings.deluge.password.input.placeholder": "סיסמה", + "connection.settings.deluge.port": "פורט", + "connection.settings.deluge.port.input.placeholder": "למשל 58846", + "connection.settings.deluge.username": "שם משתמש", + "connection.settings.deluge.username.input.placeholder": "למשל localclient", + "connection.settings.qbittorrent": "qBittorrent", + "connection.settings.qbittorrent.password": "סיסמה", + "connection.settings.qbittorrent.password.input.placeholder": "סיסמה", + "connection.settings.qbittorrent.url": "URL", + "connection.settings.qbittorrent.url.input.placeholder": "למשל http://localhost:8080", + "connection.settings.qbittorrent.username": "שם משתמש", + "connection.settings.qbittorrent.username.input.placeholder": "שם משתמש", + "connection.settings.rtorrent": "rTorrent", + "connection.settings.rtorrent.host": "מארח", + "connection.settings.rtorrent.host.input.placeholder": "שם מארח", + "connection.settings.rtorrent.port": "פורט", + "connection.settings.rtorrent.port.input.placeholder": "פורט", + "connection.settings.rtorrent.socket": "מסלול", + "connection.settings.rtorrent.socket.input.placeholder": "למשל ‎~/.local/share/rtorrent/rtorrent.sock‏", + "connection.settings.rtorrent.type": "סוג חיבור", + "connection.settings.rtorrent.type.socket": "שקע", + "connection.settings.rtorrent.type.tcp": "TCP", + "connection.settings.rtorrent.type.tcp.warning": "חשיפת rTorrent דרך TCP עלולה לאפשר העלאת הרשאות.", + "connection.settings.transmission": "Transmission", + "connection.settings.transmission.password": "סיסמה", + "connection.settings.transmission.password.input.placeholder": "סיסמה", + "connection.settings.transmission.url": "URL", + "connection.settings.transmission.url.input.placeholder": "למשל http://localhost:9091/transmission/rpc", + "connection.settings.transmission.username": "שם משתמש", + "connection.settings.transmission.username.input.placeholder": "שם משתמש", + "dependency.loading.notifications": "התראות", + "dependency.loading.torrent.list": "רשימת טורנטים", + "dependency.loading.torrent.taxonomy": "סיווג טורנטים", + "dependency.loading.transfer.history": "היסטוריית העברת מידע", + "dependency.loading.transfer.rate.details": "פרטים על קצב העברת מידע", + "feeds.applicable.feed": "הזן בר שימוש", + "feeds.apply.tags": "החלת תגים", + "feeds.browse.feeds": "סקירת הזנים", + "feeds.check": "וידוא החוק על ידי ניסוי שלו. לא נשמר או נשלח.", + "feeds.exclude": "סינון", + "feeds.exclude.pattern": "תבנית סינון", + "feeds.existing.feeds": "הזנים קיימים", + "feeds.existing.rules": "חוקים קיימים", + "feeds.interval": "מרווח זמן", + "feeds.label": "תוית", + "feeds.match": "התאמת", + "feeds.match.count": "{count, plural, =1 {התאמה אחת} other {# התאמות}}", + "feeds.match.pattern": "תבנית התאמה", + "feeds.no.feeds.available": "אין הזנים זמינים.", + "feeds.no.feeds.defined": "לא הוגדרו הזנים.", + "feeds.no.items.matching": "אין פריטים המתאימים למילות החיפוש.", + "feeds.no.rules.defined": "לא הוגדרו חוקים.", + "feeds.regEx": "RegEx", + "feeds.search": "מילות חיפוש", + "feeds.search.term": "מילות חיפוש", + "feeds.select.feed": "בחירת הזן", + "feeds.select.interval": "מרווח זמן", + "feeds.start.on.load": "התחלה בעת טעינה", + "feeds.tabs.download.rules": "חוקי הורדה", + "feeds.tabs.feeds": "הזנים", + "feeds.tabs.heading": "הזני טורנטים", + "feeds.tags": "תגים", + "feeds.test.match": "בדיקת תבנית התאמת", + "feeds.time.day": "ימים", + "feeds.time.hr": "שעות", + "feeds.time.min": "דקות", + "feeds.torrent.destination": "יעד הטורנט", + "feeds.url": "URL", + "feeds.validation.interval.not.positive": "משך הזמן חייב להיות מספר שלם חיובי.", + "feeds.validation.invalid.regular.expression": "ביטוי רגולרי לא חוקי.", + "feeds.validation.must.select.feed": "יש לבחור הזן.", + "feeds.validation.must.specify.destination": "יש למלא יעד.", + "feeds.validation.must.specify.label": "יש למלא תוית.", + "feeds.validation.must.specify.valid.feed.url": "יש למלא URL של הזן חוקי.", + "filesystem.empty.directory": "תיקייה ריקה.", + "filesystem.error.eacces": "ל-Flood אין הרשאות לקרוא תיקייה זו.", + "filesystem.error.enoent": "המסלול לא קיים. הוא יווצר עכשיו.", + "filesystem.error.no.input": "נא למלא את המסלול.", + "filesystem.error.unknown": "אירעה שגיאה לא ידועה, נא לנסות שוב.", + "filesystem.fetching": "אוסף מבנה תיקיות...", + "filter.all": "הכל", + "filter.status.active": "פעיל", + "filter.status.checking": "בבדיקה", + "filter.status.completed": "הושלם", + "filter.status.downloading": "מוריד", + "filter.status.error": "שגיאה", + "filter.status.inactive": "לא פעיל", + "filter.status.seeding": "זורע", + "filter.status.stopped": "נעצר", + "filter.status.title": "סינון לפי מצב", + "filter.tag.title": "סינון לפי תג", + "filter.tracker.title": "סינון לפי גשש", + "filter.untagged": "לא מתויג", + "general.ago": "מאז", + "general.clipboard.copied": "הועתק", + "general.clipboard.copy": "העתקה", + "general.error.unknown": "אירעה שגיאה לא ידועה", + "general.of": "של", + "general.to": "אל", + "locale.language.auto": "אוטומטי", + "mediainfo.execError": "אירעה שגיאנ בהרצת mediainfo על השרת. נא לבדוק ש-mediainfo מותקנת ונגישה ב-PATH אל Flood.", + "mediainfo.fetching": "אוסף...", + "mediainfo.heading": "פלט Mediainfo", + "notification.clear.all": "ניקוי הכל", + "notification.feed.torrent.added.body": "{title}", + "notification.feed.torrent.added.heading": "פריט הזן נוסף לתור", + "notification.no.notification": "אין התראות להצגה.", + "notification.showing": "מציג", + "notification.torrent.errored.body": "{name}", + "notification.torrent.errored.heading": "השגיאה דווחה", + "notification.torrent.finished.body": "{name}", + "notification.torrent.finished.heading": "ההורדה הסתיימה", + "priority.dont.download": "לא להוריד", + "priority.high": "גבוהה", + "priority.low": "נמוכה", + "priority.normal": "רגילה", + "settings.bandwidth.slots.download.global.label": "חריצי הורדה גלובליים", + "settings.bandwidth.slots.download.label": "משבצות זמן הורדה לכל טורנט", + "settings.bandwidth.slots.heading": "זמינות משבצות זמן", + "settings.bandwidth.slots.upload.global.label": "משבצות זמן העלאה גלובליים", + "settings.bandwidth.slots.upload.label": "משבצות זמן העלאה לכל טורנט", + "settings.bandwidth.transferrate.dropdown.preset.download.label": "תפריט הגדרות: הורדה", + "settings.bandwidth.transferrate.dropdown.preset.upload.label": "תפריט הגדרות: העלאה", + "settings.bandwidth.transferrate.global.throttle.download": "הגבלת מהירות הורדה גלובלית", + "settings.bandwidth.transferrate.global.throttle.upload": "הגבלת מהירות העלאה גלובלית", + "settings.bandwidth.transferrate.heading": "הגבלת קצב העברה", + "settings.connectivity.dht.label": "הפעלת DHT", + "settings.connectivity.dht.port.label": "פורט DHT", + "settings.connectivity.dpd.heading": "גילוי עמיתים מבוזר", + "settings.connectivity.incoming.heading": "חיבורים נכנסים", + "settings.connectivity.ip.hostname.label": "כתובות/שמות מארחים מדווחים", + "settings.connectivity.max.http.connections": "מספר חיבורי HTTP מקסימלי", + "settings.connectivity.peer.exchange.label": "הפעלת החלפת עמיתים", + "settings.connectivity.peers.desired.label": "מספר עמיתים רצוי", + "settings.connectivity.peers.heading": "עמיתים", + "settings.connectivity.peers.max.label": "מספר עמיתים מקסימלי", + "settings.connectivity.peers.min.label": "מספר עמיתים מינימלי", + "settings.connectivity.peers.seeding.max.label": "מספר עמיתים מקסימלי לזריעה", + "settings.connectivity.peers.seeding.min.label": "מספר עמיתים מינימלי לזריעה", + "settings.connectivity.port.open.label": "פורט פתוח", + "settings.connectivity.port.randomize.label": "בחירת פורט אקראי", + "settings.connectivity.port.range.label": "טווח פורטים", + "settings.diskusage.mount.points": "נקודת הרכבה לחישוב שימוש בדיסק", + "settings.diskusage.show": "הצגה", + "settings.resources.disk.check.hash.label": "וידוא ערך גיבוב בסיום", + "settings.resources.disk.download.location.label": "תיקיית הורדה דיפולטית", + "settings.resources.disk.heading": "דיסק", + "settings.resources.max.open.files": "מספר קבצים פתוחים מקסימלי", + "settings.resources.memory.heading": "זיכרון", + "settings.resources.memory.max.label": "זיכרון מקסימלי לשימוש", + "settings.tabs.about": "אודות", + "settings.tabs.authentication": "הזדהות", + "settings.tabs.bandwidth": "רוחב פס", + "settings.tabs.connectivity": "חיבוריות", + "settings.tabs.diskusage": "שימוש בדיסק", + "settings.tabs.heading": "הגדרות", + "settings.tabs.resources": "משאבים", + "settings.tabs.userinterface": "ממשק משתמש", + "settings.ui.displayed.context.menu.items": "פריטי תפריט", + "settings.ui.displayed.details": "עמודות פרטי הטורנט", + "settings.ui.language": "שפה", + "settings.ui.misc": "שונות", + "settings.ui.page.title.speed": "הצגת קצב העלאה והורדה בכותרת העמוד", + "settings.ui.locale": "ניב", + "settings.ui.tag.selector.mode": "העדפת בוחר תגים", + "settings.ui.tag.selector.mode.multi": "בחירה מרובה", + "settings.ui.tag.selector.mode.single": "בחירה יחידה", + "settings.ui.torrent.context.menu.items.show": "הצגה", + "settings.ui.torrent.details.enabled": "מופעל", + "settings.ui.torrent.details.tags.placement": "בחלון המורחב, תגים עובדים הכי טוב בסוף הרשימה.", + "settings.ui.torrent.list": "הצגת רשימת הטורנטים", + "settings.ui.torrent.size": "גודל טורנט", + "settings.ui.torrent.size.condensed": "תצוגה מרוכזת", + "settings.ui.torrent.size.expanded": "תצוגה מרווחת", + "sidebar.button.feeds": "הזנים", + "sidebar.button.log.out": "התנתקות", + "sidebar.button.settings": "הגדרות", + "sidebar.button.speedlimits": "הגבלות מהירות", + "sidebar.button.theme.dark": "ערכת נושא כהה", + "sidebar.button.theme.light": "ערכת נושא בהירה", + "sidebar.search.placeholder": "חיפוש טורנטים", + "sidebar.speedlimits.download": "הורדה", + "sidebar.speedlimits.upload": "העלאה", + "sidebar.transferdata.downloaded": "ירד", + "sidebar.transferdata.uploaded": "עלה", + "speed.unlimited": "לא מוגבל", + "status.diskusage.free": "פנוי", + "status.diskusage.title": "שימוש בדיסק", + "status.diskusage.total": "סך־הכול", + "status.diskusage.used": "בשימוש", + "torrent.list.peers": "{connected} {of} {total}", + "torrent.list.peers.of": "מתוך", + "torrents.add.button.add": "הוספת טורנט", + "torrents.add.cookies.input.placeholder": "אופציונלי cookie-name=cookie-value", + "torrents.add.cookies.label": "עוגיות", + "torrents.add.destination.label": "יעד", + "torrents.add.destination.placeholder": "יעד", + "torrents.add.heading": "הוספת טורנטים", + "torrents.add.start.label": "התחלת טורנט", + "torrents.add.tab.create.title": "יצירה", + "torrents.add.tab.file.browse": "או לחיצה על דפדוף", + "torrents.add.tab.file.drop": "נקודת שחרור קבצים,", + "torrents.add.tab.file.title": "לפי קובץ", + "torrents.add.tab.url.input.placeholder": "URL של טורנט או קישור מגנט", + "torrents.add.tab.url.register.magnet.handler": "יש להירשם כדי לטפל בקישורי מגנט", + "torrents.add.tab.url.title": "לפי URL", + "torrents.add.tags": "תגים", + "torrents.add.torrents.label": "טורנטים", + "torrents.create.base.name.input.placeholder": "שם קובץ או תיקיית בסיס אופציונלי עבור הטורנט", + "torrents.create.base.name.label": "שם בסיס", + "torrents.create.comment.input.placeholder": "הערה בקובץ הטורנט. אופציונלי", + "torrents.create.comment.label": "הערה", + "torrents.create.info.source.input.placeholder": "מקור ב-infohash. אופציונלי", + "torrents.create.info.source.label": "מקור מידע", + "torrents.create.is.private.label": "פרטי", + "torrents.create.source.path.label": "מקור", + "torrents.create.tags.input.placeholder": "תגית ב-Flood. לא נוספות לטורנטים שיווצרו.", + "torrents.create.tracker.input.placeholder": "URL גשש", + "torrents.create.trackers.label": "גששים", + "torrents.destination.base_path": "השתמש בתור מסלול בסיס", + "torrents.destination.completed": "הושלם", + "torrents.destination.sequential": "הורדה סדרתית", + "torrents.details.actions.pause": "השהיה", + "torrents.details.actions.start": "התחלה", + "torrents.details.actions.stop": "עצירה", + "torrents.details.details": "פרטים", + "torrents.details.files": "קבצים", + "torrents.details.files.download.file": "{count, plural, =1 {הורדת קובץ}other {הורדת קבצים}}", + "torrents.details.files.loading": "פרטי הקובץ נטענים...", + "torrents.details.general.comment": "הערה", + "torrents.details.general.connected": "{connected} התחברו מתוך {total}", + "torrents.details.general.date.active": "פעילות אחרונה", + "torrents.details.general.date.active.now": "עכשיו", + "torrents.details.general.date.added": "נוסף", + "torrents.details.general.date.created": "נוצר", + "torrents.details.general.date.finished": "הסתיים", + "torrents.details.general.downloaded": "ירד", + "torrents.details.general.free.disk.space": "מקום פנוי בדיסק", + "torrents.details.general.hash": "גיבוב", + "torrents.details.general.heading.general": "כללי", + "torrents.details.general.heading.torrent": "טורנט", + "torrents.details.general.heading.tracker": "גשש", + "torrents.details.general.heading.transfer": "העברה", + "torrents.details.general.location": "מקום", + "torrents.details.general.none": "אין", + "torrents.details.general.peers": "עמיתים", + "torrents.details.general.scheduler": "מתזמן", + "torrents.details.general.scheduler.ignored": "התעלם", + "torrents.details.general.scheduler.obeyed": "ציית", + "torrents.details.general.seeds": "זורעים", + "torrents.details.general.size": "גודל", + "torrents.details.general.tags": "תגיות", + "torrents.details.general.tracker.message": "הודעת הטראקר", + "torrents.details.general.type": "סוג", + "torrents.details.general.type.private": "פרטי", + "torrents.details.general.type.public": "פומבי", + "torrents.details.mediainfo": "Mediainfo", + "torrents.details.peers": "עמיתים", + "torrents.details.peers.no.data": "אין מידע מעמיתים על טורנט זה.", + "torrents.details.selected.files": "{count, plural, =1 {נבחר קובץ {countElement}} other {נבחרו {countElement} קבצים}}", + "torrents.details.selected.files.set.priority": "הגדרת עדיפות", + "torrents.details.trackers": "גששים", + "torrents.details.trackers.no.data": "אין מידע עוקבים לטורנט זה.", + "torrents.details.trackers.type": "סוג", + "torrents.generate.magnet.heading": "יצירת לינק מגנט", + "torrents.generate.magnet.loading.trackers": "טוען עוקבים...", + "torrents.generate.magnet.magnet": "לינק מגנט", + "torrents.generate.magnet.magnet.with.trackers": "לינק מגנט עם עוקבים", + "torrents.generate.magnet.private.torrent": "זהו טורנט פרטי.", + "torrents.list.cannot.connect": "ההתחברות ללקוח נכשלה.", + "torrents.list.clear.filters": "ניקוי פילטרים", + "torrents.list.context.check.hash": "ניקוי הגיבוב", + "torrents.list.context.details": "פרטי הטורנט", + "torrents.list.context.download.contents": "הורדת תוכן", + "torrents.list.context.download.metainfo": "הורדת קובץ .torrent", + "torrents.list.context.generate.magnet": "יצירת לינק מגנט", + "torrents.list.context.initial.seeding": "זריעה ראשונית", + "torrents.list.context.move": "הגדרת מקום הטורנט", + "torrents.list.context.pause": "השהיה", + "torrents.list.context.priority": "עדיפות", + "torrents.list.context.reannounce": "פרסום מחדש", + "torrents.list.context.remove": "הסרה", + "torrents.list.context.sequential": "סדרתי", + "torrents.list.context.set.tags": "הגדרת תגיות", + "torrents.list.context.set.trackers": "הגדרת גששים", + "torrents.list.context.start": "התחלה", + "torrents.list.context.stop": "עצירה", + "torrents.list.drop": "הטלת קבצים כאן תוסיף אותם.", + "torrents.list.no.torrents": "אין טורנטים להצגה.", + "torrents.move.button.set.location": "הגדרת מקום", + "torrents.move.button.state.setting": "מגדיר...", + "torrents.move.check_hash.label": "בדיקת גיבוב", + "torrents.move.data.label": "הזזת מידע", + "torrents.move.heading": "הגדרת מקום הטורנט", + "torrents.properties.comment": "הערה", + "torrents.properties.date.added": "נוסף", + "torrents.properties.date.created": "נוצר", + "torrents.properties.date.finished": "הסתיים", + "torrents.properties.directory": "מקום", + "torrents.properties.download.speed": "קצב הורדה", + "torrents.properties.download.total": "ירד", + "torrents.properties.eta": "זמן שנותר", + "torrents.properties.free.disk.space": "מקום פנוי בדיסק", + "torrents.properties.hash": "גיבוב", + "torrents.properties.ignore.schedule": "התעלמות מהמתזמן", + "torrents.properties.is.private": "פרטי", + "torrents.properties.name": "שם", + "torrents.properties.peers": "עמיתים", + "torrents.properties.percentage": "אחוז שהושלם", + "torrents.properties.ratio": "יחס", + "torrents.properties.seeds": "זורעים", + "torrents.properties.size": "גודל קובץ", + "torrents.properties.tags": "תגים", + "torrents.properties.tracker.message": "הודעת גשש", + "torrents.properties.trackers": "גששים", + "torrents.properties.upload.speed": "קצב העלאה", + "torrents.properties.upload.total": "עלה", + "torrents.remove": "הסרת טורנטים", + "torrents.remove.are.you.sure": "האם ברצונך למחוק {count, plural, =1 {טורנט אחד} other {# טורנטים}}?", + "torrents.remove.delete.data": "מחיקת נתונים", + "torrents.remove.error.no.torrents.selected": "לא נבחרו טורנטים.", + "torrents.set.tags.button.set": "הגדרת תגים", + "torrents.set.tags.enter.tags": "הכנסת תגיות", + "torrents.set.tags.heading": "הגדרת תגים", + "torrents.set.trackers.button.set": "הגדרת גששים", + "torrents.set.trackers.enter.tracker": "הכנסת גשש", + "torrents.set.trackers.heading": "הגדרת גששים", + "torrents.set.trackers.loading.trackers": "טוען גששים...", + "torrents.sort.title": "מיון לפי", + "unit.size.byte": "בייט", + "unit.size.gigabyte": "גיגה-בייט", + "unit.size.kilobyte": "קילו-בייט", + "unit.size.megabyte": "מגה-בייט", + "unit.size.terabyte": "טרה-בייט", + "unit.speed": "{baseUnit} לשניה", + "unit.time.day": "יום", + "unit.time.hour": "שעה", + "unit.time.infinity": "אין-סוף", + "unit.time.minute": "דקה", + "unit.time.second": "שנייה", + "unit.time.week": "שבוע", + "unit.time.year": "שנה" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b85b77f9..00782ea7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3068,8 +3068,8 @@ packages: engines: {node: '>=12'} hasBin: true - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + cross-spawn@7.0.5: + resolution: {integrity: sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==} engines: {node: '>= 8'} css-declaration-sorter@6.4.1: @@ -10155,7 +10155,7 @@ snapshots: run-parallel: 1.2.0 simple-sha1: 3.1.0 - cross-spawn@7.0.3: + cross-spawn@7.0.5: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 @@ -11074,7 +11074,7 @@ snapshots: '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.5 debug: 4.3.6 doctrine: 3.0.0 escape-string-regexp: 4.0.0 @@ -11141,7 +11141,7 @@ snapshots: execa@5.1.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.5 get-stream: 6.0.1 human-signals: 2.1.0 is-stream: 2.0.1 @@ -11153,7 +11153,7 @@ snapshots: execa@8.0.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.5 get-stream: 8.0.1 human-signals: 5.0.0 is-stream: 3.0.0 @@ -13604,7 +13604,7 @@ snapshots: address: 1.2.2 browserslist: 4.23.3 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.5 detect-port-alt: 1.1.6 escape-string-regexp: 4.0.0 filesize: 8.0.7 diff --git a/server/services/qBittorrent/clientGatewayService.ts b/server/services/qBittorrent/clientGatewayService.ts index 63c28a029..f1e963d1a 100644 --- a/server/services/qBittorrent/clientGatewayService.ts +++ b/server/services/qBittorrent/clientGatewayService.ts @@ -85,11 +85,12 @@ class QBittorrentClientGatewayService extends ClientGatewayService { throw new Error(); } + const method = isApiVersionAtLeast(await this.clientRequestManager.apiVersion, '2.11.0') ? 'stopped' : 'paused'; await this.clientRequestManager .torrentsAddFiles(fileBuffers, { savepath: destination, tags: tags.join(','), - [isApiVersionAtLeast(this.clientRequestManager.apiVersion, '2.11.0') ? 'stopped' : 'paused']: !start, + [method]: !start, root_folder: !isBasePath, contentLayout: isBasePath ? 'NoSubfolder' : undefined, sequentialDownload: isSequential, @@ -119,11 +120,12 @@ class QBittorrentClientGatewayService extends ClientGatewayService { throw new Error(); } + const method = isApiVersionAtLeast(await this.clientRequestManager.apiVersion, '2.11.0') ? 'stopped' : 'paused'; await this.clientRequestManager .torrentsAddURLs(urls, { savepath: destination, tags: tags.join(','), - [isApiVersionAtLeast(this.clientRequestManager.apiVersion, '2.11.0') ? 'stopped' : 'paused']: !start, + [method]: !start, root_folder: !isBasePath, contentLayout: isBasePath ? 'NoSubfolder' : undefined, sequentialDownload: isSequential, @@ -526,7 +528,7 @@ class QBittorrentClientGatewayService extends ClientGatewayService { async testGateway(): Promise { return this.clientRequestManager - .updateAuthCookie() + .updateConnection() .then(() => this.processClientRequestSuccess(undefined), this.processClientRequestError); } } diff --git a/server/services/qBittorrent/clientRequestManager.ts b/server/services/qBittorrent/clientRequestManager.ts index 2bd32130a..6143cbc6f 100644 --- a/server/services/qBittorrent/clientRequestManager.ts +++ b/server/services/qBittorrent/clientRequestManager.ts @@ -36,7 +36,7 @@ const EMPTY_SERVER_STATE = { class ClientRequestManager { private connectionSettings: QBittorrentConnectionSettings; private apiBase: string; - apiVersion: string | null = null; + apiVersion: Promise = Promise.resolve(undefined); private authCookie: Promise = Promise.resolve(undefined); private isMainDataPending = false; @@ -80,17 +80,27 @@ class ClientRequestManager { }); } - async updateAuthCookie(connectionSettings?: QBittorrentConnectionSettings): Promise { - let authFailed = false; + async updateConnection(connectionSettings?: QBittorrentConnectionSettings): Promise { + let failed = false; this.authCookie = this.authenticate(connectionSettings).catch(() => { - authFailed = true; + failed = true; return undefined; }); + this.apiVersion = this.authCookie + .then(() => { + return !failed ? this.getApiVersion() : Promise.resolve(undefined); + }) + .catch(() => { + failed = true; + return undefined; + }); + await this.authCookie; + await this.apiVersion; - if (authFailed) { + if (failed) { throw new Error(); } } @@ -120,15 +130,12 @@ class ClientRequestManager { }); } - async getApiVersion(): Promise { - try { - const {data} = await axios.get(`${this.apiBase}/app/webapiVersion`, { + async getApiVersion(): Promise { + return axios + .get(`${this.apiBase}/app/webapiVersion`, { headers: await this.getRequestHeaders(), - }); - this.apiVersion = data; - } catch (error) { - this.apiVersion = null; - } + }) + .then((res) => res.data); } async getTorrentInfos(): Promise { @@ -306,7 +313,7 @@ class ClientRequestManager { } async torrentsPause(hashes: Array): Promise { - const method = isApiVersionAtLeast(this.apiVersion, '2.11.0') ? 'stop' : 'pause'; + const method = isApiVersionAtLeast(await this.apiVersion, '2.11.0') ? 'stop' : 'pause'; return axios .post( `${this.apiBase}/torrents/${method}`, @@ -323,7 +330,7 @@ class ClientRequestManager { } async torrentsResume(hashes: Array): Promise { - const method = isApiVersionAtLeast(this.apiVersion, '2.11.0') ? 'start' : 'resume'; + const method = isApiVersionAtLeast(await this.apiVersion, '2.11.0') ? 'start' : 'resume'; return axios .post( `${this.apiBase}/torrents/${method}`, @@ -622,8 +629,7 @@ class ClientRequestManager { constructor(connectionSettings: QBittorrentConnectionSettings) { this.connectionSettings = connectionSettings; this.apiBase = `${connectionSettings.url}/api/v2`; - this.updateAuthCookie().catch(() => undefined); - this.getApiVersion(); + this.updateConnection().catch(() => undefined); } } diff --git a/server/services/qBittorrent/util/apiVersionCheck.ts b/server/services/qBittorrent/util/apiVersionCheck.ts index 9ba6a3d38..7a9f84154 100644 --- a/server/services/qBittorrent/util/apiVersionCheck.ts +++ b/server/services/qBittorrent/util/apiVersionCheck.ts @@ -1,4 +1,4 @@ -export function isApiVersionAtLeast(currentVersion: string | null, targetVersion: string): boolean { +export function isApiVersionAtLeast(currentVersion: string | undefined, targetVersion: string): boolean { if (!currentVersion) { return false; } diff --git a/server/services/rTorrent/util/XMLRPCDeserializer.ts b/server/services/rTorrent/util/XMLRPCDeserializer.ts index 7dae044da..334a77b02 100644 --- a/server/services/rTorrent/util/XMLRPCDeserializer.ts +++ b/server/services/rTorrent/util/XMLRPCDeserializer.ts @@ -55,6 +55,7 @@ const closeTag = (elementName: string) => { break; case 'i4': case 'i8': + case 'int': case 'string': case 'name': dataStack.push(tagValue); diff --git a/server/services/rTorrent/util/XMLRPCSerializer.ts b/server/services/rTorrent/util/XMLRPCSerializer.ts index 860a6efa4..39b154bfc 100644 --- a/server/services/rTorrent/util/XMLRPCSerializer.ts +++ b/server/services/rTorrent/util/XMLRPCSerializer.ts @@ -46,7 +46,7 @@ const value = (value: XMLRPCValue): string => { }; const data = (values: XMLRPCValue[]) => { - return `${values.map(value)}`; + return `${values.map(value).join('')}`; }; const member = ([key, val]: [string, XMLRPCValue]) => { @@ -64,7 +64,7 @@ const param = (param: XMLRPCValue) => { const sParams = (params: XMLRPCValue[]) => { if (!params?.length) return ''; - return `${params.map(param)}`; + return `${params.map(param).join('')}`; }; const serializeSync = (methodName: string, params: XMLRPCValue[]): string => {