diff --git a/assets/css/default.css b/assets/css/default.css
index 910a8fed..ccfe8a0b 100644
--- a/assets/css/default.css
+++ b/assets/css/default.css
@@ -392,11 +392,19 @@ p.video-data { margin: 0; font-weight: bold; font-size: 80%; }
* Comments & community posts
*/
-#comments {
+.comments {
max-width: 800px;
margin: auto;
}
+/*
+ * We don't want the top and bottom margin on the post page.
+ */
+.comments.post-comments {
+ margin-bottom: 0;
+ margin-top: 0;
+}
+
.video-iframe-wrapper {
position: relative;
height: 0;
diff --git a/assets/js/comments.js b/assets/js/comments.js
new file mode 100644
index 00000000..35ffa96e
--- /dev/null
+++ b/assets/js/comments.js
@@ -0,0 +1,174 @@
+var video_data = JSON.parse(document.getElementById('video_data').textContent);
+
+var spinnerHTML = '
';
+var spinnerHTMLwithHR = spinnerHTML + '
';
+
+String.prototype.supplant = function (o) {
+ return this.replace(/{([^{}]*)}/g, function (a, b) {
+ var r = o[b];
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
+ });
+};
+
+function toggle_comments(event) {
+ var target = event.target;
+ var body = target.parentNode.parentNode.parentNode.children[1];
+ if (body.style.display === 'none') {
+ target.textContent = '[ − ]';
+ body.style.display = '';
+ } else {
+ target.textContent = '[ + ]';
+ body.style.display = 'none';
+ }
+}
+
+function hide_youtube_replies(event) {
+ var target = event.target;
+
+ var sub_text = target.getAttribute('data-inner-text');
+ var inner_text = target.getAttribute('data-sub-text');
+
+ var body = target.parentNode.parentNode.children[1];
+ body.style.display = 'none';
+
+ target.textContent = sub_text;
+ target.onclick = show_youtube_replies;
+ target.setAttribute('data-inner-text', inner_text);
+ target.setAttribute('data-sub-text', sub_text);
+}
+
+function show_youtube_replies(event) {
+ var target = event.target;
+
+ var sub_text = target.getAttribute('data-inner-text');
+ var inner_text = target.getAttribute('data-sub-text');
+
+ var body = target.parentNode.parentNode.children[1];
+ body.style.display = '';
+
+ target.textContent = sub_text;
+ target.onclick = hide_youtube_replies;
+ target.setAttribute('data-inner-text', inner_text);
+ target.setAttribute('data-sub-text', sub_text);
+}
+
+function get_youtube_comments() {
+ var comments = document.getElementById('comments');
+
+ var fallback = comments.innerHTML;
+ comments.innerHTML = spinnerHTML;
+
+ var baseUrl = video_data.base_url || '/api/v1/comments/'+ video_data.id
+ var url = baseUrl +
+ '?format=html' +
+ '&hl=' + video_data.preferences.locale +
+ '&thin_mode=' + video_data.preferences.thin_mode;
+
+ if (video_data.ucid) {
+ url += '&ucid=' + video_data.ucid
+ }
+
+ var onNon200 = function (xhr) { comments.innerHTML = fallback; };
+ if (video_data.params.comments[1] === 'youtube')
+ onNon200 = function (xhr) {};
+
+ helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
+ on200: function (response) {
+ var commentInnerHtml = ' \
+ \
+
\
+ [ − ] \
+ {commentsText} \
+
\
+
\
+ '
+ if (video_data.support_reddit) {
+ commentInnerHtml += ' \
+ {redditComments} \
+ \
+ '
+ }
+ commentInnerHtml += ' \
+
\
+ {contentHtml}
\
+
'
+ commentInnerHtml = commentInnerHtml.supplant({
+ contentHtml: response.contentHtml,
+ redditComments: video_data.reddit_comments_text,
+ commentsText: video_data.comments_text.supplant({
+ // toLocaleString correctly splits number with local thousands separator. e.g.:
+ // '1,234,567.89' for user with English locale
+ // '1 234 567,89' for user with Russian locale
+ // '1.234.567,89' for user with Portuguese locale
+ commentCount: response.commentCount.toLocaleString()
+ })
+ });
+ comments.innerHTML = commentInnerHtml;
+ comments.children[0].children[0].children[0].onclick = toggle_comments;
+ if (video_data.support_reddit) {
+ comments.children[0].children[1].children[0].onclick = swap_comments;
+ }
+ },
+ onNon200: onNon200, // declared above
+ onError: function (xhr) {
+ comments.innerHTML = spinnerHTML;
+ },
+ onTimeout: function (xhr) {
+ comments.innerHTML = spinnerHTML;
+ }
+ });
+}
+
+function get_youtube_replies(target, load_more, load_replies) {
+ var continuation = target.getAttribute('data-continuation');
+
+ var body = target.parentNode.parentNode;
+ var fallback = body.innerHTML;
+ body.innerHTML = spinnerHTML;
+ var baseUrl = video_data.base_url || '/api/v1/comments/'+ video_data.id
+ var url = baseUrl +
+ '?format=html' +
+ '&hl=' + video_data.preferences.locale +
+ '&thin_mode=' + video_data.preferences.thin_mode +
+ '&continuation=' + continuation;
+
+ if (video_data.ucid) {
+ url += '&ucid=' + video_data.ucid
+ }
+ if (load_replies) url += '&action=action_get_comment_replies';
+
+ helpers.xhr('GET', url, {}, {
+ on200: function (response) {
+ if (load_more) {
+ body = body.parentNode.parentNode;
+ body.removeChild(body.lastElementChild);
+ body.insertAdjacentHTML('beforeend', response.contentHtml);
+ } else {
+ body.removeChild(body.lastElementChild);
+
+ var p = document.createElement('p');
+ var a = document.createElement('a');
+ p.appendChild(a);
+
+ a.href = 'javascript:void(0)';
+ a.onclick = hide_youtube_replies;
+ a.setAttribute('data-sub-text', video_data.hide_replies_text);
+ a.setAttribute('data-inner-text', video_data.show_replies_text);
+ a.textContent = video_data.hide_replies_text;
+
+ var div = document.createElement('div');
+ div.innerHTML = response.contentHtml;
+
+ body.appendChild(p);
+ body.appendChild(div);
+ }
+ },
+ onNon200: function (xhr) {
+ body.innerHTML = fallback;
+ },
+ onTimeout: function (xhr) {
+ console.warn('Pulling comments failed');
+ body.innerHTML = fallback;
+ }
+ });
+}
\ No newline at end of file
diff --git a/assets/js/post.js b/assets/js/post.js
new file mode 100644
index 00000000..fcbc9155
--- /dev/null
+++ b/assets/js/post.js
@@ -0,0 +1,3 @@
+addEventListener('load', function (e) {
+ get_youtube_comments();
+});
diff --git a/assets/js/watch.js b/assets/js/watch.js
index 92f27bf8..50e1f82e 100644
--- a/assets/js/watch.js
+++ b/assets/js/watch.js
@@ -1,14 +1,4 @@
'use strict';
-var video_data = JSON.parse(document.getElementById('video_data').textContent);
-var spinnerHTML = '
';
-var spinnerHTMLwithHR = spinnerHTML + '
';
-
-String.prototype.supplant = function (o) {
- return this.replace(/{([^{}]*)}/g, function (a, b) {
- var r = o[b];
- return typeof r === 'string' || typeof r === 'number' ? r : a;
- });
-};
function toggle_parent(target) {
var body = target.parentNode.parentNode.children[1];
@@ -21,18 +11,6 @@ function toggle_parent(target) {
}
}
-function toggle_comments(event) {
- var target = event.target;
- var body = target.parentNode.parentNode.parentNode.children[1];
- if (body.style.display === 'none') {
- target.textContent = '[ − ]';
- body.style.display = '';
- } else {
- target.textContent = '[ + ]';
- body.style.display = 'none';
- }
-}
-
function swap_comments(event) {
var source = event.target.getAttribute('data-comments');
@@ -43,36 +21,6 @@ function swap_comments(event) {
}
}
-function hide_youtube_replies(event) {
- var target = event.target;
-
- var sub_text = target.getAttribute('data-inner-text');
- var inner_text = target.getAttribute('data-sub-text');
-
- var body = target.parentNode.parentNode.children[1];
- body.style.display = 'none';
-
- target.textContent = sub_text;
- target.onclick = show_youtube_replies;
- target.setAttribute('data-inner-text', inner_text);
- target.setAttribute('data-sub-text', sub_text);
-}
-
-function show_youtube_replies(event) {
- var target = event.target;
-
- var sub_text = target.getAttribute('data-inner-text');
- var inner_text = target.getAttribute('data-sub-text');
-
- var body = target.parentNode.parentNode.children[1];
- body.style.display = '';
-
- target.textContent = sub_text;
- target.onclick = hide_youtube_replies;
- target.setAttribute('data-inner-text', inner_text);
- target.setAttribute('data-sub-text', sub_text);
-}
-
var continue_button = document.getElementById('continue');
if (continue_button) {
continue_button.onclick = continue_autoplay;
@@ -261,111 +209,6 @@ function get_reddit_comments() {
});
}
-function get_youtube_comments() {
- var comments = document.getElementById('comments');
-
- var fallback = comments.innerHTML;
- comments.innerHTML = spinnerHTML;
-
- var url = '/api/v1/comments/' + video_data.id +
- '?format=html' +
- '&hl=' + video_data.preferences.locale +
- '&thin_mode=' + video_data.preferences.thin_mode;
-
- var onNon200 = function (xhr) { comments.innerHTML = fallback; };
- if (video_data.params.comments[1] === 'youtube')
- onNon200 = function (xhr) {};
-
- helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
- on200: function (response) {
- comments.innerHTML = ' \
- \
- {contentHtml}
\
-
'.supplant({
- contentHtml: response.contentHtml,
- redditComments: video_data.reddit_comments_text,
- commentsText: video_data.comments_text.supplant({
- // toLocaleString correctly splits number with local thousands separator. e.g.:
- // '1,234,567.89' for user with English locale
- // '1 234 567,89' for user with Russian locale
- // '1.234.567,89' for user with Portuguese locale
- commentCount: response.commentCount.toLocaleString()
- })
- });
-
- comments.children[0].children[0].children[0].onclick = toggle_comments;
- comments.children[0].children[1].children[0].onclick = swap_comments;
- },
- onNon200: onNon200, // declared above
- onError: function (xhr) {
- comments.innerHTML = spinnerHTML;
- },
- onTimeout: function (xhr) {
- comments.innerHTML = spinnerHTML;
- }
- });
-}
-
-function get_youtube_replies(target, load_more, load_replies) {
- var continuation = target.getAttribute('data-continuation');
-
- var body = target.parentNode.parentNode;
- var fallback = body.innerHTML;
- body.innerHTML = spinnerHTML;
-
- var url = '/api/v1/comments/' + video_data.id +
- '?format=html' +
- '&hl=' + video_data.preferences.locale +
- '&thin_mode=' + video_data.preferences.thin_mode +
- '&continuation=' + continuation;
- if (load_replies) url += '&action=action_get_comment_replies';
-
- helpers.xhr('GET', url, {}, {
- on200: function (response) {
- if (load_more) {
- body = body.parentNode.parentNode;
- body.removeChild(body.lastElementChild);
- body.insertAdjacentHTML('beforeend', response.contentHtml);
- } else {
- body.removeChild(body.lastElementChild);
-
- var p = document.createElement('p');
- var a = document.createElement('a');
- p.appendChild(a);
-
- a.href = 'javascript:void(0)';
- a.onclick = hide_youtube_replies;
- a.setAttribute('data-sub-text', video_data.hide_replies_text);
- a.setAttribute('data-inner-text', video_data.show_replies_text);
- a.textContent = video_data.hide_replies_text;
-
- var div = document.createElement('div');
- div.innerHTML = response.contentHtml;
-
- body.appendChild(p);
- body.appendChild(div);
- }
- },
- onNon200: function (xhr) {
- body.innerHTML = fallback;
- },
- onTimeout: function (xhr) {
- console.warn('Pulling comments failed');
- body.innerHTML = fallback;
- }
- });
-}
-
if (video_data.play_next) {
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
diff --git a/assets/site.webmanifest b/assets/site.webmanifest
index af9432d7..2db6ed9e 100644
--- a/assets/site.webmanifest
+++ b/assets/site.webmanifest
@@ -15,5 +15,7 @@
],
"theme_color": "#575757",
"background_color": "#575757",
- "display": "standalone"
+ "display": "standalone",
+ "description": "An alternative front-end to YouTube",
+ "start_url": "/"
}
diff --git a/locales/ar.json b/locales/ar.json
index 877fb9ff..18298913 100644
--- a/locales/ar.json
+++ b/locales/ar.json
@@ -548,5 +548,11 @@
"generic_button_rss": "RSS",
"channel_tab_releases_label": "الإصدارات",
"playlist_button_add_items": "إضافة مقاطع فيديو",
- "channel_tab_podcasts_label": "البودكاست"
+ "channel_tab_podcasts_label": "البودكاست",
+ "generic_channels_count_0": "{{count}} قناة",
+ "generic_channels_count_1": "{{count}} قناة",
+ "generic_channels_count_2": "{{count}} قناتان",
+ "generic_channels_count_3": "{{count}} قنوات",
+ "generic_channels_count_4": "{{count}} قنوات",
+ "generic_channels_count_5": "{{count}} قناة"
}
diff --git a/locales/la.json b/locales/be.json
similarity index 100%
rename from locales/la.json
rename to locales/be.json
diff --git a/locales/bg.json b/locales/bg.json
new file mode 100644
index 00000000..82591ed8
--- /dev/null
+++ b/locales/bg.json
@@ -0,0 +1,490 @@
+{
+ "Korean (auto-generated)": "Корейски (автоматично генерирано)",
+ "search_filters_features_option_three_sixty": "360°",
+ "published - reverse": "публикувани - в обратен ред",
+ "preferences_quality_dash_option_worst": "Най-ниско качество",
+ "Password is a required field": "Парола е задължитело поле",
+ "channel_tab_podcasts_label": "Подкасти",
+ "Token is expired, please try again": "Токенът е изтекъл, моля опитайте отново",
+ "Turkish": "Турски",
+ "preferences_save_player_pos_label": "Запази позицията на плейъра: ",
+ "View Reddit comments": "Виж Reddit коментари",
+ "Export data as JSON": "Експортиране на Invidious информацията като JSON",
+ "About": "За сайта",
+ "Save preferences": "Запази промените",
+ "Load more": "Зареди още",
+ "Import/export": "Импортиране/експортиране",
+ "Albanian": "Албански",
+ "New password": "Нова парола",
+ "Southern Sotho": "Южен Сото",
+ "channel_tab_videos_label": "Видеа",
+ "Spanish (Mexico)": "Испански (Мексико)",
+ "preferences_player_style_label": "Стил на плейъра: ",
+ "preferences_region_label": "Държавата на съдържанието: ",
+ "Premieres in `x`": "Премиера в `x`",
+ "Watch history": "История на гледане",
+ "generic_subscriptions_count": "{{count}} абонамент",
+ "generic_subscriptions_count_plural": "{{count}} абонамента",
+ "preferences_continue_label": "Пускай следващото видео автоматично: ",
+ "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. Натисни тук за да видиш коментарите, но обърни внимание, че може да отнеме повече време да заредят.",
+ "Polish": "Полски",
+ "Icelandic": "Исландски",
+ "preferences_local_label": "Пускане на видеа през прокси: ",
+ "Hebrew": "Иврит",
+ "Fallback captions: ": "Резервни надписи: ",
+ "search_filters_title": "Филтри",
+ "search_filters_apply_button": "Приложете избрани филтри",
+ "Download is disabled": "Изтеглянето е деактивирано",
+ "User ID is a required field": "Потребителско име е задължително поле",
+ "comments_points_count": "{{count}} точка",
+ "comments_points_count_plural": "{{count}} точки",
+ "next_steps_error_message_go_to_youtube": "Отидеш в YouTube",
+ "preferences_quality_dash_option_2160p": "2160p",
+ "search_filters_type_option_video": "Видео",
+ "Spanish (Latin America)": "Испански (Латинска Америка)",
+ "Download as: ": "Изтегли като: ",
+ "Default": "По подразбиране",
+ "search_filters_sort_option_views": "Гледания",
+ "search_filters_features_option_four_k": "4K",
+ "Igbo": "Игбо",
+ "Subscriptions": "Абонаменти",
+ "German (auto-generated)": "Немски (автоматично генерирано)",
+ "`x` is live": "`x` е на живо",
+ "Azerbaijani": "Азербайджански",
+ "Premieres `x`": "Премиера `x`",
+ "Japanese (auto-generated)": "Японски (автоматично генерирано)",
+ "preferences_quality_option_medium": "Средно",
+ "footer_donate_page": "Даряване",
+ "Show replies": "Покажи отговорите",
+ "Esperanto": "Есперанто",
+ "search_message_change_filters_or_query": "Опитай да разшириш търсенето си и/или да смениш филтрите.",
+ "CAPTCHA enabled: ": "Активиране на CAPTCHA: ",
+ "View playlist on YouTube": "Виж плейлиста в YouTube",
+ "crash_page_before_reporting": "Преди докладването на бъг, бъди сигурен, че си:",
+ "Top enabled: ": "Активиране на страница с топ видеа: ",
+ "preferences_quality_dash_option_best": "Най-високо",
+ "search_filters_duration_label": "Продължителност",
+ "Slovak": "Словашки",
+ "Channel Sponsor": "Канален спонсор",
+ "generic_videos_count": "{{count}} видео",
+ "generic_videos_count_plural": "{{count}} видеа",
+ "videoinfo_started_streaming_x_ago": "Започна да излъчва преди `x`",
+ "videoinfo_youTube_embed_link": "Вграждане",
+ "channel_tab_streams_label": "Стриймове",
+ "oldest": "най-стари",
+ "playlist_button_add_items": "Добавяне на видеа",
+ "Import NewPipe data (.zip)": "Импортиране на NewPipe информация (.zip)",
+ "Clear watch history": "Изчистване на историята на гледане",
+ "generic_count_minutes": "{{count}} минута",
+ "generic_count_minutes_plural": "{{count}} минути",
+ "published": "публикувани",
+ "Show annotations": "Покажи анотации",
+ "Login enabled: ": "Активиране на впизване: ",
+ "Somali": "Сомалийски",
+ "YouTube comment permalink": "Постоянна връзка на коментарите на YouTube",
+ "Kurdish": "Кюрдски",
+ "search_filters_date_option_hour": "Последния час",
+ "Lao": "Лаоски",
+ "Maltese": "Малтийски",
+ "Register": "Регистрация",
+ "View channel on YouTube": "Виж канала в YouTube",
+ "Playlist privacy": "Поверителен плейлист",
+ "preferences_unseen_only_label": "Показвай само негледаните: ",
+ "Gujarati": "Гуджарати",
+ "Please log in": "Моля влезте",
+ "search_filters_sort_option_rating": "Рейтинг",
+ "Manage subscriptions": "Управление на абонаментите",
+ "preferences_quality_dash_option_720p": "720p",
+ "preferences_watch_history_label": "Активирай историята на гледане: ",
+ "user_saved_playlists": "`x` запази плейлисти",
+ "preferences_extend_desc_label": "Автоматично разшири описанието на видеото ",
+ "preferences_max_results_label": "Брой видеа показани на началната страница: ",
+ "Spanish (Spain)": "Испански (Испания)",
+ "invidious": "Invidious",
+ "crash_page_refresh": "пробвал да опресниш страницата",
+ "Image CAPTCHA": "CAPTCHA с Изображение",
+ "search_filters_features_option_hd": "HD",
+ "Chinese (Hong Kong)": "Китайски (Хонг Конг)",
+ "Import Invidious data": "Импортиране на Invidious JSON информацията",
+ "Blacklisted regions: ": "Неразрешени региони: ",
+ "Only show latest video from channel: ": "Показвай само най-новите видеа в канала: ",
+ "Hmong": "Хмонг",
+ "French": "Френски",
+ "search_filters_type_option_channel": "Канал",
+ "Artist: ": "Артист: ",
+ "generic_count_months": "{{count}} месец",
+ "generic_count_months_plural": "{{count}} месеца",
+ "preferences_annotations_subscribed_label": "Показвай анотаций по подразбиране за абонирани канали? ",
+ "search_message_use_another_instance": " Можеш също да търсиш на друга инстанция.",
+ "Danish": "Датски",
+ "generic_subscribers_count": "{{count}} абонат",
+ "generic_subscribers_count_plural": "{{count}} абоната",
+ "Galician": "Галисий",
+ "newest": "най-нови",
+ "Empty playlist": "Плейлиста е празен",
+ "download_subtitles": "Субритри - `x` (.vtt)",
+ "preferences_category_misc": "Различни предпочитания",
+ "Uzbek": "Узбекски",
+ "View JavaScript license information.": "Виж Javascript лиценза.",
+ "Filipino": "Филипински",
+ "Malagasy": "Мадагаскарски",
+ "generic_button_save": "Запиши",
+ "Dark mode: ": "Тъмен режим: ",
+ "Public": "Публичен",
+ "Basque": "Баскски",
+ "channel:`x`": "Канал:`x`",
+ "Armenian": "Арменски",
+ "This channel does not exist.": "Този канал не съществува.",
+ "Luxembourgish": "Люксембургски",
+ "preferences_related_videos_label": "Покажи подобни видеа: ",
+ "English": "Английски",
+ "Delete account": "Изтриване на акаунт",
+ "Gaming": "Игри",
+ "Video mode": "Видео режим",
+ "preferences_dark_mode_label": "Тема: ",
+ "crash_page_search_issue": "потърсил за съществуващи проблеми в GitHub",
+ "preferences_category_subscription": "Предпочитания за абонаменти",
+ "last": "най-скорощни",
+ "Chinese (Simplified)": "Китайски (Опростен)",
+ "Could not create mix.": "Създаването на микс е неуспешно.",
+ "generic_button_cancel": "Отказ",
+ "search_filters_type_option_movie": "Филм",
+ "search_filters_date_option_year": "Тази година",
+ "Swedish": "Шведски",
+ "Previous page": "Предишна страница",
+ "none": "нищо",
+ "popular": "най-популярни",
+ "Unsubscribe": "Отписване",
+ "Slovenian": "Словенски",
+ "Nepali": "Непалски",
+ "Time (h:mm:ss):": "Време (h:mm:ss):",
+ "English (auto-generated)": "Английски (автоматично генерирано)",
+ "search_filters_sort_label": "Сортирай по",
+ "View more comments on Reddit": "Виж повече коментари в Reddit",
+ "Sinhala": "Синхалски",
+ "preferences_feed_menu_label": "Меню с препоръки: ",
+ "preferences_autoplay_label": "Автоматично пускане: ",
+ "Pashto": "Пущунски",
+ "English (United States)": "Английски (САЩ)",
+ "Sign In": "Вход",
+ "subscriptions_unseen_notifs_count": "{{count}} невидяно известие",
+ "subscriptions_unseen_notifs_count_plural": "{{count}} невидяни известия",
+ "Log in": "Вход",
+ "Engagement: ": "Участие: ",
+ "Album: ": "Албум: ",
+ "preferences_speed_label": "Скорост по подразбиране: ",
+ "Import FreeTube subscriptions (.db)": "Импортиране на FreeTube абонаменти (.db)",
+ "preferences_quality_option_dash": "DASH (адаптивно качество)",
+ "preferences_show_nick_label": "Показвай потребителското име отгоре: ",
+ "Private": "Частен",
+ "Samoan": "Самоански",
+ "preferences_notifications_only_label": "Показвай само известията (ако има такива): ",
+ "Create playlist": "Създаване на плейлист",
+ "next_steps_error_message_refresh": "Опресниш",
+ "Top": "Топ",
+ "preferences_quality_dash_option_1080p": "1080p",
+ "Malayalam": "Малаялам",
+ "Token": "Токен",
+ "preferences_comments_label": "Коментари по подразбиране: ",
+ "Movies": "Филми",
+ "light": "светла",
+ "Unlisted": "Скрит",
+ "preferences_category_admin": "Администраторни предпочитания",
+ "Erroneous token": "Невалиден токен",
+ "No": "Не",
+ "CAPTCHA is a required field": "CAPTCHA е задължително поле",
+ "Video unavailable": "Неналично видео",
+ "footer_source_code": "Изходен код",
+ "New passwords must match": "Новите пароли трябва да съвпадат",
+ "Playlist does not exist.": "Плейлиста не съществува.",
+ "Export subscriptions as OPML (for NewPipe & FreeTube)": "Експортиране на абонаментите като OPML (за NewPipe и FreeTube)",
+ "search_filters_duration_option_short": "Кратко (< 4 минути)",
+ "search_filters_duration_option_long": "Дълго (> 20 минути)",
+ "tokens_count": "{{count}} токен",
+ "tokens_count_plural": "{{count}} токена",
+ "Yes": "Да",
+ "Dutch": "Холандски",
+ "Arabic": "Арабски",
+ "An alternative front-end to YouTube": "Алтернативен преден план на YouTube",
+ "View `x` comments": {
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Виж `x` коментар",
+ "": "Виж `x` коментари"
+ },
+ "Chinese (China)": "Китайски (Китай)",
+ "Italian (auto-generated)": "Италиански (автоматично генерирано)",
+ "alphabetically - reverse": "обратно на азбучния ред",
+ "channel_tab_shorts_label": "Shorts",
+ "`x` marked it with a ❤": "`x` го маркира със ❤",
+ "Current version: ": "Текуща версия: ",
+ "channel_tab_community_label": "Общност",
+ "preferences_quality_dash_option_1440p": "1440p",
+ "preferences_quality_dash_option_360p": "360p",
+ "`x` uploaded a video": "`x` качи видео",
+ "Welsh": "Уелски",
+ "search_message_no_results": "Няма намерени резултати.",
+ "channel_tab_releases_label": "Версии",
+ "Bangla": "Бенгалски",
+ "preferences_quality_dash_option_144p": "144p",
+ "Indonesian": "Индонезийски",
+ "`x` ago": "преди `x`",
+ "Invidious Private Feed for `x`": "Invidious персонални видеа за `x`",
+ "Finnish": "Финландски",
+ "Amharic": "Амхарски",
+ "Malay": "Малайски",
+ "Interlingue": "Интерлинг",
+ "search_filters_date_option_month": "Този месец",
+ "Georgian": "Грузински",
+ "Xhosa": "Кхоса",
+ "Marathi": "Маратхи",
+ "Yoruba": "Йоруба",
+ "Song: ": "Музика: ",
+ "Scottish Gaelic": "Шотландски гелски",
+ "search_filters_features_label": "Функции",
+ "preferences_quality_label": "Предпочитано качество на видеото: ",
+ "generic_channels_count": "{{count}} канал",
+ "generic_channels_count_plural": "{{count}} канала",
+ "Croatian": "Хърватски",
+ "Thai": "Тайски",
+ "Chinese (Taiwan)": "Китайски (Тайван)",
+ "youtube": "YouTube",
+ "Source available here.": "Източник наличен тук.",
+ "LIVE": "На живо",
+ "Ukrainian": "Украински",
+ "Russian": "Руски",
+ "Tajik": "Таджикски",
+ "Token manager": "Управляване на токени",
+ "preferences_quality_dash_label": "Предпочитано DASH качество на видеото: ",
+ "adminprefs_modified_source_code_url_label": "URL до хранилището на променения изходен код",
+ "Japanese": "Японски",
+ "Title": "Заглавие",
+ "Authorize token for `x`?": "Разреши токена за `x`?",
+ "reddit": "Reddit",
+ "permalink": "постоянна връзка",
+ "Trending": "На върха",
+ "Turkish (auto-generated)": "Турски (автоматично генерирано)",
+ "Bulgarian": "Български",
+ "Indonesian (auto-generated)": "Индонезийски (автоматично генерирано)",
+ "Enable web notifications": "Активирай уеб известия",
+ "Western Frisian": "Западен фризски",
+ "search_filters_date_option_week": "Тази седмица",
+ "Yiddish": "Идиш",
+ "preferences_category_player": "Предпочитания за плейъра",
+ "Shared `x` ago": "Споделено преди `x`",
+ "Swahili": "Суахили",
+ "Portuguese (auto-generated)": "Португалски (автоматично генерирано)",
+ "generic_count_years": "{{count}} година",
+ "generic_count_years_plural": "{{count}} години",
+ "Wilson score: ": "Wilson оценка: ",
+ "Genre: ": "Жанр: ",
+ "videoinfo_invidious_embed_link": "Вграждане на линк",
+ "Popular enabled: ": "Активиране на популярната страница: ",
+ "Wrong username or password": "Грешно потребителско име или парола",
+ "Vietnamese": "Виетнамски",
+ "alphabetically": "по азбучен ред",
+ "Afrikaans": "Африкаанс",
+ "Zulu": "Зулуски",
+ "(edited)": "(редактирано)",
+ "Whitelisted regions: ": "Разрешени региони: ",
+ "Spanish (auto-generated)": "Испански (автоматично генерирано)",
+ "Could not fetch comments": "Получаването на коментарите е неуспешно",
+ "Sindhi": "Синдхи",
+ "News": "Новини",
+ "preferences_video_loop_label": "Винаги повтаряй: ",
+ "%A %B %-d, %Y": "%-d %B %Y, %A",
+ "preferences_quality_option_small": "Ниско",
+ "English (United Kingdom)": "Английски (Великобритания)",
+ "Rating: ": "Рейтинг: ",
+ "channel_tab_playlists_label": "Плейлисти",
+ "generic_button_edit": "Редактирай",
+ "Report statistics: ": "Активиране на статистики за репортиране: ",
+ "Cebuano": "Себуано",
+ "Chinese (Traditional)": "Китайски (Традиционен)",
+ "generic_playlists_count": "{{count}} плейлист",
+ "generic_playlists_count_plural": "{{count}} плейлиста",
+ "Import NewPipe subscriptions (.json)": "Импортиране на NewPipe абонаменти (.json)",
+ "Preferences": "Предпочитания",
+ "Subscribe": "Абониране",
+ "Import and Export Data": "Импортиране и експортиране на информация",
+ "preferences_quality_option_hd720": "HD720",
+ "search_filters_type_option_playlist": "Плейлист",
+ "Serbian": "Сръбски",
+ "Kazakh": "Казахски",
+ "Telugu": "Телугу",
+ "search_filters_features_option_purchased": "Купено",
+ "revoke": "отмяна",
+ "search_filters_sort_option_date": "Дата на качване",
+ "preferences_category_data": "Предпочитания за информацията",
+ "search_filters_date_option_none": "Всякаква дата",
+ "Log out": "Излизане",
+ "Search": "Търсене",
+ "preferences_quality_dash_option_auto": "Автоматично",
+ "dark": "тъмна",
+ "Cantonese (Hong Kong)": "Кантонски (Хонг Конг)",
+ "crash_page_report_issue": "Ако никои от горепосочените не помогнаха, моля отворете нов проблем в GitHub (предпочитано на Английски) и добавете следния текст в съобщението (НЕ превеждайте този текст):",
+ "Czech": "Чешки",
+ "crash_page_switch_instance": "пробвал да ползваш друга инстанция",
+ "generic_count_weeks": "{{count}} седмица",
+ "generic_count_weeks_plural": "{{count}} седмици",
+ "search_filters_features_option_subtitles": "Субтитри",
+ "videoinfo_watch_on_youTube": "Виж в YouTube",
+ "Portuguese": "Португалски",
+ "Music in this video": "Музика в това видео",
+ "Hide replies": "Скрий отговорите",
+ "Password cannot be longer than 55 characters": "Паролата не може да бъде по-дълга от 55 символа",
+ "footer_modfied_source_code": "Променен изходен код",
+ "Bosnian": "Босненски",
+ "Deleted or invalid channel": "Изтрит или невалиден канал",
+ "Popular": "Популярно",
+ "search_filters_type_label": "Тип",
+ "preferences_locale_label": "Език: ",
+ "Playlists": "Плейлисти",
+ "generic_button_rss": "RSS",
+ "Export": "Експортиране",
+ "preferences_quality_dash_option_4320p": "4320p",
+ "Erroneous challenge": "Невалиден тест",
+ "History": "История",
+ "generic_count_hours": "{{count}} час",
+ "generic_count_hours_plural": "{{count}} часа",
+ "Registration enabled: ": "Активиране на регистрация: ",
+ "Music": "Музика",
+ "Incorrect password": "Грешна парола",
+ "Persian": "Перскийски",
+ "Import": "Импортиране",
+ "Import/export data": "Импортиране/Експортиране на информация",
+ "Shared `x`": "Споделено `x`",
+ "Javanese": "Явански",
+ "French (auto-generated)": "Френски (автоматично генерирано)",
+ "Norwegian Bokmål": "Норвежки",
+ "Catalan": "Каталунски",
+ "Hindi": "Хинди",
+ "Tamil": "Тамилски",
+ "search_filters_features_option_live": "На живо",
+ "crash_page_read_the_faq": "прочел Често задавани въпроси (FAQ)",
+ "preferences_default_home_label": "Начална страница по подразбиране: ",
+ "Download": "Изтегляне",
+ "Show less": "Покажи по-малко",
+ "Password": "Парола",
+ "User ID": "Потребителско име",
+ "Subscription manager": "Управляване на абонаменти",
+ "search": "търсене",
+ "No such user": "Няма такъв потребител",
+ "View privacy policy.": "Виж политиката за поверителност.",
+ "Only show latest unwatched video from channel: ": "Показвай само най-новите негледани видеа в канала: ",
+ "user_created_playlists": "`x` създаде плейлисти",
+ "Editing playlist `x`": "Редактиране на плейлист `x`",
+ "preferences_thin_mode_label": "Тънък режим: ",
+ "E-mail": "Имейл",
+ "Haitian Creole": "Хаитянски креол",
+ "Irish": "Ирландски",
+ "channel_tab_channels_label": "Канали",
+ "Delete account?": "Изтрий акаунта?",
+ "Redirect homepage to feed: ": "Препращане на началната страница до препоръки ",
+ "Urdu": "Урду",
+ "preferences_vr_mode_label": "Интерактивни 360 градусови видеа (изисква WebGL): ",
+ "Password cannot be empty": "Паролата не може да бъде празна",
+ "Mongolian": "Монголски",
+ "Authorize token?": "Разреши токена?",
+ "search_filters_type_option_all": "Всякакъв тип",
+ "Romanian": "Румънски",
+ "Belarusian": "Беларуски",
+ "channel name - reverse": "име на канал - в обратен ред",
+ "Erroneous CAPTCHA": "Невалидна CAPTCHA",
+ "Watch on YouTube": "Гледай в YouTube",
+ "search_filters_features_option_location": "Местоположение",
+ "Could not pull trending pages.": "Получаването на трендинг страниците е неуспешно.",
+ "German": "Немски",
+ "search_filters_features_option_c_commons": "Creative Commons",
+ "Family friendly? ": "За всяка възраст? ",
+ "Hidden field \"token\" is a required field": "Скритото поле \"токен\" е задължително поле",
+ "Russian (auto-generated)": "Руски (автоматично генерирано)",
+ "preferences_quality_dash_option_480p": "480p",
+ "Corsican": "Корсикански",
+ "Macedonian": "Македонски",
+ "comments_view_x_replies": "Виж {{count}} отговор",
+ "comments_view_x_replies_plural": "Виж {{count}} отговора",
+ "footer_original_source_code": "Оригинален изходен код",
+ "Import YouTube subscriptions": "Импортиране на YouTube/OPML абонаменти",
+ "Lithuanian": "Литовски",
+ "Nyanja": "Нянджа",
+ "Updated `x` ago": "Актуализирано преди `x`",
+ "JavaScript license information": "Информация за Javascript лиценза",
+ "Spanish": "Испански",
+ "Latin": "Латински",
+ "Shona": "Шона",
+ "Portuguese (Brazil)": "Португалски (Бразилия)",
+ "Show more": "Покажи още",
+ "Clear watch history?": "Изчисти историята на търсене?",
+ "Manage tokens": "Управление на токени",
+ "Hausa": "Хауса",
+ "search_filters_features_option_vr180": "VR180",
+ "preferences_category_visual": "Визуални предпочитания",
+ "Italian": "Италиански",
+ "preferences_volume_label": "Сила на звука на плейъра: ",
+ "error_video_not_in_playlist": "Заявеното видео не съществува в този плейлист. Натиснете тук за началната страница на плейлиста.",
+ "preferences_listen_label": "Само звук по подразбиране: ",
+ "Dutch (auto-generated)": "Холандски (автоматично генерирано)",
+ "preferences_captions_label": "Надписи по подразбиране: ",
+ "generic_count_days": "{{count}} ден",
+ "generic_count_days_plural": "{{count}} дни",
+ "Hawaiian": "Хавайски",
+ "Could not get channel info.": "Получаването на информация за канала е неуспешно.",
+ "View as playlist": "Виж като плейлист",
+ "Vietnamese (auto-generated)": "Виетнамски (автоматично генерирано)",
+ "search_filters_duration_option_none": "Всякаква продължителност",
+ "preferences_quality_dash_option_240p": "240p",
+ "Latvian": "Латвийски",
+ "search_filters_features_option_hdr": "HDR",
+ "preferences_sort_label": "Сортирай видеата по: ",
+ "Estonian": "Естонски",
+ "Hidden field \"challenge\" is a required field": "Скритото поле \"тест\" е задължително поле",
+ "footer_documentation": "Документация",
+ "Kyrgyz": "Киргизски",
+ "preferences_continue_autoplay_label": "Пускай следващотото видео автоматично: ",
+ "Chinese": "Китайски",
+ "search_filters_sort_option_relevance": "Уместност",
+ "source": "източник",
+ "Fallback comments: ": "Резервни коментари: ",
+ "preferences_automatic_instance_redirect_label": "Автоматично препращане на инстанция (чрез redirect.invidious.io): ",
+ "Maori": "Маори",
+ "generic_button_delete": "Изтрий",
+ "Import YouTube playlist (.csv)": "Импортиране на YouTube плейлист (.csv)",
+ "Switch Invidious Instance": "Смени Invidious инстанция",
+ "channel name": "име на канал",
+ "Audio mode": "Аудио режим",
+ "search_filters_type_option_show": "Сериал",
+ "search_filters_date_option_today": "Днес",
+ "search_filters_features_option_three_d": "3D",
+ "next_steps_error_message": "След което можеш да пробваш да: ",
+ "Hide annotations": "Скрий анотации",
+ "Standard YouTube license": "Стандартен YouTube лиценз",
+ "Text CAPTCHA": "Текст CAPTCHA",
+ "Log in/register": "Вход/регистрация",
+ "Punjabi": "Пенджаби",
+ "Change password": "Смяна на паролата",
+ "License: ": "Лиценз: ",
+ "search_filters_duration_option_medium": "Средно (4 - 20 минути)",
+ "Delete playlist": "Изтриване на плейлист",
+ "Delete playlist `x`?": "Изтрий плейлиста `x`?",
+ "Korean": "Корейски",
+ "Export subscriptions as OPML": "Експортиране на абонаментите като OPML",
+ "unsubscribe": "отписване",
+ "View YouTube comments": "Виж YouTube коментарите",
+ "Kannada": "Каннада",
+ "Not a playlist.": "Невалиден плейлист.",
+ "Wrong answer": "Грешен отговор",
+ "Released under the AGPLv3 on Github.": "Публикувано под AGPLv3 в GitHub.",
+ "Burmese": "Бирмански",
+ "Sundanese": "Сундански",
+ "Hungarian": "Унгарски",
+ "generic_count_seconds": "{{count}} секунда",
+ "generic_count_seconds_plural": "{{count}} секунди",
+ "search_filters_date_label": "Дата на качване",
+ "Greek": "Гръцки",
+ "crash_page_you_found_a_bug": "Изглежда намери бъг в Invidious!",
+ "View all playlists": "Виж всички плейлисти",
+ "Khmer": "Кхмерски",
+ "preferences_annotations_label": "Покажи анотаций по подразбиране: ",
+ "generic_views_count": "{{count}} гледане",
+ "generic_views_count_plural": "{{count}} гледания",
+ "Next page": "Следваща страница"
+}
diff --git a/locales/ca.json b/locales/ca.json
index 4392c2a9..a718eb2b 100644
--- a/locales/ca.json
+++ b/locales/ca.json
@@ -476,5 +476,15 @@
"Redirect homepage to feed: ": "Redirigeix la pàgina d'inici al feed: ",
"Standard YouTube license": "Llicència estàndard de YouTube",
"Download is disabled": "Les baixades s'han inhabilitat",
- "Import YouTube playlist (.csv)": "Importar llista de reproducció de YouTube (.csv)"
+ "Import YouTube playlist (.csv)": "Importar llista de reproducció de YouTube (.csv)",
+ "channel_tab_podcasts_label": "Podcasts",
+ "playlist_button_add_items": "Afegeix vídeos",
+ "generic_button_save": "Desa",
+ "generic_button_cancel": "Cancel·la",
+ "channel_tab_releases_label": "Publicacions",
+ "generic_channels_count": "{{count}} canal",
+ "generic_channels_count_plural": "{{count}} canals",
+ "generic_button_edit": "Edita",
+ "generic_button_rss": "RSS",
+ "generic_button_delete": "Suprimeix"
}
diff --git a/locales/cs.json b/locales/cs.json
index b2cce0bd..10c114eb 100644
--- a/locales/cs.json
+++ b/locales/cs.json
@@ -500,5 +500,8 @@
"channel_tab_releases_label": "Vydání",
"generic_button_edit": "Upravit",
"generic_button_rss": "RSS",
- "playlist_button_add_items": "Přidat videa"
+ "playlist_button_add_items": "Přidat videa",
+ "generic_channels_count_0": "{{count}} kanál",
+ "generic_channels_count_1": "{{count}} kanály",
+ "generic_channels_count_2": "{{count}} kanálů"
}
diff --git a/locales/de.json b/locales/de.json
index 6ceaa44b..59c6a49c 100644
--- a/locales/de.json
+++ b/locales/de.json
@@ -97,7 +97,7 @@
"Change password": "Passwort ändern",
"Manage subscriptions": "Abonnements verwalten",
"Manage tokens": "Tokens verwalten",
- "Watch history": "Verlauf",
+ "Watch history": "Wiedergabeverlauf",
"Delete account": "Account löschen",
"preferences_category_admin": "Administrator-Einstellungen",
"preferences_default_home_label": "Standard-Startseite: ",
@@ -476,11 +476,15 @@
"Standard YouTube license": "Standard YouTube-Lizenz",
"Song: ": "Musik: ",
"Download is disabled": "Herunterladen ist deaktiviert",
- "Import YouTube playlist (.csv)": "YouTube Playlist Importieren (.csv)",
+ "Import YouTube playlist (.csv)": "YouTube Wiedergabeliste importieren (.csv)",
"generic_button_delete": "Löschen",
"generic_button_edit": "Bearbeiten",
"generic_button_save": "Speichern",
"generic_button_cancel": "Abbrechen",
"generic_button_rss": "RSS",
- "playlist_button_add_items": "Videos hinzufügen"
+ "playlist_button_add_items": "Videos hinzufügen",
+ "channel_tab_podcasts_label": "Podcasts",
+ "channel_tab_releases_label": "Veröffentlichungen",
+ "generic_channels_count": "{{count}} Kanal",
+ "generic_channels_count_plural": "{{count}} Kanäle"
}
diff --git a/locales/el.json b/locales/el.json
index 13cff649..1d827eba 100644
--- a/locales/el.json
+++ b/locales/el.json
@@ -41,7 +41,7 @@
"Time (h:mm:ss):": "Ώρα (ω:λλ:δδ):",
"Text CAPTCHA": "Κείμενο CAPTCHA",
"Image CAPTCHA": "Εικόνα CAPTCHA",
- "Sign In": "Σύνδεση",
+ "Sign In": "Εγγραφή",
"Register": "Εγγραφή",
"E-mail": "Ηλεκτρονικό ταχυδρομείο",
"Preferences": "Προτιμήσεις",
@@ -145,7 +145,7 @@
"View YouTube comments": "Προβολή σχολίων από το YouTube",
"View more comments on Reddit": "Προβολή περισσότερων σχολίων στο Reddit",
"View `x` comments": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "Προβολή `x` σχολίων",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Προβολή `x` σχολίου",
"": "Προβολή `x` σχολίων"
},
"View Reddit comments": "Προβολή σχολίων από το Reddit",
@@ -349,7 +349,7 @@
"crash_page_you_found_a_bug": "Φαίνεται ότι βρήκατε ένα σφάλμα στο Invidious!",
"crash_page_before_reporting": "Πριν αναφέρετε ένα σφάλμα, βεβαιωθείτε ότι έχετε:",
"crash_page_refresh": "προσπαθήσει να ανανεώσετε τη σελίδα",
- "crash_page_read_the_faq": "διαβάσει τις Συχνές Ερωτήσεις (ΣΕ)",
+ "crash_page_read_the_faq": "διαβάστε τις Συχνές Ερωτήσεις (ΣΕ)",
"crash_page_search_issue": "αναζητήσει για υπάρχοντα θέματα στο GitHub",
"generic_views_count": "{{count}} προβολή",
"generic_views_count_plural": "{{count}} προβολές",
@@ -442,5 +442,49 @@
"search_filters_type_option_show": "Μπάρα προόδου διαβάσματος",
"preferences_watch_history_label": "Ενεργοποίηση ιστορικού παρακολούθησης: ",
"search_filters_title": "Φίλτρο",
- "search_message_no_results": "Δε βρέθηκαν αποτελέσματα."
+ "search_message_no_results": "Δε βρέθηκαν αποτελέσματα.",
+ "channel_tab_podcasts_label": "Podcast",
+ "preferences_save_player_pos_label": "Αποθήκευση σημείου αναπαραγωγής: ",
+ "search_filters_apply_button": "Εφαρμογή επιλεγμένων φίλτρων",
+ "Download is disabled": "Είναι απενεργοποιημένη η λήψη",
+ "comments_points_count": "{{count}} βαθμός",
+ "comments_points_count_plural": "{{count}} βαθμοί",
+ "search_filters_sort_option_views": "Προβολές",
+ "search_message_change_filters_or_query": "Προσπαθήστε να διευρύνετε το ερώτημα αναζήτησης ή/και να αλλάξετε τα φίλτρα.",
+ "Channel Sponsor": "Χορηγός Καναλιού",
+ "channel_tab_streams_label": "Ζωντανή μετάδοση",
+ "playlist_button_add_items": "Προσθήκη βίντεο",
+ "Artist: ": "Καλλιτέχνης: ",
+ "search_message_use_another_instance": " Μπορείτε επίσης να αναζητήσετε σε άλλο instance.",
+ "generic_button_save": "Αποθήκευση",
+ "generic_button_cancel": "Ακύρωση",
+ "subscriptions_unseen_notifs_count": "{{count}} μη αναγνωσμένη ειδοποίηση",
+ "subscriptions_unseen_notifs_count_plural": "{{count}} μη αναγνωσμένες ειδοποιήσεις",
+ "Album: ": "Δίσκος: ",
+ "tokens_count": "{{count}} σύμβολο",
+ "tokens_count_plural": "{{count}} σύμβολα",
+ "channel_tab_shorts_label": "Short",
+ "channel_tab_releases_label": "Κυκλοφορίες",
+ "Song: ": "Τραγούδι: ",
+ "generic_channels_count": "{{count}} κανάλι",
+ "generic_channels_count_plural": "{{count}} κανάλια",
+ "Popular enabled: ": "Ενεργοποιημένα Δημοφιλή: ",
+ "channel_tab_playlists_label": "Λίστες αναπαραγωγής",
+ "generic_button_edit": "Επεξεργασία",
+ "search_filters_date_option_none": "Οποιαδήποτε ημερομηνία",
+ "crash_page_switch_instance": "προσπάθεια χρήσης άλλου instance",
+ "Music in this video": "Μουσική σε αυτό το βίντεο",
+ "generic_button_rss": "RSS",
+ "channel_tab_channels_label": "Κανάλια",
+ "search_filters_type_option_all": "Οποιοσδήποτε τύπος",
+ "search_filters_features_option_vr180": "VR180",
+ "error_video_not_in_playlist": "Το αιτούμενο βίντεο δεν υπάρχει στη δεδομένη λίστα αναπαραγωγής. Πατήστε εδώ για επιστροφή στη κεντρική σελίδα λιστών αναπαραγωγής.",
+ "search_filters_duration_option_none": "Οποιαδήποτε διάρκεια",
+ "preferences_automatic_instance_redirect_label": "Αυτόματη ανακατεύθυνση instance (εναλλακτική σε redirect.invidious.io): ",
+ "generic_button_delete": "Διαγραφή",
+ "Import YouTube playlist (.csv)": "Εισαγωγή λίστας αναπαραγωγής YouTube (.csv)",
+ "Switch Invidious Instance": "Αλλαγή Instance Invidious",
+ "Standard YouTube license": "Τυπική άδεια YouTube",
+ "search_filters_duration_option_medium": "Μεσαία (4 - 20 λεπτά)",
+ "search_filters_date_label": "Ημερομηνία αναφόρτωσης"
}
diff --git a/locales/eo.json b/locales/eo.json
index 6d1b0bc1..7276c890 100644
--- a/locales/eo.json
+++ b/locales/eo.json
@@ -484,5 +484,7 @@
"channel_tab_podcasts_label": "Podkastoj",
"generic_button_cancel": "Nuligi",
"channel_tab_releases_label": "Eldonoj",
- "generic_button_save": "Konservi"
+ "generic_button_save": "Konservi",
+ "generic_channels_count": "{{count}} kanalo",
+ "generic_channels_count_plural": "{{count}} kanaloj"
}
diff --git a/locales/es.json b/locales/es.json
index b4a56030..0b8463ea 100644
--- a/locales/es.json
+++ b/locales/es.json
@@ -484,5 +484,7 @@
"generic_button_cancel": "Cancelar",
"generic_button_rss": "RSS",
"channel_tab_podcasts_label": "Podcasts",
- "channel_tab_releases_label": "Publicaciones"
+ "channel_tab_releases_label": "Publicaciones",
+ "generic_channels_count": "{{count}} canal",
+ "generic_channels_count_plural": "{{count}} canales"
}
diff --git a/locales/fr.json b/locales/fr.json
index 7fea8f14..772c81c8 100644
--- a/locales/fr.json
+++ b/locales/fr.json
@@ -1,16 +1,22 @@
{
- "generic_channels_count": "{{count}} chaîne",
- "generic_channels_count_plural": "{{count}} chaînes",
- "generic_views_count": "{{count}} vue",
- "generic_views_count_plural": "{{count}} vues",
- "generic_videos_count": "{{count}} vidéo",
- "generic_videos_count_plural": "{{count}} vidéos",
- "generic_playlists_count": "{{count}} liste de lecture",
- "generic_playlists_count_plural": "{{count}} listes de lecture",
- "generic_subscribers_count": "{{count}} abonné",
- "generic_subscribers_count_plural": "{{count}} abonnés",
- "generic_subscriptions_count": "{{count}} abonnement",
- "generic_subscriptions_count_plural": "{{count}} abonnements",
+ "generic_channels_count_0": "{{count}} chaîne",
+ "generic_channels_count_1": "{{count}} de chaînes",
+ "generic_channels_count_2": "{{count}} chaînes",
+ "generic_views_count_0": "{{count}} vue",
+ "generic_views_count_1": "{{count}} de vues",
+ "generic_views_count_2": "{{count}} vues",
+ "generic_videos_count_0": "{{count}} vidéo",
+ "generic_videos_count_1": "{{count}} de vidéos",
+ "generic_videos_count_2": "{{count}} vidéos",
+ "generic_playlists_count_0": "{{count}} liste de lecture",
+ "generic_playlists_count_1": "{{count}} listes de lecture",
+ "generic_playlists_count_2": "{{count}} listes de lecture",
+ "generic_subscribers_count_0": "{{count}} abonné",
+ "generic_subscribers_count_1": "{{count}} d'abonnés",
+ "generic_subscribers_count_2": "{{count}} abonnés",
+ "generic_subscriptions_count_0": "{{count}} abonnement",
+ "generic_subscriptions_count_1": "{{count}} d'abonnements",
+ "generic_subscriptions_count_2": "{{count}} abonnements",
"generic_button_delete": "Supprimer",
"generic_button_edit": "Editer",
"generic_button_save": "Enregistrer",
@@ -130,14 +136,16 @@
"Subscription manager": "Gestionnaire d'abonnement",
"Token manager": "Gestionnaire de token",
"Token": "Token",
- "tokens_count": "{{count}} jeton",
- "tokens_count_plural": "{{count}} jetons",
+ "tokens_count_0": "{{count}} jeton",
+ "tokens_count_1": "{{count}} de jetons",
+ "tokens_count_2": "{{count}} jetons",
"Import/export": "Importer/Exporter",
"unsubscribe": "se désabonner",
"revoke": "révoquer",
"Subscriptions": "Abonnements",
- "subscriptions_unseen_notifs_count": "{{count}} notification non vue",
- "subscriptions_unseen_notifs_count_plural": "{{count}} notifications non vues",
+ "subscriptions_unseen_notifs_count_0": "{{count}} notification non vue",
+ "subscriptions_unseen_notifs_count_1": "{{count}} de notifications non vues",
+ "subscriptions_unseen_notifs_count_2": "{{count}} notifications non vues",
"search": "rechercher",
"Log out": "Se déconnecter",
"Released under the AGPLv3 on Github.": "Publié sous licence AGPLv3 sur GitHub.",
@@ -199,12 +207,14 @@
"This channel does not exist.": "Cette chaine n'existe pas.",
"Could not get channel info.": "Impossible de charger les informations de cette chaîne.",
"Could not fetch comments": "Impossible de charger les commentaires",
- "comments_view_x_replies": "Voir {{count}} réponse",
- "comments_view_x_replies_plural": "Voir {{count}} réponses",
+ "comments_view_x_replies_0": "Voir {{count}} réponse",
+ "comments_view_x_replies_1": "Voir {{count}} de réponses",
+ "comments_view_x_replies_2": "Voir {{count}} réponses",
"`x` ago": "il y a `x`",
"Load more": "Voir plus",
- "comments_points_count": "{{count}} point",
- "comments_points_count_plural": "{{count}} points",
+ "comments_points_count_0": "{{count}} point",
+ "comments_points_count_1": "{{count}} de points",
+ "comments_points_count_2": "{{count}} points",
"Could not create mix.": "Impossible de charger cette liste de lecture.",
"Empty playlist": "La liste de lecture est vide",
"Not a playlist.": "La liste de lecture est invalide.",
@@ -322,20 +332,27 @@
"Yiddish": "Yiddish",
"Yoruba": "Yoruba",
"Zulu": "Zoulou",
- "generic_count_years": "{{count}} an",
- "generic_count_years_plural": "{{count}} ans",
- "generic_count_months": "{{count}} mois",
- "generic_count_months_plural": "{{count}} mois",
- "generic_count_weeks": "{{count}} semaine",
- "generic_count_weeks_plural": "{{count}} semaines",
- "generic_count_days": "{{count}} jour",
- "generic_count_days_plural": "{{count}} jours",
- "generic_count_hours": "{{count}} heure",
- "generic_count_hours_plural": "{{count}} heures",
- "generic_count_minutes": "{{count}} minute",
- "generic_count_minutes_plural": "{{count}} minutes",
- "generic_count_seconds": "{{count}} seconde",
- "generic_count_seconds_plural": "{{count}} secondes",
+ "generic_count_years_0": "{{count}} an",
+ "generic_count_years_1": "{{count}} ans",
+ "generic_count_years_2": "{{count}} ans",
+ "generic_count_months_0": "{{count}} mois",
+ "generic_count_months_1": "{{count}} mois",
+ "generic_count_months_2": "{{count}} mois",
+ "generic_count_weeks_0": "{{count}} semaine",
+ "generic_count_weeks_1": "{{count}} semaines",
+ "generic_count_weeks_2": "{{count}} semaines",
+ "generic_count_days_0": "{{count}} jour",
+ "generic_count_days_1": "{{count}} jours",
+ "generic_count_days_2": "{{count}} jours",
+ "generic_count_hours_0": "{{count}} heure",
+ "generic_count_hours_1": "{{count}} heures",
+ "generic_count_hours_2": "{{count}} heures",
+ "generic_count_minutes_0": "{{count}} minute",
+ "generic_count_minutes_1": "{{count}} minutes",
+ "generic_count_minutes_2": "{{count}} minutes",
+ "generic_count_seconds_0": "{{count}} seconde",
+ "generic_count_seconds_1": "{{count}} secondes",
+ "generic_count_seconds_2": "{{count}} secondes",
"Fallback comments: ": "Commentaires alternatifs : ",
"Popular": "Populaire",
"Search": "Rechercher",
diff --git a/locales/hr.json b/locales/hr.json
index ba3dd5e5..ef931202 100644
--- a/locales/hr.json
+++ b/locales/hr.json
@@ -500,5 +500,8 @@
"generic_button_save": "Spremi",
"generic_button_cancel": "Odustani",
"generic_button_rss": "RSS",
- "channel_tab_releases_label": "Izdanja"
+ "channel_tab_releases_label": "Izdanja",
+ "generic_channels_count_0": "{{count}} kanal",
+ "generic_channels_count_1": "{{count}} kanala",
+ "generic_channels_count_2": "{{count}} kanala"
}
diff --git a/locales/id.json b/locales/id.json
index ef677251..8961880b 100644
--- a/locales/id.json
+++ b/locales/id.json
@@ -446,5 +446,28 @@
"crash_page_read_the_faq": "baca Soal Sering Ditanya (SSD/FAQ)",
"crash_page_search_issue": "mencari isu yang ada di GitHub",
"crash_page_report_issue": "Jika yang di atas tidak membantu, buka isu baru di GitHub (sebaiknya dalam bahasa Inggris) dan sertakan teks berikut dalam pesan Anda (JANGAN terjemahkan teks tersebut):",
- "Popular enabled: ": "Populer diaktifkan: "
+ "Popular enabled: ": "Populer diaktifkan: ",
+ "channel_tab_podcasts_label": "Podcast",
+ "Download is disabled": "Download dinonaktifkan",
+ "Channel Sponsor": "Saluran Sponsor",
+ "channel_tab_streams_label": "Streaming langsung",
+ "playlist_button_add_items": "Tambahkan video",
+ "Artist: ": "Artis: ",
+ "generic_button_save": "Simpan",
+ "generic_button_cancel": "Batal",
+ "Album: ": "Album: ",
+ "channel_tab_shorts_label": "Shorts",
+ "channel_tab_releases_label": "Terbit",
+ "Interlingue": "Interlingue",
+ "Song: ": "Lagu: ",
+ "generic_channels_count_0": "Saluran {{count}}",
+ "channel_tab_playlists_label": "Daftar putar",
+ "generic_button_edit": "Ubah",
+ "Music in this video": "Musik dalam video ini",
+ "generic_button_rss": "RSS",
+ "channel_tab_channels_label": "Saluran",
+ "error_video_not_in_playlist": "Video yang diminta tidak ada dalam daftar putar ini. Klik di sini untuk halaman beranda daftar putar.",
+ "generic_button_delete": "Hapus",
+ "Import YouTube playlist (.csv)": "Impor daftar putar YouTube (.csv)",
+ "Standard YouTube license": "Lisensi YouTube standar"
}
diff --git a/locales/it.json b/locales/it.json
index 894eb97f..7e1b12c6 100644
--- a/locales/it.json
+++ b/locales/it.json
@@ -1,10 +1,13 @@
{
- "generic_subscribers_count": "{{count}} iscritto",
- "generic_subscribers_count_plural": "{{count}} iscritti",
- "generic_videos_count": "{{count}} video",
- "generic_videos_count_plural": "{{count}} video",
- "generic_playlists_count": "{{count}} playlist",
- "generic_playlists_count_plural": "{{count}} playlist",
+ "generic_subscribers_count_0": "{{count}} iscritto",
+ "generic_subscribers_count_1": "{{count}} iscritti",
+ "generic_subscribers_count_2": "{{count}} iscritti",
+ "generic_videos_count_0": "{{count}} video",
+ "generic_videos_count_1": "{{count}} video",
+ "generic_videos_count_2": "{{count}} video",
+ "generic_playlists_count_0": "{{count}} playlist",
+ "generic_playlists_count_1": "{{count}} playlist",
+ "generic_playlists_count_2": "{{count}} playlist",
"LIVE": "IN DIRETTA",
"Shared `x` ago": "Condiviso `x` fa",
"Unsubscribe": "Disiscriviti",
@@ -113,16 +116,19 @@
"Subscription manager": "Gestione delle iscrizioni",
"Token manager": "Gestione dei gettoni",
"Token": "Gettone",
- "generic_subscriptions_count": "{{count}} iscrizione",
- "generic_subscriptions_count_plural": "{{count}} iscrizioni",
- "tokens_count": "{{count}} gettone",
- "tokens_count_plural": "{{count}} gettoni",
+ "generic_subscriptions_count_0": "{{count}} iscrizione",
+ "generic_subscriptions_count_1": "{{count}} iscrizioni",
+ "generic_subscriptions_count_2": "{{count}} iscrizioni",
+ "tokens_count_0": "{{count}} gettone",
+ "tokens_count_1": "{{count}} gettoni",
+ "tokens_count_2": "{{count}} gettoni",
"Import/export": "Importa/esporta",
"unsubscribe": "disiscriviti",
"revoke": "revoca",
"Subscriptions": "Iscrizioni",
- "subscriptions_unseen_notifs_count": "{{count}} notifica non visualizzata",
- "subscriptions_unseen_notifs_count_plural": "{{count}} notifiche non visualizzate",
+ "subscriptions_unseen_notifs_count_0": "{{count}} notifica non visualizzata",
+ "subscriptions_unseen_notifs_count_1": "{{count}} notifiche non visualizzate",
+ "subscriptions_unseen_notifs_count_2": "{{count}} notifiche non visualizzate",
"search": "Cerca",
"Log out": "Esci",
"Source available here.": "Codice sorgente.",
@@ -151,8 +157,9 @@
"Whitelisted regions: ": "Regioni in lista bianca: ",
"Blacklisted regions: ": "Regioni in lista nera: ",
"Shared `x`": "Condiviso `x`",
- "generic_views_count": "{{count}} visualizzazione",
- "generic_views_count_plural": "{{count}} visualizzazioni",
+ "generic_views_count_0": "{{count}} visualizzazione",
+ "generic_views_count_1": "{{count}} visualizzazioni",
+ "generic_views_count_2": "{{count}} visualizzazioni",
"Premieres in `x`": "In anteprima in `x`",
"Premieres `x`": "In anteprima `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.": "Ciao, Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti, ma considera che il caricamento potrebbe richiedere più tempo.",
@@ -300,20 +307,27 @@
"Yiddish": "Yiddish",
"Yoruba": "Yoruba",
"Zulu": "Zulu",
- "generic_count_years": "{{count}} anno",
- "generic_count_years_plural": "{{count}} anni",
- "generic_count_months": "{{count}} mese",
- "generic_count_months_plural": "{{count}} mesi",
- "generic_count_weeks": "{{count}} settimana",
- "generic_count_weeks_plural": "{{count}} settimane",
- "generic_count_days": "{{count}} giorno",
- "generic_count_days_plural": "{{count}} giorni",
- "generic_count_hours": "{{count}} ora",
- "generic_count_hours_plural": "{{count}} ore",
- "generic_count_minutes": "{{count}} minuto",
- "generic_count_minutes_plural": "{{count}} minuti",
- "generic_count_seconds": "{{count}} secondo",
- "generic_count_seconds_plural": "{{count}} secondi",
+ "generic_count_years_0": "{{count}} anno",
+ "generic_count_years_1": "{{count}} anni",
+ "generic_count_years_2": "{{count}} anni",
+ "generic_count_months_0": "{{count}} mese",
+ "generic_count_months_1": "{{count}} mesi",
+ "generic_count_months_2": "{{count}} mesi",
+ "generic_count_weeks_0": "{{count}} settimana",
+ "generic_count_weeks_1": "{{count}} settimane",
+ "generic_count_weeks_2": "{{count}} settimane",
+ "generic_count_days_0": "{{count}} giorno",
+ "generic_count_days_1": "{{count}} giorni",
+ "generic_count_days_2": "{{count}} giorni",
+ "generic_count_hours_0": "{{count}} ora",
+ "generic_count_hours_1": "{{count}} ore",
+ "generic_count_hours_2": "{{count}} ore",
+ "generic_count_minutes_0": "{{count}} minuto",
+ "generic_count_minutes_1": "{{count}} minuti",
+ "generic_count_minutes_2": "{{count}} minuti",
+ "generic_count_seconds_0": "{{count}} secondo",
+ "generic_count_seconds_1": "{{count}} secondi",
+ "generic_count_seconds_2": "{{count}} secondi",
"Fallback comments: ": "Commenti alternativi: ",
"Popular": "Popolare",
"Search": "Cerca",
@@ -417,10 +431,12 @@
"search_filters_duration_option_short": "Corto (< 4 minuti)",
"search_filters_duration_option_long": "Lungo (> 20 minuti)",
"search_filters_features_option_purchased": "Acquistato",
- "comments_view_x_replies": "Vedi {{count}} risposta",
- "comments_view_x_replies_plural": "Vedi {{count}} risposte",
- "comments_points_count": "{{count}} punto",
- "comments_points_count_plural": "{{count}} punti",
+ "comments_view_x_replies_0": "Vedi {{count}} risposta",
+ "comments_view_x_replies_1": "Vedi {{count}} risposte",
+ "comments_view_x_replies_2": "Vedi {{count}} risposte",
+ "comments_points_count_0": "{{count}} punto",
+ "comments_points_count_1": "{{count}} punti",
+ "comments_points_count_2": "{{count}} punti",
"Portuguese (auto-generated)": "Portoghese (generati automaticamente)",
"crash_page_you_found_a_bug": "Sembra che tu abbia trovato un bug in Invidious!",
"crash_page_switch_instance": "provato a usare un'altra istanza",
@@ -484,5 +500,8 @@
"generic_button_delete": "Elimina",
"generic_button_save": "Salva",
"playlist_button_add_items": "Aggiungi video",
- "channel_tab_podcasts_label": "Podcast"
+ "channel_tab_podcasts_label": "Podcast",
+ "generic_channels_count_0": "{{count}} canale",
+ "generic_channels_count_1": "{{count}} canali",
+ "generic_channels_count_2": "{{count}} canali"
}
diff --git a/locales/ja.json b/locales/ja.json
index 6fc02e2d..17e60998 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -468,5 +468,6 @@
"generic_button_edit": "編集",
"generic_button_save": "保存",
"generic_button_rss": "RSS",
- "playlist_button_add_items": "動画を追加"
+ "playlist_button_add_items": "動画を追加",
+ "generic_channels_count_0": "{{count}}個のチャンネル"
}
diff --git a/locales/ko.json b/locales/ko.json
index e02a8316..e496bd2a 100644
--- a/locales/ko.json
+++ b/locales/ko.json
@@ -468,5 +468,6 @@
"generic_button_save": "저장",
"generic_button_cancel": "취소",
"generic_button_rss": "RSS",
- "channel_tab_releases_label": "출시"
+ "channel_tab_releases_label": "출시",
+ "generic_channels_count_0": "{{count}} 채널"
}
diff --git a/locales/nb-NO.json b/locales/nb-NO.json
index 216b559f..08b1e0e2 100644
--- a/locales/nb-NO.json
+++ b/locales/nb-NO.json
@@ -484,5 +484,7 @@
"generic_button_save": "Lagre",
"generic_button_cancel": "Avbryt",
"generic_button_rss": "RSS",
- "playlist_button_add_items": "Legg til videoer"
+ "playlist_button_add_items": "Legg til videoer",
+ "generic_channels_count": "{{count}} kanal",
+ "generic_channels_count_plural": "{{count}} kanaler"
}
diff --git a/locales/pl.json b/locales/pl.json
index f1924c8a..313f11cb 100644
--- a/locales/pl.json
+++ b/locales/pl.json
@@ -500,5 +500,8 @@
"channel_tab_releases_label": "Wydania",
"generic_button_delete": "Usuń",
"generic_button_save": "Zapisz",
- "playlist_button_add_items": "Dodaj filmy"
+ "playlist_button_add_items": "Dodaj filmy",
+ "generic_channels_count_0": "{{count}} kanał",
+ "generic_channels_count_1": "{{count}} kanały",
+ "generic_channels_count_2": "{{count}} kanałów"
}
diff --git a/locales/pt-BR.json b/locales/pt-BR.json
index 68a6e3ab..1e089723 100644
--- a/locales/pt-BR.json
+++ b/locales/pt-BR.json
@@ -112,8 +112,9 @@
"Subscription manager": "Gerenciador de inscrições",
"Token manager": "Gerenciador de tokens",
"Token": "Token",
- "tokens_count": "{{count}} token",
- "tokens_count_plural": "{{count}} tokens",
+ "tokens_count_0": "{{count}} token",
+ "tokens_count_1": "{{count}} tokens",
+ "tokens_count_2": "{{count}} tokens",
"Import/export": "Importar/Exportar",
"unsubscribe": "cancelar inscrição",
"revoke": "revogar",
@@ -297,20 +298,27 @@
"Yiddish": "Iídiche",
"Yoruba": "Iorubá",
"Zulu": "Zulu",
- "generic_count_years": "{{count}} ano",
- "generic_count_years_plural": "{{count}} anos",
- "generic_count_months": "{{count}} mês",
- "generic_count_months_plural": "{{count}} meses",
- "generic_count_weeks": "{{count}} semana",
- "generic_count_weeks_plural": "{{count}} semanas",
- "generic_count_days": "{{count}} dia",
- "generic_count_days_plural": "{{count}} dias",
- "generic_count_hours": "{{count}} hora",
- "generic_count_hours_plural": "{{count}} horas",
- "generic_count_minutes": "{{count}} minuto",
- "generic_count_minutes_plural": "{{count}} minutos",
- "generic_count_seconds": "{{count}} segundo",
- "generic_count_seconds_plural": "{{count}} segundos",
+ "generic_count_years_0": "{{count}} ano",
+ "generic_count_years_1": "{{count}} anos",
+ "generic_count_years_2": "{{count}} anos",
+ "generic_count_months_0": "{{count}} mês",
+ "generic_count_months_1": "{{count}} meses",
+ "generic_count_months_2": "{{count}} meses",
+ "generic_count_weeks_0": "{{count}} semana",
+ "generic_count_weeks_1": "{{count}} semanas",
+ "generic_count_weeks_2": "{{count}} semanas",
+ "generic_count_days_0": "{{count}} dia",
+ "generic_count_days_1": "{{count}} dias",
+ "generic_count_days_2": "{{count}} dias",
+ "generic_count_hours_0": "{{count}} hora",
+ "generic_count_hours_1": "{{count}} horas",
+ "generic_count_hours_2": "{{count}} horas",
+ "generic_count_minutes_0": "{{count}} minuto",
+ "generic_count_minutes_1": "{{count}} minutos",
+ "generic_count_minutes_2": "{{count}} minutos",
+ "generic_count_seconds_0": "{{count}} segundo",
+ "generic_count_seconds_1": "{{count}} segundos",
+ "generic_count_seconds_2": "{{count}} segundos",
"Fallback comments: ": "Comentários alternativos: ",
"Popular": "Populares",
"Search": "Procurar",
@@ -377,20 +385,27 @@
"preferences_quality_dash_label": "Qualidade de vídeo do painel preferida: ",
"preferences_region_label": "País do conteúdo: ",
"preferences_quality_dash_option_4320p": "4320p",
- "generic_videos_count": "{{count}} vídeo",
- "generic_videos_count_plural": "{{count}} vídeos",
- "generic_playlists_count": "{{count}} lista de reprodução",
- "generic_playlists_count_plural": "{{count}} listas de reprodução",
- "generic_subscribers_count": "{{count}} inscrito",
- "generic_subscribers_count_plural": "{{count}} inscritos",
- "generic_subscriptions_count": "{{count}} inscrição",
- "generic_subscriptions_count_plural": "{{count}} inscrições",
- "subscriptions_unseen_notifs_count": "{{count}} notificação não vista",
- "subscriptions_unseen_notifs_count_plural": "{{count}} notificações não vistas",
- "comments_view_x_replies": "Ver {{count}} resposta",
- "comments_view_x_replies_plural": "Ver {{count}} respostas",
- "comments_points_count": "{{count}} ponto",
- "comments_points_count_plural": "{{count}} pontos",
+ "generic_videos_count_0": "{{count}} vídeo",
+ "generic_videos_count_1": "{{count}} vídeos",
+ "generic_videos_count_2": "{{count}} vídeos",
+ "generic_playlists_count_0": "{{count}} lista de reprodução",
+ "generic_playlists_count_1": "{{count}} listas de reprodução",
+ "generic_playlists_count_2": "{{count}} listas de reprodução",
+ "generic_subscribers_count_0": "{{count}} inscrito",
+ "generic_subscribers_count_1": "{{count}} inscritos",
+ "generic_subscribers_count_2": "{{count}} inscritos",
+ "generic_subscriptions_count_0": "{{count}} inscrição",
+ "generic_subscriptions_count_1": "{{count}} inscrições",
+ "generic_subscriptions_count_2": "{{count}} inscrições",
+ "subscriptions_unseen_notifs_count_0": "{{count}} notificação não vista",
+ "subscriptions_unseen_notifs_count_1": "{{count}} notificações não vistas",
+ "subscriptions_unseen_notifs_count_2": "{{count}} notificações não vistas",
+ "comments_view_x_replies_0": "Ver {{count}} resposta",
+ "comments_view_x_replies_1": "Ver {{count}} respostas",
+ "comments_view_x_replies_2": "Ver {{count}} respostas",
+ "comments_points_count_0": "{{count}} ponto",
+ "comments_points_count_1": "{{count}} pontos",
+ "comments_points_count_2": "{{count}} pontos",
"crash_page_you_found_a_bug": "Parece que você encontrou um erro no Invidious!",
"crash_page_before_reporting": "Antes de reportar um erro, verifique se você:",
"preferences_save_player_pos_label": "Salvar a posição de reprodução: ",
@@ -400,8 +415,9 @@
"crash_page_search_issue": "procurou por um erro existente no GitHub",
"crash_page_report_issue": "Se nenhuma opção acima ajudou, por favor abra um novo problema no Github (preferencialmente em inglês) e inclua o seguinte texto (NÃO traduza):",
"crash_page_read_the_faq": "leia as Perguntas frequentes (FAQ)",
- "generic_views_count": "{{count}} visualização",
- "generic_views_count_plural": "{{count}} visualizações",
+ "generic_views_count_0": "{{count}} visualização",
+ "generic_views_count_1": "{{count}} visualizações",
+ "generic_views_count_2": "{{count}} visualizações",
"preferences_quality_option_dash": "DASH (qualidade adaptável)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_small": "Pequeno",
@@ -484,5 +500,8 @@
"channel_tab_releases_label": "Lançamentos",
"channel_tab_podcasts_label": "Podcasts",
"generic_button_cancel": "Cancelar",
- "generic_button_rss": "RSS"
+ "generic_button_rss": "RSS",
+ "generic_channels_count_0": "{{count}} canal",
+ "generic_channels_count_1": "{{count}} canais",
+ "generic_channels_count_2": "{{count}} canais"
}
diff --git a/locales/ru.json b/locales/ru.json
index 5325a9b6..2769f3ab 100644
--- a/locales/ru.json
+++ b/locales/ru.json
@@ -500,5 +500,8 @@
"generic_button_cancel": "Отменить",
"generic_button_rss": "RSS",
"playlist_button_add_items": "Добавить видео",
- "channel_tab_podcasts_label": "Подкасты"
+ "channel_tab_podcasts_label": "Подкасты",
+ "generic_channels_count_0": "{{count}} канал",
+ "generic_channels_count_1": "{{count}} канала",
+ "generic_channels_count_2": "{{count}} каналов"
}
diff --git a/locales/sl.json b/locales/sl.json
index fec1cb62..9a912f2d 100644
--- a/locales/sl.json
+++ b/locales/sl.json
@@ -516,5 +516,9 @@
"generic_button_rss": "RSS",
"playlist_button_add_items": "Dodaj videoposnetke",
"channel_tab_podcasts_label": "Poddaje",
- "channel_tab_releases_label": "Izdaje"
+ "channel_tab_releases_label": "Izdaje",
+ "generic_channels_count_0": "{{count}} kanal",
+ "generic_channels_count_1": "{{count}} kanala",
+ "generic_channels_count_2": "{{count}} kanali",
+ "generic_channels_count_3": "{{count}} kanalov"
}
diff --git a/locales/sq.json b/locales/sq.json
index d28eb784..41d4161c 100644
--- a/locales/sq.json
+++ b/locales/sq.json
@@ -257,7 +257,7 @@
"Video mode": "Mënyrë video",
"channel_tab_videos_label": "Video",
"search_filters_sort_option_rating": "Vlerësim",
- "search_filters_sort_option_date": "Datë ngarkimi",
+ "search_filters_sort_option_date": "Datë Ngarkimi",
"search_filters_sort_option_views": "Numër parjesh",
"search_filters_type_label": "Lloj",
"search_filters_duration_label": "Kohëzgjatje",
@@ -345,7 +345,7 @@
"View YouTube comments": "Shihni komente Youtube",
"View more comments on Reddit": "Shihni më tepër komente në Reddit",
"View `x` comments": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "Shihni `x` komente",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Shihni `x` koment",
"": "Shihni `x` komente"
},
"View Reddit comments": "Shihni komente Reddit",
@@ -462,5 +462,20 @@
"channel_tab_channels_label": "Kanale",
"Music in this video": "Muzikë në këtë video",
"channel_tab_shorts_label": "Të shkurtra",
- "channel_tab_streams_label": "Transmetime të drejtpërdrejta"
+ "channel_tab_streams_label": "Transmetime të drejtpërdrejta",
+ "generic_button_cancel": "Anuloje",
+ "generic_channels_count": "{{count}} kanal",
+ "generic_channels_count_plural": "{{count}} kanale",
+ "generic_button_rss": "RSS",
+ "generic_button_delete": "Fshije",
+ "generic_button_save": "Ruaje",
+ "generic_button_edit": "Përpunoni",
+ "playlist_button_add_items": "Shtoni video",
+ "Report statistics: ": "Statistika raportimesh: ",
+ "Download is disabled": "Shkarkimi është i çaktivizuar",
+ "Channel Sponsor": "Sponsor Kanali",
+ "channel_tab_releases_label": "Hedhje në qarkullim",
+ "Song: ": "Pjesë: ",
+ "Import YouTube playlist (.csv)": "Importoni luajlistë YouTube (.csv)",
+ "Standard YouTube license": "Licencë YouTube standarde"
}
diff --git a/locales/sr.json b/locales/sr.json
index a2853b68..f0e5518d 100644
--- a/locales/sr.json
+++ b/locales/sr.json
@@ -1,90 +1,90 @@
{
"LIVE": "UŽIVO",
- "Shared `x` ago": "Podeljeno pre `x`",
+ "Shared `x` ago": "Deljeno pre `x`",
"Unsubscribe": "Prekini praćenje",
- "Subscribe": "Prati",
+ "Subscribe": "Zaprati",
"View channel on YouTube": "Pogledaj kanal na YouTube-u",
- "View playlist on YouTube": "Pogledaj spisak izvođenja na YouTube-u",
+ "View playlist on YouTube": "Pogledaj plejlistu na YouTube-u",
"newest": "najnovije",
"oldest": "najstarije",
"popular": "popularno",
"last": "poslednje",
"Next page": "Sledeća stranica",
"Previous page": "Prethodna stranica",
- "Clear watch history?": "Izbrisati povest pregledanja?",
+ "Clear watch history?": "Očistiti istoriju gledanja?",
"New password": "Nova lozinka",
- "New passwords must match": "Nove lozinke moraju biti istovetne",
- "Authorize token?": "Ovlasti žeton?",
- "Authorize token for `x`?": "Ovlasti žeton za `x`?",
+ "New passwords must match": "Nove lozinke moraju da se podudaraju",
+ "Authorize token?": "Autorizovati token?",
+ "Authorize token for `x`?": "Autorizovati token za `x`?",
"Yes": "Da",
"No": "Ne",
- "Import and Export Data": "Uvoz i Izvoz Podataka",
+ "Import and Export Data": "Uvoz i izvoz podataka",
"Import": "Uvezi",
- "Import Invidious data": "Uvezi podatke sa Invidious-a",
- "Import YouTube subscriptions": "Uvezi praćenja sa YouTube-a",
- "Import FreeTube subscriptions (.db)": "Uvezi praćenja sa FreeTube-a (.db)",
- "Import NewPipe subscriptions (.json)": "Uvezi praćenja sa NewPipe-a (.json)",
- "Import NewPipe data (.zip)": "Uvezi podatke sa NewPipe-a (.zip)",
+ "Import Invidious data": "Uvezi Invidious JSON podatke",
+ "Import YouTube subscriptions": "Uvezi YouTube/OPML praćenja",
+ "Import FreeTube subscriptions (.db)": "Uvezi FreeTube praćenja (.db)",
+ "Import NewPipe subscriptions (.json)": "Uvezi NewPipe praćenja (.json)",
+ "Import NewPipe data (.zip)": "Uvezi NewPipe podatke (.zip)",
"Export": "Izvezi",
- "Export subscriptions as OPML": "Izvezi praćenja kao OPML datoteku",
- "Export subscriptions as OPML (for NewPipe & FreeTube)": "Izvezi praćenja kao OPML datoteku (za NewPipe i FreeTube)",
- "Export data as JSON": "Izvezi podatke kao JSON datoteku",
- "Delete account?": "Izbrišite nalog?",
+ "Export subscriptions as OPML": "Izvezi praćenja kao OPML",
+ "Export subscriptions as OPML (for NewPipe & FreeTube)": "Izvezi praćenja kao OPML (za NewPipe i FreeTube)",
+ "Export data as JSON": "Izvezi Invidious podatke kao JSON",
+ "Delete account?": "Izbrisati nalog?",
"History": "Istorija",
- "An alternative front-end to YouTube": "Zamenski korisnički sloj za YouTube",
- "JavaScript license information": "Izveštaj o JavaScript odobrenju",
+ "An alternative front-end to YouTube": "Alternativni front-end za YouTube",
+ "JavaScript license information": "Informacije o JavaScript licenci",
"source": "izvor",
- "Log in": "Prijavi se",
- "Log in/register": "Prijavi se/Otvori nalog",
- "User ID": "Korisnički ID",
+ "Log in": "Prijava",
+ "Log in/register": "Prijava/registracija",
+ "User ID": "ID korisnika",
"Password": "Lozinka",
"Time (h:mm:ss):": "Vreme (č:mm:ss):",
- "Text CAPTCHA": "Znakovni CAPTCHA",
- "Image CAPTCHA": "Slikovni CAPTCHA",
+ "Text CAPTCHA": "Tekst CAPTCHA",
+ "Image CAPTCHA": "Slika CAPTCHA",
"Sign In": "Prijava",
- "Register": "Otvori nalog",
- "E-mail": "E-pošta",
+ "Register": "Registracija",
+ "E-mail": "Imejl",
"Preferences": "Podešavanja",
- "preferences_category_player": "Podešavanja reproduktora",
+ "preferences_category_player": "Podešavanja plejera",
"preferences_video_loop_label": "Uvek ponavljaj: ",
- "preferences_autoplay_label": "Samopuštanje: ",
- "preferences_continue_label": "Uvek podrazumevano puštaj sledeće: ",
- "preferences_continue_autoplay_label": "Samopuštanje sledećeg video zapisa: ",
- "preferences_listen_label": "Uvek podrazumevano uključen samo zvuk: ",
- "preferences_local_label": "Prikaz video zapisa preko posrednika: ",
- "Playlist privacy": "Podešavanja privatnosti plej liste",
- "Editing playlist `x`": "Izmena plej liste `x`",
- "Playlist does not exist.": "Nepostojeća plej lista.",
+ "preferences_autoplay_label": "Automatski pusti: ",
+ "preferences_continue_label": "Podrazumevano pusti sledeće: ",
+ "preferences_continue_autoplay_label": "Automatski pusti sledeći video snimak: ",
+ "preferences_listen_label": "Podrazumevano uključi samo zvuk: ",
+ "preferences_local_label": "Proksi video snimci: ",
+ "Playlist privacy": "Privatnost plejliste",
+ "Editing playlist `x`": "Izmenjivanje plejliste `x`",
+ "Playlist does not exist.": "Plejlista ne postoji.",
"Erroneous challenge": "Pogrešan izazov",
"Maltese": "Malteški",
"Download": "Preuzmi",
- "Download as: ": "Preuzmi kao: ",
- "Bangla": "Bangla/Bengalski",
- "preferences_quality_dash_label": "Preferirani kvalitet DASH video formata: ",
- "Token manager": "Upravljanje žetonima",
- "Token": "Žeton",
- "Import/export": "Uvezi/Izvezi",
+ "Download as: ": "Preuzeti kao: ",
+ "Bangla": "Bengalski",
+ "preferences_quality_dash_label": "Preferirani DASH kvalitet video snimka: ",
+ "Token manager": "Upravljanje tokenima",
+ "Token": "Token",
+ "Import/export": "Uvoz/izvoz",
"revoke": "opozovi",
"search": "pretraga",
"Log out": "Odjava",
- "Source available here.": "Izvorna koda je ovde dostupna.",
+ "Source available here.": "Izvorni kôd je dostupan ovde.",
"Trending": "U trendu",
"Updated `x` ago": "Ažurirano pre `x`",
- "Delete playlist `x`?": "Obriši plej listu `x`?",
- "Create playlist": "Napravi plej listu",
+ "Delete playlist `x`?": "Izbrisati plejlistu `x`?",
+ "Create playlist": "Napravi plejlistu",
"Show less": "Prikaži manje",
"Switch Invidious Instance": "Promeni Invidious instancu",
"Hide annotations": "Sakrij napomene",
- "User ID is a required field": "Korisnički ID je obavezno polje",
+ "User ID is a required field": "ID korisnika je obavezno polje",
"Wrong username or password": "Pogrešno korisničko ime ili lozinka",
- "Please log in": "Molimo vas da se prijavite",
+ "Please log in": "Molimo, prijavite se",
"channel:`x`": "kanal:`x`",
- "Could not fetch comments": "Uzimanje komentara nije uspelo",
- "Could not create mix.": "Pravljenje miksa nije uspelo.",
- "Empty playlist": "Prazna plej lista",
- "Not a playlist.": "Nije plej lista.",
- "Could not pull trending pages.": "Učitavanje 'U toku' stranica nije uspelo.",
- "Token is expired, please try again": "Žeton je istekao, molimo vas da pokušate ponovo",
+ "Could not fetch comments": "Nije moguće prikupiti komentare",
+ "Could not create mix.": "Nije moguće napraviti miks.",
+ "Empty playlist": "Prazna plejlista",
+ "Not a playlist.": "Nije plejlista.",
+ "Could not pull trending pages.": "Nije moguće povući stranice „U trendu“.",
+ "Token is expired, please try again": "Token je istekao, pokušajte ponovo",
"English (auto-generated)": "Engleski (automatski generisano)",
"Afrikaans": "Afrikans",
"Albanian": "Albanski",
@@ -95,19 +95,19 @@
"Bulgarian": "Bugarski",
"Burmese": "Burmanski",
"Catalan": "Katalonski",
- "Cebuano": "Sebuano",
+ "Cebuano": "Cebuanski",
"Chinese (Traditional)": "Kineski (Tradicionalni)",
"Corsican": "Korzikanski",
"Danish": "Danski",
- "Kannada": "Kanada (Jezik)",
+ "Kannada": "Kanada",
"Kazakh": "Kazaški",
"Russian": "Ruski",
"Scottish Gaelic": "Škotski Gelski",
- "Sinhala": "Sinhaleški",
+ "Sinhala": "Sinhalski",
"Slovak": "Slovački",
"Spanish": "Španski",
- "Spanish (Latin America)": "Španski (Južna Amerika)",
- "Sundanese": "Sundski",
+ "Spanish (Latin America)": "Španski (Latinska Amerika)",
+ "Sundanese": "Sundanski",
"Swedish": "Švedski",
"Tajik": "Tadžički",
"Telugu": "Telugu",
@@ -116,77 +116,77 @@
"Urdu": "Urdu",
"Uzbek": "Uzbečki",
"Vietnamese": "Vijetnamski",
- "Rating: ": "Ocena/e: ",
- "View as playlist": "Pogledaj kao plej listu",
- "Default": "Podrazumevan/o",
- "Gaming": "Igrice",
+ "Rating: ": "Ocena: ",
+ "View as playlist": "Pogledaj kao plejlistu",
+ "Default": "Podrazumevano",
+ "Gaming": "Video igre",
"Movies": "Filmovi",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"(edited)": "(izmenjeno)",
- "YouTube comment permalink": "YouTube komentar trajna veza",
- "Audio mode": "Audio mod",
- "Playlists": "Plej liste",
+ "YouTube comment permalink": "Trajni link YouTube komentara",
+ "Audio mode": "Režim audio snimka",
+ "Playlists": "Plejliste",
"search_filters_sort_option_relevance": "Relevantnost",
- "search_filters_sort_option_rating": "Ocene",
+ "search_filters_sort_option_rating": "Ocena",
"search_filters_sort_option_date": "Datum otpremanja",
"search_filters_sort_option_views": "Broj pregleda",
- "`x` marked it with a ❤": "`x` je označio/la ovo sa ❤",
+ "`x` marked it with a ❤": "`x` je označio/la sa ❤",
"search_filters_duration_label": "Trajanje",
"search_filters_features_label": "Karakteristike",
"search_filters_date_option_hour": "Poslednji sat",
- "search_filters_date_option_week": "Ove sedmice",
- "search_filters_date_option_month": "Ovaj mesec",
+ "search_filters_date_option_week": "Ove nedelje",
+ "search_filters_date_option_month": "Ovog meseca",
"search_filters_date_option_year": "Ove godine",
- "search_filters_type_option_video": "Video",
- "search_filters_type_option_playlist": "Plej lista",
+ "search_filters_type_option_video": "Video snimak",
+ "search_filters_type_option_playlist": "Plejlista",
"search_filters_type_option_movie": "Film",
"search_filters_duration_option_long": "Dugo (> 20 minuta)",
"search_filters_features_option_hd": "HD",
- "search_filters_features_option_c_commons": "Creative Commons (Licenca)",
+ "search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
- "search_filters_features_option_hdr": "Video Visoke Rezolucije",
- "next_steps_error_message": "Nakon čega bi trebali probati: ",
- "next_steps_error_message_go_to_youtube": "Idi na YouTube",
+ "search_filters_features_option_hdr": "HDR",
+ "next_steps_error_message": "Nakon toga treba da pokušate da: ",
+ "next_steps_error_message_go_to_youtube": "Odete na YouTube",
"footer_documentation": "Dokumentacija",
- "preferences_region_label": "Država porekla sadržaja: ",
+ "preferences_region_label": "Država sadržaja: ",
"preferences_player_style_label": "Stil plejera: ",
- "preferences_dark_mode_label": "Izgled/Tema: ",
- "light": "svetlo",
+ "preferences_dark_mode_label": "Tema: ",
+ "light": "svetla",
"preferences_thin_mode_label": "Kompaktni režim: ",
"preferences_category_misc": "Ostala podešavanja",
- "preferences_automatic_instance_redirect_label": "Automatsko prebacivanje na drugu instancu u slučaju otkazivanja (preči će nazad na redirect.invidious.io): ",
- "alphabetically - reverse": "po alfabetu - obrnuto",
- "Enable web notifications": "Omogući obaveštenja u veb pretraživaču",
- "`x` is live": "`x` prenosi uživo",
- "Manage tokens": "Upravljaj žetonima",
+ "preferences_automatic_instance_redirect_label": "Automatsko preusmeravanje instance (povratak na redirect.invidious.io): ",
+ "alphabetically - reverse": "abecedno - obrnuto",
+ "Enable web notifications": "Omogući veb obaveštenja",
+ "`x` is live": "`x` je uživo",
+ "Manage tokens": "Upravljaj tokenima",
"Watch history": "Istorija gledanja",
- "preferences_feed_menu_label": "Dovodna stranica: ",
+ "preferences_feed_menu_label": "Fid meni: ",
"preferences_show_nick_label": "Prikaži nadimke na vrhu: ",
"CAPTCHA enabled: ": "CAPTCHA omogućena: ",
"Registration enabled: ": "Registracija omogućena: ",
"Subscription manager": "Upravljanje praćenjima",
- "Wilson score: ": "Wilsonova ocena: ",
+ "Wilson score: ": "Vilsonova ocena: ",
"Engagement: ": "Angažovanje: ",
- "Whitelisted regions: ": "Dozvoljene oblasti: ",
- "Shared `x`": "Podeljeno `x`",
- "Premieres in `x`": "Premera u `x`",
- "Premieres `x`": "Premere u `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.": "Hej! Izgleda da ste onemogućili JavaScript. Kliknite ovde da vidite komentare, čuvajte na umu da ovo može da potraje duže dok se ne učitaju.",
+ "Whitelisted regions: ": "Dostupni regioni: ",
+ "Shared `x`": "Deljeno `x`",
+ "Premieres in `x`": "Premijera u `x`",
+ "Premieres `x`": "Premijera `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.": "Hej! Izgleda da ste isključili JavaScript. Kliknite ovde da biste videli komentare, imajte na umu da će možda potrajati malo duže da se učitaju.",
"View `x` comments": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "Prikaži `x` komentar",
- "": "Prikaži `x` komentara"
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Pogledaj `x` komentar",
+ "": "Pogledaj`x` komentare"
},
- "View Reddit comments": "Prikaži Reddit komentare",
+ "View Reddit comments": "Pogledaj Reddit komentare",
"CAPTCHA is a required field": "CAPTCHA je obavezno polje",
"Croatian": "Hrvatski",
"Estonian": "Estonski",
- "Filipino": "Filipino",
+ "Filipino": "Filipinski",
"French": "Francuski",
"Galician": "Galicijski",
"German": "Nemački",
"Greek": "Grčki",
"Hausa": "Hausa",
- "Italian": "Talijanski",
+ "Italian": "Italijanski",
"Khmer": "Kmerski",
"Kurdish": "Kurdski",
"Kyrgyz": "Kirgiski",
@@ -195,68 +195,68 @@
"Macedonian": "Makedonski",
"Malagasy": "Malgaški",
"Malay": "Malajski",
- "Marathi": "Marathi",
+ "Marathi": "Maratski",
"Mongolian": "Mongolski",
"Norwegian Bokmål": "Norveški Bokmal",
- "Nyanja": "Čeva",
+ "Nyanja": "Nijandža",
"Pashto": "Paštunski",
"Persian": "Persijski",
- "Punjabi": "Pundžabi",
+ "Punjabi": "Pandžapski",
"Romanian": "Rumunski",
"Welsh": "Velški",
"Western Frisian": "Zapadnofrizijski",
- "Fallback comments: ": "Komentari u slučaju otkazivanja: ",
+ "Fallback comments: ": "Rezervni komentari: ",
"Popular": "Popularno",
"Search": "Pretraga",
- "About": "O programu",
- "footer_source_code": "Izvorna Koda",
- "footer_original_source_code": "Originalna Izvorna Koda",
- "preferences_related_videos_label": "Prikaži slične video klipove: ",
- "preferences_annotations_label": "Prikaži napomene podrazumevano: ",
- "preferences_extend_desc_label": "Automatski prikaži ceo opis videa: ",
- "preferences_vr_mode_label": "Interaktivni video klipovi u 360 stepeni: ",
- "preferences_category_visual": "Vizuelne preference",
- "preferences_captions_label": "Podrazumevani titl: ",
+ "About": "O sajtu",
+ "footer_source_code": "Izvorni kôd",
+ "footer_original_source_code": "Originalni izvorni kôd",
+ "preferences_related_videos_label": "Prikaži povezane video snimke: ",
+ "preferences_annotations_label": "Podrazumevano prikaži napomene: ",
+ "preferences_extend_desc_label": "Automatski proširi opis video snimka: ",
+ "preferences_vr_mode_label": "Interaktivni video snimci od 360 stepeni (zahteva WebGl): ",
+ "preferences_category_visual": "Vizuelna podešavanja",
+ "preferences_captions_label": "Podrazumevani titlovi: ",
"Music": "Muzika",
- "search_filters_type_label": "Tip",
+ "search_filters_type_label": "Vrsta",
"Tamil": "Tamilski",
"Save preferences": "Sačuvaj podešavanja",
- "Only show latest unwatched video from channel: ": "Prikaži samo poslednje video klipove koji nisu pogledani sa kanala: ",
- "Xhosa": "Kosa (Jezik)",
+ "Only show latest unwatched video from channel: ": "Prikaži samo najnoviji neodgledani video snimak sa kanala: ",
+ "Xhosa": "Kosa (Khosa)",
"search_filters_type_option_channel": "Kanal",
"Hungarian": "Mađarski",
- "Maori": "Maori (Jezik)",
- "Manage subscriptions": "Upravljaj zapisima",
+ "Maori": "Maorski",
+ "Manage subscriptions": "Upravljaj praćenjima",
"Hindi": "Hindi",
"`x` ago": "pre `x`",
"Import/export data": "Uvezi/Izvezi podatke",
- "`x` uploaded a video": "`x` je otpremio/la video klip",
- "Delete account": "Obriši nalog",
+ "`x` uploaded a video": "`x` je otpremio/la video snimak",
+ "Delete account": "Izbriši nalog",
"preferences_default_home_label": "Podrazumevana početna stranica: ",
"Serbian": "Srpski",
"License: ": "Licenca: ",
"search_filters_features_option_live": "Uživo",
- "Report statistics: ": "Izveštavaj o statistici: ",
- "Only show latest video from channel: ": "Prikazuj poslednje video klipove samo sa kanala: ",
+ "Report statistics: ": "Izveštavaj statistike: ",
+ "Only show latest video from channel: ": "Prikaži samo najnoviji video snimak sa kanala: ",
"channel name - reverse": "ime kanala - obrnuto",
- "Could not get channel info.": "Uzimanje podataka o kanalu nije uspelo.",
- "View privacy policy.": "Pogledaj izveštaj o privatnosti.",
+ "Could not get channel info.": "Nije moguće prikupiti informacije o kanalu.",
+ "View privacy policy.": "Pogledaj politiku privatnosti.",
"Change password": "Promeni lozinku",
- "Malayalam": "Malajalam",
- "View more comments on Reddit": "Prikaži više komentara na Reddit-u",
+ "Malayalam": "Malajalamski",
+ "View more comments on Reddit": "Pogledaj više komentara na Reddit-u",
"Portuguese": "Portugalski",
- "View YouTube comments": "Prikaži YouTube komentare",
+ "View YouTube comments": "Pogledaj YouTube komentare",
"published - reverse": "objavljeno - obrnuto",
"Dutch": "Holandski",
- "preferences_volume_label": "Jačina zvuka: ",
+ "preferences_volume_label": "Jačina zvuka plejera: ",
"preferences_locale_label": "Jezik: ",
- "adminprefs_modified_source_code_url_label": "URL veza do skladišta sa Izmenjenom Izvornom Kodom",
+ "adminprefs_modified_source_code_url_label": "URL adresa do repozitorijuma izmenjenog izvornog koda",
"channel_tab_community_label": "Zajednica",
- "Video mode": "Video mod",
- "Fallback captions: ": "Titl u slučaju da glavni nije dostupan: ",
+ "Video mode": "Režim video snimka",
+ "Fallback captions: ": "Rezervni titlovi: ",
"Private": "Privatno",
- "alphabetically": "po alfabetu",
- "No such user": "Nepostojeći korisnik",
+ "alphabetically": "abecedno",
+ "No such user": "Ne postoji korisnik",
"Subscriptions": "Praćenja",
"search_filters_date_option_today": "Danas",
"Finnish": "Finski",
@@ -265,30 +265,30 @@
"Shona": "Šona",
"search_filters_features_option_location": "Lokacija",
"Load more": "Učitaj više",
- "Released under the AGPLv3 on Github.": "Izbačeno pod licencom AGPLv3 na GitHub-u.",
+ "Released under the AGPLv3 on Github.": "Objavljeno pod licencom AGPLv3 na GitHub-u.",
"Slovenian": "Slovenački",
- "View JavaScript license information.": "Pogledaj informacije licence vezane za JavaScript.",
+ "View JavaScript license information.": "Pogledaj informacije o JavaScript licenci.",
"Chinese (Simplified)": "Kineski (Pojednostavljeni)",
"preferences_comments_label": "Podrazumevani komentari: ",
"Incorrect password": "Netačna lozinka",
"Show replies": "Prikaži odgovore",
- "Invidious Private Feed for `x`": "Invidious Privatni Dovod za `x`",
+ "Invidious Private Feed for `x`": "Invidious privatni fid za `x`",
"Watch on YouTube": "Gledaj na YouTube-u",
"Wrong answer": "Pogrešan odgovor",
- "preferences_quality_label": "Preferirani video kvalitet: ",
+ "preferences_quality_label": "Preferirani kvalitet video snimka: ",
"Hide replies": "Sakrij odgovore",
"Erroneous CAPTCHA": "Pogrešna CAPTCHA",
- "Erroneous token": "Pogrešan žeton",
+ "Erroneous token": "Pogrešan token",
"Czech": "Češki",
"Latin": "Latinski",
- "channel_tab_videos_label": "Video klipovi",
+ "channel_tab_videos_label": "Video snimci",
"search_filters_features_option_four_k": "4К",
"footer_donate_page": "Doniraj",
"English": "Engleski",
"Arabic": "Arapski",
- "Unlisted": "Nenavedeno",
- "Hidden field \"challenge\" is a required field": "Sakriveno \"challenge\" polje je obavezno",
- "Hidden field \"token\" is a required field": "Sakriveno \"token\" polje je obavezno",
+ "Unlisted": "Po pozivu",
+ "Hidden field \"challenge\" is a required field": "Skriveno polje „izazov“ je obavezno polje",
+ "Hidden field \"token\" is a required field": "Skriveno polje „token“ je obavezno polje",
"Georgian": "Gruzijski",
"Hawaiian": "Havajski",
"Hebrew": "Hebrejski",
@@ -297,68 +297,211 @@
"Japanese": "Japanski",
"Javanese": "Javanski",
"Sindhi": "Sindi",
- "Swahili": "Svahili",
+ "Swahili": "Suvali",
"Yiddish": "Jidiš",
"Zulu": "Zulu",
- "search_filters_features_option_subtitles": "Titl/Prevod",
- "Password cannot be longer than 55 characters": "Lozinka ne može biti duža od 55 karaktera",
+ "search_filters_features_option_subtitles": "Titlovi/Skriveni titlovi",
+ "Password cannot be longer than 55 characters": "Lozinka ne može biti duža od 55 znakova",
"This channel does not exist.": "Ovaj kanal ne postoji.",
"Belarusian": "Beloruski",
"Gujarati": "Gudžarati",
"Haitian Creole": "Haićanski Kreolski",
"Somali": "Somalijski",
- "Top": "Vrh",
- "footer_modfied_source_code": "Izmenjena Izvorna Koda",
+ "Top": "Top",
+ "footer_modfied_source_code": "Izmenjeni izvorni kôd",
"preferences_category_subscription": "Podešavanja praćenja",
"preferences_annotations_subscribed_label": "Podrazumevano prikazati napomene za kanale koje pratite? ",
- "preferences_max_results_label": "Broj video klipova prikazanih u dovodnoj listi: ",
- "preferences_sort_label": "Sortiraj video klipove po: ",
- "preferences_unseen_only_label": "Prikaži samo video klipove koji nisu pogledani: ",
- "preferences_notifications_only_label": "Prikaži samo obaveštenja (ako ih uopšte ima): ",
+ "preferences_max_results_label": "Broj video snimaka prikazanih u fidu: ",
+ "preferences_sort_label": "Sortiraj video snimke po: ",
+ "preferences_unseen_only_label": "Prikaži samo neodgledano: ",
+ "preferences_notifications_only_label": "Prikaži samo obaveštenja (ako ih ima): ",
"preferences_category_data": "Podešavanja podataka",
- "Clear watch history": "Obriši istoriju gledanja",
- "preferences_category_admin": "Administratorska podešavanja",
+ "Clear watch history": "Očisti istoriju gledanja",
+ "preferences_category_admin": "Podešavanja administratora",
"published": "objavljeno",
- "search_filters_sort_label": "Poredaj prema",
+ "search_filters_sort_label": "Sortiranje po",
"search_filters_type_option_show": "Emisija",
- "search_filters_duration_option_short": "Kratko (< 4 minute)",
+ "search_filters_duration_option_short": "Kratko (< 4 minuta)",
"Current version: ": "Trenutna verzija: ",
- "Top enabled: ": "Vrh omogućen: ",
+ "Top enabled: ": "Top omogućeno: ",
"Public": "Javno",
- "Delete playlist": "Obriši plej listu",
+ "Delete playlist": "Izbriši plejlistu",
"Title": "Naslov",
"Show annotations": "Prikaži napomene",
"Password cannot be empty": "Lozinka ne može biti prazna",
- "Deleted or invalid channel": "Obrisan ili nepostojeći kanal",
+ "Deleted or invalid channel": "Izbrisan ili nevažeći kanal",
"Esperanto": "Esperanto",
"Hmong": "Hmong",
"Luxembourgish": "Luksemburški",
"Nepali": "Nepalski",
"Samoan": "Samoanski",
"News": "Vesti",
- "permalink": "trajna veza",
+ "permalink": "trajni link",
"Password is a required field": "Lozinka je obavezno polje",
"Amharic": "Amharski",
- "Indonesian": "Indonežanski",
+ "Indonesian": "Indonezijski",
"Irish": "Irski",
"Korean": "Korejski",
"Southern Sotho": "Južni Soto",
"Thai": "Tajski",
"preferences_speed_label": "Podrazumevana brzina: ",
"Dark mode: ": "Tamni režim: ",
- "dark": "tamno",
- "Redirect homepage to feed: ": "Prebaci sa početne stranice na dovodnu listu: ",
+ "dark": "tamna",
+ "Redirect homepage to feed: ": "Preusmeri početnu stranicu na fid: ",
"channel name": "ime kanala",
- "View all playlists": "Pregledaj sve plej liste",
+ "View all playlists": "Pogledaj sve plejliste",
"Show more": "Prikaži više",
"Genre: ": "Žanr: ",
"Family friendly? ": "Pogodno za porodicu? ",
- "next_steps_error_message_refresh": "Osveži stranicu",
+ "next_steps_error_message_refresh": "Osvežite",
"youtube": "YouTube",
"reddit": "Reddit",
- "unsubscribe": "prekini sa praćenjem",
- "Blacklisted regions: ": "Zabranjene oblasti: ",
+ "unsubscribe": "prekini praćenje",
+ "Blacklisted regions: ": "Nedostupni regioni: ",
"Polish": "Poljski",
"Yoruba": "Joruba",
- "search_filters_title": "Filter"
+ "search_filters_title": "Filteri",
+ "Korean (auto-generated)": "Korejski (automatski generisano)",
+ "search_filters_features_option_three_sixty": "360°",
+ "preferences_quality_dash_option_worst": "Najgore",
+ "channel_tab_podcasts_label": "Podkasti",
+ "preferences_save_player_pos_label": "Sačuvaj poziciju reprodukcije: ",
+ "Spanish (Mexico)": "Španski (Meksiko)",
+ "generic_subscriptions_count_0": "{{count}} praćenje",
+ "generic_subscriptions_count_1": "{{count}} praćenja",
+ "generic_subscriptions_count_2": "{{count}} praćenja",
+ "search_filters_apply_button": "Primeni izabrane filtere",
+ "Download is disabled": "Preuzimanje je onemogućeno",
+ "comments_points_count_0": "{{count}} poen",
+ "comments_points_count_1": "{{count}} poena",
+ "comments_points_count_2": "{{count}} poena",
+ "preferences_quality_dash_option_2160p": "2160p",
+ "German (auto-generated)": "Nemački (automatski generisano)",
+ "Japanese (auto-generated)": "Japanski (automatski generisano)",
+ "preferences_quality_option_medium": "Srednje",
+ "search_message_change_filters_or_query": "Pokušajte da proširite upit za pretragu i/ili promenite filtere.",
+ "crash_page_before_reporting": "Pre nego što prijavite grešku, uverite se da ste:",
+ "preferences_quality_dash_option_best": "Najbolje",
+ "Channel Sponsor": "Sponzor kanala",
+ "generic_videos_count_0": "{{count}} video snimak",
+ "generic_videos_count_1": "{{count}} video snimka",
+ "generic_videos_count_2": "{{count}} video snimaka",
+ "videoinfo_started_streaming_x_ago": "Započeto strimovanje pre `x`",
+ "videoinfo_youTube_embed_link": "Ugrađeno",
+ "channel_tab_streams_label": "Strimovi uživo",
+ "playlist_button_add_items": "Dodaj video snimke",
+ "generic_count_minutes_0": "{{count}} minut",
+ "generic_count_minutes_1": "{{count}} minuta",
+ "generic_count_minutes_2": "{{count}} minuta",
+ "preferences_quality_dash_option_720p": "720p",
+ "preferences_watch_history_label": "Omogući istoriju gledanja: ",
+ "user_saved_playlists": "Sačuvanih plejlista: `x`",
+ "Spanish (Spain)": "Španski (Španija)",
+ "invidious": "Invidious",
+ "crash_page_refresh": "pokušali da osvežite stranicu",
+ "Chinese (Hong Kong)": "Kineski (Hong Kong)",
+ "Artist: ": "Izvođač: ",
+ "generic_count_months_0": "{{count}} mesec",
+ "generic_count_months_1": "{{count}} meseca",
+ "generic_count_months_2": "{{count}} meseci",
+ "search_message_use_another_instance": " Takođe, možete pretraživati na drugoj instanci.",
+ "generic_subscribers_count_0": "{{count}} pratilac",
+ "generic_subscribers_count_1": "{{count}} pratioca",
+ "generic_subscribers_count_2": "{{count}} pratilaca",
+ "download_subtitles": "Titlovi - `x` (.vtt)",
+ "generic_button_save": "Sačuvaj",
+ "crash_page_search_issue": "pretražili postojeće izveštaje o problemima na GitHub-u",
+ "generic_button_cancel": "Otkaži",
+ "none": "nijedno",
+ "English (United States)": "Engleski (Sjedinjene Američke Države)",
+ "subscriptions_unseen_notifs_count_0": "{{count}} neviđeno obaveštenje",
+ "subscriptions_unseen_notifs_count_1": "{{count}} neviđena obaveštenja",
+ "subscriptions_unseen_notifs_count_2": "{{count}} neviđenih obaveštenja",
+ "Album: ": "Album: ",
+ "preferences_quality_option_dash": "DASH (adaptivni kvalitet)",
+ "preferences_quality_dash_option_1080p": "1080p",
+ "Video unavailable": "Video snimak nedostupan",
+ "tokens_count_0": "{{count}} token",
+ "tokens_count_1": "{{count}} tokena",
+ "tokens_count_2": "{{count}} tokena",
+ "Chinese (China)": "Kineski (Kina)",
+ "Italian (auto-generated)": "Italijanski (automatski generisano)",
+ "channel_tab_shorts_label": "Shorts",
+ "preferences_quality_dash_option_1440p": "1440p",
+ "preferences_quality_dash_option_360p": "360p",
+ "search_message_no_results": "Nisu pronađeni rezultati.",
+ "channel_tab_releases_label": "Izdanja",
+ "preferences_quality_dash_option_144p": "144p",
+ "Interlingue": "Interlingva",
+ "Song: ": "Pesma: ",
+ "generic_channels_count_0": "{{count}} kanal",
+ "generic_channels_count_1": "{{count}} kanala",
+ "generic_channels_count_2": "{{count}} kanala",
+ "Chinese (Taiwan)": "Kineski (Tajvan)",
+ "Turkish (auto-generated)": "Turski (automatski generisano)",
+ "Indonesian (auto-generated)": "Indonezijski (automatski generisano)",
+ "Portuguese (auto-generated)": "Portugalski (automatski generisano)",
+ "generic_count_years_0": "{{count}} godina",
+ "generic_count_years_1": "{{count}} godine",
+ "generic_count_years_2": "{{count}} godina",
+ "videoinfo_invidious_embed_link": "Ugrađeni link",
+ "Popular enabled: ": "Popularno omogućeno: ",
+ "Spanish (auto-generated)": "Španski (automatski generisano)",
+ "preferences_quality_option_small": "Malo",
+ "English (United Kingdom)": "Engleski (Ujedinjeno Kraljevstvo)",
+ "channel_tab_playlists_label": "Plejliste",
+ "generic_button_edit": "Izmeni",
+ "generic_playlists_count_0": "{{count}} plejlista",
+ "generic_playlists_count_1": "{{count}} plejliste",
+ "generic_playlists_count_2": "{{count}} plejlista",
+ "preferences_quality_option_hd720": "HD720",
+ "search_filters_features_option_purchased": "Kupljeno",
+ "search_filters_date_option_none": "Bilo koji datum",
+ "preferences_quality_dash_option_auto": "Automatski",
+ "Cantonese (Hong Kong)": "Kantonski (Hong Kong)",
+ "crash_page_report_issue": "Ako ništa od gorenavedenog nije pomoglo, otvorite novi izveštaj o problemu na GitHub-u (po mogućnosti na engleskom) i uključite sledeći tekst u svoju poruku (NE prevodite taj tekst):",
+ "crash_page_switch_instance": "pokušali da koristite drugu instancu",
+ "generic_count_weeks_0": "{{count}} nedelja",
+ "generic_count_weeks_1": "{{count}} nedelje",
+ "generic_count_weeks_2": "{{count}} nedelja",
+ "videoinfo_watch_on_youTube": "Gledaj na YouTube-u",
+ "Music in this video": "Muzika u ovom video snimku",
+ "generic_button_rss": "RSS",
+ "preferences_quality_dash_option_4320p": "4320p",
+ "generic_count_hours_0": "{{count}} sat",
+ "generic_count_hours_1": "{{count}} sata",
+ "generic_count_hours_2": "{{count}} sati",
+ "French (auto-generated)": "Francuski (automatski generisano)",
+ "crash_page_read_the_faq": "pročitali Često Postavljana Pitanja (ČPP)",
+ "user_created_playlists": "Napravljenih plejlista: `x`",
+ "channel_tab_channels_label": "Kanali",
+ "search_filters_type_option_all": "Bilo koja vrsta",
+ "Russian (auto-generated)": "Ruski (automatski generisano)",
+ "preferences_quality_dash_option_480p": "480p",
+ "comments_view_x_replies_0": "Pogledaj {{count}} odgovor",
+ "comments_view_x_replies_1": "Pogledaj {{count}} odgovora",
+ "comments_view_x_replies_2": "Pogledaj {{count}} odgovora",
+ "Portuguese (Brazil)": "Portugalski (Brazil)",
+ "search_filters_features_option_vr180": "VR180",
+ "error_video_not_in_playlist": "Traženi video snimak ne postoji na ovoj plejlisti. Kliknite ovde za početnu stranicu plejliste.",
+ "Dutch (auto-generated)": "Holandski (automatski generisano)",
+ "generic_count_days_0": "{{count}} dan",
+ "generic_count_days_1": "{{count}} dana",
+ "generic_count_days_2": "{{count}} dana",
+ "Vietnamese (auto-generated)": "Vijetnamski (automatski generisano)",
+ "search_filters_duration_option_none": "Bilo koje trajanje",
+ "preferences_quality_dash_option_240p": "240p",
+ "Chinese": "Kineski",
+ "generic_button_delete": "Izbriši",
+ "Import YouTube playlist (.csv)": "Uvezi YouTube plejlistu (.csv)",
+ "Standard YouTube license": "Standardna YouTube licenca",
+ "search_filters_duration_option_medium": "Srednje (4 - 20 minuta)",
+ "generic_count_seconds_0": "{{count}} sekunda",
+ "generic_count_seconds_1": "{{count}} sekunde",
+ "generic_count_seconds_2": "{{count}} sekundi",
+ "search_filters_date_label": "Datum otpremanja",
+ "crash_page_you_found_a_bug": "Izgleda da ste pronašli grešku u Invidious-u!",
+ "generic_views_count_0": "{{count}} pregled",
+ "generic_views_count_1": "{{count}} pregleda",
+ "generic_views_count_2": "{{count}} pregleda"
}
diff --git a/locales/sr_Cyrl.json b/locales/sr_Cyrl.json
index 218f31c9..bf439b28 100644
--- a/locales/sr_Cyrl.json
+++ b/locales/sr_Cyrl.json
@@ -1,166 +1,166 @@
{
"LIVE": "УЖИВО",
- "Shared `x` ago": "Подељено пре `x`",
+ "Shared `x` ago": "Дељено пре `x`",
"Unsubscribe": "Прекини праћење",
- "Subscribe": "Прати",
+ "Subscribe": "Запрати",
"View channel on YouTube": "Погледај канал на YouTube-у",
- "View playlist on YouTube": "Погледај списак извођења на YоуТубе-у",
+ "View playlist on YouTube": "Погледај плејлисту на YouTube-у",
"newest": "најновије",
"oldest": "најстарије",
"popular": "популарно",
"last": "последње",
- "Next page": "Следећа страна",
- "Previous page": "Претходна страна",
- "Clear watch history?": "Избрисати повест прегледања?",
+ "Next page": "Следећа страница",
+ "Previous page": "Претходна страница",
+ "Clear watch history?": "Очистити историју гледања?",
"New password": "Нова лозинка",
- "New passwords must match": "Нове лозинке морају бити истоветне",
- "Authorize token?": "Овласти жетон?",
- "Authorize token for `x`?": "Овласти жетон за `x`?",
+ "New passwords must match": "Нове лозинке морају да се подударају",
+ "Authorize token?": "Ауторизовати токен?",
+ "Authorize token for `x`?": "Ауторизовати токен за `x`?",
"Yes": "Да",
"No": "Не",
"Import and Export Data": "Увоз и извоз података",
"Import": "Увези",
- "Import Invidious data": "Увези податке са Individious-а",
- "Import YouTube subscriptions": "Увези праћења са YouTube-а",
- "Import FreeTube subscriptions (.db)": "Увези праћења са FreeTube-а (.db)",
- "Import NewPipe subscriptions (.json)": "Увези праћења са NewPipe-а (.json)",
- "Import NewPipe data (.zip)": "Увези податке са NewPipe-a (.zip)",
+ "Import Invidious data": "Увези Invidious JSON податке",
+ "Import YouTube subscriptions": "Увези YouTube/OPML праћења",
+ "Import FreeTube subscriptions (.db)": "Увези FreeTube праћења (.db)",
+ "Import NewPipe subscriptions (.json)": "Увези NewPipe праћења (.json)",
+ "Import NewPipe data (.zip)": "Увези NewPipe податке (.zip)",
"Export": "Извези",
- "Export subscriptions as OPML": "Извези праћења као ОПМЛ датотеку",
- "Export subscriptions as OPML (for NewPipe & FreeTube)": "Извези праћења као ОПМЛ датотеку (за NewPipe и FreeTube)",
- "Export data as JSON": "Извези податке као JSON датотеку",
- "Delete account?": "Избришите налог?",
+ "Export subscriptions as OPML": "Извези праћења као OPML",
+ "Export subscriptions as OPML (for NewPipe & FreeTube)": "Извези праћења као OPML (за NewPipe и FreeTube)",
+ "Export data as JSON": "Извези Invidious податке као JSON",
+ "Delete account?": "Избрисати налог?",
"History": "Историја",
- "An alternative front-end to YouTube": "Заменски кориснички слој за YouTube",
- "JavaScript license information": "Извештај о JavaScript одобрењу",
+ "An alternative front-end to YouTube": "Алтернативни фронт-енд за YouTube",
+ "JavaScript license information": "Информације о JavaScript лиценци",
"source": "извор",
- "Log in": "Пријави се",
- "Log in/register": "Пријави се/Отворите налог",
- "User ID": "Кориснички ИД",
+ "Log in": "Пријава",
+ "Log in/register": "Пријава/регистрација",
+ "User ID": "ID корисника",
"Password": "Лозинка",
"Time (h:mm:ss):": "Време (ч:мм:сс):",
- "Text CAPTCHA": "Знаковни ЦАПТЧА",
- "Image CAPTCHA": "Сликовни CAPTCHA",
+ "Text CAPTCHA": "Текст CAPTCHA",
+ "Image CAPTCHA": "Слика CAPTCHA",
"Sign In": "Пријава",
- "Register": "Отвори налог",
- "E-mail": "Е-пошта",
+ "Register": "Регистрација",
+ "E-mail": "Имејл",
"Preferences": "Подешавања",
- "preferences_category_player": "Подешавања репродуктора",
+ "preferences_category_player": "Подешавања плејера",
"preferences_video_loop_label": "Увек понављај: ",
- "preferences_autoplay_label": "Самопуштање: ",
- "preferences_continue_label": "Увек подразумевано пуштај следеће: ",
- "preferences_continue_autoplay_label": "Самопуштање следећег видео записа: ",
- "preferences_listen_label": "Увек подразумевано укључен само звук: ",
- "preferences_local_label": "Приказ видео записа преко посредника: ",
+ "preferences_autoplay_label": "Аутоматски пусти: ",
+ "preferences_continue_label": "Подразумевано пусти следеће: ",
+ "preferences_continue_autoplay_label": "Аутоматски пусти следећи видео снимак: ",
+ "preferences_listen_label": "Подразумевано укључи само звук: ",
+ "preferences_local_label": "Прокси видео снимци: ",
"preferences_speed_label": "Подразумевана брзина: ",
- "preferences_quality_label": "Преферирани видео квалитет: ",
- "preferences_volume_label": "Јачина звука: ",
+ "preferences_quality_label": "Преферирани квалитет видео снимка: ",
+ "preferences_volume_label": "Јачина звука плејера: ",
"preferences_comments_label": "Подразумевани коментари: ",
"youtube": "YouTube",
"reddit": "Reddit",
- "preferences_captions_label": "Подразумевани титл: ",
- "Fallback captions: ": "Титл у случају да главни није доступан: ",
- "preferences_related_videos_label": "Прикажи сличне видео клипове: ",
- "preferences_annotations_label": "Прикажи напомене подразумевано: ",
- "preferences_category_visual": "Визуелне преференце",
+ "preferences_captions_label": "Подразумевани титлови: ",
+ "Fallback captions: ": "Резервни титлови: ",
+ "preferences_related_videos_label": "Прикажи повезане видео снимке: ",
+ "preferences_annotations_label": "Подразумевано прикажи напомене: ",
+ "preferences_category_visual": "Визуелна подешавања",
"preferences_player_style_label": "Стил плејера: ",
"Dark mode: ": "Тамни режим: ",
- "preferences_dark_mode_label": "Изглед/Тема: ",
- "dark": "тамно",
- "light": "светло",
+ "preferences_dark_mode_label": "Тема: ",
+ "dark": "тамна",
+ "light": "светла",
"preferences_thin_mode_label": "Компактни режим: ",
"preferences_category_subscription": "Подешавања праћења",
"preferences_annotations_subscribed_label": "Подразумевано приказати напомене за канале које пратите? ",
- "Redirect homepage to feed: ": "Пребаци са почетне странице на доводну листу: ",
- "preferences_max_results_label": "Број видео клипова приказаних у доводној листи: ",
- "preferences_sort_label": "Сортирај видео клипове по: ",
+ "Redirect homepage to feed: ": "Преусмери почетну страницу на фид: ",
+ "preferences_max_results_label": "Број видео снимака приказаних у фиду: ",
+ "preferences_sort_label": "Сортирај видео снимке по: ",
"published": "објављено",
"published - reverse": "објављено - обрнуто",
- "alphabetically": "по алфабету",
- "alphabetically - reverse": "по алфабету - обрнуто",
+ "alphabetically": "абецедно",
+ "alphabetically - reverse": "абецедно - обрнуто",
"channel name": "име канала",
"channel name - reverse": "име канала - обрнуто",
- "Only show latest video from channel: ": "Приказуј последње видео клипове само са канала: ",
- "Only show latest unwatched video from channel: ": "Прикажи само последње видео клипове који нису погледани са канала: ",
- "preferences_unseen_only_label": "Прикажи само видео клипове који нису погледани: ",
- "preferences_notifications_only_label": "Прикажи само обавештења (ако их уопште има): ",
- "Enable web notifications": "Омогући обавештења у веб претраживачу",
- "`x` uploaded a video": "`x` је отпремио/ла видео клип",
- "`x` is live": "`x` преноси уживо",
+ "Only show latest video from channel: ": "Прикажи само најновији видео снимак са канала: ",
+ "Only show latest unwatched video from channel: ": "Прикажи само најновији неодгледани видео снимак са канала: ",
+ "preferences_unseen_only_label": "Прикажи само недогледано: ",
+ "preferences_notifications_only_label": "Прикажи само обавештења (ако их има): ",
+ "Enable web notifications": "Омогући веб обавештења",
+ "`x` uploaded a video": "`x` је отпремио/ла видео снимак",
+ "`x` is live": "`x` је уживо",
"preferences_category_data": "Подешавања података",
- "Clear watch history": "Обриши историју гледања",
+ "Clear watch history": "Очисти историју гледања",
"Import/export data": "Увези/Извези податке",
"Change password": "Промени лозинку",
- "Manage subscriptions": "Управљај записима",
- "Manage tokens": "Управљај жетонима",
+ "Manage subscriptions": "Управљај праћењима",
+ "Manage tokens": "Управљај токенима",
"Watch history": "Историја гледања",
- "Delete account": "Обриши налог",
- "preferences_category_admin": "Администраторска подешавања",
+ "Delete account": "Избриши налог",
+ "preferences_category_admin": "Подешавања администратора",
"preferences_default_home_label": "Подразумевана почетна страница: ",
- "preferences_feed_menu_label": "Доводна страница: ",
+ "preferences_feed_menu_label": "Фид мени: ",
"CAPTCHA enabled: ": "CAPTCHA омогућена: ",
"Login enabled: ": "Пријава омогућена: ",
"Registration enabled: ": "Регистрација омогућена: ",
"Save preferences": "Сачувај подешавања",
"Subscription manager": "Управљање праћењима",
- "Token manager": "Управљање жетонима",
- "Token": "Жетон",
- "Import/export": "Увези/Извези",
- "unsubscribe": "прекини са праћењем",
+ "Token manager": "Управљање токенима",
+ "Token": "Токен",
+ "Import/export": "Увоз/извоз",
+ "unsubscribe": "прекини праћење",
"revoke": "опозови",
"Subscriptions": "Праћења",
"search": "претрага",
"Log out": "Одјава",
- "Source available here.": "Изворна кода је овде доступна.",
- "View JavaScript license information.": "Погледај информације лиценце везане за JavaScript.",
- "View privacy policy.": "Погледај извештај о приватности.",
+ "Source available here.": "Изворни кôд је доступан овде.",
+ "View JavaScript license information.": "Погледај информације о JavaScript лиценци.",
+ "View privacy policy.": "Погледај политику приватности.",
"Trending": "У тренду",
"Public": "Јавно",
- "Unlisted": "Ненаведено",
+ "Unlisted": "По позиву",
"Private": "Приватно",
- "View all playlists": "Прегледај све плеј листе",
+ "View all playlists": "Погледај све плејлисте",
"Updated `x` ago": "Ажурирано пре `x`",
- "Delete playlist `x`?": "Обриши плеј листу `x`?",
- "Delete playlist": "Обриши плеј листу",
- "Create playlist": "Направи плеј листу",
+ "Delete playlist `x`?": "Избрисати плејлисту `x`?",
+ "Delete playlist": "Избриши плејлисту",
+ "Create playlist": "Направи плејлисту",
"Title": "Наслов",
- "Playlist privacy": "Подешавања приватности плеј листе",
- "Editing playlist `x`": "Измена плеј листе `x`",
+ "Playlist privacy": "Приватност плејлисте",
+ "Editing playlist `x`": "Измењивање плејлисте `x`",
"Watch on YouTube": "Гледај на YouTube-у",
"Hide annotations": "Сакриј напомене",
"Show annotations": "Прикажи напомене",
"Genre: ": "Жанр: ",
"License: ": "Лиценца: ",
"Engagement: ": "Ангажовање: ",
- "Whitelisted regions: ": "Дозвољене области: ",
- "Blacklisted regions: ": "Забрањене области: ",
- "Premieres in `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 YouTube comments": "Прикажи YouTube коментаре",
- "View more comments on Reddit": "Прикажи више коментара на Reddit-у",
- "View Reddit comments": "Прикажи Reddit коментаре",
+ "Whitelisted regions: ": "Доступни региони: ",
+ "Blacklisted regions: ": "Недоступни региони: ",
+ "Premieres in `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 YouTube comments": "Погледај YouTube коментаре",
+ "View more comments on Reddit": "Погледај више коментара на Reddit-у",
+ "View Reddit comments": "Погледај Reddit коментаре",
"Hide replies": "Сакриј одговоре",
"Show replies": "Прикажи одговоре",
"Incorrect password": "Нетачна лозинка",
"Current version: ": "Тренутна верзија: ",
- "Wilson score: ": "Wилсонова оцена: ",
+ "Wilson score: ": "Вилсонова оцена: ",
"Burmese": "Бурмански",
- "preferences_quality_dash_label": "Преферирани квалитет DASH видео формата: ",
- "Erroneous token": "Погрешан жетон",
+ "preferences_quality_dash_label": "Преферирани DASH квалитет видео снимка: ",
+ "Erroneous token": "Погрешан токен",
"CAPTCHA is a required field": "CAPTCHA је обавезно поље",
- "No such user": "Непостојећи корисник",
+ "No such user": "Не постоји корисник",
"Chinese (Traditional)": "Кинески (Традиционални)",
- "adminprefs_modified_source_code_url_label": "УРЛ веза до складишта са Измењеном Изворном Кодом",
+ "adminprefs_modified_source_code_url_label": "URL адреса до репозиторијума измењеног изворног кода",
"Lao": "Лаоски",
"Czech": "Чешки",
- "Kannada": "Канада (Језик)",
+ "Kannada": "Канада",
"Polish": "Пољски",
- "Cebuano": "Себуано",
+ "Cebuano": "Цебуански",
"preferences_show_nick_label": "Прикажи надимке на врху: ",
- "Report statistics: ": "Извештавај о статистици: ",
+ "Report statistics: ": "Извештавај статистике: ",
"Show more": "Прикажи више",
"Wrong answer": "Погрешан одговор",
- "Hidden field \"token\" is a required field": "Сакривено \"token\" поље је обавезно",
+ "Hidden field \"token\" is a required field": "Скривено поље „токен“ је обавезно поље",
"English": "Енглески",
"Albanian": "Албански",
"Amharic": "Амхарски",
@@ -176,38 +176,38 @@
"Georgian": "Грузијски",
"Greek": "Грчки",
"Hausa": "Хауса",
- "search_filters_type_option_video": "Видео",
- "search_filters_type_option_playlist": "Плеј листа",
+ "search_filters_type_option_video": "Видео снимак",
+ "search_filters_type_option_playlist": "Плејлиста",
"search_filters_type_option_movie": "Филм",
"search_filters_duration_option_long": "Дуго (> 20 минута)",
- "search_filters_features_option_c_commons": "Creative Commons (Лиценца)",
+ "search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_live": "Уживо",
"search_filters_features_option_location": "Локација",
- "next_steps_error_message": "Након чега би требали пробати: ",
+ "next_steps_error_message": "Након тога би требало да покушате да: ",
"footer_donate_page": "Донирај",
"footer_documentation": "Документација",
- "footer_modfied_source_code": "Измењена Изворна Кода",
- "preferences_region_label": "Држава порекла садржаја: ",
+ "footer_modfied_source_code": "Измењени изворни кôд",
+ "preferences_region_label": "Држава садржаја: ",
"preferences_category_misc": "Остала подешавања",
- "User ID is a required field": "Кориснички ИД је обавезно поље",
+ "User ID is a required field": "ID корисника је обавезно поље",
"Password is a required field": "Лозинка је обавезно поље",
"Wrong username or password": "Погрешно корисничко име или лозинка",
"Password cannot be empty": "Лозинка не може бити празна",
- "Password cannot be longer than 55 characters": "Лозинка не може бити дужа од 55 карактера",
- "Invidious Private Feed for `x`": "Инвидиоус Приватни Довод за `x`",
- "Deleted or invalid channel": "Обрисан или непостојећи канал",
+ "Password cannot be longer than 55 characters": "Лозинка не може бити дужа од 55 знакова",
+ "Invidious Private Feed for `x`": "Invidious приватни фид за `x`",
+ "Deleted or invalid channel": "Избрисан или неважећи канал",
"This channel does not exist.": "Овај канал не постоји.",
- "Could not create mix.": "Прављење микса није успело.",
- "Empty playlist": "Празна плеј листа",
- "Not a playlist.": "Није плеј листа.",
- "Playlist does not exist.": "Непостојећа плеј листа.",
- "Could not pull trending pages.": "Учитавање 'У току' страница није успело.",
- "Hidden field \"challenge\" is a required field": "Сакривено \"challenge\" поље је обавезно",
+ "Could not create mix.": "Није могуће направити микс.",
+ "Empty playlist": "Празна плејлиста",
+ "Not a playlist.": "Није плејлиста.",
+ "Playlist does not exist.": "Плејлиста не постоји.",
+ "Could not pull trending pages.": "Није могуће повући странице „У тренду“.",
+ "Hidden field \"challenge\" is a required field": "Скривено поље „изазов“ је обавезно поље",
"Telugu": "Телугу",
"Turkish": "Турски",
"Urdu": "Урду",
- "Western Frisian": "Западнофрисијски",
- "Xhosa": "Коса (Језик)",
+ "Western Frisian": "Западнофризијски",
+ "Xhosa": "Коса (Кхоса)",
"Yiddish": "Јидиш",
"Hawaiian": "Хавајски",
"Hmong": "Хмонг",
@@ -217,58 +217,58 @@
"Khmer": "Кмерски",
"Kyrgyz": "Киргиски",
"Macedonian": "Македонски",
- "Maori": "Маори (Језик)",
- "Marathi": "Маратхи",
+ "Maori": "Маорски",
+ "Marathi": "Маратски",
"Nepali": "Непалски",
"Norwegian Bokmål": "Норвешки Бокмал",
- "Nyanja": "Чева",
+ "Nyanja": "Нијанџа",
"Russian": "Руски",
"Scottish Gaelic": "Шкотски Гелски",
"Shona": "Шона",
"Slovak": "Словачки",
- "Spanish (Latin America)": "Шпански (Јужна Америка)",
- "Sundanese": "Сундски",
- "Swahili": "Свахили",
+ "Spanish (Latin America)": "Шпански (Латинска Америка)",
+ "Sundanese": "Сундански",
+ "Swahili": "Сували",
"Tajik": "Таџички",
"Search": "Претрага",
- "Rating: ": "Ocena/e: ",
- "Default": "Подразумеван/о",
+ "Rating: ": "Оцена: ",
+ "Default": "Подразумевано",
"News": "Вести",
"Download": "Преузми",
"(edited)": "(измењено)",
- "`x` marked it with a ❤": "`x` је означио/ла ово са ❤",
- "Audio mode": "Аудио мод",
- "channel_tab_videos_label": "Видео клипови",
+ "`x` marked it with a ❤": "`x` је означио/ла са ❤",
+ "Audio mode": "Режим аудио снимка",
+ "channel_tab_videos_label": "Видео снимци",
"search_filters_sort_option_views": "Број прегледа",
"search_filters_features_label": "Карактеристике",
"search_filters_date_option_today": "Данас",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"preferences_locale_label": "Језик: ",
- "Persian": "Перзијски",
+ "Persian": "Персијски",
"View `x` comments": {
- "": "Прикажи `x` коментара",
- "([^.,0-9]|^)1([^.,0-9]|$)": "Прикажи `x` коментар"
+ "": "Погледај `x` коментаре",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Погледај `x` коментар"
},
"search_filters_type_option_channel": "Канал",
"Haitian Creole": "Хаићански Креолски",
"Armenian": "Јерменски",
- "next_steps_error_message_go_to_youtube": "Иди на YouTube",
- "Indonesian": "Индонежански",
- "preferences_vr_mode_label": "Интерактивни видео клипови у 360 степени: ",
+ "next_steps_error_message_go_to_youtube": "Одете на YouTube",
+ "Indonesian": "Индонезијски",
+ "preferences_vr_mode_label": "Интерактивни видео снимци од 360 степени (захтева WebGL): ",
"Switch Invidious Instance": "Промени Invidious инстанцу",
"Portuguese": "Португалски",
- "search_filters_date_option_week": "Ове седмице",
+ "search_filters_date_option_week": "Ове недеље",
"search_filters_type_option_show": "Емисија",
- "Fallback comments: ": "Коментари у случају отказивања: ",
- "search_filters_features_option_hdr": "Видео Високе Резолуције",
- "About": "О програму",
+ "Fallback comments: ": "Резервни коментари: ",
+ "search_filters_features_option_hdr": "HDR",
+ "About": "О сајту",
"Kazakh": "Казашки",
- "Shared `x`": "Подељено `x`",
- "Playlists": "Плеј листе",
+ "Shared `x`": "Дељено `x`",
+ "Playlists": "Плејлисте",
"Yoruba": "Јоруба",
"Erroneous challenge": "Погрешан изазов",
"Danish": "Дански",
- "Could not get channel info.": "Узимање података о каналу није успело.",
+ "Could not get channel info.": "Није могуће прикупити информације о каналу.",
"search_filters_features_option_hd": "HD",
"Slovenian": "Словеначки",
"Load more": "Учитај више",
@@ -276,53 +276,53 @@
"Luxembourgish": "Луксембуршки",
"Mongolian": "Монголски",
"Latvian": "Летонски",
- "channel:`x`": "kanal:`x`",
+ "channel:`x`": "канал:`x`",
"Southern Sotho": "Јужни Сото",
"Popular": "Популарно",
"Gujarati": "Гуџарати",
"search_filters_date_option_year": "Ове године",
"Irish": "Ирски",
- "YouTube comment permalink": "YouTube коментар трајна веза",
+ "YouTube comment permalink": "Трајни линк YouTube коментара",
"Malagasy": "Малгашки",
- "Token is expired, please try again": "Жетон је истекао, молимо вас да покушате поново",
- "search_filters_duration_option_short": "Кратко (< 4 минуте)",
+ "Token is expired, please try again": "Токен је истекао, покушајте поново",
+ "search_filters_duration_option_short": "Кратко (< 4 минута)",
"Samoan": "Самоански",
"Tamil": "Тамилски",
"Ukrainian": "Украјински",
- "permalink": "трајна веза",
+ "permalink": "трајни линк",
"Pashto": "Паштунски",
"channel_tab_community_label": "Заједница",
"Sindhi": "Синди",
- "Could not fetch comments": "Узимање коментара није успело",
- "Bangla": "Бангла/Бенгалски",
+ "Could not fetch comments": "Није могуће прикупити коментаре",
+ "Bangla": "Бенгалски",
"Uzbek": "Узбечки",
"Lithuanian": "Литвански",
"Icelandic": "Исландски",
"Thai": "Тајски",
- "search_filters_date_option_month": "Овај месец",
- "search_filters_type_label": "Тип",
+ "search_filters_date_option_month": "Овог месеца",
+ "search_filters_type_label": "Врста",
"search_filters_date_option_hour": "Последњи сат",
"Spanish": "Шпански",
"search_filters_sort_option_date": "Датум отпремања",
- "View as playlist": "Погледај као плеј листу",
+ "View as playlist": "Погледај као плејлисту",
"search_filters_sort_option_relevance": "Релевантност",
"Estonian": "Естонски",
- "Sinhala": "Синхалешки",
+ "Sinhala": "Синхалски",
"Corsican": "Корзикански",
- "Filipino": "Филипино",
- "Gaming": "Игрице",
+ "Filipino": "Филипински",
+ "Gaming": "Видео игре",
"Movies": "Филмови",
- "search_filters_sort_option_rating": "Оцене",
- "Top enabled: ": "Врх омогућен: ",
- "Released under the AGPLv3 on Github.": "Избачено под лиценцом AGPLv3 на GitHub-у.",
+ "search_filters_sort_option_rating": "Оцена",
+ "Top enabled: ": "Топ омогућено: ",
+ "Released under the AGPLv3 on Github.": "Објављено под лиценцом AGPLv3 на GitHub-у.",
"Afrikaans": "Африканс",
- "preferences_automatic_instance_redirect_label": "Аутоматско пребацивање на другу инстанцу у случају отказивања (пречи ће назад на редирецт.инвидиоус.ио): ",
- "Please log in": "Молимо вас да се пријавите",
+ "preferences_automatic_instance_redirect_label": "Аутоматско преусмеравање инстанце (повратак на redirect.invidious.io): ",
+ "Please log in": "Молимо, пријавите се",
"English (auto-generated)": "Енглески (аутоматски генерисано)",
"Hindi": "Хинди",
- "Italian": "Талијански",
- "Malayalam": "Малајалам",
- "Punjabi": "Пунџаби",
+ "Italian": "Италијански",
+ "Malayalam": "Малајаламски",
+ "Punjabi": "Панџапски",
"Somali": "Сомалијски",
"Vietnamese": "Вијетнамски",
"Welsh": "Велшки",
@@ -330,25 +330,25 @@
"Maltese": "Малтешки",
"Swedish": "Шведски",
"Music": "Музика",
- "Download as: ": "Преузми као: ",
+ "Download as: ": "Преузети као: ",
"search_filters_duration_label": "Трајање",
- "search_filters_sort_label": "Поредај према",
- "search_filters_features_option_subtitles": "Титл/Превод",
- "preferences_extend_desc_label": "Аутоматски прикажи цео опис видеа: ",
+ "search_filters_sort_label": "Сортирање по",
+ "search_filters_features_option_subtitles": "Титлови/Скривени титлови",
+ "preferences_extend_desc_label": "Аутоматски прошири опис видео снимка: ",
"Show less": "Прикажи мање",
"Family friendly? ": "Погодно за породицу? ",
- "Premieres `x`": "Премерe у `x`",
+ "Premieres `x`": "Премијера `x`",
"Bosnian": "Босански",
"Catalan": "Каталонски",
"Japanese": "Јапански",
"Latin": "Латински",
- "next_steps_error_message_refresh": "Освежи страницу",
- "footer_original_source_code": "Оригинална Изворна Кода",
+ "next_steps_error_message_refresh": "Освежите",
+ "footer_original_source_code": "Оригинални изворни кôд",
"Romanian": "Румунски",
"Serbian": "Српски",
- "Top": "Врх",
- "Video mode": "Видео мод",
- "footer_source_code": "Изворна Кода",
+ "Top": "Топ",
+ "Video mode": "Режим видео снимка",
+ "footer_source_code": "Изворни кôд",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_four_k": "4K",
"Erroneous CAPTCHA": "Погрешна CAPTCHA",
@@ -360,5 +360,148 @@
"Korean": "Корејски",
"Kurdish": "Курдски",
"Malay": "Малајски",
- "search_filters_title": "Филтер"
+ "search_filters_title": "Филтери",
+ "Korean (auto-generated)": "Корејски (аутоматски генерисано)",
+ "search_filters_features_option_three_sixty": "360°",
+ "preferences_quality_dash_option_worst": "Најгоре",
+ "channel_tab_podcasts_label": "Подкасти",
+ "preferences_save_player_pos_label": "Сачувај позицију репродукције: ",
+ "Spanish (Mexico)": "Шпански (Мексико)",
+ "generic_subscriptions_count_0": "{{count}} праћење",
+ "generic_subscriptions_count_1": "{{count}} праћења",
+ "generic_subscriptions_count_2": "{{count}} праћења",
+ "search_filters_apply_button": "Примени изабране филтере",
+ "Download is disabled": "Преузимање је онемогућено",
+ "comments_points_count_0": "{{count}} поен",
+ "comments_points_count_1": "{{count}} поена",
+ "comments_points_count_2": "{{count}} поена",
+ "preferences_quality_dash_option_2160p": "2160p",
+ "German (auto-generated)": "Немачки (аутоматски генерисано)",
+ "Japanese (auto-generated)": "Јапански (аутоматски генерисано)",
+ "preferences_quality_option_medium": "Средње",
+ "search_message_change_filters_or_query": "Покушајте да проширите упит за претрагу и/или промените филтере.",
+ "crash_page_before_reporting": "Пре него што пријавите грешку, уверите се да сте:",
+ "preferences_quality_dash_option_best": "Најбоље",
+ "Channel Sponsor": "Спонзор канала",
+ "generic_videos_count_0": "{{count}} видео снимак",
+ "generic_videos_count_1": "{{count}} видео снимка",
+ "generic_videos_count_2": "{{count}} видео снимака",
+ "videoinfo_started_streaming_x_ago": "Започето стримовање пре `x`",
+ "videoinfo_youTube_embed_link": "Уграђено",
+ "channel_tab_streams_label": "Стримови уживо",
+ "playlist_button_add_items": "Додај видео снимке",
+ "generic_count_minutes_0": "{{count}} минут",
+ "generic_count_minutes_1": "{{count}} минута",
+ "generic_count_minutes_2": "{{count}} минута",
+ "preferences_quality_dash_option_720p": "720p",
+ "preferences_watch_history_label": "Омогући историју гледања: ",
+ "user_saved_playlists": "Сачуваних плејлиста: `x`",
+ "Spanish (Spain)": "Шпански (Шпанија)",
+ "invidious": "Invidious",
+ "crash_page_refresh": "покушали да освежите страницу",
+ "Chinese (Hong Kong)": "Кинески (Хонг Конг)",
+ "Artist: ": "Извођач: ",
+ "generic_count_months_0": "{{count}} месец",
+ "generic_count_months_1": "{{count}} месеца",
+ "generic_count_months_2": "{{count}} месеци",
+ "search_message_use_another_instance": " Такође, можете претраживати на другој инстанци.",
+ "generic_subscribers_count_0": "{{count}} пратилац",
+ "generic_subscribers_count_1": "{{count}} пратиоца",
+ "generic_subscribers_count_2": "{{count}} пратилаца",
+ "download_subtitles": "Титлови - `x` (.vtt)",
+ "generic_button_save": "Сачувај",
+ "crash_page_search_issue": "претражили постојеће извештаје о проблемима на GitHub-у",
+ "generic_button_cancel": "Откажи",
+ "none": "ниједно",
+ "English (United States)": "Енглески (Сједињене Америчке Државе)",
+ "subscriptions_unseen_notifs_count_0": "{{count}} невиђено обавештење",
+ "subscriptions_unseen_notifs_count_1": "{{count}} невиђена обавештења",
+ "subscriptions_unseen_notifs_count_2": "{{count}} невиђених обавештења",
+ "Album: ": "Албум: ",
+ "preferences_quality_option_dash": "DASH (адаптивни квалитет)",
+ "preferences_quality_dash_option_1080p": "1080p",
+ "Video unavailable": "Видео снимак недоступан",
+ "tokens_count_0": "{{count}} токен",
+ "tokens_count_1": "{{count}} токена",
+ "tokens_count_2": "{{count}} токена",
+ "Chinese (China)": "Кинески (Кина)",
+ "Italian (auto-generated)": "Италијански (аутоматски генерисано)",
+ "channel_tab_shorts_label": "Shorts",
+ "preferences_quality_dash_option_1440p": "1440p",
+ "preferences_quality_dash_option_360p": "360p",
+ "search_message_no_results": "Нису пронађени резултати.",
+ "channel_tab_releases_label": "Издања",
+ "preferences_quality_dash_option_144p": "144p",
+ "Interlingue": "Интерлингва",
+ "Song: ": "Песма: ",
+ "generic_channels_count_0": "{{count}} канал",
+ "generic_channels_count_1": "{{count}} канала",
+ "generic_channels_count_2": "{{count}} канала",
+ "Chinese (Taiwan)": "Кинески (Тајван)",
+ "Turkish (auto-generated)": "Турски (аутоматски генерисано)",
+ "Indonesian (auto-generated)": "Индонезијски (аутоматски генерисано)",
+ "Portuguese (auto-generated)": "Португалски (аутоматски генерисано)",
+ "generic_count_years_0": "{{count}} година",
+ "generic_count_years_1": "{{count}} године",
+ "generic_count_years_2": "{{count}} година",
+ "videoinfo_invidious_embed_link": "Уграђени линк",
+ "Popular enabled: ": "Популарно омогућено: ",
+ "Spanish (auto-generated)": "Шпански (аутоматски генерисано)",
+ "preferences_quality_option_small": "Мало",
+ "English (United Kingdom)": "Енглески (Уједињено Краљевство)",
+ "channel_tab_playlists_label": "Плејлисте",
+ "generic_button_edit": "Измени",
+ "generic_playlists_count_0": "{{count}} плејлиста",
+ "generic_playlists_count_1": "{{count}} плејлисте",
+ "generic_playlists_count_2": "{{count}} плејлиста",
+ "preferences_quality_option_hd720": "HD720",
+ "search_filters_features_option_purchased": "Купљено",
+ "search_filters_date_option_none": "Било који датум",
+ "preferences_quality_dash_option_auto": "Аутоматски",
+ "Cantonese (Hong Kong)": "Кантонски (Хонг Конг)",
+ "crash_page_report_issue": "Ако ништа од горенаведеног није помогло, отворите нови извештај о проблему на GitHub-у (по могућности на енглеском) и укључите следећи текст у своју поруку (НЕ преводите тај текст):",
+ "crash_page_switch_instance": "покушали да користите другу инстанцу",
+ "generic_count_weeks_0": "{{count}} недеља",
+ "generic_count_weeks_1": "{{count}} недеље",
+ "generic_count_weeks_2": "{{count}} недеља",
+ "videoinfo_watch_on_youTube": "Гледај на YouTube-у",
+ "Music in this video": "Музика у овом видео снимку",
+ "generic_button_rss": "RSS",
+ "preferences_quality_dash_option_4320p": "4320p",
+ "generic_count_hours_0": "{{count}} сат",
+ "generic_count_hours_1": "{{count}} сата",
+ "generic_count_hours_2": "{{count}} сати",
+ "French (auto-generated)": "Француски (аутоматски генерисано)",
+ "crash_page_read_the_faq": "прочитали Често Постављана Питања (ЧПП)",
+ "user_created_playlists": "Направљених плејлиста: `x`",
+ "channel_tab_channels_label": "Канали",
+ "search_filters_type_option_all": "Било која врста",
+ "Russian (auto-generated)": "Руски (аутоматски генерисано)",
+ "preferences_quality_dash_option_480p": "480p",
+ "comments_view_x_replies_0": "Погледај {{count}} одговор",
+ "comments_view_x_replies_1": "Погледај {{count}} одговора",
+ "comments_view_x_replies_2": "Погледај {{count}} одговора",
+ "Portuguese (Brazil)": "Португалски (Бразил)",
+ "search_filters_features_option_vr180": "VR180",
+ "error_video_not_in_playlist": "Тражени видео снимак не постоји на овој плејлисти. Кликните овде за почетну страницу плејлисте.",
+ "Dutch (auto-generated)": "Холандски (аутоматски генерисано)",
+ "generic_count_days_0": "{{count}} дан",
+ "generic_count_days_1": "{{count}} дана",
+ "generic_count_days_2": "{{count}} дана",
+ "Vietnamese (auto-generated)": "Вијетнамски (аутоматски генерисано)",
+ "search_filters_duration_option_none": "Било које трајање",
+ "preferences_quality_dash_option_240p": "240p",
+ "Chinese": "Кинески",
+ "generic_button_delete": "Избриши",
+ "Import YouTube playlist (.csv)": "Увези YouTube плејлисту (.csv)",
+ "Standard YouTube license": "Стандардна YouTube лиценца",
+ "search_filters_duration_option_medium": "Средње (4 - 20 минута)",
+ "generic_count_seconds_0": "{{count}} секунда",
+ "generic_count_seconds_1": "{{count}} секунде",
+ "generic_count_seconds_2": "{{count}} секунди",
+ "search_filters_date_label": "Датум отпремања",
+ "crash_page_you_found_a_bug": "Изгледа да сте пронашли грешку у Invidious-у!",
+ "generic_views_count_0": "{{count}} преглед",
+ "generic_views_count_1": "{{count}} прегледа",
+ "generic_views_count_2": "{{count}} прегледа"
}
diff --git a/locales/tr.json b/locales/tr.json
index 7f3f2de8..0575a4dd 100644
--- a/locales/tr.json
+++ b/locales/tr.json
@@ -484,5 +484,7 @@
"generic_button_rss": "RSS",
"channel_tab_releases_label": "Yayınlar",
"playlist_button_add_items": "Video ekle",
- "channel_tab_podcasts_label": "Podcast'ler"
+ "channel_tab_podcasts_label": "Podcast'ler",
+ "generic_channels_count": "{{count}} kanal",
+ "generic_channels_count_plural": "{{count}} kanal"
}
diff --git a/locales/uk.json b/locales/uk.json
index 4d8f06a5..c26618fe 100644
--- a/locales/uk.json
+++ b/locales/uk.json
@@ -500,5 +500,8 @@
"channel_tab_releases_label": "Випуски",
"generic_button_delete": "Видалити",
"generic_button_edit": "Змінити",
- "generic_button_save": "Зберегти"
+ "generic_button_save": "Зберегти",
+ "generic_channels_count_0": "{{count}} канал",
+ "generic_channels_count_1": "{{count}} канали",
+ "generic_channels_count_2": "{{count}} каналів"
}
diff --git a/locales/zh-CN.json b/locales/zh-CN.json
index 62f45a29..5e5d0ebb 100644
--- a/locales/zh-CN.json
+++ b/locales/zh-CN.json
@@ -468,5 +468,6 @@
"generic_button_edit": "编辑",
"generic_button_save": "保存",
"generic_button_rss": "RSS",
- "channel_tab_releases_label": "公告"
+ "channel_tab_releases_label": "公告",
+ "generic_channels_count_0": "{{count}} 个频道"
}
diff --git a/locales/zh-TW.json b/locales/zh-TW.json
index da81922b..de659c92 100644
--- a/locales/zh-TW.json
+++ b/locales/zh-TW.json
@@ -468,5 +468,6 @@
"generic_button_delete": "刪除",
"playlist_button_add_items": "新增影片",
"channel_tab_podcasts_label": "Podcast",
- "channel_tab_releases_label": "發布"
+ "channel_tab_releases_label": "發布",
+ "generic_channels_count_0": "{{count}} 個頻道"
}
diff --git a/spec/helpers/vtt/builder_spec.cr b/spec/helpers/vtt/builder_spec.cr
new file mode 100644
index 00000000..7b543ddc
--- /dev/null
+++ b/spec/helpers/vtt/builder_spec.cr
@@ -0,0 +1,64 @@
+require "../../spec_helper.cr"
+
+MockLines = [
+ {
+ "start_time": Time::Span.new(seconds: 1),
+ "end_time": Time::Span.new(seconds: 2),
+ "text": "Line 1",
+ },
+
+ {
+ "start_time": Time::Span.new(seconds: 2),
+ "end_time": Time::Span.new(seconds: 3),
+ "text": "Line 2",
+ },
+]
+
+Spectator.describe "WebVTT::Builder" do
+ it "correctly builds a vtt file" do
+ result = WebVTT.build do |vtt|
+ MockLines.each do |line|
+ vtt.cue(line["start_time"], line["end_time"], line["text"])
+ end
+ end
+
+ expect(result).to eq([
+ "WEBVTT",
+ "",
+ "00:00:01.000 --> 00:00:02.000",
+ "Line 1",
+ "",
+ "00:00:02.000 --> 00:00:03.000",
+ "Line 2",
+ "",
+ "",
+ ].join('\n'))
+ end
+
+ it "correctly builds a vtt file with setting fields" do
+ setting_fields = {
+ "Kind" => "captions",
+ "Language" => "en",
+ }
+
+ result = WebVTT.build(setting_fields) do |vtt|
+ MockLines.each do |line|
+ vtt.cue(line["start_time"], line["end_time"], line["text"])
+ end
+ end
+
+ expect(result).to eq([
+ "WEBVTT",
+ "Kind: captions",
+ "Language: en",
+ "",
+ "00:00:01.000 --> 00:00:02.000",
+ "Line 1",
+ "",
+ "00:00:02.000 --> 00:00:03.000",
+ "Line 2",
+ "",
+ "",
+ ].join('\n'))
+ end
+end
diff --git a/spec/i18next_plurals_spec.cr b/spec/i18next_plurals_spec.cr
index ee9ff394..dab97710 100644
--- a/spec/i18next_plurals_spec.cr
+++ b/spec/i18next_plurals_spec.cr
@@ -15,12 +15,15 @@ FORM_TESTS = {
"ar" => I18next::Plurals::PluralForms::Special_Arabic,
"be" => I18next::Plurals::PluralForms::Dual_Slavic,
"cy" => I18next::Plurals::PluralForms::Special_Welsh,
+ "fr" => I18next::Plurals::PluralForms::Special_French_Portuguese,
"en" => I18next::Plurals::PluralForms::Single_not_one,
- "fr" => I18next::Plurals::PluralForms::Single_gt_one,
+ "es" => I18next::Plurals::PluralForms::Single_not_one,
"ga" => I18next::Plurals::PluralForms::Special_Irish,
"gd" => I18next::Plurals::PluralForms::Special_Scottish_Gaelic,
"he" => I18next::Plurals::PluralForms::Special_Hebrew,
+ "hr" => I18next::Plurals::PluralForms::Special_Hungarian_Serbian,
"is" => I18next::Plurals::PluralForms::Special_Icelandic,
+ "it" => I18next::Plurals::PluralForms::Special_Spanish_Italian,
"jv" => I18next::Plurals::PluralForms::Special_Javanese,
"kw" => I18next::Plurals::PluralForms::Special_Cornish,
"lt" => I18next::Plurals::PluralForms::Special_Lithuanian,
@@ -31,12 +34,12 @@ FORM_TESTS = {
"or" => I18next::Plurals::PluralForms::Special_Odia,
"pl" => I18next::Plurals::PluralForms::Special_Polish_Kashubian,
"pt" => I18next::Plurals::PluralForms::Single_gt_one,
- "pt-PT" => I18next::Plurals::PluralForms::Single_not_one,
- "pt-BR" => I18next::Plurals::PluralForms::Single_gt_one,
+ "pt-BR" => I18next::Plurals::PluralForms::Special_French_Portuguese,
"ro" => I18next::Plurals::PluralForms::Special_Romanian,
- "su" => I18next::Plurals::PluralForms::None,
"sk" => I18next::Plurals::PluralForms::Special_Czech_Slovak,
"sl" => I18next::Plurals::PluralForms::Special_Slovenian,
+ "su" => I18next::Plurals::PluralForms::None,
+ "sr" => I18next::Plurals::PluralForms::Special_Hungarian_Serbian,
}
SUFFIX_TESTS = {
@@ -73,10 +76,18 @@ SUFFIX_TESTS = {
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
],
- "fr" => [
- {num: 0, suffix: ""},
+ "es" => [
+ {num: 0, suffix: "_plural"},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
+ {num: 6_000_000, suffix: "_plural"},
+ ],
+ "fr" => [
+ {num: 0, suffix: "_0"},
+ {num: 1, suffix: "_0"},
+ {num: 10, suffix: "_2"},
+ {num: 4_000_000, suffix: "_1"},
+ {num: 6_260_000, suffix: "_2"},
],
"ga" => [
{num: 1, suffix: "_0"},
@@ -155,31 +166,24 @@ SUFFIX_TESTS = {
{num: 1, suffix: "_0"},
{num: 5, suffix: "_2"},
],
- "pt" => [
- {num: 0, suffix: ""},
- {num: 1, suffix: ""},
- {num: 10, suffix: "_plural"},
+ "pt-BR" => [
+ {num: 0, suffix: "_0"},
+ {num: 1, suffix: "_0"},
+ {num: 10, suffix: "_2"},
+ {num: 42, suffix: "_2"},
+ {num: 9_000_000, suffix: "_1"},
],
"pt-PT" => [
- {num: 0, suffix: "_plural"},
- {num: 1, suffix: ""},
- {num: 10, suffix: "_plural"},
- ],
- "pt-BR" => [
{num: 0, suffix: ""},
{num: 1, suffix: ""},
{num: 10, suffix: "_plural"},
+ {num: 9_000_000, suffix: "_plural"},
],
"ro" => [
{num: 0, suffix: "_1"},
{num: 1, suffix: "_0"},
{num: 20, suffix: "_2"},
],
- "su" => [
- {num: 0, suffix: "_0"},
- {num: 1, suffix: "_0"},
- {num: 10, suffix: "_0"},
- ],
"sk" => [
{num: 0, suffix: "_2"},
{num: 1, suffix: "_0"},
@@ -191,6 +195,18 @@ SUFFIX_TESTS = {
{num: 2, suffix: "_2"},
{num: 3, suffix: "_3"},
],
+ "su" => [
+ {num: 0, suffix: "_0"},
+ {num: 1, suffix: "_0"},
+ {num: 10, suffix: "_0"},
+ ],
+ "sr" => [
+ {num: 1, suffix: "_0"},
+ {num: 51, suffix: "_0"},
+ {num: 32, suffix: "_1"},
+ {num: 100, suffix: "_2"},
+ {num: 100_000, suffix: "_2"},
+ ],
}
Spectator.describe "i18next_Plural_Resolver" do
diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr
index 791f1641..49ffd990 100644
--- a/src/invidious/channels/community.cr
+++ b/src/invidious/channels/community.cr
@@ -24,7 +24,33 @@ def fetch_channel_community(ucid, cursor, locale, format, thin_mode)
return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode)
end
-def extract_channel_community(items, *, ucid, locale, format, thin_mode)
+def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode)
+ object = {
+ "2:string" => "community",
+ "25:embedded" => {
+ "22:string" => post_id.to_s,
+ },
+ "45:embedded" => {
+ "2:varint" => 1_i64,
+ "3:varint" => 1_i64,
+ },
+ }
+ params = object.try { |i| Protodec::Any.cast_json(i) }
+ .try { |i| Protodec::Any.from_json(i) }
+ .try { |i| Base64.urlsafe_encode(i) }
+ .try { |i| URI.encode_www_form(i) }
+
+ initial_data = YoutubeAPI.browse(ucid, params: params)
+
+ items = [] of JSON::Any
+ extract_items(initial_data) do |item|
+ items << item
+ end
+
+ return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode, is_single_post: true)
+end
+
+def extract_channel_community(items, *, ucid, locale, format, thin_mode, is_single_post : Bool = false)
if message = items[0]["messageRenderer"]?
error_message = (message["text"]["simpleText"]? ||
message["text"]["runs"]?.try &.[0]?.try &.["text"]?)
@@ -39,6 +65,9 @@ def extract_channel_community(items, *, ucid, locale, format, thin_mode)
response = JSON.build do |json|
json.object do
json.field "authorId", ucid
+ if is_single_post
+ json.field "singlePost", true
+ end
json.field "comments" do
json.array do
items.each do |post|
@@ -240,8 +269,10 @@ def extract_channel_community(items, *, ucid, locale, format, thin_mode)
end
end
end
- if cont = items.dig?(-1, "continuationItemRenderer", "continuationEndpoint", "continuationCommand", "token")
- json.field "continuation", extract_channel_community_cursor(cont.as_s)
+ if !is_single_post
+ if cont = items.dig?(-1, "continuationItemRenderer", "continuationEndpoint", "continuationCommand", "token")
+ json.field "continuation", extract_channel_community_cursor(cont.as_s)
+ end
end
end
end
diff --git a/src/invidious/comments/youtube.cr b/src/invidious/comments/youtube.cr
index 1ba1b534..185d8e43 100644
--- a/src/invidious/comments/youtube.cr
+++ b/src/invidious/comments/youtube.cr
@@ -13,6 +13,51 @@ module Invidious::Comments
client_config = YoutubeAPI::ClientConfig.new(region: region)
response = YoutubeAPI.next(continuation: ctoken, client_config: client_config)
+ return parse_youtube(id, response, format, locale, thin_mode, sort_by)
+ end
+
+ def fetch_community_post_comments(ucid, post_id)
+ object = {
+ "2:string" => "community",
+ "25:embedded" => {
+ "22:string" => post_id,
+ },
+ "45:embedded" => {
+ "2:varint" => 1_i64,
+ "3:varint" => 1_i64,
+ },
+ "53:embedded" => {
+ "4:embedded" => {
+ "6:varint" => 0_i64,
+ "27:varint" => 1_i64,
+ "29:string" => post_id,
+ "30:string" => ucid,
+ },
+ "8:string" => "comments-section",
+ },
+ }
+
+ object_parsed = object.try { |i| Protodec::Any.cast_json(i) }
+ .try { |i| Protodec::Any.from_json(i) }
+ .try { |i| Base64.urlsafe_encode(i) }
+
+ object2 = {
+ "80226972:embedded" => {
+ "2:string" => ucid,
+ "3:string" => object_parsed,
+ },
+ }
+
+ continuation = object2.try { |i| Protodec::Any.cast_json(i) }
+ .try { |i| Protodec::Any.from_json(i) }
+ .try { |i| Base64.urlsafe_encode(i) }
+ .try { |i| URI.encode_www_form(i) }
+
+ initial_data = YoutubeAPI.browse(continuation: continuation)
+ return initial_data
+ end
+
+ def parse_youtube(id, response, format, locale, thin_mode, sort_by = "top", isPost = false)
contents = nil
if on_response_received_endpoints = response["onResponseReceivedEndpoints"]?
@@ -68,7 +113,11 @@ module Invidious::Comments
json.field "commentCount", comment_count
end
- json.field "videoId", id
+ if isPost
+ json.field "postId", id
+ else
+ json.field "videoId", id
+ end
json.field "comments" do
json.array do
diff --git a/src/invidious/frontend/comments_youtube.cr b/src/invidious/frontend/comments_youtube.cr
index 41f43f04..ecc0bc1b 100644
--- a/src/invidious/frontend/comments_youtube.cr
+++ b/src/invidious/frontend/comments_youtube.cr
@@ -23,6 +23,24 @@ module Invidious::Frontend::Comments
END_HTML
+ elsif comments["authorId"]? && !comments["singlePost"]?
+ # for posts we should display a link to the post
+ replies_count_text = translate_count(locale,
+ "comments_view_x_replies",
+ child["replyCount"].as_i64 || 0,
+ NumberFormatting::Separator
+ )
+
+ replies_html = <<-END_HTML
+
+ END_HTML
end
if !thin_mode
diff --git a/src/invidious/helpers/i18next.cr b/src/invidious/helpers/i18next.cr
index e84f88fb..252af6b9 100644
--- a/src/invidious/helpers/i18next.cr
+++ b/src/invidious/helpers/i18next.cr
@@ -35,19 +35,27 @@ module I18next::Plurals
Special_Slovenian = 21
Special_Hebrew = 22
Special_Odia = 23
+
+ # Mixed v3/v4 rules in Weblate
+ # `es`, `pt` and `pt-PT` doesn't seem to have been refreshed
+ # by weblate yet, but I suspect it will happen one day.
+ # See: https://github.com/translate/translate/issues/4873
+ Special_French_Portuguese
+ Special_Hungarian_Serbian
+ Special_Spanish_Italian
end
private PLURAL_SETS = {
PluralForms::Single_gt_one => [
- "ach", "ak", "am", "arn", "br", "fil", "fr", "gun", "ln", "mfe", "mg",
- "mi", "oc", "pt", "pt-BR", "tg", "tl", "ti", "tr", "uz", "wa",
+ "ach", "ak", "am", "arn", "br", "fil", "gun", "ln", "mfe", "mg",
+ "mi", "oc", "pt", "tg", "tl", "ti", "tr", "uz", "wa",
],
PluralForms::Single_not_one => [
"af", "an", "ast", "az", "bg", "bn", "ca", "da", "de", "dev", "el", "en",
"eo", "es", "et", "eu", "fi", "fo", "fur", "fy", "gl", "gu", "ha", "hi",
- "hu", "hy", "ia", "it", "kk", "kn", "ku", "lb", "mai", "ml", "mn", "mr",
+ "hu", "hy", "ia", "kk", "kn", "ku", "lb", "mai", "ml", "mn", "mr",
"nah", "nap", "nb", "ne", "nl", "nn", "no", "nso", "pa", "pap", "pms",
- "ps", "pt-PT", "rm", "sco", "se", "si", "so", "son", "sq", "sv", "sw",
+ "ps", "rm", "sco", "se", "si", "so", "son", "sq", "sv", "sw",
"ta", "te", "tk", "ur", "yo",
],
PluralForms::None => [
@@ -55,7 +63,7 @@ module I18next::Plurals
"lo", "ms", "sah", "su", "th", "tt", "ug", "vi", "wo", "zh",
],
PluralForms::Dual_Slavic => [
- "be", "bs", "cnr", "dz", "hr", "ru", "sr", "uk",
+ "be", "bs", "cnr", "dz", "ru", "uk",
],
}
@@ -81,6 +89,12 @@ module I18next::Plurals
"ro" => PluralForms::Special_Romanian,
"sk" => PluralForms::Special_Czech_Slovak,
"sl" => PluralForms::Special_Slovenian,
+ # Mixed v3/v4 rules
+ "fr" => PluralForms::Special_French_Portuguese,
+ "hr" => PluralForms::Special_Hungarian_Serbian,
+ "it" => PluralForms::Special_Spanish_Italian,
+ "pt-BR" => PluralForms::Special_French_Portuguese,
+ "sr" => PluralForms::Special_Hungarian_Serbian,
}
# These are the v1 and v2 compatible suffixes.
@@ -150,9 +164,8 @@ module I18next::Plurals
end
def get_plural_form(locale : String) : PluralForms
- # Extract the ISO 639-1 or 639-2 code from an RFC 5646 language code,
- # except for pt-BR and pt-PT which needs to be kept as-is.
- if !locale.matches?(/^pt-(BR|PT)$/)
+ # Extract the ISO 639-1 or 639-2 code from an RFC 5646 language code
+ if !locale.matches?(/^pt-BR$/)
locale = locale.split('-')[0]
end
@@ -246,6 +259,10 @@ module I18next::Plurals
when .special_slovenian? then return special_slovenian(count)
when .special_hebrew? then return special_hebrew(count)
when .special_odia? then return special_odia(count)
+ # Mixed v3/v4 forms
+ when .special_spanish_italian? then return special_cldr_Spanish_Italian(count)
+ when .special_french_portuguese? then return special_cldr_French_Portuguese(count)
+ when .special_hungarian_serbian? then return special_cldr_Hungarian_Serbian(count)
else
# default, if nothing matched above
return 0_u8
@@ -507,5 +524,42 @@ module I18next::Plurals
def self.special_odia(count : Int) : UInt8
return (count == 1) ? 0_u8 : 1_u8
end
+
+ # -------------------
+ # "v3.5" rules
+ # -------------------
+
+ # Plural form for Spanish & Italian languages
+ #
+ # This rule is mostly compliant to CLDR v42
+ #
+ def self.special_cldr_Spanish_Italian(count : Int) : UInt8
+ return 0_u8 if (count == 1) # one
+ return 1_u8 if (count != 0 && count % 1_000_000 == 0) # many
+ return 2_u8 # other
+ end
+
+ # Plural form for French and Portuguese
+ #
+ # This rule is mostly compliant to CLDR v42
+ #
+ def self.special_cldr_French_Portuguese(count : Int) : UInt8
+ return 0_u8 if (count == 0 || count == 1) # one
+ return 1_u8 if (count % 1_000_000 == 0) # many
+ return 2_u8 # other
+ end
+
+ # Plural form for Hungarian and Serbian
+ #
+ # This rule is mostly compliant to CLDR v42
+ #
+ def self.special_cldr_Hungarian_Serbian(count : Int) : UInt8
+ n_mod_10 = count % 10
+ n_mod_100 = count % 100
+
+ return 0_u8 if (n_mod_10 == 1 && n_mod_100 != 11) # one
+ return 1_u8 if (2 <= n_mod_10 <= 4 && (n_mod_100 < 12 || 14 < n_mod_100)) # few
+ return 2_u8 # other
+ end
end
end
diff --git a/src/invidious/helpers/serialized_yt_data.cr b/src/invidious/helpers/serialized_yt_data.cr
index e0bd7279..31a3cf44 100644
--- a/src/invidious/helpers/serialized_yt_data.cr
+++ b/src/invidious/helpers/serialized_yt_data.cr
@@ -186,6 +186,7 @@ struct SearchChannel
property author_thumbnail : String
property subscriber_count : Int32
property video_count : Int32
+ property channel_handle : String?
property description_html : String
property auto_generated : Bool
property author_verified : Bool
@@ -214,6 +215,7 @@ struct SearchChannel
json.field "autoGenerated", self.auto_generated
json.field "subCount", self.subscriber_count
json.field "videoCount", self.video_count
+ json.field "channelHandle", self.channel_handle
json.field "description", html_to_content(self.description_html)
json.field "descriptionHtml", self.description_html
diff --git a/src/invidious/helpers/webvtt.cr b/src/invidious/helpers/webvtt.cr
new file mode 100644
index 00000000..56f761ed
--- /dev/null
+++ b/src/invidious/helpers/webvtt.cr
@@ -0,0 +1,67 @@
+# Namespace for logic relating to generating WebVTT files
+#
+# Probably not compliant to WebVTT's specs but it is enough for Invidious.
+module WebVTT
+ # A WebVTT builder generates WebVTT files
+ private class Builder
+ def initialize(@io : IO)
+ end
+
+ # Writes an vtt cue with the specified time stamp and contents
+ def cue(start_time : Time::Span, end_time : Time::Span, text : String)
+ timestamp(start_time, end_time)
+ @io << text
+ @io << "\n\n"
+ end
+
+ private def timestamp(start_time : Time::Span, end_time : Time::Span)
+ timestamp_component(start_time)
+ @io << " --> "
+ timestamp_component(end_time)
+
+ @io << '\n'
+ end
+
+ private def timestamp_component(timestamp : Time::Span)
+ @io << timestamp.hours.to_s.rjust(2, '0')
+ @io << ':' << timestamp.minutes.to_s.rjust(2, '0')
+ @io << ':' << timestamp.seconds.to_s.rjust(2, '0')
+ @io << '.' << timestamp.milliseconds.to_s.rjust(3, '0')
+ end
+
+ def document(setting_fields : Hash(String, String)? = nil, &)
+ @io << "WEBVTT\n"
+
+ if setting_fields
+ setting_fields.each do |name, value|
+ @io << name << ": " << value << '\n'
+ end
+ end
+
+ @io << '\n'
+
+ yield
+ end
+ end
+
+ # Returns the resulting `String` of writing WebVTT to the yielded `WebVTT::Builder`
+ #
+ # ```
+ # string = WebVTT.build do |vtt|
+ # vtt.cue(Time::Span.new(seconds: 1), Time::Span.new(seconds: 2), "Line 1")
+ # vtt.cue(Time::Span.new(seconds: 2), Time::Span.new(seconds: 3), "Line 2")
+ # end
+ #
+ # string # => "WEBVTT\n\n00:00:01.000 --> 00:00:02.000\nLine 1\n\n00:00:02.000 --> 00:00:03.000\nLine 2\n\n"
+ # ```
+ #
+ # Accepts an optional settings fields hash to add settings attribute to the resulting vtt file.
+ def self.build(setting_fields : Hash(String, String)? = nil, &)
+ String.build do |str|
+ builder = Builder.new(str)
+ builder.document(setting_fields) do
+ yield builder
+ end
+ end
+ end
+end
diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr
index adf05d30..67018660 100644
--- a/src/invidious/routes/api/v1/channels.cr
+++ b/src/invidious/routes/api/v1/channels.cr
@@ -343,6 +343,59 @@ module Invidious::Routes::API::V1::Channels
end
end
+ def self.post(env)
+ locale = env.get("preferences").as(Preferences).locale
+
+ env.response.content_type = "application/json"
+ id = env.params.url["id"].to_s
+ ucid = env.params.query["ucid"]?
+
+ thin_mode = env.params.query["thin_mode"]?
+ thin_mode = thin_mode == "true"
+
+ format = env.params.query["format"]?
+ format ||= "json"
+
+ if ucid.nil?
+ response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}")
+ return error_json(400, "Invalid post ID") if response["error"]?
+ ucid = response.dig("endpoint", "browseEndpoint", "browseId").as_s
+ else
+ ucid = ucid.to_s
+ end
+
+ begin
+ fetch_channel_community_post(ucid, id, locale, format, thin_mode)
+ rescue ex
+ return error_json(500, ex)
+ end
+ end
+
+ def self.post_comments(env)
+ locale = env.get("preferences").as(Preferences).locale
+
+ env.response.content_type = "application/json"
+
+ id = env.params.url["id"]
+
+ thin_mode = env.params.query["thin_mode"]?
+ thin_mode = thin_mode == "true"
+
+ format = env.params.query["format"]?
+ format ||= "json"
+
+ continuation = env.params.query["continuation"]?
+
+ case continuation
+ when nil, ""
+ ucid = env.params.query["ucid"]
+ comments = Comments.fetch_community_post_comments(ucid, id)
+ else
+ comments = YoutubeAPI.browse(continuation: continuation)
+ end
+ return Comments.parse_youtube(id, comments, format, locale, thin_mode, isPost: true)
+ end
+
def self.channels(env)
locale = env.get("preferences").as(Preferences).locale
ucid = env.params.url["ucid"]
diff --git a/src/invidious/routes/api/v1/misc.cr b/src/invidious/routes/api/v1/misc.cr
index 4fdb7074..701b22d4 100644
--- a/src/invidious/routes/api/v1/misc.cr
+++ b/src/invidious/routes/api/v1/misc.cr
@@ -228,17 +228,20 @@ module Invidious::Routes::API::V1::Misc
resolved_url = YoutubeAPI.resolve_url(url.as(String))
endpoint = resolved_url["endpoint"]
pageType = endpoint.dig?("commandMetadata", "webCommandMetadata", "webPageType").try &.as_s || ""
- if resolved_ucid = endpoint.dig?("watchEndpoint", "videoId")
- elsif resolved_ucid = endpoint.dig?("browseEndpoint", "browseId")
- elsif pageType == "WEB_PAGE_TYPE_UNKNOWN"
+ if pageType == "WEB_PAGE_TYPE_UNKNOWN"
return error_json(400, "Unknown url")
end
+
+ sub_endpoint = endpoint["watchEndpoint"]? || endpoint["browseEndpoint"]? || endpoint
+ params = sub_endpoint.try &.dig?("params")
rescue ex
return error_json(500, ex)
end
JSON.build do |json|
json.object do
- json.field "ucid", resolved_ucid.try &.as_s || ""
+ json.field "ucid", sub_endpoint["browseId"].as_s if sub_endpoint["browseId"]?
+ json.field "videoId", sub_endpoint["videoId"].as_s if sub_endpoint["videoId"]?
+ json.field "params", params.try &.as_s
json.field "pageType", pageType
end
end
diff --git a/src/invidious/routes/api/v1/videos.cr b/src/invidious/routes/api/v1/videos.cr
index 25e766d2..449c9f9b 100644
--- a/src/invidious/routes/api/v1/videos.cr
+++ b/src/invidious/routes/api/v1/videos.cr
@@ -101,20 +101,17 @@ module Invidious::Routes::API::V1::Videos
if caption.name.includes? "auto-generated"
caption_xml = YT_POOL.client &.get(url).body
+ settings_field = {
+ "Kind" => "captions",
+ "Language" => "#{tlang || caption.language_code}",
+ }
+
if caption_xml.starts_with?("/, "")
text = text.gsub(/<\/font>/, "")
@@ -137,12 +131,7 @@ module Invidious::Routes::API::V1::Videos
text = "#{md["text"]}"
end
- str << <<-END_CUE
- #{start_time} --> #{end_time}
- #{text}
-
-
- END_CUE
+ webvtt.cue(start_time, end_time, text)
end
end
end
@@ -215,11 +204,7 @@ module Invidious::Routes::API::V1::Videos
storyboard = storyboard[0]
end
- String.build do |str|
- str << <<-END_VTT
- WEBVTT
- END_VTT
-
+ WebVTT.build do |vtt|
start_time = 0.milliseconds
end_time = storyboard[:interval].milliseconds
@@ -231,12 +216,8 @@ module Invidious::Routes::API::V1::Videos
storyboard[:storyboard_height].times do |j|
storyboard[:storyboard_width].times do |k|
- str << <<-END_CUE
- #{start_time}.000 --> #{end_time}.000
- #{url}#xywh=#{storyboard[:width] * k},#{storyboard[:height] * j},#{storyboard[:width] - 2},#{storyboard[:height]}
-
-
- END_CUE
+ current_cue_url = "#{url}#xywh=#{storyboard[:width] * k},#{storyboard[:height] * j},#{storyboard[:width] - 2},#{storyboard[:height]}"
+ vtt.cue(start_time, end_time, current_cue_url)
start_time += storyboard[:interval].milliseconds
end_time += storyboard[:interval].milliseconds
diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr
index 9892ae2a..d4d8b1c1 100644
--- a/src/invidious/routes/channels.cr
+++ b/src/invidious/routes/channels.cr
@@ -1,6 +1,12 @@
{% skip_file if flag?(:api_only) %}
module Invidious::Routes::Channels
+ # Redirection for unsupported routes ("tabs")
+ def self.redirect_home(env)
+ ucid = env.params.url["ucid"]
+ return env.redirect "/channel/#{URI.encode_www_form(ucid)}"
+ end
+
def self.home(env)
self.videos(env)
end
@@ -159,6 +165,11 @@ module Invidious::Routes::Channels
end
locale, user, subscriptions, continuation, ucid, channel = data
+ # redirect to post page
+ if lb = env.params.query["lb"]?
+ env.redirect "/post/#{URI.encode_www_form(lb)}?ucid=#{URI.encode_www_form(ucid)}"
+ end
+
thin_mode = env.params.query["thin_mode"]? || env.get("preferences").as(Preferences).thin_mode
thin_mode = thin_mode == "true"
@@ -187,6 +198,44 @@ module Invidious::Routes::Channels
templated "community"
end
+ def self.post(env)
+ # /post/{postId}
+ id = env.params.url["id"]
+ ucid = env.params.query["ucid"]?
+
+ prefs = env.get("preferences").as(Preferences)
+
+ locale = prefs.locale
+
+ thin_mode = env.params.query["thin_mode"]? || prefs.thin_mode
+ thin_mode = thin_mode == "true"
+
+ nojs = env.params.query["nojs"]?
+
+ nojs ||= "0"
+ nojs = nojs == "1"
+
+ if !ucid.nil?
+ ucid = ucid.to_s
+ post_response = fetch_channel_community_post(ucid, id, locale, "json", thin_mode)
+ else
+ # resolve the url to get the author's UCID
+ response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}")
+ return error_template(400, "Invalid post ID") if response["error"]?
+
+ ucid = response.dig("endpoint", "browseEndpoint", "browseId").as_s
+ post_response = fetch_channel_community_post(ucid, id, locale, "json", thin_mode)
+ end
+
+ post_response = JSON.parse(post_response)
+
+ if nojs
+ comments = Comments.fetch_community_post_comments(ucid, id)
+ comment_html = JSON.parse(Comments.parse_youtube(id, comments, "html", locale, thin_mode, isPost: true))["contentHtml"]
+ end
+ templated "post"
+ end
+
def self.channels(env)
data = self.fetch_basic_information(env)
return data if !data.is_a?(Tuple)
@@ -217,6 +266,11 @@ module Invidious::Routes::Channels
env.redirect "/channel/#{ucid}"
end
+ private KNOWN_TABS = {
+ "home", "videos", "shorts", "streams", "podcasts",
+ "releases", "playlists", "community", "channels", "about",
+ }
+
# Redirects brand url channels to a normal /channel/:ucid route
def self.brand_redirect(env)
locale = env.get("preferences").as(Preferences).locale
@@ -227,7 +281,10 @@ module Invidious::Routes::Channels
yt_url_params = URI::Params.encode(env.params.query.to_h.select(["a", "u", "user"]))
# Retrieves URL params that only Invidious uses
- invidious_url_params = URI::Params.encode(env.params.query.to_h.select!(["a", "u", "user"]))
+ invidious_url_params = env.params.query.dup
+ invidious_url_params.delete_all("a")
+ invidious_url_params.delete_all("u")
+ invidious_url_params.delete_all("user")
begin
resolved_url = YoutubeAPI.resolve_url("https://youtube.com#{env.request.path}#{yt_url_params.size > 0 ? "?#{yt_url_params}" : ""}")
@@ -236,14 +293,17 @@ module Invidious::Routes::Channels
return error_template(404, translate(locale, "This channel does not exist."))
end
- selected_tab = env.request.path.split("/")[-1]
- if {"home", "videos", "shorts", "streams", "playlists", "community", "channels", "about"}.includes? selected_tab
+ selected_tab = env.params.url["tab"]?
+
+ if KNOWN_TABS.includes? selected_tab
url = "/channel/#{ucid}/#{selected_tab}"
else
url = "/channel/#{ucid}"
end
- env.redirect url
+ url += "?#{invidious_url_params}" if !invidious_url_params.empty?
+
+ return env.redirect url
end
# Handles redirects for the /profile endpoint
diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr
index a5ee47b9..b4f079a5 100644
--- a/src/invidious/routing.cr
+++ b/src/invidious/routing.cr
@@ -136,28 +136,42 @@ module Invidious::Routing
get "/channel/:ucid/community", Routes::Channels, :community
get "/channel/:ucid/channels", Routes::Channels, :channels
get "/channel/:ucid/about", Routes::Channels, :about
+
get "/channel/:ucid/live", Routes::Channels, :live
get "/user/:user/live", Routes::Channels, :live
get "/c/:user/live", Routes::Channels, :live
+ get "/post/:id", Routes::Channels, :post
- {"", "/videos", "/shorts", "/streams", "/playlists", "/community", "/about"}.each do |path|
- # /c/LinusTechTips
- get "/c/:user#{path}", Routes::Channels, :brand_redirect
- # /user/linustechtips | Not always the same as /c/
- get "/user/:user#{path}", Routes::Channels, :brand_redirect
- # /@LinusTechTips | Handle
- get "/@:user#{path}", Routes::Channels, :brand_redirect
- # /attribution_link?a=anything&u=/channel/UCZYTClx2T1of7BRZ86-8fow
- get "/attribution_link#{path}", Routes::Channels, :brand_redirect
- # /profile?user=linustechtips
- get "/profile/#{path}", Routes::Channels, :profile
- end
+ # Channel catch-all, to redirect future routes to the channel's home
+ # NOTE: defined last in order to be processed after the other routes
+ get "/channel/:ucid/*", Routes::Channels, :redirect_home
+
+ # /c/LinusTechTips
+ get "/c/:user", Routes::Channels, :brand_redirect
+ get "/c/:user/:tab", Routes::Channels, :brand_redirect
+
+ # /user/linustechtips (Not always the same as /c/)
+ get "/user/:user", Routes::Channels, :brand_redirect
+ get "/user/:user/:tab", Routes::Channels, :brand_redirect
+
+ # /@LinusTechTips (Handle)
+ get "/@:user", Routes::Channels, :brand_redirect
+ get "/@:user/:tab", Routes::Channels, :brand_redirect
+
+ # /attribution_link?a=anything&u=/channel/UCZYTClx2T1of7BRZ86-8fow
+ get "/attribution_link", Routes::Channels, :brand_redirect
+ get "/attribution_link/:tab", Routes::Channels, :brand_redirect
+
+ # /profile?user=linustechtips
+ get "/profile", Routes::Channels, :profile
+ get "/profile/*", Routes::Channels, :profile
end
def register_watch_routes
get "/watch", Routes::Watch, :handle
post "/watch_ajax", Routes::Watch, :mark_watched
get "/watch/:id", Routes::Watch, :redirect
+ get "/live/:id", Routes::Watch, :redirect
get "/shorts/:id", Routes::Watch, :redirect
get "/clip/:clip", Routes::Watch, :clip
get "/w/:id", Routes::Watch, :redirect
@@ -256,6 +270,10 @@ module Invidious::Routing
get "/api/v1/channels/:ucid/#{{{route}}}", {{namespace}}::Channels, :{{route}}
{% end %}
+ # Posts
+ get "/api/v1/post/:id", {{namespace}}::Channels, :post
+ get "/api/v1/post/:id/comments", {{namespace}}::Channels, :post_comments
+
# 301 redirects to new /api/v1/channels/community/:ucid and /:ucid/community
get "/api/v1/channels/comments/:ucid", {{namespace}}::Channels, :channel_comments_redirect
get "/api/v1/channels/:ucid/comments", {{namespace}}::Channels, :channel_comments_redirect
@@ -265,6 +283,7 @@ module Invidious::Routing
get "/api/v1/search/suggestions", {{namespace}}::Search, :search_suggestions
get "/api/v1/hashtag/:hashtag", {{namespace}}::Search, :hashtag
+
# Authenticated
# The notification APIs cannot be extracted yet! They require the *local* notifications constant defined in invidious.cr
diff --git a/src/invidious/videos/caption.cr b/src/invidious/videos/caption.cr
index 256dfcc0..484e61d2 100644
--- a/src/invidious/videos/caption.cr
+++ b/src/invidious/videos/caption.cr
@@ -52,17 +52,13 @@ module Invidious::Videos
break
end
end
- result = String.build do |result|
- result << <<-END_VTT
- WEBVTT
- Kind: captions
- Language: #{tlang || @language_code}
+ settings_field = {
+ "Kind" => "captions",
+ "Language" => "#{tlang || @language_code}",
+ }
- END_VTT
-
- result << "\n\n"
-
+ result = WebVTT.build(settings_field) do |vtt|
cues.each_with_index do |node, i|
start_time = node["t"].to_f.milliseconds
@@ -76,29 +72,16 @@ module Invidious::Videos
end_time = start_time + duration
end
- # start_time
- result << start_time.hours.to_s.rjust(2, '0')
- result << ':' << start_time.minutes.to_s.rjust(2, '0')
- result << ':' << start_time.seconds.to_s.rjust(2, '0')
- result << '.' << start_time.milliseconds.to_s.rjust(3, '0')
-
- result << " --> "
-
- # end_time
- result << end_time.hours.to_s.rjust(2, '0')
- result << ':' << end_time.minutes.to_s.rjust(2, '0')
- result << ':' << end_time.seconds.to_s.rjust(2, '0')
- result << '.' << end_time.milliseconds.to_s.rjust(3, '0')
-
- result << "\n"
-
- node.children.each do |s|
- result << s.content
+ text = String.build do |io|
+ node.children.each do |s|
+ io << s.content
+ end
end
- result << "\n"
- result << "\n"
+
+ vtt.cue(start_time, end_time, text)
end
end
+
return result
end
end
diff --git a/src/invidious/videos/transcript.cr b/src/invidious/videos/transcript.cr
index f3360a52..dac00eea 100644
--- a/src/invidious/videos/transcript.cr
+++ b/src/invidious/videos/transcript.cr
@@ -34,41 +34,15 @@ module Invidious::Videos
# Convert into array of TranscriptLine
lines = self.parse(initial_data)
+ settings_field = {
+ "Kind" => "captions",
+ "Language" => target_language,
+ }
+
# Taken from Invidious::Videos::Captions::Metadata.timedtext_to_vtt()
- vtt = String.build do |vtt|
- vtt << <<-END_VTT
- WEBVTT
- Kind: captions
- Language: #{target_language}
-
-
- END_VTT
-
- vtt << "\n\n"
-
+ vtt = WebVTT.build(settings_field) do |vtt|
lines.each do |line|
- start_time = line.start_ms
- end_time = line.end_ms
-
- # start_time
- vtt << start_time.hours.to_s.rjust(2, '0')
- vtt << ':' << start_time.minutes.to_s.rjust(2, '0')
- vtt << ':' << start_time.seconds.to_s.rjust(2, '0')
- vtt << '.' << start_time.milliseconds.to_s.rjust(3, '0')
-
- vtt << " --> "
-
- # end_time
- vtt << end_time.hours.to_s.rjust(2, '0')
- vtt << ':' << end_time.minutes.to_s.rjust(2, '0')
- vtt << ':' << end_time.seconds.to_s.rjust(2, '0')
- vtt << '.' << end_time.milliseconds.to_s.rjust(3, '0')
-
- vtt << "\n"
- vtt << line.line
-
- vtt << "\n"
- vtt << "\n"
+ vtt.cue(line.start_ms, line.end_ms, line.line)
end
end
diff --git a/src/invidious/views/community.ecr b/src/invidious/views/community.ecr
index 24efc34e..d2a305d3 100644
--- a/src/invidious/views/community.ecr
+++ b/src/invidious/views/community.ecr
@@ -26,7 +26,7 @@
<%= error_message %>
<% else %>
-
+ <% if !item.channel_handle.nil? %><%= item.channel_handle %>
<% end %>
<%= translate_count(locale, "generic_subscribers_count", item.subscriber_count, NumberFormatting::Separator) %>
- <% if !item.auto_generated %><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %>
<% end %>
+ <% if !item.auto_generated && item.channel_handle.nil? %><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %>
<% end %>
<%= item.description_html %>
<% when SearchHashtag %>
<% if !thin_mode %>
diff --git a/src/invidious/views/post.ecr b/src/invidious/views/post.ecr
new file mode 100644
index 00000000..fb03a44c
--- /dev/null
+++ b/src/invidious/views/post.ecr
@@ -0,0 +1,48 @@
+<% content_for "header" do %>
+Invidious
+<% end %>
+
+
+
+
+ <% if nojs %>
+
+ <% end %>
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr
index 4c844534..0ccb10c8 100644
--- a/src/invidious/views/watch.ecr
+++ b/src/invidious/views/watch.ecr
@@ -67,7 +67,8 @@ we're going to need to do it here in order to allow for translations.
"premiere_timestamp" => video.premiere_timestamp.try &.to_unix,
"vr" => video.is_vr,
"projection_type" => video.projection_type,
- "local_disabled" => CONFIG.disabled?("local")
+ "local_disabled" => CONFIG.disabled?("local"),
+ "support_reddit" => true
}.to_pretty_json
%>
@@ -301,7 +302,7 @@ we're going to need to do it here in order to allow for translations.
<% end %>
-
+
diff --git a/src/invidious/yt_backend/extractors.cr b/src/invidious/yt_backend/extractors.cr
index aaf7772e..56325cf7 100644
--- a/src/invidious/yt_backend/extractors.cr
+++ b/src/invidious/yt_backend/extractors.cr
@@ -175,17 +175,18 @@ private module Parsers
# Always simpleText
# TODO change default value to nil
- subscriber_count = item_contents.dig?("subscriberCountText", "simpleText")
+ subscriber_count = item_contents.dig?("subscriberCountText", "simpleText").try &.as_s
+ channel_handle = subscriber_count if (subscriber_count.try &.starts_with? "@")
# Since youtube added channel handles, `VideoCountText` holds the number of
# subscribers and `subscriberCountText` holds the handle, except when the
# channel doesn't have a handle (e.g: some topic music channels).
# See https://github.com/iv-org/invidious/issues/3394#issuecomment-1321261688
- if !subscriber_count || !subscriber_count.as_s.includes? " subscriber"
- subscriber_count = item_contents.dig?("videoCountText", "simpleText")
+ if !subscriber_count || !subscriber_count.includes? " subscriber"
+ subscriber_count = item_contents.dig?("videoCountText", "simpleText").try &.as_s
end
subscriber_count = subscriber_count
- .try { |s| short_text_to_number(s.as_s.split(" ")[0]).to_i32 } || 0
+ .try { |s| short_text_to_number(s.split(" ")[0]).to_i32 } || 0
# Auto-generated channels doesn't have videoCountText
# Taken from: https://github.com/iv-org/invidious/pull/2228#discussion_r717620922
@@ -200,6 +201,7 @@ private module Parsers
author_thumbnail: author_thumbnail,
subscriber_count: subscriber_count,
video_count: video_count,
+ channel_handle: channel_handle,
description_html: description_html,
auto_generated: auto_generated,
author_verified: author_verified,