Merge pull request #1940 from syeopite/instance-redirect-button

Add instance redirects!
This commit is contained in:
TheFrenchGhosty 2021-06-19 11:35:40 +00:00 committed by GitHub
commit 00425670d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 567 additions and 158 deletions

View File

@ -86,6 +86,8 @@
"dark": "غامق (اسود)",
"light": "فاتح (ابيض)",
"Thin mode: ": "الوضع الخفيف: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "تفضيلات الإشتراك",
"Show annotations by default for subscribed channels: ": "عرض الملاحظات في الفيديوهات تلقائيا في القنوات المشترك بها فقط: ",
"Redirect homepage to feed: ": "إعادة التوجية من الصفحة الرئيسية لصفحة المشتركين (لرؤية اخر فيديوهات المشتركين): ",
@ -161,6 +163,8 @@
"Show more": "أظهر المزيد",
"Show less": "عرض اقل",
"Watch on YouTube": "مشاهدة الفيديو على اليوتيوب",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "إخفاء الملاحظات فى الفيديو",
"Show annotations": "عرض الملاحظات فى الفيديو",
"Genre: ": "النوع: ",
@ -415,5 +419,8 @@
"location": "الاماكن",
"hdr": "وضع التباين العالي",
"filter": "معامل الفرز",
"Current version: ": "الإصدار الحالي: "
"Current version: ": "الإصدار الحالي: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -80,6 +80,8 @@
"dark": "",
"light": "",
"Thin mode: ": "",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "",
"Show annotations by default for subscribed channels: ": "",
"Redirect homepage to feed: ": "",
@ -149,6 +151,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "",
"Show annotations": "",
"Genre: ": "",
@ -354,5 +358,8 @@
"Videos": "",
"Playlists": "",
"Community": "",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "tmavý",
"light": "světlý",
"Thin mode: ": "Kompaktní režim: ",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "Nastavení předplatných",
"Show annotations by default for subscribed channels: ": "Ve výchozím nastavení zobrazovat poznámky u odebíraných kanálů: ",
"Redirect homepage to feed: ": "Přesměrovávat domovskou stránku na informační kanál: ",
@ -161,6 +163,8 @@
"Show more": "Zobrazit více",
"Show less": "Zobrazit méně",
"Watch on YouTube": "Sledovat na YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Skrýt vysvětlivky",
"Show annotations": "Zobrazit vysvětlivky",
"Genre: ": "Žánr: ",
@ -415,5 +419,8 @@
"location": "umístění",
"hdr": "HDR",
"filter": "filtr",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "mørk",
"light": "lys",
"Thin mode: ": "Tynd tilstand: ",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "Abonnements præferencer",
"Show annotations by default for subscribed channels: ": "Vis annotationer som standard for abonnerede kanaler: ",
"Redirect homepage to feed: ": "Omdiriger startside til feed: ",
@ -161,6 +163,8 @@
"Show more": "Vis mere",
"Show less": "Vis mindre",
"Watch on YouTube": "Se på YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Skjul annotationer",
"Show annotations": "Vis annotationer",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "Nachtmodus",
"light": "heller Modus",
"Thin mode: ": "Schlanker Modus: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Abonnementeinstellungen",
"Show annotations by default for subscribed channels: ": "Anmerkungen für abonnierte Kanäle standardmäßig anzeigen? ",
"Redirect homepage to feed: ": "Startseite zu Feed umleiten: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Video auf YouTube ansehen",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Anmerkungen ausblenden",
"Show annotations": "Anmerkungen anzeigen",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "Standort",
"hdr": "HDR",
"filter": "Filtern",
"Current version: ": "Aktuelle Version: "
"Current version: ": "Aktuelle Version: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "σκοτεινό",
"light": "φωτεινό",
"Thin mode: ": "Ελαφριά λειτουργία: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Προτιμήσεις συνδρομών",
"Show annotations by default for subscribed channels: ": "Προβολή σημειώσεων μόνο για κανάλια στα οποία είστε συνδρομητής; ",
"Redirect homepage to feed: ": "Ανακατεύθυνση αρχικής στη ροή συνδρομών: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Προβολή στο YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Απόκρυψη σημειώσεων",
"Show annotations": "Προβολή σημειώσεων",
"Genre: ": "Είδος: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Τρέχουσα έκδοση: "
"Current version: ": "Τρέχουσα έκδοση: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "dark",
"light": "light",
"Thin mode: ": "Thin mode: ",
"Miscellaneous preferences": "Miscellaneous preferences",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "Automaticatic instance redirection (fallback to redirect.invidious.io): ",
"Subscription preferences": "Subscription preferences",
"Show annotations by default for subscribed channels: ": "Show annotations by default for subscribed channels? ",
"Redirect homepage to feed: ": "Redirect homepage to feed: ",
@ -161,6 +163,8 @@
"Show more": "Show more",
"Show less": "Show less",
"Watch on YouTube": "Watch on YouTube",
"Switch Invidious Instance": "Switch Invidious Instance",
"Broken? Try another Invidious Instance": "Broken? Try another Invidious Instance",
"Hide annotations": "Hide annotations",
"Show annotations": "Show annotations",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "Location",
"hdr": "HDR",
"filter": "Filter",
"Current version: ": "Current version: "
"Current version: ": "Current version: ",
"next_steps_error_message": "After which you should try to: ",
"next_steps_error_message_refresh": "Refresh",
"next_steps_error_message_go_to_youtube": "Go to Youtube"
}

View File

@ -86,6 +86,8 @@
"dark": "malhela",
"light": "hela",
"Thin mode: ": "Maldika reĝimo: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Abonaj agordoj",
"Show annotations by default for subscribed channels: ": "Ĉu montri prinotojn defaŭlte por abonitaj kanaloj? ",
"Redirect homepage to feed: ": "Alidirekti hejmpâgon al fluo: ",
@ -161,6 +163,8 @@
"Show more": "Montri pli",
"Show less": "Montri malpli",
"Watch on YouTube": "Vidi filmeton en JuTubo",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Kaŝi prinotojn",
"Show annotations": "Montri prinotojn",
"Genre: ": "Ĝenro: ",
@ -415,5 +419,8 @@
"location": "loko",
"hdr": "granddinamikgama",
"filter": "filtri",
"Current version: ": "Nuna versio: "
"Current version: ": "Nuna versio: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "oscuro",
"light": "claro",
"Thin mode: ": "Modo compacto: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferencias de la suscripción",
"Show annotations by default for subscribed channels: ": "¿Mostrar anotaciones por defecto para los canales suscritos? ",
"Redirect homepage to feed: ": "Redirigir la página de inicio a la fuente: ",
@ -161,6 +163,8 @@
"Show more": "Mostrar más",
"Show less": "Mostrar menos",
"Watch on YouTube": "Ver el vídeo en Youtube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Ocultar anotaciones",
"Show annotations": "Mostrar anotaciones",
"Genre: ": "Género: ",
@ -415,5 +419,8 @@
"location": "ubicación",
"hdr": "hdr",
"filter": "filtro",
"Current version: ": "Versión actual: "
"Current version: ": "Versión actual: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -77,6 +77,8 @@
"dark": "iluna",
"light": "argia",
"Thin mode: ": "",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "Harpidetzen hobespenak",
"Show annotations by default for subscribed channels: ": "",
"Redirect homepage to feed: ": "",
@ -143,6 +145,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "",
"Show annotations": "",
"Genre: ": "",
@ -337,5 +341,8 @@
"Videos": "",
"Playlists": "",
"Community": "",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "تاریک",
"light": "روشن",
"Thin mode: ": "حالت نازک: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "ترجیحات اشتراک",
"Show annotations by default for subscribed channels: ": "نمایش حاشیه نویسی ها به طور پیشفرض برای کانال های مشترک شده: ",
"Redirect homepage to feed: ": "تغییر مسیر صفحه خانه به خوراک: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "تماشا در یوتیوب",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "مخفی کردن حاشیه نویسی ها",
"Show annotations": "نمایش حاشیه نویسی ها",
"Genre: ": "ژانر: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "نسخه فعلی: "
"Current version: ": "نسخه فعلی: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "tumma",
"light": "vaalea",
"Thin mode: ": "Kapea tila ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Tilausten asetukset",
"Show annotations by default for subscribed channels: ": "Näytä oletuksena tilattujen kanavien huomautukset: ",
"Redirect homepage to feed: ": "Uudelleenohjaa kotisivu syötteeseen: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Katso YouTubessa",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Piilota merkkaukset",
"Show annotations": "Näytä merkkaukset",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Tämänhetkinen versio: "
"Current version: ": "Tämänhetkinen versio: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -87,6 +87,8 @@
"light": "clair",
"Thin mode: ": "Mode léger : ",
"Subscription preferences": "Préférences des abonnements",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Miscellaneous preferences": "",
"Show annotations by default for subscribed channels: ": "Afficher les annotations par défaut sur les chaînes auxquelles vous êtes abonnés : ",
"Redirect homepage to feed: ": "Rediriger la page d'accueil vers la page d'abonnements : ",
"Number of videos shown in feed: ": "Nombre de vidéos affichées dans la page d'abonnements : ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Voir la vidéo sur Youtube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Masquer les annotations",
"Show annotations": "Afficher les annotations",
"Genre: ": "Genre : ",
@ -415,5 +419,8 @@
"location": "emplacement",
"hdr": "HDR",
"filter": "filtrer",
"Current version: ": "Version actuelle : "
"Current version: ": "Version actuelle : ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "כהה",
"light": "בהיר",
"Thin mode: ": "",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "העדפות מינויים",
"Show annotations by default for subscribed channels: ": "Show annotations by default for subscribed channels? ",
"Redirect homepage to feed: ": "",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "צפייה ב־YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "",
"Show annotations": "",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "מיקום",
"hdr": "HDR",
"filter": "סינון",
"Current version: ": "הגרסה הנוכחית: "
"Current version: ": "הגרסה הנוכחית: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "tamno",
"light": "svijetlo",
"Thin mode: ": "Pojednostavljen prikaz: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Postavke pretplata",
"Show annotations by default for subscribed channels: ": "Standardno prikaži napomene za pretplaćene kanale: ",
"Redirect homepage to feed: ": "Preusmjeri početnu stranicu na feed: ",
@ -161,6 +163,8 @@
"Show more": "Pokaži više",
"Show less": "Pokaži manje",
"Watch on YouTube": "Gledaj na YouTubeu",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Sakrij napomene",
"Show annotations": "Prikaži napomene",
"Genre: ": "Žanr: ",
@ -415,5 +419,8 @@
"location": "lokacija",
"hdr": "hdr",
"filter": "filtar",
"Current version: ": "Trenutačna verzija: "
"Current version: ": "Trenutačna verzija: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -77,6 +77,8 @@
"dark": "sötét",
"light": "világos",
"Thin mode: ": "Vékony mód: ",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "Feliratkozási beállítások",
"Show annotations by default for subscribed channels: ": "Szövegmagyarázatok mutatása alapértelmezésben feliratkozott csatornák esetében: ",
"Redirect homepage to feed: ": "Kezdő oldal átirányitása a feed-re: ",
@ -145,6 +147,8 @@
"Watch on YouTube": "Megtekintés a YouTube-on",
"Hide annotations": "Szövegmagyarázat elrejtése",
"Show annotations": "Szövegmagyarázat mutatása",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Genre: ": "Műfaj: ",
"License: ": "Licensz: ",
"Family friendly? ": "Családbarát? ",
@ -336,5 +340,8 @@
"Videos": "Videók",
"Playlists": "Lejátszási listák",
"Community": "Közösség",
"Current version: ": "Jelenlegi verzió: "
"Current version: ": "Jelenlegi verzió: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "gelap",
"light": "terang",
"Thin mode: ": "Mode tipis: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferensi langganan",
"Show annotations by default for subscribed channels: ": "Tampilkan anotasi secara default untuk kanal langganan: ",
"Redirect homepage to feed: ": "Arahkan kembali laman beranda ke umpan: ",
@ -161,6 +163,8 @@
"Show more": "Tampilkan lainnya",
"Show less": "Tampilkan lebih sedikit",
"Watch on YouTube": "Tonton di YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Sembunyikan anotasi",
"Show annotations": "Tampilkan anotasi",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "lokasi",
"hdr": "hdr",
"filter": "saring",
"Current version: ": "Versi saat ini: "
"Current version: ": "Versi saat ini: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "dimmt",
"light": "ljóst",
"Thin mode: ": "Þunnt ham: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Áskriftarstillingar",
"Show annotations by default for subscribed channels: ": "Á að sýna glósur sjálfgefið fyrir áskriftarrásir? ",
"Redirect homepage to feed: ": "Endurbeina heimasíðu að straumi: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Horfa á YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Fela glósur",
"Show annotations": "Sýna glósur",
"Genre: ": "Tegund: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Núverandi útgáfa: "
"Current version: ": "Núverandi útgáfa: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "scuro",
"light": "chiaro",
"Thin mode: ": "Modalità per connessioni lente: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferenze iscrizioni",
"Show annotations by default for subscribed channels: ": "Mostrare annotazioni in modo predefinito per i canali sottoscritti: ",
"Redirect homepage to feed: ": "Reindirizza la pagina principale a quella delle iscrizioni: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Guarda su YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Nascondi annotazioni",
"Show annotations": "Mostra annotazioni",
"Genre: ": "Genere: ",
@ -415,5 +419,8 @@
"location": "Posizione",
"hdr": "HDR",
"filter": "Filtra",
"Current version: ": "Versione attuale: "
"Current version: ": "Versione attuale: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "ダーク",
"light": "ライト",
"Thin mode: ": "最小モード: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "登録チャンネル設定",
"Show annotations by default for subscribed channels: ": "デフォルトで登録チャンネルのアノテーションを表示しますか? ",
"Redirect homepage to feed: ": "ホームからフィードにリダイレクト: ",
@ -161,6 +163,8 @@
"Show more": "表示を増やす",
"Show less": "表示を減らす",
"Watch on YouTube": "YouTube で視聴",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "アノテーションを隠す",
"Show annotations": "アノテーションを表示",
"Genre: ": "ジャンル: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "HDR",
"filter": "フィルタ",
"Current version: ": "現在のバージョン: "
"Current version: ": "現在のバージョン: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "Mørk",
"light": "Lys",
"Thin mode: ": "Tynt modus: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Abonnementsinnstillinger",
"Show annotations by default for subscribed channels: ": "Vis merknader som forvalg for kanaler det abonneres på? ",
"Redirect homepage to feed: ": "Videresend hjemmeside til kilde: ",
@ -161,6 +163,8 @@
"Show more": "Vis mer",
"Show less": "Vis mindre",
"Watch on YouTube": "Vis video på YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Skjul merknader",
"Show annotations": "Vis merknader",
"Genre: ": "Sjanger: ",
@ -415,5 +419,8 @@
"location": "sted",
"hdr": "HDR",
"filter": "filtrer",
"Current version: ": "Gjeldende versjon: "
"Current version: ": "Gjeldende versjon: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "donker",
"light": "licht",
"Thin mode: ": "Smalle modus: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Abonnementsinstellingen",
"Show annotations by default for subscribed channels: ": "Standaard annotaties tonen voor geabonneerde kanalen? ",
"Redirect homepage to feed: ": "Startpagina omleiden naar feed: ",
@ -161,6 +163,8 @@
"Show more": "Toon meer",
"Show less": "Toon minder",
"Watch on YouTube": "Video bekijken op YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Annotaties verbergen",
"Show annotations": "Annotaties tonen",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "locatie",
"hdr": "HDR",
"filter": "verfijnen",
"Current version: ": "Huidige versie: "
"Current version: ": "Huidige versie: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "ciemny",
"light": "jasny",
"Thin mode: ": "Tryb minimalny: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferencje subskrybcji",
"Show annotations by default for subscribed channels: ": "Domyślnie wyświetlaj adnotacje dla subskrybowanych kanałów: ",
"Redirect homepage to feed: ": "Przekieruj stronę główną do subskrybcji: ",
@ -161,6 +163,8 @@
"Show more": "Pokaż więcej",
"Show less": "Pokaż mniej",
"Watch on YouTube": "Zobacz film na YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Ukryj adnotacje",
"Show annotations": "Pokaż adnotacje",
"Genre: ": "Gatunek: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "hdr",
"filter": "filtr",
"Current version: ": "Aktualna wersja: "
"Current version: ": "Aktualna wersja: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "escuro",
"light": "claro",
"Thin mode: ": "Modo compacto: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferências de inscrições",
"Show annotations by default for subscribed channels: ": "Sempre mostrar anotações dos vídeos de canais inscritos: ",
"Redirect homepage to feed: ": "Redirecionar página inicial para o feed: ",
@ -161,6 +163,8 @@
"Show more": "Mostrar mais",
"Show less": "Mostrar menos",
"Watch on YouTube": "Assistir no YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Ocultar anotações",
"Show annotations": "Mostrar anotações",
"Genre: ": "Gênero: ",
@ -415,5 +419,8 @@
"location": "localização",
"hdr": "hdr",
"filter": "filtro",
"Current version: ": "Versão atual: "
"Current version: ": "Versão atual: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "escuro",
"light": "claro",
"Thin mode: ": "Modo compacto: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferências de subscrições",
"Show annotations by default for subscribed channels: ": "Mostrar sempre anotações aos canais subscritos: ",
"Redirect homepage to feed: ": "Redirecionar página inicial para subscrições: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Ver no YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Ocultar anotações",
"Show annotations": "Mostrar anotações",
"Genre: ": "Género: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Versão atual: "
"Current version: ": "Versão atual: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "întunecat",
"light": "luminos",
"Thin mode: ": "Mod lejer: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Preferințele paginii de abonamente",
"Show annotations by default for subscribed channels: ": "Afișați adnotările în mod implicit pentru canalele la care v-ați abonat: ",
"Redirect homepage to feed: ": "Redirecționați pagina principală la pagina de abonamente: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Urmăriți videoclipul pe YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Ascundeți adnotările",
"Show annotations": "Afișați adnotările",
"Genre: ": "Categorie: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Versiunea actuală: "
"Current version: ": "Versiunea actuală: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "темная",
"light": "светлая",
"Thin mode: ": "Облегчённое оформление: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Настройки подписок",
"Show annotations by default for subscribed channels: ": "Всегда показывать аннотации в видео каналов, на которые вы подписаны? ",
"Redirect homepage to feed: ": "Отображать видео с каналов, на которые вы подписаны, как главную страницу: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Смотреть на YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Скрыть аннотации",
"Show annotations": "Показать аннотации",
"Genre: ": "Жанр: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Текущая версия: "
"Current version: ": "Текущая версия: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "",
"light": "",
"Thin mode: ": "",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "",
"Show annotations by default for subscribed channels: ": "",
"Redirect homepage to feed: ": "",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "",
"Show annotations": "",
"Genre: ": "",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -80,6 +80,8 @@
"dark": "tmavá",
"light": "svetlá",
"Thin mode: ": "Tenký režim: ",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "Nastavenia predplatného",
"Show annotations by default for subscribed channels: ": "Predvolene zobraziť anotácie odoberaných kanálov: ",
"Redirect homepage to feed: ": "Presmerovanie domovskej stránky na informačný kanál: ",
@ -149,6 +151,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "",
"Show annotations": "",
"Genre: ": "",
@ -354,5 +358,8 @@
"Videos": "",
"Playlists": "",
"Community": "",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "",
"light": "",
"Thin mode: ": "",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "",
"Show annotations by default for subscribed channels: ": "",
"Redirect homepage to feed: ": "",
@ -415,5 +417,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": ""
"Current version: ": "",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -77,6 +77,8 @@
"dark": "тамна",
"light": "светла",
"Thin mode: ": "Узани режим: ",
"Miscellaneous preferences": "",
"Automatically redirect to another Instance: ": "",
"Subscription preferences": "Подешавања о праћењима",
"Show annotations by default for subscribed channels: ": "Увек приказуј анотације за канале које пратим: ",
"Redirect homepage to feed: ": "Прикажи праћења као почетну страницу: ",
@ -143,6 +145,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Гледајте на YouTube-у",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Сакриј анотације",
"Show annotations": "Прикажи анотације",
"Genre: ": "Жанр: ",
@ -337,5 +341,8 @@
"Videos": "",
"Playlists": "",
"Community": "",
"Current version: ": "Тренутна верзија: "
"Current version: ": "Тренутна верзија: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "Mörkt",
"light": "Ljust",
"Thin mode: ": "Lättviktigt läge: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Prenumerationsinställningar",
"Show annotations by default for subscribed channels: ": "Visa länkar-i-videor som förval för kanaler som prenumereras på? ",
"Redirect homepage to feed: ": "Omdirigera hemsida till flöde: ",
@ -161,6 +163,8 @@
"Show more": "Visa mer",
"Show less": "Visa mindre",
"Watch on YouTube": "Titta på YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Dölj länkar-i-video",
"Show annotations": "Visa länkar-i-video",
"Genre: ": "Genre: ",
@ -415,5 +419,8 @@
"location": "plats",
"hdr": "hdr",
"filter": "",
"Current version: ": "Nuvarande version: "
"Current version: ": "Nuvarande version: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "karanlık",
"light": "aydınlık",
"Thin mode: ": "İnce mod: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Abonelik tercihleri",
"Show annotations by default for subscribed channels: ": "Abone olunan kanallar için ek açıklamaları öntanımlı olarak göster: ",
"Redirect homepage to feed: ": "Ana sayfayı akışa yönlendir: ",
@ -161,6 +163,8 @@
"Show more": "Daha fazla göster",
"Show less": "Daha az göster",
"Watch on YouTube": "YouTube'da izle",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Ek açıklamaları gizle",
"Show annotations": "Ek açıklamaları göster",
"Genre: ": "Tür: ",
@ -415,5 +419,8 @@
"location": "konum",
"hdr": "HDR",
"filter": "filtrele",
"Current version: ": "Şu anki sürüm: "
"Current version: ": "Şu anki sürüm: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "темна",
"light": "Світла",
"Thin mode: ": "Полегшене оформлення: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "Налаштування підписок",
"Show annotations by default for subscribed channels: ": "Завжди показувати анотації у відео каналів, на які ви підписані? ",
"Redirect homepage to feed: ": "Показувати відео з каналів, на які підписані, як головну сторінку: ",
@ -161,6 +163,8 @@
"Show more": "",
"Show less": "",
"Watch on YouTube": "Дивитися на YouTube",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "Приховати анотації",
"Show annotations": "Показати анотації",
"Genre: ": "Жанр: ",
@ -415,5 +419,8 @@
"location": "",
"hdr": "",
"filter": "",
"Current version: ": "Поточна версія: "
"Current version: ": "Поточна версія: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "暗色",
"light": "亮色",
"Thin mode: ": "窄页模式: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "订阅设置",
"Show annotations by default for subscribed channels: ": "默认情况下显示已订阅频道的注释: ",
"Redirect homepage to feed: ": "跳转主页到 feed: ",
@ -161,6 +163,8 @@
"Show more": "显示更多",
"Show less": "显示较少",
"Watch on YouTube": "在 YouTube 观看",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "隐藏注释",
"Show annotations": "显示注释",
"Genre: ": "风格: ",
@ -415,5 +419,8 @@
"location": "位置",
"hdr": "hdr",
"filter": "过滤器",
"Current version: ": "当前版本: "
"Current version: ": "当前版本: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -86,6 +86,8 @@
"dark": "深色",
"light": "淺色",
"Thin mode: ": "精簡模式: ",
"Miscellaneous preferences": "",
"Automaticatic instance redirection (fallback to redirect.invidious.io): ": "",
"Subscription preferences": "訂閱偏好設定",
"Show annotations by default for subscribed channels: ": "預設為已訂閱的頻道顯示註釋: ",
"Redirect homepage to feed: ": "重新導向首頁至 feed ",
@ -161,6 +163,8 @@
"Show more": "顯示更多",
"Show less": "顯示較少",
"Watch on YouTube": "在 YouTube 上觀看",
"Switch Invidious Instance": "",
"Broken? Try another Invidious Instance": "",
"Hide annotations": "隱藏註釋",
"Show annotations": "顯示註釋",
"Genre: ": "風格: ",
@ -415,5 +419,8 @@
"location": "位置",
"hdr": "HDR",
"filter": "篩選條件",
"Current version: ": "目前版本: "
"Current version: ": "目前版本: ",
"next_steps_error_message": "",
"next_steps_error_message_refresh": "",
"next_steps_error_message_go_to_youtube": ""
}

View File

@ -314,6 +314,7 @@ Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/w/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/v/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/e/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/redirect", Invidious::Routes::Misc, :cross_instance_redirect
Invidious::Routing.get "/embed/", Invidious::Routes::Embed, :redirect
Invidious::Routing.get "/embed/:id", Invidious::Routes::Embed, :show

View File

@ -40,6 +40,9 @@ def error_template_helper(env : HTTP::Server::Context, locale : Hash(String, JSO
and include the following text in your message:
<pre style="padding: 20px; background: rgba(0, 0, 0, 0.12345);">#{issue_template}</pre>
END_HTML
next_steps = error_redirect_helper(env, locale)
return templated "error"
end
@ -47,6 +50,7 @@ def error_template_helper(env : HTTP::Server::Context, locale : Hash(String, JSO
env.response.content_type = "text/html"
env.response.status_code = status_code
error_message = translate(locale, message)
next_steps = error_redirect_helper(env, locale)
return templated "error"
end
@ -103,3 +107,34 @@ end
def error_json_helper(env : HTTP::Server::Context, locale : Hash(String, JSON::Any) | Nil, status_code : Int32, message : String)
error_json_helper(env, locale, status_code, message, nil)
end
def error_redirect_helper(env : HTTP::Server::Context, locale : Hash(String, JSON::Any) | Nil)
request_path = env.request.path
if request_path.starts_with?("/search") || request_path.starts_with?("/watch") ||
request_path.starts_with?("/channel") || request_path.starts_with?("/playlist?list=PL")
next_steps_text = translate(locale, "next_steps_error_message")
refresh = translate(locale, "next_steps_error_message_refresh")
go_to_youtube = translate(locale, "next_steps_error_message_go_to_youtube")
switch_instance = translate(locale, "Switch Invidious Instance")
return <<-END_HTML
<p style="margin-bottom: 4px;">#{next_steps_text}</p>
<ul>
<li>
<a href="#{env.request.resource}">#{refresh}</a>
</li>
<li>
<a href="/redirect?referer=#{env.get("current_page")}">#{switch_instance}</a>
</li>
<li>
<a href="https://youtube.com#{env.request.resource}">#{go_to_youtube}</a>
</li>
</ul>
END_HTML
return next_step_html
else
return ""
end
end

View File

@ -44,6 +44,7 @@ struct ConfigPreferences
property quality_dash : String = "auto"
property default_home : String? = "Popular"
property feed_menu : Array(String) = ["Popular", "Trending", "Subscriptions", "Playlists"]
property automatic_instance_redirect : Bool = false
property related_videos : Bool = true
property sort : String = "published"
property speed : Float32 = 1.0_f32

View File

@ -409,3 +409,65 @@ def convert_theme(theme)
theme
end
end
def fetch_random_instance
begin
instance_api_client = HTTP::Client.new(URI.parse("https://api.invidious.io"))
# Timeouts
instance_api_client.connect_timeout = 10.seconds
instance_api_client.dns_timeout = 10.seconds
instance_list = JSON.parse(instance_api_client.get("/instances.json").body).as_a
instance_api_client.close
rescue Socket::ConnectError | IO::TimeoutError | JSON::ParseException
instance_list = [] of JSON::Any
end
filtered_instance_list = [] of String
instance_list.each do |data|
# TODO Check if current URL is onion instance and use .onion types if so.
if data[1]["type"] == "https"
# Instances can have statisitics disabled, which is an requirement of version validation.
# as_nil? doesn't exist. Thus we'll have to handle the error rasied if as_nil fails.
begin
data[1]["stats"].as_nil
next
rescue TypeCastError
end
# stats endpoint could also lack the software dict.
next if data[1]["stats"]["software"]?.nil?
# Makes sure the instance isn't too outdated.
if remote_version = data[1]["stats"]?.try &.["software"]?.try &.["version"]
remote_commit_date = remote_version.as_s.match(/\d{4}\.\d{2}\.\d{2}/)
next if !remote_commit_date
remote_commit_date = Time.parse(remote_commit_date[0], "%Y.%m.%d", Time::Location::UTC)
local_commit_date = Time.parse(CURRENT_VERSION, "%Y.%m.%d", Time::Location::UTC)
next if (remote_commit_date - local_commit_date).abs.days > 30
begin
data[1]["monitor"].as_nil
health = data[1]["monitor"].as_h["dailyRatios"][0].as_h["ratio"]
filtered_instance_list << data[0].as_s if health.to_s.to_f > 90
rescue TypeCastError
# We can't check the health if the monitoring is broken. Thus we'll just add it to the list
# and move on. Ideally we'll ignore any instance that has broken health monitoring but due to the fact that
# it's an error that often occurs with all the instances at the same time, we have to just skip the check.
filtered_instance_list << data[0].as_s
end
end
end
end
# If for some reason no instances managed to get fetched successfully then we'll just redirect to redirect.invidious.io
if filtered_instance_list.size == 0
return "redirect.invidious.io"
end
return filtered_instance_list.sample(1)[0]
end

View File

@ -35,4 +35,15 @@ class Invidious::Routes::Misc < Invidious::Routes::BaseRoute
locale = LOCALES[env.get("preferences").as(Preferences).locale]?
rendered "licenses"
end
def cross_instance_redirect(env)
referer = get_referer(env)
if !env.get("preferences").as(Preferences).automatic_instance_redirect
return env.redirect("https://redirect.invidious.io#{referer}")
end
instance_url = fetch_random_instance
env.redirect "https://#{instance_url}#{referer}"
end
end

View File

@ -92,6 +92,10 @@ class Invidious::Routes::PreferencesRoute < Invidious::Routes::BaseRoute
end
end
automatic_instance_redirect = env.params.body["automatic_instance_redirect"]?.try &.as(String)
automatic_instance_redirect ||= "off"
automatic_instance_redirect = automatic_instance_redirect == "on"
locale = env.params.body["locale"]?.try &.as(String)
locale ||= CONFIG.default_user_preferences.locale
@ -122,34 +126,35 @@ class Invidious::Routes::PreferencesRoute < Invidious::Routes::BaseRoute
# Convert to JSON and back again to take advantage of converters used for compatability
preferences = Preferences.from_json({
annotations: annotations,
annotations_subscribed: annotations_subscribed,
autoplay: autoplay,
captions: captions,
comments: comments,
continue: continue,
continue_autoplay: continue_autoplay,
dark_mode: dark_mode,
latest_only: latest_only,
listen: listen,
local: local,
locale: locale,
max_results: max_results,
notifications_only: notifications_only,
player_style: player_style,
quality: quality,
quality_dash: quality_dash,
default_home: default_home,
feed_menu: feed_menu,
related_videos: related_videos,
sort: sort,
speed: speed,
thin_mode: thin_mode,
unseen_only: unseen_only,
video_loop: video_loop,
volume: volume,
extend_desc: extend_desc,
vr_mode: vr_mode,
annotations: annotations,
annotations_subscribed: annotations_subscribed,
autoplay: autoplay,
captions: captions,
comments: comments,
continue: continue,
continue_autoplay: continue_autoplay,
dark_mode: dark_mode,
latest_only: latest_only,
listen: listen,
local: local,
locale: locale,
max_results: max_results,
notifications_only: notifications_only,
player_style: player_style,
quality: quality,
quality_dash: quality_dash,
default_home: default_home,
feed_menu: feed_menu,
automatic_instance_redirect: automatic_instance_redirect,
related_videos: related_videos,
sort: sort,
speed: speed,
thin_mode: thin_mode,
unseen_only: unseen_only,
video_loop: video_loop,
volume: volume,
extend_desc: extend_desc,
vr_mode: vr_mode,
}.to_json).to_json
if user = env.get? "user"

View File

@ -36,6 +36,7 @@ struct Preferences
property annotations : Bool = CONFIG.default_user_preferences.annotations
property annotations_subscribed : Bool = CONFIG.default_user_preferences.annotations_subscribed
property autoplay : Bool = CONFIG.default_user_preferences.autoplay
property automatic_instance_redirect : Bool = CONFIG.default_user_preferences.automatic_instance_redirect
@[JSON::Field(converter: Preferences::StringToArray)]
@[YAML::Field(converter: Preferences::StringToArray)]

View File

@ -41,6 +41,9 @@
<div class="pure-g h-box">
<div class="pure-u-1-3">
<a href="https://www.youtube.com/channel/<%= channel.ucid %>"><%= translate(locale, "View channel on YouTube") %></a>
<div class="pure-u-1 pure-md-1-3">
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Switch Invidious Instance") %></a>
</div>
<% if !channel.auto_generated %>
<div class="pure-u-1 pure-md-1-3">
<b><%= translate(locale, "Videos") %></b>

View File

@ -40,6 +40,9 @@
<div class="pure-g h-box">
<div class="pure-u-1-3">
<a href="https://www.youtube.com/channel/<%= channel.ucid %>/community"><%= translate(locale, "View channel on YouTube") %></a>
<div class="pure-u-1 pure-md-1-3">
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Switch Invidious Instance") %></a>
</div>
<% if !channel.auto_generated %>
<div class="pure-u-1 pure-md-1-3">
<a href="/channel/<%= channel.ucid %>"><%= translate(locale, "Videos") %></a>

View File

@ -137,17 +137,22 @@
</a>
<% end %>
<p><a href="/watch?v=<%= item.id %>"><%= HTML.escape(item.title) %></a></p>
<p style="display: flex;">
<div style="display: flex">
<b style="flex: 1;">
<a style="width:100%" href="/channel/<%= item.ucid %>"><%= item.author %></a>
</b>
<a title="<%=translate(locale, "Watch on YouTube")%>" href="https://www.youtube.com/watch?v=<%= item.id %>" style="margin-right: 5px;">
<i class="icon ion-logo-youtube"></i>
</a>
<a title="<%=translate(locale, "Audio mode")%>" href="/watch?v=<%= item.id %>&amp;listen=1">
<i class="icon ion-md-headset"></i>
</a>
</p>
<div class="icon-buttons">
<a title="<%=translate(locale, "Watch on YouTube")%>" href="https://www.youtube.com/watch?v=<%= item.id %>">
<i class="icon ion-logo-youtube"></i>
</a>
<a title="<%=translate(locale, "Audio mode")%>" href="/watch?v=<%= item.id %>&amp;listen=1">
<i class="icon ion-md-headset"></i>
</a>
<a title="<%=translate(locale, "Switch Invidious Instance")%>" href="/redirect?referer=<%=HTML.escape("watch?v=#{item.id}")%>">
<i class="icon ion-md-jet"></i>
</a>
</div>
</div>
<h5 class="pure-g">
<% if item.responds_to?(:premiere_timestamp) && item.premiere_timestamp.try &.> Time.utc %>

View File

@ -4,4 +4,5 @@
<div class="h-box">
<%= error_message %>
<%= next_steps %>
</div>

View File

@ -36,6 +36,11 @@
<a href="https://www.youtube.com/playlist?list=<%= playlist.id %>">
<%= translate(locale, "View playlist on YouTube") %>
</a>
<span> | </span>
<a href="/redirect?referer=<%= env.get?("current_page") %>">
<%= translate(locale, "Switch Invidious Instance") %>
</a>
</div>
<% end %>
</div>

View File

@ -42,6 +42,11 @@
<div class="pure-u-1 pure-md-1-3">
<a href="https://www.youtube.com/channel/<%= channel.ucid %>/playlists"><%= translate(locale, "View channel on YouTube") %></a>
</div>
<div class="pure-u-1 pure-md-1-3">
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Switch Invidious Instance") %></a>
</div>
<div class="pure-u-1 pure-md-1-3">
<a href="/channel/<%= channel.ucid %>"><%= translate(locale, "Videos") %></a>
</div>

View File

@ -176,6 +176,13 @@
<% end %>
</div>
<legend><%= translate(locale, "Miscellaneous preferences") %></legend>
<div class="pure-control-group">
<label for="automatic_instance_redirect"><%= translate(locale, "Automaticatic instance redirection (fallback to redirect.invidious.io): ") %></label>
<input name="automatic_instance_redirect" id="automatic_instance_redirect" type="checkbox" <% if preferences.automatic_instance_redirect %>checked<% end %>>
</div>
<% if env.get? "user" %>
<legend><%= translate(locale, "Subscription preferences") %></legend>

View File

@ -2,94 +2,105 @@
<title><%= search_query.not_nil!.size > 30 ? HTML.escape(query.not_nil![0,30].rstrip(".") + "...") : HTML.escape(query.not_nil!) %> - Invidious</title>
<% end %>
<details id="filters">
<summary>
<h3 style="display:inline"> <%= translate(locale, "filter") %> </h3>
</summary>
<div id="filters" class="pure-g h-box">
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "date") %></b>
<hr/>
<% ["hour", "today", "week", "month", "year"].each do |date| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("date", "all") == date %>
<b><%= translate(locale, date) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?date:[a-z]+/, "") + " date:" + date) %>&page=<%= page %>">
<%= translate(locale, date) %>
</a>
<% end %>
</div>
<% end %>
<!-- Search redirection and filtering UI -->
<% if count == 0 %>
<h3 style="text-align: center">
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Broken? Try another Invidious Instance!") %></a>
</h3>
<% else %>
<details id="filters">
<summary>
<h3 style="display:inline"> <%= translate(locale, "filter") %> </h3>
</summary>
<div id="filters" class="pure-g h-box">
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "date") %></b>
<hr/>
<% ["hour", "today", "week", "month", "year"].each do |date| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("date", "all") == date %>
<b><%= translate(locale, date) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?date:[a-z]+/, "") + " date:" + date) %>&page=<%= page %>">
<%= translate(locale, date) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "content_type") %></b>
<hr/>
<% ["video", "channel", "playlist", "movie", "show"].each do |content_type| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("content_type", "all") == content_type %>
<b><%= translate(locale, content_type) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?content_type:[a-z]+/, "") + " content_type:" + content_type) %>&page=<%= page %>">
<%= translate(locale, content_type) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "duration") %></b>
<hr/>
<% ["short", "long"].each do |duration| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("duration", "all") == duration %>
<b><%= translate(locale, duration) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?duration:[a-z]+/, "") + " duration:" + duration) %>&page=<%= page %>">
<%= translate(locale, duration) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "features") %></b>
<hr/>
<% ["hd", "subtitles", "creative_commons", "3d", "live", "purchased", "4k", "360", "location", "hdr"].each do |feature| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("features", "all").includes?(feature) %>
<b><%= translate(locale, feature) %></b>
<% elsif operator_hash.has_key?("features") %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/features:/, "features:" + feature + ",")) %>&page=<%= page %>">
<%= translate(locale, feature) %>
</a>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil! + " features:" + feature) %>&page=<%= page %>">
<%= translate(locale, feature) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "sort") %></b>
<hr/>
<% ["relevance", "rating", "date", "views"].each do |sort| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("sort", "relevance") == sort %>
<b><%= translate(locale, sort) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?sort:[a-z]+/, "") + " sort:" + sort) %>&page=<%= page %>">
<%= translate(locale, sort) %>
</a>
<% end %>
</div>
<% end %>
</div>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "content_type") %></b>
<hr/>
<% ["video", "channel", "playlist", "movie", "show"].each do |content_type| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("content_type", "all") == content_type %>
<b><%= translate(locale, content_type) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?content_type:[a-z]+/, "") + " content_type:" + content_type) %>&page=<%= page %>">
<%= translate(locale, content_type) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "duration") %></b>
<hr/>
<% ["short", "long"].each do |duration| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("duration", "all") == duration %>
<b><%= translate(locale, duration) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?duration:[a-z]+/, "") + " duration:" + duration) %>&page=<%= page %>">
<%= translate(locale, duration) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "features") %></b>
<hr/>
<% ["hd", "subtitles", "creative_commons", "3d", "live", "purchased", "4k", "360", "location", "hdr"].each do |feature| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("features", "all").includes?(feature) %>
<b><%= translate(locale, feature) %></b>
<% elsif operator_hash.has_key?("features") %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/features:/, "features:" + feature + ",")) %>&page=<%= page %>">
<%= translate(locale, feature) %>
</a>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil! + " features:" + feature) %>&page=<%= page %>">
<%= translate(locale, feature) %>
</a>
<% end %>
</div>
<% end %>
</div>
<div class="pure-u-1-3 pure-u-md-1-5">
<b><%= translate(locale, "sort") %></b>
<hr/>
<% ["relevance", "rating", "date", "views"].each do |sort| %>
<div class="pure-u-1 pure-md-1-5">
<% if operator_hash.fetch("sort", "relevance") == sort %>
<b><%= translate(locale, sort) %></b>
<% else %>
<a href="/search?q=<%= HTML.escape(query.not_nil!.gsub(/ ?sort:[a-z]+/, "") + " sort:" + sort) %>&page=<%= page %>">
<%= translate(locale, sort) %>
</a>
<% end %>
</div>
<% end %>
</div>
</div>
</details>
</details>
<% end %>
<hr/>
<% if count == 0 %>
<hr style="margin: 0;"/>
<% else %>
<hr/>
<% end %>
<div class="pure-g h-box v-box">
<div class="pure-u-1 pure-u-lg-1-5">

View File

@ -109,6 +109,9 @@ we're going to need to do it here in order to allow for translations.
<a href="https://www.youtube.com/watch?v=<%= video.id %>"><%= translate(locale, "Watch on YouTube") %></a>
(<a href="https://www.youtube.com/embed/<%= video.id %>"><%= translate(locale, "Embed") %></a>)
</span>
<p id="watch-on-another-invidious-instance">
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Switch Invidious Instance") %></a>
</p>
<p id="embed-link">
<a href="<%= embed_link %>"><%= translate(locale, "Embed Link") %></a>
</p>