From 05c5448bc137a7798450dec71b0750841bac2c5e Mon Sep 17 00:00:00 2001 From: syeopite Date: Thu, 19 Dec 2024 13:18:04 -0800 Subject: [PATCH 01/48] Update Kemal to 1.6.0 and remove Kilt Kilt is unmaintained and the ECR templating logic has been natively integrated into Kemal with the issues previously seen having been resolved. This commit is mostly a precursor to support the next Kemal release which will add the ability to create error handlers for raised exceptions. See https://github.com/kemalcr/kemal/pull/688 --- shard.lock | 8 ++------ shard.yml | 5 +---- src/ext/kemal_content_for.cr | 16 ---------------- src/ext/kemal_static_file_handler.cr | 2 +- src/invidious.cr | 8 +++----- src/invidious/helpers/macros.cr | 5 ++--- 6 files changed, 9 insertions(+), 35 deletions(-) delete mode 100644 src/ext/kemal_content_for.cr diff --git a/shard.lock b/shard.lock index a097b081..1265eda6 100644 --- a/shard.lock +++ b/shard.lock @@ -18,7 +18,7 @@ shards: exception_page: git: https://github.com/crystal-loot/exception_page.git - version: 0.2.2 + version: 0.4.1 http_proxy: git: https://github.com/mamantoha/http_proxy.git @@ -26,11 +26,7 @@ shards: kemal: git: https://github.com/kemalcr/kemal.git - version: 1.1.2 - - kilt: - git: https://github.com/jeromegn/kilt.git - version: 0.6.1 + version: 1.6.0 pg: git: https://github.com/will/crystal-pg.git diff --git a/shard.yml b/shard.yml index af7e4186..154e44fc 100644 --- a/shard.yml +++ b/shard.yml @@ -17,10 +17,7 @@ dependencies: version: ~> 0.21.0 kemal: github: kemalcr/kemal - version: ~> 1.1.2 - kilt: - github: jeromegn/kilt - version: ~> 0.6.1 + version: ~> 1.6.0 protodec: github: iv-org/protodec version: ~> 0.1.5 diff --git a/src/ext/kemal_content_for.cr b/src/ext/kemal_content_for.cr deleted file mode 100644 index a4f3fd96..00000000 --- a/src/ext/kemal_content_for.cr +++ /dev/null @@ -1,16 +0,0 @@ -# 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 diff --git a/src/ext/kemal_static_file_handler.cr b/src/ext/kemal_static_file_handler.cr index eb068aeb..a5f42261 100644 --- a/src/ext/kemal_static_file_handler.cr +++ b/src/ext/kemal_static_file_handler.cr @@ -71,7 +71,7 @@ def send_file(env : HTTP::Server::Context, file_path : String, data : Slice(UInt filesize = data.bytesize attachment(env, filename, disposition) - Kemal.config.static_headers.try(&.call(env.response, file_path, filestat)) + Kemal.config.static_headers.try(&.call(env, file_path, filestat)) file = IO::Memory.new(data) if env.request.method == "GET" && env.request.headers.has_key?("Range") diff --git a/src/invidious.cr b/src/invidious.cr index b422dcbb..629e6e59 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -17,10 +17,8 @@ require "digest/md5" require "file_utils" -# Require kemal, kilt, then our own overrides +# Require kemal, then our own overrides require "kemal" -require "kilt" -require "./ext/kemal_content_for.cr" require "./ext/kemal_static_file_handler.cr" require "http_proxy" @@ -221,8 +219,8 @@ error 500 do |env, ex| error_template(500, ex) end -static_headers do |response| - response.headers.add("Cache-Control", "max-age=2629800") +static_headers do |env| + env.response.headers.add("Cache-Control", "max-age=2629800") end # Init Kemal diff --git a/src/invidious/helpers/macros.cr b/src/invidious/helpers/macros.cr index 43e7171b..84847321 100644 --- a/src/invidious/helpers/macros.cr +++ b/src/invidious/helpers/macros.cr @@ -55,12 +55,11 @@ macro templated(_filename, template = "template", navbar_search = true) {{ layout = "src/invidious/views/" + template + ".ecr" }} __content_filename__ = {{filename}} - content = Kilt.render({{filename}}) - Kilt.render({{layout}}) + render {{filename}}, {{layout}} end macro rendered(filename) - Kilt.render("src/invidious/views/#{{{filename}}}.ecr") + render("src/invidious/views/#{{{filename}}}.ecr") end # Similar to Kemals halt method but works in a From dd2e9994021ffb85ddfe01efc145e6fd79561187 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Fri, 28 Feb 2025 19:41:49 -0300 Subject: [PATCH 02/48] require base_job before the other jobs The crystal compiler seems to evaluate `require` in an alphabetical way, so if anyone in the future, wants to add another job and that job is above `base_job.cr` in alphabetical order, the compiler is going to fail with `Error: undefined constant: Invidious::Jobs::BaseJob`. This doesn't fix anything, but it will prevent a future headache. --- src/invidious.cr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index 12ffad33..21ca9f7e 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -49,7 +49,8 @@ require "./invidious/channels/*" require "./invidious/user/*" require "./invidious/search/*" require "./invidious/routes/**" -require "./invidious/jobs/**" +require "./invidious/jobs/base_job" +require "./invidious/jobs/*" # Declare the base namespace for invidious module Invidious From 05b99df49a514d628e863fbf459fc958f605cd0e Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 17 Apr 2025 16:55:30 -0400 Subject: [PATCH 03/48] fix(typo): 'Salect' -> 'Select' --- src/invidious/database/playlists.cr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/invidious/database/playlists.cr b/src/invidious/database/playlists.cr index 08aa719a..6dbcaa05 100644 --- a/src/invidious/database/playlists.cr +++ b/src/invidious/database/playlists.cr @@ -91,7 +91,7 @@ module Invidious::Database::Playlists end # ------------------- - # Salect + # Select # ------------------- def select(*, id : String) : InvidiousPlaylist? @@ -113,7 +113,7 @@ module Invidious::Database::Playlists end # ------------------- - # Salect (filtered) + # Select (filtered) # ------------------- def select_like_iv(email : String) : Array(InvidiousPlaylist) @@ -213,7 +213,7 @@ module Invidious::Database::PlaylistVideos end # ------------------- - # Salect + # Select # ------------------- def select(plid : String, index : VideoIndex, offset, limit = 100) : Array(PlaylistVideo) From 35896d086bad46a4ac6cbb778617ea3f3f8fd820 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 8 May 2025 01:00:46 -0400 Subject: [PATCH 04/48] fix: do not strip '+' character from referer Fix that a user of my instance (https://inv.nadeko.net) sent me by email. --- src/invidious/helpers/utils.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 85462eb8..5637e533 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -262,7 +262,7 @@ def get_referer(env, fallback = "/", unroll = true) end referer = referer.request_target - referer = "/" + referer.gsub(/[^\/?@&%=\-_.:,*0-9a-zA-Z]/, "").lstrip("/\\") + referer = "/" + referer.gsub(/[^\/?@&%=\-_.:,*0-9a-zA-Z+]/, "").lstrip("/\\") if referer == env.request.path referer = fallback From 25eade589f28e41de03111fadc6140cade7af725 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 8 May 2025 03:12:00 -0400 Subject: [PATCH 05/48] fix: pass user to `query.process` if present. Fixes https://github.com/iv-org/invidious/issues/5097 --- src/invidious/routes/search.cr | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index 44970922..b195c7b3 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -58,7 +58,11 @@ module Invidious::Routes::Search end begin - items = query.process + if user + items = query.process(user.as(User)) + else + items = query.process + end rescue ex : ChannelSearchException return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.") rescue ex From b120abdcc550060fc414390c7c06a879f3bea348 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Fri, 9 May 2025 02:58:29 -0400 Subject: [PATCH 06/48] fix: safely access "label" key Fixes https://github.com/iv-org/invidious/issues/5095 On some videos, `label` is missing from the video information. Invidious assumed that the `label` key existed. Videos with label have this inside `metadataBadgeRenderer`: ``` {"style" => "BADGE_STYLE_TYPE_SIMPLE", "label" => "4K", "trackingParams" => "COMDENwwGAoiEwiCrebe6JWNAxWIxz8EHSQRFTU="} ``` but other videos, for some reason, look like this: ``` {"icon" => {"iconType" => "PERSON_RADAR"}, "style" => "BADGE_STYLE_TYPE_SIMPLE", "trackingParams" => "CM4DENwwGAsiEwiCrebe6JWNAxWIxz8EHSQRFTU="} ``` --- src/invidious/yt_backend/extractors.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/yt_backend/extractors.cr b/src/invidious/yt_backend/extractors.cr index edd7bf1b..b78f01c6 100644 --- a/src/invidious/yt_backend/extractors.cr +++ b/src/invidious/yt_backend/extractors.cr @@ -115,7 +115,7 @@ private module Parsers badges = VideoBadges::None item_contents["badges"]?.try &.as_a.each do |badge| b = badge["metadataBadgeRenderer"] - case b["label"].as_s + case b["label"]?.try &.as_s when "LIVE" badges |= VideoBadges::LiveNow when "New" From 30ae222bf21a0970b25352ad3eac7a471656b2e1 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Fri, 9 May 2025 23:01:04 -0400 Subject: [PATCH 07/48] Add missing javascript licenses --- src/invidious/views/licenses.ecr | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/invidious/views/licenses.ecr b/src/invidious/views/licenses.ecr index 667cfa37..4d64ec3f 100644 --- a/src/invidious/views/licenses.ecr +++ b/src/invidious/views/licenses.ecr @@ -302,6 +302,90 @@ <%= translate(locale, "source") %> + + + + comments.js + + + + AGPL-3.0 + + + + <%= translate(locale, "source") %> + + + + + + pagination.js + + + + AGPL-3.0 + + + + <%= translate(locale, "source") %> + + + + + + playlist_widget.js + + + + AGPL-3.0 + + + + <%= translate(locale, "source") %> + + + + + + post.js + + + + AGPL-3.0 + + + + <%= translate(locale, "source") %> + + + + + + watched_indicator.js + + + + AGPL-3.0 + + + + <%= translate(locale, "source") %> + + + + + + watched_widget.js + + + + AGPL-3.0 + + + + <%= translate(locale, "source") %> + + From 401bc110d6a6231aa8e2c55bb03876825129b88d Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 8 May 2025 02:21:06 -0400 Subject: [PATCH 08/48] fix: set CSP header after setting preferences of registered users Fixes https://github.com/iv-org/invidious/issues/5142 add reason why extra_media_csp is after reading user preferences from the database and cookies set media-src after loading database user preferences --- src/invidious/routes/before_all.cr | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index 5695dee9..0cc04021 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -20,14 +20,6 @@ module Invidious::Routes::BeforeAll 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' file: http: https:" @@ -45,7 +37,7 @@ module Invidious::Routes::BeforeAll "font-src 'self' data:", "connect-src 'self'", "manifest-src 'self'", - "media-src 'self' blob:" + extra_media_csp, + "media-src 'self' blob:", "child-src 'self' blob:", "frame-src 'self'", "frame-ancestors " + frame_ancestors, @@ -110,6 +102,20 @@ module Invidious::Routes::BeforeAll preferences.locale = locale env.set "preferences", preferences + # Allow media resources to be loaded from google servers + # TODO: check if *.youtube.com can be removed + # + # `!preferences.local` has to be checked after setting and + # reading `preferences` from the "PREFS" cookie and + # saved user preferences from the database, otherwise + # the `extra_media_csp` variable will be always empty if + # `default_user_preferences.local` is set to true on the + # configuration file, causing preference “Proxy Videos” + # not to work. + if CONFIG.disabled?("local") || !preferences.local + env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"].gsub("media-src", "media-src https://*.googlevideo.com:443 https://*.youtube.com:443") + end + current_page = env.request.path if env.request.query query = HTTP::Params.parse(env.request.query.not_nil!) From 1492453c6018c633e944f08b93ecf054599caa62 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 10 May 2025 16:30:19 -0400 Subject: [PATCH 09/48] update comment --- src/invidious/routes/before_all.cr | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index 0cc04021..b5269668 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -108,10 +108,11 @@ module Invidious::Routes::BeforeAll # `!preferences.local` has to be checked after setting and # reading `preferences` from the "PREFS" cookie and # saved user preferences from the database, otherwise - # the `extra_media_csp` variable will be always empty if + # `https://*.googlevideo.com:443 https://*.youtube.com:443` + # will not be set in the CSP header if # `default_user_preferences.local` is set to true on the # configuration file, causing preference “Proxy Videos” - # not to work. + # not to work while having it disabled and using medium quality. if CONFIG.disabled?("local") || !preferences.local env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"].gsub("media-src", "media-src https://*.googlevideo.com:443 https://*.youtube.com:443") end From 20cf913a4ebd03c89da1e7c32c15ab8a20c8b146 Mon Sep 17 00:00:00 2001 From: syeopite Date: Sat, 10 May 2025 18:37:46 -0700 Subject: [PATCH 10/48] Add Javascript licence information automatically This commit automates the process of documenting the licenses of Invidious Javascript files through a compile time macro in the licenses.ecr template file. This should hopefully help keep the license documentation up-to-date and allow extensions like LibreJS to always be able to load the latest Javascript files of Invidious. Currently only Invidious's first-party Javascript files are supported. In the future it should be possible to leverage videojs-dependencies.yml to automatically document the Javascript licenses for VideoJS and co. as well. --- scripts/generate_js_licenses.cr | 56 ++++++++++++++ src/invidious/views/licenses.ecr | 128 +------------------------------ 2 files changed, 59 insertions(+), 125 deletions(-) create mode 100644 scripts/generate_js_licenses.cr diff --git a/scripts/generate_js_licenses.cr b/scripts/generate_js_licenses.cr new file mode 100644 index 00000000..1f4ffa62 --- /dev/null +++ b/scripts/generate_js_licenses.cr @@ -0,0 +1,56 @@ +# This file automatically generates Crystal strings of rows within an HTML Javascript licenses table +# +# These strings will then be placed within a `<%= %>` statement in licenses.ecr at compile time which +# will be interpolated at run-time. This interpolation is only for the translation of the "source" string +# so maybe we can just switch to a non-translated string to simplify the logic here. +# +# The Javascript Web Labels table defined at https://www.gnu.org/software/librejs/free-your-javascript.html#step3 +# for example just reiterates the name of the source file rather than use a "source" string. +all_javascript_files = Dir.glob("assets/**/*.js") + +videojs_js = [] of String +invidious_js = [] of String + +all_javascript_files.each do |js_path| + if js_path.starts_with?("assets/videojs/") + videojs_js << js_path[7..] + else + invidious_js << js_path[7..] + end +end + +def create_licence_tr(path, file_name, licence_name, licence_link, source_location) + tr = <<-HTML + " + #{file_name} + #{licence_name} + \#{translate(locale, "source")} + " + HTML + + # New lines are removed as to allow for using String.join and StringLiteral.split + # to get a clean list of each table row. + tr.gsub('\n', "") +end + +# TODO Use videojs-dependencies.yml to generate license info for videojs javascript +jslicence_table_rows = [] of String + +invidious_js.each do |path| + file_name = path.split('/')[-1] + + # A couple non Invidious JS files are also shipped alongside Invidious due to various reasons + next if { + "sse.js", "silvermine-videojs-quality-selector.min.js", "videojs-youtube-annotations.min.js", + }.includes?(file_name) + + jslicence_table_rows << create_licence_tr( + path: path, + file_name: file_name, + licence_name: "AGPL-3.0", + licence_link: "https://www.gnu.org/licenses/agpl-3.0.html", + source_location: path + ) +end + +puts jslicence_table_rows.join("\n") diff --git a/src/invidious/views/licenses.ecr b/src/invidious/views/licenses.ecr index 667cfa37..3037f3d7 100644 --- a/src/invidious/views/licenses.ecr +++ b/src/invidious/views/licenses.ecr @@ -9,90 +9,6 @@

<%= translate(locale, "JavaScript license information") %>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + <%- {% for row in run("../../../scripts/generate_js_licenses.cr").stringify.split('\n') %} %> + <%-= {{row.id}} -%> + <% {% end %} -%>
- _helpers.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
- handlers.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
- community.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
- embed.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
- notifications.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
- player.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
silvermine-videojs-quality-selector.min.js @@ -121,34 +37,6 @@
- subscribe_widget.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
- themes.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
videojs-contrib-quality-levels.js @@ -289,19 +177,9 @@
- watch.js - - AGPL-3.0 - - <%= translate(locale, "source") %> -
From aab6ff4bb6e4d3174ab812e5a2cdeec841d2358e Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 10 May 2025 23:02:34 -0400 Subject: [PATCH 11/48] Update src/invidious/routes/before_all.cr Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --- src/invidious/routes/before_all.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index b5269668..0c7bbdc2 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -114,7 +114,7 @@ module Invidious::Routes::BeforeAll # configuration file, causing preference “Proxy Videos” # not to work while having it disabled and using medium quality. if CONFIG.disabled?("local") || !preferences.local - env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"].gsub("media-src", "media-src https://*.googlevideo.com:443 https://*.youtube.com:443") + env.response.headers.update("Content-Security-Policy", &.gsub("media-src", "media-src https://*.googlevideo.com:443 https://*.youtube.com:443")) end current_page = env.request.path From 6fe21a7523c2c944ebc616e3573f50ee5fc6ce8f Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 10 May 2025 23:08:48 -0400 Subject: [PATCH 12/48] Revert "Update src/invidious/routes/before_all.cr" This reverts commit aab6ff4bb6e4d3174ab812e5a2cdeec841d2358e. --- src/invidious/routes/before_all.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index 0c7bbdc2..b5269668 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -114,7 +114,7 @@ module Invidious::Routes::BeforeAll # configuration file, causing preference “Proxy Videos” # not to work while having it disabled and using medium quality. if CONFIG.disabled?("local") || !preferences.local - env.response.headers.update("Content-Security-Policy", &.gsub("media-src", "media-src https://*.googlevideo.com:443 https://*.youtube.com:443")) + env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"].gsub("media-src", "media-src https://*.googlevideo.com:443 https://*.youtube.com:443") end current_page = env.request.path From d4eb2a97412ed36e0db7f059616d48bb193ab85f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 01:20:50 -0400 Subject: [PATCH 13/48] Bump crystallang/crystal from 1.16.2-alpine to 1.16.3-alpine in /docker (#5301) Bumps crystallang/crystal from 1.16.2-alpine to 1.16.3-alpine. --- updated-dependencies: - dependency-name: crystallang/crystal dependency-version: 1.16.3-alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c1820240..4cfc3c72 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:1.16.2-alpine AS builder +FROM crystallang/crystal:1.16.3-alpine AS builder RUN apk add --no-cache sqlite-static yaml-static From 03f89be9291b70ea7234e4291348e80b6c2c5d4e Mon Sep 17 00:00:00 2001 From: Fijxu Date: Wed, 14 May 2025 01:51:03 -0400 Subject: [PATCH 14/48] CI: Bump Crystal version matrix (#5293) * CI: Bump Crystal version matrix - 1.12.1 -> 1.12.2 - 1.13.2 -> 1.13.3 - 1.14.0 -> 1.14.1 - 1.15.0 -> 1.15.1 - Add 1.16.3 * Update Crystal 1.16.2 to 1.16.3 https://github.com/crystal-lang/crystal/releases/tag/1.16.3 --- .github/workflows/ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c4635c4..9d6a930a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,11 @@ jobs: matrix: stable: [true] crystal: - - 1.12.1 - - 1.13.2 - - 1.14.0 - - 1.15.0 + - 1.12.2 + - 1.13.3 + - 1.14.1 + - 1.15.1 + - 1.16.3 include: - crystal: nightly stable: false From 0dff773a070f4f55ba91b01bab11b4dadd82ac89 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:27 +0200 Subject: [PATCH 15/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/tr.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/locales/tr.json b/locales/tr.json index 94c127db..cf3f8987 100644 --- a/locales/tr.json +++ b/locales/tr.json @@ -497,5 +497,9 @@ "carousel_skip": "Kayar menüyü atla", "carousel_go_to": "`x` sunumuna git", "The Popular feed has been disabled by the administrator.": "Popüler akışı yönetici tarafından devre dışı bırakıldı.", - "preferences_preload_label": "Video verilerini önceden yükle: " + "preferences_preload_label": "Video verilerini önceden yükle: ", + "First page": "İlk sayfa", + "Filipino (auto-generated)": "Filipince (oto-oluşturuldu)", + "channel_tab_courses_label": "Kurslar", + "channel_tab_posts_label": "Yazılar" } From 3b87bf2675fa6c4f3cee7a18bb6944e4cdcee82f Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:28 +0200 Subject: [PATCH 16/48] Update Latvian translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Latvian translation Co-authored-by: Hosted Weblate Co-authored-by: ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) --- locales/lv.json | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 locales/lv.json diff --git a/locales/lv.json b/locales/lv.json new file mode 100644 index 00000000..a867c8f3 --- /dev/null +++ b/locales/lv.json @@ -0,0 +1,69 @@ +{ + "generic_channels_count_0": "{{count}} kanāli", + "generic_channels_count_1": "{{count}} kanāls", + "generic_channels_count_2": "{{count}} kanāli", + "Add to playlist": "Pievienot atskaņošanas sarakstam", + "Answer": "Atbildēt", + "generic_subscribers_count_0": "{{count}} abonenti", + "generic_subscribers_count_1": "{{count}} abonents", + "generic_subscribers_count_2": "{{count}} abonenti", + "generic_button_delete": "Dzēst", + "generic_button_edit": "Rediģēt", + "generic_button_save": "Saglabāt", + "generic_button_cancel": "Atcelt", + "generic_button_rss": "RSS", + "Unsubscribe": "Pārtraukt abonementu", + "View playlist on YouTube": "Skatīt atskaņošanas sarakstu YouTube vietnē", + "New password": "Jaunā parole", + "Yes": "Jā", + "No": "Nē", + "Import and Export Data": "Ievietot un izgūt datus", + "Import": "Ievietot", + "Import Invidious data": "Ievietot Invidious JSON datus", + "Delete account?": "Vai dzēst kontu?", + "History": "Vēsture", + "User ID": "Lietotāja ID", + "Password": "Parole", + "Import YouTube subscriptions": "Ievietot YouTube CSV vai OPML abonementus", + "E-mail": "E-pasts", + "Preferences": "Iestatījumi", + "preferences_category_player": "Atskaņotāja iestatījumi", + "preferences_quality_option_hd720": "HD - 720p", + "preferences_quality_option_medium": "Vidēja", + "preferences_quality_dash_option_worst": "Vissliktākā", + "preferences_quality_dash_option_2160p": "2160p (4K)", + "preferences_quality_dash_option_1080p": "1080p (Full HD)", + "preferences_quality_dash_option_720p": "720p (HD)", + "preferences_quality_dash_option_1440p": "1440p (2.5K, QHD)", + "preferences_quality_dash_option_480p": "480p (SD)", + "preferences_quality_dash_option_360p": "360p", + "preferences_quality_dash_option_240p": "240p", + "preferences_quality_dash_option_144p": "144p", + "preferences_volume_label": "Atskaņošanas skaļums: ", + "reddit": "Reddit", + "invidious": "Invidious", + "Bangla": "Bengāļu", + "Basque": "Basku", + "Cebuano": "Sebuāņu", + "Chinese (Traditional)": "Ķīniešu (tradicionālā)", + "Corsican": "Korsikāņu", + "Croatian": "Horvātu", + "Galician": "Galisiešu", + "Georgian": "Gruzīnu", + "Gujarati": "Gudžaratu", + "German": "Vācu", + "Greek": "Grieķu", + "Haitian Creole": "Haitiešu", + "Hausa": "Hausu", + "Hawaiian": "Havajiešu", + "Export data as JSON": "Izgūt Invidious datus JSON formātā", + "preferences_quality_dash_option_4320p": "4320p (8K)", + "Time (h:mm:ss):": "Laiks (h:mm:ss):", + "Chinese (Simplified)": "Ķīniešu (vienkāršotā)", + "preferences_quality_dash_option_best": "Vislabākā", + "preferences_quality_option_small": "Zema", + "youtube": "YouTube", + "Add to playlist: ": "Pievienot atskaņošanas sarakstam: ", + "Subscribe": "Abonēt", + "View channel on YouTube": "Skatīt kanālu YouTube vietnē" +} From 96b226b130cf3613ddbbed90064659177a72a0be Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:28 +0200 Subject: [PATCH 17/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pt-BR.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 3d653caf..1eb3c989 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -515,5 +515,8 @@ "carousel_skip": "Ignorar carrossel", "carousel_go_to": "Ir ao slide `x`", "preferences_preload_label": "Pré-carregar dados do vídeo: ", - "Filipino (auto-generated)": "Filipino (gerado automaticamente)" + "Filipino (auto-generated)": "Filipino (gerado automaticamente)", + "channel_tab_posts_label": "Postagens", + "First page": "Primeira página", + "channel_tab_courses_label": "Cursos" } From 476bc51b0e7ff2d9d1752a95db404db2b287d3c4 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:28 +0200 Subject: [PATCH 18/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/de.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/de.json b/locales/de.json index ce6fde8b..e51d40b9 100644 --- a/locales/de.json +++ b/locales/de.json @@ -499,5 +499,7 @@ "carousel_go_to": "Zu Element `x` springen", "carousel_slide": "Seite {{current}} von {{total}}", "carousel_skip": "Galerie überspringen", - "Filipino (auto-generated)": "Philippinisch (automatisch generiert)" + "Filipino (auto-generated)": "Philippinisch (automatisch generiert)", + "channel_tab_courses_label": "Kurse", + "channel_tab_posts_label": "Beiträge" } From 1e73f4e38258398473ed7eae75886d9f4d0128d9 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:29 +0200 Subject: [PATCH 19/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/el.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/locales/el.json b/locales/el.json index 32efaaf8..e5a89a44 100644 --- a/locales/el.json +++ b/locales/el.json @@ -490,7 +490,7 @@ "Search for videos": "Αναζήτηση βίντεο", "The Popular feed has been disabled by the administrator.": "Η δημοφιλής ροή έχει απενεργοποιηθεί από τον διαχειριστή.", "Answer": "Απάντηση", - "Add to playlist": "Προσθήκη στην λίιστα αναπαραγωγής", + "Add to playlist": "Προσθήκη στην λίστα αναπαραγωγής", "Add to playlist: ": "Προσθήκη στην λίστα αναπαραγωγής : ", "carousel_slide": "Εικόνα {{current}}απο {{total}}", "carousel_go_to": "Πήγαινε στην εικόνα`x`", @@ -498,5 +498,8 @@ "Import YouTube watch history (.json)": "Εισαγωγή ιστορικού προβολής YouTube (.json)", "Filipino (auto-generated)": "Φιλιππινέζικα (αυτόματη παραγωγή)", "preferences_preload_label": "Προφόρτιση δεδομένων βίντεο: ", - "carousel_skip": "Αποφυγή εμφάνισης εικόνων" + "carousel_skip": "Αποφυγή εμφάνισης εικόνων", + "First page": "Πρώτη σελίδα", + "channel_tab_courses_label": "Μαθήματα", + "channel_tab_posts_label": "Δημοσιεύσεις" } From f8f6eb74f5d460853aa693328698a844fa5d8a68 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:29 +0200 Subject: [PATCH 20/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ru.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/locales/ru.json b/locales/ru.json index b7dc91cf..906f00fc 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -475,7 +475,7 @@ "search_filters_date_option_none": "Любая дата", "search_filters_date_label": "Дата загрузки", "search_message_no_results": "Ничего не найдено.", - "search_message_use_another_instance": " Дополнительно вы можете поискать на других зеркалах.", + "search_message_use_another_instance": "Дополнительно вы можете поискать на других зеркалах.", "search_filters_features_option_vr180": "VR180", "search_message_change_filters_or_query": "Попробуйте расширить поисковый запрос и/или изменить фильтры.", "search_filters_duration_option_medium": "Средние (4 - 20 минут)", @@ -515,5 +515,7 @@ "carousel_slide": "Пролистано {{current}} из {{total}}", "carousel_skip": "Пропустить всё", "carousel_go_to": "Перейти к странице `x`", - "preferences_preload_label": "Предзагрузка видеоданных: " + "preferences_preload_label": "Предзагрузка видеоданных: ", + "channel_tab_courses_label": "Курсы", + "channel_tab_posts_label": "Записи" } From a5b97a585017c2bf0a875fce27bdacf1633be772 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:30 +0200 Subject: [PATCH 21/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/bg.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/locales/bg.json b/locales/bg.json index baa683c9..5c99d98f 100644 --- a/locales/bg.json +++ b/locales/bg.json @@ -403,7 +403,7 @@ "comments_view_x_replies": "Виж {{count}} отговор", "comments_view_x_replies_plural": "Виж {{count}} отговора", "footer_original_source_code": "Оригинален изходен код", - "Import YouTube subscriptions": "Импортиране на YouTube/OPML абонаменти", + "Import YouTube subscriptions": "Импортиране на YouTube-CSV/OPML абонаменти", "Lithuanian": "Литовски", "Nyanja": "Нянджа", "Updated `x` ago": "Актуализирано преди `x`", @@ -493,5 +493,8 @@ "Add to playlist: ": "Добави към плейлист: ", "Answer": "Отговор", "Search for videos": "Търсене на видеа", - "The Popular feed has been disabled by the administrator.": "Популярната страница е деактивирана от администратора." + "The Popular feed has been disabled by the administrator.": "Популярната страница е деактивирана от администратора.", + "Filipino (auto-generated)": "Филипински (автоматично генериран)", + "preferences_preload_label": "Предварително заредете видео данни: ", + "First page": "Първа страница" } From 6a9ed48d5d3997989a67b3e53432460e8479b323 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:31 +0200 Subject: [PATCH 22/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/uk.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/uk.json b/locales/uk.json index 2472f247..b99923e2 100644 --- a/locales/uk.json +++ b/locales/uk.json @@ -515,5 +515,8 @@ "carousel_skip": "Пропустити карусель", "carousel_go_to": "Перейти до слайда `x`", "preferences_preload_label": "Попереднє завантаження відеоданих: ", - "Filipino (auto-generated)": "Філіппінська (згенеровано автоматично)" + "Filipino (auto-generated)": "Філіппінська (згенеровано автоматично)", + "First page": "Перша сторінка", + "channel_tab_courses_label": "Курси", + "channel_tab_posts_label": "Дописи" } From 435106b7de12d226c56f3cc350f727ce7fc11d0f Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:31 +0200 Subject: [PATCH 23/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ja.json | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/locales/ja.json b/locales/ja.json index 5e90148d..c4b82486 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -25,7 +25,7 @@ "No": "いいえ", "Import and Export Data": "データのインポートとエクスポート", "Import": "インポート", - "Import Invidious data": "Invidious JSONデータをインポート", + "Import Invidious data": "Invidious JSON データをインポート", "Import YouTube subscriptions": "YouTube/OPML 登録チャンネルをインポート", "Import FreeTube subscriptions (.db)": "FreeTube 登録チャンネルをインポート (.db)", "Import NewPipe subscriptions (.json)": "NewPipe 登録チャンネルをインポート (.json)", @@ -68,7 +68,7 @@ "preferences_related_videos_label": "関連動画を表示: ", "preferences_annotations_label": "最初からアノテーションを表示: ", "preferences_extend_desc_label": "動画の説明文を自動的に拡張: ", - "preferences_vr_mode_label": "対話的な360°動画 (WebGLが必要): ", + "preferences_vr_mode_label": "対話的な 360° 動画 (WebGL が必要): ", "preferences_category_visual": "外観設定", "preferences_player_style_label": "プレイヤーのスタイル: ", "Dark mode: ": "ダークモード: ", @@ -77,7 +77,7 @@ "light": "ライト", "preferences_thin_mode_label": "最小モード: ", "preferences_category_misc": "ほかの設定", - "preferences_automatic_instance_redirect_label": "インスタンスの自動転送 (redirect.invidious.ioにフォールバック): ", + "preferences_automatic_instance_redirect_label": "インスタンスの自動転送 (redirect.invidious.io にフォールバック): ", "preferences_category_subscription": "登録チャンネル設定", "preferences_annotations_subscribed_label": "最初から登録チャンネルのアノテーションを表示 ", "Redirect homepage to feed: ": "ホームからフィードにリダイレクト: ", @@ -125,7 +125,7 @@ "subscriptions_unseen_notifs_count_0": "{{count}}件の未読通知", "search": "検索", "Log out": "ログアウト", - "Released under the AGPLv3 on Github.": "GitHub上でAGPLv3の元で公開", + "Released under the AGPLv3 on Github.": "GitHub 上で AGPLv3 の元で公開", "Source available here.": "ソースはここで閲覧可能です。", "View JavaScript license information.": "JavaScriptライセンス情報", "View privacy policy.": "個人情報保護方針", @@ -143,8 +143,8 @@ "Editing playlist `x`": "再生リスト `x` を編集中", "Show more": "もっと見る", "Show less": "表示を少なく", - "Watch on YouTube": "YouTubeで視聴", - "Switch Invidious Instance": "Invidiousインスタンスの変更", + "Watch on YouTube": "YouTube で視聴", + "Switch Invidious Instance": "Invidious インスタンスの変更", "Hide annotations": "アノテーションを隠す", "Show annotations": "アノテーションを表示", "Genre: ": "ジャンル: ", @@ -330,7 +330,7 @@ "(edited)": "(編集済み)", "YouTube comment permalink": "YouTube コメントのパーマリンク", "permalink": "パーマリンク", - "`x` marked it with a ❤": "`x` が❤を送りました", + "`x` marked it with a ❤": "`x` が ❤ を送りました", "Audio mode": "音声モード", "Video mode": "動画モード", "channel_tab_videos_label": "動画", @@ -343,7 +343,7 @@ "search_filters_type_label": "種類", "search_filters_duration_label": "再生時間", "search_filters_features_label": "特徴", - "search_filters_sort_label": "順番", + "search_filters_sort_label": "並べ替え", "search_filters_date_option_hour": "1時間以内", "search_filters_date_option_today": "今日", "search_filters_date_option_week": "今週", @@ -365,13 +365,13 @@ "Current version: ": "現在のバージョン: ", "next_steps_error_message": "以下をお試しください: ", "next_steps_error_message_refresh": "再読み込み", - "next_steps_error_message_go_to_youtube": "YouTubeを開く", + "next_steps_error_message_go_to_youtube": "YouTube を開く", "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", + "footer_modfied_source_code": "改変し使用中", + "adminprefs_modified_source_code_url_label": "改変されたソースコードのレポジトリの URL", "search_filters_duration_option_long": "20分以上", "preferences_region_label": "地域: ", "footer_donate_page": "寄付する", @@ -399,7 +399,7 @@ "preferences_quality_dash_option_worst": "最低", "preferences_quality_dash_option_best": "最高", "videoinfo_started_streaming_x_ago": "`x`前に配信を開始", - "videoinfo_watch_on_youTube": "YouTubeで視聴", + "videoinfo_watch_on_youTube": "YouTube で視聴", "user_created_playlists": "`x`個の作成した再生リスト", "Video unavailable": "動画は利用できません", "Chinese": "中国語", @@ -446,7 +446,7 @@ "search_filters_duration_option_medium": "4 ~ 20分", "preferences_save_player_pos_label": "再生位置を保存: ", "crash_page_before_reporting": "バグを報告する前に、次のことを確認してください。", - "crash_page_report_issue": "上記が助けにならないなら、GitHub に新しい issue を作成し(英語が好ましい)、メッセージに次のテキストを含めてください(テキストは翻訳しない)。", + "crash_page_report_issue": "上記が助けにならない場合、GitHub に新しい issue を作成し (できれば英語で) 、メッセージに次のテキストを含めてください (テキストは翻訳しない) 。", "crash_page_search_issue": "GitHub の既存の問題 (issue) を検索", "channel_tab_streams_label": "ライブ", "channel_tab_playlists_label": "再生リスト", @@ -481,5 +481,8 @@ "carousel_skip": "画像のスライド表示をスキップ", "toggle_theme": "テーマの切り替え", "preferences_preload_label": "動画データを事前に読み込む: ", - "Filipino (auto-generated)": "フィリピノ語 (自動生成)" + "Filipino (auto-generated)": "フィリピノ語 (自動生成)", + "First page": "最初のページ", + "channel_tab_posts_label": "投稿", + "channel_tab_courses_label": "コース" } From 9c9a8592e0addc369c6bfdd2b2dac84788fdd671 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:31 +0200 Subject: [PATCH 24/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ca.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/locales/ca.json b/locales/ca.json index bbcadf89..474d6a3c 100644 --- a/locales/ca.json +++ b/locales/ca.json @@ -204,7 +204,7 @@ "View JavaScript license information.": "Consulta la informació de la llicència de JavaScript.", "Playlist privacy": "Privacitat de la llista de reproducció", "search_message_no_results": "No s'han trobat resultats.", - "search_message_use_another_instance": " També es pot buscar en una altra instància.", + "search_message_use_another_instance": "També es pot cercar en una altra instància.", "Genre: ": "Gènere: ", "Hidden field \"challenge\" is a required field": "El camp ocult \"repte\" és un camp obligatori", "Burmese": "Birmà", @@ -489,5 +489,16 @@ "generic_button_delete": "Suprimeix", "Import YouTube watch history (.json)": "Importa l'historial de visualitzacions de YouTube (.json)", "Answer": "Resposta", - "toggle_theme": "Commuta el tema" + "toggle_theme": "Commuta el tema", + "Add to playlist": "Afegeix a la llista de reproducció", + "Add to playlist: ": "Afegeix a la llista de reproducció: ", + "Search for videos": "Cercar vídeos", + "carousel_slide": "Diapositiva {{current}} de {{total}}", + "preferences_preload_label": "Precarregar dades del vídeo: ", + "carousel_go_to": "Anar a la diapositiva `x`", + "First page": "Primera pàgina", + "Filipino (auto-generated)": "Filipí (generat automàticament)", + "channel_tab_courses_label": "Cursos", + "channel_tab_posts_label": "Missatges", + "carousel_skip": "Saltar l'exhibició" } From 2d8326c63dcf2c7517fb4941a13ae2c1bf24a003 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:32 +0200 Subject: [PATCH 25/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/cy.json | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/locales/cy.json b/locales/cy.json index 566e73e1..eb391572 100644 --- a/locales/cy.json +++ b/locales/cy.json @@ -141,7 +141,7 @@ "An alternative front-end to YouTube": "Pen blaen amgen i YouTube", "source": "ffynhonnell", "Log in": "Mewngofnodi", - "Log in/register": "Mewngofnodi/Cofrestru", + "Log in/register": "Mewngofnodi/cofrestru", "User ID": "Enw defnyddiwr", "preferences_quality_option_dash": "DASH (ansawdd addasol)", "Sign In": "Mewngofnodi", @@ -381,5 +381,32 @@ "channel_tab_channels_label": "Sianeli", "channel_tab_community_label": "Cymuned", "channel_tab_shorts_label": "Fideos byrion", - "channel_tab_videos_label": "Fideos" + "channel_tab_videos_label": "Fideos", + "generic_playlists_count_0": "{{count}} rhestr chwarae", + "generic_playlists_count_1": "{{count}} rhestr chwarae", + "generic_playlists_count_2": "{{count}} rhestri chwarae", + "generic_playlists_count_3": "{{count}} rhestri chwarae", + "generic_playlists_count_4": "{{count}} rhestri chwarae", + "generic_playlists_count_5": "{{count}} rhestri chwarae", + "New passwords must match": "Rhaid i'r cyfrineiriau newydd cyfateb â'i gilydd", + "last": "diwethaf", + "First page": "Tudalen gyntaf", + "preferences_preload_label": "Cynlwytho data fideo: ", + "preferences_extend_desc_label": "Ymestyn disgrifiad fideo'n awtomatig: ", + "preferences_vr_mode_label": "Fideos rhyngweithiol 360 gradd (angen WebGL): ", + "preferences_video_loop_label": "Doleniwch bob amser: ", + "Top enabled: ": "Tudalen fideos brig wedi'i alluogi: ", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Allforio tanysgrifiadau ar fformat OPML (i NewPipe a FreeTube)", + "Export subscriptions as OPML": "Allforio tanysgrifiadau ar fformat OPML", + "preferences_annotations_subscribed_label": "Ddangos nodiadau sianeli tanysgrifiwyd fel rhagosodiad? ", + "Redirect homepage to feed: ": "Ailgyfeirio tudalen gartref i'r borthiant: ", + "preferences_feed_menu_label": "Dewislen porthiant: ", + "Login enabled: ": "Mewngofnodi wedi'i alluogi: ", + "tokens_count_0": "", + "tokens_count_1": "tocyn", + "tokens_count_2": "", + "tokens_count_3": "", + "tokens_count_4": "tocynnau", + "tokens_count_5": "", + "Source available here.": "Tarddle ar gael yma." } From 546a799f0b23a92a3d9533143adf308db81589ee Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:32 +0200 Subject: [PATCH 26/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/cs.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/cs.json b/locales/cs.json index d28f2098..41f3db5c 100644 --- a/locales/cs.json +++ b/locales/cs.json @@ -515,5 +515,8 @@ "carousel_skip": "Přeskočit galerii", "carousel_go_to": "Přejít na snímek `x`", "preferences_preload_label": "Předem načíst data videa: ", - "Filipino (auto-generated)": "Filipínština (vytvořeno automaticky)" + "Filipino (auto-generated)": "Filipínština (vytvořeno automaticky)", + "First page": "První stránka", + "channel_tab_courses_label": "Kurzy", + "channel_tab_posts_label": "Příspěvky" } From 9186020f942270341d3aac70ca9807258e02853b Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:33 +0200 Subject: [PATCH 27/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pt.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/pt.json b/locales/pt.json index 9c8562f2..6438e15b 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -515,5 +515,8 @@ "carousel_go_to": "Ir para o diapositivo`x`", "The Popular feed has been disabled by the administrator.": "O feed Popular foi desativado por um administrador.", "preferences_preload_label": "Pré-carregamento dos dados: ", - "Filipino (auto-generated)": "Filipino (gerado automaticamente)" + "Filipino (auto-generated)": "Filipino (gerado automaticamente)", + "First page": "Primeira página", + "channel_tab_courses_label": "Cursos", + "channel_tab_posts_label": "Publicações" } From f96e476ed919fbc57e2e38348c78897f237b6292 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:33 +0200 Subject: [PATCH 28/48] Update Vietnamese translation Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Abc's Noob Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/vi.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/vi.json b/locales/vi.json index 229f8fa9..9c4a5a15 100644 --- a/locales/vi.json +++ b/locales/vi.json @@ -314,11 +314,11 @@ "search_filters_duration_label": "Thời lượng", "search_filters_features_label": "Đặc điểm", "search_filters_sort_label": "Sắp xếp theo", - "search_filters_date_option_hour": "Một giờ qua", + "search_filters_date_option_hour": "Một giờ trước", "search_filters_date_option_today": "Hôm nay", "search_filters_date_option_week": "Tuần này", "search_filters_date_option_month": "Tháng này", - "search_filters_date_option_year": "Năm này", + "search_filters_date_option_year": "Năm nay", "search_filters_type_option_video": "video", "search_filters_type_option_channel": "Kênh", "search_filters_type_option_playlist": "Danh sách phát", @@ -479,5 +479,8 @@ "carousel_skip": "Bỏ qua Carousel", "carousel_go_to": "Đi tới trang `x`", "Search for videos": "Tìm kiếm video", - "The Popular feed has been disabled by the administrator.": "Bảng tin phổ biến đã bị tắt bởi ban quản lý." + "The Popular feed has been disabled by the administrator.": "Bảng tin phổ biến đã bị tắt bởi ban quản lý.", + "preferences_preload_label": "Tải trước dữ liệu video: ", + "Filipino (auto-generated)": "Tiếng Philippines (tự động tạo)", + "First page": "Trang đầu" } From 583195ccbd8a17b1f43fdf49189ed2f255b4ceb3 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:34 +0200 Subject: [PATCH 29/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/is.json | 57 ++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/locales/is.json b/locales/is.json index d94357f1..28cacf31 100644 --- a/locales/is.json +++ b/locales/is.json @@ -2,7 +2,7 @@ "LIVE": "BEINT", "Shared `x` ago": "Deilt fyrir `x` síðan", "Unsubscribe": "Afskrá", - "Subscribe": "Áskrifa", + "Subscribe": "Setja í áskrift", "View channel on YouTube": "Skoða rás á YouTube", "View playlist on YouTube": "Skoða spilunarlista á YouTube", "newest": "nýjasta", @@ -14,8 +14,8 @@ "Clear watch history?": "Hreinsa áhorfsferil?", "New password": "Nýtt lykilorð", "New passwords must match": "Nýtt lykilorð verður að passa", - "Authorize token?": "Leyfa teikn?", - "Authorize token for `x`?": "Leyfa teikn fyrir `x`?", + "Authorize token?": "Auðkenna teikn?", + "Authorize token for `x`?": "Auðkenna teikn fyrir `x`?", "Yes": "Já", "No": "Nei", "Import and Export Data": "Inn- og útflutningur gagna", @@ -36,17 +36,17 @@ "source": "uppruni", "Log in": "Skrá inn", "Log in/register": "Innskráning/nýskráning", - "User ID": "Notandakenni", + "User ID": "Auðkenni notanda", "Password": "Lykilorð", "Time (h:mm:ss):": "Tími (h:mm: ss):", - "Text CAPTCHA": "Texta CAPTCHA", - "Image CAPTCHA": "Mynd CAPTCHA", + "Text CAPTCHA": "CAPTCHA-texti", + "Image CAPTCHA": "CAPTCHA-mynd", "Sign In": "Skrá inn", "Register": "Nýskrá", "E-mail": "Tölvupóstur", "Preferences": "Kjörstillingar", "preferences_category_player": "Kjörstillingar spilara", - "preferences_video_loop_label": "Alltaf lykkja: ", + "preferences_video_loop_label": "Alltaf endurtaka: ", "preferences_autoplay_label": "Sjálfvirk spilun: ", "preferences_continue_label": "Spila næst sjálfgefið: ", "preferences_continue_autoplay_label": "Spila næsta myndskeið sjálfkrafa: ", @@ -85,7 +85,7 @@ "preferences_unseen_only_label": "Sýna aðeins óséð: ", "preferences_notifications_only_label": "Sýna aðeins tilkynningar (ef einhverjar eru): ", "Enable web notifications": "Virkja veftilkynningar", - "`x` uploaded a video": "`x` hlóð upp myndband", + "`x` uploaded a video": "`x` sendi inn myndskeið", "`x` is live": "`x` er í beinni", "preferences_category_data": "Gagnastillingar", "Clear watch history": "Hreinsa áhorfsferil", @@ -104,8 +104,8 @@ "Registration enabled: ": "Nýskráning virkjuð? ", "Report statistics: ": "Skrá tölfræði? ", "Save preferences": "Vista stillingar", - "Subscription manager": "Áskriftarstjóri", - "Token manager": "Teiknastjórnun", + "Subscription manager": "Áskriftastýring", + "Token manager": "Teiknastýring", "Token": "Teikn", "Import/export": "Flytja inn/út", "unsubscribe": "afskrá", @@ -233,7 +233,7 @@ "Korean": "Kóreska", "Kurdish": "Kúrdíska", "Kyrgyz": "Kirgisíska", - "Lao": "Laó", + "Lao": "Laóska", "Latin": "Latína", "Latvian": "Lettneska", "Lithuanian": "Litháíska", @@ -295,18 +295,18 @@ "View as playlist": "Skoða sem spilunarlista", "Default": "Sjálfgefið", "Music": "Tónlist", - "Gaming": "Tólvuleikja", + "Gaming": "Spilun leikja", "News": "Fréttir", "Movies": "Kvikmyndir", "Download": "Niðurhal", - "Download as: ": "Niðurhala sem: ", + "Download as: ": "Sækja sem: ", "%A %B %-d, %Y": "%A %B %-d, %Y", "(edited)": "(breytt)", - "YouTube comment permalink": "YouTube ummæli varanlegur tengill", + "YouTube comment permalink": "Varanlegur tengill á YouTube-ummæli", "permalink": "Varanlegur tengill", "`x` marked it with a ❤": "`x` merkti það með ❤", - "Audio mode": "Hljóð ham", - "Video mode": "Myndband ham", + "Audio mode": "Hljóðhamur", + "Video mode": "Myndhamur", "channel_tab_videos_label": "Myndskeið", "Playlists": "Spilunarlistar", "channel_tab_community_label": "Samfélag", @@ -388,7 +388,7 @@ "crash_page_before_reporting": "Áður en þú tilkynnir villu, gakktu úr skugga um að þú hafir:", "crash_page_switch_instance": "reynt að nota annað tilvik", "crash_page_report_issue": "Ef ekkert af ofantöldu hjálpaði, ættirðu að opna nýja verkbeiðni (issue) á GitHub (helst á ensku) og láta fylgja eftirfarandi texta í skilaboðunum þínum (alls EKKI þýða þennan texta):", - "channel_tab_shorts_label": "Stuttmyndir", + "channel_tab_shorts_label": "Símamyndir", "carousel_slide": "Skyggna {{current}} af {{total}}", "carousel_go_to": "Fara á skyggnu `x`", "channel_tab_streams_label": "Bein streymi", @@ -401,8 +401,8 @@ "English (United Kingdom)": "Enska (Bretland)", "English (United States)": "Enska (Bandarísk)", "Vietnamese (auto-generated)": "Víetnamska (sjálfvirkt útbúið)", - "generic_count_months": "{{count}} mánuður", - "generic_count_months_plural": "{{count}} mánuðir", + "generic_count_months": "{{count}} mánuði", + "generic_count_months_plural": "{{count}} mánuðum", "search_filters_sort_option_rating": "Einkunn", "videoinfo_youTube_embed_link": "Ívefja", "error_video_not_in_playlist": "Umbeðið myndskeið fyrirfinnst ekki í þessum spilunarlista. Smelltu hér til að fara á heimasíðu spilunarlistans.", @@ -429,11 +429,11 @@ "Spanish (auto-generated)": "Spænska (sjálfvirkt útbúið)", "Spanish (Mexico)": "Spænska (Mexíkó)", "generic_count_hours": "{{count}} klukkustund", - "generic_count_hours_plural": "{{count}} klukkustundir", - "generic_count_years": "{{count}} ár", - "generic_count_years_plural": "{{count}} ár", - "generic_count_weeks": "{{count}} vika", - "generic_count_weeks_plural": "{{count}} vikur", + "generic_count_hours_plural": "{{count}} klukkustundum", + "generic_count_years": "{{count}} ári", + "generic_count_years_plural": "{{count}} árum", + "generic_count_weeks": "{{count}} viku", + "generic_count_weeks_plural": "{{count}} vikum", "search_filters_date_option_none": "Hvaða dagsetning sem er", "Channel Sponsor": "Styrktaraðili rásar", "search_filters_date_option_week": "Í þessari viku", @@ -476,8 +476,8 @@ "preferences_quality_dash_option_144p": "144p", "invidious": "Invidious", "Korean (auto-generated)": "Kóreska (sjálfvirkt útbúið)", - "generic_count_days": "{{count}} dagur", - "generic_count_days_plural": "{{count}} dagar", + "generic_count_days": "{{count}} degi", + "generic_count_days_plural": "{{count}} dögum", "search_filters_date_option_today": "Í dag", "search_filters_type_label": "Tegund", "search_filters_type_option_all": "Hvaða tegund sem er", @@ -498,5 +498,8 @@ "Import YouTube playlist (.csv)": "Flytja inn YouTube spilunarlista (.csv)", "preferences_quality_option_dash": "DASH (aðlaganleg gæði)", "preferences_preload_label": "Forhlaða gögnum myndskeiðs: ", - "Filipino (auto-generated)": "Filippínska (sjálfvirkt útbúin)" + "Filipino (auto-generated)": "Filippínska (sjálfvirkt útbúin)", + "channel_tab_posts_label": "Færslur", + "First page": "Fyrsta síða", + "channel_tab_courses_label": "Kennsluefni" } From 7bd1abecde92dd2291766f05beb13b74937ad11c Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:34 +0200 Subject: [PATCH 30/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pl.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/pl.json b/locales/pl.json index b119ab22..d78b7a95 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -515,5 +515,8 @@ "carousel_skip": "Pomiń karuzelę", "carousel_go_to": "Przejdź do slajdu `x`", "preferences_preload_label": "Wstępne ładowanie danych wideo: ", - "Filipino (auto-generated)": "filipiński (wygenerowany automatycznie)" + "Filipino (auto-generated)": "filipiński (wygenerowany automatycznie)", + "First page": "Pierwsza strona", + "channel_tab_posts_label": "Posty", + "channel_tab_courses_label": "Kursy" } From 31556d0f88011e57d479dc300ebe5f35ea7d0367 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:35 +0200 Subject: [PATCH 31/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/it.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/it.json b/locales/it.json index 3f008ccd..c7143ef6 100644 --- a/locales/it.json +++ b/locales/it.json @@ -515,5 +515,8 @@ "carousel_skip": "Salta la galleria", "carousel_go_to": "Vai al fotogramma `x`", "preferences_preload_label": "Precarica dati video: ", - "Filipino (auto-generated)": "Filippino (generati automaticamente)" + "Filipino (auto-generated)": "Filippino (generati automaticamente)", + "First page": "Prima pagina", + "channel_tab_courses_label": "Corsi", + "channel_tab_posts_label": "Post" } From 5953f7286f2ccc8815b400a683e1adc6b004a078 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:36 +0200 Subject: [PATCH 32/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ar.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index a8f5e62d..94103c29 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -154,8 +154,8 @@ "View YouTube comments": "عرض تعليقات اليوتيوب", "View more comments on Reddit": "عرض المزيد من التعليقات على\\من موقع ريديت", "View `x` comments": { - "([^.,0-9]|^)1([^.,0-9]|$)": "عرض `x` تعليقات", - "": "عرض `x` تعليقات." + "([^.,0-9]|^)1([^.,0-9]|$)": "عرض `x` تعليق", + "": "عرض `x` تعليقات" }, "View Reddit comments": "عرض تعليقات ريديت", "Hide replies": "إخفاء الردود", @@ -566,5 +566,8 @@ "carousel_skip": "تخطي الكاروسيل", "carousel_go_to": "انتقل إلى الشريحة `x`", "preferences_preload_label": "التحميل المسبق لبيانات الفيديو: ", - "Filipino (auto-generated)": "الفلبينية (المولدة تلقائيًا)" + "Filipino (auto-generated)": "الفلبينية (المولدة تلقائيًا)", + "channel_tab_courses_label": "الدورات", + "channel_tab_posts_label": "المنشورات", + "First page": "الصفحة الأولى" } From 42125dfadd3dc4a4811c08b42cc4f926c8cbcc9a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:36 +0200 Subject: [PATCH 33/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/nl.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/nl.json b/locales/nl.json index a908e26a..e9ce7674 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -498,5 +498,8 @@ "carousel_skip": "Carousel overslaan", "toggle_theme": "Thema omschakelen", "preferences_preload_label": "Videogegevens vooraf laden: ", - "Filipino (auto-generated)": "Filipijns (automatisch gegenereerd)" + "Filipino (auto-generated)": "Filipijns (automatisch gegenereerd)", + "channel_tab_courses_label": "Cursussen", + "First page": "Eerste pagina", + "channel_tab_posts_label": "Gepost" } From a5904ecce2ba23f2cca9c52de9b1d1d3318abf51 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:37 +0200 Subject: [PATCH 34/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/es.json | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/locales/es.json b/locales/es.json index ad65e07d..46217943 100644 --- a/locales/es.json +++ b/locales/es.json @@ -187,10 +187,10 @@ "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 existe", + "No such user": "El 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 (generado automáticamente)", + "English (auto-generated)": "Inglés (generados automáticamente)", "Afrikaans": "Afrikáans", "Albanian": "Albanés", "Amharic": "Amárico", @@ -276,7 +276,7 @@ "Somali": "Somalí", "Southern Sotho": "Sesoto", "Spanish": "Español", - "Spanish (Latin America)": "Español (Hispanoamérica)", + "Spanish (Latin America)": "Español (Latinoamérica)", "Sundanese": "Sondanés", "Swahili": "Suajili", "Swedish": "Sueco", @@ -412,8 +412,8 @@ "generic_count_weeks_1": "{{count}} semanas", "generic_count_weeks_2": "{{count}} semanas", "generic_playlists_count_0": "{{count}} lista de reproducción", - "generic_playlists_count_1": "{{count}} listas de reproducciones", - "generic_playlists_count_2": "{{count}} listas de reproducciones", + "generic_playlists_count_1": "{{count}} listas de reproducción", + "generic_playlists_count_2": "{{count}} listas de reproducción", "generic_videos_count_0": "{{count}} video", "generic_videos_count_1": "{{count}} videos", "generic_videos_count_2": "{{count}} videos", @@ -463,7 +463,7 @@ "Chinese (Hong Kong)": "Chino (Hong Kong)", "Chinese (China)": "Chino (China)", "Korean (auto-generated)": "Coreano (generados automáticamente)", - "Spanish (Mexico)": "Español (Méjico)", + "Spanish (Mexico)": "Español (México)", "Spanish (auto-generated)": "Español (generados automáticamente)", "preferences_watch_history_label": "Habilitar historial de reproducciones: ", "search_message_no_results": "No se han encontrado resultados.", @@ -500,7 +500,7 @@ "generic_button_cancel": "Cancelar", "generic_button_rss": "RSS", "channel_tab_podcasts_label": "Podcasts", - "channel_tab_releases_label": "Publicaciones", + "channel_tab_releases_label": "Lanzamientos", "generic_channels_count_0": "{{count}} canal", "generic_channels_count_1": "{{count}} canales", "generic_channels_count_2": "{{count}} canales", @@ -515,5 +515,8 @@ "carousel_skip": "Saltar el carrusel", "carousel_go_to": "Ir a la diapositiva `x`", "preferences_preload_label": "Precargar datos del vídeo: ", - "Filipino (auto-generated)": "Filipino (generado automáticamente)" + "Filipino (auto-generated)": "Filipino (generados automáticamente)", + "channel_tab_posts_label": "Publicaciones", + "First page": "Primera página", + "channel_tab_courses_label": "Cursos" } From 4d381aca6020b696582b63aa306e21a74284ffaa Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:37 +0200 Subject: [PATCH 35/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/fr.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index 800c7aaf..49aa09df 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -515,5 +515,8 @@ "carousel_go_to": "Aller à la diapositive `x`", "toggle_theme": "Changer le Thème", "Filipino (auto-generated)": "Philippines (automatiquement générer)", - "preferences_preload_label": "Précharger les données de la vidéo : " + "preferences_preload_label": "Précharger les données de la vidéo : ", + "First page": "Première page", + "channel_tab_courses_label": "Cours", + "channel_tab_posts_label": "Messages" } From 88195113bf92de6f876af63c5ad67f4b057cecee Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:38 +0200 Subject: [PATCH 36/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sv-SE.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/sv-SE.json b/locales/sv-SE.json index 614132e0..8f050d98 100644 --- a/locales/sv-SE.json +++ b/locales/sv-SE.json @@ -498,5 +498,8 @@ "carousel_skip": "Hoppa över karusellen", "carousel_go_to": "Gå till bildspel `x`", "preferences_preload_label": "Förladda video data: ", - "Filipino (auto-generated)": "Filippinska (auto-genererad)" + "Filipino (auto-generated)": "Filippinska (auto-genererad)", + "First page": "Första sidan", + "channel_tab_courses_label": "Kurser", + "channel_tab_posts_label": "Inlägg" } From b6b245586a051fcdce23c7f3093ca64b7dd17509 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:38 +0200 Subject: [PATCH 37/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sr.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/locales/sr.json b/locales/sr.json index 1d54972c..c6614ba5 100644 --- a/locales/sr.json +++ b/locales/sr.json @@ -513,7 +513,10 @@ "Answer": "Odgovor", "Search for videos": "Pretražite video snimke", "carousel_skip": "Preskoči karusel", - "toggle_theme": "Подеси тему", + "toggle_theme": "Podesi temu", "preferences_preload_label": "Unapred učitaj podatke o video snimku: ", - "Filipino (auto-generated)": "Filipinski (automatski generisano)" + "Filipino (auto-generated)": "Filipinski (automatski generisano)", + "channel_tab_posts_label": "Objave", + "First page": "Prva stranica", + "channel_tab_courses_label": "Kursevi" } From be469304deee53acd56d7d30c64d96ad4de522c5 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:39 +0200 Subject: [PATCH 38/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sq.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/locales/sq.json b/locales/sq.json index 2a404828..cdf4b605 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -494,5 +494,9 @@ "carousel_slide": "Diapozitiv {{current}} nga {{total}}", "carousel_go_to": "Kalo te diapozitivi `x`", "Filipino (auto-generated)": "Filipineze (të prodhuara automatikisht)", - "preferences_preload_label": "Parangarko të dhëna videoje: " + "preferences_preload_label": "Parangarko të dhëna videoje: ", + "toggle_theme": "Ndërroni Temë", + "channel_tab_courses_label": "Kurse", + "channel_tab_posts_label": "Postime", + "First page": "Faqja e parë" } From b9097d0a3b27325b5ca55bb556abd79eadf6de17 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:39 +0200 Subject: [PATCH 39/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ko.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/locales/ko.json b/locales/ko.json index c2d3f6e2..0224955f 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -419,7 +419,7 @@ "Portuguese (Brazil)": "포르투갈어 (브라질)", "search_message_no_results": "결과가 없습니다.", "search_message_change_filters_or_query": "필터를 변경하시거나 검색어를 넓게 시도해보세요.", - "search_message_use_another_instance": " 다른 인스턴스에서 검색할 수도 있습니다.", + "search_message_use_another_instance": "다른 인스턴스에서 검색할 수도 있습니다.", "English (United States)": "영어 (미국)", "Chinese": "중국어", "Chinese (China)": "중국어 (중국)", @@ -480,5 +480,9 @@ "Search for videos": "비디오 검색", "toggle_theme": "테마 전환", "carousel_slide": "{{total}}의 슬라이드 {{current}}", - "preferences_preload_label": "비디오 데이터 사전 로드: " + "preferences_preload_label": "비디오 데이터 사전 로드: ", + "First page": "첫 페이지", + "Filipino (auto-generated)": "Filipino (auto-generated)", + "channel_tab_posts_label": "게시글", + "channel_tab_courses_label": "코스" } From ee7b8b6c615c5e015b1cd8eb392804ad8b44059d Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:39 +0200 Subject: [PATCH 40/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pt-PT.json | 257 +++++++++++++++++++++++++++------------------ 1 file changed, 152 insertions(+), 105 deletions(-) diff --git a/locales/pt-PT.json b/locales/pt-PT.json index f83a80a9..449bde77 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -1,27 +1,27 @@ { - "LIVE": "Em direto", + "LIVE": "Direto", "Shared `x` ago": "Partilhado `x` atrás", "Unsubscribe": "Anular subscrição", "Subscribe": "Subscrever", "View channel on YouTube": "Ver canal no YouTube", "View playlist on YouTube": "Ver lista de reprodução no YouTube", - "newest": "mais recentes", - "oldest": "mais antigos", - "popular": "popular", + "newest": "recentes", + "oldest": "antigos", + "popular": "populares", "last": "últimos", - "Next page": "Próxima página", + "Next page": "Página seguinte", "Previous page": "Página anterior", "Clear watch history?": "Limpar histórico de reprodução?", - "New password": "Nova palavra-chave", - "New passwords must match": "As novas palavra-chaves devem corresponder", - "Authorize token?": "Autorizar token?", - "Authorize token for `x`?": "Autorizar token para `x`?", + "New password": "Nova palavra-passe", + "New passwords must match": "As novas palavras-passe devem ser iguais", + "Authorize token?": "Autorizar 'token'?", + "Authorize token for `x`?": "Autorizar 'token' para `x`?", "Yes": "Sim", "No": "Não", "Import and Export Data": "Importar e exportar dados", "Import": "Importar", "Import Invidious data": "Importar dados JSON do Invidious", - "Import YouTube subscriptions": "Importar subscrições do YouTube/OPML", + "Import YouTube subscriptions": "Importar via YouTube csv ou subscrição OPML", "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)", @@ -32,38 +32,38 @@ "Delete account?": "Eliminar conta?", "History": "Histórico", "An alternative front-end to YouTube": "Uma interface alternativa ao YouTube", - "JavaScript license information": "Informação de licença do JavaScript", - "source": "código-fonte", + "JavaScript license information": "Informação da licença JavaScript", + "source": "fonte", "Log in": "Iniciar sessão", "Log in/register": "Iniciar sessão/registar", "User ID": "Utilizador", - "Password": "Palavra-chave", + "Password": "Palavra-passe", "Time (h:mm:ss):": "Tempo (h:mm:ss):", "Text CAPTCHA": "Texto CAPTCHA", "Image CAPTCHA": "Imagem CAPTCHA", - "Sign In": "Iniciar sessão", + "Sign In": "Entrar", "Register": "Registar", "E-mail": "E-mail", "Preferences": "Preferências", "preferences_category_player": "Preferências do reprodutor", "preferences_video_loop_label": "Repetir sempre: ", "preferences_autoplay_label": "Reprodução automática: ", - "preferences_continue_label": "Reproduzir sempre o próximo: ", + "preferences_continue_label": "Reproduzir sempre o seguinte: ", "preferences_continue_autoplay_label": "Reproduzir próximo vídeo automaticamente: ", "preferences_listen_label": "Apenas áudio: ", "preferences_local_label": "Usar proxy nos vídeos: ", "preferences_speed_label": "Velocidade preferida: ", "preferences_quality_label": "Qualidade de vídeo preferida: ", - "preferences_volume_label": "Volume da reprodução: ", - "preferences_comments_label": "Preferência dos comentários: ", + "preferences_volume_label": "Volume de reprodução: ", + "preferences_comments_label": "Comentários padrão: ", "youtube": "YouTube", "reddit": "Reddit", - "preferences_captions_label": "Legendas predefinidas: ", + "preferences_captions_label": "Legendas padrão: ", "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 (necessita de WebGL): ", + "preferences_extend_desc_label": "Expandir automaticamente a descrição do vídeo: ", + "preferences_vr_mode_label": "Vídeos interativos de 360 graus (requer WebGL): ", "preferences_category_visual": "Preferências visuais", "preferences_player_style_label": "Estilo do reprodutor: ", "Dark mode: ": "Modo escuro: ", @@ -74,9 +74,9 @@ "preferences_category_misc": "Preferências diversas", "preferences_automatic_instance_redirect_label": "Redirecionamento de instância automática (solução de último recurso para redirect.invidious.io): ", "preferences_category_subscription": "Preferências de subscrições", - "preferences_annotations_subscribed_label": "Mostrar sempre anotações aos canais subscritos: ", + "preferences_annotations_subscribed_label": "Mostrar sempre anotações nos canais subscritos: ", "Redirect homepage to feed: ": "Redirecionar página inicial para subscrições: ", - "preferences_max_results_label": "Quantidade de vídeos nas subscrições: ", + "preferences_max_results_label": "Número de vídeos nas subscrições: ", "preferences_sort_label": "Ordenar vídeos por: ", "published": "publicado", "published - reverse": "publicado - inverso", @@ -88,19 +88,19 @@ "Only show latest unwatched video from channel: ": "Mostrar apenas vídeos mais recentes não visualizados do canal: ", "preferences_unseen_only_label": "Mostrar apenas vídeos não visualizados: ", "preferences_notifications_only_label": "Mostrar apenas notificações (se existirem): ", - "Enable web notifications": "Ativar notificações pela web", - "`x` uploaded a video": "`x` publicou um novo vídeo", + "Enable web notifications": "Ativar notificações web", + "`x` uploaded a video": "`x` publicou um vídeo", "`x` is live": "`x` está em direto", "preferences_category_data": "Preferências de dados", "Clear watch history": "Limpar histórico de reprodução", - "Import/export data": "Importar / exportar dados", - "Change password": "Alterar palavra-chave", - "Manage subscriptions": "Gerir as subscrições", + "Import/export data": "Importar/exportar dados", + "Change password": "Alterar palavra-passe", + "Manage subscriptions": "Gerir subscrições", "Manage tokens": "Gerir tokens", "Watch history": "Histórico de reprodução", "Delete account": "Eliminar conta", "preferences_category_admin": "Preferências de administrador", - "preferences_default_home_label": "Página inicial predefinida: ", + "preferences_default_home_label": "Página inicial padrão: ", "preferences_feed_menu_label": "Menu de subscrições: ", "preferences_show_nick_label": "Mostrar nome de utilizador em cima: ", "Top enabled: ": "Destaques ativados: ", @@ -109,28 +109,29 @@ "Registration enabled: ": "Registar ativado: ", "Report statistics: ": "Relatório de estatísticas: ", "Save preferences": "Guardar preferências", - "Subscription manager": "Gerir subscrições", - "Token manager": "Gerir tokens", + "Subscription manager": "Gestor de subscrições", + "Token manager": "Gestor de tokens", "Token": "Token", - "tokens_count": "{{count}} token", - "tokens_count_plural": "{{count}} tokens", - "Import/export": "Importar / exportar", + "tokens_count_0": "{{count}} token", + "tokens_count_1": "{{count}} tokens", + "tokens_count_2": "{{count}} tokens", + "Import/export": "Importar/exportar", "unsubscribe": "anular subscrição", "revoke": "revogar", "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.": "Disponibilizada 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.", + "View JavaScript license information.": "Ver informações da licença JavaScript.", + "View privacy policy.": "Ver política de privacidade.", "Trending": "Tendências", "Public": "Público", "Unlisted": "Não listado", "Private": "Privado", "View all playlists": "Ver todas as listas de reprodução", - "Updated `x` ago": "Atualizado `x` atrás", - "Delete playlist `x`?": "Eliminar a lista de reprodução `x`?", + "Updated `x` ago": "Atualizado há `x`", + "Delete playlist `x`?": "Eliminar lista de reprodução `x`?", "Delete playlist": "Eliminar lista de reprodução", "Create playlist": "Criar lista de reprodução", "Title": "Título", @@ -139,7 +140,7 @@ "Show more": "Mostrar mais", "Show less": "Mostrar menos", "Watch on YouTube": "Ver no YouTube", - "Switch Invidious Instance": "Mudar a instância do Invidious", + "Switch Invidious Instance": "Alterar instância Invidious", "Hide annotations": "Ocultar anotações", "Show annotations": "Mostrar anotações", "Genre: ": "Género: ", @@ -150,27 +151,27 @@ "Whitelisted regions: ": "Regiões permitidas: ", "Blacklisted regions: ": "Regiões bloqueadas: ", "Shared `x`": "Partilhado `x`", - "Premieres in `x`": "Estreias em `x`", - "Premieres `x`": "Estreias `x`", - "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Olá! Parece que o JavaScript está desativado. Clique aqui para ver os comentários, entretanto eles podem levar mais tempo para carregar.", + "Premieres in `x`": "Estreia a `x`", + "Premieres `x`": "Estreia `x`", + "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Olá! Parece que o JavaScript está desativado. Clique aqui para ver os comentários, mas tenha e conta que podem levar mais tempo para carregar.", "View YouTube comments": "Ver comentários do YouTube", "View more comments on Reddit": "Ver mais comentários no Reddit", "View `x` comments": { - "([^.,0-9]|^)1([^.,0-9]|$)": "Ver `x` comentários", + "([^.,0-9]|^)1([^.,0-9]|$)": "Ver `x` comentário", "": "Ver `x` comentários" }, "View Reddit comments": "Ver comentários do Reddit", "Hide replies": "Ocultar respostas", "Show replies": "Mostrar respostas", - "Incorrect password": "Palavra-chave incorreta", + "Incorrect password": "Palavra-passe incorreta", "Wrong answer": "Resposta errada", "Erroneous CAPTCHA": "CAPTCHA inválido", "CAPTCHA is a required field": "CAPTCHA é um campo obrigatório", "User ID is a required field": "O nome de utilizador é um campo obrigatório", - "Password is a required field": "Palavra-chave é um campo obrigatório", - "Wrong username or password": "Nome de utilizador ou palavra-chave incorreto", - "Password cannot be empty": "A palavra-chave não pode estar vazia", - "Password cannot be longer than 55 characters": "A palavra-chave não pode ser superior a 55 caracteres", + "Password is a required field": "Palavra-passe é um campo obrigatório", + "Wrong username or password": "Nome de utilizador ou palavra-passe incorreta", + "Password cannot be empty": "A palavra-passe não pode estar vazia", + "Password cannot be longer than 55 characters": "A palavra-passe não pode ter mais do que 55 caracteres", "Please log in": "Por favor, inicie sessão", "Invidious Private Feed for `x`": "Feed Privado do Invidious para `x`", "channel:`x`": "canal:`x`", @@ -180,20 +181,20 @@ "Could not fetch comments": "Não foi possível obter os comentários", "`x` ago": "`x` atrás", "Load more": "Carregar mais", - "Could not create mix.": "Não foi possível criar a mistura.", + "Could not create mix.": "Não foi possível criar o mix.", "Empty playlist": "Lista de reprodução vazia", "Not a playlist.": "Não é uma lista de reprodução.", "Playlist does not exist.": "A lista de reprodução não existe.", - "Could not pull trending pages.": "Não foi possível obter as páginas de tendências.", + "Could not pull trending pages.": "Não foi possível obter a página de tendências.", "Hidden field \"challenge\" is a required field": "O campo oculto \"desafio\" é obrigatório", "Hidden field \"token\" is a required field": "O campo oculto \"token\" é um campo obrigatório", "Erroneous challenge": "Desafio inválido", "Erroneous token": "Token inválido", "No such user": "Utilizador inválido", - "Token is expired, please try again": "Token expirou, tente novamente", + "Token is expired, please try again": "Token caducado, tente novamente", "English": "Inglês", "English (auto-generated)": "Inglês (auto-gerado)", - "Afrikaans": "Africano", + "Afrikaans": "Africânder", "Albanian": "Albanês", "Amharic": "Amárico", "Arabic": "Árabe", @@ -209,7 +210,7 @@ "Cebuano": "Cebuano", "Chinese (Simplified)": "Chinês (simplificado)", "Chinese (Traditional)": "Chinês (tradicional)", - "Corsican": "Corso", + "Corsican": "Córsego", "Croatian": "Croata", "Czech": "Checo", "Danish": "Dinamarquês", @@ -252,7 +253,7 @@ "Macedonian": "Macedónio", "Malagasy": "Malgaxe", "Malay": "Malaio", - "Malayalam": "Malaiala", + "Malayalam": "Malaialaio", "Maltese": "Maltês", "Maori": "Maori", "Marathi": "Marathi", @@ -297,30 +298,37 @@ "Yiddish": "Iídiche", "Yoruba": "Ioruba", "Zulu": "Zulu", - "generic_count_years": "{{count}} ano", - "generic_count_years_plural": "{{count}} anos", - "generic_count_months": "{{count}} mês", - "generic_count_months_plural": "{{count}} meses", - "generic_count_weeks": "{{count}} seman", - "generic_count_weeks_plural": "{{count}} semanas", - "generic_count_days": "{{count}} dia", - "generic_count_days_plural": "{{count}} dias", - "generic_count_hours": "{{count}} hora", - "generic_count_hours_plural": "{{count}} horas", - "generic_count_minutes": "{{count}} minuto", - "generic_count_minutes_plural": "{{count}} minutos", - "generic_count_seconds": "{{count}} segundo", - "generic_count_seconds_plural": "{{count}} segundos", - "Fallback comments: ": "Comentários alternativos: ", + "generic_count_years_0": "{{count}} ano", + "generic_count_years_1": "{{count}} anos", + "generic_count_years_2": "{{count}} anos", + "generic_count_months_0": "{{count}} mês", + "generic_count_months_1": "{{count}} meses", + "generic_count_months_2": "{{count}} meses", + "generic_count_weeks_0": "{{count}} semana", + "generic_count_weeks_1": "{{count}} semanas", + "generic_count_weeks_2": "{{count}} semanas", + "generic_count_days_0": "{{count}} dia", + "generic_count_days_1": "{{count}} dias", + "generic_count_days_2": "{{count}} dias", + "generic_count_hours_0": "{{count}} hora", + "generic_count_hours_1": "{{count}} horas", + "generic_count_hours_2": "{{count}} horas", + "generic_count_minutes_0": "{{count}} minuto", + "generic_count_minutes_1": "{{count}} minutos", + "generic_count_minutes_2": "{{count}} minutos", + "generic_count_seconds_0": "{{count}} segundo", + "generic_count_seconds_1": "{{count}} segundos", + "generic_count_seconds_2": "{{count}} segundos", + "Fallback comments: ": "Alternativa para comentários: ", "Popular": "Popular", "Search": "Pesquisar", "Top": "Destaques", - "About": "Sobre", + "About": "Acerca", "Rating: ": "Avaliação: ", "preferences_locale_label": "Idioma: ", "View as playlist": "Ver como lista de reprodução", - "Default": "Predefinido", - "Music": "Música", + "Default": "Padrão", + "Music": "Músicas", "Gaming": "Jogos", "News": "Notícias", "Movies": "Filmes", @@ -328,9 +336,9 @@ "Download as: ": "Descarregar como: ", "%A %B %-d, %Y": "%A %B %-d, %Y", "(edited)": "(editado)", - "YouTube comment permalink": "Hiperligação permanente do comentário no YouTube", - "permalink": "hiperligação permanente", - "`x` marked it with a ❤": "`x` foi marcado como ❤", + "YouTube comment permalink": "Ligação permanente do comentário no YouTube", + "permalink": "ligação permanente", + "`x` marked it with a ❤": "`x` foi marcado com um ❤", "Audio mode": "Modo de áudio", "Video mode": "Modo de vídeo", "channel_tab_videos_label": "Vídeos", @@ -338,7 +346,7 @@ "channel_tab_community_label": "Comunidade", "search_filters_sort_option_relevance": "Relevância", "search_filters_sort_option_rating": "Avaliação", - "search_filters_sort_option_date": "Data de envio", + "search_filters_sort_option_date": "Data de carregamento", "search_filters_sort_option_views": "Visualizações", "search_filters_type_label": "Tipo", "search_filters_duration_label": "Duração", @@ -353,38 +361,44 @@ "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_type_option_show": "Séries", "search_filters_features_option_hd": "HD", "search_filters_features_option_subtitles": "Legendas", "search_filters_features_option_c_commons": "Creative Commons", "search_filters_features_option_three_d": "3D", - "search_filters_features_option_live": "Em direto", + "search_filters_features_option_live": "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_refresh": "Recarregar", + "next_steps_error_message_go_to_youtube": "Ir para o 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}} inscrição", - "generic_subscriptions_count_plural": "{{count}} inscrições", - "generic_views_count": "{{count}} visualização", - "generic_views_count_plural": "{{count}} visualizações", - "generic_subscribers_count": "{{count}} inscrito", - "generic_subscribers_count_plural": "{{count}} inscritos", + "generic_videos_count_0": "{{count}} vídeo", + "generic_videos_count_1": "{{count}} vídeos", + "generic_videos_count_2": "{{count}} vídeos", + "generic_playlists_count_0": "{{count}} lista de reprodução", + "generic_playlists_count_1": "{{count}} listas de reprodução", + "generic_playlists_count_2": "{{count}} listas de reprodução", + "generic_subscriptions_count_0": "{{count}} subscrição", + "generic_subscriptions_count_1": "{{count}} subscrições", + "generic_subscriptions_count_2": "{{count}} subscrições", + "generic_views_count_0": "{{count}} visualização", + "generic_views_count_1": "{{count}} visualizações", + "generic_views_count_2": "{{count}} visualizações", + "generic_subscribers_count_0": "{{count}} subscritor", + "generic_subscribers_count_1": "{{count}} subscritores", + "generic_subscribers_count_2": "{{count}} subscritores", "preferences_quality_dash_option_4320p": "4320p", "preferences_quality_dash_label": "Qualidade de vídeo DASH preferida: ", "preferences_quality_dash_option_2160p": "2160p", - "subscriptions_unseen_notifs_count": "{{count}} notificação não vista", - "subscriptions_unseen_notifs_count_plural": "{{count}} notificações não vistas", + "subscriptions_unseen_notifs_count_0": "{{count}} notificação não vista", + "subscriptions_unseen_notifs_count_1": "{{count}} notificações não vistas", + "subscriptions_unseen_notifs_count_2": "{{count}} notificações não vistas", "Popular enabled: ": "Página \"popular\" ativada: ", "search_message_no_results": "Nenhum resultado encontrado.", - "preferences_quality_dash_option_auto": "Automático", + "preferences_quality_dash_option_auto": "Automática", "preferences_region_label": "País do conteúdo: ", "preferences_quality_dash_option_1440p": "1440p", "preferences_quality_dash_option_720p": "720p", @@ -403,10 +417,12 @@ "preferences_quality_dash_option_240p": "240p", "Video unavailable": "Vídeo não disponível", "Russian (auto-generated)": "Russo (gerado 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", + "comments_view_x_replies_0": "Ver {{count}} resposta", + "comments_view_x_replies_1": "Ver {{count}} respostas", + "comments_view_x_replies_2": "Ver {{count}} respostas", + "comments_points_count_0": "{{count}} ponto", + "comments_points_count_1": "{{count}} pontos", + "comments_points_count_2": "{{count}} pontos", "English (United Kingdom)": "Inglês (Reino Unido)", "Chinese (Hong Kong)": "Chinês (Hong Kong)", "Chinese (Taiwan)": "Chinês (Taiwan)", @@ -432,13 +448,13 @@ "videoinfo_watch_on_youTube": "Ver no YouTube", "videoinfo_youTube_embed_link": "Incorporar", "adminprefs_modified_source_code_url_label": "URL do repositório do código-fonte alterado", - "videoinfo_invidious_embed_link": "Incorporar hiperligação", + "videoinfo_invidious_embed_link": "Incorporar ligação", "none": "nenhum", "videoinfo_started_streaming_x_ago": "Iniciou a transmissão 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 a posição de reprodução atual do vídeo: ", + "preferences_save_player_pos_label": "Guardar posição de reprodução: ", "Turkish (auto-generated)": "Turco (gerado automaticamente)", "Cantonese (Hong Kong)": "Cantonês (Hong Kong)", "Chinese (China)": "Chinês (China)", @@ -455,21 +471,52 @@ "search_filters_date_option_none": "Qualquer data", "search_filters_features_option_three_sixty": "360°", "search_filters_features_option_vr180": "VR180", - "search_message_use_another_instance": " Também pode pesquisar noutra instância.", + "search_message_use_another_instance": "Também pode pesquisar noutra instância.", "crash_page_you_found_a_bug": "Parece que encontrou um erro no Invidious!", "crash_page_before_reporting": "Antes de reportar um erro, verifique se:", - "crash_page_read_the_faq": "leia as Perguntas frequentes (FAQ)", + "crash_page_read_the_faq": "leu as Perguntas frequentes (FAQ)", "crash_page_search_issue": "procurou se o erro já foi reportado no GitHub", - "crash_page_report_issue": "Se nenhuma opção acima ajudou, por favor abra um novo problema no Github (preferencialmente em inglês) e inclua o seguinte texto tal qual (NÃO o traduza):", + "crash_page_report_issue": "Se nenhuma opção acima ajudou, por favor abra um novo problema no Github (preferencialmente em inglês) e inclua o seguinte texto (NÃO o traduza):", "search_message_change_filters_or_query": "Tente alargar os termos genéricos da pesquisa e/ou alterar os filtros.", "crash_page_refresh": "tentou recarregar a página", "crash_page_switch_instance": "tentou usar outra instância", - "error_video_not_in_playlist": "O vídeo pedido não existe nesta lista de reprodução. Clique aqui para a página inicial da lista de reprodução.", + "error_video_not_in_playlist": "O vídeo pedido não existe nesta lista de reprodução. Clique aqui para voltar à página inicial da lista de reprodução.", "Artist: ": "Artista: ", "Album: ": "Álbum: ", - "channel_tab_streams_label": "Diretos", + "channel_tab_streams_label": "Emissões em direto", "channel_tab_playlists_label": "Listas de reprodução", "channel_tab_channels_label": "Canais", "Music in this video": "Música neste vídeo", - "channel_tab_shorts_label": "Curtos" + "channel_tab_shorts_label": "Curtos", + "generic_button_delete": "Eliminar", + "generic_button_edit": "Editar", + "generic_button_save": "Guardar", + "generic_button_cancel": "Cancelar", + "Import YouTube playlist (.csv)": "Importar lista de reprodução do YouTube (.csv)", + "Song: ": "Canção: ", + "Answer": "Responder", + "The Popular feed has been disabled by the administrator.": "O feed Popular foi desativado por um administrador.", + "Channel Sponsor": "Patrocinador do canal", + "Download is disabled": "A descarga está desativada", + "Add to playlist": "Adicionar à lista de reprodução", + "Add to playlist: ": "Adicionar à lista de reprodução: ", + "Search for videos": "Procurar vídeos", + "generic_channels_count_0": "{{count}} canal", + "generic_channels_count_1": "{{count}} canais", + "generic_channels_count_2": "{{count}} canais", + "generic_button_rss": "RSS", + "Import YouTube watch history (.json)": "Importar histórico de reprodução do YouTube (.json)", + "preferences_preload_label": "Pré-carregamento dos dados: ", + "playlist_button_add_items": "Adicionar vídeos", + "channel_tab_podcasts_label": "Podcasts", + "channel_tab_releases_label": "Lançamentos", + "carousel_slide": "Diapositivo {{current}} de{{total}}", + "carousel_skip": "Ignorar carrossel", + "carousel_go_to": "Ir para o diapositivo`x`", + "First page": "Primeira página", + "Standard YouTube license": "Licença padrão do YouTube", + "Filipino (auto-generated)": "Filipino (gerado automaticamente)", + "channel_tab_courses_label": "Cursos", + "channel_tab_posts_label": "Publicações", + "toggle_theme": "Trocar tema" } From 9f192d4f741537bcfeb32b18130ce6e9653f0135 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:40 +0200 Subject: [PATCH 41/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/zh-TW.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/zh-TW.json b/locales/zh-TW.json index b3d67130..77805349 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -481,5 +481,8 @@ "carousel_go_to": "跳到投影片 `x`", "The Popular feed has been disabled by the administrator.": "熱門 feed 已被管理員停用。", "preferences_preload_label": "預先載入影片資訊 ", - "Filipino (auto-generated)": "菲律賓語(自動產生)" + "Filipino (auto-generated)": "菲律賓語(自動產生)", + "channel_tab_courses_label": "課程", + "First page": "第一頁", + "channel_tab_posts_label": "貼文" } From 8d0834005fbec08915acd5bab5333186594eb7ca Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:40 +0200 Subject: [PATCH 42/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/zh-CN.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 2024bdd5..f3bc660b 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -420,7 +420,7 @@ "Chinese": "中文", "Chinese (China)": "中文 (中国)", "Chinese (Hong Kong)": "中文 (中国香港)", - "Chinese (Taiwan)": "中文 (中国台湾)", + "Chinese (Taiwan)": "中文 (台湾)", "German (auto-generated)": "德语 (自动生成)", "Indonesian (auto-generated)": "印尼语 (自动生成)", "Interlingue": "国际语", @@ -481,5 +481,8 @@ "carousel_skip": "跳过图集", "carousel_go_to": "转到图 `x`", "preferences_preload_label": "预加载视频数据: ", - "Filipino (auto-generated)": "菲律宾语 (自动生成)" + "Filipino (auto-generated)": "菲律宾语 (自动生成)", + "channel_tab_posts_label": "帖子", + "First page": "第一页", + "channel_tab_courses_label": "课程" } From 9e172d837169e70e0841bbb2e89e0018bda3edc2 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 12 May 2025 17:03:41 +0200 Subject: [PATCH 43/48] Update translation files Updated by "Remove blank strings" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sr_Cyrl.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locales/sr_Cyrl.json b/locales/sr_Cyrl.json index e5279c8a..e6ab0f35 100644 --- a/locales/sr_Cyrl.json +++ b/locales/sr_Cyrl.json @@ -515,5 +515,8 @@ "The Popular feed has been disabled by the administrator.": "Администратор је онемогућио фид „Популарно“.", "carousel_slide": "Слајд {{current}} од {{total}}", "preferences_preload_label": "Унапред учитај податке о видео снимку: ", - "Filipino (auto-generated)": "Филипински (аутоматски генерисано)" + "Filipino (auto-generated)": "Филипински (аутоматски генерисано)", + "channel_tab_courses_label": "Курсеви", + "First page": "Прва страница", + "channel_tab_posts_label": "Објаве" } From 6376fd55dba2155a1f1a1aa40258eff77147c864 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 17 May 2025 13:17:26 -0400 Subject: [PATCH 44/48] Remove text captcha due to textcaptcha.com being down Fixes https://github.com/iv-org/invidious/issues/5295 textcaptcha.com seems to be down since April and it does not appear that service will be restored. Text captchas can be easily automated using free LLMs, so keeping the text captcha is more like a gate to create accounts in mass on public Invidious instances. It also gives headaches like bots automating account creation to modify the videos that appear popular page of each instance (since the popular page is based on the subscriptions of the registered users). --- src/invidious/routes/login.cr | 52 +++--------------------------- src/invidious/user/captcha.cr | 16 --------- src/invidious/views/user/login.ecr | 39 ++++------------------ 3 files changed, 11 insertions(+), 96 deletions(-) diff --git a/src/invidious/routes/login.cr b/src/invidious/routes/login.cr index d0f7ac22..e7de5018 100644 --- a/src/invidious/routes/login.cr +++ b/src/invidious/routes/login.cr @@ -21,9 +21,6 @@ module Invidious::Routes::Login account_type = env.params.query["type"]? account_type ||= "invidious" - captcha_type = env.params.query["captcha"]? - captcha_type ||= "image" - templated "user/login" end @@ -88,34 +85,14 @@ module Invidious::Routes::Login password = password.byte_slice(0, 55) if CONFIG.captcha_enabled - captcha_type = env.params.body["captcha_type"]? answer = env.params.body["answer"]? - change_type = env.params.body["change_type"]? - if !captcha_type || change_type - if change_type - captcha_type = change_type - end - captcha_type ||= "image" - - account_type = "invidious" - - if captcha_type == "image" - captcha = Invidious::User::Captcha.generate_image(HMAC_KEY) - else - captcha = Invidious::User::Captcha.generate_text(HMAC_KEY) - end - - return templated "user/login" - end + account_type = "invidious" + captcha = Invidious::User::Captcha.generate_image(HMAC_KEY) tokens = env.params.body.select { |k, _| k.match(/^token\[\d+\]$/) }.map { |_, v| v } - answer ||= "" - captcha_type ||= "image" - - case captcha_type - when "image" + if answer answer = answer.lstrip('0') answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer) @@ -124,27 +101,8 @@ module Invidious::Routes::Login rescue ex return error_template(400, ex) end - else # "text" - answer = Digest::MD5.hexdigest(answer.downcase.strip) - - if tokens.empty? - return error_template(500, "Erroneous CAPTCHA") - end - - found_valid_captcha = false - error_exception = Exception.new - tokens.each do |tok| - begin - validate_request(tok, answer, env.request, HMAC_KEY, locale) - found_valid_captcha = true - rescue ex - error_exception = ex - end - end - - if !found_valid_captcha - return error_template(500, error_exception) - end + else + return templated "user/login" end end diff --git a/src/invidious/user/captcha.cr b/src/invidious/user/captcha.cr index 8a0f67e5..b175c3b9 100644 --- a/src/invidious/user/captcha.cr +++ b/src/invidious/user/captcha.cr @@ -4,8 +4,6 @@ struct Invidious::User module Captcha extend self - private TEXTCAPTCHA_URL = URI.parse("https://textcaptcha.com") - def generate_image(key) second = Random::Secure.rand(12) second_angle = second * 30 @@ -60,19 +58,5 @@ struct Invidious::User tokens: {generate_response(answer, {":login"}, key, use_nonce: true)}, } end - - def generate_text(key) - response = make_client(TEXTCAPTCHA_URL, &.get("/github.com/iv.org/invidious.json").body) - response = JSON.parse(response) - - tokens = response["a"].as_a.map do |answer| - generate_response(answer.as_s, {":login"}, key, use_nonce: true) - end - - return { - question: response["q"].as_s, - tokens: tokens, - } - end end end diff --git a/src/invidious/views/user/login.ecr b/src/invidious/views/user/login.ecr index 2b03d280..7ac96bc6 100644 --- a/src/invidious/views/user/login.ecr +++ b/src/invidious/views/user/login.ecr @@ -25,44 +25,17 @@ <% end %> <% if captcha %> - <% case captcha_type when %> - <% when "image" %> - <% captcha = captcha.not_nil! %> - - <% captcha[:tokens].each_with_index do |token, i| %> - - <% end %> - - - - <% else # "text" %> - <% captcha = captcha.not_nil! %> - <% captcha[:tokens].each_with_index do |token, i| %> - - <% end %> - - - "> + <% captcha = captcha.not_nil! %> + + <% captcha[:tokens].each_with_index do |token, i| %> + <% end %> + + - - <% case captcha_type when %> - <% when "image" %> - - <% else # "text" %> - - <% end %> <% else %>