diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 02e129a1..62948f97 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7312,6 +7312,11 @@ packages: optional: true dev: true + /xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + dev: true + /xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} diff --git a/src/assets/locales/ca.json b/src/assets/locales/ca.json index d046688f..0f71d187 100644 --- a/src/assets/locales/ca.json +++ b/src/assets/locales/ca.json @@ -532,6 +532,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Difuminat del fons", "backgroundLabel": "Opacitat del fons", "colorLabel": "Color", "previewQuote": "No he de tenir por. La por és l'assassina de la ment.", diff --git a/src/assets/locales/ca@valencia.json b/src/assets/locales/ca@valencia.json index e1e7615e..3c8c57b9 100644 --- a/src/assets/locales/ca@valencia.json +++ b/src/assets/locales/ca@valencia.json @@ -532,6 +532,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Difuminat del fons", "backgroundLabel": "Opacitat del fons", "colorLabel": "Color", "previewQuote": "No he de tindre por. La por és l'assassina de la ment.", diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 86ff372e..c2f5ee0a 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -122,7 +122,7 @@ "default": "Co si přejete sledovat?", "extra": [ "Co chcete objevit?", - null, + "Co je na vašem seznamu sledovaných filmů?", "Jaký je váš oblíbený film?", "Jaký je tvůj oblíbený seriál?" ] @@ -132,21 +132,15 @@ "titles": { "day": { "default": "Na co byste se chtěli dnes odpoledne dívat?", - "extra": [ - "Chceš zažít dobrodružství? Jurský Park je pro tebe." - ] + "extra": ["Chceš zažít dobrodružství? Jurský Park je pro tebe."] }, "morning": { "default": "Na co byste se chtěli dnes ráno dívat?", - "extra": [ - "Slyšel jsem, že Před úsvitem je super." - ] + "extra": ["Slyšel jsem, že Před úsvitem je super"] }, "night": { "default": "Na co byste se chtěli dnes večer dívat?", - "extra": [ - "Unaven? Slyšel jsem, že Vymítač ďábla je super." - ] + "extra": ["Unaven? Slyšel jsem, že Vymítač ďábla je super."] } } }, @@ -187,9 +181,10 @@ "back": "Zpět", "explainer": "Pomocí rozšíření prohlížeče můžete získat nejlepší streamy, které nabízíme. S pouhou instalací.", "explainerIos": "Bohužel rozšíření není podporováno na iOS. Stiskněte Zpět pro výběr jiné možnosti.", - "extensionHelp": "Pokud jste rozšíření nainstalovali, ale nebylo zjištěno. Otevřete rozšíření pomocí nabídky rozšíření ve vašem prohlížeči a postupujte podle pokynů na obrazovce.", + "extensionHelp": "Pokud jste rozšíření nainstalovali, ale nebylo zjištěno, otevřete rozšíření pomocí nabídky rozšíření ve vašem prohlížeči a postupujte podle pokynů na obrazovce.", "linkChrome": "Instalovat rozšíření pro Chrome", "linkFirefox": "Instalovat rozšíření pro Firefox", + "notDetecting": "Nainstalováno na Chromu, ale stránka to nezaznamenala? Skuste přenačíst stránku!", "notDetectingAction": "Obnovit stránku", "status": { "disallowed": "Rozšíření není pro tuto stránku povoleno", @@ -534,6 +529,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Rozostření pozadí", "backgroundLabel": "Neprůhlednost pozadí", "colorLabel": "Barva", "previewQuote": "Nesmím se bát. Strach zabíjí myšlení.", diff --git a/src/assets/locales/de.json b/src/assets/locales/de.json index b39cc412..28bf233a 100644 --- a/src/assets/locales/de.json +++ b/src/assets/locales/de.json @@ -290,6 +290,7 @@ "title": "Qualität" }, "settings": { + "audioItem": "Audio", "downloadItem": "Download", "enableSubtitles": "Untettitel aktivieren", "experienceSection": "Anzeigeerlebnis", @@ -316,8 +317,9 @@ "unknownOption": "Unbekannt" }, "subtitles": { - "customChoice": "Untertitel aus Datei wählen", + "customChoice": "Untertiteldatei auswählen oder hier ablegen", "customizeLabel": "Anpassen", + "dropSubtitleFile": "Untertiteldatei hier ablegen", "offChoice": "Aus", "settings": { "backlink": "Eigene Untertitel", @@ -375,6 +377,13 @@ "title": "Hoppla, etwas ist schiefgegangen!" }, "scraping": { + "extensionFailure": { + "badge": "Erweiterung deaktiviert", + "enableExtension": "Erweiterung aktivieren", + "homeButton": "Zur Startseite", + "text": "Du hast die sudo-flixe Erweiterung installiert. Um die Erweiterung zu benutzen, musst du sie für diese Seite aktivieren.", + "title": "Bitte aktiviere die Erweiterung" + }, "items": { "failure": "Ein Fehler ist aufgetreten", "notFound": "Video nicht gefunden", diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index fca7c290..212c9e0a 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -142,6 +142,7 @@ "Sudo-Flix is the best site ever!", "What's on your watchlist today?", "How was your day?", + "My bad the site never works...", "Isn't sudo-flix just the best?" ] }, @@ -177,6 +178,7 @@ }, "media": { "episodeDisplay": "S{{season}} - E{{episode}}", + "unreleased": "Unreleased", "types": { "movie": "Movie", "show": "Show" @@ -203,11 +205,11 @@ "title": "Couldn't find that page" }, "downtimeNotice": { - "badge": "Maintenance", + "badge": "Issues", "goHome": "Go home", - "message": "sudo-flix.lol is dedicated to providing its users with the most up-to-date and stable experience in order to do this we are switching to a new DNS. Expect downtime between the below times.", - "timeFrame": "March 10th 7:00 PM - 7:30 AM", - "title": "Maintenance expected" + "message": "sudo-flix.lol is experiencing issues with some providers again, if you cant find or play a show please change the source. Expect this error to persist throughout the below times.", + "timeFrame": "March 31th 11:00 PM - 5:00 AM EST", + "title": "Provider issues" }, "onboarding": { "defaultConfirm": { @@ -487,6 +489,11 @@ "editProfile": "Edit", "logoutButton": "Log out" }, + "admin": { + "title": "Admin panel", + "text": "Utilize tools made for testing sudo-flix's condition.", + "button": "Check it out" + }, "actions": { "delete": { "button": "Delete account", diff --git a/src/assets/locales/es.json b/src/assets/locales/es.json index b3ca28e2..b9c77c03 100644 --- a/src/assets/locales/es.json +++ b/src/assets/locales/es.json @@ -290,6 +290,7 @@ "title": "Calidad" }, "settings": { + "audioItem": "Audio", "downloadItem": "Descargar", "enableSubtitles": "Habilitar subtítulos", "experienceSection": "Experiencia de visualización", @@ -316,8 +317,9 @@ "unknownOption": "Desconocida" }, "subtitles": { - "customChoice": "Seleccionar subtítulo del archivo", + "customChoice": "Sube o arrastra un archivo", "customizeLabel": "Personalizar", + "dropSubtitleFile": "Suelta el archivo de subtítulos aquí", "offChoice": "Apagado", "settings": { "backlink": "Subtítulos personalizados", @@ -532,6 +534,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Desefoque de fondo", "backgroundLabel": "Opacidad del fondo", "colorLabel": "Color", "previewQuote": "No debo temer. El miedo es el asesino de la mente.", diff --git a/src/assets/locales/et.json b/src/assets/locales/et.json index a9906460..bf8bb92d 100644 --- a/src/assets/locales/et.json +++ b/src/assets/locales/et.json @@ -151,7 +151,8 @@ "types": { "movie": "Film", "show": "Saade" - } + }, + "unreleased": "Avaldamata" }, "navigation": { "banner": { @@ -290,6 +291,7 @@ "title": "Kvaliteet" }, "settings": { + "audioItem": "Audio", "downloadItem": "Lae alla", "enableSubtitles": "Luba Subtiitrid", "experienceSection": "Vaatamise kogemus", @@ -316,8 +318,9 @@ "unknownOption": "Teadmata" }, "subtitles": { - "customChoice": "Vali subtiitrid failist", + "customChoice": "Kukuta või vali subtiitri fail", "customizeLabel": "Kohanda", + "dropSubtitleFile": "Kukuta subtiitri fail siia", "offChoice": "Välja", "settings": { "backlink": "Kohandatud subtiitrid", @@ -375,6 +378,13 @@ "title": "Video mängimine ebaōnnestus!" }, "scraping": { + "extensionFailure": { + "badge": "Brauserilaiendus väljalülitatud", + "enableExtension": "Lülita brauserilaiendus sisse", + "homeButton": "Tagasi", + "text": "Olete allalaadinud sudo-flix'i brauserilaiendue. Selle kasutamiseks peate vajutama brauserilaienduse peale ning andma ligipääsu praegusele saidile.", + "title": "Palun lülita brauserilaiendus sisse" + }, "items": { "failure": "Tekkis viga", "notFound": "Ei ole videot", diff --git a/src/assets/locales/fa.json b/src/assets/locales/fa.json index e6d6f3c1..3f59058b 100644 --- a/src/assets/locales/fa.json +++ b/src/assets/locales/fa.json @@ -73,7 +73,7 @@ } }, "errors": { - "badge": "مشکلی رخ داده", + "badge": "مشکلی رخ داد", "details": "جزئیات خطا", "reloadPage": "صفحه را دوباره بارگذاری کنید", "showError": "نمایش جزئیات خطا", @@ -89,7 +89,7 @@ "dmca": "DMCA", "github": "گیت هاب" }, - "tagline": "فیلم و سریال مورد علاقه‌تان را با این برنامه استریم متن باز تماشا کنید." + "tagline": "فیلم و سریال مورد علاقه‌تان را با این برنامه استریم اوپن سورس تماشا کنید." }, "global": { "name": "مووی-وب", @@ -155,7 +155,8 @@ "types": { "movie": "فیلم", "show": "سریال" - } + }, + "unreleased": "منتشر نشده" }, "navigation": { "banner": { @@ -294,6 +295,7 @@ "title": "کیفیت" }, "settings": { + "audioItem": "صدا", "downloadItem": "دانلود", "enableSubtitles": "فعال کردن زیرنویس", "experienceSection": "تجربه مشاهده", @@ -320,8 +322,9 @@ "unknownOption": "ناشناخته" }, "subtitles": { - "customChoice": "انتخاب زیرنویس از فایل", + "customChoice": "فایل را رها یا آپلود کنید", "customizeLabel": "شخصی سازی", + "dropSubtitleFile": "فایل زیرنویس را اینجا بکشید", "offChoice": "خاموش", "settings": { "backlink": "زیرنویس سفارشی", @@ -379,6 +382,13 @@ "title": "پخش ویدئو موفقیت آمیز نبود!" }, "scraping": { + "extensionFailure": { + "badge": "اکستنشن غیر فعال شد", + "enableExtension": "اکستنشن را فعال کنید", + "homeButton": "خانه", + "text": "شما اکستنشن مووی-وب را نصب کردید. برای شروع استفاده از ان، نیاز به فعال کردن آن دارید", + "title": "لطفا اکستنشن را فعال کنید" + }, "items": { "failure": "مشکلی پیش آمده", "notFound": "این ویدیو وجود ندارد", diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index beab2c57..cec7f50a 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -295,6 +295,7 @@ "title": "Qualité" }, "settings": { + "audioItem": "Audio", "downloadItem": "Télécharger", "enableSubtitles": "Activer les sous-titres", "experienceSection": "Expérience de visionnage", @@ -321,8 +322,9 @@ "unknownOption": "Inconnu" }, "subtitles": { - "customChoice": "Importer des sous-titres depuis un fichier", + "customChoice": "Glisser ou charger un fichier", "customizeLabel": "Personnaliser", + "dropSubtitleFile": "Glisser le fichier des sous-titres ici", "offChoice": "Désactivé", "settings": { "backlink": "Sous-titres personnalisés", diff --git a/src/assets/locales/gl.json b/src/assets/locales/gl.json index c3a6c902..052d10ce 100644 --- a/src/assets/locales/gl.json +++ b/src/assets/locales/gl.json @@ -57,6 +57,8 @@ }, "host": "Estaste a conectar a <0>{{hostname}} - por favor, confirma se confías antes de crear a conta", "no": "Regresar", + "noHost": "O servidor non está configurado, polo que non podes crear unha conta", + "noHostTitle": "O servidor non está configurado!", "title": "Confías neste servidor?", "yes": "Si, si que confío neste servidor" }, @@ -118,7 +120,12 @@ "noResults": "Non atopamos nada!", "placeholder": { "default": "Que che gustaría ver?", - "extra": [] + "extra": [ + "Qué queres explorar?", + "Que está na túa lista se seguimiento?", + "Cal é a túa película favorita?", + "Cal é a túa serie favorita?" + ] }, "sectionTitle": "Resultados da busca" }, @@ -241,6 +248,7 @@ }, "menus": { "downloads": { + "copyHlsPlaylist": "Copiar a ligazón da lista HLS", "disclaimer": "As descargas proveñen do provedor. sudo-flix non ten control sobre as descargas e a súa procedencia.", "downloadSubtitle": "Descargar subtítulos actuais", "downloadVideo": "Descargar video", @@ -282,6 +290,7 @@ "title": "Calidade" }, "settings": { + "audioItem": "Audio", "downloadItem": "Descargar", "enableSubtitles": "Activar subtítulos", "experienceSection": "Configuración de experiencia", @@ -308,8 +317,9 @@ "unknownOption": "Descoñecido" }, "subtitles": { - "customChoice": "Seleccionar subtítulos dende o arquivo", + "customChoice": "Sube ou arrastra o arquivo", "customizeLabel": "Personalizar", + "dropSubtitleFile": "Solta o arquivo de subtítulos aquí", "offChoice": "Apagar", "settings": { "backlink": "Subtítulos personalizados", @@ -524,6 +534,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Desenfoque do fondo", "backgroundLabel": "Opacidade do fondo", "colorLabel": "Cór", "previewQuote": "Non debo temer. O medo é o asasino da mente.", diff --git a/src/assets/locales/id.json b/src/assets/locales/id.json index f2ccc039..f9781682 100644 --- a/src/assets/locales/id.json +++ b/src/assets/locales/id.json @@ -4,7 +4,7 @@ "faqTitle": "Pertanyaan umum", "q1": { "body": "sudo-flix tidak menyimpan berkas media apapun. Ketika anda mengklik sesuatu untuk ditonton, aplikasi akan mencari berkas media di internet (saat media dimuat dan pada tab 'sumber media' anda dapat melihat sumber mana yang digunakan). sudo-flix tidak pernah mengunggah media apapun, semua media didapat melalui mekanisme pencarian di internet.", - "title": "Dari mana konten media di sini berasal?" + "title": "Dari mana konten berasal?" }, "q2": { "body": "Kami tidak menerima permintaan penambahan serial televisi atau film, sudo-flix tidak mengelola konten apapun. Semua konten ditonton melalui sumber-sumber dari internet.", @@ -26,24 +26,24 @@ "deviceNamePlaceholder": "Perangkat personal", "generate": { "description": "Kombinasi kata ini berfungsi sebagai nama pengguna sekaligus kata sandi anda. Pastikan untuk menyimpannya dengan aman karena anda memerlukannya untuk masuk ke akun anda", - "next": "Saya sudah menyimpan kombinasi kata di atas", + "next": "Saya sudah menyimpan kombinasi kata", "passphraseFrameLabel": "Kombinasi kata", - "title": "Kombinasi kata anda" + "title": "Kombinasi kata Anda" }, "hasAccount": "Sudah memiliki akun? <0>Masuk disini.", "login": { - "description": "Mohon masukkan kombinasi kata anda untuk masuk ke akun anda", + "description": "Mohon masukkan kombinasi kata anda untuk masuk ke akun Anda", "deviceLengthError": "Mohon masukkan nama perangkat", "passphraseLabel": "12 kombinasi kata unik", "passphrasePlaceholder": "Kombinasi kata", "submit": "Masuk", - "title": "Masuk ke akun anda", - "validationError": "Kombinasi kata unik salah" + "title": "Masuk ke akun Anda", + "validationError": "Kombinasi kata salah atau tidak lengkap" }, "register": { "information": { - "color1": "Gradasi warna profil pertama", - "color2": "Gradasi warna profil kedua", + "color1": "Warna profil pertama", + "color2": "Warna profil kedua", "header": "Masukkan nama perangkat anda lalu pilih warna latar belakang dan ikon pengguna yang ingin anda gunakan", "icon": "Ikon pengguna", "next": "Berikutnya", @@ -52,29 +52,31 @@ }, "trust": { "failed": { - "text": "Apakah anda mengkonfigurasi server dengan benar?", + "text": "Apakah Anda mengkonfigurasi server dengan benar?", "title": "Gagal terhubung dengan server" }, - "host": "Anda ingin terhubung ke <0>{{hostname}} - mohon konfirmasi anda mempercayai server ini sebelum anda membuat akun", + "host": "Anda ingin terhubung ke <0>{{hostname}} - mohon konfirmasi Anda mempercayai server ini sebelum Anda membuat akun", "no": "Kembali", - "title": "Apakah anda mempercayai server ini?", - "yes": "Saya percaya" + "noHost": "Server belum dikonfigurasi, maka dari itu Anda tidak dapat membuat akun", + "noHostTitle": "Server belum dikonfigurasi!", + "title": "Apakah Anda mempercayai server ini?", + "yes": "Saya percaya server ini" }, "verify": { - "description": "Mohon masukkan kombinasi kata pribadi anda sebelumnya untuk mengonfirmasi bahwa anda telah menyimpannya untuk melanjutkan proses pembuatan akun", + "description": "Mohon masukkan kombinasi kata pribadi Anda sebelumnya untuk mengonfirmasi bahwa Anda telah menyimpannya untuk melanjutkan proses pembuatan akun", "invalidData": "Data tidak valid", "noMatch": "Kombinasi kata tidak cocok", - "passphraseLabel": "12 kombinasi kata pribadi anda", + "passphraseLabel": "12 kombinasi kata Anda", "recaptchaFailed": "Validasi reCaptcha gagal", "register": "Buat akun", - "title": "Konfirmasi kombinasi kata pribadi anda" + "title": "Konfirmasi kombinasi kata Anda" } }, "errors": { "badge": "Terjadi masalah", - "details": "Detail eror", + "details": "Rincian kesalahan", "reloadPage": "Muat ulang halaman", - "showError": "Lihat detail eror", + "showError": "Lihat rincian kesalahan", "title": "Kami mengalami galat!" }, "footer": { @@ -87,7 +89,7 @@ "dmca": "DMCA", "github": "GitHub" }, - "tagline": "Tonton serial televisi dan film favorit anda dengan aplikasi streaming open source ini." + "tagline": "Tonton serial televisi dan film favorit anda dengan aplikasi streaming sumber terbuka ini." }, "global": { "name": "sudo-flix", @@ -95,6 +97,7 @@ "about": "Tentang", "dmca": "DMCA", "login": "Masuk", + "onboarding": "Penyiapan", "pagetitle": "{{title}} - sudo-flix", "register": "Daftar", "settings": "Pengaturan" @@ -108,7 +111,7 @@ "sectionTitle": "Lanjut menonton" }, "mediaList": { - "stopEditing": "Berhenti mengubah" + "stopEditing": "Berhenti menyunting" }, "search": { "allResults": "Hanya itu yang kami punya!", @@ -117,7 +120,12 @@ "noResults": "Kami tidak dapat menemukan apapun!", "placeholder": { "default": "Apa yang ingin anda tonton?", - "extra": [] + "extra": [ + "Apa yang ingin kamu jelajahi?", + "Ada apa di daftar tontonmu?", + "Apa film favoritmu?", + "Apa serial favoritmu?" + ] }, "sectionTitle": "Hasil pencarian" }, @@ -125,7 +133,7 @@ "day": { "default": "Apa yang ingin anda tonton sore ini?", "extra": [ - "Lagi pengen nonton genre Adventure? Jurassic Park mungkin cocok buat anda." + "Merasa suka bertualang? Jurassic Park mungkin pilihan cocok untuk Anda." ] }, "morning": { @@ -133,8 +141,8 @@ "extra": ["Kayaknya film Before Sunrise bagus deh"] }, "night": { - "default": "Apa yang ingin anda tonton malam ini?", - "extra": ["Capek? Katanya The Exocist rekomended."] + "default": "Apa yang ingin Anda tonton malam ini?", + "extra": ["Capek? Saya dengar The Exocist bagus."] } } }, @@ -143,11 +151,12 @@ "types": { "movie": "Film", "show": "Serial TV" - } + }, + "unreleased": "Belum dirilis" }, "navigation": { "banner": { - "offline": "Periksa koneksi internet anda" + "offline": "Periksa koneksi internet Anda" }, "menu": { "about": "Tentang kami", @@ -161,9 +170,69 @@ "notFound": { "badge": "Tidak ditemukan", "goHome": "Kembali", - "message": "Kami sudah mencari dimana-mana: di bawah tempat sampah, di lemari, di belakang server proxy, tapi tetap gagal menemukan halaman yang anda cari.", + "message": "Kami sudah mencari dimana-mana: di bawah tempat sampah, di lemari, di belakang server proxy, tetapi tidak dapat menemukan halaman yang Anda cari.", "title": "Gagal menemukan halaman" }, + "onboarding": { + "defaultConfirm": { + "cancel": "Batal", + "confirm": "Gunakan pengaturan bawaan", + "description": "Pengaturan bawaan tidak memiliki streaming terbaik dan bisa menjadi sangat lambat.", + "title": "Apa Anda yakin?" + }, + "extension": { + "back": "Kembali", + "explainer": "Menggunakan ekstensi browser, Anda dapat mendapatkan streaming terbaik yang kami tawarkan. Dengan instalasi sederhana.", + "explainerIos": "Sayangnya, ekstensi browser tidak didukung di iOS, Tekan Kembali untuk memilih opsi lain.", + "extensionHelp": "Jika Anda telah menginstal ekstensi tetapi tidak terdeteksi, buka ekstensi melalui menu ekstensi browser Anda dan ikuti instruksi di layar.", + "linkChrome": "Instal ekstensi Chrome", + "linkFirefox": "Instal ekstensi Firefox", + "notDetecting": "Terinstal di Chrome tetapi situs tidak mendeteksinya? Coba muat ulang halaman!", + "notDetectingAction": "Muat ulang halaman", + "status": { + "disallowed": "Ekstensi tidak diaktifkan untuk halaman ini", + "disallowedAction": "Aktifkan ekstensi", + "failed": "Gagal meminta status", + "loading": "Menunggu Anda menginstal ekstensi", + "outdated": "Versi ekstensi terlalu tua", + "success": "Ekstensi berkerja sesuai harapan!" + }, + "submit": "Lanjutkan", + "title": "Mari mulai dengan ekstensi" + }, + "proxy": { + "back": "Kembali", + "explainer": "Menggunakan metode proxy, Anda dapat mendapatkan streaming berkualitas baik dengan membuat layanan proxy mandiri.", + "input": { + "errorConnection": "Tidak dapat terhubung ke proxy", + "errorInvalidUrl": "URL tidak valid", + "errorNotProxy": "Mengharapkan proxy tapi menerima situs", + "label": "URL proxy", + "placeholder": "https://" + }, + "link": "Belajar cara membuat proxy", + "title": "Mari buat proxy baru" + }, + "start": { + "explainer": "Untuk mendapatkan streaming terbaik, Anda perlu memilih metode streaming yang Anda ingin gunakan.", + "options": { + "default": { + "text": "Saya tidak menginginkan streaming kualitas baik, <0 /> <1>gunakan pengaturan bawaan" + }, + "extension": { + "action": "Instal ekstensi", + "description": "Instal ekstensi browser dan dapatkan akses ke sumber terbaik.", + "quality": "Kualitas terbaik", + "title": "Ekstensi browser" + }, + "proxy": { + "action": "Atur proxy", + "description": "Atur proxy dalam hanya 5 menit dan dapatkan akses ke sumber terbaik.", + "quality": "Kualitas baik" + } + } + } + }, "overlays": { "close": "Tutup" }, @@ -177,12 +246,13 @@ }, "menus": { "downloads": { + "copyHlsPlaylist": "Salin tautan daftar putar HLS", "disclaimer": "Tautan unduhan diambil langsung dari penyedia pihak ketiga. Aplikasi ini tidak memiliki kendali bagaimana unduhan disediakan.", - "downloadSubtitle": "Unduh subtitle", + "downloadSubtitle": "Unduh subtitle saat ini", "downloadVideo": "Unduh media", - "hlsDisclaimer": "Tautan unduhan diambil langsung dari penyedia pihak ketiga. Aplikasi ini tidak memiliki kendali bagaimana unduhan disediakan. Harap diperhatikan, anda akan mengunduh HLS playlist, media ini hanya ditunjukan bagi pengguna tingkat lanjut.", + "hlsDisclaimer": "Unduhan didapatkan langsung dari penyedia. sudo-flix tidak memiliki kendali bagaimana unduan disediakan.

Harap diperhatikan bahwa Anda mengunduh daftar putar HLS, ini tidak direkomendasikan untuk diunduh jika Anda tidak terbiasa dengan format streaming tingkat lanjutCoba sumber berbeda untuk format berbeda.", "onAndroid": { - "1": "Untuk mengunduh di Android, klik tombol unduh, lalu di halaman baru klik dan tahan pada video, lalu pilih save.", + "1": "Untuk mengunduh di Android, klik tombol unduh, lalu di halaman baru klik dan tahan pada video, lalu pilih simpan.", "shortTitle": "Unduh / Android", "title": "Unduh di Android" }, @@ -200,11 +270,12 @@ }, "episodes": { "button": "Episode", - "emptyState": "Tidak ada episode di season ini, check lagi nanti!", + "emptyState": "Tidak ada episode di season ini, periksa kembali nanti!", "episodeBadge": "E{{episode}}", - "loadingError": "Eror memuat season", + "loadingError": "Gagal memuat season", "loadingList": "Memuat...", - "loadingTitle": "Memuat..." + "loadingTitle": "Memuat...", + "unairedEpisodes": "Satu atau lebih episode dalam season ini telah dinonaktifkan karena mereka belum ditayangkan." }, "playback": { "speedLabel": "Kecepatan pemutar", @@ -212,13 +283,13 @@ }, "quality": { "automaticLabel": "Otomatis", - "hint": "Anda dapat mencoba <0>mengganti sumber media untuk mendapatkan opsi kualitas yang berbeda.", - "iosNoQuality": "Karena keterbatasan dari Apple, opsi kualitas pada sumber ini tidak tersedia untuk iOS. Anda dapat mencoba <0>mengganti sumber media untuk mendapatkan opsi kualitas yang berbeda.", + "hint": "Anda dapat mencoba <0>mengganti sumber untuk mendapatkan opsi kualitas yang berbeda.", + "iosNoQuality": "Karena keterbatasan dari Apple, opsi kualitas pada sumber ini tidak tersedia untuk iOS. Anda dapat mencoba <0>mengganti sumber untuk mendapatkan opsi kualitas yang berbeda.", "title": "Kualitas" }, "settings": { "downloadItem": "Unduh", - "enableSubtitles": "Hidupkan subtitle", + "enableSubtitles": "Aktifkan subtitle", "experienceSection": "Pengaturan tambahan", "playbackItem": "Pengaturan pemutar", "qualityItem": "Kualitas", @@ -228,22 +299,22 @@ }, "sources": { "failed": { - "text": "Terjadi galat saat mencoba mencari media, mohon pilih sumber yang lain.", + "text": "Terjadi galat saat mencoba mencari media, mohon pilih sumber lain.", "title": "Gagal memuat data" }, "noEmbeds": { - "text": "Kami tidak dapat menemukan tautan, mohon pilih sumber yang lain.", + "text": "Kami tidak dapat menemukan tautan, mohon pilih sumber lain.", "title": "Tautan tidak ditemukan" }, "noStream": { - "text": "Sumber ini tidak memiliki media untuk film atau seri yang anda cari.", + "text": "Sumber ini tidak memiliki media untuk film atau seri yang Anda cari.", "title": "Tidak ada media" }, "title": "Sumber", "unknownOption": "Tidak diketahui" }, "subtitles": { - "customChoice": "Pilih subtitle dari file", + "customChoice": "Jatuhkan atau unggah berkas", "customizeLabel": "Sesuaikan", "offChoice": "Matikan", "settings": { diff --git a/src/assets/locales/it.json b/src/assets/locales/it.json index c4baa6a6..62ccbd48 100644 --- a/src/assets/locales/it.json +++ b/src/assets/locales/it.json @@ -138,15 +138,11 @@ }, "morning": { "default": "Cosa vorresti guardare questa mattina?", - "extra": [ - "Ho sentito che «Prima Dell'alba» è buono" - ] + "extra": ["Ho sentito che «Prima Dell'alba» è buono"] }, "night": { "default": "Cosa vorresti guardare questa sera?", - "extra": [ - "Stanco? Ho sentito che L'esorciccio è buono." - ] + "extra": ["Stanco? Ho sentito che L'esorciccio è buono."] } } }, @@ -155,7 +151,8 @@ "types": { "movie": "Film", "show": "Serie" - } + }, + "unreleased": "Inedito" }, "navigation": { "banner": { @@ -294,6 +291,7 @@ "title": "Qualità" }, "settings": { + "audioItem": "Audio", "downloadItem": "Scarica", "enableSubtitles": "Abilita i sottotitoli", "experienceSection": "Esperienza di visione", @@ -320,8 +318,9 @@ "unknownOption": "Sconosciuto" }, "subtitles": { - "customChoice": "Selezionare i sottotitoli dal file", + "customChoice": "Trascina o carica il file", "customizeLabel": "Personalizzare", + "dropSubtitleFile": "Trascina il file dei sottotitoli qui", "offChoice": "Spento", "settings": { "backlink": "Sottotitoli personalizzati", @@ -379,6 +378,13 @@ "title": "Impossibile riprodurre il video!" }, "scraping": { + "extensionFailure": { + "badge": "L'estensione è disabilitata", + "enableExtension": "Abilita l'estensione", + "homeButton": "Torna alla pagina iniziale", + "text": "Avete installato l'estensione sudo-flix. Per iniziare a usarla, è necessario abilitare l'estensione per questo sito.", + "title": "Abilita l'estensione" + }, "items": { "failure": "Si è verificato un errore", "notFound": "Non ha il video", diff --git a/src/assets/locales/nl.json b/src/assets/locales/nl.json index 1ef3c2ba..1c66e661 100644 --- a/src/assets/locales/nl.json +++ b/src/assets/locales/nl.json @@ -138,15 +138,11 @@ }, "morning": { "default": "Waar wil je deze ochtend naar kijken?", - "extra": [ - "Ik hoor dat Before Sunrise goed is" - ] + "extra": ["Ik hoor dat Before Sunrise goed is"] }, "night": { "default": "Wat wil je vanavond bekijken?", - "extra": [ - "Moe? Ik hoor dat The Exorcist goed is." - ] + "extra": ["Moe? Ik hoor dat The Exorcist goed is."] } } }, @@ -294,6 +290,7 @@ "title": "Kwaliteit" }, "settings": { + "audioItem": "Audio", "downloadItem": "Download", "enableSubtitles": "Ondertitels inschakelen", "experienceSection": "Kijk-ervaring", @@ -320,8 +317,9 @@ "unknownOption": "Onbekend" }, "subtitles": { - "customChoice": "Selecteer ondertiteling uit bestand", + "customChoice": "Sleep of upload bestand", "customizeLabel": "Aanpassen", + "dropSubtitleFile": "Sleep ondertitelbestand naar hier", "offChoice": "Uit", "settings": { "backlink": "Aangepaste ondertiteling", @@ -379,6 +377,13 @@ "title": "Oeps, hier ging iets mis!" }, "scraping": { + "extensionFailure": { + "badge": "Extensie uitgeschakeld", + "enableExtension": "Extensie inschakelen", + "homeButton": "Naar hoofdpagina", + "text": "Je hebt de sudo-flix extensie geïnstalleerd. Om deze te gebruiken, moet je de extensie inschakelen voor deze site.", + "title": "Activeer alstublieft de extensie" + }, "items": { "failure": "Daar ging iets mis", "notFound": "Er is geen video gevonden", diff --git a/src/assets/locales/pl.json b/src/assets/locales/pl.json index e9756b57..0c8c58ab 100644 --- a/src/assets/locales/pl.json +++ b/src/assets/locales/pl.json @@ -57,6 +57,8 @@ }, "host": "Łączysz się z <0>{{hostname}} - przed utworzeniem konta potwierdź że ufasz temu serwerowi", "no": "Wstecz", + "noHost": "Serwer nie został skonfigurowany, więc nie można utworzyć konta", + "noHostTitle": "Serwer nie skonfigurowany!", "title": "Ufasz temu serwerowi?", "yes": "Ufam temu serwerowi" }, @@ -117,7 +119,13 @@ "loading": "Wczytywanie...", "noResults": "Nie mogliśmy niczego znaleźć!", "placeholder": { - "default": "Co chciałbyś obejrzeć?" + "default": "Co chciałbyś obejrzeć?", + "extra": [ + "Co chcesz odkryć?", + "Co znajduje się na Twojej liście do obejrzenia?", + "Jaki jest twój ulubiony film?", + "Jaki jest twój ulubiony serial?" + ] }, "sectionTitle": "Wyniki wyszukiwania" }, @@ -130,15 +138,11 @@ }, "morning": { "default": "Co chciałbyś obejrzeć dziś rano?", - "extra": [ - "Słyszałem że „Przed wschodem słońca” jest dobre" - ] + "extra": ["Słyszałem że „Przed wschodem słońca” jest dobre"] }, "night": { "default": "Co chciałbyś obejrzeć dziś wieczorem?", - "extra": [ - "Zmęczony? Słyszałem że „Egzorcysta” jest dobry." - ] + "extra": ["Zmęczony? Słyszałem że „Egzorcysta” jest dobry."] } } }, @@ -182,7 +186,7 @@ "extensionHelp": "Jeżeli zainstalowałeś rozszerzenie, ale nie zostało ono wykryte, otwórz rozszerzenie za pomocą menu rozszerzeń przeglądarki i postępuj zgodnie z instrukcjami wyświetlanymi na ekranie.", "linkChrome": "Zainstaluj rozszerzenie na Chrome", "linkFirefox": "Zainstaluj rozszerzenie na Firefox", - "notDetecting": "Zainstalowano na Chrome, ale się nie wyświetla? Spróbuj odświeżyć stronę!", + "notDetecting": "Zainstalowano w Chrome, ale strona go nie wykrywa? Spróbuj odświeżyć stronę!", "notDetectingAction": "Odśwież stronę", "status": { "disallowed": "Rozszerzenie nie jest włączone dla tej strony", @@ -244,6 +248,7 @@ }, "menus": { "downloads": { + "copyHlsPlaylist": "Kopiuj link do listy odtwarzania HLS", "disclaimer": "Pliki do pobrania są pobierane bezpośrednio od dostawcy. sudo-flix nie ma kontroli nad sposobem dostarczania plików do pobrania.", "downloadSubtitle": "Pobierz aktualne napisy", "downloadVideo": "Pobierz wideo", @@ -285,6 +290,7 @@ "title": "Jakość" }, "settings": { + "audioItem": "Dźwięk", "downloadItem": "Pobierz", "enableSubtitles": "Włącz napisy", "experienceSection": "Odtwarzanie", @@ -311,8 +317,9 @@ "unknownOption": "Nieznany" }, "subtitles": { - "customChoice": "Wybierz napisy z pliku", + "customChoice": "Wrzuć lub prześlij plik", "customizeLabel": "Dostosuj", + "dropSubtitleFile": "Przeciągnij i upuść plik z napisami tutaj", "offChoice": "Wyłączone", "settings": { "backlink": "Własne napisy", diff --git a/src/assets/locales/pt-BR.json b/src/assets/locales/pt-BR.json index 6f7c76ea..58564616 100644 --- a/src/assets/locales/pt-BR.json +++ b/src/assets/locales/pt-BR.json @@ -57,6 +57,8 @@ }, "host": "Você está se conectando a <0>{{hostname}} - por favor, confirme se confia nele antes de criar uma conta", "no": "Voltar", + "noHost": "O servidor não foi configurado, portanto você não pode criar uma conta", + "noHostTitle": "Servidor não configurado!", "title": "Você confia neste servidor?", "yes": "Eu confio neste servidor" }, @@ -118,7 +120,12 @@ "noResults": "Não conseguimos encontrar nada!", "placeholder": { "default": "O que você quer assistir?", - "extra": [] + "extra": [ + "O que você gostaria de explorar?", + "O que está na sua lista para assistir?", + "Qual o seu filme favorito?", + "Qual a sua série favorita?" + ] }, "sectionTitle": "Resultados da pesquisa" }, @@ -144,7 +151,8 @@ "types": { "movie": "Filme", "show": "Série" - } + }, + "unreleased": "Não lançado" }, "navigation": { "banner": { @@ -283,6 +291,7 @@ "title": "Qualidade" }, "settings": { + "audioItem": "Áudio", "downloadItem": "Baixar", "enableSubtitles": "Ativar Legendas", "experienceSection": "Experiência de visualização", @@ -309,8 +318,9 @@ "unknownOption": "Desconhecido" }, "subtitles": { - "customChoice": "Selecione arquivo de legenda", + "customChoice": "Solte ou faça upload do arquivo", "customizeLabel": "Personalizar", + "dropSubtitleFile": "Solte o arquivo da legenda aqui", "offChoice": "Desativadas", "settings": { "backlink": "Legendas personalizadas", @@ -368,6 +378,13 @@ "title": "Falha ao reproduzir o vídeo!" }, "scraping": { + "extensionFailure": { + "badge": "Extensão desativada", + "enableExtension": "Ativar extensão", + "homeButton": "Ir para o início", + "text": "Você instalou a extensão sudo-flix. Para começar a usá-la, você precisa ativar a extensão neste site.", + "title": "Por favor, ative a extensão" + }, "items": { "failure": "Ocorreu um erro", "notFound": "Não tem o vídeo", @@ -525,6 +542,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Desfoque de fundo", "backgroundLabel": "Opacidade do fundo", "colorLabel": "Cor", "previewQuote": "Eu não devo ter medo. Medo é o assassino da mente.", diff --git a/src/assets/locales/ro.json b/src/assets/locales/ro.json index b8534893..75933a72 100644 --- a/src/assets/locales/ro.json +++ b/src/assets/locales/ro.json @@ -57,6 +57,8 @@ }, "host": "Vă conectați la <0>{{hostname}} - vă rugăm să confirmați că aveți încredere înainte de a vă crea un cont", "no": "Întoarce-te", + "noHost": "Serverul nu a fost configurat, deci nu vă puteți crea un cont", + "noHostTitle": "Serverul nu este configurat!", "title": "Ai încredere în acest server?", "yes": "Am încredere în acest server" }, @@ -79,6 +81,7 @@ }, "footer": { "legal": { + "disclaimer": "Declinare a răspunderii", "disclaimerText": "sudo-flix nu găzduiește niciun fișier, ci doar trimite la servicii terțe. Problemele juridice ar trebui abordate cu gazdele și furnizorii de fișiere. sudo-flix nu este responsabil pentru niciun fișier media afișat de furnizorii de video." }, "links": { @@ -94,6 +97,7 @@ "about": "Despre", "dmca": "DMCA", "login": "Log in", + "onboarding": "Configurație", "pagetitle": "{{title}} - sudo-flix", "register": "Inregistreaza-te", "settings": "Setări" @@ -116,7 +120,12 @@ "noResults": "Nu am putut găsi nimic!", "placeholder": { "default": "La ce dorești să te uiți?", - "extra": [] + "extra": [ + "Ce vrei să explorezi?", + "Ce e pe lista dvs. de urmărire?", + "Care e filmul tău preferat?", + "Care e serialul tău preferat?" + ] }, "sectionTitle": "Rezultate de căutare" }, @@ -163,6 +172,69 @@ "message": "Ne-am uitat peste tot: sub pubele, în dulap, În spatele proxy-ului dar din păcate nu am găsit pagina pe care dumneavoastră o căutați.", "title": "N-am putut găsi pagina" }, + "onboarding": { + "defaultConfirm": { + "cancel": "Anulare", + "confirm": "Folosește configurația implicită", + "description": "Configurația implicită nu are cele mai bune fluxuri și poate fi insuportabil de înceată.", + "title": "Sunteți sigur(ă)?" + }, + "extension": { + "back": "Înapoi", + "explainer": "Folosind această extensie de browser, puteți obține cele mai bune fluxuri pe care le avem de oferit. Cu doar o simplă instalare.", + "explainerIos": "Din păcate, extensia de browser nu e suportată pe iOS, Apăsați Înapoi pentru a alege altă opțiune.", + "extensionHelp": "Dacă ați instalat extensia dar nu e detectată, deschideți extensia din meniul extensiilor al browserului dvs. și urmăriți pașii de pe ecran.", + "linkChrome": "Instalare extensie pentru Chrome", + "linkFirefox": "Instalare extensie pentru Firefox", + "notDetecting": "Instalată pe Chrome dar site-ul nu o detectează? Încerați să reîmprospătați pagina!", + "notDetectingAction": "Reîncarcă pagina", + "status": { + "disallowed": "Extensia nu e activată pentru această pagină", + "disallowedAction": "Activare extensie", + "failed": "Nu s-a putut obține statusul", + "loading": "Așteptăm să vă instalați extensia", + "outdated": "Versiunea extensiei este prea veche", + "success": "Extensia funcționează conform așteptărilor!" + }, + "submit": "Continuare", + "title": "Să începem cu o extensie" + }, + "proxy": { + "back": "Înapoi", + "explainer": "Cu metoda proxy, puteți obține fluxuri de calitate prin a face un proxy cu autoservire.", + "input": { + "errorConnection": "Nu s-a putut conecta la proxy", + "errorInvalidUrl": "URL invalid", + "errorNotProxy": "Am așteptat un proxy dar am primit un site web", + "label": "URL-ul proxy-ului", + "placeholder": "https://" + }, + "link": "Învață cum se face un proxy", + "submit": "Validare proxy", + "title": "Să facem un proxy nou" + }, + "start": { + "explainer": "Pentru a obține cele mai bune fluxuri posibile, va trebui să alegeți ce metodă de streaming vreți să folosiți.", + "options": { + "default": { + "text": "Nu vreau fluxuri de calitate,<0 /> <1>folosește configurația implicită" + }, + "extension": { + "action": "Instalare extensie", + "description": "Instalați extensia browser și obțineți acces la cele mai bune surse.", + "quality": "Cea mai bună calitate", + "title": "Extensie browser" + }, + "proxy": { + "action": "Configurare proxy", + "description": "Configurați un proxy în doar 5 minute și obținți acces la resurse grozave.", + "quality": "Calitate bună", + "title": "Proxy personalizat" + } + }, + "title": "Hai să configurăm sudo-flix" + } + }, "overlays": { "close": "Închide" }, @@ -176,10 +248,11 @@ }, "menus": { "downloads": { + "copyHlsPlaylist": "Copiere link către lista de redare HLS", "disclaimer": "Descărcările sunt luate direct de la furnizor. sudo-flix nu are control cum descărcările sunt furnizate.", "downloadSubtitle": "Descărcați subtitlul curente", "downloadVideo": "Descarcă video", - "hlsDisclaimer": "Descărcările sunt preluate direct de la furnizor. sudo-flix nu are control asupra modului în care sunt furnizate descărcările. Vă rugăm să rețineți că descărcați o listă de redare HLS, aceasta este destinată utilizatorilor familiar cu streamingul avansat.", + "hlsDisclaimer": "Descărcările sunt preluate direct de la furnizor. sudo-flix nu are control asupra modului în care sunt furnizate descărcările.

Vă rugăm să rețineți că descărcați o listă de redare HLS, nu este recomandat să o descărcați dacă nu sunteți familiari cu formate avasate de streaming. Încercați surse diferite pentru formate diferte.", "onAndroid": { "1": "Pentru a descărca pe android, apăsați butonul de descărcare apoi în pagina nouă,apăsați și țineți pe video, apoi selectați salvează.", "shortTitle": "Descărcare / Android", @@ -236,8 +309,8 @@ "title": "Nu a fost găsită nicio încorporare" }, "noStream": { - "text": "Sursa asta nu are nicio sursă de streaming pentru filmul său spectacolul.", - "title": "Niciun stream" + "text": "Sursa aceasta nu are niciun flux pentru acest film sau serial.", + "title": "Niciun flux" }, "title": "Surse", "unknownOption": "Necunoscut" @@ -398,25 +471,50 @@ }, "connections": { "server": { - "description": "Dacă doriți să vă conectați la un backend personalizat pentru a vă stoca datele, activați acest lucru și furnizați adresa URL.", + "description": "Dacă doriți să vă conectați la un backend personalizat pentru a vă stoca datele, activați acest lucru și furnizați adresa URL. <0>Instrucțiuni.", "label": "Server personalizat", "urlLabel": "Adresa URL personalizată a serverului" }, "setup": { + "doSetup": "Configurează", "errorStatus": { + "description": "Se pare că unul sau mai multe obiecte din această configurație au nevoie de atenția ta.", "title": "Ceva are nevoie de atenția ta" + }, + "itemError": "Ceva nu e bine cu această setare. Parcurge configurația din nou pentru a o corecta.", + "items": { + "default": "Configurație implicită", + "extension": "Extensie", + "proxy": "Proxy personalizat" + }, + "redoSetup": "Refă configurația", + "successStatus": { + "description": "Toate sunt la locul lor ca să începeți să urmariți conținutul preferat.", + "title": "Totul este pregătit!" + }, + "unsetStatus": { + "description": "Apăsați butonul din dreapta pentru a începe procesul de configurare.", + "title": "Nu ați parcurs configurația" } }, "title": "Conexiuni", "workers": { "addButton": "Adaugă un nou muncitor", - "description": "Pentru ca aplicația să funcționeze, tot traficul este direcționat prin proxy. Activați acest lucru dacă doriți să vă aduceți proprii lucrători.", + "description": "Pentru ca aplicația să funcționeze, tot traficul este direcționat prin proxy. Activați acest lucru dacă doriți să vă aduceți proprii lucrători. <0>Instrucțiuni.", "emptyState": "Niciun muncitor incă, adaugă unu", "label": "Utilizați lucrători proxy personalizați", "urlLabel": "Adresele URL ale lucrătorilor", "urlPlaceholder": "https://" } }, + "preferences": { + "language": "Limba aplicației", + "languageDescription": "Limba aplicată întregii aplicații.", + "thumbnail": "Generați pictograme", + "thumbnailDescription": "De cele mai multe ori videoclipurile nu au pictograme. Puteți activa această setare pentru a le genera din mers, dar vă pot încetini videoclipul.", + "thumbnailLabel": "Generați pictograme", + "title": "Preferințe" + }, "reset": "Resetare", "save": "Salvează", "sidebar": { @@ -434,6 +532,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Blurarea fundalului", "backgroundLabel": "Opacitatea fundalului", "colorLabel": "Culoare", "previewQuote": "nu trebuie să mă tem. Frica este ucigașul minții.", diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 2d0bea4a..42a9704c 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -138,9 +138,7 @@ }, "morning": { "default": "Что бы вы хотели посмотреть этим утром?", - "extra": [ - "Слышали, что «Перед рассветом» – отличный фильм" - ] + "extra": ["Слышали, что «Перед рассветом» – отличный фильм"] }, "night": { "default": "Что бы вы хотели посмотреть этим вечером?", @@ -155,7 +153,8 @@ "types": { "movie": "Фильм", "show": "Сериал" - } + }, + "unreleased": "Ожидается" }, "navigation": { "banner": { @@ -294,6 +293,7 @@ "title": "Качество" }, "settings": { + "audioItem": "Аудио", "downloadItem": "Скачать", "enableSubtitles": "Включить субтитры", "experienceSection": "Впечатления от просмотра", @@ -320,8 +320,9 @@ "unknownOption": "Неизвестный" }, "subtitles": { - "customChoice": "Выбрать субтитры из файла", + "customChoice": "Перетащите файл или нажмите для загрузки", "customizeLabel": "Настроить", + "dropSubtitleFile": "Перетащите файл субтитров", "offChoice": "Выключить", "settings": { "backlink": "Пользовательские субтитры", @@ -379,6 +380,13 @@ "title": "Не удалось воспроизвести видео!" }, "scraping": { + "extensionFailure": { + "badge": "Расширение отключено", + "enableExtension": "Включить расширение", + "homeButton": "Вернуться на главную", + "text": "Вы установили расширение sudo-flix. Чтобы начать его использовать, необходимо включить расширение для этого сайта.", + "title": "Пожалуйста, включите расширение" + }, "items": { "failure": "Возникла ошибка", "notFound": "Такого видео нет", diff --git a/src/assets/locales/tr.json b/src/assets/locales/tr.json index 7fd0f0f5..88e27306 100644 --- a/src/assets/locales/tr.json +++ b/src/assets/locales/tr.json @@ -57,6 +57,8 @@ }, "host": "<0>{{hostname}} adlı sunucuya bağlanıyorsunuz - lütfen hesap oluşturmadan önce sunucuya güvendiğinizi onaylayın", "no": "Geri dön", + "noHost": "Sunucu henüz yapılandırılmadığı için hesap oluşturamazsınız", + "noHostTitle": "Sunucu kullanılamıyor!", "title": "Bu sunucuya güveniyor musunuz?", "yes": "Bu sunucuya güveniyorum" }, @@ -118,7 +120,12 @@ "noResults": "Hiçbir şey bulamadık!", "placeholder": { "default": "Ne izlemek istersiniz?", - "extra": [] + "extra": [ + "Ne keşfetmek istiyorsunuz?", + "İzleme listenizde neler var?", + "Favori filmin ne?", + "En sevdiğiniz dizi ne?" + ] }, "sectionTitle": "Arama sonuçları" }, @@ -144,7 +151,8 @@ "types": { "movie": "Film", "show": "Dizi" - } + }, + "unreleased": "Yayınlanmamış" }, "navigation": { "banner": { @@ -165,6 +173,69 @@ "message": "Her yere baktık: bazanın altına, dolabın içine hatta ara sunucuya ama maalesef aradığınız sayfayı bulamadık.", "title": "Sayfa bulunamadı" }, + "onboarding": { + "defaultConfirm": { + "cancel": "İptal Et", + "confirm": "Ön Tanımlı Ayarları Kullan", + "description": "Varsayılan ayarlar en iyi akış hizmetlerini sunmayabilir ve oldukça yavaş olabilir.", + "title": "Emin misiniz?" + }, + "extension": { + "back": "Geri Dön", + "explainer": "Tarayıcı uzantısını kullanarak, size sunduğumuz en iyi akışlara erişebilirsiniz. Kurulumu ise oldukça basit.", + "explainerIos": "Ne yazık ki, tarayıcı uzantısı iOS cihazlarında desteklenmemektedir. Geri Dön düğmesine basarak başka bir seçenek seçebilirsiniz.", + "extensionHelp": "Eklenti yüklediyseniz ancak algılamıyorsa, tarayıcınızın uzantı menüsünden eklentiyi açın ve ekran adımları takip edin.", + "linkChrome": "Chrome uzantısını yükleyin", + "linkFirefox": "Firefox uzantısını yükleyin", + "notDetecting": "Chrome'a yüklendi, ancak site algılamıyor mu? Sayfayı yenileyin!", + "notDetectingAction": "Sayfayı yenile", + "status": { + "disallowed": "Bu sayfa için uzantı etkinleştirilmemiş", + "disallowedAction": "Uzantıyı etkinleştir", + "failed": "Durum bilgisi alınamadı", + "loading": "Uzantıyı yüklemenizi bekliyoruz", + "outdated": "Uzantınız çok eski", + "success": "Uzantı sorunsuz çalışıyor!" + }, + "submit": "Devam Et", + "title": "Hadi bir uzantıyla başlayalım" + }, + "proxy": { + "back": "Geri Dön", + "explainer": "Ara sunucu yöntemiyle, yüksek kalitede yayınlara kolayca erişin.", + "input": { + "errorConnection": "Proxy'ye bağlanılamadı", + "errorInvalidUrl": "Geçerli bir URL değil", + "errorNotProxy": "Proxy bekleniyordu, web sitesine yönlendirildi", + "label": "Proxy URL", + "placeholder": "https://" + }, + "link": "Proxy oluşturmayı öğrenin", + "submit": "Proxy'yi Gönder", + "title": "Hadi yeni bir proxy oluşturalım" + }, + "start": { + "explainer": "En iyi akış deneyimi için kullanmak istediğiniz akış yöntemini seçmeniz gerekiyor.", + "options": { + "default": { + "text": "Yüksek kaliteli akış istemiyorum,<0 /> <1>varsayılan ayarı kullanın" + }, + "extension": { + "action": "Uzantıyı Yükle", + "description": "En iyi kaynaklara erişmek için tarayıcı uzantısını yükleyin.", + "quality": "En yüksek kalite", + "title": "Tarayıcı uzantısı" + }, + "proxy": { + "action": "Proxy'yi Kur", + "description": "Sadece 5 dakikada proxy kurun ve harika kaynaklara erişin.", + "quality": "İyi kalite", + "title": "Özel Proxy" + } + }, + "title": "sudo-flix ile sizi hazır hale getirelim" + } + }, "overlays": { "close": "Kapat" }, @@ -178,10 +249,11 @@ }, "menus": { "downloads": { + "copyHlsPlaylist": "HLS oynatma listesi bağlantısını kopyala", "disclaimer": "İndirme bağlantıları doğrudan sağlayıcının kendisinden alınır. sudo-flix'in sağlanan indirme bağlantıları üzerinde hiçbir konrolü yoktur.", "downloadSubtitle": "Geçerli altyazıyı indir", "downloadVideo": "Videoyu indir", - "hlsDisclaimer": "İndirme bağlantıları doğrudan sağlayıcının kendisinden alınır. sudo-flix'in sağlanan indirme bağlantıları üzerinde hiçbir konrolü yoktur. Lütfen bir HLS oynatma listesi indirdiğinizi unutmayın; bu, gelişmiş multimedya akışına aşina olan kullanıcılara yöneliktir.", + "hlsDisclaimer": "İndirmeler doğrudan sağlayıcıdan alınır. sudo-flix, indirmelerin nasıl sağlanacağı üzerinde kontrole sahip değildir.

Lütfen bir HLS oynatma listesi indirdiğinizi unutmayın; ileri seviye bilginiz yoksa indirmeniz önerilmez. akış biçimleri. Farklı formatlar için farklı kaynakları deneyin.", "onAndroid": { "1": "Android'e indirmek için önce indir butonuna basın, sonra açılan yeni sayfada video üzerine basılı tutun, ardından Videoyu indir seçeneğini seçin.", "shortTitle": "İndir / Android", @@ -219,6 +291,7 @@ "title": "Kalite" }, "settings": { + "audioItem": "Ses", "downloadItem": "İndir", "enableSubtitles": "Altyazıları Etkinleştir", "experienceSection": "İzleme deneyimi", @@ -245,8 +318,9 @@ "unknownOption": "Bilinmeyen" }, "subtitles": { - "customChoice": "Altyazı dosyası yükle", + "customChoice": "Dosya sürükleyin veya yükleyin", "customizeLabel": "Seçenekler", + "dropSubtitleFile": "Altyazı dosyasını buraya sürükleyin", "offChoice": "Kapat", "settings": { "backlink": "Kişisel altyazılar", @@ -262,6 +336,17 @@ "text": "API üstverisi yüklenemedi, lütfen internet bağlantınızı kontrol edin.", "title": "API üstverisi yüklenemedi" }, + "dmca": { + "badge": "Kaldırıldı", + "text": "Üzgünüz, bu içerik telif hakkı ihlali veya yayından kaldırma bildirimi nedeniyle kullanılamıyor.", + "title": "İçerik kaldırıldı" + }, + "extensionPermission": { + "badge": "İzin Gerekli", + "button": "Uzantıyı kullanın", + "text": "Tarayıcı uzantısını yüklemişsiniz, ancak uzantıyı kullanmaya başlamak için izninize ihtiyacımız var.", + "title": "Uzantıyı Kişiselleştir" + }, "failed": { "badge": "Başarısız oldu", "homeButton": "Ana sayfaya dön", @@ -293,6 +378,13 @@ "title": "Video oynatılamadı!" }, "scraping": { + "extensionFailure": { + "badge": "Eklenti devre dışı", + "enableExtension": "Eklentiyi etkinleştir", + "homeButton": "Eve git", + "text": "sudo-flix uzantısını kurdunuz. Kullanmaya başlamak için, uzantıyı bu site için etkinleştirmeniz gerekiyor.", + "title": "Lütfen eklentiyi etkinleştirin" + }, "items": { "failure": "Hata oluştu", "notFound": "Video mevcut değil", @@ -393,6 +485,28 @@ "label": "Özel sunucu", "urlLabel": "Özel sunucu URL'si" }, + "setup": { + "doSetup": "Başlayın", + "errorStatus": { + "description": "Kurulumda dikkat etmeniz gereken bir veya daha fazla öğe var gibi görünüyor.", + "title": "Dikkatinizi gerektiren bir şey var" + }, + "itemError": "Kurulum sırasında bir hata oluşmuş olabilir. Sorunu çözmek için kurulum adımlarını tekrar izleyin.", + "items": { + "default": "Varsayılan ayarlar", + "extension": "Tarayıcı uzantısı", + "proxy": "Özel Proxy" + }, + "redoSetup": "Kurulumu tekrar yapın", + "successStatus": { + "description": "Sevdiğiniz şeyleri izlemek için her şey hazır. Başlayın ve keyfini çıkarın.", + "title": "Tamam!" + }, + "unsetStatus": { + "description": "Kurulum sürecini başlatmak için lütfen sağdaki düğmeye tıklayın.", + "title": "Kurulumu tamamlamadınız" + } + }, "title": "Bağlantılar", "workers": { "addButton": "Yeni işleyici ekle", @@ -403,6 +517,14 @@ "urlPlaceholder": "https://" } }, + "preferences": { + "language": "Uygulama dili", + "languageDescription": "Uygulamanın tamamı için seçili dil", + "thumbnail": "Küçük resimler oluştur", + "thumbnailDescription": "Çoğu video için ön izleme görseli bulunmaz. Bu ayarı etkinleştirerek anında oluşturulmasını sağlayabilirsiniz, ancak bu videonuzu yavaşlatabilir.", + "thumbnailLabel": "Küçük resim oluştur", + "title": "Ayarlar" + }, "reset": "Sıfırla", "save": "Kaydet", "sidebar": { @@ -420,6 +542,7 @@ } }, "subtitles": { + "backgroundBlurLabel": "Arka plan bulanıklığı", "backgroundLabel": "Arka plan opaklığı", "colorLabel": "Renk", "previewQuote": "Korkmamalıyım. Korku aklın katilidir.", diff --git a/src/assets/locales/zh-Hant.json b/src/assets/locales/zh-Hant.json index d10e2e91..61cb97b4 100644 --- a/src/assets/locales/zh-Hant.json +++ b/src/assets/locales/zh-Hant.json @@ -1,6 +1,6 @@ { "about": { - "description": "sudo-flix 是一款在互聯網上搜尋流媒體的網路應用程式。團隊致力於讓使用者以最簡約的方式消費內容。", + "description": "sudo-flix 是一款在互聯網上搜尋串流媒體的網路應用程式。團隊致力於讓使用者以最簡約的方式觀看內容。", "faqTitle": "常見問題", "q1": { "body": "sudo-flix 不託管任何內容。您點選觀看內容時,系統均從互聯網搜尋(在加載提示頁和“視頻源”選項卡中,您可以看到正在使用的源)。媒體從未在 sudo-flix 中上傳,所有內容均通過搜索機制而得。", @@ -12,7 +12,7 @@ }, "q3": { "body": "我們的搜尋結果由電影資料庫(TMDB)驅動,無論視訊來源是否有對應內容,都會顯示結果。", - "title": "搜尋結果中已顯示了影視劇或其他節目,為何我無法播放?" + "title": "搜尋結果中已顯示了電視劇或其他節目,為何我無法播放?" }, "title": "關於 sudo-flix" }, @@ -22,18 +22,18 @@ }, "auth": { "createAccount": "還沒有帳戶? <0>建立一個", - "deviceNameLabel": "設備名稱", + "deviceNameLabel": "裝置名稱", "deviceNamePlaceholder": "我的手機", "generate": { "description": "您的密碼短語相當於使用者名稱與密碼。由於您需要輸入它來登入帳戶,請確保將其存放到安全位置", - "next": "我已儲存密碼短語", + "next": "我已經儲存密碼短語", "passphraseFrameLabel": "密碼短語", "title": "您的密碼短語" }, "hasAccount": "已經擁有帳戶? <0>點此登入。 ", "login": { "description": "請輸入密碼短語以登入您的帳戶", - "deviceLengthError": "請輸入設備名稱", + "deviceLengthError": "請輸入裝置名稱", "passphraseLabel": "12 字密碼短語", "passphrasePlaceholder": "密碼短語", "submit": "登入", @@ -57,6 +57,8 @@ }, "host": "您正在連線到 <0>{{hostname}} - 在建立帳戶之前,請確保您信任它", "no": "返回", + "noHost": "因為沒有配置伺服器,所以你不能夠創建帳戶", + "noHostTitle": "没有配置伺服器!", "title": "您是否信任這個伺服器?", "yes": "我信任這個伺服器" }, @@ -71,7 +73,7 @@ } }, "errors": { - "badge": "它已損壞", + "badge": "它壞了", "details": "錯誤詳情", "reloadPage": "重新加載頁面", "showError": "顯示錯誤詳情", @@ -87,7 +89,7 @@ "dmca": "DMCA", "github": "GitHub" }, - "tagline": "使用這個開源流媒體應用程序觀看您最喜歡的節目和電影。" + "tagline": "使用這個開源串流媒體應用程式觀看您最喜歡的節目和電影。" }, "global": { "name": "sudo-flix", @@ -118,7 +120,12 @@ "noResults": "我们找不到任何结果!", "placeholder": { "default": "您想看什麼?", - "extra": [] + "extra": [ + "你想探索什麼?", + "你的觀看清單有甚麼電影/電視劇?", + "你最喜愛的電影是甚麽?", + "你最喜愛的電視劇是甚麽?" + ] }, "sectionTitle": "搜索結果" }, @@ -133,7 +140,7 @@ }, "night": { "default": "您今晚想看什麼?", - "extra": ["疲倦了嗎?我聽說《驅魔人》不錯。"] + "extra": ["你疲倦嗎?我聽說《驅魔人》不錯。"] } } }, @@ -150,7 +157,7 @@ }, "menu": { "about": "關於我們", - "donation": "捐", + "donation": "捐錢", "logout": "登出", "register": "同步到雲端", "settings": "設定", @@ -167,32 +174,32 @@ "defaultConfirm": { "cancel": "取消", "confirm": "使用預設設置", - "description": "默認設置沒有最好的直播,並且可能慢得令人難以忍受。", + "description": "默認設置沒有最好的串流,並且可能慢得令人難以忍受。", "title": "您確定嗎?" }, "extension": { "back": "返回", - "explainer": "使用瀏覽器擴展程式,您可以獲得我們提供的最佳直播。只需簡單的安裝。", - "explainerIos": "不幸的是,iOS 不支援瀏覽器擴展程式,按 返回 選擇其他選項。", - "extensionHelp": "如果您已安裝該擴展程式,但未檢測到該擴展程式, 請通過瀏覽器的擴展程式功能表打開該擴展 程式 ,然後按照螢幕上的步驟操作。", - "linkChrome": "安裝 Chrome 擴展程式", - "linkFirefox": "安裝 Firefox 擴展程式", + "explainer": "使用瀏覽器擴充功能,您可以獲得我們提供的最佳直播。只需簡單的安裝。", + "explainerIos": "不幸的是,iOS 不支援瀏覽器擴充功能,按 返回 選擇其他選項。", + "extensionHelp": "如果您已安裝該擴充功能,但未檢測到該擴充功能, 請通過瀏覽器的擴充功能功能表打開該擴展 程式 ,然後按照螢幕上的步驟操作。", + "linkChrome": "安裝 Chrome 擴充功能", + "linkFirefox": "安裝 Firefox 擴充功能", "notDetecting": "安裝在 Chrome 上,但網站沒有檢測到它?嘗試重新載入頁面!", "notDetectingAction": "重新加載頁面", "status": { - "disallowed": "未為此頁面啟用擴展程式", - "disallowedAction": "啟用擴展程式", + "disallowed": "未為此頁面啟用瀏覽器擴充功能", + "disallowedAction": "啟用瀏覽器擴充功能", "failed": "無法請求狀態", - "loading": "等待您安裝擴展程式", - "outdated": "擴展程式版本太舊", - "success": "擴展程式正在按預期工作!" + "loading": "等待您安裝瀏覽器擴充功能", + "outdated": "瀏覽器擴充功能版本太舊", + "success": "瀏覽器擴充功能正在正常運作!" }, "submit": "繼續", - "title": "讓我們從擴展程式開始" + "title": "讓我們從瀏覽器擴充功能開始" }, "proxy": { "back": "返回", - "explainer": "使用代理伺服器,您可以通過製作自定代理伺服器來獲得高品質的直播。", + "explainer": "使用代理伺服器,您可以通過製作自定代理伺服器來獲得高品質的串流。", "input": { "errorConnection": "無法連接到代理伺服器", "errorInvalidUrl": "URL 無效", @@ -205,20 +212,20 @@ "title": "讓我們創建一個新的代理伺服器" }, "start": { - "explainer": "為了獲得最好的流媒體,您需要選擇您想使用的流媒體方法。", + "explainer": "為了獲得最好的串流媒體,您需要選擇您想使用的串流方法。", "options": { "default": { - "text": "我不想要高品質的流,<0 /> <1> 使用預設設置" + "text": "我不想要高品質的串流,<0 /> <1> 使用預設設置" }, "extension": { - "action": "安裝擴展程式", - "description": "安裝瀏覽器擴展程式並訪問最佳資源。", + "action": "安裝瀏覽器擴充功能", + "description": "安裝瀏覽器擴充功能來使用最佳資源。", "quality": "最好的品質", - "title": "瀏覽器擴展程式" + "title": "瀏覽器擴充功能" }, "proxy": { "action": "設置代理伺服器", - "description": "只需 5 分鐘即可設置代理伺服器並訪問優質資源。", + "description": "只需 5 分鐘即可設置代理伺服器並訪問優質來源。", "quality": "好品質", "title": "自訂代理伺服器" } @@ -235,11 +242,12 @@ "short": "後退" }, "casting": { - "enabled": "正在投放到設備…" + "enabled": "正在投放到裝置…" }, "menus": { "downloads": { - "disclaimer": "下載直接從供應商處獲取。sudo-flix 無法控制下載的提供方式。", + "copyHlsPlaylist": "複製 HLS 播放清單鏈接", + "disclaimer": "視頻直接從供應商處獲取。sudo-flix 無法控制下載的提供方式。", "downloadSubtitle": "下載當前字幕", "downloadVideo": "下載視頻", "hlsDisclaimer": "下載直接從供應商處獲取。sudo-flix 無法控制下載的提供方式。

請注意,您正在下載 HLS 播放清單, 如果您不熟悉高級流媒體格式,則不建議下載 。嘗試使用不同格式的不同來源。", @@ -261,10 +269,10 @@ "title": "下載" }, "episodes": { - "button": "分集", - "emptyState": "該季暫無分集,請稍後再來!", + "button": "集數", + "emptyState": "該季暫無集數,請稍後再來!", "episodeBadge": "E{{episode}}", - "loadingError": "加載分集時出錯", + "loadingError": "加載集數時出錯", "loadingList": "載入中...", "loadingTitle": "載入中...", "unairedEpisodes": "本季中的一集或多集已因尚未播出而被禁用。" @@ -276,7 +284,7 @@ "quality": { "automaticLabel": "自動品質", "hint": "您可以嘗試<0>切換源以獲得不同的質量選項。", - "iosNoQuality": "由於 Apple 定義的限制,此來源的品質選擇在 iOS 上不可用。您可以嘗試<0>切換到另一個來源以獲得不同的質量選項。", + "iosNoQuality": "由於 Apple 的限制,此來源的品質選擇在 iOS 上不可用。您可以嘗試<0>切換到另一個來源以獲得不同的質量選項。", "title": "品質" }, "settings": { @@ -330,9 +338,9 @@ }, "extensionPermission": { "badge": "缺少權限", - "button": "使用擴展程式", - "text": "您已安裝瀏覽器擴展,但我們需要您的許可才能啟用它。", - "title": "配置擴展程式" + "button": "使用瀏覽器擴充功能", + "text": "您已安裝瀏覽器擴展功能,但我們需要您的許可才能啟用它。", + "title": "配置瀏覽器擴充功能" }, "failed": { "badge": "失敗", @@ -368,7 +376,7 @@ "items": { "failure": "發生錯誤", "notFound": "沒有視頻", - "pending": "檢查影片..." + "pending": "尋找影片中..." }, "notFound": { "badge": "未找到", @@ -386,9 +394,9 @@ }, "turnstile": { "description": "請通過右側的驗證碼來確認您是人類。這是為了保護 sudo-flix 的安全!", - "error": "無法驗證您的人類身份。請再試一次。", + "error": "無法驗證您是一個人類。請再試一次。", "title": "我們需要驗證您是否為人類。", - "verifyingHumanity": "正在驗證您的人類身份..." + "verifyingHumanity": "正在驗證您是不是一個人類..." } }, "screens": { @@ -430,7 +438,7 @@ }, "devices": { "deviceNameLabel": "設備名稱", - "failed": "無法載入階段", + "failed": "無法載入", "removeDevice": "刪除", "title": "設備" }, @@ -503,7 +511,7 @@ "thumbnail": "生成縮圖", "thumbnailDescription": "大多數時候,視頻沒有縮圖。您可以啟用此設置以即時生成它們,但它們會使您的視頻變慢。", "thumbnailLabel": "生成縮圖", - "title": "偏好" + "title": "偏好設定" }, "reset": "重置", "save": "保存", @@ -516,12 +524,13 @@ "insecure": "不安全", "notLoggedIn": "您尚未登錄", "secure": "安全", - "title": "應用資訊", + "title": "應用程式的資訊", "unknownVersion": "未知", "userId": "使用者ID" } }, "subtitles": { + "backgroundBlurLabel": "背景模糊", "backgroundLabel": "背景不透明度", "colorLabel": "顏色", "previewQuote": "我絕不能害怕。 恐懼會扼殺思維能力。", diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index c280f9bd..bf0e3253 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -9,6 +9,7 @@ import { ExtensionMakeRequestResponse } from "@/backend/extension/plasmo"; export const RULE_IDS = { PREPARE_STREAM: 1, SET_DOMAINS_HLS: 2, + SET_DOMAINS_HLS_AUDIO: 3, }; // for some reason, about 500 ms is needed after diff --git a/src/backend/metadata/getmeta.ts b/src/backend/metadata/getmeta.ts index 3839d0f9..cfb34b91 100644 --- a/src/backend/metadata/getmeta.ts +++ b/src/backend/metadata/getmeta.ts @@ -43,7 +43,7 @@ export function formatTMDBMetaResult( title: movie.title, object_type: mediaTypeToTMDB(type), poster: getMediaPoster(movie.poster_path) ?? undefined, - original_release_year: new Date(movie.release_date).getFullYear(), + original_release_date: new Date(movie.release_date), }; } if (type === MWMediaType.SERIES) { @@ -58,7 +58,7 @@ export function formatTMDBMetaResult( title: v.name, })), poster: getMediaPoster(show.poster_path) ?? undefined, - original_release_year: new Date(show.first_air_date).getFullYear(), + original_release_date: new Date(show.first_air_date), }; } diff --git a/src/backend/metadata/tmdb.ts b/src/backend/metadata/tmdb.ts index ddd484ca..a8cbe002 100644 --- a/src/backend/metadata/tmdb.ts +++ b/src/backend/metadata/tmdb.ts @@ -66,7 +66,7 @@ export function formatTMDBMeta( return { title: media.title, id: media.id.toString(), - year: media.original_release_year?.toString(), + year: media.original_release_date?.getFullYear()?.toString(), poster: media.poster, type, seasons: seasons as any, @@ -94,7 +94,8 @@ export function formatTMDBMetaToMediaItem(media: TMDBMediaResult): MediaItem { return { title: media.title, id: media.id.toString(), - year: media.original_release_year ?? 0, + year: media.original_release_date?.getFullYear() ?? 0, + release_date: media.original_release_date, poster: media.poster, type, }; @@ -260,7 +261,7 @@ export function formatTMDBSearchResult( title: show.name, poster: getMediaPoster(show.poster_path), id: show.id, - original_release_year: new Date(show.first_air_date).getFullYear(), + original_release_date: new Date(show.first_air_date), object_type: mediatype, }; } @@ -271,7 +272,7 @@ export function formatTMDBSearchResult( title: movie.title, poster: getMediaPoster(movie.poster_path), id: movie.id, - original_release_year: new Date(movie.release_date).getFullYear(), + original_release_date: new Date(movie.release_date), object_type: mediatype, }; } diff --git a/src/backend/metadata/types/tmdb.ts b/src/backend/metadata/types/tmdb.ts index 1071d96c..5d082f55 100644 --- a/src/backend/metadata/types/tmdb.ts +++ b/src/backend/metadata/types/tmdb.ts @@ -20,7 +20,7 @@ export type TMDBMediaResult = { title: string; poster?: string; id: number; - original_release_year?: number; + original_release_date?: Date; object_type: TMDBContentTypes; seasons?: TMDBSeasonShort[]; }; diff --git a/src/components/media/MediaCard.tsx b/src/components/media/MediaCard.tsx index cad3ae6a..17ada085 100644 --- a/src/components/media/MediaCard.tsx +++ b/src/components/media/MediaCard.tsx @@ -1,4 +1,5 @@ import classNames from "classnames"; +import { useCallback } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; @@ -24,6 +25,20 @@ export interface MediaCardProps { onClose?: () => void; } +function checkReleased(media: MediaItem): boolean { + const isReleasedYear = Boolean( + media.year && media.year <= new Date().getFullYear(), + ); + const isReleasedDate = Boolean( + media.release_date && media.release_date <= new Date(), + ); + + // If the media has a release date, use that, otherwise use the year + const isReleased = media.release_date ? isReleasedDate : isReleasedYear; + + return isReleased; +} + function MediaCardContent({ media, linkable, @@ -35,10 +50,19 @@ function MediaCardContent({ const { t } = useTranslation(); const percentageString = `${Math.round(percentage ?? 0).toFixed(0)}%`; - const canLink = linkable && !closable; + const isReleased = useCallback(() => checkReleased(media), [media]); + + const canLink = linkable && !closable && isReleased(); const dotListContent = [t(`media.types.${media.type}`)]; - if (media.year) dotListContent.push(media.year.toFixed()); + + if (media.year) { + dotListContent.push(media.year.toFixed()); + } + + if (!isReleased()) { + dotListContent.push(t("media.unreleased")); + } return (
; - const canLink = props.linkable && !props.closable; + const isReleased = useCallback( + () => checkReleased(props.media), + [props.media], + ); + + const canLink = props.linkable && !props.closable && isReleased(); let link = canLink ? `/media/${encodeURIComponent(mediaItemToId(props.media))}` @@ -157,7 +186,7 @@ export function MediaCard(props: MediaCardProps) { } } - if (!props.linkable) return {content}; + if (!canLink) return {content}; return ( s.setShouldStartFromBeginning, ); + const updateItem = useProgressStore((s) => s.updateItem); let show = false; if (showingState === "always") show = true; @@ -78,7 +80,19 @@ export function NextEpisodeButton(props: { setShouldStartFromBeginning(true); setDirectMeta(metaCopy); props.onChange?.(metaCopy); - }, [setDirectMeta, nextEp, meta, props, setShouldStartFromBeginning]); + const defaultProgress = { duration: 0, watched: 0 }; + updateItem({ + meta: metaCopy, + progress: defaultProgress, + }); + }, [ + setDirectMeta, + nextEp, + meta, + props, + setShouldStartFromBeginning, + updateItem, + ]); const startCurrentEpisodeFromBeginning = useCallback(() => { if (!meta || !meta.episode) return; @@ -88,6 +102,8 @@ export function NextEpisodeButton(props: { props.onChange?.(metaCopy); }, [setDirectMeta, meta, props, setShouldStartFromBeginning]); + // TODO: If the type is a movie add a Go home button instead! + if (!meta?.episode || !nextEp) return null; if (metaType !== "show") return null; diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts index 8e155f69..8322b82b 100644 --- a/src/components/player/display/base.ts +++ b/src/components/player/display/base.ts @@ -191,6 +191,21 @@ export function makeVideoElementDisplayInterface(): DisplayInterface { }, }); }); + hls.on(Hls.Events.AUDIO_TRACK_LOADED, async (_, data) => { + const chunkUrlsDomains = data.details.fragments.map( + (v) => new URL(v.url).hostname, + ); + const chunkUrls = [...new Set(chunkUrlsDomains)]; + + await setDomainRule({ + ruleId: RULE_IDS.SET_DOMAINS_HLS_AUDIO, + targetDomains: chunkUrls, + requestHeaders: { + ...src.preferredHeaders, + ...src.headers, + }, + }); + }); } }); hls.on(Hls.Events.LEVEL_SWITCHED, () => { diff --git a/src/hooks/useRandomTranslation.ts b/src/hooks/useRandomTranslation.ts index 4351ffad..50d78aee 100644 --- a/src/hooks/useRandomTranslation.ts +++ b/src/hooks/useRandomTranslation.ts @@ -1,8 +1,8 @@ import { useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; -// 10% chance of getting a joke title -const shouldGiveJokeTitle = () => Math.floor(Math.random() * 10) === 0; +// 35% chance of getting a joke title (Cooper done changed this code!) +const shouldGiveJokeTitle = () => Math.random() < 0.35; export function useRandomTranslation() { const { t } = useTranslation(); diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index b6bf4fc4..523adaa7 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -36,6 +36,7 @@ import { useSubtitleStore } from "@/stores/subtitles"; import { usePreviewThemeStore, useThemeStore } from "@/stores/theme"; import { SubPageLayout } from "./layouts/SubPageLayout"; +import { AdminPanelPart } from "./parts/settings/AdminPanel"; import { PreferencesPart } from "./parts/settings/PreferencesPart"; function SettingsLayout(props: { children: React.ReactNode }) { @@ -260,6 +261,9 @@ export function SettingsPage() { )}
+
+ +
+
+

+

{props.name}

+

+

{props.children}

+
+ + + ); +} + +async function getTopSources() { + const response = await fetch(`${BACKEND_URL}/metrics`); + const text = await response.text(); + + const regex = + /mw_provider_status_count{provider_id="([^"]+)",status="([^"]+)"} (\d+)/g; + let match = regex.exec(text); + const items: { [key: string]: any } = {}; + + while (match !== null) { + const [_, providerId, status, count] = match; + if (items[providerId]) { + items[providerId].count += parseInt(count, 10); + } else { + items[providerId] = { + providerId, + status, + count: parseInt(count, 10), + }; + } + match = regex.exec(text); + } + + if (Object.keys(items).length > 0) { + return Object.values(items); + } + throw new Error("RECENT_PLAYED_ITEMS not found"); +} + +export function TopSources() { + const [recentPlayedItems, setRecentPlayedItems] = useState([]); + const [failStatusCount, setFailStatusCount] = useState(0); + const [successStatusCount, setSuccessStatusCount] = useState(0); + const navigate = useNavigate(); + + useEffect(() => { + getTopSources() + .then((items) => { + const limitedItems = items.filter( + (item, index, self) => + index === self.findIndex((t2) => t2.providerId === item.providerId), + ); + setRecentPlayedItems(limitedItems); + + // Calculate fail and success status counts + const failCount = limitedItems.reduce( + (acc, item) => + item.status === "failed" || item.status === "notfound" + ? acc + parseInt(item.count, 10) + : acc, + 0, + ); + const successCount = limitedItems.reduce( + (acc, item) => + item.status === "success" ? acc + parseInt(item.count, 10) : acc, + 0, + ); + setFailStatusCount(failCount.toLocaleString()); + setSuccessStatusCount(successCount.toLocaleString()); + }) + .catch((error) => { + console.error("Error fetching recent played items:", error); + }); + }, []); + + function getItemsForCurrentPage() { + const sortedItems = recentPlayedItems.sort((a, b) => b.count - a.count); + + return sortedItems.map((item, index) => ({ + ...item, + rank: index + 1, + })); + } + + return ( + + + +
+ Top sources + + The most used providers on sudo-flix.lol, this data is fetched from + the current backend deployment too. + +
+
+
+

+ Fail Count: {failStatusCount} +

+
+
+

+ Success Count: {successStatusCount} +

+
+
+
+ +
+
+
+ +
+ + {getItemsForCurrentPage().map((item) => { + return ( + + {`Requests: `} + {parseInt(item.count, 10).toLocaleString()} + + ); + })} +
+
+
+ ); +} diff --git a/src/pages/parts/admin/ConfigValuesPart.tsx b/src/pages/parts/admin/ConfigValuesPart.tsx index dce783b2..74372361 100644 --- a/src/pages/parts/admin/ConfigValuesPart.tsx +++ b/src/pages/parts/admin/ConfigValuesPart.tsx @@ -3,9 +3,10 @@ import { ReactNode, useEffect, useState } from "react"; import { Divider } from "@/components/utils/Divider"; import { Heading2 } from "@/components/utils/Text"; import { conf } from "@/setup/config"; +import { BACKEND_URL } from "@/setup/constants"; async function getAccountNumber() { - const response = await fetch("https://backend.sudo-flix.lol/metrics"); + const response = await fetch(`${BACKEND_URL}/metrics`); const text = await response.text(); // Adjusted regex to match any hostname @@ -26,7 +27,7 @@ async function getAccountNumber() { } async function getAllAccounts() { - const response = await fetch("https://backend.sudo-flix.lol/metrics"); + const response = await fetch(`${BACKEND_URL}/metrics`); const text = await response.text(); const regex = /mw_user_count{namespace="movie-web"} (\d+)/; diff --git a/src/pages/parts/settings/AdminPanel.tsx b/src/pages/parts/settings/AdminPanel.tsx new file mode 100644 index 00000000..1f656439 --- /dev/null +++ b/src/pages/parts/settings/AdminPanel.tsx @@ -0,0 +1,30 @@ +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; + +import { Button } from "@/components/buttons/Button"; +import { SolidSettingsCard } from "@/components/layout/SettingsCard"; +import { Heading3 } from "@/components/utils/Text"; + +export function AdminPanelPart() { + const { t } = useTranslation(); + const navigate = useNavigate(); + + return ( +
+ +
+ {t("settings.account.admin.title")} +

{t("settings.account.admin.text")}

+
+
+ +
+
+
+ ); +} diff --git a/src/setup/App.tsx b/src/setup/App.tsx index 9d54fbd7..25309e21 100644 --- a/src/setup/App.tsx +++ b/src/setup/App.tsx @@ -89,7 +89,7 @@ function QueryView() { function App() { useHistoryListener(); useOnlineListener(); - const maintenance = false; // Changing to true shows maintenance page + const maintenance = false; // Shows maintance page const [showDowntime, setShowDowntime] = useState(maintenance); const handleButtonClick = () => { diff --git a/src/stores/banner/BannerLocation.tsx b/src/stores/banner/BannerLocation.tsx index 3162e768..4b7fed61 100644 --- a/src/stores/banner/BannerLocation.tsx +++ b/src/stores/banner/BannerLocation.tsx @@ -87,8 +87,8 @@ export function ExtensionBanner(props: { if (currentLocation !== loc || pathname === "/onboarding/extension") return null; - // Show the banner with a 35% chance or not if users dont meet requirements - if (!isEligible && Math.random() < 0.35) { + // Show the banner with a 36.5% chance or not if users dont meet requirements + if (!isEligible && Math.random() < 0.365) { let bannerText = ""; switch (props.extensionState) { case "noperms": diff --git a/src/stores/player/utils/qualities.ts b/src/stores/player/utils/qualities.ts index afd90d25..5531fc63 100644 --- a/src/stores/player/utils/qualities.ts +++ b/src/stores/player/utils/qualities.ts @@ -38,7 +38,7 @@ const qualitySorting: Record = { "480": 20, "720": 30, "1080": 40, - "4k": 25, // 4k has lower priority, you need faster internet for it + "4k": 35, // 4k has lower priority, you need faster internet for it }; const sortedQualities: SourceQuality[] = Object.entries(qualitySorting) .sort((a, b) => b[1] - a[1]) diff --git a/src/stores/progress/utils.ts b/src/stores/progress/utils.ts index 9a439141..6ea09462 100644 --- a/src/stores/progress/utils.ts +++ b/src/stores/progress/utils.ts @@ -46,6 +46,15 @@ function progressIsAcceptableRange(duration: number, watched: number): boolean { return true; } +function isFirstEpisodeOfShow( + item: ProgressMediaItem, + episode: ProgressEpisodeItem, +): boolean { + const seasonId = episode.seasonId; + const season = item.seasons[seasonId]; + return season.number === 1 && episode.number === 1; +} + export function shouldShowProgress( item: ProgressMediaItem, ): ShowProgressResult { @@ -66,8 +75,10 @@ export function shouldShowProgress( .sort((a, b) => b.updatedAt - a.updatedAt) .filter( (epi) => - !progressIsNotStarted(epi.progress.duration, epi.progress.watched), + !progressIsNotStarted(epi.progress.duration, epi.progress.watched) || + !isFirstEpisodeOfShow(item, epi), )[0]; + const season = item.seasons[ep?.seasonId]; if (!ep || !season) return { diff --git a/src/utils/mediaTypes.ts b/src/utils/mediaTypes.ts index f577ca5f..c81b1ac0 100644 --- a/src/utils/mediaTypes.ts +++ b/src/utils/mediaTypes.ts @@ -2,6 +2,7 @@ export interface MediaItem { id: string; title: string; year?: number; + release_date?: Date; poster?: string; type: "show" | "movie"; }