mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-04 06:08:31 -06:00 
			
		
		
		
	Merge branch 'master' into api-only
This commit is contained in:
		
						commit
						3d76898bb9
					
				@ -10,7 +10,7 @@
 | 
				
			|||||||
  "newest": "الأجدد",
 | 
					  "newest": "الأجدد",
 | 
				
			||||||
  "oldest": "الأقدم",
 | 
					  "oldest": "الأقدم",
 | 
				
			||||||
  "popular": "الاكثر شعبية",
 | 
					  "popular": "الاكثر شعبية",
 | 
				
			||||||
  "last": "",
 | 
					  "last": "اخر الفيديوهات المعدلة",
 | 
				
			||||||
  "Next page": "الصفحة الثانية",
 | 
					  "Next page": "الصفحة الثانية",
 | 
				
			||||||
  "Previous page": "الصفحة السابقة",
 | 
					  "Previous page": "الصفحة السابقة",
 | 
				
			||||||
  "Clear watch history?": "مسح السجل ؟",
 | 
					  "Clear watch history?": "مسح السجل ؟",
 | 
				
			||||||
@ -50,7 +50,7 @@
 | 
				
			|||||||
  "Autoplay: ": "تشغيل تلقائى: ",
 | 
					  "Autoplay: ": "تشغيل تلقائى: ",
 | 
				
			||||||
  "Autoplay next video: ": "شغل الفيديو التالى تلقائى: ",
 | 
					  "Autoplay next video: ": "شغل الفيديو التالى تلقائى: ",
 | 
				
			||||||
  "Listen by default: ": "تشغيل النسخة السمعية تلقائى: ",
 | 
					  "Listen by default: ": "تشغيل النسخة السمعية تلقائى: ",
 | 
				
			||||||
  "Proxy videos? ": "",
 | 
					  "Proxy videos? ": "عرض الفيديوهات عن طريق الوكيل(proxy) ؟",
 | 
				
			||||||
  "Default speed: ": "السرعة الإفتراضية: ",
 | 
					  "Default speed: ": "السرعة الإفتراضية: ",
 | 
				
			||||||
  "Preferred video quality: ": "الجودة المفضلة للفيديوهات: ",
 | 
					  "Preferred video quality: ": "الجودة المفضلة للفيديوهات: ",
 | 
				
			||||||
  "Player volume: ": "صوت المشغل: ",
 | 
					  "Player volume: ": "صوت المشغل: ",
 | 
				
			||||||
@ -83,14 +83,14 @@
 | 
				
			|||||||
  "Manage subscriptions": "إدارة المشتركين",
 | 
					  "Manage subscriptions": "إدارة المشتركين",
 | 
				
			||||||
  "Watch history": "سجل المشاهدة",
 | 
					  "Watch history": "سجل المشاهدة",
 | 
				
			||||||
  "Delete account": "حذف الحساب",
 | 
					  "Delete account": "حذف الحساب",
 | 
				
			||||||
  "Administrator preferences": "",
 | 
					  "Administrator preferences": "إعدادات المدير",
 | 
				
			||||||
  "Default homepage: ": "",
 | 
					  "Default homepage: ": "الصفحة الرئيسية الافتراضية ",
 | 
				
			||||||
  "Feed menu: ": "",
 | 
					  "Feed menu: ": "قائمة التغذية",
 | 
				
			||||||
  "Top enabled? ": "",
 | 
					  "Top enabled? ": "تفعيل 'الأفضل' ؟ ",
 | 
				
			||||||
  "CAPTCHA enabled? ": "",
 | 
					  "CAPTCHA enabled? ": "تفعيل الكابتشا ؟",
 | 
				
			||||||
  "Login enabled? ": "",
 | 
					  "Login enabled? ": "تفعيل تسجيل الدخول ؟",
 | 
				
			||||||
  "Registration enabled? ": "",
 | 
					  "Registration enabled? ": "تفعيل التسجيل ؟",
 | 
				
			||||||
  "Report statistics? ": "",
 | 
					  "Report statistics? ": "إبلاغ الإحصائيات",
 | 
				
			||||||
  "Save preferences": "حفظ التفضيلات",
 | 
					  "Save preferences": "حفظ التفضيلات",
 | 
				
			||||||
  "Subscription manager": "مدير الإشتراكات",
 | 
					  "Subscription manager": "مدير الإشتراكات",
 | 
				
			||||||
  "`x` subscriptions": "`x` مشتركين",
 | 
					  "`x` subscriptions": "`x` مشتركين",
 | 
				
			||||||
@ -103,8 +103,9 @@
 | 
				
			|||||||
  "Released under the AGPLv3 by Omar Roth.": "تم الإنشاء تحت AGPLv3 بواسطة عمر روث.",
 | 
					  "Released under the AGPLv3 by Omar Roth.": "تم الإنشاء تحت AGPLv3 بواسطة عمر روث.",
 | 
				
			||||||
  "Source available here.": "الأكواد متوفرة هنا.",
 | 
					  "Source available here.": "الأكواد متوفرة هنا.",
 | 
				
			||||||
  "View JavaScript license information.": "مشاهدة معلومات حول تراخيص الجافاسكريبت.",
 | 
					  "View JavaScript license information.": "مشاهدة معلومات حول تراخيص الجافاسكريبت.",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "عرض سياسة الخصوصية",
 | 
				
			||||||
  "Trending": "الشائع",
 | 
					  "Trending": "الشائع",
 | 
				
			||||||
 | 
					  "Unlisted": "غير مصنف",
 | 
				
			||||||
  "Watch video on Youtube": "مشاهدة الفيديو على اليوتيوب",
 | 
					  "Watch video on Youtube": "مشاهدة الفيديو على اليوتيوب",
 | 
				
			||||||
  "Genre: ": "النوع: ",
 | 
					  "Genre: ": "النوع: ",
 | 
				
			||||||
  "License: ": "التراخيص: ",
 | 
					  "License: ": "التراخيص: ",
 | 
				
			||||||
@ -114,6 +115,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "الدول المسموح فيها هذا الفيديو: ",
 | 
					  "Whitelisted regions: ": "الدول المسموح فيها هذا الفيديو: ",
 | 
				
			||||||
  "Blacklisted regions: ": "الدول الحظور فيها هذا الفيديو: ",
 | 
					  "Blacklisted regions: ": "الدول الحظور فيها هذا الفيديو: ",
 | 
				
			||||||
  "Shared `x`": "شارك منذ `x`",
 | 
					  "Shared `x`": "شارك منذ `x`",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "يعرض فى 'x'",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "اهلا! يبدو ان الجافاسكريبت معطلة. اضغط هنا لعرض التعليقات, ضع فى إعتبارك انها ستأخذ وقت اطول للعرض.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "اهلا! يبدو ان الجافاسكريبت معطلة. اضغط هنا لعرض التعليقات, ضع فى إعتبارك انها ستأخذ وقت اطول للعرض.",
 | 
				
			||||||
  "View YouTube comments": "عرض تعليقات اليوتيوب",
 | 
					  "View YouTube comments": "عرض تعليقات اليوتيوب",
 | 
				
			||||||
  "View more comments on Reddit": "عرض المزيد من التعليقات على\\من موقع Reddit",
 | 
					  "View more comments on Reddit": "عرض المزيد من التعليقات على\\من موقع Reddit",
 | 
				
			||||||
 | 
				
			|||||||
@ -105,6 +105,7 @@
 | 
				
			|||||||
  "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.",
 | 
					  "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "",
 | 
				
			||||||
  "Trending": "Trending",
 | 
					  "Trending": "Trending",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Watch video on Youtube": "Video auf YouTube ansehen",
 | 
					  "Watch video on Youtube": "Video auf YouTube ansehen",
 | 
				
			||||||
  "Genre: ": "Genre: ",
 | 
					  "Genre: ": "Genre: ",
 | 
				
			||||||
  "License: ": "Lizenz: ",
 | 
					  "License: ": "Lizenz: ",
 | 
				
			||||||
@ -114,6 +115,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "Erlaubte Regionen: ",
 | 
					  "Whitelisted regions: ": "Erlaubte Regionen: ",
 | 
				
			||||||
  "Blacklisted regions: ": "Unerlaubte Regionen: ",
 | 
					  "Blacklisted regions: ": "Unerlaubte Regionen: ",
 | 
				
			||||||
  "Shared `x`": "Geteilt `x`",
 | 
					  "Shared `x`": "Geteilt `x`",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.",
 | 
				
			||||||
  "View YouTube comments": "YouTube Kommentare anzeigen",
 | 
					  "View YouTube comments": "YouTube Kommentare anzeigen",
 | 
				
			||||||
  "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen",
 | 
					  "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen",
 | 
				
			||||||
 | 
				
			|||||||
@ -103,6 +103,7 @@
 | 
				
			|||||||
  "View JavaScript license information.": "View JavaScript license information.",
 | 
					  "View JavaScript license information.": "View JavaScript license information.",
 | 
				
			||||||
  "View privacy policy.": "View privacy policy.",
 | 
					  "View privacy policy.": "View privacy policy.",
 | 
				
			||||||
  "Trending": "Trending",
 | 
					  "Trending": "Trending",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Watch video on Youtube": "Watch video on Youtube",
 | 
					  "Watch video on Youtube": "Watch video on Youtube",
 | 
				
			||||||
  "Genre: ": "Genre: ",
 | 
					  "Genre: ": "Genre: ",
 | 
				
			||||||
  "License: ": "License: ",
 | 
					  "License: ": "License: ",
 | 
				
			||||||
@ -112,6 +113,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "Whitelisted regions: ",
 | 
					  "Whitelisted regions: ": "Whitelisted regions: ",
 | 
				
			||||||
  "Blacklisted regions: ": "Blacklisted regions: ",
 | 
					  "Blacklisted regions: ": "Blacklisted regions: ",
 | 
				
			||||||
  "Shared `x`": "Shared `x`",
 | 
					  "Shared `x`": "Shared `x`",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.",
 | 
				
			||||||
  "View YouTube comments": "View YouTube comments",
 | 
					  "View YouTube comments": "View YouTube comments",
 | 
				
			||||||
  "View more comments on Reddit": "View more comments on Reddit",
 | 
					  "View more comments on Reddit": "View more comments on Reddit",
 | 
				
			||||||
 | 
				
			|||||||
@ -102,6 +102,7 @@
 | 
				
			|||||||
  "Source available here.": "",
 | 
					  "Source available here.": "",
 | 
				
			||||||
  "View JavaScript license information.": "",
 | 
					  "View JavaScript license information.": "",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Trending": "",
 | 
					  "Trending": "",
 | 
				
			||||||
  "Watch video on Youtube": "",
 | 
					  "Watch video on Youtube": "",
 | 
				
			||||||
  "Genre: ": "",
 | 
					  "Genre: ": "",
 | 
				
			||||||
@ -112,6 +113,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "",
 | 
					  "Whitelisted regions: ": "",
 | 
				
			||||||
  "Blacklisted regions: ": "",
 | 
					  "Blacklisted regions: ": "",
 | 
				
			||||||
  "Shared `x`": "",
 | 
					  "Shared `x`": "",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "",
 | 
				
			||||||
  "View YouTube comments": "",
 | 
					  "View YouTube comments": "",
 | 
				
			||||||
  "View more comments on Reddit": "",
 | 
					  "View more comments on Reddit": "",
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
  "`x` subscribers": "`x` abonnés",
 | 
					  "`x` subscribers": "`x` abonnés",
 | 
				
			||||||
  "`x` videos": "`x` vidéos",
 | 
					  "`x` videos": "`x` vidéos",
 | 
				
			||||||
  "LIVE": "EN DIRECT",
 | 
					  "LIVE": "EN DIRECT",
 | 
				
			||||||
  "Shared `x` ago": "Partagé il y a `x`",
 | 
					  "Shared `x` ago": "Ajoutée il y a `x`",
 | 
				
			||||||
  "Unsubscribe": "Se désabonner",
 | 
					  "Unsubscribe": "Se désabonner",
 | 
				
			||||||
  "Subscribe": "S'abonner",
 | 
					  "Subscribe": "S'abonner",
 | 
				
			||||||
  "Login to subscribe to `x`": "Vous devez vous connecter pour vous abonner à `x`",
 | 
					  "Login to subscribe to `x`": "Vous devez vous connecter pour vous abonner à `x`",
 | 
				
			||||||
@ -16,7 +16,7 @@
 | 
				
			|||||||
  "Clear watch history?": "Êtes-vous sûr de vouloir supprimer l'historique des vidéos regardées ?",
 | 
					  "Clear watch history?": "Êtes-vous sûr de vouloir supprimer l'historique des vidéos regardées ?",
 | 
				
			||||||
  "Yes": "Oui",
 | 
					  "Yes": "Oui",
 | 
				
			||||||
  "No": "Non",
 | 
					  "No": "Non",
 | 
				
			||||||
  "Import and Export Data": "Importer et Exporter les Données",
 | 
					  "Import and Export Data": "Importer et exporter des données",
 | 
				
			||||||
  "Import": "Importer",
 | 
					  "Import": "Importer",
 | 
				
			||||||
  "Import Invidious data": "Importer des données Invidious",
 | 
					  "Import Invidious data": "Importer des données Invidious",
 | 
				
			||||||
  "Import YouTube subscriptions": "Importer des abonnements YouTube",
 | 
					  "Import YouTube subscriptions": "Importer des abonnements YouTube",
 | 
				
			||||||
@ -32,32 +32,32 @@
 | 
				
			|||||||
  "An alternative front-end to YouTube": "Un front-end alternatif à YouTube",
 | 
					  "An alternative front-end to YouTube": "Un front-end alternatif à YouTube",
 | 
				
			||||||
  "JavaScript license information": "Informations sur les licences JavaScript",
 | 
					  "JavaScript license information": "Informations sur les licences JavaScript",
 | 
				
			||||||
  "source": "source",
 | 
					  "source": "source",
 | 
				
			||||||
  "Login": "Connexion",
 | 
					  "Login": "Se connecter",
 | 
				
			||||||
  "Login/Register": "Connexion/S'inscrire",
 | 
					  "Login/Register": "Se connecter/Créer un compte",
 | 
				
			||||||
  "Login to Google": "Se connecter à Google",
 | 
					  "Login to Google": "Se connecter avec Google",
 | 
				
			||||||
  "User ID:": "Identifiant utilisateur :",
 | 
					  "User ID:": "Identifiant utilisateur :",
 | 
				
			||||||
  "Password:": "Mot de passe :",
 | 
					  "Password:": "Mot de passe :",
 | 
				
			||||||
  "Time (h:mm:ss):": "Heure (h:mm:ss) :",
 | 
					  "Time (h:mm:ss):": "Heure (h:mm:ss) :",
 | 
				
			||||||
  "Text CAPTCHA": "CAPTCHA Texte",
 | 
					  "Text CAPTCHA": "CAPTCHA Texte",
 | 
				
			||||||
  "Image CAPTCHA": "CAPTCHA Image",
 | 
					  "Image CAPTCHA": "CAPTCHA Image",
 | 
				
			||||||
  "Sign In": "S'identifier",
 | 
					  "Sign In": "Se connecter",
 | 
				
			||||||
  "Register": "S'inscrire",
 | 
					  "Register": "S'inscrire",
 | 
				
			||||||
  "Email:": "E-mail :",
 | 
					  "Email:": "E-mail :",
 | 
				
			||||||
  "Google verification code:": "Code de vérification Google :",
 | 
					  "Google verification code:": "Code de vérification Google :",
 | 
				
			||||||
  "Preferences": "Préférences",
 | 
					  "Preferences": "Préférences",
 | 
				
			||||||
  "Player preferences": "Préférences du Lecteur",
 | 
					  "Player preferences": "Préférences du lecteur",
 | 
				
			||||||
  "Always loop: ": "Lire en boucle : ",
 | 
					  "Always loop: ": "Lire en boucle : ",
 | 
				
			||||||
  "Autoplay: ": "Lire Automatiquement : ",
 | 
					  "Autoplay: ": "Lire automatiquement : ",
 | 
				
			||||||
  "Autoplay next video: ": "Lire automatiquement la vidéo suivante : ",
 | 
					  "Autoplay next video: ": "Lire automatiquement la vidéo suivante : ",
 | 
				
			||||||
  "Listen by default: ": "Audio Uniquement par défaut : ",
 | 
					  "Listen by default: ": "Audio uniquement : ",
 | 
				
			||||||
  "Proxy videos? ": "Souhaitez vous charger les vidéos à travers un proxy ?",
 | 
					  "Proxy videos? ": "Charger les vidéos à travers un proxy ? ",
 | 
				
			||||||
  "Default speed: ": "Vitesse par défaut : ",
 | 
					  "Default speed: ": "Vitesse par défaut : ",
 | 
				
			||||||
  "Preferred video quality: ": "Qualité vidéo souhaitée : ",
 | 
					  "Preferred video quality: ": "Qualité vidéo souhaitée : ",
 | 
				
			||||||
  "Player volume: ": "Volume du lecteur : ",
 | 
					  "Player volume: ": "Volume du lecteur : ",
 | 
				
			||||||
  "Default comments: ": "Source des Commentaires : ",
 | 
					  "Default comments: ": "Source des commentaires : ",
 | 
				
			||||||
  "Default captions: ": "Sous-titres principal : ",
 | 
					  "Default captions: ": "Sous-titres par défaut : ",
 | 
				
			||||||
  "Fallback captions: ": "Sous-titres secondaire : ",
 | 
					  "Fallback captions: ": "Fallback captions: ",
 | 
				
			||||||
  "Show related videos? ": "Voir les vidéos liées à ce sujet ? ",
 | 
					  "Show related videos? ": "Voir les vidéos liées ? ",
 | 
				
			||||||
  "Visual preferences": "Préférences du site",
 | 
					  "Visual preferences": "Préférences du site",
 | 
				
			||||||
  "Dark mode: ": "Mode Sombre : ",
 | 
					  "Dark mode: ": "Mode Sombre : ",
 | 
				
			||||||
  "Thin mode: ": "Mode Simplifié : ",
 | 
					  "Thin mode: ": "Mode Simplifié : ",
 | 
				
			||||||
@ -82,13 +82,13 @@
 | 
				
			|||||||
  "Watch history": "Historique de visionnage",
 | 
					  "Watch history": "Historique de visionnage",
 | 
				
			||||||
  "Delete account": "Supprimer votre compte",
 | 
					  "Delete account": "Supprimer votre compte",
 | 
				
			||||||
  "Administrator preferences": "Préferences d'Administrateur",
 | 
					  "Administrator preferences": "Préferences d'Administrateur",
 | 
				
			||||||
  "Default homepage: ": "Page d'accueil par defaut :",
 | 
					  "Default homepage: ": "Page d'accueil par défaut : ",
 | 
				
			||||||
  "Feed menu: ": "Menu des Flux :",
 | 
					  "Feed menu: ": "Menu des Flux : ",
 | 
				
			||||||
  "Top enabled? ": "Top activé ?",
 | 
					  "Top enabled? ": "Top activé ? ",
 | 
				
			||||||
  "CAPTCHA enabled? ": "CAPTCHA activé ?",
 | 
					  "CAPTCHA enabled? ": "CAPTCHA activé ? ",
 | 
				
			||||||
  "Login enabled? ": "Connexion activé ?",
 | 
					  "Login enabled? ": "Connexion activé ? ",
 | 
				
			||||||
  "Registration enabled? ": "Inscription activé ?",
 | 
					  "Registration enabled? ": "Inscription activée ? ",
 | 
				
			||||||
  "Report statistics? ": "Telemetrie activé ?",
 | 
					  "Report statistics? ": "Télémétrie activé ? ",
 | 
				
			||||||
  "Save preferences": "Enregistrer les préférences",
 | 
					  "Save preferences": "Enregistrer les préférences",
 | 
				
			||||||
  "Subscription manager": "Gestionnaire d'abonnement",
 | 
					  "Subscription manager": "Gestionnaire d'abonnement",
 | 
				
			||||||
  "`x` subscriptions": "`x` abonnements",
 | 
					  "`x` subscriptions": "`x` abonnements",
 | 
				
			||||||
@ -103,16 +103,18 @@
 | 
				
			|||||||
  "View JavaScript license information.": "Voir les informations des licences JavaScript.",
 | 
					  "View JavaScript license information.": "Voir les informations des licences JavaScript.",
 | 
				
			||||||
  "View privacy policy.": "Politique de confidentialité",
 | 
					  "View privacy policy.": "Politique de confidentialité",
 | 
				
			||||||
  "Trending": "Tendances",
 | 
					  "Trending": "Tendances",
 | 
				
			||||||
 | 
					  "Unlisted": "Non répertoriée",
 | 
				
			||||||
  "Watch video on Youtube": "Voir la vidéo sur Youtube",
 | 
					  "Watch video on Youtube": "Voir la vidéo sur Youtube",
 | 
				
			||||||
  "Genre: ": "Genre : ",
 | 
					  "Genre: ": "Genre : ",
 | 
				
			||||||
  "License: ": "Licence : ",
 | 
					  "License: ": "Licence : ",
 | 
				
			||||||
  "Family friendly? ": "Tout Public ? ",
 | 
					  "Family friendly? ": "Tout Public ? ",
 | 
				
			||||||
  "Wilson score: ": "Score de Wilson : ",
 | 
					  "Wilson score: ": "Score de Wilson : ",
 | 
				
			||||||
  "Engagement: ": "Poucentage de spectateur aillant aimé Liker ou Disliker la vidéo : ",
 | 
					  "Engagement: ": "Poucentage de spectateur aillant aimé Like ou Dislike la vidéo : ",
 | 
				
			||||||
  "Whitelisted regions: ": "Régions en liste blanche : ",
 | 
					  "Whitelisted regions: ": "Régions en liste blanche : ",
 | 
				
			||||||
  "Blacklisted regions: ": "Régions sur liste noire : ",
 | 
					  "Blacklisted regions: ": "Régions sur liste noire : ",
 | 
				
			||||||
  "Shared `x`": "Partagée `x`",
 | 
					  "Shared `x`": "Ajoutée le `x`",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Il semblerait que JavaScript sois désactivé. Cliquez ici pour voir les commentaires. Gardez à l'esprit que le chargement peut prendre plus de temps.",
 | 
					  "Premieres in `x`": "Première dans `x`",
 | 
				
			||||||
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Il semblerait que JavaScript soit désactivé. Cliquez ici pour voir les commentaires sans. Gardez à l'esprit que le chargement peut prendre plus de temps.",
 | 
				
			||||||
  "View YouTube comments": "Voir les commentaires YouTube",
 | 
					  "View YouTube comments": "Voir les commentaires YouTube",
 | 
				
			||||||
  "View more comments on Reddit": "Voir plus de commentaires sur Reddit",
 | 
					  "View more comments on Reddit": "Voir plus de commentaires sur Reddit",
 | 
				
			||||||
  "View `x` comments": "Voir `x` commentaires",
 | 
					  "View `x` comments": "Voir `x` commentaires",
 | 
				
			||||||
@ -124,13 +126,13 @@
 | 
				
			|||||||
  "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Si vous ne parvenez pas à vous connecter, assurez-vous que l'authentification à deux facteurs (Authenticator ou SMS) est activée.",
 | 
					  "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Si vous ne parvenez pas à vous connecter, assurez-vous que l'authentification à deux facteurs (Authenticator ou SMS) est activée.",
 | 
				
			||||||
  "Invalid TFA code": "Code d'authentification à deux facteurs invalide",
 | 
					  "Invalid TFA code": "Code d'authentification à deux facteurs invalide",
 | 
				
			||||||
  "Login failed. This may be because two-factor authentication is not enabled on your account.": "La connexion a échoué. Cela peut être dû au fait que l'authentification à deux facteurs n'est pas activée sur votre compte.",
 | 
					  "Login failed. This may be because two-factor authentication is not enabled on your account.": "La connexion a échoué. Cela peut être dû au fait que l'authentification à deux facteurs n'est pas activée sur votre compte.",
 | 
				
			||||||
  "Invalid answer": "Réponse non valide",
 | 
					  "Invalid answer": "Réponse invalide",
 | 
				
			||||||
  "Invalid CAPTCHA": "CAPTCHA invalide",
 | 
					  "Invalid CAPTCHA": "CAPTCHA invalide",
 | 
				
			||||||
  "CAPTCHA is a required field": "Veuillez rentrez un CAPTCHA",
 | 
					  "CAPTCHA is a required field": "Veuillez entrer un CAPTCHA",
 | 
				
			||||||
  "User ID is a required field": "Veuillez rentrez un Identifiant Utilisateur",
 | 
					  "User ID is a required field": "Veuillez entrer un Identifiant Utilisateur",
 | 
				
			||||||
  "Password is a required field": "Veuillez rentrez un Mot de passe",
 | 
					  "Password is a required field": "Veuillez entrer un Mot de passe",
 | 
				
			||||||
  "Invalid username or password": "Nom d'utilisateur ou mot de passe invalide",
 | 
					  "Invalid username or password": "Nom d'utilisateur ou mot de passe invalide",
 | 
				
			||||||
  "Please sign in using 'Sign in with Google'": "Veuillez vous connecter en utilisant \"S'identifier avec Google\"",
 | 
					  "Please sign in using 'Sign in with Google'": "Veuillez vous connecter en utilisant \"Se connecter avec Google\"",
 | 
				
			||||||
  "Password cannot be empty": "Le mot de passe ne peut pas être vide",
 | 
					  "Password cannot be empty": "Le mot de passe ne peut pas être vide",
 | 
				
			||||||
  "Password cannot be longer than 55 characters": "Le mot de passe ne doit pas comporter plus de 55 caractères",
 | 
					  "Password cannot be longer than 55 characters": "Le mot de passe ne doit pas comporter plus de 55 caractères",
 | 
				
			||||||
  "Please sign in": "Veuillez vous connecter",
 | 
					  "Please sign in": "Veuillez vous connecter",
 | 
				
			||||||
@ -268,7 +270,7 @@
 | 
				
			|||||||
  "`x` hours": "`x` heures",
 | 
					  "`x` hours": "`x` heures",
 | 
				
			||||||
  "`x` minutes": "`x` minutes",
 | 
					  "`x` minutes": "`x` minutes",
 | 
				
			||||||
  "`x` seconds": "`x` secondes",
 | 
					  "`x` seconds": "`x` secondes",
 | 
				
			||||||
  "Fallback comments: ": "Commentaires secondaires : ",
 | 
					  "Fallback comments: ": "Fallback comments: ",
 | 
				
			||||||
  "Popular": "Populaire",
 | 
					  "Popular": "Populaire",
 | 
				
			||||||
  "Top": "Top",
 | 
					  "Top": "Top",
 | 
				
			||||||
  "About": "A Propos",
 | 
					  "About": "A Propos",
 | 
				
			||||||
@ -289,5 +291,5 @@
 | 
				
			|||||||
  "Video mode": "Mode Vidéo",
 | 
					  "Video mode": "Mode Vidéo",
 | 
				
			||||||
  "Videos": "Vidéos",
 | 
					  "Videos": "Vidéos",
 | 
				
			||||||
  "Playlists": "Liste de lecture",
 | 
					  "Playlists": "Liste de lecture",
 | 
				
			||||||
  "Current version: ": "Version actuelle :"
 | 
					  "Current version: ": "Version :"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -103,6 +103,7 @@
 | 
				
			|||||||
  "View JavaScript license information.": "Guarda le informazioni di licenza del codice JavaScript.",
 | 
					  "View JavaScript license information.": "Guarda le informazioni di licenza del codice JavaScript.",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "",
 | 
				
			||||||
  "Trending": "Tendenze",
 | 
					  "Trending": "Tendenze",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Watch video on Youtube": "Guarda il video su YouTube",
 | 
					  "Watch video on Youtube": "Guarda il video su YouTube",
 | 
				
			||||||
  "Genre: ": "Genere: ",
 | 
					  "Genre: ": "Genere: ",
 | 
				
			||||||
  "License: ": "Licenza: ",
 | 
					  "License: ": "Licenza: ",
 | 
				
			||||||
@ -112,6 +113,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "Regioni nella lista bianca: ",
 | 
					  "Whitelisted regions: ": "Regioni nella lista bianca: ",
 | 
				
			||||||
  "Blacklisted regions: ": "Regioni nella lista nera: ",
 | 
					  "Blacklisted regions: ": "Regioni nella lista nera: ",
 | 
				
			||||||
  "Shared `x`": "Condiviso `x`",
 | 
					  "Shared `x`": "Condiviso `x`",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Ciao! Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti. Considera che potrebbe volerci più tempo.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Ciao! Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti. Considera che potrebbe volerci più tempo.",
 | 
				
			||||||
  "View YouTube comments": "Visualizza i commenti da YouTube",
 | 
					  "View YouTube comments": "Visualizza i commenti da YouTube",
 | 
				
			||||||
  "View more comments on Reddit": "Visualizza più commenti su Reddit",
 | 
					  "View more comments on Reddit": "Visualizza più commenti su Reddit",
 | 
				
			||||||
 | 
				
			|||||||
@ -103,6 +103,7 @@
 | 
				
			|||||||
  "View JavaScript license information.": "Vis JavaScript-lisensinfo.",
 | 
					  "View JavaScript license information.": "Vis JavaScript-lisensinfo.",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "",
 | 
				
			||||||
  "Trending": "Trendsettende",
 | 
					  "Trending": "Trendsettende",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Watch video on Youtube": "Vis video på YouTube",
 | 
					  "Watch video on Youtube": "Vis video på YouTube",
 | 
				
			||||||
  "Genre: ": "Sjanger: ",
 | 
					  "Genre: ": "Sjanger: ",
 | 
				
			||||||
  "License: ": "Lisens: ",
 | 
					  "License: ": "Lisens: ",
 | 
				
			||||||
@ -112,6 +113,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "Hvitlistede regioner: ",
 | 
					  "Whitelisted regions: ": "Hvitlistede regioner: ",
 | 
				
			||||||
  "Blacklisted regions: ": "Svartelistede regioner: ",
 | 
					  "Blacklisted regions: ": "Svartelistede regioner: ",
 | 
				
			||||||
  "Shared `x`": "Delt `x`",
 | 
					  "Shared `x`": "Delt `x`",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hei. Det ser ut til at du har JavaScript avslått. Klikk her for å vise kommentarer, ha i minnet at innlasting tar lengre tid.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hei. Det ser ut til at du har JavaScript avslått. Klikk her for å vise kommentarer, ha i minnet at innlasting tar lengre tid.",
 | 
				
			||||||
  "View YouTube comments": "Vis YouTube-kommentarer",
 | 
					  "View YouTube comments": "Vis YouTube-kommentarer",
 | 
				
			||||||
  "View more comments on Reddit": "Vis flere kommenterer på Reddit",
 | 
					  "View more comments on Reddit": "Vis flere kommenterer på Reddit",
 | 
				
			||||||
 | 
				
			|||||||
@ -103,6 +103,7 @@
 | 
				
			|||||||
  "View JavaScript license information.": "Bekijk JavaScript licentie informatie.",
 | 
					  "View JavaScript license information.": "Bekijk JavaScript licentie informatie.",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "",
 | 
				
			||||||
  "Trending": "Trending",
 | 
					  "Trending": "Trending",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Watch video on Youtube": "Bekijk video op Youtube",
 | 
					  "Watch video on Youtube": "Bekijk video op Youtube",
 | 
				
			||||||
  "Genre: ": "Genre: ",
 | 
					  "Genre: ": "Genre: ",
 | 
				
			||||||
  "License: ": "Licentie: ",
 | 
					  "License: ": "Licentie: ",
 | 
				
			||||||
@ -112,6 +113,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "Toegestane regio's: ",
 | 
					  "Whitelisted regions: ": "Toegestane regio's: ",
 | 
				
			||||||
  "Blacklisted regions: ": "Geblokkeerde regio's: ",
 | 
					  "Blacklisted regions: ": "Geblokkeerde regio's: ",
 | 
				
			||||||
  "Shared `x`": "`x` gedeeld",
 | 
					  "Shared `x`": "`x` gedeeld",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hoi! Het lijkt erop dat je JavaScript uit hebt staan. Klik hier om de reacties te bekijken, hou er rekening mee dat het wat langer duurt om te laden.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hoi! Het lijkt erop dat je JavaScript uit hebt staan. Klik hier om de reacties te bekijken, hou er rekening mee dat het wat langer duurt om te laden.",
 | 
				
			||||||
  "View YouTube comments": "Bekijk YouTube reacties",
 | 
					  "View YouTube comments": "Bekijk YouTube reacties",
 | 
				
			||||||
  "View more comments on Reddit": "Bekijk meer reacties op Reddit",
 | 
					  "View more comments on Reddit": "Bekijk meer reacties op Reddit",
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@
 | 
				
			|||||||
  "newest": "najnowsze",
 | 
					  "newest": "najnowsze",
 | 
				
			||||||
  "oldest": "najstarsze",
 | 
					  "oldest": "najstarsze",
 | 
				
			||||||
  "popular": "popularne",
 | 
					  "popular": "popularne",
 | 
				
			||||||
  "last": "",
 | 
					  "last": "ostatnie",
 | 
				
			||||||
  "Next page": "Następna strona",
 | 
					  "Next page": "Następna strona",
 | 
				
			||||||
  "Previous page": "Poprzednia strona",
 | 
					  "Previous page": "Poprzednia strona",
 | 
				
			||||||
  "Clear watch history?": "Wyczyścić historię?",
 | 
					  "Clear watch history?": "Wyczyścić historię?",
 | 
				
			||||||
@ -50,7 +50,7 @@
 | 
				
			|||||||
  "Autoplay: ": "Autoodtwarzanie: ",
 | 
					  "Autoplay: ": "Autoodtwarzanie: ",
 | 
				
			||||||
  "Autoplay next video: ": "Odtwórz następny film: ",
 | 
					  "Autoplay next video: ": "Odtwórz następny film: ",
 | 
				
			||||||
  "Listen by default: ": "Tryb dźwiękowy: ",
 | 
					  "Listen by default: ": "Tryb dźwiękowy: ",
 | 
				
			||||||
  "Proxy videos? ": "",
 | 
					  "Proxy videos? ": "Filmy przez proxy? ",
 | 
				
			||||||
  "Default speed: ": "Domyślna prędkość: ",
 | 
					  "Default speed: ": "Domyślna prędkość: ",
 | 
				
			||||||
  "Preferred video quality: ": "Preferowana jakość filmów: ",
 | 
					  "Preferred video quality: ": "Preferowana jakość filmów: ",
 | 
				
			||||||
  "Player volume: ": "Głośność odtwarzacza: ",
 | 
					  "Player volume: ": "Głośność odtwarzacza: ",
 | 
				
			||||||
@ -101,8 +101,9 @@
 | 
				
			|||||||
  "Released under the AGPLv3 by Omar Roth.": "Wydano na licencji AGPLv3 przez Omar Roth.",
 | 
					  "Released under the AGPLv3 by Omar Roth.": "Wydano na licencji AGPLv3 przez Omar Roth.",
 | 
				
			||||||
  "Source available here.": "Kod źródłowy dostępny tutaj.",
 | 
					  "Source available here.": "Kod źródłowy dostępny tutaj.",
 | 
				
			||||||
  "View JavaScript license information.": "Wyświetl informację o licencji JavaScript.",
 | 
					  "View JavaScript license information.": "Wyświetl informację o licencji JavaScript.",
 | 
				
			||||||
  "View privacy policy.": "",
 | 
					  "View privacy policy.": "Polityka prywatności.",
 | 
				
			||||||
  "Trending": "Na czasie",
 | 
					  "Trending": "Na czasie",
 | 
				
			||||||
 | 
					  "Unlisted": "",
 | 
				
			||||||
  "Watch video on Youtube": "Zobacz film na YouTube",
 | 
					  "Watch video on Youtube": "Zobacz film na YouTube",
 | 
				
			||||||
  "Genre: ": "Gatunek: ",
 | 
					  "Genre: ": "Gatunek: ",
 | 
				
			||||||
  "License: ": "Licencja: ",
 | 
					  "License: ": "Licencja: ",
 | 
				
			||||||
@ -112,6 +113,7 @@
 | 
				
			|||||||
  "Whitelisted regions: ": "Dostępny na obszarach: ",
 | 
					  "Whitelisted regions: ": "Dostępny na obszarach: ",
 | 
				
			||||||
  "Blacklisted regions: ": "Niedostępny na obszarach: ",
 | 
					  "Blacklisted regions: ": "Niedostępny na obszarach: ",
 | 
				
			||||||
  "Shared `x`": "Udostępniono `x`",
 | 
					  "Shared `x`": "Udostępniono `x`",
 | 
				
			||||||
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Cześć! Wygląda na to, że masz wyłączoną obsługę JavaScriptu. Kliknij tutaj, żeby zobaczyć komentarze. Pamiętaj, że wczytywanie może potrwać dłużej.",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Cześć! Wygląda na to, że masz wyłączoną obsługę JavaScriptu. Kliknij tutaj, żeby zobaczyć komentarze. Pamiętaj, że wczytywanie może potrwać dłużej.",
 | 
				
			||||||
  "View YouTube comments": "Wyświetl komentarze z YouTube",
 | 
					  "View YouTube comments": "Wyświetl komentarze z YouTube",
 | 
				
			||||||
  "View more comments on Reddit": "Wyświetl więcej komentarzy na Reddicie",
 | 
					  "View more comments on Reddit": "Wyświetl więcej komentarzy na Reddicie",
 | 
				
			||||||
@ -270,7 +272,7 @@
 | 
				
			|||||||
  "`x` seconds": "`x` sekund",
 | 
					  "`x` seconds": "`x` sekund",
 | 
				
			||||||
  "Fallback comments: ": "Zastępcze komentarze: ",
 | 
					  "Fallback comments: ": "Zastępcze komentarze: ",
 | 
				
			||||||
  "Popular": "Popularne",
 | 
					  "Popular": "Popularne",
 | 
				
			||||||
  "Top": "Na czasie",
 | 
					  "Top": "Najczęściej oglądane",
 | 
				
			||||||
  "About": "Informacje",
 | 
					  "About": "Informacje",
 | 
				
			||||||
  "Rating: ": "Ocena: ",
 | 
					  "Rating: ": "Ocena: ",
 | 
				
			||||||
  "Language: ": "Język: ",
 | 
					  "Language: ": "Język: ",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										588
									
								
								locales/ru.json
									
									
									
									
									
								
							
							
						
						
									
										588
									
								
								locales/ru.json
									
									
									
									
									
								
							@ -1,295 +1,297 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "`x` subscribers": "`x` подписчиков",
 | 
					  "`x` subscribers": "`x` подписчиков",
 | 
				
			||||||
    "`x` videos": "`x` видео",
 | 
					  "`x` videos": "`x` видео",
 | 
				
			||||||
    "LIVE": "ПРЯМОЙ ЭФИР",
 | 
					  "LIVE": "ПРЯМОЙ ЭФИР",
 | 
				
			||||||
    "Shared `x` ago": "Опубликовано `x` назад",
 | 
					  "Shared `x` ago": "Опубликовано `x` назад",
 | 
				
			||||||
    "Unsubscribe": "Отписаться",
 | 
					  "Unsubscribe": "Отписаться",
 | 
				
			||||||
    "Subscribe": "Подписаться",
 | 
					  "Subscribe": "Подписаться",
 | 
				
			||||||
    "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`",
 | 
					  "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`",
 | 
				
			||||||
    "View channel on YouTube": "Канал на YouTube",
 | 
					  "View channel on YouTube": "Канал на YouTube",
 | 
				
			||||||
    "newest": "новые",
 | 
					  "newest": "новые",
 | 
				
			||||||
    "oldest": "старые",
 | 
					  "oldest": "старые",
 | 
				
			||||||
    "popular": "популярные",
 | 
					  "popular": "популярные",
 | 
				
			||||||
    "last": "недавно обновленные",
 | 
					  "last": "недавно обновленные",
 | 
				
			||||||
    "Next page": "Следующая страница",
 | 
					  "Next page": "Следующая страница",
 | 
				
			||||||
    "Previous page": "Предыдущая страница",
 | 
					  "Previous page": "Предыдущая страница",
 | 
				
			||||||
    "Clear watch history?": "Очистить историю просмотров?",
 | 
					  "Clear watch history?": "Очистить историю просмотров?",
 | 
				
			||||||
    "Yes": "Да",
 | 
					  "Yes": "Да",
 | 
				
			||||||
    "No": "Нет",
 | 
					  "No": "Нет",
 | 
				
			||||||
    "Import and Export Data": "Импорт и экспорт данных",
 | 
					  "Import and Export Data": "Импорт и экспорт данных",
 | 
				
			||||||
    "Import": "Импорт",
 | 
					  "Import": "Импорт",
 | 
				
			||||||
    "Import Invidious data": "Импортировать данные Invidious",
 | 
					  "Import Invidious data": "Импортировать данные Invidious",
 | 
				
			||||||
    "Import YouTube subscriptions": "Импортировать YouTube подписки",
 | 
					  "Import YouTube subscriptions": "Импортировать YouTube подписки",
 | 
				
			||||||
    "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)",
 | 
					  "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)",
 | 
				
			||||||
    "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)",
 | 
					  "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)",
 | 
				
			||||||
    "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)",
 | 
					  "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)",
 | 
				
			||||||
    "Export": "Экспорт",
 | 
					  "Export": "Экспорт",
 | 
				
			||||||
    "Export subscriptions as OPML": "Экспортировать подписки в OPML",
 | 
					  "Export subscriptions as OPML": "Экспортировать подписки в OPML",
 | 
				
			||||||
    "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)",
 | 
					  "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)",
 | 
				
			||||||
    "Export data as JSON": "Экспортировать данные в JSON",
 | 
					  "Export data as JSON": "Экспортировать данные в JSON",
 | 
				
			||||||
    "Delete account?": "Удалить аккаунт?",
 | 
					  "Delete account?": "Удалить аккаунт?",
 | 
				
			||||||
    "History": "История",
 | 
					  "History": "История",
 | 
				
			||||||
    "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube",
 | 
					  "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube",
 | 
				
			||||||
    "JavaScript license information": "Лицензии JavaScript",
 | 
					  "JavaScript license information": "Лицензии JavaScript",
 | 
				
			||||||
    "source": "источник",
 | 
					  "source": "источник",
 | 
				
			||||||
    "Login": "Войти",
 | 
					  "Login": "Войти",
 | 
				
			||||||
    "Login/Register": "Войти/Регистрация",
 | 
					  "Login/Register": "Войти/Регистрация",
 | 
				
			||||||
    "Login to Google": "Войти через Google",
 | 
					  "Login to Google": "Войти через Google",
 | 
				
			||||||
    "User ID:": "ID пользователя:",
 | 
					  "User ID:": "ID пользователя:",
 | 
				
			||||||
    "Password:": "Пароль:",
 | 
					  "Password:": "Пароль:",
 | 
				
			||||||
    "Time (h:mm:ss):": "Время (ч:мм:сс):",
 | 
					  "Time (h:mm:ss):": "Время (ч:мм:сс):",
 | 
				
			||||||
    "Text CAPTCHA": "Текст капчи",
 | 
					  "Text CAPTCHA": "Текст капчи",
 | 
				
			||||||
    "Image CAPTCHA": "Изображение капчи",
 | 
					  "Image CAPTCHA": "Изображение капчи",
 | 
				
			||||||
    "Sign In": "Войти",
 | 
					  "Sign In": "Войти",
 | 
				
			||||||
    "Register": "Регистрация",
 | 
					  "Register": "Регистрация",
 | 
				
			||||||
    "Email:": "Эл. почта:",
 | 
					  "Email:": "Эл. почта:",
 | 
				
			||||||
    "Google verification code:": "Код подтверждения Google:",
 | 
					  "Google verification code:": "Код подтверждения Google:",
 | 
				
			||||||
    "Preferences": "Настройки",
 | 
					  "Preferences": "Настройки",
 | 
				
			||||||
    "Player preferences": "Настройки проигрывателя",
 | 
					  "Player preferences": "Настройки проигрывателя",
 | 
				
			||||||
    "Always loop: ": "Всегда повторять: ",
 | 
					  "Always loop: ": "Всегда повторять: ",
 | 
				
			||||||
    "Autoplay: ": "Автовоспроизведение: ",
 | 
					  "Autoplay: ": "Автовоспроизведение: ",
 | 
				
			||||||
    "Autoplay next video: ": "Автовоспроизведение следующего видео: ",
 | 
					  "Autoplay next video: ": "Автовоспроизведение следующего видео: ",
 | 
				
			||||||
    "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ",
 | 
					  "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ",
 | 
				
			||||||
    "Proxy videos? ": "Проксировать видео? ",
 | 
					  "Proxy videos? ": "Проксировать видео? ",
 | 
				
			||||||
    "Default speed: ": "Скорость по-умолчанию: ",
 | 
					  "Default speed: ": "Скорость по-умолчанию: ",
 | 
				
			||||||
    "Preferred video quality: ": "Предпочтительное качество видео: ",
 | 
					  "Preferred video quality: ": "Предпочтительное качество видео: ",
 | 
				
			||||||
    "Player volume: ": "Громкость воспроизведения: ",
 | 
					  "Player volume: ": "Громкость воспроизведения: ",
 | 
				
			||||||
    "Default comments: ": "Источник комментариев: ",
 | 
					  "Default comments: ": "Источник комментариев: ",
 | 
				
			||||||
    "youtube": "YouTube",
 | 
					  "youtube": "YouTube",
 | 
				
			||||||
    "reddit": "Reddit",
 | 
					  "reddit": "Reddit",
 | 
				
			||||||
    "Default captions: ": "Субтитры по-умолчанию: ",
 | 
					  "Default captions: ": "Субтитры по-умолчанию: ",
 | 
				
			||||||
    "Fallback captions: ": "Резервные субтитры: ",
 | 
					  "Fallback captions: ": "Резервные субтитры: ",
 | 
				
			||||||
    "Show related videos? ": "Показывать похожие видео? ",
 | 
					  "Show related videos? ": "Показывать похожие видео? ",
 | 
				
			||||||
    "Visual preferences": "Визуальные настройки",
 | 
					  "Visual preferences": "Визуальные настройки",
 | 
				
			||||||
    "Dark mode: ": "Темная тема: ",
 | 
					  "Dark mode: ": "Темная тема: ",
 | 
				
			||||||
    "Thin mode: ": "Облегченный режим: ",
 | 
					  "Thin mode: ": "Облегченный режим: ",
 | 
				
			||||||
    "Subscription preferences": "Настройки подписок",
 | 
					  "Subscription preferences": "Настройки подписок",
 | 
				
			||||||
    "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ",
 | 
					  "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ",
 | 
				
			||||||
    "Number of videos shown in feed: ": "Число видео в ленте: ",
 | 
					  "Number of videos shown in feed: ": "Число видео в ленте: ",
 | 
				
			||||||
    "Sort videos by: ": "Сортировать видео по: ",
 | 
					  "Sort videos by: ": "Сортировать видео по: ",
 | 
				
			||||||
    "published": "дате публикации",
 | 
					  "published": "дате публикации",
 | 
				
			||||||
    "published - reverse": "дате - обратный порядок",
 | 
					  "published - reverse": "дате - обратный порядок",
 | 
				
			||||||
    "alphabetically": "алфавиту",
 | 
					  "alphabetically": "алфавиту",
 | 
				
			||||||
    "alphabetically - reverse": "алфавиту - обратный порядок",
 | 
					  "alphabetically - reverse": "алфавиту - обратный порядок",
 | 
				
			||||||
    "channel name": "имени канала",
 | 
					  "channel name": "имени канала",
 | 
				
			||||||
    "channel name - reverse": "имени канала - обратный порядок",
 | 
					  "channel name - reverse": "имени канала - обратный порядок",
 | 
				
			||||||
    "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ",
 | 
					  "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ",
 | 
				
			||||||
    "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ",
 | 
					  "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ",
 | 
				
			||||||
    "Only show unwatched: ": "Отображать только непросмотренные видео: ",
 | 
					  "Only show unwatched: ": "Отображать только непросмотренные видео: ",
 | 
				
			||||||
    "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ",
 | 
					  "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ",
 | 
				
			||||||
    "Data preferences": "Настройки данных",
 | 
					  "Data preferences": "Настройки данных",
 | 
				
			||||||
    "Clear watch history": "Очистить историю просмотра",
 | 
					  "Clear watch history": "Очистить историю просмотра",
 | 
				
			||||||
    "Import/Export data": "Импорт/Экспорт данных",
 | 
					  "Import/Export data": "Импорт/Экспорт данных",
 | 
				
			||||||
    "Manage subscriptions": "Управление подписками",
 | 
					  "Manage subscriptions": "Управление подписками",
 | 
				
			||||||
    "Watch history": "История просмотров",
 | 
					  "Watch history": "История просмотров",
 | 
				
			||||||
    "Delete account": "Удалить аккаунт",
 | 
					  "Delete account": "Удалить аккаунт",
 | 
				
			||||||
    "Administrator preferences": "Настройки администратора",
 | 
					  "Administrator preferences": "Настройки администратора",
 | 
				
			||||||
    "Default homepage: ": "Главная страница по умолчанию: ",
 | 
					  "Default homepage: ": "Главная страница по умолчанию: ",
 | 
				
			||||||
    "Feed menu: ": "Меню ленты: ",
 | 
					  "Feed menu: ": "Меню ленты: ",
 | 
				
			||||||
    "Top enabled? ": "Включить ТОП? ",
 | 
					  "Top enabled? ": "Включить ТОП? ",
 | 
				
			||||||
    "CAPTCHA enabled? ": "Включить капчу? ",
 | 
					  "CAPTCHA enabled? ": "Включить капчу? ",
 | 
				
			||||||
    "Login enabled? ": "Включить логин? ",
 | 
					  "Login enabled? ": "Включить логин? ",
 | 
				
			||||||
    "Registration enabled? ": "Включить регистрацию? ",
 | 
					  "Registration enabled? ": "Включить регистрацию? ",
 | 
				
			||||||
    "Report statistics? ": "Отображать статистику? ",
 | 
					  "Report statistics? ": "Отображать статистику? ",
 | 
				
			||||||
    "Save preferences": "Сохранить настройки",
 | 
					  "Save preferences": "Сохранить настройки",
 | 
				
			||||||
    "Subscription manager": "Менеджер подписок",
 | 
					  "Subscription manager": "Менеджер подписок",
 | 
				
			||||||
    "`x` subscriptions": "`x` подписок",
 | 
					  "`x` subscriptions": "`x` подписок",
 | 
				
			||||||
    "Import/Export": "Импорт/Экспорт",
 | 
					  "Import/Export": "Импорт/Экспорт",
 | 
				
			||||||
    "unsubscribe": "отписаться",
 | 
					  "unsubscribe": "отписаться",
 | 
				
			||||||
    "Subscriptions": "Подписки",
 | 
					  "Subscriptions": "Подписки",
 | 
				
			||||||
    "`x` unseen notifications": "`x` новых оповещений",
 | 
					  "`x` unseen notifications": "`x` новых оповещений",
 | 
				
			||||||
    "search": "поиск",
 | 
					  "search": "поиск",
 | 
				
			||||||
    "Sign out": "Выйти",
 | 
					  "Sign out": "Выйти",
 | 
				
			||||||
    "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.",
 | 
					  "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.",
 | 
				
			||||||
    "Source available here.": "Исходный код доступен здесь.",
 | 
					  "Source available here.": "Исходный код доступен здесь.",
 | 
				
			||||||
    "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.",
 | 
					  "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.",
 | 
				
			||||||
    "View privacy policy.": "См. политику конфиденциальности.",
 | 
					  "View privacy policy.": "См. политику конфиденциальности.",
 | 
				
			||||||
    "Trending": "В тренде",
 | 
					  "Trending": "В тренде",
 | 
				
			||||||
    "Watch video on Youtube": "Смотреть на YouTube",
 | 
					  "Unlisted": "",
 | 
				
			||||||
    "Genre: ": "Жанр: ",
 | 
					  "Watch video on Youtube": "Смотреть на YouTube",
 | 
				
			||||||
    "License: ": "Лицензия: ",
 | 
					  "Genre: ": "Жанр: ",
 | 
				
			||||||
    "Family friendly? ": "Семейный просмотр: ",
 | 
					  "License: ": "Лицензия: ",
 | 
				
			||||||
    "Wilson score: ": "Рейтинг Вильсона: ",
 | 
					  "Family friendly? ": "Семейный просмотр: ",
 | 
				
			||||||
    "Engagement: ": "Вовлеченность: ",
 | 
					  "Wilson score: ": "Рейтинг Вильсона: ",
 | 
				
			||||||
    "Whitelisted regions: ": "Доступно для: ",
 | 
					  "Engagement: ": "Вовлеченность: ",
 | 
				
			||||||
    "Blacklisted regions: ": "Недоступно для: ",
 | 
					  "Whitelisted regions: ": "Доступно для: ",
 | 
				
			||||||
    "Shared `x`": "Опубликовано `x`",
 | 
					  "Blacklisted regions: ": "Недоступно для: ",
 | 
				
			||||||
    "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).",
 | 
					  "Shared `x`": "Опубликовано `x`",
 | 
				
			||||||
    "View YouTube comments": "Смотреть комментарии с YouTube",
 | 
					  "Premieres in `x`": "",
 | 
				
			||||||
    "View more comments on Reddit": "Больше комментариев на Reddit",
 | 
					  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).",
 | 
				
			||||||
    "View `x` comments": "Показать `x` комментариев",
 | 
					  "View YouTube comments": "Смотреть комментарии с YouTube",
 | 
				
			||||||
    "View Reddit comments": "Смотреть комментарии с Reddit",
 | 
					  "View more comments on Reddit": "Больше комментариев на Reddit",
 | 
				
			||||||
    "Hide replies": "Скрыть ответы",
 | 
					  "View `x` comments": "Показать `x` комментариев",
 | 
				
			||||||
    "Show replies": "Показать ответы",
 | 
					  "View Reddit comments": "Смотреть комментарии с Reddit",
 | 
				
			||||||
    "Incorrect password": "Неправильный пароль",
 | 
					  "Hide replies": "Скрыть ответы",
 | 
				
			||||||
    "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов",
 | 
					  "Show replies": "Показать ответы",
 | 
				
			||||||
    "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.",
 | 
					  "Incorrect password": "Неправильный пароль",
 | 
				
			||||||
    "Invalid TFA code": "Неправильный TFA код",
 | 
					  "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов",
 | 
				
			||||||
    "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.",
 | 
					  "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.",
 | 
				
			||||||
    "Invalid answer": "Неверный ответ",
 | 
					  "Invalid TFA code": "Неправильный TFA код",
 | 
				
			||||||
    "Invalid CAPTCHA": "Неверная капча",
 | 
					  "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.",
 | 
				
			||||||
    "CAPTCHA is a required field": "Необходимо ввести капчу",
 | 
					  "Invalid answer": "Неверный ответ",
 | 
				
			||||||
    "User ID is a required field": "Необходимо ввести идентификатор пользователя",
 | 
					  "Invalid CAPTCHA": "Неверная капча",
 | 
				
			||||||
    "Password is a required field": "Необходимо ввести пароль",
 | 
					  "CAPTCHA is a required field": "Необходимо ввести капчу",
 | 
				
			||||||
    "Invalid username or password": "Недопустимый пароль или имя пользователя",
 | 
					  "User ID is a required field": "Необходимо ввести идентификатор пользователя",
 | 
				
			||||||
    "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google",
 | 
					  "Password is a required field": "Необходимо ввести пароль",
 | 
				
			||||||
    "Password cannot be empty": "Пароль не может быть пустым",
 | 
					  "Invalid username or password": "Недопустимый пароль или имя пользователя",
 | 
				
			||||||
    "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов",
 | 
					  "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google",
 | 
				
			||||||
    "Please sign in": "Пожалуйста, войдите",
 | 
					  "Password cannot be empty": "Пароль не может быть пустым",
 | 
				
			||||||
    "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`",
 | 
					  "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов",
 | 
				
			||||||
    "channel:`x`": "канал: `x`",
 | 
					  "Please sign in": "Пожалуйста, войдите",
 | 
				
			||||||
    "Deleted or invalid channel": "Канал удален или не найден",
 | 
					  "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`",
 | 
				
			||||||
    "This channel does not exist.": "Такой канал не существует.",
 | 
					  "channel:`x`": "канал: `x`",
 | 
				
			||||||
    "Could not get channel info.": "Невозможно получить информацию о канале.",
 | 
					  "Deleted or invalid channel": "Канал удален или не найден",
 | 
				
			||||||
    "Could not fetch comments": "Невозможно получить комментарии",
 | 
					  "This channel does not exist.": "Такой канал не существует.",
 | 
				
			||||||
    "View `x` replies": "Показать `x` ответов",
 | 
					  "Could not get channel info.": "Невозможно получить информацию о канале.",
 | 
				
			||||||
    "`x` ago": "`x` назад",
 | 
					  "Could not fetch comments": "Невозможно получить комментарии",
 | 
				
			||||||
    "Load more": "Загрузить больше",
 | 
					  "View `x` replies": "Показать `x` ответов",
 | 
				
			||||||
    "`x` points": "`x` очков",
 | 
					  "`x` ago": "`x` назад",
 | 
				
			||||||
    "Could not create mix.": "Невозможно создать \"микс\".",
 | 
					  "Load more": "Загрузить больше",
 | 
				
			||||||
    "Playlist is empty": "Плейлист пуст",
 | 
					  "`x` points": "`x` очков",
 | 
				
			||||||
    "Invalid playlist.": "Некорректный плейлист.",
 | 
					  "Could not create mix.": "Невозможно создать \"микс\".",
 | 
				
			||||||
    "Playlist does not exist.": "Плейлист не существует.",
 | 
					  "Playlist is empty": "Плейлист пуст",
 | 
				
			||||||
    "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".",
 | 
					  "Invalid playlist.": "Некорректный плейлист.",
 | 
				
			||||||
    "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"",
 | 
					  "Playlist does not exist.": "Плейлист не существует.",
 | 
				
			||||||
    "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"",
 | 
					  "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".",
 | 
				
			||||||
    "Invalid challenge": "Неправильный ответ в \"challenge\"",
 | 
					  "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"",
 | 
				
			||||||
    "Invalid token": "Неправильный токен",
 | 
					  "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"",
 | 
				
			||||||
    "Invalid user": "Недопустимое имя пользователя",
 | 
					  "Invalid challenge": "Неправильный ответ в \"challenge\"",
 | 
				
			||||||
    "Token is expired, please try again": "Срок действия токена истек, попробуйте позже",
 | 
					  "Invalid token": "Неправильный токен",
 | 
				
			||||||
    "English": "Английский",
 | 
					  "Invalid user": "Недопустимое имя пользователя",
 | 
				
			||||||
    "English (auto-generated)": "Английский (созданы автоматически)",
 | 
					  "Token is expired, please try again": "Срок действия токена истек, попробуйте позже",
 | 
				
			||||||
    "Afrikaans": "Африкаанс",
 | 
					  "English": "Английский",
 | 
				
			||||||
    "Albanian": "Албанский",
 | 
					  "English (auto-generated)": "Английский (созданы автоматически)",
 | 
				
			||||||
    "Amharic": "Амхарский",
 | 
					  "Afrikaans": "Африкаанс",
 | 
				
			||||||
    "Arabic": "Арабский",
 | 
					  "Albanian": "Албанский",
 | 
				
			||||||
    "Armenian": "Армянский",
 | 
					  "Amharic": "Амхарский",
 | 
				
			||||||
    "Azerbaijani": "Азербайджанский",
 | 
					  "Arabic": "Арабский",
 | 
				
			||||||
    "Bangla": "Бенгальский",
 | 
					  "Armenian": "Армянский",
 | 
				
			||||||
    "Basque": "Баскский",
 | 
					  "Azerbaijani": "Азербайджанский",
 | 
				
			||||||
    "Belarusian": "Белорусский",
 | 
					  "Bangla": "Бенгальский",
 | 
				
			||||||
    "Bosnian": "Боснийский",
 | 
					  "Basque": "Баскский",
 | 
				
			||||||
    "Bulgarian": "Болгарский",
 | 
					  "Belarusian": "Белорусский",
 | 
				
			||||||
    "Burmese": "Бирманский",
 | 
					  "Bosnian": "Боснийский",
 | 
				
			||||||
    "Catalan": "Каталонский",
 | 
					  "Bulgarian": "Болгарский",
 | 
				
			||||||
    "Cebuano": "Себуанский",
 | 
					  "Burmese": "Бирманский",
 | 
				
			||||||
    "Chinese (Simplified)": "Китайский (упрощенный)",
 | 
					  "Catalan": "Каталонский",
 | 
				
			||||||
    "Chinese (Traditional)": "Китайский (традиционный)",
 | 
					  "Cebuano": "Себуанский",
 | 
				
			||||||
    "Corsican": "Корсиканский",
 | 
					  "Chinese (Simplified)": "Китайский (упрощенный)",
 | 
				
			||||||
    "Croatian": "Хорватский",
 | 
					  "Chinese (Traditional)": "Китайский (традиционный)",
 | 
				
			||||||
    "Czech": "Чешский",
 | 
					  "Corsican": "Корсиканский",
 | 
				
			||||||
    "Danish": "Датский",
 | 
					  "Croatian": "Хорватский",
 | 
				
			||||||
    "Dutch": "Нидерландский",
 | 
					  "Czech": "Чешский",
 | 
				
			||||||
    "Esperanto": "Эсперанто",
 | 
					  "Danish": "Датский",
 | 
				
			||||||
    "Estonian": "Эстонский",
 | 
					  "Dutch": "Нидерландский",
 | 
				
			||||||
    "Filipino": "Филиппинский",
 | 
					  "Esperanto": "Эсперанто",
 | 
				
			||||||
    "Finnish": "Финский",
 | 
					  "Estonian": "Эстонский",
 | 
				
			||||||
    "French": "Французский",
 | 
					  "Filipino": "Филиппинский",
 | 
				
			||||||
    "Galician": "Галисийский",
 | 
					  "Finnish": "Финский",
 | 
				
			||||||
    "Georgian": "Грузинский",
 | 
					  "French": "Французский",
 | 
				
			||||||
    "German": "Немецкий",
 | 
					  "Galician": "Галисийский",
 | 
				
			||||||
    "Greek": "Греческий",
 | 
					  "Georgian": "Грузинский",
 | 
				
			||||||
    "Gujarati": "Гуджаратский",
 | 
					  "German": "Немецкий",
 | 
				
			||||||
    "Haitian Creole": "Гаит. креольский",
 | 
					  "Greek": "Греческий",
 | 
				
			||||||
    "Hausa": "Хауса",
 | 
					  "Gujarati": "Гуджаратский",
 | 
				
			||||||
    "Hawaiian": "Гавайский",
 | 
					  "Haitian Creole": "Гаит. креольский",
 | 
				
			||||||
    "Hebrew": "Иврит",
 | 
					  "Hausa": "Хауса",
 | 
				
			||||||
    "Hindi": "Хинди",
 | 
					  "Hawaiian": "Гавайский",
 | 
				
			||||||
    "Hmong": "Хмонг (мяо)",
 | 
					  "Hebrew": "Иврит",
 | 
				
			||||||
    "Hungarian": "Венгерский",
 | 
					  "Hindi": "Хинди",
 | 
				
			||||||
    "Icelandic": "Исландский",
 | 
					  "Hmong": "Хмонг (мяо)",
 | 
				
			||||||
    "Igbo": "Игбо",
 | 
					  "Hungarian": "Венгерский",
 | 
				
			||||||
    "Indonesian": "Индонезийский",
 | 
					  "Icelandic": "Исландский",
 | 
				
			||||||
    "Irish": "Ирландский",
 | 
					  "Igbo": "Игбо",
 | 
				
			||||||
    "Italian": "Итальянский",
 | 
					  "Indonesian": "Индонезийский",
 | 
				
			||||||
    "Japanese": "Японский",
 | 
					  "Irish": "Ирландский",
 | 
				
			||||||
    "Javanese": "Яванский",
 | 
					  "Italian": "Итальянский",
 | 
				
			||||||
    "Kannada": "Каннада",
 | 
					  "Japanese": "Японский",
 | 
				
			||||||
    "Kazakh": "Казахский",
 | 
					  "Javanese": "Яванский",
 | 
				
			||||||
    "Khmer": "Кхмерский",
 | 
					  "Kannada": "Каннада",
 | 
				
			||||||
    "Korean": "Корейский",
 | 
					  "Kazakh": "Казахский",
 | 
				
			||||||
    "Kurdish": "Курдский",
 | 
					  "Khmer": "Кхмерский",
 | 
				
			||||||
    "Kyrgyz": "Киргизский",
 | 
					  "Korean": "Корейский",
 | 
				
			||||||
    "Lao": "Лаосский",
 | 
					  "Kurdish": "Курдский",
 | 
				
			||||||
    "Latin": "Латинский",
 | 
					  "Kyrgyz": "Киргизский",
 | 
				
			||||||
    "Latvian": "Латышский",
 | 
					  "Lao": "Лаосский",
 | 
				
			||||||
    "Lithuanian": "Литовский",
 | 
					  "Latin": "Латинский",
 | 
				
			||||||
    "Luxembourgish": "Люксембургский",
 | 
					  "Latvian": "Латышский",
 | 
				
			||||||
    "Macedonian": "Македонский",
 | 
					  "Lithuanian": "Литовский",
 | 
				
			||||||
    "Malagasy": "Малагасийский",
 | 
					  "Luxembourgish": "Люксембургский",
 | 
				
			||||||
    "Malay": "Малайский",
 | 
					  "Macedonian": "Македонский",
 | 
				
			||||||
    "Malayalam": "Малаялам",
 | 
					  "Malagasy": "Малагасийский",
 | 
				
			||||||
    "Maltese": "Мальтийский",
 | 
					  "Malay": "Малайский",
 | 
				
			||||||
    "Maori": "Маори",
 | 
					  "Malayalam": "Малаялам",
 | 
				
			||||||
    "Marathi": "Маратхи",
 | 
					  "Maltese": "Мальтийский",
 | 
				
			||||||
    "Mongolian": "Монгольская",
 | 
					  "Maori": "Маори",
 | 
				
			||||||
    "Nepali": "Непальский",
 | 
					  "Marathi": "Маратхи",
 | 
				
			||||||
    "Norwegian": "Норвежский",
 | 
					  "Mongolian": "Монгольская",
 | 
				
			||||||
    "Nyanja": "Ньянджа",
 | 
					  "Nepali": "Непальский",
 | 
				
			||||||
    "Pashto": "Пушту",
 | 
					  "Norwegian": "Норвежский",
 | 
				
			||||||
    "Persian": "Персидский",
 | 
					  "Nyanja": "Ньянджа",
 | 
				
			||||||
    "Polish": "Польский",
 | 
					  "Pashto": "Пушту",
 | 
				
			||||||
    "Portuguese": "Португальский",
 | 
					  "Persian": "Персидский",
 | 
				
			||||||
    "Punjabi": "Панджаби",
 | 
					  "Polish": "Польский",
 | 
				
			||||||
    "Romanian": "Румынский",
 | 
					  "Portuguese": "Португальский",
 | 
				
			||||||
    "Russian": "Русский",
 | 
					  "Punjabi": "Панджаби",
 | 
				
			||||||
    "Samoan": "Самоанский",
 | 
					  "Romanian": "Румынский",
 | 
				
			||||||
    "Scottish Gaelic": "Шотландский (гэльский)",
 | 
					  "Russian": "Русский",
 | 
				
			||||||
    "Serbian": "Сербский",
 | 
					  "Samoan": "Самоанский",
 | 
				
			||||||
    "Shona": "Шона",
 | 
					  "Scottish Gaelic": "Шотландский (гэльский)",
 | 
				
			||||||
    "Sindhi": "Синдхи",
 | 
					  "Serbian": "Сербский",
 | 
				
			||||||
    "Sinhala": "Сингальский",
 | 
					  "Shona": "Шона",
 | 
				
			||||||
    "Slovak": "Словацкий",
 | 
					  "Sindhi": "Синдхи",
 | 
				
			||||||
    "Slovenian": "Словенский",
 | 
					  "Sinhala": "Сингальский",
 | 
				
			||||||
    "Somali": "Сомалийский",
 | 
					  "Slovak": "Словацкий",
 | 
				
			||||||
    "Southern Sotho": "Сесото (южный сото)",
 | 
					  "Slovenian": "Словенский",
 | 
				
			||||||
    "Spanish": "Испанский",
 | 
					  "Somali": "Сомалийский",
 | 
				
			||||||
    "Spanish (Latin America)": "Испанский (Латинская Америка)",
 | 
					  "Southern Sotho": "Сесото (южный сото)",
 | 
				
			||||||
    "Sundanese": "Сунданский",
 | 
					  "Spanish": "Испанский",
 | 
				
			||||||
    "Swahili": "Суахили",
 | 
					  "Spanish (Latin America)": "Испанский (Латинская Америка)",
 | 
				
			||||||
    "Swedish": "Шведский",
 | 
					  "Sundanese": "Сунданский",
 | 
				
			||||||
    "Tajik": "Таджикский",
 | 
					  "Swahili": "Суахили",
 | 
				
			||||||
    "Tamil": "Тамильский",
 | 
					  "Swedish": "Шведский",
 | 
				
			||||||
    "Telugu": "Телугу",
 | 
					  "Tajik": "Таджикский",
 | 
				
			||||||
    "Thai": "Тайский",
 | 
					  "Tamil": "Тамильский",
 | 
				
			||||||
    "Turkish": "Турецкий",
 | 
					  "Telugu": "Телугу",
 | 
				
			||||||
    "Ukrainian": "Украинский",
 | 
					  "Thai": "Тайский",
 | 
				
			||||||
    "Urdu": "Урду",
 | 
					  "Turkish": "Турецкий",
 | 
				
			||||||
    "Uzbek": "Узбекский",
 | 
					  "Ukrainian": "Украинский",
 | 
				
			||||||
    "Vietnamese": "Вьетнамский",
 | 
					  "Urdu": "Урду",
 | 
				
			||||||
    "Welsh": "Валлийский",
 | 
					  "Uzbek": "Узбекский",
 | 
				
			||||||
    "Western Frisian": "Западнофризский",
 | 
					  "Vietnamese": "Вьетнамский",
 | 
				
			||||||
    "Xhosa": "Коса",
 | 
					  "Welsh": "Валлийский",
 | 
				
			||||||
    "Yiddish": "Идиш",
 | 
					  "Western Frisian": "Западнофризский",
 | 
				
			||||||
    "Yoruba": "Йоруба",
 | 
					  "Xhosa": "Коса",
 | 
				
			||||||
    "Zulu": "Зулусский",
 | 
					  "Yiddish": "Идиш",
 | 
				
			||||||
    "`x` years": "`x` лет",
 | 
					  "Yoruba": "Йоруба",
 | 
				
			||||||
    "`x` months": "`x` месяцев",
 | 
					  "Zulu": "Зулусский",
 | 
				
			||||||
    "`x` weeks": "`x` недель",
 | 
					  "`x` years": "`x` лет",
 | 
				
			||||||
    "`x` days": "`x` дней",
 | 
					  "`x` months": "`x` месяцев",
 | 
				
			||||||
    "`x` hours": "`x` часов",
 | 
					  "`x` weeks": "`x` недель",
 | 
				
			||||||
    "`x` minutes": "`x` минут",
 | 
					  "`x` days": "`x` дней",
 | 
				
			||||||
    "`x` seconds": "`x` секунд",
 | 
					  "`x` hours": "`x` часов",
 | 
				
			||||||
    "Fallback comments: ": "Резервные комментарии: ",
 | 
					  "`x` minutes": "`x` минут",
 | 
				
			||||||
    "Popular": "Популярное",
 | 
					  "`x` seconds": "`x` секунд",
 | 
				
			||||||
    "Top": "Топ",
 | 
					  "Fallback comments: ": "Резервные комментарии: ",
 | 
				
			||||||
    "About": "О сайте",
 | 
					  "Popular": "Популярное",
 | 
				
			||||||
    "Rating: ": "Рейтинг: ",
 | 
					  "Top": "Топ",
 | 
				
			||||||
    "Language: ": "Язык: ",
 | 
					  "About": "О сайте",
 | 
				
			||||||
    "Default": "По-умолчанию",
 | 
					  "Rating: ": "Рейтинг: ",
 | 
				
			||||||
    "Music": "Музыка",
 | 
					  "Language: ": "Язык: ",
 | 
				
			||||||
    "Gaming": "Игры",
 | 
					  "Default": "По-умолчанию",
 | 
				
			||||||
    "News": "Новости",
 | 
					  "Music": "Музыка",
 | 
				
			||||||
    "Movies": "Фильмы",
 | 
					  "Gaming": "Игры",
 | 
				
			||||||
    "Download": "Скачать",
 | 
					  "News": "Новости",
 | 
				
			||||||
    "Download as: ": "Скачать как: ",
 | 
					  "Movies": "Фильмы",
 | 
				
			||||||
    "%A %B %-d, %Y": "%-d %B %Y, %A",
 | 
					  "Download": "Скачать",
 | 
				
			||||||
    "(edited)": "(изменено)",
 | 
					  "Download as: ": "Скачать как: ",
 | 
				
			||||||
    "Youtube permalink of the comment": "Прямая ссылка на YouTube",
 | 
					  "%A %B %-d, %Y": "%-d %B %Y, %A",
 | 
				
			||||||
    "`x` marked it with a ❤": "❤ от автора канала \"`x`\"",
 | 
					  "(edited)": "(изменено)",
 | 
				
			||||||
    "Audio mode": "Аудио режим",
 | 
					  "Youtube permalink of the comment": "Прямая ссылка на YouTube",
 | 
				
			||||||
    "Video mode": "Видео режим",
 | 
					  "`x` marked it with a ❤": "❤ от автора канала \"`x`\"",
 | 
				
			||||||
    "Videos": "Видео",
 | 
					  "Audio mode": "Аудио режим",
 | 
				
			||||||
    "Playlists": "Плейлисты",
 | 
					  "Video mode": "Видео режим",
 | 
				
			||||||
    "Current version: ": "Текущая версия: "
 | 
					  "Videos": "Видео",
 | 
				
			||||||
 | 
					  "Playlists": "Плейлисты",
 | 
				
			||||||
 | 
					  "Current version: ": "Текущая версия: "
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -242,6 +242,9 @@ get "/api/v1/comments/:id" do |env|
 | 
				
			|||||||
  source = env.params.query["source"]?
 | 
					  source = env.params.query["source"]?
 | 
				
			||||||
  source ||= "youtube"
 | 
					  source ||= "youtube"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  thin_mode = env.params.query["thin_mode"]?
 | 
				
			||||||
 | 
					  thin_mode = thin_mode == "true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  format = env.params.query["format"]?
 | 
					  format = env.params.query["format"]?
 | 
				
			||||||
  format ||= "json"
 | 
					  format ||= "json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -249,7 +252,7 @@ get "/api/v1/comments/:id" do |env|
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if source == "youtube"
 | 
					  if source == "youtube"
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
      comments = fetch_youtube_comments(id, continuation, proxies, format, locale, region)
 | 
					      comments = fetch_youtube_comments(id, continuation, proxies, format, locale, thin_mode, region)
 | 
				
			||||||
    rescue ex
 | 
					    rescue ex
 | 
				
			||||||
      error_message = {"error" => ex.message}.to_json
 | 
					      error_message = {"error" => ex.message}.to_json
 | 
				
			||||||
      env.response.status_code = 500
 | 
					      env.response.status_code = 500
 | 
				
			||||||
@ -1688,6 +1691,11 @@ get "/videoplayback" do |env|
 | 
				
			|||||||
  fvip = query_params["fvip"]? || "3"
 | 
					  fvip = query_params["fvip"]? || "3"
 | 
				
			||||||
  mns = query_params["mn"].split(",")
 | 
					  mns = query_params["mn"].split(",")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if query_params["region"]?
 | 
				
			||||||
 | 
					    region = query_params["region"]
 | 
				
			||||||
 | 
					    query_params.delete("region")
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if query_params["host"]? && !query_params["host"].empty?
 | 
					  if query_params["host"]? && !query_params["host"].empty?
 | 
				
			||||||
    host = "https://#{query_params["host"]}"
 | 
					    host = "https://#{query_params["host"]}"
 | 
				
			||||||
    query_params.delete("host")
 | 
					    query_params.delete("host")
 | 
				
			||||||
@ -1704,8 +1712,6 @@ get "/videoplayback" do |env|
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  region = query_params["region"]?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  response = HTTP::Client::Response.new(403)
 | 
					  response = HTTP::Client::Response.new(403)
 | 
				
			||||||
  5.times do
 | 
					  5.times do
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
@ -1725,9 +1731,12 @@ get "/videoplayback" do |env|
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if response.headers["Location"]?
 | 
					  if response.headers["Location"]?
 | 
				
			||||||
    url = URI.parse(response.headers["Location"])
 | 
					    url = URI.parse(response.headers["Location"])
 | 
				
			||||||
 | 
					    host = url.host
 | 
				
			||||||
    env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
					    env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    url = url.full_path
 | 
					    url = url.full_path
 | 
				
			||||||
 | 
					    url += "&host=#{host}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if region
 | 
					    if region
 | 
				
			||||||
      url += "®ion=#{region}"
 | 
					      url += "®ion=#{region}"
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
@ -1744,15 +1753,30 @@ get "/videoplayback" do |env|
 | 
				
			|||||||
  client.get(url, headers) do |response|
 | 
					  client.get(url, headers) do |response|
 | 
				
			||||||
    env.response.status_code = response.status_code
 | 
					    env.response.status_code = response.status_code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if title = env.params.query["title"]?
 | 
					 | 
				
			||||||
      # https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
 | 
					 | 
				
			||||||
      env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    response.headers.each do |key, value|
 | 
					    response.headers.each do |key, value|
 | 
				
			||||||
      env.response.headers[key] = value
 | 
					      env.response.headers[key] = value
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if response.headers["Location"]?
 | 
				
			||||||
 | 
					      url = URI.parse(response.headers["Location"])
 | 
				
			||||||
 | 
					      host = url.host
 | 
				
			||||||
 | 
					      env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      url = url.full_path
 | 
				
			||||||
 | 
					      url += "&host=#{host}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if region
 | 
				
			||||||
 | 
					        url += "®ion=#{region}"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      next env.redirect url
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if title = query_params["title"]?
 | 
				
			||||||
 | 
					      # https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
 | 
				
			||||||
 | 
					      env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
					    env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
class InvidiousChannel
 | 
					struct InvidiousChannel
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    id:         String,
 | 
					    id:         String,
 | 
				
			||||||
    author:     String,
 | 
					    author:     String,
 | 
				
			||||||
@ -8,7 +8,7 @@ class InvidiousChannel
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChannelVideo
 | 
					struct ChannelVideo
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    id:                 String,
 | 
					    id:                 String,
 | 
				
			||||||
    title:              String,
 | 
					    title:              String,
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ class RedditComment
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RedditLink
 | 
					struct RedditLink
 | 
				
			||||||
  JSON.mapping({
 | 
					  JSON.mapping({
 | 
				
			||||||
    author:       String,
 | 
					    author:       String,
 | 
				
			||||||
    score:        Int32,
 | 
					    score:        Int32,
 | 
				
			||||||
@ -41,7 +41,7 @@ class RedditLink
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RedditMore
 | 
					struct RedditMore
 | 
				
			||||||
  JSON.mapping({
 | 
					  JSON.mapping({
 | 
				
			||||||
    children: Array(String),
 | 
					    children: Array(String),
 | 
				
			||||||
    count:    Int32,
 | 
					    count:    Int32,
 | 
				
			||||||
@ -56,7 +56,7 @@ class RedditListing
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def fetch_youtube_comments(id, continuation, proxies, format, locale, region)
 | 
					def fetch_youtube_comments(id, continuation, proxies, format, locale, thin_mode, region)
 | 
				
			||||||
  video = fetch_video(id, proxies, region: region)
 | 
					  video = fetch_video(id, proxies, region: region)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  session_token = video.info["session_token"]?
 | 
					  session_token = video.info["session_token"]?
 | 
				
			||||||
@ -232,7 +232,7 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale, region)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if format == "html"
 | 
					  if format == "html"
 | 
				
			||||||
    comments = JSON.parse(comments)
 | 
					    comments = JSON.parse(comments)
 | 
				
			||||||
    content_html = template_youtube_comments(comments, locale)
 | 
					    content_html = template_youtube_comments(comments, locale, thin_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    comments = JSON.build do |json|
 | 
					    comments = JSON.build do |json|
 | 
				
			||||||
      json.object do
 | 
					      json.object do
 | 
				
			||||||
@ -278,7 +278,7 @@ def fetch_reddit_comments(id)
 | 
				
			|||||||
  return comments, thread
 | 
					  return comments, thread
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def template_youtube_comments(comments, locale)
 | 
					def template_youtube_comments(comments, locale, thin_mode)
 | 
				
			||||||
  html = ""
 | 
					  html = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  root = comments["comments"].as_a
 | 
					  root = comments["comments"].as_a
 | 
				
			||||||
@ -297,7 +297,11 @@ def template_youtube_comments(comments, locale)
 | 
				
			|||||||
      END_HTML
 | 
					      END_HTML
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    author_thumbnail = "/ggpht#{URI.parse(child["authorThumbnails"][-1]["url"].as_s).full_path}"
 | 
					    if !thin_mode
 | 
				
			||||||
 | 
					      author_thumbnail = "/ggpht#{URI.parse(child["authorThumbnails"][-1]["url"].as_s).full_path}"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      author_thumbnail = ""
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    html += <<-END_HTML
 | 
					    html += <<-END_HTML
 | 
				
			||||||
    <div class="pure-g">
 | 
					    <div class="pure-g">
 | 
				
			||||||
@ -318,7 +322,12 @@ def template_youtube_comments(comments, locale)
 | 
				
			|||||||
    END_HTML
 | 
					    END_HTML
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if child["creatorHeart"]?
 | 
					    if child["creatorHeart"]?
 | 
				
			||||||
      creator_thumbnail = "/ggpht#{URI.parse(child["creatorHeart"]["creatorThumbnail"].as_s).full_path}"
 | 
					      if !thin_mode
 | 
				
			||||||
 | 
					        creator_thumbnail = "/ggpht#{URI.parse(child["creatorHeart"]["creatorThumbnail"].as_s).full_path}"
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        creator_thumbnail = ""
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      html += <<-END_HTML
 | 
					      html += <<-END_HTML
 | 
				
			||||||
          <span class="creator-heart-container" title="#{translate(locale, "`x` marked it with a ❤", child["creatorHeart"]["creatorName"].as_s)}">
 | 
					          <span class="creator-heart-container" title="#{translate(locale, "`x` marked it with a ❤", child["creatorHeart"]["creatorName"].as_s)}">
 | 
				
			||||||
              <div class="creator-heart">
 | 
					              <div class="creator-heart">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
class Config
 | 
					struct Config
 | 
				
			||||||
  YAML.mapping({
 | 
					  YAML.mapping({
 | 
				
			||||||
    channel_threads: Int32,      # Number of threads to use for crawling videos from channels (for updating subscriptions)
 | 
					    channel_threads: Int32,      # Number of threads to use for crawling videos from channels (for updating subscriptions)
 | 
				
			||||||
    feed_threads:    Int32,      # Number of threads to use for updating feeds
 | 
					    feed_threads:    Int32,      # Number of threads to use for updating feeds
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,17 @@ macro add_mapping(mapping)
 | 
				
			|||||||
    DB.mapping({{mapping}})
 | 
					    DB.mapping({{mapping}})
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro json_mapping(mapping)
 | 
				
			||||||
 | 
					    def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_a
 | 
				
			||||||
 | 
					        return [{{*mapping.keys.map { |id| "@#{id}".id }}}]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JSON.mapping({{mapping}})
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro templated(filename, template = "template")
 | 
					macro templated(filename, template = "template")
 | 
				
			||||||
    render "src/invidious/views/#{{{filename}}}.ecr", "src/invidious/views/#{{{template}}}.ecr"
 | 
					    render "src/invidious/views/#{{{filename}}}.ecr", "src/invidious/views/#{{{template}}}.ecr"
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -106,7 +106,7 @@ def subscribe_to_feeds(db, logger, key, config)
 | 
				
			|||||||
  if config.use_pubsub_feeds
 | 
					  if config.use_pubsub_feeds
 | 
				
			||||||
    spawn do
 | 
					    spawn do
 | 
				
			||||||
      loop do
 | 
					      loop do
 | 
				
			||||||
        db.query_all("SELECT id FROM channels WHERE CURRENT_TIMESTAMP - subscribed > '4 days'") do |rs|
 | 
					        db.query_all("SELECT id FROM channels WHERE CURRENT_TIMESTAMP - subscribed > '4 days' OR subscribed IS NULL") do |rs|
 | 
				
			||||||
          rs.each do
 | 
					          rs.each do
 | 
				
			||||||
            ucid = rs.read(String)
 | 
					            ucid = rs.read(String)
 | 
				
			||||||
            response = subscribe_pubsub(ucid, key, config)
 | 
					            response = subscribe_pubsub(ucid, key, config)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
class MixVideo
 | 
					struct MixVideo
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:          String,
 | 
					    title:          String,
 | 
				
			||||||
    id:             String,
 | 
					    id:             String,
 | 
				
			||||||
@ -10,7 +10,7 @@ class MixVideo
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Mix
 | 
					struct Mix
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:  String,
 | 
					    title:  String,
 | 
				
			||||||
    id:     String,
 | 
					    id:     String,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
class PlaylistVideo
 | 
					struct PlaylistVideo
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:          String,
 | 
					    title:          String,
 | 
				
			||||||
    id:             String,
 | 
					    id:             String,
 | 
				
			||||||
@ -12,7 +12,7 @@ class PlaylistVideo
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Playlist
 | 
					struct Playlist
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:            String,
 | 
					    title:            String,
 | 
				
			||||||
    id:               String,
 | 
					    id:               String,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
class SearchVideo
 | 
					struct SearchVideo
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:              String,
 | 
					    title:              String,
 | 
				
			||||||
    id:                 String,
 | 
					    id:                 String,
 | 
				
			||||||
@ -16,7 +16,7 @@ class SearchVideo
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SearchPlaylistVideo
 | 
					struct SearchPlaylistVideo
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:          String,
 | 
					    title:          String,
 | 
				
			||||||
    id:             String,
 | 
					    id:             String,
 | 
				
			||||||
@ -24,7 +24,7 @@ class SearchPlaylistVideo
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SearchPlaylist
 | 
					struct SearchPlaylist
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    title:        String,
 | 
					    title:        String,
 | 
				
			||||||
    id:           String,
 | 
					    id:           String,
 | 
				
			||||||
@ -36,7 +36,7 @@ class SearchPlaylist
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SearchChannel
 | 
					struct SearchChannel
 | 
				
			||||||
  add_mapping({
 | 
					  add_mapping({
 | 
				
			||||||
    author:           String,
 | 
					    author:           String,
 | 
				
			||||||
    ucid:             String,
 | 
					    ucid:             String,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
require "crypto/bcrypt/password"
 | 
					require "crypto/bcrypt/password"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class User
 | 
					struct User
 | 
				
			||||||
  module PreferencesConverter
 | 
					  module PreferencesConverter
 | 
				
			||||||
    def self.from_rs(rs)
 | 
					    def self.from_rs(rs)
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
        Preferences.from_json(rs.read(String))
 | 
					        Preferences.from_json(rs.read(String))
 | 
				
			||||||
      rescue ex
 | 
					      rescue ex
 | 
				
			||||||
        DEFAULT_USER_PREFERENCES
 | 
					        Preferences.from_json("{}")
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@ -18,7 +18,6 @@ class User
 | 
				
			|||||||
    email:         String,
 | 
					    email:         String,
 | 
				
			||||||
    preferences:   {
 | 
					    preferences:   {
 | 
				
			||||||
      type:      Preferences,
 | 
					      type:      Preferences,
 | 
				
			||||||
      default:   DEFAULT_USER_PREFERENCES,
 | 
					 | 
				
			||||||
      converter: PreferencesConverter,
 | 
					      converter: PreferencesConverter,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    password: String?,
 | 
					    password: String?,
 | 
				
			||||||
@ -27,30 +26,30 @@ class User
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFAULT_USER_PREFERENCES = Preferences.from_json({
 | 
					DEFAULT_USER_PREFERENCES = Preferences.new(
 | 
				
			||||||
  "video_loop"         => false,
 | 
					  video_loop: false,
 | 
				
			||||||
  "autoplay"           => false,
 | 
					  autoplay: false,
 | 
				
			||||||
  "continue"           => false,
 | 
					  continue: false,
 | 
				
			||||||
  "local"              => false,
 | 
					  local: false,
 | 
				
			||||||
  "listen"             => false,
 | 
					  listen: false,
 | 
				
			||||||
  "speed"              => 1.0,
 | 
					  speed: 1.0_f32,
 | 
				
			||||||
  "quality"            => "hd720",
 | 
					  quality: "hd720",
 | 
				
			||||||
  "volume"             => 100,
 | 
					  volume: 100,
 | 
				
			||||||
  "comments"           => ["youtube", ""],
 | 
					  comments: ["youtube", ""],
 | 
				
			||||||
  "captions"           => ["", "", ""],
 | 
					  captions: ["", "", ""],
 | 
				
			||||||
  "related_videos"     => true,
 | 
					  related_videos: true,
 | 
				
			||||||
  "redirect_feed"      => false,
 | 
					  redirect_feed: false,
 | 
				
			||||||
  "locale"             => "en-US",
 | 
					  locale: "en-US",
 | 
				
			||||||
  "dark_mode"          => false,
 | 
					  dark_mode: false,
 | 
				
			||||||
  "thin_mode"          => false,
 | 
					  thin_mode: false,
 | 
				
			||||||
  "max_results"        => 40,
 | 
					  max_results: 40,
 | 
				
			||||||
  "sort"               => "published",
 | 
					  sort: "published",
 | 
				
			||||||
  "latest_only"        => false,
 | 
					  latest_only: false,
 | 
				
			||||||
  "unseen_only"        => false,
 | 
					  unseen_only: false,
 | 
				
			||||||
  "notifications_only" => false,
 | 
					  notifications_only: false,
 | 
				
			||||||
}.to_json)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Preferences
 | 
					struct Preferences
 | 
				
			||||||
  module StringToArray
 | 
					  module StringToArray
 | 
				
			||||||
    def self.to_json(value : Array(String), json : JSON::Builder)
 | 
					    def self.to_json(value : Array(String), json : JSON::Builder)
 | 
				
			||||||
      json.array do
 | 
					      json.array do
 | 
				
			||||||
@ -74,58 +73,27 @@ class Preferences
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  JSON.mapping({
 | 
					  json_mapping({
 | 
				
			||||||
    video_loop: Bool,
 | 
					    video_loop:         {type: Bool, default: DEFAULT_USER_PREFERENCES.video_loop},
 | 
				
			||||||
    autoplay:   Bool,
 | 
					    autoplay:           {type: Bool, default: DEFAULT_USER_PREFERENCES.autoplay},
 | 
				
			||||||
    continue:   {
 | 
					    continue:           {type: Bool, default: DEFAULT_USER_PREFERENCES.continue},
 | 
				
			||||||
      type:    Bool,
 | 
					    local:              {type: Bool, default: DEFAULT_USER_PREFERENCES.local},
 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.continue,
 | 
					    listen:             {type: Bool, default: DEFAULT_USER_PREFERENCES.listen},
 | 
				
			||||||
    },
 | 
					    speed:              {type: Float32, default: DEFAULT_USER_PREFERENCES.speed},
 | 
				
			||||||
    local: {
 | 
					    quality:            {type: String, default: DEFAULT_USER_PREFERENCES.quality},
 | 
				
			||||||
      type:    Bool,
 | 
					    volume:             {type: Int32, default: DEFAULT_USER_PREFERENCES.volume},
 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.local,
 | 
					    comments:           {type: Array(String), default: DEFAULT_USER_PREFERENCES.comments, converter: StringToArray},
 | 
				
			||||||
    },
 | 
					    captions:           {type: Array(String), default: DEFAULT_USER_PREFERENCES.captions, converter: StringToArray},
 | 
				
			||||||
    listen: {
 | 
					    redirect_feed:      {type: Bool, default: DEFAULT_USER_PREFERENCES.redirect_feed},
 | 
				
			||||||
      type:    Bool,
 | 
					    related_videos:     {type: Bool, default: DEFAULT_USER_PREFERENCES.related_videos},
 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.listen,
 | 
					    dark_mode:          {type: Bool, default: DEFAULT_USER_PREFERENCES.dark_mode},
 | 
				
			||||||
    },
 | 
					    thin_mode:          {type: Bool, default: DEFAULT_USER_PREFERENCES.thin_mode},
 | 
				
			||||||
    speed:    Float32,
 | 
					    max_results:        {type: Int32, default: DEFAULT_USER_PREFERENCES.max_results},
 | 
				
			||||||
    quality:  String,
 | 
					    sort:               {type: String, default: DEFAULT_USER_PREFERENCES.sort},
 | 
				
			||||||
    volume:   Int32,
 | 
					    latest_only:        {type: Bool, default: DEFAULT_USER_PREFERENCES.latest_only},
 | 
				
			||||||
    comments: {
 | 
					    unseen_only:        {type: Bool, default: DEFAULT_USER_PREFERENCES.unseen_only},
 | 
				
			||||||
      type:      Array(String),
 | 
					    notifications_only: {type: Bool, default: DEFAULT_USER_PREFERENCES.notifications_only},
 | 
				
			||||||
      default:   DEFAULT_USER_PREFERENCES.comments,
 | 
					    locale:             {type: String, default: DEFAULT_USER_PREFERENCES.locale},
 | 
				
			||||||
      converter: StringToArray,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    captions: {
 | 
					 | 
				
			||||||
      type:    Array(String),
 | 
					 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.captions,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    redirect_feed: {
 | 
					 | 
				
			||||||
      type:    Bool,
 | 
					 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.redirect_feed,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    related_videos: {
 | 
					 | 
				
			||||||
      type:    Bool,
 | 
					 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.related_videos,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    dark_mode: Bool,
 | 
					 | 
				
			||||||
    thin_mode: {
 | 
					 | 
				
			||||||
      type:    Bool,
 | 
					 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.thin_mode,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    max_results:        Int32,
 | 
					 | 
				
			||||||
    sort:               String,
 | 
					 | 
				
			||||||
    latest_only:        Bool,
 | 
					 | 
				
			||||||
    unseen_only:        Bool,
 | 
					 | 
				
			||||||
    notifications_only: {
 | 
					 | 
				
			||||||
      type:    Bool,
 | 
					 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.notifications_only,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    locale: {
 | 
					 | 
				
			||||||
      type:    String,
 | 
					 | 
				
			||||||
      default: DEFAULT_USER_PREFERENCES.locale,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -241,7 +241,7 @@ VIDEO_FORMATS = {
 | 
				
			|||||||
  "251" => {"ext" => "webm", "format" => "DASH audio", "acodec" => "opus", "abr" => 160},
 | 
					  "251" => {"ext" => "webm", "format" => "DASH audio", "acodec" => "opus", "abr" => 160},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Video
 | 
					struct Video
 | 
				
			||||||
  property player_json : JSON::Any?
 | 
					  property player_json : JSON::Any?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  module HTTPParamConverter
 | 
					  module HTTPParamConverter
 | 
				
			||||||
@ -251,7 +251,7 @@ class Video
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def allow_ratings
 | 
					  def allow_ratings
 | 
				
			||||||
    allow_ratings = player_response["videoDetails"].try &.["allowRatings"]?.try &.as_bool
 | 
					    allow_ratings = player_response["videoDetails"]?.try &.["allowRatings"]?.try &.as_bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if allow_ratings.nil?
 | 
					    if allow_ratings.nil?
 | 
				
			||||||
      return true
 | 
					      return true
 | 
				
			||||||
@ -271,7 +271,7 @@ class Video
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def is_listed
 | 
					  def is_listed
 | 
				
			||||||
    is_listed = player_response["videoDetails"].try &.["isCrawlable"]?.try &.as_bool
 | 
					    is_listed = player_response["videoDetails"]?.try &.["isCrawlable"]?.try &.as_bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if is_listed.nil?
 | 
					    if is_listed.nil?
 | 
				
			||||||
      return true
 | 
					      return true
 | 
				
			||||||
@ -281,7 +281,7 @@ class Video
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def is_upcoming
 | 
					  def is_upcoming
 | 
				
			||||||
    is_upcoming = player_response["videoDetails"].try &.["isUpcoming"]?.try &.as_bool
 | 
					    is_upcoming = player_response["videoDetails"]?.try &.["isUpcoming"]?.try &.as_bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if is_upcoming.nil?
 | 
					    if is_upcoming.nil?
 | 
				
			||||||
      return false
 | 
					      return false
 | 
				
			||||||
@ -297,7 +297,7 @@ class Video
 | 
				
			|||||||
          .try &.["liveStreamabilityRenderer"]?
 | 
					          .try &.["liveStreamabilityRenderer"]?
 | 
				
			||||||
            .try &.["offlineSlate"]?
 | 
					            .try &.["offlineSlate"]?
 | 
				
			||||||
              .try &.["liveStreamOfflineSlateRenderer"]?
 | 
					              .try &.["liveStreamOfflineSlateRenderer"]?
 | 
				
			||||||
                .try &.["scheduledStartTime"].as_s.to_i64
 | 
					                .try &.["scheduledStartTime"]?.try &.as_s.to_i64
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if premiere_timestamp
 | 
					    if premiere_timestamp
 | 
				
			||||||
@ -549,7 +549,7 @@ class Video
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Caption
 | 
					struct Caption
 | 
				
			||||||
  JSON.mapping(
 | 
					  JSON.mapping(
 | 
				
			||||||
    name: CaptionName,
 | 
					    name: CaptionName,
 | 
				
			||||||
    baseUrl: String,
 | 
					    baseUrl: String,
 | 
				
			||||||
@ -557,7 +557,7 @@ class Caption
 | 
				
			|||||||
  )
 | 
					  )
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CaptionName
 | 
					struct CaptionName
 | 
				
			||||||
  JSON.mapping(
 | 
					  JSON.mapping(
 | 
				
			||||||
    simpleText: String,
 | 
					    simpleText: String,
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user