Compare commits

..

434 Commits

Author SHA1 Message Date
bb7f7bb4d1 add check video id for android client too 2022-08-25 08:32:40 +00:00
389e49183c throw error if the videoID returned is different 2022-08-23 19:34:54 +00:00
4c1a5f84fa Fix prefs cookies in player (#3276) 2022-08-22 16:16:50 +00:00
b0bb156918 Adapt StaticFileHandler for Crystal 1.6 (#3269) 2022-08-17 21:34:01 +02:00
5565204273 StaticFileHandler: use HTTP::Status rather than integers 2022-08-15 13:22:39 +02:00
d950a0ef5d StaticFileHandler: Adapt for Crystal 1.6
See:
 - https://github.com/crystal-lang/crystal/pull/12310
 - https://github.com/kemalcr/kemal/pull/644
2022-08-15 13:22:27 +02:00
b2c0f7efc3 Fix missing hash key: "toggleButtonRenderer" (issue #3260) 2022-08-15 10:34:52 +02:00
9e58bc19c4 Fix #3265 2022-08-13 20:23:45 +02:00
0d7e2afba4 Merge pull request #3261 from SamantazFox/routing-cleanup 2022-08-13 15:15:15 +02:00
e0d063d306 Merge pull request #3197 from weblate/weblate-invidious-translations 2022-08-13 15:14:18 +02:00
ed0ad587dc Update Indonesian translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: uwu as a service <okayokokay@protonmail.com>
2022-08-11 01:03:47 +02:00
56fe591eee Update Portuguese (Portugal) translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Tmpod <tmpod@pm.me>
2022-08-11 01:03:47 +02:00
7b9693bca4 Update German translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Pixelcode <pixelcode@dismail.de>
2022-08-11 01:03:47 +02:00
fd0417b14c Update Greek translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: THANOS SIOURDAKIS <siourdakisthanos@gmail.com>
2022-08-11 01:03:46 +02:00
89c12f2585 Update Italian translation
Co-authored-by: atilluF <atilluf@outlook.com>
2022-08-11 01:03:46 +02:00
5c71adb137 Update Norwegian Bokmål translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Petter Reinholdtsen <pere-weblate@hungry.com>
2022-08-11 01:03:46 +02:00
4c23062d1e Update Arabic translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rex_sa <rex.sa@pm.me>
2022-08-11 01:03:46 +02:00
190b45086c Update Russian translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Егор Ермаков <eg.ermakov2016@yandex.ru>
2022-08-11 01:03:46 +02:00
008983c8e3 Update Sinhala translation
Update Sinhala translation

Add Sinhala translation

Co-authored-by: DilshanH <ntpghiran@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-08-11 01:03:46 +02:00
cb8a375c5e routing: Directly call Kemal's add_route function 2022-08-10 20:50:49 +02:00
848a60aa9b routes: remove useless 'locale' variable in error 505 handler 2022-08-10 01:01:31 +02:00
88ea794fdb routes: move error 404 logic to its own module 2022-08-10 01:00:44 +02:00
870350fd61 routes: move before_all logic to its own module 2022-08-10 00:55:58 +02:00
1e25894f7e routing: move the remaining routes registration to a wrapper function 2022-08-10 00:48:09 +02:00
223e74569a routing: move feed routes registration to Invidious::Routing 2022-08-10 00:46:35 +02:00
0a4d793556 routing: move search routes registration to Invidious::Routing 2022-08-10 00:31:15 +02:00
5503914abe routing: move playlist routes registration to Invidious::Routing 2022-08-10 00:26:41 +02:00
906466d7fb routing: move watch/embed routes registration to Invidious::Routing 2022-08-10 00:22:40 +02:00
e2532de766 routing: move image proxy routes registration to Invidious::Routing 2022-08-10 00:20:04 +02:00
3ac4390d11 routing: move channel routes registration to Invidious::Routing 2022-08-10 00:14:26 +02:00
389ae7a573 routing: register playback routes with a function, rather than a macro 2022-08-10 00:10:29 +02:00
176247091d routing: register API routes with a function, rather than a macro 2022-08-10 00:07:47 +02:00
e22cc73f32 routing: register user routes with a function, rather than a macro 2022-08-09 23:56:34 +02:00
c23ad25899 routing: remove HEAD from HTTP methods
Kemal automatically creates an associated HEAD route for all GET routes
2022-08-09 23:39:53 +02:00
9cc0418769 Merge pull request #3249 from iv-org/improve-extractor 2022-08-07 21:58:17 +02:00
925a2c8e77 Merge pull request #3253 from amarakon/master 2022-08-07 21:54:40 +02:00
390734d86e Merge pull request #3255 from iv-org/fix-content-not-available 2022-08-07 21:40:57 +02:00
218f7be1a7 For android client send sdk version to youtube 2022-08-07 21:37:11 +02:00
246955b68a if case for sectionListRenderer 2022-08-07 10:31:42 +02:00
d24506baed Add Ytfzf to projects using Invidious 2022-08-06 20:42:08 -04:00
b0be2237fa Merge pull request #3248 from iv-org/fix-cookies 2022-08-07 01:33:11 +02:00
945394fb1a Merge pull request #3252 from SamantazFox/bump-ytapi-clients 2022-08-07 01:15:49 +02:00
19886f71f5 Merge pull request #3250 from iv-org/fix-cookies 2022-08-07 00:52:30 +02:00
23855c09dc Remove 'screen' where not required 2022-08-07 00:37:09 +02:00
618ab01cd7 Add TVHtml5 client 2022-08-07 00:36:22 +02:00
349d90b60e Add IOS clients 2022-08-07 00:32:26 +02:00
9e7c2dcdbb Move the default API key to a constant for clarity 2022-08-06 23:49:36 +02:00
f353589a53 Bump web clients versions 2022-08-06 23:47:16 +02:00
fc97929dee Bump android app version 2022-08-06 23:28:19 +02:00
3d77642a1e Disable decrypt_polling by default + add comment (#3244) 2022-08-06 17:09:10 +00:00
b55c1a35bf Set cookies to Lax 2022-08-06 19:01:57 +02:00
5df700a56e Added image tag to RSS channel for favicon rendering
https://validator.w3.org/feed/docs/rss2.html#ltimagegtSubelementOfLtchannelgt
2022-08-06 17:14:17 +02:00
0c64a86ebe crystal 1.5.0 to CI and update crystal version 2022-08-06 15:12:45 +02:00
644ba46945 Remove mentions that decrypt_polling is broken
And add notice about bandwidth usage, related to https://github.com/iv-org/invidious/issues/3234
2022-08-06 10:09:45 +00:00
4ab54f284c Merge pull request #3214 from SamantazFox/fix-scheduled-streams 2022-08-03 22:44:58 +02:00
210c2a8855 Fix updated sources not returned inside map func
This fix the issue reported in https://github.com/iv-org/invidious/issues/2055#issuecomment-1192894698
2022-07-25 12:38:17 +00:00
0ed4f1a9a4 Add unit tests for scheduled livestreams 2022-07-21 00:33:39 +02:00
7e648840a1 Move InfoException to exceptions.cr 2022-07-19 21:05:49 +02:00
5e090778ae Use alpine 3.16 for crystal 1.4.1
Until crystal 1.5 has been tested.
2022-07-19 09:12:50 +02:00
049ed114fd Separate video data fetching from parsing in videos.cr 2022-07-18 23:35:34 +02:00
88007a08f2 Merge pull request #3205 from iv-org/escape-username 2022-07-15 00:30:10 +02:00
6c4ed282bb HTML escape username 2022-07-14 21:26:58 +00:00
c8765385df Fetch data from next endpoint for scheduled streams 2022-07-14 17:56:53 +02:00
0ed22c0be0 Merge pull request #3140 from AHOHNMYC/css-ie11-fixes 2022-07-14 16:31:03 +02:00
3ffef4b9fb Merge pull request #3133 from AHOHNMYC/widen-settings-name 2022-07-14 16:27:47 +02:00
ceeebceb3a Merge pull request #3199 from AHOHNMYC/fix-js-in-embed 2022-07-14 14:28:08 +02:00
0338b26d5c Include _helpers.js in embedded view 2022-07-14 02:07:19 +03:00
6577cc0c8c Fix a dead link to Docker install documentation (#3198) 2022-07-13 19:55:06 +00:00
586000ca3d add more explanation about checking the player dependencies 2022-07-12 08:38:22 +00:00
abc81ebd08 Merge pull request #3165 from SamantazFox/small-fixes-06-2022 2022-07-11 17:41:58 +02:00
cd6c73e487 Merge pull request #3162 from 138138138/138138138-audio-quality-1 2022-07-11 17:36:28 +02:00
69ad57338f Mention why we use multiple AdaptationSet for audio 2022-07-11 17:29:42 +02:00
cbcf31a4f9 Skip OTF streams in DASH audio
Skip OTF streams, prevent creating empty AdaptationSet in DASH audio
2022-07-10 16:54:56 +08:00
b19beac5b4 Update src/invidious/views/components/player.ecr
better syntax

Co-authored-by: Samantaz Fox <coding@samantaz.fr>
2022-07-10 16:29:50 +08:00
dc6d088e30 Merge pull request #3158 from 138138138/138138138-mobileui-forward-rate 2022-07-07 00:05:25 +02:00
b0ad27af23 Merge pull request #3151 from weblate/weblate-invidious-translations 2022-07-07 00:02:36 +02:00
5f23c6358a Update Czech translation
Update Czech translation

Co-authored-by: Fjuro <fjuro@seznam.cz>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-07-06 23:25:13 +02:00
da776c935f Update Indonesian translation
Update Indonesian translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: liimee <alt3753.7@gmail.com>
Co-authored-by: uwu as a service <okayokokay@protonmail.com>
2022-07-06 23:25:12 +02:00
0a315783ef Update Portuguese (Portugal) translation
Update Portuguese (Portugal) translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Tmpod <tmpod@pm.me>
2022-07-06 23:25:12 +02:00
65061b0514 Update Japanese translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: uwu as a service <okayokokay@protonmail.com>
2022-07-06 23:25:12 +02:00
063e5e359e Update Turkish translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
2022-07-06 23:25:12 +02:00
f460afca35 Update Chinese (Simplified) translation
Co-authored-by: Eric <alchemillatruth@purelymail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-07-06 23:25:12 +02:00
66a08ace1d Update Slovenian translation
Co-authored-by: Damjan Gerl <damjan@damjan.net>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-07-06 23:25:11 +02:00
68e65e968a Update Portuguese translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SC <lalocas@protonmail.com>
2022-07-06 23:25:11 +02:00
1ba0ab982b Update Croatian translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
2022-07-06 23:25:11 +02:00
8752b8bb3f Update Finnish translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Markus Mikkonen <markus.mikkonen@outlook.com>
2022-07-06 23:25:11 +02:00
168f86ef89 Update Portuguese (Brazil) translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: The Cats <philosoph@snopyta.org>
2022-07-06 23:25:11 +02:00
85927853f9 Update Chinese (Traditional) translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
2022-07-06 23:25:11 +02:00
57f60bf173 Update Ukrainian translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
2022-07-06 23:25:10 +02:00
d16c3ed40a Update Italian translation
Update Italian translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Pietro Cappuccino <p.cappuccino@tiscali.it>
Co-authored-by: ㅤAbsurdUsername <sgso@pm.me>
2022-07-06 23:25:10 +02:00
e90f4a2cbf Update Norwegian Bokmål translation
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-07-06 23:25:10 +02:00
d00839ec68 Update Russian translation
Update Russian translation

Update Russian translation

Update Russian translation

Co-authored-by: AHOHNMYC <lqwh2h2cwa@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Егор Ермаков <eg.ermakov2016@yandex.ru>
2022-07-06 23:25:10 +02:00
ea35d92493 Merge pull request #3157 from 138138138/138138138-fix-captions 2022-07-06 23:22:56 +02:00
beb9894c47 Merge pull request #3124 from iv-org/add-404-status-code 2022-07-06 22:05:01 +02:00
5556a996cd Update comment for NotFoundException 2022-07-06 19:59:05 +00:00
f7b1dcc271 Don't treat LIVE_STREAM_OFFLINE playability status as an error (fixes #3155) 2022-07-04 22:24:36 +02:00
eb226e1dcf Remove all backend code related to dislikes 2022-07-04 22:24:23 +02:00
8332ad0f16 Fix syntax errors in shell scripts 2022-07-04 22:24:17 +02:00
06af5a004e Remove useless link in item forms (buttons on thumbnail) 2022-07-04 22:24:11 +02:00
ce32873ef8 Remove item (video/channel/mix) thumbnail from keyboard navigation tree 2022-07-04 22:23:56 +02:00
99bc230fe6 Fix missing hash key: "availableCountries" (Closes #3047) 2022-07-04 22:23:31 +02:00
0e3820b634 Add #to_http_params method to Query (Fixes #3148) 2022-07-04 22:21:27 +02:00
eba84dcd78 Merge pull request #3183 from 11Tuvork28/fix-selected-key-missing 2022-07-04 22:03:38 +02:00
864f27ef72 switched to extract_selected_tab for the community tab 2022-07-03 14:59:33 +02:00
a8b72d8342 Fixed community tab 2022-07-03 14:23:34 +02:00
15d2cfba90 Fix Missing hash key: "selected" (KeyError) 2022-07-03 14:03:42 +02:00
2851d993ad updated comment to represent current structure 2022-07-03 14:03:30 +02:00
3f1d88282e Update some comments 2022-06-25 19:26:14 +08:00
cc9ce916c6 Update MobileUi 2022-06-25 19:24:20 +08:00
c7d468578f Update MobileUi 2022-06-25 19:03:35 +08:00
e0f6988eb5 DASH Default to high quality m4a 2022-06-25 18:52:34 +08:00
09ff370ddc Change player.css order 2022-06-25 17:19:40 +08:00
32ecf30c82 Add audioTrackButton 2022-06-25 17:19:11 +08:00
a62adccd3d change lang to label
lang has to be BCP 47 standard. Using label also can let video.js know there are 2 audio tracks.
2022-06-25 16:33:02 +08:00
c75bf35f59 Update DASH format to serve 2 audio to player
player.audioTracks() can successfully show
tracks_: Array(2)
2022-06-24 17:26:30 +08:00
3013782b7b formatting 2022-06-23 03:03:54 +08:00
81abebd144 Highest quality m4a on audio only mode as default
Audio mode will automatically select highest quality m4a as default.
2022-06-23 02:27:46 +08:00
140b6c1227 DASH playback force highest quality m4a
Since VideoJS is unable to handle adaptive audio quality, the best audo quality is forced for every video quality.
2022-06-23 02:13:22 +08:00
ac685f65e9 Fix captions
textTracks 0 in DASH mode shows debug messages.
Use textTracks 1 in DASH mode, and textTracks 0 in non-DASH mode and audio mode.
2022-06-23 01:01:11 +08:00
f6b1cbd5d0 Player MobileUi fast forward/backward rate
The fast forward/backward seconds will be adjusted according to playback rate (same as YouTube app behavior).
5 seconds is used when the playback rate is 1x. Previously it was 10 seconds. I believe most of the users watch videos at 2x, so the change will not be obvious.
2022-06-22 19:33:02 +08:00
7db6e43e3f Fix captions
Captions should automatically show according to preferences.
2022-06-22 19:10:46 +08:00
6c73614a47 Bump revision for crystal alpine package on Docker 2022-06-13 13:18:37 +02:00
b5c54b4e41 Merge pull request #3137 from SamantazFox/add-hashtags
Add hashtags
2022-06-09 00:35:09 +02:00
8f1c84e6d4 Merge pull request #3119 from GauthierPLM/popular-enabled
Add "Popular Enabled: " string to localisation
2022-06-09 00:34:11 +02:00
d1df4af734 Merge pull request #3118 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-06-09 00:33:44 +02:00
23cd04fe88 Merge pull request #3116 from DoodlesEpic/fix-reddit-comments-nojs-ytkids
Fix document is empty error on yt kids video when reddit comments are enabled
2022-06-09 00:33:09 +02:00
dbc7c97e0b Merge pull request #3103 from SamantazFox/add-utility-scripts
Add utility scripts
2022-06-09 00:32:44 +02:00
2313ca8f72 Merge pull request #3084 from AHOHNMYC/js-helpers-polyfills
JS refactoring part 2: helper functions, poyfills
2022-06-09 00:30:34 +02:00
9418ba1687 Update Bengali translation
Update Bengali translation

Add Bengali translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Oymate <dhruboadittya96@gmail.com>
2022-06-09 00:12:33 +02:00
233491940c Update Indonesian translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: I. Musthafa <i.musthafa66@gmail.com>
2022-06-09 00:12:33 +02:00
7708e7ab08 Update Slovenian translation
Update Slovenian translation

Co-authored-by: Damjan Gerl <damjan@damjan.net>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-06-09 00:12:32 +02:00
600bd38630 Update Portuguese translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SC <lalocas@protonmail.com>
2022-06-09 00:12:32 +02:00
f7290dfcb6 Update Croatian translation
Update Croatian translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
2022-06-09 00:12:32 +02:00
e22f7583eb Update Ukrainian translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
2022-06-09 00:12:32 +02:00
c0e85f5687 Update Russian translation
Co-authored-by: AHOHNMYC <lqwh2h2cwa@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-06-09 00:12:32 +02:00
3593f67eb6 Fix: related videos is a Hash(String, String) 2022-06-08 23:57:16 +02:00
1b251264a6 Pull submodules during CI 2022-06-08 23:57:15 +02:00
93c1a1d42e Add mocks as a submodule 2022-06-08 23:56:40 +02:00
d7f6b6b018 Fix CI: support reloadContinuationItemsCommand containers 2022-06-08 23:56:40 +02:00
fd99f20404 Fix CI: use be_close() with 1s delta for Time comparisons 2022-06-08 23:56:40 +02:00
2b1e1b11a3 Fix CI: support BADGE_STYLE_TYPE_VERIFIED_ARTIST 2022-06-08 23:56:40 +02:00
96ac7f9f35 Add hashtag extractor spec 2022-06-08 23:56:40 +02:00
33da64a669 Add support for hashtags 2022-06-08 23:56:40 +02:00
38eb4ccbc4 CSS. Small IE11 fixes 2022-06-06 21:51:47 +03:00
a57414307e CSS. Small IE11 fixes 2022-06-06 01:10:00 +03:00
7ad111e2f6 Update actions used in GH workflows (#3138) 2022-06-05 22:05:19 +02:00
a402128a7d Move _helpers.js include from various .ecr's into template.ecr head tag 2022-06-05 21:19:59 +03:00
d3ab4a5145 JS. Trailing spaces removed 2022-06-05 20:54:48 +03:00
4ae77bcef9 Remove rating display from the frontend 2022-06-04 15:39:04 +02:00
e84416e56d Remove dislikes icon (#3092) 2022-06-04 12:58:34 +02:00
59ccc9d73e Merge pull request #3134 from lhc-sudo/patch-1
Add TubiTui to Projects Using Invidious section of README.md
2022-06-01 20:21:55 +02:00
777
1533a28817 Add TubiTui to Projects Using Invidious section 2022-06-01 18:48:52 +01:00
7e4840867e CSS. Wider settings name to less word wrap 2022-06-01 17:16:07 +03:00
f2f3f045e5 fix time adding dirung redirection 2022-05-31 12:18:42 +03:00
b12149bafd Save time during redirection on another instance 2022-05-31 11:58:12 +03:00
307c1b0b62 Merge pull request #3128 from arekf/patch-1
Add Yattee to README
2022-05-29 19:56:30 +02:00
b201745988 Markdown enhancement 2022-05-29 19:56:11 +02:00
352266481e Add Yattee to README 2022-05-29 19:46:49 +02:00
c201ea53ba Add 404 status code on all possible endpoints 2022-05-27 14:06:38 +00:00
958867e92b Fix wrong french translation
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
2022-05-25 23:41:12 +02:00
b50de2f2ed Add "Popular Enabled: " string to localisation 2022-05-25 20:58:58 +00:00
ad37db4c82 Fix document is empty error on yt kids video when reddit comments are enabled 2022-05-24 20:34:36 -03:00
c2d91c9544 Merge pull request #3112 from Froggo8311/Change-Badge-Mastodon-Fediverse
Change README.md badge from 'Mastodon' to 'Fediverse'
2022-05-24 13:41:27 +02:00
6eedca6e7e Fix alt text for readme badge (Mastodon -> Fediverse) 2022-05-23 20:55:08 -05:00
0bd1d0bb05 Change from 'Mastodon' to 'Fediverse'
Mastodon is one of multiple softwares that compose the Fediverse ("Federeated Universe"). Some of the most popular softwares include Misskey, Plemora, PeerTube, and Pixelfed, among others. 

As each instance (server) integrates using ActivityPub, any one of these softwares can be used to follow users or reply to posts(/toots/notes) on any instance.

Most people seem to not realize that Mastodon is different from the "umbrella term" Fediverse. :)
2022-05-23 20:51:52 -05:00
1f359f5a13 Print some helpful notice for PostgreSQL configuration 2022-05-21 19:18:01 +02:00
fe53b5503c Add a script to start postgres and create user/DB 2022-05-21 19:06:45 +02:00
d66ef8fe22 Add a script to install dependencies 2022-05-21 19:06:45 +02:00
6ff3a633f7 Merge pull request #2968 from mathiusD/description-link 2022-05-21 18:58:47 +02:00
46891437e9 Add Estonian to i18n.cr 2022-05-21 18:39:49 +02:00
b729597728 comment changed
extra spaces removed
2022-05-21 19:30:51 +03:00
f99d139025 Merge pull request #3058 from weblate/weblate-invidious-translations 2022-05-21 18:24:56 +02:00
b72b917af2 handled invalid values in storage
partial rewrite notifications.js
innerText to textContent
fixed bug with clamping
2022-05-21 13:35:41 +03:00
749869fdca Update translation files
Updated by "Remove blank strings" hook in Weblate.

Update Estonian translation

Add Estonian translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Koshkov <jedrikwojcik@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-05-19 23:18:58 +02:00
e56a694878 Update Czech translation
Co-authored-by: Fjuro <fjuro@seznam.cz>
2022-05-19 23:18:58 +02:00
8cb4d1dc28 Update Portuguese (Brazil) translation
Co-authored-by: André Marcelo Alvarenga <andrealvarenga@gmx.net>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-05-19 23:18:58 +02:00
68f1351507 Update Arabic translation
Co-authored-by: Light <0f723d5979@catdogmail.live>
2022-05-19 23:18:58 +02:00
66205286e4 Update Hindi translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Saurmandal <saurmandal@protonmail.com>
2022-05-19 23:18:58 +02:00
32be373552 Invert title & video ID in downloaded file name
Fixes a regression of #2922
Issue reported by email
2022-05-19 23:16:51 +02:00
b1128c17f1 Merge pull request #3099 from SamantazFox/fix-3096
Fix for #3096
2022-05-19 23:05:17 +02:00
319bbd2f81 JS code minor formatting
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
2022-05-19 07:15:17 +03:00
d8fb4f0a87 Update text_to_parsed_content for add docs
Follow this comment :
https://github.com/iv-org/invidious/pull/2968#discussion_r851808433
2022-05-18 23:45:47 +02:00
2e195575a6 Rename uriMatch to urlMatch inside comments.cr
This refactor update text_to_parsed_content method
2022-05-18 23:45:47 +02:00
28efeaa4f2 Update management of channel description
Follow this comment :
https://github.com/iv-org/invidious/pull/2968#issuecomment-1066428317
2022-05-18 23:45:28 +02:00
137534f901 Fix for #3096 2022-05-18 23:36:50 +02:00
c9594d46af Add links redirect inside channel description 2022-05-18 23:24:41 +02:00
1097648f0a Fix HTML validation. This is how browser really split tags 2022-05-17 10:09:01 +03:00
17e6213448 Less player reload timeout 2022-05-17 10:03:07 +03:00
2ea423032e Share video regression. Single quotes are required 2022-05-17 09:43:05 +03:00
2dead1a19b JS theme switching simplified 2022-05-16 13:51:28 +03:00
e18b10297b JS fixes: recursion in themes, keys for frame walking, JSON XHR and details-summary in IE11 2022-05-16 13:13:00 +03:00
fd66084388 js code rewrite. Themes rewritten, bugs fixed 2022-05-15 08:38:46 +03:00
ca27e096f3 Merge pull request #3094 from rfwatson/remove-puts-statements
Remove puts statements in config.cr
2022-05-11 17:49:45 +02:00
125997f45f Remove puts statements in config.cr 2022-05-11 10:22:39 +02:00
da8a2c7bbb Merge pull request #3087 from iv-org/fix-captions-download
Fix download of captions
2022-05-07 15:39:23 +02:00
81ca205caa Fix download of captions 2022-05-07 15:34:56 +02:00
f06d5b973b jsdoc type fix 2022-05-06 07:42:15 +03:00
fd890f9c0a fix helpers storage 2022-05-06 07:21:19 +03:00
835237382f fix helpers 2022-05-06 06:16:41 +03:00
7dd699370f js code rewrite. Created _helpers.js with XHR and storage wrapper 2022-05-06 04:46:59 +03:00
ef8c7184de Merge pull request #3083 from iv-org/add-slovenian
Add Slovenian to i18n.cr
2022-05-04 22:40:13 +02:00
92026c1f98 Merge pull request #3082 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-05-04 22:36:52 +02:00
9bd9dcc41c Add Slovenian to i18n.cr 2022-05-04 22:36:31 +02:00
81b97ba52f Update Slovenian translation
Add Slovenian translation

Co-authored-by: Damjan Gerl <damjan@damjan.net>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-05-04 22:30:08 +02:00
ae36777d14 Update Portuguese (Brazil) translation
Co-authored-by: Vinicius <rodriguessv30@gmail.com>
2022-05-04 22:30:07 +02:00
3d7ad82f3e Update Dutch translation
Co-authored-by: Gert-dev <qnyasgjhapqyuhoibr@kiabws.com>
2022-05-04 22:30:07 +02:00
059796c60d Merge pull request #3076 from SamantazFox/fix-3062-3063
Fix regressions of #2936
2022-05-04 22:29:10 +02:00
b0342b7449 Other minor fixes 2022-05-03 22:28:19 +02:00
b867dd82ca Merge pull request #3077 from SamantazFox/verified-checkmark
Merge "Youtube verification badge" again (with fixes)
2022-05-02 23:57:01 +02:00
a122286d48 Add Hindi to i18n.cr 2022-05-02 20:49:12 +02:00
837db800bc Merge pull request #3080 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-05-02 19:30:21 +02:00
44fe39821a Update Portuguese (Brazil) translation
Co-authored-by: Vinicius <rodriguessv30@gmail.com>
2022-05-02 19:28:57 +02:00
fbc6b14424 Update Russian translation
Co-authored-by: Егор Ермаков <eg.ermakov2016@gmail.com>
2022-05-02 19:28:57 +02:00
9c00140464 Update Hindi translation
Add Hindi translation

Co-authored-by: Creeper <abhijit.naug@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-05-02 19:28:57 +02:00
00d8deda0e Merge pull request #3065 from 138138138/master
Fix iOS 3 buttons separated lines
2022-05-02 19:28:38 +02:00
b84ce6a556 Fix "cast from Nil to Bool failed" 2022-05-01 21:11:12 +02:00
f5fb4c6c64 Apply 2859.diff 2022-05-01 21:10:43 +02:00
ac686fefe1 Merge pull request #3075 from SamantazFox/video-api-newpipe-compat-2
Video API: Improve NewPipe compatibility (part 2)
2022-05-01 19:11:59 +02:00
e690e166b0 Fix javascript:void(0) instead of youtu.be links 2022-05-01 18:48:08 +02:00
6a02dd8842 Fix broken hashtag links 2022-05-01 17:42:53 +02:00
66e2c01a3e Merge pull request #3073 from iv-org/SamantazFox-patch-1
Revert html escaping of backtrace
2022-05-01 17:30:20 +02:00
7f2176d7fc Add 'targetDurationSec' and 'maxDvrDurationSec' to videos API 2022-05-01 17:21:10 +02:00
4434889270 Merge pull request #3072 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-05-01 13:57:07 +02:00
96afc1a45d Revert html escaping of backtrace 2022-05-01 13:40:02 +02:00
dbe49610a1 Update Russian translation
Co-authored-by: AHOHNMYC <lqwh2h2cwa@protonmail.com>
2022-05-01 11:13:03 +02:00
62fadb54ee Update Hungarian translation
Co-authored-by: f3rr31 <5920873@disroot.org>
2022-05-01 11:13:03 +02:00
3832383936 Update English (United States) translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-05-01 11:13:03 +02:00
595c3fb833 Revert "Youtube verification badge" (#3070) 2022-04-30 23:42:38 +02:00
1d25c55c0b Merge pull request #2859 from jonas-w/verified-badge
Youtube verification badge
2022-04-30 18:54:38 +02:00
6376e78e0b Merge pull request #3054 from DUOLabs333/patch-1
Widen Youtube player seek bar a little
2022-04-30 18:53:36 +02:00
1f08d2929c Fix iOS 3 buttons separated lines 2022-04-30 16:55:12 +08:00
04953d97ad Merge pull request #3064 from iv-org/crystal1.4.1
bump to crystal 1.4.1
2022-04-29 19:06:55 +02:00
64fe4de3fb bump to crystal 1.4.1 2022-04-29 06:16:54 +00:00
58008445e2 Merge pull request #3060 from SamantazFox/video-api-newpipe-compat
Video API: Improve NewPipe compatibility
2022-04-27 21:58:03 +02:00
b7f0b054b8 It's OTF, not OFT 2022-04-27 21:46:45 +02:00
3bbd709bd6 Merge pull request #3045 from AHOHNMYC/js-lint
Js lint
2022-04-27 18:32:40 +02:00
dbb1e3f5d8 replace tabs to spaces 2022-04-27 15:01:34 +03:00
8144308aee Add extra data to 'adaptiveFormats' in videos API 2022-04-27 00:22:34 +02:00
0503d2a9f3 Fix 'adaptiveFormats' not available for livestreams in videos API 2022-04-27 00:22:10 +02:00
fafd4d9396 new lines in the end of file 2022-04-25 13:14:08 +03:00
3431a1b1de console.warn and info instead of log 2022-04-25 12:54:32 +03:00
026ea52445 optional catchng is not supported by IE11 2022-04-25 12:54:31 +03:00
1e60b9a322 destructing binding is not supported by IE11 2022-04-25 12:54:31 +03:00
7450cb1f21 default parameters 2022-04-25 12:54:30 +03:00
cdd5a9e935 replace huphen-minus to real minus 2022-04-25 12:54:30 +03:00
c4cc50ca39 replace innerHTML to safer textContent where possible 2022-04-25 12:54:30 +03:00
9b09d369d9 add variable declarations 2022-04-25 12:54:25 +03:00
12ab11413f fix double variable declaration 2022-04-25 10:17:15 +03:00
352f3640cf transform template string 2022-04-25 10:17:12 +03:00
7940e91cbe single quotes 2022-04-25 10:15:57 +03:00
577a2356a0 convert arrow functions 2022-04-25 10:14:29 +03:00
38ef0b10e7 eqeqeq 2022-04-25 10:14:24 +03:00
c72d3c4a0e semicolons 2022-04-25 10:13:00 +03:00
eb7e48b059 use strict 2022-04-25 10:12:16 +03:00
ab62fa1c4f Lower margin-bottom some more 2022-04-24 19:51:29 -04:00
a7cf1f6cca Update player.css
Fixed "floating" seek bar
2022-04-24 19:06:28 -04:00
80d89f31fe Widen Youtube player a bit 2022-04-24 18:06:56 -04:00
a0f566fef3 Merge pull request #3052 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-04-24 23:39:47 +02:00
c93d362dd4 Update Albanian translation
Co-authored-by: Besnik Bleta <besnik@programeshqip.org>
2022-04-24 17:32:14 +02:00
db72f5d011 Update French translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-04-24 17:32:13 +02:00
03704384a8 Update Slovak translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Juraj Liso <lisojuraj@gmail.com>
2022-04-24 17:32:13 +02:00
5b17ec0b56 Update Finnish translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Markus Mikkonen <markus.mikkonen@outlook.com>
2022-04-24 17:32:13 +02:00
d4acd03698 Merge pull request #3044 from MathiusD/base-time-code-lost
Fix regression related of timestamp 0:00
2022-04-24 17:32:01 +02:00
2ea986326d Bump videojs to 7.12.1 (#3011) 2022-04-22 22:37:45 +02:00
da53de2097 Fix regression related of timestamp 0:00 2022-04-20 00:42:09 +02:00
cf755dec22 Merge pull request #3027 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-04-18 15:57:51 +02:00
d25e5e1849 Update Italian translation
Update Italian translation

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:10 +02:00
593648780f Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:10 +02:00
bb04ff5942 Update Dutch translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:10 +02:00
12db276eb8 Update Albanian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:10 +02:00
596fc3e908 Update Portuguese translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:10 +02:00
9c54b94265 Update Korean translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:09 +02:00
3c1cfce95a Update Vietnamese translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:09 +02:00
2f9f3142e2 Update Lithuanian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:09 +02:00
92070e502c Update Serbian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:09 +02:00
48b1154a71 Update Czech translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Fjuro <fjuro@seznam.cz>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:09 +02:00
bcdfb98454 Update Hebrew translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:08 +02:00
f26c1f8095 Update Danish translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:08 +02:00
790a24bdeb Update Croatian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:08 +02:00
5d2b9392d5 Update Indonesian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:08 +02:00
6be242fc15 Update Persian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:08 +02:00
8158c5042b Update Portuguese (Portugal) translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:07 +02:00
c70cdd88c7 Update Swedish translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:07 +02:00
bc6d6b6550 Update Serbian (cyrillic) translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:07 +02:00
9584d8e16d Update Portuguese (Brazil) translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:07 +02:00
4693c678d0 Update Romanian translation
Co-authored-by: Dorian Oszczęda <vxern@wordcollector.co.uk>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-04-18 15:56:07 +02:00
2c7d668f81 Update Japanese translation
Update Japanese translation

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:06 +02:00
de2f963717 Update Turkish translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:06 +02:00
e83da76dc7 Update Chinese (Simplified) translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Eric <alchemillatruth@purelymail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:06 +02:00
643730221d Update Greek translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:06 +02:00
ab63f9ef31 Update Ukrainian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Denys Nykula <nykula@ukr.net>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:06 +02:00
dc870c4cc4 Update Esperanto translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:05 +02:00
dd709dec18 Update Spanish translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hin Weisner <translatu.godwit@aleeas.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:05 +02:00
cd5b71aedd Update French translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:05 +02:00
d33cc025ee Update Norwegian Bokmål translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:05 +02:00
e7159f2803 Update Arabic translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:05 +02:00
56b8a18820 Update Polish translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:04 +02:00
5832794034 Update German translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:04 +02:00
a26b197687 Update Russian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:04 +02:00
12dba0955a Update Chinese (Traditional) translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:04 +02:00
7bd425bb3d Update Hungarian translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:04 +02:00
845ad17a04 Update Finnish translation
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
Translate-URL: https://hosted.weblate.org/projects/invidious/translations/
Translation: Invidious/Invidious Translations
2022-04-18 15:56:03 +02:00
67e8fcaf93 bump to crystal 1.4.0 (#3041) 2022-04-18 09:05:18 +02:00
aa07ee22cf Merge pull request #3039 from iv-org/SamantazFox-patch-1
Fix comment "pings" (#3038)
2022-04-17 23:34:38 +02:00
3702e8c6fe Fix comment "pings" (#3038) 2022-04-17 18:02:47 +02:00
21bd4edee4 Merge pull request #3034 from AHOHNMYC/http-fix
Remove insecure protocol in embedded view
2022-04-17 12:08:54 +02:00
31de39a7a4 Remove insecure protocol in embedded view 2022-04-17 04:32:15 +03:00
d0fc2569ff Merge pull request #2934 from SamantazFox/bump-kemal
Bump kemal dependency to v1.1.2
2022-04-17 00:12:00 +02:00
4fd1631b30 Update crystal version in CI 2022-04-16 22:49:56 +02:00
0a1614a872 Also move the other Kemal class override to src/ext/ 2022-04-16 22:48:24 +02:00
1f66d7ef74 Keep using kilt for rendering
Directly using Crystal's ECR seems to be causing issues, so
don't use kemal's 'render' macro and patch 'content_for' to
have the same behavior as before Kemal v1.1.1
2022-04-16 22:48:24 +02:00
84b6429ca6 Fix error due to templating engine change 2022-04-16 22:48:24 +02:00
212e5ebab5 Also bump 'exception_page', a kemal dependency 2022-04-16 22:48:24 +02:00
a6106077bd Bump kemal to v1.1.2 2022-04-16 22:48:24 +02:00
fa4ce6b4e6 Merge pull request #3033 from SamantazFox/search-fixes
Search fixes
2022-04-16 20:32:41 +02:00
4130136718 Merge pull request #2936 from MathiusD/expand-link
Increase size of links displayed in video description
2022-04-16 20:31:28 +02:00
c7c1b8d4f1 Fix issues in Search::Query 2022-04-16 20:25:25 +02:00
25b60a1b90 Add spec for the Search::Query class 2022-04-16 20:24:50 +02:00
dda4dadfa3 Merge pull request #3031 from AHOHNMYC/fix-filter-checkbox
Fix filter checkbox
2022-04-16 13:21:19 +02:00
570dbc7b47 Fix filter checkbox
Due to different prefixes in id (`filter-features` in `input` and `filter-feature` in `label`) click on `label` didn't affect corresponding checkbox.
2022-04-16 08:58:45 +03:00
6c122248f5 Update regex reduce_uri utils
Follow this comment :
https://github.com/iv-org/invidious/pull/2936#discussion_r850712676
2022-04-14 22:42:21 +02:00
4a369bb3c0 Merge pull request #3023 from AHOHNMYC/improve-filters-visual
Filters visual improvement
2022-04-14 20:36:53 +02:00
95cf57e3bd Merge pull request #3026 from iv-org/revert-2928-bump-dependencies
Revert "Bump dependencies"
2022-04-14 18:35:06 +02:00
0e6f7a4dc1 Revert "Bump dependencies" 2022-04-14 17:59:22 +02:00
6f21834e71 Real minus sign instead of hyphen-minus
Minus sign in comparison with hyphen-minus (symbol that prints your keyboard by default) has horizontal line on same level as plus sign and same width, so one can be toggled to another with perfect visuals.
https://en.wikipedia.org/wiki/Plus_and_minus_signs
https://en.wikipedia.org/wiki/Hyphen-minus
2022-04-13 04:23:10 +03:00
cf6ad254fb Pointer cursor on Filters `summary'
`summary` clickable by design, but by default (at least in Chrome) it has `text` cursor.
2022-04-13 04:15:37 +03:00
fabbecf4c2 Merge pull request #2928 from SamantazFox/bump-dependencies
Bump dependencies
2022-04-09 20:36:09 +02:00
8262aa4138 Merge pull request #2895 from MathiusD/master
Persist player volume/speed
2022-04-09 20:05:28 +02:00
95d86ebf22 Sanity check + comment why we add a leading dot 2022-04-09 20:04:42 +02:00
6aa7db2358 Minor code/comments cleaning 2022-04-09 19:58:49 +02:00
5637c6e651 Merge pull request #3013 from iv-org/rescue-db-errors-get-video
Rescue DB errors in get_video()
2022-04-09 19:35:49 +02:00
Leo
6f705b053a Updates the URL of the var url_faq (#3016) 2022-04-09 08:20:28 +02:00
1f3f2788d4 Merge pull request #3002 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-04-09 01:59:39 +02:00
ed3c202099 Update Ukrainian translation
Co-authored-by: Denys Nykula <nykula@ukr.net>
2022-04-09 01:58:20 +02:00
0396eec398 Update Norwegian Bokmål translation
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
2022-04-09 01:58:20 +02:00
62dcec49e4 Update German translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Pixelcode <pixelcode@dismail.de>
2022-04-09 01:58:20 +02:00
2f6afb5e86 Update Danish translation
Co-authored-by: Grooty12 <Rasmus@rosendahl-kaa.name>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-04-09 01:58:20 +02:00
a3a2b2aafb Replace "Github" by "GitHub" 2022-04-09 01:57:51 +02:00
4900ce24fa Merge pull request #2956 from SamantazFox/search-filters
Overhaul search filters
2022-04-08 23:49:03 +02:00
135aaf56fd Rescue DB errors in get_video() 2022-04-08 22:52:34 +02:00
62d7abdd9e Add a user friendly message for when no results are found 2022-04-08 22:28:43 +02:00
91b079f4df Merge pull request #3007 from iv-org/TheFrenchGhosty-postgres13
Set the Postgres version to 13 as a temporary workaround for #2938
2022-04-04 20:37:10 +00:00
2c6cd74dc1 Set the Postgres version to 13 as a temporary workaround for #2938 2022-04-04 20:36:45 +00:00
68ac18dc98 Remove useless call
Follow this comment :
https://github.com/iv-org/invidious/pull/2936#discussion_r841277735
2022-04-03 23:26:34 +02:00
dbc74164ab Clean up CSS and add light/dark theme support 2022-04-03 22:56:54 +02:00
76c7b2ee9c Normalize translation keys in other locales (3/3) 2022-04-03 22:28:11 +02:00
d6913c1eb9 Normalize translation keys in other locales (2/3) 2022-04-03 22:28:11 +02:00
9aa00b2f0a Normalize translation keys in other locales (1/3) 2022-04-03 22:28:11 +02:00
af02917766 Code cleanup 2022-04-03 22:28:11 +02:00
d93a7b315d Make use of Search::Query/Filters and associated HTML generator 2022-04-03 22:27:52 +02:00
a813955ad3 Add Search::Query class to handle search queries 2022-04-03 20:03:34 +02:00
1e3425fdee Add filters UI HTML generator 2022-04-03 20:01:24 +02:00
a2b326e306 Merge pull request #2993 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-04-03 15:07:22 +02:00
0fa0e8e3f3 Merge pull request #2990 from 138138138/master
Safari audio double duration fix for iOS 15
2022-04-03 15:01:30 +02:00
dbae7502e5 Update Italian translation
Co-authored-by: Renix <kastletxd@protonmail.com>
2022-03-30 19:52:43 +02:00
f47552c0c4 Update Norwegian Bokmål translation
Co-authored-by: Petter Reinholdtsen <pere-weblate@hungry.com>
2022-03-30 19:52:43 +02:00
74836828c9 Update Finnish translation
Co-authored-by: Markus Mikkonen <markus.mikkonen@outlook.com>
2022-03-30 19:52:43 +02:00
c152243b4d new method for bypassing age restriction (#2996) 2022-03-30 19:52:39 +02:00
2a40c9a595 Merge pull request #2997 from iv-org/TheFrenchGhosty-patch-1
Update the documentation documents links in the README
2022-03-29 20:40:08 +00:00
3cea493d49 Update the documentation documents links in the README 2022-03-29 20:39:59 +00:00
6991d0851f Add a function to generate HTTP::Params from Filters 2022-03-29 20:31:23 +02:00
fb2a331f79 Add a function to parse search filters from invidious URL params 2022-03-29 20:31:23 +02:00
c888524523 Add a function to parse invidious legacy search filters 2022-03-29 20:31:23 +02:00
75c9dbaf6b Add a function to parse youtube search parameters 2022-03-29 20:31:23 +02:00
c01a29fe76 Add a function to build youtube search filters
(it aims at replacing produce_search_params)
2022-03-29 20:31:23 +02:00
80417281c4 Add a struct for search filters 2022-03-29 20:31:23 +02:00
f9b8bc006f Create a search processors module 2022-03-29 20:31:23 +02:00
2c22b0839f Safari audio double duration fix for iOS 15
The previous method breaks Always Loop feature on iOS 15.
The previous player.currentTime(player.duration() + 1) sometimes breaks the entire player.
Now it jumps to (end - 1) seconds when the time goes between over half and (end - 2) seconds.
With Always Loop on, player will jump to the beginning after 1 second.
2022-03-27 18:32:00 +08:00
ec3e67e0d2 Wait that was too much replacing 2022-03-26 20:18:24 +01:00
611e7e9dd8 Changed icon to checkmark and for verified author to checkmark-circle 2022-03-26 20:13:33 +01:00
f4e19ac05c Merge pull request #2983 from llsc12/master
Add WatchTube
2022-03-23 22:18:45 +01:00
70663af190 Add WatchTube 2022-03-22 17:41:15 +00:00
ed265cfdcd Request minified JSON from innertube (#2974) 2022-03-16 09:07:30 +01:00
5b82370bc3 Merge pull request #2961 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-03-15 07:59:56 +01:00
47690fffc1 Merge pull request #2965 from AHOHNMYC/patch-2
Uppercase some first letters in language selector
2022-03-13 23:14:23 +01:00
aa09bbe23d Done some refactoring 2022-03-13 20:16:30 +01:00
a09fbad8b0 Merge branch 'iv-org:master' into verified-badge 2022-03-13 19:06:52 +01:00
357ba2f4f6 Uppercase some first letters 2022-03-13 08:53:27 +03:00
b32dd746a6 Update Indonesian translation
Co-authored-by: I. Musthafa <i.musthafa66@gmail.com>
2022-03-11 20:51:15 +01:00
b4ea1ccc23 Update Basque translation
Update Basque translation

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Izei <mikelbre@gmail.com>
2022-03-11 20:51:15 +01:00
2aecbfbb67 Update Czech translation
Co-authored-by: Fjuro <fjuro@seznam.cz>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2022-03-11 20:51:15 +01:00
6d3b907307 Update --help to mention that --migrate is still in beta 2022-03-11 20:51:12 +01:00
55da1e3e92 Merge pull request #2878 from matthewmcgarvey/migrations
Add custom migration implementation
2022-03-11 20:49:26 +01:00
f3aa0d6428 Merge pull request #2960 from weblate/weblate-invidious-translations
Translations update from Hosted Weblate
2022-03-10 00:22:10 +01:00
ad89be7523 Update Italian translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:05 +01:00
49a7c16de5 Update Greek translation
Co-authored-by: THANOS SIOURDAKIS <siourdakisthanos@gmail.com>
2022-03-09 23:54:05 +01:00
e414476c6e Update Spanish translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:05 +01:00
391690d570 Update Lithuanian translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:05 +01:00
1be4af733b Update Croatian translation
Co-authored-by: Milo Ivir <mail@milotype.de>
2022-03-09 23:54:04 +01:00
e3222d99ac Update Swedish translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:04 +01:00
5b19d33387 Update Russian translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:04 +01:00
272c85c062 Update Czech translation
Co-authored-by: Fjuro <fjuro@seznam.cz>
2022-03-09 23:54:04 +01:00
7101af764a Update German translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:04 +01:00
e582d25654 Update Arabic translation
Co-authored-by: Rex_sa <rex.sa@pm.me>
2022-03-09 23:54:04 +01:00
9991c4507d Update Japanese translation
Co-authored-by: GnuPGを使うべきだ <dieeeazpnnqbpddh@cock.email>
2022-03-09 23:54:03 +01:00
37b3248202 Update English (United States) translation
Co-authored-by: Samantaz Fox <translator-weblate@samantaz.fr>
2022-03-09 23:54:03 +01:00
0585131f78 Update Finnish translation
Co-authored-by: Markus Mikkonen <markus.mikkonen@outlook.com>
2022-03-09 23:54:03 +01:00
7e351b21bc Fix broken links (#2958) 2022-03-09 15:24:32 +01:00
440549fcc5 Merge pull request #2952 from iv-org/SamantazFox-patch-1
API: fix suggestions not workin
2022-03-07 15:52:50 +00:00
f7b557eed1 API: fix suggestions not workin
Closes #2914 
Thanks to @TiA4f8R for the help
2022-03-06 01:12:57 +01:00
bdfe317e20 Fix deprecated helm chart dependency (#2944) 2022-03-03 16:09:13 +01:00
19805b91d9 Patch links related to youtube.com
Related to followings comments :
- https://github.com/iv-org/invidious/pull/2936#discussion_r815253405
2022-02-26 17:53:39 +01:00
420c458b6a Update links related to youtube.com
Following comment at :
- https://github.com/iv-org/invidious/pull/2936#discussion_r814435888
2022-02-25 21:07:12 +01:00
6de449811d Merge branch 'iv-org:master' into verified-badge 2022-02-25 19:29:12 +01:00
081fd541af Merge pull request #2939 from iv-org/dockerfile-fix
Fix the Dockerfile sed command
2022-02-25 18:25:06 +00:00
7dcd5035c0 Fix the Dockerfile sed command (Closes #2938) 2022-02-25 19:01:14 +01:00
0f1bb3fb3b Update reduce_uri signature
Following request_change at :
- https://github.com/iv-org/invidious/pull/2936#discussion_r814436660
2022-02-25 11:47:07 +01:00
78c447829a Increase size of links displayed in video description 2022-02-25 02:11:30 +01:00
3da0287ede Let 'shards update' sort the shard.lock file 2022-02-23 13:23:17 +01:00
ea3331840d Fix typo in shard.yml 2022-02-23 13:21:52 +01:00
3fc0f72f3a Bump 'spectator' to v0.10.5 2022-02-23 13:21:03 +01:00
ea3abe6069 Bump 'sqlite3' to v0.19.0 and 'pg' to v0.26.0 2022-02-23 13:15:38 +01:00
e66b317f02 Reduce regex in player script
Following correction at:
https://github.com/iv-org/invidious/pull/2895#issuecomment-1048245008
2022-02-22 22:53:26 +01:00
aa8758dec2 Patch updateCookie for preserve extra args (like domain) 2022-02-22 20:05:22 +01:00
ad6b29c09f Update cookie domain definition in player script
Related with :
https://github.com/iv-org/invidious/pull/2895#issuecomment-1047762544
2022-02-22 18:58:41 +01:00
09a585c93b Add sameSite policy in cookie management in server side 2022-02-22 18:57:21 +01:00
8e4959a621 Update cookie declaration for preserve SameSite directive 2022-02-22 13:15:53 +01:00
1e3f4ed398 Lint player.js
Follow lint indications :
- https://github.com/iv-org/invidious/pull/2895#discussion_r809461103
- https://github.com/iv-org/invidious/pull/2895#discussion_r809461622
2022-02-17 22:22:04 +01:00
7048193f00 Move store of modification in Cookie instead of localStorage 2022-02-14 17:22:06 +01:00
17ae2648ed Modify use of module (Only if video settings are default)
Following remark at https://github.com/iv-org/invidious/pull/2895#issuecomment-1037279953
2022-02-14 17:01:10 +01:00
c952754c8c Add videojs-persist plugin 2022-02-14 17:01:10 +01:00
bf054dfda5 Do not check for pending migrations on app start
This is so that we don't break deploys with this PR.
Instead we only ship the 'invidious --migrate' cli command
and let people test that. Maybe even ship a new migration that wouldn't break
apps that don't run the migrations. Then we roll out the functionality
that requires migrations.
2022-02-12 09:20:43 -06:00
59654289cb Run migrations through CLI instead of when app starts 2022-02-11 22:43:16 -06:00
cf13c11236 Migrations tweaks 2022-02-11 22:29:19 -06:00
8ec992a8a3 Add custom migration implementation 2022-02-09 00:50:32 -06:00
f8b29674b2 Gave them marks some space and added nil checks 2022-02-07 02:25:34 +01:00
fe55141a7b Crystal format 2022-02-07 02:04:50 +01:00
9205ccc124 Removed dummy values and added checks for items.ecr 2022-02-07 02:00:43 +01:00
00df3e2c40 Refactored code and added badges to Search but many dummies because of the way components/item works 2022-02-04 19:59:07 +01:00
a2578ac6b4 Added Verified Badge to related videos 2022-02-04 17:55:22 +01:00
1fee636afa Added verification badge to video player and error with related_videos 2022-02-03 23:18:50 +01:00
154bca4635 Added Verification Badge to Youtube Comments 2022-02-03 22:32:00 +01:00
c584e31657 Inlined the if statement 2022-02-03 22:14:00 +01:00
66340281e6 Added verification badge for channel view 2022-02-03 21:42:28 +01:00
159 changed files with 9506 additions and 3760 deletions

View File

@ -77,10 +77,6 @@ Metrics/CyclomaticComplexity:
# process_video_params(query, preferences) => [20/10]
- src/invidious/videos.cr
# produce_search_params(page, sort, ...) => [29/10]
# process_search_query(query, page, ...) => [14/10]
- src/invidious/search.cr
#src/invidious/playlists.cr:327:5

View File

@ -38,23 +38,26 @@ jobs:
matrix:
stable: [true]
crystal:
- 1.0.0
- 1.1.1
- 1.2.2
- 1.3.2
- 1.4.0
- 1.5.0
include:
- crystal: nightly
stable: false
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- name: Install Crystal
uses: crystal-lang/install-crystal@v1.5.3
uses: crystal-lang/install-crystal@v1.6.0
with:
crystal: ${{ matrix.crystal }}
- name: Cache Shards
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ./lib
key: shards-${{ hashFiles('shard.lock') }}
@ -84,7 +87,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Build Docker
run: docker-compose build --build-arg release=0
@ -100,18 +103,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
- name: Build Docker ARM64 image
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
file: docker/Dockerfile.arm64

View File

@ -15,20 +15,20 @@ on:
- screenshots/*
- .github/ISSUE_TEMPLATE/*
- kubernetes/**
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install Crystal
uses: oprypin/install-crystal@v1.2.4
uses: crystal-lang/install-crystal@v1.6.0
with:
crystal: 1.2.2
crystal: 1.5.0
- name: Run lint
run: |
if ! crystal tool format --check; then
@ -38,15 +38,15 @@ jobs:
fi
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
- name: Login to registry
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_USERNAME }}
@ -54,7 +54,7 @@ jobs:
- name: Build and push Docker AMD64 image for Push Event
if: github.ref == 'refs/heads/master'
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
file: docker/Dockerfile
@ -66,7 +66,7 @@ jobs:
- name: Build and push Docker ARM64 image for Push Event
if: github.ref == 'refs/heads/master'
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
file: docker/Dockerfile.arm64

View File

@ -10,11 +10,11 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
- uses: actions/stale@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 365
days-before-pr-stale: 45 # PRs should be active. Anything that hasn't had activity in more than 45 days should be considered abandoned.
days-before-pr-stale: 45 # PRs should be active. Anything that hasn't had activity in more than 45 days should be considered abandoned.
days-before-close: 30
exempt-pr-labels: blocked
stale-issue-message: 'This issue has been automatically marked as stale and will be closed in 30 days because it has not had recent activity and is much likely outdated. If you think this issue is still relevant and applicable, you just have to post a comment and it will be unmarked.'

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "mocks"]
path = mocks
url = ../mocks

View File

@ -20,7 +20,7 @@
<a href="https://hosted.weblate.org/engage/invidious/">
<img alt="Translation Status" src="https://hosted.weblate.org/widgets/invidious/-/translations/svg-badge.svg">
</a>
<a href="https://github.com/humanetech-community/awesome-humane-tech">
<img alt="Awesome Humane Tech" src="https://raw.githubusercontent.com/humanetech-community/awesome-humane-tech/main/humane-tech-badge.svg?sanitize=true">
</a>
@ -28,17 +28,17 @@
<h3>An open source alternative front-end to YouTube</h3>
<a href="https://invidious.io/">Website</a>
&nbsp;&nbsp;
&nbsp;&nbsp;
<a href="https://instances.invidious.io/">Instances list</a>
&nbsp;&nbsp;
<a href="https://docs.invidious.io/FAQ.md">FAQ</a>
&nbsp;&nbsp;
<a href="https://docs.invidious.io/faq/">FAQ</a>
&nbsp;&nbsp;
<a href="https://docs.invidious.io/">Documentation</a>
&nbsp;&nbsp;
<a href="#contribute">Contribute</a>
&nbsp;&nbsp;
<a href="https://invidious.io/donate/">Donate</a>
<h5>Chat with us:</h5>
<a href="https://matrix.to/#/#invidious:matrix.org">
<img alt="Matrix" src="https://img.shields.io/matrix/invidious:matrix.org?label=Matrix&color=darkgreen">
@ -48,7 +48,7 @@
</a>
<br>
<a rel="me" href="https://social.tchncs.de/@invidious">
<img alt="Mastodon: @invidious@social.tchncs.de" src="https://img.shields.io/badge/Mastodon-%40invidious%40social.tchncs.de-darkgreen">
<img alt="Fediverse: @invidious@social.tchncs.de" src="https://img.shields.io/badge/Fediverse-%40invidious%40social.tchncs.de-darkgreen">
</a>
<br>
<a href="https://invidious.io/contact/">
@ -88,7 +88,7 @@
**Technical features**
- Embedded video support
- [Developer API](https://docs.invidious.io/API.md)
- [Developer API](https://docs.invidious.io/api/)
- Does not use official YouTube APIs
- No Contributor License Agreement (CLA)
@ -101,7 +101,7 @@
**Hosting invidious:**
- [Follow the installation instructions](https://docs.invidious.io/Installation.md)
- [Follow the installation instructions](https://docs.invidious.io/installation/)
## Documentation
@ -119,7 +119,7 @@ embedded youtube videos on other websites with invidious.
The documentation contains a list of browser extensions that we recommended to use along with Invidious.
You can read more here: https://docs.invidious.io/Extensions.md
You can read more here: https://docs.invidious.io/applications/
## Contribute
@ -150,6 +150,10 @@ Weblate also allows you to log-in with major SSO providers like Github, Gitlab,
- [PeerTubeify](https://gitlab.com/Cha_deL/peertubeify): On YouTube, displays a link to the same video on PeerTube, if it exists.
- [MusicPiped](https://github.com/deep-gaurav/MusicPiped): A material design music player that streams music from YouTube.
- [HoloPlay](https://github.com/stephane-r/HoloPlay): Funny Android application connecting on Invidious API's with search, playlists and favorites.
- [WatchTube](https://github.com/WatchTubeTeam/WatchTube): Powerful YouTube client for Apple Watch.
- [Yattee](https://github.com/yattee/yattee): Alternative YouTube frontend for iPhone, iPad, Mac and Apple TV.
- [TubiTui](https://codeberg.org/777/TubiTui): A lightweight, libre, TUI-based YouTube client.
- [Ytfzf](https://github.com/pystardust/ytfzf): A posix script to find and watch youtube videos from the terminal. (Without API)
## Liability

View File

@ -15,6 +15,11 @@ body {
background-color: rgb(255, 0, 0, 0.5);
}
.underlined {
border-bottom: 1px solid;
margin-bottom: 20px;
}
.channel-profile > * {
font-size: 1.17em;
font-weight: bold;
@ -199,7 +204,8 @@ img.thumbnail {
margin: 1px;
border: 1px solid;
border-color: #0000 #0000 #CCC #0000;
border-color: rgba(0,0,0,0);
border-bottom-color: #CCC;
border-radius: 0;
box-shadow: none;
@ -209,7 +215,8 @@ img.thumbnail {
.searchbar input[type="search"]:focus {
margin: 0 0 0.5px 0;
border: 2px solid;
border-color: #0000 #0000 #FED #0000;
border-color: rgba(0,0,0,0);
border-bottom-color: #FED;
}
/* https://stackoverflow.com/a/55170420 */
@ -229,7 +236,7 @@ input[type="search"]::-webkit-search-cancel-button {
}
.user-field div {
width: initial;
width: auto;
}
.user-field div:not(:last-child) {
@ -286,7 +293,7 @@ input[type="search"]::-webkit-search-cancel-button {
.flexible { display: flex; }
.flex-left { flex: 1 1 100%; flex-wrap: wrap; }
.flex-right { flex: 1 0 max-content; flex-wrap: nowrap; }
.flex-right { flex: 1 0 auto; flex-wrap: nowrap; }
p.channel-name { margin: 0; }
p.video-data { margin: 0; font-weight: bold; font-size: 80%; }
@ -475,30 +482,6 @@ body.dark-theme {
}
}
#filters {
display: inline;
margin-top: 15px;
}
#filters > div {
display: inline-block;
}
#filters > summary {
display: block;
margin-bottom: 15px;
}
#filters > summary::before {
content: "[ + ]";
font-size: 1.5em;
}
#filters[open] > summary::before {
content: "[ - ]";
font-size: 1.5em;
}
/*With commit d9528f5 all contents of the page is now within a flexbox. However,
the hr element is rendered improperly within one.
See https://stackoverflow.com/a/34372979 for more info */
@ -546,3 +529,9 @@ p,
/* Center the "invidious" logo on the search page */
#logo > h1 { text-align: center; }
/* IE11 fixes */
:-ms-input-placeholder { color: #888; }
/* Wider settings name to less word wrap */
.pure-form-aligned .pure-control-group label { width: 19em; }

View File

@ -70,6 +70,9 @@
margin-bottom: 2em;
}
.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control {height: 5px;
margin-bottom: 10px;}
ul.vjs-menu-content::-webkit-scrollbar {
display: none;
}
@ -98,23 +101,27 @@ ul.vjs-menu-content::-webkit-scrollbar {
order: 2;
}
.vjs-quality-selector,
.video-js .vjs-http-source-selector {
.vjs-audio-button {
order: 3;
}
.vjs-playback-rate {
.vjs-quality-selector,
.video-js .vjs-http-source-selector {
order: 4;
}
.vjs-share-control {
.vjs-playback-rate {
order: 5;
}
.vjs-fullscreen-control {
.vjs-share-control {
order: 6;
}
.vjs-fullscreen-control {
order: 7;
}
.vjs-playback-rate > .vjs-menu {
width: 50px;
}

121
assets/css/search.css Normal file
View File

@ -0,0 +1,121 @@
summary {
/* This should hide the marker */
display: block;
font-size: 1.17em;
font-weight: bold;
margin: 0 auto 10px auto;
cursor: pointer;
}
summary::-webkit-details-marker,
summary::marker { display: none; }
summary:before {
border-radius: 5px;
content: "[ + ]";
margin: -2px 10px 0 10px;
padding: 1px 0 3px 0;
text-align: center;
width: 40px;
}
details[open] > summary:before { content: "[ ]"; }
#filters-box {
padding: 10px 20px 20px 10px;
margin: 10px 15px;
}
#filters-flex {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: flex-start;
align-content: flex-start;
justify-content: flex-start;
}
fieldset, legend {
display: contents !important;
border: none !important;
margin: 0 !important;
padding: 0 !important;
}
.filter-column {
display: inline-block;
display: inline-flex;
width: max-content;
min-width: max-content;
max-width: 16em;
margin: 15px;
flex-grow: 2;
flex-basis: auto;
flex-direction: column;
}
.filter-name, .filter-options {
display: block;
padding: 5px 10px;
margin: 0;
text-align: start;
}
.filter-options div { margin: 6px 0; }
.filter-options div * { vertical-align: middle; }
.filter-options label { margin: 0 10px; }
#filters-apply {
text-align: right; /* IE11 only */
text-align: end; /* Override for compatible browsers */
}
/* Error message */
.no-results-error {
text-align: center;
line-height: 180%;
font-size: 110%;
padding: 15px 15px 125px 15px;
}
/* Responsive rules */
@media only screen and (max-width: 800px) {
summary { font-size: 1.30em; }
#filters-box {
margin: 10px 0 0 0;
padding: 0;
}
#filters-apply {
text-align: center;
padding: 15px;
}
}
/* Light theme */
.light-theme #filters-box {
background: #dfdfdf;
}
@media (prefers-color-scheme: light) {
.no-theme #filters-box {
background: #dfdfdf;
}
}
/* Dark theme */
.dark-theme #filters-box {
background: #373737;
}
@media (prefers-color-scheme: dark) {
.no-theme #filters-box {
background: #373737;
}
}

249
assets/js/_helpers.js Normal file
View File

@ -0,0 +1,249 @@
'use strict';
// Contains only auxiliary methods
// May be included and executed unlimited number of times without any consequences
// Polyfills for IE11
Array.prototype.find = Array.prototype.find || function (condition) {
return this.filter(condition)[0];
};
Array.from = Array.from || function (source) {
return Array.prototype.slice.call(source);
};
NodeList.prototype.forEach = NodeList.prototype.forEach || function (callback) {
Array.from(this).forEach(callback);
};
String.prototype.includes = String.prototype.includes || function (searchString) {
return this.indexOf(searchString) >= 0;
};
String.prototype.startsWith = String.prototype.startsWith || function (prefix) {
return this.substr(0, prefix.length) === prefix;
};
Math.sign = Math.sign || function(x) {
x = +x;
if (!x) return x; // 0 and NaN
return x > 0 ? 1 : -1;
};
if (!window.hasOwnProperty('HTMLDetailsElement') && !window.hasOwnProperty('mockHTMLDetailsElement')) {
window.mockHTMLDetailsElement = true;
const style = 'details:not([open]) > :not(summary) {display: none}';
document.head.appendChild(document.createElement('style')).textContent = style;
addEventListener('click', function (e) {
if (e.target.nodeName !== 'SUMMARY') return;
const details = e.target.parentElement;
if (details.hasAttribute('open'))
details.removeAttribute('open');
else
details.setAttribute('open', '');
});
}
// Monstrous global variable for handy code
// Includes: clamp, xhr, storage.{get,set,remove}
window.helpers = window.helpers || {
/**
* https://en.wikipedia.org/wiki/Clamping_(graphics)
* @param {Number} num Source number
* @param {Number} min Low border
* @param {Number} max High border
* @returns {Number} Clamped value
*/
clamp: function (num, min, max) {
if (max < min) {
var t = max; max = min; min = t; // swap max and min
}
if (max < num)
return max;
if (min > num)
return min;
return num;
},
/** @private */
_xhr: function (method, url, options, callbacks) {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
// Default options
xhr.responseType = 'json';
xhr.timeout = 10000;
// Default options redefining
if (options.responseType)
xhr.responseType = options.responseType;
if (options.timeout)
xhr.timeout = options.timeout;
if (method === 'POST')
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// better than onreadystatechange because of 404 codes https://stackoverflow.com/a/36182963
xhr.onloadend = function () {
if (xhr.status === 200) {
if (callbacks.on200) {
// fix for IE11. It doesn't convert response to JSON
if (xhr.responseType === '' && typeof(xhr.response) === 'string')
callbacks.on200(JSON.parse(xhr.response));
else
callbacks.on200(xhr.response);
}
} else {
// handled by onerror
if (xhr.status === 0) return;
if (callbacks.onNon200)
callbacks.onNon200(xhr);
}
};
xhr.ontimeout = function () {
if (callbacks.onTimeout)
callbacks.onTimeout(xhr);
};
xhr.onerror = function () {
if (callbacks.onError)
callbacks.onError(xhr);
};
if (options.payload)
xhr.send(options.payload);
else
xhr.send();
},
/** @private */
_xhrRetry: function(method, url, options, callbacks) {
if (options.retries <= 0) {
console.warn('Failed to pull', options.entity_name);
if (callbacks.onTotalFail)
callbacks.onTotalFail();
return;
}
helpers._xhr(method, url, options, callbacks);
},
/**
* @callback callbackXhrOn200
* @param {Object} response - xhr.response
*/
/**
* @callback callbackXhrError
* @param {XMLHttpRequest} xhr
*/
/**
* @param {'GET'|'POST'} method - 'GET' or 'POST'
* @param {String} url - URL to send request to
* @param {Object} options - other XHR options
* @param {XMLHttpRequestBodyInit} [options.payload=null] - payload for POST-requests
* @param {'arraybuffer'|'blob'|'document'|'json'|'text'} [options.responseType=json]
* @param {Number} [options.timeout=10000]
* @param {Number} [options.retries=1]
* @param {String} [options.entity_name='unknown'] - string to log
* @param {Number} [options.retry_timeout=1000]
* @param {Object} callbacks - functions to execute on events fired
* @param {callbackXhrOn200} [callbacks.on200]
* @param {callbackXhrError} [callbacks.onNon200]
* @param {callbackXhrError} [callbacks.onTimeout]
* @param {callbackXhrError} [callbacks.onError]
* @param {callbackXhrError} [callbacks.onTotalFail] - if failed after all retries
*/
xhr: function(method, url, options, callbacks) {
if (!options.retries || options.retries <= 1) {
helpers._xhr(method, url, options, callbacks);
return;
}
if (!options.entity_name) options.entity_name = 'unknown';
if (!options.retry_timeout) options.retry_timeout = 1000;
const retries_total = options.retries;
let currentTry = 1;
const retry = function () {
console.warn('Pulling ' + options.entity_name + ' failed... ' + (currentTry++) + '/' + retries_total);
setTimeout(function () {
options.retries--;
helpers._xhrRetry(method, url, options, callbacks);
}, options.retry_timeout);
};
// Pack retry() call into error handlers
callbacks._onError = callbacks.onError;
callbacks.onError = function (xhr) {
if (callbacks._onError)
callbacks._onError(xhr);
retry();
};
callbacks._onTimeout = callbacks.onTimeout;
callbacks.onTimeout = function (xhr) {
if (callbacks._onTimeout)
callbacks._onTimeout(xhr);
retry();
};
helpers._xhrRetry(method, url, options, callbacks);
},
/**
* @typedef {Object} invidiousStorage
* @property {(key:String) => Object} get
* @property {(key:String, value:Object)} set
* @property {(key:String)} remove
*/
/**
* Universal storage, stores and returns JS objects. Uses inside localStorage or cookies
* @type {invidiousStorage}
*/
storage: (function () {
// access to localStorage throws exception in Tor Browser, so try is needed
let localStorageIsUsable = false;
try{localStorageIsUsable = !!localStorage.setItem;}catch(e){}
if (localStorageIsUsable) {
return {
get: function (key) {
if (!localStorage[key]) return;
try {
return JSON.parse(decodeURIComponent(localStorage[key]));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
},
set: function (key, value) { localStorage[key] = encodeURIComponent(JSON.stringify(value)); },
remove: function (key) { localStorage.removeItem(key); }
};
}
// TODO: fire 'storage' event for cookies
console.info('Storage: localStorage is disabled or unaccessible. Cookies used as fallback');
return {
get: function (key) {
const cookiePrefix = key + '=';
function findCallback(cookie) {return cookie.startsWith(cookiePrefix);}
const matchedCookie = document.cookie.split('; ').find(findCallback);
if (matchedCookie) {
const cookieBody = matchedCookie.replace(cookiePrefix, '');
if (cookieBody.length === 0) return;
try {
return JSON.parse(decodeURIComponent(cookieBody));
} catch(e) {
// Erase non parsable value
helpers.storage.remove(key);
}
}
},
set: function (key, value) {
const cookie_data = encodeURIComponent(JSON.stringify(value));
// Set expiration in 2 year
const date = new Date();
date.setFullYear(date.getFullYear()+2);
document.cookie = key + '=' + cookie_data + '; expires=' + date.toGMTString();
},
remove: function (key) {
document.cookie = key + '=; Max-Age=0';
}
};
})()
};

View File

@ -1,19 +1,13 @@
var community_data = JSON.parse(document.getElementById('community_data').innerHTML);
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g, function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
});
}
'use strict';
var community_data = JSON.parse(document.getElementById('community_data').textContent);
function hide_youtube_replies(event) {
var target = event.target;
sub_text = target.getAttribute('data-inner-text');
inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
body = target.parentNode.parentNode.children[1];
var body = target.parentNode.parentNode.children[1];
body.style.display = 'none';
target.innerHTML = sub_text;
@ -25,10 +19,10 @@ function hide_youtube_replies(event) {
function show_youtube_replies(event) {
var target = event.target;
sub_text = target.getAttribute('data-inner-text');
inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
body = target.parentNode.parentNode.children[1];
var body = target.parentNode.parentNode.children[1];
body.style.display = '';
target.innerHTML = sub_text;
@ -37,13 +31,6 @@ function show_youtube_replies(event) {
target.setAttribute('data-sub-text', sub_text);
}
function number_with_separator(val) {
while (/(\d+)(\d{3})/.test(val.toString())) {
val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
}
return val;
}
function get_youtube_replies(target, load_more) {
var continuation = target.getAttribute('data-continuation');
@ -57,47 +44,39 @@ function get_youtube_replies(target, load_more) {
'&hl=' + community_data.preferences.locale +
'&thin_mode=' + community_data.preferences.thin_mode +
'&continuation=' + continuation;
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
if (load_more) {
body = body.parentNode.parentNode;
body.removeChild(body.lastElementChild);
body.innerHTML += xhr.response.contentHtml;
} else {
body.removeChild(body.lastElementChild);
var p = document.createElement('p');
var a = document.createElement('a');
p.appendChild(a);
a.href = 'javascript:void(0)';
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', community_data.hide_replies_text);
a.setAttribute('data-inner-text', community_data.show_replies_text);
a.innerText = community_data.hide_replies_text;
var div = document.createElement('div');
div.innerHTML = xhr.response.contentHtml;
body.appendChild(p);
body.appendChild(div);
}
helpers.xhr('GET', url, {}, {
on200: function (response) {
if (load_more) {
body = body.parentNode.parentNode;
body.removeChild(body.lastElementChild);
body.innerHTML += response.contentHtml;
} else {
body.innerHTML = fallback;
body.removeChild(body.lastElementChild);
var p = document.createElement('p');
var a = document.createElement('a');
p.appendChild(a);
a.href = 'javascript:void(0)';
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', community_data.hide_replies_text);
a.setAttribute('data-inner-text', community_data.show_replies_text);
a.textContent = community_data.hide_replies_text;
var div = document.createElement('div');
div.innerHTML = response.contentHtml;
body.appendChild(p);
body.appendChild(div);
}
},
onNon200: function (xhr) {
body.innerHTML = fallback;
},
onTimeout: function (xhr) {
console.warn('Pulling comments failed');
body.innerHTML = fallback;
}
}
xhr.ontimeout = function () {
console.log('Pulling comments failed.');
body.innerHTML = fallback;
}
xhr.send();
});
}

View File

@ -1,103 +1,62 @@
var video_data = JSON.parse(document.getElementById('video_data').innerHTML);
function get_playlist(plid, retries) {
if (retries == undefined) retries = 5;
if (retries <= 0) {
console.log('Failed to pull playlist');
return;
}
'use strict';
var video_data = JSON.parse(document.getElementById('video_data').textContent);
function get_playlist(plid) {
var plid_url;
if (plid.startsWith('RD')) {
var plid_url = '/api/v1/mixes/' + plid +
plid_url = '/api/v1/mixes/' + plid +
'?continuation=' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
} else {
var plid_url = '/api/v1/playlists/' + plid +
plid_url = '/api/v1/playlists/' + plid +
'?index=' + video_data.index +
'&continuation' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', plid_url, true);
helpers.xhr('GET', plid_url, {retries: 5, entity_name: 'playlist'}, {
on200: function (response) {
if (!response.nextVideo)
return;
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (xhr.response.nextVideo) {
player.on('ended', function () {
var url = new URL('https://example.com/embed/' + xhr.response.nextVideo);
player.on('ended', function () {
var url = new URL('https://example.com/embed/' + response.nextVideo);
url.searchParams.set('list', plid);
if (!plid.startsWith('RD')) {
url.searchParams.set('index', xhr.response.index);
}
url.searchParams.set('list', plid);
if (!plid.startsWith('RD'))
url.searchParams.set('index', response.index);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
url.searchParams.set('autoplay', '1');
}
if (video_data.params.listen !== video_data.preferences.listen) {
url.searchParams.set('listen', video_data.params.listen);
}
if (video_data.params.speed !== video_data.preferences.speed) {
url.searchParams.set('speed', video_data.params.speed);
}
if (video_data.params.local !== video_data.preferences.local) {
url.searchParams.set('local', video_data.params.local);
}
location.assign(url.pathname + url.search);
});
}
}
location.assign(url.pathname + url.search);
});
}
}
xhr.onerror = function () {
console.log('Pulling playlist failed... ' + retries + '/5');
setTimeout(function () { get_playlist(plid, retries - 1) }, 1000);
}
xhr.ontimeout = function () {
console.log('Pulling playlist failed... ' + retries + '/5');
get_playlist(plid, retries - 1);
}
xhr.send();
});
}
window.addEventListener('load', function (e) {
addEventListener('load', function (e) {
if (video_data.plid) {
get_playlist(video_data.plid);
} else if (video_data.video_series) {
player.on('ended', function () {
var url = new URL('https://example.com/embed/' + video_data.video_series.shift());
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
}
if (video_data.params.listen !== video_data.preferences.listen) {
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
}
if (video_data.params.speed !== video_data.preferences.speed) {
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
}
if (video_data.params.local !== video_data.preferences.local) {
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
}
if (video_data.video_series.length !== 0) {
url.searchParams.set('playlist', video_data.video_series.join(','))
}
if (video_data.video_series.length !== 0)
url.searchParams.set('playlist', video_data.video_series.join(','));
location.assign(url.pathname + url.search);
});

View File

@ -1,8 +1,6 @@
'use strict';
(function () {
var n2a = function (n) { return Array.prototype.slice.call(n); };
var video_player = document.getElementById('player_html5_api');
if (video_player) {
video_player.onmouseenter = function () { video_player['data-title'] = video_player['title']; video_player['title'] = ''; };
@ -11,140 +9,124 @@
}
// For dynamically inserted elements
document.addEventListener('click', function (e) {
if (!e || !e.target) { return; }
e = e.target;
var handler_name = e.getAttribute('data-onclick');
addEventListener('click', function (e) {
if (!e || !e.target) return;
var t = e.target;
var handler_name = t.getAttribute('data-onclick');
switch (handler_name) {
case 'jump_to_time':
var time = e.getAttribute('data-jump-time');
e.preventDefault();
var time = t.getAttribute('data-jump-time');
player.currentTime(time);
break;
case 'get_youtube_replies':
var load_more = e.getAttribute('data-load-more') !== null;
var load_replies = e.getAttribute('data-load-replies') !== null;
get_youtube_replies(e, load_more, load_replies);
var load_more = t.getAttribute('data-load-more') !== null;
var load_replies = t.getAttribute('data-load-replies') !== null;
get_youtube_replies(t, load_more, load_replies);
break;
case 'toggle_parent':
toggle_parent(e);
e.preventDefault();
toggle_parent(t);
break;
default:
break;
}
});
n2a(document.querySelectorAll('[data-mouse="switch_classes"]')).forEach(function (e) {
var classes = e.getAttribute('data-switch-classes').split(',');
var ec = classes[0];
var lc = classes[1];
var onoff = function (on, off) {
var cs = e.getAttribute('class');
cs = cs.split(off).join(on);
e.setAttribute('class', cs);
};
e.onmouseenter = function () { onoff(ec, lc); };
e.onmouseleave = function () { onoff(lc, ec); };
document.querySelectorAll('[data-mouse="switch_classes"]').forEach(function (el) {
var classes = el.getAttribute('data-switch-classes').split(',');
var classOnEnter = classes[0];
var classOnLeave = classes[1];
function toggle_classes(toAdd, toRemove) {
el.classList.add(toAdd);
el.classList.remove(toRemove);
}
el.onmouseenter = function () { toggle_classes(classOnEnter, classOnLeave); };
el.onmouseleave = function () { toggle_classes(classOnLeave, classOnEnter); };
});
n2a(document.querySelectorAll('[data-onsubmit="return_false"]')).forEach(function (e) {
e.onsubmit = function () { return false; };
document.querySelectorAll('[data-onsubmit="return_false"]').forEach(function (el) {
el.onsubmit = function () { return false; };
});
n2a(document.querySelectorAll('[data-onclick="mark_watched"]')).forEach(function (e) {
e.onclick = function () { mark_watched(e); };
document.querySelectorAll('[data-onclick="mark_watched"]').forEach(function (el) {
el.onclick = function () { mark_watched(el); };
});
n2a(document.querySelectorAll('[data-onclick="mark_unwatched"]')).forEach(function (e) {
e.onclick = function () { mark_unwatched(e); };
document.querySelectorAll('[data-onclick="mark_unwatched"]').forEach(function (el) {
el.onclick = function () { mark_unwatched(el); };
});
n2a(document.querySelectorAll('[data-onclick="add_playlist_video"]')).forEach(function (e) {
e.onclick = function () { add_playlist_video(e); };
document.querySelectorAll('[data-onclick="add_playlist_video"]').forEach(function (el) {
el.onclick = function () { add_playlist_video(el); };
});
n2a(document.querySelectorAll('[data-onclick="add_playlist_item"]')).forEach(function (e) {
e.onclick = function () { add_playlist_item(e); };
document.querySelectorAll('[data-onclick="add_playlist_item"]').forEach(function (el) {
el.onclick = function () { add_playlist_item(el); };
});
n2a(document.querySelectorAll('[data-onclick="remove_playlist_item"]')).forEach(function (e) {
e.onclick = function () { remove_playlist_item(e); };
document.querySelectorAll('[data-onclick="remove_playlist_item"]').forEach(function (el) {
el.onclick = function () { remove_playlist_item(el); };
});
n2a(document.querySelectorAll('[data-onclick="revoke_token"]')).forEach(function (e) {
e.onclick = function () { revoke_token(e); };
document.querySelectorAll('[data-onclick="revoke_token"]').forEach(function (el) {
el.onclick = function () { revoke_token(el); };
});
n2a(document.querySelectorAll('[data-onclick="remove_subscription"]')).forEach(function (e) {
e.onclick = function () { remove_subscription(e); };
document.querySelectorAll('[data-onclick="remove_subscription"]').forEach(function (el) {
el.onclick = function () { remove_subscription(el); };
});
n2a(document.querySelectorAll('[data-onclick="notification_requestPermission"]')).forEach(function (e) {
e.onclick = function () { Notification.requestPermission(); };
document.querySelectorAll('[data-onclick="notification_requestPermission"]').forEach(function (el) {
el.onclick = function () { Notification.requestPermission(); };
});
n2a(document.querySelectorAll('[data-onrange="update_volume_value"]')).forEach(function (e) {
var cb = function () { update_volume_value(e); }
e.oninput = cb;
e.onchange = cb;
document.querySelectorAll('[data-onrange="update_volume_value"]').forEach(function (el) {
function update_volume_value() {
document.getElementById('volume-value').textContent = el.value;
}
el.oninput = update_volume_value;
el.onchange = update_volume_value;
});
function update_volume_value(element) {
document.getElementById('volume-value').innerText = element.value;
}
function revoke_token(target) {
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = 'none';
var count = document.getElementById('count');
count.innerText = count.innerText - 1;
count.textContent--;
var referer = window.encodeURIComponent(document.location.href);
var url = '/token_ajax?action_revoke_token=1&redirect=false' +
'&referer=' + referer +
'&referer=' + encodeURIComponent(location.href) +
'&session=' + target.getAttribute('data-session');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
count.innerText = parseInt(count.innerText) + 1;
row.style.display = '';
}
var payload = 'csrf_token=' + target.parentNode.querySelector('input[name="csrf_token"]').value;
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
count.textContent++;
row.style.display = '';
}
}
var csrf_token = target.parentNode.querySelector('input[name="csrf_token"]').value;
xhr.send('csrf_token=' + csrf_token);
});
}
function remove_subscription(target) {
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
row.style.display = 'none';
var count = document.getElementById('count');
count.innerText = count.innerText - 1;
count.textContent--;
var referer = window.encodeURIComponent(document.location.href);
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
'&referer=' + referer +
'&referer=' + encodeURIComponent(location.href) +
'&c=' + target.getAttribute('data-ucid');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
count.innerText = parseInt(count.innerText) + 1;
row.style.display = '';
}
var payload = 'csrf_token=' + target.parentNode.querySelector('input[name="csrf_token"]').value;
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
count.textContent++;
row.style.display = '';
}
}
var csrf_token = target.parentNode.querySelector('input[name="csrf_token"]').value;
xhr.send('csrf_token=' + csrf_token);
});
}
// Handle keypresses
window.addEventListener('keydown', (event) => {
addEventListener('keydown', function (event) {
// Ignore modifier keys
if (event.ctrlKey || event.metaKey) return;
@ -152,14 +134,14 @@
let focused_tag = document.activeElement.tagName.toLowerCase();
const allowed = /^(button|checkbox|file|radio|submit)$/;
if (focused_tag === "textarea") return;
if (focused_tag === "input") {
if (focused_tag === 'textarea') return;
if (focused_tag === 'input') {
let focused_type = document.activeElement.type.toLowerCase();
if (!focused_type.match(allowed)) return;
}
// Focus search bar on '/'
if (event.key == "/") {
if (event.key === '/') {
document.getElementById('searchbox').focus();
event.preventDefault();
}

View File

@ -1,46 +1,30 @@
var notification_data = JSON.parse(document.getElementById('notification_data').innerHTML);
'use strict';
var notification_data = JSON.parse(document.getElementById('notification_data').textContent);
/** Boolean meaning 'some tab have stream' */
const STORAGE_KEY_STREAM = 'stream';
/** Number of notifications. May be increased or reset */
const STORAGE_KEY_NOTIF_COUNT = 'notification_count';
var notifications, delivered;
var notifications_mock = { close: function () { } };
function get_subscriptions(callback, retries) {
if (retries == undefined) retries = 5;
if (retries <= 0) {
return;
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', '/api/v1/auth/subscriptions?fields=authorId', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
subscriptions = xhr.response;
callback(subscriptions);
}
}
}
xhr.onerror = function () {
console.log('Pulling subscriptions failed... ' + retries + '/5');
setTimeout(function () { get_subscriptions(callback, retries - 1) }, 1000);
}
xhr.ontimeout = function () {
console.log('Pulling subscriptions failed... ' + retries + '/5');
get_subscriptions(callback, retries - 1);
}
xhr.send();
function get_subscriptions() {
helpers.xhr('GET', '/api/v1/auth/subscriptions?fields=authorId', {
retries: 5,
entity_name: 'subscriptions'
}, {
on200: create_notification_stream
});
}
function create_notification_stream(subscriptions) {
// sse.js can't be replaced to EventSource in place as it lack support of payload and headers
// see https://developer.mozilla.org/en-US/docs/Web/API/EventSource/EventSource
notifications = new SSE(
'/api/v1/auth/notifications?fields=videoId,title,author,authorId,publishedText,published,authorThumbnails,liveNow', {
withCredentials: true,
payload: 'topics=' + subscriptions.map(function (subscription) { return subscription.authorId }).join(','),
payload: 'topics=' + subscriptions.map(function (subscription) { return subscription.authorId; }).join(','),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
delivered = [];
@ -48,96 +32,100 @@ function create_notification_stream(subscriptions) {
var start_time = Math.round(new Date() / 1000);
notifications.onmessage = function (event) {
if (!event.id) {
return;
}
if (!event.id) return;
var notification = JSON.parse(event.data);
console.log('Got notification:', notification);
console.info('Got notification:', notification);
if (start_time < notification.published && !delivered.includes(notification.videoId)) {
if (Notification.permission === 'granted') {
var system_notification =
new Notification((notification.liveNow ? notification_data.live_now_text : notification_data.upload_text).replace('`x`', notification.author), {
body: notification.title,
icon: '/ggpht' + new URL(notification.authorThumbnails[2].url).pathname,
img: '/ggpht' + new URL(notification.authorThumbnails[4].url).pathname,
tag: notification.videoId
});
// Ignore not actual and delivered notifications
if (start_time > notification.published || delivered.includes(notification.videoId)) return;
system_notification.onclick = function (event) {
window.open('/watch?v=' + event.currentTarget.tag, '_blank');
}
}
delivered.push(notification.videoId);
delivered.push(notification.videoId);
localStorage.setItem('notification_count', parseInt(localStorage.getItem('notification_count') || '0') + 1);
var notification_ticker = document.getElementById('notification_ticker');
let notification_count = helpers.storage.get(STORAGE_KEY_NOTIF_COUNT) || 0;
notification_count++;
helpers.storage.set(STORAGE_KEY_NOTIF_COUNT, notification_count);
if (parseInt(localStorage.getItem('notification_count')) > 0) {
notification_ticker.innerHTML =
'<span id="notification_count">' + localStorage.getItem('notification_count') + '</span> <i class="icon ion-ios-notifications"></i>';
} else {
notification_ticker.innerHTML =
'<i class="icon ion-ios-notifications-outline"></i>';
}
update_ticker_count();
// permission for notifications handled on settings page. JS handler is in handlers.js
if (window.Notification && Notification.permission === 'granted') {
var notification_text = notification.liveNow ? notification_data.live_now_text : notification_data.upload_text;
notification_text = notification_text.replace('`x`', notification.author);
var system_notification = new Notification(notification_text, {
body: notification.title,
icon: '/ggpht' + new URL(notification.authorThumbnails[2].url).pathname,
img: '/ggpht' + new URL(notification.authorThumbnails[4].url).pathname
});
system_notification.onclick = function (e) {
open('/watch?v=' + notification.videoId, '_blank');
};
}
}
};
notifications.addEventListener('error', function (e) {
console.warn('Something went wrong with notifications, trying to reconnect...');
notifications = notifications_mock;
setTimeout(get_subscriptions, 1000);
});
notifications.addEventListener('error', handle_notification_error);
notifications.stream();
}
function handle_notification_error(event) {
console.log('Something went wrong with notifications, trying to reconnect...');
notifications = { close: function () { } };
setTimeout(function () { get_subscriptions(create_notification_stream) }, 1000);
function update_ticker_count() {
var notification_ticker = document.getElementById('notification_ticker');
const notification_count = helpers.storage.get(STORAGE_KEY_STREAM);
if (notification_count > 0) {
notification_ticker.innerHTML =
'<span id="notification_count">' + notification_count + '</span> <i class="icon ion-ios-notifications"></i>';
} else {
notification_ticker.innerHTML =
'<i class="icon ion-ios-notifications-outline"></i>';
}
}
window.addEventListener('load', function (e) {
localStorage.setItem('notification_count', document.getElementById('notification_count') ? document.getElementById('notification_count').innerText : '0');
if (localStorage.getItem('stream')) {
localStorage.removeItem('stream');
} else {
setTimeout(function () {
if (!localStorage.getItem('stream')) {
notifications = { close: function () { } };
localStorage.setItem('stream', true);
get_subscriptions(create_notification_stream);
}
}, Math.random() * 1000 + 50);
}
window.addEventListener('storage', function (e) {
if (e.key === 'stream' && !e.newValue) {
if (notifications) {
localStorage.setItem('stream', true);
} else {
setTimeout(function () {
if (!localStorage.getItem('stream')) {
notifications = { close: function () { } };
localStorage.setItem('stream', true);
get_subscriptions(create_notification_stream);
}
}, Math.random() * 1000 + 50);
}
} else if (e.key === 'notification_count') {
var notification_ticker = document.getElementById('notification_ticker');
if (parseInt(e.newValue) > 0) {
notification_ticker.innerHTML =
'<span id="notification_count">' + e.newValue + '</span> <i class="icon ion-ios-notifications"></i>';
} else {
notification_ticker.innerHTML =
'<i class="icon ion-ios-notifications-outline"></i>';
}
function start_stream_if_needed() {
// random wait for other tabs set 'stream' flag
setTimeout(function () {
if (!helpers.storage.get(STORAGE_KEY_STREAM)) {
// if no one set 'stream', set it by yourself and start stream
helpers.storage.set(STORAGE_KEY_STREAM, true);
notifications = notifications_mock;
get_subscriptions();
}
});
});
}, Math.random() * 1000 + 50); // [0.050 .. 1.050) second
}
window.addEventListener('unload', function (e) {
if (notifications) {
localStorage.removeItem('stream');
addEventListener('storage', function (e) {
if (e.key === STORAGE_KEY_NOTIF_COUNT)
update_ticker_count();
// if 'stream' key was removed
if (e.key === STORAGE_KEY_STREAM && !helpers.storage.get(STORAGE_KEY_STREAM)) {
if (notifications) {
// restore it if we have active stream
helpers.storage.set(STORAGE_KEY_STREAM, true);
} else {
start_stream_if_needed();
}
}
});
addEventListener('load', function () {
var notification_count_el = document.getElementById('notification_count');
var notification_count = notification_count_el ? parseInt(notification_count_el.textContent) : 0;
helpers.storage.set(STORAGE_KEY_NOTIF_COUNT, notification_count);
if (helpers.storage.get(STORAGE_KEY_STREAM))
helpers.storage.remove(STORAGE_KEY_STREAM);
start_stream_if_needed();
});
addEventListener('unload', function () {
// let chance to other tabs to be a streamer via firing 'storage' event
if (notifications) helpers.storage.remove(STORAGE_KEY_STREAM);
});

View File

@ -1,5 +1,6 @@
var player_data = JSON.parse(document.getElementById('player_data').innerHTML);
var video_data = JSON.parse(document.getElementById('video_data').innerHTML);
'use strict';
var player_data = JSON.parse(document.getElementById('player_data').textContent);
var video_data = JSON.parse(document.getElementById('video_data').textContent);
var options = {
preload: 'auto',
@ -16,6 +17,7 @@ var options = {
'remainingTimeDisplay',
'Spacer',
'captionsButton',
'audioTrackButton',
'qualitySelector',
'playbackRateMenuButton',
'fullscreenToggle'
@ -27,7 +29,7 @@ var options = {
overrideNative: true
}
}
}
};
if (player_data.aspect_ratio) {
options.aspectRatio = player_data.aspect_ratio;
@ -38,21 +40,66 @@ embed_url.searchParams.delete('v');
var short_url = location.origin + '/' + video_data.id + embed_url.search;
embed_url = location.origin + '/embed/' + video_data.id + embed_url.search;
var save_player_pos_key = "save_player_pos";
var save_player_pos_key = 'save_player_pos';
videojs.Vhs.xhr.beforeRequest = function(options) {
if (options.uri.indexOf('videoplayback') === -1 && options.uri.indexOf('local=true') === -1) {
options.uri = options.uri + '?local=true';
// set local if requested not videoplayback
if (!options.uri.includes('videoplayback')) {
if (!options.uri.includes('local=true'))
options.uri += '?local=true';
}
return options;
};
var player = videojs('player', options);
player.on('error', function () {
if (video_data.params.quality === 'dash') return;
var localNotDisabled = (
!player.currentSrc().includes('local=true') && !video_data.local_disabled
);
var reloadMakesSense = (
player.error().code === MediaError.MEDIA_ERR_NETWORK ||
player.error().code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED
);
if (localNotDisabled) {
// add local=true to all current sources
player.src(player.currentSources().map(function (source) {
source.src += '&local=true';
return source;
}));
} else if (reloadMakesSense) {
setTimeout(function () {
console.warn('An error occurred in the player, reloading...');
// After load() all parameters are reset. Save them
var currentTime = player.currentTime();
var playbackRate = player.playbackRate();
var paused = player.paused();
player.load();
if (currentTime > 0.5) currentTime -= 0.5;
player.currentTime(currentTime);
player.playbackRate(playbackRate);
if (!paused) player.play();
}, 5000);
}
});
if (video_data.params.quality === 'dash') {
player.reloadSourceOnError({
errorInterval: 10
});
}
/**
* Function for add time argument to url
* @param {String} url
* @returns urlWithTimeArg
* @returns {URL} urlWithTimeArg
*/
function addCurrentTimeToURL(url) {
var urlUsed = new URL(url);
@ -75,18 +122,12 @@ var shareOptions = {
description: player_data.description,
image: player_data.thumbnail,
get embedCode() {
// Single quotes inside here required. HTML inserted as is into value attribute of input
return "<iframe id='ivplayer' width='640' height='360' src='" +
addCurrentTimeToURL(embed_url) + "' style='border:none;'></iframe>";
}
};
const storage = (() => {
try { if (localStorage.length !== -1) return localStorage; }
catch (e) { console.info('No storage available: ' + e); }
return undefined;
})();
if (location.pathname.startsWith('/embed/')) {
var overlay_content = '<h1><a rel="noopener" target="_blank" href="' + location.origin + '/watch?v=' + video_data.id + '">' + player_data.title + '</a></h1>';
player.overlay({
@ -101,78 +142,58 @@ if (location.pathname.startsWith('/embed/')) {
// Detection code taken from https://stackoverflow.com/a/20293441
function isMobile() {
try{ document.createEvent("TouchEvent"); return true; }
try{ document.createEvent('TouchEvent'); return true; }
catch(e){ return false; }
}
if (isMobile()) {
player.mobileUi();
player.mobileUi({ touchControls: { seekSeconds: 5 * player.playbackRate() } });
buttons = ["playToggle", "volumePanel", "captionsButton"];
var buttons = ['playToggle', 'volumePanel', 'captionsButton'];
if (video_data.params.quality !== 'dash') buttons.push("qualitySelector")
if (!video_data.params.listen && video_data.params.quality === 'dash') buttons.push('audioTrackButton');
if (video_data.params.listen || video_data.params.quality !== 'dash') buttons.push('qualitySelector');
// Create new control bar object for operation buttons
const ControlBar = videojs.getComponent("controlBar");
const ControlBar = videojs.getComponent('controlBar');
let operations_bar = new ControlBar(player, {
children: [],
playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
});
buttons.slice(1).forEach(child => operations_bar.addChild(child))
buttons.slice(1).forEach(function (child) {operations_bar.addChild(child);});
// Remove operation buttons from primary control bar
primary_control_bar = player.getChild("controlBar");
buttons.forEach(child => primary_control_bar.removeChild(child));
var primary_control_bar = player.getChild('controlBar');
buttons.forEach(function (child) {primary_control_bar.removeChild(child);});
operations_bar_element = operations_bar.el();
operations_bar_element.className += " mobile-operations-bar"
player.addChild(operations_bar)
var operations_bar_element = operations_bar.el();
operations_bar_element.classList.add('mobile-operations-bar');
player.addChild(operations_bar);
// Playback menu doesn't work when it's initialized outside of the primary control bar
playback_element = document.getElementsByClassName("vjs-playback-rate")[0]
operations_bar_element.append(playback_element)
var playback_element = document.getElementsByClassName('vjs-playback-rate')[0];
operations_bar_element.append(playback_element);
// The share and http source selector element can't be fetched till the players ready.
player.one("playing", () => {
share_element = document.getElementsByClassName("vjs-share-control")[0]
operations_bar_element.append(share_element)
player.one('playing', function () {
var share_element = document.getElementsByClassName('vjs-share-control')[0];
operations_bar_element.append(share_element);
if (video_data.params.quality === 'dash') {
http_source_selector = document.getElementsByClassName("vjs-http-source-selector vjs-menu-button")[0]
operations_bar_element.append(http_source_selector)
}
})
if (!video_data.params.listen && video_data.params.quality === 'dash') {
var http_source_selector = document.getElementsByClassName('vjs-http-source-selector vjs-menu-button')[0];
operations_bar_element.append(http_source_selector);
}
});
}
player.on('error', function (event) {
if (player.error().code === 2 || player.error().code === 4) {
setTimeout(function (event) {
console.log('An error occurred in the player, reloading...');
var currentTime = player.currentTime();
var playbackRate = player.playbackRate();
var paused = player.paused();
player.load();
if (currentTime > 0.5) currentTime -= 0.5;
player.currentTime(currentTime);
player.playbackRate(playbackRate);
if (!paused) player.play();
}, 5000);
}
});
// Enable VR video support
if (!video_data.params.listen && video_data.vr && video_data.params.vr_mode) {
player.crossOrigin("anonymous")
player.crossOrigin('anonymous');
switch (video_data.projection_type) {
case "EQUIRECTANGULAR":
player.vr({projection: "equirectangular"});
default: // Should only be "MESH" but we'll use this as a fallback.
player.vr({projection: "EAC"});
case 'EQUIRECTANGULAR':
player.vr({projection: 'equirectangular'});
default: // Should only be 'MESH' but we'll use this as a fallback.
player.vr({projection: 'EAC'});
}
}
@ -200,9 +221,76 @@ if (video_data.params.video_start > 0 || video_data.params.video_end > 0) {
player.volume(video_data.params.volume / 100);
player.playbackRate(video_data.params.speed);
/**
* Method for getting the contents of a cookie
*
* @param {String} name Name of cookie
* @returns {String|null} cookieValue
*/
function getCookieValue(name) {
var cookiePrefix = name + '=';
var matchedCookie = document.cookie.split(';').find(function (item) {return item.includes(cookiePrefix);});
if (matchedCookie)
return matchedCookie.replace(cookiePrefix, '');
return null;
}
/**
* Method for updating the 'PREFS' cookie (or creating it if missing)
*
* @param {number} newVolume New volume defined (null if unchanged)
* @param {number} newSpeed New speed defined (null if unchanged)
*/
function updateCookie(newVolume, newSpeed) {
var volumeValue = newVolume !== null ? newVolume : video_data.params.volume;
var speedValue = newSpeed !== null ? newSpeed : video_data.params.speed;
var cookieValue = getCookieValue('PREFS');
var cookieData;
if (cookieValue !== null) {
var cookieJson = JSON.parse(decodeURIComponent(cookieValue));
cookieJson.volume = volumeValue;
cookieJson.speed = speedValue;
cookieData = encodeURIComponent(JSON.stringify(cookieJson));
} else {
cookieData = encodeURIComponent(JSON.stringify({ 'volume': volumeValue, 'speed': speedValue }));
}
// Set expiration in 2 year
var date = new Date();
date.setFullYear(date.getFullYear() + 2);
var ipRegex = /^((\d+\.){3}\d+|[A-Fa-f0-9]*:[A-Fa-f0-9:]*:[A-Fa-f0-9:]+)$/;
var domainUsed = location.hostname;
// Fix for a bug in FF where the leading dot in the FQDN is not ignored
if (domainUsed.charAt(0) !== '.' && !ipRegex.test(domainUsed) && domainUsed !== 'localhost')
domainUsed = '.' + location.hostname;
var secure = location.protocol.startsWith("https") ? " Secure;" : "";
document.cookie = 'PREFS=' + cookieData + '; SameSite=Lax; path=/; domain=' +
domainUsed + '; expires=' + date.toGMTString() + ';' + secure;
video_data.params.volume = volumeValue;
video_data.params.speed = speedValue;
}
player.on('ratechange', function () {
updateCookie(null, player.playbackRate());
if (isMobile()) {
player.mobileUi({ touchControls: { seekSeconds: 5 * player.playbackRate() } });
}
});
player.on('volumechange', function () {
updateCookie(Math.ceil(player.volume() * 100), null);
});
player.on('waiting', function () {
if (player.playbackRate() > 1 && player.liveTracker.isLive() && player.liveTracker.atLiveEdge()) {
console.log('Player has caught up to source, resetting playbackRate.')
console.info('Player has caught up to source, resetting playbackRate');
player.playbackRate(1);
}
});
@ -213,13 +301,13 @@ if (video_data.premiere_timestamp && Math.round(new Date() / 1000) < video_data.
if (video_data.params.save_player_pos) {
const url = new URL(location);
const hasTimeParam = url.searchParams.has("t");
const remeberedTime = get_video_time();
const hasTimeParam = url.searchParams.has('t');
const rememberedTime = get_video_time();
let lastUpdated = 0;
if(!hasTimeParam) set_seconds_after_start(remeberedTime);
if(!hasTimeParam) set_seconds_after_start(rememberedTime);
const updateTime = () => {
player.on('timeupdate', function () {
const raw = player.currentTime();
const time = Math.floor(raw);
@ -227,9 +315,7 @@ if (video_data.params.save_player_pos) {
save_video_time(time);
lastUpdated = time;
}
};
player.on("timeupdate", updateTime);
});
}
else remove_all_video_times();
@ -239,13 +325,13 @@ if (video_data.params.autoplay) {
player.ready(function () {
new Promise(function (resolve, reject) {
setTimeout(() => resolve(1), 1);
setTimeout(function () {resolve(1);}, 1);
}).then(function (result) {
var promise = player.play();
if (promise !== undefined) {
promise.then(_ => {
}).catch(error => {
promise.then(function () {
}).catch(function (error) {
bpb.show();
});
}
@ -256,67 +342,47 @@ if (video_data.params.autoplay) {
if (!video_data.params.listen && video_data.params.quality === 'dash') {
player.httpSourceSelector();
if (video_data.params.quality_dash != "auto") {
player.ready(() => {
player.on("loadedmetadata", () => {
const qualityLevels = Array.from(player.qualityLevels()).sort((a, b) => a.height - b.height);
if (video_data.params.quality_dash !== 'auto') {
player.ready(function () {
player.on('loadedmetadata', function () {
const qualityLevels = Array.from(player.qualityLevels()).sort(function (a, b) {return a.height - b.height;});
let targetQualityLevel;
switch (video_data.params.quality_dash) {
case "best":
case 'best':
targetQualityLevel = qualityLevels.length - 1;
break;
case "worst":
case 'worst':
targetQualityLevel = 0;
break;
default:
const targetHeight = Number.parseInt(video_data.params.quality_dash, 10);
const targetHeight = parseInt(video_data.params.quality_dash);
for (let i = 0; i < qualityLevels.length; i++) {
if (qualityLevels[i].height <= targetHeight) {
if (qualityLevels[i].height <= targetHeight)
targetQualityLevel = i;
} else {
else
break;
}
}
}
for (let i = 0; i < qualityLevels.length; i++) {
qualityLevels[i].enabled = (i == targetQualityLevel);
}
qualityLevels.forEach(function (level, index) {
level.enabled = (index === targetQualityLevel);
});
});
});
}
}
player.vttThumbnails({
src: location.origin + '/api/v1/storyboards/' + video_data.id + '?height=90',
src: '/api/v1/storyboards/' + video_data.id + '?height=90',
showTimestamp: true
});
// Enable annotations
if (!video_data.params.listen && video_data.params.annotations) {
window.addEventListener('load', function (e) {
var video_container = document.getElementById('player');
let xhr = new XMLHttpRequest();
xhr.responseType = 'text';
xhr.timeout = 60000;
xhr.open('GET', '/api/v1/annotations/' + video_data.id, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
videojs.registerPlugin('youtubeAnnotationsPlugin', youtubeAnnotationsPlugin);
if (!player.paused()) {
player.youtubeAnnotationsPlugin({ annotationXml: xhr.response, videoContainer: video_container });
} else {
player.one('play', function (event) {
player.youtubeAnnotationsPlugin({ annotationXml: xhr.response, videoContainer: video_container });
});
}
}
}
}
window.addEventListener('__ar_annotation_click', e => {
const { url, target, seconds } = e.detail;
addEventListener('load', function (e) {
addEventListener('__ar_annotation_click', function (e) {
const url = e.detail.url,
target = e.detail.target,
seconds = e.detail.seconds;
var path = new URL(url);
if (path.href.startsWith('https://www.youtube.com/watch?') && seconds) {
@ -326,41 +392,48 @@ if (!video_data.params.listen && video_data.params.annotations) {
path = path.pathname + path.search;
if (target === 'current') {
window.location.href = path;
location.href = path;
} else if (target === 'new') {
window.open(path, '_blank');
open(path, '_blank');
}
});
helpers.xhr('GET', '/api/v1/annotations/' + video_data.id, {
responseType: 'text',
timeout: 60000
}, {
on200: function (response) {
var video_container = document.getElementById('player');
videojs.registerPlugin('youtubeAnnotationsPlugin', youtubeAnnotationsPlugin);
if (player.paused()) {
player.one('play', function (event) {
player.youtubeAnnotationsPlugin({ annotationXml: response, videoContainer: video_container });
});
} else {
player.youtubeAnnotationsPlugin({ annotationXml: response, videoContainer: video_container });
}
}
});
xhr.send();
});
}
function increase_volume(delta) {
function change_volume(delta) {
const curVolume = player.volume();
let newVolume = curVolume + delta;
if (newVolume > 1) {
newVolume = 1;
} else if (newVolume < 0) {
newVolume = 0;
}
newVolume = helpers.clamp(newVolume, 0, 1);
player.volume(newVolume);
}
function toggle_muted() {
const isMuted = player.muted();
player.muted(!isMuted);
player.muted(!player.muted());
}
function skip_seconds(delta) {
const duration = player.duration();
const curTime = player.currentTime();
let newTime = curTime + delta;
if (newTime > duration) {
newTime = duration;
} else if (newTime < 0) {
newTime = 0;
}
newTime = helpers.clamp(newTime, 0, duration);
player.currentTime(newTime);
}
@ -370,57 +443,21 @@ function set_seconds_after_start(delta) {
}
function save_video_time(seconds) {
const videoId = video_data.id;
const all_video_times = get_all_video_times();
all_video_times[videoId] = seconds;
set_all_video_times(all_video_times);
all_video_times[video_data.id] = seconds;
helpers.storage.set(save_player_pos_key, all_video_times);
}
function get_video_time() {
try {
const videoId = video_data.id;
const all_video_times = get_all_video_times();
const timestamp = all_video_times[videoId];
return timestamp || 0;
}
catch {
return 0;
}
}
function set_all_video_times(times) {
if (storage) {
if (times) {
try {
storage.setItem(save_player_pos_key, JSON.stringify(times));
} catch (e) {
console.debug('set_all_video_times: ' + e);
}
} else {
storage.removeItem(save_player_pos_key);
}
}
return get_all_video_times()[video_data.id] || 0;
}
function get_all_video_times() {
if (storage) {
const raw = storage.getItem(save_player_pos_key);
if (raw !== null) {
try {
return JSON.parse(raw);
} catch (e) {
console.debug('get_all_video_times: ' + e);
}
}
}
return {};
return helpers.storage.get(save_player_pos_key) || {};
}
function remove_all_video_times() {
set_all_video_times(null);
helpers.storage.remove(save_player_pos_key);
}
function set_time_percent(percent) {
@ -436,21 +473,23 @@ function toggle_play() { player.paused() ? play() : pause(); }
const toggle_captions = (function () {
let toggledTrack = null;
const onChange = function (e) {
toggledTrack = null;
};
const bindChange = function (onOrOff) {
player.textTracks()[onOrOff]('change', onChange);
};
function bindChange(onOrOff) {
player.textTracks()[onOrOff]('change', function (e) {
toggledTrack = null;
});
}
// Wrapper function to ignore our own emitted events and only listen
// to events emitted by Video.js on click on the captions menu items.
const setMode = function (track, mode) {
function setMode(track, mode) {
bindChange('off');
track.mode = mode;
window.setTimeout(function () {
setTimeout(function () {
bindChange('on');
}, 0);
};
}
bindChange('on');
return function () {
if (toggledTrack !== null) {
@ -498,15 +537,11 @@ function increase_playback_rate(steps) {
const maxIndex = options.playbackRates.length - 1;
const curIndex = options.playbackRates.indexOf(player.playbackRate());
let newIndex = curIndex + steps;
if (newIndex > maxIndex) {
newIndex = maxIndex;
} else if (newIndex < 0) {
newIndex = 0;
}
newIndex = helpers.clamp(newIndex, 0, maxIndex);
player.playbackRate(options.playbackRates[newIndex]);
}
window.addEventListener('keydown', e => {
addEventListener('keydown', function (e) {
if (e.target.tagName.toLowerCase() === 'input') {
// Ignore input when focus is on certain elements, e.g. form fields.
return;
@ -539,10 +574,10 @@ window.addEventListener('keydown', e => {
case 'MediaStop': action = stop; break;
case 'ArrowUp':
if (isPlayerFocused) action = increase_volume.bind(this, 0.1);
if (isPlayerFocused) action = change_volume.bind(this, 0.1);
break;
case 'ArrowDown':
if (isPlayerFocused) action = increase_volume.bind(this, -0.1);
if (isPlayerFocused) action = change_volume.bind(this, -0.1);
break;
case 'm':
@ -593,12 +628,11 @@ window.addEventListener('keydown', e => {
// TODO: Add support to play back previous video.
break;
case '.':
// TODO: Add support for next-frame-stepping.
break;
case ',':
// TODO: Add support for previous-frame-stepping.
break;
// TODO: More precise step. Now FPS is taken equal to 29.97
// Common FPS: https://forum.videohelp.com/threads/81868#post323588
// Possible solution is new HTMLVideoElement.requestVideoFrameCallback() https://wicg.github.io/video-rvfc/
case ',': action = function () { pause(); skip_seconds(-1/29.97); }; break;
case '.': action = function () { pause(); skip_seconds( 1/29.97); }; break;
case '>': action = increase_playback_rate.bind(this, 1); break;
case '<': action = increase_playback_rate.bind(this, -1); break;
@ -617,84 +651,77 @@ window.addEventListener('keydown', e => {
// Add support for controlling the player volume by scrolling over it. Adapted from
// https://github.com/ctd1500/videojs-hotkeys/blob/bb4a158b2e214ccab87c2e7b95f42bc45c6bfd87/videojs.hotkeys.js#L292-L328
(function () {
const volumeStep = 0.05;
const enableVolumeScroll = true;
const enableHoverScroll = true;
const doc = document;
const pEl = document.getElementById('player');
var volumeHover = false;
var volumeSelector = pEl.querySelector('.vjs-volume-menu-button') || pEl.querySelector('.vjs-volume-panel');
if (volumeSelector != null) {
if (volumeSelector !== null) {
volumeSelector.onmouseover = function () { volumeHover = true; };
volumeSelector.onmouseout = function () { volumeHover = false; };
}
var mouseScroll = function mouseScroll(event) {
var activeEl = doc.activeElement;
if (enableHoverScroll) {
// If we leave this undefined then it can match non-existent elements below
activeEl = 0;
}
function mouseScroll(event) {
// When controls are disabled, hotkeys will be disabled as well
if (player.controls()) {
if (volumeHover) {
if (enableVolumeScroll) {
event = window.event || event;
var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
event.preventDefault();
if (!player.controls() || !volumeHover) return;
if (delta == 1) {
increase_volume(volumeStep);
} else if (delta == -1) {
increase_volume(-volumeStep);
}
}
}
}
};
event.preventDefault();
var wheelMove = event.wheelDelta || -event.detail;
var volumeSign = Math.sign(wheelMove);
change_volume(volumeSign * 0.05); // decrease/increase by 5%
}
player.on('mousewheel', mouseScroll);
player.on("DOMMouseScroll", mouseScroll);
player.on('DOMMouseScroll', mouseScroll);
}());
// Since videojs-share can sometimes be blocked, we defer it until last
if (player.share) {
player.share(shareOptions);
}
if (player.share) player.share(shareOptions);
// show the preferred caption by default
if (player_data.preferred_caption_found) {
player.ready(() => {
player.textTracks()[1].mode = 'showing';
player.ready(function () {
if (!video_data.params.listen && video_data.params.quality === 'dash') {
// play.textTracks()[0] on DASH mode is showing some debug messages
player.textTracks()[1].mode = 'showing';
} else {
player.textTracks()[0].mode = 'showing';
}
});
}
// Safari audio double duration fix
if (navigator.vendor == "Apple Computer, Inc." && video_data.params.listen) {
if (navigator.vendor === 'Apple Computer, Inc.' && video_data.params.listen) {
player.on('loadedmetadata', function () {
player.on('timeupdate', function () {
if (player.remainingTime() < player.duration() / 2) {
player.currentTime(player.duration() + 1);
if (player.remainingTime() < player.duration() / 2 && player.remainingTime() >= 2) {
player.currentTime(player.duration() - 1);
}
});
});
}
// Watch on Invidious link
if (window.location.pathname.startsWith("/embed/")) {
if (location.pathname.startsWith('/embed/')) {
const Button = videojs.getComponent('Button');
let watch_on_invidious_button = new Button(player);
// Create hyperlink for current instance
redirect_element = document.createElement("a");
redirect_element.setAttribute("href", `http://${window.location.host}/watch?v=${window.location.pathname.replace("/embed/","")}`)
redirect_element.appendChild(document.createTextNode("Invidious"))
var redirect_element = document.createElement('a');
redirect_element.setAttribute('href', location.pathname.replace('/embed/', '/watch?v='));
redirect_element.appendChild(document.createTextNode('Invidious'));
watch_on_invidious_button.el().appendChild(redirect_element)
watch_on_invidious_button.addClass("watch-on-invidious")
watch_on_invidious_button.el().appendChild(redirect_element);
watch_on_invidious_button.addClass('watch-on-invidious');
cb = player.getChild('ControlBar')
cb.addChild(watch_on_invidious_button)
};
var cb = player.getChild('ControlBar');
cb.addChild(watch_on_invidious_button);
}
addEventListener('DOMContentLoaded', function () {
// Save time during redirection on another instance
const changeInstanceLink = document.querySelector('#watch-on-another-invidious-instance > a');
if (changeInstanceLink) changeInstanceLink.addEventListener('click', function () {
changeInstanceLink.href = addCurrentTimeToURL(changeInstanceLink.href);
});
});

View File

@ -1,4 +1,6 @@
var playlist_data = JSON.parse(document.getElementById('playlist_data').innerHTML);
'use strict';
var playlist_data = JSON.parse(document.getElementById('playlist_data').textContent);
var payload = 'csrf_token=' + playlist_data.csrf_token;
function add_playlist_video(target) {
var select = target.parentNode.children[0].children[1];
@ -7,21 +9,12 @@ function add_playlist_video(target) {
var url = '/playlist_ajax?action_add_video=1&redirect=false' +
'&video_id=' + target.getAttribute('data-id') +
'&playlist_id=' + option.getAttribute('data-plid');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
option.innerText = '✓' + option.innerText;
}
helpers.xhr('POST', url, {payload: payload}, {
on200: function (response) {
option.textContent = '✓' + option.textContent;
}
}
xhr.send('csrf_token=' + playlist_data.csrf_token);
});
}
function add_playlist_item(target) {
@ -31,21 +24,12 @@ function add_playlist_item(target) {
var url = '/playlist_ajax?action_add_video=1&redirect=false' +
'&video_id=' + target.getAttribute('data-id') +
'&playlist_id=' + target.getAttribute('data-plid');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
tile.style.display = '';
}
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
tile.style.display = '';
}
}
xhr.send('csrf_token=' + playlist_data.csrf_token);
});
}
function remove_playlist_item(target) {
@ -55,19 +39,10 @@ function remove_playlist_item(target) {
var url = '/playlist_ajax?action_remove_video=1&redirect=false' +
'&set_video_id=' + target.getAttribute('data-index') +
'&playlist_id=' + target.getAttribute('data-plid');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
tile.style.display = '';
}
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
tile.style.display = '';
}
}
xhr.send('csrf_token=' + playlist_data.csrf_token);
}
});
}

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,9 @@
var subscribe_data = JSON.parse(document.getElementById('subscribe_data').innerHTML);
'use strict';
var subscribe_data = JSON.parse(document.getElementById('subscribe_data').textContent);
var payload = 'csrf_token=' + subscribe_data.csrf_token;
var subscribe_button = document.getElementById('subscribe');
subscribe_button.parentNode['action'] = 'javascript:void(0)';
subscribe_button.parentNode.action = 'javascript:void(0)';
if (subscribe_button.getAttribute('data-type') === 'subscribe') {
subscribe_button.onclick = subscribe;
@ -9,82 +11,34 @@ if (subscribe_button.getAttribute('data-type') === 'subscribe') {
subscribe_button.onclick = unsubscribe;
}
function subscribe(retries = 5) {
if (retries <= 0) {
console.log('Failed to subscribe.');
return;
}
var url = '/subscription_ajax?action_create_subscription_to_channel=1&redirect=false' +
'&c=' + subscribe_data.ucid;
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
function subscribe() {
var fallback = subscribe_button.innerHTML;
subscribe_button.onclick = unsubscribe;
subscribe_button.innerHTML = '<b>' + subscribe_data.unsubscribe_text + ' | ' + subscribe_data.sub_count_text + '</b>';
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
subscribe_button.onclick = subscribe;
subscribe_button.innerHTML = fallback;
}
var url = '/subscription_ajax?action_create_subscription_to_channel=1&redirect=false' +
'&c=' + subscribe_data.ucid;
helpers.xhr('POST', url, {payload: payload, retries: 5, entity_name: 'subscribe request'}, {
onNon200: function (xhr) {
subscribe_button.onclick = subscribe;
subscribe_button.innerHTML = fallback;
}
}
xhr.onerror = function () {
console.log('Subscribing failed... ' + retries + '/5');
setTimeout(function () { subscribe(retries - 1) }, 1000);
}
xhr.ontimeout = function () {
console.log('Subscribing failed... ' + retries + '/5');
subscribe(retries - 1);
}
xhr.send('csrf_token=' + subscribe_data.csrf_token);
});
}
function unsubscribe(retries = 5) {
if (retries <= 0) {
console.log('Failed to subscribe');
return;
}
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
'&c=' + subscribe_data.ucid;
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
function unsubscribe() {
var fallback = subscribe_button.innerHTML;
subscribe_button.onclick = subscribe;
subscribe_button.innerHTML = '<b>' + subscribe_data.subscribe_text + ' | ' + subscribe_data.sub_count_text + '</b>';
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
subscribe_button.onclick = unsubscribe;
subscribe_button.innerHTML = fallback;
}
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
'&c=' + subscribe_data.ucid;
helpers.xhr('POST', url, {payload: payload, retries: 5, entity_name: 'unsubscribe request'}, {
onNon200: function (xhr) {
subscribe_button.onclick = unsubscribe;
subscribe_button.innerHTML = fallback;
}
}
xhr.onerror = function () {
console.log('Unsubscribing failed... ' + retries + '/5');
setTimeout(function () { unsubscribe(retries - 1) }, 1000);
}
xhr.ontimeout = function () {
console.log('Unsubscribing failed... ' + retries + '/5');
unsubscribe(retries - 1);
}
xhr.send('csrf_token=' + subscribe_data.csrf_token);
});
}

View File

@ -1,91 +1,44 @@
'use strict';
var toggle_theme = document.getElementById('toggle_theme');
toggle_theme.href = 'javascript:void(0);';
toggle_theme.href = 'javascript:void(0)';
const STORAGE_KEY_THEME = 'dark_mode';
const THEME_DARK = 'dark';
const THEME_LIGHT = 'light';
// TODO: theme state controlled by system
toggle_theme.addEventListener('click', function () {
var dark_mode = document.body.classList.contains("light-theme");
var url = '/toggle_theme?redirect=false';
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', url, true);
set_mode(dark_mode);
try {
window.localStorage.setItem('dark_mode', dark_mode ? 'dark' : 'light');
} catch {}
xhr.send();
const isDarkTheme = helpers.storage.get(STORAGE_KEY_THEME) === THEME_DARK;
const newTheme = isDarkTheme ? THEME_LIGHT : THEME_DARK;
setTheme(newTheme);
helpers.storage.set(STORAGE_KEY_THEME, newTheme);
helpers.xhr('GET', '/toggle_theme?redirect=false', {}, {});
});
window.addEventListener('storage', function (e) {
if (e.key === 'dark_mode') {
update_mode(e.newValue);
}
});
window.addEventListener('DOMContentLoaded', function () {
const dark_mode = document.getElementById('dark_mode_pref').textContent;
try {
// Update localStorage if dark mode preference changed on preferences page
window.localStorage.setItem('dark_mode', dark_mode);
} catch {}
update_mode(dark_mode);
});
var darkScheme = window.matchMedia('(prefers-color-scheme: dark)');
var lightScheme = window.matchMedia('(prefers-color-scheme: light)');
darkScheme.addListener(scheme_switch);
lightScheme.addListener(scheme_switch);
function scheme_switch (e) {
// ignore this method if we have a preference set
try {
if (localStorage.getItem('dark_mode')) {
return;
}
} catch {}
if (e.matches) {
if (e.media.includes("dark")) {
set_mode(true);
} else if (e.media.includes("light")) {
set_mode(false);
}
}
}
function set_mode (bool) {
if (bool) {
// dark
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-sunny');
document.body.classList.remove('no-theme');
document.body.classList.remove('light-theme');
document.body.classList.add('dark-theme');
/** @param {THEME_DARK|THEME_LIGHT} theme */
function setTheme(theme) {
// By default body element has .no-theme class that uses OS theme via CSS @media rules
// It rewrites using hard className below
if (theme === THEME_DARK) {
toggle_theme.children[0].className = 'icon ion-ios-sunny';
document.body.className = 'dark-theme';
} else {
// light
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-moon');
document.body.classList.remove('no-theme');
document.body.classList.remove('dark-theme');
document.body.classList.add('light-theme');
toggle_theme.children[0].className = 'icon ion-ios-moon';
document.body.className = 'light-theme';
}
}
function update_mode (mode) {
if (mode === 'true' /* for backwards compatibility */ || mode === 'dark') {
// If preference for dark mode indicated
set_mode(true);
}
else if (mode === 'false' /* for backwards compatibility */ || mode === 'light') {
// If preference for light mode indicated
set_mode(false);
}
else if (document.getElementById('dark_mode_pref').textContent === '' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
// If no preference indicated here and no preference indicated on the preferences page (backend), but the browser tells us that the operating system has a dark theme
set_mode(true);
}
// else do nothing, falling back to the mode defined by the `dark_mode` preference on the preferences page (backend)
}
// Handles theme change event caused by other tab
addEventListener('storage', function (e) {
if (e.key === STORAGE_KEY_THEME)
setTheme(helpers.storage.get(STORAGE_KEY_THEME));
});
// Set theme from preferences on page load
addEventListener('DOMContentLoaded', function () {
const prefTheme = document.getElementById('dark_mode_pref').textContent;
if (prefTheme) {
setTheme(prefTheme);
helpers.storage.set(STORAGE_KEY_THEME, prefTheme);
}
});

View File

@ -1,32 +1,35 @@
var video_data = JSON.parse(document.getElementById('video_data').innerHTML);
'use strict';
var video_data = JSON.parse(document.getElementById('video_data').textContent);
var spinnerHTML = '<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
var spinnerHTMLwithHR = spinnerHTML + '<hr>';
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g, function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
});
}
};
function toggle_parent(target) {
body = target.parentNode.parentNode.children[1];
if (body.style.display === null || body.style.display === '') {
target.innerHTML = '[ + ]';
body.style.display = 'none';
} else {
target.innerHTML = '[ - ]';
var body = target.parentNode.parentNode.children[1];
if (body.style.display === 'none') {
target.textContent = '[ ]';
body.style.display = '';
} else {
target.textContent = '[ + ]';
body.style.display = 'none';
}
}
function toggle_comments(event) {
var target = event.target;
body = target.parentNode.parentNode.parentNode.children[1];
if (body.style.display === null || body.style.display === '') {
target.innerHTML = '[ + ]';
body.style.display = 'none';
} else {
target.innerHTML = '[ - ]';
var body = target.parentNode.parentNode.parentNode.children[1];
if (body.style.display === 'none') {
target.textContent = '[ ]';
body.style.display = '';
} else {
target.textContent = '[ + ]';
body.style.display = 'none';
}
}
@ -43,13 +46,13 @@ function swap_comments(event) {
function hide_youtube_replies(event) {
var target = event.target;
sub_text = target.getAttribute('data-inner-text');
inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
body = target.parentNode.parentNode.children[1];
var body = target.parentNode.parentNode.children[1];
body.style.display = 'none';
target.innerHTML = sub_text;
target.textContent = sub_text;
target.onclick = show_youtube_replies;
target.setAttribute('data-inner-text', inner_text);
target.setAttribute('data-sub-text', sub_text);
@ -58,13 +61,13 @@ function hide_youtube_replies(event) {
function show_youtube_replies(event) {
var target = event.target;
sub_text = target.getAttribute('data-inner-text');
inner_text = target.getAttribute('data-sub-text');
var sub_text = target.getAttribute('data-inner-text');
var inner_text = target.getAttribute('data-sub-text');
body = target.parentNode.parentNode.children[1];
var body = target.parentNode.parentNode.children[1];
body.style.display = '';
target.innerHTML = sub_text;
target.textContent = sub_text;
target.onclick = hide_youtube_replies;
target.setAttribute('data-inner-text', inner_text);
target.setAttribute('data-sub-text', sub_text);
@ -78,287 +81,186 @@ if (continue_button) {
function next_video() {
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
}
if (video_data.params.listen !== video_data.preferences.listen) {
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
}
if (video_data.params.speed !== video_data.preferences.speed) {
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
}
if (video_data.params.local !== video_data.preferences.local) {
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
}
url.searchParams.set('continue', '1');
location.assign(url.pathname + url.search);
}
function continue_autoplay(event) {
if (event.target.checked) {
player.on('ended', function () {
next_video();
});
player.on('ended', next_video);
} else {
player.off('ended');
}
}
function number_with_separator(val) {
while (/(\d+)(\d{3})/.test(val.toString())) {
val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
}
return val;
}
function get_playlist(plid) {
var playlist = document.getElementById('playlist');
function get_playlist(plid, retries) {
if (retries == undefined) retries = 5;
playlist = document.getElementById('playlist');
if (retries <= 0) {
console.log('Failed to pull playlist');
playlist.innerHTML = '';
return;
}
playlist.innerHTML = ' \
<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3> \
<hr>'
playlist.innerHTML = spinnerHTMLwithHR;
var plid_url;
if (plid.startsWith('RD')) {
var plid_url = '/api/v1/mixes/' + plid +
plid_url = '/api/v1/mixes/' + plid +
'?continuation=' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
} else {
var plid_url = '/api/v1/playlists/' + plid +
plid_url = '/api/v1/playlists/' + plid +
'?index=' + video_data.index +
'&continuation=' + video_data.id +
'&format=html&hl=' + video_data.preferences.locale;
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', plid_url, true);
helpers.xhr('GET', plid_url, {retries: 5, entity_name: 'playlist'}, {
on200: function (response) {
playlist.innerHTML = response.playlistHtml;
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
playlist.innerHTML = xhr.response.playlistHtml;
var nextVideo = document.getElementById(xhr.response.nextVideo);
nextVideo.parentNode.parentNode.scrollTop = nextVideo.offsetTop;
if (!response.nextVideo) return;
if (xhr.response.nextVideo) {
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + xhr.response.nextVideo);
var nextVideo = document.getElementById(response.nextVideo);
nextVideo.parentNode.parentNode.scrollTop = nextVideo.offsetTop;
url.searchParams.set('list', plid);
if (!plid.startsWith('RD')) {
url.searchParams.set('index', xhr.response.index);
}
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + response.nextVideo);
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
url.searchParams.set('autoplay', '1');
}
url.searchParams.set('list', plid);
if (!plid.startsWith('RD'))
url.searchParams.set('index', response.index);
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
if (video_data.params.listen !== video_data.preferences.listen) {
url.searchParams.set('listen', video_data.params.listen);
}
if (video_data.params.speed !== video_data.preferences.speed) {
url.searchParams.set('speed', video_data.params.speed);
}
if (video_data.params.local !== video_data.preferences.local) {
url.searchParams.set('local', video_data.params.local);
}
location.assign(url.pathname + url.search);
});
}
} else {
playlist.innerHTML = '';
document.getElementById('continue').style.display = '';
}
location.assign(url.pathname + url.search);
});
},
onNon200: function (xhr) {
playlist.innerHTML = '';
document.getElementById('continue').style.display = '';
},
onError: function (xhr) {
playlist.innerHTML = spinnerHTMLwithHR;
},
onTimeout: function (xhr) {
playlist.innerHTML = spinnerHTMLwithHR;
}
}
xhr.onerror = function () {
playlist = document.getElementById('playlist');
playlist.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3><hr>';
console.log('Pulling playlist timed out... ' + retries + '/5');
setTimeout(function () { get_playlist(plid, retries - 1) }, 1000);
}
xhr.ontimeout = function () {
playlist = document.getElementById('playlist');
playlist.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3><hr>';
console.log('Pulling playlist timed out... ' + retries + '/5');
get_playlist(plid, retries - 1);
}
xhr.send();
});
}
function get_reddit_comments(retries) {
if (retries == undefined) retries = 5;
comments = document.getElementById('comments');
if (retries <= 0) {
console.log('Failed to pull comments');
comments.innerHTML = '';
return;
}
function get_reddit_comments() {
var comments = document.getElementById('comments');
var fallback = comments.innerHTML;
comments.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
comments.innerHTML = spinnerHTML;
var url = '/api/v1/comments/' + video_data.id +
'?source=reddit&format=html' +
'&hl=' + video_data.preferences.locale;
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
comments.innerHTML = ' \
<div> \
<h3> \
<a href="javascript:void(0)">[ - ]</a> \
{title} \
</h3> \
<p> \
<b> \
<a href="javascript:void(0)" data-comments="youtube"> \
{youtubeCommentsText} \
</a> \
</b> \
</p> \
var onNon200 = function (xhr) { comments.innerHTML = fallback; };
if (video_data.params.comments[1] === 'youtube')
onNon200 = function (xhr) {};
helpers.xhr('GET', url, {retries: 5, entity_name: ''}, {
on200: function (response) {
comments.innerHTML = ' \
<div> \
<h3> \
<a href="javascript:void(0)">[ ]</a> \
{title} \
</h3> \
<p> \
<b> \
<a rel="noopener" target="_blank" href="https://reddit.com{permalink}">{redditPermalinkText}</a> \
<a href="javascript:void(0)" data-comments="youtube"> \
{youtubeCommentsText} \
</a> \
</b> \
</div> \
<div>{contentHtml}</div> \
<hr>'.supplant({
title: xhr.response.title,
youtubeCommentsText: video_data.youtube_comments_text,
redditPermalinkText: video_data.reddit_permalink_text,
permalink: xhr.response.permalink,
contentHtml: xhr.response.contentHtml
});
</p> \
<b> \
<a rel="noopener" target="_blank" href="https://reddit.com{permalink}">{redditPermalinkText}</a> \
</b> \
</div> \
<div>{contentHtml}</div> \
<hr>'.supplant({
title: response.title,
youtubeCommentsText: video_data.youtube_comments_text,
redditPermalinkText: video_data.reddit_permalink_text,
permalink: response.permalink,
contentHtml: response.contentHtml
});
comments.children[0].children[0].children[0].onclick = toggle_comments;
comments.children[0].children[1].children[0].onclick = swap_comments;
} else {
if (video_data.params.comments[1] === 'youtube') {
console.log('Pulling comments failed... ' + retries + '/5');
setTimeout(function () { get_youtube_comments(retries - 1) }, 1000);
} else {
comments.innerHTML = fallback;
}
}
}
}
xhr.onerror = function () {
console.log('Pulling comments failed... ' + retries + '/5');
setTimeout(function () { get_reddit_comments(retries - 1) }, 1000);
}
xhr.ontimeout = function () {
console.log('Pulling comments failed... ' + retries + '/5');
get_reddit_comments(retries - 1);
}
xhr.send();
comments.children[0].children[0].children[0].onclick = toggle_comments;
comments.children[0].children[1].children[0].onclick = swap_comments;
},
onNon200: onNon200, // declared above
});
}
function get_youtube_comments(retries) {
if (retries == undefined) retries = 5;
comments = document.getElementById('comments');
if (retries <= 0) {
console.log('Failed to pull comments');
comments.innerHTML = '';
return;
}
function get_youtube_comments() {
var comments = document.getElementById('comments');
var fallback = comments.innerHTML;
comments.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
comments.innerHTML = spinnerHTML;
var url = '/api/v1/comments/' + video_data.id +
'?format=html' +
'&hl=' + video_data.preferences.locale +
'&thin_mode=' + video_data.preferences.thin_mode;
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
comments.innerHTML = ' \
<div> \
<h3> \
<a href="javascript:void(0)">[ - ]</a> \
{commentsText} \
</h3> \
<b> \
<a href="javascript:void(0)" data-comments="reddit"> \
{redditComments} \
</a> \
</b> \
</div> \
<div>{contentHtml}</div> \
<hr>'.supplant({
contentHtml: xhr.response.contentHtml,
redditComments: video_data.reddit_comments_text,
commentsText: video_data.comments_text.supplant(
{ commentCount: number_with_separator(xhr.response.commentCount) }
)
});
var onNon200 = function (xhr) { comments.innerHTML = fallback; };
if (video_data.params.comments[1] === 'youtube')
onNon200 = function (xhr) {};
comments.children[0].children[0].children[0].onclick = toggle_comments;
comments.children[0].children[1].children[0].onclick = swap_comments;
} else {
if (video_data.params.comments[1] === 'youtube') {
setTimeout(function () { get_youtube_comments(retries - 1) }, 1000);
} else {
comments.innerHTML = '';
}
}
helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
on200: function (response) {
comments.innerHTML = ' \
<div> \
<h3> \
<a href="javascript:void(0)">[ ]</a> \
{commentsText} \
</h3> \
<b> \
<a href="javascript:void(0)" data-comments="reddit"> \
{redditComments} \
</a> \
</b> \
</div> \
<div>{contentHtml}</div> \
<hr>'.supplant({
contentHtml: response.contentHtml,
redditComments: video_data.reddit_comments_text,
commentsText: video_data.comments_text.supplant({
// toLocaleString correctly splits number with local thousands separator. e.g.:
// '1,234,567.89' for user with English locale
// '1 234 567,89' for user with Russian locale
// '1.234.567,89' for user with Portuguese locale
commentCount: response.commentCount.toLocaleString()
})
});
comments.children[0].children[0].children[0].onclick = toggle_comments;
comments.children[0].children[1].children[0].onclick = swap_comments;
},
onNon200: onNon200, // declared above
onError: function (xhr) {
comments.innerHTML = spinnerHTML;
},
onTimeout: function (xhr) {
comments.innerHTML = spinnerHTML;
}
}
xhr.onerror = function () {
comments.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
console.log('Pulling comments failed... ' + retries + '/5');
setTimeout(function () { get_youtube_comments(retries - 1) }, 1000);
}
xhr.ontimeout = function () {
comments.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
console.log('Pulling comments failed... ' + retries + '/5');
get_youtube_comments(retries - 1);
}
xhr.send();
});
}
function get_youtube_replies(target, load_more, load_replies) {
@ -366,91 +268,72 @@ function get_youtube_replies(target, load_more, load_replies) {
var body = target.parentNode.parentNode;
var fallback = body.innerHTML;
body.innerHTML =
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
body.innerHTML = spinnerHTML;
var url = '/api/v1/comments/' + video_data.id +
'?format=html' +
'&hl=' + video_data.preferences.locale +
'&thin_mode=' + video_data.preferences.thin_mode +
'&continuation=' + continuation
if (load_replies) {
url += '&action=action_get_comment_replies';
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('GET', url, true);
'&continuation=' + continuation;
if (load_replies) url += '&action=action_get_comment_replies';
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
if (load_more) {
body = body.parentNode.parentNode;
body.removeChild(body.lastElementChild);
body.innerHTML += xhr.response.contentHtml;
} else {
body.removeChild(body.lastElementChild);
var p = document.createElement('p');
var a = document.createElement('a');
p.appendChild(a);
a.href = 'javascript:void(0)';
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', video_data.hide_replies_text);
a.setAttribute('data-inner-text', video_data.show_replies_text);
a.innerText = video_data.hide_replies_text;
var div = document.createElement('div');
div.innerHTML = xhr.response.contentHtml;
body.appendChild(p);
body.appendChild(div);
}
helpers.xhr('GET', url, {}, {
on200: function (response) {
if (load_more) {
body = body.parentNode.parentNode;
body.removeChild(body.lastElementChild);
body.innerHTML += response.contentHtml;
} else {
body.innerHTML = fallback;
body.removeChild(body.lastElementChild);
var p = document.createElement('p');
var a = document.createElement('a');
p.appendChild(a);
a.href = 'javascript:void(0)';
a.onclick = hide_youtube_replies;
a.setAttribute('data-sub-text', video_data.hide_replies_text);
a.setAttribute('data-inner-text', video_data.show_replies_text);
a.textContent = video_data.hide_replies_text;
var div = document.createElement('div');
div.innerHTML = response.contentHtml;
body.appendChild(p);
body.appendChild(div);
}
},
onNon200: function (xhr) {
body.innerHTML = fallback;
},
onTimeout: function (xhr) {
console.warn('Pulling comments failed');
body.innerHTML = fallback;
}
}
xhr.ontimeout = function () {
console.log('Pulling comments failed.');
body.innerHTML = fallback;
}
xhr.send();
});
}
if (video_data.play_next) {
player.on('ended', function () {
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
if (video_data.params.autoplay || video_data.params.continue_autoplay)
url.searchParams.set('autoplay', '1');
}
if (video_data.params.listen !== video_data.preferences.listen) {
if (video_data.params.listen !== video_data.preferences.listen)
url.searchParams.set('listen', video_data.params.listen);
}
if (video_data.params.speed !== video_data.preferences.speed) {
if (video_data.params.speed !== video_data.preferences.speed)
url.searchParams.set('speed', video_data.params.speed);
}
if (video_data.params.local !== video_data.preferences.local) {
if (video_data.params.local !== video_data.preferences.local)
url.searchParams.set('local', video_data.params.local);
}
url.searchParams.set('continue', '1');
location.assign(url.pathname + url.search);
});
}
window.addEventListener('load', function (e) {
if (video_data.plid) {
addEventListener('load', function (e) {
if (video_data.plid)
get_playlist(video_data.plid);
}
if (video_data.params.comments[0] === 'youtube') {
get_youtube_comments();
@ -461,7 +344,7 @@ window.addEventListener('load', function (e) {
} else if (video_data.params.comments[1] === 'reddit') {
get_reddit_comments();
} else {
comments = document.getElementById('comments');
var comments = document.getElementById('comments');
comments.innerHTML = '';
}
});

View File

@ -1,4 +1,6 @@
var watched_data = JSON.parse(document.getElementById('watched_data').innerHTML);
'use strict';
var watched_data = JSON.parse(document.getElementById('watched_data').textContent);
var payload = 'csrf_token=' + watched_data.csrf_token;
function mark_watched(target) {
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
@ -6,45 +8,27 @@ function mark_watched(target) {
var url = '/watch_ajax?action_mark_watched=1&redirect=false' +
'&id=' + target.getAttribute('data-id');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
tile.style.display = '';
}
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
tile.style.display = '';
}
}
xhr.send('csrf_token=' + watched_data.csrf_token);
});
}
function mark_unwatched(target) {
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
tile.style.display = 'none';
var count = document.getElementById('count')
count.innerText = count.innerText - 1;
var count = document.getElementById('count');
count.textContent--;
var url = '/watch_ajax?action_mark_unwatched=1&redirect=false' +
'&id=' + target.getAttribute('data-id');
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status != 200) {
count.innerText = count.innerText - 1 + 2;
tile.style.display = '';
}
helpers.xhr('POST', url, {payload: payload}, {
onNon200: function (xhr) {
count.textContent++;
tile.style.display = '';
}
}
xhr.send('csrf_token=' + watched_data.csrf_token);
}
});
}

View File

@ -349,13 +349,16 @@ feed_threads: 1
## Enable/Disable the polling job that keeps the decryption
## function (for "secured" videos) up to date.
##
## Note: This part of the code is currently broken, so changing
## Note: This part of the code generate a small amount of data every minute.
## This may not be desired if you have bandwidth limits set by your ISP.
##
## Note 2: This part of the code is currently broken, so changing
## this setting has no impact.
##
## Accepted values: true, false
## Default: true
## Default: false
##
#decrypt_polling: true
#decrypt_polling: false
# -----------------------------

View File

@ -2,7 +2,7 @@
# Using it will build an image from the locally cloned repository.
#
# If you want to use Invidious in production, see the docker-compose.yml file provided
# in the installation documentation: https://docs.invidious.io/Installation.md
# in the installation documentation: https://docs.invidious.io/installation/
version: "3"
services:
@ -39,7 +39,7 @@ services:
- invidious-db
invidious-db:
image: docker.io/library/postgres:14
image: docker.io/library/postgres:13
restart: unless-stopped
volumes:
- postgresdata:/var/lib/postgresql/data

View File

@ -1,4 +1,4 @@
FROM crystallang/crystal:1.2.2-alpine AS builder
FROM crystallang/crystal:1.4.1-alpine AS builder
RUN apk add --no-cache sqlite-static yaml-static
ARG release
@ -42,7 +42,7 @@ RUN addgroup -g 1000 -S invidious && \
adduser -u 1000 -S invidious -G invidious
COPY --chown=invidious ./config/config.* ./config/
RUN mv -n config/config.example.yml config/config.yml
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: postgres/' config/config.yml
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: invidious-db/' config/config.yml
COPY ./config/sql/ ./config/sql/
COPY ./locales/ ./locales/
COPY --from=builder /invidious/assets ./assets/

View File

@ -1,5 +1,5 @@
FROM alpine:3.15 AS builder
RUN apk add --no-cache 'crystal=1.2.2-r0' shards sqlite-static yaml-static yaml-dev libxml2-dev zlib-static openssl-libs-static openssl-dev musl-dev
FROM alpine:3.16 AS builder
RUN apk add --no-cache 'crystal=1.4.1-r0' shards sqlite-static yaml-static yaml-dev libxml2-dev zlib-static openssl-libs-static openssl-dev musl-dev
ARG release
@ -34,14 +34,14 @@ RUN if [ ${release} == 1 ] ; then \
--link-flags "-lxml2 -llzma"; \
fi
FROM alpine:3.15
FROM alpine:3.16
RUN apk add --no-cache librsvg ttf-opensans
WORKDIR /invidious
RUN addgroup -g 1000 -S invidious && \
adduser -u 1000 -S invidious -G invidious
COPY --chown=invidious ./config/config.* ./config/
RUN mv -n config/config.example.yml config/config.yml
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: postgres/' config/config.yml
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: invidious-db/' config/config.yml
COPY ./config/sql/ ./config/sql/
COPY ./locales/ ./locales/
COPY --from=builder /invidious/assets ./assets/

View File

@ -1,6 +1,6 @@
dependencies:
- name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/
version: 8.3.0
digest: sha256:1feec3c396cbf27573dc201831ccd3376a4a6b58b2e7618ce30a89b8f5d707fd
generated: "2020-02-07T13:39:38.624846+01:00"
repository: https://charts.bitnami.com/bitnami/
version: 11.1.3
digest: sha256:79061645472b6fb342d45e8e5b3aacd018ef5067193e46a060bccdc99fe7f6e1
generated: "2022-03-02T05:57:20.081432389+13:00"

View File

@ -1,7 +1,7 @@
apiVersion: v2
name: invidious
description: Invidious is an alternative front-end to YouTube
version: 1.1.0
version: 1.1.1
appVersion: 0.20.1
keywords:
- youtube
@ -17,6 +17,6 @@ maintainers:
email: mail@leonklingele.de
dependencies:
- name: postgresql
version: ~8.3.0
repository: "https://kubernetes-charts.storage.googleapis.com/"
version: ~11.1.3
repository: "https://charts.bitnami.com/bitnami/"
engine: gotpl

View File

@ -14,7 +14,7 @@ autoscaling:
targetCPUUtilizationPercentage: 50
service:
type: clusterIP
type: ClusterIP
port: 3000
#loadBalancerIP:
@ -32,14 +32,19 @@ securityContext:
runAsGroup: 1000
fsGroup: 1000
# See https://github.com/helm/charts/tree/master/stable/postgresql
# See https://github.com/bitnami/charts/tree/master/bitnami/postgresql
postgresql:
postgresqlUsername: kemal
postgresqlPassword: kemal
postgresqlDatabase: invidious
initdbUsername: kemal
initdbPassword: kemal
initdbScriptsConfigMap: invidious-postgresql-init
image:
registry: quay.io
auth:
username: kemal
password: kemal
database: invidious
primary:
initdb:
username: kemal
password: kemal
scriptsConfigMap: invidious-postgresql-init
# Adapted from ../config/config.yml
config:

View File

@ -21,15 +21,15 @@
"No": "لا",
"Import and Export Data": "اِستيراد البيانات وتصديرها",
"Import": "استيراد",
"Import Invidious data": "استيراد بيانات انفيدياس",
"Import YouTube subscriptions": "استيراد اشتراكات يوتيوب",
"Import Invidious data": "استيراد بيانات JSON Invidious",
"Import YouTube subscriptions": "استيراد اشتراكات YouTube/OPML",
"Import FreeTube subscriptions (.db)": "استيراد اشتراكات فريتيوب (.db)",
"Import NewPipe subscriptions (.json)": "استيراد اشتراكات نيو بايب (.json)",
"Import NewPipe data (.zip)": "استيراد بيانات نيو بايب (.zip)",
"Export": "تصدير",
"Export subscriptions as OPML": "تصدير الاشتراكات كـOPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "تصدير الاشتراكات كـOPML (لِنيو بايب و فريتيوب)",
"Export data as JSON": "تصدير البيانات بتنسيق JSON",
"Export data as JSON": "تصدير بيانات Invidious كـ JSON",
"Delete account?": "حذف الحساب؟",
"History": "السِّجل",
"An alternative front-end to YouTube": "واجهة أمامية بديلة لموقع يوتيوب",
@ -66,7 +66,7 @@
"preferences_related_videos_label": "اعرض الفيديوهات ذات الصلة: ",
"preferences_annotations_label": "اعرض الملاحظات في الفيديو تلقائيا: ",
"preferences_extend_desc_label": "توسيع وصف الفيديو تلقائيا: ",
"preferences_vr_mode_label": "مقاطع فيديو تفاعلية ب درجة 360: ",
"preferences_vr_mode_label": "مقاطع فيديو تفاعلية بزاوية 360 درجة (تتطلب WebGL): ",
"preferences_category_visual": "التفضيلات المرئية",
"preferences_player_style_label": "شكل مشغل الفيديوهات: ",
"Dark mode: ": "الوضع الليلي: ",
@ -108,9 +108,9 @@
"preferences_show_nick_label": "إظهار اللقب في الأعلى: ",
"Top enabled: ": "تفعيل 'الأفضل' ؟ ",
"CAPTCHA enabled: ": "تفعيل الكابتشا: ",
"Login enabled: ": فعيل الولوج: ",
"Login enabled: ": مكين تسجيل الدخول: ",
"Registration enabled: ": "تفعيل التسجيل: ",
"Report statistics: ": "الإبلاغ عن الإحصائيات: ",
"Report statistics: ": "تقرير الإحصائيات: ",
"Save preferences": "حفظ الإعدادات",
"Subscription manager": "مدير الاشتراكات",
"Token manager": "إداره الرمز",
@ -121,7 +121,7 @@
"Subscriptions": "الاشتراكات",
"search": "بحث",
"Log out": "تسجيل الخروج",
"Released under the AGPLv3 on Github.": "صدر تحت AGPLv3 على Github.",
"Released under the AGPLv3 on Github.": "صدر تحت AGPLv3 على GitHub.",
"Source available here.": "الأكواد متوفرة هنا.",
"View JavaScript license information.": "مشاهدة معلومات حول تراخيص الجافاسكريبت.",
"View privacy policy.": "عرض سياسة الخصوصية.",
@ -141,7 +141,6 @@
"Show less": "عرض اقل",
"Watch on YouTube": "مشاهدة الفيديو على اليوتيوب",
"Switch Invidious Instance": "تبديل المثيل Invidious",
"Broken? Try another Invidious Instance": "معطل؟ جرب مثيل Invidious آخر",
"Hide annotations": "إخفاء الملاحظات في الفيديو",
"Show annotations": "عرض الملاحظات في الفيديو",
"Genre: ": "النوع: ",
@ -175,7 +174,7 @@
"User ID is a required field": "مكان اسم المستخدم مطلوب",
"Password is a required field": "مكان كلمة السر مطلوب",
"Wrong username or password": "اسم المستخدم او كلمة السر غير صحيح",
"Please sign in using 'Log in with Google'": "الرجاء تسجيل الدخول 'تسجيل الدخول بواسطة جوجل'",
"Please sign in using 'Log in with Google'": "الرجاء تسجيل الدخول باستخدام \"تسجيل الدخول باستخدام Google\"",
"Password cannot be empty": "لا يمكن أن تكون كلمة السر فارغة",
"Password cannot be longer than 55 characters": "يجب أن لا تتعدى كلمة السر 55 حرفًا",
"Please log in": "الرجاء تسجيل الدخول",
@ -187,7 +186,7 @@
"Could not fetch comments": "لم يتمكن من إحضار التعليقات",
"`x` ago": "`x` منذ",
"Load more": "عرض المزيد",
"Could not create mix.": "لم يستطع عمل خلط.",
"Could not create mix.": "تعذر إنشاء مزيج.",
"Empty playlist": "قائمة التشغيل فارغة",
"Not a playlist.": "قائمة التشغيل غير صالحة.",
"Playlist does not exist.": "قائمة التشغيل غير موجودة.",
@ -195,7 +194,7 @@
"Hidden field \"challenge\" is a required field": "مكان مخفي \"تحدي\" مكان مطلوب",
"Hidden field \"token\" is a required field": "مكان مخفي \"رمز\" مكان مطلوب",
"Erroneous challenge": "تحدي غير صالح",
"Erroneous token": وز غير صالح",
"Erroneous token": مز مميز خاطئ",
"No such user": "مستخدم غير صالح",
"Token is expired, please try again": "الرمز منتهى الصلاحية، الرجاء المحاولة مرة اخرى",
"English": "إنجليزي",
@ -329,48 +328,47 @@
"Videos": "الفيديوهات",
"Playlists": "قوائم التشغيل",
"Community": "المجتمع",
"relevance": "ملاؤم",
"rating": "تقييم",
"date": "التاريخ",
"views": "مشاهدات",
"content_type": "نوع المحتوى",
"duration": "المدة الزمنية",
"features": "الميزات",
"sort": "فرز",
"hour": "ساعة",
"today": "اليوم",
"week": "هذا الأسبوع",
"month": "هذا الشهر",
"year": "هذه السنة",
"video": "فيديو",
"channel": "قناة",
"playlist": "قائمة التشغيل",
"movie": "فيلم",
"show": "عرض",
"hd": "عالية الدقة",
"subtitles": "ترجمات",
"creative_commons": "المشاع الإبداعي",
"3d": "ثلاثي الأبعاد",
"live": "مباشر",
"4k": "4k",
"location": "الأماكن",
"hdr": "وضع التباين العالي",
"filter": "معامل الفرز",
"search_filters_sort_option_relevance": "ملاؤم",
"search_filters_sort_option_rating": "تقييم",
"search_filters_sort_option_date": "التاريخ",
"search_filters_sort_option_views": "مشاهدات",
"search_filters_type_label": "نوع المحتوى",
"search_filters_duration_label": "المدة الزمنية",
"search_filters_features_label": "الميزات",
"search_filters_sort_label": "فرز",
"search_filters_date_option_hour": "آخر ساعة",
"search_filters_date_option_today": "اليوم",
"search_filters_date_option_week": "هذا الأسبوع",
"search_filters_date_option_month": "هذا الشهر",
"search_filters_date_option_year": "هذه السنة",
"search_filters_type_option_video": "فيديو",
"search_filters_type_option_channel": "قناة",
"search_filters_type_option_playlist": "قائمة التشغيل",
"search_filters_type_option_movie": "فيلم",
"search_filters_type_option_show": "عرض",
"search_filters_features_option_hd": "عالية الدقة",
"search_filters_features_option_subtitles": "ترجمات",
"search_filters_features_option_c_commons": "المشاع الإبداعي",
"search_filters_features_option_three_d": "ثلاثي الأبعاد",
"search_filters_features_option_live": "مباشر",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "الأماكن",
"search_filters_features_option_hdr": "وضع التباين العالي",
"Current version: ": "الإصدار الحالي: ",
"next_steps_error_message": "بعد ذلك يجب أن تحاول: ",
"next_steps_error_message_refresh": "تحديث",
"next_steps_error_message_go_to_youtube": "انتقل إلى يوتيوب",
"short": "قصير (< 4 دقائق)",
"long": "طويل (> 20 دقيقة)",
"search_filters_duration_option_short": "قصير (< 4 دقائق)",
"search_filters_duration_option_long": "طويل (> 20 دقيقة)",
"footer_source_code": "شفرة المصدر",
"footer_original_source_code": "شفرة المصدر الأصلية",
"footer_original_source_code": "كود المصدر الأصلي",
"footer_modfied_source_code": "شفرة المصدر المعدلة",
"adminprefs_modified_source_code_url_label": "URL إلى مستودع التعليمات البرمجية المصدرية المعدلة",
"footer_documentation": "التوثيق",
"footer_donate_page": "تبرّع",
"preferences_region_label": "بلد المحتوى: ",
"preferences_quality_dash_label": "جودة فيديو DASH المفضلة: ",
"preferences_quality_option_dash": "DASH (جودة تكييفية)",
"preferences_quality_option_dash": "DASH (الجودة التلقائية)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "متوسطة",
"preferences_quality_option_small": "صغيرة",
@ -386,7 +384,7 @@
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"purchased": "تم شراؤها",
"search_filters_features_option_purchased": "تم شراؤها",
"none": "لاشيء",
"videoinfo_started_streaming_x_ago": "بدأ البث منذ `x`",
"videoinfo_watch_on_youTube": "مشاهدة على يوتيوب",
@ -395,10 +393,10 @@
"user_created_playlists": "'x' إنشاء قوائم التشغيل",
"user_saved_playlists": "قوائم التشغيل المحفوظة 'x'",
"Video unavailable": "الفيديو غير متوفر",
"360": "360°",
"search_filters_features_option_three_sixty": "360°",
"download_subtitles": "ترجمات - 'x' (.vtt)",
"invidious": "الخيالي",
"preferences_save_player_pos_label": "احفظ وقت الفيديو الحالي: ",
"preferences_save_player_pos_label": "حفظ موضع التشغيل: ",
"crash_page_you_found_a_bug": "يبدو أنك قد وجدت خطأً برمجيًّا في Invidious!",
"generic_videos_count_0": "لا فيديوهات",
"generic_videos_count_1": "فيديو واحد",
@ -429,5 +427,113 @@
"generic_playlists_count_2": "قائمتا تشغيل",
"generic_playlists_count_3": "{{count}} قوائم تشغيل",
"generic_playlists_count_4": "{{count}} قائمة تشغيل",
"generic_playlists_count_5": "{{count}} قائمة تشغيل"
"generic_playlists_count_5": "{{count}} قائمة تشغيل",
"English (United States)": "الإنجليزية (الولايات المتحدة)",
"Indonesian (auto-generated)": "إندونيسي (مُنشأ تلقائيًا)",
"Interlingue": "إنترلينغوي",
"Italian (auto-generated)": "الإيطالية (مُنشأة تلقائيًا)",
"Spanish (auto-generated)": "الأسبانية (تم إنشاؤه تلقائيًا)",
"crash_page_before_reporting": "قبل الإبلاغ عن خطأ، تأكد من وجود:",
"French (auto-generated)": "الفرنسية (مُنشأة تلقائيًا)",
"Portuguese (auto-generated)": "البرتغالية (تم إنشاؤه تلقائيًا)",
"Turkish (auto-generated)": "التركية (تم إنشاؤها تلقائيًا)",
"crash_page_refresh": "حاول <a href=\"`x`\"> تحديث الصفحة </a>",
"crash_page_switch_instance": "حاول <a href=\"`x`\"> استخدام مثيل آخر </a>",
"Korean (auto-generated)": "كوري (تم إنشاؤه تلقائيًا)",
"Spanish (Mexico)": "الإسبانية (المكسيك)",
"Vietnamese (auto-generated)": "فيتنامي (تم إنشاؤه تلقائيًا)",
"crash_page_report_issue": "إذا لم يساعد أي مما سبق، يرجى فتح <a href=\"`x`\"> مشكلة جديدة على GitHub </a> (ويفضل أن يكون باللغة الإنجليزية) وتضمين النص التالي في رسالتك (لا تترجم هذا النص):",
"crash_page_read_the_faq": "قراءة <a href=\"`x`\"> الأسئلة المتكررة (الأسئلة الشائعة) </a>",
"preferences_watch_history_label": "تمكين سجل المشاهدة: ",
"English (United Kingdom)": "الإنجليزية (المملكة المتحدة)",
"Cantonese (Hong Kong)": "الكانتونية (هونغ كونغ)",
"Chinese": "الصينية",
"Chinese (China)": "الصينية (الصين)",
"Chinese (Hong Kong)": "الصينية (هونج كونج)",
"Chinese (Taiwan)": "الصينية (تايوان)",
"Dutch (auto-generated)": "هولندي (تم إنشاؤه تلقائيًا)",
"German (auto-generated)": "ألماني (تم إنشاؤه تلقائيًا)",
"Japanese (auto-generated)": "اليابانية (مُنشأة تلقائيًا)",
"Portuguese (Brazil)": "البرتغالية (البرازيل)",
"Russian (auto-generated)": "الروسية (منشأة تلقائيا)",
"Spanish (Spain)": "الإسبانية (إسبانيا)",
"crash_page_search_issue": "بحثت عن <a href=\"`x`\"> المشكلات الموجودة على GitHub </a>",
"search_filters_title": "معامل الفرز",
"search_message_no_results": "لا توجد نتائج.",
"search_message_change_filters_or_query": "حاول توسيع استعلام البحث و / أو تغيير عوامل التصفية.",
"search_filters_date_label": "تاريخ الرفع",
"generic_count_weeks_0": "{{count}} أسبوع",
"generic_count_weeks_1": "{{count}} أسبوع",
"generic_count_weeks_2": "{{count}} أسبوع",
"generic_count_weeks_3": "{{count}} أسبوع",
"generic_count_weeks_4": "{{count}} أسابيع",
"generic_count_weeks_5": "{{count}} أسبوع",
"Popular enabled: ": "تم تمكين الشعبية: ",
"search_filters_duration_option_medium": "متوسط (4-20 دقيقة)",
"search_filters_date_option_none": "أي تاريخ",
"search_filters_type_option_all": "أي نوع",
"search_filters_features_option_vr180": "VR180",
"generic_count_minutes_0": "{{count}} دقيقة",
"generic_count_minutes_1": "{{count}} دقيقة",
"generic_count_minutes_2": "{{count}} دقيقة",
"generic_count_minutes_3": "{{count}} دقيقة",
"generic_count_minutes_4": "{{count}} دقائق",
"generic_count_minutes_5": "{{count}} دقيقة",
"generic_count_hours_0": "{{count}} ساعة",
"generic_count_hours_1": "{{count}} ساعة",
"generic_count_hours_2": "{{count}} ساعة",
"generic_count_hours_3": "{{count}} ساعة",
"generic_count_hours_4": "{{count}} ساعات",
"generic_count_hours_5": "{{count}} ساعة",
"comments_view_x_replies_0": "عرض رد {{count}}",
"comments_view_x_replies_1": "عرض رد {{count}}",
"comments_view_x_replies_2": "عرض رد {{count}}",
"comments_view_x_replies_3": "عرض رد {{count}}",
"comments_view_x_replies_4": "عرض الردود {{count}}",
"comments_view_x_replies_5": "عرض رد {{count}}",
"search_message_use_another_instance": " يمكنك أيضًا البحث عن <a href=\"`x`\"> في مثيل آخر </a>.",
"comments_points_count_0": "{{count}} نقطة",
"comments_points_count_1": "{{count}} نقطة",
"comments_points_count_2": "{{count}} نقطة",
"comments_points_count_3": "{{count}} نقطة",
"comments_points_count_4": "{{count}} نقاط",
"comments_points_count_5": "{{count}} نقطة",
"generic_count_years_0": "{{count}} السنة",
"generic_count_years_1": "{{count}} السنة",
"generic_count_years_2": "{{count}} السنة",
"generic_count_years_3": "{{count}} السنة",
"generic_count_years_4": "{{count}} سنوات",
"generic_count_years_5": "{{count}} السنة",
"tokens_count_0": "الرمز المميز {{count}}",
"tokens_count_1": "الرمز المميز {{count}}",
"tokens_count_2": "الرمز المميز {{count}}",
"tokens_count_3": "الرمز المميز {{count}}",
"tokens_count_4": "الرموز المميزة {{count}}",
"tokens_count_5": "الرمز المميز {{count}}",
"search_filters_apply_button": "تطبيق الفلاتر المحددة",
"search_filters_duration_option_none": "أي مدة",
"subscriptions_unseen_notifs_count_0": "{{count}} إشعار غير مرئي",
"subscriptions_unseen_notifs_count_1": "{{count}} إشعار غير مرئي",
"subscriptions_unseen_notifs_count_2": "{{count}} إشعار غير مرئي",
"subscriptions_unseen_notifs_count_3": "{{count}} إشعار غير مرئي",
"subscriptions_unseen_notifs_count_4": "{{count}} إشعارات غير مرئية",
"subscriptions_unseen_notifs_count_5": "{{count}} إشعار غير مرئي",
"generic_count_days_0": "{{count}} يوم",
"generic_count_days_1": "{{count}} يوم",
"generic_count_days_2": "{{count}} يوم",
"generic_count_days_3": "{{count}} يوم",
"generic_count_days_4": "{{count}} أيام",
"generic_count_days_5": "{{count}} يوم",
"generic_count_months_0": "{{count}} شهر",
"generic_count_months_1": "{{count}} شهر",
"generic_count_months_2": "{{count}} شهر",
"generic_count_months_3": "{{count}} شهر",
"generic_count_months_4": "{{count}} شهور",
"generic_count_months_5": "{{count}} شهر",
"generic_count_seconds_0": "{{count}} ثانية",
"generic_count_seconds_1": "{{count}} ثانية",
"generic_count_seconds_2": "{{count}} ثانية",
"generic_count_seconds_3": "{{count}} ثانية",
"generic_count_seconds_4": "{{count}} ثوانٍ",
"generic_count_seconds_5": "{{count}} ثانية"
}

97
locales/bn.json Normal file
View File

@ -0,0 +1,97 @@
{
"Subscribe": "সাবস্ক্রাইব",
"View channel on YouTube": "ইউটিউবে চ্যানেল দেখুন",
"View playlist on YouTube": "ইউটিউবে প্লেলিস্ট দেখুন",
"newest": "সর্ব-নতুন",
"oldest": "পুরানতম",
"popular": "জনপ্রিয়",
"last": "শেষটা",
"Next page": "পরের পৃষ্ঠা",
"Previous page": "আগের পৃষ্ঠা",
"Clear watch history?": "দেখার ইতিহাস সাফ করবেন?",
"New password": "নতুন পাসওয়ার্ড",
"New passwords must match": "নতুন পাসওয়ার্ড অবশ্যই মিলতে হবে",
"Cannot change password for Google accounts": "গুগল অ্যাকাউন্টগুলোর জন্য পাসওয়ার্ড পরিবর্তন করা যায় না",
"Authorize token?": "টোকেন অনুমোদন করবেন?",
"Authorize token for `x`?": "`x` -এর জন্য টোকেন অনুমোদন?",
"Yes": "হ্যাঁ",
"No": "না",
"Import and Export Data": "তথ্য আমদানি ও রপ্তানি",
"Import": "আমদানি",
"Import Invidious data": "ইনভিডিয়াস তথ্য আমদানি",
"Import YouTube subscriptions": "ইউটিউব সাবস্ক্রিপশন আনুন",
"Import FreeTube subscriptions (.db)": "ফ্রিটিউব সাবস্ক্রিপশন (.db) আনুন",
"Import NewPipe subscriptions (.json)": "নতুন পাইপ সাবস্ক্রিপশন আনুন (.json)",
"Import NewPipe data (.zip)": "নিউপাইপ তথ্য আনুন (.zip)",
"Export": "তথ্য বের করুন",
"Export subscriptions as OPML": "সাবস্ক্রিপশন OPML হিসাবে আনুন",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "OPML-এ সাবস্ক্রিপশন বের করুন(নিউ পাইপ এবং ফ্রিউটিউব এর জন্য)",
"Export data as JSON": "JSON হিসাবে তথ্য বের করুন",
"Delete account?": "অ্যাকাউন্ট মুছে ফেলবেন?",
"History": "ইতিহাস",
"An alternative front-end to YouTube": "ইউটিউবের একটি বিকল্পস্বরূপ সম্মুখ-প্রান্ত",
"JavaScript license information": "জাভাস্ক্রিপ্ট লাইসেন্সের তথ্য",
"source": "সূত্র",
"Log in": "লগ ইন",
"Log in/register": "লগ ইন/রেজিস্টার",
"Log in with Google": "গুগল দিয়ে লগ ইন করুন",
"User ID": "ইউজার আইডি",
"Password": "পাসওয়ার্ড",
"Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):",
"Text CAPTCHA": "টেক্সট ক্যাপচা",
"Image CAPTCHA": "চিত্র ক্যাপচা",
"Sign In": "সাইন ইন",
"Register": "নিবন্ধন",
"E-mail": "ই-মেইল",
"Google verification code": "গুগল যাচাইকরণ কোড",
"Preferences": "পছন্দসমূহ",
"preferences_category_player": "প্লেয়ারের পছন্দসমূহ",
"preferences_video_loop_label": "সর্বদা লুপ: ",
"preferences_autoplay_label": "স্বয়ংক্রিয় চালু: ",
"preferences_continue_label": "ডিফল্টভাবে পরবর্তী চালাও: ",
"preferences_continue_autoplay_label": "পরবর্তী ভিডিও স্বয়ংক্রিয়ভাবে চালাও: ",
"preferences_listen_label": "সহজাতভাবে শোনো: ",
"preferences_local_label": "ভিডিও প্রক্সি করো: ",
"preferences_speed_label": "সহজাত গতি: ",
"preferences_quality_label": "পছন্দের ভিডিও মান: ",
"preferences_volume_label": "প্লেয়ার শব্দের মাত্রা: ",
"LIVE": "লাইভ",
"Shared `x` ago": "`x` আগে শেয়ার করা হয়েছে",
"Unsubscribe": "আনসাবস্ক্রাইব",
"generic_views_count": "{{count}}জন দেখেছে",
"generic_views_count_plural": "{{count}}জন দেখেছে",
"generic_videos_count": "{{count}}টি ভিডিও",
"generic_videos_count_plural": "{{count}}টি ভিডিও",
"generic_subscribers_count": "{{count}}জন অনুসরণকারী",
"generic_subscribers_count_plural": "{{count}}জন অনুসরণকারী",
"preferences_watch_history_label": "দেখার ইতিহাস চালু করো: ",
"preferences_quality_option_dash": "ড্যাশ (সময়োপযোগী মান)",
"preferences_quality_dash_option_auto": "স্বয়ংক্রিয়",
"preferences_quality_dash_option_best": "সেরা",
"preferences_quality_dash_option_worst": "মন্দতম",
"preferences_quality_dash_option_4320p": "৪৩২০পি",
"preferences_quality_dash_option_2160p": "২১৬০পি",
"preferences_quality_dash_option_1440p": "১৪৪০পি",
"preferences_quality_dash_option_480p": "৪৮০পি",
"preferences_quality_dash_option_360p": "৩৬০পি",
"preferences_quality_dash_option_240p": "২৪০পি",
"preferences_quality_dash_option_144p": "১৪৪পি",
"preferences_comments_label": "সহজাত মন্তব্য: ",
"youtube": "ইউটিউব",
"Fallback captions: ": "বিকল্প উপাখ্যান: ",
"preferences_related_videos_label": "সম্পর্কিত ভিডিও দেখাও: ",
"preferences_annotations_label": "সহজাতভাবে টীকা দেখাও ",
"preferences_quality_option_hd720": "উচ্চ৭২০",
"preferences_quality_dash_label": "পছন্দের ড্যাশ ভিডিও মান: ",
"preferences_captions_label": "সহজাত উপাখ্যান: ",
"generic_playlists_count": "{{count}}টি চালুতালিকা",
"generic_playlists_count_plural": "{{count}}টি চালুতালিকা",
"reddit": "রেডিট",
"invidious": "ইনভিডিয়াস",
"generic_subscriptions_count": "{{count}}টি অনুসরণ",
"generic_subscriptions_count_plural": "{{count}}টি অনুসরণ",
"preferences_quality_option_medium": "মধ্যম",
"preferences_quality_option_small": "ছোট",
"preferences_quality_dash_option_1080p": "১০৮০পি",
"preferences_quality_dash_option_720p": "৭২০পি"
}

View File

@ -52,16 +52,16 @@
"Download": "Descarrega",
"Download as: ": "Descarrega com: ",
"Videos": "Vídeos",
"content_type": "Tipus",
"duration": "Duració",
"sort": "Ordena per",
"week": "Aquesta setmana",
"month": "Aquest mes",
"year": "Aquest any",
"video": "Vídeo",
"channel": "Canal",
"short": "Curt (< 4 minuts)",
"long": "Llarg (> 20 minuts)",
"search_filters_type_label": "Tipus",
"search_filters_duration_label": "Duració",
"search_filters_sort_label": "Ordena per",
"search_filters_date_option_week": "Aquesta setmana",
"search_filters_date_option_month": "Aquest mes",
"search_filters_date_option_year": "Aquest any",
"search_filters_type_option_video": "Vídeo",
"search_filters_type_option_channel": "Canal",
"search_filters_duration_option_short": "Curt (< 4 minuts)",
"search_filters_duration_option_long": "Llarg (> 20 minuts)",
"Current version: ": "Versió actual: ",
"Malay": "Malai",
"Persian": "Persa",
@ -93,11 +93,11 @@
"Spanish": "Castellà",
"Vietnamese": "Vietnamita",
"News": "Notícies",
"show": "Mostra",
"search_filters_type_option_show": "Mostra",
"footer_documentation": "Documentació",
"Thai": "Tailandès",
"Music": "Música",
"relevance": "Rellevància",
"hour": "Última hora",
"today": "Avui"
"search_filters_sort_option_relevance": "Rellevància",
"search_filters_date_option_hour": "Última hora",
"search_filters_date_option_today": "Avui"
}

View File

@ -1,6 +1,6 @@
{
"LIVE": "ŽIVĚ",
"Shared `x` ago": "Sdíleno před `x`",
"Shared `x` ago": "Zveřejněno před `x`",
"Unsubscribe": "Odhlásit odběr",
"Subscribe": "Odebírat",
"View channel on YouTube": "Otevřít kanál na YouTube",
@ -19,17 +19,17 @@
"Authorize token for `x`?": "Autorizovat token pro `x`?",
"Yes": "Ano",
"No": "Ne",
"Import and Export Data": "Import a Export úda",
"Import": "Inport",
"Import Invidious data": "Importovat údaje Invidious",
"Import YouTube subscriptions": "Importovat odběry z YouTube",
"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 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)",
"Export": "Exportovat",
"Export subscriptions as OPML": "Exportovat odběry jako OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportovat údaje jako OPML (na NewPipe a FreeTube)",
"Export data as JSON": "Exportovat data jako JSON",
"Export data as JSON": "Exportovat data Invidious jako JSON",
"Delete account?": "Smazat účet?",
"History": "Historie",
"An alternative front-end to YouTube": "Alternativní front-end pro YouTube",
@ -38,7 +38,7 @@
"Log in": "Přihlásit se",
"Log in/register": "Přihlásit se/vytvořit účet",
"Log in with Google": "Přihlásit se s Googlem",
"User ID": "Uživatelské IČ",
"User ID": "ID uživatele",
"Password": "Heslo",
"Time (h:mm:ss):": "Čas (h:mm:ss):",
"Text CAPTCHA": "Textové CAPTCHA",
@ -51,17 +51,17 @@
"preferences_category_player": "Nastavení přehravače",
"preferences_video_loop_label": "Vždy opakovat: ",
"preferences_autoplay_label": "Automatické přehrávání: ",
"preferences_continue_label": "Přehrát další ve výchozím stavu: ",
"preferences_continue_label": "Automaticky přehrát další: ",
"preferences_continue_autoplay_label": "Automaticky přehrát další video: ",
"preferences_listen_label": "Poslouchat ve výchozím nastavení: ",
"preferences_local_label": "Video přes proxy: ",
"preferences_speed_label": "Základní Rychlost: ",
"preferences_speed_label": "Výchozí rychlost: ",
"preferences_quality_label": "Preferovaná kvalita videa: ",
"preferences_volume_label": "Hlasitost přehrávače: ",
"preferences_comments_label": "Předpřipravené komentáře: ",
"youtube": "YouTube",
"reddit": "reddit",
"preferences_captions_label": "Standartní Titulky: ",
"reddit": "Reddit",
"preferences_captions_label": "Výchozí titulky: ",
"Fallback captions: ": "Záložní titulky: ",
"preferences_related_videos_label": "Zobrazit podobné videa: ",
"preferences_annotations_label": "Zobrazovat poznámky ve výchozím nastavení: ",
@ -88,28 +88,28 @@
"Only show latest unwatched video from channel: ": "Zobrazit jen nejnovější nezhlédnuté video z daného kanálu: ",
"preferences_unseen_only_label": "Zobrazit jen již nezhlédnuté: ",
"preferences_notifications_only_label": "Zobrazit pouze upozornění (pokud nějaká jsou): ",
"Enable web notifications": "Povolit webové upozornění",
"Enable web notifications": "Povolit webová upozornění",
"`x` uploaded a video": "`x` nahrál(a) video",
"`x` is live": "`x` je živě",
"preferences_category_data": "Nastavení dat",
"Clear watch history": "Smazat historii",
"Import/export data": "importovat/exportovat data",
"Import/export data": "Importovat/exportovat data",
"Change password": "Změnit heslo",
"Manage subscriptions": "Spravovat odebírané kanály",
"Manage tokens": "Spravovat klíče",
"Watch history": "Historie Sledování",
"Delete account": "Smazat Účet",
"Manage tokens": "Spravovat tokeny",
"Watch history": "Historie sledování",
"Delete account": "Smazat účet",
"preferences_category_admin": "Administrátorská nastavení",
"preferences_default_home_label": "Základní domovská stránka: ",
"preferences_feed_menu_label": "Menu doporučených: ",
"CAPTCHA enabled: ": "CAPTCHA povolen: ",
"CAPTCHA enabled: ": "CAPTCHA povolena: ",
"Login enabled: ": "Přihlášení povoleno: ",
"Registration enabled: ": "Registrace povolena ",
"Report statistics: ": "Oznámit statistiky: ",
"Save preferences": "Uložit nastavení",
"Subscription manager": "Správa Odběrů",
"Token manager": "Správa klíčů",
"Token": "Klíč",
"Subscription manager": "Správa odběrů",
"Token manager": "Správa tokenů",
"Token": "Token",
"Import/export": "Importovat/exportovat",
"unsubscribe": "odhlásit odběr",
"revoke": "vrátit zpět",
@ -118,10 +118,10 @@
"Log out": "Odhlásit se",
"Source available here.": "Zdrojový kód dostupný zde.",
"View JavaScript license information.": "Zobrazit informace o licenci JavaScript .",
"View privacy policy.": "Zobrazit Zásady ochrany osobních údajů.",
"View privacy policy.": "Zobrazit zásady ochrany osobních údajů.",
"Trending": "Trendy",
"Public": "Veřejné",
"Unlisted": "Nevypsáno",
"Unlisted": "Neveřejné",
"Private": "Soukromé",
"View all playlists": "Zobrazit všechny playlisty",
"Updated `x` ago": "Aktualizováno před `x`",
@ -133,12 +133,12 @@
"Show more": "Zobrazit více",
"Show less": "Zobrazit méně",
"Watch on YouTube": "Sledovat na YouTube",
"Hide annotations": "Skrýt vysvětlivky",
"Show annotations": "Zobrazit vysvětlivky",
"Hide annotations": "Skrýt poznámky",
"Show annotations": "Zobrazit poznámky",
"Genre: ": "Žánr: ",
"License: ": "Licence: ",
"Family friendly? ": "Vhodné pro děti? ",
"Engagement: ": "Závaznost: ",
"Family friendly? ": "Vhodné pro rodiny? ",
"Engagement: ": "Zapojení: ",
"English": "Angličtina",
"English (auto-generated)": "Angličtina (automaticky generováno)",
"Afrikaans": "Afrikánština",
@ -262,27 +262,230 @@
"Video mode": "Videový režim",
"Videos": "Videa",
"Community": "Komunita",
"rating": "hodnocení",
"date": "datum",
"views": "zhlédnutí",
"duration": "délka",
"hour": "hodina",
"today": "dnes",
"week": "týden",
"month": "měsíc",
"year": "rok",
"video": "video",
"channel": "kanál",
"playlist": "playlist",
"movie": "film",
"show": "zobrazit",
"hd": "HD",
"subtitles": "titulky",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "živě",
"4k": "4k",
"location": "umístění",
"hdr": "HDR",
"filter": "filtr"
"search_filters_sort_option_rating": "Hodnocení",
"search_filters_sort_option_date": "Datum nahrání",
"search_filters_sort_option_views": "Počet zhlédnutí",
"search_filters_duration_label": "Délka",
"search_filters_date_option_hour": "Poslední hodina",
"search_filters_date_option_today": "Dnes",
"search_filters_date_option_week": "Tento týden",
"search_filters_date_option_month": "Tento měsíc",
"search_filters_date_option_year": "Tento rok",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanál",
"search_filters_type_option_playlist": "Playlist",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Seriál",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Titulky",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Živě",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Umístění",
"search_filters_features_option_hdr": "HDR",
"generic_count_days_0": "{{count}} dnem",
"generic_count_days_1": "{{count}} dny",
"generic_count_days_2": "{{count}} dny",
"generic_count_hours_0": "{{count}} hodinou",
"generic_count_hours_1": "{{count}} hodinami",
"generic_count_hours_2": "{{count}} hodinami",
"crash_page_refresh": "zkusili <a href=\"`x`\">obnovit stránku</a>",
"crash_page_switch_instance": "zkusili <a href=\"`x`\">použít jinou instanci</a>",
"preferences_vr_mode_label": "Interaktivní 360-stupňová videa (vyžaduje WebGL): ",
"English (United Kingdom)": "Angličtina (Spojené království)",
"Chinese (China)": "Čínština (Čína)",
"Chinese (Hong Kong)": "Čínština (Hong Kong)",
"Chinese (Taiwan)": "Čínština (Taiwan)",
"Portuguese (auto-generated)": "Portugalština (automaticky generováno)",
"Spanish (auto-generated)": "Španělština (automaticky generováno)",
"Spanish (Mexico)": "Španělština (Mexiko)",
"Spanish (Spain)": "Španělština (Španělsko)",
"generic_count_years_0": "{{count}} rokem",
"generic_count_years_1": "{{count}} lety",
"generic_count_years_2": "{{count}} lety",
"Fallback comments: ": "Záložní komentáře: ",
"Search": "Hledat",
"Top": "Nejlepší",
"Playlists": "Playlisty",
"videoinfo_started_streaming_x_ago": "Stream spuštěn před `x`",
"videoinfo_watch_on_youTube": "Sledovat na YouTube",
"videoinfo_youTube_embed_link": "Vložení",
"crash_page_read_the_faq": "si přečetli <a href=\"`x`\">často kladené otázky (FAQ)</a>",
"crash_page_before_reporting": "Před nahlášením chyby se ujistěte, že jste:",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_dash": "DASH (adaptivní kvalita)",
"generic_views_count_0": "{{count}} zhlédnutí",
"generic_views_count_1": "{{count}} zhlédnutí",
"generic_views_count_2": "{{count}} zhlédnutí",
"generic_subscriptions_count_0": "{{count}} odběr",
"generic_subscriptions_count_1": "{{count}} odběry",
"generic_subscriptions_count_2": "{{count}} odběrů",
"preferences_quality_dash_option_4320p": "4320p",
"generic_videos_count_0": "{{count}} video",
"generic_videos_count_1": "{{count}} videa",
"generic_videos_count_2": "{{count}} videí",
"preferences_quality_option_small": "Nízká",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_1080p": "1080p",
"preferences_quality_dash_option_720p": "720p",
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_144p": "144p",
"preferences_quality_option_medium": "Střední",
"preferences_quality_dash_option_1440p": "1440p",
"invidious": "Invidious",
"View more comments on Reddit": "Zobrazit více komentářů na Redditu",
"Invalid TFA code": "Nesprávný TFA kód",
"generic_playlists_count_0": "{{count}} playlist",
"generic_playlists_count_1": "{{count}} playlisty",
"generic_playlists_count_2": "{{count}} playlistů",
"generic_subscribers_count_0": "{{count}} odběratel",
"generic_subscribers_count_1": "{{count}} odběratelé",
"generic_subscribers_count_2": "{{count}} odběratelů",
"preferences_watch_history_label": "Povolit historii sledování: ",
"preferences_quality_dash_option_240p": "240p",
"preferences_region_label": "Země obsahu: ",
"subscriptions_unseen_notifs_count_0": "{{count}} nezobrazené oznámení",
"subscriptions_unseen_notifs_count_1": "{{count}} nezobrazená oznámení",
"subscriptions_unseen_notifs_count_2": "{{count}} nezobrazených oznámení",
"Show replies": "Zobrazit odpovědi",
"Quota exceeded, try again in a few hours": "Kvóta překročena, zkuste to znovu za pár hodin",
"Password cannot be longer than 55 characters": "Heslo nesmí být delší než 55 znaků",
"comments_view_x_replies_0": "Zobrazit {{count}} odpověď",
"comments_view_x_replies_1": "Zobrazit {{count}} odpovědi",
"comments_view_x_replies_2": "Zobrazit {{count}} odpovědí",
"comments_points_count_0": "{{count}} bod",
"comments_points_count_1": "{{count}} body",
"comments_points_count_2": "{{count}} bodů",
"German (auto-generated)": "Němčina (automaticky generováno)",
"Indonesian (auto-generated)": "Indonéština (automaticky generováno)",
"Interlingue": "Interlingue",
"Italian (auto-generated)": "Italština (automaticky generováno)",
"Japanese (auto-generated)": "Japonština (automaticky generováno)",
"Korean (auto-generated)": "Korejština (automaticky generováno)",
"Russian (auto-generated)": "Ruština (automaticky generováno)",
"generic_count_months_0": "{{count}} měsícem",
"generic_count_months_1": "{{count}} měsíci",
"generic_count_months_2": "{{count}} měsíci",
"generic_count_weeks_0": "{{count}} týdnem",
"generic_count_weeks_1": "{{count}} týdny",
"generic_count_weeks_2": "{{count}} týdny",
"generic_count_minutes_0": "{{count}} minutou",
"generic_count_minutes_1": "{{count}} minutami",
"generic_count_minutes_2": "{{count}} minutami",
"footer_documentation": "Dokumentace",
"next_steps_error_message_refresh": "Obnovit stránku",
"Chinese": "Čínština",
"Dutch (auto-generated)": "Nizozemština (automaticky generováno)",
"Erroneous token": "Chybný token",
"tokens_count_0": "{{count}} token",
"tokens_count_1": "{{count}} tokeny",
"tokens_count_2": "{{count}} tokenů",
"Portuguese (Brazil)": "Portugalština (Brazílie)",
"Token is expired, please try again": "Token vypršel, zkuste to prosím znovu",
"English (United States)": "Angličtina (Spojené státy)",
"Cantonese (Hong Kong)": "Kantonština (Hong Kong)",
"French (auto-generated)": "Francouzština (automaticky generováno)",
"Turkish (auto-generated)": "Turečtina (automaticky generováno)",
"Vietnamese (auto-generated)": "Vietnamština (automaticky generováno)",
"Current version: ": "Aktuální verze: ",
"next_steps_error_message": "Měli byste zkusit: ",
"footer_donate_page": "Přispět",
"download_subtitles": "Titulky - `x` (.vtt)",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"YouTube comment permalink": "Permanentní odkaz YouTube komentáře",
"permalink": "permalink",
"footer_original_source_code": "Původní zdrojový kód",
"adminprefs_modified_source_code_url_label": "URL repozitáře s upraveným zdrojovým kódem",
"Video unavailable": "Video není dostupné",
"next_steps_error_message_go_to_youtube": "Jít na YouTube",
"footer_modfied_source_code": "Upravený zdrojový kód",
"none": "žádné",
"videoinfo_invidious_embed_link": "Odkaz na vložení",
"user_saved_playlists": "`x` uložených playlistů",
"crash_page_you_found_a_bug": "Vypadá to, že jste našli chybu v Invidious!",
"user_created_playlists": "`x` vytvořených playlistů",
"crash_page_search_issue": "vyhledali <a href=\"`x`\">existující problémy na GitHubu</a>",
"crash_page_report_issue": "Pokud nepomohlo nic z výše uvedeného, <a href=\"`x`\">otevřete prosím nový problém na GitHubu</a> (pokud možno v angličtině) a zahrňte do zprávy následující text (NEpřekládejte jej):",
"preferences_quality_dash_label": "Preferovaná kvalita videí DASH: ",
"preferences_quality_dash_option_auto": "Automatická",
"preferences_quality_dash_option_best": "Nejlepší",
"preferences_quality_dash_option_worst": "Nejhorší",
"preferences_quality_dash_option_480p": "480p",
"Top enabled: ": "Povoleny nejlepší: ",
"generic_count_seconds_0": "{{count}} sekundou",
"generic_count_seconds_1": "{{count}} sekundami",
"generic_count_seconds_2": "{{count}} sekundami",
"preferences_save_player_pos_label": "Uložit pozici přehrávání: ",
"Incorrect password": "Nesprávné heslo",
"View as playlist": "Zobrazit jako playlist",
"View Reddit comments": "Zobrazit komentáře z Redditu",
"No such user": "Uživatel nenalezen",
"Playlist privacy": "Soukromí playlistu",
"Wrong answer": "Špatná odpověď",
"Could not pull trending pages.": "Nepodařilo se získat trendy stránky.",
"Erroneous CAPTCHA": "Chybná CAPTCHA",
"Password is a required field": "Heslo je vyžadované pole",
"preferences_automatic_instance_redirect_label": "Automatické přesměrování instance (fallback na redirect.invidious.io): ",
"Switch Invidious Instance": "Přepnout instanci Invidious",
"Empty playlist": "Prázdný playlist",
"footer_source_code": "Zdrojový kód",
"View YouTube comments": "Zobrazit YouTube komentáře",
"Blacklisted regions: ": "Oblasti na černé listině: ",
"Wrong username or password": "Nesprávné uživatelské jméno nebo heslo",
"Please sign in using 'Log in with Google'": "Přihlaste se prosím pomocí Googlu",
"Password cannot be empty": "Heslo nemůže být prázné",
"preferences_category_misc": "Různá nastavení",
"preferences_show_nick_label": "Zobrazit přezdívku na vrchu: ",
"Whitelisted regions: ": "Oblasti na bílé listině: ",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Zdravíme! Zdá se, že máte vypnutý JavaScript. Klikněte sem pro zobrazení komentářů - nezapomeňte, že se mohou načítat trochu déle.",
"User ID is a required field": "ID uživatele je vyžadované pole",
"Please log in": "Přihlaste se prosím",
"Invidious Private Feed for `x`": "Soukromý kanál Invidious pro `x`",
"Deleted or invalid channel": "Smazaný nebo neplatný kanál",
"This channel does not exist.": "Tento kanál neexistuje.",
"Hidden field \"token\" is a required field": "Skryté pole \"token\" je vyžadované",
"Wilson score: ": "Skóre Wilson: ",
"Shared `x`": "Zveřejněno `x`",
"Premieres in `x`": "Premiéra za `x`",
"View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "Zobrazit `x` komentář",
"": "Zobrazit `x` komentářů"
},
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Nepodařilo se přihlásit, ujistěte se, že je povoleno dvoufázové ověřování (autentifikátor nebo SMS).",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Přihlášení selhalo. Toto se může stát, když není na vašem účtu povolené dvoufázové ověřování.",
"Could not get channel info.": "Nepodařilo se získat informace o kanálu.",
"Could not fetch comments": "Nepodařilo se získat komentáře",
"Could not create mix.": "Nepodařilo se vytvořit mix.",
"Hidden field \"challenge\" is a required field": "Skryté pole \"challenge\" je vyžadované",
"Released under the AGPLv3 on Github.": "Vydáno pod licencí AGPLv3 na GitHubu.",
"Hide replies": "Skrýt odpovědi",
"channel:`x`": "kanál: `x`",
"Load more": "Načíst další",
"Not a playlist.": "Není playlist.",
"Playlist does not exist.": "Playlist neexistuje.",
"Erroneous challenge": "Chybná výzva",
"Premieres `x`": "Premiéra `x`",
"CAPTCHA is a required field": "CAPTCHA je vyžadované pole",
"`x` ago": "Před `x`",
"search_message_change_filters_or_query": "Zkuste rozšířit vyhledávaný dotaz a/nebo změnit filtry.",
"search_filters_date_option_none": "Jakékoli datum",
"search_filters_date_label": "Datum nahrání",
"search_filters_type_option_all": "Jakýkoli typ",
"search_filters_duration_option_none": "Jakákoli délka",
"search_filters_type_label": "Typ",
"search_filters_duration_option_short": "Krátká (< 4 minuty)",
"search_message_no_results": "Nenalezeny žádné výsledky.",
"search_filters_title": "Filtry",
"search_filters_duration_option_medium": "Střední (4 - 20 minut)",
"search_filters_duration_option_long": "Dlouhá (> 20 minut)",
"search_message_use_another_instance": " Můžete také <a href=\"`x`\">hledat na jiné instanci</a>.",
"search_filters_features_label": "Vlastnosti",
"search_filters_features_option_three_sixty": "360°",
"search_filters_features_option_vr180": "VR180",
"search_filters_features_option_purchased": "Zakoupeno",
"search_filters_sort_label": "Řadit dle",
"search_filters_sort_option_relevance": "Relevantnost",
"search_filters_apply_button": "Použít vybrané filtry",
"Popular enabled: ": "Populární povoleno: "
}

View File

@ -21,15 +21,15 @@
"No": "Nej",
"Import and Export Data": "Importer og Eksporter Data",
"Import": "Importer",
"Import Invidious data": "Importer Invidious data",
"Import YouTube subscriptions": "Importer YouTube abonnementer",
"Import Invidious data": "Importer Invidious JSON-data",
"Import YouTube subscriptions": "Importer YouTube/OPML-abonnementer",
"Import FreeTube subscriptions (.db)": "Importer FreeTube abonnementer (.db)",
"Import NewPipe subscriptions (.json)": "Importer NewPipe abonnementer (.json)",
"Import NewPipe data (.zip)": "Importer NewPipe data (.zip)",
"Export": "Exporter",
"Export subscriptions as OPML": "Exporter abonnementer som OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exporter abonnementer som OPML (til NewPipe & FreeTube)",
"Export data as JSON": "Exporter data som JSON",
"Export data as JSON": "Eksporter Invidious-data som JSON",
"Delete account?": "Slet konto?",
"History": "Historik",
"An alternative front-end to YouTube": "Et alternativt front-end til YouTube",
@ -66,7 +66,7 @@
"preferences_related_videos_label": "Vis relaterede videoer: ",
"preferences_annotations_label": "Vis annotationer som standard: ",
"preferences_extend_desc_label": "Automatisk udvid videoens beskrivelse: ",
"preferences_vr_mode_label": "Interaktiv 360 graders videoer: ",
"preferences_vr_mode_label": "Interaktive 360 graders videoer (kræver WebGL): ",
"preferences_category_visual": "Visuelle præferencer",
"preferences_player_style_label": "Afspiller stil: ",
"Dark mode: ": "Mørk tilstand: ",
@ -202,7 +202,7 @@
"Hidden field \"challenge\" is a required field": "Det skjulte felt \"challenge\" er et påkrævet felt",
"Albanian": "Albansk",
"preferences_quality_dash_label": "Fortrukket DASH video kvalitet: ",
"live": "Direkte",
"search_filters_features_option_live": "Direkte",
"Lao": "Lao-tse",
"Filipino": "Filippinsk",
"Greek": "Græsk",
@ -213,23 +213,22 @@
"preferences_locale_label": "Sprog: ",
"News": "Nyheder",
"permalink": "permalink",
"date": "Upload dato",
"features": "Funktioner",
"filter": "Filter",
"search_filters_sort_option_date": "Upload dato",
"search_filters_features_label": "Funktioner",
"Khmer": "Khmer",
"Finnish": "Finsk",
"week": "Denne uge",
"search_filters_date_option_week": "Denne uge",
"Korean": "Koreansk",
"Telugu": "Telugu",
"Malayalam": "Malayalam",
"View as playlist": "Se som spilleliste",
"Hungarian": "Ungarsk",
"Welsh": "Walisisk",
"subtitles": "Undertekster/CC",
"search_filters_features_option_subtitles": "Undertekster/CC",
"Bosnian": "Bosnisk",
"Yiddish": "Jiddisch",
"Belarusian": "Belarussisk",
"today": "I dag",
"search_filters_date_option_today": "I dag",
"Shona": "Shona",
"Slovenian": "Slovensk",
"Gaming": "Gaming",
@ -246,35 +245,35 @@
"footer_documentation": "Dokumentation",
"Pashto": "Pashto",
"footer_modfied_source_code": "Modificeret Kildekode",
"Released under the AGPLv3 on Github.": "Udgivet under AGPLv3 på Github.",
"Released under the AGPLv3 on Github.": "Udgivet under AGPLv3 på GitHub.",
"Tajik": "Tadsjikisk",
"month": "Denne måned",
"search_filters_date_option_month": "Denne måned",
"Hebrew": "Hebraisk",
"Kannada": "Kannada",
"Current version: ": "Nuværende version: ",
"Amharic": "Amharisk",
"Swedish": "Svensk",
"Corsican": "Korsikansk",
"movie": "Film",
"search_filters_type_option_movie": "Film",
"Could not pull trending pages.": "Kunne ikke hente trending sider.",
"English": "Engelsk",
"hd": "HD",
"search_filters_features_option_hd": "HD",
"Hausa": "Islandsk",
"year": "Dette år",
"search_filters_date_option_year": "Dette år",
"Japanese": "Japansk",
"content_type": "Type",
"search_filters_type_label": "Type",
"Icelandic": "Islandsk",
"Basque": "Baskisk",
"rating": "Bedømmelse",
"search_filters_sort_option_rating": "Bedømmelse",
"Yoruba": "Yoruba",
"Erroneous token": "Fejlagtig token",
"Videos": "Videoer",
"show": "Vis",
"search_filters_type_option_show": "Vis",
"Luxembourgish": "Luxemboursk",
"Vietnamese": "Vietnamesisk",
"Latvian": "Lettisk",
"Indonesian": "Indonesisk",
"duration": "Varighed",
"search_filters_duration_label": "Varighed",
"footer_original_source_code": "Original kildekode",
"Search": "Søg",
"Serbian": "Serbisk",
@ -289,8 +288,8 @@
"Rating: ": "Bedømmelse: ",
"Movies": "Film",
"YouTube comment permalink": "Youtube kommentarer permalink",
"location": "Lokation",
"hdr": "HDR",
"search_filters_features_option_location": "Lokation",
"search_filters_features_option_hdr": "HDR",
"Cebuano": "Cebuano (Sugbuanon)",
"Nyanja": "Nyanja",
"Chinese (Simplified)": "Kinesisk (forenklet)",
@ -306,11 +305,11 @@
"German": "Tysk",
"Maori": "Maori",
"Slovak": "Slovakisk",
"relevance": "Relevans",
"hour": "Sidste time",
"playlist": "Spilleliste",
"long": "Lang (> 20 minutter)",
"creative_commons": "Creative Commons",
"search_filters_sort_option_relevance": "Relevans",
"search_filters_date_option_hour": "Sidste time",
"search_filters_type_option_playlist": "Spilleliste",
"search_filters_duration_option_long": "Lang (> 20 minutter)",
"search_filters_features_option_c_commons": "Creative Commons",
"Marathi": "Marathi",
"Sindhi": "Sindhi",
"preferences_category_misc": "Diverse indstillinger",
@ -327,8 +326,8 @@
"Western Frisian": "Vestfrisisk",
"Top": "Top",
"Music": "Musik",
"views": "Antal visninger",
"sort": "Sorter efter",
"search_filters_sort_option_views": "Antal visninger",
"search_filters_sort_label": "Sorter efter",
"Zulu": "Zulu",
"Invidious Private Feed for `x`": "Invidious Privat Feed til `x`",
"English (auto-generated)": "Engelsk (autogenereret)",
@ -349,7 +348,6 @@
"next_steps_error_message": "Efter det burde du prøve at: ",
"Sinhala": "Singalesisk (Sinhala)",
"Thai": "Thai",
"Broken? Try another Invidious Instance": "I stykker? Prøv en anden Invidious instans",
"No such user": "Brugeren findes ikke",
"Token is expired, please try again": "Token er udløbet, prøv igen",
"Catalan": "Catalansk",
@ -359,16 +357,16 @@
"Scottish Gaelic": "Skotsk Gælisk",
"Default": "Standard",
"Video mode": "Videotilstand",
"short": "Kort (< 4 minutter)",
"search_filters_duration_option_short": "Kort (< 4 minutter)",
"Hidden field \"token\" is a required field": "Det skjulte felt \"token\" er et påkrævet felt",
"Azerbaijani": "Aserbajdsjansk",
"Georgian": "Georgisk",
"Italian": "Italiensk",
"Audio mode": "Lydtilstand",
"video": "Video",
"channel": "Kanal",
"3d": "3D",
"4k": "4K",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanal",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_four_k": "4K",
"Hmong": "Hmong",
"preferences_quality_option_medium": "Medium",
"preferences_quality_option_small": "Lille",
@ -381,8 +379,8 @@
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"purchased": "Købt",
"360": "360°",
"search_filters_features_option_purchased": "Købt",
"search_filters_features_option_three_sixty": "360°",
"none": "ingen",
"videoinfo_started_streaming_x_ago": "Streamen blev startet for `x`siden",
"videoinfo_watch_on_youTube": "Se på YouTube",
@ -392,11 +390,75 @@
"user_created_playlists": "`x`opretede spillelister",
"user_saved_playlists": "´x`gemte spillelister",
"Video unavailable": "Video ikke tilgængelig",
"preferences_save_player_pos_label": "Gem den nuværende videotid: ",
"preferences_save_player_pos_label": "Gem afspilningsposition: ",
"preferences_quality_dash_option_auto": "Auto",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_option_dash": "DASH (adaptiv kvalitet)",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_240p": "240p"
"preferences_quality_dash_option_240p": "240p",
"subscriptions_unseen_notifs_count": "{{count}} uset notifikation",
"subscriptions_unseen_notifs_count_plural": "{{count}} usete notifikationer",
"comments_view_x_replies": "Vis {{count}} svar",
"comments_view_x_replies_plural": "Vis {{count}} svar",
"comments_points_count": "{{count}} point",
"comments_points_count_plural": "{{count}} point",
"generic_count_years": "{{count}} år",
"generic_count_years_plural": "{{count}} år",
"generic_count_months": "{{count}} måned",
"generic_count_months_plural": "{{count}} måneder",
"generic_count_days": "{{count}} dag",
"generic_count_days_plural": "{{count}} dage",
"generic_count_minutes": "{{count}} minut",
"generic_count_minutes_plural": "{{count}} minutter",
"generic_count_seconds": "{{count}} sekund",
"generic_count_seconds_plural": "{{count}} sekunder",
"generic_subscribers_count": "{{count}} abonnent",
"generic_subscribers_count_plural": "{{count}} abonnenter",
"generic_subscriptions_count": "{{count}} abonnement",
"generic_subscriptions_count_plural": "{{count}} abonnementer",
"generic_videos_count": "{{count}} video",
"generic_videos_count_plural": "{{count}} videoer",
"English (United States)": "Engelsk (USA)",
"French (auto-generated)": "Fransk (autogenereret)",
"Spanish (auto-generated)": "Spansk (autogenereret)",
"crash_page_before_reporting": "Før du rapporterer en fejl, skal du sikre dig, at du har:",
"crash_page_refresh": "forsøgte at <a href=\"`x`\">opdatere siden</a>",
"generic_playlists_count": "{{count}} spilleliste",
"generic_playlists_count_plural": "{{count}} spillelister",
"preferences_watch_history_label": "Aktiver afspilningshistorik: ",
"tokens_count": "{{count}} token",
"tokens_count_plural": "{{count}} tokens",
"Cantonese (Hong Kong)": "Kantonesisk (Hongkong)",
"Chinese": "Kinesisk",
"Chinese (China)": "Kinesisk (Kina)",
"Chinese (Hong Kong)": "Kinesisk (Hongkong)",
"Chinese (Taiwan)": "Kinesisk (Taiwan)",
"Dutch (auto-generated)": "Hollandsk (autogenereret)",
"Indonesian (auto-generated)": "Indonesisk (autogenereret)",
"Interlingue": "Interlingue",
"Japanese (auto-generated)": "Japansk (autogenereret)",
"Korean (auto-generated)": "Koreansk (autogenereret)",
"Russian (auto-generated)": "Russisk (autogenereret)",
"Turkish (auto-generated)": "Tyrkisk (autogenereret)",
"Vietnamese (auto-generated)": "Vietnamesisk (autogenereret)",
"crash_page_report_issue": "Hvis intet af ovenstående hjalp, bedes du <a href=\"`x`\">åbne et nyt problem på GitHub</a> (helst på engelsk) og inkludere følgende tekst i din besked (oversæt IKKE denne tekst):",
"English (United Kingdom)": "Engelsk (Storbritannien)",
"Italian (auto-generated)": "Italiensk (autogenereret)",
"Portuguese (auto-generated)": "Portugisisk (autogenereret)",
"Portuguese (Brazil)": "Portugisisk (Brasilien)",
"generic_views_count": "{{count}} visning",
"generic_views_count_plural": "{{count}} visninger",
"generic_count_hours": "{{count}} time",
"generic_count_hours_plural": "{{count}} timer",
"Spanish (Spain)": "Spansk (Spanien)",
"crash_page_switch_instance": "forsøgte at <a href=\"`x`\">bruge en anden instans</a>",
"German (auto-generated)": "Tysk (autogenereret)",
"Spanish (Mexico)": "Spansk (Mexico)",
"generic_count_weeks": "{{count}} uge",
"generic_count_weeks_plural": "{{count}} uger",
"crash_page_you_found_a_bug": "Det ser ud til, at du har fundet en fejl i Invidious!",
"crash_page_read_the_faq": "læs <a href=\"`x`\">Ofte stillede spørgsmål (FAQ)</a>",
"crash_page_search_issue": "søgte efter <a href=\"`x`\">eksisterende problemer på GitHub</a>",
"search_filters_title": "Filter"
}

View File

@ -21,15 +21,15 @@
"No": "Nein",
"Import and Export Data": "Daten importieren und exportieren",
"Import": "Importieren",
"Import Invidious data": "Invidious Daten importieren",
"Import YouTube subscriptions": "YouTube Abonnements importieren",
"Import Invidious data": "Invidious-JSON-Daten importieren",
"Import YouTube subscriptions": "YouTube-/OPML-Abonnements importieren",
"Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)",
"Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)",
"Export": "Exportieren",
"Export subscriptions as OPML": "Abonnements als OPML exportieren",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)",
"Export data as JSON": "Daten als JSON exportieren",
"Export data as JSON": "Invidious-Daten als JSON exportieren",
"Delete account?": "Konto löschen?",
"History": "Verlauf",
"An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube",
@ -51,10 +51,10 @@
"preferences_category_player": "Wiedergabeeinstellungen",
"preferences_video_loop_label": "Immer wiederholen: ",
"preferences_autoplay_label": "Automatisch abspielen: ",
"preferences_continue_label": "Immer automatisch nächstes Video spielen: ",
"preferences_continue_autoplay_label": "nächstes Video automatisch abspielen: ",
"preferences_continue_label": "Immer automatisch nächstes Video abspielen: ",
"preferences_continue_autoplay_label": "Nächstes Video automatisch abspielen: ",
"preferences_listen_label": "Nur Ton als Standard: ",
"preferences_local_label": "Proxy-Videos: ",
"preferences_local_label": "Videos durch Proxy leiten: ",
"preferences_speed_label": "Standardgeschwindigkeit: ",
"preferences_quality_label": "Bevorzugte Videoqualität: ",
"preferences_volume_label": "Wiedergabelautstärke: ",
@ -63,12 +63,12 @@
"reddit": "Reddit",
"preferences_captions_label": "Standarduntertitel: ",
"Fallback captions: ": "Ersatzuntertitel: ",
"preferences_related_videos_label": "Ähnliche Videos anzeigen? ",
"preferences_annotations_label": "Standardmäßig Anmerkungen anzeigen? ",
"preferences_related_videos_label": "Ähnliche Videos anzeigen: ",
"preferences_annotations_label": "Anmerkungen standardmäßig anzeigen: ",
"preferences_extend_desc_label": "Videobeschreibung automatisch erweitern: ",
"preferences_vr_mode_label": "Interaktive 360 Grad Videos: ",
"preferences_vr_mode_label": "Interaktive 360-Grad-Videos (erfordert WebGL): ",
"preferences_category_visual": "Anzeigeeinstellungen",
"preferences_player_style_label": "Abspielgeräterstil: ",
"preferences_player_style_label": "Player-Stil: ",
"Dark mode: ": "Nachtmodus: ",
"preferences_dark_mode_label": "Modus: ",
"dark": "Nachtmodus",
@ -121,7 +121,7 @@
"Subscriptions": "Abonnements",
"search": "Suchen",
"Log out": "Abmelden",
"Released under the AGPLv3 on Github.": "Auf Github unter der AGPLv3 Lizenz veröffentlicht.",
"Released under the AGPLv3 on Github.": "Auf GitHub unter der AGPLv3 Lizenz veröffentlicht.",
"Source available here.": "Quellcode verfügbar hier.",
"View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.",
"View privacy policy.": "Datenschutzerklärung einsehen.",
@ -141,7 +141,6 @@
"Show less": "Weniger anzeigen",
"Watch on YouTube": "Video auf YouTube ansehen",
"Switch Invidious Instance": "Invidious Instanz wechseln",
"Broken? Try another Invidious Instance": "Funktioniert nicht? Probiere eine andere Invidious Instanz aus",
"Hide annotations": "Anmerkungen ausblenden",
"Show annotations": "Anmerkungen anzeigen",
"Genre: ": "Genre: ",
@ -329,47 +328,46 @@
"Videos": "Videos",
"Playlists": "Wiedergabelisten",
"Community": "Gemeinschaft",
"relevance": "Relevanz",
"rating": "Bewertung",
"date": "Datum",
"views": "Aufrufe",
"content_type": "Inhaltstyp",
"duration": "Dauer",
"features": "Eigenschaften",
"sort": "sortieren",
"hour": "Letzte Stunde",
"today": "Heute",
"week": "Diese Woche",
"month": "Diesen Monat",
"year": "Dieses Jahr",
"video": "Video",
"channel": "Kanal",
"playlist": "Wiedergabeliste",
"movie": "Film",
"show": "Anzeigen",
"hd": "HD",
"subtitles": "Untertitel / CC",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Live",
"4k": "4K",
"location": "Standort",
"hdr": "HDR",
"filter": "Filtern",
"search_filters_sort_option_relevance": "Relevanz",
"search_filters_sort_option_rating": "Bewertung",
"search_filters_sort_option_date": "Datum",
"search_filters_sort_option_views": "Aufrufe",
"search_filters_type_label": "Inhaltstyp",
"search_filters_duration_label": "Dauer",
"search_filters_features_label": "Eigenschaften",
"search_filters_sort_label": "sortieren",
"search_filters_date_option_hour": "Letzte Stunde",
"search_filters_date_option_today": "Heute",
"search_filters_date_option_week": "Diese Woche",
"search_filters_date_option_month": "Diesen Monat",
"search_filters_date_option_year": "Dieses Jahr",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Wiedergabeliste",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Anzeigen",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Untertitel / CC",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Live",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Standort",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Aktuelle Version: ",
"next_steps_error_message": "Danach folgendes versuchen: ",
"next_steps_error_message_refresh": "Aktualisieren",
"next_steps_error_message_go_to_youtube": "Zu YouTube gehen",
"footer_donate_page": "Spende",
"long": "Lang (> 20 Minuten)",
"search_filters_duration_option_long": "Lang (> 20 Minuten)",
"footer_original_source_code": "Original Quellcode",
"footer_modfied_source_code": "Modifizierter Quellcode",
"footer_documentation": "Dokumentation",
"footer_source_code": "Quellcode",
"adminprefs_modified_source_code_url_label": "URL zum Repositorie des modifizierten Quellcodes",
"short": "Kurz (< 4 Minuten)",
"search_filters_duration_option_short": "Kurz (< 4 Minuten)",
"preferences_region_label": "Land der Inhalte: ",
"preferences_quality_option_dash": "DASH (automatische Qualität)",
"preferences_quality_option_dash": "DASH (adaptive Qualität)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "Mittel",
"preferences_quality_option_small": "Niedrig",
@ -388,15 +386,90 @@
"Video unavailable": "Video nicht verfügbar",
"user_created_playlists": "`x` Wiedergabelisten erstellt",
"user_saved_playlists": "`x` Wiedergabelisten gespeichert",
"preferences_save_player_pos_label": "Aktuelle Position speichern: ",
"360": "360°",
"preferences_save_player_pos_label": "Wiedergabeposition speichern: ",
"search_filters_features_option_three_sixty": "360°",
"preferences_quality_dash_option_best": "Höchste",
"preferences_quality_dash_option_worst": "Niedrigste",
"preferences_quality_dash_option_1440p": "1440p",
"videoinfo_youTube_embed_link": "Eingebettet",
"purchased": "Gekauft",
"search_filters_features_option_purchased": "Gekauft",
"none": "keine",
"videoinfo_started_streaming_x_ago": "Stream begann vor `x`",
"videoinfo_watch_on_youTube": "Auf YouTube ansehen",
"preferences_quality_dash_label": "Bevorzugte DASH-Videoqualität: "
"preferences_quality_dash_label": "Bevorzugte DASH-Videoqualität: ",
"generic_subscribers_count": "{{count}} Abonnent",
"generic_subscribers_count_plural": "{{count}} Abonnenten",
"generic_videos_count": "{{count}} Video",
"generic_videos_count_plural": "{{count}} Videos",
"subscriptions_unseen_notifs_count": "{{count}} ungesehene Benachrichtung",
"subscriptions_unseen_notifs_count_plural": "{{count}} ungesehene Benachrichtungen",
"crash_page_refresh": "Versucht haben, <a href=\"`x`\">die Seite neu zu laden</a>",
"comments_view_x_replies": "{{count}} Antwort anzeigen",
"comments_view_x_replies_plural": "{{count}} Antworten anzeigen",
"generic_count_years": "{{count}} Jahr",
"generic_count_years_plural": "{{count}} Jahre",
"generic_count_weeks": "{{count}} Woche",
"generic_count_weeks_plural": "{{count}} Wochen",
"generic_count_days": "{{count}} Tag",
"generic_count_days_plural": "{{count}} Tage",
"crash_page_before_reporting": "Bevor Sie einen Bug melden, stellen Sie sicher, dass Sie:",
"crash_page_switch_instance": "Eine <a href=\"`x`\">andere Instanz</a> versucht haben",
"generic_count_hours": "{{count}} Stunde",
"generic_count_hours_plural": "{{count}} Stunden",
"generic_count_minutes": "{{count}} Minute",
"generic_count_minutes_plural": "{{count}} Minuten",
"crash_page_read_the_faq": "Das <a href=\"`x`\">FAQ</a> gelesen haben",
"crash_page_search_issue": "Nach <a href=\"`x`\">bereits gemeldeten Bugs auf GitHub</a> gesucht haben",
"crash_page_report_issue": "Wenn all dies nicht geholfen hat, <a href=\"`x`\">öffnen Sie bitte ein neues Problem (issue) auf Github</a> (vorzugsweise auf Englisch) und fügen Sie den folgenden Text in Ihre Nachricht ein (bitte übersetzen Sie diesen Text NICHT):",
"generic_views_count": "{{count}} Aufruf",
"generic_views_count_plural": "{{count}} Aufrufe",
"generic_count_seconds": "{{count}} Sekunde",
"generic_count_seconds_plural": "{{count}} Sekunden",
"generic_subscriptions_count": "{{count}} Abo",
"generic_subscriptions_count_plural": "{{count}} Abos",
"tokens_count": "{{count}} Token",
"tokens_count_plural": "{{count}} Tokens",
"comments_points_count": "{{count}} Punkt",
"comments_points_count_plural": "{{count}} Punkte",
"crash_page_you_found_a_bug": "Anscheinend haben Sie einen Fehler in Invidious gefunden!",
"generic_count_months": "{{count}} Monat",
"generic_count_months_plural": "{{count}} Monate",
"Cantonese (Hong Kong)": "Kantonesisch (Hong Kong)",
"Chinese (Hong Kong)": "Chinesisch (Hong Kong)",
"generic_playlists_count": "{{count}} Wiedergabeliste",
"generic_playlists_count_plural": "{{count}} Wiedergabelisten",
"preferences_watch_history_label": "Wiedergabeverlauf aktivieren: ",
"English (United Kingdom)": "Englisch (Vereinigtes Königreich)",
"English (United States)": "Englisch (Vereinigte Staaten)",
"Dutch (auto-generated)": "Niederländisch (automatisch generiert)",
"French (auto-generated)": "Französisch (automatisch generiert)",
"German (auto-generated)": "Deutsch (automatisch generiert)",
"Indonesian (auto-generated)": "Indonesisch (automatisch generiert)",
"Interlingue": "Interlingue",
"Italian (auto-generated)": "Italienisch (automatisch generiert)",
"Japanese (auto-generated)": "Japanisch (automatisch generiert)",
"Spanish (Mexico)": "Spanisch (Mexiko)",
"Spanish (Spain)": "Spanisch (Spanien)",
"Vietnamese (auto-generated)": "Vietnamesisch (automatisch generiert)",
"Russian (auto-generated)": "Russisch (automatisch generiert)",
"Chinese": "Chinesisch",
"Portuguese (Brazil)": "Portugiesisch (Brasilien)",
"Spanish (auto-generated)": "Spanisch (automatisch generiert)",
"Turkish (auto-generated)": "Türkisch (automatisch generiert)",
"Chinese (China)": "Chinesisch (China)",
"Chinese (Taiwan)": "Chinesisch (Taiwan)",
"Korean (auto-generated)": "Koreanisch (automatisch generiert)",
"Portuguese (auto-generated)": "Portugiesisch (automatisch generiert)",
"search_filters_title": "Filtern",
"search_message_change_filters_or_query": "Versuchen Sie, Ihre Suchanfrage zu erweitern und/oder die Filter zu ändern.",
"search_message_use_another_instance": " Sie können auch <a href=\"`x`\">auf einer anderen Instanz suchen</a>.",
"Popular enabled: ": "„Beliebt“-Seite aktiviert: ",
"search_message_no_results": "Keine Ergebnisse gefunden.",
"search_filters_duration_option_medium": "Mittel (4 - 20 Minuten)",
"search_filters_features_option_vr180": "VR180",
"search_filters_type_option_all": "Beliebiger Typ",
"search_filters_apply_button": "Ausgewählte Filter anwenden",
"search_filters_duration_option_none": "Beliebige Länge",
"search_filters_date_label": "Upload-Datum",
"search_filters_date_option_none": "Beliebiges Datum"
}

View File

@ -358,7 +358,7 @@
"crash_page_before_reporting": "Πριν αναφέρετε ένα σφάλμα, βεβαιωθείτε ότι έχετε:",
"crash_page_refresh": "προσπαθήσει να <a href=\"`x`\">ανανεώσετε τη σελίδα</a>",
"crash_page_read_the_faq": "διαβάσει τις <a href=\"`x`\">Συχνές Ερωτήσεις (ΣΕ)</a>",
"crash_page_search_issue": "αναζητήσει για <a href=\"`x`\">υπάρχοντα θέματα στο Github</a>",
"crash_page_search_issue": "αναζητήσει για <a href=\"`x`\">υπάρχοντα θέματα στο GitHub</a>",
"generic_views_count": "{{count}} προβολή",
"generic_views_count_plural": "{{count}} προβολές",
"generic_videos_count": "{{count}} βίντεο",
@ -373,51 +373,50 @@
"preferences_region_label": "Χώρα περιεχομένου: ",
"preferences_category_misc": "Διάφορες προτιμήσεις",
"Show more": "Εμφάνιση περισσότερων",
"today": "Σήμερα",
"360": "360°",
"search_filters_date_option_today": "Σήμερα",
"search_filters_features_option_three_sixty": "360°",
"videoinfo_started_streaming_x_ago": "Ξεκίνησε η ροή `x` πριν από",
"videoinfo_watch_on_youTube": "Παρακολουθήστε στο YouTube",
"download_subtitles": "Υπότιτλοι - `x` (.vtt)",
"user_created_playlists": "`x` δημιουργημένες λίστες αναπαραγωγής",
"user_saved_playlists": "`x` αποθηκευμένες λίστες αναπαραγωγής",
"rating": "Αξιολόγηση",
"relevance": "Συνάφεια",
"purchased": "Αγορασμένο",
"date": "Ημερομηνία μεταφόρτωσης",
"content_type": "Τύπος",
"duration": "Διάρκεια",
"week": "Αυτή την εβδομάδα",
"year": "Φέτος",
"channel": "Κανάλι",
"playlist": "Λίστα αναπαραγωγής",
"long": "Μεγάλο (> 20 λεπτά)",
"hd": "HD",
"location": "Τοποθεσία",
"3d": "3D",
"search_filters_sort_option_rating": "Αξιολόγηση",
"search_filters_sort_option_relevance": "Συνάφεια",
"search_filters_features_option_purchased": "Αγορασμένο",
"search_filters_sort_option_date": "Ημερομηνία μεταφόρτωσης",
"search_filters_type_label": "Τύπος",
"search_filters_duration_label": "Διάρκεια",
"search_filters_date_option_week": "Αυτή την εβδομάδα",
"search_filters_date_option_year": "Φέτος",
"search_filters_type_option_channel": "Κανάλι",
"search_filters_type_option_playlist": "Λίστα αναπαραγωγής",
"search_filters_duration_option_long": "Μεγάλο (> 20 λεπτά)",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_location": "Τοποθεσία",
"search_filters_features_option_three_d": "3D",
"next_steps_error_message": "Μετά από αυτό θα πρέπει να προσπαθήσετε να: ",
"next_steps_error_message_go_to_youtube": "Μεταβείτε στο YouTube",
"footer_donate_page": "Δωρεά",
"footer_original_source_code": "Πρωτότυπος πηγαίος κώδικας",
"preferences_show_nick_label": "Εμφάνιση ψευδώνυμου στην κορυφή: ",
"hour": "Τελευταία ώρα",
"search_filters_date_option_hour": "Τελευταία ώρα",
"adminprefs_modified_source_code_url_label": "URL σε αποθετήριο τροποποιημένου πηγαίου κώδικα",
"subtitles": "Υπότιτλοι/CC",
"month": "Αυτόν τον μήνα",
"Released under the AGPLv3 on Github.": "Κυκλοφορεί υπό την AGPLv3 στο Github.",
"sort": "Ταξινόμηση κατά",
"filter": "Φίλτρο",
"movie": "Ταινία",
"search_filters_features_option_subtitles": "Υπότιτλοι/CC",
"search_filters_date_option_month": "Αυτόν τον μήνα",
"Released under the AGPLv3 on Github.": "Κυκλοφορεί υπό την AGPLv3 στο GitHub.",
"search_filters_sort_label": "Ταξινόμηση κατά",
"search_filters_type_option_movie": "Ταινία",
"footer_modfied_source_code": "Τροποποιημένος πηγαίος κώδικας",
"features": "Χαρακτηριστικά",
"4k": "4K",
"search_filters_features_label": "Χαρακτηριστικά",
"search_filters_features_option_four_k": "4K",
"footer_documentation": "Τεκμηρίωση",
"short": "Σύντομο (< 4 λεπτά)",
"search_filters_duration_option_short": "Σύντομο (< 4 λεπτά)",
"next_steps_error_message_refresh": "Ανανέωση",
"video": "Βίντεο",
"live": "Ζωντανά",
"creative_commons": "Creative Commons",
"search_filters_type_option_video": "Βίντεο",
"search_filters_features_option_live": "Ζωντανά",
"search_filters_features_option_c_commons": "Creative Commons",
"Search": "Αναζήτηση",
"hdr": "HDR",
"search_filters_features_option_hdr": "HDR",
"preferences_extend_desc_label": "Αυτόματη επέκταση της περιγραφής του βίντεο: ",
"preferences_vr_mode_label": "Διαδραστικά βίντεο 360 μοιρών (απαιτεί WebGL): ",
"Show less": "Εμφάνιση λιγότερων",
@ -448,5 +447,8 @@
"none": "κανένα",
"videoinfo_youTube_embed_link": "Ενσωμάτωση",
"videoinfo_invidious_embed_link": "Σύνδεσμος Ενσωμάτωσης",
"show": "Μπάρα προόδου διαβάσματος"
"search_filters_type_option_show": "Μπάρα προόδου διαβάσματος",
"preferences_watch_history_label": "Ενεργοποίηση ιστορικού παρακολούθησης: ",
"search_filters_title": "Φίλτρο",
"search_message_no_results": "Δεν"
}

View File

@ -66,10 +66,9 @@
"preferences_listen_label": "Listen by default: ",
"preferences_local_label": "Proxy videos: ",
"preferences_watch_history_label": "Enable watch history: ",
"preferences_notifications_label": "Enable notifications: ",
"preferences_speed_label": "Default speed: ",
"preferences_quality_label": "Preferred video quality: ",
"preferences_quality_option_dash": "DASH (adaptative quality)",
"preferences_quality_option_dash": "DASH (adaptive quality)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "Medium",
"preferences_quality_option_small": "Small",
@ -137,6 +136,7 @@
"preferences_default_home_label": "Default homepage: ",
"preferences_feed_menu_label": "Feed menu: ",
"preferences_show_nick_label": "Show nickname on top: ",
"Popular enabled: ": "Popular enabled: ",
"Top enabled: ": "Top enabled: ",
"CAPTCHA enabled: ": "CAPTCHA enabled: ",
"Login enabled: ": "Login enabled: ",
@ -156,7 +156,7 @@
"subscriptions_unseen_notifs_count_plural": "{{count}} unseen notifications",
"search": "search",
"Log out": "Log out",
"Released under the AGPLv3 on Github.": "Released under the AGPLv3 on Github.",
"Released under the AGPLv3 on Github.": "Released under the AGPLv3 on GitHub.",
"Source available here.": "Source available here.",
"View JavaScript license information.": "View JavaScript license information.",
"View privacy policy.": "View privacy policy.",
@ -176,7 +176,9 @@
"Show less": "Show less",
"Watch on YouTube": "Watch on YouTube",
"Switch Invidious Instance": "Switch Invidious Instance",
"Broken? Try another Invidious Instance": "Broken? Try another Invidious Instance",
"search_message_no_results": "No results found.",
"search_message_change_filters_or_query": "Try widening your search query and/or changing the filters.",
"search_message_use_another_instance": " You can also <a href=\"`x`\">search on another instance</a>.",
"Hide annotations": "Hide annotations",
"Show annotations": "Show annotations",
"Genre: ": "Genre: ",
@ -405,37 +407,44 @@
"Videos": "Videos",
"Playlists": "Playlists",
"Community": "Community",
"relevance": "Relevance",
"rating": "Rating",
"date": "Upload date",
"views": "View count",
"content_type": "Type",
"duration": "Duration",
"features": "Features",
"sort": "Sort By",
"hour": "Last Hour",
"today": "Today",
"week": "This week",
"month": "This month",
"year": "This year",
"video": "Video",
"channel": "Channel",
"playlist": "Playlist",
"movie": "Movie",
"show": "Show",
"short": "Short (< 4 minutes)",
"long": "Long (> 20 minutes)",
"hd": "HD",
"subtitles": "Subtitles/CC",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Live",
"4k": "4K",
"location": "Location",
"hdr": "HDR",
"purchased": "Purchased",
"360": "360°",
"filter": "Filter",
"search_filters_title": "Filters",
"search_filters_date_label": "Upload date",
"search_filters_date_option_none": "Any date",
"search_filters_date_option_hour": "Last Hour",
"search_filters_date_option_today": "Today",
"search_filters_date_option_week": "This week",
"search_filters_date_option_month": "This month",
"search_filters_date_option_year": "This year",
"search_filters_type_label": "Type",
"search_filters_type_option_all": "Any type",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Channel",
"search_filters_type_option_playlist": "Playlist",
"search_filters_type_option_movie": "Movie",
"search_filters_type_option_show": "Show",
"search_filters_duration_label": "Duration",
"search_filters_duration_option_none": "Any duration",
"search_filters_duration_option_short": "Short (< 4 minutes)",
"search_filters_duration_option_medium": "Medium (4 - 20 minutes)",
"search_filters_duration_option_long": "Long (> 20 minutes)",
"search_filters_features_label": "Features",
"search_filters_features_option_live": "Live",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Subtitles/CC",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_sixty": "360°",
"search_filters_features_option_vr180": "VR180",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_hdr": "HDR",
"search_filters_features_option_location": "Location",
"search_filters_features_option_purchased": "Purchased",
"search_filters_sort_label": "Sort By",
"search_filters_sort_option_relevance": "Relevance",
"search_filters_sort_option_rating": "Rating",
"search_filters_sort_option_date": "Upload Date",
"search_filters_sort_option_views": "View count",
"search_filters_apply_button": "Apply selected filters",
"Current version: ": "Current version: ",
"next_steps_error_message": "After which you should try to: ",
"next_steps_error_message_refresh": "Refresh",
@ -460,7 +469,7 @@
"crash_page_before_reporting": "Before reporting a bug, make sure that you have:",
"crash_page_refresh": "tried to <a href=\"`x`\">refresh the page</a>",
"crash_page_switch_instance": "tried to <a href=\"`x`\">use another instance</a>",
"crash_page_read_the_faq": "read the <a href=\"`x`\">Frenquently Asked Questions (FAQ)</a>",
"crash_page_search_issue": "searched for <a href=\"`x`\">existing issues on Github</a>",
"crash_page_read_the_faq": "read the <a href=\"`x`\">Frequently Asked Questions (FAQ)</a>",
"crash_page_search_issue": "searched for <a href=\"`x`\">existing issues on GitHub</a>",
"crash_page_report_issue": "If none of the above helped, please <a href=\"`x`\">open a new issue on GitHub</a> (preferably in English) and include the following text in your message (do NOT translate that text):"
}

View File

@ -121,7 +121,7 @@
"Subscriptions": "Abonoj",
"search": "serĉi",
"Log out": "Elsaluti",
"Released under the AGPLv3 on Github.": "Eldonita sub la AGPLv3 en Github.",
"Released under the AGPLv3 on Github.": "Eldonita sub la AGPLv3 en GitHub.",
"Source available here.": "Fonto havebla ĉi tie.",
"View JavaScript license information.": "Vidi Ĝavoskriptan licencan informon.",
"View privacy policy.": "Vidi regularon pri privateco.",
@ -141,7 +141,6 @@
"Show less": "Montri malpli",
"Watch on YouTube": "Vidi filmeton en JuTubo",
"Switch Invidious Instance": "Ŝanĝi instalaĵon de Indivious",
"Broken? Try another Invidious Instance": "Ĉu misfunkcio? Provu alian instalaĵon de Indivious",
"Hide annotations": "Kaŝi prinotojn",
"Show annotations": "Montri prinotojn",
"Genre: ": "Ĝenro: ",
@ -329,39 +328,38 @@
"Videos": "Filmetoj",
"Playlists": "Ludlistoj",
"Community": "Komunumo",
"relevance": "rilateco",
"rating": "takso",
"date": "dato",
"views": "vidoj",
"content_type": "enhavtipo",
"duration": "daŭro",
"features": "trajtoj",
"sort": "ordigi",
"hour": "horo",
"today": "hodiaŭ",
"week": "semajno",
"month": "monato",
"year": "jaro",
"video": "filmeto",
"channel": "kanalo",
"playlist": "ludlisto",
"movie": "filmo",
"show": "spektaĵo",
"hd": "altdistingiva",
"subtitles": "subtekstoj",
"creative_commons": "Krea Komunaĵo",
"3d": "3D",
"live": "nuna",
"4k": "4k",
"location": "loko",
"hdr": "granddinamikgama",
"filter": "filtri",
"search_filters_sort_option_relevance": "rilateco",
"search_filters_sort_option_rating": "takso",
"search_filters_sort_option_date": "dato",
"search_filters_sort_option_views": "vidoj",
"search_filters_type_label": "enhavtipo",
"search_filters_duration_label": "daŭro",
"search_filters_features_label": "trajtoj",
"search_filters_sort_label": "ordigi",
"search_filters_date_option_hour": "horo",
"search_filters_date_option_today": "hodiaŭ",
"search_filters_date_option_week": "semajno",
"search_filters_date_option_month": "monato",
"search_filters_date_option_year": "jaro",
"search_filters_type_option_video": "filmeto",
"search_filters_type_option_channel": "kanalo",
"search_filters_type_option_playlist": "ludlisto",
"search_filters_type_option_movie": "filmo",
"search_filters_type_option_show": "spektaĵo",
"search_filters_features_option_hd": "altdistingiva",
"search_filters_features_option_subtitles": "subtekstoj",
"search_filters_features_option_c_commons": "Krea Komunaĵo",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "nuna",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "loko",
"search_filters_features_option_hdr": "granddinamikgama",
"Current version: ": "Nuna versio: ",
"next_steps_error_message": "Poste, vi provu: ",
"next_steps_error_message_refresh": "Reŝargi",
"next_steps_error_message_go_to_youtube": "Iri al JuTubo",
"long": "Longa (> 20 minutos)",
"short": "Mallonga (< 4 minutos)",
"search_filters_duration_option_long": "Longa (> 20 minutos)",
"search_filters_duration_option_short": "Mallonga (< 4 minutos)",
"footer_documentation": "Dokumentaro",
"footer_source_code": "Fontkodo",
"adminprefs_modified_source_code_url_label": "URL al modifita deponejo de fontkodo",
@ -369,5 +367,6 @@
"footer_original_source_code": "Originala fontkodo",
"footer_donate_page": "Donaci",
"preferences_region_label": "Lando de la enhavo: ",
"preferences_quality_dash_label": "Preferata DASH-a videkvalito: "
"preferences_quality_dash_label": "Preferata DASH-a videkvalito: ",
"search_filters_title": "Filtri"
}

View File

@ -121,7 +121,7 @@
"Subscriptions": "Suscripciones",
"search": "buscar",
"Log out": "Cerrar la sesión",
"Released under the AGPLv3 on Github.": "Publicado bajo la AGPLv3 en Github.",
"Released under the AGPLv3 on Github.": "Publicado bajo la AGPLv3 en GitHub.",
"Source available here.": "Código fuente disponible aquí.",
"View JavaScript license information.": "Ver información de licencia de JavaScript.",
"View privacy policy.": "Ver la política de privacidad.",
@ -141,7 +141,6 @@
"Show less": "Mostrar menos",
"Watch on YouTube": "Ver el vídeo en YouTube",
"Switch Invidious Instance": "Cambiar Instancia de Invidious",
"Broken? Try another Invidious Instance": "¿Algún error? Prueba otra instancia de Invidious",
"Hide annotations": "Ocultar anotaciones",
"Show annotations": "Mostrar anotaciones",
"Genre: ": "Género: ",
@ -196,7 +195,7 @@
"Hidden field \"token\" is a required field": "El campo oculto «símbolo» es un campo obligatorio",
"Erroneous challenge": "Desafío no válido",
"Erroneous token": "Símbolo no válido",
"No such user": "Usuario no válido",
"No such user": "Usuario no existe",
"Token is expired, please try again": "El símbolo ha caducado, inténtelo de nuevo",
"English": "Inglés",
"English (auto-generated)": "Inglés (generados automáticamente)",
@ -329,39 +328,38 @@
"Videos": "Vídeos",
"Playlists": "Listas de reproducción",
"Community": "Comunidad",
"relevance": "relevancia",
"rating": "valoración",
"date": "fecha",
"views": "visualizaciones",
"content_type": "content_type",
"duration": "duración",
"features": "funcionalidades",
"sort": "ordenar",
"hour": "hora",
"today": "hoy",
"week": "semana",
"month": "mes",
"year": "año",
"video": "vídeo",
"channel": "canal",
"playlist": "lista de reproducción",
"movie": "película",
"show": "programa",
"hd": "hd",
"subtitles": "subtítulos",
"creative_commons": "creative_commons",
"3d": "3d",
"live": "directo",
"4k": "4k",
"location": "ubicación",
"hdr": "hdr",
"filter": "filtro",
"search_filters_sort_option_relevance": "relevancia",
"search_filters_sort_option_rating": "valoración",
"search_filters_sort_option_date": "fecha",
"search_filters_sort_option_views": "visualizaciones",
"search_filters_type_label": "content_type",
"search_filters_duration_label": "duración",
"search_filters_features_label": "funcionalidades",
"search_filters_sort_label": "ordenar",
"search_filters_date_option_hour": "hora",
"search_filters_date_option_today": "hoy",
"search_filters_date_option_week": "semana",
"search_filters_date_option_month": "mes",
"search_filters_date_option_year": "año",
"search_filters_type_option_video": "vídeo",
"search_filters_type_option_channel": "canal",
"search_filters_type_option_playlist": "lista de reproducción",
"search_filters_type_option_movie": "película",
"search_filters_type_option_show": "programa",
"search_filters_features_option_hd": "hd",
"search_filters_features_option_subtitles": "subtítulos",
"search_filters_features_option_c_commons": "creative_commons",
"search_filters_features_option_three_d": "3d",
"search_filters_features_option_live": "directo",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "ubicación",
"search_filters_features_option_hdr": "hdr",
"Current version: ": "Versión actual: ",
"next_steps_error_message": "Después de lo cual deberías intentar: ",
"next_steps_error_message_refresh": "Recargar",
"next_steps_error_message_refresh": "Recargar la página",
"next_steps_error_message_go_to_youtube": "Ir a YouTube",
"short": "Corto (< 4 minutos)",
"long": "Largo (> 20 minutos)",
"search_filters_duration_option_short": "Corto (< 4 minutos)",
"search_filters_duration_option_long": "Largo (> 20 minutos)",
"footer_documentation": "Documentación",
"footer_original_source_code": "Código fuente original",
"adminprefs_modified_source_code_url_label": "URL al repositorio de código fuente modificado",
@ -395,8 +393,8 @@
"preferences_quality_dash_option_worst": "La peor",
"videoinfo_invidious_embed_link": "Enlace para Insertar",
"preferences_quality_dash_option_1080p": "1080p",
"purchased": "Comprado",
"360": "360°",
"search_filters_features_option_purchased": "Comprado",
"search_filters_features_option_three_sixty": "360°",
"videoinfo_watch_on_youTube": "Ver en YouTube",
"preferences_save_player_pos_label": "Guardar posición de reproducción: ",
"generic_views_count": "{{count}} visualización",
@ -432,7 +430,7 @@
"crash_page_before_reporting": "Antes de notificar un error asegúrate de que has:",
"crash_page_switch_instance": "probado a <a href=\"`x`\">usar otra instancia</a>",
"crash_page_read_the_faq": "leído las <a href=\"`x`\">Preguntas Frecuentes</a>",
"crash_page_search_issue": "buscado <a href=\"`x`\">problemas existentes en Github</a>",
"crash_page_search_issue": "buscado <a href=\"`x`\">problemas existentes en GitHub</a>",
"crash_page_you_found_a_bug": "¡Parece que has encontrado un error en Invidious!",
"crash_page_refresh": "probado a <a href=\"`x`\">recargar la página</a>",
"crash_page_report_issue": "Si nada de lo anterior ha sido de ayuda, por favor, <a href=\"`x`\">abre una nueva incidencia en GitHub</a> (preferiblemente en inglés) e incluye el siguiente texto en tu mensaje (NO traduzcas este texto):",
@ -459,5 +457,18 @@
"Korean (auto-generated)": "Coreano (generados automáticamente)",
"Spanish (Mexico)": "Español (Méjico)",
"Spanish (auto-generated)": "Español (generados automáticamente)",
"preferences_watch_history_label": "Habilitar historial de reproducciones: "
"preferences_watch_history_label": "Habilitar historial de reproducciones: ",
"search_message_no_results": "No se han encontrado resultados.",
"search_message_change_filters_or_query": "Pruebe ampliar la consulta de búsqueda y/o a cambiar los filtros.",
"search_filters_title": "Filtros",
"search_filters_date_label": "Fecha de subida",
"search_filters_date_option_none": "Cualquier fecha",
"search_filters_type_option_all": "Cualquier tipo",
"search_filters_duration_option_none": "Cualquier duración",
"search_filters_features_option_vr180": "VR180",
"search_filters_apply_button": "Aplicar filtros seleccionados",
"tokens_count": "{{count}} token",
"tokens_count_plural": "{{count}} tokens",
"search_message_use_another_instance": " También puede <a href=\"`x`\">buscar en otra instancia</a>.",
"search_filters_duration_option_medium": "Medio (4 - 20 minutes)"
}

338
locales/et.json Normal file
View File

@ -0,0 +1,338 @@
{
"generic_playlists_count": "{{count}} esitusloend",
"generic_playlists_count_plural": "{{count}} esindusloendit",
"LIVE": "OTSEÜLEKANNE",
"View channel on YouTube": "Vaata kanalit YouTube'is",
"Log in": "Logi sisse",
"Log in/register": "Logi sisse/registreeru",
"Dark mode: ": "Tume režiim: ",
"generic_videos_count": "{{count}} video",
"generic_videos_count_plural": "{{count}} videot",
"generic_subscribers_count": "{{count}} tellija",
"generic_subscribers_count_plural": "{{count}} tellijat",
"generic_subscriptions_count": "{{count}} tellimus",
"generic_subscriptions_count_plural": "{{count}} tellimust",
"Shared `x` ago": "Jagatud `x` tagasi",
"Unsubscribe": "Loobu tellimusest",
"Subscribe": "Telli",
"View playlist on YouTube": "Vaata esitusloendit YouTube'is",
"newest": "uusimad",
"oldest": "vanimad",
"popular": "populaarsed",
"last": "viimane",
"Next page": "Järgmine leht",
"Previous page": "Eelmine leht",
"Clear watch history?": "Kustuta vaatamiste ajalugu?",
"New password": "Uus salasõna",
"New passwords must match": "Uued salasõnad peavad ühtima",
"Cannot change password for Google accounts": "Google'i kasutaja salasõna ei saa muuta",
"Import and Export Data": "Impordi ja ekspordi andmed",
"Import": "Impordi",
"Import YouTube subscriptions": "Impordi tellimused Youtube'ist/OPML-ist",
"Import FreeTube subscriptions (.db)": "Impordi tellimused FreeTube'ist (.db)",
"Import NewPipe data (.zip)": "Impordi NewPipe'i andmed (.zip)",
"Export": "Ekspordi",
"Export subscriptions as OPML": "Ekspordi tellimused OPML-ina",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Ekspordi tellimused OPML-ina (NewPipe'i ja FreeTube'i jaoks)",
"Delete account?": "Kustuta kasutaja?",
"History": "Ajalugu",
"JavaScript license information": "JavaScripti litsentsi info",
"source": "allikas",
"Log in with Google": "Logi sisse Google'iga",
"User ID": "Kasutada ID",
"Password": "Salasõna",
"Time (h:mm:ss):": "Aeg (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA-tekst",
"Image CAPTCHA": "CAPTCHA-foto",
"Sign In": "Logi sisse",
"Register": "Registreeru",
"E-mail": "E-post",
"Preferences": "Eelistused",
"preferences_category_player": "Mängija eelistused",
"preferences_continue_autoplay_label": "Mängi järgmine video automaatselt: ",
"preferences_quality_label": "Eelistatud videokvaliteet: ",
"preferences_quality_option_dash": "DASH (kohanduv kvaliteet)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "Keskmine",
"preferences_quality_option_small": "Väike",
"preferences_quality_dash_label": "Eelistatav DASH-video kvaliteet: ",
"preferences_quality_dash_option_auto": "Automaatne",
"preferences_quality_dash_option_best": "Parim",
"preferences_quality_dash_option_worst": "Halvim",
"preferences_volume_label": "Video helitugevus: ",
"youtube": "YouTube",
"reddit": "Reddit",
"preferences_related_videos_label": "Näita sarnaseid videosid: ",
"preferences_vr_mode_label": "Interaktiivne 360-kraadine video (vajalik WebGL): ",
"preferences_dark_mode_label": "Teema: ",
"dark": "tume",
"light": "hele",
"preferences_category_subscription": "Tellimuse seaded",
"preferences_max_results_label": "Avalehel näidatavate videote arv: ",
"preferences_sort_label": "Sorteeri: ",
"published": "avaldatud",
"alphabetically": "tähestikulises järjekorras",
"alphabetically - reverse": "vastupidi tähestikulises järjekorras",
"channel name": "kanali nimi",
"preferences_unseen_only_label": "Näita ainult vaatamata videosid: ",
"Only show latest video from channel: ": "Näita ainult viimast videot: ",
"preferences_notifications_only_label": "Näita ainult teavitusi (kui neid on): ",
"Enable web notifications": "Luba veebiteavitused",
"`x` uploaded a video": "`x` laadis video üles",
"`x` is live": "`x` teeb otseülekannet",
"preferences_category_data": "Andme-eelistused",
"Clear watch history": "Puhasta vaatamisajalugu",
"Import/export data": "Impordi/ekspordi andmed",
"Change password": "Muuda salasõna",
"Watch history": "Vaatamisajalugu",
"Delete account": "Kustuta kasutaja",
"Save preferences": "Salvesta eelistused",
"Token": "Token",
"Import/export": "Imprort/eksport",
"unsubscribe": "loobu tellimusest",
"Subscriptions": "Tellimused",
"search": "otsi",
"Source available here.": "Allikas on kättesaadaval siin.",
"View privacy policy.": "Vaata privaatsuspoliitikat.",
"Public": "Avalik",
"Private": "Privaatne",
"View all playlists": "Vaata kõiki esitusloendeid",
"Updated `x` ago": "Uuendas `x` tagasi",
"Delete playlist `x`?": "Kustuta esitusloend `x`?",
"Delete playlist": "Kustuta esitusloend",
"Create playlist": "Loo esitlusloend",
"Title": "Pealkiri",
"Playlist privacy": "Esitusloendi privaatsus",
"Show more": "Näita rohkem",
"Show less": "Näita vähem",
"Watch on YouTube": "Vaata YouTube'is",
"search_message_no_results": "Tulemusi ei leitud.",
"search_message_change_filters_or_query": "Proovi otsingut laiendada või filtreid muuta.",
"Genre: ": "Žanr: ",
"License: ": "Litsents: ",
"Family friendly? ": "Peresõbralik? ",
"Shared `x`": "Jagas `x`",
"Premieres in `x`": "Esilinastub `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.": "Tundub, et oled JavaScripti välja lülitanud. Vajuta siia, et kommentaare vaadata; nende laadimine võib võtta natukene rohkem aega.",
"View Reddit comments": "Vaata Redditi kommentaare",
"Hide replies": "Peida vastused",
"Show replies": "Näita vastuseid",
"Incorrect password": "Vale salasõna",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Sisselogimine ei õnnestunud. Asi võib olla selles, et",
"Wrong answer": "Vale vastus",
"User ID is a required field": "Kasutaja ID on kohustuslik väli",
"Password is a required field": "Salasõna on kohustuslik väli",
"Wrong username or password": "Vale kasutajanimi või salasõna",
"Please sign in using 'Log in with Google'": "Palun kasutage 'Logi sisse Google'iga'",
"Password cannot be longer than 55 characters": "Salasõna ei tohi olla pikem kui 55 tähemärki",
"Password cannot be empty": "Salasõna ei tohi olla tühi",
"Please log in": "Palun logige sisse",
"channel:`x`": "kanal:`x`",
"Deleted or invalid channel": "Kanal on kustutatud või seda ei leitud",
"This channel does not exist.": "Sellist kanalit pole olemas.",
"comments_view_x_replies": "{{count}} vastus",
"comments_view_x_replies_plural": "{{count}} vastust",
"`x` ago": "`x` tagasi",
"Load more": "Laadi rohkem",
"Empty playlist": "Tühi esitusloend",
"Not a playlist.": "Tegu pole esitusloendiga.",
"Playlist does not exist.": "Seda esitusloendit pole olemas.",
"No such user": "Sellist kasutajat pole",
"English": "Inglise",
"English (United Kingdom)": "Inglise (Suurbritannia)",
"English (United States)": "Inglise (USA)",
"English (auto-generated)": "Inglise (automaatselt koostatud)",
"Afrikaans": "Afrikaani",
"Albanian": "Albaania",
"Arabic": "Araabia",
"Armenian": "Armeenia",
"Bangla": "Bengali",
"Basque": "Baski",
"Belarusian": "Valgevene",
"Bulgarian": "Bulgaaria",
"Burmese": "Birma",
"Cantonese (Hong Kong)": "Kantoni (Hong Konk)",
"Chinese (China)": "Hiina (Hiina)",
"Chinese (Hong Kong)": "Hiina (Hong Kong)",
"Chinese (Simplified)": "Hiina (lihtsustatud)",
"Chinese (Taiwan)": "Hiina (Taiwan)",
"Croatian": "Horvaatia",
"Czech": "Tšehhi",
"Danish": "Taani",
"Dutch": "Hollandi",
"Esperanto": "Esperanto",
"Estonian": "Eesti",
"Filipino": "Filipiini",
"Finnish": "Soome",
"French": "Prantsuse",
"French (auto-generated)": "Prantsuse (automaatne)",
"Dutch (auto-generated)": "Hollandi (automaatne)",
"Galician": "Kaliitsia",
"Georgian": "Gruusia",
"Haitian Creole": "Haiti kreool",
"Hausa": "Hausa",
"Hawaiian": "Havaii",
"Hebrew": "Heebrea",
"Hindi": "Hindi",
"Hungarian": "Ungari",
"Icelandic": "Islandi",
"Indonesian": "Indoneesia",
"Japanese (auto-generated)": "Jaapani (automaatne)",
"Kannada": "Kannada",
"Kazakh": "Kasahhi",
"Luxembourgish": "Luksemburgi",
"Macedonian": "Makedoonia",
"Malay": "Malai",
"Maltese": "Malta",
"Maori": "Maori",
"Marathi": "Marathi",
"Mongolian": "Mongoli",
"Nepali": "Nepaali",
"Norwegian Bokmål": "Norra (Bokmål)",
"Persian": "Pärsia",
"Polish": "Poola",
"Portuguese": "Portugali",
"Portuguese (auto-generated)": "Portugali (automaatne)",
"Portuguese (Brazil)": "Portugali (Brasiilia)",
"Romanian": "Rumeenia",
"Russian": "Vene",
"Russian (auto-generated)": "Vene (automaatne)",
"Scottish Gaelic": "Šoti (Gaeli)",
"Serbian": "Serbia",
"Slovak": "Slovaki",
"Slovenian": "Sloveeni",
"Somali": "Somaali",
"Spanish": "Hispaania",
"Spanish (auto-generated)": "Hispaania (automaatne)",
"Spanish (Latin America)": "Hispaania (Ladina-Ameerika)",
"Spanish (Mexico)": "Hispaania (Mehhiko)",
"Spanish (Spain)": "Hispaania (Hispaania)",
"Swahili": "Suahili",
"Swedish": "Rootsi",
"Tajik": "Tadžiki",
"Tamil": "Tamiili",
"Thai": "Tai",
"Turkish": "Türgi",
"Turkish (auto-generated)": "Türgi (automaatne)",
"Ukrainian": "Ukraina",
"Uzbek": "Usbeki",
"Vietnamese": "Vietnami",
"Vietnamese (auto-generated)": "Vietnami (automaatne)",
"generic_count_years": "{{count}} aasta",
"generic_count_years_plural": "{{count}} aastat",
"generic_count_months": "{{count}} kuu",
"generic_count_months_plural": "{{count}} kuud",
"generic_count_weeks": "{{count}} nädal",
"generic_count_weeks_plural": "{{count}} nädalat",
"generic_count_days": "{{count}} päev",
"generic_count_days_plural": "{{count}} päeva",
"generic_count_hours": "{{count}} tund",
"generic_count_hours_plural": "{{count}} tundi",
"generic_count_minutes": "{{count}} minut",
"generic_count_minutes_plural": "{{count}} minutit",
"Popular": "Populaarne",
"Search": "Otsi",
"Top": "Top",
"About": "Leheküljest",
"preferences_locale_label": "Keel: ",
"View as playlist": "Vaata esitusloendina",
"Movies": "Filmid",
"Download as: ": "Laadi kui: ",
"(edited)": "(muudetud)",
"`x` marked it with a ❤": "`x` märkis ❤",
"Audio mode": "Audiorežiim",
"Video mode": "Videorežiim",
"search_filters_date_label": "Üleslaadimise kuupäev",
"search_filters_date_option_none": "Ükskõik mis kuupäev",
"search_filters_date_option_today": "Täna",
"search_filters_date_option_week": "Sel nädalal",
"search_filters_date_option_hour": "Viimasel tunnil",
"search_filters_date_option_month": "Sel kuul",
"search_filters_date_option_year": "Sel aastal",
"search_filters_type_label": "Tüüp",
"search_filters_type_option_all": "Ükskõik mis tüüp",
"search_filters_duration_label": "Kestus",
"search_filters_type_option_show": "Näita",
"search_filters_duration_option_none": "Ükskõik mis kestus",
"search_filters_duration_option_short": "Lühike (alla 4 minuti)",
"search_filters_duration_option_medium": "Keskmine (4 - 20 minutit)",
"search_filters_duration_option_long": "Pikk (üle 20 minuti)",
"search_filters_features_option_live": "Otseülekanne",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Subtiitrid",
"search_filters_features_option_location": "Asukoht",
"search_filters_sort_label": "Sorteeri",
"search_filters_sort_option_views": "Vaatamiste arv",
"next_steps_error_message": "Pärast mida võiksite proovida: ",
"videoinfo_started_streaming_x_ago": "Alustas otseülekannet `x` tagasi",
"Yes": "Jah",
"generic_views_count": "{{count}} vaatamine",
"generic_views_count_plural": "{{count}} vaatamist",
"Import NewPipe subscriptions (.json)": "Impordi tellimused NewPipe'ist (.json)",
"No": "Ei",
"preferences_region_label": "Riik: ",
"View YouTube comments": "Vaata YouTube'i kommentaare",
"preferences_extend_desc_label": "Ava video kirjeldus automaatselt: ",
"German (auto-generated)": "Saksa (automaatne)",
"Italian": "Itaalia",
"preferences_player_style_label": "Mängija stiil: ",
"subscriptions_unseen_notifs_count": "{{count}} lugemata teavitus",
"subscriptions_unseen_notifs_count_plural": "{{count}} lugemata teavitust",
"View more comments on Reddit": "Vaata teisi kommentaare Redditis",
"Only show latest unwatched video from channel: ": "Näita ainult viimast vaatamata videot: ",
"tokens_count": "{{count}} token",
"tokens_count_plural": "{{count}} tokenit",
"Log out": "Logi välja",
"Premieres `x`": "Linastub`x`",
"View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "Vaata `x` kommentaari",
"": "Vaata `x` kommentaare"
},
"Khmer": "Khmeeri",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Sisselogimine ei õnnestunud. Kontrollige, kas two-factor authentication (Authenticator või SMS) on sisselülitatud.",
"Invalid TFA code": "Vale TFA-kood",
"Bosnian": "Bosnia",
"Corsican": "Korsika",
"Javanese": "Jaava",
"Lithuanian": "Leedu",
"Videos": "Videod",
"Community": "Kogukond",
"CAPTCHA is a required field": "CAPTCHA on kohustuslik väli",
"comments_points_count": "{{count}} punkt",
"comments_points_count_plural": "{{count}} punkti",
"Chinese": "Hiina",
"German": "Saksa",
"Indonesian (auto-generated)": "Indoneesia (automaatne)",
"Italian (auto-generated)": "Itaalia (automaatne)",
"Kyrgyz": "Kirkiisi",
"Latin": "Ladina",
"generic_count_seconds": "{{count}} sekund",
"generic_count_seconds_plural": "{{count}} sekundit",
"Catalan": "Katalaani",
"Chinese (Traditional)": "Hiina (traditsiooniline)",
"Greek": "Kreeka",
"Kurdish": "Kurdi",
"Latvian": "Läti",
"Irish": "Iiri",
"Korean": "Korea",
"Japanese": "Jaapani",
"Korean (auto-generated)": "Korea (automaatne)",
"Music": "Muusika",
"Playlists": "Esitusloendid",
"search_filters_type_option_video": "Video",
"search_filters_sort_option_date": "Üleslaadimise kuupäev",
"Current version: ": "Praegune versioon: ",
"footer_documentation": "Dokumentatsioon",
"Gaming": "Mängud",
"News": "Uudised",
"Download": "Laadi alla",
"search_filters_title": "Filtrid",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Esitusloend",
"search_filters_type_option_movie": "Film",
"next_steps_error_message_go_to_youtube": "Minna YouTube'i",
"next_steps_error_message_refresh": "Laadida uuesti",
"footer_donate_page": "Anneta",
"videoinfo_watch_on_youTube": "Vaata YouTube'is"
}

View File

@ -20,15 +20,15 @@
"No": "Ez",
"Import and Export Data": "Datuak inportatu eta esportatu",
"Import": "Inportatu",
"Import Invidious data": "Inportatu Invidiouseko datuak",
"Import YouTube subscriptions": "Inportatu YouTubeko harpidetzak",
"Import Invidious data": "Inportatu Invidiouseko JSON datuak",
"Import YouTube subscriptions": "Inportatu YouTubeko/OPML harpidetzak",
"Import FreeTube subscriptions (.db)": "Inportatu FreeTubeko harpidetzak (.db)",
"Import NewPipe subscriptions (.json)": "Inportatu NewPipeko harpidetzak (.json)",
"Import NewPipe data (.zip)": "Inportatu NewPipeko datuak (.zip)",
"Export": "Esportatu",
"Export subscriptions as OPML": "Esportatu harpidetzak OPML bezala",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Esportatu harpidetzak OPML bezala (NewPipe eta FreeTuberako)",
"Export data as JSON": "Esportatu datuak JSON bezala",
"Export data as JSON": "Esportatu Invidious datuak JSON gisa",
"Delete account?": "Kontua ezabatu?",
"History": "Historia",
"An alternative front-end to YouTube": "YouTuberako interfaze alternatibo bat",
@ -53,7 +53,7 @@
"preferences_volume_label": "Erreproduzigailuaren bolumena: ",
"preferences_comments_label": "Lehenetsitako iruzkinak: ",
"youtube": "YouTube",
"reddit": "reddit",
"reddit": "Reddit",
"preferences_captions_label": "Lehenetsitako azpitituluak: ",
"preferences_related_videos_label": "Erakutsi erlazionatutako bideoak: ",
"preferences_annotations_label": "Erakutsi oharrak modu lehenetsian: ",
@ -62,5 +62,216 @@
"Dark mode: ": "Gai iluna: ",
"preferences_dark_mode_label": "Gaia: ",
"dark": "iluna",
"light": "argia"
"light": "argia",
"generic_subscriptions_count": "{{count}} harpidetza",
"generic_subscriptions_count_plural": "{{count}} harpidetzak",
"tokens_count": "{{count}} tokena",
"tokens_count_plural": "{{count}} tokenak",
"comments_points_count": "{{count}} puntua",
"comments_points_count_plural": "{{count}} puntuak",
"View more comments on Reddit": "Iruzkin gehiago Redditen",
"Fallback captions: ": "Ordezko azpitituluak: ",
"generic_subscribers_count": "{{count}} harpidedun",
"generic_subscribers_count_plural": "{{count}} harpidedunak",
"preferences_quality_option_dash": "DASH (kalitate egokitua)",
"preferences_listen_label": "Lehenetsiz jo: ",
"preferences_speed_label": "Abiadura lehenetsia: ",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_144p": "144p",
"preferences_quality_dash_option_auto": "Auto",
"preferences_quality_dash_option_worst": "Txarrena",
"preferences_quality_dash_option_best": "Hoberena",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_option_480p": "480p",
"preferences_quality_dash_option_240p": "240p",
"preferences_extend_desc_label": "Bideoaren azalpena automatikoki zabaldu: ",
"preferences_annotations_subscribed_label": "Harpidetutako kanalen oharrak erakutsi lehenetsiz? ",
"Redirect homepage to feed: ": "Hasierako orrira bidali jarraitzeko: ",
"channel name - reverse": "kanalaren izena - alderantziz",
"preferences_notifications_only_label": "Jakinarazpenak soilik erakutsi (baldin badago): ",
"Top enabled: ": "Goikoa gaitu: ",
"Import/export data": "Inportatu/exportatu data",
"Create playlist": "Zerrenda sortu",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Aditu! JavaScript itzalita dakazula ematen du. Hemen sakatu iruzkinak ikusteko. Denbora luza leikeela kontuan hartu.",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Ezinezkoa izena eman. Ziurtatu berresteko bi faktoreak (Authenticator edo SMS) piztuta daudela.",
"generic_views_count": "{{count}}ikusia",
"generic_views_count_plural": "{{count}}ikusiak",
"generic_playlists_count": "{{count}}zerrenda",
"generic_playlists_count_plural": "{{count}}zerrendak",
"Could not fetch comments": "Iruzkinei ezin heldu",
"Erroneous token": "Token okerra",
"Albanian": "Albaniarra",
"Azerbaijani": "Azerbaitarra",
"No such user": "Ez dago erabiltzailerik",
"Bulgarian": "Bulgariarra",
"Filipino": "Filipinera",
"French": "Frantsesa",
"French (auto-generated)": "Frantsesa (auto-sortua)",
"Show more": "Erakutsi gehiago",
"Show less": "Erakutsi gutxiago",
"Delete playlist": "Zerrenda ezabatu",
"Delete account": "Kontua ezabatu",
"User ID is a required field": "Erabiltzailearen IDa beharrezkoa da",
"English (United Kingdom)": "Ingelesa (Britania Handia",
"preferences_vr_mode_label": "360 graduko bideo interaktiboak (WebGL beharko): ",
"English (United States)": "Estatu batuarra (AEB)",
"English (auto-generated)": "Ingelesa (autosortua)",
"Arabic": "Arabiarra",
"Armenian": "Armeniarra",
"Bangla": "Banglera",
"Belarusian": "Bielorrusiara",
"Burmese": "Burmesera",
"Chinese (Simplified)": "Txinera (sinplifikatua)",
"preferences_watch_history_label": "Baimendu historia ikusi ",
"generic_videos_count": "{{count}}bideo",
"generic_videos_count_plural": "{{count}}bideoak",
"View privacy policy.": "Pribatutasun politika ikusi.",
"Cantonese (Hong Kong)": "Kantoniera (Hong Kong)",
"subscriptions_unseen_notifs_count": "{{count}} ezikusitako oharra",
"subscriptions_unseen_notifs_count_plural": "{{count}} ezikusitako oharrak",
"Trending": "Joera",
"Playlist privacy": "Zerrendaren privatutasuna",
"Switch Invidious Instance": "Invidious adibidea aldatu",
"Genre: ": "Genero: ",
"License: ": "Lizentzia: ",
"Family friendly? ": "Adeikorra familiarekin? ",
"Wilson score: ": "Wilsonen puntuazioa: ",
"Quota exceeded, try again in a few hours": "Kuota gaindituta, ordu batzuren bueltan berriro saiatu",
"comments_view_x_replies": "{{count}} erantzuna ikusi",
"comments_view_x_replies_plural": "{{count}} erantzunak ikusi",
"Catalan": "Katalaniera",
"Chinese": "Txinera",
"Chinese (China)": "Txinatarra",
"Chinese (Hong Kong)": "Hongkondarra",
"Chinese (Taiwan)": "Taiwandarra",
"Corsican": "Korsikera",
"Dutch (auto-generated)": "Alemaniera (auto-sortua)",
"Estonian": "Estoniera",
"Finnish": "Finlandiera",
"Galician": "Galizera",
"German (auto-generated)": "Alemaiera (auto-sortua)",
"Greek": "Greziera",
"crash_page_report_issue": "Aurreko ezerk ez badizu lagundu, arren <a href=\"`x`\"> GitHuben gai berri bat zabaldu </a> (ingelesez ahal bada) eta zure mezuan hurrengo testua sartu (testuari EZ itzulpena egin):",
"crash_page_search_issue": "GitHuben dauden gaiak <a href=\"`x`\"> buruz</a>",
"preferences_quality_option_medium": "Erdixka",
"preferences_quality_option_small": "Txikia",
"preferences_quality_dash_label": "DASH bideo kalitate lehenetsia: ",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_1080p": "1080p",
"preferences_quality_dash_option_720p": "720p",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_dash_option_360p": "360p",
"invidious": "Invidious",
"Source available here.": "Iturburua hemen eskura.",
"View JavaScript license information.": "JavaScriptaren lizentzi adierazpena ikusi.",
"Blacklisted regions: ": "zerrenda beltzaren zonaldeak: ",
"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'",
"Czech": "Txekiera",
"preferences_region_label": "Herrialdeko edukiera: ",
"preferences_sort_label": "Bideoak ordenatu: ",
"published": "argitaratuta",
"Only show latest video from channel: ": "Kanalaren azken bideoa soilik erakutsi ",
"preferences_category_admin": "Administratzailearen lehentasunak",
"Registration enabled: ": "Harpidetza gaituta: ",
"Save preferences": "Baloreak gorde",
"Token manager": "Token kudeatzailea",
"unsubscribe": "Baja eman",
"search": "Bilatu",
"Log out": "Irten",
"English": "Ingelesa",
"Afrikaans": "Afrikarra",
"Amharic": "Amharerra",
"Basque": "Euskera",
"Bosnian": "Bosniarra",
"Cebuano": "Zebuera",
"Chinese (Traditional)": "Txinera (Tradizionala)",
"Croatian": "Croaziera",
"Danish": "Daniera",
"Dutch": "Alemaniera",
"Esperanto": "Esperanto",
"Erroneous challenge": "Erronka okerra",
"View all playlists": "Zerrenda guztiak ikusi",
"Show annotations": "Oharrak erakutsi",
"Empty playlist": "Zerrenda hutsik",
"Please log in": "Sartu, mesedez",
"CAPTCHA is a required field": "CAPTCHA beharrezko eremua da",
"preferences_category_data": "Dataren lehentasunak",
"preferences_default_home_label": "Homepage lehenetsia: ",
"preferences_automatic_instance_redirect_label": "berbideratze adibide automatikoa (atzera egin berbideratzeko: invidious.io) ",
"Please sign in using 'Log in with Google'": "'Log in Googlerekin' erabili",
"`x` uploaded a video": "' x'(e)k bideo bat igo du",
"published - reverse": "argitaratuta - alderantziz",
"Could not get channel info.": "Kanalaren adierazpena ezin lortu.",
"alphabetically - reverse": "alfabetikoki - alderantziz",
"Public": "Orokorra",
"Unlisted": "Ez zerrendatua",
"Subscription manager": "Harpidetzen kudeatzailea",
"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?",
"Token is expired, please try again": "Token kadukatua, saiatu berriro",
"Invalid TFA code": "TFA kodea ez da zuzena",
"CAPTCHA enabled: ": "CAPTCHA gaitu: ",
"Released under the AGPLv3 on Github.": "GitHubeko AGPLv3pean argitaratuta.",
"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"
},
"Report statistics: ": "Estatistikak adierazi: ",
"preferences_max_results_label": "Jotzeko bideo zerrendaren luzera: ",
"Subscriptions": "Harpidetzak",
"Load more": "Gehiago atera",
"Change password": "Pasahitza aldatu",
"preferences_show_nick_label": "Erakutsi ezizena goian: ",
"View Reddit comments": "Redditeko iruzkinak ikusi",
"preferences_category_subscription": "Harpidetzaren lehentasunak",
"Hidden field \"challenge\" is a required field": "\"challenge\" eremu ezkutua beharrezkoa da",
"German": "Alemaniarra",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Ezin izena eman. Izan leike zure konturako berresteko bi faktoreak piztuta ez daudela.",
"View YouTube comments": "YouTubeko iruzkinak ikusi",
"Google verification code": "Googleren berresteko kodea",
"`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 ",
"Enable web notifications": "Webaren jakinarazpenak baimendu",
"revoke": "ukatu",
"preferences_continue_label": "Hurrengo lehenetsia jo: ",
"Whitelisted regions: ": "Zuri zerrendaren zonaldeak: ",
"Erroneous CAPTCHA": "CAPTCHA gaizki",
"Deleted or invalid channel": "Ezgai edota ezabatutako kanala",
"Could not create mix.": "Nahastea ezin sortu.",
"Not a playlist.": "Ez da zerrenda.",
"Hidden field \"token\" is a required field": "\"token\" eremu ezkutua beharrezkoa da",
"Import/export": "Inportatu/esportatu",
"alphabetically": "alfabetikoki",
"preferences_unseen_only_label": "Ezikusiak besterik ez erakutsi: ",
"Clear watch history": "Historia ezabatu",
"Manage subscriptions": "Harpidetzak kudeatu",
"Manage tokens": "Fitxak kudeatu",
"Watch history": "Historia ikusi",
"Login enabled: ": "Login gaitu: ",
"Hide annotations": "Oharrak izkutatu",
"Title": "Titulua",
"channel name": "Kanalaren izena",
"Authorize token for `x`?": "Baimendu tokena 'x'tzako?",
"Private": "Pribatua",
"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>"
}

View File

@ -148,7 +148,6 @@
"Show less": "نمایش کم‌تر",
"Watch on YouTube": "تماشا در یوتیوب",
"Switch Invidious Instance": "تعویض نمونه اینویدیوس",
"Broken? Try another Invidious Instance": "کار نمی‌کند؟ نمونه دیگری از اینویدیوس را امتحان کنید",
"Hide annotations": "مخفی کردن حاشیه نویسی ها",
"Show annotations": "نمایش حاشیه نویسی ها",
"Genre: ": "ژانر: ",
@ -345,33 +344,32 @@
"Videos": "ویدیو ها",
"Playlists": "سیاهه‌های پخش",
"Community": "اجتماع",
"relevance": "مرتبط بودن",
"rating": "امتیاز",
"date": "تاریخ بارگذاری",
"views": "تعداد بازدید",
"content_type": "نوع",
"duration": "مدت",
"features": "ویژگی‌ها",
"sort": "به ترتیب",
"hour": "یک ساعت گذشته",
"today": "امروز",
"week": "این هفته",
"month": "این ماه",
"year": "امسال",
"video": "ویدئو",
"channel": "کانال",
"playlist": "سیاههٔ پخش",
"movie": "فیلم",
"show": "نمایش",
"hd": "HD",
"subtitles": "زیرنویس",
"creative_commons": "کریتیو کامونز",
"3d": "سه‌بعدی",
"live": "زنده",
"4k": "4K",
"location": "مکان",
"hdr": "HDR",
"filter": "پالایه",
"search_filters_sort_option_relevance": "مرتبط بودن",
"search_filters_sort_option_rating": "امتیاز",
"search_filters_sort_option_date": "تاریخ بارگذاری",
"search_filters_sort_option_views": "تعداد بازدید",
"search_filters_type_label": "نوع",
"search_filters_duration_label": "مدت",
"search_filters_features_label": "ویژگی‌ها",
"search_filters_sort_label": "به ترتیب",
"search_filters_date_option_hour": "یک ساعت گذشته",
"search_filters_date_option_today": "امروز",
"search_filters_date_option_week": "این هفته",
"search_filters_date_option_month": "این ماه",
"search_filters_date_option_year": "امسال",
"search_filters_type_option_video": "ویدئو",
"search_filters_type_option_channel": "کانال",
"search_filters_type_option_playlist": "سیاههٔ پخش",
"search_filters_type_option_movie": "فیلم",
"search_filters_type_option_show": "نمایش",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "زیرنویس",
"search_filters_features_option_c_commons": "کریتیو کامونز",
"search_filters_features_option_three_d": "سه‌بعدی",
"search_filters_features_option_live": "زنده",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "مکان",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "نسخه فعلی: ",
"next_steps_error_message": "اکنون بایستی یکی از این موارد را امتحان کنید: ",
"next_steps_error_message_refresh": "تازه‌سازی",
@ -393,7 +391,7 @@
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "اینویدیوس",
"360": "360°",
"search_filters_features_option_three_sixty": "360°",
"footer_donate_page": "کمک مالی",
"footer_source_code": "کد منبع",
"footer_modfied_source_code": "کد منبع ویرایش شده",
@ -405,12 +403,13 @@
"download_subtitles": "زیرنویس‌ها - `x` (.vtt)",
"Video unavailable": "ویدئو دردسترس نیست",
"preferences_save_player_pos_label": "ذخیره زمان کنونی ویدئو: ",
"purchased": "خریداری شده",
"search_filters_features_option_purchased": "خریداری شده",
"preferences_quality_dash_label": "کیفیت ترجیحی ویدئو DASH: ",
"preferences_region_label": "کشور محتوا: ",
"footer_documentation": "مستندات",
"footer_original_source_code": "کد منبع اصلی",
"long": "بلند (> 20 دقیقه)",
"search_filters_duration_option_long": "بلند (> 20 دقیقه)",
"adminprefs_modified_source_code_url_label": "URL مخزن کد منبع ویریش شده",
"short": "کوتاه (< 4 دقیقه)"
"search_filters_duration_option_short": "کوتاه (< 4 دقیقه)",
"search_filters_title": "پالایه"
}

View File

@ -21,15 +21,15 @@
"No": "Ei",
"Import and Export Data": "Tuo ja vie tietoja",
"Import": "Tuo",
"Import Invidious data": "Tuo Invidious-tietoja",
"Import YouTube subscriptions": "Tuo YouTube-tilaukset",
"Import Invidious data": "Tuo Invidiousin JSON-tietoja",
"Import YouTube subscriptions": "Tuo YouTube/OPML-tilaukset",
"Import FreeTube subscriptions (.db)": "Tuo FreeTube-tilaukset (.db)",
"Import NewPipe subscriptions (.json)": "Tuo NewPipe-tilaukset (.json)",
"Import NewPipe data (.zip)": "Tuo NewPipe-tietoja (.zip)",
"Export": "Vie",
"Export subscriptions as OPML": "Vie tilaukset OPML-muodossa",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Vie tilaukset OPML-muodossa (NewPipe & FreeTube)",
"Export data as JSON": "Vie data JSON-muodossa",
"Export data as JSON": "Vie Invidious-data JSON-muodossa",
"Delete account?": "Poista tili?",
"History": "Historia",
"An alternative front-end to YouTube": "Vaihtoehtoinen front-end YouTubelle",
@ -66,7 +66,7 @@
"preferences_related_videos_label": "Näytä aiheeseen liittyviä videoita: ",
"preferences_annotations_label": "Näytä huomautukset oletuksena: ",
"preferences_extend_desc_label": "Laajenna automaattisesti videon kuvausta: ",
"preferences_vr_mode_label": "Interaktiiviset 360-asteiset videot: ",
"preferences_vr_mode_label": "Interaktiiviset 360-asteiset videot (vaatii WebGL:n): ",
"preferences_category_visual": "Visuaaliset asetukset",
"preferences_player_style_label": "Soittimen tyyli: ",
"Dark mode: ": "Tumma tila: ",
@ -140,7 +140,6 @@
"Show less": "Näytä vähemmän",
"Watch on YouTube": "Katso YouTubessa",
"Switch Invidious Instance": "Vaihda Invidious-instanssia",
"Broken? Try another Invidious Instance": "Rikki? Kokeile toista Invidious-instanssia",
"Hide annotations": "Piilota merkkaukset",
"Show annotations": "Näytä merkkaukset",
"Genre: ": "Genre: ",
@ -328,33 +327,32 @@
"Videos": "Videot",
"Playlists": "Soittolistat",
"Community": "Yhteisö",
"relevance": "Osuvuus",
"rating": "Arvostelu",
"date": "Latauspäivämäärä",
"views": "Katselukerrat",
"content_type": "Tyyppi",
"duration": "Kesto",
"features": "Ominaisuudet",
"sort": "Luokittele",
"hour": "Viimeisin tunti",
"today": "Tänään",
"week": "Tämä viikko",
"month": "Tämä kuukausi",
"year": "Tämä vuosi",
"video": "Video",
"channel": "Kanava",
"playlist": "Soittolista",
"movie": "Elokuva",
"show": "Ohjelma",
"hd": "HD",
"subtitles": "Tekstitys/CC",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Suora lähetys",
"4k": "4K",
"location": "Sijainti",
"hdr": "HDR",
"filter": "Suodatin",
"search_filters_sort_option_relevance": "Osuvuus",
"search_filters_sort_option_rating": "Arvostelu",
"search_filters_sort_option_date": "Latauspäivämäärä",
"search_filters_sort_option_views": "Katselukerrat",
"search_filters_type_label": "Tyyppi",
"search_filters_duration_label": "Kesto",
"search_filters_features_label": "Ominaisuudet",
"search_filters_sort_label": "Luokittele",
"search_filters_date_option_hour": "Viimeisin tunti",
"search_filters_date_option_today": "Tänään",
"search_filters_date_option_week": "Tämä viikko",
"search_filters_date_option_month": "Tämä kuukausi",
"search_filters_date_option_year": "Tämä vuosi",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanava",
"search_filters_type_option_playlist": "Soittolista",
"search_filters_type_option_movie": "Elokuva",
"search_filters_type_option_show": "Ohjelma",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Tekstitys/CC",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Suora lähetys",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Sijainti",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Tämänhetkinen versio: ",
"next_steps_error_message": "Sinun tulisi kokeilla seuraavia: ",
"next_steps_error_message_refresh": "Päivitä",
@ -390,7 +388,7 @@
"crash_page_before_reporting": "Varmista ennen bugin ilmoittamista, että sinä olet:",
"crash_page_refresh": "yrittänyt <a href=\"`x`\">päivittää sivun</a>",
"crash_page_read_the_faq": "lukenut <a href=\"`x`\">Usein kysytyt kysymykset (FAQ)</a>",
"crash_page_search_issue": "etsinyt <a href=\"`x`\">olemassa olevia issueita Githubissa</a>",
"crash_page_search_issue": "etsinyt <a href=\"`x`\">olemassa olevia issueita GitHubissa</a>",
"generic_views_count": "{{count}} katselu",
"generic_views_count_plural": "{{count}} katselua",
"preferences_quality_dash_option_720p": "720p",
@ -423,8 +421,8 @@
"preferences_quality_dash_label": "Haluttava DASH-videolaatu: ",
"generic_count_years": "{{count}} vuosi",
"generic_count_years_plural": "{{count}} vuotta",
"purchased": "Ostettu",
"360": "360°",
"search_filters_features_option_purchased": "Ostettu",
"search_filters_features_option_three_sixty": "360°",
"videoinfo_watch_on_youTube": "Katso YouTubessa",
"none": "ei mikään",
"videoinfo_started_streaming_x_ago": "Striimaaminen aloitettu `x` sitten",
@ -433,9 +431,45 @@
"footer_source_code": "Lähdekoodi",
"adminprefs_modified_source_code_url_label": "URL muokattuun lähdekoodirepositoryyn",
"Released under the AGPLv3 on Github.": "Julkaistu AGPLv3-lisenssin alla GitHubissa.",
"short": "Lyhyt (< 4 minuuttia)",
"long": "Pitkä (> 20 minuuttia)",
"search_filters_duration_option_short": "Lyhyt (< 4 minuuttia)",
"search_filters_duration_option_long": "Pitkä (> 20 minuuttia)",
"footer_documentation": "Dokumentaatio",
"footer_original_source_code": "Alkuperäinen lähdekoodi",
"footer_modfied_source_code": "Muokattu lähdekoodi"
"footer_modfied_source_code": "Muokattu lähdekoodi",
"Japanese (auto-generated)": "Japani (automaattisesti luotu)",
"German (auto-generated)": "Saksa (automaattisesti luotu)",
"Portuguese (auto-generated)": "portugali (automaattisesti luotu)",
"Russian (auto-generated)": "Venäjä (automaattisesti luotu)",
"preferences_watch_history_label": "Ota katseluhistoria käyttöön: ",
"English (United Kingdom)": "Englanti (Iso-Britannia)",
"English (United States)": "Englanti (Yhdysvallat)",
"Cantonese (Hong Kong)": "Kantoninkiina (Hong Kong)",
"Chinese": "Kiina",
"Chinese (China)": "Kiina (Kiina)",
"Chinese (Hong Kong)": "Kiina (Hong Kong)",
"Chinese (Taiwan)": "Kiina (Taiwan)",
"Dutch (auto-generated)": "Hollanti (automaattisesti luotu)",
"French (auto-generated)": "Ranska (automaattisesti luotu)",
"Indonesian (auto-generated)": "Indonesia (automaattisesti luotu)",
"Interlingue": "Interlingue",
"Italian (auto-generated)": "Italia (automaattisesti luotu)",
"Korean (auto-generated)": "Korea (automaattisesti luotu)",
"Portuguese (Brazil)": "portugali (Brasilia)",
"Spanish (auto-generated)": "Espanja (automaattisesti luotu)",
"Spanish (Mexico)": "Espanja (Meksiko)",
"Spanish (Spain)": "Espanja (Espanja)",
"Turkish (auto-generated)": "Turkki (automaattisesti luotu)",
"Vietnamese (auto-generated)": "Vietnam (automaattisesti luotu)",
"search_filters_title": "Suodatin",
"search_message_no_results": "Ei tuloksia löydetty.",
"search_message_change_filters_or_query": "Yritä hakukyselysi laajentamista ja/tai suodattimien muuttamista.",
"search_filters_duration_option_none": "Mikä tahansa kesto",
"search_filters_features_option_vr180": "VR180",
"search_filters_apply_button": "Ota valitut suodattimet käyttöön",
"search_filters_date_label": "Latausaika",
"search_filters_duration_option_medium": "Keskipituinen (4 - 20 minuuttia)",
"search_message_use_another_instance": " Voit myös <a href=\"`x`\">hakea toisella instanssilla</a>.",
"search_filters_date_option_none": "Milloin tahansa",
"search_filters_type_option_all": "Mikä tahansa tyyppi",
"Popular enabled: ": "Suosittu käytössä: "
}

View File

@ -116,6 +116,7 @@
"preferences_default_home_label": "Page d'accueil par défaut : ",
"preferences_feed_menu_label": "Préferences des abonnements : ",
"preferences_show_nick_label": "Afficher le nom d'utilisateur en haut à droite : ",
"Popular enabled: ": "Page \"populaire\" activée: ",
"Top enabled: ": "Top activé : ",
"CAPTCHA enabled: ": "CAPTCHA activé : ",
"Login enabled: ": "Autoriser l'ouverture de sessions utilisateur : ",
@ -135,7 +136,7 @@
"subscriptions_unseen_notifs_count_plural": "{{count}} notifications non vues",
"search": "rechercher",
"Log out": "Se déconnecter",
"Released under the AGPLv3 on Github.": "Publié sous licence AGPLv3 sur Github.",
"Released under the AGPLv3 on Github.": "Publié sous licence AGPLv3 sur GitHub.",
"Source available here.": "Code source disponible ici.",
"View JavaScript license information.": "Informations des licences JavaScript.",
"View privacy policy.": "Politique de confidentialité.",
@ -155,7 +156,6 @@
"Show less": "Afficher moins",
"Watch on YouTube": "Voir la vidéo sur Youtube",
"Switch Invidious Instance": "Changer d'instance",
"Broken? Try another Invidious Instance": "Instance Invidious défectueuse ? Essayez-en une autre",
"Hide annotations": "Masquer les annotations",
"Show annotations": "Afficher les annotations",
"Genre: ": "Genre : ",
@ -361,33 +361,32 @@
"Videos": "Vidéos",
"Playlists": "Listes de lecture",
"Community": "Communauté",
"relevance": "pertinence",
"rating": "évaluation",
"date": "date",
"views": "nombre de vues",
"content_type": "type",
"duration": "durée",
"features": "fonctionnalités",
"sort": "Trier par",
"hour": "dernière heure",
"today": "aujourd'hui",
"week": "semaine",
"month": "mois",
"year": "année",
"video": "vidéo",
"channel": "chaîne",
"playlist": "liste de lecture",
"movie": "film",
"show": "émission",
"hd": "HD",
"subtitles": "sous-titres / CC",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "en direct",
"4k": "4K",
"location": "emplacement",
"hdr": "HDR",
"filter": "filtrer",
"search_filters_sort_option_relevance": "Pertinence",
"search_filters_sort_option_rating": "Notation",
"search_filters_sort_option_date": "Date d'ajout",
"search_filters_sort_option_views": "Nombre de vues",
"search_filters_type_label": "Type de contenu",
"search_filters_duration_label": "Durée",
"search_filters_features_label": "Fonctionnalités",
"search_filters_sort_label": "Trier par",
"search_filters_date_option_hour": "Dernière heure",
"search_filters_date_option_today": "Aujourd'hui",
"search_filters_date_option_week": "Cette semaine",
"search_filters_date_option_month": "Ce mois-ci",
"search_filters_date_option_year": "Cette année",
"search_filters_type_option_video": "Vidéo",
"search_filters_type_option_channel": "Chaîne",
"search_filters_type_option_playlist": "Liste de lecture",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Émission",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Sous-titres (CC)",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "En direct",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "emplacement",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Version actuelle : ",
"next_steps_error_message": "Vous pouvez essayer de : ",
"next_steps_error_message_refresh": "Rafraîchir la page",
@ -397,8 +396,8 @@
"preferences_region_label": "Pays du contenu : ",
"footer_donate_page": "Faire un don",
"footer_modfied_source_code": "Code source modifié",
"short": "Courte (< 4 minutes)",
"long": "Longue (> 20 minutes)",
"search_filters_duration_option_short": "Courte (< 4 minutes)",
"search_filters_duration_option_long": "Longue (> 20 minutes)",
"adminprefs_modified_source_code_url_label": "URL du dépôt du code source modifié",
"footer_documentation": "Documentation",
"footer_original_source_code": "Code source original",
@ -415,12 +414,12 @@
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"360": "360°",
"search_filters_features_option_three_sixty": "360°",
"none": "aucun",
"videoinfo_started_streaming_x_ago": "En stream depuis `x`",
"videoinfo_watch_on_youTube": "Regarder sur YouTube",
"videoinfo_youTube_embed_link": "Intégrer",
"purchased": "Acheter",
"search_filters_features_option_purchased": "Acheté",
"videoinfo_invidious_embed_link": "Lien intégré",
"download_subtitles": "Sous-titres - `x` (.vtt)",
"user_saved_playlists": "`x` listes de lecture sauvegardées",
@ -435,7 +434,7 @@
"crash_page_refresh": "tenté de <a href=\"`x`\">rafraîchir la page</a>",
"crash_page_switch_instance": "essayé d'<a href=\"`x`\">utiliser une autre instance</a>",
"crash_page_read_the_faq": "lu la <a href=\"`x`\">Foire Aux Questions (FAQ)</a>",
"crash_page_search_issue": "<a href=\"`x`\">cherché ce bug sur Github</a>",
"crash_page_search_issue": "<a href=\"`x`\">cherché ce bug sur GitHub</a>",
"crash_page_before_reporting": "Avant de signaler un bug, veuillez vous assurez que vous avez :",
"crash_page_report_issue": "Si aucune des solutions proposées ci-dessus ne vous a aidé, veuillez <a href=\"`x`\">ouvrir une \"issue\" sur GitHub</a> (de préférence en anglais) et d'y inclure le message suivant (ne PAS traduire le texte) :",
"English (United States)": "Anglais (Etats-Unis)",
@ -461,5 +460,16 @@
"Vietnamese (auto-generated)": "Vietnamien (auto-généré)",
"Russian (auto-generated)": "Russe (auto-généré)",
"Spanish (Spain)": "Espagnol (Espagne)",
"preferences_watch_history_label": "Activer l'historique de visionnage : "
"preferences_watch_history_label": "Activer l'historique de visionnage : ",
"search_filters_title": "Filtres",
"search_message_change_filters_or_query": "Essayez d'élargir votre recherche et/ou de changer les filtres.",
"search_filters_date_option_none": "Toutes les dates",
"search_filters_duration_option_medium": "Moyenne (de 4 à 20 minutes)",
"search_filters_apply_button": "Appliquer les filtres",
"search_message_no_results": "Aucun résultat.",
"search_message_use_another_instance": " Vous pouvez également <a href=\"`x`\">effectuer votre recherche sur une autre instance</a>.",
"search_filters_type_option_all": "Tous les types",
"search_filters_date_label": "Date d'ajout",
"search_filters_features_option_vr180": "VR180",
"search_filters_duration_option_none": "Toutes les durées"
}

View File

@ -274,32 +274,32 @@
"Videos": "סרטונים",
"Playlists": "פלייליסטים",
"Community": "קהילה",
"relevance": "רלוונטיות",
"rating": "דירוג",
"date": "תאריך העלאה",
"views": "מספר צפיות",
"content_type": "סוג",
"duration": "משך זמן",
"features": "תכונות",
"sort": "מיון לפי",
"hour": "השעה האחרונה",
"today": "היום",
"week": "השבוע",
"month": "החודש",
"year": "השנה",
"video": "סרטון",
"channel": "ערוץ",
"playlist": "פלייליסט",
"movie": "סרט",
"show": "תכנית טלוויזיה",
"hd": "HD",
"subtitles": "כתוביות",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Live",
"4k": "4K",
"location": "מיקום",
"hdr": "HDR",
"filter": "סינון",
"Current version: ": "הגרסה הנוכחית: "
"search_filters_sort_option_relevance": "רלוונטיות",
"search_filters_sort_option_rating": "דירוג",
"search_filters_sort_option_date": "תאריך העלאה",
"search_filters_sort_option_views": "מספר צפיות",
"search_filters_type_label": "סוג",
"search_filters_duration_label": "משך זמן",
"search_filters_features_label": "תכונות",
"search_filters_sort_label": "מיון לפי",
"search_filters_date_option_hour": "השעה האחרונה",
"search_filters_date_option_today": "היום",
"search_filters_date_option_week": "השבוע",
"search_filters_date_option_month": "החודש",
"search_filters_date_option_year": "השנה",
"search_filters_type_option_video": "סרטון",
"search_filters_type_option_channel": "ערוץ",
"search_filters_type_option_playlist": "פלייליסט",
"search_filters_type_option_movie": "סרט",
"search_filters_type_option_show": "תכנית טלוויזיה",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "כתוביות",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Live",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "מיקום",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "הגרסה הנוכחית: ",
"search_filters_title": "סינון"
}

474
locales/hi.json Normal file
View File

@ -0,0 +1,474 @@
{
"last": "आखिरी",
"Yes": "हाँ",
"No": "नहीं",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "OPML के रूप में सदस्यताएँ निर्यात करें (NewPipe और FreeTube के लिए)",
"Log in/register": "लॉग-इन/पंजीकृत करें",
"Log in with Google": "Google के साथ लॉग-इन करें",
"preferences_autoplay_label": "अपने आप चलाने की सुविधा: ",
"preferences_dark_mode_label": "थीम: ",
"preferences_default_home_label": "डिफ़ॉल्ट मुखपृष्ठ: ",
"Could not fetch comments": "टिप्पणियाँ प्राप्त न की जा सकीं",
"comments_points_count": "{{count}} पॉइंट",
"comments_points_count_plural": "{{count}} पॉइंट्स",
"Subscription manager": "सदस्यता प्रबंधन",
"License: ": "लाइसेंस: ",
"Wilson score: ": "Wilson स्कोर: ",
"Wrong answer": "गलत जवाब",
"Erroneous CAPTCHA": "गलत CAPTCHA",
"Please log in": "कृपया लॉग-इन करें",
"Bosnian": "बोस्नियाई",
"Bulgarian": "बुल्गारियाई",
"Burmese": "बर्मी",
"Chinese (Traditional)": "चीनी (पारंपरिक)",
"Kurdish": "कुर्द",
"Punjabi": "पंजाबी",
"Sinhala": "सिंहली",
"Slovak": "स्लोवाक",
"generic_count_days": "{{count}} दिन",
"generic_count_days_plural": "{{count}} दिन",
"generic_count_hours": "{{count}} घंटे",
"generic_count_hours_plural": "{{count}} घंटे",
"generic_count_minutes": "{{count}} मिनट",
"generic_count_minutes_plural": "{{count}} मिनट",
"generic_count_seconds": "{{count}} सेकंड",
"generic_count_seconds_plural": "{{count}} सेकंड",
"generic_playlists_count": "{{count}} प्लेलिस्ट",
"generic_playlists_count_plural": "{{count}} प्लेलिस्ट्स",
"crash_page_report_issue": "अगर इनमें से कुछ भी काम नहीं करता, कृपया <a href=\"`x`\">GitHub पर एक नया मुद्दा खोल दें</a> (अंग्रेज़ी में) और अपने संदेश में यह टेक्स्ट दर्ज करें (इसे अनुवादित न करें!):",
"generic_views_count": "{{count}} बार देखा गया",
"generic_views_count_plural": "{{count}} बार देखा गया",
"generic_videos_count": "{{count}} वीडियो",
"generic_videos_count_plural": "{{count}} वीडियो",
"generic_subscribers_count": "{{count}} सदस्य",
"generic_subscribers_count_plural": "{{count}} सदस्य",
"generic_subscriptions_count": "{{count}} सदस्यता",
"generic_subscriptions_count_plural": "{{count}} सदस्यताएँ",
"LIVE": "लाइव",
"Shared `x` ago": "`x` पहले बाँटा गया",
"Unsubscribe": "सदस्यता छोड़ें",
"Subscribe": "सदस्यता लें",
"View channel on YouTube": "चैनल YouTube पर देखें",
"View playlist on YouTube": "प्लेलिस्ट YouTube पर देखें",
"newest": "सबसे नया",
"oldest": "सबसे पुराना",
"popular": "सर्वाधिक लोकप्रिय",
"Next page": "अगला पृष्ठ",
"Previous page": "पिछला पृष्ठ",
"Clear watch history?": "देखने का इतिहास मिटाएँ?",
"New password": "नया पासवर्ड",
"New passwords must match": "पासवर्ड्स को मेल खाना होगा",
"Cannot change password for Google accounts": "Google खातों के लिए पासवर्ड नहीं बदल सकते",
"Authorize token?": "टोकन को प्रमाणित करें?",
"Authorize token for `x`?": "`x` के लिए टोकन को प्रमाणित करें?",
"Import and Export Data": "डेटा को आयात और निर्यात करें",
"Import": "आयात करें",
"Import Invidious data": "Invidious JSON डेटा आयात करें",
"Import YouTube subscriptions": "YouTube/OPML सदस्यताएँ आयात करें",
"Import FreeTube subscriptions (.db)": "FreeTube सदस्यताएँ आयात करें (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe सदस्यताएँ आयात करें (.json)",
"Import NewPipe data (.zip)": "NewPipe डेटा आयात करें (.zip)",
"Export": "निर्यात करें",
"Export subscriptions as OPML": "OPML के रूप में सदस्यताएँ निर्यात करें",
"Export data as JSON": "Invidious डेटा को JSON के रूप में निर्यात करें",
"Delete account?": "खाता हटाएँ?",
"History": "देखे गए वीडियो",
"An alternative front-end to YouTube": "YouTube का एक वैकल्पिक फ्रंट-एंड",
"JavaScript license information": "जावास्क्रिप्ट लाइसेंस की जानकारी",
"source": "स्रोत",
"Log in": "लॉग-इन करें",
"User ID": "सदस्य ID",
"Password": "पासवर्ड",
"Register": "पंजीकृत करें",
"E-mail": "ईमेल",
"Google verification code": "Google प्रमाणीकरण कोड",
"Time (h:mm:ss):": "समय (घं:मिमि:सेसे):",
"Text CAPTCHA": "टेक्स्ट CAPTCHA",
"Image CAPTCHA": "चित्र CAPTCHA",
"Sign In": "साइन इन करें",
"Preferences": "प्राथमिकताएँ",
"preferences_category_player": "प्लेयर की प्राथमिकताएँ",
"preferences_video_loop_label": "हमेशा लूप करें: ",
"preferences_continue_label": "डिफ़ॉल्ट से अगला चलाएँ: ",
"preferences_continue_autoplay_label": "अगला वीडियो अपने आप चलाएँ: ",
"preferences_listen_label": "डिफ़ॉल्ट से सुनें: ",
"preferences_local_label": "प्रॉक्सी वीडियो: ",
"preferences_watch_history_label": "देखने का इतिहास सक्षम करें: ",
"preferences_speed_label": "वीडियो चलाने की डिफ़ॉल्ट रफ़्तार: ",
"preferences_quality_label": "वीडियो की प्राथमिक क्वालिटी: ",
"preferences_quality_option_dash": "DASH (अनुकूली गुणवत्ता)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "मध्यम",
"preferences_quality_option_small": "छोटा",
"preferences_quality_dash_label": "प्राथमिक DASH वीडियो क्वालिटी: ",
"preferences_quality_dash_option_720p": "720p",
"preferences_quality_dash_option_auto": "अपने-आप",
"preferences_quality_dash_option_best": "सबसे अच्छा",
"preferences_quality_dash_option_worst": "सबसे खराब",
"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_480p": "480p",
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"preferences_comments_label": "डिफ़ॉल्ट टिप्पणियाँ: ",
"preferences_volume_label": "प्लेयर का वॉल्यूम: ",
"youtube": "YouTube",
"reddit": "Reddit",
"invidious": "Invidious",
"preferences_captions_label": "डिफ़ॉल्ट कैप्शन: ",
"Fallback captions: ": "वैकल्पिक कैप्शन: ",
"preferences_related_videos_label": "संबंधित वीडियो दिखाएँ: ",
"preferences_annotations_label": "डिफ़ॉल्ट से टिप्पणियाँ दिखाएँ: ",
"preferences_extend_desc_label": "अपने आप वीडियो के विवरण का विस्तार करें: ",
"preferences_vr_mode_label": "उत्तरदायी 360 डिग्री वीडियो (WebGL की ज़रूरत है): ",
"preferences_category_visual": "यथादृश्य प्राथमिकताएँ",
"preferences_region_label": "सामग्री का राष्ट्र: ",
"preferences_player_style_label": "प्लेयर का स्टाइल: ",
"Dark mode: ": "डार्क मोड: ",
"dark": "डार्क",
"light": "लाइट",
"preferences_thin_mode_label": "हल्का मोड: ",
"preferences_category_misc": "विविध प्राथमिकताएँ",
"preferences_automatic_instance_redirect_label": "अपने आप अनुप्रेषित करें (redirect.invidious.io पर फ़ॉलबैक करें): ",
"preferences_category_subscription": "सदस्यताओं की प्राथमिकताएँ",
"preferences_annotations_subscribed_label": "सदस्यता लिए गए चैनलों पर डिफ़ॉल्ट से टिप्पणियाँ दिखाएँ? ",
"Redirect homepage to feed: ": "फ़ीड पर मुखपृष्ठ को अनुप्रेषित करें: ",
"preferences_max_results_label": "फ़ीड में दिखाए जाने वाले वीडियों की संख्या: ",
"preferences_sort_label": "वीडियों को इस मानदंड पर छाँटें: ",
"published": "प्रकाशित",
"published - reverse": "प्रकाशित - उल्टा",
"Only show latest video from channel: ": "चैनल से सिर्फ नवीनतम वीडियो ही दिखाएँ: ",
"alphabetically": "वर्णक्रमानुसार",
"Only show latest unwatched video from channel: ": "चैनल से सिर्फ न देखा गया नवीनतम वीडियो ही दिखाएँ: ",
"alphabetically - reverse": "वर्णक्रमानुसार - उल्टा",
"channel name": "चैनल का नाम",
"channel name - reverse": "चैनल का नाम - उल्टा",
"preferences_unseen_only_label": "सिर्फ न देखे गए वीडियो ही दिखाएँ: ",
"preferences_notifications_only_label": "सिर्फ सूचनाएँ दिखाएँ (अगर हो तो): ",
"Enable web notifications": "वेब सूचनाएँ सक्षम करें",
"`x` uploaded a video": "`x` ने वीडियो अपलोड किया",
"`x` is live": "`x` लाइव हैं",
"preferences_category_data": "डेटा की प्राथमिकताएँ",
"Clear watch history": "देखने का इतिहास साफ़ करें",
"Import/export data": "डेटा को आयात/निर्यात करें",
"Change password": "पासवर्ड बदलें",
"Manage subscriptions": "सदस्यताएँ प्रबंधित करें",
"Manage tokens": "टोकन प्रबंधित करें",
"Watch history": "देखने का इतिहास",
"Delete account": "खाता हटाएँ",
"preferences_category_admin": "प्रबंधक प्राथमिकताएँ",
"preferences_feed_menu_label": "फ़ीड मेन्यू: ",
"preferences_show_nick_label": "ऊपर उपनाम दिखाएँ: ",
"Top enabled: ": "ऊपर का हिस्सा सक्षम है: ",
"CAPTCHA enabled: ": "CAPTCHA सक्षम है: ",
"Login enabled: ": "लॉग-इन सक्षम है: ",
"Registration enabled: ": "पंजीकरण सक्षम है: ",
"Report statistics: ": "सांख्यिकी रिपोर्ट करें: ",
"Released under the AGPLv3 on Github.": "GitHub पर AGPLv3 के अंतर्गत प्रकाशित।",
"Save preferences": "प्राथमिकताएँ सहेजें",
"Token manager": "टोकन प्रबंधन",
"Token": "टोकन",
"tokens_count": "{{count}} टोकन",
"tokens_count_plural": "{{count}} टोकन",
"Import/export": "आयात/निर्यात करें",
"unsubscribe": "सदस्यता छोड़ें",
"revoke": "हटाएँ",
"Subscriptions": "सदस्यताएँ",
"subscriptions_unseen_notifs_count": "{{count}} अपठित सूचना",
"subscriptions_unseen_notifs_count_plural": "{{count}} अपठित सूचना",
"search": "खोजें",
"Log out": "लॉग-आउट करें",
"Source available here.": "स्रोत यहाँ उपलब्ध है।",
"View JavaScript license information.": "जावास्क्रिप्ट लाइसेंस की जानकारी देखें।",
"View privacy policy.": "निजता नीति देखें।",
"Trending": "रुझान में",
"Public": "सार्वजनिक",
"Unlisted": "सबके लिए उपलब्ध नहीं",
"Private": "निजी",
"View all playlists": "सभी प्लेलिस्ट देखें",
"Create playlist": "प्लेलिस्ट बनाएँ",
"Updated `x` ago": "`x` पहले अपडेट किया गया",
"Delete playlist `x`?": "प्लेलिस्ट `x` हटाएँ?",
"Delete playlist": "प्लेलिस्ट हटाएँ",
"Title": "शीर्षक",
"Playlist privacy": "प्लेलिस्ट की निजता",
"Editing playlist `x`": "प्लेलिस्ट `x` को संपादित किया जा रहा है",
"Show more": "अधिक देखें",
"Show less": "कम देखें",
"Watch on YouTube": "YouTube पर देखें",
"Switch Invidious Instance": "Invidious उदाहरण बदलें",
"search_message_no_results": "कोई परिणाम नहीं मिला।",
"search_message_change_filters_or_query": "अपने खोज क्वेरी को और चौड़ा करें और/या फ़िल्टर बदलें।",
"search_message_use_another_instance": " आप <a href=\"`x`\">दूसरे उदाहरण पर भी खोज सकते हैं</a>।",
"Hide annotations": "टिप्पणियाँ छिपाएँ",
"Show annotations": "टिप्पणियाँ दिखाएँ",
"Genre: ": "श्रेणी: ",
"Family friendly? ": "परिवार के लिए ठीक है? ",
"Engagement: ": "सगाई: ",
"Whitelisted regions: ": "स्वीकृत क्षेत्र: ",
"Blacklisted regions: ": "अस्वीकृत क्षेत्र: ",
"Shared `x`": "`x` बाँटा गया",
"Premieres in `x`": "`x` बाद प्रीमियर होगा",
"Premieres `x`": "`x` को प्रीमिर होगा",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "नमस्कार! ऐसा लगता है कि आपका जावास्क्रिप्ट अक्षम है। टिप्पणियाँ देखने के लिए यहाँ क्लिक करें, लेकिन याद रखें कि इन्हें लोड होने में थोड़ा ज़्यादा समय लग सकता है।",
"View YouTube comments": "YouTube टिप्पणियाँ देखें",
"View more comments on Reddit": "Reddit पर अधिक टिप्पणियाँ देखें",
"View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` टिप्पणी देखें",
"": "`x` टिप्पणियाँ देखें"
},
"View Reddit comments": "Reddit पर टिप्पणियाँ",
"Hide replies": "जवाब छिपाएँ",
"Show replies": "जवाब दिखाएँ",
"Incorrect password": "गलत पासवर्ड",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "लॉग-इन नहीं किया जा सका, सुनिश्चित करें कि दो-कारक प्रमाणीकरण (Authenticator या SMS) सक्षम है।",
"Invalid TFA code": "अमान्य TFA कोड",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "लॉग-इन नाकाम रहा। ऐसा इसलिए हो सकता है कि दो-कारक प्रमाणीकरण आपके खाते पर सक्षम नहीं है।",
"Quota exceeded, try again in a few hours": "कोटा पार हो चुका है, कृपया कुछ घंटों में फिर कोशिश करें",
"CAPTCHA is a required field": "CAPTCHA एक ज़रूरी फ़ील्ड है",
"User ID is a required field": "सदस्य ID एक ज़रूरी फ़ील्ड है",
"Password is a required field": "पासवर्ड एक ज़रूरी फ़ील्ड है",
"Wrong username or password": "गलत सदस्यनाम या पासवर्ड",
"Please sign in using 'Log in with Google'": "कृपया 'Google के साथ लॉग-इन करें' के साथ साइन-इन करें",
"Password cannot be empty": "पासवर्ड खाली नहीं हो सकता",
"Password cannot be longer than 55 characters": "पासवर्ड में अधिकतम 55 अक्षर हो सकते हैं",
"Invidious Private Feed for `x`": "`x` के लिए Invidious निजी फ़ीड",
"channel:`x`": "चैनल:`x`",
"Deleted or invalid channel": "हटाया गया या अमान्य चैनल",
"This channel does not exist.": "यह चैनल मौजूद नहीं है।",
"Could not get channel info.": "चैनल की जानकारी प्राप्त न की जा सकी।",
"comments_view_x_replies": "{{count}} टिप्पणी देखें",
"comments_view_x_replies_plural": "{{count}} टिप्पणियाँ देखें",
"`x` ago": "`x` पहले",
"Load more": "अधिक लोड करें",
"Could not create mix.": "मिक्स न बनाया जा सका।",
"Empty playlist": "खाली प्लेलिस्ट",
"Not a playlist.": "यह प्लेलिस्ट नहीं है।",
"Playlist does not exist.": "प्लेलिस्ट मौजूद नहीं है।",
"Could not pull trending pages.": "रुझान के पृष्ठ प्राप्त न किए जा सके।",
"Hidden field \"challenge\" is a required field": "छिपाया गया फ़ील्ड \"चुनौती\" एक आवश्यक फ़ील्ड है",
"Hidden field \"token\" is a required field": "छिपाया गया फ़ील्ड \"टोकन\" एक आवश्यक फ़ील्ड है",
"Erroneous challenge": "त्रुटिपूर्ण चुनौती",
"Erroneous token": "त्रुटिपूर्ण टोकन",
"No such user": "यह सदस्य मौजूद नहीं हैं",
"Token is expired, please try again": "टोकन की समय-सीमा समाप्त हो चुकी है, कृपया दोबारा कोशिश करें",
"English": "अंग्रेज़ी",
"English (United Kingdom)": "अंग्रेज़ी (यूनाइटेड किंग्डम)",
"English (United States)": "अंग्रेज़ी (संयुक्त राष्ट्र)",
"English (auto-generated)": "अंग्रेज़ी (अपने-आप जनरेट हुआ)",
"Afrikaans": "अफ़्रीकी",
"Albanian": "अल्बानियाई",
"Amharic": "अम्हेरी",
"Arabic": "अरबी",
"Armenian": "आर्मेनियाई",
"Belarusian": "बेलारूसी",
"Azerbaijani": "अज़रबैजानी",
"Bangla": "बंगाली",
"Basque": "बास्क",
"Cantonese (Hong Kong)": "कैंटोनीज़ (हाँग काँग)",
"Catalan": "कातालान",
"Cebuano": "सेबुआनो",
"Chinese": "चीनी",
"Chinese (China)": "चीनी (चीन)",
"Chinese (Hong Kong)": "चीनी (हाँग काँग)",
"Chinese (Simplified)": "चीनी (सरलीकृत)",
"Chinese (Taiwan)": "चीनी (ताइवान)",
"Corsican": "कोर्सिकन",
"Croatian": "क्रोएशियाई",
"Czech": "चेक",
"Danish": "डेनिश",
"Dutch": "डच",
"Dutch (auto-generated)": "डच (अपने-आप जनरेट हुआ)",
"Esperanto": "एस्पेरांतो",
"Estonian": "एस्टोनियाई",
"Filipino": "फ़िलिपीनो",
"Finnish": "फ़िनिश",
"French": "फ़्रेंच",
"French (auto-generated)": "फ़्रेंच (अपने-आप जनरेट हुआ)",
"Galician": "गैलिशियन",
"Georgian": "जॉर्जियाई",
"German": "जर्मन",
"German (auto-generated)": "जर्मन (अपने-आप जनरेट हुआ)",
"Greek": "यूनानी",
"Gujarati": "गुजराती",
"Haitian Creole": "हैती क्रियोल",
"Hausa": "हौसा",
"Hawaiian": "हवाई",
"Hebrew": "हीब्रू",
"Hindi": "हिन्दी",
"Hmong": "हमोंग",
"Hungarian": "हंगेरी",
"Icelandic": "आइसलैंडिक",
"Igbo": "इग्बो",
"Indonesian": "इंडोनेशियाई",
"Indonesian (auto-generated)": "इंडोनेशियाई (अपने-आप जनरेट हुआ)",
"Interlingue": "इंटरलिंगुआ",
"Irish": "आयरिश",
"Italian": "इतालवी",
"Italian (auto-generated)": "इतालवी (अपने-आप जनरेट हुआ)",
"Japanese": "जापानी",
"Japanese (auto-generated)": "जापानी (अपने-आप जनरेट हुआ)",
"Javanese": "जावानीज़",
"Kannada": "कन्नड़",
"Kazakh": "कज़ाख़",
"Khmer": "खमेर",
"Korean": "कोरियाई",
"Korean (auto-generated)": "कोरियाई (अपने-आप जनरेट हुआ)",
"Kyrgyz": "किर्गीज़",
"Lao": "लाओ",
"Latin": "लैटिन",
"Latvian": "लातवियाई",
"Lithuanian": "लिथुएनियाई",
"Luxembourgish": "लग्ज़मबर्गी",
"Macedonian": "मकादूनियाई",
"Malagasy": "मालागासी",
"Malay": "मलय",
"Malayalam": "मलयालम",
"Maltese": "माल्टीज़",
"Maori": "माओरी",
"Marathi": "मराठी",
"Mongolian": "मंगोलियाई",
"Nepali": "नेपाली",
"Norwegian Bokmål": "नॉर्वेजियाई",
"Nyanja": "न्यानजा",
"Pashto": "पश्तो",
"Persian": "फ़ारसी",
"Polish": "पोलिश",
"Portuguese": "पुर्तगाली",
"Portuguese (auto-generated)": "पुर्तगाली (अपने-आप जनरेट हुआ)",
"Portuguese (Brazil)": "पुर्तगाली (ब्राज़ील)",
"Romanian": "रोमेनियाई",
"Russian": "रूसी",
"Russian (auto-generated)": "रूसी (अपने-आप जनरेट हुआ)",
"Samoan": "सामोन",
"Scottish Gaelic": "स्कॉटिश गाएलिक",
"Serbian": "सर्बियाई",
"Shona": "शोणा",
"Sindhi": "सिंधी",
"Slovenian": "स्लोवेनियाई",
"Somali": "सोमाली",
"Southern Sotho": "दक्षिणी सोथो",
"Spanish": "स्पेनी",
"Spanish (auto-generated)": "स्पेनी (अपने-आप जनरेट हुआ)",
"Spanish (Latin America)": "स्पेनी (लातिन अमेरिकी)",
"Spanish (Mexico)": "स्पेनी (मेक्सिको)",
"Spanish (Spain)": "स्पेनी (स्पेन)",
"Sundanese": "सुंडानी",
"Swahili": "स्वाहिली",
"Swedish": "स्वीडिश",
"Tajik": "ताजीक",
"Tamil": "तमिल",
"Telugu": "तेलुगु",
"Thai": "थाई",
"Turkish": "तुर्की",
"Turkish (auto-generated)": "तुर्की (अपने-आप जनरेट हुआ)",
"Ukrainian": "यूक्रेनी",
"Urdu": "उर्दू",
"Uzbek": "उज़्बेक",
"Vietnamese": "वियतनामी",
"Vietnamese (auto-generated)": "वियतनामी (अपने-आप जनरेट हुआ)",
"Welsh": "Welsh",
"Western Frisian": "पश्चिमी फ़्रिसियाई",
"Xhosa": "खोसा",
"Yiddish": "यहूदी",
"generic_count_years": "{{count}} वर्ष",
"generic_count_years_plural": "{{count}} वर्ष",
"Yoruba": "योरुबा",
"generic_count_months": "{{count}} महीने",
"generic_count_months_plural": "{{count}} महीने",
"Zulu": "ज़ूलू",
"generic_count_weeks": "{{count}} हफ़्ते",
"generic_count_weeks_plural": "{{count}} हफ़्ते",
"Fallback comments: ": "फ़ॉलबैक टिप्पणियाँ: ",
"Popular": "प्रसिद्ध",
"Search": "खोजें",
"Top": "ऊपर",
"About": "जानकारी",
"Rating: ": "रेटिंग: ",
"preferences_locale_label": "भाषा: ",
"View as playlist": "प्लेलिस्ट के रूप में देखें",
"Default": "डिफ़ॉल्ट",
"Download": "डाउनलोड करें",
"Download as: ": "इस रूप में डाउनलोड करें: ",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"Music": "संगीत",
"Gaming": "गेमिंग",
"News": "समाचार",
"Movies": "फ़िल्में",
"(edited)": "(संपादित)",
"YouTube comment permalink": "YouTube पर टिप्पणी की स्थायी कड़ी",
"permalink": "स्थायी कड़ी",
"Videos": "वीडियो",
"`x` marked it with a ❤": "`x` ने इसे एक ❤ से चिह्नित किया",
"Audio mode": "ऑडियो मोड",
"Playlists": "प्लेलिस्ट्स",
"Video mode": "वीडियो मोड",
"Community": "समुदाय",
"search_filters_title": "फ़िल्टर",
"search_filters_date_label": "अपलोड करने का समय",
"search_filters_date_option_none": "कोई भी समय",
"search_filters_date_option_week": "इस हफ़्ते",
"search_filters_date_option_month": "इस महीने",
"search_filters_date_option_hour": "पिछला घंटा",
"search_filters_date_option_today": "आज",
"search_filters_date_option_year": "इस साल",
"search_filters_type_label": "प्रकार",
"search_filters_type_option_all": "कोई भी प्रकार",
"search_filters_type_option_video": "वीडियो",
"search_filters_type_option_channel": "चैनल",
"search_filters_sort_option_relevance": "प्रासंगिकता",
"search_filters_type_option_playlist": "प्लेलिस्ट",
"search_filters_type_option_movie": "फ़िल्म",
"search_filters_type_option_show": "शो",
"search_filters_duration_label": "अवधि",
"search_filters_duration_option_none": "कोई भी अवधि",
"search_filters_duration_option_short": "4 मिनट से कम",
"search_filters_duration_option_medium": "4 से 20 मिनट तक",
"search_filters_duration_option_long": "20 मिनट से ज़्यादा",
"search_filters_features_label": "सुविधाएँ",
"search_filters_features_option_live": "लाइव",
"search_filters_sort_option_rating": "रेटिंग",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "उपशीर्षक/कैप्शन",
"search_filters_features_option_c_commons": "क्रिएटिव कॉमन्स",
"search_filters_features_option_three_sixty": "360°",
"search_filters_features_option_vr180": "VR180",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_hdr": "HDR",
"search_filters_features_option_location": "जगह",
"search_filters_features_option_purchased": "खरीदा गया",
"search_filters_sort_label": "इस क्रम से लगाएँ",
"search_filters_sort_option_date": "अपलोड की ताऱीख",
"search_filters_sort_option_views": "देखे जाने की संख्या",
"search_filters_apply_button": "चयनित फ़िल्टर लागू करें",
"footer_documentation": "प्रलेख",
"footer_source_code": "स्रोत कोड",
"footer_original_source_code": "मूल स्रोत कोड",
"footer_modfied_source_code": "बदला गया स्रोत कोड",
"Current version: ": "वर्तमान संस्करण: ",
"next_steps_error_message": "इसके बाद आपके ये आज़माने चाहिए: ",
"next_steps_error_message_refresh": "साफ़ करें",
"next_steps_error_message_go_to_youtube": "YouTube पर जाएँ",
"footer_donate_page": "दान करें",
"adminprefs_modified_source_code_url_label": "बदले गए स्रोत कोड के रिपॉज़िटरी का URL",
"none": "कुछ नहीं",
"videoinfo_started_streaming_x_ago": "`x` पहले स्ट्रीम करना शुरू किया",
"videoinfo_watch_on_youTube": "YouTube पर देखें",
"Video unavailable": "वीडियो उपलब्ध नहीं है",
"preferences_save_player_pos_label": "यहाँ से चलाना शुरू करें: ",
"crash_page_you_found_a_bug": "शायद आपको Invidious में कोई बग नज़र आ गया है!",
"videoinfo_youTube_embed_link": "एम्बेड करें",
"videoinfo_invidious_embed_link": "एम्बेड करने की कड़ी",
"download_subtitles": "उपशीर्षक - `x` (.vtt)",
"user_created_playlists": "बनाए गए `x` प्लेलिस्ट्स",
"user_saved_playlists": "सहेजे गए `x` प्लेलिस्ट्स",
"crash_page_before_reporting": "बग रिपोर्ट करने से पहले:",
"crash_page_switch_instance": "<a href=\"`x`\">किसी दूसरे उदाहरण का इस्तेमाल करें</a>",
"crash_page_read_the_faq": "<a href=\"`x`\">अक्सर पूछे जाने वाले प्रश्न (FAQ)</a> पढ़ें",
"crash_page_refresh": "<a href=\"`x`\">पृष्ठ को एक बार साफ़ करें</a>",
"crash_page_search_issue": "<a href=\"`x`\">GitHub पर मौजूदा मुद्दे</a> ढूँढ़ें"
}

View File

@ -88,7 +88,7 @@
"channel name": "ime kanala",
"channel name - reverse": "ime kanala obrnuto",
"Only show latest video from channel: ": "Prikaži samo najnovija videa kanala: ",
"Only show latest unwatched video from channel: ": "Prikaži samo najnovija nepogledana videa kanala: ",
"Only show latest unwatched video from channel: ": "Prikaži samo najnovija nepogledana videa od kanala: ",
"preferences_unseen_only_label": "Prikaži samo nepogledane: ",
"preferences_notifications_only_label": "Prikaži samo obavijesti (ako ih ima): ",
"Enable web notifications": "Aktiviraj web-obavijesti",
@ -107,7 +107,7 @@
"preferences_feed_menu_label": "Izbornik za feedove: ",
"preferences_show_nick_label": "Prikaži nadimak na vrhu: ",
"Top enabled: ": "Najbolji aktivirani: ",
"CAPTCHA enabled: ": "Aktivirani CAPTCHA: ",
"CAPTCHA enabled: ": "CAPTCHA aktiviran: ",
"Login enabled: ": "Prijava aktivirana: ",
"Registration enabled: ": "Registracija aktivirana: ",
"Report statistics: ": "Izvještaj o statistici: ",
@ -121,7 +121,7 @@
"Subscriptions": "Pretplate",
"search": "traži",
"Log out": "Odjavi se",
"Released under the AGPLv3 on Github.": "Izdano pod licencom AGPLv3 na Github-u.",
"Released under the AGPLv3 on Github.": "Izdano pod licencom AGPLv3 na GitHub-u.",
"Source available here.": "Izvor je ovdje dostupan.",
"View JavaScript license information.": "Prikaži informacije o JavaScript licenci.",
"View privacy policy.": "Prikaži politiku privatnosti.",
@ -137,11 +137,10 @@
"Title": "Naslov",
"Playlist privacy": "Privatnost zbirke",
"Editing playlist `x`": "Uređivanje zbirke `x`",
"Show more": "Pokaži više",
"Show less": "Pokaži manje",
"Show more": "Prikaži više",
"Show less": "Prikaži manje",
"Watch on YouTube": "Gledaj na YouTubeu",
"Switch Invidious Instance": "Promijeni Invidious instancu",
"Broken? Try another Invidious Instance": "Pokvarena? Probaj jednu drugu Invidious instancu",
"Hide annotations": "Sakrij napomene",
"Show annotations": "Prikaži napomene",
"Genre: ": "Žanr: ",
@ -319,7 +318,7 @@
"Movies": "Filmovi",
"Download": "Preuzmi",
"Download as: ": "Preuzmi kao: ",
"%A %B %-d, %Y": "%A, %-d. %B %Y",
"%A %B %-d, %Y": "%A, %-d. %B %Y.",
"(edited)": "(uređeno)",
"YouTube comment permalink": "Stalna poveznica YouTube komentara",
"permalink": "stalna poveznica",
@ -329,41 +328,40 @@
"Videos": "Videa",
"Playlists": "Zbirke",
"Community": "Zajednica",
"relevance": "značaj",
"rating": "ocjena",
"date": "datum",
"views": "prikazi",
"content_type": "vrsta_sadržaja",
"duration": "trajanje",
"features": "funkcije",
"sort": "redoslijed",
"hour": "sat",
"today": "danas",
"week": "tjedan",
"month": "mjesec",
"year": "godina",
"video": "video",
"channel": "kanal",
"playlist": "Zbirka",
"movie": "film",
"show": "emisija",
"hd": "hd",
"subtitles": "titlovi",
"creative_commons": "creative_commons",
"3d": "3d",
"live": "uživo",
"4k": "4k",
"location": "lokacija",
"hdr": "hdr",
"filter": "filtar",
"search_filters_sort_option_relevance": "Značaj",
"search_filters_sort_option_rating": "Ocjena",
"search_filters_sort_option_date": "Datum prijenosa",
"search_filters_sort_option_views": "Broj gledanja",
"search_filters_type_label": "Vrsta",
"search_filters_duration_label": "Trajanje",
"search_filters_features_label": "Funkcije",
"search_filters_sort_label": "Redoslijed",
"search_filters_date_option_hour": "Zadnjih sat vremena",
"search_filters_date_option_today": "Danas",
"search_filters_date_option_week": "Ovaj tjedan",
"search_filters_date_option_month": "Ovaj mjesec",
"search_filters_date_option_year": "Ova godina",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Zbirka",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Emisija",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Titlovi/CC",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Uživo",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "Lokacija",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Trenutačna verzija: ",
"next_steps_error_message": "Nakon toga bi trebali pokušati sljedeće: ",
"next_steps_error_message_refresh": "Aktualiziraj stranicu",
"next_steps_error_message_go_to_youtube": "Idi na YouTube",
"footer_donate_page": "Doniraj",
"adminprefs_modified_source_code_url_label": "URL do repozitorija izmijenjenog izvornog koda",
"short": "Kratki (< 4 minute)",
"long": "Dugi (> 20 minute)",
"search_filters_duration_option_short": "Kratko (< 4 minute)",
"search_filters_duration_option_long": "Dugo (> 20 minute)",
"footer_source_code": "Izvorni kod",
"footer_modfied_source_code": "Izmijenjeni izvorni kod",
"footer_documentation": "Dokumentacija",
@ -382,12 +380,12 @@
"preferences_quality_dash_option_240p": "240 p",
"preferences_quality_dash_option_144p": "144 p",
"invidious": "Invidious",
"purchased": "Kupljeno",
"360": "360 °",
"search_filters_features_option_purchased": "Kupljeno",
"search_filters_features_option_three_sixty": "360 °",
"none": "bez",
"videoinfo_youTube_embed_link": "Ugradi",
"user_created_playlists": "`x` stvorene zbirke",
"user_saved_playlists": "`x` spremljene zbirke",
"user_created_playlists": "`x` je stvorio/la zbirke",
"user_saved_playlists": "`x` je spremio/la zbirke",
"Video unavailable": "Video nedostupan",
"preferences_save_player_pos_label": "Spremi mjesto reprodukcije: ",
"videoinfo_watch_on_youTube": "Gledaj na YouTubeu",
@ -434,7 +432,7 @@
"generic_subscriptions_count_2": "{{count}} pretplata",
"generic_playlists_count_0": "{{count}} zbirka",
"generic_playlists_count_1": "{{count}} zbirke",
"generic_playlists_count_2": "{{count}} zbirka",
"generic_playlists_count_2": "{{count}} zbiraka",
"generic_videos_count_0": "{{count}} video",
"generic_videos_count_1": "{{count}} videa",
"generic_videos_count_2": "{{count}} videa",
@ -452,7 +450,7 @@
"crash_page_refresh": "pokušaj <a href=\"`x`\">aktualizirati stranicu</a>",
"crash_page_switch_instance": "pokušaj <a href=\"`x`\">koristiti jednu drugu instancu</a>",
"crash_page_read_the_faq": "pročitaj <a href=\"`x`\">Često postavljena pitanja (ČPP)</a>",
"crash_page_search_issue": "pretraži <a href=\"`x`\">postojeće probleme na Github-u</a>",
"crash_page_search_issue": "pretraži <a href=\"`x`\">postojeće probleme na GitHub-u</a>",
"crash_page_report_issue": "Ako ništa od gore navedenog ne pomaže, <a href=\"`x`\">prijavi novi problem na GitHub-u</a> (po mogućnosti na engleskom) i uključi sljedeći tekst u poruku (NEMOJ prevoditi taj tekst):",
"English (United Kingdom)": "Engleski (Ujedinjeno Kraljevstvo)",
"English (United States)": "Engleski (Sjedinjene Američke Države)",
@ -476,5 +474,18 @@
"Chinese (Hong Kong)": "Kineski (Hong Kong)",
"Korean (auto-generated)": "Korejski (automatski generiran)",
"Portuguese (auto-generated)": "Portugalski (automatski generiran)",
"Spanish (auto-generated)": "Španjolski (automatski generiran)"
"Spanish (auto-generated)": "Španjolski (automatski generiran)",
"preferences_watch_history_label": "Aktiviraj povijest gledanja: ",
"search_filters_title": "Filtri",
"search_filters_date_option_none": "Bilo koji datum",
"search_filters_date_label": "Datum prijenosa",
"search_message_no_results": "Nema rezultata.",
"search_message_use_another_instance": " Također možeš <a href=\"`x`\">tražiti na jednoj drugoj instanci</a>.",
"search_message_change_filters_or_query": "Pokušaj proširiti upit za pretragu i/ili promijeni filtre.",
"search_filters_features_option_vr180": "VR180",
"search_filters_duration_option_none": "Bilo koje duljine",
"search_filters_duration_option_medium": "Srednje (4 20 minuta)",
"search_filters_apply_button": "Primijeni odabrane filtre",
"search_filters_type_option_all": "Bilo koja vrsta",
"Popular enabled: ": "Popularni aktivirani: "
}

View File

@ -31,15 +31,15 @@
"No": "Nem",
"Import and Export Data": "Adatok importálása és exportálása",
"Import": "Importálás",
"Import Invidious data": "Az Invidious adatainak importálása",
"Import YouTube subscriptions": "YouTube-feliratkozások importálása",
"Import Invidious data": "Az Invidious JSON-adatainak importálása",
"Import YouTube subscriptions": "YouTube- vagy OPML-feliratkozások importálása",
"Import FreeTube subscriptions (.db)": "FreeTube-feliratkozások importálása (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe-feliratkozások importálása (.json)",
"Import NewPipe data (.zip)": "NewPipe adatainak importálása (.zip)",
"Export": "Exportálás",
"Export subscriptions as OPML": "Feliratkozások exportálása OPML-ként",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Feliratkozások exportálása OPML-ként (NewPipe-hoz és FreeTube-hoz)",
"Export data as JSON": "Adat exportálása JSON-ként",
"Export data as JSON": "Az Invidious JSON-adatainak exportálása",
"Delete account?": "Törlésre kerüljön a fiók?",
"History": "Megnézett videók naplója",
"An alternative front-end to YouTube": "Ez az oldal egyike a YouTube alternatív kezelőfelületeinek",
@ -159,7 +159,7 @@
"Engagement: ": "Visszajelzési mutató: ",
"Whitelisted regions: ": "Engedélyezett régiók: ",
"Blacklisted regions: ": "Tiltott régiók: ",
"Shared `x`": "`x` napon osztották meg",
"Shared `x`": "`x` dátummal osztották meg",
"Premieres in `x`": "`x` később lesz a premierje",
"Premieres `x`": "`x` lesz a premierje",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Helló! Úgy tűnik a JavaScript ki van kapcsolva a böngészőben. Ide kattintva lehet olvasni a hozzászólásokat, de a betöltésük így kicsit több időbe telik.",
@ -365,14 +365,14 @@
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"videoinfo_started_streaming_x_ago": "`x` ezelőtt kezdte streamelni",
"views": "Mennyien látták",
"purchased": "Megvásárolva",
"360": "360°-os",
"search_filters_sort_option_views": "Mennyien látták",
"search_filters_features_option_purchased": "Megvásárolt",
"search_filters_features_option_three_sixty": "360°-os virtuális valóság",
"footer_original_source_code": "Eredeti forráskód",
"none": "egyik sem",
"videoinfo_watch_on_youTube": "YouTube-on megnézni",
"videoinfo_youTube_embed_link": "beágyazva",
"videoinfo_invidious_embed_link": "Beágyazás linkje",
"videoinfo_invidious_embed_link": "Beágyazott hivatkozás",
"download_subtitles": "Felirat `x` (.vtt)",
"user_created_playlists": "`x` létrehozott lejátszási lista",
"user_saved_playlists": "`x` mentett lejátszási lista",
@ -382,14 +382,13 @@
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_label": "DASH-videó minősége: ",
"preferences_quality_option_small": "Rossz",
"date": "Feltöltés dátuma",
"search_filters_sort_option_date": "Feltöltés dátuma",
"Video unavailable": "A videó nem érhető el",
"preferences_save_player_pos_label": "A videó folytatása onnan, ahol félbe lett hagyva: ",
"preferences_show_nick_label": "Becenév mutatása felül: ",
"Released under the AGPLv3 on Github.": "AGPLv3 licenc alapján a GitHubon",
"3d": "3D-ben",
"live": "Élőben",
"filter": "Szűrők",
"search_filters_features_option_three_d": "3D-ben",
"search_filters_features_option_live": "Élőben",
"next_steps_error_message_refresh": "Újratöltés",
"footer_donate_page": "Adakozás",
"footer_source_code": "Forráskód",
@ -397,40 +396,39 @@
"adminprefs_modified_source_code_url_label": "A módosított forráskód repositoryjának URL-je:",
"preferences_automatic_instance_redirect_label": "Váltáskor másik Invidious oldal automatikus betöltése (redirect.invidious.io töltődik, ha nem működne): ",
"preferences_region_label": "Ország tartalmainak mutatása: ",
"relevance": "Relevancia",
"rating": "Pontszám",
"content_type": "Típus",
"today": "Mai napon",
"channel": "Csatorna",
"video": "Videó",
"playlist": "Lejátszási lista",
"creative_commons": "Creative Commons",
"features": "Jellemzők",
"sort": "Rendezés módja",
"search_filters_sort_option_relevance": "Relevancia",
"search_filters_sort_option_rating": "Pontszám",
"search_filters_type_label": "Típus",
"search_filters_date_option_today": "Mai napon",
"search_filters_type_option_channel": "Csatorna",
"search_filters_type_option_video": "Videó",
"search_filters_type_option_playlist": "Lejátszási lista",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_label": "Jellemzők",
"search_filters_sort_label": "Rendezés módja",
"preferences_category_misc": "További beállítások",
"%A %B %-d, %Y": "%Y. %B %-d %A",
"long": "Hosszú (20 percnél hosszabb)",
"year": "Ebben az évben",
"hour": "Az elmúlt órában",
"movie": "Film",
"hdr": "HDR",
"Broken? Try another Invidious Instance": "Nem működik? Próbáld meg egy másik Invidious oldallal.",
"duration": "Játékidő",
"search_filters_duration_option_long": "Hosszú (20 percnél hosszabb)",
"search_filters_date_option_year": "Ebben az évben",
"search_filters_date_option_hour": "Az elmúlt órában",
"search_filters_type_option_movie": "Film",
"search_filters_features_option_hdr": "HDR",
"search_filters_duration_label": "Játékidő",
"next_steps_error_message": "Az alábbi lehetőségek állnak rendelkezésre: ",
"Xhosa": "xhosza",
"Switch Invidious Instance": "Váltás másik Invidious-oldalra",
"Urdu": "urdu",
"week": "Ezen a héten",
"search_filters_date_option_week": "Ezen a héten",
"Invalid TFA code": "A kétlépéses hitelesítés kódja nem megfelelő",
"footer_documentation": "Dokumentáció",
"hd": "HD",
"search_filters_features_option_hd": "HD",
"next_steps_error_message_go_to_youtube": "Ugrás a YouTube-ra",
"show": "Műsor",
"4k": "4K",
"short": "Rövid (4 percnél nem több)",
"month": "Ebben a hónapban",
"subtitles": "Felirattal",
"location": "Közelben",
"search_filters_type_option_show": "Műsor",
"search_filters_features_option_four_k": "4K",
"search_filters_duration_option_short": "Rövid (4 percnél nem több)",
"search_filters_date_option_month": "Ebben a hónapban",
"search_filters_features_option_subtitles": "Felirattal",
"search_filters_features_option_location": "Közelben",
"crash_page_you_found_a_bug": "Úgy néz ki, találtál egy hibát az Invidiousban.",
"crash_page_before_reporting": "Mielőtt jelentenéd a hibát:",
"crash_page_read_the_faq": "olvasd el a <a href=\"`x`\">Gyakran Ismételt Kérdéseket (GYIK)</a>",
@ -460,5 +458,17 @@
"Italian (auto-generated)": "olasz (automatikusan generált)",
"Dutch (auto-generated)": "holland (automatikusan generált)",
"French (auto-generated)": "francia (automatikusan generált)",
"Vietnamese (auto-generated)": "vietnámi (automatikusan generált)"
"Vietnamese (auto-generated)": "vietnámi (automatikusan generált)",
"search_filters_title": "Szűrők",
"preferences_watch_history_label": "Megnézett videók naplózása: ",
"search_message_no_results": "Nincs találat.",
"search_message_change_filters_or_query": "Próbálj meg bővebben rákeresni vagy a szűrőkön állítani.",
"search_message_use_another_instance": " Megpróbálhatod <a href=\"`x`\">egy másik</a> Invidious-oldalon is a keresést.",
"search_filters_date_label": "Feltöltés ideje",
"search_filters_date_option_none": "Mindegy mikor",
"search_filters_type_option_all": "Bármilyen",
"search_filters_duration_option_none": "Mindegy",
"search_filters_duration_option_medium": "Átlagos (4 és 20 perc között)",
"search_filters_features_option_vr180": "180°-os virtuális valóság",
"search_filters_apply_button": "Keresés a megadott szűrőkkel"
}

View File

@ -26,15 +26,15 @@
"No": "Tidak",
"Import and Export Data": "Impor dan Ekspor Data",
"Import": "Impor",
"Import Invidious data": "Impor data Invidious",
"Import YouTube subscriptions": "Impor langganan YouTube",
"Import Invidious data": "Impor JSON data Invidious",
"Import YouTube subscriptions": "Impor langganan YouTube/OPML",
"Import FreeTube subscriptions (.db)": "Impor langganan FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Impor langganan NewPipe (.json)",
"Import NewPipe data (.zip)": "Impor data NewPipe (.zip)",
"Export": "Ekspor",
"Export subscriptions as OPML": "Ekspor langganan sebagai OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Ekspor langganan sebagai OPML (untuk NewPipe & FreeTube)",
"Export data as JSON": "Ekspor data sebagai JSON",
"Export data as JSON": "Ekspor data Invidious sebagai JSON",
"Delete account?": "Hapus akun?",
"History": "Riwayat",
"An alternative front-end to YouTube": "Sebuah alternatif layar depan untuk YouTube",
@ -71,7 +71,7 @@
"preferences_related_videos_label": "Tampilkan video terkait: ",
"preferences_annotations_label": "Tampilkan anotasi secara baku: ",
"preferences_extend_desc_label": "Perluas deskripsi video secara otomatis: ",
"preferences_vr_mode_label": "Video interaktif 360°: ",
"preferences_vr_mode_label": "Video interaktif 360° (memerlukan WebGL): ",
"preferences_category_visual": "Preferensi visual",
"preferences_player_style_label": "Gaya pemutar: ",
"Dark mode: ": "Mode gelap: ",
@ -126,9 +126,9 @@
"revoke": "cabut",
"Subscriptions": "Langganan",
"subscriptions_unseen_notifs_count_0": "{{count}} pemberitahuan belum dilihat",
"search": "cari",
"search": "Telusuri",
"Log out": "Keluar",
"Released under the AGPLv3 on Github.": "Dirilis di bawah AGPLv3 di Github.",
"Released under the AGPLv3 on Github.": "Dirilis di bawah AGPLv3 di GitHub.",
"Source available here.": "Sumber tersedia di sini.",
"View JavaScript license information.": "Tampilkan informasi lisensi JavaScript.",
"View privacy policy.": "Lihat kebijakan privasi.",
@ -148,7 +148,6 @@
"Show less": "Tampilkan lebih sedikit",
"Watch on YouTube": "Tonton di YouTube",
"Switch Invidious Instance": "Ganti peladen Invidious",
"Broken? Try another Invidious Instance": "Rusak? Coba peladen Invidious yang lain",
"Hide annotations": "Sembunyikan anotasi",
"Show annotations": "Tampilkan anotasi",
"Genre: ": "Genre: ",
@ -345,33 +344,32 @@
"Videos": "Video",
"Playlists": "Daftar putar",
"Community": "Komunitas",
"relevance": "Relevansi",
"rating": "Penilaian",
"date": "Tanggal unggah",
"views": "Jumlah ditonton",
"content_type": "Tipe",
"duration": "Durasi",
"features": "Fitur",
"sort": "Urut Berdasarkan",
"hour": "Jam Terakhir",
"today": "Hari Ini",
"week": "Pekan Ini",
"month": "Bulan Ini",
"year": "Tahun Ini",
"video": "Video",
"channel": "Kanal",
"playlist": "Daftar Putar",
"movie": "Film",
"show": "Pertunjukan/Acara",
"hd": "HD",
"subtitles": "Takarir",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Siaran Langsung",
"4k": "4K",
"location": "Lokasi",
"hdr": "HDR",
"filter": "Saring",
"search_filters_sort_option_relevance": "Relevansi",
"search_filters_sort_option_rating": "Penilaian",
"search_filters_sort_option_date": "Tanggal Unggah",
"search_filters_sort_option_views": "Jumlah ditonton",
"search_filters_type_label": "Tipe",
"search_filters_duration_label": "Durasi",
"search_filters_features_label": "Fitur",
"search_filters_sort_label": "Urut Berdasarkan",
"search_filters_date_option_hour": "Jam Terakhir",
"search_filters_date_option_today": "Hari Ini",
"search_filters_date_option_week": "Pekan Ini",
"search_filters_date_option_month": "Bulan Ini",
"search_filters_date_option_year": "Tahun Ini",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Daftar Putar",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Pertunjukan/Acara",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Takarir",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Siaran Langsung",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Lokasi",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Versi saat ini: ",
"next_steps_error_message": "Setelah itu Anda harus mencoba: ",
"next_steps_error_message_refresh": "Segarkan",
@ -380,8 +378,8 @@
"adminprefs_modified_source_code_url_label": "URL ke repositori kode sumber yang dimodifikasi",
"footer_source_code": "Kode sumber",
"footer_original_source_code": "Kode sumber yang asli",
"short": "Pendek (< 4 menit)",
"long": "Panjang (> 20 menit)",
"search_filters_duration_option_short": "Pendek (< 4 menit)",
"search_filters_duration_option_long": "Panjang (> 20 menit)",
"footer_modfied_source_code": "Kode sumber yang dimodifikasi",
"footer_documentation": "Dokumentasi",
"preferences_region_label": "Konten dari negara: ",
@ -398,8 +396,8 @@
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"purchased": "Dibeli",
"360": "360°",
"search_filters_features_option_purchased": "Dibeli",
"search_filters_features_option_three_sixty": "360°",
"none": "tidak ada",
"videoinfo_watch_on_youTube": "Tonton di YouTube",
"videoinfo_youTube_embed_link": "Tersemat",
@ -416,5 +414,39 @@
"Video unavailable": "Video tidak tersedia",
"preferences_save_player_pos_label": "Simpan posisi pemutaran: ",
"crash_page_you_found_a_bug": "Sepertinya kamu telah menemukan masalah di invidious!",
"crash_page_before_reporting": "Sebelum melaporkan masalah, pastikan anda memiliki:"
"crash_page_before_reporting": "Sebelum melaporkan masalah, pastikan anda memiliki:",
"English (United States)": "Inggris (US)",
"preferences_watch_history_label": "Aktifkan riwayat tontonan: ",
"English (United Kingdom)": "Inggris (UK)",
"search_filters_title": "Saring",
"search_message_no_results": "Tidak ada hasil yang ditemukan.",
"search_message_change_filters_or_query": "Coba perbanyak kueri pencarian dan/atau ubah filter Anda.",
"search_message_use_another_instance": " Anda juga bisa <a href=\"`x`\">mencari di peladen lain</a>.",
"Indonesian (auto-generated)": "Indonesia (dibuat secara otomatis)",
"Japanese (auto-generated)": "Jepang (dibuat secara otomatis)",
"Korean (auto-generated)": "Korea (dibuat secara otomatis)",
"Portuguese (Brazil)": "Portugis (Brasil)",
"Russian (auto-generated)": "Rusia (dibuat secara otomatis)",
"Spanish (Mexico)": "Spanyol (Meksiko)",
"Spanish (Spain)": "Spanyol (Spanyol)",
"Vietnamese (auto-generated)": "Vietnam (dibuat secara otomatis)",
"search_filters_features_option_vr180": "VR180",
"Spanish (auto-generated)": "Spanyol (dibuat secara otomatis)",
"Chinese": "Bahasa Cina",
"Chinese (Taiwan)": "Bahasa Cina (Taiwan)",
"Chinese (Hong Kong)": "Bahasa Cina (Hong Kong)",
"Chinese (China)": "Bahasa Cina (China)",
"French (auto-generated)": "Perancis (dibuat secara otomatis)",
"German (auto-generated)": "Jerman (dibuat secara otomatis)",
"Italian (auto-generated)": "Italia (dibuat secara otomatis)",
"Portuguese (auto-generated)": "Portugis (dibuat secara otomatis)",
"Turkish (auto-generated)": "Turki (dibuat secara otomatis)",
"search_filters_date_label": "Tanggal unggah",
"search_filters_type_option_all": "Segala jenis",
"search_filters_apply_button": "Terapkan saringan yang dipilih",
"Dutch (auto-generated)": "Belanda (dihasilkan secara otomatis)",
"search_filters_date_option_none": "Tanggal berapa pun",
"search_filters_duration_option_none": "Durasi berapa pun",
"search_filters_duration_option_medium": "Sedang (4 - 20 menit)",
"Cantonese (Hong Kong)": "Bahasa Kanton (Hong Kong)"
}

View File

@ -14,7 +14,7 @@
"newest": "più recente",
"oldest": "più vecchio",
"popular": "Tendenze",
"last": "durare",
"last": "ultimo",
"Next page": "Pagina successiva",
"Previous page": "Pagina precedente",
"Clear watch history?": "Eliminare la cronologia dei video guardati?",
@ -27,15 +27,15 @@
"No": "No",
"Import and Export Data": "Importazione ed esportazione dati",
"Import": "Importa",
"Import Invidious data": "Importa dati Invidious",
"Import YouTube subscriptions": "Importa le iscrizioni da YouTube",
"Import Invidious data": "Importa dati Invidious in formato JSON",
"Import YouTube subscriptions": "Importa le iscrizioni da YouTube/OPML",
"Import FreeTube subscriptions (.db)": "Importa le iscrizioni da FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importa le iscrizioni da NewPipe (.json)",
"Import NewPipe data (.zip)": "Importa i dati di NewPipe (.zip)",
"Export": "Esporta",
"Export subscriptions as OPML": "Esporta gli abbonamenti come OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Esporta gli abbonamenti come OPML (per NewPipe e FreeTube)",
"Export data as JSON": "Esporta i dati in formato JSON",
"Export data as JSON": "Esporta i dati Invidious in formato JSON",
"Delete account?": "Eliminare l'account?",
"History": "Cronologia",
"An alternative front-end to YouTube": "Un'interfaccia alternativa per YouTube",
@ -158,7 +158,7 @@
"generic_views_count_plural": "{{count}} visualizzazioni",
"Premieres in `x`": "In anteprima in `x`",
"Premieres `x`": "In anteprima `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Ciao! Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti. Considera che potrebbe volerci più tempo.",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Ciao, Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti, ma considera che il caricamento potrebbe richiedere più tempo.",
"View YouTube comments": "Visualizza i commenti da YouTube",
"View more comments on Reddit": "Visualizza più commenti su Reddit",
"View `x` comments": {
@ -212,7 +212,7 @@
"Azerbaijani": "Azero",
"Bangla": "Bengalese",
"Basque": "Basco",
"Belarusian": "Biellorusso",
"Belarusian": "Bielorusso",
"Bosnian": "Bosniaco",
"Bulgarian": "Bulgaro",
"Burmese": "Birmano",
@ -238,10 +238,10 @@
"Haitian Creole": "Creolo haitiano",
"Hausa": "Lingua hausa",
"Hawaiian": "Hawaiano",
"Hebrew": "Ebreo",
"Hebrew": "Ebraico",
"Hindi": "Hindi",
"Hmong": "Hmong",
"Hungarian": "Ungarese",
"Hungarian": "Ungherese",
"Icelandic": "Islandese",
"Igbo": "Igbo",
"Indonesian": "Indonesiano",
@ -254,7 +254,7 @@
"Khmer": "Khmer",
"Korean": "Coreano",
"Kurdish": "Curdo",
"Kyrgyz": "Kirghize",
"Kyrgyz": "Kirghiso",
"Lao": "Lao",
"Latin": "Latino",
"Latvian": "Lettone",
@ -269,7 +269,7 @@
"Marathi": "Marathi",
"Mongolian": "Mongolo",
"Nepali": "Nepalese",
"Norwegian Bokmål": "Norvegese",
"Norwegian Bokmål": "Norvegese bokmål",
"Nyanja": "Nyanja",
"Pashto": "Pashtu",
"Persian": "Persiano",
@ -278,7 +278,7 @@
"Punjabi": "Punjabi",
"Romanian": "Rumeno",
"Russian": "Russo",
"Samoan": "Samoan",
"Samoan": "Samoano",
"Scottish Gaelic": "Gaelico scozzese",
"Serbian": "Serbo",
"Shona": "Shona",
@ -293,15 +293,15 @@
"Sundanese": "Sudanese",
"Swahili": "Swahili",
"Swedish": "Svedese",
"Tajik": "Tajik",
"Tajik": "Tagico",
"Tamil": "Tamil",
"Telugu": "Telugu",
"Thai": "Thaï",
"Thai": "Thailandese",
"Turkish": "Turco",
"Ukrainian": "Ucraino",
"Urdu": "Urdu",
"Uzbek": "Uzbeco",
"Vietnamese": "Vietnamese",
"Vietnamese": "Vietnamita",
"Welsh": "Gallese",
"Western Frisian": "Frisone occidentale",
"Xhosa": "Xhosa",
@ -340,39 +340,38 @@
"%A %B %-d, %Y": "%A %-d %B %Y",
"(edited)": "(modificato)",
"YouTube comment permalink": "Link permanente al commento di YouTube",
"permalink": "permalink",
"permalink": "perma-collegamento",
"`x` marked it with a ❤": "`x` l'ha contrassegnato con un ❤",
"Audio mode": "Modalità audio",
"Video mode": "Modalità video",
"Videos": "Video",
"Playlists": "Playlist",
"Community": "Comunità",
"relevance": "Pertinenza",
"rating": "Valutazione",
"date": "Data di caricamento",
"views": "Numero di visualizzazioni",
"content_type": "Tipo",
"duration": "Durata",
"features": "Caratteristiche",
"sort": "Ordina per",
"hour": "Ultima ora",
"today": "Oggi",
"week": "Questa settimana",
"month": "Questo mese",
"year": "Quest'anno",
"video": "Video",
"channel": "Canale",
"playlist": "Playlist",
"movie": "Film",
"hd": "AD",
"subtitles": "Sottotitoli / CC",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "In diretta",
"4k": "4K",
"location": "Posizione",
"hdr": "HDR",
"filter": "Filtra",
"search_filters_sort_option_relevance": "Pertinenza",
"search_filters_sort_option_rating": "Valutazione",
"search_filters_sort_option_date": "Data di caricamento",
"search_filters_sort_option_views": "Numero di visualizzazioni",
"search_filters_type_label": "Tipo",
"search_filters_duration_label": "Durata",
"search_filters_features_label": "Caratteristiche",
"search_filters_sort_label": "Ordina per",
"search_filters_date_option_hour": "Ultima ora",
"search_filters_date_option_today": "Oggi",
"search_filters_date_option_week": "Questa settimana",
"search_filters_date_option_month": "Questo mese",
"search_filters_date_option_year": "Quest'anno",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Canale",
"search_filters_type_option_playlist": "Playlist",
"search_filters_type_option_movie": "Film",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Sottotitoli / CC",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "In diretta",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Posizione",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Versione attuale: ",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_360p": "360p",
@ -382,15 +381,95 @@
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_4320p": "4320p",
"360": "360°",
"search_filters_features_option_three_sixty": "360°",
"preferences_quality_dash_option_144p": "144p",
"Released under the AGPLv3 on Github.": "Rilasciato su Github con licenza AGPLv3.",
"Released under the AGPLv3 on Github.": "Pubblicato su GitHub con licenza AGPLv3.",
"preferences_quality_option_medium": "Media",
"preferences_quality_option_small": "Piccola",
"preferences_quality_option_small": "Limitata",
"preferences_quality_dash_option_best": "Migliore",
"preferences_quality_dash_option_worst": "Peggiore",
"invidious": "Invidious",
"preferences_quality_dash_label": "Qualità video DASH preferita ",
"preferences_quality_dash_label": "Qualità video DASH preferita: ",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_dash_option_auto": "Automatica"
"preferences_quality_dash_option_auto": "Automatica",
"videoinfo_watch_on_youTube": "Guarda su YouTube",
"preferences_extend_desc_label": "Estendi automaticamente la descrizione del video: ",
"preferences_vr_mode_label": "Video interattivi a 360 gradi: ",
"Show less": "Mostra di meno",
"Switch Invidious Instance": "Cambia istanza Invidious",
"next_steps_error_message_go_to_youtube": "Andare su YouTube",
"footer_documentation": "Documentazione",
"footer_original_source_code": "Codice sorgente originale",
"footer_modfied_source_code": "Codice sorgente modificato",
"none": "nessuno",
"videoinfo_started_streaming_x_ago": "Ha iniziato a trasmettere `x` fa",
"download_subtitles": "Sottotitoli - `x` (.vtt)",
"user_saved_playlists": "playlist salvate da `x`",
"preferences_automatic_instance_redirect_label": "Reindirizzamento automatico dell'istanza (ripiego su redirect.invidious.io): ",
"Video unavailable": "Video non disponibile",
"preferences_show_nick_label": "Mostra nickname in alto: ",
"videoinfo_youTube_embed_link": "Incorpora",
"videoinfo_invidious_embed_link": "Incorpora collegamento",
"user_created_playlists": "playlist create da `x`",
"preferences_save_player_pos_label": "Memorizza il minutaggio raggiunto dal video: ",
"preferences_quality_option_dash": "DASH (qualità adattiva)",
"preferences_region_label": "Nazione del contenuto: ",
"preferences_category_misc": "Preferenze varie",
"next_steps_error_message": "Dopodiché dovresti provare a: ",
"next_steps_error_message_refresh": "Aggiornare",
"footer_donate_page": "Dona",
"footer_source_code": "Codice sorgente",
"adminprefs_modified_source_code_url_label": "Link per il repository del codice sorgente modificato",
"Show more": "Mostra di più",
"search_filters_title": "Filtra",
"search_filters_type_option_show": "Serie",
"search_filters_duration_option_short": "Corto (< 4 minuti)",
"search_filters_duration_option_long": "Lungo (> 20 minuti)",
"search_filters_features_option_purchased": "Acquistato",
"comments_view_x_replies": "Vedi {{count}} risposta",
"comments_view_x_replies_plural": "Vedi {{count}} risposte",
"comments_points_count": "{{count}} punto",
"comments_points_count_plural": "{{count}} punti",
"Portuguese (auto-generated)": "Portoghese (generati automaticamente)",
"crash_page_you_found_a_bug": "Sembra che tu abbia trovato un bug in Invidious!",
"crash_page_switch_instance": "provato a <a href=\"`x`\">usare un'altra istanza</a>",
"crash_page_before_reporting": "Prima di segnalare un bug, assicurati di aver:",
"crash_page_read_the_faq": "letto le <a href=\"`x`\">domande più frequenti (FAQ)</a>",
"crash_page_search_issue": "cercato tra <a href=\"`x`\"> i problemi esistenti su GitHub</a>",
"crash_page_report_issue": "Se niente di tutto ciò ha aiutato, per favore <a href=\"`x`\">apri un nuovo problema su GitHub</a> (preferibilmente in inglese) e includi il seguente testo nel tuo messaggio (NON tradurre il testo):",
"Popular enabled: ": "Popolare attivato: ",
"English (United Kingdom)": "Inglese (Regno Unito)",
"Portuguese (Brazil)": "Portoghese (Brasile)",
"preferences_watch_history_label": "Attiva cronologia di riproduzione: ",
"French (auto-generated)": "Francese (generati automaticamente)",
"search_message_use_another_instance": " Puoi anche <a href=\"`x`\">cercare in un'altra istanza</a>.",
"search_message_no_results": "Nessun risultato trovato.",
"search_message_change_filters_or_query": "Prova ad ampliare la ricerca e/o modificare i filtri.",
"English (United States)": "Inglese (Stati Uniti)",
"Cantonese (Hong Kong)": "Cantonese (Hong Kong)",
"Chinese": "Cinese",
"Chinese (China)": "Cinese (Cina)",
"Chinese (Hong Kong)": "Cinese (Hong Kong)",
"Chinese (Taiwan)": "Cinese (Taiwan)",
"Dutch (auto-generated)": "Olandese (generati automaticamente)",
"German (auto-generated)": "Tedesco (generati automaticamente)",
"Indonesian (auto-generated)": "Indonesiano (generati automaticamente)",
"Interlingue": "Interlingua",
"Italian (auto-generated)": "Italiano (generati automaticamente)",
"Japanese (auto-generated)": "Giapponese (generati automaticamente)",
"Korean (auto-generated)": "Coreano (generati automaticamente)",
"Russian (auto-generated)": "Russo (generati automaticamente)",
"Spanish (auto-generated)": "Spagnolo (generati automaticamente)",
"Spanish (Mexico)": "Spagnolo (Messico)",
"Spanish (Spain)": "Spagnolo (Spagna)",
"Turkish (auto-generated)": "Turco (auto-generato)",
"Vietnamese (auto-generated)": "Vietnamita (auto-generato)",
"search_filters_date_label": "Data caricamento",
"search_filters_date_option_none": "Qualunque data",
"search_filters_type_option_all": "Qualunque tipo",
"search_filters_duration_option_none": "Qualunque durata",
"search_filters_duration_option_medium": "Media (4 - 20 minuti)",
"search_filters_features_option_vr180": "VR180",
"search_filters_apply_button": "Applica filtri selezionati",
"crash_page_refresh": "provato a <a href=\"`x`\">ricaricare la pagina</a>"
}

View File

@ -26,15 +26,15 @@
"No": "いいえ",
"Import and Export Data": "データのインポートとエクスポート",
"Import": "インポート",
"Import Invidious data": "Invidious データをインポート",
"Import YouTube subscriptions": "YouTube 登録チャンネルをインポート",
"Import Invidious data": "Invidious JSONデータをインポート",
"Import YouTube subscriptions": "YouTube/OPML 登録チャンネルをインポート",
"Import FreeTube subscriptions (.db)": "FreeTube 登録チャンネルをインポート (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe 登録チャンネルをインポート (.json)",
"Import NewPipe data (.zip)": "NewPipe データをインポート (.zip)",
"Export": "エクスポート",
"Export subscriptions as OPML": "登録チャンネルを OPML でエクスポート",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "登録チャンネルを OPML でエクスポート (NewPipe & FreeTube 用)",
"Export data as JSON": "データを JSON でエクスポート",
"Export data as JSON": "Invidious のデータを JSON でエクスポート",
"Delete account?": "アカウントを削除しますか?",
"History": "履歴",
"An alternative front-end to YouTube": "YouTube 向けの代用フロントエンド",
@ -71,7 +71,7 @@
"preferences_related_videos_label": "関連動画を表示: ",
"preferences_annotations_label": "デフォルトでアノテーションを表示: ",
"preferences_extend_desc_label": "動画の説明文を自動的に拡張: ",
"preferences_vr_mode_label": "対話的な360°動画: ",
"preferences_vr_mode_label": "対話的な360°動画 (WebGL が必要): ",
"preferences_category_visual": "外観設定",
"preferences_player_style_label": "プレイヤースタイル: ",
"Dark mode: ": "ダークモード: ",
@ -148,7 +148,6 @@
"Show less": "表示を減らす",
"Watch on YouTube": "YouTube で視聴",
"Switch Invidious Instance": "Invidiousインスタンスの変更",
"Broken? Try another Invidious Instance": "壊れる違うInvidiousインスタンスを試してみる",
"Hide annotations": "アノテーションを隠す",
"Show annotations": "アノテーションを表示",
"Genre: ": "ジャンル: ",
@ -345,44 +344,43 @@
"Videos": "動画",
"Playlists": "プレイリスト",
"Community": "コミュニティ",
"relevance": "関連",
"rating": "評価",
"date": "時刻",
"views": "再生回数",
"content_type": "コンテンツの種類",
"duration": "再生時間",
"features": "機能",
"sort": "順番",
"hour": "1時間前",
"today": "今日",
"week": "今週",
"month": "今月",
"year": "今年",
"video": "動画",
"channel": "チャンネル",
"playlist": "再生リスト",
"movie": "映画",
"show": "番組",
"hd": "HD",
"subtitles": "字幕",
"creative_commons": "クリエイティブ・コモンズ",
"3d": "3D",
"live": "生配信",
"4k": "4K",
"location": "場所",
"hdr": "HDR",
"filter": "フィルタ",
"search_filters_sort_option_relevance": "関連",
"search_filters_sort_option_rating": "評価",
"search_filters_sort_option_date": "時刻",
"search_filters_sort_option_views": "再生回数",
"search_filters_type_label": "コンテンツの種類",
"search_filters_duration_label": "再生時間",
"search_filters_features_label": "機能",
"search_filters_sort_label": "順番",
"search_filters_date_option_hour": "1時間前",
"search_filters_date_option_today": "今日",
"search_filters_date_option_week": "今週",
"search_filters_date_option_month": "今月",
"search_filters_date_option_year": "今年",
"search_filters_type_option_video": "動画",
"search_filters_type_option_channel": "チャンネル",
"search_filters_type_option_playlist": "再生リスト",
"search_filters_type_option_movie": "映画",
"search_filters_type_option_show": "番組",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "字幕",
"search_filters_features_option_c_commons": "クリエイティブ・コモンズ",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "生配信",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "場所",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "現在のバージョン: ",
"next_steps_error_message": "下記のものを試して下さい: ",
"next_steps_error_message_refresh": "再読込",
"next_steps_error_message_go_to_youtube": "YouTubeへ",
"short": "4 分未満",
"search_filters_duration_option_short": "4 分未満",
"footer_documentation": "文書",
"footer_source_code": "ソースコード",
"footer_original_source_code": "ソースコード(元)",
"footer_modfied_source_code": "ソースコード(編集)",
"adminprefs_modified_source_code_url_label": "編集したソースコードのレポジトリーURL",
"long": "20 分以上",
"search_filters_duration_option_long": "20 分以上",
"preferences_region_label": "地域: ",
"footer_donate_page": "寄付する",
"preferences_quality_dash_label": "優先するDash画質 : ",
@ -404,12 +402,41 @@
"videoinfo_invidious_embed_link": "埋め込みリンク",
"none": "なし",
"download_subtitles": "字幕 - `x` (.vtt)",
"purchased": "購入済み",
"search_filters_features_option_purchased": "購入済み",
"preferences_quality_option_dash": "DASH (適切な品質)",
"preferences_quality_dash_option_worst": "最悪",
"preferences_quality_dash_option_best": "最高",
"videoinfo_started_streaming_x_ago": "`x`分前に配信を開始",
"videoinfo_watch_on_youTube": "YouTube上で見る",
"user_created_playlists": "`x`が作成したプレイリスト",
"Video unavailable": "ビデオは利用できません"
"Video unavailable": "ビデオは利用できません",
"Chinese": "中国語",
"Chinese (Taiwan)": "中国語 (台湾)",
"Korean (auto-generated)": "韓国語 (自動生成)",
"Portuguese (auto-generated)": "ポルトガル語 (自動生成)",
"Turkish (auto-generated)": "トルコ語 (自動生成)",
"English (United Kingdom)": "英語 (イギリス)",
"Cantonese (Hong Kong)": "広東語 (香港)",
"Chinese (China)": "中国語 (中国)",
"Chinese (Hong Kong)": "中国語 (香港)",
"Dutch (auto-generated)": "オランダ語 (自動生成)",
"French (auto-generated)": "フランス語 (自動生成)",
"German (auto-generated)": "ドイツ語 (自動生成)",
"Indonesian (auto-generated)": "インドネシア語 (自動生成)",
"Italian (auto-generated)": "イタリア語 (自動生成)",
"Japanese (auto-generated)": "日本語 (自動生成)",
"Interlingue": "インターリング",
"Portuguese (Brazil)": "ポルトガル語 (ブラジル)",
"Russian (auto-generated)": "ロシア語 (自動生成)",
"Spanish (auto-generated)": "スペイン語 (自動生成)",
"Spanish (Mexico)": "スペイン語 (メキシコ)",
"Spanish (Spain)": "スペイン語 (スペイン)",
"Vietnamese (auto-generated)": "ベトナム語 (自動生成)",
"search_filters_title": "フィルタ",
"search_filters_features_option_three_sixty": "360°",
"search_message_change_filters_or_query": "別のキーワードを試してみるか、検索フィルタを削除してください",
"search_message_no_results": "一致する検索結果はありませんでした",
"English (United States)": "英語 (アメリカ)",
"search_filters_date_label": "アップロード日",
"search_filters_features_option_vr180": "VR180"
}

View File

@ -86,7 +86,7 @@
"generic_playlists_count_0": "{{count}} 재생목록",
"generic_subscribers_count_0": "{{count}} 구독자",
"generic_subscriptions_count_0": "{{count}} 구독",
"playlist": "재생목록",
"search_filters_type_option_playlist": "재생목록",
"Korean": "한국어",
"Japanese": "일본어",
"Greek": "그리스어",
@ -129,7 +129,7 @@
"Delete playlist": "재생목록 삭제",
"Delete playlist `x`?": "재생목록 `x` 를 삭제 하시겠습니까?",
"Updated `x` ago": "`x` 전에 업데이트됨",
"Released under the AGPLv3 on Github.": "Github에 AGPLv3 으로 배포됩니다.",
"Released under the AGPLv3 on Github.": "GitHub에 AGPLv3 으로 배포됩니다.",
"View all playlists": "모든 재생목록 보기",
"Private": "비공개",
"Unlisted": "목록에 없음",
@ -195,16 +195,15 @@
"Maori": "마오리어",
"Maltese": "몰타어",
"Wrong answer": "잘못된 답변",
"live": "실시간",
"3d": "3D",
"location": "지역",
"4k": "4K",
"filter": "필터",
"hdr": "HDR",
"search_filters_features_option_live": "실시간",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_location": "지역",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "현재 버전: ",
"next_steps_error_message_refresh": "새로 고침",
"next_steps_error_message_go_to_youtube": "YouTube로 가기",
"subtitles": "자막",
"search_filters_features_option_subtitles": "자막",
"`x` marked it with a ❤": "`x`님의 ❤",
"Download as: ": "다음으로 다운로드: ",
"Download": "다운로드",
@ -219,7 +218,7 @@
"Latvian": "라트비아어",
"Latin": "라틴어",
"Lao": "라오어",
"channel": "채널",
"search_filters_type_option_channel": "채널",
"Kyrgyz": "키르기스어",
"Kurdish": "쿠르드어",
"Khmer": "크메르어",
@ -279,7 +278,7 @@
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "JavaScript가 꺼져 있는 것 같습니다! 댓글을 보려면 여기를 클릭하세요. 댓글을 로드하는 데 시간이 조금 더 걸릴 수 있습니다.",
"Shared `x`": "공유된 `x`",
"Whitelisted regions: ": "차단되지 않은 지역: ",
"views": "조회수",
"search_filters_sort_option_views": "조회수",
"Please log in": "로그인하세요",
"Password cannot be longer than 55 characters": "비밀번호는 55자 이하여야 합니다",
"Password cannot be empty": "비밀번호는 비워둘 수 없습니다",
@ -298,7 +297,6 @@
"Empty playlist": "재생목록 비어 있음",
"Show annotations": "주석 보이기",
"Hide annotations": "주석 숨기기",
"Broken? Try another Invidious Instance": "안되나요? 다른 Invidious 인스턴스를 시도해보세요",
"Switch Invidious Instance": "Invidious 인스턴스 변경",
"Spanish": "스페인어",
"Southern Sotho": "소토어",
@ -343,12 +341,12 @@
"Premieres `x`": "최초 공개 `x`",
"Premieres in `x`": "`x` 에 최초 공개",
"next_steps_error_message": "다음 방법을 시도해 보세요: ",
"creative_commons": "크리에이티브 커먼즈",
"duration": "길이",
"content_type": "구분",
"date": "업로드 날짜",
"rating": "평점",
"relevance": "관련성",
"search_filters_features_option_c_commons": "크리에이티브 커먼즈",
"search_filters_duration_label": "길이",
"search_filters_type_label": "구분",
"search_filters_sort_option_date": "업로드 날짜",
"search_filters_sort_option_rating": "평점",
"search_filters_sort_option_relevance": "관련성",
"Community": "커뮤니티",
"Videos": "동영상",
"Video mode": "비디오 모드",
@ -365,22 +363,23 @@
"Rating: ": "평점: ",
"About": "정보",
"Top": "최고",
"hd": "HD",
"show": "쇼",
"movie": "영화",
"video": "동영상",
"year": "올해",
"month": "이번 달",
"week": "이번 주",
"today": "오늘",
"hour": "지난 1시간",
"sort": "정렬기준",
"features": "기능별",
"short": "4분 미만",
"long": "20분 초과",
"search_filters_features_option_hd": "HD",
"search_filters_type_option_show": "쇼",
"search_filters_type_option_movie": "영화",
"search_filters_type_option_video": "동영상",
"search_filters_date_option_year": "올해",
"search_filters_date_option_month": "이번 달",
"search_filters_date_option_week": "이번 주",
"search_filters_date_option_today": "오늘",
"search_filters_date_option_hour": "지난 1시간",
"search_filters_sort_label": "정렬기준",
"search_filters_features_label": "기능별",
"search_filters_duration_option_short": "4분 미만",
"search_filters_duration_option_long": "20분 초과",
"footer_documentation": "문서",
"footer_source_code": "소스 코드",
"footer_original_source_code": "원본 소스 코드",
"footer_modfied_source_code": "수정된 소스 코드",
"adminprefs_modified_source_code_url_label": "수정된 소스 코드 저장소의 URL"
"adminprefs_modified_source_code_url_label": "수정된 소스 코드 저장소의 URL",
"search_filters_title": "필터"
}

View File

@ -121,7 +121,7 @@
"Subscriptions": "Prenumeratos",
"search": "ieškoti",
"Log out": "Atsijungti",
"Released under the AGPLv3 on Github.": "Išleista pagal AGPLv3 licenciją Github.",
"Released under the AGPLv3 on Github.": "Išleista pagal AGPLv3 licenciją GitHub.",
"Source available here.": "Kodas prieinamas čia.",
"View JavaScript license information.": "Žiūrėti JavaScript licencijos informaciją.",
"View privacy policy.": "Žiūrėti privatumo politiką.",
@ -141,7 +141,6 @@
"Show less": "Rodyti mažiau",
"Watch on YouTube": "Žiaurėti Youtube",
"Switch Invidious Instance": "Keisti Invidious šaltinį",
"Broken? Try another Invidious Instance": "Neveikia? Bandyk kitą Invidious šaltinį",
"Hide annotations": "Slėpti anotacijas",
"Show annotations": "Rodyti anotacijas",
"Genre: ": "Žanras: ",
@ -329,39 +328,38 @@
"Videos": "Vaizdo įrašai",
"Playlists": "Grojaraiščiai",
"Community": "Bendruomenė",
"relevance": "Aktualumas",
"rating": "Reitingas",
"date": "Įkėlimo data",
"views": "Peržiūrų skaičius",
"content_type": "Tipas",
"duration": "Trukmė",
"features": "Funkcijos",
"sort": "Rūšiuoti pagal",
"hour": "Per paskutinę valandą",
"today": "Šiandien",
"week": "Šią savaitę",
"month": "Šį mėnesį",
"year": "Šiais metais",
"video": "Vaizdo įrašas",
"channel": "Kanalas",
"playlist": "Grojaraštis",
"movie": "Filmas",
"show": "Serialas",
"hd": "HD",
"subtitles": "Subtitrai/CC",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Tiesiogiai",
"4k": "4K",
"location": "Vietovė",
"hdr": "HDR",
"filter": "Filtras",
"search_filters_sort_option_relevance": "Aktualumas",
"search_filters_sort_option_rating": "Reitingas",
"search_filters_sort_option_date": "Įkėlimo data",
"search_filters_sort_option_views": "Peržiūrų skaičius",
"search_filters_type_label": "Tipas",
"search_filters_duration_label": "Trukmė",
"search_filters_features_label": "Funkcijos",
"search_filters_sort_label": "Rūšiuoti pagal",
"search_filters_date_option_hour": "Per paskutinę valandą",
"search_filters_date_option_today": "Šiandien",
"search_filters_date_option_week": "Šią savaitę",
"search_filters_date_option_month": "Šį mėnesį",
"search_filters_date_option_year": "Šiais metais",
"search_filters_type_option_video": "Vaizdo įrašas",
"search_filters_type_option_channel": "Kanalas",
"search_filters_type_option_playlist": "Grojaraštis",
"search_filters_type_option_movie": "Filmas",
"search_filters_type_option_show": "Serialas",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Subtitrai/CC",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Tiesiogiai",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Vietovė",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Dabartinė versija: ",
"next_steps_error_message": "Po to turėtumėte pabandyti: ",
"next_steps_error_message_refresh": "Atnaujinti",
"next_steps_error_message_go_to_youtube": "Eiti į YouTube",
"short": "Trumpas (< 4 minučių)",
"long": "Ilgas (> 20 minučių)",
"search_filters_duration_option_short": "Trumpas (< 4 minučių)",
"search_filters_duration_option_long": "Ilgas (> 20 minučių)",
"footer_documentation": "Dokumentacija",
"footer_source_code": "Pirminis kodas",
"footer_original_source_code": "Pradinis pirminis kodas",
@ -369,5 +367,9 @@
"footer_modfied_source_code": "Pakeistas pirminis kodas",
"footer_donate_page": "Paaukoti",
"preferences_region_label": "Turinio šalis: ",
"preferences_quality_dash_label": "Pageidaujama DASH vaizdo kokybė: "
"preferences_quality_dash_label": "Pageidaujama DASH vaizdo kokybė: ",
"preferences_quality_dash_option_best": "Geriausia",
"preferences_quality_dash_option_worst": "Blogiausia",
"preferences_quality_dash_option_auto": "Automatinis",
"search_filters_title": "Filtras"
}

View File

@ -29,7 +29,7 @@
"Export": "Eksporter",
"Export subscriptions as OPML": "Eksporter abonnementer som OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Eksporter abonnementer som OPML (for NewPipe og FreeTube)",
"Export data as JSON": "Eksporter data som JSON",
"Export data as JSON": "Eksporter Invidiousdata som JSON",
"Delete account?": "Slett konto?",
"History": "Historikk",
"An alternative front-end to YouTube": "En alternativ grenseflate for YouTube",
@ -66,7 +66,7 @@
"preferences_related_videos_label": "Vis relaterte videoer? ",
"preferences_annotations_label": "Vis merknader som forvalg? ",
"preferences_extend_desc_label": "Utvid videobeskrivelse automatisk: ",
"preferences_vr_mode_label": "Interaktive 360-gradersfilmer: ",
"preferences_vr_mode_label": "Interaktive 360-gradersfilmer (krever WebGL): ",
"preferences_category_visual": "Visuelle innstillinger",
"preferences_player_style_label": "Avspillerstil: ",
"Dark mode: ": "Mørk drakt: ",
@ -121,7 +121,7 @@
"Subscriptions": "Abonnement",
"search": "søk",
"Log out": "Logg ut",
"Released under the AGPLv3 on Github.": "Tilgjengelig med AGPLv3-lisens på Github.",
"Released under the AGPLv3 on Github.": "Tilgjengelig med AGPLv3-lisens på GitHub.",
"Source available here.": "Kildekode tilgjengelig her.",
"View JavaScript license information.": "Vis JavaScript-lisensinfo.",
"View privacy policy.": "Vis personvernspraksis.",
@ -141,7 +141,6 @@
"Show less": "Vis mindre",
"Watch on YouTube": "Vis video på YouTube",
"Switch Invidious Instance": "Bytt Invidious-instans",
"Broken? Try another Invidious Instance": "Knekt? Forsøk en annen Invidious-instans",
"Hide annotations": "Skjul merknader",
"Show annotations": "Vis merknader",
"Genre: ": "Sjanger: ",
@ -199,7 +198,7 @@
"No such user": "Ugyldig bruker",
"Token is expired, please try again": "Symbol utløpt, prøv igjen",
"English": "Engelsk",
"English (auto-generated)": "Engelsk (auto-generert)",
"English (auto-generated)": "Engelsk (laget automatisk)",
"Afrikaans": "Afrikansk",
"Albanian": "Albansk",
"Amharic": "Amharisk",
@ -329,40 +328,39 @@
"Videos": "Videoer",
"Playlists": "Spillelister",
"Community": "Gemenskap",
"relevance": "relevans",
"rating": "vurdering",
"date": "dato",
"views": "visninger",
"content_type": "innholdstype",
"duration": "varighet",
"features": "funksjoner",
"sort": "sorter",
"hour": "time",
"today": "i dag",
"week": "uke",
"month": "måned",
"year": "år",
"video": "video",
"channel": "kanal",
"playlist": "spilleliste",
"movie": "film",
"show": "vis",
"hd": "HD",
"subtitles": "undertekster",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "direkte",
"4k": "4k",
"location": "sted",
"hdr": "HDR",
"filter": "filtrer",
"search_filters_sort_option_relevance": "relevans",
"search_filters_sort_option_rating": "vurdering",
"search_filters_sort_option_date": "dato",
"search_filters_sort_option_views": "visninger",
"search_filters_type_label": "innholdstype",
"search_filters_duration_label": "varighet",
"search_filters_features_label": "funksjoner",
"search_filters_sort_label": "sorter",
"search_filters_date_option_hour": "time",
"search_filters_date_option_today": "i dag",
"search_filters_date_option_week": "uke",
"search_filters_date_option_month": "måned",
"search_filters_date_option_year": "år",
"search_filters_type_option_video": "video",
"search_filters_type_option_channel": "kanal",
"search_filters_type_option_playlist": "spilleliste",
"search_filters_type_option_movie": "film",
"search_filters_type_option_show": "vis",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "undertekster",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "direkte",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "sted",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Gjeldende versjon: ",
"next_steps_error_message": "Etterpå bør du prøve dette: ",
"next_steps_error_message_refresh": "Gjenoppfrisk",
"next_steps_error_message_go_to_youtube": "Gå til YouTube",
"long": "Lang (> 20 minutter)",
"search_filters_duration_option_long": "Lang (> 20 minutter)",
"footer_donate_page": "Doner",
"short": "Kort (< 4 minutter)",
"search_filters_duration_option_short": "Kort (< 4 minutter)",
"footer_documentation": "Dokumentasjon",
"footer_source_code": "Kildekode",
"footer_original_source_code": "Opprinnelig kildekode",
@ -384,8 +382,8 @@
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"purchased": "Kjøpt",
"360": "360°",
"search_filters_features_option_purchased": "Kjøpt",
"search_filters_features_option_three_sixty": "360°",
"none": "intet",
"videoinfo_watch_on_youTube": "Se på YouTube",
"videoinfo_youTube_embed_link": "Bak inn",
@ -432,10 +430,46 @@
"generic_count_years": "{{count}} år",
"generic_count_years_plural": "{{count}} år",
"crash_page_read_the_faq": "lest de <a href=\"`x`\">Ofte stilte spørsmålene (OSS/FAQ)</a>",
"crash_page_search_issue": "søkt etter <a href=\"`x`\">eksisterende utfordringer på Github</a>",
"crash_page_search_issue": "søkt etter <a href=\"`x`\">eksisterende utfordringer på GitHub</a>",
"crash_page_you_found_a_bug": "Det ser ut til at du fant en feil i Invidious!",
"crash_page_refresh": "forsøkt å <a href=\"`x`\">laste siden på nytt</a>",
"crash_page_switch_instance": "forsøkt et <a href=\"`x`\">annet eksemplar</a>",
"crash_page_before_reporting": "Før du rapporterer en feil, sikre at du har:",
"crash_page_report_issue": "Hvis intet av det overnevnte hjalp, <a href=\"`x`\">lag en ny utfordring på Github</a> (fortrinnsvis på engelsk) og ta med følgende tekstbit i meldingen dit (IKKE oversett denne teksten):"
"crash_page_report_issue": "Sett at det overnevnte ikke hjalp, <a href=\"`x`\">lag en ny utfordring på GitHub</a> (fortrinnsvis på engelsk) og med følgende tekstbit i meldingen dithen (IKKE oversett denne teksten):",
"English (United Kingdom)": "Engelsk (Storbritannia)",
"English (United States)": "Engelsk (USA)",
"Cantonese (Hong Kong)": "Kantonesisk (Hong Kong)",
"Portuguese (Brazil)": "Portugisisk (Brasil)",
"Spanish (Mexico)": "Spansk (Mexico)",
"Spanish (Spain)": "Spansk (Spania)",
"Spanish (auto-generated)": "Spansk (laget automatisk)",
"Vietnamese (auto-generated)": "Vietnamesisk (laget automatisk)",
"preferences_watch_history_label": "Aktiver seerhistorikk: ",
"Chinese": "Kinesisk",
"Chinese (China)": "Kinesisk (Kina)",
"Chinese (Hong Kong)": "Kinesisk (Hong Kong)",
"Chinese (Taiwan)": "Kinesisk (Taiwan)",
"French (auto-generated)": "Fransk (laget automatisk)",
"German (auto-generated)": "Tysk (laget automatisk)",
"Indonesian (auto-generated)": "Indonesisk (laget automatisk)",
"Interlingue": "Interlingue",
"Italian (auto-generated)": "Italiensk (laget automatisk)",
"Japanese (auto-generated)": "Japansk (laget automatisk)",
"Korean (auto-generated)": "Koreansk (laget automatisk)",
"Portuguese (auto-generated)": "Portugisisk (laget automatisk)",
"Russian (auto-generated)": "Russisk (laget automatisk)",
"Dutch (auto-generated)": "Nederlandsk (laget automatisk)",
"Turkish (auto-generated)": "Tyrkisk (laget automatisk)",
"search_filters_title": "Filtrer",
"Popular enabled: ": "Populære aktiv: ",
"search_message_change_filters_or_query": "Prøv ett mindre snevert søk og/eller endre filterne.",
"search_filters_duration_option_medium": "Middels (420 minutter)",
"search_message_no_results": "Resultatløst.",
"search_filters_type_option_all": "Alle typer",
"search_filters_duration_option_none": "Enhver varighet",
"search_message_use_another_instance": " Du kan også <a href=\"`x`\">søke på en annen instans</a>.",
"search_filters_date_label": "Opplastningsdato",
"search_filters_apply_button": "Bruk valgte filtre",
"search_filters_date_option_none": "Siden begynnelsen",
"search_filters_features_option_vr180": "VR180"
}

View File

@ -21,15 +21,15 @@
"No": "Nee",
"Import and Export Data": "Gegevens im- en exporteren",
"Import": "Importeren",
"Import Invidious data": "Invidious-gegevens importeren",
"Import YouTube subscriptions": "YouTube-abonnementen importeren",
"Import Invidious data": "JSON-gegevens Invidious importeren",
"Import YouTube subscriptions": "YouTube-/OPML-abonnementen importeren",
"Import FreeTube subscriptions (.db)": "FreeTube-abonnementen importeren (.db)",
"Import NewPipe subscriptions (.json)": "NewPipe-abonnementen importeren (.json)",
"Import NewPipe data (.zip)": "NewPipe-gegevens importeren (.zip)",
"Export": "Exporteren",
"Export subscriptions as OPML": "Abonnementen exporteren als OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnementen exporteren als OPML (voor NewPipe en FreeTube)",
"Export data as JSON": "Gegevens exporteren als JSON",
"Export data as JSON": "Invidious-gegevens naar JSON exporteren",
"Delete account?": "Wilt u uw account verwijderen?",
"History": "Geschiedenis",
"An alternative front-end to YouTube": "Een alternatief front-end voor YouTube",
@ -66,7 +66,7 @@
"preferences_related_videos_label": "Gerelateerde video's tonen? ",
"preferences_annotations_label": "Standaard annotaties tonen? ",
"preferences_extend_desc_label": "Breid videobeschrijving automatisch uit: ",
"preferences_vr_mode_label": "Interactieve 360-graden-video's ",
"preferences_vr_mode_label": "Interactieve 360-graden-video's (vereist WebGL) ",
"preferences_category_visual": "Visuele instellingen",
"preferences_player_style_label": "Speler vormgeving ",
"Dark mode: ": "Donkere modus: ",
@ -323,33 +323,32 @@
"Videos": "Video's",
"Playlists": "Afspeellijsten",
"Community": "Gemeenschap",
"relevance": "relevantie",
"rating": "beoordeling",
"date": "datum",
"views": "keren bekeken",
"content_type": "Type inhoud",
"duration": "duur",
"features": "eigenschappen",
"sort": "sorteren",
"hour": "uur",
"today": "vandaag",
"week": "week",
"month": "maand",
"year": "jaar",
"video": "video",
"channel": "kanaal",
"playlist": "afspeellijst",
"movie": "film",
"show": "show",
"hd": "HD",
"subtitles": "ondertitels",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Live",
"4k": "4K",
"location": "locatie",
"hdr": "HDR",
"filter": "verfijnen",
"search_filters_sort_option_relevance": "relevantie",
"search_filters_sort_option_rating": "beoordeling",
"search_filters_sort_option_date": "datum",
"search_filters_sort_option_views": "keren bekeken",
"search_filters_type_label": "Type inhoud",
"search_filters_duration_label": "duur",
"search_filters_features_label": "eigenschappen",
"search_filters_sort_label": "sorteren",
"search_filters_date_option_hour": "uur",
"search_filters_date_option_today": "vandaag",
"search_filters_date_option_week": "week",
"search_filters_date_option_month": "maand",
"search_filters_date_option_year": "jaar",
"search_filters_type_option_video": "video",
"search_filters_type_option_channel": "kanaal",
"search_filters_type_option_playlist": "afspeellijst",
"search_filters_type_option_movie": "film",
"search_filters_type_option_show": "show",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "ondertitels",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Live",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "locatie",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Huidige versie: ",
"Switch Invidious Instance": "Schakel tussen de Invidious Instanties",
"preferences_automatic_instance_redirect_label": "Automatische instantie-omleiding (terugval naar redirect.invidious.io): ",
@ -357,8 +356,8 @@
"preferences_region_label": "Inhoud land: ",
"preferences_category_misc": "Diverse voorkeuren",
"preferences_show_nick_label": "Toon bijnaam bovenaan: ",
"Released under the AGPLv3 on Github.": "Uitgebracht onder de AGPLv3 op Github.",
"short": "Kort (<4 minuten)",
"Released under the AGPLv3 on Github.": "Uitgebracht onder de AGPLv3 op GitHub.",
"search_filters_duration_option_short": "Kort (<4 minuten)",
"next_steps_error_message_refresh": "Vernieuwen",
"next_steps_error_message_go_to_youtube": "Ga naar YouTube",
"footer_donate_page": "Doneren",
@ -366,10 +365,9 @@
"footer_original_source_code": "Originele bron-code",
"footer_modfied_source_code": "Gewijzigde bron-code",
"adminprefs_modified_source_code_url_label": "URL naar gewijzigde bron-code-opslagplaats",
"Broken? Try another Invidious Instance": "Kapot? Probeer een andere Invidious Instantie",
"next_steps_error_message": "Waarna u moet proberen om: ",
"footer_source_code": "Bron-code",
"long": "Lang (> 20 minuten)",
"search_filters_duration_option_long": "Lang (> 20 minuten)",
"preferences_quality_option_dash": "DASH (adaptieve kwaliteit)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "Gemiddeld",
@ -395,8 +393,82 @@
"user_created_playlists": "`x` afspeellijsten aangemaakt",
"user_saved_playlists": "`x` afspeellijsten opgeslagen",
"Video unavailable": "Video onbeschikbaar",
"preferences_save_player_pos_label": "Huidig afspeeltijdstip opslaan: ",
"preferences_save_player_pos_label": "Afspeelpositie opslaan: ",
"none": "geen",
"purchased": "Gekocht",
"360": "360º"
"search_filters_features_option_purchased": "Gekocht",
"search_filters_features_option_three_sixty": "360º",
"search_filters_title": "Verfijnen",
"generic_count_days": "{{count}} dag",
"generic_count_days_plural": "{{count}} dagen",
"Chinese (Taiwan)": "Chinees (Taiwan)",
"Dutch (auto-generated)": "Nederlands (automatisch gegenereerd)",
"tokens_count": "{{count}} token",
"tokens_count_plural": "{{count}} tokens",
"generic_count_seconds": "{{count}} second",
"generic_count_seconds_plural": "{{count}} seconden",
"generic_count_weeks": "{{count}} week",
"generic_count_weeks_plural": "{{count}} weken",
"English (United States)": "Engels (Verenigde Staten)",
"generic_views_count": "{{count}} keer bekeken",
"generic_views_count_plural": "{{count}} keren bekeken",
"generic_videos_count": "{{count}} video",
"generic_videos_count_plural": "{{count}} video's",
"generic_subscriptions_count": "{{count}} abonnement",
"generic_subscriptions_count_plural": "{{count}} abonnementen",
"subscriptions_unseen_notifs_count": "{{count}} ongeziene melding",
"subscriptions_unseen_notifs_count_plural": "{{count}} ongeziene meldingen",
"preferences_watch_history_label": "Kijkgeschiedenis inschakelen: ",
"crash_page_switch_instance": "geprobeerd hebt om <a href=\"`x`\">een andere instantie te gebruiken</a>",
"Portuguese (auto-generated)": "Portugees (automatisch gegenereerd)",
"Russian (auto-generated)": "Russisch (automatisch gegenereerd)",
"Vietnamese (auto-generated)": "Vietnamees (automatisch gegenereerd)",
"comments_points_count": "{{count}} punt",
"comments_points_count_plural": "{{count}} punten",
"crash_page_before_reporting": "Voor je een bug rapporteert, kijk even na of je:",
"Chinese": "Chinees",
"search_filters_features_option_vr180": "VR180",
"search_filters_date_label": "Uploaddatum",
"Portuguese (Brazil)": "Portugees (Brazilië)",
"Interlingue": "Interlingue",
"Turkish (auto-generated)": "Turks (automatisch gegenereerd)",
"search_filters_date_option_none": "Alle datums",
"generic_subscribers_count": "{{count}} abonnee",
"generic_subscribers_count_plural": "{{count}} abonnees",
"search_message_no_results": "Geen resultaten teruggevonden.",
"search_message_change_filters_or_query": "Probeer je zoekopdracht uit te breiden en/of de filters aan te passen.",
"English (United Kingdom)": "Engels (Verenigd Koninkrijk)",
"German (auto-generated)": "Duits (automatisch gegenereerd)",
"Spanish (Mexico)": "Spaans (Mexico)",
"Spanish (Spain)": "Spaans (Spanje)",
"search_filters_type_option_all": "Alle types",
"crash_page_refresh": "geprobeerd hebt om <a href=\"`x`\">de pagina te herladen</a>",
"comments_view_x_replies": "{{count}} reactie bekijken",
"comments_view_x_replies_plural": "{{count}} reacties bekijken",
"generic_count_years": "{{count}} jaar",
"generic_count_years_plural": "{{count}} jaren",
"generic_count_months": "{{count}} maand",
"generic_count_months_plural": "{{count}} maanden",
"generic_count_hours": "{{count}} uur",
"generic_count_hours_plural": "{{count}} uren",
"generic_count_minutes": "{{count}} minuut",
"generic_count_minutes_plural": "{{count}} minuten",
"French (auto-generated)": "Frans (automatisch gegenereerd)",
"generic_playlists_count": "{{count}} afspeellijst",
"generic_playlists_count_plural": "{{count}} afspeellijsten",
"Chinese (Hong Kong)": "Chinees (Hongkong)",
"Korean (auto-generated)": "Koreaans (automatisch gegenereerd)",
"search_filters_apply_button": "Geselecteerd filters toepassen",
"search_message_use_another_instance": " Je kan ook <a href=\"`x`\">zoeken op een andere instantie</a>.",
"Cantonese (Hong Kong)": "Kantonees (Hongkong)",
"Chinese (China)": "Chinees (China)",
"crash_page_read_the_faq": "de <a href=\"`x`\">veelgestelde vragen (FAQ)</a> gelezen hebt",
"crash_page_search_issue": "gezocht hebt op <a href=\"`x`\">bestaande problemen op GitHub</a>",
"search_filters_duration_option_none": "Alle lengtes",
"Indonesian (auto-generated)": "Indonesisch (automatisch gegenereerd)",
"Italian (auto-generated)": "Italiaans (automatisch gegenereerd)",
"Japanese (auto-generated)": "Japans (automatisch gegenereerd)",
"Spanish (auto-generated)": "Spaans (automatisch gegenereerd)",
"crash_page_you_found_a_bug": "Je lijkt een bug in Invidious tegengekomen te zijn!",
"search_filters_duration_option_medium": "Gemiddeld (4 - 20 minuten)",
"crash_page_report_issue": "Indien het bovenstaande niet hielp, gelieve dan <a href=\"`x`\">een nieuw ticket op GitHub</a> te openen (liefst in het Engels) en neem de volgende tekst op in je bericht (gelieve deze NIET te vertalen):"
}

View File

@ -140,7 +140,6 @@
"Show less": "Pokaż mniej",
"Watch on YouTube": "Zobacz film na YouTube",
"Switch Invidious Instance": "Przełącz instancję Invidious",
"Broken? Try another Invidious Instance": "Nie działa? Spróbuj innej instancji Invidious",
"Hide annotations": "Ukryj adnotacje",
"Show annotations": "Pokaż adnotacje",
"Genre: ": "Gatunek: ",
@ -328,33 +327,32 @@
"Videos": "Filmy",
"Playlists": "Playlisty",
"Community": "Społeczność",
"relevance": "Trafność",
"rating": "Ocena",
"date": "data",
"views": "Liczba wyświetleń",
"content_type": "Typ",
"duration": "Długość",
"features": "Funkcje",
"sort": "sortuj",
"hour": "godzina",
"today": "dzisiaj",
"week": "tydzień",
"month": "miesiąc",
"year": "rok",
"video": "Film",
"channel": "kanał",
"playlist": "playlista",
"movie": "film",
"show": "pokaż",
"hd": "hd",
"subtitles": "napisy",
"creative_commons": "creative_commons",
"3d": "3d",
"live": "Na żywo",
"4k": "4k",
"location": "Lokalizacja",
"hdr": "hdr",
"filter": "filtr",
"search_filters_sort_option_relevance": "Trafność",
"search_filters_sort_option_rating": "Ocena",
"search_filters_sort_option_date": "data",
"search_filters_sort_option_views": "Liczba wyświetleń",
"search_filters_type_label": "Typ",
"search_filters_duration_label": "Długość",
"search_filters_features_label": "Funkcje",
"search_filters_sort_label": "sortuj",
"search_filters_date_option_hour": "godzina",
"search_filters_date_option_today": "dzisiaj",
"search_filters_date_option_week": "tydzień",
"search_filters_date_option_month": "miesiąc",
"search_filters_date_option_year": "rok",
"search_filters_type_option_video": "Film",
"search_filters_type_option_channel": "kanał",
"search_filters_type_option_playlist": "playlista",
"search_filters_type_option_movie": "film",
"search_filters_type_option_show": "pokaż",
"search_filters_features_option_hd": "hd",
"search_filters_features_option_subtitles": "napisy",
"search_filters_features_option_c_commons": "creative_commons",
"search_filters_features_option_three_d": "3d",
"search_filters_features_option_live": "Na żywo",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "Lokalizacja",
"search_filters_features_option_hdr": "hdr",
"Current version: ": "Aktualna wersja: ",
"next_steps_error_message": "Po czym powinien*ś spróbować: ",
"next_steps_error_message_refresh": "Odśwież",
@ -432,8 +430,8 @@
"preferences_quality_dash_label": "Preferowana jakość filmu DASH: ",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_option_2160p": "2160p",
"purchased": "Zakupione",
"360": "360°",
"search_filters_features_option_purchased": "Zakupione",
"search_filters_features_option_three_sixty": "360°",
"footer_donate_page": "Dotacja",
"none": "żadne",
"videoinfo_started_streaming_x_ago": "Transmisja rozpoczęta `x` temu",
@ -446,9 +444,9 @@
"Video unavailable": "Film niedostępny",
"preferences_save_player_pos_label": "Zapisz pozycję odtwarzania: ",
"preferences_region_label": "Region zawartości: ",
"Released under the AGPLv3 on Github.": "Wydany na licencji AGPLv3 na Github.",
"short": "Krótkie (< 4 minutes)",
"long": "Długie (> 20 minutes)",
"Released under the AGPLv3 on Github.": "Wydany na licencji AGPLv3 na GitHub.",
"search_filters_duration_option_short": "Krótkie (< 4 minutes)",
"search_filters_duration_option_long": "Długie (> 20 minutes)",
"footer_documentation": "Dokumentacja",
"footer_source_code": "Kod źródłowy",
"footer_modfied_source_code": "Zmodyfikowany Kod źródłowy",
@ -476,5 +474,6 @@
"Japanese (auto-generated)": "japoński (wygenerowany automatycznie)",
"Russian (auto-generated)": "rosyjski (wygenerowany automatycznie)",
"Portuguese (auto-generated)": "portugalski (wygenerowany automatycznie)",
"Portuguese (Brazil)": "portugalski (Brazylia)"
"Portuguese (Brazil)": "portugalski (Brazylia)",
"search_filters_title": "Filtr"
}

View File

@ -21,15 +21,15 @@
"No": "Não",
"Import and Export Data": "Importar e Exportar Dados",
"Import": "Importar",
"Import Invidious data": "Importar dados do Invidious",
"Import YouTube subscriptions": "Importar inscrições do YouTube",
"Import Invidious data": "Importar dados em JSON do Invidious",
"Import YouTube subscriptions": "Importar inscrições do YouTube/OPML",
"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)",
"Export": "Exportar",
"Export subscriptions as OPML": "Exportar inscrições como OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportar inscrições como OPML (para NewPipe e FreeTube)",
"Export data as JSON": "Exportar dados como JSON",
"Export data as JSON": "Exportar dados Invidious como JSON",
"Delete account?": "Excluir conta?",
"History": "Histórico",
"An alternative front-end to YouTube": "Uma interface alternativa para o YouTube",
@ -66,7 +66,7 @@
"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_vr_mode_label": "Vídeos interativos de 360 graus: ",
"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: ",
"Dark mode: ": "Modo escuro: ",
@ -123,7 +123,7 @@
"Subscriptions": "Inscrições",
"search": "Pesquisar",
"Log out": "Sair",
"Released under the AGPLv3 on Github.": "Lançado sob a AGPLv3 no Github.",
"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.",
@ -143,7 +143,6 @@
"Show less": "Mostrar menos",
"Watch on YouTube": "Assistir no YouTube",
"Switch Invidious Instance": "Mudar a instância do Invidious",
"Broken? Try another Invidious Instance": "Quebrou? Tente outra Instância do Invidious",
"Hide annotations": "Ocultar anotações",
"Show annotations": "Mostrar anotações",
"Genre: ": "Gênero: ",
@ -345,41 +344,40 @@
"Videos": "Vídeos",
"Playlists": "Listas de reprodução",
"Community": "Comunidade",
"relevance": "relevância",
"rating": "avaliação",
"date": "data",
"views": "visualizações",
"content_type": "content_type",
"duration": "duração",
"features": "recursos",
"sort": "ordenar",
"hour": "hora",
"today": "hoje",
"week": "semana",
"month": "mês",
"year": "ano",
"video": "vídeo",
"channel": "Canal",
"playlist": "playlist",
"movie": "filme",
"show": "show",
"hd": "hd",
"subtitles": "legendas",
"creative_commons": "creative_commons",
"3d": "3d",
"live": "ao vivo",
"4k": "4k",
"location": "localização",
"hdr": "hdr",
"filter": "filtro",
"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_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",
"Current version: ": "Versão atual: ",
"next_steps_error_message": "Depois disso, você deve tentar: ",
"next_steps_error_message_refresh": "Atualizar",
"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",
"long": "Longo (> 20 minutos)",
"short": "Curto (< 4 minutos)",
"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",
@ -404,15 +402,15 @@
"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: ",
"purchased": "Comprado",
"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_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": "leu as <a href=\"`x`\">Perguntas Frequentes (FAQ)</a>",
"crash_page_read_the_faq": "leia as <a href=\"`x`\">Perguntas frequentes (FAQ)</a>",
"generic_views_count": "{{count}} visualização",
"generic_views_count_plural": "{{count}} visualizações",
"preferences_quality_option_dash": "DASH (qualidade adaptiva)",
"preferences_quality_option_dash": "DASH (qualidade adaptável)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_small": "Pequeno",
"preferences_quality_dash_option_auto": "Auto",
@ -428,7 +426,7 @@
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"preferences_quality_option_medium": "Médio",
"360": "360°",
"search_filters_features_option_three_sixty": "360°",
"none": "none",
"videoinfo_watch_on_youTube": "Assistir no YouTube",
"videoinfo_youTube_embed_link": "Embutir",
@ -437,5 +435,41 @@
"user_created_playlists": "`x` listas de reprodução criadas",
"user_saved_playlists": "`x` listas de reprodução salvas",
"Video unavailable": "Vídeo indisponível",
"videoinfo_started_streaming_x_ago": "Iniciou a transmissão a `x`"
"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: ",
"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)",
"English (United States)": "Inglês (Estados Unidos)",
"German (auto-generated)": "Alemão (gerado automaticamente)",
"Chinese": "Chinês",
"Chinese (China)": "Chinês (China)",
"Cantonese (Hong Kong)": "Cantonês (Hong Kong)",
"Interlingue": "Interlíngua",
"search_filters_type_option_all": "Qualquer tipo",
"search_filters_apply_button": "Aplicar filtros selecionados",
"Chinese (Hong Kong)": "Chinês (Hong Kong)",
"Chinese (Taiwan)": "Chinês (Taiwan)",
"Japanese (auto-generated)": "Japonês (gerado automaticamente)",
"Korean (auto-generated)": "Coreano (gerado automaticamente)",
"Portuguese (auto-generated)": "Português (gerado automaticamente)",
"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_option_none": "Qualquer data",
"Dutch (auto-generated)": "Holandês (gerado automaticamente)",
"French (auto-generated)": "Francês (gerado automaticamente)",
"Indonesian (auto-generated)": "Indonésio (gerado automaticamente)",
"Italian (auto-generated)": "Italiano (gerado automaticamente)",
"Spanish (auto-generated)": "Espanhol (gerado automaticamente)",
"Spanish (Mexico)": "Espanhol (México)",
"search_filters_duration_option_none": "Qualquer duração",
"search_message_use_another_instance": " Você também pode <a href=\"`x`\">pesquisar em outra instância</a>.",
"Spanish (Spain)": "Espanhol (Espanha)",
"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: "
}

View File

@ -21,15 +21,15 @@
"No": "Não",
"Import and Export Data": "Importar e exportar dados",
"Import": "Importar",
"Import Invidious data": "Importar dados do Invidious",
"Import YouTube subscriptions": "Importar subscrições do YouTube",
"Import Invidious data": "Importar dados JSON do Invidious",
"Import YouTube subscriptions": "Importar subscrições OPML ou do YouTube",
"Import FreeTube subscriptions (.db)": "Importar subscrições do FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importar subscrições do NewPipe (.json)",
"Import NewPipe data (.zip)": "Importar dados do NewPipe (.zip)",
"Export": "Exportar",
"Export subscriptions as OPML": "Exportar subscrições como OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportar subscrições como OPML (para NewPipe e FreeTube)",
"Export data as JSON": "Exportar dados como JSON",
"Export data as JSON": "Exportar dados do Invidious como JSON",
"Delete account?": "Eliminar conta?",
"History": "Histórico",
"An alternative front-end to YouTube": "Uma interface alternativa ao YouTube",
@ -60,13 +60,13 @@
"preferences_volume_label": "Volume da reprodução: ",
"preferences_comments_label": "Preferência dos comentários: ",
"youtube": "YouTube",
"reddit": "reddit",
"reddit": "Reddit",
"preferences_captions_label": "Legendas predefinidas: ",
"Fallback captions: ": "Legendas alternativas: ",
"preferences_related_videos_label": "Mostrar vídeos relacionados: ",
"preferences_annotations_label": "Mostrar anotações sempre: ",
"preferences_extend_desc_label": "Estender automaticamente a descrição do vídeo: ",
"preferences_vr_mode_label": "Vídeos interativos de 360 graus: ",
"preferences_vr_mode_label": "Vídeos interativos de 360 graus (necessita de WebGL): ",
"preferences_category_visual": "Preferências visuais",
"preferences_player_style_label": "Estilo do reprodutor: ",
"Dark mode: ": "Modo escuro: ",
@ -123,7 +123,7 @@
"Subscriptions": "Subscrições",
"search": "pesquisar",
"Log out": "Terminar sessão",
"Released under the AGPLv3 on Github.": "Lançado sob a AGPLv3 no Github.",
"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.",
@ -143,7 +143,6 @@
"Show less": "Mostrar menos",
"Watch on YouTube": "Ver no YouTube",
"Switch Invidious Instance": "Mudar a instância do Invidious",
"Broken? Try another Invidious Instance": "Falhou? Tente outra Instância do Invidious",
"Hide annotations": "Ocultar anotações",
"Show annotations": "Mostrar anotações",
"Genre: ": "Género: ",
@ -345,35 +344,123 @@
"Videos": "Vídeos",
"Playlists": "Listas de reprodução",
"Community": "Comunidade",
"relevance": "Relevância",
"rating": "Avaliação",
"date": "Data de envio",
"views": "Visualizações",
"content_type": "Tipo",
"duration": "Duração",
"features": "Funcionalidades",
"sort": "Ordenar por",
"hour": "Última hora",
"today": "Hoje",
"week": "Esta semana",
"month": "Este mês",
"year": "Este ano",
"video": "Vídeo",
"channel": "Canal",
"playlist": "Lista de reprodução",
"movie": "Filme",
"show": "Espetáculo",
"hd": "HD",
"subtitles": "Legendas",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Em direto",
"4k": "4K",
"location": "Localização",
"hdr": "HDR",
"filter": "Filtro",
"search_filters_sort_option_relevance": "Relevância",
"search_filters_sort_option_rating": "Avaliação",
"search_filters_sort_option_date": "Data de envio",
"search_filters_sort_option_views": "Visualizações",
"search_filters_type_label": "Tipo",
"search_filters_duration_label": "Duração",
"search_filters_features_label": "Funcionalidades",
"search_filters_sort_label": "Ordenar por",
"search_filters_date_option_hour": "Última hora",
"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": "Lista de reprodução",
"search_filters_type_option_movie": "Filme",
"search_filters_type_option_show": "Espetáculo",
"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": "Em direto",
"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": "Pode tentar as seguintes opções: ",
"next_steps_error_message_refresh": "Atualizar",
"next_steps_error_message_go_to_youtube": "Ir ao YouTube"
"next_steps_error_message_go_to_youtube": "Ir ao YouTube",
"search_filters_title": "Filtro",
"generic_videos_count": "{{count}} vídeo",
"generic_videos_count_plural": "{{count}} vídeos",
"generic_playlists_count": "{{count}} lista de reprodução",
"generic_playlists_count_plural": "{{count}} listas de reprodução",
"generic_subscriptions_count": "{{count}} subscrição",
"generic_subscriptions_count_plural": "{{count}} subscrições",
"generic_views_count": "{{count}} visualização",
"generic_views_count_plural": "{{count}} visualizações",
"generic_subscribers_count": "{{count}} subscritor",
"generic_subscribers_count_plural": "{{count}} subscritores",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_label": "Qualidade de vídeo DASH preferencial ",
"preferences_quality_dash_option_2160p": "2160p",
"subscriptions_unseen_notifs_count": "{{count}} notificação por ver",
"subscriptions_unseen_notifs_count_plural": "{{count}} notificações por ver",
"Popular enabled: ": "Página \"Popular\" ativada: ",
"search_message_no_results": "Nenhum resultado encontrado.",
"preferences_quality_dash_option_auto": "Automática",
"preferences_region_label": "País para o conteúdo: ",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_720p": "720p",
"preferences_watch_history_label": "Ativar histórico de visualizações ",
"preferences_quality_dash_option_best": "Melhor",
"preferences_quality_dash_option_worst": "Pior",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_dash": "DASH (qualidade adaptativa)",
"preferences_quality_option_medium": "Média",
"preferences_quality_option_small": "Pequena",
"preferences_quality_dash_option_1080p": "1080p",
"preferences_quality_dash_option_480p": "480p",
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_240p": "240p",
"Video unavailable": "Vídeo indisponível",
"Russian (auto-generated)": "Russo (geradas automaticamente)",
"comments_view_x_replies": "Ver {{count}} resposta",
"comments_view_x_replies_plural": "Ver {{count}} respostas",
"comments_points_count": "{{count}} ponto",
"comments_points_count_plural": "{{count}} pontos",
"English (United Kingdom)": "Inglês (Reino Unido)",
"Chinese (Hong Kong)": "Chinês (Hong Kong)",
"Chinese (Taiwan)": "Chinês (Taiwan)",
"Dutch (auto-generated)": "Holandês (geradas automaticamente)",
"French (auto-generated)": "Francês (geradas automaticamente)",
"German (auto-generated)": "Alemão (geradas automaticamente)",
"Indonesian (auto-generated)": "Indonésio (geradas automaticamente)",
"Interlingue": "Interlingue",
"Italian (auto-generated)": "Italiano (geradas automaticamente)",
"Japanese (auto-generated)": "Japonês (geradas automaticamente)",
"Korean (auto-generated)": "Coreano (geradas automaticamente)",
"Portuguese (auto-generated)": "Português (geradas automaticamente)",
"Portuguese (Brazil)": "Português (Brasil)",
"Spanish (Spain)": "Espanhol (Espanha)",
"Vietnamese (auto-generated)": "Vietnamita (geradas automaticamente)",
"search_filters_type_option_all": "Qualquer tipo",
"search_filters_duration_option_none": "Qualquer duração",
"search_filters_duration_option_short": "Curto (< 4 minutos)",
"search_filters_duration_option_medium": "Médio (4 - 20 minutos)",
"search_filters_duration_option_long": "Longo (> 20 minutos)",
"search_filters_features_option_purchased": "Comprado",
"search_filters_apply_button": "Aplicar filtros selecionados",
"videoinfo_watch_on_youTube": "Ver no YouTube",
"videoinfo_youTube_embed_link": "Embutir",
"adminprefs_modified_source_code_url_label": "URL do repositório do código-fonte modificado",
"videoinfo_invidious_embed_link": "Ligação embutida",
"none": "nenhum",
"videoinfo_started_streaming_x_ago": "Entrou em direto há `x`",
"download_subtitles": "Legendas - `x` (.vtt)",
"user_created_playlists": "`x` listas de reprodução criadas",
"user_saved_playlists": "`x` listas de reprodução guardadas",
"preferences_save_player_pos_label": "Guardar posição de reprodução: ",
"Turkish (auto-generated)": "Turco (geradas automaticamente)",
"Cantonese (Hong Kong)": "Cantonês (Hong Kong)",
"Chinese (China)": "Chinês (China)",
"Spanish (auto-generated)": "Espanhol (geradas automaticamente)",
"Spanish (Mexico)": "Espanhol (México)",
"English (United States)": "Inglês (Estados Unidos)",
"footer_donate_page": "Doar",
"footer_documentation": "Documentação",
"footer_source_code": "Código-fonte",
"footer_original_source_code": "Código-fonte original",
"footer_modfied_source_code": "Código-fonte modificado",
"Chinese": "Chinês",
"search_filters_date_label": "Data de carregamento",
"search_filters_date_option_none": "Qualquer data",
"search_filters_features_option_three_sixty": "360°",
"search_filters_features_option_vr180": "VR180"
}

View File

@ -1,44 +1,42 @@
{
"show": "Espetáculo",
"views": "Visualizações",
"date": "Data de envio",
"rating": "Avaliação",
"relevance": "Relevância",
"Broken? Try another Invidious Instance": "Falhou? Tente outra Instância do Invidious",
"search_filters_type_option_show": "Espetáculo",
"search_filters_sort_option_views": "Visualizações",
"search_filters_sort_option_date": "Data de envio",
"search_filters_sort_option_rating": "Avaliação",
"search_filters_sort_option_relevance": "Relevância",
"Switch Invidious Instance": "Mudar a instância do 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.": "Lançado 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: ",
"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: ",
"next_steps_error_message_go_to_youtube": "Ir ao YouTube",
"next_steps_error_message": "Pode tentar as seguintes opções: ",
"next_steps_error_message_refresh": "Atualizar",
"filter": "Filtro",
"hdr": "HDR",
"location": "Localização",
"4k": "4K",
"live": "Em direto",
"3d": "3D",
"creative_commons": "Creative Commons",
"subtitles": "Legendas",
"hd": "HD",
"movie": "Filme",
"playlist": "Lista de reprodução",
"channel": "Canal",
"video": "Vídeo",
"year": "Este ano",
"month": "Este mês",
"week": "Esta semana",
"today": "Hoje",
"hour": "Última hora",
"sort": "Ordenar por",
"features": "Funcionalidades",
"duration": "Duração",
"content_type": "Tipo",
"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": "Em direto",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_subtitles": "Legendas",
"search_filters_features_option_hd": "HD",
"search_filters_type_option_movie": "Filme",
"search_filters_type_option_playlist": "Lista de reprodução",
"search_filters_type_option_channel": "Canal",
"search_filters_type_option_video": "Vídeo",
"search_filters_date_option_year": "Este ano",
"search_filters_date_option_month": "Este mês",
"search_filters_date_option_week": "Esta semana",
"search_filters_date_option_today": "Hoje",
"search_filters_date_option_hour": "Última hora",
"search_filters_sort_label": "Ordenar por",
"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",
"Download as: ": "Descarregar como: ",
@ -248,15 +246,15 @@
"JavaScript license information": "Informação de licença do JavaScript",
"An alternative front-end to YouTube": "Uma interface alternativa ao YouTube",
"History": "Histórico",
"Export data as JSON": "Exportar dados como JSON",
"Export data as JSON": "Exportar dados Invidious como JSON",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportar subscrições como OPML (para NewPipe e FreeTube)",
"Export subscriptions as OPML": "Exportar subscrições como OPML",
"Export": "Exportar",
"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",
"Import Invidious data": "Importar dados do Invidious",
"Import YouTube subscriptions": "Importar subscrições do YouTube/OPML",
"Import Invidious data": "Importar dados JSON do Invidious",
"Import": "Importar",
"No": "Não",
"Yes": "Sim",
@ -376,8 +374,8 @@
"Unsubscribe": "Anular subscrição",
"Shared `x` ago": "Partilhado `x` atrás",
"LIVE": "Em direto",
"short": "Curto (< 4 minutos)",
"long": "Longo (> 20 minutos)",
"search_filters_duration_option_short": "Curto (< 4 minutos)",
"search_filters_duration_option_long": "Longo (> 20 minutos)",
"footer_source_code": "Código-fonte",
"footer_original_source_code": "Código-fonte original",
"adminprefs_modified_source_code_url_label": "URL do repositório do código-fonte alterado",
@ -397,8 +395,8 @@
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"purchased": "Comprado",
"360": "360°",
"search_filters_features_option_purchased": "Comprado",
"search_filters_features_option_three_sixty": "360°",
"videoinfo_invidious_embed_link": "Incorporar hiperligação",
"Video unavailable": "Vídeo não disponível",
"invidious": "Invidious",
@ -434,8 +432,44 @@
"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": "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_read_the_faq": "leia 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 tal qual (NÃO o traduza):",
"user_created_playlists": "`x` listas de reprodução criadas"
"user_created_playlists": "`x` listas de reprodução criadas",
"search_filters_title": "Filtro",
"Chinese (Taiwan)": "Chinês (Taiwan)",
"search_message_no_results": "Nenhum resultado encontrado.",
"search_message_change_filters_or_query": "Tente alargar os termos genéricos da pesquisa e/ou alterar os filtros.",
"search_message_use_another_instance": " Também pode <a href=\"`x`\">pesquisar noutra instância</a>.",
"English (United Kingdom)": "Inglês (Reino Unido)",
"English (United States)": "Inglês (Estados Unidos)",
"Cantonese (Hong Kong)": "Cantonês (Hong Kong)",
"Chinese": "Chinês",
"Chinese (Hong Kong)": "Chinês (Hong Kong)",
"Dutch (auto-generated)": "Holandês (gerado automaticamente)",
"French (auto-generated)": "Francês (gerado automaticamente)",
"German (auto-generated)": "Alemão (gerado automaticamente)",
"Indonesian (auto-generated)": "Indonésio (gerado automaticamente)",
"Interlingue": "Interlíngua",
"Italian (auto-generated)": "Italiano (gerado automaticamente)",
"Japanese (auto-generated)": "Japonês (gerado automaticamente)",
"Korean (auto-generated)": "Coreano (gerado automaticamente)",
"Portuguese (auto-generated)": "Português (gerado automaticamente)",
"Portuguese (Brazil)": "Português (Brasil)",
"Turkish (auto-generated)": "Turco (gerado automaticamente)",
"Vietnamese (auto-generated)": "Vietnamita (gerado automaticamente)",
"search_filters_duration_option_medium": "Médio (4 - 20 minutos)",
"search_filters_features_option_vr180": "VR180",
"search_filters_apply_button": "Aplicar filtros selecionados",
"Spanish (auto-generated)": "Espanhol (gerado automaticamente)",
"Spanish (Mexico)": "Espanhol (México)",
"preferences_watch_history_label": "Ativar histórico de reprodução: ",
"Chinese (China)": "Chinês (China)",
"Russian (auto-generated)": "Russo (gerado automaticamente)",
"Spanish (Spain)": "Espanhol (Espanha)",
"search_filters_date_label": "Data de publicação",
"search_filters_date_option_none": "Qualquer data",
"search_filters_type_option_all": "Qualquer tipo",
"search_filters_duration_option_none": "Qualquer duração",
"Popular enabled: ": "Página \"popular\" ativada: "
}

View File

@ -21,7 +21,7 @@
"No": "Nu",
"Import and Export Data": "Importați și Exportați Datele",
"Import": "Importați",
"Import Invidious data": "Importați Datele de pe Invidious",
"Import Invidious data": "Importați datele JSON de pe Invidious",
"Import YouTube subscriptions": "Importați abonamentele de pe YouTube",
"Import FreeTube subscriptions (.db)": "Importați abonamentele de pe FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importați abonamentele de pe NewPipe (.json)",
@ -29,7 +29,7 @@
"Export": "Exportați",
"Export subscriptions as OPML": "Exportați abonamentele în format OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportați abonamentele în format OPML (pentru NewPipe și FreeTube)",
"Export data as JSON": "Exportați datele în format JSON",
"Export data as JSON": "Exportați datele Invidious în format JSON",
"Delete account?": "Sunteți siguri că doriți să vă ștergeți contul?",
"History": "Istoric",
"An alternative front-end to YouTube": "O alternativă front-end pentru YouTube",
@ -155,7 +155,7 @@
"Hide replies": "Ascundeți replicile",
"Show replies": "Afișați replicile",
"Incorrect password": "Parolă incorectă",
"Quota exceeded, try again in a few hours": "Numărul de tentative de conectare a fost depășit. Va rugăm să încercați din nou în câteva ore.",
"Quota exceeded, try again in a few hours": "Numărul de tentative de conectare a fost depășit. Va rugăm să încercați din nou în câteva ore",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Conectare eșuată. Dacă nu reușiți să vă conectați, verificați dacă ați activat autentificarea cu doi factori (Autentificator sau SMS).",
"Invalid TFA code": "Codul de autentificare cu doi factori este invalid",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Conectare eșuată. Acest lucru ar putea fi cauzat de faptul că nu ați activat autentificarea cu doi factori.",
@ -174,7 +174,7 @@
"Deleted or invalid channel": "Canal șters sau invalid",
"This channel does not exist.": "Acest canal nu există.",
"Could not get channel info.": "Nu am putut primi informații despre acest canal.",
"Could not fetch comments": "Încărcarea comentariilor a eșuat.",
"Could not fetch comments": "Încărcarea comentariilor a eșuat",
"`x` ago": "acum `x`",
"Load more": "Vedeți mai mult",
"Could not create mix.": "Nu am putut crea această listă de redare.",
@ -187,7 +187,7 @@
"Erroneous challenge": "Challenge invalid",
"Erroneous token": "Token invalid",
"No such user": "Acest utilizator nu există",
"Token is expired, please try again": "Token-ul este expirat, vă rugăm să reîncercați.",
"Token is expired, please try again": "Jetonul a expirat, vă rugăm să încercați din nou",
"English": "Engleză",
"English (auto-generated)": "Engleză (generată automat)",
"Afrikaans": "Afrikaans",
@ -295,7 +295,7 @@
"Yoruba": "Yoruba",
"Zulu": "Zoulou",
"Fallback comments: ": "Comentarii alternative: ",
"Popular": "Popular",
"Popular": "Populare",
"Top": "Top",
"About": "Despre",
"Rating: ": "Evaluare: ",
@ -318,5 +318,173 @@
"Videos": "Videoclipuri",
"Playlists": "Liste de redare",
"Community": "Comunitate",
"Current version: ": "Versiunea actuală: "
"Current version: ": "Versiunea actuală: ",
"crash_page_read_the_faq": "citit lista <a href=\"`x`\">Întrebărilor Frecvente (FAQ)</a>",
"generic_count_days_0": "{{count}} zi",
"generic_count_days_1": "{{count}} zile",
"generic_count_days_2": "{{count}} de zile",
"generic_count_hours_0": "{{count}} oră",
"generic_count_hours_1": "{{count}} ore",
"generic_count_hours_2": "{{count}} de ore",
"generic_count_minutes_0": "{{count}} minut",
"generic_count_minutes_1": "{{count}} minute",
"generic_count_minutes_2": "{{count}} de minute",
"generic_views_count_0": "{{count}} vizionare",
"generic_views_count_1": "{{count}} vizionări",
"generic_views_count_2": "{{count}} de vizionări",
"subscriptions_unseen_notifs_count_0": "{{count}} notificare neverificată",
"subscriptions_unseen_notifs_count_1": "{{count}} notificări neverificate",
"subscriptions_unseen_notifs_count_2": "{{count}} de notificări neverificate",
"crash_page_refresh": "încercat să <a href=\"`x`\">reîmprospătați pagina</a>",
"crash_page_switch_instance": "am încercat să <a href=\"`x`\">folosim o altă instanță</a>",
"preferences_watch_history_label": "Activează istoricul: ",
"invidious": "Invidious",
"preferences_vr_mode_label": "Videoclipuri interactive de 360 de grade (necesită WebGL): ",
"English (United Kingdom)": "Engleză (Regatul Unit)",
"English (United States)": "Engleză (Statele Unite ale Americii)",
"Chinese": "Chineză",
"Chinese (China)": "Chineză (China)",
"Chinese (Hong Kong)": "Chineză (Hong Kong)",
"Chinese (Taiwan)": "Chineză (Taiwan)",
"Cantonese (Hong Kong)": "Cantoneză (Hong Kong)",
"Portuguese (auto-generated)": "Portugheză (generată automat)",
"Portuguese (Brazil)": "Portugheză (Brazilia)",
"Russian (auto-generated)": "Rusă (generată automat)",
"Turkish (auto-generated)": "Turcă (generată automat)",
"Vietnamese (auto-generated)": "Vietnameză (generată automat)",
"videoinfo_started_streaming_x_ago": "În direct de acum `x`",
"preferences_quality_dash_option_2160p": "2160p",
"footer_modfied_source_code": "Codul sursă modificat",
"preferences_quality_dash_label": "Calitatea video DASH preferată: ",
"generic_videos_count_0": "{{count}} videoclip",
"generic_videos_count_1": "{{count}} videoclipuri",
"generic_videos_count_2": "{{count}} de videoclipuri",
"generic_playlists_count_0": "{{count}} playlist",
"generic_playlists_count_1": "{{count}} playlisturi",
"generic_playlists_count_2": "{{count}} de playlisturi",
"tokens_count_0": "{{count}} jeton",
"tokens_count_1": "{{count}} jetoane",
"tokens_count_2": "{{count}} de jetoane",
"comments_points_count_0": "{{count}} punct",
"comments_points_count_1": "{{count}} puncte",
"comments_points_count_2": "{{count}} de puncte",
"Spanish (Spain)": "Spaniolă (Spania)",
"Video unavailable": "Videoclip indisponibil",
"crash_page_search_issue": "căutat <a href=\"`x`\">sugestiile existente pe GitHub</a>",
"Show more": "Afișați mai mult",
"Released under the AGPLv3 on Github.": "Lansat sub licența AGPLv3 pe GitHub.",
"preferences_quality_option_dash": "DASH (calitate adaptativă)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_small": "Mică",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_1080p": "1080p",
"preferences_category_misc": "Setări diverse",
"preferences_automatic_instance_redirect_label": "Redirecționare automată de instanță (trecere prin redirect.invidious.io): ",
"preferences_quality_dash_option_480p": "480p",
"preferences_quality_option_medium": "Medie",
"Switch Invidious Instance": "Schimbă instanța Invidious",
"preferences_quality_dash_option_720p": "720p",
"preferences_quality_dash_option_auto": "Automatică",
"preferences_quality_dash_option_best": "Cea mai bună",
"preferences_quality_dash_option_worst": "Cea mai redusă",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_option_360p": "360p",
"preferences_region_label": "Țară de conținut: ",
"preferences_extend_desc_label": "Extindeți automat descrierea: ",
"preferences_show_nick_label": "Afișați numele de utilizator pe partea de sus: ",
"generic_subscribers_count_0": "{{count}} abonat",
"generic_subscribers_count_1": "{{count}} abonați",
"generic_subscribers_count_2": "{{count}} de abonați",
"generic_subscriptions_count_0": "{{count}} abonament",
"generic_subscriptions_count_1": "{{count}} abonamente",
"generic_subscriptions_count_2": "{{count}} de abonamente",
"Search": "Căutați",
"search_filters_title": "Filtre",
"search_filters_date_label": "Data încărcării",
"none": "niciunul",
"search_message_use_another_instance": " Puteți <a href=\"`x`\">căuta într-o altă instanță</a>.",
"comments_view_x_replies_0": "Afișați {{count}} răspuns",
"comments_view_x_replies_1": "Afișați {{count}} răspunsuri",
"comments_view_x_replies_2": "Afișați {{count}} de răspunsuri",
"search_message_no_results": "Nu s-au găsit rezultate.",
"Dutch (auto-generated)": "Olandeză (generată automat)",
"Indonesian (auto-generated)": "Indoneziană (generată automat)",
"German (auto-generated)": "Germană (generată automat)",
"French (auto-generated)": "Franceză (generată automat)",
"Interlingue": "Interlingue",
"Italian (auto-generated)": "Italiană (generată automat)",
"Japanese (auto-generated)": "Japoneză (generată automat)",
"Korean (auto-generated)": "Coreeană (generată automat)",
"Spanish (auto-generated)": "Spaniolă (generată automat)",
"search_filters_date_option_none": "Oricând",
"search_filters_date_option_year": "an",
"search_filters_type_option_channel": "canal",
"Spanish (Mexico)": "Spaniolă (Mexic)",
"generic_count_weeks_0": "{{count}} săptămână",
"generic_count_weeks_1": "{{count}} săptămâni",
"generic_count_weeks_2": "{{count}} de săptămâni",
"generic_count_seconds_0": "{{count}} secundă",
"generic_count_seconds_1": "{{count}} secunde",
"generic_count_seconds_2": "{{count}} de secunde",
"search_filters_type_option_video": "videoclip",
"generic_count_years_0": "{{count}} an",
"generic_count_years_1": "{{count}} ani",
"generic_count_years_2": "{{count}} de ani",
"generic_count_months_0": "{{count}} lună",
"generic_count_months_1": "{{count}} luni",
"generic_count_months_2": "{{count}} de luni",
"search_filters_duration_label": "durată",
"search_filters_date_option_month": "lună",
"search_filters_type_label": "Tip",
"search_filters_date_option_today": "azi",
"search_filters_date_option_week": "săptămână",
"search_filters_features_option_vr180": "VR180",
"search_filters_type_option_playlist": "playlist",
"search_filters_type_option_movie": "film",
"search_filters_type_option_show": "emisiune",
"search_filters_duration_option_short": "Scurt (< 4 minute)",
"search_filters_duration_option_medium": "Medie (4 - 20 de minute)",
"search_filters_duration_option_none": "Fără limită",
"search_filters_duration_option_long": "Lungă (> 20 de minute)",
"search_filters_features_label": "atribute",
"search_filters_features_option_live": "în direct",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_sixty": "360°",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_subtitles": "subtitrări/CC",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_hdr": "HDR",
"search_filters_features_option_purchased": "Cumpărate",
"next_steps_error_message": "După ce ar trebui să încercați să: ",
"user_saved_playlists": "`x` playlisturi salvate",
"search_filters_features_option_location": "locație",
"search_filters_sort_label": "Sortați după",
"search_filters_sort_option_relevance": "relevanță",
"search_filters_sort_option_rating": "clasificare",
"search_filters_sort_option_date": "Data încărcării",
"search_filters_sort_option_views": "Numărul de vizionări",
"footer_source_code": "Codul sursă",
"search_filters_apply_button": "Aplicați filtrele selectate",
"footer_original_source_code": "Codul sursă original",
"next_steps_error_message_refresh": "Reîmprospătează",
"next_steps_error_message_go_to_youtube": "Mergeți pe YouTube",
"footer_donate_page": "Donați",
"adminprefs_modified_source_code_url_label": "URL către depozitul de cod sursă modificat",
"footer_documentation": "Documentație",
"videoinfo_youTube_embed_link": "Încorporați",
"videoinfo_watch_on_youTube": "Vizionați pe YouTube",
"videoinfo_invidious_embed_link": "Link de încorporare",
"download_subtitles": "Subtitrări - `x` (.vtt)",
"user_created_playlists": "`x` playlisturi create",
"preferences_save_player_pos_label": "Salvați poziția de redare: ",
"crash_page_you_found_a_bug": "Se pare că ați găsit un bug în aplicația Invidious!",
"crash_page_before_reporting": "Înainte de a reporta bugul, asigurați-vă că ați:",
"search_filters_date_option_hour": "oră",
"search_message_change_filters_or_query": "Încercați să lărgiți căutarea sau să modificați filtrele.",
"crash_page_report_issue": "Dacă niciuna dintre sugestiile de mai sus v-a ajutat, vă rugăm să <a href=\"`x`\">postați o nouă sugestie pe GitHub</a> (cel mai bine în engleză), și să includeți următorul text în post (să nu îl traduceți):",
"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"
}

View File

@ -5,8 +5,8 @@
"Subscribe": "Подписаться",
"View channel on YouTube": "Смотреть канал на YouTube",
"View playlist on YouTube": "Посмотреть плейлист на YouTube",
"newest": "самые свежие",
"oldest": "самые старые",
"newest": "сначала новые",
"oldest": "сначала старые",
"popular": "популярные",
"last": "недавние",
"Next page": "Следующая страница",
@ -41,8 +41,8 @@
"User ID": "ID пользователя",
"Password": "Пароль",
"Time (h:mm:ss):": "Время (ч:мм:сс):",
"Text CAPTCHA": "Текст капчи",
"Image CAPTCHA": "Изображение капчи",
"Text CAPTCHA": "Текстовая капча (англ.)",
"Image CAPTCHA": "Капча-картинка",
"Sign In": "Войти",
"Register": "Зарегистрироваться",
"E-mail": "Электронная почта",
@ -51,7 +51,7 @@
"preferences_category_player": "Настройки проигрывателя",
"preferences_video_loop_label": "Всегда повторять: ",
"preferences_autoplay_label": "Автовоспроизведение: ",
"preferences_continue_label": "Всегда включать следующее видео? ",
"preferences_continue_label": "Переходить к следующему видео? ",
"preferences_continue_autoplay_label": "Автопроигрывание следующего видео: ",
"preferences_listen_label": "Режим «только аудио» по умолчанию: ",
"preferences_local_label": "Проигрывать видео через прокси? ",
@ -71,15 +71,15 @@
"preferences_player_style_label": "Стиль проигрывателя: ",
"Dark mode: ": "Тёмное оформление: ",
"preferences_dark_mode_label": "Тема: ",
"dark": емная",
"dark": ёмная",
"light": "светлая",
"preferences_thin_mode_label": "Облегчённое оформление: ",
"preferences_category_misc": "Прочие предпочтения",
"preferences_automatic_instance_redirect_label": "Автоматическое перенаправление на зеркало сайта (резервный вариант redirect.invidious.io): ",
"preferences_category_misc": "Прочие настройки",
"preferences_automatic_instance_redirect_label": "Автоматическая смена зеркала (переход на redirect.invidious.io): ",
"preferences_category_subscription": "Настройки подписок",
"preferences_annotations_subscribed_label": "Всегда показывать аннотации в видео каналов, на которые вы подписаны? ",
"Redirect homepage to feed: ": "Отображать видео с каналов, на которые вы подписаны, как главную страницу: ",
"preferences_max_results_label": "Число видео, на которые вы подписаны, в ленте: ",
"preferences_annotations_subscribed_label": "Всегда показывать аннотации на каналах из ваших подписок? ",
"Redirect homepage to feed: ": "Показывать подписки на главной странице: ",
"preferences_max_results_label": "Число видео в ленте: ",
"preferences_sort_label": "Сортировать видео: ",
"published": "по дате публикации",
"published - reverse": "по дате публикации в обратном порядке",
@ -96,24 +96,24 @@
"`x` is live": "`x` в прямом эфире",
"preferences_category_data": "Настройки данных",
"Clear watch history": "Очистить историю просмотров",
"Import/export data": "Импорткспорт данных",
"Import/export data": "Импорт и экспорт данных",
"Change password": "Изменить пароль",
"Manage subscriptions": "Управлять подписками",
"Manage tokens": "Управлять токенами",
"Manage subscriptions": "Управление подписками",
"Manage tokens": "Управление токенами",
"Watch history": "История просмотров",
"Delete account": "Удалить аккаунт",
"preferences_category_admin": "Администраторские настройки",
"preferences_category_admin": "Настройки администратора",
"preferences_default_home_label": "Главная страница по умолчанию: ",
"preferences_feed_menu_label": "Меню ленты видео: ",
"preferences_show_nick_label": "Показать ник вверху: ",
"Top enabled: ": "Включить топ видео? ",
"CAPTCHA enabled: ": "Включить капчу? ",
"Login enabled: ": "Включить авторизацию? ",
"Login enabled: ": "Включить авторизацию: ",
"Registration enabled: ": "Включить регистрацию? ",
"Report statistics: ": "Сообщать статистику? ",
"Save preferences": "Сохранить настройки",
"Subscription manager": "Менеджер подписок",
"Token manager": "Менеджер токенов",
"Subscription manager": "Управление подписками",
"Token manager": "Управление токенами",
"Token": "Токен",
"Import/export": "Импорт и экспорт",
"unsubscribe": "отписаться",
@ -121,10 +121,10 @@
"Subscriptions": "Подписки",
"search": "поиск",
"Log out": "Выйти",
"Released under the AGPLv3 on Github.": "Выпущено под лицензией AGPLv3 на Github.",
"Source available here.": "Исходный код доступен здесь.",
"View JavaScript license information.": "Посмотреть информацию по лицензии JavaScript.",
"View privacy policy.": "Посмотреть политику конфиденциальности.",
"Released under the AGPLv3 on Github.": "Выпущено под лицензией AGPLv3 на GitHub.",
"Source available here.": "Исходный код.",
"View JavaScript license information.": "Информация о лицензиях JavaScript.",
"View privacy policy.": "Политика конфиденциальности.",
"Trending": "В тренде",
"Public": "Публичный",
"Unlisted": "Нет в списке",
@ -135,43 +135,42 @@
"Delete playlist": "Удалить плейлист",
"Create playlist": "Создать плейлист",
"Title": "Заголовок",
"Playlist privacy": "Конфиденциальность плейлиста",
"Playlist privacy": "Видимость плейлиста",
"Editing playlist `x`": "Редактирование плейлиста `x`",
"Show more": "Показать больше",
"Show less": "Показать меньше",
"Show more": "Развернуть",
"Show less": "Свернуть",
"Watch on YouTube": "Смотреть на YouTube",
"Switch Invidious Instance": "Сменить экземпляр Invidious",
"Broken? Try another Invidious Instance": "Сломался? Попробуйте другой экземпляр Invidious",
"Switch Invidious Instance": "Сменить зеркало Invidious",
"Hide annotations": "Скрыть аннотации",
"Show annotations": "Показать аннотации",
"Genre: ": "Жанр: ",
"License: ": "Лицензия: ",
"Family friendly? ": "Семейный просмотр: ",
"Wilson score: ": "Рейтинг Уилсона: ",
"Wilson score: ": "Оценка Уилсона: ",
"Engagement: ": "Вовлечённость: ",
"Whitelisted regions: ": "Доступно в регионах: ",
"Blacklisted regions: ": "Недоступно в регионах: ",
"Shared `x`": "Опубликовано `x`",
"Premieres in `x`": "Премьера через `x`",
"Premieres `x`": "Премьера `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Похоже, у вас отключён JavaScript. Чтобы увидить комментарии, нажмите сюда, но учтите: они могут загружаться немного медленнее.",
"View YouTube comments": "Смотреть комментарии с YouTube",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Похоже, у вас отключён JavaScript. Нажмите сюда, чтобы увидеть комментарии. Но учтите: они могут загружаться немного медленнее.",
"View YouTube comments": "Показать комментарии с YouTube",
"View more comments on Reddit": "Посмотреть больше комментариев на Reddit",
"View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "Показать `x` комментариев",
"": "Показать `x` комментариев"
"([^.,0-9]|^)1([^.,0-9]|$)": "Показано `x` комментариев",
"": "Показано `x` комментариев"
},
"View Reddit comments": "Смотреть комментарии с Reddit",
"Hide replies": "Скрыть ответы",
"Show replies": "Показать ответы",
"Incorrect password": "Неправильный пароль",
"Quota exceeded, try again in a few hours": "Лимит превышен, попробуйте снова через несколько часов",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Войти не удаётся. Проверьте, не включена ли двухфакторная аутентификация (по коду или смс).",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Не удалось войти. Проверьте, не включена ли двухфакторная аутентификация (по коду или смс).",
"Invalid TFA code": "Неправильный код двухфакторной аутентификации",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Не удаётся войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.",
"Wrong answer": "Неправильный ответ",
"Erroneous CAPTCHA": "Неправильная капча",
"CAPTCHA is a required field": "Необходимо пройти капчу",
"CAPTCHA is a required field": "Необходимо решить капчу",
"User ID is a required field": "Необходимо ввести ID пользователя",
"Password is a required field": "Необходимо ввести пароль",
"Wrong username or password": "Неправильный логин или пароль",
@ -186,8 +185,8 @@
"Could not get channel info.": "Не удаётся получить информацию об этом канале.",
"Could not fetch comments": "Не удаётся загрузить комментарии",
"`x` ago": "`x` назад",
"Load more": "Загрузить больше",
"Could not create mix.": "Не удаётся создать микс.",
"Load more": "Загрузить ещё",
"Could not create mix.": "Не удалось создать микс.",
"Empty playlist": "Плейлист пуст",
"Not a playlist.": "Некорректный плейлист.",
"Playlist does not exist.": "Плейлист не существует.",
@ -196,7 +195,7 @@
"Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле «токен»",
"Erroneous challenge": "Неправильный ответ в «challenge»",
"Erroneous token": "Неправильный токен",
"No such user": "Недопустимое имя пользователя",
"No such user": "Пользователь не найден",
"Token is expired, please try again": "Срок действия токена истёк, попробуйте позже",
"English": "Английский",
"English (auto-generated)": "Английский (созданы автоматически)",
@ -220,7 +219,7 @@
"Croatian": "Хорватский",
"Czech": "Чешский",
"Danish": "Датский",
"Dutch": "Нидерландский",
"Dutch": "Голландский",
"Esperanto": "Эсперанто",
"Estonian": "Эстонский",
"Filipino": "Филиппинский",
@ -230,8 +229,8 @@
"Georgian": "Грузинский",
"German": "Немецкий",
"Greek": "Греческий",
"Gujarati": "Гуджаратский",
"Haitian Creole": "Гаит. креольский",
"Gujarati": "Гуджарати",
"Haitian Creole": "Гаитянский креольский",
"Hausa": "Хауса",
"Hawaiian": "Гавайский",
"Hebrew": "Иврит",
@ -252,7 +251,7 @@
"Kurdish": "Курдский",
"Kyrgyz": "Киргизский",
"Lao": "Лаосский",
"Latin": "Латинский",
"Latin": "Латынь",
"Latvian": "Латышский",
"Lithuanian": "Литовский",
"Luxembourgish": "Люксембургский",
@ -263,9 +262,9 @@
"Maltese": "Мальтийский",
"Maori": "Маори",
"Marathi": "Маратхи",
"Mongolian": "Монгольская",
"Mongolian": "Монгольский",
"Nepali": "Непальский",
"Norwegian Bokmål": "Норвежский",
"Norwegian Bokmål": "Норвежский букмол",
"Nyanja": "Ньянджа",
"Pashto": "Пушту",
"Persian": "Персидский",
@ -300,7 +299,7 @@
"Vietnamese": "Вьетнамский",
"Welsh": "Валлийский",
"Western Frisian": "Западнофризский",
"Xhosa": "Коса",
"Xhosa": "Коса (кхоса)",
"Yiddish": "Идиш",
"Yoruba": "Йоруба",
"Zulu": "Зулусский",
@ -312,7 +311,7 @@
"Rating: ": "Рейтинг: ",
"preferences_locale_label": "Язык: ",
"View as playlist": "Смотреть как плейлист",
"Default": "По-умолчанию",
"Default": "По умолчанию",
"Music": "Музыка",
"Gaming": "Игры",
"News": "Новости",
@ -329,39 +328,38 @@
"Videos": "Видео",
"Playlists": "Плейлисты",
"Community": "Сообщество",
"relevance": "Актуальность",
"rating": "Рейтинг",
"date": "Дата загрузки",
"views": "Просмотры",
"content_type": "Тип",
"duration": "Длительность",
"features": "Функции",
"sort": "Сортировать по",
"hour": "Последний час",
"today": "Сегодня",
"week": "Эта неделя",
"month": "Этот месяц",
"year": "Этот год",
"video": "Видео",
"channel": "Канал",
"playlist": "Плейлист",
"movie": "Фильм",
"show": "Показать",
"hd": "HD",
"subtitles": "Субтитры",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Прямой эфир",
"4k": "4K",
"location": "Местоположение",
"hdr": "HDR",
"filter": "Фильтр",
"search_filters_sort_option_relevance": "по актуальности",
"search_filters_sort_option_rating": "по рейтингу",
"search_filters_sort_option_date": "по дате загрузки",
"search_filters_sort_option_views": "по просмотрам",
"search_filters_type_label": "Тип",
"search_filters_duration_label": "Длительность",
"search_filters_features_label": "Дополнительно",
"search_filters_sort_label": "Сортировать",
"search_filters_date_option_hour": "Последний час",
"search_filters_date_option_today": "Сегодня",
"search_filters_date_option_week": "Эта неделя",
"search_filters_date_option_month": "Этот месяц",
"search_filters_date_option_year": "Этот год",
"search_filters_type_option_video": "Видео",
"search_filters_type_option_channel": "Канал",
"search_filters_type_option_playlist": "Плейлист",
"search_filters_type_option_movie": "Фильм",
"search_filters_type_option_show": "Сериал",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Субтитры",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Прямой эфир",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Местоположение",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Текущая версия: ",
"next_steps_error_message": "После чего следует попробовать: ",
"next_steps_error_message_refresh": "Обновить",
"next_steps_error_message_go_to_youtube": "Перейти на YouTube",
"short": "Короткие (< 4 минут)",
"long": "Длинные (> 20 минут)",
"search_filters_duration_option_short": "Короткие (< 4 минут)",
"search_filters_duration_option_long": "Длинные (> 20 минут)",
"preferences_quality_dash_option_best": "Наилучшее",
"generic_count_weeks_0": "{{count}} неделя",
"generic_count_weeks_1": "{{count}} недели",
@ -370,28 +368,28 @@
"English (United States)": "Английский (США)",
"Cantonese (Hong Kong)": "Кантонский (Гонконг)",
"Chinese (Taiwan)": "Китайский (Тайвань)",
"Dutch (auto-generated)": "Голландский (автоматический)",
"German (auto-generated)": "Немецкий (автоматический)",
"Indonesian (auto-generated)": "Индонезийский (автоматический)",
"Italian (auto-generated)": "Итальянский (автоматический)",
"Dutch (auto-generated)": "Голландский (созданы автоматически)",
"German (auto-generated)": "Немецкий (созданы автоматически)",
"Indonesian (auto-generated)": "Индонезийский (созданы автоматически)",
"Italian (auto-generated)": "Итальянский (созданы автоматически)",
"Interlingue": "Окциденталь",
"Russian (auto-generated)": "Русский (автоматический)",
"Spanish (auto-generated)": "Испанский (автоматический)",
"Russian (auto-generated)": "Русский (созданы автоматически)",
"Spanish (auto-generated)": "Испанский (созданы автоматически)",
"Spanish (Spain)": "Испанский (Испания)",
"Turkish (auto-generated)": "Турецкий (автоматический)",
"Vietnamese (auto-generated)": "Вьетнамский (автоматический)",
"Turkish (auto-generated)": "Турецкий (созданы автоматически)",
"Vietnamese (auto-generated)": "Вьетнамский (созданы автоматически)",
"footer_documentation": "Документация",
"adminprefs_modified_source_code_url_label": "Ссылка на нашу ветку репозитория",
"none": "ничего",
"videoinfo_watch_on_youTube": "Смотреть на YouTube",
"videoinfo_youTube_embed_link": "Встраиваемый элемент",
"videoinfo_invidious_embed_link": "Встраиваемая ссылка",
"videoinfo_youTube_embed_link": "Версия для встраивания",
"videoinfo_invidious_embed_link": "Ссылка для встраивания",
"download_subtitles": "Субтитры - `x` (.vtt)",
"user_created_playlists": "`x` созданных плейлистов",
"crash_page_you_found_a_bug": "Похоже вы нашли баг в Invidious!",
"crash_page_you_found_a_bug": "Похоже, вы нашли ошибку в Invidious!",
"crash_page_before_reporting": "Прежде чем сообщать об ошибке, убедитесь, что вы:",
"crash_page_refresh": "пробовали <a href=\"`x`\"> перезагрузить страницу</a>",
"crash_page_report_issue": "Если ни один вариант не помог, пожалуйста <a href=\"`x`\">откройте новую проблему на GitHub</a> (желательно на английском) и приложите следующий текст к вашему сообщению (НЕ переводите его):",
"crash_page_report_issue": "Если ни один вариант не помог, пожалуйста <a href=\"`x`\">откройте новую проблему на GitHub</a> (на английском, пжлста) и приложите следующий текст к вашему сообщению (НЕ переводите его):",
"generic_videos_count_0": "{{count}} видео",
"generic_videos_count_1": "{{count}} видео",
"generic_videos_count_2": "{{count}} видео",
@ -419,8 +417,8 @@
"generic_views_count_0": "{{count}} просмотр",
"generic_views_count_1": "{{count}} просмотра",
"generic_views_count_2": "{{count}} просмотров",
"French (auto-generated)": "Французский (автоматический)",
"Portuguese (auto-generated)": "Португальский (автоматический)",
"French (auto-generated)": "Французский (созданы автоматически)",
"Portuguese (auto-generated)": "Португальский (созданы автоматически)",
"generic_count_days_0": "{{count}} день",
"generic_count_days_1": "{{count}} дня",
"generic_count_days_2": "{{count}} дней",
@ -437,15 +435,15 @@
"generic_count_seconds_0": "{{count}} секунда",
"generic_count_seconds_1": "{{count}} секунды",
"generic_count_seconds_2": "{{count}} секунд",
"purchased": "Приобретено",
"search_filters_features_option_purchased": "Приобретено",
"videoinfo_started_streaming_x_ago": "Трансляция началась `x` назад",
"crash_page_switch_instance": "пробовали <a href=\"`x`\">использовать другое зеркало</a>",
"crash_page_read_the_faq": "прочли <a href=\"`x`\">Частые Вопросы (ЧаВо)</a>",
"crash_page_read_the_faq": "прочли ответы на <a href=\"`x`\">Частые Вопросы (ЧаВо)</a>",
"Chinese": "Китайский",
"Chinese (Hong Kong)": "Китайский (Гонконг)",
"Japanese (auto-generated)": "Японский (автоматический)",
"Japanese (auto-generated)": "Японский (созданы автоматически)",
"Chinese (China)": "Китайский (Китай)",
"Korean (auto-generated)": "Корейский (автоматический)",
"Korean (auto-generated)": "Корейский (созданы автоматически)",
"generic_count_months_0": "{{count}} месяц",
"generic_count_months_1": "{{count}} месяца",
"generic_count_months_2": "{{count}} месяцев",
@ -457,7 +455,7 @@
"footer_original_source_code": "Оригинальный исходный код",
"footer_modfied_source_code": "Изменённый исходный код",
"user_saved_playlists": "`x` сохранённых плейлистов",
"crash_page_search_issue": "искали <a href=\"`x`\">похожую проблему на Github</a>",
"crash_page_search_issue": "поискали <a href=\"`x`\">похожую проблему на GitHub</a>",
"comments_points_count_0": "{{count}} плюс",
"comments_points_count_1": "{{count}} плюса",
"comments_points_count_2": "{{count}} плюсов",
@ -466,15 +464,28 @@
"preferences_quality_option_dash": "DASH (автоматическое качество)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_option_medium": "Среднее",
"preferences_quality_dash_label": "Предпочтительное автоматическое качество видео: ",
"preferences_quality_dash_label": "Предпочтительное качество для DASH: ",
"preferences_quality_dash_option_worst": "Очень низкое",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"360": "360°",
"search_filters_features_option_three_sixty": "360°",
"Video unavailable": "Видео недоступно",
"preferences_save_player_pos_label": "Запоминать позицию: ",
"preferences_region_label": "Страна: "
"preferences_region_label": "Страна: ",
"preferences_watch_history_label": "Включить историю просмотров: ",
"search_filters_title": "Фильтр",
"search_filters_duration_option_none": "Любой длины",
"search_filters_type_option_all": "Любого типа",
"search_filters_date_option_none": "Любая дата",
"search_filters_date_label": "Дата загрузки",
"search_message_no_results": "Ничего не найдено.",
"search_message_use_another_instance": " Дополнительно вы можете <a href=\"`x`\">поискать на других зеркалах</a>.",
"search_filters_features_option_vr180": "VR180",
"search_message_change_filters_or_query": "Попробуйте расширить поисковый запрос или изменить фильтры.",
"search_filters_duration_option_medium": "Средние (4 - 20 минут)",
"search_filters_apply_button": "Применить фильтры",
"Popular enabled: ": "Популярное включено: "
}

126
locales/si.json Normal file
View File

@ -0,0 +1,126 @@
{
"generic_views_count": "බැලීම් {{count}}",
"generic_views_count_plural": "බැලීම් {{count}}",
"generic_videos_count": "{{count}} වීඩියෝව",
"generic_videos_count_plural": "වීඩියෝ {{count}}",
"generic_subscribers_count": "ග්‍රාහකයන් {{count}}",
"generic_subscribers_count_plural": "ග්‍රාහකයන් {{count}}",
"generic_subscriptions_count": "දායකත්ව {{count}}",
"generic_subscriptions_count_plural": "දායකත්ව {{count}}",
"Shared `x` ago": "`x` පෙර බෙදා ගන්නා ලදී",
"Unsubscribe": "දායක නොවන්න",
"View playlist on YouTube": "YouTube හි ධාවන ලැයිස්තුව බලන්න",
"newest": "අලුත්ම",
"oldest": "පැරණිතම",
"popular": "ජනප්‍රිය",
"last": "අවසන්",
"Cannot change password for Google accounts": "Google ගිණුම් සඳහා මුරපදය වෙනස් කළ නොහැක",
"Authorize token?": "ටෝකනය අනුමත කරනවා ද?",
"Authorize token for `x`?": "`x` සඳහා ටෝකනය අනුමත කරනවා ද?",
"Yes": "ඔව්",
"Import and Export Data": "දත්ත ආනයනය සහ අපනයනය කිරීම",
"Import": "ආනයන",
"Import Invidious data": "Invidious JSON දත්ත ආයාත කරන්න",
"Import FreeTube subscriptions (.db)": "FreeTube දායකත්වයන් (.db) ආයාත කරන්න",
"Import NewPipe subscriptions (.json)": "NewPipe දායකත්වයන් (.json) ආයාත කරන්න",
"Import NewPipe data (.zip)": "NewPipe දත්ත (.zip) ආයාත කරන්න",
"Export": "අපනයන",
"Export data as JSON": "Invidious දත්ත JSON ලෙස අපනයනය කරන්න",
"Delete account?": "ගිණුම මකාදමනවා ද?",
"History": "ඉතිහාසය",
"An alternative front-end to YouTube": "YouTube සඳහා විකල්ප ඉදිරිපස අන්තයක්",
"source": "මූලාශ්‍රය",
"Log in/register": "පුරන්න/ලියාපදිංචිවන්න",
"Log in with Google": "Google සමඟ පුරන්න",
"Password": "මුරපදය",
"Time (h:mm:ss):": "වේලාව (h:mm:ss):",
"Sign In": "පුරන්න",
"Preferences": "මනාපයන්",
"preferences_category_player": "වීඩියෝ ධාවක මනාපයන්",
"preferences_video_loop_label": "නැවත නැවතත්: ",
"preferences_autoplay_label": "ස්වයංක්‍රීය වාදනය: ",
"preferences_continue_label": "මීලඟට වාදනය කරන්න: ",
"preferences_continue_autoplay_label": "මීළඟ වීඩියෝව ස්වයංක්‍රීයව ධාවනය කරන්න: ",
"preferences_local_label": "Proxy වීඩියෝ: ",
"preferences_watch_history_label": "නැරඹුම් ඉතිහාසය සබල කරන්න: ",
"preferences_speed_label": "පෙරනිමි වේගය: ",
"preferences_quality_option_dash": "DASH (අනුවර්තිත ගුණත්වය)",
"preferences_quality_option_medium": "මධ්‍යස්ථ",
"preferences_quality_dash_label": "කැමති DASH වීඩියෝ ගුණත්වය: ",
"preferences_quality_dash_option_4320p": "4320p",
"preferences_quality_dash_option_1080p": "1080p",
"preferences_quality_dash_option_480p": "480p",
"preferences_quality_dash_option_360p": "360p",
"preferences_quality_dash_option_144p": "144p",
"preferences_volume_label": "ධාවකයේ හඬ: ",
"preferences_comments_label": "පෙරනිමි අදහස්: ",
"youtube": "YouTube",
"reddit": "Reddit",
"invidious": "Invidious",
"preferences_captions_label": "පෙරනිමි උපසිරැසි: ",
"preferences_related_videos_label": "අදාළ වීඩියෝ පෙන්වන්න: ",
"preferences_annotations_label": "අනුසටහන් පෙන්වන්න: ",
"preferences_vr_mode_label": "අන්තර්ක්‍රියාකාරී අංශක 360 වීඩියෝ (WebGL අවශ්‍යයි): ",
"preferences_region_label": "අන්තර්ගත රට: ",
"preferences_player_style_label": "වීඩියෝ ධාවක විලාසය: ",
"Dark mode: ": "අඳුරු මාදිලිය: ",
"preferences_dark_mode_label": "තේමාව: ",
"light": "ආලෝකමත්",
"generic_playlists_count": "{{count}} ධාවන ලැයිස්තුව",
"generic_playlists_count_plural": "ධාවන ලැයිස්තු {{count}}",
"LIVE": "සජීව",
"Subscribe": "දායක වන්න",
"View channel on YouTube": "YouTube හි නාලිකාව බලන්න",
"Next page": "ඊළඟ පිටුව",
"Previous page": "පෙර පිටුව",
"Clear watch history?": "නැරඹුම් ඉතිහාසය මකාදමනවා ද?",
"No": "නැත",
"Log in": "පුරන්න",
"New password": "නව මුරපදය",
"Import YouTube subscriptions": "YouTube/OPML දායකත්වයන් ආයාත කරන්න",
"Register": "ලියාපදිංචිවන්න",
"New passwords must match": "නව මුරපද ගැලපිය යුතුය",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "OPML ලෙස දායකත්වයන් අපනයනය කරන්න (NewPipe සහ FreeTube සඳහා)",
"Export subscriptions as OPML": "දායකත්වයන් OPML ලෙස අපනයනය කරන්න",
"JavaScript license information": "JavaScript බලපත්‍ර තොරතුරු",
"User ID": "පරිශීලක කේතය",
"Text CAPTCHA": "CAPTCHA පෙල",
"Image CAPTCHA": "CAPTCHA රූපය",
"Google verification code": "Google සත්‍යාපන කේතය",
"E-mail": "විද්‍යුත් තැපෑල",
"preferences_quality_label": "කැමති වීඩියෝ ගුණත්වය: ",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_dash_option_auto": "ස්වයංක්‍රීය",
"preferences_quality_option_small": "කුඩා",
"preferences_quality_dash_option_best": "උසස්",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_720p": "720p",
"preferences_quality_dash_option_240p": "240p",
"preferences_extend_desc_label": "වීඩියෝ විස්තරය ස්වයංක්‍රීයව දිගහරින්න: ",
"preferences_category_visual": "දෘශ්‍ය මනාපයන්",
"dark": "අඳුරු",
"preferences_category_misc": "විවිධ මනාප",
"preferences_category_subscription": "දායකත්ව මනාප",
"Redirect homepage to feed: ": "මුල් පිටුව පෝෂණය වෙත හරවා යවන්න: ",
"preferences_max_results_label": "සංග්‍රහයේ පෙන්වන වීඩියෝ ගණන: ",
"preferences_sort_label": "වීඩියෝ වර්ග කරන්න: ",
"alphabetically": "අකාරාදී ලෙස",
"alphabetically - reverse": "අකාරාදී - ආපසු",
"channel name": "නාලිකාවේ නම",
"Only show latest video from channel: ": "නාලිකාවේ නවතම වීඩියෝව පමණක් පෙන්වන්න: ",
"preferences_unseen_only_label": "නොබැලූ පමණක් පෙන්වන්න: ",
"Enable web notifications": "වෙබ් දැනුම්දීම් සබල කරන්න",
"Import/export data": "දත්ත ආනයනය / අපනයනය",
"Change password": "මුරපදය වෙනස් කරන්න",
"Manage subscriptions": "දායකත්ව කළමනාකරණය",
"Manage tokens": "ටෝකන කළමනාකරණය",
"Watch history": "නැරඹුම් ඉතිහාසය",
"Save preferences": "මනාප සුරකින්න",
"Token": "ටෝකනය",
"View privacy policy.": "රහස්‍යතා ප්‍රතිපත්තිය බලන්න.",
"Only show latest unwatched video from channel: ": "නාලිකාවේ නවතම නැරඹන නොලද වීඩියෝව පමණක් පෙන්වන්න: ",
"preferences_category_data": "දත්ත මනාප",
"Clear watch history": "නැරඹුම් ඉතිහාසය මකාදැමීම",
"Subscriptions": "දායකත්ව"
}

View File

@ -18,15 +18,15 @@
"No": "Nie",
"Import and Export Data": "Import a Export údajov",
"Import": "Import",
"Import Invidious data": "Importovať údaje Invidious",
"Import YouTube subscriptions": "Importovať odbery YouTube",
"Import Invidious data": "Importovať JSON údaje Invidious",
"Import YouTube subscriptions": "Importovať odbery YouTube/OPML",
"Import FreeTube subscriptions (.db)": "Importovať odbery FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Importovať odbery NewPipe (.json)",
"Import NewPipe data (.zip)": "Importovať údaje NewPipe (.zip)",
"Export": "Export",
"Export subscriptions as OPML": "Exportovať odbery ako OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportovať odbery ako OPML (pre NewPipe a FreeTube)",
"Export data as JSON": "Export údajov ako JSON",
"Export data as JSON": "Exportovať údaje Invidious ako JSON",
"Delete account?": "Zrušiť účet?",
"History": "História",
"An alternative front-end to YouTube": "Alternatívny front-end pre YouTube",
@ -84,5 +84,23 @@
"preferences_unseen_only_label": "Zobraziť iba neprehrané: ",
"preferences_notifications_only_label": "Zobraziť iba upozornenia (ak existujú): ",
"Enable web notifications": "Povoliť webové upozornenia",
"`x` uploaded a video": "`x` nahral(a) video"
"`x` uploaded a video": "`x` nahral(a) video",
"generic_views_count_0": "{{count}} zhliadnutie",
"generic_views_count_1": "{{count}} zhliadnutia",
"generic_views_count_2": "{{count}} zhliadnutí",
"generic_subscribers_count_0": "{{count}} odberateľ",
"generic_subscribers_count_1": "{{count}} odberatelia",
"generic_subscribers_count_2": "{{count}} odberateľov",
"Shared `x` ago": "Zverejnené pred `x`",
"generic_playlists_count_0": "{{count}} playlist",
"generic_playlists_count_1": "{{count}} playlisty",
"generic_playlists_count_2": "{{count}} playlistov",
"generic_videos_count_0": "{{count}} video",
"generic_videos_count_1": "{{count}} videá",
"generic_videos_count_2": "{{count}} videí",
"generic_subscriptions_count_0": "{{count}} odber",
"generic_subscriptions_count_1": "{{count}} odbery",
"generic_subscriptions_count_2": "{{count}} odberov",
"Authorize token for `x`?": "Autorizovať token pre `x`?",
"View playlist on YouTube": "Zobraziť playlist na YouTube"
}

507
locales/sl.json Normal file
View File

@ -0,0 +1,507 @@
{
"No": "Ne",
"Subscribe": "Naroči se",
"View playlist on YouTube": "Ogled seznama predvajanja v YouTubu",
"last": "zadnji",
"Next page": "Naslednja stran",
"Previous page": "Prejšnja stran",
"Clear watch history?": "Izbrisati zgodovino ogledov?",
"New password": "Novo geslo",
"New passwords must match": "Nova gesla se morajo ujemati",
"Cannot change password for Google accounts": "Ni mogoče spremeniti gesla za račune Google",
"Authorize token?": "Naj odobrim žeton?",
"Yes": "Da",
"Import and Export Data": "Uvoz in izvoz podatkov",
"Import": "Uvozi",
"Import Invidious data": "Uvozi Invidious JSON podatke",
"Import YouTube subscriptions": "Uvozi YouTube/OPML naročnine",
"Import FreeTube subscriptions (.db)": "Uvozi FreeTube (.db) naročnine",
"Import NewPipe data (.zip)": "Uvozi NewPipe (.zip) podatke",
"Export": "Izvozi",
"Export subscriptions as OPML": "Izvozi naročnine kot OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Izvozi naročnine kot OPML (za NewPipe in FreeTube)",
"Log in": "Prijava",
"Log in/register": "Prijava/registracija",
"Log in with Google": "Prijavi se z Googlom",
"User ID": "ID uporabnika",
"Password": "Geslo",
"Time (h:mm:ss):": "Čas (h:mm:ss):",
"Text CAPTCHA": "Besedilo CAPTCHA",
"source": "izvorna koda",
"Image CAPTCHA": "Slika CAPTCHA",
"Sign In": "Prijavi se",
"Register": "Registriraj se",
"E-mail": "E-pošta",
"Google verification code": "Googlova koda za preverjanje",
"Preferences": "Nastavitve",
"preferences_video_loop_label": "Vedno v zanki: ",
"preferences_autoplay_label": "Samodejno predvajanje: ",
"preferences_continue_autoplay_label": "Samodejno predvajanje naslednjega videoposnetka: ",
"preferences_listen_label": "Privzeto poslušaj: ",
"preferences_local_label": "Proxy za videoposnetke: ",
"preferences_speed_label": "Privzeta hitrost: ",
"preferences_quality_label": "Prednostna kakovost videoposnetka: ",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_dash_option_best": "najboljša",
"preferences_quality_dash_option_4320p": "4320p",
"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_volume_label": "Glasnost predvajalnika: ",
"reddit": "Reddit",
"preferences_player_style_label": "Slog predvajalnika: ",
"dark": "temna",
"light": "svetla",
"preferences_thin_mode_label": "Tanki način: ",
"preferences_automatic_instance_redirect_label": "Samodejna preusmeritev (na redirect.invidious.io): ",
"preferences_annotations_subscribed_label": "Privzeto prikazati opombe za naročene kanale? ",
"Redirect homepage to feed: ": "Preusmeri domačo stran na vir: ",
"preferences_max_results_label": "Število videoposnetkov, prikazanih v viru: ",
"preferences_sort_label": "Razvrsti videoposnetke po: ",
"published": "datumu objave",
"published - reverse": "datumu objave - obratno",
"alphabetically": "abecednem vrstnem redu",
"alphabetically - reverse": "po abecednem vrstnem redu - obratno",
"channel name": "imenu kanala",
"channel name - reverse": "imenu kanala - obratno",
"Only show latest video from channel: ": "Pokaži samo najnovejši videoposnetek iz kanala: ",
"Only show latest unwatched video from channel: ": "Pokaži samo najnovejši še neogledani videoposnetek iz kanala: ",
"preferences_unseen_only_label": "Pokaži samo neogledane: ",
"preferences_notifications_only_label": "Pokaži samo obvestila (če obstajajo): ",
"preferences_category_data": "Nastavitve podatkov",
"Clear watch history": "Počisti zgodovino ogledov",
"Import/export data": "Uvoz/izvoz podatkov",
"Change password": "Spremeni geslo",
"Watch history": "Oglej si zgodovino",
"Delete account": "Izbriši račun",
"preferences_category_admin": "Skrbniške nastavitve",
"preferences_default_home_label": "Privzeta domača stran: ",
"preferences_feed_menu_label": "Meni vira: ",
"Top enabled: ": "Vrh omogočen: ",
"CAPTCHA enabled: ": "CAPTCHA omogočeni: ",
"Login enabled: ": "Prijava je omogočena: ",
"Registration enabled: ": "Registracija je omogočena: ",
"Token manager": "Upravitelj žetonov",
"Token": "Žeton",
"tokens_count_0": "{{count}} žeton",
"tokens_count_1": "{{count}} žetona",
"tokens_count_2": "{{count}} žetoni",
"tokens_count_3": "{{count}} žetonov",
"Import/export": "Uvoz/izvoz",
"unsubscribe": "odjava",
"revoke": "prekliči",
"search": "iskanje",
"Log out": "Odjava",
"Released under the AGPLv3 on Github.": "Objavljeno pod licenco AGPLv3 na GitHubu.",
"Trending": "Trendi",
"Private": "Zasebno",
"View all playlists": "Oglej si vse sezname predvajanja",
"Updated `x` ago": "Posodobljeno pred `x`",
"Delete playlist `x`?": "Brisanje seznama predvajanja `x`?",
"Delete playlist": "Izbriši seznam predvajanja",
"Title": "Naslov",
"Playlist privacy": "Zasebnost seznama predvajanja",
"Editing playlist `x`": "Urejanje seznama predvajanja `x`",
"Show more": "Pokaži več",
"Switch Invidious Instance": "Preklopi Invidious instanco",
"search_message_change_filters_or_query": "Poskusi razširiti iskalno poizvedbo in/ali spremeniti filtre.",
"search_message_use_another_instance": " Lahko tudi <a href=\"`x`\">iščeš v drugi istanci</a>.",
"Wilson score: ": "Wilsonov rezultat: ",
"Engagement: ": "Sodelovanje: ",
"Blacklisted regions: ": "Regije na seznamu nedovoljenih: ",
"Shared `x`": "V skupni rabi od: `x`",
"Premieres `x`": "Premiere `x`",
"View YouTube comments": "Oglej si YouTube komentarje",
"View more comments on Reddit": "Prikaži več komentarjev na Reddit",
"View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "Poglej `x` komentar",
"": "Poglej `x` komentarjev"
},
"Quota exceeded, try again in a few hours": "Kvota je presežena, poskusi znova čez nekaj ur",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Ne morem se prijaviti, preveri, ali je vklopljeno dvofaktorsko preverjanje pristnosti (avtentikator ali SMS).",
"Please sign in using 'Log in with Google'": "Prijavi se z uporabo »Prijava z Googlom«",
"Password cannot be empty": "Geslo ne sme biti prazno",
"`x` ago": "`x` nazaj",
"Load more": "Naloži več",
"comments_points_count_0": "{{count}} točka",
"comments_points_count_1": "{{count}} točki",
"comments_points_count_2": "{{count}} točke",
"comments_points_count_3": "{{count}} točk",
"Hidden field \"token\" is a required field": "Skrito polje »žeton« je zahtevano polje",
"Erroneous challenge": "Napačen izziv",
"English": "angleščina",
"English (United States)": "angleščina (Združene države)",
"Albanian": "albanščina",
"Amharic": "amharščina",
"Azerbaijani": "azerbajdžanščina",
"Bangla": "bengalščina",
"Belarusian": "beloruščina",
"Burmese": "birmanščina",
"Cebuano": "cebuanščina",
"Chinese (Hong Kong)": "kitajščina (Hongkong)",
"Chinese (Simplified)": "kitajščina (poenostavljena)",
"Chinese (Taiwan)": "kitajščina (Tajvan)",
"Corsican": "korzijščina",
"Croatian": "hrvaščina",
"Danish": "danščina",
"Dutch": "nizozemščina",
"Estonian": "estonščina",
"Filipino": "filipinščina",
"Finnish": "finščina",
"French": "francoščina",
"French (auto-generated)": "francoščina (samodejno ustvarjeno)",
"Georgian": "gruzinščina",
"German": "nemščina",
"Greek": "grščina",
"Gujarati": "gudžaratščina",
"Haitian Creole": "haitijska kreolščina",
"Hausa": "havščina",
"Hawaiian": "havajščina",
"Hmong": "hmonščina",
"Hungarian": "madžarščina",
"Icelandic": "islandščina",
"Igbo": "igbo",
"Interlingue": "interlingua",
"Italian (auto-generated)": "italijanščina (samodejno ustvarjeno)",
"Japanese": "japonščina",
"Japanese (auto-generated)": "japonščina (samodejno ustvarjeno)",
"Khmer": "kmerščina",
"Korean": "korejščina",
"Korean (auto-generated)": "korejščina (samodejno ustvarjeno)",
"Kurdish": "kurdščina",
"Kannada": "kanadejščina",
"Latvian": "latvijščina",
"Lithuanian": "litovščina",
"Luxembourgish": "luksemburščina",
"Macedonian": "makedonščina",
"Malagasy": "malgaščina",
"Malay": "malajščina",
"Nepali": "nepalščina",
"Norwegian Bokmål": "norveščina bokmal",
"Nyanja": "njanščina",
"Punjabi": "pandžabščina",
"Romanian": "romunščina",
"Russian": "ruščina",
"Samoan": "samoanščina",
"Scottish Gaelic": "škotska galščina",
"Shona": "šonaščina",
"Sundanese": "sudanščina",
"Thai": "tajščina",
"Turkish": "turščina",
"Turkish (auto-generated)": "turščina (samodejno ustvarjeno)",
"Ukrainian": "ukrajinščina",
"Urdu": "urdujščina",
"Telugu": "telugu",
"Vietnamese": "vietnamščina",
"Welsh": "valižanščina",
"Western Frisian": "zahodnofrizijščina",
"Yiddish": "jidiš",
"Yoruba": "joruba",
"Xhosa": "xhosa",
"generic_count_years_0": "{{count}} letom",
"generic_count_years_1": "{{count}} leti",
"generic_count_years_2": "{{count}} leti",
"generic_count_years_3": "{{count}} leti",
"generic_count_days_0": "{{count}} dnevom",
"generic_count_days_1": "{{count}} dnevi",
"generic_count_days_2": "{{count}} dnevi",
"generic_count_days_3": "{{count}} dnevi",
"generic_count_hours_0": "{{count}} uro",
"generic_count_hours_1": "{{count}} urami",
"generic_count_hours_2": "{{count}} urami",
"generic_count_hours_3": "{{count}} urami",
"generic_count_minutes_0": "{{count}} minuto",
"generic_count_minutes_1": "{{count}} minutami",
"generic_count_minutes_2": "{{count}} minutami",
"generic_count_minutes_3": "{{count}} minutami",
"Search": "Iskanje",
"Top": "Vrh",
"About": "O aplikaciji",
"%A %B %-d, %Y": "%A %-d %B %Y",
"Audio mode": "Avdio način",
"Videos": "Videoposnetki",
"search_filters_date_label": "Datum nalaganja",
"search_filters_date_option_today": "Danes",
"search_filters_date_option_week": "Ta teden",
"search_filters_type_label": "Vrsta",
"search_filters_type_option_all": "Katerakoli vrsta",
"search_filters_type_option_playlist": "Seznami predvajanja",
"search_filters_features_option_subtitles": "Podnapisi/CC",
"search_filters_features_option_location": "Lokacija",
"footer_donate_page": "Prispevaj",
"footer_documentation": "Dokumentacija",
"footer_original_source_code": "Izvirna izvorna koda",
"none": "ni",
"videoinfo_started_streaming_x_ago": "Začetek pretakanja `x` nazaj",
"videoinfo_watch_on_youTube": "Oglej si v YouTubu",
"user_saved_playlists": "`x` shranjenih seznamov predvajanja",
"Video unavailable": "Video ni na voljo",
"preferences_save_player_pos_label": "Shrani položaj predvajanja: ",
"crash_page_you_found_a_bug": "Videti je, da si v Invidiousu našel hrošča!",
"crash_page_read_the_faq": "prebral/a <a href=\"`x`\">Pogosto zastavljena vprašanja (FAQ)</a>",
"generic_videos_count_0": "{{count}} video",
"generic_videos_count_1": "{{count}} videa",
"generic_videos_count_2": "{{count}} videi",
"generic_videos_count_3": "{{count}} videov",
"generic_views_count_0": "{{count}} ogled",
"generic_views_count_1": "{{count}} ogleda",
"generic_views_count_2": "{{count}} ogledi",
"generic_views_count_3": "{{count}} ogledov",
"generic_playlists_count_0": "{{count}} seznam predvajanja",
"generic_playlists_count_1": "{{count}} seznama predvajanja",
"generic_playlists_count_2": "{{count}} seznami predvajanja",
"generic_playlists_count_3": "{{count}} seznamov predvajanja",
"generic_subscribers_count_0": "{{count}} naročnik",
"generic_subscribers_count_1": "{{count}} naročnika",
"generic_subscribers_count_2": "{{count}} naročniki",
"generic_subscribers_count_3": "{{count}} naročnikov",
"generic_subscriptions_count_0": "{{count}} naročnina",
"generic_subscriptions_count_1": "{{count}} naročnini",
"generic_subscriptions_count_2": "{{count}} naročnine",
"generic_subscriptions_count_3": "{{count}} naročnin",
"LIVE": "V ŽIVO",
"Shared `x` ago": "Deljeno pred `x`",
"View channel on YouTube": "Ogled kanala v YouTubu",
"newest": "najnovejši",
"Unsubscribe": "Odjavi se",
"Authorize token for `x`?": "Odobriti žeton za `x`?",
"Import NewPipe subscriptions (.json)": "Uvozi NewPipe (.json) naročnine",
"History": "Zgodovina",
"JavaScript license information": "Podatki o licenci JavaScript",
"oldest": "najstarejši",
"popular": "priljubljen",
"Export data as JSON": "Izvozi Invidious podatke kot JSON",
"Delete account?": "Izbrisati račun?",
"An alternative front-end to YouTube": "Alternativni vmesnik za YouTube",
"preferences_category_player": "Nastavitve predvajalnika",
"preferences_continue_label": "Privzeto predvajaj naslednjega: ",
"preferences_watch_history_label": "Omogoči zgodovino ogledov: ",
"preferences_quality_option_medium": "srednja",
"preferences_quality_option_dash": "DASH (prilagodljiva kakovost)",
"preferences_quality_option_small": "majhna",
"preferences_quality_dash_option_worst": "najslabša",
"preferences_quality_dash_label": "Prednostna kakovost videoposnetkov DASH: ",
"preferences_comments_label": "Privzeti komentarji: ",
"preferences_quality_dash_option_auto": "samodejna",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_quality_dash_option_144p": "144p",
"youtube": "YouTube",
"invidious": "Invidious",
"preferences_vr_mode_label": "Interaktivni videoposnetki na 360 stopinj (zahteva WebGL): ",
"preferences_captions_label": "Privzeti napisi: ",
"Fallback captions: ": "Pomožni napisi: ",
"preferences_extend_desc_label": "Samodejno razširi opis videoposnetka: ",
"preferences_related_videos_label": "Prikaži povezane videoposnetke: ",
"preferences_annotations_label": "Privzeto prikaži opombe: ",
"preferences_category_visual": "Vizualne nastavitve",
"preferences_region_label": "Država vsebine: ",
"Dark mode: ": "Temni način: ",
"preferences_dark_mode_label": "Tema: ",
"preferences_category_misc": "Različne nastavitve",
"preferences_category_subscription": "Nastavitve naročnine",
"Unlisted": "Nerazporejeno",
"Enable web notifications": "Omogoči spletna obvestila",
"`x` is live": "`x` je v živo",
"Manage subscriptions": "Upravljaj naročnine",
"Manage tokens": "Upravljaj žetone",
"Subscription manager": "Upravitelj naročnin",
"`x` uploaded a video": "`x` je naložil/a videoposnetek",
"preferences_show_nick_label": "Prikaži vzdevek na vrhu: ",
"search_message_no_results": "Ni zadetkov.",
"Save preferences": "Shrani nastavitve",
"Subscriptions": "Naročnine",
"Report statistics: ": "Poročilo o statistiki: ",
"subscriptions_unseen_notifs_count_0": "{{count}} neogledano obvestilo",
"subscriptions_unseen_notifs_count_1": "{{count}} neogledani obvestili",
"subscriptions_unseen_notifs_count_2": "{{count}} neogledana obvestila",
"subscriptions_unseen_notifs_count_3": "{{count}} neogledanih obvestil",
"View JavaScript license information.": "Oglej si informacije o licenci za JavaScript.",
"Show less": "Pokaži manj",
"Watch on YouTube": "Oglej si v YouTubu",
"Source available here.": "Izvorna koda na voljo tukaj.",
"License: ": "Licenca: ",
"View privacy policy.": "Oglej si pravilnik o zasebnosti.",
"Public": "Javno",
"Create playlist": "Ustvari seznam predvajanja",
"Hide annotations": "Skrij opombe",
"Show annotations": "Pokaži opombe",
"Genre: ": "Žanr: ",
"Family friendly? ": "Družinam prijazno? ",
"Whitelisted regions: ": "Regije na seznamu dovoljenih: ",
"Premieres in `x`": "Premiere v `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.": "Živjo! Izgleda, da imaš izklopljene JavaScripte . Klikni tukaj, če si želiš ogledati komentarje, vendar vedi, da bo lahko nalaganje trajajo nekoliko dlje.",
"Show replies": "Pokaži odgovore",
"Erroneous CAPTCHA": "Napačna CAPTCHA",
"User ID is a required field": "ID uporabnika je obvezno polje",
"Password is a required field": "Geslo je obvezno polje",
"Wrong username or password": "Napačno uporabniško ime ali geslo",
"Password cannot be longer than 55 characters": "Geslo ne sme biti daljše od 55 znakov",
"channel:`x`": "kanal: `x`",
"Could not fetch comments": "Ni bilo mogoče pridobiti komentarjev",
"Could not pull trending pages.": "Ni bilo mogoče povleči trendovskih strani.",
"Please log in": "Prosim, prijavi se",
"Playlist does not exist.": "Seznam predvajanja ne obstaja.",
"Incorrect password": "Napačno geslo",
"View Reddit comments": "Oglej si komentarje na Redditu",
"This channel does not exist.": "Ta kanal ne obstaja.",
"Hide replies": "Skrij odgovore",
"Invalid TFA code": "Neveljavna koda TFA",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Prijava ni uspela. To je lahko zato, ker za tvoj račun ni vklopljeno dvofaktorsko preverjanje pristnosti.",
"Invidious Private Feed for `x`": "Invidious zasebni vir za `x`",
"Deleted or invalid channel": "Izbrisan ali neveljaven kanal",
"Empty playlist": "Prazen seznam predvajanja",
"No such user": "Ni tega uporabnika",
"Token is expired, please try again": "Žeton je potekel, poskusi znova",
"English (United Kingdom)": "angleščina (Združeno kraljestvo)",
"Wrong answer": "Napačen odgovor",
"CAPTCHA is a required field": "CAPTCHA je obvezno polje",
"Could not get channel info.": "Ni bilo mogoče dobiti informacij o kanalu.",
"comments_view_x_replies_0": "Poglej {{count}} odgovor",
"comments_view_x_replies_1": "Poglej {{count}} odgovora",
"comments_view_x_replies_2": "Poglej {{count}} odgovore",
"comments_view_x_replies_3": "Poglej {{count}} odgovorov",
"Could not create mix.": "Ni bilo mogoče ustvariti mixa.",
"Not a playlist.": "Ni seznam predvajanja.",
"Hidden field \"challenge\" is a required field": "Skrito polje »izziv« je obvezno polje",
"Erroneous token": "Napačen žeton",
"Afrikaans": "afrikanščina",
"Arabic": "arabščina",
"Armenian": "armenščina",
"English (auto-generated)": "angleščina (samodejno ustvarjeno)",
"Bulgarian": "bolgarščina",
"Catalan": "katalonščina",
"Cantonese (Hong Kong)": "kantonščina (Hongkong)",
"Chinese (Traditional)": "kitajščina (tradicionalna)",
"Basque": "baskovščina",
"Czech": "češčina",
"Bosnian": "bosanščina",
"Chinese": "kitajščina",
"Chinese (China)": "kitajščina (Kitajska)",
"Dutch (auto-generated)": "nizozemščina (samodejno ustvarjeno)",
"Esperanto": "esperanto",
"Galician": "galicijščina",
"German (auto-generated)": "nemščina (samodejno ustvarjeno)",
"Hebrew": "hebrejščina",
"Malayalam": "malajalamščina",
"Hindi": "hindijščina",
"Indonesian": "indonezijščina",
"Kazakh": "kazahstanščina",
"Indonesian (auto-generated)": "indonezijščina (samodejno generirano)",
"Irish": "irščina",
"Persian": "perzijščina",
"Slovak": "slovaščina",
"Italian": "italijanščina",
"Maori": "maorščina",
"Portuguese": "portugalščina",
"Javanese": "javanščina",
"Kyrgyz": "kirgiščina",
"Lao": "laoščina",
"Latin": "latinščina",
"Mongolian": "mongolščina",
"Portuguese (auto-generated)": "portugalščina (samodejno ustvarjeno)",
"Sindhi": "sindščina",
"Maltese": "malteščina",
"Marathi": "maratščina",
"Pashto": "paštu",
"Polish": "poljščina",
"Portuguese (Brazil)": "portugalščina (Brazilija)",
"Fallback comments: ": "Nadomestni komentarji: ",
"Gaming": "Igralništvo",
"Russian (auto-generated)": "ruščina (samodejno ustvarjeno)",
"Serbian": "srbščina",
"Sinhala": "singalščina",
"Slovenian": "slovenščina",
"Somali": "somalijščina",
"Spanish": "španščina",
"Southern Sotho": "južni sotho",
"Spanish (auto-generated)": "španščina (samodejno ustvarjeno)",
"Spanish (Mexico)": "španščina (Mehika)",
"Spanish (Latin America)": "španščina (Latinska Amerika)",
"Spanish (Spain)": "španščina (Španija)",
"Tajik": "tadžiščina",
"Tamil": "tamilščina",
"generic_count_weeks_0": "{{count}} tednom",
"generic_count_weeks_1": "{{count}} tedni",
"generic_count_weeks_2": "{{count}} tedni",
"generic_count_weeks_3": "{{count}} tedni",
"Swahili": "svahilščina",
"Swedish": "švedščina",
"Vietnamese (auto-generated)": "vietnamščina (samodejno ustvarjeno)",
"generic_count_months_0": "{{count}} mesecem",
"generic_count_months_1": "{{count}} meseci",
"generic_count_months_2": "{{count}} meseci",
"generic_count_months_3": "{{count}} meseci",
"Uzbek": "uzbeščina",
"Zulu": "zulujščina",
"generic_count_seconds_0": "{{count}} sekundo",
"generic_count_seconds_1": "{{count}} sekundami",
"generic_count_seconds_2": "{{count}} sekundami",
"generic_count_seconds_3": "{{count}} sekundami",
"Popular": "Priljubljeni",
"Music": "Glasba",
"Movies": "Filmi",
"YouTube comment permalink": "Stalna povezava za komentar na YouTubu",
"search_filters_title": "Filtri",
"preferences_locale_label": "Jezik: ",
"Rating: ": "Ocena: ",
"Default": "Privzeto",
"News": "Novice",
"Download as: ": "Prenesi kot: ",
"(edited)": "(urejeno)",
"View as playlist": "Poglej kot seznam predvajanja",
"Download": "Prenesi",
"permalink": "stalna povezava",
"`x` marked it with a ❤": "`x` ga je označil/a z ❤",
"Community": "Skupnost",
"search_filters_features_option_three_sixty": "360°",
"Video mode": "Video način",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"Playlists": "Seznami predvajanja",
"search_filters_date_option_none": "Katerikoli datum",
"search_filters_date_option_month": "Ta mesec",
"search_filters_date_option_year": "Letos",
"search_filters_type_option_movie": "Film",
"search_filters_duration_option_long": "Dolg (> 20 minut)",
"search_filters_features_label": "Lastnosti",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_hdr": "HDR",
"next_steps_error_message_refresh": "Osveži",
"search_filters_date_option_hour": "Zadnja ura",
"search_filters_features_option_purchased": "Kupljeno",
"search_filters_sort_label": "Razvrsti po",
"search_filters_sort_option_views": "številu ogledov",
"Current version: ": "Trenutna različica: ",
"search_filters_features_option_live": "V živo",
"search_filters_features_option_hd": "HD",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_show": "Pokaži",
"search_filters_duration_label": "Trajanje",
"search_filters_duration_option_none": "Poljubno trajanje",
"search_filters_duration_option_short": "Kratek (< 4 minute)",
"search_filters_duration_option_medium": "Srednji (4 - 20 minut)",
"search_filters_features_option_vr180": "VR180",
"search_filters_sort_option_date": "datumu nalaganja",
"search_filters_type_option_video": "Videoposnetek",
"search_filters_sort_option_relevance": "ustreznosti",
"search_filters_sort_option_rating": "oceni",
"search_filters_apply_button": "Uporabi izbrane filtre",
"next_steps_error_message": "Po tem moraš poskusiti: ",
"next_steps_error_message_go_to_youtube": "Pojdi na YouTube",
"footer_source_code": "Izvorna koda",
"footer_modfied_source_code": "Spremenjena izvorna koda",
"user_created_playlists": "`x` ustvarjenih seznamov predvajanja",
"adminprefs_modified_source_code_url_label": "URL do shrambe spremenjene izvorne kode",
"videoinfo_youTube_embed_link": "Vdelati",
"videoinfo_invidious_embed_link": "Povezava za vdelavo",
"crash_page_switch_instance": "poskušal/a <a href=\"`x`\">uporabiti drugo instanco</a>",
"download_subtitles": "Podnapisi - `x` (.vtt)",
"crash_page_refresh": "poskušal/a <a href=\"`x`\">osvežiti stran</a>",
"crash_page_before_reporting": "Preden prijaviš napako, se prepričaj, da si:",
"crash_page_search_issue": "preiskal/a <a href=\"`x`\">obstoječe težave na GitHubu</a>",
"crash_page_report_issue": "Če nič od navedenega ni pomagalo, prosim <a href=\"`x`\">odpri novo težavo v GitHubu</a> (po možnosti v angleščini) in v svoje sporočilo vključi naslednje besedilo (tega besedila NE prevajaj):",
"Popular enabled: ": "Priljubljeni omogočeni: "
}

View File

@ -26,11 +26,11 @@
"Tamil": "Tamilisht",
"Telugu": "Telugu",
"Vietnamese": "Vietnamisht",
"creative_commons": "Creative Commons",
"3d": "3D",
"live": "Drejtpërsëdrejti",
"4k": "4K",
"location": "Vendndodhja",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Drejtpërsëdrejti",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Vendndodhja",
"videoinfo_watch_on_youTube": "Shiheni në YouTube",
"videoinfo_youTube_embed_link": "Trupëzojeni",
"videoinfo_invidious_embed_link": "Lidhje Trupëzimi",
@ -127,7 +127,7 @@
"Subscriptions": "Pajtime",
"search": "kërko",
"Log out": "Dilni",
"Released under the AGPLv3 on Github.": "Hedhur në qarkullim në Github sipas licencës AGPLv3.",
"Released under the AGPLv3 on Github.": "Hedhur në qarkullim në GitHub sipas licencës AGPLv3.",
"Source available here.": "Burimi i passhëm që këtu.",
"View JavaScript license information.": "Shihni hollësi licence JavaScript.",
"View privacy policy.": "Shihni rregulla privatësie.",
@ -147,7 +147,6 @@
"Show less": "Shfaq më pak",
"Watch on YouTube": "Shiheni në YouTube",
"Switch Invidious Instance": "Ndërroni Instancë Invidious",
"Broken? Try another Invidious Instance": "E prishur? Provoni një tjetër Instancë Invidious",
"Hide annotations": "Fshihi shënimet",
"Show annotations": "Shfaq shënime",
"License: ": "Licencë: ",
@ -261,32 +260,32 @@
"Audio mode": "Mënyrë për audion",
"Playlists": "Luajlista",
"Community": "Bashkësi",
"relevance": "Rëndësi",
"search_filters_sort_option_relevance": "Rëndësi",
"Video mode": "Mënyrë video",
"Videos": "Video",
"rating": "Vlerësim",
"date": "Datë ngarkimi",
"views": "Numër parjesh",
"content_type": "Lloj",
"duration": "Kohëzgjatje",
"features": "Veçori",
"sort": "Renditi Sipas",
"hour": "Orën e Fundit",
"today": "Sot",
"long": "E gjatë (> 20 minuta)",
"hd": "HD",
"subtitles": "Titra/CC",
"hdr": "HDR",
"week": "Këtë javë",
"month": "Këtë muaj",
"year": "Këtë vit",
"video": "Video",
"channel": "Kanal",
"playlist": "Luajlistë",
"movie": "Film",
"show": "Shfaqe",
"short": "E shkurtër (< 4 minuta)",
"purchased": "Të blera",
"search_filters_sort_option_rating": "Vlerësim",
"search_filters_sort_option_date": "Datë ngarkimi",
"search_filters_sort_option_views": "Numër parjesh",
"search_filters_type_label": "Lloj",
"search_filters_duration_label": "Kohëzgjatje",
"search_filters_features_label": "Veçori",
"search_filters_sort_label": "Renditi Sipas",
"search_filters_date_option_hour": "Orën e Fundit",
"search_filters_date_option_today": "Sot",
"search_filters_duration_option_long": "E gjatë (> 20 minuta)",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Titra/CC",
"search_filters_features_option_hdr": "HDR",
"search_filters_date_option_week": "Këtë javë",
"search_filters_date_option_month": "Këtë muaj",
"search_filters_date_option_year": "Këtë vit",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Luajlistë",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Shfaqe",
"search_filters_duration_option_short": "E shkurtër (< 4 minuta)",
"search_filters_features_option_purchased": "Të blera",
"footer_modfied_source_code": "Kod Burim i ndryshuar",
"adminprefs_modified_source_code_url_label": "URL e depos së ndryshuar të kodit burim",
"none": "asnjë",
@ -370,8 +369,7 @@
"Mongolian": "Mongolisht",
"Nepali": "Nepaleze",
"Norwegian Bokmål": "Norvegjishte Bokmål",
"360": "360°",
"filter": "Filtroji",
"search_filters_features_option_three_sixty": "360°",
"Current version: ": "Versioni i tanishëm: ",
"next_steps_error_message": "Pas të cilës duhet të provoni të: ",
"next_steps_error_message_refresh": "Rifreskoje",
@ -437,7 +435,7 @@
"Spanish (Spain)": "Spanjisht (Spanjë)",
"Turkish (auto-generated)": "Turqisht (të prodhuara automatikisht)",
"Vietnamese (auto-generated)": "Vietnamisht (të prodhuara automatikisht)",
"crash_page_search_issue": "kërkuar për <a href=\"`x`\">çështje ekzistuese në Github</a>",
"crash_page_search_issue": "kërkuar për <a href=\"`x`\">çështje ekzistuese në GitHub</a>",
"crash_page_report_issue": "Nëse asnjë nga sa më sipër sndihmoi, ju lutemi, <a href=\"`x`\">hapni një çështje në GitHub</a> (mundësisht në anglisht) dhe përfshini në mesazhin tuaj tekstin vijues (MOS e përktheni këtë tekst):",
"generic_subscriptions_count": "{{count}} pajtim",
"generic_subscriptions_count_plural": "{{count}} pajtime",
@ -448,5 +446,6 @@
"Import YouTube subscriptions": "Importoni pajtime YouTube/OPML",
"Export data as JSON": "Eksportoji të dhënat Invidious si JSON",
"preferences_vr_mode_label": "Video me ndërveprim 360 gradë (lyp WebGL): ",
"Shared `x`": "Ndau me të tjerë `x`"
"Shared `x`": "Ndau me të tjerë `x`",
"search_filters_title": "Filtra"
}

View File

@ -131,26 +131,25 @@
"YouTube comment permalink": "YouTube komentar trajna veza",
"Audio mode": "Audio mod",
"Playlists": "Plej liste",
"relevance": "Relevantnost",
"rating": "Ocene",
"date": "Datum otpremanja",
"views": "Broj pregleda",
"search_filters_sort_option_relevance": "Relevantnost",
"search_filters_sort_option_rating": "Ocene",
"search_filters_sort_option_date": "Datum otpremanja",
"search_filters_sort_option_views": "Broj pregleda",
"`x` marked it with a ❤": "`x` je označio/la ovo sa ❤",
"duration": "Trajanje",
"features": "Karakteristike",
"hour": "Poslednji sat",
"week": "Ove sedmice",
"month": "Ovaj mesec",
"year": "Ove godine",
"video": "Video",
"playlist": "Plej lista",
"movie": "Film",
"long": "Dugo (> 20 minuta)",
"hd": "HD",
"creative_commons": "Creative Commons (Licenca)",
"3d": "3D",
"hdr": "Video Visoke Rezolucije",
"filter": "Filter",
"search_filters_duration_label": "Trajanje",
"search_filters_features_label": "Karakteristike",
"search_filters_date_option_hour": "Poslednji sat",
"search_filters_date_option_week": "Ove sedmice",
"search_filters_date_option_month": "Ovaj mesec",
"search_filters_date_option_year": "Ove godine",
"search_filters_type_option_video": "Video",
"search_filters_type_option_playlist": "Plej lista",
"search_filters_type_option_movie": "Film",
"search_filters_duration_option_long": "Dugo (> 20 minuta)",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_c_commons": "Creative Commons (Licenca)",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_hdr": "Video Visoke Rezolucije",
"next_steps_error_message": "Nakon čega bi trebali probati: ",
"next_steps_error_message_go_to_youtube": "Idi na YouTube",
"footer_documentation": "Dokumentacija",
@ -225,13 +224,12 @@
"preferences_category_visual": "Vizuelne preference",
"preferences_captions_label": "Podrazumevani titl: ",
"Music": "Muzika",
"content_type": "Tip",
"Broken? Try another Invidious Instance": "Ne funkcioniše ispravno? Probajte drugu Invidious instancu",
"search_filters_type_label": "Tip",
"Tamil": "Tamilski",
"Save preferences": "Sačuvaj podešavanja",
"Only show latest unwatched video from channel: ": "Prikaži samo poslednje video klipove koji nisu pogledani sa kanala: ",
"Xhosa": "Kosa (Jezik)",
"channel": "Kanal",
"search_filters_type_option_channel": "Kanal",
"Hungarian": "Mađarski",
"Maori": "Maori (Jezik)",
"Manage subscriptions": "Upravljaj zapisima",
@ -243,7 +241,7 @@
"preferences_default_home_label": "Podrazumevana početna stranica: ",
"Serbian": "Srpski",
"License: ": "Licenca: ",
"live": "Uživo",
"search_filters_features_option_live": "Uživo",
"Report statistics: ": "Izveštavaj o statistici: ",
"Only show latest video from channel: ": "Prikazuj poslednje video klipove samo sa kanala: ",
"channel name - reverse": "ime kanala - obrnuto",
@ -266,14 +264,14 @@
"alphabetically": "po alfabetu",
"No such user": "Nepostojeći korisnik",
"Subscriptions": "Praćenja",
"today": "Danas",
"search_filters_date_option_today": "Danas",
"Finnish": "Finski",
"Lao": "Laoski",
"Login enabled: ": "Prijava omogućena: ",
"Shona": "Šona",
"location": "Lokacija",
"search_filters_features_option_location": "Lokacija",
"Load more": "Učitaj više",
"Released under the AGPLv3 on Github.": "Izbačeno pod licencom AGPLv3 na Github-u.",
"Released under the AGPLv3 on Github.": "Izbačeno pod licencom AGPLv3 na GitHub-u.",
"Slovenian": "Slovenački",
"View JavaScript license information.": "Pogledaj informacije licence vezane za JavaScript.",
"Chinese (Simplified)": "Kineski (Pojednostavljeni)",
@ -292,7 +290,7 @@
"Czech": "Češki",
"Latin": "Latinski",
"Videos": "Video klipovi",
"4k": "4К",
"search_filters_features_option_four_k": "4К",
"footer_donate_page": "Doniraj",
"English": "Engleski",
"Arabic": "Arapski",
@ -310,7 +308,7 @@
"Swahili": "Svahili",
"Yiddish": "Jidiš",
"Zulu": "Zulu",
"subtitles": "Titl/Prevod",
"search_filters_features_option_subtitles": "Titl/Prevod",
"Password cannot be longer than 55 characters": "Lozinka ne može biti duža od 55 karaktera",
"This channel does not exist.": "Ovaj kanal ne postoji.",
"Belarusian": "Beloruski",
@ -329,9 +327,9 @@
"Clear watch history": "Obriši istoriju gledanja",
"preferences_category_admin": "Administratorska podešavanja",
"published": "objavljeno",
"sort": "Poredaj prema",
"show": "Emisija",
"short": "Kratko (< 4 minute)",
"search_filters_sort_label": "Poredaj prema",
"search_filters_type_option_show": "Emisija",
"search_filters_duration_option_short": "Kratko (< 4 minute)",
"Current version: ": "Trenutna verzija: ",
"Top enabled: ": "Vrh omogućen: ",
"Public": "Javno",
@ -369,5 +367,6 @@
"unsubscribe": "prekini sa praćenjem",
"Blacklisted regions: ": "Zabranjene oblasti: ",
"Polish": "Poljski",
"Yoruba": "Joruba"
"Yoruba": "Joruba",
"search_filters_title": "Filter"
}

View File

@ -182,14 +182,13 @@
"Georgian": "Грузијски",
"Greek": "Грчки",
"Hausa": "Хауса",
"video": "Видео",
"playlist": "Плеј листа",
"movie": "Филм",
"long": "Дуго (> 20 минута)",
"creative_commons": "Creative Commons (Лиценца)",
"live": "Уживо",
"location": "Локација",
"filter": "Филтер",
"search_filters_type_option_video": "Видео",
"search_filters_type_option_playlist": "Плеј листа",
"search_filters_type_option_movie": "Филм",
"search_filters_duration_option_long": "Дуго (> 20 минута)",
"search_filters_features_option_c_commons": "Creative Commons (Лиценца)",
"search_filters_features_option_live": "Уживо",
"search_filters_features_option_location": "Локација",
"next_steps_error_message": "Након чега би требали пробати: ",
"footer_donate_page": "Донирај",
"footer_documentation": "Документација",
@ -247,9 +246,9 @@
"`x` marked it with a ❤": "`x` је означио/ла ово са ❤",
"Audio mode": "Аудио мод",
"Videos": "Видео клипови",
"views": "Број прегледа",
"features": "Карактеристике",
"today": "Данас",
"search_filters_sort_option_views": "Број прегледа",
"search_filters_features_label": "Карактеристике",
"search_filters_date_option_today": "Данас",
"%A %B %-d, %Y": "%A %B %-d, %Y",
"preferences_locale_label": "Језик: ",
"Persian": "Перзијски",
@ -257,7 +256,7 @@
"": "Прикажи `x` коментара",
"([^.,0-9]|^)1([^.,0-9]|$)": "Прикажи `x` коментар"
},
"channel": "Канал",
"search_filters_type_option_channel": "Канал",
"Haitian Creole": "Хаићански Креолски",
"Armenian": "Јерменски",
"next_steps_error_message_go_to_youtube": "Иди на YouTube",
@ -265,10 +264,10 @@
"preferences_vr_mode_label": "Интерактивни видео клипови у 360 степени: ",
"Switch Invidious Instance": "Промени Invidious инстанцу",
"Portuguese": "Португалски",
"week": "Ове седмице",
"show": "Емисија",
"search_filters_date_option_week": "Ове седмице",
"search_filters_type_option_show": "Емисија",
"Fallback comments: ": "Коментари у случају отказивања: ",
"hdr": "Видео Високе Резолуције",
"search_filters_features_option_hdr": "Видео Високе Резолуције",
"About": "О програму",
"Kazakh": "Казашки",
"Shared `x`": "Подељено `x`",
@ -277,7 +276,7 @@
"Erroneous challenge": "Погрешан изазов",
"Danish": "Дански",
"Could not get channel info.": "Узимање података о каналу није успело.",
"hd": "HD",
"search_filters_features_option_hd": "HD",
"Slovenian": "Словеначки",
"Load more": "Учитај више",
"German": "Немачки",
@ -288,12 +287,12 @@
"Southern Sotho": "Јужни Сото",
"Popular": "Популарно",
"Gujarati": "Гуџарати",
"year": "Ове године",
"search_filters_date_option_year": "Ове године",
"Irish": "Ирски",
"YouTube comment permalink": "YouTube коментар трајна веза",
"Malagasy": "Малгашки",
"Token is expired, please try again": "Жетон је истекао, молимо вас да покушате поново",
"short": "Кратко (< 4 минуте)",
"search_filters_duration_option_short": "Кратко (< 4 минуте)",
"Samoan": "Самоански",
"Tamil": "Тамилски",
"Ukrainian": "Украјински",
@ -307,22 +306,22 @@
"Lithuanian": "Литвански",
"Icelandic": "Исландски",
"Thai": "Тајски",
"month": "Овај месец",
"content_type": "Тип",
"hour": "Последњи сат",
"search_filters_date_option_month": "Овај месец",
"search_filters_type_label": "Тип",
"search_filters_date_option_hour": "Последњи сат",
"Spanish": "Шпански",
"date": "Датум отпремања",
"search_filters_sort_option_date": "Датум отпремања",
"View as playlist": "Погледај као плеј листу",
"relevance": "Релевантност",
"search_filters_sort_option_relevance": "Релевантност",
"Estonian": "Естонски",
"Sinhala": "Синхалешки",
"Corsican": "Корзикански",
"Filipino": "Филипино",
"Gaming": "Игрице",
"Movies": "Филмови",
"rating": "Оцене",
"search_filters_sort_option_rating": "Оцене",
"Top enabled: ": "Врх омогућен: ",
"Released under the AGPLv3 on Github.": "Избачено под лиценцом AGPLv3 на Github-у.",
"Released under the AGPLv3 on Github.": "Избачено под лиценцом AGPLv3 на GitHub-у.",
"Afrikaans": "Африканс",
"preferences_automatic_instance_redirect_label": "Аутоматско пребацивање на другу инстанцу у случају отказивања (пречи ће назад на редирецт.инвидиоус.ио): ",
"Invalid TFA code": "Неважећа TFA кода",
@ -340,12 +339,11 @@
"Swedish": "Шведски",
"Music": "Музика",
"Download as: ": "Преузми као: ",
"duration": "Трајање",
"sort": "Поредај према",
"subtitles": "Титл/Превод",
"search_filters_duration_label": "Трајање",
"search_filters_sort_label": "Поредај према",
"search_filters_features_option_subtitles": "Титл/Превод",
"preferences_extend_desc_label": "Аутоматски прикажи цео опис видеа: ",
"Show less": "Прикажи мање",
"Broken? Try another Invidious Instance": "Не функционише исправно? Пробајте другу Invidious инстанцу",
"Family friendly? ": "Погодно за породицу? ",
"Premieres `x`": ремерe у `x`",
"Bosnian": "Босански",
@ -359,8 +357,8 @@
"Top": "Врх",
"Video mode": "Видео мод",
"footer_source_code": "Изворна Кода",
"3d": "3D",
"4k": "4K",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_four_k": "4K",
"Erroneous CAPTCHA": "Погрешна CAPTCHA",
"`x` ago": "пре `x`",
"Arabic": "Арапски",
@ -369,5 +367,6 @@
"Hebrew": "Хебрејски",
"Korean": "Корејски",
"Kurdish": "Курдски",
"Malay": "Малајски"
"Malay": "Малајски",
"search_filters_title": "Филтер"
}

View File

@ -139,7 +139,6 @@
"Show less": "Visa mindre",
"Watch on YouTube": "Titta på YouTube",
"Switch Invidious Instance": "Byt Invidious Instans",
"Broken? Try another Invidious Instance": "Trasig? Prova en annan Invidious Instance",
"Hide annotations": "Dölj länkar-i-video",
"Show annotations": "Visa länkar-i-video",
"Genre: ": "Genre: ",
@ -327,39 +326,39 @@
"Videos": "Videor",
"Playlists": "Spellistor",
"Community": "Gemenskap",
"relevance": "relevans",
"rating": "rankning",
"date": "datum",
"views": "visningar",
"content_type": "Typ",
"duration": "Varaktighet",
"features": "Funktioner",
"sort": "Sortera efter",
"hour": "timme",
"today": "idag",
"week": "vecka",
"month": "månad",
"year": "år",
"video": "video",
"channel": "kanal",
"playlist": "spellista",
"movie": "film",
"show": "tv-serie",
"hd": "hd",
"subtitles": "undertexter",
"creative_commons": "creative_commons",
"3d": "3d",
"live": "live",
"4k": "4k",
"location": "plats",
"hdr": "hdr",
"filter": "Filter",
"search_filters_sort_option_relevance": "Relevans",
"search_filters_sort_option_rating": "Rankning",
"search_filters_sort_option_date": "Datum",
"search_filters_sort_option_views": "Visningar",
"search_filters_type_label": "Typ",
"search_filters_duration_label": "Varaktighet",
"search_filters_features_label": "Funktioner",
"search_filters_sort_label": "Sortera efter",
"search_filters_date_option_hour": "timme",
"search_filters_date_option_today": "idag",
"search_filters_date_option_week": "vecka",
"search_filters_date_option_month": "månad",
"search_filters_date_option_year": "år",
"search_filters_type_option_video": "video",
"search_filters_type_option_channel": "kanal",
"search_filters_type_option_playlist": "spellista",
"search_filters_type_option_movie": "film",
"search_filters_type_option_show": "tv-serie",
"search_filters_features_option_hd": "hd",
"search_filters_features_option_subtitles": "undertexter",
"search_filters_features_option_c_commons": "creative_commons",
"search_filters_features_option_three_d": "3d",
"search_filters_features_option_live": "live",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "plats",
"search_filters_features_option_hdr": "hdr",
"Current version: ": "Nuvarande version: ",
"next_steps_error_message_refresh": "Uppdatera",
"next_steps_error_message_go_to_youtube": "Gå till Youtube",
"Released under the AGPLv3 on Github.": "Publicerad under AGPLv3 på Github.",
"Released under the AGPLv3 on Github.": "Publicerad under AGPLv3 på GitHub.",
"footer_source_code": "Källkod",
"long": "Lång (> 20 minuter)",
"search_filters_duration_option_long": "Lång (> 20 minuter)",
"footer_documentation": "Dokumentation",
"short": "Kort (< 4 minuter)"
"search_filters_duration_option_short": "Kort (< 4 minuter)",
"search_filters_title": "Filter"
}

View File

@ -121,7 +121,7 @@
"Subscriptions": "Abonelikler",
"search": "ara",
"Log out": ıkış yap",
"Released under the AGPLv3 on Github.": "Github'da AGPLv3 altında yayınlandı.",
"Released under the AGPLv3 on Github.": "GitHub'da AGPLv3 altında yayınlandı.",
"Source available here.": "Kaynak kodları burada bulunabilir.",
"View JavaScript license information.": "JavaScript lisans bilgilerini görüntüle.",
"View privacy policy.": "Gizlilik politikasını görüntüle.",
@ -141,7 +141,6 @@
"Show less": "Daha az göster",
"Watch on YouTube": "YouTube'da izle",
"Switch Invidious Instance": "Invidious Örneğini Değiştir",
"Broken? Try another Invidious Instance": "Bozuk mu? Başka bir Invidious örneğini deneyin",
"Hide annotations": "Ek açıklamaları gizle",
"Show annotations": "Ek açıklamaları göster",
"Genre: ": "Tür: ",
@ -329,39 +328,38 @@
"Videos": "Videolar",
"Playlists": "Oynatma listeleri",
"Community": "Topluluk",
"relevance": "İlgi",
"rating": "Değerlendirme",
"date": "Yükleme tarihi",
"views": "Görüntüleme sayısı",
"content_type": "Tür",
"duration": "Süre",
"features": "Özellikler",
"sort": "Sıralama Ölçütü",
"hour": "Son Saat",
"today": "Bugün",
"week": "Bu hafta",
"month": "Bu ay",
"year": "Bu yıl",
"video": "Video",
"channel": "Kanal",
"playlist": "Oynatma listesi",
"movie": "Film",
"show": "Gösteri",
"hd": "HD",
"subtitles": "Alt yazılar",
"creative_commons": "Creative Commons",
"3d": "3B",
"live": "Canlı",
"4k": "4K",
"location": "Konum",
"hdr": "HDR",
"filter": "Filtrele",
"search_filters_sort_option_relevance": "İlgi",
"search_filters_sort_option_rating": "Değerlendirme",
"search_filters_sort_option_date": "Yükleme tarihi",
"search_filters_sort_option_views": "Görüntüleme sayısı",
"search_filters_type_label": "Tür",
"search_filters_duration_label": "Süre",
"search_filters_features_label": "Özellikler",
"search_filters_sort_label": "Sıralama Ölçütü",
"search_filters_date_option_hour": "Son Saat",
"search_filters_date_option_today": "Bugün",
"search_filters_date_option_week": "Bu hafta",
"search_filters_date_option_month": "Bu ay",
"search_filters_date_option_year": "Bu yıl",
"search_filters_type_option_video": "Video",
"search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Oynatma listesi",
"search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Gösteri",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Alt yazılar",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3B",
"search_filters_features_option_live": "Canlı",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "Konum",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "Şu anki sürüm: ",
"next_steps_error_message": "Bundan sonra şunları denemelisiniz: ",
"next_steps_error_message_refresh": "Yenile",
"next_steps_error_message_go_to_youtube": "YouTube'a git",
"short": "Kısa (4 dakikadan az)",
"long": "Uzun (20 dakikadan fazla)",
"search_filters_duration_option_short": "Kısa (4 dakikadan az)",
"search_filters_duration_option_long": "Uzun (20 dakikadan fazla)",
"footer_documentation": "Belgelendirme",
"footer_source_code": "Kaynak kodları",
"footer_original_source_code": "Orijinal kaynak kodları",
@ -394,8 +392,8 @@
"Video unavailable": "Video kullanılamıyor",
"preferences_quality_option_dash": "DASH (uyarlanabilir kalite)",
"preferences_quality_dash_option_auto": "Otomatik",
"purchased": "Satın alınan",
"360": "360°",
"search_filters_features_option_purchased": "Satın alınan",
"search_filters_features_option_three_sixty": "360°",
"videoinfo_watch_on_youTube": "YouTube'da izle",
"download_subtitles": "Alt yazılar - `x` (.vtt)",
"preferences_save_player_pos_label": "Oynatma konumunu kaydet: ",
@ -436,7 +434,7 @@
"crash_page_refresh": "<a href=\"`x`\">sayfayı yenilemeye</a> çalıştınız",
"crash_page_switch_instance": "<a href=\"`x`\">başka bir örnek kullanmaya</a> çalıştınız",
"crash_page_read_the_faq": "<a href=\"`x`\">Sık Sorulan Soruları (SSS)</a> okudunuz",
"crash_page_search_issue": "<a href=\"`x`\">Github'daki sorunlarda</a> aradınız",
"crash_page_search_issue": "<a href=\"`x`\">GitHub'daki sorunlarda</a> aradınız",
"crash_page_report_issue": "Yukarıdakilerin hiçbiri yardımcı olmadıysa, lütfen <a href=\"`x`\">GitHub'da yeni bir sorun açın</a> (tercihen İngilizce) ve mesajınıza aşağıdaki metni ekleyin (bu metni ÇEVİRMEYİN):",
"English (United Kingdom)": "İngilizce (Birleşik Krallık)",
"Chinese": "Çince",
@ -461,5 +459,17 @@
"Portuguese (auto-generated)": "Portekizce (otomatik oluşturuldu)",
"Spanish (Spain)": "İspanyolca (İspanya)",
"Vietnamese (auto-generated)": "Vietnamca (otomatik oluşturuldu)",
"preferences_watch_history_label": "İzleme geçmişini etkinleştir: "
"preferences_watch_history_label": "İzleme geçmişini etkinleştir: ",
"search_message_use_another_instance": " Ayrıca <a href=\"`x`\">başka bir örnekte arayabilirsiniz</a>.",
"search_filters_type_option_all": "Herhangi bir tür",
"search_filters_duration_option_none": "Herhangi bir süre",
"search_message_no_results": "Sonuç bulunamadı.",
"search_filters_date_label": "Yükleme tarihi",
"search_filters_apply_button": "Seçili filtreleri uygula",
"search_filters_date_option_none": "Herhangi bir tarih",
"search_filters_duration_option_medium": "Orta (4 - 20 dakika)",
"search_filters_features_option_vr180": "VR180",
"search_filters_title": "Filtreler",
"search_message_change_filters_or_query": "Arama sorgunuzu genişletmeyi ve/veya filtreleri değiştirmeyi deneyin.",
"Popular enabled: ": "Popüler etkin: "
}

View File

@ -1,6 +1,6 @@
{
"LIVE": "ПРЯМИЙ ЕФІР",
"Shared `x` ago": "Розміщено `x` назад",
"LIVE": "НАЖИВО",
"Shared `x` ago": "Розміщено `x` тому",
"Unsubscribe": "Відписатися",
"Subscribe": "Підписатися",
"View channel on YouTube": "Подивитися канал на YouTube",
@ -21,16 +21,16 @@
"No": "Ні",
"Import and Export Data": "Імпорт і експорт даних",
"Import": "Імпорт",
"Import Invidious data": "Імпортувати дані Invidious",
"Import YouTube subscriptions": "Імпортувати підписки з YouTube",
"Import Invidious data": "Імпортувати JSON-дані Invidious",
"Import YouTube subscriptions": "Імпортувати підписки з YouTube чи OPML",
"Import FreeTube subscriptions (.db)": "Імпортувати підписки з FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Імпортувати підписки з NewPipe (.json)",
"Import NewPipe data (.zip)": "Імпортувати дані з NewPipe (.zip)",
"Export": "Експорт",
"Export subscriptions as OPML": "Експортувати підписки у форматі OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Експортувати підписки у форматі OPML (для NewPipe та FreeTube)",
"Export data as JSON": "Експортувати дані у форматі JSON",
"Delete account?": "Видалити обліківку?",
"Export data as JSON": "Експортувати дані Invidious у форматі JSON",
"Delete account?": "Видалити обліковий запис?",
"History": "Історія",
"An alternative front-end to YouTube": "Альтернативний фронтенд до YouTube",
"JavaScript license information": "Інформація щодо ліцензій JavaScript",
@ -40,9 +40,9 @@
"Log in with Google": "Увійти через Google",
"User ID": "ID користувача",
"Password": "Пароль",
"Time (h:mm:ss):": "Час (г:мм:сс):",
"Text CAPTCHA": "Текст капчі",
"Image CAPTCHA": "Зображення капчі",
"Time (h:mm:ss):": "Час (г:хх:сс):",
"Text CAPTCHA": "Текст CAPTCHA",
"Image CAPTCHA": "Зображення CAPTCHA",
"Sign In": "Увійти",
"Register": "Зареєструватися",
"E-mail": "Електронна пошта",
@ -142,7 +142,7 @@
"Whitelisted regions: ": "Доступно у регіонах: ",
"Blacklisted regions: ": "Недоступно у регіонах: ",
"Shared `x`": "Розміщено `x`",
"Premieres in `x`": "Прем’єра через `x`",
"Premieres in `x`": "Прем’єра за `x`",
"Premieres `x`": "Прем’єра `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Схоже, у вас відключений JavaScript. Щоб побачити коментарі, натисніть сюда, але майте на увазі, що вони можуть завантажуватися трохи довше.",
"View YouTube comments": "Переглянути коментарі з YouTube",
@ -157,11 +157,11 @@
"Incorrect password": "Неправильний пароль",
"Quota exceeded, try again in a few hours": "Ліміт перевищено, спробуйте знову за декілька годин",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Не вдається увійти. Перевірте, чи не ввімкнена двофакторна аутентифікація (за кодом чи смс).",
"Invalid TFA code": "Неправильний код двофакторної аутентифікації",
"Invalid TFA code": "Неправильний код двофакторної автентифікації",
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Не вдається увійти. Це може бути через те, що у вашій обліківці не ввімкнена двофакторна аутентифікація.",
"Wrong answer": "Неправильна відповідь",
"Erroneous CAPTCHA": "Неправильна капча",
"CAPTCHA is a required field": "Необхідно пройти капчу",
"CAPTCHA is a required field": "Необхідно пройти CAPTCHA",
"User ID is a required field": "Необхідно ввести ID користувача",
"Password is a required field": "Необхідно ввести пароль",
"Wrong username or password": "Неправильний логін чи пароль",
@ -169,7 +169,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.": "Такого каналу не існує.",
@ -189,7 +189,7 @@
"No such user": "Недопустиме ім’я користувача",
"Token is expired, please try again": "Термін дії токена закінчився, спробуйте пізніше",
"English": "Англійська",
"English (auto-generated)": "Англійська (сгенеровано автоматично)",
"English (auto-generated)": "Англійська (автогенератор)",
"Afrikaans": "Африкаанс",
"Albanian": "Албанська",
"Amharic": "Амхарська",
@ -275,7 +275,7 @@
"Somali": "Сомалійська",
"Southern Sotho": "Сесото (південна сото)",
"Spanish": "Іспанська",
"Spanish (Latin America)": "Испанська (Латинська Америка)",
"Spanish (Latin America)": "Іспанська (Латинська Америка)",
"Sundanese": "Сунданська",
"Swahili": "Суахілі",
"Swedish": "Шведська",
@ -318,5 +318,174 @@
"Videos": "Відео",
"Playlists": "Плейлисти",
"Community": "Спільнота",
"Current version: ": "Поточна версія: "
"Current version: ": "Поточна версія: ",
"generic_views_count_0": "{{count}} перегляд",
"generic_views_count_1": "{{count}} перегляди",
"generic_views_count_2": "{{count}} переглядів",
"generic_videos_count_0": "{{count}} відео",
"generic_videos_count_1": "{{count}} відео",
"generic_videos_count_2": "{{count}} відео",
"generic_playlists_count_0": "{{count}} список відтворення",
"generic_playlists_count_1": "{{count}} списки відтворення",
"generic_playlists_count_2": "{{count}} списків відтворення",
"generic_subscribers_count_0": "{{count}} стежить",
"generic_subscribers_count_1": "{{count}} стежать",
"generic_subscribers_count_2": "{{count}} стежать",
"generic_subscriptions_count_0": "{{count}} підписка",
"generic_subscriptions_count_1": "{{count}} підписки",
"generic_subscriptions_count_2": "{{count}} підписок",
"tokens_count_0": "{{count}} токен",
"tokens_count_1": "{{count}} токени",
"tokens_count_2": "{{count}} токенів",
"subscriptions_unseen_notifs_count_0": "{{count}} нове сповіщення",
"subscriptions_unseen_notifs_count_1": "{{count}} нові сповіщення",
"subscriptions_unseen_notifs_count_2": "{{count}} нових сповіщень",
"comments_view_x_replies_0": "Переглянути {{count}} відповідь",
"comments_view_x_replies_1": "Переглянути {{count}} відповіді",
"comments_view_x_replies_2": "Переглянути {{count}} відповідей",
"generic_count_years_0": "{{count}} рік",
"generic_count_years_1": "{{count}} роки",
"generic_count_years_2": "{{count}} років",
"generic_count_weeks_0": "{{count}} тиждень",
"generic_count_weeks_1": "{{count}} тижні",
"generic_count_weeks_2": "{{count}} тижнів",
"generic_count_days_0": "{{count}} день",
"generic_count_days_1": "{{count}} дні",
"generic_count_days_2": "{{count}} днів",
"generic_count_hours_0": "{{count}} годину",
"generic_count_hours_1": "{{count}} години",
"generic_count_hours_2": "{{count}} годин",
"crash_page_switch_instance": "спробуйте <a href=\"`x`\">використати інший сервер</a>",
"crash_page_read_the_faq": "прочитайте <a href=\"`x`\">часті питання (ЧаП)</a>",
"crash_page_search_issue": "перегляньте <a href=\"`x`\">наявні обговорення на GitHub</a>",
"crash_page_report_issue": "Якщо нічого не допомогло, просимо <a href=\"`x`\">створити обговорення на GitHub</a> (бажано англійською), додавши наступний текст у повідомлення (НЕ перекладайте цього тексту):",
"Chinese (Hong Kong)": "Китайська (Гонконг)",
"Cantonese (Hong Kong)": "Кантонська (Гонконг)",
"Chinese": "Китайська",
"Chinese (China)": "Китайська (Китай)",
"Interlingue": "Інтерлінгва",
"Italian (auto-generated)": "Італійська (автогенератор)",
"Turkish (auto-generated)": "Турецька (автогенератор)",
"Vietnamese (auto-generated)": "В'єтнамська (автогенератор)",
"user_created_playlists": "Створено списків відтворення: `x`",
"user_saved_playlists": "Збережено списків відтворення: `x`",
"Video unavailable": "Відео недоступне",
"preferences_watch_history_label": "Історія переглядів: ",
"preferences_quality_dash_label": "Бажана DASH-якість відео: ",
"preferences_quality_dash_option_144p": "144p",
"preferences_vr_mode_label": "Взаємодія з 360-градусними відео (потребує WebGL): ",
"Released under the AGPLv3 on Github.": "Випущено під AGPLv3 на GitHub.",
"English (United Kingdom)": "Англійська (Сполучене Королівство)",
"English (United States)": "Англійська (США)",
"French (auto-generated)": "Французька (автогенератор)",
"German (auto-generated)": "Німецька (автогенератор)",
"Portuguese (auto-generated)": "Португальська (автогенератор)",
"Portuguese (Brazil)": "Португальська (Бразилія)",
"Russian (auto-generated)": ":^)",
"Spanish (auto-generated)": "Іспанська (автогенератор)",
"Spanish (Mexico)": "Іспанська (Мексика)",
"Spanish (Spain)": "Іспанська (Іспанія)",
"next_steps_error_message_go_to_youtube": "Перейти до YouTube",
"footer_donate_page": "Пожертвувати",
"footer_documentation": "Документація",
"footer_source_code": "Вихідний код",
"footer_original_source_code": "Оригінал вихідного коду",
"footer_modfied_source_code": "Змінений вихідний код",
"adminprefs_modified_source_code_url_label": "URL-адреса репозиторію зміненого вихідного коду",
"none": "нема",
"videoinfo_started_streaming_x_ago": "Трансляцію розпочато `x` тому",
"crash_page_you_found_a_bug": "Схоже, ви знайшли ваду в Invidious!",
"crash_page_before_reporting": "Перш ніж прозвітувати про ваду:",
"crash_page_refresh": "спробуйте <a href=\"`x`\">оновити сторінку</a>",
"preferences_quality_dash_option_auto": "Авто",
"preferences_quality_dash_option_best": "Найкраща",
"preferences_quality_dash_option_worst": "Найгірша",
"preferences_quality_dash_option_1440p": "1440p",
"preferences_quality_dash_option_1080p": "1080p",
"preferences_save_player_pos_label": "Зберегти позицію відтворення: ",
"preferences_show_nick_label": "Псевдонім угорі: ",
"Show more": "Докладніше",
"next_steps_error_message": "Після чого спробуйте: ",
"next_steps_error_message_refresh": "Оновити сторінку",
"Search": "Пошук",
"preferences_extend_desc_label": "Автоматично розширювати опис відео: ",
"preferences_category_misc": "Різноманітні параметри",
"Show less": "Коротше",
"preferences_quality_option_small": "Низька",
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_option_medium": "Середня",
"preferences_quality_dash_option_4320p": "4320p",
"invidious": "Invidious",
"preferences_quality_dash_option_720p": "720p",
"preferences_quality_dash_option_360p": "360p",
"preferences_region_label": "Ваша країна: ",
"preferences_quality_option_dash": "DASH (змінна якість)",
"preferences_quality_option_hd720": "HD720",
"preferences_quality_dash_option_2160p": "2160p",
"preferences_automatic_instance_redirect_label": "Автоматична зміна сервера (redirect.invidious.io як резерв): ",
"Switch Invidious Instance": "Інший сервер Invidious",
"preferences_quality_dash_option_480p": "480p",
"Chinese (Taiwan)": "Китайська (Тайвань)",
"Dutch (auto-generated)": "Нідерландська (автогенератор)",
"Indonesian (auto-generated)": "Індонезійська (автогенератор)",
"Japanese (auto-generated)": "Японська (автогенератор)",
"Korean (auto-generated)": "Корейська (автогенератор)",
"generic_count_months_0": "{{count}} місяць",
"generic_count_months_1": "{{count}} місяці",
"generic_count_months_2": "{{count}} місяців",
"videoinfo_youTube_embed_link": "Вкласти",
"generic_count_minutes_0": "{{count}} хвилину",
"generic_count_minutes_1": "{{count}} хвилини",
"generic_count_minutes_2": "{{count}} хвилин",
"generic_count_seconds_0": "{{count}} секунду",
"generic_count_seconds_1": "{{count}} секунди",
"generic_count_seconds_2": "{{count}} секунд",
"videoinfo_watch_on_youTube": "Переглянути на YouTube",
"videoinfo_invidious_embed_link": "Вкласти посилання",
"download_subtitles": "Субтитри — `x` (.vtt)",
"comments_points_count_0": "{{count}} пункт",
"comments_points_count_1": "{{count}} пункти",
"comments_points_count_2": "{{count}} пунктів",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_location": "Геомітка",
"search_filters_duration_option_none": "Будь-які",
"search_filters_features_option_hd": "HD",
"search_message_change_filters_or_query": "Спробуйте ширший запит і/або інші фільтри.",
"search_filters_type_option_all": "Будь-що",
"search_filters_type_option_movie": "Фільм",
"search_filters_type_option_show": "Шоу",
"search_filters_duration_label": "Тривалість",
"search_filters_duration_option_short": "Короткі (до 4 хвилин)",
"search_message_no_results": "Результатів не знайдено.",
"search_filters_date_label": "Дата вивантаження",
"search_filters_date_option_none": "Будь-яка дата",
"search_filters_date_option_today": "Сьогодні",
"search_filters_date_option_week": "Цей тиждень",
"search_filters_type_label": "Тип",
"search_filters_type_option_channel": "Канал",
"search_message_use_another_instance": " Можете також <a href=\"`x`\">пошукати іншим сервером</a>.",
"search_filters_title": "Фільтри",
"search_filters_date_option_hour": "Остання година",
"search_filters_date_option_month": "Цей місяць",
"search_filters_date_option_year": "Цей рік",
"search_filters_type_option_video": "Відео",
"search_filters_type_option_playlist": "Добірка",
"search_filters_duration_option_medium": "Середні (420 хвилин)",
"search_filters_duration_option_long": "Довгі (понад 20 хвилин)",
"search_filters_features_label": "Особливості",
"search_filters_features_option_live": "Наживо",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_subtitles": "Субтитри",
"search_filters_features_option_c_commons": "Creative Commons",
"search_filters_features_option_three_sixty": "360°",
"search_filters_features_option_hdr": "HDR",
"search_filters_sort_label": "Спершу",
"search_filters_sort_option_date": "Нещодавні",
"search_filters_apply_button": "Застосувати фільтри",
"search_filters_features_option_vr180": "VR180",
"search_filters_features_option_purchased": "Придбано",
"search_filters_sort_option_relevance": "Відповідні",
"search_filters_sort_option_rating": "Рейтингові",
"search_filters_sort_option_views": "Популярні",
"Popular enabled: ": "Популярне ввімкнено: "
}

View File

@ -138,7 +138,6 @@
"Show less": "Hiện ít hơn",
"Watch on YouTube": "Xem trên YouTube",
"Switch Invidious Instance": "Chuyển phiên bản Invidious",
"Broken? Try another Invidious Instance": "Bị hỏng? Hãy thử một Phiên bản Invidious khác",
"Hide annotations": "Ẩn chú thích",
"Show annotations": "Hiển thị chú thích",
"Genre: ": "Thể loại: ",
@ -315,32 +314,32 @@
"Videos": "Video",
"Playlists": "Danh sách phát",
"Community": "Cộng đồng",
"relevance": "liên quan",
"rating": "Xếp hạng",
"date": "ngày",
"views": "lượt xem",
"content_type": "content_type",
"duration": "thời lượng",
"features": "đặc trưng",
"sort": "sắp xếp",
"hour": "giờ",
"today": "hôm nay",
"week": "tuần",
"month": "tháng",
"year": "năm",
"video": "video",
"channel": "kênh",
"playlist": "danh sách phát",
"movie": "bộ phim",
"show": "chỉ",
"hd": "hd",
"subtitles": "phụ đề",
"creative_commons": "Commons sáng tạo",
"3d": "3d",
"live": "trực tiếp",
"4k": "4k",
"location": "vị trí",
"hdr": "hdr",
"filter": "bộ lọc",
"Current version: ": "Phiên bản hiện tại: "
"search_filters_sort_option_relevance": "liên quan",
"search_filters_sort_option_rating": "Xếp hạng",
"search_filters_sort_option_date": "ngày",
"search_filters_sort_option_views": "lượt xem",
"search_filters_type_label": "content_type",
"search_filters_duration_label": "thời lượng",
"search_filters_features_label": "đặc trưng",
"search_filters_sort_label": "sắp xếp",
"search_filters_date_option_hour": "giờ",
"search_filters_date_option_today": "hôm nay",
"search_filters_date_option_week": "tuần",
"search_filters_date_option_month": "tháng",
"search_filters_date_option_year": "năm",
"search_filters_type_option_video": "video",
"search_filters_type_option_channel": "kênh",
"search_filters_type_option_playlist": "danh sách phát",
"search_filters_type_option_movie": "bộ phim",
"search_filters_type_option_show": "chỉ",
"search_filters_features_option_hd": "hd",
"search_filters_features_option_subtitles": "phụ đề",
"search_filters_features_option_c_commons": "Commons sáng tạo",
"search_filters_features_option_three_d": "3d",
"search_filters_features_option_live": "trực tiếp",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "vị trí",
"search_filters_features_option_hdr": "hdr",
"Current version: ": "Phiên bản hiện tại: ",
"search_filters_title": "bộ lọc"
}

View File

@ -128,7 +128,7 @@
"subscriptions_unseen_notifs_count_0": "{{count}} 条未读通知",
"search": "搜索",
"Log out": "登出",
"Released under the AGPLv3 on Github.": "依据 AGPLv3 许可证发布于 Github。",
"Released under the AGPLv3 on Github.": "依据 AGPLv3 许可证发布于 GitHub。",
"Source available here.": "源码可在此查看。",
"View JavaScript license information.": "查看 JavaScript 协议信息。",
"View privacy policy.": "查看隐私政策。",
@ -148,7 +148,6 @@
"Show less": "显示较少",
"Watch on YouTube": "在 YouTube 观看",
"Switch Invidious Instance": "切换 Invidious 实例",
"Broken? Try another Invidious Instance": "无法正常工作? 尝试另一个 Invidious 实例",
"Hide annotations": "隐藏注释",
"Show annotations": "显示注释",
"Genre: ": "风格: ",
@ -345,39 +344,38 @@
"Videos": "视频",
"Playlists": "播放列表",
"Community": "社区",
"relevance": "相关度",
"rating": "评分",
"date": "上传日期",
"views": "观看次数",
"content_type": "类型",
"duration": "持续时间",
"features": "功能",
"sort": "排序依据",
"hour": "上个小时",
"today": "今日",
"week": "本周",
"month": "本月",
"year": "今年",
"video": "视频",
"channel": "频道",
"playlist": "播放列表",
"movie": "电影",
"show": "真人秀",
"hd": "高清",
"subtitles": "字幕",
"creative_commons": "creative_commons 许可",
"3d": "3d",
"live": "直播",
"4k": "4k",
"location": "位置",
"hdr": "hdr",
"filter": "过滤器",
"search_filters_sort_option_relevance": "相关度",
"search_filters_sort_option_rating": "评分",
"search_filters_sort_option_date": "上传日期",
"search_filters_sort_option_views": "观看次数",
"search_filters_type_label": "类型",
"search_filters_duration_label": "持续时间",
"search_filters_features_label": "功能",
"search_filters_sort_label": "排序依据",
"search_filters_date_option_hour": "上个小时",
"search_filters_date_option_today": "今日",
"search_filters_date_option_week": "本周",
"search_filters_date_option_month": "本月",
"search_filters_date_option_year": "今年",
"search_filters_type_option_video": "视频",
"search_filters_type_option_channel": "频道",
"search_filters_type_option_playlist": "播放列表",
"search_filters_type_option_movie": "电影",
"search_filters_type_option_show": "真人秀",
"search_filters_features_option_hd": "高清",
"search_filters_features_option_subtitles": "字幕",
"search_filters_features_option_c_commons": "creative_commons 许可",
"search_filters_features_option_three_d": "3d",
"search_filters_features_option_live": "直播",
"search_filters_features_option_four_k": "4k",
"search_filters_features_option_location": "位置",
"search_filters_features_option_hdr": "hdr",
"Current version: ": "当前版本: ",
"next_steps_error_message": "在此之后你应尝试: ",
"next_steps_error_message_refresh": "刷新",
"next_steps_error_message_go_to_youtube": "转到 YouTube",
"short": "短少于4分钟",
"long": "长(多于 20 分钟)",
"search_filters_duration_option_short": "短少于4分钟",
"search_filters_duration_option_long": "长(多于 20 分钟)",
"footer_documentation": "文档",
"footer_source_code": "源代码",
"footer_modfied_source_code": "修改的源代码",
@ -391,7 +389,7 @@
"crash_page_refresh": "试着 <a href=\"`x`\">刷新页面</a>",
"crash_page_switch_instance": "试着<a href=\"`x`\">使用另一个实例</a>",
"crash_page_read_the_faq": "阅读<a href=\"`x`\">常见问题</a>",
"crash_page_search_issue": "搜索过 <a href=\"`x`\">Github 上的现有 issue</a>",
"crash_page_search_issue": "搜索过 <a href=\"`x`\">GitHub 上的现有 issue</a>",
"crash_page_report_issue": "如果以上这些都没用的话,请<a href=\"`x`\">在 Github 上新开一个 issue</a>(最好用英语撰写),并在你的消息中包含以下文本(不要翻译该文本)",
"videoinfo_invidious_embed_link": "嵌入链接",
"download_subtitles": "字幕 - `x` (.vtt)",
@ -418,8 +416,8 @@
"user_created_playlists": "`x` 创建了播放列表",
"user_saved_playlists": "`x` 保存了播放列表",
"Video unavailable": "视频不可用",
"purchased": "已购买",
"360": "360°",
"search_filters_features_option_purchased": "已购买",
"search_filters_features_option_three_sixty": "360°",
"none": "无",
"preferences_save_player_pos_label": "保存播放位置: ",
"Spanish (Mexico)": "西班牙语 (墨西哥)",
@ -445,5 +443,17 @@
"French (auto-generated)": "法语 (自动生成)",
"Turkish (auto-generated)": "土耳其语 (自动生成)",
"Spanish (Spain)": "西班牙语 (西班牙)",
"preferences_watch_history_label": "启用观看历史: "
"preferences_watch_history_label": "启用观看历史: ",
"search_message_use_another_instance": " 你也可以 <a href=\"`x`\">在另一实例上搜索</a>。",
"search_filters_title": "过滤器",
"search_filters_date_label": "上传日期",
"search_filters_apply_button": "应用所选过滤器",
"search_message_no_results": "没找到结果。",
"search_filters_duration_option_medium": "中等4-20 分钟)",
"search_filters_date_option_none": "任意日期",
"search_message_change_filters_or_query": "尝试扩大你的搜索查询和/或更改过滤器。",
"search_filters_duration_option_none": "任意时长",
"search_filters_type_option_all": "任意类型",
"search_filters_features_option_vr180": "VR180",
"Popular enabled: ": "已启用流行度: "
}

View File

@ -148,7 +148,6 @@
"Show less": "顯示較少",
"Watch on YouTube": "在 YouTube 上觀看",
"Switch Invidious Instance": "切換 Invidious 站台",
"Broken? Try another Invidious Instance": "故障了嗎?試試看其他 Invidious 站台吧",
"Hide annotations": "隱藏註釋",
"Show annotations": "顯示註釋",
"Genre: ": "風格: ",
@ -345,39 +344,38 @@
"Videos": "影片",
"Playlists": "播放清單",
"Community": "社群",
"relevance": "關聯",
"rating": "評分",
"date": "日期",
"views": "檢視",
"content_type": "內容類型",
"duration": "時長",
"features": "特色",
"sort": "排序",
"hour": "小時",
"today": "今天",
"week": "週",
"month": "月",
"year": "年",
"video": "影片",
"channel": "頻道",
"playlist": "播放清單",
"movie": "電影",
"show": "秀",
"hd": "HD",
"subtitles": "字幕",
"creative_commons": "創用 CC",
"3d": "3D",
"live": "直播",
"4k": "4K",
"location": "位置",
"hdr": "HDR",
"filter": "篩選條件",
"search_filters_sort_option_relevance": "關聯",
"search_filters_sort_option_rating": "評分",
"search_filters_sort_option_date": "日期",
"search_filters_sort_option_views": "檢視",
"search_filters_type_label": "內容類型",
"search_filters_duration_label": "時長",
"search_filters_features_label": "特色",
"search_filters_sort_label": "排序",
"search_filters_date_option_hour": "小時",
"search_filters_date_option_today": "今天",
"search_filters_date_option_week": "週",
"search_filters_date_option_month": "月",
"search_filters_date_option_year": "年",
"search_filters_type_option_video": "影片",
"search_filters_type_option_channel": "頻道",
"search_filters_type_option_playlist": "播放清單",
"search_filters_type_option_movie": "電影",
"search_filters_type_option_show": "秀",
"search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "字幕",
"search_filters_features_option_c_commons": "創用 CC",
"search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "直播",
"search_filters_features_option_four_k": "4K",
"search_filters_features_option_location": "位置",
"search_filters_features_option_hdr": "HDR",
"Current version: ": "目前版本: ",
"next_steps_error_message": "之後您應該嘗試: ",
"next_steps_error_message_refresh": "重新整理",
"next_steps_error_message_go_to_youtube": "到 YouTube",
"short": "短小於4分鐘",
"long": "長多於20分鐘",
"search_filters_duration_option_short": "短小於4分鐘",
"search_filters_duration_option_long": "長多於20分鐘",
"footer_documentation": "文件",
"footer_source_code": "原始碼",
"footer_original_source_code": "原本的原始碼",
@ -398,8 +396,8 @@
"preferences_quality_dash_option_240p": "240p",
"preferences_quality_dash_option_144p": "144p",
"invidious": "Invidious",
"purchased": "已購買",
"360": "360°",
"search_filters_features_option_purchased": "已購買",
"search_filters_features_option_three_sixty": "360°",
"none": "無",
"videoinfo_started_streaming_x_ago": "`x` 前開始串流",
"videoinfo_watch_on_youTube": "在 YouTube 上觀看",
@ -445,5 +443,17 @@
"Portuguese (Brazil)": "葡萄牙語(巴西)",
"Japanese (auto-generated)": "日語(自動產生)",
"Portuguese (auto-generated)": "葡萄牙語(自動產生)",
"preferences_watch_history_label": "啟用觀看紀錄: "
"preferences_watch_history_label": "啟用觀看紀錄: ",
"search_message_change_filters_or_query": "嘗試擴大您的查詢字詞與/或變更過濾條件。",
"search_filters_apply_button": "套用選定的過濾條件",
"search_message_no_results": "找不到結果。",
"search_filters_duration_option_none": "任何時長",
"search_filters_duration_option_medium": "中等4到20分鐘",
"search_filters_features_option_vr180": "VR180",
"search_message_use_another_instance": " 您也可以<a href=\"`x`\">在其他站台上搜尋</a>。",
"search_filters_title": "過濾條件",
"search_filters_date_label": "上傳日期",
"search_filters_type_option_all": "任何類型",
"search_filters_date_option_none": "任何日期",
"Popular enabled: ": "已啟用人氣: "
}

1
mocks Submodule

Submodule mocks added at c401dd9203

View File

@ -0,0 +1,60 @@
#!/bin/sh
#
# Parameters
#
interactive=true
if [ "$1" = "--no-interactive" ]; then
interactive=false
fi
#
# Enable and start Postgres
#
sudo systemctl start postgresql.service
sudo systemctl enable postgresql.service
#
# Create databse and user
#
if [ "$interactive" = "true" ]; then
sudo -u postgres -- createuser -P kemal
sudo -u postgres -- createdb -O kemal invidious
else
# Generate a DB password
if [ -z "$POSTGRES_PASS" ]; then
echo "Generating database password"
POSTGRES_PASS=$(tr -dc 'A-Za-z0-9.;!?{[()]}\\/' < /dev/urandom | head -c16)
fi
# hostname:port:database:username:password
echo "Writing .pgpass"
echo "127.0.0.1:*:invidious:kemal:${POSTGRES_PASS}" > "$HOME/.pgpass"
sudo -u postgres -- psql -c "CREATE USER kemal WITH PASSWORD '$POSTGRES_PASS';"
sudo -u postgres -- psql -c "CREATE DATABASE invidious WITH OWNER kemal;"
sudo -u postgres -- psql -c "GRANT ALL ON DATABASE invidious TO kemal;"
fi
#
# Instructions for modification of pg_hba.conf
#
if [ "$interactive" = "true" ]; then
echo
echo "-------------"
echo " NOTICE "
echo "-------------"
echo
echo "Make sure that your postgreSQL's pg_hba.conf file contains the follwong"
echo "lines before previous 'host' configurations:"
echo
echo "host invidious kemal 127.0.0.1/32 md5"
echo "host invidious kemal ::1/128 md5"
echo
fi

View File

@ -0,0 +1,174 @@
#!/bin/sh
#
# Script that installs the various dependencies of invidious
#
# Dependencies:
# - crystal => Language in which Invidious is developed
# - postgres => Database server
# - git => required to clone Invidious
# - librsvg2-bin => For login captcha (provides 'rsvg-convert')
#
# - libssl-dev => Used by Crystal's SSL module (standard library)
# - libxml2-dev => Used by Crystal's XML module (standard library)
# - libyaml-dev => Used by Crystal's YAML module (standard library)
# - libgmp-dev => Used by Crystal's BigNumbers module (standard library)
# - libevent-dev => Used by crystal's internal scheduler (?)
# - libpcre3-dev => Used by Crystal's regex engine (?)
#
# - libsqlite3-dev => Used to open .db files from NewPipe exports
# - zlib1g-dev => TBD
# - libreadline-dev => TBD
#
#
# Tested on:
# - OpenSUSE Leap 15.3
#
# Load system details
#
if [ -e /etc/os-release ]; then
. /etc/os-release
elif [ -e /usr/lib/os-release ]; then
. /usr/lib/os-release
else
echo "Unsupported Linux system"
exit 2
fi
#
# Some variables
#
repo_base_url="https://download.opensuse.org/repositories/devel:/languages:/crystal/"
repo_end_url="devel:languages:crystal.repo"
apt_gpg_key="/usr/share/keyrings/crystal.gpg"
apt_list_file="/etc/apt/sources.list.d/crystal.list"
yum_repo_file="/etc/yum.repos.d/crystal.repo"
#
# Major install functions
#
make_repo_url() {
echo "${repo_base_url}/${1}/${repo_end_url}"
}
install_apt() {
repo="$1"
echo "Adding Crystal repository"
curl -fsSL "${repo_base_url}/${repo}/Release.key" \
| gpg --dearmor \
| sudo tee "${apt_gpg_key}" > /dev/null
echo "deb [signed-by=${apt_gpg_key}] ${repo_base_url}/${repo}/ /" \
| sudo tee "$apt_list_file"
sudo apt-get update
sudo apt-get install --yes --no-install-recommends \
libssl-dev libxml2-dev libyaml-dev libgmp-dev libevent-dev \
libpcre3-dev libreadline-dev libsqlite3-dev zlib1g-dev \
crystal postgresql-13 git librsvg2-bin make
}
install_yum() {
repo=$(make_repo_url "$1")
echo "Adding Crystal repository"
cat << END | sudo tee "${yum_repo_file}" > /dev/null
[crystal]
name=Crystal
type=rpm-md
baseurl=${repo}/
gpgcheck=1
gpgkey=${repo}/repodata/repomd.xml.key
enabled=1
END
sudo yum -y install \
openssl-devel libxml2-devel libyaml-devel gmp-devel \
readline-devel sqlite-devel \
crystal postgresql postgresql-server git librsvg2-tools make
}
install_pacman() {
# TODO: find an alternative to --no-confirm?
sudo pacman -S --no-confirm \
base-devel librsvg postgresql crystal
}
install_zypper()
{
repo=$(make_repo_url "$1")
echo "Adding Crystal repository"
sudo zypper --non-interactive addrepo -f "$repo"
sudo zypper --non-interactive --gpg-auto-import-keys install --no-recommends \
libopenssl-devel libxml2-devel libyaml-devel gmp-devel libevent-devel \
pcre-devel readline-devel sqlite3-devel zlib-devel \
crystal postgresql postgresql-server git rsvg-convert make
}
#
# System-specific logic
#
case "$ID" in
archlinux) install_pacman;;
centos) install_dnf "CentOS_${VERSION_ID}";;
debian)
case "$VERSION_CODENAME" in
sid) install_apt "Debian_Unstable";;
bookworm) install_apt "Debian_Testing";;
*) install_apt "Debian_${VERSION_ID}";;
esac
;;
fedora)
if [ "$VERSION" == *"Prerelease"* ]; then
install_dnf "Fedora_Rawhide"
else
install_dnf "Fedora_${VERSION}"
fi
;;
opensuse-leap) install_zypper "openSUSE_Leap_${VERSION}";;
opensuse-tumbleweed) install_zypper "openSUSE_Tumbleweed";;
rhel) install_dnf "RHEL_${VERSION_ID}";;
ubuntu)
# Small workaround for recently released 22.04
case "$VERSION_ID" in
22.04) install_apt "xUbuntu_21.04";;
*) install_apt "xUbuntu_${VERSION_ID}";;
esac
;;
*)
# Try to match on ID_LIKE instead
# Not guaranteed to 100% work
case "$ID_LIKE" in
archlinux) install_pacman;;
centos) install_dnf "CentOS_${VERSION_ID}";;
debian) install_apt "Debian_${VERSION_ID}";;
*)
echo "Error: distribution ${CODENAME} is not supported"
echo "Please install dependencies manually"
exit 2
;;
esac
;;
esac

View File

@ -14,11 +14,11 @@ shards:
exception_page:
git: https://github.com/crystal-loot/exception_page.git
version: 0.2.0
version: 0.2.2
kemal:
git: https://github.com/kemalcr/kemal.git
version: 1.1.0
version: 1.1.2
kilt:
git: https://github.com/jeromegn/kilt.git

View File

@ -18,7 +18,10 @@ dependencies:
version: ~> 0.18.0
kemal:
github: kemalcr/kemal
version: ~> 1.1.0
version: ~> 1.1.2
kilt:
github: jeromegn/kilt
version: ~> 0.6.1
protodec:
github: iv-org/protodec
version: ~> 0.1.4

View File

@ -0,0 +1,109 @@
require "../parsers_helper.cr"
Spectator.describe Invidious::Hashtag do
it "parses richItemRenderer containers (test 1)" do
# Enable mock
test_content = load_mock("hashtag/martingarrix_page1")
videos = extract_items(test_content)
expect(typeof(videos)).to eq(Array(SearchItem))
expect(videos.size).to eq(60)
#
# Random video check 1
#
expect(typeof(videos[11])).to eq(SearchItem)
video_11 = videos[11].as(SearchVideo)
expect(video_11.id).to eq("06eSsOWcKYA")
expect(video_11.title).to eq("Martin Garrix - Live @ Tomorrowland 2018")
expect(video_11.ucid).to eq("UC5H_KXkPbEsGs0tFt8R35mA")
expect(video_11.author).to eq("Martin Garrix")
expect(video_11.author_verified).to be_true
expect(video_11.published).to be_close(Time.utc - 3.years, 1.second)
expect(video_11.length_seconds).to eq((56.minutes + 41.seconds).total_seconds.to_i32)
expect(video_11.views).to eq(40_504_893)
expect(video_11.live_now).to be_false
expect(video_11.premium).to be_false
expect(video_11.premiere_timestamp).to be_nil
#
# Random video check 2
#
expect(typeof(videos[35])).to eq(SearchItem)
video_35 = videos[35].as(SearchVideo)
expect(video_35.id).to eq("b9HpOAYjY9I")
expect(video_35.title).to eq("Martin Garrix feat. Mike Yung - Dreamer (Official Video)")
expect(video_35.ucid).to eq("UC5H_KXkPbEsGs0tFt8R35mA")
expect(video_35.author).to eq("Martin Garrix")
expect(video_35.author_verified).to be_true
expect(video_35.published).to be_close(Time.utc - 3.years, 1.second)
expect(video_35.length_seconds).to eq((3.minutes + 14.seconds).total_seconds.to_i32)
expect(video_35.views).to eq(30_790_049)
expect(video_35.live_now).to be_false
expect(video_35.premium).to be_false
expect(video_35.premiere_timestamp).to be_nil
end
it "parses richItemRenderer containers (test 2)" do
# Enable mock
test_content = load_mock("hashtag/martingarrix_page2")
videos = extract_items(test_content)
expect(typeof(videos)).to eq(Array(SearchItem))
expect(videos.size).to eq(60)
#
# Random video check 1
#
expect(typeof(videos[41])).to eq(SearchItem)
video_41 = videos[41].as(SearchVideo)
expect(video_41.id).to eq("qhstH17zAjs")
expect(video_41.title).to eq("Martin Garrix Radio - Episode 391")
expect(video_41.ucid).to eq("UC5H_KXkPbEsGs0tFt8R35mA")
expect(video_41.author).to eq("Martin Garrix")
expect(video_41.author_verified).to be_true
expect(video_41.published).to be_close(Time.utc - 2.months, 1.second)
expect(video_41.length_seconds).to eq((1.hour).total_seconds.to_i32)
expect(video_41.views).to eq(63_240)
expect(video_41.live_now).to be_false
expect(video_41.premium).to be_false
expect(video_41.premiere_timestamp).to be_nil
#
# Random video check 2
#
expect(typeof(videos[48])).to eq(SearchItem)
video_48 = videos[48].as(SearchVideo)
expect(video_48.id).to eq("lqGvW0NIfdc")
expect(video_48.title).to eq("Martin Garrix SENTIO Full Album Mix by Sakul")
expect(video_48.ucid).to eq("UC3833PXeLTS6yRpwGMQpp4Q")
expect(video_48.author).to eq("SAKUL")
expect(video_48.author_verified).to be_false
expect(video_48.published).to be_close(Time.utc - 3.weeks, 1.second)
expect(video_48.length_seconds).to eq((35.minutes + 46.seconds).total_seconds.to_i32)
expect(video_48.views).to eq(68_704)
expect(video_48.live_now).to be_false
expect(video_48.premium).to be_false
expect(video_48.premiere_timestamp).to be_nil
end
end

View File

@ -29,20 +29,6 @@ Spectator.describe "Helper" do
end
end
describe "#produce_search_params" do
it "correctly produces token for searching with specified filters" do
expect(produce_search_params).to eq("CAASAhABSAA%3D")
expect(produce_search_params(sort: "upload_date", content_type: "video")).to eq("CAISAhABSAA%3D")
expect(produce_search_params(content_type: "playlist")).to eq("CAASAhADSAA%3D")
expect(produce_search_params(sort: "date", content_type: "video", features: ["hd", "cc", "purchased", "hdr"])).to eq("CAISCxABIAEwAUgByAEBSAA%3D")
expect(produce_search_params(content_type: "channel")).to eq("CAASAhACSAA%3D")
end
end
describe "#produce_comment_continuation" do
it "correctly produces a continuation token for comments" do
expect(produce_comment_continuation("_cE8xSu6swE", "ADSJ_i2qvJeFtL0htmS5_K5Ctj3eGFVBMWL9Wd42o3kmUL6_mAzdLp85-liQZL0mYr_16BhaggUqX652Sv9JqV6VXinShSP-ZT6rL4NolPBaPXVtJsO5_rA_qE3GubAuLFw9uzIIXU2-HnpXbdgPLWTFavfX206hqWmmpHwUOrmxQV_OX6tYkM3ux3rPAKCDrT8eWL7MU3bLiNcnbgkW8o0h8KYLL_8BPa8LcHbTv8pAoNkjerlX1x7K4pqxaXPoyz89qNlnh6rRx6AXgAzzoHH1dmcyQ8CIBeOHg-m4i8ZxdX4dP88XWrIFg-jJGhpGP8JUMDgZgavxVx225hUEYZMyrLGler5em4FgbG62YWC51moLDLeYEA")).to eq("EkMSC19jRTh4U3U2c3dFyAEA4AEBogINKP___________wFAAMICHQgEGhdodHRwczovL3d3dy55b3V0dWJlLmNvbSIAGAYyjAMK9gJBRFNKX2kycXZKZUZ0TDBodG1TNV9LNUN0ajNlR0ZWQk1XTDlXZDQybzNrbVVMNl9tQXpkTHA4NS1saVFaTDBtWXJfMTZCaGFnZ1VxWDY1MlN2OUpxVjZWWGluU2hTUC1aVDZyTDROb2xQQmFQWFZ0SnNPNV9yQV9xRTNHdWJBdUxGdzl1eklJWFUyLUhucFhiZGdQTFdURmF2ZlgyMDZocVdtbXBId1VPcm14UVZfT1g2dFlrTTN1eDNyUEFLQ0RyVDhlV0w3TVUzYkxpTmNuYmdrVzhvMGg4S1lMTF84QlBhOExjSGJUdjhwQW9Oa2plcmxYMXg3SzRwcXhhWFBveXo4OXFObG5oNnJSeDZBWGdBenpvSEgxZG1jeVE4Q0lCZU9IZy1tNGk4WnhkWDRkUDg4WFdySUZnLWpKR2hwR1A4SlVNRGdaZ2F2eFZ4MjI1aFVFWVpNeXJMR2xlcjVlbTRGZ2JHNjJZV0M1MW1vTERMZVlFQSIPIgtfY0U4eFN1NnN3RTAAKBQ%3D")

View File

@ -0,0 +1,371 @@
require "../../../src/invidious/search/filters"
require "http/params"
require "spectator"
Spectator.configure do |config|
config.fail_blank
config.randomize
end
FEATURES_TEXT = {
Invidious::Search::Filters::Features::Live => "live",
Invidious::Search::Filters::Features::FourK => "4k",
Invidious::Search::Filters::Features::HD => "hd",
Invidious::Search::Filters::Features::Subtitles => "subtitles",
Invidious::Search::Filters::Features::CCommons => "commons",
Invidious::Search::Filters::Features::ThreeSixty => "360",
Invidious::Search::Filters::Features::VR180 => "vr180",
Invidious::Search::Filters::Features::ThreeD => "3d",
Invidious::Search::Filters::Features::HDR => "hdr",
Invidious::Search::Filters::Features::Location => "location",
Invidious::Search::Filters::Features::Purchased => "purchased",
}
Spectator.describe Invidious::Search::Filters do
# -------------------
# Decode (legacy)
# -------------------
describe "#from_legacy_filters" do
it "Decodes channel: filter" do
query = "test channel:UC123456 request"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new)
expect(chan).to eq("UC123456")
expect(qury).to eq("test request")
expect(subs).to be_false
end
it "Decodes user: filter" do
query = "user:LinusTechTips broke something (again)"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new)
expect(chan).to eq("LinusTechTips")
expect(qury).to eq("broke something (again)")
expect(subs).to be_false
end
it "Decodes type: filter" do
Invidious::Search::Filters::Type.each do |value|
query = "Eiffel 65 - Blue [1 Hour] type:#{value}"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new(type: value))
expect(chan).to eq("")
expect(qury).to eq("Eiffel 65 - Blue [1 Hour]")
expect(subs).to be_false
end
end
it "Decodes content_type: filter" do
Invidious::Search::Filters::Type.each do |value|
query = "I like to watch content_type:#{value}"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new(type: value))
expect(chan).to eq("")
expect(qury).to eq("I like to watch")
expect(subs).to be_false
end
end
it "Decodes date: filter" do
Invidious::Search::Filters::Date.each do |value|
query = "This date:#{value} is old!"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new(date: value))
expect(chan).to eq("")
expect(qury).to eq("This is old!")
expect(subs).to be_false
end
end
it "Decodes duration: filter" do
Invidious::Search::Filters::Duration.each do |value|
query = "This duration:#{value} is old!"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new(duration: value))
expect(chan).to eq("")
expect(qury).to eq("This is old!")
expect(subs).to be_false
end
end
it "Decodes feature: filter" do
Invidious::Search::Filters::Features.each do |value|
string = FEATURES_TEXT[value]
query = "I like my precious feature:#{string} ^^"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new(features: value))
expect(chan).to eq("")
expect(qury).to eq("I like my precious ^^")
expect(subs).to be_false
end
end
it "Decodes features: filter" do
query = "This search has many features:vr180,cc,hdr :o"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
features = Invidious::Search::Filters::Features.flags(HDR, VR180, CCommons)
expect(fltr).to eq(described_class.new(features: features))
expect(chan).to eq("")
expect(qury).to eq("This search has many :o")
expect(subs).to be_false
end
it "Decodes sort: filter" do
Invidious::Search::Filters::Sort.each do |value|
query = "Computer? sort:#{value} my files!"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new(sort: value))
expect(chan).to eq("")
expect(qury).to eq("Computer? my files!")
expect(subs).to be_false
end
end
it "Decodes subscriptions: filter" do
query = "enable subscriptions:true"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new)
expect(chan).to eq("")
expect(qury).to eq("enable")
expect(subs).to be_true
end
it "Ignores junk data" do
query = "duration:I sort:like type:cleaning features:stuff date:up!"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new)
expect(chan).to eq("")
expect(qury).to eq("")
expect(subs).to be_false
end
it "Keeps unknown keys" do
query = "to:be or:not to:be"
fltr, chan, qury, subs = described_class.from_legacy_filters(query)
expect(fltr).to eq(described_class.new)
expect(chan).to eq("")
expect(qury).to eq("to:be or:not to:be")
expect(subs).to be_false
end
end
# -------------------
# Decode (URL)
# -------------------
describe "#from_iv_params" do
it "Decodes type= filter" do
Invidious::Search::Filters::Type.each do |value|
params = HTTP::Params.parse("type=#{value}")
expect(described_class.from_iv_params(params))
.to eq(described_class.new(type: value))
end
end
it "Decodes date= filter" do
Invidious::Search::Filters::Date.each do |value|
params = HTTP::Params.parse("date=#{value}")
expect(described_class.from_iv_params(params))
.to eq(described_class.new(date: value))
end
end
it "Decodes duration= filter" do
Invidious::Search::Filters::Duration.each do |value|
params = HTTP::Params.parse("duration=#{value}")
expect(described_class.from_iv_params(params))
.to eq(described_class.new(duration: value))
end
end
it "Decodes features= filter (single)" do
Invidious::Search::Filters::Features.each do |value|
string = described_class.format_features(value)
params = HTTP::Params.parse("features=#{string}")
expect(described_class.from_iv_params(params))
.to eq(described_class.new(features: value))
end
end
it "Decodes features= filter (multiple - comma separated)" do
features = Invidious::Search::Filters::Features.flags(HDR, VR180, CCommons)
params = HTTP::Params.parse("features=vr180%2Ccc%2Chdr") # %2C is a comma
expect(described_class.from_iv_params(params))
.to eq(described_class.new(features: features))
end
it "Decodes features= filter (multiple - URL parameters)" do
features = Invidious::Search::Filters::Features.flags(ThreeSixty, HD, FourK)
params = HTTP::Params.parse("features=4k&features=360&features=hd")
expect(described_class.from_iv_params(params))
.to eq(described_class.new(features: features))
end
it "Decodes sort= filter" do
Invidious::Search::Filters::Sort.each do |value|
params = HTTP::Params.parse("sort=#{value}")
expect(described_class.from_iv_params(params))
.to eq(described_class.new(sort: value))
end
end
it "Ignores junk data" do
params = HTTP::Params.parse("foo=bar&sort=views&answer=42&type=channel")
expect(described_class.from_iv_params(params)).to eq(
described_class.new(
sort: Invidious::Search::Filters::Sort::Views,
type: Invidious::Search::Filters::Type::Channel
)
)
end
end
# -------------------
# Encode (URL)
# -------------------
describe "#to_iv_params" do
it "Encodes date filter" do
Invidious::Search::Filters::Date.each do |value|
filters = described_class.new(date: value)
params = filters.to_iv_params
if value.none?
expect("#{params}").to eq("")
else
expect("#{params}").to eq("date=#{value.to_s.underscore}")
end
end
end
it "Encodes type filter" do
Invidious::Search::Filters::Type.each do |value|
filters = described_class.new(type: value)
params = filters.to_iv_params
if value.all?
expect("#{params}").to eq("")
else
expect("#{params}").to eq("type=#{value.to_s.underscore}")
end
end
end
it "Encodes duration filter" do
Invidious::Search::Filters::Duration.each do |value|
filters = described_class.new(duration: value)
params = filters.to_iv_params
if value.none?
expect("#{params}").to eq("")
else
expect("#{params}").to eq("duration=#{value.to_s.underscore}")
end
end
end
it "Encodes features filter (single)" do
Invidious::Search::Filters::Features.each do |value|
string = described_class.format_features(value)
filters = described_class.new(features: value)
expect("#{filters.to_iv_params}")
.to eq("features=" + FEATURES_TEXT[value])
end
end
it "Encodes features filter (multiple)" do
features = Invidious::Search::Filters::Features.flags(Subtitles, Live, ThreeSixty)
filters = described_class.new(features: features)
expect("#{filters.to_iv_params}")
.to eq("features=live%2Csubtitles%2C360") # %2C is a comma
end
it "Encodes sort filter" do
Invidious::Search::Filters::Sort.each do |value|
filters = described_class.new(sort: value)
params = filters.to_iv_params
if value.relevance?
expect("#{params}").to eq("")
else
expect("#{params}").to eq("sort=#{value.to_s.underscore}")
end
end
end
it "Encodes multiple filters" do
filters = described_class.new(
date: Invidious::Search::Filters::Date::Today,
duration: Invidious::Search::Filters::Duration::Medium,
features: Invidious::Search::Filters::Features.flags(Location, Purchased),
sort: Invidious::Search::Filters::Sort::Relevance
)
params = filters.to_iv_params
# Check the `date` param
expect(params).to have_key("date")
expect(params.fetch_all("date")).to contain_exactly("today")
# Check the `type` param
expect(params).to_not have_key("type")
expect(params["type"]?).to be_nil
# Check the `duration` param
expect(params).to have_key("duration")
expect(params.fetch_all("duration")).to contain_exactly("medium")
# Check the `features` param
expect(params).to have_key("features")
expect(params.fetch_all("features")).to contain_exactly("location,purchased")
# Check the `sort` param
expect(params).to_not have_key("sort")
expect(params["sort"]?).to be_nil
# Check if there aren't other parameters
params.delete("date")
params.delete("duration")
params.delete("features")
expect(params).to be_empty
end
end
end

View File

@ -0,0 +1,242 @@
require "../../../src/invidious/search/filters"
require "../../../src/invidious/search/query"
require "http/params"
require "spectator"
Spectator.configure do |config|
config.fail_blank
config.randomize
end
Spectator.describe Invidious::Search::Query do
describe Type::Regular do
# -------------------
# Query parsing
# -------------------
it "parses query with URL prameters (q)" do
query = described_class.new(
HTTP::Params.parse("q=What+is+Love+10+hour&type=video&duration=long"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Regular)
expect(query.channel).to be_empty
expect(query.text).to eq("What is Love 10 hour")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
type: Invidious::Search::Filters::Type::Video,
duration: Invidious::Search::Filters::Duration::Long
)
)
end
it "parses query with URL prameters (search_query)" do
query = described_class.new(
HTTP::Params.parse("search_query=What+is+Love+10+hour&type=video&duration=long"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Regular)
expect(query.channel).to be_empty
expect(query.text).to eq("What is Love 10 hour")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
type: Invidious::Search::Filters::Type::Video,
duration: Invidious::Search::Filters::Duration::Long
)
)
end
it "parses query with legacy filters (q)" do
query = described_class.new(
HTTP::Params.parse("q=Nyan+cat+duration:long"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Regular)
expect(query.channel).to be_empty
expect(query.text).to eq("Nyan cat")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
duration: Invidious::Search::Filters::Duration::Long
)
)
end
it "parses query with legacy filters (search_query)" do
query = described_class.new(
HTTP::Params.parse("search_query=Nyan+cat+duration:long"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Regular)
expect(query.channel).to be_empty
expect(query.text).to eq("Nyan cat")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
duration: Invidious::Search::Filters::Duration::Long
)
)
end
it "parses query with both URL params and legacy filters" do
query = described_class.new(
HTTP::Params.parse("q=Vamos+a+la+playa+duration:long&type=Video&date=year"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Regular)
expect(query.channel).to be_empty
expect(query.text).to eq("Vamos a la playa duration:long")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
type: Invidious::Search::Filters::Type::Video,
date: Invidious::Search::Filters::Date::Year
)
)
end
# -------------------
# Type switching
# -------------------
it "switches to channel search (URL param)" do
query = described_class.new(
HTTP::Params.parse("q=thunderbolt+4&channel=UC0vBXGSyV14uvJ4hECDOl0Q"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Channel)
expect(query.channel).to eq("UC0vBXGSyV14uvJ4hECDOl0Q")
expect(query.text).to eq("thunderbolt 4")
expect(query.filters.default?).to be_true
end
it "switches to channel search (legacy)" do
query = described_class.new(
HTTP::Params.parse("q=channel%3AUCRPdsCVuH53rcbTcEkuY4uQ+rdna3"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Channel)
expect(query.channel).to eq("UCRPdsCVuH53rcbTcEkuY4uQ")
expect(query.text).to eq("rdna3")
expect(query.filters.default?).to be_true
end
it "switches to subscriptions search" do
query = described_class.new(
HTTP::Params.parse("q=subscriptions:true+tunak+tunak+tun"),
Invidious::Search::Query::Type::Regular, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Subscriptions)
expect(query.channel).to be_empty
expect(query.text).to eq("tunak tunak tun")
expect(query.filters.default?).to be_true
end
end
describe Type::Channel do
it "ignores extra parameters" do
query = described_class.new(
HTTP::Params.parse("q=Take+on+me+channel%3AUC12345679&type=video&date=year"),
Invidious::Search::Query::Type::Channel, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Channel)
expect(query.channel).to be_empty
expect(query.text).to eq("Take on me")
expect(query.filters.default?).to be_true
end
end
describe Type::Subscriptions do
it "works" do
query = described_class.new(
HTTP::Params.parse("q=Harlem+shake&type=video&date=year"),
Invidious::Search::Query::Type::Subscriptions, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Subscriptions)
expect(query.channel).to be_empty
expect(query.text).to eq("Harlem shake")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
type: Invidious::Search::Filters::Type::Video,
date: Invidious::Search::Filters::Date::Year
)
)
end
end
describe Type::Playlist do
it "ignores extra parameters" do
query = described_class.new(
HTTP::Params.parse("q=Harlem+shake+type:video+date:year&channel=UC12345679"),
Invidious::Search::Query::Type::Playlist, nil
)
expect(query.type).to eq(Invidious::Search::Query::Type::Playlist)
expect(query.channel).to be_empty
expect(query.text).to eq("Harlem shake")
expect(query.filters).to eq(
Invidious::Search::Filters.new(
type: Invidious::Search::Filters::Type::Video,
date: Invidious::Search::Filters::Date::Year
)
)
end
end
describe "#to_http_params" do
it "formats regular search" do
query = described_class.new(
HTTP::Params.parse("q=The+Simpsons+hiding+in+bush&duration=short"),
Invidious::Search::Query::Type::Regular, nil
)
params = query.to_http_params
expect(params).to have_key("duration")
expect(params["duration"]?).to eq("short")
expect(params).to have_key("q")
expect(params["q"]?).to eq("The Simpsons hiding in bush")
# Check if there aren't other parameters
params.delete("duration")
params.delete("q")
expect(params).to be_empty
end
it "formats channel search" do
query = described_class.new(
HTTP::Params.parse("q=channel:UC2DjFE7Xf11URZqWBigcVOQ%20multimeter"),
Invidious::Search::Query::Type::Regular, nil
)
params = query.to_http_params
expect(params).to have_key("channel")
expect(params["channel"]?).to eq("UC2DjFE7Xf11URZqWBigcVOQ")
expect(params).to have_key("q")
expect(params["q"]?).to eq("multimeter")
# Check if there aren't other parameters
params.delete("channel")
params.delete("q")
expect(params).to be_empty
end
end
end

View File

@ -0,0 +1,143 @@
require "../../../src/invidious/search/filters"
require "http/params"
require "spectator"
Spectator.configure do |config|
config.fail_blank
config.randomize
end
# Encoded filter values are extracted from the search
# page of Youtube with any browser devtools HTML inspector.
DATE_FILTERS = {
Invidious::Search::Filters::Date::Hour => "EgIIAQ%3D%3D",
Invidious::Search::Filters::Date::Today => "EgIIAg%3D%3D",
Invidious::Search::Filters::Date::Week => "EgIIAw%3D%3D",
Invidious::Search::Filters::Date::Month => "EgIIBA%3D%3D",
Invidious::Search::Filters::Date::Year => "EgIIBQ%3D%3D",
}
TYPE_FILTERS = {
Invidious::Search::Filters::Type::Video => "EgIQAQ%3D%3D",
Invidious::Search::Filters::Type::Channel => "EgIQAg%3D%3D",
Invidious::Search::Filters::Type::Playlist => "EgIQAw%3D%3D",
Invidious::Search::Filters::Type::Movie => "EgIQBA%3D%3D",
}
DURATION_FILTERS = {
Invidious::Search::Filters::Duration::Short => "EgIYAQ%3D%3D",
Invidious::Search::Filters::Duration::Medium => "EgIYAw%3D%3D",
Invidious::Search::Filters::Duration::Long => "EgIYAg%3D%3D",
}
FEATURE_FILTERS = {
Invidious::Search::Filters::Features::Live => "EgJAAQ%3D%3D",
Invidious::Search::Filters::Features::FourK => "EgJwAQ%3D%3D",
Invidious::Search::Filters::Features::HD => "EgIgAQ%3D%3D",
Invidious::Search::Filters::Features::Subtitles => "EgIoAQ%3D%3D",
Invidious::Search::Filters::Features::CCommons => "EgIwAQ%3D%3D",
Invidious::Search::Filters::Features::ThreeSixty => "EgJ4AQ%3D%3D",
Invidious::Search::Filters::Features::VR180 => "EgPQAQE%3D",
Invidious::Search::Filters::Features::ThreeD => "EgI4AQ%3D%3D",
Invidious::Search::Filters::Features::HDR => "EgPIAQE%3D",
Invidious::Search::Filters::Features::Location => "EgO4AQE%3D",
Invidious::Search::Filters::Features::Purchased => "EgJIAQ%3D%3D",
}
SORT_FILTERS = {
Invidious::Search::Filters::Sort::Relevance => "",
Invidious::Search::Filters::Sort::Date => "CAI%3D",
Invidious::Search::Filters::Sort::Views => "CAM%3D",
Invidious::Search::Filters::Sort::Rating => "CAE%3D",
}
Spectator.describe Invidious::Search::Filters do
# -------------------
# Encode YT params
# -------------------
describe "#to_yt_params" do
sample DATE_FILTERS do |value, result|
it "Encodes upload date filter '#{value}'" do
expect(described_class.new(date: value).to_yt_params).to eq(result)
end
end
sample TYPE_FILTERS do |value, result|
it "Encodes content type filter '#{value}'" do
expect(described_class.new(type: value).to_yt_params).to eq(result)
end
end
sample DURATION_FILTERS do |value, result|
it "Encodes duration filter '#{value}'" do
expect(described_class.new(duration: value).to_yt_params).to eq(result)
end
end
sample FEATURE_FILTERS do |value, result|
it "Encodes feature filter '#{value}'" do
expect(described_class.new(features: value).to_yt_params).to eq(result)
end
end
sample SORT_FILTERS do |value, result|
it "Encodes sort filter '#{value}'" do
expect(described_class.new(sort: value).to_yt_params).to eq(result)
end
end
end
# -------------------
# Decode YT params
# -------------------
describe "#from_yt_params" do
sample DATE_FILTERS do |value, encoded|
it "Decodes upload date filter '#{value}'" do
params = HTTP::Params.parse("sp=#{encoded}")
expect(described_class.from_yt_params(params))
.to eq(described_class.new(date: value))
end
end
sample TYPE_FILTERS do |value, encoded|
it "Decodes content type filter '#{value}'" do
params = HTTP::Params.parse("sp=#{encoded}")
expect(described_class.from_yt_params(params))
.to eq(described_class.new(type: value))
end
end
sample DURATION_FILTERS do |value, encoded|
it "Decodes duration filter '#{value}'" do
params = HTTP::Params.parse("sp=#{encoded}")
expect(described_class.from_yt_params(params))
.to eq(described_class.new(duration: value))
end
end
sample FEATURE_FILTERS do |value, encoded|
it "Decodes feature filter '#{value}'" do
params = HTTP::Params.parse("sp=#{encoded}")
expect(described_class.from_yt_params(params))
.to eq(described_class.new(features: value))
end
end
sample SORT_FILTERS do |value, encoded|
it "Decodes sort filter '#{value}'" do
params = HTTP::Params.parse("sp=#{encoded}")
expect(described_class.from_yt_params(params))
.to eq(described_class.new(sort: value))
end
end
end
end

View File

@ -0,0 +1,113 @@
require "../../parsers_helper.cr"
Spectator.describe Invidious::Hashtag do
it "parses scheduled livestreams data (test 1)" do
# Enable mock
_player = load_mock("video/scheduled_live_nintendo.player")
_next = load_mock("video/scheduled_live_nintendo.next")
raw_data = _player.merge!(_next)
info = parse_video_info("QMGibBzTu0g", raw_data)
# Some basic verifications
expect(typeof(info)).to eq(Hash(String, JSON::Any))
expect(info["shortDescription"].as_s).to eq(
"Tune in on 6/22 at 7 a.m. PT for a livestreamed Xenoblade Chronicles 3 Direct presentation featuring roughly 20 minutes of information about the upcoming RPG adventure for Nintendo Switch."
)
expect(info["descriptionHtml"].as_s).to eq(
"Tune in on 6/22 at 7 a.m. PT for a livestreamed Xenoblade Chronicles 3 Direct presentation featuring roughly 20 minutes of information about the upcoming RPG adventure for Nintendo Switch."
)
expect(info["likes"].as_i).to eq(2_283)
expect(info["genre"].as_s).to eq("Gaming")
expect(info["genreUrl"].raw).to be_nil
expect(info["genreUcid"].as_s).to be_empty
expect(info["license"].as_s).to be_empty
expect(info["authorThumbnail"].as_s).to eq(
"https://yt3.ggpht.com/ytc/AKedOLTt4vtjREUUNdHlyu9c4gtJjG90M9jQheRlLKy44A=s48-c-k-c0x00ffffff-no-rj"
)
expect(info["authorVerified"].as_bool).to be_true
expect(info["subCountText"].as_s).to eq("8.5M")
expect(info["relatedVideos"].as_a.size).to eq(20)
# related video #1
expect(info["relatedVideos"][3]["id"].as_s).to eq("a-SN3lLIUEo")
expect(info["relatedVideos"][3]["author"].as_s).to eq("Nintendo")
expect(info["relatedVideos"][3]["ucid"].as_s).to eq("UCGIY_O-8vW4rfX98KlMkvRg")
expect(info["relatedVideos"][3]["view_count"].as_s).to eq("147796")
expect(info["relatedVideos"][3]["short_view_count"].as_s).to eq("147K")
expect(info["relatedVideos"][3]["author_verified"].as_s).to eq("true")
# Related video #2
expect(info["relatedVideos"][16]["id"].as_s).to eq("l_uC1jFK0lo")
expect(info["relatedVideos"][16]["author"].as_s).to eq("Nintendo")
expect(info["relatedVideos"][16]["ucid"].as_s).to eq("UCGIY_O-8vW4rfX98KlMkvRg")
expect(info["relatedVideos"][16]["view_count"].as_s).to eq("53510")
expect(info["relatedVideos"][16]["short_view_count"].as_s).to eq("53K")
expect(info["relatedVideos"][16]["author_verified"].as_s).to eq("true")
end
it "parses scheduled livestreams data (test 2)" do
# Enable mock
_player = load_mock("video/scheduled_live_PBD-Podcast.player")
_next = load_mock("video/scheduled_live_PBD-Podcast.next")
raw_data = _player.merge!(_next)
info = parse_video_info("RG0cjYbXxME", raw_data)
# Some basic verifications
expect(typeof(info)).to eq(Hash(String, JSON::Any))
expect(info["shortDescription"].as_s).to start_with(
<<-TXT
PBD Podcast Episode 171. In this episode, Patrick Bet-David is joined by Dr. Patrick Moore and Adam Sosnick.
Join the channel to get exclusive access to perks: https://bit.ly/3Q9rSQL
TXT
)
expect(info["descriptionHtml"].as_s).to start_with(
<<-TXT
PBD Podcast Episode 171. In this episode, Patrick Bet-David is joined by Dr. Patrick Moore and Adam Sosnick.
Join the channel to get exclusive access to perks: <a href="https://bit.ly/3Q9rSQL">bit.ly/3Q9rSQL</a>
TXT
)
expect(info["likes"].as_i).to eq(22)
expect(info["genre"].as_s).to eq("Entertainment")
expect(info["genreUrl"].raw).to be_nil
expect(info["genreUcid"].as_s).to be_empty
expect(info["license"].as_s).to be_empty
expect(info["authorThumbnail"].as_s).to eq(
"https://yt3.ggpht.com/61ArDiQshJrvSXcGLhpFfIO3hlMabe2fksitcf6oGob0Mdr5gztdkXxRljICUodL4iuTSrtxW4A=s48-c-k-c0x00ffffff-no-rj"
)
expect(info["authorVerified"].as_bool).to be_false
expect(info["subCountText"].as_s).to eq("227K")
expect(info["relatedVideos"].as_a.size).to eq(20)
# related video #1
expect(info["relatedVideos"][2]["id"]).to eq("La9oLLoI5Rc")
expect(info["relatedVideos"][2]["author"]).to eq("Tom Bilyeu")
expect(info["relatedVideos"][2]["ucid"]).to eq("UCnYMOamNKLGVlJgRUbamveA")
expect(info["relatedVideos"][2]["view_count"]).to eq("13329149")
expect(info["relatedVideos"][2]["short_view_count"]).to eq("13M")
expect(info["relatedVideos"][2]["author_verified"]).to eq("true")
# Related video #2
expect(info["relatedVideos"][9]["id"]).to eq("IQ_4fvpzYuA")
expect(info["relatedVideos"][9]["author"]).to eq("Business Today")
expect(info["relatedVideos"][9]["ucid"]).to eq("UCaPHWiExfUWaKsUtENLCv5w")
expect(info["relatedVideos"][9]["view_count"]).to eq("26432")
expect(info["relatedVideos"][9]["short_view_count"]).to eq("26K")
expect(info["relatedVideos"][9]["author_verified"]).to eq("true")
end
end

34
spec/parsers_helper.cr Normal file
View File

@ -0,0 +1,34 @@
require "db"
require "json"
require "kemal"
require "protodec/utils"
require "spectator"
require "../src/invidious/exceptions"
require "../src/invidious/helpers/macros"
require "../src/invidious/helpers/logger"
require "../src/invidious/helpers/utils"
require "../src/invidious/videos"
require "../src/invidious/comments"
require "../src/invidious/helpers/serialized_yt_data"
require "../src/invidious/yt_backend/extractors"
require "../src/invidious/yt_backend/extractors_utils"
OUTPUT = File.open(File::NULL, "w")
LOGGER = Invidious::LogHandler.new(OUTPUT, LogLevel::Off)
def load_mock(file) : Hash(String, JSON::Any)
file = File.join(__DIR__, "..", "mocks", file + ".json")
content = File.read(file)
return JSON.parse(content).as_h
end
Spectator.configure do |config|
config.fail_blank
config.randomize
end

View File

@ -8,7 +8,7 @@ require "../src/invidious/channels/*"
require "../src/invidious/videos"
require "../src/invidious/comments"
require "../src/invidious/playlists"
require "../src/invidious/search"
require "../src/invidious/search/ctoken"
require "../src/invidious/trending"
require "spectator"

View File

@ -0,0 +1,16 @@
# Overrides for Kemal's `content_for` macro in order to keep using
# kilt as it was before Kemal v1.1.1 (Kemal PR #618).
require "kemal"
require "kilt"
macro content_for(key, file = __FILE__)
%proc = ->() {
__kilt_io__ = IO::Memory.new
{{ yield }}
__kilt_io__.to_s
}
CONTENT_FOR_BLOCKS[{{key}}] = Tuple.new {{file}}, %proc
nil
end

View File

@ -111,7 +111,7 @@ module Kemal
if @fallthrough
call_next(context)
else
context.response.status_code = 405
context.response.status = HTTP::Status::METHOD_NOT_ALLOWED
context.response.headers.add("Allow", "GET, HEAD")
end
return
@ -124,7 +124,7 @@ module Kemal
# File path cannot contains '\0' (NUL) because all filesystem I know
# don't accept '\0' character as file name.
if request_path.includes? '\0'
context.response.status_code = 400
context.response.status = HTTP::Status::BAD_REQUEST
return
end
@ -143,13 +143,15 @@ module Kemal
add_cache_headers(context.response.headers, last_modified)
if cache_request?(context, last_modified)
context.response.status_code = 304
context.response.status = HTTP::Status::NOT_MODIFIED
return
end
send_file(context, file_path, file[:data], file[:filestat])
else
is_dir = Dir.exists? file_path
file_info = File.info?(file_path)
is_dir = file_info.try &.directory? || false
is_file = file_info.try &.file? || false
if request_path != expanded_path
redirect_to context, expanded_path
@ -157,19 +159,21 @@ module Kemal
redirect_to context, expanded_path + '/'
end
if Dir.exists?(file_path)
return call_next(context) if file_info.nil?
if is_dir
if config.is_a?(Hash) && config["dir_listing"] == true
context.response.content_type = "text/html"
directory_listing(context.response, request_path, file_path)
else
call_next(context)
end
elsif File.exists?(file_path)
last_modified = modification_time(file_path)
elsif is_file
last_modified = file_info.modification_time
add_cache_headers(context.response.headers, last_modified)
if cache_request?(context, last_modified)
context.response.status_code = 304
context.response.status = HTTP::Status::NOT_MODIFIED
return
end
@ -177,14 +181,12 @@ module Kemal
data = Bytes.new(size)
File.open(file_path, &.read(data))
filestat = File.info(file_path)
@cached_files[file_path] = {data: data, filestat: filestat}
send_file(context, file_path, data, filestat)
@cached_files[file_path] = {data: data, filestat: file_info}
send_file(context, file_path, data, file_info)
else
send_file(context, file_path)
end
else
else # Not a normal file (FIFO/device/socket)
call_next(context)
end
end

View File

@ -16,7 +16,13 @@
require "digest/md5"
require "file_utils"
# Require kemal, kilt, then our own overrides
require "kemal"
require "kilt"
require "./ext/kemal_content_for.cr"
require "./ext/kemal_static_file_handler.cr"
require "athena-negotiation"
require "openssl/hmac"
require "option_parser"
@ -27,6 +33,7 @@ require "compress/zip"
require "protodec/utils"
require "./invidious/database/*"
require "./invidious/database/migrations/*"
require "./invidious/helpers/*"
require "./invidious/yt_backend/*"
require "./invidious/frontend/*"
@ -34,6 +41,7 @@ require "./invidious/frontend/*"
require "./invidious/*"
require "./invidious/channels/*"
require "./invidious/user/*"
require "./invidious/search/*"
require "./invidious/routes/**"
require "./invidious/jobs/**"
@ -102,6 +110,10 @@ Kemal.config.extra_options do |parser|
puts SOFTWARE.to_pretty_json
exit
end
parser.on("--migrate", "Run any migrations (beta, use at your own risk!!") do
Invidious::Database::Migrator.new(PG_DB).migrate
exit
end
end
Kemal::CLI.new ARGV
@ -121,12 +133,13 @@ Invidious::Database.check_integrity(CONFIG)
# Running the script by itself would show some colorful feedback while this doesn't.
# Perhaps we should just move the script to runtime in order to get that feedback?
{% puts "\nChecking player dependencies...\n" %}
{% puts "\nChecking player dependencies, this may take more than 20 minutes... If it is stuck, check your internet connection.\n" %}
{% if flag?(:minified_player_dependencies) %}
{% puts run("../scripts/fetch-player-dependencies.cr", "--minified").stringify %}
{% else %}
{% puts run("../scripts/fetch-player-dependencies.cr").stringify %}
{% end %}
{% puts "\nDone checking player dependencies, now compiling Invidious...\n" %}
{% end %}
# Start jobs
@ -165,304 +178,19 @@ def popular_videos
Invidious::Jobs::PullPopularVideosJob::POPULAR_VIDEOS.get
end
# Routing
before_all do |env|
preferences = Preferences.from_json("{}")
begin
if prefs_cookie = env.request.cookies["PREFS"]?
preferences = Preferences.from_json(URI.decode_www_form(prefs_cookie.value))
else
if language_header = env.request.headers["Accept-Language"]?
if language = ANG.language_negotiator.best(language_header, LOCALES.keys)
preferences.locale = language.header
end
end
end
rescue
preferences = Preferences.from_json("{}")
end
env.set "preferences", preferences
env.response.headers["X-XSS-Protection"] = "1; mode=block"
env.response.headers["X-Content-Type-Options"] = "nosniff"
# Allow media resources to be loaded from google servers
# TODO: check if *.youtube.com can be removed
if CONFIG.disabled?("local") || !preferences.local
extra_media_csp = " https://*.googlevideo.com:443 https://*.youtube.com:443"
else
extra_media_csp = ""
end
# Only allow the pages at /embed/* to be embedded
if env.request.resource.starts_with?("/embed")
frame_ancestors = "'self' http: https:"
else
frame_ancestors = "'none'"
end
# TODO: Remove style-src's 'unsafe-inline', requires to remove all
# inline styles (<style> [..] </style>, style=" [..] ")
env.response.headers["Content-Security-Policy"] = {
"default-src 'none'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"font-src 'self' data:",
"connect-src 'self'",
"manifest-src 'self'",
"media-src 'self' blob:" + extra_media_csp,
"child-src 'self' blob:",
"frame-src 'self'",
"frame-ancestors " + frame_ancestors,
}.join("; ")
env.response.headers["Referrer-Policy"] = "same-origin"
# Ask the chrom*-based browsers to disable FLoC
# See: https://blog.runcloud.io/google-floc/
env.response.headers["Permissions-Policy"] = "interest-cohort=()"
if (Kemal.config.ssl || CONFIG.https_only) && CONFIG.hsts
env.response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload"
end
next if {
"/sb/",
"/vi/",
"/s_p/",
"/yts/",
"/ggpht/",
"/api/manifest/",
"/videoplayback",
"/latest_version",
"/download",
}.any? { |r| env.request.resource.starts_with? r }
if env.request.cookies.has_key? "SID"
sid = env.request.cookies["SID"].value
if sid.starts_with? "v1:"
raise "Cannot use token as SID"
end
# Invidious users only have SID
if !env.request.cookies.has_key? "SSID"
if email = Invidious::Database::SessionIDs.select_email(sid)
user = Invidious::Database::Users.select!(email: email)
csrf_token = generate_response(sid, {
":authorize_token",
":playlist_ajax",
":signout",
":subscription_ajax",
":token_ajax",
":watch_ajax",
}, HMAC_KEY, 1.week)
preferences = user.preferences
env.set "preferences", preferences
env.set "sid", sid
env.set "csrf_token", csrf_token
env.set "user", user
end
else
headers = HTTP::Headers.new
headers["Cookie"] = env.request.headers["Cookie"]
begin
user, sid = get_user(sid, headers, false)
csrf_token = generate_response(sid, {
":authorize_token",
":playlist_ajax",
":signout",
":subscription_ajax",
":token_ajax",
":watch_ajax",
}, HMAC_KEY, 1.week)
preferences = user.preferences
env.set "preferences", preferences
env.set "sid", sid
env.set "csrf_token", csrf_token
env.set "user", user
rescue ex
end
end
end
dark_mode = convert_theme(env.params.query["dark_mode"]?) || preferences.dark_mode.to_s
thin_mode = env.params.query["thin_mode"]? || preferences.thin_mode.to_s
thin_mode = thin_mode == "true"
locale = env.params.query["hl"]? || preferences.locale
preferences.dark_mode = dark_mode
preferences.thin_mode = thin_mode
preferences.locale = locale
env.set "preferences", preferences
current_page = env.request.path
if env.request.query
query = HTTP::Params.parse(env.request.query.not_nil!)
if query["referer"]?
query["referer"] = get_referer(env, "/")
end
current_page += "?#{query}"
end
env.set "current_page", URI.encode_www_form(current_page)
Invidious::Routes::BeforeAll.handle(env)
end
{% unless flag?(:api_only) %}
Invidious::Routing.get "/", Invidious::Routes::Misc, :home
Invidious::Routing.get "/privacy", Invidious::Routes::Misc, :privacy
Invidious::Routing.get "/licenses", Invidious::Routes::Misc, :licenses
Invidious::Routing.get "/channel/:ucid", Invidious::Routes::Channels, :home
Invidious::Routing.get "/channel/:ucid/home", Invidious::Routes::Channels, :home
Invidious::Routing.get "/channel/:ucid/videos", Invidious::Routes::Channels, :videos
Invidious::Routing.get "/channel/:ucid/playlists", Invidious::Routes::Channels, :playlists
Invidious::Routing.get "/channel/:ucid/community", Invidious::Routes::Channels, :community
Invidious::Routing.get "/channel/:ucid/about", Invidious::Routes::Channels, :about
Invidious::Routing.get "/channel/:ucid/live", Invidious::Routes::Channels, :live
Invidious::Routing.get "/user/:user/live", Invidious::Routes::Channels, :live
Invidious::Routing.get "/c/:user/live", Invidious::Routes::Channels, :live
["", "/videos", "/playlists", "/community", "/about"].each do |path|
# /c/LinusTechTips
Invidious::Routing.get "/c/:user#{path}", Invidious::Routes::Channels, :brand_redirect
# /user/linustechtips | Not always the same as /c/
Invidious::Routing.get "/user/:user#{path}", Invidious::Routes::Channels, :brand_redirect
# /attribution_link?a=anything&u=/channel/UCZYTClx2T1of7BRZ86-8fow
Invidious::Routing.get "/attribution_link#{path}", Invidious::Routes::Channels, :brand_redirect
# /profile?user=linustechtips
Invidious::Routing.get "/profile/#{path}", Invidious::Routes::Channels, :profile
end
Invidious::Routing.get "/watch", Invidious::Routes::Watch, :handle
Invidious::Routing.post "/watch_ajax", Invidious::Routes::Watch, :mark_watched
Invidious::Routing.get "/watch/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/shorts/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/clip/:clip", Invidious::Routes::Watch, :clip
Invidious::Routing.get "/w/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/v/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/e/:id", Invidious::Routes::Watch, :redirect
Invidious::Routing.get "/redirect", Invidious::Routes::Misc, :cross_instance_redirect
Invidious::Routing.post "/download", Invidious::Routes::Watch, :download
Invidious::Routing.get "/embed/", Invidious::Routes::Embed, :redirect
Invidious::Routing.get "/embed/:id", Invidious::Routes::Embed, :show
Invidious::Routing.get "/create_playlist", Invidious::Routes::Playlists, :new
Invidious::Routing.post "/create_playlist", Invidious::Routes::Playlists, :create
Invidious::Routing.get "/subscribe_playlist", Invidious::Routes::Playlists, :subscribe
Invidious::Routing.get "/delete_playlist", Invidious::Routes::Playlists, :delete_page
Invidious::Routing.post "/delete_playlist", Invidious::Routes::Playlists, :delete
Invidious::Routing.get "/edit_playlist", Invidious::Routes::Playlists, :edit
Invidious::Routing.post "/edit_playlist", Invidious::Routes::Playlists, :update
Invidious::Routing.get "/add_playlist_items", Invidious::Routes::Playlists, :add_playlist_items_page
Invidious::Routing.post "/playlist_ajax", Invidious::Routes::Playlists, :playlist_ajax
Invidious::Routing.get "/playlist", Invidious::Routes::Playlists, :show
Invidious::Routing.get "/mix", Invidious::Routes::Playlists, :mix
Invidious::Routing.get "/watch_videos", Invidious::Routes::Playlists, :watch_videos
Invidious::Routing.get "/opensearch.xml", Invidious::Routes::Search, :opensearch
Invidious::Routing.get "/results", Invidious::Routes::Search, :results
Invidious::Routing.get "/search", Invidious::Routes::Search, :search
# User routes
define_user_routes()
# Feeds
Invidious::Routing.get "/view_all_playlists", Invidious::Routes::Feeds, :view_all_playlists_redirect
Invidious::Routing.get "/feed/playlists", Invidious::Routes::Feeds, :playlists
Invidious::Routing.get "/feed/popular", Invidious::Routes::Feeds, :popular
Invidious::Routing.get "/feed/trending", Invidious::Routes::Feeds, :trending
Invidious::Routing.get "/feed/subscriptions", Invidious::Routes::Feeds, :subscriptions
Invidious::Routing.get "/feed/history", Invidious::Routes::Feeds, :history
# RSS Feeds
Invidious::Routing.get "/feed/channel/:ucid", Invidious::Routes::Feeds, :rss_channel
Invidious::Routing.get "/feed/private", Invidious::Routes::Feeds, :rss_private
Invidious::Routing.get "/feed/playlist/:plid", Invidious::Routes::Feeds, :rss_playlist
Invidious::Routing.get "/feeds/videos.xml", Invidious::Routes::Feeds, :rss_videos
# Support push notifications via PubSubHubbub
Invidious::Routing.get "/feed/webhook/:token", Invidious::Routes::Feeds, :push_notifications_get
Invidious::Routing.post "/feed/webhook/:token", Invidious::Routes::Feeds, :push_notifications_post
Invidious::Routing.get "/modify_notifications", Invidious::Routes::Notifications, :modify
Invidious::Routing.post "/subscription_ajax", Invidious::Routes::Subscriptions, :toggle_subscription
Invidious::Routing.get "/subscription_manager", Invidious::Routes::Subscriptions, :subscription_manager
{% end %}
Invidious::Routing.get "/ggpht/*", Invidious::Routes::Images, :ggpht
Invidious::Routing.options "/sb/:authority/:id/:storyboard/:index", Invidious::Routes::Images, :options_storyboard
Invidious::Routing.get "/sb/:authority/:id/:storyboard/:index", Invidious::Routes::Images, :get_storyboard
Invidious::Routing.get "/s_p/:id/:name", Invidious::Routes::Images, :s_p_image
Invidious::Routing.get "/yts/img/:name", Invidious::Routes::Images, :yts_image
Invidious::Routing.get "/vi/:id/:name", Invidious::Routes::Images, :thumbnails
# API routes (macro)
define_v1_api_routes()
# Video playback (macros)
define_api_manifest_routes()
define_video_playback_routes()
Invidious::Routing.register_all
error 404 do |env|
if md = env.request.path.match(/^\/(?<id>([a-zA-Z0-9_-]{11})|(\w+))$/)
item = md["id"]
# Check if item is branding URL e.g. https://youtube.com/gaming
response = YT_POOL.client &.get("/#{item}")
if response.status_code == 301
response = YT_POOL.client &.get(URI.parse(response.headers["Location"]).request_target)
end
if response.body.empty?
env.response.headers["Location"] = "/"
halt env, status_code: 302
end
html = XML.parse_html(response.body)
ucid = html.xpath_node(%q(//link[@rel="canonical"])).try &.["href"].split("/")[-1]
if ucid
env.response.headers["Location"] = "/channel/#{ucid}"
halt env, status_code: 302
end
params = [] of String
env.params.query.each do |k, v|
params << "#{k}=#{v}"
end
params = params.join("&")
url = "/watch?v=#{item}"
if !params.empty?
url += "&#{params}"
end
# Check if item is video ID
if item.match(/^[a-zA-Z0-9_-]{11}$/) && YT_POOL.client &.head("/watch?v=#{item}").status_code != 404
env.response.headers["Location"] = url
halt env, status_code: 302
end
end
env.response.headers["Location"] = "/"
halt env, status_code: 302
Invidious::Routes::ErrorRoutes.error_404(env)
end
error 500 do |env, ex|
locale = env.get("preferences").as(Preferences).locale
error_template(500, ex)
end
@ -470,6 +198,8 @@ static_headers do |response|
response.headers.add("Cache-Control", "max-age=2629800")
end
# Init Kemal
public_folder "assets"
Kemal.config.powered_by_header = false

View File

@ -6,13 +6,15 @@ record AboutChannel,
author_url : String,
author_thumbnail : String,
banner : String?,
description : String,
description_html : String,
total_views : Int64,
sub_count : Int32,
joined : Time,
is_family_friendly : Bool,
allowed_regions : Array(String),
tabs : Array(String)
tabs : Array(String),
verified : Bool
record AboutRelatedChannel,
ucid : String,
@ -29,7 +31,12 @@ def get_about_info(ucid, locale) : AboutChannel
end
if initdata.dig?("alerts", 0, "alertRenderer", "type") == "ERROR"
raise InfoException.new(initdata["alerts"][0]["alertRenderer"]["text"]["simpleText"].as_s)
error_message = initdata["alerts"][0]["alertRenderer"]["text"]["simpleText"].as_s
if error_message == "This channel does not exist."
raise NotFoundException.new(error_message)
else
raise InfoException.new(error_message)
end
end
if browse_endpoint = initdata["onResponseReceivedActions"]?.try &.[0]?.try &.["navigateAction"]?.try &.["endpoint"]?.try &.["browseEndpoint"]?
@ -51,15 +58,12 @@ def get_about_info(ucid, locale) : AboutChannel
banners = initdata["header"]["interactiveTabbedHeaderRenderer"]?.try &.["banner"]?.try &.["thumbnails"]?
banner = banners.try &.[-1]?.try &.["url"].as_s?
description = initdata["header"]["interactiveTabbedHeaderRenderer"]["description"]["simpleText"].as_s
description_html = HTML.escape(description)
is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool
allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map(&.as_s)
description_node = initdata["header"]["interactiveTabbedHeaderRenderer"]["description"]
else
author = initdata["metadata"]["channelMetadataRenderer"]["title"].as_s
author_url = initdata["metadata"]["channelMetadataRenderer"]["channelUrl"].as_s
author_thumbnail = initdata["metadata"]["channelMetadataRenderer"]["avatar"]["thumbnails"][0]["url"].as_s
author_verified = has_verified_badge?(initdata.dig?("header", "c4TabbedHeaderRenderer", "badges"))
ucid = initdata["metadata"]["channelMetadataRenderer"]["externalId"].as_s
@ -71,11 +75,26 @@ def get_about_info(ucid, locale) : AboutChannel
# banner = nil
# end
description = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?.try &.as_s? || ""
description_html = HTML.escape(description)
description_node = initdata["metadata"]["channelMetadataRenderer"]?.try &.["description"]?
end
is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool
allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map(&.as_s)
is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool
allowed_regions = initdata
.dig?("microformat", "microformatDataRenderer", "availableCountries")
.try &.as_a.map(&.as_s) || [] of String
description = !description_node.nil? ? description_node.as_s : ""
description_html = HTML.escape(description)
if !description_node.nil?
if description_node.as_h?.nil?
description_node = text_to_parsed_content(description_node.as_s)
end
description_html = parse_content(description_node)
if description_html == "" && description != ""
description_html = HTML.escape(description)
end
end
total_views = 0_i64
@ -121,6 +140,7 @@ def get_about_info(ucid, locale) : AboutChannel
author_url: author_url,
author_thumbnail: author_thumbnail,
banner: banner,
description: description,
description_html: description_html,
total_views: total_views,
sub_count: sub_count,
@ -128,6 +148,7 @@ def get_about_info(ucid, locale) : AboutChannel
is_family_friendly: is_family_friendly,
allowed_regions: allowed_regions,
tabs: tabs,
verified: author_verified || false,
)
end

View File

@ -226,7 +226,7 @@ def fetch_channel(ucid, pull_all_videos : Bool)
# meaning the above timestamp is always null
was_insert = Invidious::Database::ChannelVideos.insert(video)
if preferences.notifications && was_insert
if was_insert
LOGGER.trace("fetch_channel: #{ucid} : video #{video_id} : Inserted, updating subscriptions")
Invidious::Database::Users.add_notification(video)
else
@ -264,9 +264,7 @@ def fetch_channel(ucid, pull_all_videos : Bool)
# so since they don't provide a published date here we can safely ignore them.
if Time.utc - video.published > 1.minute
was_insert = Invidious::Database::ChannelVideos.insert(video)
if preferences.notifications && was_insert
Invidious::Database::Users.add_notification(video)
end
Invidious::Database::Users.add_notification(video) if was_insert
end
end

View File

@ -6,20 +6,18 @@ def fetch_channel_community(ucid, continuation, locale, format, thin_mode)
end
if response.status_code != 200
raise InfoException.new("This channel does not exist.")
raise NotFoundException.new("This channel does not exist.")
end
ucid = response.body.match(/https:\/\/www.youtube.com\/channel\/(?<ucid>UC[a-zA-Z0-9_-]{22})/).not_nil!["ucid"]
if !continuation || continuation.empty?
initial_data = extract_initial_data(response.body)
body = initial_data["contents"]?.try &.["twoColumnBrowseResultsRenderer"]["tabs"].as_a.select { |tab| tab["tabRenderer"]?.try &.["selected"].as_bool.== true }[0]?
body = extract_selected_tab(initial_data["contents"]["twoColumnBrowseResultsRenderer"]["tabs"])["content"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]
if !body
raise InfoException.new("Could not extract community tab.")
end
body = body["tabRenderer"]["content"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]
else
continuation = produce_channel_community_continuation(ucid, continuation)
@ -49,7 +47,11 @@ def fetch_channel_community(ucid, continuation, locale, format, thin_mode)
error_message = (message["text"]["simpleText"]? ||
message["text"]["runs"]?.try &.[0]?.try &.["text"]?)
.try &.as_s || ""
raise InfoException.new(error_message)
if error_message == "This channel does not exist."
raise NotFoundException.new(error_message)
else
raise InfoException.new(error_message)
end
end
response = JSON.build do |json|

View File

@ -95,7 +95,7 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b
contents = body["contents"]?
header = body["header"]?
else
raise InfoException.new("Could not fetch comments")
raise NotFoundException.new("Comments not found.")
end
if !contents
@ -143,9 +143,11 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b
node_comment = node["commentRenderer"]
end
content_html = node_comment["contentText"]?.try { |t| parse_content(t) } || ""
content_html = node_comment["contentText"]?.try { |t| parse_content(t, id) } || ""
author = node_comment["authorText"]?.try &.["simpleText"]? || ""
json.field "verified", (node_comment["authorCommentBadge"]? != nil)
json.field "author", author
json.field "authorThumbnails" do
json.array do
@ -288,7 +290,7 @@ def fetch_reddit_comments(id, sort_by = "confidence")
thread = result[0].data.as(RedditListing).children[0].data.as(RedditLink)
else
raise InfoException.new("Could not fetch comments")
raise NotFoundException.new("Comments not found.")
end
client.close
@ -329,7 +331,11 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
end
author_name = HTML.escape(child["author"].as_s)
if child["verified"]?.try &.as_bool && child["authorIsChannelOwner"]?.try &.as_bool
author_name += "&nbsp;<i class=\"icon ion ion-md-checkmark-circle\"></i>"
elsif child["verified"]?.try &.as_bool
author_name += "&nbsp;<i class=\"icon ion ion-md-checkmark\"></i>"
end
html << <<-END_HTML
<div class="pure-g" style="width:100%">
<div class="channel-profile pure-u-4-24 pure-u-md-2-24">
@ -475,7 +481,7 @@ def template_reddit_comments(root, locale)
html << <<-END_HTML
<p>
<a href="javascript:void(0)" data-onclick="toggle_parent">[ - ]</a>
<a href="javascript:void(0)" data-onclick="toggle_parent">[ ]</a>
<b><a href="https://www.reddit.com/user/#{child.author}">#{child.author}</a></b>
#{translate_count(locale, "comments_points_count", child.score, NumberFormatting::Separator)}
<span title="#{child.created_utc.to_s(translate(locale, "%a %B %-d %T %Y UTC"))}">#{translate(locale, "`x` ago", recode_date(child.created_utc, locale))}</span>
@ -494,6 +500,12 @@ def template_reddit_comments(root, locale)
end
def replace_links(html)
# Check if the document is empty
# Prevents edge-case bug with Reddit comments, see issue #3115
if html.nil? || html.empty?
return html
end
html = XML.parse_html(html)
html.xpath_nodes(%q(//a)).each do |anchor|
@ -535,6 +547,12 @@ def replace_links(html)
end
def fill_links(html, scheme, host)
# Check if the document is empty
# Prevents edge-case bug with Reddit comments, see issue #3115
if html.nil? || html.empty?
return html
end
html = XML.parse_html(html)
html.xpath_nodes("//a").each do |match|
@ -554,26 +572,65 @@ def fill_links(html, scheme, host)
return html.to_xml(options: XML::SaveOptions::NO_DECL)
end
def parse_content(content : JSON::Any) : String
content["simpleText"]?.try &.as_s.rchop('\ufeff').try { |b| HTML.escape(b) }.to_s ||
content["runs"]?.try &.as_a.try { |r| content_to_comment_html(r).try &.to_s.gsub("\n", "<br>") } || ""
def text_to_parsed_content(text : String) : JSON::Any
nodes = [] of JSON::Any
# For each line convert line to array of nodes
text.split('\n').each do |line|
# In first case line is just a simple node before
# check patterns inside line
# { 'text': line }
currentNodes = [] of JSON::Any
initialNode = {"text" => line}
currentNodes << (JSON.parse(initialNode.to_json))
# For each match with url pattern, get last node and preserve
# last node before create new node with url information
# { 'text': match, 'navigationEndpoint': { 'urlEndpoint' : 'url': match } }
line.scan(/https?:\/\/[^ ]*/).each do |urlMatch|
# Retrieve last node and update node without match
lastNode = currentNodes[currentNodes.size - 1].as_h
splittedLastNode = lastNode["text"].as_s.split(urlMatch[0])
lastNode["text"] = JSON.parse(splittedLastNode[0].to_json)
currentNodes[currentNodes.size - 1] = JSON.parse(lastNode.to_json)
# Create new node with match and navigation infos
currentNode = {"text" => urlMatch[0], "navigationEndpoint" => {"urlEndpoint" => {"url" => urlMatch[0]}}}
currentNodes << (JSON.parse(currentNode.to_json))
# If text remain after match create new simple node with text after match
afterNode = {"text" => splittedLastNode.size > 0 ? splittedLastNode[1] : ""}
currentNodes << (JSON.parse(afterNode.to_json))
end
# After processing of matches inside line
# Add \n at end of last node for preserve carriage return
lastNode = currentNodes[currentNodes.size - 1].as_h
lastNode["text"] = JSON.parse("#{currentNodes[currentNodes.size - 1]["text"]}\n".to_json)
currentNodes[currentNodes.size - 1] = JSON.parse(lastNode.to_json)
# Finally add final nodes to nodes returned
currentNodes.each do |node|
nodes << (node)
end
end
return JSON.parse({"runs" => nodes}.to_json)
end
def content_to_comment_html(content)
comment_html = content.map do |run|
def parse_content(content : JSON::Any, video_id : String? = "") : String
content["simpleText"]?.try &.as_s.rchop('\ufeff').try { |b| HTML.escape(b) }.to_s ||
content["runs"]?.try &.as_a.try { |r| content_to_comment_html(r, video_id).try &.to_s.gsub("\n", "<br>") } || ""
end
def content_to_comment_html(content, video_id : String? = "")
html_array = content.map do |run|
# Sometimes, there is an empty element.
# See: https://github.com/iv-org/invidious/issues/3096
next if run.as_h.empty?
text = HTML.escape(run["text"].as_s)
if run["bold"]?
text = "<b>#{text}</b>"
end
if run["italics"]?
text = "<i>#{text}</i>"
end
if run["navigationEndpoint"]?
if url = run["navigationEndpoint"]["urlEndpoint"]?.try &.["url"].as_s
url = URI.parse(url)
displayed_url = text
if url.host == "youtu.be"
url = "/watch?v=#{url.request_target.lstrip('/')}"
@ -581,31 +638,53 @@ def content_to_comment_html(content)
if url.path == "/redirect"
# Sometimes, links can be corrupted (why?) so make sure to fallback
# nicely. See https://github.com/iv-org/invidious/issues/2682
url = HTTP::Params.parse(url.query.not_nil!)["q"]? || ""
url = url.query_params["q"]? || ""
displayed_url = url
else
url = url.request_target
displayed_url = "youtube.com#{url}"
end
end
text = %(<a href="#{url}">#{text}</a>)
text = %(<a href="#{url}">#{reduce_uri(displayed_url)}</a>)
elsif watch_endpoint = run["navigationEndpoint"]["watchEndpoint"]?
length_seconds = watch_endpoint["startTimeSeconds"]?
video_id = watch_endpoint["videoId"].as_s
start_time = watch_endpoint["startTimeSeconds"]?.try &.as_i
link_video_id = watch_endpoint["videoId"].as_s
if length_seconds && length_seconds.as_i > 0
text = %(<a href="javascript:void(0)" data-onclick="jump_to_time" data-jump-time="#{length_seconds}">#{text}</a>)
url = "/watch?v=#{link_video_id}"
url += "&t=#{start_time}" if !start_time.nil?
# If the current video ID (passed through from the caller function)
# is the same as the video ID in the link, add HTML attributes for
# the JS handler function that bypasses page reload.
#
# See: https://github.com/iv-org/invidious/issues/3063
if link_video_id == video_id
start_time ||= 0
text = %(<a href="#{url}" data-onclick="jump_to_time" data-jump-time="#{start_time}">#{reduce_uri(text)}</a>)
else
text = %(<a href="/watch?v=#{video_id}">#{text}</a>)
text = %(<a href="#{url}">#{text}</a>)
end
elsif url = run.dig?("navigationEndpoint", "commandMetadata", "webCommandMetadata", "url").try &.as_s
text = %(<a href="#{url}">#{text}</a>)
if text.starts_with?(/\s?[@#]/)
# Handle "pings" in comments and hasthags differently
# See:
# - https://github.com/iv-org/invidious/issues/3038
# - https://github.com/iv-org/invidious/issues/3062
text = %(<a href="#{url}">#{text}</a>)
else
text = %(<a href="#{url}">#{reduce_uri(url)}</a>)
end
end
end
text
end.join("").delete('\ufeff')
text = "<b>#{text}</b>" if run["bold"]?
text = "<i>#{text}</i>" if run["italics"]?
return comment_html
text
end
return html_array.join("").delete('\ufeff')
end
def produce_comment_continuation(video_id, cursor = "", sort_by = "top")

View File

@ -24,7 +24,6 @@ struct ConfigPreferences
property local : Bool = false
property locale : String = "en-US"
property watch_history : Bool = true
property notifications : Bool = true
property max_results : Int32 = 40
property notifications_only : Bool = false
property player_style : String = "invidious"
@ -76,7 +75,7 @@ class Config
@[YAML::Field(converter: Preferences::URIConverter)]
property database_url : URI = URI.parse("")
# Use polling to keep decryption function up to date
property decrypt_polling : Bool = true
property decrypt_polling : Bool = false
# Used for crawling channels: threads should check all videos uploaded by a channel
property full_refresh : Bool = false
# Used to tell Invidious it is behind a proxy, so links to resources should be https://
@ -162,16 +161,13 @@ class Config
{% env_id = "INVIDIOUS_#{ivar.id.upcase}" %}
if ENV.has_key?({{env_id}})
# puts %(Config.{{ivar.id}} : Loading from env var {{env_id}})
env_value = ENV.fetch({{env_id}})
success = false
# Use YAML converter if specified
{% ann = ivar.annotation(::YAML::Field) %}
{% if ann && ann[:converter] %}
puts %(Config.{{ivar.id}} : Parsing "#{env_value}" as {{ivar.type}} with {{ann[:converter]}} converter)
config.{{ivar.id}} = {{ann[:converter]}}.from_yaml(YAML::ParseContext.new, YAML::Nodes.parse(ENV.fetch({{env_id}})).nodes[0])
puts %(Config.{{ivar.id}} : Set to #{config.{{ivar.id}}})
success = true
# Use regular YAML parser otherwise
@ -182,9 +178,7 @@ class Config
{{ivar_types}}.each do |ivar_type|
if !success
begin
# puts %(Config.{{ivar.id}} : Trying to parse "#{env_value}" as #{ivar_type})
config.{{ivar.id}} = ivar_type.from_yaml(env_value)
puts %(Config.{{ivar.id}} : Set to #{config.{{ivar.id}}} (#{ivar_type}))
success = true
rescue
# nop

View File

@ -0,0 +1,38 @@
abstract class Invidious::Database::Migration
macro inherited
Migrator.migrations << self
end
@@version : Int64?
def self.version(version : Int32 | Int64)
@@version = version.to_i64
end
getter? completed = false
def initialize(@db : DB::Database)
end
abstract def up(conn : DB::Connection)
def migrate
# migrator already ignores completed migrations
# but this is an extra check to make sure a migration doesn't run twice
return if completed?
@db.transaction do |txn|
up(txn.connection)
track(txn.connection)
@completed = true
end
end
def version : Int64
@@version.not_nil!
end
private def track(conn : DB::Connection)
conn.exec("INSERT INTO #{Migrator::MIGRATIONS_TABLE} (version) VALUES ($1)", version)
end
end

View File

@ -0,0 +1,30 @@
module Invidious::Database::Migrations
class CreateChannelsTable < Migration
version 1
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE TABLE IF NOT EXISTS public.channels
(
id text NOT NULL,
author text,
updated timestamp with time zone,
deleted boolean,
subscribed timestamp with time zone,
CONSTRAINT channels_id_key UNIQUE (id)
);
SQL
conn.exec <<-SQL
GRANT ALL ON TABLE public.channels TO current_user;
SQL
conn.exec <<-SQL
CREATE INDEX IF NOT EXISTS channels_id_idx
ON public.channels
USING btree
(id COLLATE pg_catalog."default");
SQL
end
end
end

View File

@ -0,0 +1,28 @@
module Invidious::Database::Migrations
class CreateVideosTable < Migration
version 2
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE UNLOGGED TABLE IF NOT EXISTS public.videos
(
id text NOT NULL,
info text,
updated timestamp with time zone,
CONSTRAINT videos_pkey PRIMARY KEY (id)
);
SQL
conn.exec <<-SQL
GRANT ALL ON TABLE public.videos TO current_user;
SQL
conn.exec <<-SQL
CREATE UNIQUE INDEX IF NOT EXISTS id_idx
ON public.videos
USING btree
(id COLLATE pg_catalog."default");
SQL
end
end
end

View File

@ -0,0 +1,35 @@
module Invidious::Database::Migrations
class CreateChannelVideosTable < Migration
version 3
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE TABLE IF NOT EXISTS public.channel_videos
(
id text NOT NULL,
title text,
published timestamp with time zone,
updated timestamp with time zone,
ucid text,
author text,
length_seconds integer,
live_now boolean,
premiere_timestamp timestamp with time zone,
views bigint,
CONSTRAINT channel_videos_id_key UNIQUE (id)
);
SQL
conn.exec <<-SQL
GRANT ALL ON TABLE public.channel_videos TO current_user;
SQL
conn.exec <<-SQL
CREATE INDEX IF NOT EXISTS channel_videos_ucid_idx
ON public.channel_videos
USING btree
(ucid COLLATE pg_catalog."default");
SQL
end
end
end

View File

@ -0,0 +1,34 @@
module Invidious::Database::Migrations
class CreateUsersTable < Migration
version 4
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE TABLE IF NOT EXISTS public.users
(
updated timestamp with time zone,
notifications text[],
subscriptions text[],
email text NOT NULL,
preferences text,
password text,
token text,
watched text[],
feed_needs_update boolean,
CONSTRAINT users_email_key UNIQUE (email)
);
SQL
conn.exec <<-SQL
GRANT ALL ON TABLE public.users TO current_user;
SQL
conn.exec <<-SQL
CREATE UNIQUE INDEX IF NOT EXISTS email_unique_idx
ON public.users
USING btree
(lower(email) COLLATE pg_catalog."default");
SQL
end
end
end

View File

@ -0,0 +1,28 @@
module Invidious::Database::Migrations
class CreateSessionIdsTable < Migration
version 5
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE TABLE IF NOT EXISTS public.session_ids
(
id text NOT NULL,
email text,
issued timestamp with time zone,
CONSTRAINT session_ids_pkey PRIMARY KEY (id)
);
SQL
conn.exec <<-SQL
GRANT ALL ON TABLE public.session_ids TO current_user;
SQL
conn.exec <<-SQL
CREATE INDEX IF NOT EXISTS session_ids_id_idx
ON public.session_ids
USING btree
(id COLLATE pg_catalog."default");
SQL
end
end
end

View File

@ -0,0 +1,27 @@
module Invidious::Database::Migrations
class CreateNoncesTable < Migration
version 6
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE TABLE IF NOT EXISTS public.nonces
(
nonce text,
expire timestamp with time zone,
CONSTRAINT nonces_id_key UNIQUE (nonce)
);
SQL
conn.exec <<-SQL
GRANT ALL ON TABLE public.nonces TO current_user;
SQL
conn.exec <<-SQL
CREATE INDEX IF NOT EXISTS nonces_nonce_idx
ON public.nonces
USING btree
(nonce COLLATE pg_catalog."default");
SQL
end
end
end

Some files were not shown because too many files have changed in this diff Show More