summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--locales/ar.json22
-rw-r--r--locales/bn.json4
-rw-r--r--locales/cs.json12
-rw-r--r--locales/da.json4
-rw-r--r--locales/de.json8
-rw-r--r--locales/en-US.json2
-rw-r--r--locales/es.json14
-rw-r--r--locales/eu.json22
-rw-r--r--locales/hi.json13
-rw-r--r--locales/hr.json13
-rw-r--r--locales/ia.json6
-rw-r--r--locales/it.json11
-rw-r--r--locales/ja.json11
-rw-r--r--locales/ko.json15
-rw-r--r--locales/lmo.json232
-rw-r--r--locales/nl.json11
-rw-r--r--locales/pl.json26
-rw-r--r--locales/pt-BR.json264
-rw-r--r--locales/pt-PT.json10
-rw-r--r--locales/pt.json168
-rw-r--r--locales/ro.json3
-rw-r--r--locales/sr.json13
-rw-r--r--locales/sr_Cyrl.json12
-rw-r--r--locales/sv-SE.json10
-rw-r--r--locales/tk.json7
-rw-r--r--locales/tr.json12
-rw-r--r--locales/uk.json12
-rw-r--r--locales/vi.json27
-rw-r--r--locales/zh-CN.json12
-rw-r--r--locales/zh-TW.json12
-rw-r--r--src/invidious/channels/about.cr16
-rw-r--r--src/invidious/jsonify/api_v1/video_json.cr2
-rw-r--r--src/invidious/routes/api/manifest.cr8
-rw-r--r--src/invidious/routes/api/v1/channels.cr1
-rw-r--r--src/invidious/videos.cr15
-rw-r--r--src/invidious/videos/parser.cr24
-rw-r--r--src/invidious/yt_backend/connection_pool.cr44
-rw-r--r--src/invidious/yt_backend/proxy.cr316
-rw-r--r--src/invidious/yt_backend/youtube_api.cr18
39 files changed, 770 insertions, 662 deletions
diff --git a/locales/ar.json b/locales/ar.json
index 57062e89..5d8b230f 100644
--- a/locales/ar.json
+++ b/locales/ar.json
@@ -15,13 +15,13 @@
"New password": "كلمة مرور جديدة",
"New passwords must match": "يَجبُ أن تكون كلمتا المرور متطابقتين",
"Authorize token?": "رمز التفويض؟",
- "Authorize token for `x`?": "السماح بالرمز المميز ل 'x'؟",
+ "Authorize token for `x`?": "السماح بالرمز المميز ل `x`؟",
"Yes": "نعم",
"No": "لا",
"Import and Export Data": "اِستيراد البيانات وتصديرها",
"Import": "استيراد",
"Import Invidious data": "استيراد بيانات JSON Invidious",
- "Import YouTube subscriptions": "استيراد اشتراكات YouTube/OPML",
+ "Import YouTube subscriptions": "استيراد الاشتراكات YouTube بتنسيق CSV أو OPML",
"Import FreeTube subscriptions (.db)": "استيراد اشتراكات فريتيوب (.db)",
"Import NewPipe subscriptions (.json)": "استيراد اشتراكات نيو بايب (.json)",
"Import NewPipe data (.zip)": "استيراد بيانات نيو بايب (.zip)",
@@ -170,7 +170,7 @@
"Password cannot be empty": "لا يمكن أن تكون كلمة السر فارغة",
"Password cannot be longer than 55 characters": "يجب أن لا تتعدى كلمة السر 55 حرفًا",
"Please log in": "الرجاء تسجيل الدخول",
- "Invidious Private Feed for `x`": "تغذية Invidious خاصة ل 'x'",
+ "Invidious Private Feed for `x`": "تغذية Invidious خاصة ل `x`",
"channel:`x`": "قناة:`x`",
"Deleted or invalid channel": "قناة ممسوحة او غير صالحة",
"This channel does not exist.": "هذه القناة غير موجودة.",
@@ -382,11 +382,11 @@
"videoinfo_watch_on_youTube": "مشاهدة على يوتيوب",
"videoinfo_youTube_embed_link": "مضمن",
"videoinfo_invidious_embed_link": "رابط مضمن",
- "user_created_playlists": "'x' إنشاء قوائم التشغيل",
- "user_saved_playlists": "قوائم التشغيل المحفوظة 'x'",
+ "user_created_playlists": "`x` إنشاء قوائم التشغيل",
+ "user_saved_playlists": "قوائم التشغيل المحفوظة `x`",
"Video unavailable": "الفيديو غير متوفر",
"search_filters_features_option_three_sixty": "360°",
- "download_subtitles": "ترجمات - 'x' (.vtt)",
+ "download_subtitles": "ترجمات - `x` (.vtt)",
"invidious": "الخيالي",
"preferences_save_player_pos_label": "حفظ موضع التشغيل: ",
"crash_page_you_found_a_bug": "يبدو أنك قد وجدت خطأً برمجيًّا في Invidious!",
@@ -556,5 +556,13 @@
"generic_channels_count_4": "{{count}} قنوات",
"generic_channels_count_5": "{{count}} قناة",
"Import YouTube watch history (.json)": "استيراد سجل مشاهدة YouTube بصيغة (.json)",
- "toggle_theme": "تبديل الموضوع"
+ "toggle_theme": "تبديل الموضوع",
+ "Add to playlist": "أضف إلى قائمة التشغيل",
+ "Add to playlist: ": "أضف إلى قائمة التشغيل: ",
+ "Answer": "الرد",
+ "Search for videos": "ابحث عن مقاطع الفيديو",
+ "The Popular feed has been disabled by the administrator.": "تم تعطيل الخلاصة الشائعة من قبل المسؤول.",
+ "carousel_slide": "الشريحة {{current}} من {{total}}",
+ "carousel_skip": "تخطي الكاروسيل",
+ "carousel_go_to": "انتقل إلى الشريحة `x`"
}
diff --git a/locales/bn.json b/locales/bn.json
index 9d1c7b24..501a1ca3 100644
--- a/locales/bn.json
+++ b/locales/bn.json
@@ -90,5 +90,7 @@
"preferences_quality_option_medium": "মধ্যম",
"preferences_quality_option_small": "ছোট",
"preferences_quality_dash_option_1080p": "১০৮০পি",
- "preferences_quality_dash_option_720p": "৭২০পি"
+ "preferences_quality_dash_option_720p": "৭২০পি",
+ "Add to playlist": "প্লেলিস্টে যোগ করুন",
+ "Add to playlist: ": "প্লেলিস্টে যোগ করুন: "
}
diff --git a/locales/cs.json b/locales/cs.json
index 4aa20f28..1350f146 100644
--- a/locales/cs.json
+++ b/locales/cs.json
@@ -21,7 +21,7 @@
"Import and Export Data": "Import a export dat",
"Import": "Importovat",
"Import Invidious data": "Importovat JSON údaje Invidious",
- "Import YouTube subscriptions": "Importovat odběry z YouTube/OPML",
+ "Import YouTube subscriptions": "Importovat odběry z YouTube CSV nebo OPML",
"Import FreeTube subscriptions (.db)": "Importovat odběry z FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importovat odběry z NewPipe (.json)",
"Import NewPipe data (.zip)": "Importovat údeje z NewPipe (.zip)",
@@ -505,5 +505,13 @@
"generic_channels_count_1": "{{count}} kanály",
"generic_channels_count_2": "{{count}} kanálů",
"Import YouTube watch history (.json)": "Importovat historii sledování z YouTube (.json)",
- "toggle_theme": "Přepnout motiv"
+ "toggle_theme": "Přepnout motiv",
+ "Add to playlist": "Přidat do playlistu",
+ "Add to playlist: ": "Přidat do playlistu: ",
+ "Answer": "Odpověď",
+ "Search for videos": "Hledat videa",
+ "The Popular feed has been disabled by the administrator.": "Kategorie Populární byla zakázána administrátorem.",
+ "carousel_slide": "Snímek {{current}} z {{total}}",
+ "carousel_skip": "Přeskočit galerii",
+ "carousel_go_to": "Přejít na snímek `x`"
}
diff --git a/locales/da.json b/locales/da.json
index 019f1c51..9cbb446a 100644
--- a/locales/da.json
+++ b/locales/da.json
@@ -165,12 +165,12 @@
"Password cannot be empty": "Adgangskoden må ikke være tom",
"Password cannot be longer than 55 characters": "Adgangskoden må ikke være længere end 55 tegn",
"Please log in": "Venligst log ind",
- "channel:`x`": "kanal: 'x'",
+ "channel:`x`": "kanal: `x`",
"Deleted or invalid channel": "Slettet eller invalid kanal",
"This channel does not exist.": "Denne kanal eksisterer ikke.",
"Could not get channel info.": "Kunne ikke hente kanal info.",
"Could not fetch comments": "Kunne ikke hente kommentarer",
- "`x` ago": "'x' siden",
+ "`x` ago": "`x` siden",
"Load more": "Hent flere",
"Could not create mix.": "Kunne ikke skabe blanding.",
"Empty playlist": "Tom playliste",
diff --git a/locales/de.json b/locales/de.json
index 756aff76..46327f57 100644
--- a/locales/de.json
+++ b/locales/de.json
@@ -487,5 +487,11 @@
"channel_tab_releases_label": "Veröffentlichungen",
"generic_channels_count": "{{count}} Kanal",
"generic_channels_count_plural": "{{count}} Kanäle",
- "Import YouTube watch history (.json)": "YouTube Wiedergabeverlauf importieren (.json)"
+ "Import YouTube watch history (.json)": "YouTube Wiedergabeverlauf importieren (.json)",
+ "Answer": "Antwort",
+ "The Popular feed has been disabled by the administrator.": "Der Angesagt-Feed wurde vom Administrator deaktiviert.",
+ "Add to playlist": "Einer Wiedergabeliste hinzufügen",
+ "Search for videos": "Nach Videos suchen",
+ "toggle_theme": "Thema wechseln",
+ "Add to playlist: ": "Einer Wiedergabeliste hinzufügen: "
}
diff --git a/locales/en-US.json b/locales/en-US.json
index 10887612..3987f796 100644
--- a/locales/en-US.json
+++ b/locales/en-US.json
@@ -43,7 +43,7 @@
"Import and Export Data": "Import and Export Data",
"Import": "Import",
"Import Invidious data": "Import Invidious JSON data",
- "Import YouTube subscriptions": "Import YouTube/OPML subscriptions",
+ "Import YouTube subscriptions": "Import YouTube CSV or OPML subscriptions",
"Import YouTube playlist (.csv)": "Import YouTube playlist (.csv)",
"Import YouTube watch history (.json)": "Import YouTube watch history (.json)",
"Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)",
diff --git a/locales/es.json b/locales/es.json
index 7a41710e..1d082e60 100644
--- a/locales/es.json
+++ b/locales/es.json
@@ -21,7 +21,7 @@
"Import and Export Data": "Importación y exportación de datos",
"Import": "Importar",
"Import Invidious data": "Importar datos JSON de Invidious",
- "Import YouTube subscriptions": "Importar suscripciones de YouTube/OPML",
+ "Import YouTube subscriptions": "Importar suscripciones CSV u OPML de YouTube",
"Import FreeTube subscriptions (.db)": "Importar suscripciones de FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importar suscripciones de NewPipe (.json)",
"Import NewPipe data (.zip)": "Importar datos de NewPipe (.zip)",
@@ -133,7 +133,7 @@
"Create playlist": "Crear lista de reproducción",
"Title": "Título",
"Playlist privacy": "Privacidad de la lista de reproducción",
- "Editing playlist `x`": "Editando la lista de reproducción 'x'",
+ "Editing playlist `x`": "Editando la lista de reproducción `x`",
"Show more": "Mostrar más",
"Show less": "Mostrar menos",
"Watch on YouTube": "Ver en YouTube",
@@ -505,5 +505,13 @@
"generic_channels_count_1": "{{count}} canales",
"generic_channels_count_2": "{{count}} canales",
"Import YouTube watch history (.json)": "Importar el historial de las visualizaciones de YouTube (.json)",
- "toggle_theme": "Alternar tema"
+ "toggle_theme": "Alternar tema",
+ "Add to playlist: ": "Añadir a la lista de reproducción: ",
+ "Add to playlist": "Añadir a la lista de reproducción",
+ "Answer": "Respuesta",
+ "Search for videos": "Buscar por vídeos",
+ "The Popular feed has been disabled by the administrator.": "El feed Popular ha sido desactivado por el administrador.",
+ "carousel_slide": "Diapositiva {{current}} de {{total}}",
+ "carousel_skip": "Saltar el carrusel",
+ "carousel_go_to": "Ir a la diapositiva `x`"
}
diff --git a/locales/eu.json b/locales/eu.json
index 8b365270..fbca537b 100644
--- a/locales/eu.json
+++ b/locales/eu.json
@@ -161,13 +161,13 @@
"Source available here.": "Iturburua hemen eskura.",
"View JavaScript license information.": "JavaScriptaren lizentzi adierazpena ikusi.",
"Blacklisted regions: ": "zerrenda beltzaren zonaldeak: ",
- "Premieres `x`": "'x' estrenaldiak",
+ "Premieres `x`": "`x` estrenaldiak",
"Wrong answer": "Erantzun ez zuzena",
"Password is a required field": "Pasahitza beharrezkoa da",
"Wrong username or password": "Pasahitza edo ezizena gaizki",
"Password cannot be longer than 55 characters": "Pasahitza 55 karaktere baino luzeagoa ezin da izan",
"This channel does not exist.": "Kanal hau ez dago.",
- "`x` ago": "duela 'x'",
+ "`x` ago": "duela `x`",
"Czech": "Txekiera",
"preferences_region_label": "Herrialdeko edukiera: ",
"preferences_sort_label": "Bideoak ordenatu: ",
@@ -207,24 +207,24 @@
"Public": "Orokorra",
"Unlisted": "Ez zerrendatua",
"Subscription manager": "Harpidetzen kudeatzailea",
- "Updated `x` ago": "Duela 'x' eguneratua",
+ "Updated `x` ago": "Duela `x` eguneratua",
"Hide replies": "Erantzunak izkutatu",
"preferences_thin_mode_label": "Urri eran: ",
"Show replies": "Erantzunak erakutsi",
"Watch on YouTube": "YouTuben ikusi",
- "Premieres in `x`": "'x'eko estrenaldiak",
- "Delete playlist `x`?": "'x' zerrenda ezabatu nahi?",
+ "Premieres in `x`": "`x`eko estrenaldiak",
+ "Delete playlist `x`?": "`x` zerrenda ezabatu nahi?",
"Token is expired, please try again": "Token kadukatua, saiatu berriro",
"CAPTCHA enabled: ": "CAPTCHA gaitu: ",
"Released under the AGPLv3 on Github.": "GitHubeko AGPLv3pean argitaratuta.",
- "channel:`x`": "Kanal: 'x'",
+ "channel:`x`": "Kanal: `x`",
"Georgian": "Georgiera",
"Incorrect password": "Pasahitza gaizki",
"Playlist does not exist.": "Zerrenda ez da existitzen.",
"preferences_category_misc": "Askotariko lehentasunak",
"View `x` comments": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "'x' iruzkina ikusi",
- "": "'x' iruzkinak ikusi"
+ "([^.,0-9]|^)1([^.,0-9]|$)": "`x` iruzkina ikusi",
+ "": "`x` iruzkinak ikusi"
},
"Report statistics: ": "Estatistikak adierazi: ",
"preferences_max_results_label": "Jotzeko bideo zerrendaren luzera: ",
@@ -237,7 +237,7 @@
"Hidden field \"challenge\" is a required field": "\"challenge\" eremu ezkutua beharrezkoa da",
"German": "Alemaniarra",
"View YouTube comments": "YouTubeko iruzkinak ikusi",
- "`x` is live": "'x' bizirik darrai",
+ "`x` is live": "`x` bizirik darrai",
"Password cannot be empty": "Pasahitza ezin da hutsik utzi",
"preferences_video_loop_label": "Beti begiztatu: ",
"Only show latest unwatched video from channel: ": "kanalaren azken bideo ezikusia erakutsi soilik ",
@@ -261,9 +261,9 @@
"Hide annotations": "Oharrak izkutatu",
"Title": "Titulua",
"channel name": "Kanalaren izena",
- "Authorize token for `x`?": "Baimendu tokena 'x'tzako?",
+ "Authorize token for `x`?": "Baimendu tokena `x`tzako?",
"Private": "Pribatua",
- "Editing playlist `x`": "'x' zerrenda editatu",
+ "Editing playlist `x`": "`x` zerrenda editatu",
"Could not pull trending pages.": "Ezin ekarri orri arrakastatsuak.",
"crash_page_read_the_faq": "Bide <a href=\"`x`\"> (FAQ) ohiko galderak</a>"
}
diff --git a/locales/hi.json b/locales/hi.json
index a7e0639a..0a1c09dd 100644
--- a/locales/hi.json
+++ b/locales/hi.json
@@ -62,7 +62,7 @@
"Import and Export Data": "डेटा को आयात और निर्यात करें",
"Import": "आयात करें",
"Import Invidious data": "Invidious JSON डेटा आयात करें",
- "Import YouTube subscriptions": "YouTube/OPML सदस्यताएँ आयात करें",
+ "Import YouTube subscriptions": "YouTube CSV या OPML सदस्यताएँ आयात करें",
"Import FreeTube subscriptions (.db)": "FreeTube सदस्यताएँ आयात करें (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe सदस्यताएँ आयात करें (.json)",
"Import NewPipe data (.zip)": "NewPipe डेटा आयात करें (.zip)",
@@ -487,5 +487,14 @@
"Download is disabled": "डाउनलोड करना अक्षम है",
"generic_channels_count": "{{count}} चैनल",
"generic_channels_count_plural": "{{count}} चैनल",
- "Import YouTube watch history (.json)": "YouTube पर देखने का इतिहास आयात करें (.json)"
+ "Import YouTube watch history (.json)": "YouTube पर देखने का इतिहास आयात करें (.json)",
+ "Add to playlist": "प्लेलिस्ट में जोड़ें",
+ "Answer": "जवाब",
+ "The Popular feed has been disabled by the administrator.": "लोकप्रिय फ़ीड व्यवस्थापक द्वारा अक्षम कर दिया गया है।",
+ "toggle_theme": "थीम टॉगल करें",
+ "carousel_slide": "{{total}} में से स्लाइड {{current}}",
+ "carousel_skip": "कैरोसेल छोड़ें",
+ "Add to playlist: ": "प्लेलिस्ट में जोड़ें: ",
+ "Search for videos": "वीडियो खोजें",
+ "carousel_go_to": "स्लाइड `x` पर जाएँ"
}
diff --git a/locales/hr.json b/locales/hr.json
index 2d86144f..91425248 100644
--- a/locales/hr.json
+++ b/locales/hr.json
@@ -21,7 +21,7 @@
"Import and Export Data": "Uvezi i izvezi podatke",
"Import": "Uvezi",
"Import Invidious data": "Uvezi Invidious JSON podatke",
- "Import YouTube subscriptions": "Uvezi YouTube/OPML pretplate",
+ "Import YouTube subscriptions": "Uvezi YouTube CSV ili OPML pretplate",
"Import FreeTube subscriptions (.db)": "Uvezi FreeTube pretplate (.db)",
"Import NewPipe subscriptions (.json)": "Uvezi NewPipe pretplate (.json)",
"Import NewPipe data (.zip)": "Uvezi NewPipe podatke (.zip)",
@@ -504,5 +504,14 @@
"generic_channels_count_0": "{{count}} kanal",
"generic_channels_count_1": "{{count}} kanala",
"generic_channels_count_2": "{{count}} kanala",
- "Import YouTube watch history (.json)": "Uvezi YouTube povijest gledanja (.json)"
+ "Import YouTube watch history (.json)": "Uvezi YouTube povijest gledanja (.json)",
+ "Add to playlist": "Dodaj u zbirku",
+ "Add to playlist: ": "Dodaj u zbirku: ",
+ "Answer": "Odgovor",
+ "Search for videos": "Traži videa",
+ "The Popular feed has been disabled by the administrator.": "Popularni feed je administrator deaktivirao.",
+ "toggle_theme": "Uklj./Isklj. temu",
+ "carousel_slide": "Kadar {{current}} od {{total}}",
+ "carousel_go_to": "Idi na kadar `x`",
+ "carousel_skip": "Preskoči vrtuljak"
}
diff --git a/locales/ia.json b/locales/ia.json
index 19b6b0c0..2c8cb2b0 100644
--- a/locales/ia.json
+++ b/locales/ia.json
@@ -37,5 +37,9 @@
"E-mail": "E-mail",
"Delete account?": "Deler conto?",
"preferences_volume_label": "Volumine del reproductor: ",
- "preferences_sort_label": "Ordinar le videos per: "
+ "preferences_sort_label": "Ordinar le videos per: ",
+ "Next page": "Pagina sequente",
+ "Previous page": "Pagina previe",
+ "Yes": "Si",
+ "Import": "Importar"
}
diff --git a/locales/it.json b/locales/it.json
index 7b6bb5d9..79aa6c16 100644
--- a/locales/it.json
+++ b/locales/it.json
@@ -504,5 +504,14 @@
"generic_channels_count_0": "{{count}} canale",
"generic_channels_count_1": "{{count}} canali",
"generic_channels_count_2": "{{count}} canali",
- "Import YouTube watch history (.json)": "Importa la cronologia delle visualizzazioni di YouTube (.json)"
+ "Import YouTube watch history (.json)": "Importa la cronologia delle visualizzazioni di YouTube (.json)",
+ "Answer": "Risposta",
+ "toggle_theme": "Cambia Tema",
+ "Add to playlist": "Aggiungi alla playlist",
+ "Add to playlist: ": "Aggiungi alla playlist ",
+ "Search for videos": "Cerca dei video",
+ "The Popular feed has been disabled by the administrator.": "La sezione dei contenuti popolari è stata disabilitata dall'amministratore.",
+ "carousel_slide": "Fotogramma {{current}} di {{total}}",
+ "carousel_skip": "Salta la galleria",
+ "carousel_go_to": "Vai al fotogramma `x`"
}
diff --git a/locales/ja.json b/locales/ja.json
index 2e3437bc..d430b2a4 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -470,5 +470,14 @@
"generic_button_rss": "RSS",
"playlist_button_add_items": "動画を追加",
"generic_channels_count_0": "{{count}}個のチャンネル",
- "Import YouTube watch history (.json)": "YouTube 視聴履歴をインポート (.json)"
+ "Import YouTube watch history (.json)": "YouTube 視聴履歴をインポート (.json)",
+ "Add to playlist": "再生リストに追加",
+ "Add to playlist: ": "再生リストに追加: ",
+ "Answer": "回答",
+ "Search for videos": "動画を検索",
+ "The Popular feed has been disabled by the administrator.": "人気の動画のページは管理者によって無効にされています。",
+ "carousel_go_to": "スライド`x`を表示",
+ "carousel_slide": "スライド{{current}} / 全{{total}}個中",
+ "carousel_skip": "画像のスライド表示をスキップ",
+ "toggle_theme": "テーマの切り替え"
}
diff --git a/locales/ko.json b/locales/ko.json
index c0257ee5..7611e8e7 100644
--- a/locales/ko.json
+++ b/locales/ko.json
@@ -460,7 +460,7 @@
"Music in this video": "동영상 속 음악",
"Artist: ": "아티스트: ",
"Download is disabled": "다운로드가 비활성화 되어있음",
- "Import YouTube playlist (.csv)": "유튜브 플레이리스트 가져오기 (.csv)",
+ "Import YouTube playlist (.csv)": "유튜브 재생목록 가져오기 (.csv)",
"playlist_button_add_items": "동영상 추가",
"channel_tab_podcasts_label": "팟캐스트",
"generic_button_delete": "삭제",
@@ -468,7 +468,16 @@
"generic_button_save": "저장",
"generic_button_cancel": "취소",
"generic_button_rss": "RSS",
- "channel_tab_releases_label": "출시",
+ "channel_tab_releases_label": "발매",
"generic_channels_count_0": "{{count}} 채널",
- "Import YouTube watch history (.json)": "유튜브 시청 기록 가져오기 (.json)"
+ "Import YouTube watch history (.json)": "유튜브 시청 기록 가져오기 (.json)",
+ "Add to playlist": "재생목록에 추가",
+ "Add to playlist: ": "재생목록에 추가: ",
+ "Answer": "답",
+ "The Popular feed has been disabled by the administrator.": "관리자가 인기 피드를 비활성화했습니다.",
+ "carousel_skip": "캐러셀 건너뛰기",
+ "carousel_go_to": "`x` 슬라이드로 이동",
+ "Search for videos": "비디오 검색",
+ "toggle_theme": "테마 전환",
+ "carousel_slide": "{{total}}의 슬라이드 {{current}}"
}
diff --git a/locales/lmo.json b/locales/lmo.json
new file mode 100644
index 00000000..9d2fe2a8
--- /dev/null
+++ b/locales/lmo.json
@@ -0,0 +1,232 @@
+{
+ "Add to playlist": "Giont a la playlist",
+ "generic_button_edit": "Modifega",
+ "generic_button_save": "Salva",
+ "LIVE": "EN DÌRETT",
+ "Shared `x` ago": "Compartiss `x` fa",
+ "View channel on YouTube": "Varda el canal sul YouTube",
+ "newest": "plù nöeuf",
+ "oldest": "plù végh",
+ "Search for videos": "Càuta dei video",
+ "The Popular feed has been disabled by the administrator.": "la seziùn Pupular la è stada disabilidada par l'amministratòr.",
+ "generic_channels_count": "{{count}} canal",
+ "generic_channels_count_plural": "{{count}} canai",
+ "popular": "pupular",
+ "generic_views_count": "{{count}} visualisazión",
+ "generic_views_count_plural": "{{count}} visualisazióni",
+ "generic_videos_count": "{{count}} video",
+ "generic_videos_count_plural": "{{count}} video",
+ "generic_playlists_count": "{{count}} playlist",
+ "generic_playlists_count_plural": "{{count}} playlist",
+ "generic_subscriptions_count": "{{count}} inscrizion",
+ "generic_subscriptions_count_plural": "{{count}} inscrizioni",
+ "generic_button_cancel": "Cançéla",
+ "generic_button_delete": "Scassa via",
+ "Unsubscribe": "Disinscriviti",
+ "Next page": "Pagina siguènt",
+ "Previous page": "Pagina indrèe",
+ "Clear watch history?": "Cançélar la istoria dei video vardàa?",
+ "New password": "Nöeva password",
+ "Import and Export Data": "Importazion ed esportazion dei dat",
+ "Import": "Importa",
+ "Import Invidious data": "Importa i dat de l'Invidious en el formàt JSON",
+ "Import YouTube subscriptions": "Importa le inscrizioni dal YouTube/OPML",
+ "Import YouTube playlist (.csv)": "Importa le playlist dal YouTube (.csv)",
+ "Import YouTube watch history (.json)": "Importa la istoria de visualizazzion dal YouTube (.json)",
+ "Import FreeTube subscriptions (.db)": "Importa le inscrizioni dal FreeTube (.db)",
+ "Import NewPipe data (.zip)": "importa i dat del NewPipe (.zip)",
+ "Export": "Esporta",
+ "Export subscriptions as OPML": "Esporta inscrizioni com OPML",
+ "Export data as JSON": "Esporta i dat de l'Invidious com JSON",
+ "Delete account?": "Eliminà 'l profil?",
+ "History": "Istoria",
+ "An alternative front-end to YouTube": "Una interfacia alternatif al YouTube",
+ "JavaScript license information": "Informaziòn su la licensa JavaScript",
+ "source": "font",
+ "Log in": "Và dent",
+ "Text CAPTCHA": "Tèst del CAPTCHA",
+ "Image CAPTCHA": "Imàgen del CAPTCHA",
+ "Sign In": "Ven denter",
+ "Register": "Registres",
+ "E-mail": "E-mail",
+ "Preferences": "Priferenze",
+ "preferences_category_player": "Priferenze del riprodutòr",
+ "preferences_quality_option_dash": "DASH (qualità adatif)",
+ "preferences_quality_option_hd720": "HD720",
+ "preferences_quality_option_medium": "Media",
+ "preferences_quality_option_small": "Picinina",
+ "preferences_quality_dash_option_auto": "Auto",
+ "preferences_quality_dash_option_best": "Meglior",
+ "preferences_quality_dash_option_worst": "Peggior",
+ "preferences_quality_dash_option_4320p": "4320p",
+ "preferences_quality_dash_option_2160p": "2160p",
+ "preferences_quality_dash_option_1440p": "1440p",
+ "preferences_quality_dash_option_1080p": "1080p",
+ "preferences_quality_dash_option_720p": "720p",
+ "preferences_quality_dash_option_480p": "480p",
+ "preferences_quality_dash_option_360p": "360p",
+ "preferences_quality_dash_option_240p": "240p",
+ "preferences_quality_dash_option_144p": "144p",
+ "reddit": "Reddit",
+ "invidious": "Invidious",
+ "light": "ciar",
+ "dark": "scur",
+ "preferences_category_misc": "Priferenze varie",
+ "preferences_category_subscription": "Priferenze de le inscrizioni",
+ "published": "data de publicazion",
+ "published - reverse": "data de publicazion - invertì",
+ "alphabetically": "orden alfabetegh",
+ "channel name": "nòm del canal",
+ "channel name - reverse": "nòm del canal - invertì",
+ "Enable web notifications": "Empisa le notifeghe da la red",
+ "`x` uploaded a video": "`x` la ghàa cargà un video",
+ "`x` is live": "`x` l'è 'n dirétt adés",
+ "preferences_category_data": "Priferenze dei dat",
+ "Import/export data": "Importa/esporta i dat",
+ "Change password": "Cambia la parola ciav",
+ "Manage subscriptions": "Organisa le inscrizioni",
+ "Manage tokens": "Organisa i tokens",
+ "Watch history": "Istoria dei video vardà",
+ "Delete account": "Cançéla 'l profil",
+ "Save preferences": "Salva priferenze",
+ "Subscription manager": "Manegia le inscrizioni",
+ "Token": "Token",
+ "tokens_count": "{{count}} token",
+ "tokens_count_plural": "{{count}} token",
+ "Import/export": "Importa/esporta",
+ "unsubscribe": "disinscriviti",
+ "subscriptions_unseen_notifs_count": "{{count}} notifega mia visualisada",
+ "subscriptions_unseen_notifs_count_plural": "{{count}} notifeghe mia visualisade",
+ "Log out": "Sortiss",
+ "Released under the AGPLv3 on Github.": "Publicà en el GitHub suta licenza AGPLv3.",
+ "Source available here.": "Codegh de la font disponivel chì.",
+ "View privacy policy.": "Varda la pulitega de la privacy.",
+ "Trending": "De moda",
+ "Public": "Publico",
+ "Unlisted": "Non en lista",
+ "Private": "Privàt",
+ "View all playlists": "Varda tute le playlist",
+ "Updated `x` ago": "Giurnà `x` fa",
+ "Delete playlist `x`?": "Cançéla la playlist `x`?",
+ "Delete playlist": "Cançéla playlist",
+ "Create playlist": "Crea playlist",
+ "Title": "Titel",
+ "Playlist privacy": "Privacy de la playlist",
+ "Editing playlist `x`": "Modifega playlist `x`",
+ "playlist_button_add_items": "Gionta video",
+ "Show more": "Varda plù",
+ "Show less": "Varda mèn",
+ "Watch on YouTube": "Varda sul YouTube",
+ "Switch Invidious Instance": "Cambia la instanza del Invidious",
+ "search_message_no_results": "Non è stat truvà nigun resultat.",
+ "Cebuano": "Cebuano",
+ "Chinese (Traditional)": "Cines (Tradizional)",
+ "Corsican": "Còrso",
+ "Croatian": "Cruat",
+ "Georgian": "Georgian",
+ "Gujarati": "Gujarati",
+ "Hawaiian": "Hawaiian",
+ "Kurdish": "Curd",
+ "Latin": "Latin",
+ "Latvian": "Letton",
+ "Lithuanian": "Lituan",
+ "Malay": "Males",
+ "Maltese": "Maltes",
+ "Mongolian": "móngol",
+ "Persian": "Persian",
+ "Polish": "Polacch",
+ "Portuguese": "Portoghes",
+ "Romanian": "Romen",
+ "Scottish Gaelic": "Gaelich Scusses",
+ "Spanish (Latin America)": "Spagnöl (America do Sùd)",
+ "Thai": "Thai",
+ "Western Frisian": "Frisian do ponente",
+ "Basque": "Basco",
+ "Chinese (Simplified)": "Cines (Semplificà)",
+ "Haitian Creole": "Creolo de Haiti",
+ "Galician": "Galiçian",
+ "Hebrew": "Ebraich",
+ "Korean": "Corean",
+ "View playlist on YouTube": "Varda la playlist sul YouTube",
+ "Southern Sotho": "Sotho do Sùd",
+ "generic_button_rss": "RSS",
+ "Welsh": "Galés",
+ "Answer": "Resposta",
+ "New passwords must match": "Le nöeve password la deven esere uguai",
+ "Authorize token?": "Autorisà 'l token?",
+ "Authorize token for `x`?": "Autorisà 'l token par `x`?",
+ "Yes": "Sì",
+ "No": "No",
+ "Export subscriptions as OPML (for NewPipe & FreeTube)": "Esporta inscrizioni com OPML (par 'l NewPipe e 'l FreeTube)",
+ "Log in/register": "Va dent/Registres",
+ "User ID": "ID utent",
+ "Password": "Parola ciav",
+ "Time (h:mm:ss):": "Temp (h:mm:ss):",
+ "Import NewPipe subscriptions (.json)": "importa le inscrizioni dal NewPipe (.json)",
+ "youtube": "YouTube",
+ "alphabetically - reverse": "orden alfabetegh - invertì",
+ "preferences_category_visual": "Priferenze grafeghe",
+ "Clear watch history": "Scompartiss la istoria dei video vardà",
+ "preferences_category_admin": "Priferenze de l'amministratòr",
+ "Token manager": "Manegia i token",
+ "Subscriptions": "Inscrizioni",
+ "search": "cerca",
+ "View JavaScript license information.": "Varda le informazion su la licenza JavaScript.",
+ "search_message_change_filters_or_query": "Ti pödi pruà a slargà la reçerca e/or a cangià i filter.",
+ "generic_subscribers_count": "{{count}} inscritt",
+ "generic_subscribers_count_plural": "{{count}} inscriti",
+ "Subscribe": "Inscriviti",
+ "last": "ùltim",
+ "Add to playlist: ": "Giont a la playlist: ",
+ "preferences_autoplay_label": "Reproduzion automatega: ",
+ "preferences_continue_label": "Reproduzion seguént preimpostà: ",
+ "preferences_continue_autoplay_label": "Fa partì en automatico el video seguént: ",
+ "preferences_listen_label": "Modalità de sól audio preimpostà: ",
+ "preferences_local_label": "Proxy par i video: ",
+ "preferences_watch_history_label": "Ativà la istoria de reproduzion: ",
+ "preferences_speed_label": "Velocità preimpostà: ",
+ "preferences_volume_label": "Volume del reprodutòr: ",
+ "preferences_region_label": "Nazion del contenut: ",
+ "Dark mode: ": "Tema scur ",
+ "preferences_dark_mode_label": "Tema: ",
+ "preferences_thin_mode_label": "Modalità legera: ",
+ "preferences_automatic_instance_redirect_label": "Reindirizazzion automatega de la instansa (rivèrt a redirect.invidious.io): ",
+ "Hide annotations": "Piaca le notazioni",
+ "Show annotations": "Mostra le notazioni",
+ "Family friendly? ": "Adàt a tüti? ",
+ "Whitelisted regions: ": "Regioni en lista bianca: ",
+ "Blacklisted regions: ": "Regioni en lista negher ",
+ "Artist: ": "Artista: ",
+ "Song: ": "Cansòn ",
+ "Album: ": "Album: ",
+ "View YouTube comments": "Varda i comment dal YouTube",
+ "Password cannot be empty": "La parola ciav la no po miga esser voeut",
+ "channel:`x`": "Canal:`x`",
+ "Bangla": "Bengales",
+ "Hausa": "Hausa",
+ "Hindi": "Hindi",
+ "Hmong": "Hmong",
+ "Igbo": "Igbo",
+ "Javanese": "Javanese",
+ "Kannada": "Kannada",
+ "Kazakh": "Kazach",
+ "Khmer": "Khmer",
+ "Kyrgyz": "Kirghiz",
+ "Lao": "Lao",
+ "Luxembourgish": "Lussemburghes",
+ "Macedonian": "Macedon",
+ "Malagasy": "Malagascio",
+ "Malayalam": "Malayalam",
+ "Maori": "Maori",
+ "Marathi": "Marati",
+ "Nepali": "Nepales",
+ "Nyanja": "Nyanja",
+ "Pashto": "Pashtu",
+ "Punjabi": "Punjabi",
+ "Samoan": "Samoan",
+ "Standard YouTube license": "licensa predefinida de Youtube",
+ "License: ": "Licensa: ",
+ "Music in this video": "Musica en sto video",
+ "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Ué! Sembra che ti la g'hà desabilitàa el JavaScript. Schisa chì para vardà i comment, ma cunsidera che peul vörse 'n po plu de temp a cargà.",
+ "preferences_video_loop_label": "Reproduci sèmper: "
+}
diff --git a/locales/nl.json b/locales/nl.json
index a30bc5b5..d495a2d1 100644
--- a/locales/nl.json
+++ b/locales/nl.json
@@ -487,5 +487,14 @@
"generic_button_delete": "Verwijderen",
"Import YouTube playlist (.csv)": "YouTube-afspeellijst importeren (.csv)",
"Standard YouTube license": "Standaard YouTube-licentie",
- "Import YouTube watch history (.json)": "YouTube-kijkgeschiedenis importeren (.json)"
+ "Import YouTube watch history (.json)": "YouTube-kijkgeschiedenis importeren (.json)",
+ "Add to playlist": "Aan afspeellijst toevoegen",
+ "The Popular feed has been disabled by the administrator.": "De Populaire feed werd uitgeschakeld door een beheerder.",
+ "carousel_slide": "Dia {{current}} van {{total}}",
+ "carousel_go_to": "Naar dia `x` gaan",
+ "Add to playlist: ": "Aan afspeellijst toevoegen: ",
+ "Answer": "Antwoorden",
+ "Search for videos": "Naar video's zoeken",
+ "carousel_skip": "Carousel overslaan",
+ "toggle_theme": "Thema omschakelen"
}
diff --git a/locales/pl.json b/locales/pl.json
index 0d18e90a..f24e9766 100644
--- a/locales/pl.json
+++ b/locales/pl.json
@@ -21,13 +21,13 @@
"Import and Export Data": "Import i eksport danych",
"Import": "Import",
"Import Invidious data": "Importuj dane JSON Invidious",
- "Import YouTube subscriptions": "Importuj subskrybcje z YouTube/OPML",
- "Import FreeTube subscriptions (.db)": "Importuj subskrybcje z FreeTube (.db)",
- "Import NewPipe subscriptions (.json)": "Importuj subskrybcje z NewPipe (.json)",
+ "Import YouTube subscriptions": "Importuj subskrypcje YouTube w formacie CSV lub OPML",
+ "Import FreeTube subscriptions (.db)": "Importuj subskrypcje FreeTube (.db)",
+ "Import NewPipe subscriptions (.json)": "Importuj subskrypcje NewPipe (.json)",
"Import NewPipe data (.zip)": "Importuj dane NewPipe (.zip)",
"Export": "Eksport",
- "Export subscriptions as OPML": "Eksportuj subskrybcje jako OPML",
- "Export subscriptions as OPML (for NewPipe & FreeTube)": "Eksportuj subskrybcje jako OPML (dla NewPipe i FreeTube)",
+ "Export subscriptions as OPML": "Eksportuj subskrypcje jako OPML",
+ "Export subscriptions as OPML (for NewPipe & FreeTube)": "Eksportuj subskrypcje jako OPML (dla NewPipe i FreeTube)",
"Export data as JSON": "Eksportuj dane Invidious jako JSON",
"Delete account?": "Usunąć konto?",
"History": "Historia",
@@ -73,7 +73,7 @@
"preferences_thin_mode_label": "Tryb minimalny: ",
"preferences_category_misc": "Różne preferencje",
"preferences_automatic_instance_redirect_label": "Automatycznie przekierowanie instancji (powrót do redirect.invidious.io): ",
- "preferences_category_subscription": "Preferencje subskrybcji",
+ "preferences_category_subscription": "Preferencje subskrypcji",
"preferences_annotations_subscribed_label": "Domyślnie wyświetlaj adnotacje dla subskrybowanych kanałów: ",
"Redirect homepage to feed: ": "Przekieruj stronę główną do subskrybcji: ",
"preferences_max_results_label": "Liczba filmów widoczna na stronie subskrybcji: ",
@@ -95,7 +95,7 @@
"Clear watch history": "Wyczyść historię",
"Import/export data": "Import/Eksport danych",
"Change password": "Zmień hasło",
- "Manage subscriptions": "Organizuj subskrybcje",
+ "Manage subscriptions": "Organizuj subskrypcje",
"Manage tokens": "Zarządzaj tokenami",
"Watch history": "Historia",
"Delete account": "Usuń konto",
@@ -115,7 +115,7 @@
"Import/export": "Import/Eksport",
"unsubscribe": "odsubskrybuj",
"revoke": "cofnij",
- "Subscriptions": "Subskrybcje",
+ "Subscriptions": "Subskrypcje",
"search": "szukaj",
"Log out": "Wyloguj",
"Source available here.": "Kod źródłowy dostępny tutaj.",
@@ -505,5 +505,13 @@
"generic_channels_count_1": "{{count}} kanały",
"generic_channels_count_2": "{{count}} kanałów",
"Import YouTube watch history (.json)": "Importuj historię oglądania z YouTube (.json)",
- "toggle_theme": "Przełącz motyw"
+ "toggle_theme": "Przełącz motyw",
+ "The Popular feed has been disabled by the administrator.": "Kanał Popularne został wyłączony przez administratora.",
+ "Answer": "Odpowiedź",
+ "Search for videos": "Wyszukaj filmy",
+ "Add to playlist": "Dodaj do playlisty",
+ "Add to playlist: ": "Dodaj do playlisty: ",
+ "carousel_slide": "Slajd {{current}} z {{total}}",
+ "carousel_skip": "Pomiń karuzelę",
+ "carousel_go_to": "Przejdź do slajdu `x`"
}
diff --git a/locales/pt-BR.json b/locales/pt-BR.json
index af14eb29..1637b5d8 100644
--- a/locales/pt-BR.json
+++ b/locales/pt-BR.json
@@ -1,27 +1,27 @@
{
"LIVE": "AO VIVO",
- "Shared `x` ago": "Compartilhado `x` atrás",
+ "Shared `x` ago": "Publicado há `x`",
"Unsubscribe": "Cancelar inscrição",
"Subscribe": "Inscrever-se",
"View channel on YouTube": "Ver canal no YouTube",
- "View playlist on YouTube": "Ver lista de reprodução no YouTube",
+ "View playlist on YouTube": "Ver playlist no YouTube",
"newest": "mais recentes",
"oldest": "mais antigos",
"popular": "populares",
- "last": "último",
+ "last": "últimos",
"Next page": "Próxima página",
"Previous page": "Página anterior",
- "Clear watch history?": "Limpar histórico de reprodução?",
+ "Clear watch history?": "Limpar histórico de exibição?",
"New password": "Nova senha",
- "New passwords must match": "Nova senha deve ser igual",
- "Authorize token?": "Autorizar o token?",
- "Authorize token for `x`?": "Autorizar o token para `x`?",
+ "New passwords must match": "As senhas devem ser iguais",
+ "Authorize token?": "Autorizar token?",
+ "Authorize token for `x`?": "Autorizar token para `x`?",
"Yes": "Sim",
"No": "Não",
- "Import and Export Data": "Importar e Exportar Dados",
+ "Import and Export Data": "Importar/exportar dados",
"Import": "Importar",
- "Import Invidious data": "Importar dados em JSON do Invidious",
- "Import YouTube subscriptions": "Importar inscrições do YouTube/OPML",
+ "Import Invidious data": "Importar dados JSON do Invidious",
+ "Import YouTube subscriptions": "Importar inscrições no formato CSV ou OPML do YouTube",
"Import FreeTube subscriptions (.db)": "Importar inscrições do FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importar inscrições do NewPipe (.json)",
"Import NewPipe data (.zip)": "Importar dados do NewPipe (.zip)",
@@ -32,49 +32,49 @@
"Delete account?": "Excluir conta?",
"History": "Histórico",
"An alternative front-end to YouTube": "Uma interface alternativa para o YouTube",
- "JavaScript license information": "Informação de licença do JavaScript",
- "source": "código-fonte",
- "Log in": "Entrar",
- "Log in/register": "Entrar/Registrar",
+ "JavaScript license information": "Informações sobre a licença do JavaScript",
+ "source": "fonte",
+ "Log in": "Fazer login",
+ "Log in/register": "Fazer login/criar conta",
"User ID": "Usuário",
"Password": "Senha",
"Time (h:mm:ss):": "Hora (h:mm:ss):",
- "Text CAPTCHA": "CAPTCHA em texto",
- "Image CAPTCHA": "CAPTCHA em imagem",
+ "Text CAPTCHA": "Mudar para um desafio de texto",
+ "Image CAPTCHA": "Mudar para um desafio visual",
"Sign In": "Entrar",
- "Register": "Registrar",
+ "Register": "Criar conta",
"E-mail": "E-mail",
"Preferences": "Preferências",
- "preferences_category_player": "Preferências do reprodutor",
+ "preferences_category_player": "Preferências de reprodução",
"preferences_video_loop_label": "Repetir sempre: ",
"preferences_autoplay_label": "Reprodução automática: ",
- "preferences_continue_label": "Sempre reproduzir próximo: ",
+ "preferences_continue_label": "Reproduzir a seguir, por padrão: ",
"preferences_continue_autoplay_label": "Reproduzir próximo vídeo automaticamente: ",
"preferences_listen_label": "Apenas áudio por padrão: ",
"preferences_local_label": "Usar proxy nos vídeos: ",
"preferences_speed_label": "Velocidade padrão: ",
"preferences_quality_label": "Qualidade de vídeo preferida: ",
"preferences_volume_label": "Volume de reprodução: ",
- "preferences_comments_label": "Preferência de comentários: ",
+ "preferences_comments_label": "Comentários padrão: ",
"youtube": "YouTube",
"reddit": "Reddit",
- "preferences_captions_label": "Preferência de legendas: ",
+ "preferences_captions_label": "Legendas padrão: ",
"Fallback captions: ": "Legendas alternativas: ",
"preferences_related_videos_label": "Mostrar vídeos relacionados: ",
"preferences_annotations_label": "Sempre mostrar anotações: ",
- "preferences_extend_desc_label": "Estenda automaticamente a descrição do vídeo: ",
+ "preferences_extend_desc_label": "Expandir automaticamente a descrição do vídeo: ",
"preferences_vr_mode_label": "Vídeos interativos de 360 graus (requer WebGL): ",
"preferences_category_visual": "Preferências visuais",
- "preferences_player_style_label": "Estilo do tocador: ",
+ "preferences_player_style_label": "Estilo de reprodução: ",
"Dark mode: ": "Modo escuro: ",
"preferences_dark_mode_label": "Tema: ",
"dark": "escuro",
"light": "claro",
"preferences_thin_mode_label": "Modo compacto: ",
"preferences_category_misc": "Preferências diversas",
- "preferences_automatic_instance_redirect_label": "Redirecionamento de instância automática (fallback para redirect.invidious.io): ",
+ "preferences_automatic_instance_redirect_label": "Redirecionamento automático de instâncias (alternativa para redirect.invidious.io): ",
"preferences_category_subscription": "Preferências de inscrições",
- "preferences_annotations_subscribed_label": "Sempre mostrar anotações dos vídeos de canais inscritos: ",
+ "preferences_annotations_subscribed_label": "Mostrar anotações por padrão para canais inscritos? ",
"Redirect homepage to feed: ": "Redirecionar página inicial para o feed: ",
"preferences_max_results_label": "Número de vídeos no feed: ",
"preferences_sort_label": "Ordenar vídeos por: ",
@@ -84,30 +84,30 @@
"alphabetically - reverse": "alfabética - ordem inversa",
"channel name": "nome do canal",
"channel name - reverse": "nome do canal - ordem inversa",
- "Only show latest video from channel: ": "Mostrar apenas o vídeo mais recente do canal: ",
- "Only show latest unwatched video from channel: ": "Mostrar apenas o vídeo mais recente não visualizado do canal: ",
- "preferences_unseen_only_label": "Mostrar apenas vídeos não visualizados: ",
- "preferences_notifications_only_label": "Mostrar apenas notificações (se existentes): ",
- "Enable web notifications": "Ativar notificações pela web",
- "`x` uploaded a video": "`x` publicou um novo vídeo",
+ "Only show latest video from channel: ": "Mostrar apenas vídeos mais recentes do canal: ",
+ "Only show latest unwatched video from channel: ": "Mostrar apenas vídeos mais recentes não assistido do canal: ",
+ "preferences_unseen_only_label": "Mostrar apenas vídeos não assistido: ",
+ "preferences_notifications_only_label": "Mostrar apenas notificações (se houver): ",
+ "Enable web notifications": "Ativar notificações da Web",
+ "`x` uploaded a video": "`x` publicou um vídeo",
"`x` is live": "`x` está ao vivo",
"preferences_category_data": "Preferências de dados",
- "Clear watch history": "Limpar histórico de reprodução",
- "Import/export data": "Importar/Exportar dados",
+ "Clear watch history": "Limpar histórico de exibição",
+ "Import/export data": "Importar/exportar dados",
"Change password": "Alterar senha",
"Manage subscriptions": "Gerenciar inscrições",
"Manage tokens": "Gerenciar tokens",
- "Watch history": "Histórico de reprodução",
- "Delete account": "Apagar sua conta",
+ "Watch history": "Histórico de exibição",
+ "Delete account": "Excluir conta",
"preferences_category_admin": "Preferências de administrador",
- "preferences_default_home_label": "Página de início padrão: ",
- "preferences_feed_menu_label": "Menu do feed: ",
- "preferences_show_nick_label": "Mostrar o nickname no topo: ",
- "Top enabled: ": "Habilitar destaques: ",
- "CAPTCHA enabled: ": "Habilitar CAPTCHA: ",
- "Login enabled: ": "Habilitar login: ",
- "Registration enabled: ": "Habilitar registro: ",
- "Report statistics: ": "Habilitar estatísticas: ",
+ "preferences_default_home_label": "Página inicial padrão: ",
+ "preferences_feed_menu_label": "Guias de feed preferidos: ",
+ "preferences_show_nick_label": "Mostrar nome de usuário na parte superior: ",
+ "Top enabled: ": "Destaques ativados: ",
+ "CAPTCHA enabled: ": "CAPTCHA ativado: ",
+ "Login enabled: ": "Fazer login ativado: ",
+ "Registration enabled: ": "Criar conta ativado: ",
+ "Report statistics: ": "Relatório de estatísticas: ",
"Save preferences": "Salvar preferências",
"Subscription manager": "Gerenciador de inscrições",
"Token manager": "Gerenciador de tokens",
@@ -115,24 +115,24 @@
"tokens_count_0": "{{count}} token",
"tokens_count_1": "{{count}} tokens",
"tokens_count_2": "{{count}} tokens",
- "Import/export": "Importar/Exportar",
+ "Import/export": "Importar/exportar",
"unsubscribe": "cancelar inscrição",
"revoke": "revogar",
"Subscriptions": "Inscrições",
- "search": "Pesquisar",
+ "search": "pesquisar",
"Log out": "Sair",
"Released under the AGPLv3 on Github.": "Lançado sob a AGPLv3 no GitHub.",
"Source available here.": "Código-fonte disponível aqui.",
- "View JavaScript license information.": "Ver informações da licença do JavaScript.",
- "View privacy policy.": "Ver a política de privacidade.",
- "Trending": "Tendências",
+ "View JavaScript license information.": "Informações de licença JavaScript.",
+ "View privacy policy.": "Política de privacidade.",
+ "Trending": "Em alta",
"Public": "Público",
"Unlisted": "Não listado",
"Private": "Privado",
- "View all playlists": "Mostrar todas listas de reprodução",
+ "View all playlists": "Ver todas as playlists",
"Updated `x` ago": "Atualizado `x` atrás",
- "Delete playlist `x`?": "Apagar a playlist `x`?",
- "Delete playlist": "Apagar playlist",
+ "Delete playlist `x`?": "Excluir playlist `x`?",
+ "Delete playlist": "Excluir playlist",
"Create playlist": "Criar playlist",
"Title": "Título",
"Playlist privacy": "Privacidade da playlist",
@@ -140,24 +140,24 @@
"Show more": "Mostrar mais",
"Show less": "Mostrar menos",
"Watch on YouTube": "Assistir no YouTube",
- "Switch Invidious Instance": "Mudar a instância do Invidious",
+ "Switch Invidious Instance": "Alterar instância Invidious",
"Hide annotations": "Ocultar anotações",
"Show annotations": "Mostrar anotações",
"Genre: ": "Gênero: ",
"License: ": "Licença: ",
"Family friendly? ": "Filtrar conteúdo impróprio: ",
"Wilson score: ": "Pontuação de Wilson: ",
- "Engagement: ": "Empenho: ",
+ "Engagement: ": "Engajamento: ",
"Whitelisted regions: ": "Regiões permitidas: ",
"Blacklisted regions: ": "Regiões bloqueadas: ",
- "Shared `x`": "Compartilhado `x`",
+ "Shared `x`": "Publicado em `x`",
"Premieres in `x`": "Estreia em `x`",
"Premieres `x`": "Estreia `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.": "Oi! Parece que seu JavaScript está desativado. Clique aqui para ver os comentários, entretanto eles podem levar um pouco mais de tempo para carregar.",
+ "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Olá! Parece que você está com o JavaScript desativado. Clique aqui para ver os comentários, mas lembre-se de que eles podem demorar um pouco mais para carregar.",
"View YouTube comments": "Ver comentários no YouTube",
"View more comments on Reddit": "Ver mais comentários no Reddit",
"View `x` comments": {
- "([^.,0-9]|^)1([^.,0-9]|$)": "Ver `x` comentários",
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Ver `x` comentário",
"": "Ver `x` comentários"
},
"View Reddit comments": "Ver comentários no Reddit",
@@ -166,7 +166,7 @@
"Incorrect password": "Senha incorreta",
"Wrong answer": "Resposta incorreta",
"Erroneous CAPTCHA": "CAPTCHA inválido",
- "CAPTCHA is a required field": "O CAPTCHA é um campo obrigatório",
+ "CAPTCHA is a required field": "CAPTCHA é um campo obrigatório",
"User ID is a required field": "O nome de usuário é um campo obrigatório",
"Password is a required field": "A senha é um campo obrigatório",
"Wrong username or password": "Nome de usuário ou senha inválidos",
@@ -175,17 +175,17 @@
"Please log in": "Por favor, inicie sua sessão",
"Invidious Private Feed for `x`": "Feed Privado do Invidious para `x`",
"channel:`x`": "canal: `x`",
- "Deleted or invalid channel": "Este canal foi apagado ou é inválido",
+ "Deleted or invalid channel": "Canal excluído ou inválido",
"This channel does not exist.": "Este canal não existe.",
"Could not get channel info.": "Não foi possível obter as informações do canal.",
"Could not fetch comments": "Não foi possível obter os comentários",
"`x` ago": "`x` atrás",
"Load more": "Carregar mais",
"Could not create mix.": "Não foi possível criar o mix.",
- "Empty playlist": "Lista de reprodução vazia",
- "Not a playlist.": "Não é uma lista de reprodução.",
- "Playlist does not exist.": "A lista de reprodução não existe.",
- "Could not pull trending pages.": "Não foi possível obter as páginas dos vídeos em alta.",
+ "Empty playlist": "Playlist vazia",
+ "Not a playlist.": "Não é uma playlist.",
+ "Playlist does not exist.": "A playlist não existe.",
+ "Could not pull trending pages.": "Não foi possível obter as páginas de vídeos em alta.",
"Hidden field \"challenge\" is a required field": "O campo oculto \"desafio\" é obrigatório",
"Hidden field \"token\" is a required field": "O campo oculto \"token\" é obrigatório",
"Erroneous challenge": "Desafio inválido",
@@ -319,87 +319,87 @@
"generic_count_seconds_0": "{{count}} segundo",
"generic_count_seconds_1": "{{count}} segundos",
"generic_count_seconds_2": "{{count}} segundos",
- "Fallback comments: ": "Comentários alternativos: ",
+ "Fallback comments: ": "Alternativa para comentários: ",
"Popular": "Populares",
- "Search": "Procurar",
- "Top": "No topo",
+ "Search": "Pesquisar",
+ "Top": "Destaques",
"About": "Sobre",
"Rating: ": "Avaliação: ",
"preferences_locale_label": "Idioma: ",
- "View as playlist": "Ver como lista de reprodução",
+ "View as playlist": "Ver como playlist",
"Default": "Padrão",
"Music": "Músicas",
"Gaming": "Jogos",
"News": "Notícias",
"Movies": "Filmes",
- "Download": "Baixar",
+ "Download": "Download",
"Download as: ": "Baixar como: ",
"%A %B %-d, %Y": "%A %-d %B %Y",
"(edited)": "(editado)",
"YouTube comment permalink": "Link permanente do comentário no YouTube",
"permalink": "Link permanente",
- "`x` marked it with a ❤": "`x` foi marcado como ❤",
+ "`x` marked it with a ❤": "`x` foi marcado com um ❤",
"Audio mode": "Modo de áudio",
"Video mode": "Modo de vídeo",
"channel_tab_videos_label": "Vídeos",
- "Playlists": "Listas de reprodução",
+ "Playlists": "Playlists",
"channel_tab_community_label": "Comunidade",
- "search_filters_sort_option_relevance": "relevância",
- "search_filters_sort_option_rating": "avaliação",
- "search_filters_sort_option_date": "data",
- "search_filters_sort_option_views": "visualizações",
- "search_filters_type_label": "content_type",
- "search_filters_duration_label": "duração",
- "search_filters_features_label": "recursos",
- "search_filters_sort_label": "ordenar",
- "search_filters_date_option_hour": "hora",
- "search_filters_date_option_today": "hoje",
- "search_filters_date_option_week": "semana",
- "search_filters_date_option_month": "mês",
- "search_filters_date_option_year": "ano",
- "search_filters_type_option_video": "vídeo",
+ "search_filters_sort_option_relevance": "Relevância",
+ "search_filters_sort_option_rating": "Avaliação",
+ "search_filters_sort_option_date": "Data de publicação",
+ "search_filters_sort_option_views": "Visualizações",
+ "search_filters_type_label": "Tipo",
+ "search_filters_duration_label": "Duração",
+ "search_filters_features_label": "Características",
+ "search_filters_sort_label": "Ordenar por",
+ "search_filters_date_option_hour": "Últimas horas",
+ "search_filters_date_option_today": "Hoje",
+ "search_filters_date_option_week": "Esta semana",
+ "search_filters_date_option_month": "Este mês",
+ "search_filters_date_option_year": "Este ano",
+ "search_filters_type_option_video": "Vídeo",
"search_filters_type_option_channel": "Canal",
- "search_filters_type_option_playlist": "playlist",
- "search_filters_type_option_movie": "filme",
- "search_filters_type_option_show": "show",
- "search_filters_features_option_hd": "hd",
- "search_filters_features_option_subtitles": "legendas",
- "search_filters_features_option_c_commons": "creative_commons",
- "search_filters_features_option_three_d": "3d",
- "search_filters_features_option_live": "ao vivo",
- "search_filters_features_option_four_k": "4k",
- "search_filters_features_option_location": "localização",
- "search_filters_features_option_hdr": "hdr",
+ "search_filters_type_option_playlist": "Playlist",
+ "search_filters_type_option_movie": "Filme",
+ "search_filters_type_option_show": "Séries",
+ "search_filters_features_option_hd": "HD",
+ "search_filters_features_option_subtitles": "Legendas",
+ "search_filters_features_option_c_commons": "Creative Commons",
+ "search_filters_features_option_three_d": "3D",
+ "search_filters_features_option_live": "AO VIVO",
+ "search_filters_features_option_four_k": "4K",
+ "search_filters_features_option_location": "Localização",
+ "search_filters_features_option_hdr": "HDR",
"Current version: ": "Versão atual: ",
"next_steps_error_message": "Depois disso, você deve tentar: ",
- "next_steps_error_message_refresh": "Atualizar",
+ "next_steps_error_message_refresh": "Recarregar",
"next_steps_error_message_go_to_youtube": "Ir para o YouTube",
- "footer_donate_page": "Doe",
- "adminprefs_modified_source_code_url_label": "URL para repositório de código fonte modificado",
+ "footer_donate_page": "Doar",
+ "adminprefs_modified_source_code_url_label": "URL para o repositório do código-fonte modificado",
"search_filters_duration_option_long": "Longo (> 20 minutos)",
"search_filters_duration_option_short": "Curto (< 4 minutos)",
"footer_documentation": "Documentação",
- "footer_source_code": "Código fonte",
- "footer_original_source_code": "Código fonte original",
+ "footer_source_code": "Código-fonte",
+ "footer_original_source_code": "Código-fonte original",
"footer_modfied_source_code": "Código-fonte modificado",
- "preferences_quality_dash_label": "Qualidade de vídeo do painel preferida: ",
+ "preferences_quality_dash_label": "Qualidade de vídeo DASH preferida: ",
"preferences_region_label": "País do conteúdo: ",
"preferences_quality_dash_option_4320p": "4320p",
"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_playlists_count_0": "{{count}} playlist",
+ "generic_playlists_count_1": "{{count}} playlists",
+ "generic_playlists_count_2": "{{count}} playlists",
"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",
+ "subscriptions_unseen_notifs_count_0": "{{count}} notificação não visualizada",
+ "subscriptions_unseen_notifs_count_1": "{{count}} notificações não visualizadas",
+ "subscriptions_unseen_notifs_count_2": "{{count}} notificações não visualizadas",
"comments_view_x_replies_0": "Ver {{count}} resposta",
"comments_view_x_replies_1": "Ver {{count}} respostas",
"comments_view_x_replies_2": "Ver {{count}} respostas",
@@ -407,14 +407,14 @@
"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: ",
+ "crash_page_before_reporting": "Antes de informar um erro, verifique se você:",
+ "preferences_save_player_pos_label": "Salvar posição de reprodução: ",
"search_filters_features_option_purchased": "Comprado",
"crash_page_refresh": "tentou <a href=\"`x`\">recarregar a página</a>",
"crash_page_switch_instance": "tentou <a href=\"`x`\">usar outra instância</a>",
"crash_page_search_issue": "procurou por um <a href=\"`x`\">erro existente no GitHub</a>",
"crash_page_report_issue": "Se nenhuma opção acima ajudou, por favor <a href=\"`x`\">abra um novo problema no Github</a> (preferencialmente em inglês) e inclua o seguinte texto (NÃO traduza):",
- "crash_page_read_the_faq": "leia as <a href=\"`x`\">Perguntas frequentes (FAQ)</a>",
+ "crash_page_read_the_faq": "leu as <a href=\"`x`\">Perguntas frequentes (FAQ)</a>",
"generic_views_count_0": "{{count}} visualização",
"generic_views_count_1": "{{count}} visualizações",
"generic_views_count_2": "{{count}} visualizações",
@@ -422,8 +422,8 @@
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_small": "Pequeno",
"preferences_quality_dash_option_auto": "Auto",
- "preferences_quality_dash_option_best": "Melhor",
- "preferences_quality_dash_option_worst": "Pior",
+ "preferences_quality_dash_option_best": "Melhor qualidade",
+ "preferences_quality_dash_option_worst": "Pior qualidade",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_1080p": "1080p",
@@ -435,17 +435,17 @@
"invidious": "Invidious",
"preferences_quality_option_medium": "Médio",
"search_filters_features_option_three_sixty": "360°",
- "none": "none",
+ "none": "nenhum",
"videoinfo_watch_on_youTube": "Assistir no YouTube",
- "videoinfo_youTube_embed_link": "Embutir",
- "videoinfo_invidious_embed_link": "Link Embutido",
+ "videoinfo_youTube_embed_link": "Embed",
+ "videoinfo_invidious_embed_link": "Embed link",
"download_subtitles": "Legendas - `x` (.vtt)",
- "user_created_playlists": "`x` listas de reprodução criadas",
- "user_saved_playlists": "`x` listas de reprodução salvas",
+ "user_created_playlists": "`x` playlists criadas",
+ "user_saved_playlists": "`x` playlists salvas",
"Video unavailable": "Vídeo indisponível",
"videoinfo_started_streaming_x_ago": "Iniciou a transmissão a `x`",
"search_filters_title": "Filtro",
- "preferences_watch_history_label": "Ative o histórico de exibição: ",
+ "preferences_watch_history_label": "Ativar histórico de exibição: ",
"search_message_no_results": "Nenhum resultado encontrado.",
"search_message_change_filters_or_query": "Tente ampliar sua consulta de pesquisa e/ou alterar os filtros.",
"English (United Kingdom)": "Inglês (Reino Unido)",
@@ -465,7 +465,7 @@
"Portuguese (Brazil)": "Português (Brasil)",
"Russian (auto-generated)": "Russo (gerado automaticamente)",
"Vietnamese (auto-generated)": "Vietnamita (gerado automaticamente)",
- "search_filters_date_label": "Data de upload",
+ "search_filters_date_label": "Data de publicação",
"search_filters_date_option_none": "Qualquer data",
"Dutch (auto-generated)": "Holandês (gerado automaticamente)",
"French (auto-generated)": "Francês (gerado automaticamente)",
@@ -479,21 +479,21 @@
"Turkish (auto-generated)": "Turco (gerado automaticamente)",
"search_filters_duration_option_medium": "Médio (4 - 20 minutos)",
"search_filters_features_option_vr180": "VR180",
- "Popular enabled: ": "Popular habilitado: ",
+ "Popular enabled: ": "Página \"Populares\" ativada: ",
"error_video_not_in_playlist": "O vídeo solicitado não existe nesta playlist. <a href=\"`x`\">Clique aqui para acessar a página inicial da playlist.</a>",
"channel_tab_channels_label": "Canais",
- "channel_tab_playlists_label": "Listas de reprodução",
- "channel_tab_shorts_label": "Curtos",
- "channel_tab_streams_label": "Ao Vivo",
+ "channel_tab_playlists_label": "Playlists",
+ "channel_tab_shorts_label": "Shorts",
+ "channel_tab_streams_label": "Transmissão ao vivo",
"Music in this video": "Música neste vídeo",
"Artist: ": "Artista: ",
"Album: ": "Álbum: ",
"Standard YouTube license": "Licença padrão do YouTube",
"Song: ": "Música: ",
- "Channel Sponsor": "Patrocinador do Canal",
- "Download is disabled": "Download está desabilitado",
- "Import YouTube playlist (.csv)": "Importar lista de reprodução do YouTube (.csv)",
- "generic_button_delete": "Apagar",
+ "Channel Sponsor": "Patrocinador do canal",
+ "Download is disabled": "Download indisponível",
+ "Import YouTube playlist (.csv)": "Importar playlist do YouTube (.csv)",
+ "generic_button_delete": "Excluir",
"generic_button_save": "Salvar",
"generic_button_edit": "Editar",
"playlist_button_add_items": "Adicionar vídeos",
@@ -504,6 +504,14 @@
"generic_channels_count_0": "{{count}} canal",
"generic_channels_count_1": "{{count}} canais",
"generic_channels_count_2": "{{count}} canais",
- "Import YouTube watch history (.json)": "Importar histórico de reprodução do YouTube (.json)",
- "toggle_theme": "Alternar Tema"
+ "Import YouTube watch history (.json)": "Importar histórico de exibição do YouTube (.json)",
+ "toggle_theme": "Alternar tema",
+ "Add to playlist": "Adicionar à playlist",
+ "Add to playlist: ": "Adicionar à playlist: ",
+ "Search for videos": "Pesquisar vídeos",
+ "The Popular feed has been disabled by the administrator.": "O feed \"Populares\" foi desativado pelo administrador.",
+ "Answer": "Resposta",
+ "carousel_slide": "Slide {{current}} de {{total}}",
+ "carousel_skip": "Ignorar carrossel",
+ "carousel_go_to": "Ir ao slide `x`"
}
diff --git a/locales/pt-PT.json b/locales/pt-PT.json
index 3834c9e2..f83a80a9 100644
--- a/locales/pt-PT.json
+++ b/locales/pt-PT.json
@@ -130,12 +130,12 @@
"Private": "Privado",
"View all playlists": "Ver todas as listas de reprodução",
"Updated `x` ago": "Atualizado `x` atrás",
- "Delete playlist `x`?": "Eliminar a lista de reprodução 'x'?",
+ "Delete playlist `x`?": "Eliminar a lista de reprodução `x`?",
"Delete playlist": "Eliminar lista de reprodução",
"Create playlist": "Criar lista de reprodução",
"Title": "Título",
"Playlist privacy": "Privacidade da lista de reprodução",
- "Editing playlist `x`": "A editar lista de reprodução 'x'",
+ "Editing playlist `x`": "A editar lista de reprodução `x`",
"Show more": "Mostrar mais",
"Show less": "Mostrar menos",
"Watch on YouTube": "Ver no YouTube",
@@ -150,8 +150,8 @@
"Whitelisted regions: ": "Regiões permitidas: ",
"Blacklisted regions: ": "Regiões bloqueadas: ",
"Shared `x`": "Partilhado `x`",
- "Premieres in `x`": "Estreias em 'x'",
- "Premieres `x`": "Estreias 'x'",
+ "Premieres in `x`": "Estreias em `x`",
+ "Premieres `x`": "Estreias `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.": "Olá! Parece que o JavaScript está desativado. Clique aqui para ver os comentários, entretanto eles podem levar mais tempo para carregar.",
"View YouTube comments": "Ver comentários do YouTube",
"View more comments on Reddit": "Ver mais comentários no Reddit",
@@ -173,7 +173,7 @@
"Password cannot be longer than 55 characters": "A palavra-chave não pode ser superior a 55 caracteres",
"Please log in": "Por favor, inicie sessão",
"Invidious Private Feed for `x`": "Feed Privado do Invidious para `x`",
- "channel:`x`": "canal:'x'",
+ "channel:`x`": "canal:`x`",
"Deleted or invalid channel": "Canal eliminado ou inválido",
"This channel does not exist.": "Este canal não existe.",
"Could not get channel info.": "Não foi possível obter as informações do canal.",
diff --git a/locales/pt.json b/locales/pt.json
index c1d8b5b4..463dbf3a 100644
--- a/locales/pt.json
+++ b/locales/pt.json
@@ -1,25 +1,25 @@
{
- "search_filters_type_option_show": "Série",
+ "search_filters_type_option_show": "Séries",
"search_filters_sort_option_views": "Visualizações",
"search_filters_sort_option_date": "Data de carregamento",
"search_filters_sort_option_rating": "Avaliação",
"search_filters_sort_option_relevance": "Relevância",
- "Switch Invidious Instance": "Mudar a instância do Invidious",
+ "Switch Invidious Instance": "Alterar instância Invidious",
"Show less": "Mostrar menos",
"Show more": "Mostrar mais",
- "Released under the AGPLv3 on Github.": "Lançado sob a AGPLv3 no GitHub.",
+ "Released under the AGPLv3 on Github.": "Disponibilizada sob a AGPLv3 no GitHub.",
"preferences_show_nick_label": "Mostrar nome de utilizador em cima: ",
"preferences_automatic_instance_redirect_label": "Redirecionamento de instância automática (solução de último recurso para redirect.invidious.io): ",
"preferences_category_misc": "Preferências diversas",
- "preferences_vr_mode_label": "Vídeos interativos de 360 graus (necessita de WebGL): ",
- "preferences_extend_desc_label": "Estender automaticamente a descrição do vídeo: ",
+ "preferences_vr_mode_label": "Vídeos interativos de 360 graus (requer WebGL): ",
+ "preferences_extend_desc_label": "Expandir automaticamente a descrição do vídeo: ",
"next_steps_error_message_go_to_youtube": "Ir para o YouTube",
"next_steps_error_message": "Pode tentar as seguintes opções: ",
- "next_steps_error_message_refresh": "Atualizar",
+ "next_steps_error_message_refresh": "Recarregar",
"search_filters_features_option_hdr": "HDR",
"search_filters_features_option_location": "Localização",
"search_filters_features_option_four_k": "4K",
- "search_filters_features_option_live": "Ao Vivo",
+ "search_filters_features_option_live": "Direto",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_subtitles": "Legendas",
@@ -37,11 +37,11 @@
"search_filters_features_label": "Funcionalidades",
"search_filters_duration_label": "Duração",
"search_filters_type_label": "Tipo",
- "permalink": "hiperligação permanente",
- "YouTube comment permalink": "Hiperligação permanente do comentário no YouTube",
+ "permalink": "ligação permanente",
+ "YouTube comment permalink": "Ligação permanente do comentário no YouTube",
"Download as: ": "Descarregar como: ",
"Download": "Descarregar",
- "Default": "Predefinido",
+ "Default": "Padrão",
"Top": "Destaques",
"Search": "Pesquisar",
"generic_count_years_0": "{{count}} ano",
@@ -67,21 +67,21 @@
"generic_count_seconds_2": "{{count}} segundos",
"Chinese (Traditional)": "Chinês (tradicional)",
"Chinese (Simplified)": "Chinês (simplificado)",
- "Could not pull trending pages.": "Não foi possível obter as páginas de tendências.",
- "Could not create mix.": "Não foi possível criar a mistura.",
+ "Could not pull trending pages.": "Não foi possível obter a página de tendências.",
+ "Could not create mix.": "Não foi possível criar o mix.",
"Deleted or invalid channel": "Canal eliminado ou inválido",
- "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Olá! Parece que o JavaScript está desativado. Clique aqui para ver os comentários, entretanto eles podem levar mais tempo para carregar.",
+ "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Olá! Parece que o JavaScript está desativado. Clique aqui para ver os comentários, mas tenha e conta que podem levar mais tempo para carregar.",
"Delete playlist": "Eliminar lista de reprodução",
- "Delete playlist `x`?": "Eliminar a lista de reprodução 'x'?",
+ "Delete playlist `x`?": "Eliminar lista de reprodução `x`?",
"search": "pesquisar",
"unsubscribe": "anular subscrição",
- "Import/export": "Importar / exportar",
+ "Import/export": "Importar/exportar",
"Save preferences": "Guardar preferências",
"Top enabled: ": "Destaques ativados: ",
"Delete account": "Eliminar conta",
- "Import/export data": "Importar / exportar dados",
+ "Import/export data": "Importar/exportar dados",
"preferences_annotations_label": "Mostrar anotações sempre: ",
- "preferences_continue_label": "Reproduzir sempre o próximo: ",
+ "preferences_continue_label": "Reproduzir sempre o seguinte: ",
"Sign In": "Entrar",
"Log in/register": "Iniciar sessão/registar",
"Delete account?": "Eliminar conta?",
@@ -93,7 +93,7 @@
"Danish": "Dinamarquês",
"Czech": "Checo",
"Croatian": "Croata",
- "Corsican": "Corso",
+ "Corsican": "Córsego",
"Cebuano": "Cebuano",
"Catalan": "Catalão",
"Burmese": "Birmanês",
@@ -107,10 +107,10 @@
"Arabic": "Árabe",
"Amharic": "Amárico",
"Albanian": "Albanês",
- "Afrikaans": "Africano",
+ "Afrikaans": "Africânder",
"English (auto-generated)": "Inglês (auto-gerado)",
"English": "Inglês",
- "Token is expired, please try again": "Token expirou, tente novamente",
+ "Token is expired, please try again": "Token caducado, tente novamente",
"No such user": "Utilizador inválido",
"Erroneous token": "Token inválido",
"Erroneous challenge": "Desafio inválido",
@@ -124,29 +124,29 @@
"Could not fetch comments": "Não foi possível obter os comentários",
"Could not get channel info.": "Não foi possível obter as informações do canal.",
"This channel does not exist.": "Este canal não existe.",
- "channel:`x`": "canal:'x'",
+ "channel:`x`": "canal:`x`",
"Invidious Private Feed for `x`": "Feed Privado do Invidious para `x`",
"Please log in": "Por favor, inicie sessão",
- "Password cannot be longer than 55 characters": "A palavra-chave não pode ser superior a 55 caracteres",
- "Password cannot be empty": "A palavra-chave não pode estar vazia",
- "Wrong username or password": "Nome de utilizador ou palavra-chave incorreto",
- "Password is a required field": "Palavra-chave é um campo obrigatório",
+ "Password cannot be longer than 55 characters": "A palavra-passe não pode ter mais do que 55 caracteres",
+ "Password cannot be empty": "A palavra-passe não pode estar vazia",
+ "Wrong username or password": "Nome de utilizador ou palavra-passe incorreta",
+ "Password is a required field": "Palavra-passe é um campo obrigatório",
"User ID is a required field": "O nome de utilizador é um campo obrigatório",
"CAPTCHA is a required field": "CAPTCHA é um campo obrigatório",
"Erroneous CAPTCHA": "CAPTCHA inválido",
"Wrong answer": "Resposta errada",
- "Incorrect password": "Palavra-chave incorreta",
+ "Incorrect password": "Palavra-passe incorreta",
"Show replies": "Mostrar respostas",
"Hide replies": "Ocultar respostas",
"View Reddit comments": "Ver comentários do Reddit",
"View `x` comments": {
"": "Ver `x` comentários",
- "([^.,0-9]|^)1([^.,0-9]|$)": "Ver `x` comentários"
+ "([^.,0-9]|^)1([^.,0-9]|$)": "Ver `x` comentário"
},
"View more comments on Reddit": "Ver mais comentários no Reddit",
"View YouTube comments": "Ver comentários do YouTube",
- "Premieres `x`": "Estreias 'x'",
- "Premieres in `x`": "Estreias em 'x'",
+ "Premieres `x`": "Estreia `x`",
+ "Premieres in `x`": "Estreia a `x`",
"Shared `x`": "Partilhado `x`",
"Blacklisted regions: ": "Regiões bloqueadas: ",
"Whitelisted regions: ": "Regiões permitidas: ",
@@ -158,44 +158,44 @@
"Show annotations": "Mostrar anotações",
"Hide annotations": "Ocultar anotações",
"Watch on YouTube": "Ver no YouTube",
- "Editing playlist `x`": "A editar lista de reprodução 'x'",
+ "Editing playlist `x`": "A editar lista de reprodução `x`",
"Playlist privacy": "Privacidade da lista de reprodução",
"Title": "Título",
"Create playlist": "Criar lista de reprodução",
- "Updated `x` ago": "Atualizado `x` atrás",
+ "Updated `x` ago": "Atualizado há `x`",
"View all playlists": "Ver todas as listas de reprodução",
"Private": "Privado",
"Unlisted": "Não listado",
"Public": "Público",
"Trending": "Tendências",
- "View privacy policy.": "Ver a política de privacidade.",
- "View JavaScript license information.": "Ver informações da licença do JavaScript.",
+ "View privacy policy.": "Ver política de privacidade.",
+ "View JavaScript license information.": "Ver informações da licença JavaScript.",
"Source available here.": "Código-fonte disponível aqui.",
"Log out": "Terminar sessão",
"Subscriptions": "Subscrições",
"revoke": "revogar",
- "tokens_count_0": "{{count}} Token",
- "tokens_count_1": "{{count}} Tokens",
- "tokens_count_2": "{{count}} Tokens",
+ "tokens_count_0": "{{count}} token",
+ "tokens_count_1": "{{count}} tokens",
+ "tokens_count_2": "{{count}} tokens",
"Token": "Token",
- "Token manager": "Gerir tokens",
- "Subscription manager": "Gerir subscrições",
+ "Token manager": "Gestor de tokens",
+ "Subscription manager": "Gestor de subscrições",
"Report statistics: ": "Relatório de estatísticas: ",
"Registration enabled: ": "Registar ativado: ",
"Login enabled: ": "Iniciar sessão ativado: ",
"CAPTCHA enabled: ": "CAPTCHA ativado: ",
"preferences_feed_menu_label": "Menu de subscrições: ",
- "preferences_default_home_label": "Página inicial predefinida: ",
+ "preferences_default_home_label": "Página inicial padrão: ",
"preferences_category_admin": "Preferências de administrador",
"Watch history": "Histórico de reprodução",
"Manage tokens": "Gerir tokens",
- "Manage subscriptions": "Gerir as subscrições",
- "Change password": "Alterar palavra-chave",
+ "Manage subscriptions": "Gerir subscrições",
+ "Change password": "Alterar palavra-passe",
"Clear watch history": "Limpar histórico de reprodução",
"preferences_category_data": "Preferências de dados",
"`x` is live": "`x` está em direto",
- "`x` uploaded a video": "`x` publicou um novo vídeo",
- "Enable web notifications": "Ativar notificações pela web",
+ "`x` uploaded a video": "`x` publicou um vídeo",
+ "Enable web notifications": "Ativar notificações web",
"preferences_notifications_only_label": "Mostrar apenas notificações (se existirem): ",
"preferences_unseen_only_label": "Mostrar apenas vídeos não visualizados: ",
"Only show latest unwatched video from channel: ": "Mostrar apenas vídeos mais recentes não visualizados do canal: ",
@@ -207,9 +207,9 @@
"published - reverse": "publicado - inverso",
"published": "publicado",
"preferences_sort_label": "Ordenar vídeos por: ",
- "preferences_max_results_label": "Quantidade de vídeos nas subscrições: ",
+ "preferences_max_results_label": "Número de vídeos nas subscrições: ",
"Redirect homepage to feed: ": "Redirecionar página inicial para subscrições: ",
- "preferences_annotations_subscribed_label": "Mostrar sempre anotações aos canais subscritos: ",
+ "preferences_annotations_subscribed_label": "Mostrar sempre anotações nos canais subscritos: ",
"preferences_category_subscription": "Preferências de subscrições",
"preferences_thin_mode_label": "Modo compacto: ",
"light": "claro",
@@ -220,11 +220,11 @@
"preferences_category_visual": "Preferências visuais",
"preferences_related_videos_label": "Mostrar vídeos relacionados: ",
"Fallback captions: ": "Legendas alternativas: ",
- "preferences_captions_label": "Legendas predefinidas: ",
+ "preferences_captions_label": "Legendas padrão: ",
"reddit": "Reddit",
"youtube": "YouTube",
- "preferences_comments_label": "Preferência dos comentários: ",
- "preferences_volume_label": "Volume da reprodução: ",
+ "preferences_comments_label": "Comentários padrão: ",
+ "preferences_volume_label": "Volume de reprodução: ",
"preferences_quality_label": "Qualidade de vídeo preferida: ",
"preferences_speed_label": "Velocidade preferida: ",
"preferences_local_label": "Usar proxy nos vídeos: ",
@@ -239,11 +239,11 @@
"Image CAPTCHA": "Imagem CAPTCHA",
"Text CAPTCHA": "Texto CAPTCHA",
"Time (h:mm:ss):": "Tempo (h:mm:ss):",
- "Password": "Palavra-chave",
+ "Password": "Palavra-passe",
"User ID": "Utilizador",
"Log in": "Iniciar sessão",
- "source": "código-fonte",
- "JavaScript license information": "Informação de licença do JavaScript",
+ "source": "fonte",
+ "JavaScript license information": "Informação da licença JavaScript",
"An alternative front-end to YouTube": "Uma interface alternativa ao YouTube",
"History": "Histórico",
"Export data as JSON": "Exportar dados Invidious como JSON",
@@ -253,18 +253,18 @@
"Import NewPipe data (.zip)": "Importar dados do NewPipe (.zip)",
"Import NewPipe subscriptions (.json)": "Importar subscrições do NewPipe (.json)",
"Import FreeTube subscriptions (.db)": "Importar subscrições do FreeTube (.db)",
- "Import YouTube subscriptions": "Importar subscrições do YouTube/OPML",
+ "Import YouTube subscriptions": "Importar subscrições via YouTube/OPML",
"Import Invidious data": "Importar dados JSON do Invidious",
"Import": "Importar",
"No": "Não",
"Yes": "Sim",
- "Authorize token for `x`?": "Autorizar token para `x`?",
- "Authorize token?": "Autorizar token?",
- "New passwords must match": "As novas palavra-chaves devem corresponder",
- "New password": "Nova palavra-chave",
+ "Authorize token for `x`?": "Autorizar 'token' para `x`?",
+ "Authorize token?": "Autorizar 'token'?",
+ "New passwords must match": "As novas palavras-passe devem ser iguais",
+ "New password": "Nova palavra-passe",
"Clear watch history?": "Limpar histórico de reprodução?",
"Previous page": "Página anterior",
- "Next page": "Próxima página",
+ "Next page": "Página seguinte",
"last": "últimos",
"Current version: ": "Versão atual: ",
"channel_tab_community_label": "Comunidade",
@@ -272,19 +272,19 @@
"channel_tab_videos_label": "Vídeos",
"Video mode": "Modo de vídeo",
"Audio mode": "Modo de áudio",
- "`x` marked it with a ❤": "`x` foi marcado como ❤",
+ "`x` marked it with a ❤": "`x` foi marcado com um ❤",
"(edited)": "(editado)",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"Movies": "Filmes",
"News": "Notícias",
"Gaming": "Jogos",
- "Music": "Música",
+ "Music": "Músicas",
"View as playlist": "Ver como lista de reprodução",
"preferences_locale_label": "Idioma: ",
"Rating: ": "Avaliação: ",
- "About": "Sobre",
+ "About": "Acerca",
"Popular": "Popular",
- "Fallback comments: ": "Comentários alternativos: ",
+ "Fallback comments: ": "Alternativa para comentários: ",
"Zulu": "Zulu",
"Yoruba": "Ioruba",
"Yiddish": "Iídiche",
@@ -329,7 +329,7 @@
"Marathi": "Marathi",
"Maori": "Maori",
"Maltese": "Maltês",
- "Malayalam": "Malaiala",
+ "Malayalam": "Malaialaio",
"Malay": "Malaio",
"Malagasy": "Malgaxe",
"Macedonian": "Macedónio",
@@ -365,15 +365,15 @@
"Galician": "Galego",
"French": "Francês",
"Finnish": "Finlandês",
- "popular": "popular",
- "oldest": "mais antigos",
- "newest": "mais recentes",
+ "popular": "populares",
+ "oldest": "antigos",
+ "newest": "recentes",
"View playlist on YouTube": "Ver lista de reprodução no YouTube",
"View channel on YouTube": "Ver canal no YouTube",
"Subscribe": "Subscrever",
"Unsubscribe": "Anular subscrição",
"Shared `x` ago": "Partilhado `x` atrás",
- "LIVE": "AO VIVO",
+ "LIVE": "Direto",
"search_filters_duration_option_short": "Curto (< 4 minutos)",
"search_filters_duration_option_long": "Longo (> 20 minutos)",
"footer_source_code": "Código-fonte",
@@ -386,7 +386,7 @@
"preferences_quality_dash_label": "Qualidade de vídeo DASH preferida: ",
"preferences_quality_option_small": "Baixa",
"preferences_quality_option_hd720": "HD720",
- "preferences_quality_dash_option_auto": "Automático",
+ "preferences_quality_dash_option_auto": "Automática",
"preferences_quality_dash_option_best": "Melhor",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_option_2160p": "2160p",
@@ -397,7 +397,7 @@
"preferences_quality_dash_option_144p": "144p",
"search_filters_features_option_purchased": "Comprado",
"search_filters_features_option_three_sixty": "360°",
- "videoinfo_invidious_embed_link": "Incorporar hiperligação",
+ "videoinfo_invidious_embed_link": "Incorporar ligação",
"Video unavailable": "Vídeo não disponível",
"invidious": "Invidious",
"preferences_quality_option_medium": "Média",
@@ -408,7 +408,7 @@
"preferences_quality_dash_option_worst": "Pior",
"none": "nenhum",
"videoinfo_youTube_embed_link": "Incorporar",
- "preferences_save_player_pos_label": "Guardar a posição de reprodução atual do vídeo: ",
+ "preferences_save_player_pos_label": "Guardar posição de reprodução: ",
"download_subtitles": "Legendas - `x` (.vtt)",
"generic_views_count_0": "{{count}} visualização",
"generic_views_count_1": "{{count}} visualizações",
@@ -427,12 +427,12 @@
"comments_view_x_replies_0": "Ver {{count}} resposta",
"comments_view_x_replies_1": "Ver {{count}} respostas",
"comments_view_x_replies_2": "Ver {{count}} respostas",
- "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",
+ "generic_subscribers_count_0": "{{count}} subscritor",
+ "generic_subscribers_count_1": "{{count}} subscritores",
+ "generic_subscribers_count_2": "{{count}} subscritores",
+ "generic_subscriptions_count_0": "{{count}} subscrição",
+ "generic_subscriptions_count_1": "{{count}} subscrições",
+ "generic_subscriptions_count_2": "{{count}} subscrições",
"comments_points_count_0": "{{count}} ponto",
"comments_points_count_1": "{{count}} pontos",
"comments_points_count_2": "{{count}} pontos",
@@ -440,7 +440,7 @@
"crash_page_before_reporting": "Antes de reportar um erro, verifique se:",
"crash_page_refresh": "tentou <a href=\"`x`\">recarregar a página</a>",
"crash_page_switch_instance": "tentou <a href=\"`x`\">usar outra instância</a>",
- "crash_page_read_the_faq": "leia as <a href=\"`x`\">Perguntas frequentes (FAQ)</a>",
+ "crash_page_read_the_faq": "leu as <a href=\"`x`\">Perguntas frequentes (FAQ)</a>",
"crash_page_search_issue": "procurou se <a href=\"`x`\">o erro já foi reportado no GitHub</a>",
"crash_page_report_issue": "Se nenhuma opção acima ajudou, por favor <a href=\"`x`\">abra um novo problema no Github</a> (preferencialmente em inglês) e inclua o seguinte texto (NÃO o traduza):",
"user_created_playlists": "`x` listas de reprodução criadas",
@@ -484,7 +484,7 @@
"channel_tab_playlists_label": "Listas de reprodução",
"channel_tab_channels_label": "Canais",
"channel_tab_shorts_label": "Curtos",
- "channel_tab_streams_label": "Diretos",
+ "channel_tab_streams_label": "Emissões em direto",
"Music in this video": "Música neste vídeo",
"Artist: ": "Artista: ",
"Album: ": "Álbum: ",
@@ -493,17 +493,25 @@
"Standard YouTube license": "Licença padrão do YouTube",
"Download is disabled": "A descarga está desativada",
"Import YouTube playlist (.csv)": "Importar lista de reprodução do YouTube (.csv)",
- "generic_button_delete": "Deletar",
+ "generic_button_delete": "Eliminar",
"generic_button_edit": "Editar",
"generic_button_rss": "RSS",
"channel_tab_podcasts_label": "Podcasts",
"channel_tab_releases_label": "Lançamentos",
- "generic_button_save": "Salvar",
+ "generic_button_save": "Guardar",
"generic_button_cancel": "Cancelar",
"playlist_button_add_items": "Adicionar vídeos",
"generic_channels_count_0": "{{count}} canal",
"generic_channels_count_1": "{{count}} canais",
"generic_channels_count_2": "{{count}} canais",
"Import YouTube watch history (.json)": "Importar histórico de reprodução do YouTube (.json)",
- "toggle_theme": "Trocar tema"
+ "toggle_theme": "Trocar tema",
+ "Add to playlist": "Adicionar à lista de reprodução",
+ "Add to playlist: ": "Adicionar à lista de reprodução: ",
+ "Answer": "Resposta",
+ "Search for videos": "Procurar vídeos",
+ "carousel_slide": "Diapositivo {{current}} de{{total}}",
+ "carousel_skip": "Ignorar carrossel",
+ "carousel_go_to": "Ir para o diapositivo`x`",
+ "The Popular feed has been disabled by the administrator.": "O feed Popular foi desativado por um administrador."
}
diff --git a/locales/ro.json b/locales/ro.json
index 85bf746f..ccbeef63 100644
--- a/locales/ro.json
+++ b/locales/ro.json
@@ -478,5 +478,6 @@
"search_filters_type_option_all": "orice tip",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
- "Show less": "Afișați mai puțin"
+ "Show less": "Afișați mai puțin",
+ "Add to playlist": "Adaugă la playlist"
}
diff --git a/locales/sr.json b/locales/sr.json
index b4a98da6..4b24e7c0 100644
--- a/locales/sr.json
+++ b/locales/sr.json
@@ -21,7 +21,7 @@
"Import and Export Data": "Uvoz i izvoz podataka",
"Import": "Uvezi",
"Import Invidious data": "Uvezi Invidious JSON podatke",
- "Import YouTube subscriptions": "Uvezi YouTube/OPML praćenja",
+ "Import YouTube subscriptions": "Uvezi YouTube CSV ili 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)",
@@ -504,5 +504,14 @@
"generic_views_count_0": "{{count}} pregled",
"generic_views_count_1": "{{count}} pregleda",
"generic_views_count_2": "{{count}} pregleda",
- "Import YouTube watch history (.json)": "Uvezi YouTube istoriju gledanja (.json)"
+ "Import YouTube watch history (.json)": "Uvezi YouTube istoriju gledanja (.json)",
+ "The Popular feed has been disabled by the administrator.": "Administrator je onemogućio fid „Popularno“.",
+ "Add to playlist: ": "Dodajte na plejlistu: ",
+ "Add to playlist": "Dodaj na plejlistu",
+ "carousel_slide": "Slajd {{current}} od {{total}}",
+ "carousel_go_to": "Idi na slajd `x`",
+ "Answer": "Odgovor",
+ "Search for videos": "Pretražite video snimke",
+ "carousel_skip": "Preskoči karusel",
+ "toggle_theme": "Подеси тему"
}
diff --git a/locales/sr_Cyrl.json b/locales/sr_Cyrl.json
index 52ac4116..57c6de9c 100644
--- a/locales/sr_Cyrl.json
+++ b/locales/sr_Cyrl.json
@@ -21,7 +21,7 @@
"Import and Export Data": "Увоз и извоз података",
"Import": "Увези",
"Import Invidious data": "Увези Invidious JSON податке",
- "Import YouTube subscriptions": "Увези YouTube/OPML праћења",
+ "Import YouTube subscriptions": "Увези YouTube CSV или OPML праћења",
"Import FreeTube subscriptions (.db)": "Увези FreeTube праћења (.db)",
"Import NewPipe subscriptions (.json)": "Увези NewPipe праћења (.json)",
"Import NewPipe data (.zip)": "Увези NewPipe податке (.zip)",
@@ -505,5 +505,13 @@
"generic_views_count_1": "{{count}} прегледа",
"generic_views_count_2": "{{count}} прегледа",
"Import YouTube watch history (.json)": "Увези YouTube историју гледањa (.json)",
- "toggle_theme": "Укључи тему"
+ "toggle_theme": "Укључи тему",
+ "Add to playlist": "Додај на плејлисту",
+ "Answer": "Одговор",
+ "Search for videos": "Претражите видео снимке",
+ "carousel_go_to": "Иди на слајд `x`",
+ "Add to playlist: ": "Додајте на плејлисту: ",
+ "carousel_skip": "Прескочи карусел",
+ "The Popular feed has been disabled by the administrator.": "Администратор је онемогућио фид „Популарно“.",
+ "carousel_slide": "Слајд {{current}} од {{total}}"
}
diff --git a/locales/sv-SE.json b/locales/sv-SE.json
index db3486df..76edc341 100644
--- a/locales/sv-SE.json
+++ b/locales/sv-SE.json
@@ -488,5 +488,13 @@
"crash_page_you_found_a_bug": "Det verkar som att du har hittat en bugg i Invidious!",
"generic_views_count": "{{count}} visning",
"generic_views_count_plural": "{{count}} visningar",
- "toggle_theme": "Växla tema"
+ "toggle_theme": "Växla tema",
+ "Add to playlist": "Lägg till i spellista",
+ "Add to playlist: ": "Lägg till i spellista: ",
+ "Answer": "Svara",
+ "Search for videos": "Sök efter videor",
+ "The Popular feed has been disabled by the administrator.": "Det populära flödet har inaktiverats av administratören.",
+ "carousel_slide": "Bildspel {{current}} av {{total}}",
+ "carousel_skip": "Hoppa över karusellen",
+ "carousel_go_to": "Gå till bildspel `x`"
}
diff --git a/locales/tk.json b/locales/tk.json
new file mode 100644
index 00000000..798ea6ce
--- /dev/null
+++ b/locales/tk.json
@@ -0,0 +1,7 @@
+{
+ "Add to playlist": "Aýdym sanawyna goş",
+ "Add to playlist: ": "Pleýliste goş: ",
+ "Answer": "Jogap",
+ "Search for videos": "Wideo gözläň",
+ "The Popular feed has been disabled by the administrator.": "Trende bolan administrator tarapyndan ýapyldy."
+}
diff --git a/locales/tr.json b/locales/tr.json
index d25cfd65..3b7bf3a4 100644
--- a/locales/tr.json
+++ b/locales/tr.json
@@ -21,7 +21,7 @@
"Import and Export Data": "Verileri İçe ve Dışa Aktar",
"Import": "İçe Aktar",
"Import Invidious data": "Invidious JSON Verilerini İçe Aktar",
- "Import YouTube subscriptions": "YouTube/OPML Aboneliklerini İçe Aktar",
+ "Import YouTube subscriptions": "YouTube CSV veya OPML Aboneliklerini İçe Aktar",
"Import FreeTube subscriptions (.db)": "FreeTube Aboneliklerini İçe Aktar (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe Aboneliklerini İçe Aktar (.json)",
"Import NewPipe data (.zip)": "NewPipe Verilerini İçe Aktar (.zip)",
@@ -488,5 +488,13 @@
"generic_channels_count": "{{count}} kanal",
"generic_channels_count_plural": "{{count}} kanal",
"Import YouTube watch history (.json)": "YouTube İzleme Geçmişini İçe Aktar (.json)",
- "toggle_theme": "Temayı Değiştir"
+ "toggle_theme": "Temayı Değiştir",
+ "Add to playlist": "Oynatma listesine ekle",
+ "Add to playlist: ": "Oynatma listesine ekle: ",
+ "Answer": "Yanıt",
+ "Search for videos": "Video ara",
+ "carousel_slide": "Sunum {{current}} / {{total}}",
+ "carousel_skip": "Kayar menüyü atla",
+ "carousel_go_to": "`x` sunumuna git",
+ "The Popular feed has been disabled by the administrator.": "Popüler akışı yönetici tarafından devre dışı bırakıldı."
}
diff --git a/locales/uk.json b/locales/uk.json
index f9640bba..223772d9 100644
--- a/locales/uk.json
+++ b/locales/uk.json
@@ -127,7 +127,7 @@
"Create playlist": "Створити список відтворення",
"Title": "Заголовок",
"Playlist privacy": "Конфіденційність списку відтворення",
- "Editing playlist `x`": "Редагування списку відтворення \"x\"",
+ "Editing playlist `x`": "Редагування списку відтворення `x`",
"Watch on YouTube": "Дивитися на YouTube",
"Hide annotations": "Приховати анотації",
"Show annotations": "Показати анотації",
@@ -505,5 +505,13 @@
"generic_channels_count_1": "{{count}} канали",
"generic_channels_count_2": "{{count}} каналів",
"Import YouTube watch history (.json)": "Імпортувати історію переглядів YouTube (.json)",
- "toggle_theme": "Перемкнути тему"
+ "toggle_theme": "Перемкнути тему",
+ "Add to playlist": "Додати до списку відтворення",
+ "Add to playlist: ": "Додати до списку відтворення: ",
+ "Answer": "Відповідь",
+ "Search for videos": "Шукати відео",
+ "The Popular feed has been disabled by the administrator.": "Стрічка Популярні вимкнена адміністратором.",
+ "carousel_slide": "Слайд {{current}} з {{total}}",
+ "carousel_skip": "Пропустити карусель",
+ "carousel_go_to": "Перейти до слайда `x`"
}
diff --git a/locales/vi.json b/locales/vi.json
index 4f8dc30d..229f8fa9 100644
--- a/locales/vi.json
+++ b/locales/vi.json
@@ -33,12 +33,12 @@
"Export data as JSON": "Xuất dữ liệu Invidious dưới dạng JSON",
"Delete account?": "Xóa tài khoản?",
"History": "Lịch sử",
- "An alternative front-end to YouTube": "Một front-end thay thế cho YouTube",
+ "An alternative front-end to YouTube": "Giao diện thay thế cho YouTube",
"JavaScript license information": "Thông tin giấy phép JavaScript",
"source": "nguồn",
"Log in": "Đăng nhập",
"Log in/register": "Đăng nhập / đăng ký",
- "User ID": "ID người dùng",
+ "User ID": "Mã nhận dạng người dùng",
"Password": "Mật khẩu",
"Time (h:mm:ss):": "Thời gian (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA dạng chữ",
@@ -46,16 +46,16 @@
"Sign In": "Đăng nhập",
"Register": "Đăng ký",
"E-mail": "E-mail",
- "Preferences": "Sở thích",
+ "Preferences": "Cài đặt",
"preferences_category_player": "Tùy chọn trình phát video",
"preferences_video_loop_label": "Luôn lặp lại: ",
"preferences_autoplay_label": "Tự động phát: ",
"preferences_continue_label": "Phát kế tiếp theo mặc định: ",
"preferences_continue_autoplay_label": "Tự động phát video tiếp theo: ",
"preferences_listen_label": "Nghe theo mặc định: ",
- "preferences_local_label": "Video proxy: ",
+ "preferences_local_label": "Máy chủ sử lý video: ",
"preferences_speed_label": "Tốc độ mặc định: ",
- "preferences_quality_label": "Chất lượng video ưa thích: ",
+ "preferences_quality_label": "Chất lượng video: ",
"preferences_volume_label": "Âm lượng video: ",
"preferences_comments_label": "Nhận xét mặc định: ",
"youtube": "YouTube",
@@ -341,13 +341,13 @@
"([^.,0-9]|^)1([^.,0-9]|$)": "Hiển thị `x`bình luận"
},
"Song: ": "Ca khúc: ",
- "Premieres in `x`": "Trình chiếu lần đầu vào `x`",
- "preferences_quality_dash_option_worst": "Thấp nhất",
+ "Premieres in `x`": "Trình chiếu ở `x`",
+ "preferences_quality_dash_option_worst": "Tệ nhất",
"preferences_watch_history_label": "Bật lịch sử video đã xem ",
"preferences_quality_option_hd720": "HD720",
"unsubscribe": "hủy đăng kí",
"revoke": "gỡ bỏ",
- "preferences_quality_dash_label": "Chất lượng video DASH ưa thích ",
+ "preferences_quality_dash_label": "Chất lượng video DASH ",
"preferences_quality_dash_option_auto": "Tự động",
"Subscriptions": "Thuê bao",
"View YouTube comments": "Hiển thị bình luận từ YouTube",
@@ -470,5 +470,14 @@
"search_filters_duration_option_medium": "Trung bình (4 - 20 phút)",
"generic_count_seconds_0": "{{count}} giây",
"search_filters_date_label": "Ngày tải lên",
- "crash_page_you_found_a_bug": "Có vẻ như bạn đã tìm ra lỗi trong Indivious!"
+ "crash_page_you_found_a_bug": "Có vẻ như bạn đã tìm ra lỗi trong Indivious!",
+ "Add to playlist": "Thêm vào danh sách phát",
+ "Add to playlist: ": "Thêm vào danh sách phát: ",
+ "Answer": "Trả lời",
+ "toggle_theme": "Bật/tắt diện mạo",
+ "carousel_slide": "Trang {{current}} trên tổng {{total}} trang",
+ "carousel_skip": "Bỏ qua Carousel",
+ "carousel_go_to": "Đi tới trang `x`",
+ "Search for videos": "Tìm kiếm video",
+ "The Popular feed has been disabled by the administrator.": "Bảng tin phổ biến đã bị tắt bởi ban quản lý."
}
diff --git a/locales/zh-CN.json b/locales/zh-CN.json
index faa67e6c..756645f4 100644
--- a/locales/zh-CN.json
+++ b/locales/zh-CN.json
@@ -26,7 +26,7 @@
"Import and Export Data": "导入与导出数据",
"Import": "导入",
"Import Invidious data": "导入 Invidious JSON 数据",
- "Import YouTube subscriptions": "导入 YouTube/OPML 订阅",
+ "Import YouTube subscriptions": "导入 YouTube CSV 或 OPML 订阅",
"Import FreeTube subscriptions (.db)": "导入 FreeTube 订阅 (.db)",
"Import NewPipe subscriptions (.json)": "导入 NewPipe 订阅 (.json)",
"Import NewPipe data (.zip)": "导入 NewPipe 数据 (.zip)",
@@ -471,5 +471,13 @@
"generic_button_rss": "RSS",
"channel_tab_releases_label": "公告",
"generic_channels_count_0": "{{count}} 个频道",
- "toggle_theme": "切换主题"
+ "toggle_theme": "切换主题",
+ "Add to playlist": "添加到播放列表",
+ "Add to playlist: ": "添加到播放列表: ",
+ "Answer": "响应",
+ "Search for videos": "搜索视频",
+ "The Popular feed has been disabled by the administrator.": "“流行”源已被管理员禁用。",
+ "carousel_slide": "当前为第 {{current}} 张图,共 {{total}} 张图",
+ "carousel_skip": "跳过图集",
+ "carousel_go_to": "转到图 `x`"
}
diff --git a/locales/zh-TW.json b/locales/zh-TW.json
index 1520c269..2584db9c 100644
--- a/locales/zh-TW.json
+++ b/locales/zh-TW.json
@@ -26,7 +26,7 @@
"Import and Export Data": "匯入與匯出資料",
"Import": "匯入",
"Import Invidious data": "匯入 Invidious JSON 資料",
- "Import YouTube subscriptions": "匯入 YouTube/OPML 訂閱",
+ "Import YouTube subscriptions": "匯入 YouTube CSV 或 OPML 訂閱",
"Import FreeTube subscriptions (.db)": "匯入 FreeTube 訂閱 (.db)",
"Import NewPipe subscriptions (.json)": "匯入 NewPipe 訂閱 (.json)",
"Import NewPipe data (.zip)": "匯入 NewPipe 資料 (.zip)",
@@ -471,5 +471,13 @@
"channel_tab_podcasts_label": "Podcast",
"channel_tab_releases_label": "發布",
"generic_channels_count_0": "{{count}} 個頻道",
- "toggle_theme": "切換佈景主題"
+ "toggle_theme": "切換佈景主題",
+ "Add to playlist": "新增至播放清單",
+ "Add to playlist: ": "新增至播放清單: ",
+ "Answer": "答案",
+ "Search for videos": "搜尋影片",
+ "carousel_slide": "第 {{current}} 張投影片,共 {{total}} 張",
+ "carousel_skip": "略過輪播",
+ "carousel_go_to": "跳到投影片 `x`",
+ "The Popular feed has been disabled by the administrator.": "熱門 feed 已被管理員停用。"
}
diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr
index 8b60a728..b5a27667 100644
--- a/src/invidious/channels/about.cr
+++ b/src/invidious/channels/about.cr
@@ -14,6 +14,7 @@ record AboutChannel,
is_family_friendly : Bool,
allowed_regions : Array(String),
tabs : Array(String),
+ tags : Array(String),
verified : Bool
def get_about_info(ucid, locale) : AboutChannel
@@ -43,6 +44,8 @@ def get_about_info(ucid, locale) : AboutChannel
auto_generated = true
end
+ tags = [] of String
+
if auto_generated
author = initdata["header"]["interactiveTabbedHeaderRenderer"]["title"]["simpleText"].as_s
author_url = initdata["microformat"]["microformatDataRenderer"]["urlCanonical"].as_s
@@ -52,7 +55,13 @@ def get_about_info(ucid, locale) : AboutChannel
banners = initdata["header"]["interactiveTabbedHeaderRenderer"]?.try &.["banner"]?.try &.["thumbnails"]?
banner = banners.try &.[-1]?.try &.["url"].as_s?
- description_node = initdata["header"]["interactiveTabbedHeaderRenderer"]["description"]
+ description_base_node = initdata["header"]["interactiveTabbedHeaderRenderer"]["description"]
+ # some channels have the description in a simpleText
+ # ex: https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg/
+ description_node = description_base_node.dig?("simpleText") || description_base_node
+
+ tags = initdata.dig?("header", "interactiveTabbedHeaderRenderer", "badges")
+ .try &.as_a.map(&.["metadataBadgeRenderer"]["label"].as_s) || [] of String
else
author = initdata["metadata"]["channelMetadataRenderer"]["title"].as_s
author_url = initdata["metadata"]["channelMetadataRenderer"]["channelUrl"].as_s
@@ -70,6 +79,7 @@ def get_about_info(ucid, locale) : AboutChannel
# end
description_node = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?
+ tags = initdata.dig?("microformat", "microformatDataRenderer", "tags").try &.as_a.map(&.as_s) || [] of String
end
is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool
@@ -131,7 +141,8 @@ def get_about_info(ucid, locale) : AboutChannel
# ["description"]["simpleText"] and ["primaryLinks"][0]["title"]["simpleText"]
auto_generated = (
(channel_about_meta["primaryLinks"]?.try &.size) == 1 && \
- extract_text(channel_about_meta.dig?("primaryLinks", 0, "title")) == "Auto-generated by YouTube"
+ extract_text(channel_about_meta.dig?("primaryLinks", 0, "title")) == "Auto-generated by YouTube" ||
+ channel_about_meta.dig?("links", 0, "channelExternalLinkViewModel", "title", "content").try &.as_s == "Auto-generated by YouTube"
)
end
end
@@ -155,6 +166,7 @@ def get_about_info(ucid, locale) : AboutChannel
is_family_friendly: is_family_friendly,
allowed_regions: allowed_regions,
tabs: tab_names,
+ tags: tags,
verified: author_verified || false,
)
end
diff --git a/src/invidious/jsonify/api_v1/video_json.cr b/src/invidious/jsonify/api_v1/video_json.cr
index 1651559a..4fe90289 100644
--- a/src/invidious/jsonify/api_v1/video_json.cr
+++ b/src/invidious/jsonify/api_v1/video_json.cr
@@ -62,6 +62,7 @@ module Invidious::JSONify::APIv1
json.field "rating", 0_i64
json.field "isListed", video.is_listed
json.field "liveNow", video.live_now
+ json.field "isPostLiveDvr", video.post_live_dvr
json.field "isUpcoming", video.is_upcoming
if video.premiere_timestamp
@@ -227,6 +228,7 @@ module Invidious::JSONify::APIv1
json.field "author", rv["author"]
json.field "authorUrl", "/channel/#{rv["ucid"]?}"
json.field "authorId", rv["ucid"]?
+ json.field "authorVerified", rv["author_verified"] == "true"
if rv["author_thumbnail"]?
json.field "authorThumbnails" do
json.array do
diff --git a/src/invidious/routes/api/manifest.cr b/src/invidious/routes/api/manifest.cr
index 662d1002..d89e752c 100644
--- a/src/invidious/routes/api/manifest.cr
+++ b/src/invidious/routes/api/manifest.cr
@@ -21,7 +21,13 @@ module Invidious::Routes::API::Manifest
end
if dashmpd = video.dash_manifest_url
- manifest = YT_POOL.client &.get(URI.parse(dashmpd).request_target).body
+ response = YT_POOL.client &.get(URI.parse(dashmpd).request_target)
+
+ if response.status_code != 200
+ haltf env, status_code: response.status_code
+ end
+
+ manifest = response.body
manifest = manifest.gsub(/<BaseURL>[^<]+<\/BaseURL>/) do |baseurl|
url = baseurl.lchop("<BaseURL>")
diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr
index c6be8b06..7faf200a 100644
--- a/src/invidious/routes/api/v1/channels.cr
+++ b/src/invidious/routes/api/v1/channels.cr
@@ -90,6 +90,7 @@ module Invidious::Routes::API::V1::Channels
json.field "allowedRegions", channel.allowed_regions
json.field "tabs", channel.tabs
+ json.field "tags", channel.tags
json.field "authorVerified", channel.verified
json.field "latestVideos" do
diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr
index a8f02056..c218b4ef 100644
--- a/src/invidious/videos.cr
+++ b/src/invidious/videos.cr
@@ -82,6 +82,10 @@ struct Video
return (self.video_type == VideoType::Livestream)
end
+ def post_live_dvr
+ return info["isPostLiveDvr"].as_bool
+ end
+
def premiere_timestamp : Time?
info
.dig?("microformat", "playerMicroformatRenderer", "liveBroadcastDetails", "startTimestamp")
@@ -394,17 +398,6 @@ def fetch_video(id, region)
.dig?("microformat", "playerMicroformatRenderer", "availableCountries")
.try &.as_a.map &.as_s || [] of String
- # Check for region-blocks
- if info["reason"]?.try &.as_s.includes?("your country")
- bypass_regions = PROXY_LIST.keys & allowed_regions
- if !bypass_regions.empty?
- region = bypass_regions[rand(bypass_regions.size)]
- region_info = extract_video_info(video_id: id, proxy_region: region)
- region_info["region"] = JSON::Any.new(region) if region
- info = region_info if !region_info["reason"]?
- end
- end
-
if reason = info["reason"]?
if reason == "Video unavailable"
raise NotFoundException.new(reason.as_s || "")
diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr
index 75fe4a36..e3816d79 100644
--- a/src/invidious/videos/parser.cr
+++ b/src/invidious/videos/parser.cr
@@ -50,9 +50,9 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)?
}
end
-def extract_video_info(video_id : String, proxy_region : String? = nil)
+def extract_video_info(video_id : String)
# Init client config for the API
- client_config = YoutubeAPI::ClientConfig.new(proxy_region: proxy_region)
+ client_config = YoutubeAPI::ClientConfig.new
# Fetch data from the player endpoint
player_response = YoutubeAPI.player(video_id: video_id, params: "", client_config: client_config)
@@ -216,6 +216,9 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
live_now = microformat.dig?("liveBroadcastDetails", "isLiveNow")
.try &.as_bool || false
+ post_live_dvr = video_details.dig?("isPostLiveDvr")
+ .try &.as_bool || false
+
# Extra video infos
allowed_regions = microformat["availableCountries"]?
@@ -267,7 +270,18 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
.try &.dig?("videoActions", "menuRenderer", "topLevelButtons")
if toplevel_buttons
- likes_button = toplevel_buttons.try &.as_a
+ # New Format as of december 2023
+ likes_button = toplevel_buttons.dig?(0,
+ "segmentedLikeDislikeButtonViewModel",
+ "likeButtonViewModel",
+ "likeButtonViewModel",
+ "toggleButtonViewModel",
+ "toggleButtonViewModel",
+ "defaultButtonViewModel",
+ "buttonViewModel"
+ )
+
+ likes_button ||= toplevel_buttons.try &.as_a
.find(&.dig?("toggleButtonRenderer", "defaultIcon", "iconType").=== "LIKE")
.try &.["toggleButtonRenderer"]
@@ -280,9 +294,10 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
)
if likes_button
+ likes_txt = likes_button.dig?("accessibilityText")
# Note: The like count from `toggledText` is off by one, as it would
# represent the new like count in the event where the user clicks on "like".
- likes_txt = (likes_button["defaultText"]? || likes_button["toggledText"]?)
+ likes_txt ||= (likes_button["defaultText"]? || likes_button["toggledText"]?)
.try &.dig?("accessibility", "accessibilityData", "label")
likes = likes_txt.as_s.gsub(/\D/, "").to_i64? if likes_txt
@@ -405,6 +420,7 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
"isListed" => JSON::Any.new(is_listed || false),
"isUpcoming" => JSON::Any.new(is_upcoming || false),
"keywords" => JSON::Any.new(keywords.map { |v| JSON::Any.new(v) }),
+ "isPostLiveDvr" => JSON::Any.new(post_live_dvr),
# Related videos
"relatedVideos" => JSON::Any.new(related),
# Description
diff --git a/src/invidious/yt_backend/connection_pool.cr b/src/invidious/yt_backend/connection_pool.cr
index 81cfb272..d3dbcc0e 100644
--- a/src/invidious/yt_backend/connection_pool.cr
+++ b/src/invidious/yt_backend/connection_pool.cr
@@ -24,25 +24,20 @@ struct YoutubeConnectionPool
@pool = build_pool()
end
- def client(region = nil, &block)
- if region
- conn = make_client(url, region, force_resolve = true)
+ def client(&block)
+ conn = pool.checkout
+ begin
response = yield conn
- else
- conn = pool.checkout
- begin
- response = yield conn
- rescue ex
- conn.close
- conn = HTTP::Client.new(url)
+ rescue ex
+ conn.close
+ conn = HTTP::Client.new(url)
- conn.family = CONFIG.force_resolve
- conn.family = Socket::Family::INET if conn.family == Socket::Family::UNSPEC
- conn.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
- response = yield conn
- ensure
- pool.release(conn)
- end
+ conn.family = CONFIG.force_resolve
+ conn.family = Socket::Family::INET if conn.family == Socket::Family::UNSPEC
+ conn.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
+ response = yield conn
+ ensure
+ pool.release(conn)
end
response
@@ -60,9 +55,9 @@ struct YoutubeConnectionPool
end
def make_client(url : URI, region = nil, force_resolve : Bool = false)
- client = HTTPClient.new(url, OpenSSL::SSL::Context::Client.insecure)
+ client = HTTP::Client.new(url)
- # Some services do not support IPv6.
+ # Force the usage of a specific configured IP Family
if force_resolve
client.family = CONFIG.force_resolve
end
@@ -71,17 +66,6 @@ def make_client(url : URI, region = nil, force_resolve : Bool = false)
client.read_timeout = 10.seconds
client.connect_timeout = 10.seconds
- if region
- PROXY_LIST[region]?.try &.sample(40).each do |proxy|
- begin
- proxy = HTTPProxy.new(proxy_host: proxy[:ip], proxy_port: proxy[:port])
- client.set_proxy(proxy)
- break
- rescue ex
- end
- end
- end
-
return client
end
diff --git a/src/invidious/yt_backend/proxy.cr b/src/invidious/yt_backend/proxy.cr
deleted file mode 100644
index 2d0fd4ba..00000000
--- a/src/invidious/yt_backend/proxy.cr
+++ /dev/null
@@ -1,316 +0,0 @@
-# See https://github.com/crystal-lang/crystal/issues/2963
-class HTTPProxy
- getter proxy_host : String
- getter proxy_port : Int32
- getter options : Hash(Symbol, String)
- getter tls : OpenSSL::SSL::Context::Client?
-
- def initialize(@proxy_host, @proxy_port = 80, @options = {} of Symbol => String)
- end
-
- def open(host, port, tls = nil, connection_options = {} of Symbol => Float64 | Nil)
- dns_timeout = connection_options.fetch(:dns_timeout, nil)
- connect_timeout = connection_options.fetch(:connect_timeout, nil)
- read_timeout = connection_options.fetch(:read_timeout, nil)
-
- socket = TCPSocket.new @proxy_host, @proxy_port, dns_timeout, connect_timeout
- socket.read_timeout = read_timeout if read_timeout
- socket.sync = true
-
- socket << "CONNECT #{host}:#{port} HTTP/1.1\r\n"
-
- if options[:user]?
- credentials = Base64.strict_encode("#{options[:user]}:#{options[:password]}")
- credentials = "#{credentials}\n".gsub(/\s/, "")
- socket << "Proxy-Authorization: Basic #{credentials}\r\n"
- end
-
- socket << "\r\n"
-
- resp = parse_response(socket)
-
- if resp[:code]? == 200
- {% if !flag?(:without_openssl) %}
- if tls
- tls_socket = OpenSSL::SSL::Socket::Client.new(socket, context: tls, sync_close: true, hostname: host)
- socket = tls_socket
- end
- {% end %}
-
- return socket
- else
- socket.close
- raise IO::Error.new(resp.inspect)
- end
- end
-
- private def parse_response(socket)
- resp = {} of Symbol => Int32 | String | Hash(String, String)
-
- begin
- version, code, reason = socket.gets.as(String).chomp.split(/ /, 3)
-
- headers = {} of String => String
-
- while (line = socket.gets.as(String)) && (line.chomp != "")
- name, value = line.split(/:/, 2)
- headers[name.strip] = value.strip
- end
-
- resp[:version] = version
- resp[:code] = code.to_i
- resp[:reason] = reason
- resp[:headers] = headers
- rescue
- end
-
- return resp
- end
-end
-
-class HTTPClient < HTTP::Client
- def set_proxy(proxy : HTTPProxy)
- begin
- @io = proxy.open(host: @host, port: @port, tls: @tls, connection_options: proxy_connection_options)
- rescue IO::Error
- @io = nil
- end
- end
-
- def unset_proxy
- @io = nil
- end
-
- def proxy_connection_options
- opts = {} of Symbol => Float64 | Nil
-
- opts[:dns_timeout] = @dns_timeout
- opts[:connect_timeout] = @connect_timeout
- opts[:read_timeout] = @read_timeout
-
- return opts
- end
-end
-
-def get_proxies(country_code = "US")
- # return get_spys_proxies(country_code)
- return get_nova_proxies(country_code)
-end
-
-def filter_proxies(proxies)
- proxies.select! do |proxy|
- begin
- client = HTTPClient.new(YT_URL)
- client.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com"
- client.read_timeout = 10.seconds
- client.connect_timeout = 10.seconds
-
- proxy = HTTPProxy.new(proxy_host: proxy[:ip], proxy_port: proxy[:port])
- client.set_proxy(proxy)
-
- status_ok = client.head("/").status_code == 200
- client.close
- status_ok
- rescue ex
- false
- end
- end
-
- return proxies
-end
-
-def get_nova_proxies(country_code = "US")
- country_code = country_code.downcase
- client = HTTP::Client.new(URI.parse("https://www.proxynova.com"))
- client.read_timeout = 10.seconds
- client.connect_timeout = 10.seconds
-
- headers = HTTP::Headers.new
- headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
- headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
- headers["Accept-Language"] = "Accept-Language: en-US,en;q=0.9"
- headers["Host"] = "www.proxynova.com"
- headers["Origin"] = "https://www.proxynova.com"
- headers["Referer"] = "https://www.proxynova.com/proxy-server-list/country-#{country_code}/"
-
- response = client.get("/proxy-server-list/country-#{country_code}/", headers)
- client.close
- document = XML.parse_html(response.body)
-
- proxies = [] of {ip: String, port: Int32, score: Float64}
- document.xpath_nodes(%q(//tr[@data-proxy-id])).each do |node|
- ip = node.xpath_node(%q(.//td/abbr/script)).not_nil!.content
- ip = ip.match(/document\.write\('(?<sub1>[^']+)'.substr\(8\) \+ '(?<sub2>[^']+)'/).not_nil!
- ip = "#{ip["sub1"][8..-1]}#{ip["sub2"]}"
- port = node.xpath_node(%q(.//td[2])).not_nil!.content.strip.to_i
-
- anchor = node.xpath_node(%q(.//td[4]/div)).not_nil!
- speed = anchor["data-value"].to_f
- latency = anchor["title"].to_f
- uptime = node.xpath_node(%q(.//td[5]/span)).not_nil!.content.rchop("%").to_f
-
- # TODO: Tweak me
- score = (uptime*4 + speed*2 + latency)/7
- proxies << {ip: ip, port: port, score: score}
- end
-
- # proxies = proxies.sort_by { |proxy| proxy[:score] }.reverse
- return proxies
-end
-
-def get_spys_proxies(country_code = "US")
- client = HTTP::Client.new(URI.parse("http://spys.one"))
- client.read_timeout = 10.seconds
- client.connect_timeout = 10.seconds
-
- headers = HTTP::Headers.new
- headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
- headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
- headers["Accept-Language"] = "Accept-Language: en-US,en;q=0.9"
- headers["Host"] = "spys.one"
- headers["Origin"] = "http://spys.one"
- headers["Referer"] = "http://spys.one/free-proxy-list/#{country_code}/"
- headers["Content-Type"] = "application/x-www-form-urlencoded"
- body = {
- "xpp" => "5",
- "xf1" => "0",
- "xf2" => "0",
- "xf4" => "0",
- "xf5" => "1",
- }
-
- response = client.post("/free-proxy-list/#{country_code}/", headers, form: body)
- client.close
- 20.times do
- if response.status_code == 200
- break
- end
- response = client.post("/free-proxy-list/#{country_code}/", headers, form: body)
- end
-
- response = XML.parse_html(response.body)
-
- mapping = response.xpath_node(%q(.//body/script)).not_nil!.content
- mapping = mapping.match(/\}\('(?<p>[^']+)',\d+,\d+,'(?<x>[^']+)'/).not_nil!
- p = mapping["p"].not_nil!
- x = mapping["x"].not_nil!
- mapping = decrypt_port(p, x)
-
- proxies = [] of {ip: String, port: Int32, score: Float64}
- response = response.xpath_node(%q(//tr/td/table)).not_nil!
- response.xpath_nodes(%q(.//tr)).each do |node|
- if !node["onmouseover"]?
- next
- end
-
- ip = node.xpath_node(%q(.//td[1]/font[2])).to_s.match(/<font class="spy14">(?<address>[^<]+)</).not_nil!["address"]
- encrypted_port = node.xpath_node(%q(.//td[1]/font[2]/script)).not_nil!.content
- encrypted_port = encrypted_port.match(/<\\\/font>"\+(?<encrypted_port>[\d\D]+)\)$/).not_nil!["encrypted_port"]
-
- port = ""
- encrypted_port.split("+").each do |number|
- number = number.delete("()")
- left_side, right_side = number.split("^")
- result = mapping[left_side] ^ mapping[right_side]
- port = "#{port}#{result}"
- end
- port = port.to_i
-
- latency = node.xpath_node(%q(.//td[6])).not_nil!.content.to_f
- speed = node.xpath_node(%q(.//td[7]/font/table)).not_nil!["width"].to_f
- uptime = node.xpath_node(%q(.//td[8]/font/acronym)).not_nil!
-
- # Skip proxies that are down
- if uptime["title"].ends_with? "?"
- next
- end
-
- if md = uptime.content.match(/^\d+/)
- uptime = md[0].to_f
- else
- next
- end
-
- score = (uptime*4 + speed*2 + latency)/7
-
- proxies << {ip: ip, port: port, score: score}
- end
-
- proxies = proxies.sort_by!(&.[:score]).reverse!
- return proxies
-end
-
-def decrypt_port(p, x)
- x = x.split("^")
- s = {} of String => String
-
- 60.times do |i|
- if x[i]?.try &.empty?
- s[y_func(i)] = y_func(i)
- else
- s[y_func(i)] = x[i]
- end
- end
-
- x = s
- p = p.gsub(/\b\w+\b/, x)
-
- p = p.split(";")
- p = p.map(&.split("="))
-
- mapping = {} of String => Int32
- p.each do |item|
- if item == [""]
- next
- end
-
- key = item[0]
- value = item[1]
- value = value.split("^")
-
- if value.size == 1
- value = value[0].to_i
- else
- left_side = value[0].to_i?
- left_side ||= mapping[value[0]]
- right_side = value[1].to_i?
- right_side ||= mapping[value[1]]
-
- value = left_side ^ right_side
- end
-
- mapping[key] = value
- end
-
- return mapping
-end
-
-def y_func(c)
- return (c < 60 ? "" : y_func((c/60).to_i)) + ((c = c % 60) > 35 ? ((c.to_u8 + 29).unsafe_chr) : c.to_s(36))
-end
-
-PROXY_LIST = {
- "GB" => [{ip: "147.135.206.233", port: 3128}, {ip: "167.114.180.102", port: 8080}, {ip: "176.35.250.108", port: 8080}, {ip: "5.148.128.44", port: 80}, {ip: "62.7.85.234", port: 8080}, {ip: "88.150.135.10", port: 36624}],
- "DE" => [{ip: "138.201.223.250", port: 31288}, {ip: "138.68.73.59", port: 32574}, {ip: "159.69.211.173", port: 3128}, {ip: "173.249.43.105", port: 3128}, {ip: "212.202.244.90", port: 8080}, {ip: "5.56.18.35", port: 38827}],
- "FR" => [{ip: "137.74.254.242", port: 3128}, {ip: "151.80.143.155", port: 53281}, {ip: "178.33.150.97", port: 3128}, {ip: "37.187.2.31", port: 3128}, {ip: "5.135.164.72", port: 3128}, {ip: "5.39.91.73", port: 3128}, {ip: "51.38.162.2", port: 32231}, {ip: "51.38.217.121", port: 808}, {ip: "51.75.109.81", port: 3128}, {ip: "51.75.109.82", port: 3128}, {ip: "51.75.109.83", port: 3128}, {ip: "51.75.109.84", port: 3128}, {ip: "51.75.109.86", port: 3128}, {ip: "51.75.109.88", port: 3128}, {ip: "51.75.109.90", port: 3128}, {ip: "62.210.167.3", port: 3128}, {ip: "90.63.218.232", port: 8080}, {ip: "91.134.165.198", port: 9999}],
- "IN" => [{ip: "1.186.151.206", port: 36253}, {ip: "1.186.63.130", port: 39142}, {ip: "103.105.40.1", port: 16538}, {ip: "103.105.40.153", port: 16538}, {ip: "103.106.148.203", port: 60227}, {ip: "103.106.148.207", port: 51451}, {ip: "103.12.246.12", port: 8080}, {ip: "103.14.235.109", port: 8080}, {ip: "103.14.235.26", port: 8080}, {ip: "103.198.172.4", port: 50820}, {ip: "103.205.112.1", port: 23500}, {ip: "103.209.64.19", port: 6666}, {ip: "103.211.76.5", port: 8080}, {ip: "103.216.82.19", port: 6666}, {ip: "103.216.82.190", port: 6666}, {ip: "103.216.82.209", port: 54806}, {ip: "103.216.82.214", port: 6666}, {ip: "103.216.82.37", port: 6666}, {ip: "103.216.82.44", port: 8080}, {ip: "103.216.82.50", port: 53281}, {ip: "103.22.173.230", port: 8080}, {ip: "103.224.38.2", port: 83}, {ip: "103.226.142.90", port: 41386}, {ip: "103.236.114.38", port: 49638}, {ip: "103.240.161.107", port: 6666}, {ip: "103.240.161.108", port: 6666}, {ip: "103.240.161.109", port: 6666}, {ip: "103.240.161.59", port: 48809}, {ip: "103.245.198.101", port: 8080}, {ip: "103.250.148.82", port: 6666}, {ip: "103.251.58.51", port: 61489}, {ip: "103.253.169.115", port: 32731}, {ip: "103.253.211.182", port: 8080}, {ip: "103.253.211.182", port: 80}, {ip: "103.255.234.169", port: 39847}, {ip: "103.42.161.118", port: 8080}, {ip: "103.42.162.30", port: 8080}, {ip: "103.42.162.50", port: 8080}, {ip: "103.42.162.58", port: 8080}, {ip: "103.46.233.12", port: 83}, {ip: "103.46.233.13", port: 83}, {ip: "103.46.233.16", port: 83}, {ip: "103.46.233.17", port: 83}, {ip: "103.46.233.21", port: 83}, {ip: "103.46.233.23", port: 83}, {ip: "103.46.233.29", port: 81}, {ip: "103.46.233.29", port: 83}, {ip: "103.46.233.50", port: 83}, {ip: "103.47.153.87", port: 8080}, {ip: "103.47.66.2", port: 39804}, {ip: "103.49.53.1", port: 81}, {ip: "103.52.220.1", port: 49068}, {ip: "103.56.228.166", port: 53281}, {ip: "103.56.30.128", port: 8080}, {ip: "103.65.193.17", port: 50862}, {ip: "103.65.195.1", port: 33960}, {ip: "103.69.220.14", port: 3128}, {ip: "103.70.128.84", port: 8080}, {ip: "103.70.128.86", port: 8080}, {ip: "103.70.131.74", port: 8080}, {ip: "103.70.146.250", port: 59563}, {ip: "103.72.216.194", port: 38345}, {ip: "103.75.161.38", port: 21776}, {ip: "103.76.253.155", port: 3128}, {ip: "103.87.104.137", port: 8080}, {ip: "110.235.198.3", port: 57660}, {ip: "114.69.229.161", port: 8080}, {ip: "117.196.231.201", port: 37769}, {ip: "117.211.166.214", port: 3128}, {ip: "117.240.175.51", port: 3128}, {ip: "117.240.210.155", port: 53281}, {ip: "117.240.59.115", port: 36127}, {ip: "117.242.154.73", port: 33889}, {ip: "117.244.15.243", port: 3128}, {ip: "119.235.54.3", port: 8080}, {ip: "120.138.117.102", port: 59308}, {ip: "123.108.200.185", port: 83}, {ip: "123.108.200.217", port: 82}, {ip: "123.176.43.218", port: 40524}, {ip: "125.21.43.82", port: 8080}, {ip: "125.62.192.225", port: 82}, {ip: "125.62.192.33", port: 84}, {ip: "125.62.194.1", port: 83}, {ip: "125.62.213.134", port: 82}, {ip: "125.62.213.18", port: 83}, {ip: "125.62.213.201", port: 84}, {ip: "125.62.213.242", port: 83}, {ip: "125.62.214.185", port: 84}, {ip: "139.5.26.27", port: 53281}, {ip: "14.102.67.101", port: 30337}, {ip: "14.142.122.134", port: 8080}, {ip: "150.129.114.194", port: 6666}, {ip: "150.129.151.62", port: 6666}, {ip: "150.129.171.115", port: 6666}, {ip: "150.129.201.30", port: 6666}, {ip: "157.119.207.38", port: 53281}, {ip: "175.100.185.151", port: 53281}, {ip: "182.18.177.114", port: 56173}, {ip: "182.73.194.170", port: 8080}, {ip: "182.74.85.230", port: 51214}, {ip: "183.82.116.56", port: 8080}, {ip: "183.82.32.56", port: 49551}, {ip: "183.87.14.229", port: 53281}, {ip: "183.87.14.250", port: 44915}, {ip: "202.134.160.168", port: 8080}, {ip: "202.134.166.1", port: 8080}, {ip: "202.134.180.50", port: 8080}, {ip: "202.62.84.210", port: 53281}, {ip: "203.192.193.225", port: 8080}, {ip: "203.192.195.14", port: 31062}, {ip: "203.192.217.11", port: 8080}, {ip: "223.196.83.182", port: 53281}, {ip: "27.116.20.169", port: 36630}, {ip: "27.116.20.209", port: 36630}, {ip: "27.116.51.21", port: 36033}, {ip: "43.224.8.114", port: 50333}, {ip: "43.224.8.116", port: 6666}, {ip: "43.224.8.124", port: 6666}, {ip: "43.224.8.86", port: 6666}, {ip: "43.225.20.73", port: 8080}, {ip: "43.225.23.26", port: 8080}, {ip: "43.230.196.98", port: 36569}, {ip: "43.240.5.225", port: 31777}, {ip: "43.241.28.248", port: 8080}, {ip: "43.242.209.201", port: 8080}, {ip: "43.246.139.82", port: 8080}, {ip: "43.248.73.86", port: 53281}, {ip: "43.251.170.145", port: 54059}, {ip: "45.112.57.230", port: 61222}, {ip: "45.115.171.30", port: 47949}, {ip: "45.121.29.254", port: 54858}, {ip: "45.123.26.146", port: 53281}, {ip: "45.125.61.193", port: 32804}, {ip: "45.125.61.209", port: 32804}, {ip: "45.127.121.194", port: 53281}, {ip: "45.250.226.14", port: 3128}, {ip: "45.250.226.38", port: 8080}, {ip: "45.250.226.47", port: 8080}, {ip: "45.250.226.55", port: 8080}, {ip: "49.249.251.86", port: 53281}],
- "CN" => [{ip: "182.61.170.45", port: 3128}],
- "RU" => [{ip: "109.106.139.225", port: 45689}, {ip: "109.161.48.228", port: 53281}, {ip: "109.167.224.198", port: 51919}, {ip: "109.172.57.250", port: 23500}, {ip: "109.194.2.126", port: 61822}, {ip: "109.195.150.128", port: 37564}, {ip: "109.201.96.171", port: 31773}, {ip: "109.201.97.204", port: 41258}, {ip: "109.201.97.235", port: 39125}, {ip: "109.206.140.74", port: 45991}, {ip: "109.206.148.31", port: 30797}, {ip: "109.69.75.5", port: 46347}, {ip: "109.71.181.170", port: 53983}, {ip: "109.74.132.190", port: 42663}, {ip: "109.74.143.45", port: 36529}, {ip: "109.75.140.158", port: 59916}, {ip: "109.95.84.114", port: 52125}, {ip: "130.255.12.24", port: 31004}, {ip: "134.19.147.72", port: 44812}, {ip: "134.90.181.7", port: 54353}, {ip: "145.255.6.171", port: 31252}, {ip: "146.120.227.3", port: 8080}, {ip: "149.255.112.194", port: 48968}, {ip: "158.46.127.222", port: 52574}, {ip: "158.46.43.144", port: 39120}, {ip: "158.58.130.185", port: 50016}, {ip: "158.58.132.12", port: 56962}, {ip: "158.58.133.106", port: 41258}, {ip: "158.58.133.13", port: 21213}, {ip: "176.101.0.47", port: 34471}, {ip: "176.101.89.226", port: 33470}, {ip: "176.106.12.65", port: 30120}, {ip: "176.107.80.110", port: 58901}, {ip: "176.110.121.9", port: 46322}, {ip: "176.110.121.90", port: 21776}, {ip: "176.111.97.18", port: 8080}, {ip: "176.112.106.230", port: 33996}, {ip: "176.112.110.40", port: 61142}, {ip: "176.113.116.70", port: 55589}, {ip: "176.113.27.192", port: 47337}, {ip: "176.115.197.118", port: 8080}, {ip: "176.117.255.182", port: 53100}, {ip: "176.120.200.69", port: 44331}, {ip: "176.124.123.93", port: 41258}, {ip: "176.192.124.98", port: 60787}, {ip: "176.192.5.238", port: 61227}, {ip: "176.192.8.206", port: 39422}, {ip: "176.193.15.94", port: 8080}, {ip: "176.196.195.170", port: 48129}, {ip: "176.196.198.154", port: 35252}, {ip: "176.196.238.234", port: 44648}, {ip: "176.196.239.46", port: 35656}, {ip: "176.196.246.6", port: 53281}, {ip: "176.196.84.138", port: 51336}, {ip: "176.197.145.246", port: 32649}, {ip: "176.197.99.142", port: 47278}, {ip: "176.215.1.108", port: 60339}, {ip: "176.215.170.147", port: 35604}, {ip: "176.56.23.14", port: 35340}, {ip: "176.62.185.54", port: 53883}, {ip: "176.74.13.110", port: 8080}, {ip: "178.130.29.226", port: 53295}, {ip: "178.170.254.178", port: 46788}, {ip: "178.213.13.136", port: 53281}, {ip: "178.218.104.8", port: 49707}, {ip: "178.219.183.163", port: 8080}, {ip: "178.237.180.34", port: 57307}, {ip: "178.57.101.212", port: 38020}, {ip: "178.57.101.235", port: 31309}, {ip: "178.64.190.133", port: 46688}, {ip: "178.75.1.111", port: 50411}, {ip: "178.75.27.131", port: 41879}, {ip: "185.13.35.178", port: 40654}, {ip: "185.15.189.67", port: 30215}, {ip: "185.175.119.137", port: 41258}, {ip: "185.18.111.194", port: 41258}, {ip: "185.19.176.237", port: 53281}, {ip: "185.190.40.115", port: 31747}, {ip: "185.216.195.134", port: 61287}, {ip: "185.22.172.94", port: 10010}, {ip: "185.22.172.94", port: 1448}, {ip: "185.22.174.65", port: 10010}, {ip: "185.22.174.65", port: 1448}, {ip: "185.23.64.100", port: 3130}, {ip: "185.23.82.39", port: 59248}, {ip: "185.233.94.105", port: 59288}, {ip: "185.233.94.146", port: 57736}, {ip: "185.3.68.54", port: 53500}, {ip: "185.32.120.177", port: 60724}, {ip: "185.34.20.164", port: 53700}, {ip: "185.34.23.43", port: 63238}, {ip: "185.51.60.141", port: 39935}, {ip: "185.61.92.228", port: 33060}, {ip: "185.61.93.67", port: 49107}, {ip: "185.7.233.66", port: 53504}, {ip: "185.72.225.10", port: 56285}, {ip: "185.75.5.158", port: 60819}, {ip: "185.9.86.186", port: 39345}, {ip: "188.133.136.10", port: 47113}, {ip: "188.168.75.254", port: 56899}, {ip: "188.170.41.6", port: 60332}, {ip: "188.187.189.142", port: 38264}, {ip: "188.234.151.103", port: 8080}, {ip: "188.235.11.88", port: 57143}, {ip: "188.235.137.196", port: 23500}, {ip: "188.244.175.2", port: 8080}, {ip: "188.255.82.136", port: 53281}, {ip: "188.43.4.117", port: 60577}, {ip: "188.68.95.166", port: 41258}, {ip: "188.92.242.180", port: 52048}, {ip: "188.93.242.213", port: 49774}, {ip: "192.162.193.243", port: 36910}, {ip: "192.162.214.11", port: 41258}, {ip: "193.106.170.133", port: 38591}, {ip: "193.232.113.244", port: 40412}, {ip: "193.232.234.130", port: 61932}, {ip: "193.242.177.105", port: 53281}, {ip: "193.242.178.50", port: 52376}, {ip: "193.242.178.90", port: 8080}, {ip: "193.33.101.152", port: 34611}, {ip: "194.114.128.149", port: 61213}, {ip: "194.135.15.146", port: 59328}, {ip: "194.135.216.178", port: 56805}, {ip: "194.135.75.74", port: 41258}, {ip: "194.146.201.67", port: 53281}, {ip: "194.186.18.46", port: 56408}, {ip: "194.186.20.62", port: 21231}, {ip: "194.190.171.214", port: 43960}, {ip: "194.9.27.82", port: 42720}, {ip: "195.133.232.58", port: 41733}, {ip: "195.14.114.116", port: 59530}, {ip: "195.14.114.24", port: 56897}, {ip: "195.158.250.97", port: 41582}, {ip: "195.16.48.142", port: 36083}, {ip: "195.191.183.169", port: 47238}, {ip: "195.206.45.112", port: 53281}, {ip: "195.208.172.70", port: 8080}, {ip: "195.209.141.67", port: 31927}, {ip: "195.209.176.2", port: 8080}, {ip: "195.210.144.166", port: 30088}, {ip: "195.211.160.88", port: 44464}, {ip: "195.218.144.182", port: 31705}, {ip: "195.46.168.147", port: 8080}, {ip: "195.9.188.78", port: 53281}, {ip: "195.9.209.10", port: 35242}, {ip: "195.9.223.246", port: 52098}, {ip: "195.9.237.66", port: 8080}, {ip: "195.9.91.66", port: 33199}, {ip: "195.91.132.20", port: 19600}, {ip: "195.98.183.82", port: 30953}, {ip: "212.104.82.246", port: 36495}, {ip: "212.119.229.18", port: 33852}, {ip: "212.13.97.122", port: 30466}, {ip: "212.19.21.19", port: 53264}, {ip: "212.19.5.157", port: 58442}, {ip: "212.19.8.223", port: 30281}, {ip: "212.19.8.239", port: 55602}, {ip: "212.192.202.207", port: 4550}, {ip: "212.22.80.224", port: 34822}, {ip: "212.26.247.178", port: 38418}, {ip: "212.33.228.161", port: 37971}, {ip: "212.33.243.83", port: 38605}, {ip: "212.34.53.126", port: 44369}, {ip: "212.5.107.81", port: 56481}, {ip: "212.7.230.7", port: 51405}, {ip: "212.77.138.161", port: 41258}, {ip: "213.108.221.201", port: 32800}, {ip: "213.109.7.135", port: 59918}, {ip: "213.128.9.204", port: 35549}, {ip: "213.134.196.12", port: 38723}, {ip: "213.168.37.86", port: 8080}, {ip: "213.187.118.184", port: 53281}, {ip: "213.21.23.98", port: 53281}, {ip: "213.210.67.166", port: 53281}, {ip: "213.234.0.242", port: 56503}, {ip: "213.247.192.131", port: 41258}, {ip: "213.251.226.208", port: 56900}, {ip: "213.33.155.80", port: 44387}, {ip: "213.33.199.194", port: 36411}, {ip: "213.33.224.82", port: 8080}, {ip: "213.59.153.19", port: 53281}, {ip: "217.10.45.103", port: 8080}, {ip: "217.107.197.39", port: 33628}, {ip: "217.116.60.66", port: 21231}, {ip: "217.195.87.58", port: 41258}, {ip: "217.197.239.54", port: 34463}, {ip: "217.74.161.42", port: 34175}, {ip: "217.8.84.76", port: 46378}, {ip: "31.131.67.14", port: 8080}, {ip: "31.132.127.142", port: 35432}, {ip: "31.132.218.252", port: 32423}, {ip: "31.173.17.118", port: 51317}, {ip: "31.193.124.70", port: 53281}, {ip: "31.210.211.147", port: 8080}, {ip: "31.220.183.217", port: 53281}, {ip: "31.29.212.82", port: 35066}, {ip: "31.42.254.24", port: 30912}, {ip: "31.47.189.14", port: 38473}, {ip: "37.113.129.98", port: 41665}, {ip: "37.192.103.164", port: 34835}, {ip: "37.192.194.50", port: 50165}, {ip: "37.192.99.151", port: 51417}, {ip: "37.205.83.91", port: 35888}, {ip: "37.233.85.155", port: 53281}, {ip: "37.235.167.66", port: 53281}, {ip: "37.235.65.2", port: 47816}, {ip: "37.235.67.178", port: 34450}, {ip: "37.9.134.133", port: 41262}, {ip: "46.150.174.90", port: 53281}, {ip: "46.151.156.198", port: 56013}, {ip: "46.16.226.10", port: 8080}, {ip: "46.163.131.55", port: 48306}, {ip: "46.173.191.51", port: 53281}, {ip: "46.174.222.61", port: 34977}, {ip: "46.180.96.79", port: 42319}, {ip: "46.181.151.79", port: 39386}, {ip: "46.21.74.130", port: 8080}, {ip: "46.227.162.98", port: 51558}, {ip: "46.229.187.169", port: 53281}, {ip: "46.229.67.198", port: 47437}, {ip: "46.243.179.221", port: 41598}, {ip: "46.254.217.54", port: 53281}, {ip: "46.32.68.188", port: 39707}, {ip: "46.39.224.112", port: 36765}, {ip: "46.63.162.171", port: 8080}, {ip: "46.73.33.253", port: 8080}, {ip: "5.128.32.12", port: 51959}, {ip: "5.129.155.3", port: 51390}, {ip: "5.129.16.27", port: 48935}, {ip: "5.141.81.65", port: 61853}, {ip: "5.16.15.234", port: 8080}, {ip: "5.167.51.235", port: 8080}, {ip: "5.167.96.238", port: 3128}, {ip: "5.19.165.235", port: 30793}, {ip: "5.35.93.157", port: 31773}, {ip: "5.59.137.90", port: 8888}, {ip: "5.8.207.160", port: 57192}, {ip: "62.122.97.66", port: 59143}, {ip: "62.148.151.253", port: 53570}, {ip: "62.152.85.158", port: 31156}, {ip: "62.165.54.153", port: 55522}, {ip: "62.173.140.14", port: 8080}, {ip: "62.173.155.206", port: 41258}, {ip: "62.182.206.19", port: 37715}, {ip: "62.213.14.166", port: 8080}, {ip: "62.76.123.224", port: 8080}, {ip: "77.221.220.133", port: 44331}, {ip: "77.232.153.248", port: 60950}, {ip: "77.233.10.37", port: 54210}, {ip: "77.244.27.109", port: 47554}, {ip: "77.37.142.203", port: 53281}, {ip: "77.39.29.29", port: 49243}, {ip: "77.75.6.34", port: 8080}, {ip: "77.87.102.7", port: 42601}, {ip: "77.94.121.212", port: 36896}, {ip: "77.94.121.51", port: 45293}, {ip: "78.110.154.177", port: 59888}, {ip: "78.140.201.226", port: 8090}, {ip: "78.153.4.122", port: 9001}, {ip: "78.156.225.170", port: 41258}, {ip: "78.156.243.146", port: 59730}, {ip: "78.29.14.201", port: 39001}, {ip: "78.81.24.112", port: 8080}, {ip: "78.85.36.203", port: 8080}, {ip: "79.104.219.125", port: 3128}, {ip: "79.104.55.134", port: 8080}, {ip: "79.137.181.170", port: 8080}, {ip: "79.173.124.194", port: 47832}, {ip: "79.173.124.207", port: 53281}, {ip: "79.174.186.168", port: 45710}, {ip: "79.175.51.13", port: 54853}, {ip: "79.175.57.77", port: 55477}, {ip: "80.234.107.118", port: 56952}, {ip: "80.237.6.1", port: 34880}, {ip: "80.243.14.182", port: 49320}, {ip: "80.251.48.215", port: 45157}, {ip: "80.254.121.66", port: 41055}, {ip: "80.254.125.236", port: 80}, {ip: "80.72.121.185", port: 52379}, {ip: "80.89.133.210", port: 3128}, {ip: "80.91.17.113", port: 41258}, {ip: "81.162.61.166", port: 40392}, {ip: "81.163.57.121", port: 41258}, {ip: "81.163.57.46", port: 41258}, {ip: "81.163.62.136", port: 41258}, {ip: "81.23.112.98", port: 55269}, {ip: "81.23.118.106", port: 60427}, {ip: "81.23.177.245", port: 8080}, {ip: "81.24.126.166", port: 8080}, {ip: "81.30.216.147", port: 41258}, {ip: "81.95.131.10", port: 44292}, {ip: "82.114.125.22", port: 8080}, {ip: "82.151.208.20", port: 8080}, {ip: "83.221.216.110", port: 47326}, {ip: "83.246.139.24", port: 8080}, {ip: "83.97.108.8", port: 41258}, {ip: "84.22.154.76", port: 8080}, {ip: "84.52.110.36", port: 38674}, {ip: "84.52.74.194", port: 8080}, {ip: "84.52.77.227", port: 41806}, {ip: "84.52.79.166", port: 43548}, {ip: "84.52.84.157", port: 44331}, {ip: "84.52.88.125", port: 32666}, {ip: "85.113.48.148", port: 8080}, {ip: "85.113.49.220", port: 8080}, {ip: "85.12.193.210", port: 58470}, {ip: "85.15.179.5", port: 8080}, {ip: "85.173.244.102", port: 53281}, {ip: "85.174.227.52", port: 59280}, {ip: "85.192.184.133", port: 8080}, {ip: "85.192.184.133", port: 80}, {ip: "85.21.240.193", port: 55820}, {ip: "85.21.63.219", port: 53281}, {ip: "85.235.190.18", port: 42494}, {ip: "85.237.56.193", port: 8080}, {ip: "85.91.119.6", port: 8080}, {ip: "86.102.116.30", port: 8080}, {ip: "86.110.30.146", port: 38109}, {ip: "87.117.3.129", port: 3128}, {ip: "87.225.108.195", port: 8080}, {ip: "87.228.103.111", port: 8080}, {ip: "87.228.103.43", port: 8080}, {ip: "87.229.143.10", port: 48872}, {ip: "87.249.205.103", port: 8080}, {ip: "87.249.21.193", port: 43079}, {ip: "87.255.13.217", port: 8080}, {ip: "88.147.159.167", port: 53281}, {ip: "88.200.225.32", port: 38583}, {ip: "88.204.59.177", port: 32666}, {ip: "88.84.209.69", port: 30819}, {ip: "88.87.72.72", port: 8080}, {ip: "88.87.79.20", port: 8080}, {ip: "88.87.91.163", port: 48513}, {ip: "88.87.93.20", port: 33277}, {ip: "89.109.12.82", port: 47972}, {ip: "89.109.21.43", port: 9090}, {ip: "89.109.239.183", port: 41041}, {ip: "89.109.54.137", port: 36469}, {ip: "89.17.37.218", port: 52957}, {ip: "89.189.130.103", port: 32626}, {ip: "89.189.159.214", port: 42530}, {ip: "89.189.174.121", port: 52636}, {ip: "89.23.18.29", port: 53281}, {ip: "89.249.251.21", port: 3128}, {ip: "89.250.149.114", port: 60981}, {ip: "89.250.17.209", port: 8080}, {ip: "89.250.19.173", port: 8080}, {ip: "90.150.87.172", port: 81}, {ip: "90.154.125.173", port: 33078}, {ip: "90.188.38.81", port: 60585}, {ip: "90.189.151.183", port: 32601}, {ip: "91.103.208.114", port: 57063}, {ip: "91.122.100.222", port: 44331}, {ip: "91.122.207.229", port: 8080}, {ip: "91.144.139.93", port: 3128}, {ip: "91.144.142.19", port: 44617}, {ip: "91.146.16.54", port: 57902}, {ip: "91.190.116.194", port: 38783}, {ip: "91.190.80.100", port: 31659}, {ip: "91.190.85.97", port: 34286}, {ip: "91.203.36.188", port: 8080}, {ip: "91.205.131.102", port: 8080}, {ip: "91.205.146.25", port: 37501}, {ip: "91.210.94.212", port: 52635}, {ip: "91.213.23.110", port: 8080}, {ip: "91.215.22.51", port: 53305}, {ip: "91.217.42.3", port: 8080}, {ip: "91.217.42.4", port: 8080}, {ip: "91.220.135.146", port: 41258}, {ip: "91.222.167.213", port: 38057}, {ip: "91.226.140.71", port: 33199}, {ip: "91.235.7.216", port: 59067}, {ip: "92.124.195.22", port: 3128}, {ip: "92.126.193.180", port: 8080}, {ip: "92.241.110.223", port: 53281}, {ip: "92.252.240.1", port: 53281}, {ip: "92.255.164.187", port: 3128}, {ip: "92.255.195.57", port: 53281}, {ip: "92.255.229.146", port: 55785}, {ip: "92.255.5.2", port: 41012}, {ip: "92.38.32.36", port: 56113}, {ip: "92.39.138.98", port: 31150}, {ip: "92.51.16.155", port: 46202}, {ip: "92.55.59.63", port: 33030}, {ip: "93.170.112.200", port: 47995}, {ip: "93.183.86.185", port: 53281}, {ip: "93.188.45.157", port: 8080}, {ip: "93.81.246.5", port: 53281}, {ip: "93.91.112.247", port: 41258}, {ip: "94.127.217.66", port: 40115}, {ip: "94.154.85.214", port: 8080}, {ip: "94.180.106.94", port: 32767}, {ip: "94.180.249.187", port: 38051}, {ip: "94.230.243.6", port: 8080}, {ip: "94.232.57.231", port: 51064}, {ip: "94.24.244.170", port: 48936}, {ip: "94.242.55.108", port: 10010}, {ip: "94.242.55.108", port: 1448}, {ip: "94.242.57.136", port: 10010}, {ip: "94.242.57.136", port: 1448}, {ip: "94.242.58.108", port: 10010}, {ip: "94.242.58.108", port: 1448}, {ip: "94.242.58.14", port: 10010}, {ip: "94.242.58.14", port: 1448}, {ip: "94.242.58.142", port: 10010}, {ip: "94.242.58.142", port: 1448}, {ip: "94.242.59.245", port: 10010}, {ip: "94.242.59.245", port: 1448}, {ip: "94.247.241.70", port: 53640}, {ip: "94.247.62.165", port: 33176}, {ip: "94.253.13.228", port: 54935}, {ip: "94.253.14.187", port: 55045}, {ip: "94.28.94.154", port: 46966}, {ip: "94.73.217.125", port: 40858}, {ip: "95.140.19.9", port: 8080}, {ip: "95.140.20.94", port: 33994}, {ip: "95.154.137.66", port: 41258}, {ip: "95.154.159.119", port: 44242}, {ip: "95.154.82.254", port: 52484}, {ip: "95.161.157.227", port: 43170}, {ip: "95.161.182.146", port: 33877}, {ip: "95.161.189.26", port: 61522}, {ip: "95.165.163.146", port: 8888}, {ip: "95.165.172.90", port: 60496}, {ip: "95.165.182.18", port: 38950}, {ip: "95.165.203.222", port: 33805}, {ip: "95.165.244.122", port: 58162}, {ip: "95.167.123.54", port: 58664}, {ip: "95.167.241.242", port: 49636}, {ip: "95.171.1.92", port: 35956}, {ip: "95.172.52.230", port: 35989}, {ip: "95.181.35.30", port: 40804}, {ip: "95.181.56.178", port: 39144}, {ip: "95.181.75.228", port: 53281}, {ip: "95.188.74.194", port: 57122}, {ip: "95.189.112.214", port: 35508}, {ip: "95.31.10.247", port: 30711}, {ip: "95.31.197.77", port: 41651}, {ip: "95.31.2.199", port: 33632}, {ip: "95.71.125.50", port: 49882}, {ip: "95.73.62.13", port: 32185}, {ip: "95.79.36.55", port: 44861}, {ip: "95.79.55.196", port: 53281}, {ip: "95.79.99.148", port: 3128}, {ip: "95.80.65.39", port: 43555}, {ip: "95.80.93.44", port: 41258}, {ip: "95.80.98.41", port: 8080}, {ip: "95.83.156.250", port: 58438}, {ip: "95.84.128.25", port: 33765}, {ip: "95.84.154.73", port: 57423}],
- "CA" => [{ip: "144.217.161.149", port: 8080}, {ip: "24.37.9.6", port: 54154}, {ip: "54.39.138.144", port: 3128}, {ip: "54.39.138.145", port: 3128}, {ip: "54.39.138.151", port: 3128}, {ip: "54.39.138.152", port: 3128}, {ip: "54.39.138.153", port: 3128}, {ip: "54.39.138.154", port: 3128}, {ip: "54.39.138.155", port: 3128}, {ip: "54.39.138.156", port: 3128}, {ip: "54.39.138.157", port: 3128}, {ip: "54.39.53.104", port: 3128}, {ip: "66.70.167.113", port: 3128}, {ip: "66.70.167.116", port: 3128}, {ip: "66.70.167.117", port: 3128}, {ip: "66.70.167.119", port: 3128}, {ip: "66.70.167.120", port: 3128}, {ip: "66.70.167.125", port: 3128}, {ip: "66.70.188.148", port: 3128}, {ip: "70.35.213.229", port: 36127}, {ip: "70.65.233.174", port: 8080}, {ip: "72.139.24.66", port: 38861}, {ip: "74.15.191.160", port: 41564}],
- "JP" => [{ip: "47.91.20.67", port: 8080}, {ip: "61.118.35.94", port: 55725}],
- "IT" => [{ip: "109.70.201.97", port: 53517}, {ip: "176.31.82.212", port: 8080}, {ip: "185.132.228.118", port: 55583}, {ip: "185.49.58.88", port: 56006}, {ip: "185.94.89.179", port: 41258}, {ip: "213.203.134.10", port: 41258}, {ip: "217.61.172.12", port: 41369}, {ip: "46.232.143.126", port: 41258}, {ip: "46.232.143.253", port: 41258}, {ip: "93.67.154.125", port: 8080}, {ip: "93.67.154.125", port: 80}, {ip: "95.169.95.242", port: 53803}],
- "TH" => [{ip: "1.10.184.166", port: 57330}, {ip: "1.10.186.100", port: 55011}, {ip: "1.10.186.209", port: 32431}, {ip: "1.10.186.245", port: 34360}, {ip: "1.10.186.93", port: 53711}, {ip: "1.10.187.118", port: 62000}, {ip: "1.10.187.34", port: 51635}, {ip: "1.10.187.43", port: 38715}, {ip: "1.10.188.181", port: 51093}, {ip: "1.10.188.83", port: 31940}, {ip: "1.10.188.95", port: 30593}, {ip: "1.10.189.58", port: 48564}, {ip: "1.179.157.237", port: 46178}, {ip: "1.179.164.213", port: 8080}, {ip: "1.179.198.37", port: 8080}, {ip: "1.20.100.99", port: 53794}, {ip: "1.20.101.221", port: 55707}, {ip: "1.20.101.254", port: 35394}, {ip: "1.20.101.80", port: 36234}, {ip: "1.20.102.133", port: 40296}, {ip: "1.20.103.13", port: 40544}, {ip: "1.20.103.56", port: 55422}, {ip: "1.20.96.234", port: 53142}, {ip: "1.20.97.54", port: 60122}, {ip: "1.20.99.63", port: 32123}, {ip: "101.108.92.20", port: 8080}, {ip: "101.109.143.71", port: 36127}, {ip: "101.51.141.110", port: 42860}, {ip: "101.51.141.60", port: 60417}, {ip: "103.246.17.237", port: 3128}, {ip: "110.164.73.131", port: 8080}, {ip: "110.164.87.80", port: 35844}, {ip: "110.77.134.106", port: 8080}, {ip: "113.53.29.92", port: 47297}, {ip: "113.53.83.192", port: 32780}, {ip: "113.53.83.195", port: 35686}, {ip: "113.53.91.214", port: 8080}, {ip: "115.87.27.0", port: 53276}, {ip: "118.172.211.3", port: 58535}, {ip: "118.172.211.40", port: 30430}, {ip: "118.174.196.174", port: 23500}, {ip: "118.174.196.203", port: 23500}, {ip: "118.174.220.107", port: 41222}, {ip: "118.174.220.110", port: 39025}, {ip: "118.174.220.115", port: 41011}, {ip: "118.174.220.118", port: 59556}, {ip: "118.174.220.136", port: 55041}, {ip: "118.174.220.163", port: 31561}, {ip: "118.174.220.168", port: 47455}, {ip: "118.174.220.231", port: 40924}, {ip: "118.174.220.238", port: 46326}, {ip: "118.174.234.13", port: 53084}, {ip: "118.174.234.26", port: 41926}, {ip: "118.174.234.32", port: 57403}, {ip: "118.174.234.59", port: 59149}, {ip: "118.174.234.68", port: 42626}, {ip: "118.174.234.83", port: 38006}, {ip: "118.175.207.104", port: 38959}, {ip: "118.175.244.111", port: 8080}, {ip: "118.175.93.207", port: 50738}, {ip: "122.154.38.53", port: 8080}, {ip: "122.154.59.6", port: 8080}, {ip: "122.154.72.102", port: 8080}, {ip: "122.155.222.98", port: 3128}, {ip: "124.121.22.121", port: 61699}, {ip: "125.24.156.16", port: 44321}, {ip: "125.25.165.105", port: 33850}, {ip: "125.25.165.111", port: 40808}, {ip: "125.25.165.42", port: 47221}, {ip: "125.25.201.14", port: 30100}, {ip: "125.26.99.135", port: 55637}, {ip: "125.26.99.141", port: 38537}, {ip: "125.26.99.148", port: 31818}, {ip: "134.236.247.137", port: 8080}, {ip: "159.192.98.224", port: 3128}, {ip: "171.100.2.154", port: 8080}, {ip: "171.100.9.126", port: 49163}, {ip: "180.180.156.116", port: 48431}, {ip: "180.180.156.46", port: 48507}, {ip: "180.180.156.87", port: 36628}, {ip: "180.180.218.204", port: 51565}, {ip: "180.180.8.34", port: 8080}, {ip: "182.52.238.125", port: 58861}, {ip: "182.52.74.73", port: 36286}, {ip: "182.52.74.76", port: 34084}, {ip: "182.52.74.77", port: 34825}, {ip: "182.52.74.78", port: 48708}, {ip: "182.52.90.45", port: 53799}, {ip: "182.53.206.155", port: 34307}, {ip: "182.53.206.43", port: 45330}, {ip: "182.53.206.49", port: 54228}, {ip: "183.88.212.141", port: 8080}, {ip: "183.88.212.184", port: 8080}, {ip: "183.88.213.85", port: 8080}, {ip: "183.88.214.47", port: 8080}, {ip: "184.82.128.211", port: 8080}, {ip: "202.183.201.13", port: 8081}, {ip: "202.29.20.151", port: 43083}, {ip: "203.150.172.151", port: 8080}, {ip: "27.131.157.94", port: 8080}, {ip: "27.145.100.22", port: 8080}, {ip: "27.145.100.243", port: 8080}, {ip: "49.231.196.114", port: 53281}, {ip: "58.97.72.83", port: 8080}, {ip: "61.19.145.66", port: 8080}],
- "ES" => [{ip: "185.198.184.14", port: 48122}, {ip: "185.26.226.241", port: 36012}, {ip: "194.224.188.82", port: 3128}, {ip: "195.235.68.61", port: 3128}, {ip: "195.53.237.122", port: 3128}, {ip: "195.53.86.82", port: 3128}, {ip: "213.96.245.47", port: 8080}, {ip: "217.125.71.214", port: 33950}, {ip: "62.14.178.72", port: 53281}, {ip: "80.35.254.42", port: 53281}, {ip: "81.33.4.214", port: 61711}, {ip: "83.175.238.170", port: 53281}, {ip: "85.217.137.77", port: 3128}, {ip: "90.170.205.178", port: 33680}, {ip: "93.156.177.91", port: 53281}, {ip: "95.60.152.139", port: 37995}],
- "AE" => [{ip: "178.32.5.90", port: 36159}],
- "KR" => [{ip: "112.217.219.179", port: 3128}, {ip: "114.141.229.2", port: 58115}, {ip: "121.139.218.165", port: 31409}, {ip: "122.49.112.2", port: 38592}, {ip: "61.42.18.132", port: 53281}],
- "BR" => [{ip: "128.201.97.157", port: 53281}, {ip: "128.201.97.158", port: 53281}, {ip: "131.0.246.157", port: 35252}, {ip: "131.161.26.90", port: 8080}, {ip: "131.72.143.100", port: 41396}, {ip: "138.0.24.66", port: 53281}, {ip: "138.121.130.50", port: 50600}, {ip: "138.121.155.127", port: 61932}, {ip: "138.121.32.133", port: 23492}, {ip: "138.185.176.63", port: 53281}, {ip: "138.204.233.190", port: 53281}, {ip: "138.204.233.242", port: 53281}, {ip: "138.219.71.74", port: 52688}, {ip: "138.36.107.24", port: 41184}, {ip: "138.94.115.166", port: 8080}, {ip: "143.0.188.161", port: 53281}, {ip: "143.202.218.135", port: 8080}, {ip: "143.208.2.42", port: 53281}, {ip: "143.208.79.223", port: 8080}, {ip: "143.255.52.102", port: 40687}, {ip: "143.255.52.116", port: 57856}, {ip: "143.255.52.117", port: 37279}, {ip: "144.217.22.128", port: 8080}, {ip: "168.0.8.225", port: 8080}, {ip: "168.0.8.55", port: 8080}, {ip: "168.121.139.54", port: 40056}, {ip: "168.181.168.23", port: 53281}, {ip: "168.181.170.198", port: 31935}, {ip: "168.232.198.25", port: 32009}, {ip: "168.232.198.35", port: 42267}, {ip: "168.232.207.145", port: 46342}, {ip: "170.0.104.107", port: 60337}, {ip: "170.0.112.2", port: 50359}, {ip: "170.0.112.229", port: 50359}, {ip: "170.238.118.107", port: 34314}, {ip: "170.239.144.9", port: 3128}, {ip: "170.247.29.138", port: 8080}, {ip: "170.81.237.36", port: 37124}, {ip: "170.84.51.74", port: 53281}, {ip: "170.84.60.222", port: 42981}, {ip: "177.10.202.67", port: 8080}, {ip: "177.101.60.86", port: 80}, {ip: "177.103.231.211", port: 55091}, {ip: "177.12.80.50", port: 50556}, {ip: "177.131.13.9", port: 20183}, {ip: "177.135.178.115", port: 42510}, {ip: "177.135.248.75", port: 20183}, {ip: "177.184.206.238", port: 39508}, {ip: "177.185.148.46", port: 58623}, {ip: "177.200.83.238", port: 8080}, {ip: "177.21.24.146", port: 666}, {ip: "177.220.188.120", port: 47556}, {ip: "177.220.188.213", port: 8080}, {ip: "177.222.229.243", port: 23500}, {ip: "177.234.161.42", port: 8080}, {ip: "177.36.11.241", port: 3128}, {ip: "177.36.12.193", port: 23500}, {ip: "177.37.199.175", port: 49608}, {ip: "177.39.187.70", port: 37315}, {ip: "177.44.175.199", port: 8080}, {ip: "177.46.148.126", port: 3128}, {ip: "177.46.148.142", port: 3128}, {ip: "177.47.194.98", port: 21231}, {ip: "177.5.98.58", port: 20183}, {ip: "177.52.55.19", port: 60901}, {ip: "177.54.200.66", port: 57526}, {ip: "177.55.255.74", port: 37147}, {ip: "177.67.217.94", port: 53281}, {ip: "177.73.248.6", port: 54381}, {ip: "177.73.4.234", port: 23500}, {ip: "177.75.143.211", port: 35955}, {ip: "177.75.161.206", port: 3128}, {ip: "177.75.86.49", port: 20183}, {ip: "177.8.216.106", port: 8080}, {ip: "177.8.216.114", port: 8080}, {ip: "177.8.37.247", port: 56052}, {ip: "177.84.216.17", port: 50569}, {ip: "177.85.200.254", port: 53095}, {ip: "177.87.169.1", port: 53281}, {ip: "179.107.97.178", port: 3128}, {ip: "179.109.144.25", port: 8080}, {ip: "179.109.193.137", port: 53281}, {ip: "179.189.125.206", port: 8080}, {ip: "179.97.30.46", port: 53100}, {ip: "186.192.195.220", port: 38983}, {ip: "186.193.11.226", port: 48999}, {ip: "186.193.26.106", port: 3128}, {ip: "186.208.220.248", port: 3128}, {ip: "186.209.243.142", port: 3128}, {ip: "186.209.243.233", port: 3128}, {ip: "186.211.106.227", port: 34334}, {ip: "186.211.160.178", port: 36756}, {ip: "186.215.133.170", port: 20183}, {ip: "186.216.81.21", port: 31773}, {ip: "186.219.214.13", port: 32708}, {ip: "186.224.94.6", port: 48957}, {ip: "186.225.97.246", port: 43082}, {ip: "186.226.171.163", port: 48698}, {ip: "186.226.179.2", port: 56089}, {ip: "186.226.234.67", port: 33834}, {ip: "186.228.147.58", port: 20183}, {ip: "186.233.97.163", port: 8888}, {ip: "186.248.170.82", port: 53281}, {ip: "186.249.213.101", port: 53482}, {ip: "186.249.213.65", port: 52018}, {ip: "186.250.213.225", port: 60774}, {ip: "186.250.96.70", port: 8080}, {ip: "186.250.96.77", port: 8080}, {ip: "187.1.43.246", port: 53396}, {ip: "187.108.36.250", port: 20183}, {ip: "187.108.38.10", port: 20183}, {ip: "187.109.36.251", port: 20183}, {ip: "187.109.40.9", port: 20183}, {ip: "187.109.56.101", port: 20183}, {ip: "187.111.90.89", port: 53281}, {ip: "187.115.10.50", port: 20183}, {ip: "187.19.62.7", port: 59010}, {ip: "187.33.79.61", port: 33469}, {ip: "187.35.158.150", port: 38872}, {ip: "187.44.1.167", port: 8080}, {ip: "187.45.127.87", port: 20183}, {ip: "187.45.156.109", port: 8080}, {ip: "187.5.218.215", port: 20183}, {ip: "187.58.65.225", port: 3128}, {ip: "187.63.111.37", port: 3128}, {ip: "187.72.166.10", port: 8080}, {ip: "187.73.68.14", port: 53281}, {ip: "187.84.177.6", port: 45903}, {ip: "187.84.191.170", port: 43936}, {ip: "187.87.204.210", port: 45597}, {ip: "187.87.39.247", port: 31793}, {ip: "189.1.16.162", port: 23500}, {ip: "189.113.124.162", port: 8080}, {ip: "189.124.195.185", port: 37318}, {ip: "189.3.196.18", port: 61595}, {ip: "189.37.33.59", port: 35532}, {ip: "189.7.49.66", port: 42700}, {ip: "189.90.194.35", port: 30843}, {ip: "189.90.248.75", port: 8080}, {ip: "189.91.231.43", port: 3128}, {ip: "191.239.243.156", port: 3128}, {ip: "191.240.154.246", port: 23500}, {ip: "191.240.156.154", port: 36127}, {ip: "191.240.99.142", port: 9090}, {ip: "191.241.226.230", port: 53281}, {ip: "191.241.228.74", port: 20183}, {ip: "191.241.228.78", port: 20183}, {ip: "191.241.33.238", port: 39188}, {ip: "191.241.36.170", port: 8080}, {ip: "191.241.36.218", port: 3128}, {ip: "191.242.182.132", port: 8081}, {ip: "191.243.221.130", port: 3128}, {ip: "191.255.207.231", port: 20183}, {ip: "191.36.192.196", port: 3128}, {ip: "191.36.244.230", port: 51377}, {ip: "191.5.0.79", port: 53281}, {ip: "191.6.228.6", port: 53281}, {ip: "191.7.193.18", port: 38133}, {ip: "191.7.20.134", port: 3128}, {ip: "192.140.91.173", port: 20183}, {ip: "200.150.86.138", port: 44677}, {ip: "200.155.36.185", port: 3128}, {ip: "200.155.36.188", port: 3128}, {ip: "200.155.39.41", port: 3128}, {ip: "200.174.158.26", port: 34112}, {ip: "200.187.177.105", port: 20183}, {ip: "200.187.87.138", port: 20183}, {ip: "200.192.252.201", port: 8080}, {ip: "200.192.255.102", port: 8080}, {ip: "200.203.144.2", port: 50262}, {ip: "200.229.238.42", port: 20183}, {ip: "200.233.134.85", port: 43172}, {ip: "200.233.136.177", port: 20183}, {ip: "200.241.44.3", port: 20183}, {ip: "200.255.122.170", port: 8080}, {ip: "200.255.122.174", port: 8080}, {ip: "201.12.21.57", port: 8080}, {ip: "201.131.224.21", port: 56200}, {ip: "201.182.223.16", port: 37492}, {ip: "201.20.89.126", port: 8080}, {ip: "201.22.95.10", port: 8080}, {ip: "201.57.167.34", port: 8080}, {ip: "201.59.200.246", port: 80}, {ip: "201.6.167.178", port: 3128}, {ip: "201.90.36.194", port: 3128}, {ip: "45.226.20.6", port: 8080}, {ip: "45.234.139.129", port: 20183}, {ip: "45.234.200.18", port: 53281}, {ip: "45.235.87.4", port: 51996}, {ip: "45.6.136.38", port: 53281}, {ip: "45.6.80.131", port: 52080}, {ip: "45.6.93.10", port: 8080}, {ip: "45.71.108.162", port: 53281}],
- "PK" => [{ip: "103.18.243.154", port: 8080}, {ip: "110.36.218.126", port: 36651}, {ip: "110.36.234.210", port: 8080}, {ip: "110.39.162.74", port: 53281}, {ip: "110.39.174.58", port: 8080}, {ip: "111.68.108.34", port: 8080}, {ip: "125.209.116.182", port: 31653}, {ip: "125.209.78.21", port: 8080}, {ip: "125.209.82.78", port: 35087}, {ip: "180.92.156.150", port: 8080}, {ip: "202.142.158.114", port: 8080}, {ip: "202.147.173.10", port: 8080}, {ip: "202.147.173.10", port: 80}, {ip: "202.69.38.82", port: 8080}, {ip: "203.128.16.126", port: 59538}, {ip: "203.128.16.154", port: 33002}, {ip: "27.255.4.170", port: 8080}],
- "ID" => [{ip: "101.128.68.113", port: 8080}, {ip: "101.255.116.113", port: 53281}, {ip: "101.255.120.170", port: 6969}, {ip: "101.255.121.74", port: 8080}, {ip: "101.255.124.242", port: 8080}, {ip: "101.255.124.242", port: 80}, {ip: "101.255.56.138", port: 53560}, {ip: "103.10.171.132", port: 41043}, {ip: "103.10.81.172", port: 80}, {ip: "103.108.158.3", port: 48196}, {ip: "103.111.219.159", port: 53281}, {ip: "103.111.54.26", port: 49781}, {ip: "103.111.54.74", port: 8080}, {ip: "103.19.110.177", port: 8080}, {ip: "103.2.146.66", port: 49089}, {ip: "103.206.168.177", port: 53281}, {ip: "103.206.253.58", port: 49573}, {ip: "103.21.92.254", port: 33929}, {ip: "103.226.49.83", port: 23500}, {ip: "103.227.147.142", port: 37581}, {ip: "103.23.101.58", port: 8080}, {ip: "103.24.107.2", port: 8181}, {ip: "103.245.19.222", port: 53281}, {ip: "103.247.122.38", port: 8080}, {ip: "103.247.218.166", port: 3128}, {ip: "103.248.219.26", port: 53634}, {ip: "103.253.2.165", port: 33543}, {ip: "103.253.2.168", port: 51229}, {ip: "103.253.2.174", port: 30827}, {ip: "103.28.114.134", port: 8080}, {ip: "103.28.220.73", port: 53281}, {ip: "103.30.246.47", port: 3128}, {ip: "103.31.45.169", port: 57655}, {ip: "103.41.122.14", port: 53281}, {ip: "103.75.101.97", port: 8080}, {ip: "103.76.17.151", port: 23500}, {ip: "103.76.50.181", port: 8080}, {ip: "103.76.50.181", port: 80}, {ip: "103.76.50.182", port: 8080}, {ip: "103.78.74.170", port: 3128}, {ip: "103.78.80.194", port: 33442}, {ip: "103.8.122.5", port: 53297}, {ip: "103.80.236.107", port: 53281}, {ip: "103.80.238.203", port: 53281}, {ip: "103.86.140.74", port: 59538}, {ip: "103.94.122.254", port: 8080}, {ip: "103.94.125.244", port: 41508}, {ip: "103.94.169.19", port: 8080}, {ip: "103.94.7.254", port: 53281}, {ip: "106.0.51.50", port: 17385}, {ip: "110.93.13.202", port: 34881}, {ip: "112.78.37.6", port: 54791}, {ip: "114.199.110.58", port: 55898}, {ip: "114.199.112.170", port: 23500}, {ip: "114.199.123.194", port: 8080}, {ip: "114.57.33.162", port: 46935}, {ip: "114.57.33.214", port: 8080}, {ip: "114.6.197.254", port: 8080}, {ip: "114.7.15.146", port: 8080}, {ip: "114.7.162.254", port: 53281}, {ip: "115.124.75.226", port: 53990}, {ip: "115.124.75.228", port: 3128}, {ip: "117.102.78.42", port: 8080}, {ip: "117.102.93.251", port: 8080}, {ip: "117.102.94.186", port: 8080}, {ip: "117.102.94.186", port: 80}, {ip: "117.103.2.249", port: 58276}, {ip: "117.54.13.174", port: 34190}, {ip: "117.74.124.129", port: 8088}, {ip: "118.97.100.83", port: 35220}, {ip: "118.97.191.162", port: 80}, {ip: "118.97.191.203", port: 8080}, {ip: "118.97.36.18", port: 8080}, {ip: "118.97.73.85", port: 53281}, {ip: "118.99.105.226", port: 8080}, {ip: "119.252.168.53", port: 53281}, {ip: "122.248.45.35", port: 53281}, {ip: "122.50.6.186", port: 8080}, {ip: "122.50.6.186", port: 80}, {ip: "123.231.226.114", port: 47562}, {ip: "123.255.202.83", port: 32523}, {ip: "124.158.164.195", port: 8080}, {ip: "124.81.99.30", port: 3128}, {ip: "137.59.162.10", port: 3128}, {ip: "139.0.29.20", port: 59532}, {ip: "139.255.123.194", port: 4550}, {ip: "139.255.16.171", port: 31773}, {ip: "139.255.17.2", port: 47421}, {ip: "139.255.19.162", port: 42371}, {ip: "139.255.7.81", port: 53281}, {ip: "139.255.91.115", port: 8080}, {ip: "139.255.92.26", port: 53281}, {ip: "158.140.181.140", port: 54041}, {ip: "160.202.40.20", port: 55655}, {ip: "175.103.42.147", port: 8080}, {ip: "180.178.98.198", port: 8080}, {ip: "180.250.101.146", port: 8080}, {ip: "182.23.107.212", port: 3128}, {ip: "182.23.2.101", port: 49833}, {ip: "182.23.7.226", port: 8080}, {ip: "182.253.209.203", port: 3128}, {ip: "183.91.66.210", port: 80}, {ip: "202.137.10.179", port: 57338}, {ip: "202.137.25.53", port: 3128}, {ip: "202.137.25.8", port: 8080}, {ip: "202.138.242.76", port: 4550}, {ip: "202.138.249.202", port: 43108}, {ip: "202.148.2.254", port: 8000}, {ip: "202.162.201.94", port: 53281}, {ip: "202.165.47.26", port: 8080}, {ip: "202.43.167.130", port: 8080}, {ip: "202.51.126.10", port: 53281}, {ip: "202.59.171.164", port: 58567}, {ip: "202.93.128.98", port: 3128}, {ip: "203.142.72.114", port: 808}, {ip: "203.153.117.65", port: 54144}, {ip: "203.189.89.1", port: 53281}, {ip: "203.77.239.18", port: 37002}, {ip: "203.99.123.25", port: 61502}, {ip: "220.247.168.163", port: 53281}, {ip: "220.247.173.154", port: 53281}, {ip: "220.247.174.206", port: 53445}, {ip: "222.124.131.211", port: 47343}, {ip: "222.124.173.146", port: 53281}, {ip: "222.124.2.131", port: 8080}, {ip: "222.124.2.186", port: 8080}, {ip: "222.124.215.187", port: 38913}, {ip: "222.124.221.179", port: 53281}, {ip: "223.25.101.242", port: 59504}, {ip: "223.25.97.62", port: 8080}, {ip: "223.25.99.38", port: 80}, {ip: "27.111.44.202", port: 80}, {ip: "27.111.47.3", port: 51144}, {ip: "36.37.124.234", port: 36179}, {ip: "36.37.124.235", port: 36179}, {ip: "36.37.81.135", port: 8080}, {ip: "36.37.89.98", port: 32323}, {ip: "36.66.217.179", port: 8080}, {ip: "36.66.98.6", port: 53281}, {ip: "36.67.143.183", port: 48746}, {ip: "36.67.206.187", port: 8080}, {ip: "36.67.32.87", port: 8080}, {ip: "36.67.93.220", port: 3128}, {ip: "36.67.93.220", port: 80}, {ip: "36.89.10.51", port: 34115}, {ip: "36.89.119.149", port: 8080}, {ip: "36.89.157.23", port: 37728}, {ip: "36.89.181.155", port: 60165}, {ip: "36.89.188.11", port: 39507}, {ip: "36.89.194.113", port: 37811}, {ip: "36.89.226.254", port: 8081}, {ip: "36.89.232.138", port: 23500}, {ip: "36.89.39.10", port: 3128}, {ip: "36.89.65.253", port: 60997}, {ip: "43.243.141.114", port: 8080}, {ip: "43.245.184.202", port: 41102}, {ip: "43.245.184.238", port: 80}, {ip: "66.96.233.225", port: 35053}, {ip: "66.96.237.253", port: 8080}],
- "BD" => [{ip: "103.103.88.91", port: 8080}, {ip: "103.106.119.154", port: 8080}, {ip: "103.106.236.1", port: 8080}, {ip: "103.106.236.41", port: 8080}, {ip: "103.108.144.139", port: 53281}, {ip: "103.109.57.218", port: 8080}, {ip: "103.109.58.242", port: 8080}, {ip: "103.112.129.106", port: 31094}, {ip: "103.112.129.82", port: 53281}, {ip: "103.114.10.177", port: 8080}, {ip: "103.114.10.250", port: 8080}, {ip: "103.15.245.26", port: 8080}, {ip: "103.195.204.73", port: 21776}, {ip: "103.197.49.106", port: 49688}, {ip: "103.198.168.29", port: 21776}, {ip: "103.214.200.6", port: 59008}, {ip: "103.218.25.161", port: 8080}, {ip: "103.218.25.41", port: 8080}, {ip: "103.218.26.204", port: 8080}, {ip: "103.218.27.221", port: 8080}, {ip: "103.231.229.90", port: 53281}, {ip: "103.239.252.233", port: 8080}, {ip: "103.239.252.50", port: 8080}, {ip: "103.239.253.193", port: 8080}, {ip: "103.250.68.193", port: 51370}, {ip: "103.5.232.146", port: 8080}, {ip: "103.73.224.53", port: 23500}, {ip: "103.9.134.73", port: 65301}, {ip: "113.11.47.242", port: 40071}, {ip: "113.11.5.67", port: 40071}, {ip: "114.31.5.34", port: 52606}, {ip: "115.127.51.226", port: 42764}, {ip: "115.127.64.62", port: 39611}, {ip: "115.127.91.106", port: 8080}, {ip: "119.40.85.198", port: 36899}, {ip: "123.200.29.110", port: 23500}, {ip: "123.49.51.42", port: 55124}, {ip: "163.47.36.90", port: 3128}, {ip: "180.211.134.158", port: 23500}, {ip: "180.211.193.74", port: 40536}, {ip: "180.92.238.226", port: 53451}, {ip: "182.160.104.213", port: 8080}, {ip: "202.191.126.58", port: 23500}, {ip: "202.4.126.170", port: 8080}, {ip: "202.5.37.241", port: 33623}, {ip: "202.5.57.5", port: 61729}, {ip: "202.79.17.65", port: 60122}, {ip: "203.188.248.52", port: 23500}, {ip: "27.147.146.78", port: 52220}, {ip: "27.147.164.10", port: 52344}, {ip: "27.147.212.38", port: 53281}, {ip: "27.147.217.154", port: 43252}, {ip: "27.147.219.102", port: 49464}, {ip: "43.239.74.137", port: 8080}, {ip: "43.240.103.252", port: 8080}, {ip: "45.125.223.57", port: 8080}, {ip: "45.125.223.81", port: 8080}, {ip: "45.251.228.122", port: 41418}, {ip: "45.64.132.137", port: 8080}, {ip: "45.64.132.137", port: 80}, {ip: "61.247.186.137", port: 8080}],
- "MX" => [{ip: "148.217.94.54", port: 3128}, {ip: "177.244.28.77", port: 53281}, {ip: "187.141.73.147", port: 53281}, {ip: "187.185.15.35", port: 53281}, {ip: "187.188.46.172", port: 53455}, {ip: "187.216.83.185", port: 8080}, {ip: "187.216.90.46", port: 53281}, {ip: "187.243.253.182", port: 33796}, {ip: "189.195.132.86", port: 43286}, {ip: "189.204.158.161", port: 8080}, {ip: "200.79.180.115", port: 8080}, {ip: "201.140.113.90", port: 37193}, {ip: "201.144.14.229", port: 53281}, {ip: "201.163.73.93", port: 53281}],
- "PH" => [{ip: "103.86.187.242", port: 23500}, {ip: "122.54.101.69", port: 8080}, {ip: "122.54.65.150", port: 8080}, {ip: "125.5.20.134", port: 53281}, {ip: "146.88.77.51", port: 8080}, {ip: "182.18.200.92", port: 8080}, {ip: "219.90.87.91", port: 53281}, {ip: "58.69.12.210", port: 8080}],
- "EG" => [{ip: "41.65.0.167", port: 8080}],
- "VN" => [{ip: "1.55.240.156", port: 53281}, {ip: "101.99.23.136", port: 3128}, {ip: "103.15.51.160", port: 8080}, {ip: "113.161.128.169", port: 60427}, {ip: "113.161.161.143", port: 57967}, {ip: "113.161.173.10", port: 3128}, {ip: "113.161.35.108", port: 30028}, {ip: "113.164.79.177", port: 46281}, {ip: "113.190.235.50", port: 34619}, {ip: "115.78.160.247", port: 8080}, {ip: "117.2.155.29", port: 47228}, {ip: "117.2.17.26", port: 53281}, {ip: "117.2.22.41", port: 41973}, {ip: "117.4.145.16", port: 51487}, {ip: "118.69.219.185", port: 55184}, {ip: "118.69.61.212", port: 53281}, {ip: "118.70.116.227", port: 61651}, {ip: "118.70.219.124", port: 53281}, {ip: "221.121.12.238", port: 36077}, {ip: "27.2.7.59", port: 52148}],
- "CD" => [{ip: "41.79.233.45", port: 8080}],
- "TR" => [{ip: "151.80.65.175", port: 3128}, {ip: "176.235.186.242", port: 37043}, {ip: "178.250.92.18", port: 8080}, {ip: "185.203.170.92", port: 8080}, {ip: "185.203.170.94", port: 8080}, {ip: "185.203.170.95", port: 8080}, {ip: "185.51.36.152", port: 41258}, {ip: "195.137.223.50", port: 41336}, {ip: "195.155.98.70", port: 52598}, {ip: "212.156.146.22", port: 40080}, {ip: "213.14.31.122", port: 44621}, {ip: "31.145.137.139", port: 31871}, {ip: "31.145.138.129", port: 31871}, {ip: "31.145.138.146", port: 34159}, {ip: "31.145.187.172", port: 30636}, {ip: "78.188.4.124", port: 34514}, {ip: "88.248.23.216", port: 36426}, {ip: "93.182.72.36", port: 8080}, {ip: "95.0.194.241", port: 9090}],
-}
diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr
index 9e0631f6..8235898f 100644
--- a/src/invidious/yt_backend/youtube_api.cr
+++ b/src/invidious/yt_backend/youtube_api.cr
@@ -188,10 +188,6 @@ module YoutubeAPI
# conf_2 = ClientConfig.new(client_type: ClientType::Android)
# YoutubeAPI::player(video_id: "dQw4w9WgXcQ", client_config: conf_2)
#
- # # Proxy request through russian proxies
- # conf_3 = ClientConfig.new(proxy_region: "RU")
- # YoutubeAPI::next({video_id: "dQw4w9WgXcQ"}, client_config: conf_3)
- # ```
#
struct ClientConfig
# Type of client to emulate.
@@ -202,16 +198,11 @@ module YoutubeAPI
# (this is passed as the `gl` parameter).
property region : String | Nil
- # ISO code of country where the proxy is located.
- # Used in case of geo-restricted videos.
- property proxy_region : String | Nil
-
# Initialization function
def initialize(
*,
@client_type = ClientType::Web,
- @region = "US",
- @proxy_region = nil
+ @region = "US"
)
end
@@ -271,9 +262,8 @@ module YoutubeAPI
# Convert to string, for logging purposes
def to_s
return {
- client_type: self.name,
- region: @region,
- proxy_region: @proxy_region,
+ client_type: self.name,
+ region: @region,
}.to_s
end
end
@@ -620,7 +610,7 @@ module YoutubeAPI
LOGGER.trace("YoutubeAPI: POST data: #{data}")
# Send the POST request
- body = YT_POOL.client(client_config.proxy_region) do |client|
+ body = YT_POOL.client() do |client|
client.post(url, headers: headers, body: data.to_json) do |response|
self._decompress(response.body_io, response.headers["Content-Encoding"]?)
end