diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..7271d9bd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,118 @@
+# -----------------------
+# Compilation options
+# -----------------------
+
+RELEASE := 1
+STATIC := 0
+
+DISABLE_LSQUIC := 0
+NO_DBG_SYMBOLS := 0
+
+
+FLAGS ?=
+
+
+ifeq ($(RELEASE), 1)
+ FLAGS += --release
+endif
+
+ifeq ($(STATIC), 1)
+ FLAGS += --static
+endif
+
+
+ifeq ($(NO_DBG_SYMBOLS), 1)
+ FLAGS += --no-debug
+else
+ FLAGS += --debug
+endif
+
+ifeq ($(DISABLE_LSQUIC), 1)
+ FLAGS += -Ddisable_lsquic
+endif
+
+
+# -----------------------
+# Main
+# -----------------------
+
+all: invidious
+
+get-libs:
+ shards install --production
+
+# TODO: add support for ARM64 via cross-compilation
+invidious: get-libs
+ crystal build src/invidious.cr $(FLAGS) --progress --stats --error-trace
+
+
+run: invidious
+ ./invidious
+
+
+# -----------------------
+# Development
+# -----------------------
+
+
+format:
+ crystal tool format
+
+test:
+ crystal spec
+
+verify:
+ crystal build src/invidious.cr --no-codegen --progress --stats --error-trace
+
+
+# -----------------------
+# (Un)Install
+# -----------------------
+
+# TODO
+
+
+# -----------------------
+# Cleaning
+# -----------------------
+
+clean:
+ rm invidious
+
+distclean: clean
+ rm -rf libs
+
+
+# -----------------------
+# Help page
+# -----------------------
+
+help:
+ echo "Targets available in this Makefile:"
+ echo ""
+ echo "get-libs Fetch Crystal libraries"
+ echo "invidious Build Invidious"
+ echo "run Launch Invidious"
+ echo ""
+ echo "format Run the Crystal formatter"
+ echo "test Run tests"
+ echo "verify Just make sure that the code compiles, but without"
+ echo " generating any binaries. Useful to search for errors"
+ echo ""
+ echo "clean Remove build artifacts"
+ echo "distclean Remove build artifacts and libraries"
+ echo ""
+ echo ""
+ echo "Build options available for this Makefile:"
+ echo ""
+ echo "RELEASE Make a release build (Default: 1)"
+ echo "STATIC Link librariess tatically (Default: 1)"
+ echo ""
+ echo "DISABLE_LSQUIC Don't use lsquic (Default: 0)"
+ echo "NO_DBG_SYMBOLS Strip debug symbols (Default: 0)"
+
+
+
+# No targets generates an output named after themselves
+.PHONY: all get-libs build amd64 run
+.PHONY: format test verify clean distclean help
diff --git a/README.md b/README.md
index 07fad864..801ed329 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,9 @@
+
+
+
@@ -17,19 +20,22 @@
+
An open source alternative front-end to YouTube
+ Website
+ •
Instances list
•
- Documentation
+ Documentation
•
Contribute
•
- Donate
+ Donate
Chat with us:
@@ -133,18 +139,7 @@ Weblate also allows you to log-in with major SSO providers like Github, Gitlab,
- [CloudTube](https://sr.ht/~cadence/tube/): A JavaScript-rich alternate YouTube player.
- [PeerTubeify](https://gitlab.com/Cha_deL/peertubeify): On YouTube, displays a link to the same video on PeerTube, if it exists.
- [MusicPiped](https://github.com/deep-gaurav/MusicPiped): A material design music player that streams music from YouTube.
-- [HoloPlay](https://github.com/stephane-r/HoloPlay): Funny Android application connecting on Invidious API's with search, playlists and favoris.
-
-
-## Donate
-
-Bitcoin (BTC): [bc1qfhe7rq3lqzuayzjxzyt9waz9ytrs09kla3tsgr](bitcoin:bc1qfhe7rq3lqzuayzjxzyt9waz9ytrs09kla3tsgr)
-
-Monero (XMR): [41nMCtek197boJtiUvGnTFYMatrLEpnpkQDmUECqx5Es2uX3sTKKWVhSL76suXsG3LXqkEJBrCZBgPTwJrDp1FrZJfycGPR](monero:41nMCtek197boJtiUvGnTFYMatrLEpnpkQDmUECqx5Es2uX3sTKKWVhSL76suXsG3LXqkEJBrCZBgPTwJrDp1FrZJfycGPR)
-
-Ethereum (ETH): [0xD1F7E3Bfb19Ee5a52baED396Ad34717aF18d995B](ethereum:0xD1F7E3Bfb19Ee5a52baED396Ad34717aF18d995B)
-
-Litecoin (LTC): [ltc1q8787aq2xrseq5yx52axx8c4fqks88zj5vr0zx9](litecoin:ltc1q8787aq2xrseq5yx52axx8c4fqks88zj5vr0zx9)
+- [HoloPlay](https://github.com/stephane-r/HoloPlay): Funny Android application connecting on Invidious API's with search, playlists and favorites.
## Liability
diff --git a/locales/ca.json b/locales/ca.json
new file mode 100644
index 00000000..1fa7cc1f
--- /dev/null
+++ b/locales/ca.json
@@ -0,0 +1,103 @@
+{
+ "oldest": "més antic",
+ "Yes": "Sí",
+ "preferences_quality_label": "Qualitat de vídeo preferida: ",
+ "newest": "més nou",
+ "No": "No",
+ "Google verification code": "Codi de verificació de Google",
+ "User ID": "ID d'usuari",
+ "Preferences": "Preferències",
+ "Dark mode: ": "Mode fosc: ",
+ "dark": "fosc",
+ "light": "clar",
+ "published": "publicat",
+ "published - reverse": "publicat - invers",
+ "alphabetically": "alfabèticament",
+ "alphabetically - reverse": "alfabèticament - invers",
+ "channel name - reverse": "nom del canal - invers",
+ "preferences_category_data": "Preferències de dades",
+ "Delete account": "Elimina compte",
+ "Save preferences": "Guarda preferències",
+ "Private": "Privat",
+ "Show more": "Mostra'n més",
+ "Show less": "Mostra'n menys",
+ "Hide replies": "Amaga respostes",
+ "Arabic": "Àrab",
+ "Armenian": "Armeni",
+ "Basque": "Basc",
+ "Filipino": "Filipí",
+ "Finnish": "Finès",
+ "German": "Alemany",
+ "Greek": "Grec",
+ "Hungarian": "Hongarès",
+ "Icelandic": "Islandès",
+ "Italian": "Italià",
+ "Japanese": "Japonès",
+ "Korean": "Coreà",
+ "Kurdish": "Kurd",
+ "Lithuanian": "Lituà",
+ "Luxembourgish": "Luxemburguès",
+ "Macedonian": "Macedoni",
+ "Polish": "Polonès",
+ "Portuguese": "Portuguès",
+ "Romanian": "Romanès",
+ "Russian": "Rus",
+ "Serbian": "Serbi",
+ "Spanish (Latin America)": "Castellà (Amèrica llatina)",
+ "Turkish": "Turc",
+ "Ukrainian": "Ucraïnès",
+ "preferences_locale_label": "Idioma: ",
+ "Gaming": "Jocs",
+ "Movies": "Películes",
+ "Download": "Descarrega",
+ "Download as: ": "Descarrega com: ",
+ "Videos": "Vídeos",
+ "content_type": "Tipus",
+ "duration": "Duració",
+ "sort": "Ordena per",
+ "week": "Aquesta setmana",
+ "month": "Aquest mes",
+ "year": "Aquest any",
+ "video": "Vídeo",
+ "channel": "Canal",
+ "short": "Curt (< 4 minuts)",
+ "long": "Llarg (> 20 minuts)",
+ "Current version: ": "Versió actual: ",
+ "Malay": "Malai",
+ "Persian": "Persa",
+ "Slovak": "Eslovac",
+ "Search": "Busca",
+ "Show annotations": "Mostra anotacions",
+ "preferences_region_label": "País del contingut: ",
+ "preferences_sort_label": "Ordena vídeos per: ",
+ "Import/export": "Importa/exporta",
+ "channel name": "nom del canal",
+ "Title": "Títol",
+ "Belarusian": "Bielorús",
+ "Enable web notifications": "Activa notificacions web",
+ "search": "busca",
+ "Catalan": "Català",
+ "Croatian": "Croat",
+ "preferences_category_admin": "Preferències d'administrador",
+ "Hide annotations": "Amaga anotacions",
+ "Show replies": "Mostra respostes",
+ "Bulgarian": "Búlgar",
+ "Albanian": "Albanès",
+ "French": "Francès",
+ "Irish": "Irlandès",
+ "Maltese": "Maltès",
+ "Danish": "Danès",
+ "Galician": "Gallec",
+ "Hebrew": "Hebreu",
+ "Indonesian": "Indonesi",
+ "Spanish": "Castellà",
+ "Vietnamese": "Vietnamita",
+ "News": "Notícies",
+ "show": "Mostra",
+ "footer_documentation": "Documentació",
+ "Thai": "Tailandès",
+ "Music": "Música",
+ "relevance": "Rellevància",
+ "hour": "Última hora",
+ "today": "Avui"
+}
diff --git a/locales/fr.json b/locales/fr.json
index 2332594a..00971576 100644
--- a/locales/fr.json
+++ b/locales/fr.json
@@ -423,5 +423,15 @@
"Current version: ": "Version actuelle : ",
"next_steps_error_message": "Vous pouvez essayer de : ",
"next_steps_error_message_refresh": "Rafraîchir la page",
- "next_steps_error_message_go_to_youtube": "Aller sur YouTube"
+ "next_steps_error_message_go_to_youtube": "Aller sur YouTube",
+ "preferences_quality_dash_label": "Qualité préférée de la vidéo du tableau de bord : ",
+ "footer_source_code": "Code source",
+ "preferences_region_label": "Pays du contenu : ",
+ "footer_donate_page": "Faire un don",
+ "footer_modfied_source_code": "Code source modifié",
+ "short": "Courte (< 4 minutes)",
+ "long": "Longue (> 20 minutes)",
+ "adminprefs_modified_source_code_url_label": "URL du dépôt du code source modifié",
+ "footer_documentation": "Documentation",
+ "footer_original_source_code": "Code source original"
}
diff --git a/locales/id.json b/locales/id.json
index ca4c1e0f..054a2557 100644
--- a/locales/id.json
+++ b/locales/id.json
@@ -14,7 +14,7 @@
"LIVE": "SIARAN LANGSUNG",
"Shared `x` ago": "Dibagikan `x` yang lalu",
"Unsubscribe": "Batal Langganan",
- "Subscribe": "Berangganan",
+ "Subscribe": "Berlangganan",
"View channel on YouTube": "Lihat kanal di YouTube",
"View playlist on YouTube": "Lihat daftar putar di YouTube",
"newest": "terbaru",
@@ -209,7 +209,7 @@
"Please log in": "Harap masuk",
"Invidious Private Feed for `x`": "Umpan pribadi Invidious untuk`x`",
"channel:`x`": "kanal:`x`",
- "Deleted or invalid channel": "Kanal terhapus atau invalid",
+ "Deleted or invalid channel": "Kanal terhapus atau tidak valid",
"This channel does not exist.": "Kanal ini tidak ada.",
"Could not get channel info.": "Tidak bisa mendapatkan info kanal.",
"Could not fetch comments": "Tidak dapat memuat komentar",
@@ -220,8 +220,8 @@
"`x` ago": "`x` lalu",
"Load more": "Muat lebih banyak",
"`x` points": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "`x` titik",
- "": "`x` titik"
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` poin",
+ "": "`x` poin"
},
"Could not create mix.": "Tidak dapat membuat mix.",
"Empty playlist": "Daftar putar kosong",
@@ -372,10 +372,10 @@
"Popular": "Populer",
"Search": "Cari",
"Top": "Teratas",
- "About": "Ihwal",
- "Rating: ": "Peringkat: ",
+ "About": "Tentang",
+ "Rating: ": "Rating: ",
"preferences_locale_label": "Bahasa: ",
- "View as playlist": "Tampilkan sebagai daftar putar",
+ "View as playlist": "Lihat sebagai daftar putar",
"Default": "Baku",
"Music": "Musik",
"Gaming": "Permainan",
@@ -385,7 +385,7 @@
"Download as: ": "Unduh sebagai: ",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"(edited)": "(disunting)",
- "YouTube comment permalink": "Komentar YouTube permalink",
+ "YouTube comment permalink": "Tautan permanen komentar YouTube",
"permalink": "tautan permanen",
"`x` marked it with a ❤": "`x` telah ditandai dengan ❤",
"Audio mode": "Mode audio",
@@ -393,33 +393,33 @@
"Videos": "Video",
"Playlists": "Daftar putar",
"Community": "Komunitas",
- "relevance": "Relevan",
- "rating": "peringkat",
- "date": "tanggal",
- "views": "ditonton",
- "content_type": "tipe_konten",
- "duration": "durasi",
- "features": "fitur",
- "sort": "urut",
- "hour": "jam",
- "today": "hari ini",
- "week": "minggu",
- "month": "bulan",
- "year": "tahun",
- "video": "video",
- "channel": "kanal",
- "playlist": "daftar putar",
- "movie": "film",
- "show": "tampilkan",
- "hd": "hd",
- "subtitles": "subtitel",
- "creative_commons": "creative_commons",
- "3d": "3d",
- "live": "siaran langsung",
- "4k": "4k",
- "location": "lokasi",
- "hdr": "hdr",
- "filter": "saring",
+ "relevance": "Relevansi",
+ "rating": "Rating",
+ "date": "Tanggal unggah",
+ "views": "Jumlah ditonton",
+ "content_type": "Tipe",
+ "duration": "Durasi",
+ "features": "Fitur",
+ "sort": "Urut Berdasarkan",
+ "hour": "Jam Terakhir",
+ "today": "Hari Ini",
+ "week": "Pekan Ini",
+ "month": "Bulan Ini",
+ "year": "Tahun Ini",
+ "video": "Video",
+ "channel": "Kanal",
+ "playlist": "Daftar Putar",
+ "movie": "Film",
+ "show": "Pertunjukan/Acara",
+ "hd": "HD",
+ "subtitles": "Takarir",
+ "creative_commons": "Creative Commons",
+ "3d": "3D",
+ "live": "Siaran Langsung",
+ "4k": "4K",
+ "location": "Lokasi",
+ "hdr": "HDR",
+ "filter": "Saring",
"Current version: ": "Versi saat ini: ",
"next_steps_error_message": "Setelah itu Anda harus mencoba: ",
"next_steps_error_message_refresh": "Segarkan",
diff --git a/locales/pt-BR.json b/locales/pt-BR.json
index 072deff2..6baa2c0d 100644
--- a/locales/pt-BR.json
+++ b/locales/pt-BR.json
@@ -431,5 +431,7 @@
"footer_documentation": "Documentação",
"footer_source_code": "Código fonte",
"footer_original_source_code": "Código fonte original",
- "footer_modfied_source_code": "Código Fonte Modificado"
+ "footer_modfied_source_code": "Código Fonte Modificado",
+ "preferences_quality_dash_label": "Qualidade de vídeo do painel preferida: ",
+ "preferences_region_label": "País do conteúdo: "
}
diff --git a/locales/sr.json b/locales/sr.json
index 0082bd66..e0713b43 100644
--- a/locales/sr.json
+++ b/locales/sr.json
@@ -19,7 +19,7 @@
"View playlist on YouTube": "Погледај списак извођења на YouTube-у",
"newest": "најновије",
"oldest": "најстарије",
- "popular": "гласовито",
+ "popular": "популарно",
"last": "последње",
"Next page": "Следећа страница",
"Previous page": "Претходна страница",
@@ -66,5 +66,372 @@
"preferences_continue_label": "Увек подразумевано пуштај следеће: ",
"preferences_continue_autoplay_label": "Самопуштање следећег видео записа: ",
"preferences_listen_label": "Увек подразумевано укључен само звук: ",
- "preferences_local_label": "Приказ видео записа преко посредника: "
+ "preferences_local_label": "Приказ видео записа преко посредника: ",
+ "Playlist privacy": "Подешавања приватности плеј листе",
+ "Editing playlist `x`": "Измена плеј листе `x`",
+ "Please sign in using 'Log in with Google'": "Молимо Вас да се пријавите помоћу 'Log in with Google'",
+ "Playlist does not exist.": "Непостојећа плеј листа.",
+ "Erroneous challenge": "Погрешан изазов",
+ "Maltese": "Малтешки",
+ "Download": "Преузми",
+ "Download as: ": "Преузми као: ",
+ "Quota exceeded, try again in a few hours": "Квота је премашена, молимо Вас да покушате за пар сати",
+ "Bangla": "Бангла/Бенгалски",
+ "preferences_quality_dash_label": "Преферирани квалитет dash видео формата: ",
+ "Token manager": "Меначер токена",
+ "Token": "Токен",
+ "`x` tokens": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` токен",
+ "": "`x` токена"
+ },
+ "Import/export": "Увези/Извези",
+ "revoke": "опозови",
+ "`x` unseen notifications": {
+ "": "`x` непрегледаних обавештења",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` непрегледаних обавештења"
+ },
+ "search": "претрага",
+ "Log out": "Одјава",
+ "Source available here.": "Изворни код.",
+ "Trending": "У тренду",
+ "Updated `x` ago": "Ажурирано пре `x`",
+ "Delete playlist `x`?": "Обриши плеј листу `x`?",
+ "Create playlist": "Направи плеј листу",
+ "Show less": "Прикажи мање",
+ "Switch Invidious Instance": "Промени Invidious инстанцу",
+ "Hide annotations": "Сакриј напомене",
+ "User ID is a required field": "Кориснички ID је обавезно поље",
+ "Wrong username or password": "Погрешно корисничко име или лозинка",
+ "Please log in": "Молимо Вас да се пријавите",
+ "channel:`x`": "канал:`x`",
+ "Could not fetch comments": "Узимање коментара није успело",
+ "`x` points": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` поен",
+ "": "`x` поена"
+ },
+ "Could not create mix.": "Прављење микса није успело.",
+ "Empty playlist": "Празна плеј листа",
+ "Not a playlist.": "Није плеј листа.",
+ "Could not pull trending pages.": "Учитавање 'У току' странције није успело.",
+ "Token is expired, please try again": "Токен је истекао, молимо Вас да покушате поново",
+ "English (auto-generated)": "Енглески (аутоматски генерисано)",
+ "Afrikaans": "Африканс",
+ "Albanian": "Албански",
+ "Armenian": "Јерменски",
+ "Azerbaijani": "Азербејџански",
+ "Basque": "Баскијски",
+ "Bosnian": "Српски (Босна и Херцеговина)",
+ "Bulgarian": "Бугарски",
+ "Burmese": "Бурмански",
+ "Catalan": "Каталонски",
+ "Cebuano": "Cebuano",
+ "Chinese (Traditional)": "Кинески (Традиционални)",
+ "Corsican": "Корзикански",
+ "Danish": "Дански",
+ "Kannada": "Канада (Језик)",
+ "Kazakh": "Казашки",
+ "Russian": "Руски",
+ "Scottish Gaelic": "Шкотски Гелски",
+ "Sinhala": "Синхалешки",
+ "Slovak": "Словачки",
+ "Spanish": "Шпански",
+ "Spanish (Latin America)": "Шпански (Јужна Америка)",
+ "Sundanese": "Сундски",
+ "Swedish": "Шведски",
+ "Tajik": "Таџички",
+ "Telugu": "Телугу",
+ "Turkish": "Турски",
+ "Ukrainian": "Украјински",
+ "Urdu": "Урду",
+ "Uzbek": "Узбечки",
+ "Vietnamese": "Вијетнамски",
+ "`x` minutes": {
+ "": "`x` минута",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` минут"
+ },
+ "`x` seconds": {
+ "": "`x` секунди",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` секунда"
+ },
+ "Rating: ": "Оцена/е: ",
+ "View as playlist": "Погледај као плеј листу",
+ "Default": "Подразумеван/о",
+ "Gaming": "Гејминг",
+ "Movies": "Филмови",
+ "%A %B %-d, %Y": "%A %B %-d, %Y",
+ "(edited)": "(измењено)",
+ "YouTube comment permalink": "YouTube коментар трајна веза",
+ "Audio mode": "Аудио мод",
+ "Playlists": "Плеј листе",
+ "relevance": "Ревелантно",
+ "rating": "Оцене",
+ "date": "Датум отпремања",
+ "views": "Број прегледа",
+ "`x` marked it with a ❤": "`x` је означио/ла ово са ❤",
+ "duration": "Трајање",
+ "features": "Карактеристике",
+ "hour": "Последњи сат",
+ "week": "Ове недеље",
+ "month": "Овај месец",
+ "year": "Ове године",
+ "video": "Видео",
+ "playlist": "Плеј листа",
+ "movie": "Филм",
+ "long": "Дуг (> 20 минута)",
+ "hd": "HD",
+ "creative_commons": "Creative Commons (Лиценца)",
+ "3d": "3Д",
+ "hdr": "Видео високе резолуције",
+ "filter": "Филтер",
+ "next_steps_error_message": "Можете урадити нешта од следећег: ",
+ "next_steps_error_message_go_to_youtube": "Иди на YouTube",
+ "footer_documentation": "Документација",
+ "preferences_region_label": "Држава порекла садржаја: ",
+ "preferences_player_style_label": "Стил плејера: ",
+ "preferences_dark_mode_label": "Изглед/Тема: ",
+ "light": "светла",
+ "preferences_thin_mode_label": "Компактни режим: ",
+ "preferences_category_misc": "Остала подешавања",
+ "preferences_automatic_instance_redirect_label": "Аутоматско пребацивање на другу инстанцу у случају отказивања (пређи на redirect.invidious.io): ",
+ "alphabetically - reverse": "по алфабету - обрнуто",
+ "Enable web notifications": "Омогући обавештења у веб претраживачу",
+ "`x` is live": "`x` преноси уживо",
+ "Manage tokens": "Управљај токенима",
+ "Watch history": "Историја гледања",
+ "preferences_feed_menu_label": "Feed мени: ",
+ "preferences_show_nick_label": "Прикажи надимке на врху: ",
+ "CAPTCHA enabled: ": "CAPTCHA омогућена: ",
+ "Registration enabled: ": "Регистрација омогућена: ",
+ "Subscription manager": "Менаџер претплата",
+ "Wilson score: ": "Wilson скор: ",
+ "Engagement: ": "Ангажовање: ",
+ "Whitelisted regions: ": "Дозвољени региони: ",
+ "Shared `x`": "Подељено `x`",
+ "`x` views": {
+ "": "`x` прегледа",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` преглед"
+ },
+ "Premieres in `x`": "Премијера у `x`",
+ "Premieres `x`": "Премијере у `x`",
+ "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Хеј! Изгледа да сте онемогућили JavaScript. Кликните овде да видите коментаре, имајте на уму да ово може да потраје дуже док се не учитају.",
+ "View `x` comments": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Прикажи `x` коментар",
+ "": "Прикажи `x` коментара"
+ },
+ "View Reddit comments": "Прикажи Reddit коментаре",
+ "Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Неуспешна пријава, проверите да ли сте упалили двофакторну аутентикацију (Аутентикатор или СМС).",
+ "CAPTCHA is a required field": "CAPTCHA је обавезно поље",
+ "Croatian": "Хрватски",
+ "Estonian": "Естонски",
+ "Filipino": "Филипино",
+ "French": "Француски",
+ "Galician": "Галицијски",
+ "German": "Немачки",
+ "Greek": "Грчки",
+ "Hausa": "Хауса",
+ "Italian": "Италијански",
+ "Khmer": "Кмерски",
+ "Kurdish": "Курдски",
+ "Kyrgyz": "Киргиски",
+ "Latvian": "Летонски",
+ "Lithuanian": "Литвански",
+ "Macedonian": "Македонски",
+ "Malagasy": "Малгашки",
+ "Malay": "Малајски",
+ "Marathi": "Маратхи",
+ "Mongolian": "Монголски",
+ "Norwegian Bokmål": "Норвешки Бокмал",
+ "Nyanja": "Чева",
+ "Pashto": "Паштунски",
+ "Persian": "Персијски",
+ "Punjabi": "Пунџаби",
+ "Romanian": "Румунски",
+ "Welsh": "Велшки",
+ "Western Frisian": "Западнофризијски",
+ "`x` years": {
+ "": "`x` година",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` година"
+ },
+ "`x` weeks": {
+ "": "`x` недеља",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` недеља"
+ },
+ "`x` days": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` дан",
+ "": "`x` дана"
+ },
+ "`x` hours": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` сат",
+ "": "`x` сати"
+ },
+ "Fallback comments: ": "Коментари у случају отказивања: ",
+ "Popular": "Популарно",
+ "Search": "Претрага",
+ "About": "О програму",
+ "footer_source_code": "Изворни Код",
+ "footer_original_source_code": "Оригинални изворни код",
+ "preferences_related_videos_label": "Прикажи сличне видео клипове: ",
+ "preferences_annotations_label": "Прикажи напомене подразумевано: ",
+ "preferences_extend_desc_label": "Аутоматски прикажи цео опис видеа: ",
+ "preferences_vr_mode_label": "Интерактивни видео клипови у 360 степени: ",
+ "preferences_category_visual": "Визуелне преференце",
+ "preferences_captions_label": "Подразумевани титл: ",
+ "Music": "Музика",
+ "content_type": "Тип",
+ "Broken? Try another Invidious Instance": "Не функционише исправно? Пробајте другу Invidious инстанцу",
+ "Tamil": "Тамилски",
+ "Save preferences": "Сачувај подешавања",
+ "Only show latest unwatched video from channel: ": "Прикажи само последње видео клипове који нису погледани са канала: ",
+ "Xhosa": "Коса (Језик)",
+ "channel": "Канал",
+ "Hungarian": "Мађарски",
+ "Maori": "Маори (Језик)",
+ "Manage subscriptions": "Управљај претплатама",
+ "Hindi": "Хинди",
+ "`x` ago": "пре `x`",
+ "Import/export data": "Увези/Извези податке",
+ "`x` uploaded a video": "`x` је отпремио/ла видео клип",
+ "View `x` replies": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Погледај `x` одоговор",
+ "": "Погледај `x` одоговора"
+ },
+ "Delete account": "Обриши налог",
+ "preferences_default_home_label": "Подразумевана почетна страница: ",
+ "Serbian": "Српски",
+ "License: ": "Лиценца: ",
+ "live": "Уживо",
+ "Report statistics: ": "Извештавај о статистици: ",
+ "Only show latest video from channel: ": "Приказуј последње видео клипове само са канала: ",
+ "channel name - reverse": "име канала - обрнуто",
+ "Could not get channel info.": "Узимање података о каналу није успело.",
+ "View privacy policy.": "Погледај политику приватности.",
+ "Change password": "Промени лозинку",
+ "Malayalam": "Малајалам",
+ "View more comments on Reddit": "Прикажи више коментара на Reddit-у",
+ "Portuguese": "Португалски",
+ "View YouTube comments": "Прикажи YouTube коментаре",
+ "published - reverse": "објављено - обрнуто",
+ "Dutch": "Белгијски",
+ "preferences_volume_label": "Јачина звука: ",
+ "preferences_locale_label": "Језик: ",
+ "`x` subscriptions": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` пратиоц",
+ "": "`x` пратилаца"
+ },
+ "adminprefs_modified_source_code_url_label": "URL веза до репозиторијума са измењеним изворним кодом",
+ "Community": "Заједница",
+ "Video mode": "Видео мод",
+ "Fallback captions: ": "Титл у случају да главни није доступан: ",
+ "Private": "Приватно",
+ "alphabetically": "по алфабету",
+ "No such user": "Непостојећи корисник",
+ "Subscriptions": "Праћења",
+ "today": "Данас",
+ "Finnish": "Фински",
+ "Lao": "Лаоски",
+ "Login enabled: ": "Пријава омогућена: ",
+ "Shona": "Шона",
+ "location": "Локација",
+ "Load more": "Учитај више",
+ "Released under the AGPLv3 on Github.": "Избачено под лиценцом AGPLv3 на Github-у.",
+ "Slovenian": "Словеначки",
+ "View JavaScript license information.": "Погледај информације лиценце везане за JavaScript.",
+ "Chinese (Simplified)": "Кинески (Поједностављени)",
+ "preferences_comments_label": "Подразумевани коментари: ",
+ "Incorrect password": "Нетачна лозинка",
+ "Show replies": "Прикажи одговоре",
+ "Invidious Private Feed for `x`": "Invidious приватни Feed за `x`",
+ "Watch on YouTube": "Гледај на YouTube-у",
+ "Wrong answer": "Погрешан одговор",
+ "preferences_quality_label": "Преферирани видео квалитет: ",
+ "Hide replies": "Сакриј одговоре",
+ "Invalid TFA code": "Неважећи TFA код",
+ "Login failed. This may be because two-factor authentication is not turned on for your account.": "Неуспешна пријава! Ово се можда дешава јер двофакторна аутентикација није омогућена на Вашем налогу.",
+ "Erroneous CAPTCHA": "Погрешна CAPTCHA",
+ "Erroneous token": "Погрешан токен",
+ "Czech": "Чешки",
+ "Latin": "Латински",
+ "Videos": "Видео клипови",
+ "4k": "4К",
+ "footer_donate_page": "Донирај",
+ "English": "Енглески",
+ "Arabic": "Арапски",
+ "Unlisted": "Ненаведено",
+ "Hidden field \"challenge\" is a required field": "Сакривено \"challenge\" поље је обавезно",
+ "Hidden field \"token\" is a required field": "Сакривено \"token\" поље је обавезно",
+ "Georgian": "Грузијски",
+ "Hawaiian": "Хавајски",
+ "Hebrew": "Хебрејски",
+ "Icelandic": "Исландски",
+ "Igbo": "Игбо",
+ "Japanese": "Јапански",
+ "Javanese": "Јавански",
+ "Sindhi": "Синди",
+ "Swahili": "Свахили",
+ "Yiddish": "Јидиш",
+ "Zulu": "Зулу",
+ "subtitles": "Титл",
+ "Password cannot be longer than 55 characters": "Лозинка не може бити дужа од 55 карактера",
+ "This channel does not exist.": "Овај канал не постоји.",
+ "Belarusian": "Белоруски",
+ "Gujarati": "Гуџарати",
+ "Haitian Creole": "Хаићански Креолски",
+ "Somali": "Сомалијски",
+ "Top": "Врх",
+ "footer_modfied_source_code": "Измењени изворни код",
+ "preferences_category_subscription": "Подешавања праћења",
+ "preferences_annotations_subscribed_label": "Подразумевано приказати напомене за канале које пратите? ",
+ "preferences_max_results_label": "Број видео клипова приказаних у листи (feed-у): ",
+ "preferences_sort_label": "Сортирај видео клипове по: ",
+ "preferences_unseen_only_label": "Прикажи само видео клипове који нису погледани: ",
+ "preferences_notifications_only_label": "Прикажи само обавештења (ако их уопште има): ",
+ "preferences_category_data": "Подешавања података",
+ "Clear watch history": "Обриши историју гледања",
+ "preferences_category_admin": "Администраторска подешавања",
+ "published": "објављено",
+ "sort": "Сортирај према",
+ "show": "Шоу",
+ "short": "Кратак (< 4 минута)",
+ "Current version: ": "Тренутна верзија: ",
+ "Top enabled: ": "Врх омогућен: ",
+ "Public": "Јавно",
+ "Delete playlist": "Обриши плеј листу",
+ "Title": "Наслов",
+ "Show annotations": "Прикажи напомене",
+ "Password cannot be empty": "Лозинка не може бити празна",
+ "Deleted or invalid channel": "Обрисан или непостојећи канал",
+ "Esperanto": "Есперанто",
+ "Hmong": "Хмонг",
+ "Luxembourgish": "Луксембуршки",
+ "Nepali": "Непалски",
+ "Samoan": "Самоански",
+ "News": "Вести",
+ "permalink": "трајна веза",
+ "Password is a required field": "Лозинка је обавезно поље",
+ "Amharic": "Амхарски",
+ "Indonesian": "Индонежански",
+ "Irish": "Ирски",
+ "Korean": "Корејски",
+ "Southern Sotho": "Сото",
+ "Thai": "Тајски",
+ "`x` months": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` месец",
+ "": "`x` месеци"
+ },
+ "preferences_speed_label": "Подразумевана брзина: ",
+ "Dark mode: ": "Тамни режим: ",
+ "dark": "тамна",
+ "Redirect homepage to feed: ": "Пребаци са почетне странице на листу (feed): ",
+ "channel name": "име канала",
+ "View all playlists": "Прегледај све плеј листе",
+ "Show more": "Прикажи више",
+ "Genre: ": "Жанр: ",
+ "Family friendly? ": "Погодно за породицу? ",
+ "next_steps_error_message_refresh": "Освежи страницу",
+ "youtube": "YouTube",
+ "reddit": "Reddit",
+ "unsubscribe": "прекини са праћењем",
+ "Blacklisted regions: ": "Блокирани региони: ",
+ "Polish": "Пољски",
+ "Yoruba": "Јоруба"
}
diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr
index d3e5800c..4406284f 100644
--- a/src/invidious/videos.cr
+++ b/src/invidious/videos.cr
@@ -857,8 +857,16 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_
else
client_config.client_type = YoutubeAPI::ClientType::Android
end
- stream_data = YoutubeAPI.player(video_id: video_id, params: "", client_config: client_config)
- params["streamingData"] = stream_data["streamingData"]? || JSON::Any.new("")
+ android_player = YoutubeAPI.player(video_id: video_id, params: "", client_config: client_config)
+
+ # Sometime, the video is available from the web client, but not on Android, so check
+ # that here, and fallback to the streaming data from the web client if needed.
+ # See: https://github.com/iv-org/invidious/issues/2549
+ if android_player["playabilityStatus"]["status"] == "OK"
+ params["streamingData"] = android_player["streamingData"]? || JSON::Any.new("")
+ else
+ params["streamingData"] = player_response["streamingData"]? || JSON::Any.new("")
+ end
end
{"captions", "microformat", "playabilityStatus", "storyboards", "videoDetails"}.each do |f|