From 73bf956af5ff2595c4840397924127e7cf329598 Mon Sep 17 00:00:00 2001 From: epicsam123 <92618898+epicsam123@users.noreply.github.com> Date: Wed, 19 Feb 2025 21:08:45 -0500 Subject: [PATCH 001/108] captions: provide "w", "o", "-", "+" keydowns for player from YT --- assets/css/player.css | 18 +++++++++++++++--- assets/js/player.js | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/assets/css/player.css b/assets/css/player.css index 9cb400ad..028d5631 100644 --- a/assets/css/player.css +++ b/assets/css/player.css @@ -71,8 +71,10 @@ padding-top: 2em } -.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control {height: 5px; -margin-bottom: 10px;} +.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control { + height: 5px; + margin-bottom: 10px; +} ul.vjs-menu-content::-webkit-scrollbar { display: none; @@ -82,10 +84,20 @@ ul.vjs-menu-content::-webkit-scrollbar { cursor: none; } +/* Customizable CSS in player.js */ +.vjs-text-track-display > div > div +{ + background-color: rgba(0, 0, 0, 0); /* caption window background: toggle with "w" event */ +} + +/* Customizable CSS in player.js */ .video-js .vjs-text-track-display > div > div > div { - background-color: rgba(0, 0, 0, 0.75) !important; + font-size: 27px !important; /* Toggle with "-/=" event */ + background-color: rgba(0, 0, 0, 0.75) !important; /* caption background: toggle with "w" event */ + color: rgb(255, 255, 255, 1) !important; /* caption text: toggle with "o" event */ border-radius: 9px !important; padding: 5px !important; + line-height: 1.5 !important; } .vjs-play-control, diff --git a/assets/js/player.js b/assets/js/player.js index 353a5296..c74a68a4 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -2,9 +2,16 @@ var player_data = JSON.parse(document.getElementById('player_data').textContent); var video_data = JSON.parse(document.getElementById('video_data').textContent); +var player_css = [...Array.from(document.styleSheets).find(sS => sS.href?.includes('player.css')).cssRules] +var caption_background_css = player_css.find(rule => rule.selectorText === '.vjs-text-track-display > div > div'); +var caption_text_css = player_css.find(rule => rule.selectorText === '.video-js .vjs-text-track-display > div > div > div'); + var options = { liveui: true, playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0], + captionSizes: ['22px', '27px', '32px', '37px'], + captionBackground: [0, 0.5, 0.8, 1].map(a => 'rgba(0, 0, 0, ' + a + ')'), + captionOpacity: [0.4, 0.7, 1].map(a => 'rgba(255, 255, 255, ' + a + ')'), controlBar: { children: [ 'playToggle', @@ -591,6 +598,31 @@ function increase_playback_rate(steps) { player.playbackRate(options.playbackRates[newIndex]); } +function increase_caption_size(steps) { + const maxIndex = options.captionSizes.length - 1; + const font_size = caption_text_css.style.getPropertyValue('font-size'); + const curIndex = options.captionSizes.indexOf(font_size); + let newIndex = curIndex + steps; + newIndex = helpers.clamp(newIndex, 0, maxIndex); + caption_text_css.style.setProperty('font-size', options.captionSizes[newIndex], 'important'); +} + +function toggle_caption_window() { + const numOptions = options.captionBackground.length; + const backgroundColor = caption_background_css.style.getPropertyValue('background-color'); + const curIndex = options.captionBackground.indexOf(backgroundColor); + const newIndex = (curIndex + 1) % numOptions; + caption_background_css.style.setProperty('background-color', options.captionBackground[newIndex], 'important'); +} + +function toggle_caption_opacity() { + const numOptions = options.captionOpacity.length; + const opacity = caption_text_css.style.getPropertyValue('color'); + const curIndex = options.captionOpacity.indexOf(opacity); + const newIndex = (curIndex + 1) % numOptions; + caption_text_css.style.setProperty('color', options.captionOpacity[newIndex], 'important'); +} + addEventListener('keydown', function (e) { if (e.target.tagName.toLowerCase() === 'input') { // Ignore input when focus is on certain elements, e.g. form fields. @@ -686,6 +718,12 @@ addEventListener('keydown', function (e) { case '>': action = increase_playback_rate.bind(this, 1); break; case '<': action = increase_playback_rate.bind(this, -1); break; + + case '=': action = increase_caption_size.bind(this, 1); break; + case '-': action = increase_caption_size.bind(this, -1); break; + + case 'w': action = toggle_caption_window; break; + case 'o': action = toggle_caption_opacity; break; default: console.info('Unhandled key down event: %s:', decoratedKey, e); From bc3b3f6d69977e799f4d4e99d5c0283916d0ca83 Mon Sep 17 00:00:00 2001 From: epicsam123 <92618898+epicsam123@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:09:43 -0400 Subject: [PATCH 002/108] updated caption features to use videojs interface --- assets/css/player.css | 11 +-------- assets/js/player.js | 52 ++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/assets/css/player.css b/assets/css/player.css index 028d5631..60f3ce73 100644 --- a/assets/css/player.css +++ b/assets/css/player.css @@ -84,17 +84,8 @@ ul.vjs-menu-content::-webkit-scrollbar { cursor: none; } -/* Customizable CSS in player.js */ -.vjs-text-track-display > div > div -{ - background-color: rgba(0, 0, 0, 0); /* caption window background: toggle with "w" event */ -} - -/* Customizable CSS in player.js */ .video-js .vjs-text-track-display > div > div > div { - font-size: 27px !important; /* Toggle with "-/=" event */ - background-color: rgba(0, 0, 0, 0.75) !important; /* caption background: toggle with "w" event */ - color: rgb(255, 255, 255, 1) !important; /* caption text: toggle with "o" event */ + background-color: rgba(0, 0, 0, 0.75) !important; border-radius: 9px !important; padding: 5px !important; line-height: 1.5 !important; diff --git a/assets/js/player.js b/assets/js/player.js index c74a68a4..dce432cb 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -2,16 +2,12 @@ var player_data = JSON.parse(document.getElementById('player_data').textContent); var video_data = JSON.parse(document.getElementById('video_data').textContent); -var player_css = [...Array.from(document.styleSheets).find(sS => sS.href?.includes('player.css')).cssRules] -var caption_background_css = player_css.find(rule => rule.selectorText === '.vjs-text-track-display > div > div'); -var caption_text_css = player_css.find(rule => rule.selectorText === '.video-js .vjs-text-track-display > div > div > div'); - var options = { liveui: true, playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0], - captionSizes: ['22px', '27px', '32px', '37px'], - captionBackground: [0, 0.5, 0.8, 1].map(a => 'rgba(0, 0, 0, ' + a + ')'), - captionOpacity: [0.4, 0.7, 1].map(a => 'rgba(255, 255, 255, ' + a + ')'), + fontPercent: [0.5, 0.75, 1.25, 1.5, 1.75, 2, 3, 4], + windowOpacity: ['0', '0.5', '1'], + textOpacity: ['0.5', '1'], controlBar: { children: [ 'playToggle', @@ -543,9 +539,9 @@ const toggle_captions = (function () { bindChange('off'); track.mode = mode; setTimeout(function () { - bindChange('on'); + bindChange('on'); }, 0); - } + } bindChange('on'); return function () { @@ -586,6 +582,13 @@ const toggle_captions = (function () { }; })(); +// For real-time updates to captions (if currently showing) +function update_captions() { + if (document.body.querySelector('.vjs-text-track-cue')) { + toggle_captions(); toggle_captions(); + } +} + function toggle_fullscreen() { player.isFullscreen() ? player.exitFullscreen() : player.requestFullscreen(); } @@ -599,28 +602,31 @@ function increase_playback_rate(steps) { } function increase_caption_size(steps) { - const maxIndex = options.captionSizes.length - 1; - const font_size = caption_text_css.style.getPropertyValue('font-size'); - const curIndex = options.captionSizes.indexOf(font_size); + const maxIndex = options.fontPercent.length - 1; + const fontPercent = player.textTrackSettings.getValues().fontPercent || 1.25; + const curIndex = options.fontPercent.indexOf(fontPercent); let newIndex = curIndex + steps; newIndex = helpers.clamp(newIndex, 0, maxIndex); - caption_text_css.style.setProperty('font-size', options.captionSizes[newIndex], 'important'); + player.textTrackSettings.setValues({ fontPercent: options.fontPercent[newIndex] }); + update_captions(); } function toggle_caption_window() { - const numOptions = options.captionBackground.length; - const backgroundColor = caption_background_css.style.getPropertyValue('background-color'); - const curIndex = options.captionBackground.indexOf(backgroundColor); + const numOptions = options.windowOpacity.length; + const windowOpacity = player.textTrackSettings.getValues().windowOpacity || '0'; + const curIndex = options.windowOpacity.indexOf(windowOpacity); const newIndex = (curIndex + 1) % numOptions; - caption_background_css.style.setProperty('background-color', options.captionBackground[newIndex], 'important'); + player.textTrackSettings.setValues({ windowOpacity: options.windowOpacity[newIndex] }); + update_captions(); } - -function toggle_caption_opacity() { - const numOptions = options.captionOpacity.length; - const opacity = caption_text_css.style.getPropertyValue('color'); - const curIndex = options.captionOpacity.indexOf(opacity); + + function toggle_caption_opacity() { + const numOptions = options.textOpacity.length; + const textOpacity = player.textTrackSettings.getValues().textOpacity || '1'; + const curIndex = options.textOpacity.indexOf(textOpacity); const newIndex = (curIndex + 1) % numOptions; - caption_text_css.style.setProperty('color', options.captionOpacity[newIndex], 'important'); + player.textTrackSettings.setValues({ textOpacity: options.textOpacity[newIndex] }); + update_captions(); } addEventListener('keydown', function (e) { From e67a30b124debf30363e5e576f089b26c46f7c93 Mon Sep 17 00:00:00 2001 From: epicsam123 <92618898+epicsam123@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:29:26 -0400 Subject: [PATCH 003/108] formatting --- assets/js/player.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/js/player.js b/assets/js/player.js index dce432cb..d6f2ec64 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -539,9 +539,9 @@ const toggle_captions = (function () { bindChange('off'); track.mode = mode; setTimeout(function () { - bindChange('on'); + bindChange('on'); }, 0); - } + } bindChange('on'); return function () { @@ -584,9 +584,9 @@ const toggle_captions = (function () { // For real-time updates to captions (if currently showing) function update_captions() { - if (document.body.querySelector('.vjs-text-track-cue')) { - toggle_captions(); toggle_captions(); - } + if (document.body.querySelector('.vjs-text-track-cue')) { + toggle_captions(); toggle_captions(); + } } function toggle_fullscreen() { @@ -620,7 +620,7 @@ function toggle_caption_window() { update_captions(); } - function toggle_caption_opacity() { +function toggle_caption_opacity() { const numOptions = options.textOpacity.length; const textOpacity = player.textTrackSettings.getValues().textOpacity || '1'; const curIndex = options.textOpacity.indexOf(textOpacity); From bef2d7b6b515bc90d8a58e3fa9776ab52fc48039 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 01:07:40 -0400 Subject: [PATCH 004/108] CI: Use public ARM64 Github actions runners for ARM64 builds. Currently, Invidious uses QEMU to build it's ARM64 Invidious image, which is slow (since we are basically using a virtual machine). This helps with the speed of building ARM64 binaries for Invidious on each release/commit. More information about the public ARM64 runners here: https://github.com/orgs/community/discussions/148648 CI: Use ARM64 compose file for build-docker-arm64 --- .github/workflows/build-nightly-container.yml | 55 +++++++------------ .github/workflows/build-stable-container.yml | 55 +++++++------------ .github/workflows/ci.yml | 20 ++----- docker-compose-arm64.yml | 55 +++++++++++++++++++ 4 files changed, 101 insertions(+), 84 deletions(-) create mode 100644 docker-compose-arm64.yml diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 4149bd0b..3277c015 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -17,17 +17,27 @@ on: jobs: release: - runs-on: ubuntu-latest + strategy: + matrix: + include: + - os: ubuntu-latest + platforms: linux/amd64 + name: "AMD64" + dockerfile: "docker/Dockerfile" + tag_suffix: "" + # GitHub doesn't has a ubuntu-latest-arm runner + - os: ubuntu-24.04-arm + platforms: linux/arm64/v8 + name: "ARM64" + dockerfile: "docker/Dockerfile.arm64" + tag_suffix: "-arm64" + + runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: arm64 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -43,45 +53,22 @@ jobs: uses: docker/metadata-action@v5 with: images: quay.io/invidious/invidious + flavor: | + suffix=${{ matrix.tag_suffix }} tags: | type=sha,format=short,prefix={{date 'YYYY.MM.DD'}}-,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} type=raw,value=master,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} labels: | quay.expires-after=12w - - name: Build and push Docker AMD64 image for Push Event + - name: Build and push Docker ${{ matrix.name }} image for Push Event uses: docker/build-push-action@v6 with: context: . - file: docker/Dockerfile - platforms: linux/amd64 + file: ${{ matrix.dockerfile }} + platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} push: true tags: ${{ steps.meta.outputs.tags }} build-args: | "release=1" - - - name: Docker meta - id: meta-arm64 - uses: docker/metadata-action@v5 - with: - images: quay.io/invidious/invidious - flavor: | - suffix=-arm64 - tags: | - type=sha,format=short,prefix={{date 'YYYY.MM.DD'}}-,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} - type=raw,value=master,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} - labels: | - quay.expires-after=12w - - - name: Build and push Docker ARM64 image for Push Event - uses: docker/build-push-action@v6 - with: - context: . - file: docker/Dockerfile.arm64 - platforms: linux/arm64/v8 - labels: ${{ steps.meta-arm64.outputs.labels }} - push: true - tags: ${{ steps.meta-arm64.outputs.tags }} - build-args: | - "release=1" diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index 1a23e68c..1498dc2e 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -8,17 +8,27 @@ on: jobs: release: - runs-on: ubuntu-latest + strategy: + matrix: + include: + - os: ubuntu-latest + platforms: linux/amd64 + name: "AMD64" + dockerfile: "docker/Dockerfile" + tag_suffix: "" + # GitHub doesn't has a ubuntu-latest-arm runner + - os: ubuntu-24.04-arm + platforms: linux/arm64/v8 + name: "ARM64" + dockerfile: "docker/Dockerfile.arm64" + tag_suffix: "-arm64" + + runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: arm64 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -36,46 +46,21 @@ jobs: images: quay.io/invidious/invidious flavor: | latest=false + suffix=${{ matrix.tag_suffix }} tags: | type=semver,pattern={{version}} type=raw,value=latest labels: | quay.expires-after=12w - - name: Build and push Docker AMD64 image for Push Event + - name: Build and push Docker ${{ matrix.name }} image for Push Event uses: docker/build-push-action@v6 with: context: . - file: docker/Dockerfile - platforms: linux/amd64 + file: ${{ matrix.dockerfile }} + platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} push: true tags: ${{ steps.meta.outputs.tags }} build-args: | "release=1" - - - name: Docker meta - id: meta-arm64 - uses: docker/metadata-action@v5 - with: - images: quay.io/invidious/invidious - flavor: | - latest=false - suffix=-arm64 - tags: | - type=semver,pattern={{version}} - type=raw,value=latest - labels: | - quay.expires-after=12w - - - name: Build and push Docker ARM64 image for Push Event - uses: docker/build-push-action@v6 - with: - context: . - file: docker/Dockerfile.arm64 - platforms: linux/arm64/v8 - labels: ${{ steps.meta-arm64.outputs.labels }} - push: true - tags: ${{ steps.meta-arm64.outputs.tags }} - build-args: | - "release=1" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d6a930a..c8805d10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,26 +100,16 @@ jobs: build-docker-arm64: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04-arm steps: - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: arm64 + - name: Build Docker + run: docker compose -f docker-compose-arm64.yml build --build-arg release=0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build Docker ARM64 image - uses: docker/build-push-action@v6 - with: - context: . - file: docker/Dockerfile.arm64 - platforms: linux/arm64/v8 - build-args: release=0 + - name: Run Docker + run: docker compose -f docker-compose-arm64.yml up -d - name: Test Docker run: while curl -Isf http://localhost:3000; do sleep 1; done diff --git a/docker-compose-arm64.yml b/docker-compose-arm64.yml new file mode 100644 index 00000000..ba9e0a3f --- /dev/null +++ b/docker-compose-arm64.yml @@ -0,0 +1,55 @@ +# Warning: This docker-compose file is made for development purposes. +# Using it will build an image from the locally cloned repository. +# +# If you want to use Invidious in production, see the docker-compose.yml file provided +# in the installation documentation: https://docs.invidious.io/installation/ + +version: "3" +services: + + invidious: + build: + context: . + dockerfile: docker/Dockerfile.arm64 + restart: unless-stopped + ports: + - "127.0.0.1:3000:3000" + environment: + # Please read the following file for a comprehensive list of all available + # configuration options and their associated syntax: + # https://github.com/iv-org/invidious/blob/master/config/config.example.yml + INVIDIOUS_CONFIG: | + db: + dbname: invidious + user: kemal + password: kemal + host: invidious-db + port: 5432 + check_tables: true + # external_port: + # domain: + # https_only: false + # statistics_enabled: false + hmac_key: "CHANGE_ME!!" + healthcheck: + test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending || exit 1 + interval: 30s + timeout: 5s + retries: 2 + + invidious-db: + image: docker.io/library/postgres:14 + restart: unless-stopped + volumes: + - postgresdata:/var/lib/postgresql/data + - ./config/sql:/config/sql + - ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh + environment: + POSTGRES_DB: invidious + POSTGRES_USER: kemal + POSTGRES_PASSWORD: kemal + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + +volumes: + postgresdata: From cef0097a309847f6075d7e9173c0362dcc83c757 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 15:28:14 -0400 Subject: [PATCH 005/108] CI: fix typo on matrix platforms --- .github/workflows/build-nightly-container.yml | 4 ++-- .github/workflows/build-stable-container.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 3277c015..6b9d4a87 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -21,13 +21,13 @@ jobs: matrix: include: - os: ubuntu-latest - platforms: linux/amd64 + platform: linux/amd64 name: "AMD64" dockerfile: "docker/Dockerfile" tag_suffix: "" # GitHub doesn't has a ubuntu-latest-arm runner - os: ubuntu-24.04-arm - platforms: linux/arm64/v8 + platform: linux/arm64/v8 name: "ARM64" dockerfile: "docker/Dockerfile.arm64" tag_suffix: "-arm64" diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index 1498dc2e..07a3520b 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -12,13 +12,13 @@ jobs: matrix: include: - os: ubuntu-latest - platforms: linux/amd64 + platform: linux/amd64 name: "AMD64" dockerfile: "docker/Dockerfile" tag_suffix: "" # GitHub doesn't has a ubuntu-latest-arm runner - os: ubuntu-24.04-arm - platforms: linux/arm64/v8 + platform: linux/arm64/v8 name: "ARM64" dockerfile: "docker/Dockerfile.arm64" tag_suffix: "-arm64" From 1d2f4b68133231c66e18d878706e8e263e47a66f Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 15:29:24 -0400 Subject: [PATCH 006/108] CI: fix typo on comment about the os used on the ARM64 builder --- .github/workflows/build-nightly-container.yml | 2 +- .github/workflows/build-stable-container.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nightly-container.yml b/.github/workflows/build-nightly-container.yml index 6b9d4a87..1a5abeea 100644 --- a/.github/workflows/build-nightly-container.yml +++ b/.github/workflows/build-nightly-container.yml @@ -25,7 +25,7 @@ jobs: name: "AMD64" dockerfile: "docker/Dockerfile" tag_suffix: "" - # GitHub doesn't has a ubuntu-latest-arm runner + # GitHub doesn't have a ubuntu-latest-arm runner - os: ubuntu-24.04-arm platform: linux/arm64/v8 name: "ARM64" diff --git a/.github/workflows/build-stable-container.yml b/.github/workflows/build-stable-container.yml index 07a3520b..7c2a276b 100644 --- a/.github/workflows/build-stable-container.yml +++ b/.github/workflows/build-stable-container.yml @@ -16,7 +16,7 @@ jobs: name: "AMD64" dockerfile: "docker/Dockerfile" tag_suffix: "" - # GitHub doesn't has a ubuntu-latest-arm runner + # GitHub doesn't have a ubuntu-latest-arm runner - os: ubuntu-24.04-arm platform: linux/arm64/v8 name: "ARM64" From 94f0a7a9d22e46e58447810fbb0da05508162fad Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 15:31:17 -0400 Subject: [PATCH 007/108] CI: remove --build-arg Dockerfile and Dockerfile.arm64 already build Invidious without release mode if `release` argument is not present. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8805d10..1bb92101 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,7 +90,7 @@ jobs: - uses: actions/checkout@v4 - name: Build Docker - run: docker compose build --build-arg release=0 + run: docker compose build - name: Run Docker run: docker compose up -d @@ -106,7 +106,7 @@ jobs: - uses: actions/checkout@v4 - name: Build Docker - run: docker compose -f docker-compose-arm64.yml build --build-arg release=0 + run: docker compose -f docker-compose-arm64.yml build - name: Run Docker run: docker compose -f docker-compose-arm64.yml up -d From 1d664c759f17b5455d1ffbbe5e276a35dd4202e9 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 16:33:03 -0400 Subject: [PATCH 008/108] CI: Use matrix for `build-docker` on ci.yml --- .github/workflows/ci.yml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bb92101..51a5052d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,14 +83,22 @@ jobs: run: crystal build --warnings all --error-on-warnings --error-trace src/invidious.cr build-docker: + strategy: + matrix: + include: + - os: ubuntu-latest + docker_compose_file: "docker-compose.yml" + # GitHub doesn't have a ubuntu-latest-arm runner + - os: ubuntu-24.04-arm + docker_compose_file: "docker-compose-arm64.yml" - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Build Docker - run: docker compose build + run: docker compose -f ${{ matrix.docker_compose_file }} build - name: Run Docker run: docker compose up -d @@ -98,22 +106,6 @@ jobs: - name: Test Docker run: while curl -Isf http://localhost:3000; do sleep 1; done - build-docker-arm64: - - runs-on: ubuntu-24.04-arm - - steps: - - uses: actions/checkout@v4 - - - name: Build Docker - run: docker compose -f docker-compose-arm64.yml build - - - name: Run Docker - run: docker compose -f docker-compose-arm64.yml up -d - - - name: Test Docker - run: while curl -Isf http://localhost:3000; do sleep 1; done - lint: runs-on: ubuntu-latest From a3375e512edf00c5c0c00089d370392c37bbe550 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 17:43:03 -0400 Subject: [PATCH 009/108] CI: Add name attribute to `build-docker` job --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51a5052d..80cb81a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,10 +88,13 @@ jobs: include: - os: ubuntu-latest docker_compose_file: "docker-compose.yml" + name: "AMD64" # GitHub doesn't have a ubuntu-latest-arm runner - os: ubuntu-24.04-arm docker_compose_file: "docker-compose-arm64.yml" + name: "ARM64" + name: Test ${{ matrix.name }} Docker build runs-on: ${{ matrix.os }} steps: From 033a44fab574df56dd63a41d63d089b84cdb31f5 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 17:58:24 -0400 Subject: [PATCH 010/108] CI: Also use `matrix.docker_compose_file` for `Run Docker` step --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80cb81a0..d3b6455a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: run: docker compose -f ${{ matrix.docker_compose_file }} build - name: Run Docker - run: docker compose up -d + run: docker compose -f ${{ matrix.docker_compose_file }} up -d - name: Test Docker run: while curl -Isf http://localhost:3000; do sleep 1; done From 381074fce1f3e405d8c527a672f524c4700aead5 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 19:38:21 -0400 Subject: [PATCH 011/108] CI: Replace Dockerfile path depending of the os used --- .github/workflows/ci.yml | 10 +++++--- docker-compose-arm64.yml | 55 ---------------------------------------- 2 files changed, 6 insertions(+), 59 deletions(-) delete mode 100644 docker-compose-arm64.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3b6455a..7a5e8850 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,11 +87,9 @@ jobs: matrix: include: - os: ubuntu-latest - docker_compose_file: "docker-compose.yml" name: "AMD64" # GitHub doesn't have a ubuntu-latest-arm runner - os: ubuntu-24.04-arm - docker_compose_file: "docker-compose-arm64.yml" name: "ARM64" name: Test ${{ matrix.name }} Docker build @@ -100,11 +98,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Use ARM64 Dockerfile if ARM64 + if: ${{ matrix.name }} == "ARM64" + run: sed -i 's/Dockerfile/Dockerfile.arm64/' docker-compose.yml + - name: Build Docker - run: docker compose -f ${{ matrix.docker_compose_file }} build + run: docker compose build - name: Run Docker - run: docker compose -f ${{ matrix.docker_compose_file }} up -d + run: docker compose up -d - name: Test Docker run: while curl -Isf http://localhost:3000; do sleep 1; done diff --git a/docker-compose-arm64.yml b/docker-compose-arm64.yml deleted file mode 100644 index ba9e0a3f..00000000 --- a/docker-compose-arm64.yml +++ /dev/null @@ -1,55 +0,0 @@ -# Warning: This docker-compose file is made for development purposes. -# Using it will build an image from the locally cloned repository. -# -# If you want to use Invidious in production, see the docker-compose.yml file provided -# in the installation documentation: https://docs.invidious.io/installation/ - -version: "3" -services: - - invidious: - build: - context: . - dockerfile: docker/Dockerfile.arm64 - restart: unless-stopped - ports: - - "127.0.0.1:3000:3000" - environment: - # Please read the following file for a comprehensive list of all available - # configuration options and their associated syntax: - # https://github.com/iv-org/invidious/blob/master/config/config.example.yml - INVIDIOUS_CONFIG: | - db: - dbname: invidious - user: kemal - password: kemal - host: invidious-db - port: 5432 - check_tables: true - # external_port: - # domain: - # https_only: false - # statistics_enabled: false - hmac_key: "CHANGE_ME!!" - healthcheck: - test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending || exit 1 - interval: 30s - timeout: 5s - retries: 2 - - invidious-db: - image: docker.io/library/postgres:14 - restart: unless-stopped - volumes: - - postgresdata:/var/lib/postgresql/data - - ./config/sql:/config/sql - - ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh - environment: - POSTGRES_DB: invidious - POSTGRES_USER: kemal - POSTGRES_PASSWORD: kemal - healthcheck: - test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] - -volumes: - postgresdata: From cc643f209a95cbf9fcc7e97ae3587454b35c3bc5 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 15 May 2025 17:49:54 -0400 Subject: [PATCH 012/108] CI: Fix build-docker job not checking if Invidious starts successfully or not --- .github/workflows/ci.yml | 12 +++++++++++- docker-compose.yml | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a5e8850..27debc1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,11 +105,21 @@ jobs: - name: Build Docker run: docker compose build + - name: Change hmac_key on docker-compose.yml + run: sed -i '/hmac_key/s/CHANGE_ME!!/docker-build-hmac-key/' docker-compose.yml + - name: Run Docker run: docker compose up -d - name: Test Docker - run: while curl -Isf http://localhost:3000; do sleep 1; done + id: test + run: curl -If http://localhost:3000 --retry 5 --retry-delay 1 --retry-all-errors + + - name: Print Invidious container logs + # Tells Github Actions to always run this step regardless of whether the previous step has failed + # Without this expression this step would simply be skipped when the previous step fails. + if: success() || steps.test.conclusion == 'failure' + run: docker compose logs lint: diff --git a/docker-compose.yml b/docker-compose.yml index afda8726..0de51feb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,6 +14,10 @@ services: restart: unless-stopped ports: - "127.0.0.1:3000:3000" + depends_on: + invidious-db: + condition: service_healthy + restart: true environment: # Please read the following file for a comprehensive list of all available # configuration options and their associated syntax: From f9472e4e4b910acb9962159e97b37c4d95f8b804 Mon Sep 17 00:00:00 2001 From: epicsam123 <92618898+epicsam123@users.noreply.github.com> Date: Mon, 19 May 2025 22:34:59 -0400 Subject: [PATCH 013/108] revert format --- assets/css/player.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/assets/css/player.css b/assets/css/player.css index 60f3ce73..d95549ac 100644 --- a/assets/css/player.css +++ b/assets/css/player.css @@ -71,10 +71,8 @@ padding-top: 2em } -.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control { - height: 5px; - margin-bottom: 10px; -} +.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control {height: 5px; +margin-bottom: 10px;} ul.vjs-menu-content::-webkit-scrollbar { display: none; From 6497e1c41888756b0f624df725712bf3b00d49c2 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 22 May 2025 16:06:13 -0400 Subject: [PATCH 014/108] YtAPI: Bump client versions --- src/invidious/yt_backend/youtube_api.cr | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index b40092a1..1f21ddf0 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -6,10 +6,10 @@ module YoutubeAPI extend self # For Android versions, see https://en.wikipedia.org/wiki/Android_version_history - private ANDROID_APP_VERSION = "19.32.34" - private ANDROID_VERSION = "12" + private ANDROID_APP_VERSION = "19.35.36" + private ANDROID_VERSION = "13" private ANDROID_USER_AGENT = "com.google.android.youtube/#{ANDROID_APP_VERSION} (Linux; U; Android #{ANDROID_VERSION}; US) gzip" - private ANDROID_SDK_VERSION = 31_i64 + private ANDROID_SDK_VERSION = 33_i64 private ANDROID_TS_APP_VERSION = "1.9" private ANDROID_TS_USER_AGENT = "com.google.android.youtube/1.9 (Linux; U; Android 12; US) gzip" @@ -49,7 +49,7 @@ module YoutubeAPI ClientType::Web => { name: "WEB", name_proto: "1", - version: "2.20240814.00.00", + version: "2.20250222.10.00", screen: "WATCH_FULL_SCREEN", os_name: "Windows", os_version: WINDOWS_VERSION, @@ -58,7 +58,7 @@ module YoutubeAPI ClientType::WebEmbeddedPlayer => { name: "WEB_EMBEDDED_PLAYER", name_proto: "56", - version: "1.20240812.01.00", + version: "1.20250219.01.00", screen: "EMBED", os_name: "Windows", os_version: WINDOWS_VERSION, @@ -67,7 +67,7 @@ module YoutubeAPI ClientType::WebMobile => { name: "MWEB", name_proto: "2", - version: "2.20240813.02.00", + version: "2.20250224.01.00", os_name: "Android", os_version: ANDROID_VERSION, platform: "MOBILE", @@ -75,7 +75,7 @@ module YoutubeAPI ClientType::WebScreenEmbed => { name: "WEB", name_proto: "1", - version: "2.20240814.00.00", + version: "2.20250222.10.00", screen: "EMBED", os_name: "Windows", os_version: WINDOWS_VERSION, @@ -84,7 +84,7 @@ module YoutubeAPI ClientType::WebCreator => { name: "WEB_CREATOR", name_proto: "62", - version: "1.20240918.03.00", + version: "1.20241203.01.00", os_name: "Windows", os_version: WINDOWS_VERSION, platform: "DESKTOP", @@ -170,7 +170,7 @@ module YoutubeAPI ClientType::TvHtml5 => { name: "TVHTML5", name_proto: "7", - version: "7.20240813.07.00", + version: "7.20250219.14.00", }, ClientType::TvHtml5ScreenEmbed => { name: "TVHTML5_SIMPLY_EMBEDDED_PLAYER", From 97354adf0fc359d2898f69613d1ab668aaf6931f Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 22 May 2025 17:15:45 -0400 Subject: [PATCH 015/108] Update src/invidious/yt_backend/youtube_api.cr Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --- src/invidious/yt_backend/youtube_api.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 1f21ddf0..bedbb978 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -8,7 +8,7 @@ module YoutubeAPI # For Android versions, see https://en.wikipedia.org/wiki/Android_version_history private ANDROID_APP_VERSION = "19.35.36" private ANDROID_VERSION = "13" - private ANDROID_USER_AGENT = "com.google.android.youtube/#{ANDROID_APP_VERSION} (Linux; U; Android #{ANDROID_VERSION}; US) gzip" + private ANDROID_USER_AGENT = "com.google.android.youtube/#{ANDROID_APP_VERSION} (Linux; U; Android #{ANDROID_VERSION}; en_US; SM-S908E Build/TP1A.220624.014) gzip" private ANDROID_SDK_VERSION = 33_i64 private ANDROID_TS_APP_VERSION = "1.9" From 3a8d4f333f1ef5b42a4eb0a2e8b5743b646862cb Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 22 May 2025 17:17:01 -0400 Subject: [PATCH 016/108] update IOS_APP_VERSION --- src/invidious/yt_backend/youtube_api.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index bedbb978..5f89d0e6 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -17,7 +17,7 @@ module YoutubeAPI # For Apple device names, see https://gist.github.com/adamawolf/3048717 # For iOS versions, see https://en.wikipedia.org/wiki/IOS_version_history#Releases, # then go to the dedicated article of the major version you want. - private IOS_APP_VERSION = "19.32.8" + private IOS_APP_VERSION = "20.11.6" private IOS_USER_AGENT = "com.google.ios.youtube/#{IOS_APP_VERSION} (iPhone14,5; U; CPU iOS 17_6 like Mac OS X;)" private IOS_VERSION = "17.6.1.21G93" # Major.Minor.Patch.Build From 09d342b84d4639026b90beb3f95403f6cf93275a Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 22 May 2025 17:55:46 -0400 Subject: [PATCH 017/108] Update src/invidious/yt_backend/youtube_api.cr Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --- src/invidious/yt_backend/youtube_api.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 5f89d0e6..9f2078c7 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -18,8 +18,8 @@ module YoutubeAPI # For iOS versions, see https://en.wikipedia.org/wiki/IOS_version_history#Releases, # then go to the dedicated article of the major version you want. private IOS_APP_VERSION = "20.11.6" - private IOS_USER_AGENT = "com.google.ios.youtube/#{IOS_APP_VERSION} (iPhone14,5; U; CPU iOS 17_6 like Mac OS X;)" - private IOS_VERSION = "17.6.1.21G93" # Major.Minor.Patch.Build + private IOS_USER_AGENT = "com.google.ios.youtube/#{IOS_APP_VERSION} (iPhone14,5; U; CPU iOS 18_5 like Mac OS X;)" + private IOS_VERSION = "18.5.0.22F76" # Major.Minor.Patch.Build private WINDOWS_VERSION = "10.0" From 4daf1f081828dd9137e58bf7a2cc79872f7afa6f Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 01:24:45 -0400 Subject: [PATCH 018/108] Add `TvSimply` client Data taken from: https://github.com/LuanRT/YouTube.js/commit/8cf658151fc4e4266fadfb7e53dd5db3db693355, https://github.com/LuanRT/YouTube.js/commit/689fb0b90edab6f0e4326a35144541d68f72fe01 and https://github.com/LuanRT/YouTube.js/commit/b15f623dab3acb44eaef33175df2d22d35be2979 --- src/invidious/yt_backend/youtube_api.cr | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index b40092a1..78915aef 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -42,6 +42,7 @@ module YoutubeAPI TvHtml5 TvHtml5ScreenEmbed + TvSimply end # List of hard-coded values used by the different clients @@ -178,6 +179,11 @@ module YoutubeAPI version: "2.0", screen: "EMBED", }, + ClientType::TvSimply => { + name: "TVHTML5_SIMPLY", + name_proto: "74", + version: "1.0", + }, } #################################################################### From 37be513e142061067604d7ec1981fe7a309f8713 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 01:25:59 -0400 Subject: [PATCH 019/108] Add fallback to TvSimply client --- src/invidious/videos/parser.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index feb58440..5be59352 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -111,7 +111,7 @@ def extract_video_info(video_id : String) if !CONFIG.invidious_companion.present? if player_response.dig?("streamingData", "adaptiveFormats", 0, "url").nil? LOGGER.warn("Missing URLs for adaptive formats, falling back to other YT clients.") - players_fallback = {YoutubeAPI::ClientType::TvHtml5, YoutubeAPI::ClientType::WebMobile} + players_fallback = {YoutubeAPI::ClientType::TvHtml5, YoutubeAPI::ClientType::TvSimply, YoutubeAPI::ClientType::WebMobile} players_fallback.each do |player_fallback| client_config.client_type = player_fallback From 0c96e0977fd805731d8fdbe97afac1ee22b6626a Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 16:06:04 -0400 Subject: [PATCH 020/108] check for signatureCipher too --- src/invidious/videos/parser.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 5be59352..212b3b35 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -118,7 +118,7 @@ def extract_video_info(video_id : String) next if !(player_fallback_response = try_fetch_streaming_data(video_id, client_config)) - if player_fallback_response.dig?("streamingData", "adaptiveFormats", 0, "url") + if player_fallback_response.dig?("streamingData", "adaptiveFormats", 0, "url") || player_fallback_response.dig?("streamingData", "adaptiveFormats", 0, "signatureCipher") streaming_data = player_response["streamingData"].as_h streaming_data["adaptiveFormats"] = player_fallback_response["streamingData"]["adaptiveFormats"] player_response["streamingData"] = JSON::Any.new(streaming_data) From b1e7e0c45e8cfe0ca262dc5774c8ccca3fc6db66 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 16:18:01 -0400 Subject: [PATCH 021/108] replace url by signatureCipher if url is not present --- src/invidious/videos/parser.cr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 212b3b35..e58c0e8f 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -146,6 +146,9 @@ def extract_video_info(video_id : String) if streaming_data = player_response["streamingData"]? %w[formats adaptiveFormats].each do |key| streaming_data.as_h[key]?.try &.as_a.each do |format| + if format.as_h["url"].nil? + format.as_h["url"] = format.as_h["signatureCipher"] + end format.as_h["url"] = JSON::Any.new(convert_url(format)) end end From 01cdb384e0629ade15a83f8a2bcb50722d03340c Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 17:25:19 -0400 Subject: [PATCH 022/108] add suggestions from syeopite --- src/invidious/videos/parser.cr | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index e58c0e8f..6892b37c 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -146,10 +146,11 @@ def extract_video_info(video_id : String) if streaming_data = player_response["streamingData"]? %w[formats adaptiveFormats].each do |key| streaming_data.as_h[key]?.try &.as_a.each do |format| - if format.as_h["url"].nil? - format.as_h["url"] = format.as_h["signatureCipher"] + format = format.as_h + if format["url"]?.nil? + format["url"] = format["signatureCipher"] end - format.as_h["url"] = JSON::Any.new(convert_url(format)) + format["url"] = JSON::Any.new(convert_url(format)) end end From 8cd9d53fb1ff4a8a15d208f587a0a4ce330890bd Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 12 Jun 2025 18:44:01 -0400 Subject: [PATCH 023/108] show message when connection to the database is not possible --- src/invidious.cr | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index 69f8a26c..d1f84f39 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -60,7 +60,13 @@ alias IV = Invidious CONFIG = Config.load HMAC_KEY = CONFIG.hmac_key -PG_DB = DB.open CONFIG.database_url +PG_DB = begin + DB.open CONFIG.database_url +rescue ex + puts "Failed to connect to PostgreSQL database: #{ex.cause.try &.message}" + puts "Check your 'config.yml' database settings or PostgreSQL settings." + exit(1) +end ARCHIVE_URL = URI.parse("https://archive.org") PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com") REDDIT_URL = URI.parse("https://www.reddit.com") From cf0a68bd77251528713404822a19c411a1c0aaca Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sun, 15 Jun 2025 16:51:04 -0400 Subject: [PATCH 024/108] store adaptiveFormats data into a variable --- src/invidious/videos/parser.cr | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 6892b37c..178b905b 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -118,9 +118,10 @@ def extract_video_info(video_id : String) next if !(player_fallback_response = try_fetch_streaming_data(video_id, client_config)) - if player_fallback_response.dig?("streamingData", "adaptiveFormats", 0, "url") || player_fallback_response.dig?("streamingData", "adaptiveFormats", 0, "signatureCipher") + adaptive_formats = player_fallback_response.dig?("streamingData", "adaptiveFormats") + if adaptive_formats && (adaptive_formats.dig?(0, "url") || adaptive_formats.dig?(0, "signatureCipher")) streaming_data = player_response["streamingData"].as_h - streaming_data["adaptiveFormats"] = player_fallback_response["streamingData"]["adaptiveFormats"] + streaming_data["adaptiveFormats"] = adaptive_formats player_response["streamingData"] = JSON::Any.new(streaming_data) break end From d51e1cb0514fe2be4b94f7233e36a8aada542496 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sun, 15 Jun 2025 17:45:53 -0400 Subject: [PATCH 025/108] remove fallback to TV client --- src/invidious/videos/parser.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 178b905b..5335aa79 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -111,7 +111,7 @@ def extract_video_info(video_id : String) if !CONFIG.invidious_companion.present? if player_response.dig?("streamingData", "adaptiveFormats", 0, "url").nil? LOGGER.warn("Missing URLs for adaptive formats, falling back to other YT clients.") - players_fallback = {YoutubeAPI::ClientType::TvHtml5, YoutubeAPI::ClientType::TvSimply, YoutubeAPI::ClientType::WebMobile} + players_fallback = {YoutubeAPI::ClientType::TvSimply, YoutubeAPI::ClientType::WebMobile} players_fallback.each do |player_fallback| client_config.client_type = player_fallback From 8723fdca06510a2ab64c194fa284f011fd327e42 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 21 Jun 2025 12:02:32 -0400 Subject: [PATCH 026/108] Update src/invidious.cr Co-authored-by: Samantaz Fox --- src/invidious.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index d1f84f39..2d244dd2 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -62,8 +62,8 @@ HMAC_KEY = CONFIG.hmac_key PG_DB = begin DB.open CONFIG.database_url -rescue ex - puts "Failed to connect to PostgreSQL database: #{ex.cause.try &.message}" +rescue exc + puts "Failed to connect to PostgreSQL database: #{exc.cause.try &.message}" puts "Check your 'config.yml' database settings or PostgreSQL settings." exit(1) end From f3f6937ffcc703f11173653dc250c7f5bac5d736 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Wed, 25 Jun 2025 22:22:30 -0400 Subject: [PATCH 027/108] Fix community tab not loading --- src/invidious/channels/community.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr index 49ffd990..6a296009 100644 --- a/src/invidious/channels/community.cr +++ b/src/invidious/channels/community.cr @@ -3,8 +3,8 @@ private IMAGE_QUALITIES = {320, 560, 640, 1280, 2000} # TODO: Add "sort_by" def fetch_channel_community(ucid, cursor, locale, format, thin_mode) if cursor.nil? - # Egljb21tdW5pdHk%3D is the protobuf object to load "community" - initial_data = YoutubeAPI.browse(ucid, params: "Egljb21tdW5pdHk%3D") + # EgVwb3N0c_IGBAoCSgA%3D is the protobuf object to load "community" + initial_data = YoutubeAPI.browse(ucid, params: "EgVwb3N0c_IGBAoCSgA%3D") items = [] of JSON::Any extract_items(initial_data) do |item| From b9171d9dab7e6791376c4cc899ed3b6fa16e5f19 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Wed, 25 Jun 2025 22:34:26 -0400 Subject: [PATCH 028/108] Update protobuf for individual community post --- src/invidious/channels/community.cr | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr index 6a296009..c0688416 100644 --- a/src/invidious/channels/community.cr +++ b/src/invidious/channels/community.cr @@ -3,7 +3,7 @@ private IMAGE_QUALITIES = {320, 560, 640, 1280, 2000} # TODO: Add "sort_by" def fetch_channel_community(ucid, cursor, locale, format, thin_mode) if cursor.nil? - # EgVwb3N0c_IGBAoCSgA%3D is the protobuf object to load "community" + # EgVwb3N0c_IGBAoCSgA%3D is the protobuf object to load "posts" initial_data = YoutubeAPI.browse(ucid, params: "EgVwb3N0c_IGBAoCSgA%3D") items = [] of JSON::Any @@ -26,21 +26,18 @@ end def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode) object = { - "2:string" => "community", - "25:embedded" => { - "22:string" => post_id.to_s, - }, - "45:embedded" => { - "2:varint" => 1_i64, - "3:varint" => 1_i64, - }, + "56:embedded" => { + "2:string" => ucid, + "3:string" => post_id.to_s, + "11:string" => ucid, + } } params = object.try { |i| Protodec::Any.cast_json(i) } .try { |i| Protodec::Any.from_json(i) } .try { |i| Base64.urlsafe_encode(i) } .try { |i| URI.encode_www_form(i) } - initial_data = YoutubeAPI.browse(ucid, params: params) + initial_data = YoutubeAPI.browse("FEpost_detail", params: params) items = [] of JSON::Any extract_items(initial_data) do |item| From 4155f15bf73ede39434e7aa3878e295d5d203c04 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:33:28 -0400 Subject: [PATCH 029/108] update resolve_url api to better support new post endpoint --- src/invidious/routes/api/v1/misc.cr | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/invidious/routes/api/v1/misc.cr b/src/invidious/routes/api/v1/misc.cr index 4f5b58da..40f2a439 100644 --- a/src/invidious/routes/api/v1/misc.cr +++ b/src/invidious/routes/api/v1/misc.cr @@ -190,15 +190,30 @@ module Invidious::Routes::API::V1::Misc sub_endpoint = endpoint["watchEndpoint"]? || endpoint["browseEndpoint"]? || endpoint params = sub_endpoint.try &.dig?("params") + + if sub_endpoint["browseId"]?.try &.as_s == "FEpost_detail" + decoded_protobuf = params.try &.as_s.try { |i| URI.decode_www_form(i) } + .try { |i| Base64.decode(i) } + .try { |i| IO::Memory.new(i) } + .try { |i| Protodec::Any.parse(i) } + + ucid = decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s) + post_id = decoded_protobuf.try(&.["56:0:embedded"]["3:1:string"].as_s) + else + ucid = sub_endpoint["browseId"]? if sub_endpoint["browseId"]? && sub_endpoint["browseId"]?.try &.as_s.starts_with? "UC" + post_id = nil + end rescue ex return error_json(500, ex) end JSON.build do |json| json.object do - json.field "ucid", sub_endpoint["browseId"].as_s if sub_endpoint["browseId"]? + json.field "browseId", sub_endpoint["browseId"].as_s if sub_endpoint["browseId"]? + json.field "ucid", ucid if ucid != nil json.field "videoId", sub_endpoint["videoId"].as_s if sub_endpoint["videoId"]? json.field "playlistId", sub_endpoint["playlistId"].as_s if sub_endpoint["playlistId"]? json.field "startTimeSeconds", sub_endpoint["startTimeSeconds"].as_i if sub_endpoint["startTimeSeconds"]? + json.field "postId", post_id if post_id != nil json.field "params", params.try &.as_s json.field "pageType", page_type end From 436f955e0f20c9e398e3587175f3071dcec153d4 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:34:30 -0400 Subject: [PATCH 030/108] update fetch_community_post_comments protobuf to match currently used protobuf, add sort_by option --- src/invidious/channels/community.cr | 9 +++++++++ src/invidious/comments/youtube.cr | 26 ++++++++++++++----------- src/invidious/routes/api/v1/channels.cr | 6 ++++-- src/invidious/routes/channels.cr | 2 +- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr index c0688416..8927c81b 100644 --- a/src/invidious/channels/community.cr +++ b/src/invidious/channels/community.cr @@ -24,6 +24,15 @@ def fetch_channel_community(ucid, cursor, locale, format, thin_mode) return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode) end +def decode_ucid_from_post_protobuf(params) + decoded_protobuf = params.try { |i| URI.decode_www_form(i) } + .try { |i| Base64.decode(i) } + .try { |i| IO::Memory.new(i) } + .try { |i| Protodec::Any.parse(i) } + + return decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s) +end + def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode) object = { "56:embedded" => { diff --git a/src/invidious/comments/youtube.cr b/src/invidious/comments/youtube.cr index 0716fcde..18403656 100644 --- a/src/invidious/comments/youtube.cr +++ b/src/invidious/comments/youtube.cr @@ -16,34 +16,38 @@ module Invidious::Comments return parse_youtube(id, response, format, locale, thin_mode, sort_by) end - def fetch_community_post_comments(ucid, post_id) + def fetch_community_post_comments(ucid, post_id, sort_by = "top") object = { - "2:string" => "community", - "25:embedded" => { - "22:string" => post_id, - }, - "45:embedded" => { - "2:varint" => 1_i64, - "3:varint" => 1_i64, - }, + "2:string" => "posts", "53:embedded" => { "4:embedded" => { "6:varint" => 0_i64, - "27:varint" => 1_i64, + "15:varint" => 2_i64, + "25:varint" => 0_i64, "29:string" => post_id, "30:string" => ucid, }, + "7:varint" => 0_i64, "8:string" => "comments-section", }, } + case sort_by + when "top" + object["53:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 + when "new", "newest" + object["53:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 1_i64 + else # top + object["53:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 + end + object_parsed = object.try { |i| Protodec::Any.cast_json(i) } .try { |i| Protodec::Any.from_json(i) } .try { |i| Base64.urlsafe_encode(i) } object2 = { "80226972:embedded" => { - "2:string" => ucid, + "2:string" => "FEcomment_post_detail_page_web_top_level", "3:string" => object_parsed, }, } diff --git a/src/invidious/routes/api/v1/channels.cr b/src/invidious/routes/api/v1/channels.cr index a940ee68..503b8c05 100644 --- a/src/invidious/routes/api/v1/channels.cr +++ b/src/invidious/routes/api/v1/channels.cr @@ -436,7 +436,7 @@ module Invidious::Routes::API::V1::Channels if ucid.nil? response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}") return error_json(400, "Invalid post ID") if response["error"]? - ucid = response.dig("endpoint", "browseEndpoint", "browseId").as_s + ucid = decode_ucid_from_post_protobuf(response.dig("endpoint", "browseEndpoint", "params").as_s) else ucid = ucid.to_s end @@ -460,13 +460,15 @@ module Invidious::Routes::API::V1::Channels format = env.params.query["format"]? format ||= "json" + sort_by = env.params.query["sort_by"]?.try &.downcase + sort_by ||= "top" continuation = env.params.query["continuation"]? case continuation when nil, "" ucid = env.params.query["ucid"] - comments = Comments.fetch_community_post_comments(ucid, id) + comments = Comments.fetch_community_post_comments(ucid, id, sort_by: sort_by) else comments = YoutubeAPI.browse(continuation: continuation) end diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr index 508aa3e4..6d2b4465 100644 --- a/src/invidious/routes/channels.cr +++ b/src/invidious/routes/channels.cr @@ -284,7 +284,7 @@ module Invidious::Routes::Channels response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}") return error_template(400, "Invalid post ID") if response["error"]? - ucid = response.dig("endpoint", "browseEndpoint", "browseId").as_s + ucid = decode_ucid_from_post_protobuf(response.dig("endpoint", "browseEndpoint", "params").as_s) post_response = fetch_channel_community_post(ucid, id, locale, "json", thin_mode) end From f8febbe2b2fbc618e96cad027619b1acbc8509f4 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Wed, 25 Jun 2025 23:53:07 -0400 Subject: [PATCH 031/108] format changes --- src/invidious/channels/community.cr | 12 ++++++------ src/invidious/routes/api/v1/misc.cr | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/invidious/channels/community.cr b/src/invidious/channels/community.cr index 8927c81b..43843b11 100644 --- a/src/invidious/channels/community.cr +++ b/src/invidious/channels/community.cr @@ -26,9 +26,9 @@ end def decode_ucid_from_post_protobuf(params) decoded_protobuf = params.try { |i| URI.decode_www_form(i) } - .try { |i| Base64.decode(i) } - .try { |i| IO::Memory.new(i) } - .try { |i| Protodec::Any.parse(i) } + .try { |i| Base64.decode(i) } + .try { |i| IO::Memory.new(i) } + .try { |i| Protodec::Any.parse(i) } return decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s) end @@ -36,10 +36,10 @@ end def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode) object = { "56:embedded" => { - "2:string" => ucid, - "3:string" => post_id.to_s, + "2:string" => ucid, + "3:string" => post_id.to_s, "11:string" => ucid, - } + }, } params = object.try { |i| Protodec::Any.cast_json(i) } .try { |i| Protodec::Any.from_json(i) } diff --git a/src/invidious/routes/api/v1/misc.cr b/src/invidious/routes/api/v1/misc.cr index 40f2a439..4ae877a8 100644 --- a/src/invidious/routes/api/v1/misc.cr +++ b/src/invidious/routes/api/v1/misc.cr @@ -197,8 +197,8 @@ module Invidious::Routes::API::V1::Misc .try { |i| IO::Memory.new(i) } .try { |i| Protodec::Any.parse(i) } - ucid = decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s) - post_id = decoded_protobuf.try(&.["56:0:embedded"]["3:1:string"].as_s) + ucid = decoded_protobuf.try(&.["56:0:embedded"]["2:0:string"].as_s) + post_id = decoded_protobuf.try(&.["56:0:embedded"]["3:1:string"].as_s) else ucid = sub_endpoint["browseId"]? if sub_endpoint["browseId"]? && sub_endpoint["browseId"]?.try &.as_s.starts_with? "UC" post_id = nil From b0c9f87fbea9a527b1e96774de97dc366e76df12 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Thu, 26 Jun 2025 19:09:52 +0000 Subject: [PATCH 032/108] Fix missing .id to retrieve first playlist video ID This was missed in the review of PR 5196 --- src/invidious/routes/embed.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index 930e4915..721a57f8 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -20,7 +20,7 @@ module Invidious::Routes::Embed return error_template(500, ex) end - url = "/embed/#{first_playlist_video}?#{env.params.query}" + url = "/embed/#{first_playlist_video.id}?#{env.params.query}" if env.params.query.size > 0 url += "?#{env.params.query}" From 64ac3b5203a94291bad709ffcaae665e50544485 Mon Sep 17 00:00:00 2001 From: epicsam123 <92618898+epicsam123@users.noreply.github.com> Date: Thu, 26 Jun 2025 18:40:06 -0400 Subject: [PATCH 033/108] add missing noreferrers --- assets/js/player.js | 4 ++-- assets/js/watch.js | 2 +- src/invidious/frontend/watch_page.cr | 2 +- src/invidious/views/user/data_control.ecr | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/js/player.js b/assets/js/player.js index f32c9b56..1a20c932 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -180,7 +180,7 @@ var shareOptions = { }; if (location.pathname.startsWith('/embed/')) { - var overlay_content = '

' + player_data.title + '

'; + var overlay_content = '

' + player_data.title + '

'; player.overlay({ overlays: [ { start: 'loadstart', content: overlay_content, end: 'playing', align: 'top'}, @@ -450,7 +450,7 @@ if (!video_data.params.listen && video_data.params.annotations) { if (target === 'current') { location.href = path; } else if (target === 'new') { - open(path, '_blank'); + open(path, '_blank', 'noopener,noreferrer') } }); diff --git a/assets/js/watch.js b/assets/js/watch.js index d869d40d..ee9c29e8 100644 --- a/assets/js/watch.js +++ b/assets/js/watch.js @@ -141,7 +141,7 @@ function get_reddit_comments() { \

\ \ - {redditPermalinkText} \ + {redditPermalinkText} \ \ \
{contentHtml}
\ diff --git a/src/invidious/frontend/watch_page.cr b/src/invidious/frontend/watch_page.cr index 15d925e3..c0926164 100644 --- a/src/invidious/frontend/watch_page.cr +++ b/src/invidious/frontend/watch_page.cr @@ -34,7 +34,7 @@ module Invidious::Frontend::WatchPage str << " class=\"pure-form pure-form-stacked\"" str << " action='#{url}'" str << " method='post'" - str << " rel='noopener'" + str << " rel='noopener noreferrer'" str << " target='_blank'>" str << '\n' diff --git a/src/invidious/views/user/data_control.ecr b/src/invidious/views/user/data_control.ecr index 9ce42c99..e57926f5 100644 --- a/src/invidious/views/user/data_control.ecr +++ b/src/invidious/views/user/data_control.ecr @@ -14,7 +14,7 @@
From 803311713d43860bcdbba81008544ef2d67bc657 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:34:45 -0400 Subject: [PATCH 034/108] make `sort_by` code more legible --- src/invidious/comments/youtube.cr | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/invidious/comments/youtube.cr b/src/invidious/comments/youtube.cr index 18403656..e923b2f8 100644 --- a/src/invidious/comments/youtube.cr +++ b/src/invidious/comments/youtube.cr @@ -17,11 +17,20 @@ module Invidious::Comments end def fetch_community_post_comments(ucid, post_id, sort_by = "top") + case sort_by + when "top" + sort_by_val = 0_i64 + when "new", "newest" + sort_by_val = 1_i64 + else # top + sort_by_val = 0_i64 + end + object = { "2:string" => "posts", "53:embedded" => { "4:embedded" => { - "6:varint" => 0_i64, + "6:varint" => sort_by_val, "15:varint" => 2_i64, "25:varint" => 0_i64, "29:string" => post_id, @@ -32,15 +41,6 @@ module Invidious::Comments }, } - case sort_by - when "top" - object["53:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 - when "new", "newest" - object["53:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 1_i64 - else # top - object["53:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 - end - object_parsed = object.try { |i| Protodec::Any.cast_json(i) } .try { |i| Protodec::Any.from_json(i) } .try { |i| Base64.urlsafe_encode(i) } @@ -324,6 +324,15 @@ module Invidious::Comments end def produce_continuation(video_id, cursor = "", sort_by = "top") + case sort_by + when "top" + sort_by_val = 0_i64 + when "new", "newest" + sort_by_val = 1_i64 + else # top + sort_by_val = 0_i64 + end + object = { "2:embedded" => { "2:string" => video_id, @@ -344,21 +353,12 @@ module Invidious::Comments "1:string" => cursor, "4:embedded" => { "4:string" => video_id, - "6:varint" => 0_i64, + "6:varint" => sort_by_val, }, "5:varint" => 20_i64, }, } - case sort_by - when "top" - object["6:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 - when "new", "newest" - object["6:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 1_i64 - else # top - object["6:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 - end - continuation = object.try { |i| Protodec::Any.cast_json(i) } .try { |i| Protodec::Any.from_json(i) } .try { |i| Base64.urlsafe_encode(i) } From 227c041b86c97a5197c673af7efadbaf649f812d Mon Sep 17 00:00:00 2001 From: Nami Sunami Date: Sat, 28 Jun 2025 11:38:31 +0200 Subject: [PATCH 035/108] fix(config.example.yml): Fix typo (effet -> effect) --- config/config.example.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.example.yml b/config/config.example.yml index 8d3e6212..e8ab658b 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -865,7 +865,7 @@ default_user_preferences: ## ## Default dash video quality. ## - ## Note: this setting only takes effet if the + ## Note: this setting only takes effect if the ## 'quality' parameter is set to "dash". ## ## Accepted values: From 24252b836ceee3bbcfe98a91963439b1bee44dcc Mon Sep 17 00:00:00 2001 From: epicsam123 <92618898+epicsam123@users.noreply.github.com> Date: Mon, 30 Jun 2025 22:38:30 -0400 Subject: [PATCH 036/108] add back semicolon --- assets/js/player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/player.js b/assets/js/player.js index 1a20c932..7ab3d0e7 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -450,7 +450,7 @@ if (!video_data.params.listen && video_data.params.annotations) { if (target === 'current') { location.href = path; } else if (target === 'new') { - open(path, '_blank', 'noopener,noreferrer') + open(path, '_blank', 'noopener,noreferrer'); } }); From a84bb1d22ed4d59deb50d8ecf72fac1e3a8f3ff4 Mon Sep 17 00:00:00 2001 From: fieryhenry <74794355+fieryhenry@users.noreply.github.com> Date: Fri, 18 Jul 2025 19:02:50 +0000 Subject: [PATCH 037/108] Fix `TRUE` number of notifications `update_ticker_count` used to use STORAGE_KEY_STREAM to get the number of notifications which is a boolean value, now it uses STORAGE_KEY_NOTIF_COUNT which is an integer --- assets/js/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/notifications.js b/assets/js/notifications.js index 55b7a15c..b8d73a82 100644 --- a/assets/js/notifications.js +++ b/assets/js/notifications.js @@ -77,7 +77,7 @@ function create_notification_stream(subscriptions) { function update_ticker_count() { var notification_ticker = document.getElementById('notification_ticker'); - const notification_count = helpers.storage.get(STORAGE_KEY_STREAM); + const notification_count = helpers.storage.get(STORAGE_KEY_NOTIF_COUNT); if (notification_count > 0) { notification_ticker.innerHTML = '' + notification_count + ' '; From 3335bc8c388677517e5c4b86eb917fd3fdace2f8 Mon Sep 17 00:00:00 2001 From: fieryhenry <74794355+fieryhenry@users.noreply.github.com> Date: Fri, 18 Jul 2025 19:07:41 +0000 Subject: [PATCH 038/108] Get a count of 0 if STORAGE_KEY_NOTIF_COUNT is not present in storage Not sure if this is necessary as I think it should always be present in storage, but just in case it isn't --- assets/js/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/notifications.js b/assets/js/notifications.js index b8d73a82..16d9866d 100644 --- a/assets/js/notifications.js +++ b/assets/js/notifications.js @@ -77,7 +77,7 @@ function create_notification_stream(subscriptions) { function update_ticker_count() { var notification_ticker = document.getElementById('notification_ticker'); - const notification_count = helpers.storage.get(STORAGE_KEY_NOTIF_COUNT); + const notification_count = helpers.storage.get(STORAGE_KEY_NOTIF_COUNT) || 0; if (notification_count > 0) { notification_ticker.innerHTML = '' + notification_count + ' '; From 875d8e7e41b58cce007cd3cc5fa8d615815c593a Mon Sep 17 00:00:00 2001 From: Eugene Pakhomov Date: Wed, 13 Aug 2025 13:26:48 +0300 Subject: [PATCH 039/108] Persist caption settings --- assets/js/player.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/player.js b/assets/js/player.js index f32c9b56..cce0b030 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -5,6 +5,7 @@ var video_data = JSON.parse(document.getElementById('video_data').textContent); var options = { liveui: true, playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0], + persistTextTrackSettings: true, controlBar: { children: [ 'playToggle', From dd8086e6d9d4fe79e5645cdc494a22877624cc86 Mon Sep 17 00:00:00 2001 From: Kristian Vos Date: Wed, 13 Aug 2025 15:43:54 +0200 Subject: [PATCH 040/108] fix: fetching channel playlists returned 500 error --- src/invidious/channels/playlists.cr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/invidious/channels/playlists.cr b/src/invidious/channels/playlists.cr index 9b45d0c8..cba1abd9 100644 --- a/src/invidious/channels/playlists.cr +++ b/src/invidious/channels/playlists.cr @@ -6,19 +6,19 @@ def fetch_channel_playlists(ucid, author, continuation, sort_by) case sort_by when "last", "last_added" # Equivalent to "&sort=lad" - # {"2:string": "playlists", "3:varint": 4, "4:varint": 1, "6:varint": 1} - "EglwbGF5bGlzdHMYBCABMAE%3D" + # {"2:string": "playlists", "3:varint": 4, "4:varint": 1, "6:varint": 1, "110:embedded": {"1:embedded": {"8:string": ""}}} + "EglwbGF5bGlzdHMYBCABMAHyBgQKAkIA" when "oldest", "oldest_created" # formerly "&sort=da" # Not available anymore :c or maybe ?? - # {"2:string": "playlists", "3:varint": 2, "4:varint": 1, "6:varint": 1} - "EglwbGF5bGlzdHMYAiABMAE%3D" + # {"2:string": "playlists", "3:varint": 2, "4:varint": 1, "6:varint": 1, "110:embedded": {"1:embedded": {"8:string": ""}}} + "EglwbGF5bGlzdHMYAiABMAHyBgQKAkIA" # {"2:string": "playlists", "3:varint": 1, "4:varint": 1, "6:varint": 1} # "EglwbGF5bGlzdHMYASABMAE%3D" when "newest", "newest_created" # Formerly "&sort=dd" - # {"2:string": "playlists", "3:varint": 3, "4:varint": 1, "6:varint": 1} - "EglwbGF5bGlzdHMYAyABMAE%3D" + # {"2:string": "playlists", "3:varint": 3, "4:varint": 1, "6:varint": 1, "110:embedded": {"1:embedded": {"8:string": ""}}} + "EglwbGF5bGlzdHMYAyABMAHyBgQKAkIA" end initial_data = YoutubeAPI.browse(ucid, params: params || "") From 67f93e55d8e9be4c81a58920c4651d2eb1327fd6 Mon Sep 17 00:00:00 2001 From: syeopite Date: Sat, 23 Aug 2025 03:35:59 -0700 Subject: [PATCH 041/108] Fix "ex" variable collision in invidious.cr The exception handling for database connections results in an `ex` variable which Ameba sees as overshadowing the `ex` used by the `ex` block arg used to define the HTTP status code 500 handler below. Although this is a non-issue since the db connection exception handling will cause Invidious to exit, Ameba's nature as a static checker means that it isn't aware of this. The simplest fix without a dirty ameba ignore comment is to rename `ex` within the Kemal handler block below, since `ex` within a begin rescue block is a Crystal convention that will also cause Ameba to raise when not adhered to. --- src/invidious.cr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 2d244dd2..197b150c 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -62,8 +62,8 @@ HMAC_KEY = CONFIG.hmac_key PG_DB = begin DB.open CONFIG.database_url -rescue exc - puts "Failed to connect to PostgreSQL database: #{exc.cause.try &.message}" +rescue ex + puts "Failed to connect to PostgreSQL database: #{ex.cause.try &.message}" puts "Check your 'config.yml' database settings or PostgreSQL settings." exit(1) end @@ -227,8 +227,8 @@ error 404 do |env| Invidious::Routes::ErrorRoutes.error_404(env) end -error 500 do |env, ex| - error_template(500, ex) +error 500 do |env, exception| + error_template(500, exception) end static_headers do |env| From 89c8b1b901062c729370370116aa9127a39cd214 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Tue, 2 Sep 2025 10:57:29 -0400 Subject: [PATCH 042/108] CI: fix wrong if statement for build-docker job (#5442) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52559825..ce166b7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,7 +99,7 @@ jobs: - uses: actions/checkout@v5 - name: Use ARM64 Dockerfile if ARM64 - if: ${{ matrix.name }} == "ARM64" + if: ${{ matrix.name == 'ARM64' }} run: sed -i 's/Dockerfile/Dockerfile.arm64/' docker-compose.yml - name: Build Docker From 324a416fd47cb7adbfdda20622dd0f47b60dd661 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 3 May 2025 01:10:12 +0200 Subject: [PATCH 043/108] initial support for base_url with invidious companion + proxy invidious_companion --- config/config.example.yml | 6 ++-- src/invidious/routes/companion.cr | 37 +++++++++++++++++++++ src/invidious/routes/embed.cr | 8 +++-- src/invidious/routes/watch.cr | 8 +++-- src/invidious/routing.cr | 9 ++++- src/invidious/yt_backend/connection_pool.cr | 34 ++++++++++++++----- src/invidious/yt_backend/youtube_api.cr | 30 ++++++++++------- 7 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 src/invidious/routes/companion.cr diff --git a/config/config.example.yml b/config/config.example.yml index e8ab658b..60fbc825 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -75,7 +75,7 @@ db: ## If you are using a reverse proxy then you will probably need to ## configure the public_url to be the same as the domain used for Invidious. ## Also apply when used from an external IP address (without a domain). -## Examples: https://MYINVIDIOUSDOMAIN or http://192.168.1.100:8282 +## Examples: https://MYINVIDIOUSDOMAIN/companion or http://192.168.1.100:8282/companion ## ## Both parameter can have identical URL when Invidious is hosted in ## an internal network or at home or locally (localhost). @@ -84,8 +84,8 @@ db: ## Default: ## #invidious_companion: -# - private_url: "http://localhost:8282" -# public_url: "http://localhost:8282" +# - private_url: "http://localhost:8282/companion" +# public_url: "http://localhost:8282/companion" ## ## API key for Invidious companion, used for securing the communication diff --git a/src/invidious/routes/companion.cr b/src/invidious/routes/companion.cr new file mode 100644 index 00000000..23b62e9d --- /dev/null +++ b/src/invidious/routes/companion.cr @@ -0,0 +1,37 @@ +module Invidious::Routes::Companion + # /companion + def self.get_companion(env) + url = env.request.path.lchop("/companion") + + begin + COMPANION_POOL.client &.get(url, env.request.header) do |resp| + return self.proxy_companion(env, resp) + end + rescue ex + end + end + + def self.options_companion(env) + url = env.request.path.lchop("/companion") + + begin + COMPANION_POOL.client &.options(url, env.request.header) do |resp| + return self.proxy_companion(env, resp) + end + rescue ex + end + end + + private def self.proxy_companion(env, response) + env.response.status_code = response.status_code + response.headers.each do |key, value| + env.response.headers[key] = value + end + + if response.status_code >= 300 + return env.response.headers.delete("Transfer-Encoding") + end + + return proxy_file(response, env) + end +end diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index 721a57f8..2fb7bebf 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -209,10 +209,14 @@ module Invidious::Routes::Embed if CONFIG.invidious_companion.present? invidious_companion = CONFIG.invidious_companion.sample + invidious_companion_urls = CONFIG.invidious_companion.map do |companion| + uri = + "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" + end.join(" ") env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion.public_url}") - .gsub("connect-src", "connect-src #{invidious_companion.public_url}") + .gsub("media-src", "media-src #{invidious_companion_urls}") + .gsub("connect-src", "connect-src #{invidious_companion_urls}") end rendered "embed" diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr index e777b3f1..a50a146d 100644 --- a/src/invidious/routes/watch.cr +++ b/src/invidious/routes/watch.cr @@ -194,10 +194,14 @@ module Invidious::Routes::Watch if CONFIG.invidious_companion.present? invidious_companion = CONFIG.invidious_companion.sample + invidious_companion_urls = CONFIG.invidious_companion.map do |companion| + uri = + "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" + end.join(" ") env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion.public_url}") - .gsub("connect-src", "connect-src #{invidious_companion.public_url}") + .gsub("media-src", "media-src #{invidious_companion_urls}") + .gsub("connect-src", "connect-src #{invidious_companion_urls}") end templated "watch" diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 46b71f1f..b95ac706 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -188,7 +188,7 @@ module Invidious::Routing end # ------------------- - # Media proxy routes + # Proxy routes # ------------------- def register_api_manifest_routes @@ -223,6 +223,13 @@ module Invidious::Routing get "/vi/:id/:name", Routes::Images, :thumbnails end + def register_companion_routes + if CONFIG.invidious_companion.present? + get "/companion/*", Routes::Companion, :get_companion + options "/companion/*", Routes::Companion, :options_companion + end + end + # ------------------- # API routes # ------------------- diff --git a/src/invidious/yt_backend/connection_pool.cr b/src/invidious/yt_backend/connection_pool.cr index 0daed46c..97ce7c40 100644 --- a/src/invidious/yt_backend/connection_pool.cr +++ b/src/invidious/yt_backend/connection_pool.cr @@ -46,8 +46,22 @@ struct YoutubeConnectionPool end end +class CompanionWrapper + property client : HTTP::Client + property companion : Config::CompanionConfig + + def initialize(companion : Config::CompanionConfig) + @companion = companion + @client = HTTP::Client.new(companion.private_url) + end + + def close + @client.close + end +end + struct CompanionConnectionPool - property pool : DB::Pool(HTTP::Client) + property pool : DB::Pool(CompanionWrapper) def initialize(capacity = 5, timeout = 5.0) options = DB::Pool::Options.new( @@ -57,26 +71,28 @@ struct CompanionConnectionPool checkout_timeout: timeout ) - @pool = DB::Pool(HTTP::Client).new(options) do + @pool = DB::Pool(CompanionWrapper).new(options) do companion = CONFIG.invidious_companion.sample - next make_client(companion.private_url, use_http_proxy: false) + client = make_client(companion.private_url, use_http_proxy: false) + CompanionWrapper.new(companion: companion) end end def client(&) - conn = pool.checkout + wrapper = pool.checkout begin - response = yield conn + response = yield wrapper rescue ex - conn.close + wrapper.client.close companion = CONFIG.invidious_companion.sample - conn = make_client(companion.private_url, use_http_proxy: false) + client = make_client(companion.private_url, use_http_proxy: false) + wrapper = CompanionWrapper.new(companion: companion) - response = yield conn + response = yield wrapper ensure - pool.release(conn) + pool.release(wrapper) end response diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index d287a42f..f87e3091 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -701,22 +701,28 @@ module YoutubeAPI # Send the POST request begin - response = COMPANION_POOL.client &.post(endpoint, headers: headers, body: data.to_json) - body = response.body - if (response.status_code != 200) - raise Exception.new( - "Error while communicating with Invidious companion: \ - status code: #{response.status_code} and body: #{body.dump}" - ) + response_body = "" + + COMPANION_POOL.client do |wrapper| + companion_base_url = wrapper.companion.private_url.path + puts "Using companion: #{wrapper.companion.private_url}" + + response = wrapper.client.post(companion_base_url + endpoint, headers: headers, body: data.to_json) + response_body = response.body + + if response.status_code != 200 + raise Exception.new( + "Error while communicating with Invidious companion: " \ + "status code: #{response.status_code} and body: #{response_body.dump}" + ) + end end + + # Convert result to Hash + return JSON.parse(response_body).as_h rescue ex raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found")) end - - # Convert result to Hash - initial_data = JSON.parse(body).as_h - - return initial_data end #################################################################### From 42b955d713c54632f1886641dcedac27ee625c8a Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 14 Jun 2025 18:01:44 +0200 Subject: [PATCH 044/108] chore: add the suggestions --- src/invidious/routes/before_all.cr | 1 + src/invidious/routes/companion.cr | 6 +----- src/invidious/yt_backend/connection_pool.cr | 15 ++++++++++----- src/invidious/yt_backend/youtube_api.cr | 16 ++++------------ 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index b5269668..63b935ec 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -63,6 +63,7 @@ module Invidious::Routes::BeforeAll "/videoplayback", "/latest_version", "/download", + "/companion/", }.any? { |r| env.request.resource.starts_with? r } if env.request.cookies.has_key? "SID" diff --git a/src/invidious/routes/companion.cr b/src/invidious/routes/companion.cr index 23b62e9d..cd7ed422 100644 --- a/src/invidious/routes/companion.cr +++ b/src/invidious/routes/companion.cr @@ -28,10 +28,6 @@ module Invidious::Routes::Companion env.response.headers[key] = value end - if response.status_code >= 300 - return env.response.headers.delete("Transfer-Encoding") - end - - return proxy_file(response, env) + return IO.copy response.body_io, env.response end end diff --git a/src/invidious/yt_backend/connection_pool.cr b/src/invidious/yt_backend/connection_pool.cr index 97ce7c40..45455a8a 100644 --- a/src/invidious/yt_backend/connection_pool.cr +++ b/src/invidious/yt_backend/connection_pool.cr @@ -46,13 +46,18 @@ struct YoutubeConnectionPool end end -class CompanionWrapper +# Packages a `HTTP::Client` to an Invidious companion instance alongside the configuration for that instance. +# +# This is used as the resource for the `CompanionPool` as to allow the ability to +# proxy the requests to Invidious companion from Invidious directly. +# Instead of setting up routes in a reverse proxy. +struct CompanionWrapper property client : HTTP::Client property companion : Config::CompanionConfig def initialize(companion : Config::CompanionConfig) @companion = companion - @client = HTTP::Client.new(companion.private_url) + @client = make_client(companion.private_url, use_http_proxy: false) end def close @@ -73,7 +78,7 @@ struct CompanionConnectionPool @pool = DB::Pool(CompanionWrapper).new(options) do companion = CONFIG.invidious_companion.sample - client = make_client(companion.private_url, use_http_proxy: false) + make_client(companion.private_url, use_http_proxy: false) CompanionWrapper.new(companion: companion) end end @@ -84,10 +89,10 @@ struct CompanionConnectionPool begin response = yield wrapper rescue ex - wrapper.client.close + wrapper.close companion = CONFIG.invidious_companion.sample - client = make_client(companion.private_url, use_http_proxy: false) + make_client(companion.private_url, use_http_proxy: false) wrapper = CompanionWrapper.new(companion: companion) response = yield wrapper diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index f87e3091..4b39acd7 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -701,25 +701,17 @@ module YoutubeAPI # Send the POST request begin - response_body = "" + response_body = Hash(String, JSON::Any).new COMPANION_POOL.client do |wrapper| companion_base_url = wrapper.companion.private_url.path - puts "Using companion: #{wrapper.companion.private_url}" - response = wrapper.client.post(companion_base_url + endpoint, headers: headers, body: data.to_json) - response_body = response.body - - if response.status_code != 200 - raise Exception.new( - "Error while communicating with Invidious companion: " \ - "status code: #{response.status_code} and body: #{response_body.dump}" - ) + wrapper.client.post("#{companion_base_url}#{endpoint}", headers: headers, body: data.to_json) do | response | + response_body = JSON.parse(response.body_io).as_h end end - # Convert result to Hash - return JSON.parse(response_body).as_h + return response_body rescue ex raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found")) end From cba2adc6ef19d52736356a84af21fa513c7b3f74 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 14 Jun 2025 19:10:52 +0200 Subject: [PATCH 045/108] fix csp + progress proxy + allow omit public_url --- config/config.example.yml | 8 ++++++++ src/invidious/config.cr | 11 +++++++++++ src/invidious/routes/companion.cr | 23 +++++++++++++++++------ src/invidious/routes/embed.cr | 13 ++++++++----- src/invidious/routes/watch.cr | 13 ++++++++----- src/invidious/routing.cr | 1 + 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 60fbc825..cabbecfd 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -80,12 +80,20 @@ db: ## Both parameter can have identical URL when Invidious is hosted in ## an internal network or at home or locally (localhost). ## +## NOTE: If public_url is omitted, Invidious will use its built-in proxy +## to route companion requests through /companion, which is useful for +## simple setups where companion runs on the same network. When using +## the built-in proxy, CSP headers are not modified since requests +## stay within the same domain. +## ## Accepted values: "http(s)://:" ## Default: ## #invidious_companion: # - private_url: "http://localhost:8282/companion" # public_url: "http://localhost:8282/companion" +# # Example with built-in proxy (omit public_url): +# # - private_url: "http://localhost:8282/companion" ## ## API key for Invidious companion, used for securing the communication diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 4d69854c..e47e405c 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -82,6 +82,9 @@ class Config @[YAML::Field(converter: Preferences::URIConverter)] property public_url : URI = URI.parse("") + + # Indicates if this companion instance uses the built-in proxy + property builtin_proxy : Bool = false end # Number of threads to use for crawling videos from channels (for updating subscriptions) @@ -271,6 +274,14 @@ class Config puts "Config: The value of 'invidious_companion_key' needs to be a size of 16 characters." exit(1) end + + # Set public_url to built-in proxy path when omitted + config.invidious_companion.each do |companion| + if companion.public_url.to_s.empty? + companion.public_url = URI.parse("/companion") + companion.builtin_proxy = true + end + end elsif config.signature_server puts("WARNING: inv-sig-helper is deprecated. Please switch to Invidious companion: https://docs.invidious.io/companion-installation/") else diff --git a/src/invidious/routes/companion.cr b/src/invidious/routes/companion.cr index cd7ed422..bcfbad6b 100644 --- a/src/invidious/routes/companion.cr +++ b/src/invidious/routes/companion.cr @@ -1,22 +1,33 @@ module Invidious::Routes::Companion # /companion def self.get_companion(env) - url = env.request.path.lchop("/companion") + url = env.request.path + if env.request.query + url += "?#{env.request.query}" + end begin - COMPANION_POOL.client &.get(url, env.request.header) do |resp| - return self.proxy_companion(env, resp) + COMPANION_POOL.client do |wrapper| + puts env.request.headers + wrapper.client.get(url, env.request.headers) do |resp| + return self.proxy_companion(env, resp) + end end rescue ex end end def self.options_companion(env) - url = env.request.path.lchop("/companion") + url = env.request.path + if env.request.query + url += "?#{env.request.query}" + end begin - COMPANION_POOL.client &.options(url, env.request.header) do |resp| - return self.proxy_companion(env, resp) + COMPANION_POOL.client do |wrapper| + wrapper.client.options(url, env.request.headers) do |resp| + return self.proxy_companion(env, resp) + end end rescue ex end diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index 2fb7bebf..1318b290 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -209,14 +209,17 @@ module Invidious::Routes::Embed if CONFIG.invidious_companion.present? invidious_companion = CONFIG.invidious_companion.sample - invidious_companion_urls = CONFIG.invidious_companion.map do |companion| + invidious_companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion| uri = "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" end.join(" ") - env.response.headers["Content-Security-Policy"] = - env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion_urls}") - .gsub("connect-src", "connect-src #{invidious_companion_urls}") + + if !invidious_companion_urls.empty? + env.response.headers["Content-Security-Policy"] = + env.response.headers["Content-Security-Policy"] + .gsub("media-src", "media-src #{invidious_companion_urls}") + .gsub("connect-src", "connect-src #{invidious_companion_urls}") + end end rendered "embed" diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr index a50a146d..83893457 100644 --- a/src/invidious/routes/watch.cr +++ b/src/invidious/routes/watch.cr @@ -194,14 +194,17 @@ module Invidious::Routes::Watch if CONFIG.invidious_companion.present? invidious_companion = CONFIG.invidious_companion.sample - invidious_companion_urls = CONFIG.invidious_companion.map do |companion| + invidious_companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion| uri = "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" end.join(" ") - env.response.headers["Content-Security-Policy"] = - env.response.headers["Content-Security-Policy"] - .gsub("media-src", "media-src #{invidious_companion_urls}") - .gsub("connect-src", "connect-src #{invidious_companion_urls}") + + if !invidious_companion_urls.empty? + env.response.headers["Content-Security-Policy"] = + env.response.headers["Content-Security-Policy"] + .gsub("media-src", "media-src #{invidious_companion_urls}") + .gsub("connect-src", "connect-src #{invidious_companion_urls}") + end end templated "watch" diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index b95ac706..a51bb4b6 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -46,6 +46,7 @@ module Invidious::Routing self.register_api_v1_routes self.register_api_manifest_routes self.register_video_playback_routes + self.register_companion_routes end # ------------------- From 1653dd629e34bf4e5dc081ac15c070607e7d2908 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sat, 14 Jun 2025 22:35:11 +0200 Subject: [PATCH 046/108] fix formatting --- src/invidious/routes/embed.cr | 2 +- src/invidious/routes/watch.cr | 2 +- src/invidious/yt_backend/connection_pool.cr | 2 +- src/invidious/yt_backend/youtube_api.cr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/invidious/routes/embed.cr b/src/invidious/routes/embed.cr index 1318b290..6b0887d5 100644 --- a/src/invidious/routes/embed.cr +++ b/src/invidious/routes/embed.cr @@ -213,7 +213,7 @@ module Invidious::Routes::Embed uri = "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" end.join(" ") - + if !invidious_companion_urls.empty? env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"] diff --git a/src/invidious/routes/watch.cr b/src/invidious/routes/watch.cr index 83893457..8a4fa246 100644 --- a/src/invidious/routes/watch.cr +++ b/src/invidious/routes/watch.cr @@ -198,7 +198,7 @@ module Invidious::Routes::Watch uri = "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}" end.join(" ") - + if !invidious_companion_urls.empty? env.response.headers["Content-Security-Policy"] = env.response.headers["Content-Security-Policy"] diff --git a/src/invidious/yt_backend/connection_pool.cr b/src/invidious/yt_backend/connection_pool.cr index 45455a8a..42241d15 100644 --- a/src/invidious/yt_backend/connection_pool.cr +++ b/src/invidious/yt_backend/connection_pool.cr @@ -47,7 +47,7 @@ struct YoutubeConnectionPool end # Packages a `HTTP::Client` to an Invidious companion instance alongside the configuration for that instance. -# +# # This is used as the resource for the `CompanionPool` as to allow the ability to # proxy the requests to Invidious companion from Invidious directly. # Instead of setting up routes in a reverse proxy. diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 4b39acd7..6fa8ae0e 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -706,7 +706,7 @@ module YoutubeAPI COMPANION_POOL.client do |wrapper| companion_base_url = wrapper.companion.private_url.path - wrapper.client.post("#{companion_base_url}#{endpoint}", headers: headers, body: data.to_json) do | response | + wrapper.client.post("#{companion_base_url}#{endpoint}", headers: headers, body: data.to_json) do |response| response_body = JSON.parse(response.body_io).as_h end end From 5e9d51c06e387ea38108234406cfa0aa5e6fc12c Mon Sep 17 00:00:00 2001 From: syeopite Date: Wed, 28 May 2025 15:38:49 -0700 Subject: [PATCH 047/108] Refactor `FilteredCompressHandler` to inherit from stdlib This changes its behavior to align with the stdlib variant in that compression is now delayed till the moment that the server begins to send a response. This allows the handler to avoid compressing empty responses,and safeguards against any double compression of content that may occur if another handler decides to compressi ts response. This does however come at the drawback(?) of it now removing `content-length` headers on requests if it exists; since compression makes the value inaccurate anyway. See: https://github.com/crystal-lang/crystal/pull/9625 --- src/invidious/helpers/handlers.cr | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/invidious/helpers/handlers.cr b/src/invidious/helpers/handlers.cr index 13ea9fe9..7c5ef118 100644 --- a/src/invidious/helpers/handlers.cr +++ b/src/invidious/helpers/handlers.cr @@ -61,28 +61,13 @@ class Kemal::ExceptionHandler end end -class FilteredCompressHandler < Kemal::Handler +class FilteredCompressHandler < HTTP::CompressHandler exclude ["/videoplayback", "/videoplayback/*", "/vi/*", "/sb/*", "/ggpht/*", "/api/v1/auth/notifications"] exclude ["/api/v1/auth/notifications", "/data_control"], "POST" - def call(env) - return call_next env if exclude_match? env - - {% if flag?(:without_zlib) %} - call_next env - {% else %} - request_headers = env.request.headers - - if request_headers.includes_word?("Accept-Encoding", "gzip") - env.response.headers["Content-Encoding"] = "gzip" - env.response.output = Compress::Gzip::Writer.new(env.response.output, sync_close: true) - elsif request_headers.includes_word?("Accept-Encoding", "deflate") - env.response.headers["Content-Encoding"] = "deflate" - env.response.output = Compress::Deflate::Writer.new(env.response.output, sync_close: true) - end - - call_next env - {% end %} + def call(context) + return call_next context if exclude_match? context + super end end From 21c13bba9ddee5db02b7584efe5ae5912cbeabd6 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Wed, 3 Sep 2025 15:57:48 +0200 Subject: [PATCH 048/108] chore: use api captions from companion when available --- src/invidious/views/components/player.ecr | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index af352102..85fa4373 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -65,12 +65,18 @@ <% end %> <% end %> - <% preferred_captions.each do |caption| %> - + <% preferred_captions.each do |caption| + api_captions_url = "/api/v1/captions/" + api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion) + %> + <% end %> - <% captions.each do |caption| %> - + <% captions.each do |caption| + api_captions_url = "/api/v1/captions/" + api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion) + %> + <% end %> <% end %> From cf2dfbb75d51a645fd7440d45a48d24fd8b15676 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Wed, 3 Sep 2025 15:57:58 +0200 Subject: [PATCH 049/108] chore: remove debug --- src/invidious/routes/companion.cr | 1 - 1 file changed, 1 deletion(-) diff --git a/src/invidious/routes/companion.cr b/src/invidious/routes/companion.cr index bcfbad6b..11c2e3f5 100644 --- a/src/invidious/routes/companion.cr +++ b/src/invidious/routes/companion.cr @@ -8,7 +8,6 @@ module Invidious::Routes::Companion begin COMPANION_POOL.client do |wrapper| - puts env.request.headers wrapper.client.get(url, env.request.headers) do |resp| return self.proxy_companion(env, resp) end From ba02a4cdf5f266b28c4f6ebe7b58b615330d3ee5 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Mon, 8 Sep 2025 17:16:22 -0300 Subject: [PATCH 050/108] Prevent player microformat from being overwritten by the next microformat (#5453) * Prevent player microformat from being overwritten by the next microformat Closes https://github.com/iv-org/invidious/issues/5443 The player microformat is what we need to get the published date, premiere timestamp, allowed regions and more information of the video. Youtube introduced a new `microformat.microformatDataRenderer` in the next endpoint which overwrote the player microformat `microformat.playerMicroformatRenderer` when merged * Update src/invidious/videos/parser.cr Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --------- Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com> --- src/invidious/videos/parser.cr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/invidious/videos/parser.cr b/src/invidious/videos/parser.cr index 5335aa79..6b1dedd6 100644 --- a/src/invidious/videos/parser.cr +++ b/src/invidious/videos/parser.cr @@ -102,6 +102,9 @@ def extract_video_info(video_id : String) # Don't fetch the next endpoint if the video is unavailable. if {"OK", "LIVE_STREAM_OFFLINE", "LOGIN_REQUIRED"}.any?(playability_status) next_response = YoutubeAPI.next({"videoId": video_id, "params": ""}) + # Remove the microformat returned by the /next endpoint on some videos + # to prevent player_response microformat from being overwritten. + next_response.delete("microformat") player_response = player_response.merge(next_response) end From 9e160d45d33e25f4faeaf4bfcde9a6b450426aba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 20:45:44 +0000 Subject: [PATCH 051/108] Bump actions/stale from 9 to 10 Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v9...v10) --- updated-dependencies: - dependency-name: actions/stale dependency-version: '10' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 65340d14..ab45ce12 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 730 From 14a629a4e8103aa1483cfc70bf68d31ecebc64a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milien=20=28perso=29?= <4016501+unixfox@users.noreply.github.com> Date: Wed, 10 Sep 2025 21:30:18 +0200 Subject: [PATCH 052/108] Better documentation for the specific case public_url with companion --- config/config.example.yml | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index cabbecfd..2b99345b 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -61,39 +61,32 @@ db: ## When this setting is commented out, Invidious companion is not used. ## Otherwise, Invidious will proxy the requests to Invidious companion. ## -## Note: multiple URL can be configured. In this case, invidious will +## Note: multiple URL can be configured. In this case, Invidious will ## randomly pick one every time video data needs to be retrieved. This ## URL is then kept in the video metadata cache to allow video playback ## to work. Once said cache has expired, requesting that video's data ## again will cause a new companion URL to be picked. ## -## The parameter private_url needs to be configured for the internal -## communication between the companion and Invidious. -## And public_url is the public URL from which companion is listening -## to the requests from the user(s). +## The parameter private_url is required for the internal communication +## between Invidious companion and Invidious. ## -## If you are using a reverse proxy then you will probably need to -## configure the public_url to be the same as the domain used for Invidious. -## Also apply when used from an external IP address (without a domain). -## Examples: https://MYINVIDIOUSDOMAIN/companion or http://192.168.1.100:8282/companion -## -## Both parameter can have identical URL when Invidious is hosted in -## an internal network or at home or locally (localhost). -## -## NOTE: If public_url is omitted, Invidious will use its built-in proxy -## to route companion requests through /companion, which is useful for -## simple setups where companion runs on the same network. When using -## the built-in proxy, CSP headers are not modified since requests -## stay within the same domain. +## The optional parameter public_url is the public URL from which +## Invidious companion is listening to the requests from the user(s). +## When this setting is commented out, Invidious proxy all requests to +## Invidious companion. Useful for simple setups. +## Otherwise, requests from the user(s) will reach Invidious companion directly. +## And you will need to configure a reverse proxy with separate routes +## for Invidious and Invidious companion. +## Read the post-install documentation for advanced reverse proxy +## documentation: https://docs.invidious.io/installation/#post-install-configuration ## ## Accepted values: "http(s)://:" ## Default: ## #invidious_companion: # - private_url: "http://localhost:8282/companion" -# public_url: "http://localhost:8282/companion" -# # Example with built-in proxy (omit public_url): -# # - private_url: "http://localhost:8282/companion" +# # Uncomment for advanced reverse proxy configuration (see above). +# # public_url: "http://localhost:8282/companion" ## ## API key for Invidious companion, used for securing the communication From f9cf70f9d7cf54e2d774a8bcf336dd1a142e71b3 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 11 Sep 2025 11:05:09 -0300 Subject: [PATCH 053/108] Add default playlist preference (#5449) * Add default playlist preference Closes https://github.com/iv-org/invidious/issues/5421 * Add option to set default playlist to none * Move it to player preferences --- locales/en-US.json | 2 ++ locales/es.json | 2 ++ src/invidious/config.cr | 2 ++ src/invidious/routes/preferences.cr | 3 +++ src/invidious/user/preferences.cr | 1 + src/invidious/views/user/preferences.ecr | 13 +++++++++++++ src/invidious/views/watch.ecr | 2 +- 7 files changed, 24 insertions(+), 1 deletion(-) diff --git a/locales/en-US.json b/locales/en-US.json index 3f42a509..fa28e7f8 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -122,6 +122,8 @@ "Redirect homepage to feed: ": "Redirect homepage to feed: ", "preferences_max_results_label": "Number of videos shown in feed: ", "preferences_sort_label": "Sort videos by: ", + "preferences_default_playlist": "Default playlist: ", + "preferences_default_playlist_none": "No default playlist set", "published": "published", "published - reverse": "published - reverse", "alphabetically": "alphabetically", diff --git a/locales/es.json b/locales/es.json index 46217943..686e13f9 100644 --- a/locales/es.json +++ b/locales/es.json @@ -78,6 +78,8 @@ "Redirect homepage to feed: ": "Redirigir la página de inicio a la fuente: ", "preferences_max_results_label": "Número de videos mostrados en la fuente: ", "preferences_sort_label": "Ordenar los videos por: ", + "preferences_default_playlist": "Lista de reproducción por defecto: ", + "preferences_default_playlist_none": "Ninguna lista de reproducción por defecto establecida", "published": "fecha de publicación", "published - reverse": "fecha de publicación: orden inverso", "alphabetically": "alfabéticamente", diff --git a/src/invidious/config.cr b/src/invidious/config.cr index e47e405c..36f09d28 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -52,6 +52,8 @@ struct ConfigPreferences property vr_mode : Bool = true property show_nick : Bool = true property save_player_pos : Bool = false + @[YAML::Field(ignore: true)] + property default_playlist : String? = nil def to_tuple {% begin %} diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 39ca77c0..9936e523 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -144,6 +144,8 @@ module Invidious::Routes::PreferencesRoute notifications_only ||= "off" notifications_only = notifications_only == "on" + default_playlist = env.params.body["default_playlist"]?.try &.as(String) + # Convert to JSON and back again to take advantage of converters used for compatibility preferences = Preferences.from_json({ annotations: annotations, @@ -180,6 +182,7 @@ module Invidious::Routes::PreferencesRoute vr_mode: vr_mode, show_nick: show_nick, save_player_pos: save_player_pos, + default_playlist: default_playlist, }.to_json) if user = env.get? "user" diff --git a/src/invidious/user/preferences.cr b/src/invidious/user/preferences.cr index 0a8525f3..df195dd6 100644 --- a/src/invidious/user/preferences.cr +++ b/src/invidious/user/preferences.cr @@ -56,6 +56,7 @@ struct Preferences property extend_desc : Bool = CONFIG.default_user_preferences.extend_desc property volume : Int32 = CONFIG.default_user_preferences.volume property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos + property default_playlist : String? = nil module BoolToString def self.to_json(value : String, json : JSON::Builder) diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index cf8b5593..23cb89f6 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -126,6 +126,19 @@ checked<% end %>>
+ <% if user = env.get?("user").try &.as(User) %> + <% playlists = Invidious::Database::Playlists.select_user_created_playlists(user.email) %> +
+ + +
+ <% end %> + <%= translate(locale, "preferences_category_visual") %>
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 6f9ced6f..fada6361 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -163,7 +163,7 @@ we're going to need to do it here in order to allow for translations.
From 97783f84c13b12ba0f6aadf416f6f82a0f6a24d7 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:11 +0200 Subject: [PATCH 054/108] Update Turkish translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Bora Atıcı Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/tr.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/tr.json b/locales/tr.json index cf3f8987..08162973 100644 --- a/locales/tr.json +++ b/locales/tr.json @@ -39,8 +39,6 @@ "User ID": "Kullanıcı Kimliği", "Password": "Parola", "Time (h:mm:ss):": "Zaman (h:mm:ss):", - "Text CAPTCHA": "Metin CAPTCHA", - "Image CAPTCHA": "Resim CAPTCHA", "Sign In": "Oturum Aç", "Register": "Kayıt Ol", "E-mail": "E-Posta", @@ -501,5 +499,8 @@ "First page": "İlk sayfa", "Filipino (auto-generated)": "Filipince (oto-oluşturuldu)", "channel_tab_courses_label": "Kurslar", - "channel_tab_posts_label": "Yazılar" + "channel_tab_posts_label": "Yazılar", + "timeline_parse_error_placeholder_heading": "Öge ayrıştıramıyor", + "timeline_parse_error_placeholder_message": "Invidious, bu ögeyi ayrıştırmaya çalışırken bir hatayla karşılaştı. Daha fazla bilgi için aşağıya bakın:", + "timeline_parse_error_show_technical_details": "Teknik ayrıntıları göster" } From ae75c142d0d43810f80507a822275c0c962efcf8 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:12 +0200 Subject: [PATCH 055/108] Update Latvian translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Latvian translation Co-authored-by: Hosted Weblate Co-authored-by: ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) --- locales/lv.json | 76 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/locales/lv.json b/locales/lv.json index a867c8f3..12d7feef 100644 --- a/locales/lv.json +++ b/locales/lv.json @@ -65,5 +65,79 @@ "youtube": "YouTube", "Add to playlist: ": "Pievienot atskaņošanas sarakstam: ", "Subscribe": "Abonēt", - "View channel on YouTube": "Skatīt kanālu YouTube vietnē" + "View channel on YouTube": "Skatīt kanālu YouTube vietnē", + "LIVE": "TIEŠRAIDE", + "Export": "Izgūt", + "preferences_dark_mode_label": "Motīvs: ", + "published": "Publicēšanas datuma", + "preferences_sort_label": "Kārtot video pēc: ", + "search_filters_sort_label": "Kārtot pēc", + "search_filters_sort_option_date": "Augšupielādes datuma", + "search_filters_sort_option_views": "Skatījumu skaita", + "published - reverse": "Publicēšanas datuma apgrieztā secībā", + "generic_views_count_0": "{{count}} skatījumi", + "generic_views_count_1": "{{count}} skatījums", + "generic_views_count_2": "{{count}} skatījumi", + "generic_videos_count_0": "{{count}} video", + "generic_videos_count_1": "{{count}} video", + "generic_videos_count_2": "{{count}} video", + "generic_playlists_count_0": "{{count}} atskaņošanas saraksti", + "generic_playlists_count_1": "{{count}} atskaņošanas saraksts", + "generic_playlists_count_2": "{{count}} atskaņošanas saraksti", + "generic_subscriptions_count_0": "{{count}} abonementi", + "generic_subscriptions_count_1": "{{count}} abonements", + "generic_subscriptions_count_2": "{{count}} abonementi", + "subscriptions_unseen_notifs_count_0": "{{count}} jauni paziņojumi", + "subscriptions_unseen_notifs_count_1": "{{count}} jauns paziņojums", + "subscriptions_unseen_notifs_count_2": "{{count}} jauni paziņojumi", + "comments_view_x_replies_0": "Skatīt {{count}} atbildes", + "comments_view_x_replies_1": "Skatīt {{count}} atbildi", + "comments_view_x_replies_2": "Skatīt {{count}} atbildes", + "generic_count_years_0": "{{count}} gadi", + "generic_count_years_1": "{{count}} gads", + "generic_count_years_2": "{{count}} gadi", + "generic_count_months_0": "{{count}} mēneši", + "generic_count_months_1": "{{count}} mēnesis", + "generic_count_months_2": "{{count}} mēneši", + "generic_count_weeks_0": "{{count}} nedēļas", + "generic_count_weeks_1": "{{count}} nedēļa", + "generic_count_weeks_2": "{{count}} nedēļas", + "generic_count_days_0": "{{count}} dienas", + "generic_count_days_1": "{{count}} diena", + "generic_count_days_2": "{{count}} dienas", + "generic_count_hours_0": "{{count}} stundas", + "generic_count_hours_1": "{{count}} stunda", + "generic_count_hours_2": "{{count}} stundas", + "generic_count_minutes_0": "{{count}} minūtes", + "generic_count_minutes_1": "{{count}} minūte", + "generic_count_minutes_2": "{{count}} minūtes", + "generic_count_seconds_0": "{{count}} sekundes", + "generic_count_seconds_1": "{{count}} sekunde", + "generic_count_seconds_2": "{{count}} sekundes", + "Import YouTube playlist (.csv)": "Ievietot YouTube atskaņošanas sarakstu (.csv)", + "Import YouTube watch history (.json)": "Ievietot YouTube skatīto video vēsturi (.json)", + "Import FreeTube subscriptions (.db)": "Ievietot FreeTube abonementus (.db)", + "Import NewPipe subscriptions (.json)": "Ievietot NewPipe abonementus (.json)", + "Import NewPipe data (.zip)": "Ievietot NewPipe datus (.zip)", + "Export subscriptions as OPML": "Izgūt abonementus OPML formātā", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Izgūt abonementus OPML formātā (der NewPipe un FreeTube lietotnēm)", + "preferences_max_results_label": "Video skaits plūsmā: ", + "channel name": "kanāla nosaukuma", + "channel name - reverse": "kanāla nosaukuma apgrieztā secībā", + "preferences_unseen_only_label": "Rādīt tikai neskatītos video: ", + "Enable web notifications": "Iespējot paziņojumus pārlūkā", + "`x` uploaded a video": "`x` augšupielādēja video", + "Watch history": "Skatīto video vēsture", + "Delete account": "Dzēst kontu", + "Save preferences": "Saglabāt iestatījumus", + "Import/export": "Ievietot/Izgūt", + "Released under the AGPLv3 on Github.": "Izvietots GitHub saskaņā ar AGPLv3 licenci.", + "Source available here.": "Pirmkods pieejams šeit.", + "View JavaScript license information.": "Skatīt JavaScript licences informāciju.", + "Public": "Publisks", + "Private": "Privāts", + "View all playlists": "Skatīt visus atskaņošanas sarakstus", + "Delete playlist `x`?": "Vai tiešām dzēst `x` atskaņošanas sarakstu?", + "Delete playlist": "Dzēst atskaņošanas sarakstu", + "Create playlist": "Izveidot atskaņošanas sarakstu" } From c28fb22db54a698520396e0081b014815802ff79 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:13 +0200 Subject: [PATCH 056/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/lt.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/lt.json b/locales/lt.json index 740be7b6..6f0a58bb 100644 --- a/locales/lt.json +++ b/locales/lt.json @@ -39,8 +39,6 @@ "User ID": "Naudotojo ID", "Password": "Slaptažodis", "Time (h:mm:ss):": "Laikas (h:mm:ss):", - "Text CAPTCHA": "CAPTCHA tekstas", - "Image CAPTCHA": "CAPTCHA paveikslėlis", "Sign In": "Prisijungti", "Register": "Registruotis", "E-mail": "El. paštas", From d38f5d0ab70baa0327f3b73e29ab4c055ca926f6 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:16 +0200 Subject: [PATCH 057/108] Update Turkmen translation Co-authored-by: Hosted Weblate Co-authored-by: Hydyr Sopyyew --- locales/tk.json | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/locales/tk.json b/locales/tk.json index 798ea6ce..b540abb1 100644 --- a/locales/tk.json +++ b/locales/tk.json @@ -1,7 +1,26 @@ { - "Add to playlist": "Aýdym sanawyna goş", + "Add to playlist": "Pleýer Sanawa goş", "Add to playlist: ": "Pleýliste goş: ", "Answer": "Jogap", "Search for videos": "Wideo gözläň", - "The Popular feed has been disabled by the administrator.": "Trende bolan administrator tarapyndan ýapyldy." + "The Popular feed has been disabled by the administrator.": "Trende bolan administrator tarapyndan ýapyldy.", + "generic_views_count": "{{count}} gezek görülen", + "generic_views_count_plural": "{{count}} görülen", + "generic_button_delete": "Öçür", + "generic_button_save": "Ýatda sakla", + "generic_button_cancel": "Goýbolsun", + "generic_button_rss": "RSS", + "LIVE": "Efif", + "generic_playlists_count": "{{count}} Oýnaw sanawy", + "generic_playlists_count_plural": "{{count}} Oýnaw sanawlary", + "generic_subscribers_count": "{{count}} abuna", + "generic_subscribers_count_plural": "{{count}} abunaçalar", + "generic_subscriptions_count": "{{count}} abuna", + "generic_subscriptions_count_plural": "{{count}} abunalar", + "generic_button_edit": "Üýtget", + "generic_videos_count": "{{count}} widýo", + "generic_videos_count_plural": "{{count}} widýolar", + "Shared `x` ago": "`x` öň paýlaşyldy", + "generic_channels_count": "{{count}} kanal", + "generic_channels_count_plural": "{{count}} kanallar" } From f9821d08ee66be1a43f11bd46794982c377e8f90 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:18 +0200 Subject: [PATCH 058/108] Update Tamil translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: தமிழ்நேரம் Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ta.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/locales/ta.json b/locales/ta.json index 89e58668..1f8f1290 100644 --- a/locales/ta.json +++ b/locales/ta.json @@ -282,8 +282,6 @@ "Import": "இறக்குமதி", "Import NewPipe subscriptions (.json)": "நியூபிப்பிப் சந்தாக்களை இறக்குமதி செய்யுங்கள் (.json)", "Export": "ஏற்றுமதி", - "Text CAPTCHA": "உரை கேப்ட்சா", - "Image CAPTCHA": "பட கேப்ட்சா", "preferences_category_player": "பிளேயர் விருப்பத்தேர்வுகள்", "preferences_video_loop_label": "எப்போதும் லூப்: ", "preferences_continue_autoplay_label": "தன்னியக்க அடுத்த வீடியோ: ", @@ -498,5 +496,11 @@ "channel_tab_channels_label": "சேனல்கள்", "toggle_theme": "கருப்பொருளை மாற்றவும்", "carousel_slide": "{{total}} இன் ச்லைடு {{current}}", - "carousel_skip": "கொணர்வி தவிர்க்கவும்" + "carousel_skip": "கொணர்வி தவிர்க்கவும்", + "First page": "முதல் பக்கம்", + "channel_tab_courses_label": "படிப்புகள்", + "channel_tab_posts_label": "இடுகைகள்", + "timeline_parse_error_placeholder_heading": "உருப்படியை அலச முடியவில்லை", + "timeline_parse_error_placeholder_message": "இந்த உருப்படியை அலச முயற்சிக்கும் போது ஒரு பிழையை அடக்கமடைந்தது. மேலும் தகவலுக்கு கீழே காண்க:", + "timeline_parse_error_show_technical_details": "தொழில்நுட்ப விவரங்களைக் காட்டு" } From 08821d78973339a48c0e8e6a0f298903f335ce81 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:19 +0200 Subject: [PATCH 059/108] Update Portuguese (Brazil) translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Portuguese (Brazil) translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Juzé Co-authored-by: joaooliva Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pt-BR.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 1eb3c989..ef1eb249 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -18,7 +18,7 @@ "Authorize token for `x`?": "Autorizar token para `x`?", "Yes": "Sim", "No": "Não", - "Import and Export Data": "Importar/exportar dados", + "Import and Export Data": "Importar e exportar dados", "Import": "Importar", "Import Invidious data": "Importar dados JSON do Invidious", "Import YouTube subscriptions": "Importar inscrições no formato CSV ou OPML do YouTube", @@ -39,8 +39,6 @@ "User ID": "Usuário", "Password": "Senha", "Time (h:mm:ss):": "Hora (h:mm:ss):", - "Text CAPTCHA": "Mudar para um desafio de texto", - "Image CAPTCHA": "Mudar para um desafio visual", "Sign In": "Fazer login", "Register": "Criar conta", "E-mail": "E-mail", @@ -484,7 +482,7 @@ "channel_tab_channels_label": "Canais", "channel_tab_playlists_label": "Playlists", "channel_tab_shorts_label": "Shorts", - "channel_tab_streams_label": "Transmissão ao vivo", + "channel_tab_streams_label": "Transmissões ao vivo", "Music in this video": "Música neste vídeo", "Artist: ": "Artista: ", "Album: ": "Álbum: ", @@ -518,5 +516,8 @@ "Filipino (auto-generated)": "Filipino (gerado automaticamente)", "channel_tab_posts_label": "Postagens", "First page": "Primeira página", - "channel_tab_courses_label": "Cursos" + "channel_tab_courses_label": "Cursos", + "timeline_parse_error_show_technical_details": "Mostrar detalhes técnicos", + "timeline_parse_error_placeholder_message": "O Invidious encontrou um problema ao processar este item. Para mais informações, veja abaixo:", + "timeline_parse_error_placeholder_heading": "Incapaz de processar item" } From bda898d7fb9ccdda71f26ffa842e634e23981b9d Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:21 +0200 Subject: [PATCH 060/108] Update German translation Update German translation Update German translation Update German translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Ettore Atalan Co-authored-by: Hosted Weblate Co-authored-by: Lenny Angst Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/de.json | 67 +++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/locales/de.json b/locales/de.json index e51d40b9..33039814 100644 --- a/locales/de.json +++ b/locales/de.json @@ -12,7 +12,7 @@ "Next page": "Nächste Seite", "Previous page": "Vorherige Seite", "First page": "Erste Seite", - "Clear watch history?": "Verlauf löschen?", + "Clear watch history?": "Wiedergabeverlauf löschen?", "New password": "Neues Passwort", "New passwords must match": "Neue Passwörter müssen übereinstimmen", "Authorize token?": "Token autorisieren?", @@ -40,8 +40,6 @@ "User ID": "Benutzer-ID", "Password": "Passwort", "Time (h:mm:ss):": "Zeit (h:mm:ss):", - "Text CAPTCHA": "Text CAPTCHA", - "Image CAPTCHA": "Bild CAPTCHA", "Sign In": "Anmelden", "Register": "Registrieren", "E-mail": "E-Mail", @@ -108,11 +106,11 @@ "Top enabled: ": "Top aktiviert? ", "CAPTCHA enabled: ": "CAPTCHA aktiviert? ", "Login enabled: ": "Anmeldung aktiviert: ", - "Registration enabled: ": "Registrierung aktiviert? ", - "Report statistics: ": "Statistiken berichten? ", + "Registration enabled: ": "Registrierung aktiviert: ", + "Report statistics: ": "Statistiken berichten: ", "Save preferences": "Einstellungen speichern", "Subscription manager": "Abonnementverwaltung", - "Token manager": "Tokenverwalter", + "Token manager": "Tokenverwaltung", "Token": "Token", "Import/export": "Importieren/Exportieren", "unsubscribe": "abbestellen", @@ -122,20 +120,20 @@ "Log out": "Abmelden", "Released under the AGPLv3 on Github.": "Auf GitHub unter der AGPLv3 Lizenz veröffentlicht.", "Source available here.": "Quellcode verfügbar hier.", - "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.", + "View JavaScript license information.": "Javascript-Lizenzinformationen anzeigen.", "View privacy policy.": "Datenschutzerklärung einsehen.", "Trending": "Angesagt", "Public": "Öffentlich", - "Unlisted": "Nicht aufgeführt", + "Unlisted": "Nicht gelistet", "Private": "Privat", "View all playlists": "Alle Wiedergabelisten anzeigen", - "Updated `x` ago": "Aktualisiert `x` vor", - "Delete playlist `x`?": "Wiedergabeliste löschen `x`?", + "Updated `x` ago": "Aktualisiert vor `x`", + "Delete playlist `x`?": "Wiedergabeliste `x` löschen?", "Delete playlist": "Wiedergabeliste löschen", "Create playlist": "Wiedergabeliste erstellen", "Title": "Titel", - "Playlist privacy": "Vertrauliche Wiedergabeliste", - "Editing playlist `x`": "Wiedergabeliste bearbeiten `x`", + "Playlist privacy": "Wiedergabelisten-Privatsphäre", + "Editing playlist `x`": "Wiedergabeliste `x` bearbeiten", "Show more": "Mehr anzeigen", "Show less": "Weniger anzeigen", "Watch on YouTube": "Video auf YouTube ansehen", @@ -151,12 +149,12 @@ "Blacklisted regions: ": "Unerlaubte Regionen: ", "Shared `x`": "Geteilt `x`", "Premieres in `x`": "Premiere in `x`", - "Premieres `x`": "Erster Start `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.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.", + "Premieres `x`": "Premiere `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.": "Hallo! Anscheinend hast du JavaScript deaktiviert. Klicke hier, um Kommentare anzuzeigen, beachte, dass es etwas länger dauern kann, um sie zu laden.", "View YouTube comments": "YouTube Kommentare anzeigen", "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen", "View `x` comments": { - "([^.,0-9]|^)1([^.,0-9]|$)": "`x` Kommentare anzeigen", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` Kommentar anzeigen", "": "`x` Kommentare anzeigen" }, "View Reddit comments": "Reddit Kommentare anzeigen", @@ -184,7 +182,7 @@ "Empty playlist": "Wiedergabeliste ist leer", "Not a playlist.": "Ungültige Wiedergabeliste.", "Playlist does not exist.": "Wiedergabeliste existiert nicht.", - "Could not pull trending pages.": "Trendenz-Seiten konnten nicht geladen werden.", + "Could not pull trending pages.": "Beliebt-Seiten konnten nicht geladen werden.", "Hidden field \"challenge\" is a required field": "Verstecktes Feld „challenge“ ist eine erforderliche Eingabe", "Hidden field \"token\" is a required field": "Verstecktes Feld „token“ ist eine erforderliche Eingabe", "Erroneous challenge": "Ungültiger Test", @@ -192,7 +190,7 @@ "No such user": "Ungültiger Benutzer", "Token is expired, please try again": "Token ist abgelaufen, bitte erneut versuchen", "English": "Englisch", - "English (auto-generated)": "Englisch (automatisch erzeugt)", + "English (auto-generated)": "Englisch (automatisch generiert)", "Afrikaans": "Afrikaans", "Albanian": "Albanisch", "Amharic": "Amharisch", @@ -313,7 +311,7 @@ "Download": "Herunterladen", "Download as: ": "Herunterladen als: ", "%A %B %-d, %Y": "%A %-d %B %Y", - "(edited)": "(editiert)", + "(edited)": "(bearbeitet)", "YouTube comment permalink": "YouTube-Kommentar Permalink", "permalink": "Permalink", "`x` marked it with a ❤": "`x` markierte es mit einem ❤", @@ -321,7 +319,7 @@ "Video mode": "Videomodus", "channel_tab_videos_label": "Videos", "Playlists": "Wiedergabelisten", - "channel_tab_community_label": "Gemeinschaft", + "channel_tab_community_label": "Community", "search_filters_sort_option_relevance": "Relevanz", "search_filters_sort_option_rating": "Bewertung", "search_filters_sort_option_date": "Hochladedatum", @@ -329,7 +327,7 @@ "search_filters_type_label": "Inhaltstyp", "search_filters_duration_label": "Dauer", "search_filters_features_label": "Eigenschaften", - "search_filters_sort_label": "sortieren", + "search_filters_sort_label": "Sortieren nach", "search_filters_date_option_hour": "Letzte Stunde", "search_filters_date_option_today": "Heute", "search_filters_date_option_week": "Diese Woche", @@ -341,7 +339,7 @@ "search_filters_type_option_movie": "Film", "search_filters_type_option_show": "Anzeigen", "search_filters_features_option_hd": "HD", - "search_filters_features_option_subtitles": "Untertitel / CC", + "search_filters_features_option_subtitles": "Untertitel/CC", "search_filters_features_option_c_commons": "Creative Commons", "search_filters_features_option_three_d": "3D", "search_filters_features_option_live": "Live", @@ -358,7 +356,7 @@ "footer_modfied_source_code": "Modifizierter Quellcode", "footer_documentation": "Dokumentation", "footer_source_code": "Quellcode", - "adminprefs_modified_source_code_url_label": "URL zum Repositorie des modifizierten Quellcodes", + "adminprefs_modified_source_code_url_label": "URL zum Repository des modifizierten Quellcodes", "search_filters_duration_option_short": "Kurz (< 4 Minuten)", "preferences_region_label": "Land der Inhalte: ", "preferences_quality_option_dash": "DASH (adaptive Qualität)", @@ -397,7 +395,7 @@ "generic_videos_count_plural": "{{count}} Videos", "subscriptions_unseen_notifs_count": "{{count}} ungesehene Benachrichtung", "subscriptions_unseen_notifs_count_plural": "{{count}} ungesehene Benachrichtungen", - "crash_page_refresh": "Versucht haben, die Seite neu zu laden", + "crash_page_refresh": "Versucht hast, die Seite neu zu laden", "comments_view_x_replies": "{{count}} Antwort anzeigen", "comments_view_x_replies_plural": "{{count}} Antworten anzeigen", "generic_count_years": "{{count}} Jahr", @@ -406,15 +404,15 @@ "generic_count_weeks_plural": "{{count}} Wochen", "generic_count_days": "{{count}} Tag", "generic_count_days_plural": "{{count}} Tage", - "crash_page_before_reporting": "Bevor Sie einen Bug melden, stellen Sie sicher, dass Sie:", - "crash_page_switch_instance": "Eine andere Instanz versucht haben", + "crash_page_before_reporting": "Bevor du einen Bug meldest, stelle sicher, dass du:", + "crash_page_switch_instance": "Eine andere Instanz versucht hast", "generic_count_hours": "{{count}} Stunde", "generic_count_hours_plural": "{{count}} Stunden", "generic_count_minutes": "{{count}} Minute", "generic_count_minutes_plural": "{{count}} Minuten", - "crash_page_read_the_faq": "Das FAQ gelesen haben", - "crash_page_search_issue": "Nach bereits gemeldeten Bugs auf GitHub gesucht haben", - "crash_page_report_issue": "Wenn all dies nicht geholfen hat, öffnen Sie bitte ein neues Problem (issue) auf Github (vorzugsweise auf Englisch) und fügen Sie den folgenden Text in Ihre Nachricht ein (bitte übersetzen Sie diesen Text NICHT):", + "crash_page_read_the_faq": "Das FAQ gelesen hast", + "crash_page_search_issue": "Nach bereits gemeldeten Bugs auf GitHub gesucht hast", + "crash_page_report_issue": "Wenn all dies nicht geholfen hat, öffne bitte ein neues Problem (issue) auf GitHub (vorzugsweise auf Englisch) und füge den folgenden Text in deine Nachricht ein (bitte übersetze diesen Text NICHT):", "generic_views_count": "{{count}} Aufruf", "generic_views_count_plural": "{{count}} Aufrufe", "generic_count_seconds": "{{count}} Sekunde", @@ -425,7 +423,7 @@ "tokens_count_plural": "{{count}} Tokens", "comments_points_count": "{{count}} Punkt", "comments_points_count_plural": "{{count}} Punkte", - "crash_page_you_found_a_bug": "Anscheinend haben Sie einen Fehler in Invidious gefunden!", + "crash_page_you_found_a_bug": "Anscheinend hast du einen Fehler in Invidious gefunden!", "generic_count_months": "{{count}} Monat", "generic_count_months_plural": "{{count}} Monaten", "Cantonese (Hong Kong)": "Kantonesisch (Hong Kong)", @@ -455,8 +453,8 @@ "Korean (auto-generated)": "Koreanisch (automatisch generiert)", "Portuguese (auto-generated)": "Portugiesisch (automatisch generiert)", "search_filters_title": "Filtern", - "search_message_change_filters_or_query": "Versuchen Sie, Ihre Suchanfrage zu erweitern und/oder die Filter zu ändern.", - "search_message_use_another_instance": "Sie können auch auf einer anderen Instanz suchen.", + "search_message_change_filters_or_query": "Versuche, deine Suchanfrage zu erweitern und/oder die Filter zu ändern.", + "search_message_use_another_instance": "Du kannst auch auf einer anderen Instanz suchen.", "Popular enabled: ": "„Beliebt“-Seite aktiviert: ", "search_message_no_results": "Keine Ergebnisse gefunden.", "search_filters_duration_option_medium": "Mittel (4 - 20 Minuten)", @@ -466,7 +464,7 @@ "search_filters_duration_option_none": "Beliebige Länge", "search_filters_date_label": "Upload-Datum", "search_filters_date_option_none": "Beliebiges Datum", - "error_video_not_in_playlist": "Das angeforderte Video existiert nicht in dieser Wiedergabeliste. Klicken Sie hier, um zur Startseite der Wiedergabeliste zu gelangen.", + "error_video_not_in_playlist": "Das angeforderte Video existiert nicht in dieser Wiedergabeliste. Klicke hier, um zur Startseite der Wiedergabeliste zu gelangen.", "channel_tab_shorts_label": "Shorts", "channel_tab_streams_label": "Livestreams", "Music in this video": "Musik in diesem Video", @@ -501,5 +499,8 @@ "carousel_skip": "Galerie überspringen", "Filipino (auto-generated)": "Philippinisch (automatisch generiert)", "channel_tab_courses_label": "Kurse", - "channel_tab_posts_label": "Beiträge" + "channel_tab_posts_label": "Beiträge", + "timeline_parse_error_show_technical_details": "Technische Details anzeigen", + "timeline_parse_error_placeholder_heading": "Element kann nicht geparsed werden", + "timeline_parse_error_placeholder_message": "Invidious ist beim Parsen dieses Elements auf einen Fehler gestossen. Für weitere Informationen siehe unten:" } From 0ae262c3969ad84d51581e0f231f928af440d165 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:23 +0200 Subject: [PATCH 061/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/da.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/da.json b/locales/da.json index 9cbb446a..4b2834ef 100644 --- a/locales/da.json +++ b/locales/da.json @@ -39,8 +39,6 @@ "User ID": "Bruger ID", "Password": "Kodeord", "Time (h:mm:ss):": "Tid (t:mm:ss):", - "Text CAPTCHA": "Tekst CAPTCHA", - "Image CAPTCHA": "Billede CAPTCHA", "Sign In": "Log ind", "Register": "Registrer", "E-mail": "E-mail", From eee9d8441cc8f43ec1b2ab8ee48c0f5303b0097a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:34 +0200 Subject: [PATCH 062/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/el.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/el.json b/locales/el.json index e5a89a44..396400a0 100644 --- a/locales/el.json +++ b/locales/el.json @@ -39,8 +39,6 @@ "User ID": "Ταυτότητα χρήστη", "Password": "Κωδικός πρόσβασης", "Time (h:mm:ss):": "Ώρα (ω:λλ:δδ):", - "Text CAPTCHA": "Κείμενο CAPTCHA", - "Image CAPTCHA": "Εικόνα CAPTCHA", "Sign In": "Εγγραφή", "Register": "Εγγραφή", "E-mail": "Ηλεκτρονικό ταχυδρομείο", From 5d7a60ba3896c0832bccfe4d14208afa0da7d1f1 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:42 +0200 Subject: [PATCH 063/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/eo.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/eo.json b/locales/eo.json index 7276c890..27f694e6 100644 --- a/locales/eo.json +++ b/locales/eo.json @@ -39,8 +39,6 @@ "User ID": "Uzula identigilo", "Password": "Pasvorto", "Time (h:mm:ss):": "Horo (h:mm:ss):", - "Text CAPTCHA": "Teksta CAPTCHA", - "Image CAPTCHA": "Bilda CAPTCHA", "Sign In": "Ensaluti", "Register": "Registriĝi", "E-mail": "Retpoŝto", From f6d29204793699a39af28b4e4305aa529a58a56c Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:02:50 +0200 Subject: [PATCH 064/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/eu.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/eu.json b/locales/eu.json index fbca537b..0138768b 100644 --- a/locales/eu.json +++ b/locales/eu.json @@ -38,8 +38,6 @@ "User ID": "Erabiltzaile IDa", "Password": "Pasahitza", "Time (h:mm:ss):": "Denbora (h:mm:ss):", - "Text CAPTCHA": "CAPTCHA testua", - "Image CAPTCHA": "CAPTCHA irudia", "Sign In": "Hasi saioa", "Register": "Eman izena", "E-mail": "E-posta", From d68d01315a234f51c5e453844fd52b28cf50ae13 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:03:06 +0200 Subject: [PATCH 065/108] Update Estonian translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Estonian translation Update Estonian translation Update Estonian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Priit Jõerüüt Co-authored-by: Priit Jõerüüt Co-authored-by: kovabait12 Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/et.json | 448 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 312 insertions(+), 136 deletions(-) diff --git a/locales/et.json b/locales/et.json index 7f652810..1e5720ae 100644 --- a/locales/et.json +++ b/locales/et.json @@ -5,7 +5,7 @@ "View channel on YouTube": "Vaata kanalit YouTube'is", "Log in": "Logi sisse", "Log in/register": "Logi sisse/registreeru", - "Dark mode: ": "Tume režiim: ", + "Dark mode: ": "Tume kujundus: ", "generic_videos_count": "{{count}} video", "generic_videos_count_plural": "{{count}} videot", "generic_subscribers_count": "{{count}} tellija", @@ -22,12 +22,12 @@ "last": "viimane", "Next page": "Järgmine leht", "Previous page": "Eelmine leht", - "Clear watch history?": "Kustuta vaatamiste ajalugu?", + "Clear watch history?": "Kas kustutame vaatamiste ajaloo?", "New password": "Uus salasõna", "New passwords must match": "Uued salasõnad peavad ühtima", "Import and Export Data": "Impordi ja ekspordi andmed", "Import": "Impordi", - "Import YouTube subscriptions": "Impordi tellimused Youtube'ist/OPML-ist", + "Import YouTube subscriptions": "Impordi CSV või OPML-vormingus Youtube'i tellimused", "Import FreeTube subscriptions (.db)": "Impordi tellimused FreeTube'ist (.db)", "Import NewPipe data (.zip)": "Impordi NewPipe'i andmed (.zip)", "Export": "Ekspordi", @@ -37,11 +37,9 @@ "History": "Ajalugu", "JavaScript license information": "JavaScripti litsentsi info", "source": "allikas", - "User ID": "Kasutada ID", + "User ID": "Kasutajatunnus", "Password": "Salasõna", "Time (h:mm:ss):": "Aeg (h:mm:ss):", - "Text CAPTCHA": "CAPTCHA-tekst", - "Image CAPTCHA": "CAPTCHA-foto", "Sign In": "Logi sisse", "Register": "Registreeru", "E-mail": "E-post", @@ -57,48 +55,48 @@ "preferences_quality_dash_option_auto": "Automaatne", "preferences_quality_dash_option_best": "Parim", "preferences_quality_dash_option_worst": "Halvim", - "preferences_volume_label": "Video helitugevus: ", + "preferences_volume_label": "Video helivaljus: ", "youtube": "YouTube", "reddit": "Reddit", - "preferences_related_videos_label": "Näita sarnaseid videosid: ", + "preferences_related_videos_label": "Näita sarnaseid videoid: ", "preferences_vr_mode_label": "Interaktiivne 360-kraadine video (vajalik WebGL): ", - "preferences_dark_mode_label": "Teema: ", + "preferences_dark_mode_label": "Kujundus: ", "dark": "tume", "light": "hele", - "preferences_category_subscription": "Tellimuse seaded", + "preferences_category_subscription": "Tellimuse eelistused", "preferences_max_results_label": "Avalehel näidatavate videote arv: ", "preferences_sort_label": "Sorteeri: ", "published": "avaldatud", "alphabetically": "tähestikulises järjekorras", "alphabetically - reverse": "vastupidi tähestikulises järjekorras", "channel name": "kanali nimi", - "preferences_unseen_only_label": "Näita ainult vaatamata videosid: ", + "preferences_unseen_only_label": "Näita ainult vaatamata videoid: ", "Only show latest video from channel: ": "Näita ainult viimast videot: ", "preferences_notifications_only_label": "Näita ainult teavitusi (kui neid on): ", "Enable web notifications": "Luba veebiteavitused", "`x` uploaded a video": "`x` laadis video üles", "`x` is live": "`x` teeb otseülekannet", "preferences_category_data": "Andme-eelistused", - "Clear watch history": "Puhasta vaatamisajalugu", + "Clear watch history": "Kustuta vaatamisajalugu", "Import/export data": "Impordi/ekspordi andmed", "Change password": "Muuda salasõna", "Watch history": "Vaatamisajalugu", "Delete account": "Kustuta kasutaja", "Save preferences": "Salvesta eelistused", - "Token": "Token", + "Token": "Tunnusluba", "Import/export": "Imprort/eksport", "unsubscribe": "loobu tellimusest", "Subscriptions": "Tellimused", "search": "otsi", - "Source available here.": "Allikas on kättesaadaval siin.", - "View privacy policy.": "Vaata privaatsuspoliitikat.", + "Source available here.": "Lähtekood on kättesaadaval siin.", + "View privacy policy.": "Vaata andmekaitsepõhimõtteid.", "Public": "Avalik", "Private": "Privaatne", "View all playlists": "Vaata kõiki esitusloendeid", "Updated `x` ago": "Uuendas `x` tagasi", "Delete playlist `x`?": "Kustuta esitusloend `x`?", "Delete playlist": "Kustuta esitusloend", - "Create playlist": "Loo esitlusloend", + "Create playlist": "Koosta esitlusloend", "Title": "Pealkiri", "Playlist privacy": "Esitusloendi privaatsus", "Show more": "Näita rohkem", @@ -117,14 +115,14 @@ "Show replies": "Näita vastuseid", "Incorrect password": "Vale salasõna", "Wrong answer": "Vale vastus", - "User ID is a required field": "Kasutaja ID on kohustuslik väli", + "User ID is a required field": "Kasutajatunnus on kohustuslik väli", "Password is a required field": "Salasõna on kohustuslik väli", "Wrong username or password": "Vale kasutajanimi või salasõna", "Password cannot be longer than 55 characters": "Salasõna ei tohi olla pikem kui 55 tähemärki", "Password cannot be empty": "Salasõna ei tohi olla tühi", - "Please log in": "Palun logige sisse", + "Please log in": "Palun logi sisse", "channel:`x`": "kanal:`x`", - "Deleted or invalid channel": "Kanal on kustutatud või seda ei leitud", + "Deleted or invalid channel": "Kanal on kustutatud või seda ei leidu", "This channel does not exist.": "Sellist kanalit pole olemas.", "comments_view_x_replies": "{{count}} vastus", "comments_view_x_replies_plural": "{{count}} vastust", @@ -134,86 +132,86 @@ "Not a playlist.": "Tegu pole esitusloendiga.", "Playlist does not exist.": "Seda esitusloendit pole olemas.", "No such user": "Sellist kasutajat pole", - "English": "Inglise", - "English (United Kingdom)": "Inglise (Suurbritannia)", - "English (United States)": "Inglise (USA)", - "English (auto-generated)": "Inglise (automaatselt koostatud)", - "Afrikaans": "Afrikaani", - "Albanian": "Albaania", - "Arabic": "Araabia", - "Armenian": "Armeenia", - "Bangla": "Bengali", - "Basque": "Baski", - "Belarusian": "Valgevene", - "Bulgarian": "Bulgaaria", - "Burmese": "Birma", - "Cantonese (Hong Kong)": "Kantoni (Hong Konk)", - "Chinese (China)": "Hiina (Hiina)", - "Chinese (Hong Kong)": "Hiina (Hong Kong)", - "Chinese (Simplified)": "Hiina (lihtsustatud)", - "Chinese (Taiwan)": "Hiina (Taiwan)", - "Croatian": "Horvaatia", - "Czech": "Tšehhi", - "Danish": "Taani", - "Dutch": "Hollandi", - "Esperanto": "Esperanto", - "Estonian": "Eesti", - "Filipino": "Filipiini", - "Finnish": "Soome", - "French": "Prantsuse", - "French (auto-generated)": "Prantsuse (automaatne)", - "Dutch (auto-generated)": "Hollandi (automaatne)", - "Galician": "Kaliitsia", - "Georgian": "Gruusia", - "Haitian Creole": "Haiti kreool", - "Hausa": "Hausa", - "Hawaiian": "Havaii", - "Hebrew": "Heebrea", - "Hindi": "Hindi", - "Hungarian": "Ungari", - "Icelandic": "Islandi", - "Indonesian": "Indoneesia", - "Japanese (auto-generated)": "Jaapani (automaatne)", - "Kannada": "Kannada", - "Kazakh": "Kasahhi", - "Luxembourgish": "Luksemburgi", - "Macedonian": "Makedoonia", - "Malay": "Malai", - "Maltese": "Malta", - "Maori": "Maori", - "Marathi": "Marathi", - "Mongolian": "Mongoli", - "Nepali": "Nepaali", - "Norwegian Bokmål": "Norra (Bokmål)", - "Persian": "Pärsia", - "Polish": "Poola", - "Portuguese": "Portugali", - "Portuguese (auto-generated)": "Portugali (automaatne)", - "Portuguese (Brazil)": "Portugali (Brasiilia)", - "Romanian": "Rumeenia", - "Russian": "Vene", - "Russian (auto-generated)": "Vene (automaatne)", - "Scottish Gaelic": "Šoti (Gaeli)", - "Serbian": "Serbia", - "Slovak": "Slovaki", - "Slovenian": "Sloveeni", - "Somali": "Somaali", - "Spanish": "Hispaania", - "Spanish (auto-generated)": "Hispaania (automaatne)", - "Spanish (Latin America)": "Hispaania (Ladina-Ameerika)", - "Spanish (Mexico)": "Hispaania (Mehhiko)", - "Spanish (Spain)": "Hispaania (Hispaania)", - "Swahili": "Suahili", - "Swedish": "Rootsi", - "Tajik": "Tadžiki", - "Tamil": "Tamiili", - "Thai": "Tai", - "Turkish": "Türgi", - "Turkish (auto-generated)": "Türgi (automaatne)", - "Ukrainian": "Ukraina", - "Uzbek": "Usbeki", - "Vietnamese": "Vietnami", - "Vietnamese (auto-generated)": "Vietnami (automaatne)", + "English": "inglise", + "English (United Kingdom)": "inglise (Suurbritannia)", + "English (United States)": "inglise (USA)", + "English (auto-generated)": "inglise (automaatselt koostatud)", + "Afrikaans": "afrikaani", + "Albanian": "albaania", + "Arabic": "araabia", + "Armenian": "armeenia", + "Bangla": "bengali", + "Basque": "baski", + "Belarusian": "valgevene", + "Bulgarian": "bulgaaria", + "Burmese": "birma", + "Cantonese (Hong Kong)": "kantoni (Hongkong)", + "Chinese (China)": "hiina (Hiina)", + "Chinese (Hong Kong)": "hiina (Hongkong)", + "Chinese (Simplified)": "hiina (lihtsustatud)", + "Chinese (Taiwan)": "hiina (Taiwan)", + "Croatian": "horvaadi", + "Czech": "tšehhi", + "Danish": "taani", + "Dutch": "hollandi", + "Esperanto": "esperanto", + "Estonian": "eesti", + "Filipino": "filipiini", + "Finnish": "soome", + "French": "prantsuse", + "French (auto-generated)": "prantsuse (automaatselt koostatud)", + "Dutch (auto-generated)": "hollandi (automaatne)", + "Galician": "galeegi", + "Georgian": "gruusia", + "Haitian Creole": "haiti kreooli", + "Hausa": "hausa", + "Hawaiian": "havaii", + "Hebrew": "heebrea", + "Hindi": "hindi", + "Hungarian": "ungari", + "Icelandic": "islandi", + "Indonesian": "indoneesia", + "Japanese (auto-generated)": "jaapani (automaatselt koostatud)", + "Kannada": "kannada", + "Kazakh": "kasahhi", + "Luxembourgish": "letseburgi", + "Macedonian": "makedoonia", + "Malay": "malai", + "Maltese": "malta", + "Maori": "maoori", + "Marathi": "marathi", + "Mongolian": "mongoli", + "Nepali": "nepaali", + "Norwegian Bokmål": "norra (Bokmål)", + "Persian": "pärsia", + "Polish": "poola", + "Portuguese": "portugali", + "Portuguese (auto-generated)": "portugali (automaatne)", + "Portuguese (Brazil)": "portugali (Brasiilia)", + "Romanian": "rumeenia", + "Russian": "vene", + "Russian (auto-generated)": "vene (automaatne)", + "Scottish Gaelic": "gaeli", + "Serbian": "serbia", + "Slovak": "slovaki", + "Slovenian": "sloveeni", + "Somali": "somaali", + "Spanish": "hispaania", + "Spanish (auto-generated)": "hispaania (automaatne)", + "Spanish (Latin America)": "hispaania (Ladina-Ameerika)", + "Spanish (Mexico)": "hispaania (Mehhiko)", + "Spanish (Spain)": "hispaania (Hispaania)", + "Swahili": "suahiili", + "Swedish": "rootsi", + "Tajik": "tadžiki", + "Tamil": "tamili", + "Thai": "tai", + "Turkish": "türgi", + "Turkish (auto-generated)": "türgi (automaatne)", + "Ukrainian": "ukraina", + "Uzbek": "usbeki", + "Vietnamese": "vietnami", + "Vietnamese (auto-generated)": "vietnami (automaatne)", "generic_count_years": "{{count}} aasta", "generic_count_years_plural": "{{count}} aastat", "generic_count_months": "{{count}} kuu", @@ -228,15 +226,15 @@ "generic_count_minutes_plural": "{{count}} minutit", "Popular": "Populaarne", "Search": "Otsi", - "Top": "Top", - "About": "Leheküljest", + "Top": "Parimad", + "About": "Saidi teave", "preferences_locale_label": "Keel: ", "View as playlist": "Vaata esitusloendina", "Movies": "Filmid", - "Download as: ": "Laadi kui: ", + "Download as: ": "Laadi alla kui: ", "(edited)": "(muudetud)", "`x` marked it with a ❤": "`x` märkis ❤", - "Audio mode": "Audiorežiim", + "Audio mode": "Helirežiim", "Video mode": "Videorežiim", "search_filters_date_label": "Üleslaadimise kuupäev", "search_filters_date_option_none": "Ükskõik mis kuupäev", @@ -246,10 +244,10 @@ "search_filters_date_option_month": "Sel kuul", "search_filters_date_option_year": "Sel aastal", "search_filters_type_label": "Tüüp", - "search_filters_type_option_all": "Ükskõik mis tüüp", + "search_filters_type_option_all": "Ükskõik mis tüüpi", "search_filters_duration_label": "Kestus", "search_filters_type_option_show": "Näita", - "search_filters_duration_option_none": "Ükskõik mis kestus", + "search_filters_duration_option_none": "Ükskõik mis kestusega", "search_filters_duration_option_short": "Lühike (alla 4 minuti)", "search_filters_duration_option_medium": "Keskmine (4 - 20 minutit)", "search_filters_duration_option_long": "Pikk (üle 20 minuti)", @@ -258,9 +256,9 @@ "search_filters_features_option_hd": "HD", "search_filters_features_option_subtitles": "Subtiitrid", "search_filters_features_option_location": "Asukoht", - "search_filters_sort_label": "Sorteeri", + "search_filters_sort_label": "Järjestus", "search_filters_sort_option_views": "Vaatamiste arv", - "next_steps_error_message": "Pärast mida võiksite proovida: ", + "next_steps_error_message": "Pärast seda võiksid proovida: ", "videoinfo_started_streaming_x_ago": "Alustas otseülekannet `x` tagasi", "Yes": "Jah", "generic_views_count": "{{count}} vaatamine", @@ -270,48 +268,48 @@ "preferences_region_label": "Riik: ", "View YouTube comments": "Vaata YouTube'i kommentaare", "preferences_extend_desc_label": "Ava video kirjeldus automaatselt: ", - "German (auto-generated)": "Saksa (automaatne)", - "Italian": "Itaalia", - "preferences_player_style_label": "Mängija stiil: ", + "German (auto-generated)": "saksa (automaatselt koostatud)", + "Italian": "itaalia", + "preferences_player_style_label": "Meediaesitaja stiil: ", "subscriptions_unseen_notifs_count": "{{count}} lugemata teavitus", "subscriptions_unseen_notifs_count_plural": "{{count}} lugemata teavitust", "View more comments on Reddit": "Vaata teisi kommentaare Redditis", "Only show latest unwatched video from channel: ": "Näita ainult viimast vaatamata videot: ", - "tokens_count": "{{count}} token", - "tokens_count_plural": "{{count}} tokenit", + "tokens_count": "{{count}} tunnusluba", + "tokens_count_plural": "{{count}} tunnusluba", "Log out": "Logi välja", "Premieres `x`": "Linastub`x`", "View `x` comments": { "([^.,0-9]|^)1([^.,0-9]|$)": "Vaata `x` kommentaari", "": "Vaata `x` kommentaare" }, - "Khmer": "Khmeeri", - "Bosnian": "Bosnia", - "Corsican": "Korsika", - "Javanese": "Jaava", - "Lithuanian": "Leedu", + "Khmer": "khmeeri", + "Bosnian": "bosnia", + "Corsican": "korsika", + "Javanese": "jaava", + "Lithuanian": "leedu", "channel_tab_videos_label": "Videod", "channel_tab_community_label": "Kogukond", - "CAPTCHA is a required field": "CAPTCHA on kohustuslik väli", + "CAPTCHA is a required field": "Robotilõks on kohustuslik väli", "comments_points_count": "{{count}} punkt", "comments_points_count_plural": "{{count}} punkti", - "Chinese": "Hiina", - "German": "Saksa", - "Indonesian (auto-generated)": "Indoneesia (automaatne)", - "Italian (auto-generated)": "Itaalia (automaatne)", - "Kyrgyz": "Kirkiisi", - "Latin": "Ladina", + "Chinese": "hiina", + "German": "saksa", + "Indonesian (auto-generated)": "indoneesia (automaatselt koostatud)", + "Italian (auto-generated)": "itaalia (automaatselt koostatud)", + "Kyrgyz": "kirgiisi", + "Latin": "ladina", "generic_count_seconds": "{{count}} sekund", "generic_count_seconds_plural": "{{count}} sekundit", - "Catalan": "Katalaani", - "Chinese (Traditional)": "Hiina (traditsiooniline)", - "Greek": "Kreeka", - "Kurdish": "Kurdi", - "Latvian": "Läti", - "Irish": "Iiri", - "Korean": "Korea", - "Japanese": "Jaapani", - "Korean (auto-generated)": "Korea (automaatne)", + "Catalan": "katalaani", + "Chinese (Traditional)": "hiina (traditsiooniline)", + "Greek": "kreeka", + "Kurdish": "kurdi", + "Latvian": "läti", + "Irish": "iiri", + "Korean": "korea", + "Japanese": "jaapani", + "Korean (auto-generated)": "korea (automaatselt koostatud)", "Music": "Muusika", "Playlists": "Esitusloendid", "search_filters_type_option_video": "Video", @@ -325,8 +323,186 @@ "search_filters_type_option_channel": "Kanal", "search_filters_type_option_playlist": "Esitusloend", "search_filters_type_option_movie": "Film", - "next_steps_error_message_go_to_youtube": "Minna YouTube'i", - "next_steps_error_message_refresh": "Laadida uuesti", + "next_steps_error_message_go_to_youtube": "Mine YouTube'i", + "next_steps_error_message_refresh": "Laadi uuesti", "footer_donate_page": "Anneta", - "videoinfo_watch_on_youTube": "Vaata YouTube'is" + "videoinfo_watch_on_youTube": "Vaata YouTube'is", + "Authorize token for `x`?": "Kas volitad tunnusloa kasutamise `x`-le?", + "Export data as JSON": "Expordi Invidious andmed JSON-ina", + "Import Invidious data": "Impordi Invidious JSON andmed", + "preferences_local_label": "Edasta videod vaheserveri kaudu: ", + "Music in this video": "Muusika selles videos", + "Token manager": "Tunnuslubade haldur", + "search_message_use_another_instance": "Võid ka otsida teisest serverist.", + "Standard YouTube license": "Tavaline Youtube'i litsens", + "Song: ": "Lugu: ", + "Add to playlist": "Lisa esitlusloendisse", + "Add to playlist: ": "Lisa esitlusloendisse: ", + "Search for videos": "Otsi videoid", + "The Popular feed has been disabled by the administrator.": "Administraator on populaarse voo välja lülitanud.", + "preferences_quality_dash_option_2160p": "2160p", + "generic_button_rss": "RSS uudisvoog", + "Import YouTube watch history (.json)": "Impordi Youtube vaatamiste ajalugu (.json)", + "published - reverse": "avaldatud - vastupidine", + "preferences_default_home_label": "Vaikimisi koduleht: ", + "preferences_feed_menu_label": "Voogude menüü: ", + "Login enabled: ": "Sisselogimine lubatud: ", + "Registration enabled: ": "Registreerimine lubatud: ", + "CAPTCHA enabled: ": "Robotilõks on kasutusel: ", + "Blacklisted regions: ": "Mustas nimekirjas piirkonnad: ", + "Wilson score: ": "Wilsoni skoor: ", + "generic_button_delete": "Kustuta", + "generic_button_edit": "Muuda", + "generic_button_save": "Salvesta", + "generic_button_cancel": "Tühista", + "Import YouTube playlist (.csv)": "Impordi Youtube esitlusloend (.csv)", + "preferences_category_misc": "Muud seadistused", + "preferences_annotations_subscribed_label": "Kas vaikimisi näitame tellitud kanalite sisukokkuvõtteid?: ", + "preferences_quality_dash_option_480p": "480p", + "preferences_continue_label": "Vaikimisi mängi järgmine video: ", + "View JavaScript license information.": "Vaata JavaScripti litsensiteavet.", + "preferences_listen_label": "Kuula vaikimisi: ", + "preferences_quality_dash_option_1080p": "1080p", + "Erroneous CAPTCHA": "Vigane robotilõks", + "Hidden field \"challenge\" is a required field": "Peidetud väli \"väljakutse\" on kohustuslik väli", + "Fallback captions: ": "Tagavara subtiitrid: ", + "preferences_category_admin": "Administraatori seadistused", + "preferences_automatic_instance_redirect_label": "Automaatne serveri ümbersuunamine (varuvariandile redirect.invidious.io): ", + "channel name - reverse": "kanali nimi - vastupidine", + "An alternative front-end to YouTube": "Alternatiivne Youtube esiliides", + "Subscription manager": "Tellimuste haldur", + "Redirect homepage to feed: ": "Suuna koduleht voole: ", + "Azerbaijani": "aserbaidžaani", + "Gujarati": "gudžarati", + "generic_channels_count": "{{count}} kanal", + "generic_channels_count_plural": "{{count}} kanalit", + "preferences_video_loop_label": "Alati korda: ", + "preferences_watch_history_label": "Lülita vaatamiste ajalugu sisse: ", + "preferences_speed_label": "Vaikimisi kiirus: ", + "preferences_quality_dash_option_4320p": "4320p", + "preferences_quality_dash_option_1440p": "1440p", + "preferences_quality_dash_option_720p": "720p", + "preferences_quality_dash_option_360p": "360p", + "preferences_quality_dash_option_240p": "240p", + "preferences_captions_label": "Vaikimisi subtiitrid: ", + "preferences_annotations_label": "Vaikimisi näita sisukokkuvõtteid: ", + "preferences_thin_mode_label": "Napp režiim: ", + "Manage subscriptions": "Halda tellimusi", + "Manage tokens": "Halda tunnuslube", + "preferences_show_nick_label": "Näita üleval hüüdnime ", + "revoke": "võta tagasi", + "Released under the AGPLv3 on Github.": "Avaldatud GitHubis AGPLv3 litsentsi alusel.", + "Trending": "Trendikas", + "Unlisted": "Ajajooneväline", + "Switch Invidious Instance": "Vaheta Invidiouse Serverit", + "Whitelisted regions: ": "Valges nimekirjas piirkonnad: ", + "Artist: ": "Esitaja: ", + "Could not fetch comments": "Kommentaaride laadimine ei õnnestunud", + "Album: ": "Album: ", + "Invidious Private Feed for `x`": "Invidiouse privaatne Voog `x`-ile", + "Could not pull trending pages.": "Ei saanud alla laadida trendikaid lehti.", + "Hidden field \"token\" is a required field": "Peidetud väli \"tunnusluba\" on kohustuslik väli", + "Erroneous challenge": "Ekslik väljakutse", + "Erroneous token": "Ekslik tunnusluba", + "Token is expired, please try again": "Tunnusluba on aegunud, palun proovi uuesti", + "Amharic": "amhari", + "Cebuano": "sebu", + "preferences_autoplay_label": "Automaatesitus: ", + "invidious": "Invidious", + "preferences_quality_dash_option_144p": "144p", + "Popular enabled: ": "Populaarsed videod on kasutusel: ", + "Top enabled: ": "Ülariba lubatud: ", + "Editing playlist `x`": "Esitlusloendi `x` muutmine", + "Show annotations": "Näita sisukokkuvõtteid", + "Hide annotations": "Peida sisukokkuvõtted", + "Could not create mix.": "Ei saanud miksi luua.", + "Authorize token?": "Kas volitad tunnusloa kasutamise?", + "playlist_button_add_items": "Lisa videoid", + "First page": "Esimene leht", + "preferences_preload_label": "Eellaadi videoandmed: ", + "preferences_category_visual": "Visuaalsed seadistused", + "preferences_comments_label": "Vaikimisi kommentaarid: ", + "Filipino (auto-generated)": "filipiini (automaatselt koostatud)", + "Could not get channel info.": "Kanali info tuvastamine ei õnnestunud.", + "Answer": "Vastus", + "Report statistics: ": "Teavita statistikast: ", + "Hmong": "hmongi", + "Igbo": "igbo", + "Interlingue": "interlingue", + "Lao": "lao", + "Malagasy": "malagassi", + "Malayalam": "malajalami", + "Pashto": "puštu", + "Nyanja": "njandža", + "Punjabi": "pandžabi", + "Samoan": "samoa", + "Shona": "šona", + "Sindhi": "sindhi", + "Sinhala": "singali", + "Southern Sotho": "lõunasotho", + "Sundanese": "sunda", + "Telugu": "telugu", + "Urdu": "urdu", + "Welsh": "kõmri", + "Western Frisian": "läänefriisi", + "Xhosa": "koosa", + "Yiddish": "jidiši", + "Yoruba": "joruba", + "Zulu": "suulu", + "Fallback comments: ": "Kommentaaride tagavaravariant: ", + "Rating: ": "Hinnang: ", + "Default": "Vaikimisi", + "Download is disabled": "Allalaadimine on keelatud", + "YouTube comment permalink": "YouTube'i kommentaari püsilink", + "permalink": "püsilink", + "Channel Sponsor": "Kanali sponsor", + "search_filters_features_label": "Omadused", + "search_filters_features_option_c_commons": "Creative Commons litsents", + "search_filters_features_option_three_sixty": "360°-video", + "search_filters_features_option_vr180": "VR180-video", + "search_filters_features_option_three_d": "3D-video", + "search_filters_features_option_hdr": "HDR-video", + "search_filters_features_option_purchased": "Ostetud", + "search_filters_sort_option_relevance": "Olulisus", + "search_filters_sort_option_rating": "Hinnang", + "search_filters_apply_button": "Rakenda valitud filtrid", + "footer_source_code": "Lähtekood", + "footer_original_source_code": "Algne lähtekood", + "footer_modfied_source_code": "Muudetud lähtekood", + "none": "mitte midagi", + "videoinfo_youTube_embed_link": "Lõimi", + "videoinfo_invidious_embed_link": "Lõimi link", + "adminprefs_modified_source_code_url_label": "Link muudetud lähtekoodi hoidlale", + "channel_tab_podcasts_label": "Taskuhäälingud", + "Engagement: ": "Kaasatus: ", + "download_subtitles": "Subtiitrid - `x` (.vtt)", + "user_created_playlists": "`x` - koostatud esitusloendid", + "user_saved_playlists": "`x` - salvestatud esitusloendid", + "Video unavailable": "Video pole saadaval", + "preferences_save_player_pos_label": "Salvesta taasesituse asukoht: ", + "crash_page_you_found_a_bug": "Tundub, et oled Invidiousest leidnud vea!", + "crash_page_before_reporting": "Enne veast teatamist, palun kontrolli, et oleksid:", + "crash_page_refresh": "proovinud lehte uuesti laadida", + "crash_page_switch_instance": "proovinud kasutada mõnda muud Invidiouse serverit", + "crash_page_read_the_faq": "lugenud Korduma kippuvaid küsimusi (KKK)", + "crash_page_search_issue": "otsinud GitHubist sarnaseid ja juba teaeatud vigu", + "crash_page_report_issue": "Kui ükski ülaltoodud võimalustest seda viga ei lahendanud, siis palun koosta GitHubis meie veahalduses uus veateade (soovitavalt inglise keeles) ja lisa sinnakogu järgnev tekst (palun ÄRA tõlgi seda teksti):", + "error_video_not_in_playlist": "Selles esitusloendis ei leidu soovitud videot. Siit pääsed esitusloendi avalehele.", + "channel_tab_shorts_label": "Lühivideod", + "channel_tab_streams_label": "Otseülekanded", + "%A %B %-d, %Y": "%A %B %-d, %Y", + "channel_tab_releases_label": "Versioonid", + "channel_tab_courses_label": "Kursused", + "channel_tab_playlists_label": "Esitusloendid", + "channel_tab_posts_label": "Postitused", + "channel_tab_channels_label": "Kanalid", + "toggle_theme": "Vaheta kujundust", + "carousel_slide": "Slaid {{current}} / {{total}}", + "carousel_skip": "Jäta karussell vahele", + "carousel_go_to": "Ava slaid `x`", + "timeline_parse_error_placeholder_heading": "Objekti töötlemine ei õnnestu", + "timeline_parse_error_placeholder_message": "Selle objekti töötlemisel tekkis Invidiouses viga. Lisateave on alljärgnevas:", + "timeline_parse_error_show_technical_details": "Näita tehnilisi üksikasju", + "preferences_default_playlist": "Vaikimisi esitusloend: ", + "preferences_default_playlist_none": "Ühtegi vaikimisi esitusloendit ei leidu" } From 2c5a3a9538f49f7bdd9057ad5f4fae4a2f4e2908 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:03:16 +0200 Subject: [PATCH 066/108] Update Russian translation Update Russian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Artyom Rybakov Co-authored-by: Hosted Weblate Co-authored-by: Yurt Page Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ru.json | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/locales/ru.json b/locales/ru.json index 906f00fc..6de83bca 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -22,7 +22,7 @@ "Import and Export Data": "Импорт и экспорт данных", "Import": "Импорт", "Import Invidious data": "Импортировать JSON с данными Invidious", - "Import YouTube subscriptions": "Импортировать подписки из CSV или OPML", + "Import YouTube subscriptions": "Импортировать подписки из YouTube через файлы CSV или OPML", "Import FreeTube subscriptions (.db)": "Импортировать подписки из FreeTube (.db)", "Import NewPipe subscriptions (.json)": "Импортировать подписки из NewPipe (.json)", "Import NewPipe data (.zip)": "Импортировать данные из NewPipe (.zip)", @@ -40,8 +40,6 @@ "User ID": "ИД пользователя", "Password": "Пароль", "Time (h:mm:ss):": "Время (ч:мм:сс):", - "Text CAPTCHA": "Текстовая капча (англ.)", - "Image CAPTCHA": "Капча-картинка", "Sign In": "Войти", "Register": "Регистрация", "E-mail": "Эл. почта", @@ -511,11 +509,17 @@ "Answer": "Ответить", "Search for videos": "Поиск видео", "The Popular feed has been disabled by the administrator.": "Лента популярного была отключена администратором.", - "toggle_theme": "Переключатель тем", - "carousel_slide": "Пролистано {{current}} из {{total}}", + "toggle_theme": "Переключить тему оформления", + "carousel_slide": "Слайд {{current}} из {{total}}", "carousel_skip": "Пропустить всё", - "carousel_go_to": "Перейти к странице `x`", + "carousel_go_to": "Перейти на слайд `x`", "preferences_preload_label": "Предзагрузка видеоданных: ", "channel_tab_courses_label": "Курсы", - "channel_tab_posts_label": "Записи" + "channel_tab_posts_label": "Записи", + "timeline_parse_error_placeholder_message": "Invidious столкнулся с ошибкой, пытаясь разобрать с этот элемент. Подробнее смотрите ниже:", + "timeline_parse_error_placeholder_heading": "Невозможно разобрать элемент", + "timeline_parse_error_show_technical_details": "Показать технические подробности", + "Filipino (auto-generated)": "Филиппинский (автоматически сгенерировано)", + "preferences_default_playlist": "Плейлист по умолчанию: ", + "preferences_default_playlist_none": "Плейлист по умолчанию не указан" } From abd5bfb7b7acd0c90d1d7167ed49f9df5fd679f8 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:03:27 +0200 Subject: [PATCH 067/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ro.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/ro.json b/locales/ro.json index ccbeef63..a3bfeb1f 100644 --- a/locales/ro.json +++ b/locales/ro.json @@ -39,8 +39,6 @@ "User ID": "ID Utilizator", "Password": "Parolă", "Time (h:mm:ss):": "Ora (h:mm:ss) :", - "Text CAPTCHA": "Text CAPTCHA", - "Image CAPTCHA": "Imagine CAPTCHA", "Sign In": "Conectați-vă", "Register": "Înregistrați-vă", "E-mail": "E-mail", From 5a1e86ddb6ef852201b7b332797e5a29f6e3b7ec Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:03:37 +0200 Subject: [PATCH 068/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/bn.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/bn.json b/locales/bn.json index 501a1ca3..79347286 100644 --- a/locales/bn.json +++ b/locales/bn.json @@ -36,8 +36,6 @@ "User ID": "ইউজার আইডি", "Password": "পাসওয়ার্ড", "Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):", - "Text CAPTCHA": "টেক্সট ক্যাপচা", - "Image CAPTCHA": "চিত্র ক্যাপচা", "Sign In": "সাইন ইন", "Register": "নিবন্ধন", "E-mail": "ই-মেইল", From dd03b16ff9ea6770a044b41361088b1bcb4d4c48 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:03:46 +0200 Subject: [PATCH 069/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/bg.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/bg.json b/locales/bg.json index 5c99d98f..cf74a659 100644 --- a/locales/bg.json +++ b/locales/bg.json @@ -102,7 +102,6 @@ "Spanish (Spain)": "Испански (Испания)", "invidious": "Invidious", "crash_page_refresh": "пробвал да опресниш страницата", - "Image CAPTCHA": "CAPTCHA с Изображение", "search_filters_features_option_hd": "HD", "Chinese (Hong Kong)": "Китайски (Хонг Конг)", "Import Invidious data": "Импортиране на Invidious JSON информацията", @@ -457,7 +456,6 @@ "next_steps_error_message": "След което можеш да пробваш да: ", "Hide annotations": "Скрий анотации", "Standard YouTube license": "Стандартен YouTube лиценз", - "Text CAPTCHA": "Текст CAPTCHA", "Log in/register": "Вход/регистрация", "Punjabi": "Пенджаби", "Change password": "Смяна на паролата", From f38742e4e764bf500915f7fc9a08cb4afffc2f33 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:03:57 +0200 Subject: [PATCH 070/108] Update Ukrainian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Ihor Hordiichuk Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/uk.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/uk.json b/locales/uk.json index b99923e2..fbf2cd6a 100644 --- a/locales/uk.json +++ b/locales/uk.json @@ -39,8 +39,6 @@ "User ID": "ID користувача", "Password": "Пароль", "Time (h:mm:ss):": "Час (г:хх:сс):", - "Text CAPTCHA": "Текст CAPTCHA", - "Image CAPTCHA": "Зображення CAPTCHA", "Sign In": "Увійти", "Register": "Зареєструватися", "E-mail": "Електронна пошта", @@ -518,5 +516,8 @@ "Filipino (auto-generated)": "Філіппінська (згенеровано автоматично)", "First page": "Перша сторінка", "channel_tab_courses_label": "Курси", - "channel_tab_posts_label": "Дописи" + "channel_tab_posts_label": "Дописи", + "timeline_parse_error_placeholder_heading": "Неможливо розібрати елемент", + "timeline_parse_error_show_technical_details": "Показати технічні подробиці", + "timeline_parse_error_placeholder_message": "Invidious зіткнувся з помилкою під час спроби розібрати цей елемент. Докладнішу інформацію читайте нижче:" } From 5b3cb5268bcd679c406d1a0c6cc5cee2e57656b8 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:04 +0200 Subject: [PATCH 071/108] Update Japanese translation Update Japanese translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Himmel Co-authored-by: Hosted Weblate Co-authored-by: maboroshin Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ja.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/ja.json b/locales/ja.json index c4b82486..633dfa0d 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -44,8 +44,6 @@ "User ID": "ユーザー ID", "Password": "パスワード", "Time (h:mm:ss):": "時間 (時:分分:秒秒):", - "Text CAPTCHA": "テキスト CAPTCHA", - "Image CAPTCHA": "画像 CAPTCHA", "Sign In": "サインイン", "Register": "登録", "E-mail": "メールアドレス", @@ -484,5 +482,10 @@ "Filipino (auto-generated)": "フィリピノ語 (自動生成)", "First page": "最初のページ", "channel_tab_posts_label": "投稿", - "channel_tab_courses_label": "コース" + "channel_tab_courses_label": "コース", + "timeline_parse_error_placeholder_message": "Invidious によるこの項目の解析中にエラーが発生。詳細は以下:", + "timeline_parse_error_placeholder_heading": "この項目を解析できません", + "timeline_parse_error_show_technical_details": "技術的詳細を表示", + "preferences_default_playlist": "デフォルトのプレイリスト: ", + "preferences_default_playlist_none": "デフォルトのプレイリストは設定されていません" } From 9b3c46e74e287be9d6f9b66f63858ba941932fae Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:10 +0200 Subject: [PATCH 072/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ca.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/ca.json b/locales/ca.json index 474d6a3c..7b753153 100644 --- a/locales/ca.json +++ b/locales/ca.json @@ -167,7 +167,6 @@ "comments_points_count_plural": "{{count}} punts", "%A %B %-d, %Y": "%A %B %-d, %Y", "Create playlist": "Crear llista de reproducció", - "Text CAPTCHA": "Text CAPTCHA", "Next page": "Pàgina següent", "preferences_category_visual": "Preferències visuals", "preferences_unseen_only_label": "Mostra només no vistos: ", @@ -387,7 +386,6 @@ "Delete account?": "Esborrar compte?", "Please log in": "Si us plau inicieu sessió", "Import NewPipe data (.zip)": "Importar dades de NewPipe (.zip)", - "Image CAPTCHA": "Imatge CAPTCHA", "channel_tab_streams_label": "Transmissions en directe", "preferences_category_misc": "Preferències diverses", "preferences_annotations_subscribed_label": "Mostra les anotacions per defecte dels canals subscrits? ", From 019a5cdb7de8b18370aae217b2c628350273083d Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:16 +0200 Subject: [PATCH 073/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/cy.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/cy.json b/locales/cy.json index eb391572..6eee5961 100644 --- a/locales/cy.json +++ b/locales/cy.json @@ -162,8 +162,6 @@ "preferences_quality_dash_option_1080p": "1080p", "preferences_quality_dash_option_720p": "720p", "invidious": "Invidious", - "Text CAPTCHA": "CAPTCHA testun", - "Image CAPTCHA": "CAPTCHA delwedd", "preferences_continue_label": "Chwarae'r fideo nesaf fel rhagosodiad: ", "preferences_continue_autoplay_label": "Chwarae'r fideo nesaf yn awtomatig: ", "preferences_listen_label": "Sain yn unig: ", From 90269a5d09bec5877afc611b22b2ac49fd3ee50d Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:22 +0200 Subject: [PATCH 074/108] Update Czech translation Update Czech translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Fjuro Co-authored-by: Fjuro Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/cs.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/cs.json b/locales/cs.json index 41f3db5c..a4a65d70 100644 --- a/locales/cs.json +++ b/locales/cs.json @@ -39,8 +39,6 @@ "User ID": "ID uživatele", "Password": "Heslo", "Time (h:mm:ss):": "Čas (h:mm:ss):", - "Text CAPTCHA": "Textové CAPTCHA", - "Image CAPTCHA": "Obrázkové CAPTCHA", "Sign In": "Přihlásit se", "Register": "Vytvořit účet", "E-mail": "E-mail", @@ -518,5 +516,10 @@ "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" + "channel_tab_posts_label": "Příspěvky", + "timeline_parse_error_show_technical_details": "Zobrazit technické podrobnosti", + "timeline_parse_error_placeholder_message": "Invidious narazil při pokusu o zpracování této položky na chybu. Další informace naleznete níže:", + "timeline_parse_error_placeholder_heading": "Nepodařilo se zpracovat položku", + "preferences_default_playlist": "Výchozí playlist: ", + "preferences_default_playlist_none": "Nenastaven žádný výchozí playlist" } From 166435b26d860033544a59f314cb22afff65b9c7 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:28 +0200 Subject: [PATCH 075/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pt.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/pt.json b/locales/pt.json index 6438e15b..e5484a30 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -236,8 +236,6 @@ "Preferences": "Preferências", "E-mail": "E-mail", "Register": "Registar", - "Image CAPTCHA": "Imagem CAPTCHA", - "Text CAPTCHA": "Texto CAPTCHA", "Time (h:mm:ss):": "Tempo (h:mm:ss):", "Password": "Palavra-passe", "User ID": "Utilizador", From 1d671b61176d70460f484e877ed763d93190f2ee Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:33 +0200 Subject: [PATCH 076/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/vi.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/vi.json b/locales/vi.json index 9c4a5a15..a8bdc735 100644 --- a/locales/vi.json +++ b/locales/vi.json @@ -41,8 +41,6 @@ "User ID": "Mã nhận dạng người dùng", "Password": "Mật khẩu", "Time (h:mm:ss):": "Thời gian (h:mm:ss):", - "Text CAPTCHA": "CAPTCHA dạng chữ", - "Image CAPTCHA": "CAPTCHA dạng ảnh", "Sign In": "Đăng nhập", "Register": "Đăng ký", "E-mail": "E-mail", From 22ee5573e393dfa4483cd72f674535ad69c2a785 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:38 +0200 Subject: [PATCH 077/108] Update Icelandic translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Sveinn í Felli Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/is.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/is.json b/locales/is.json index 28cacf31..332a5367 100644 --- a/locales/is.json +++ b/locales/is.json @@ -39,8 +39,6 @@ "User ID": "Auðkenni notanda", "Password": "Lykilorð", "Time (h:mm:ss):": "Tími (h:mm: ss):", - "Text CAPTCHA": "CAPTCHA-texti", - "Image CAPTCHA": "CAPTCHA-mynd", "Sign In": "Skrá inn", "Register": "Nýskrá", "E-mail": "Tölvupóstur", @@ -501,5 +499,8 @@ "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" + "channel_tab_courses_label": "Kennsluefni", + "timeline_parse_error_placeholder_heading": "Tekst ekki að meðhöndla þetta atriði", + "timeline_parse_error_placeholder_message": "Invidious rakst á villu við að reyna að meðhöndla þetta atriði. Skoðaðu nánari upplýsingar hér fyrir neðan:", + "timeline_parse_error_show_technical_details": "Sýna nánari tæknilegar upplýsingar" } From 1176ac59e5e8f604cd1256f01e990f934e61519a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:41 +0200 Subject: [PATCH 078/108] Update Croatian translation Update Croatian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Milo Ivir Co-authored-by: Vid Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/hr.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/locales/hr.json b/locales/hr.json index 6adbcdc3..7698b32c 100644 --- a/locales/hr.json +++ b/locales/hr.json @@ -39,8 +39,6 @@ "User ID": "Korisnički ID", "Password": "Lozinka", "Time (h:mm:ss):": "Vrijeme (h:mm:ss):", - "Text CAPTCHA": "Tekstualni CAPTCHA", - "Image CAPTCHA": "Slikovni CAPTCHA", "Sign In": "Prijavi se", "Register": "Registriraj se", "E-mail": "E-mail adresa", @@ -515,5 +513,11 @@ "carousel_go_to": "Idi na kadar `x`", "carousel_skip": "Preskoči vrtuljak", "Filipino (auto-generated)": "Filipinski (automatski generirano)", - "preferences_preload_label": "Unaprijed učitaj podatke videa: " + "preferences_preload_label": "Unaprijed učitaj podatke videa: ", + "channel_tab_posts_label": "Objave", + "timeline_parse_error_placeholder_heading": "Nije moguće obraditi stavku", + "timeline_parse_error_placeholder_message": "Invidious je naišao na grešku prilikom obrade ove stavke. Za više informacija pogledajte niže dolje:", + "timeline_parse_error_show_technical_details": "Prikaži tehničke detalje", + "First page": "Prva stranica", + "channel_tab_courses_label": "Tečajevi" } From fb2fcc48d5134df8465d462e3b9aaee5d64117ae Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:45 +0200 Subject: [PATCH 079/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/hu-HU.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/hu-HU.json b/locales/hu-HU.json index 8fbdd82f..39bc2c51 100644 --- a/locales/hu-HU.json +++ b/locales/hu-HU.json @@ -49,8 +49,6 @@ "User ID": "Felhasználói azonosító", "Password": "Jelszó", "Time (h:mm:ss):": "A pontos idő (ó:pp:mm):", - "Text CAPTCHA": "Szöveges CAPTCHA kérése", - "Image CAPTCHA": "Kép CAPTCHA kérése", "Sign In": "Bejelentkezés", "Register": "Regisztrálás", "E-mail": "E-mail-cím", From 2e59a50c24eb4b66378fe847a7a6e4a339a5b5d3 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:49 +0200 Subject: [PATCH 080/108] Update Hindi translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Hindi translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Saurmanđal Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/hi.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/locales/hi.json b/locales/hi.json index 0a1c09dd..b44e4f71 100644 --- a/locales/hi.json +++ b/locales/hi.json @@ -80,8 +80,6 @@ "Register": "पंजीकृत करें", "E-mail": "ईमेल", "Time (h:mm:ss):": "समय (घं:मिमि:सेसे):", - "Text CAPTCHA": "टेक्स्ट CAPTCHA", - "Image CAPTCHA": "चित्र CAPTCHA", "Sign In": "साइन इन करें", "Preferences": "प्राथमिकताएँ", "preferences_category_player": "प्लेयर की प्राथमिकताएँ", @@ -199,7 +197,7 @@ "Switch Invidious Instance": "Invidious उदाहरण बदलें", "search_message_no_results": "कोई परिणाम नहीं मिला।", "search_message_change_filters_or_query": "अपने खोज क्वेरी को और चौड़ा करें और/या फ़िल्टर बदलें।", - "search_message_use_another_instance": " आप दूसरे उदाहरण पर भी खोज सकते हैं।", + "search_message_use_another_instance": "आप दूसरे उदाहरण पर भी खोज सकते हैं।", "Hide annotations": "टिप्पणियाँ छिपाएँ", "Show annotations": "टिप्पणियाँ दिखाएँ", "Genre: ": "श्रेणी: ", @@ -434,7 +432,7 @@ "search_filters_features_option_location": "जगह", "search_filters_features_option_purchased": "खरीदा गया", "search_filters_sort_label": "इस क्रम से लगाएँ", - "search_filters_sort_option_date": "अपलोड की ताऱीख", + "search_filters_sort_option_date": "अपलोड की तारीख", "search_filters_sort_option_views": "देखे जाने की संख्या", "search_filters_apply_button": "चयनित फ़िल्टर लागू करें", "footer_documentation": "प्रलेख", @@ -476,7 +474,7 @@ "generic_button_cancel": "रद्द करें", "generic_button_rss": "आरएसएस", "generic_button_edit": "संपादित करें", - "generic_button_delete": "हटाएं", + "generic_button_delete": "हटाएँ", "playlist_button_add_items": "वीडियो जोड़ें", "Song: ": "गाना: ", "channel_tab_podcasts_label": "पाॅडकास्ट", @@ -496,5 +494,13 @@ "carousel_skip": "कैरोसेल छोड़ें", "Add to playlist: ": "प्लेलिस्ट में जोड़ें: ", "Search for videos": "वीडियो खोजें", - "carousel_go_to": "स्लाइड `x` पर जाएँ" + "carousel_go_to": "स्लाइड `x` पर जाएँ", + "First page": "पहला पृष्ठ", + "preferences_preload_label": "वीडियो डेटा प्रीलोड करें: ", + "Filipino (auto-generated)": "फ़िलिपीनो (अपने-आप जनरेट हुआ)", + "channel_tab_courses_label": "कोर्स", + "channel_tab_posts_label": "पोस्ट", + "timeline_parse_error_placeholder_heading": "आयटम को पार्स नहीं किया जा सका", + "timeline_parse_error_placeholder_message": "इस आयटम को पार्स करते समय Invidious को एक त्रुटि आई। अधिक जानकारी के लिए नीचे देखें:", + "timeline_parse_error_show_technical_details": "तकनीकी जानकारी दिखाएँ" } From deee01fe7bc54d6aa7219031a0d8543983e83ee5 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:04:56 +0200 Subject: [PATCH 081/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/he.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/he.json b/locales/he.json index 6fee93b2..c05db107 100644 --- a/locales/he.json +++ b/locales/he.json @@ -39,8 +39,6 @@ "User ID": "שם משתמש", "Password": "סיסמה", "Time (h:mm:ss):": "זמן (h:mm:ss):", - "Text CAPTCHA": "Text CAPTCHA", - "Image CAPTCHA": "Image CAPTCHA", "Sign In": "התחברות", "Register": "הרשמה", "E-mail": "דוא״ל", From 0eff8c8cd91689104a3b15027140357c0c689c54 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:02 +0200 Subject: [PATCH 082/108] Update Polish translation Update Polish translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Matthaiks Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pl.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/locales/pl.json b/locales/pl.json index d78b7a95..bb68f53b 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -39,8 +39,6 @@ "User ID": "ID użytkownika", "Password": "Hasło", "Time (h:mm:ss):": "Godzina (h:mm:ss):", - "Text CAPTCHA": "Tekst CAPTCHA", - "Image CAPTCHA": "Obraz CAPTCHA", "Sign In": "Zaloguj się", "Register": "Zarejestruj się", "E-mail": "E-mail", @@ -78,7 +76,7 @@ "Redirect homepage to feed: ": "Przekieruj stronę główną do subskrybcji: ", "preferences_max_results_label": "Liczba filmów widoczna na stronie subskrybcji: ", "preferences_sort_label": "Sortuj filmy: ", - "published": "po czasie publikacji", + "published": "opublikowano", "published - reverse": "po czasie publikacji od najstarszych", "alphabetically": "alfabetycznie", "alphabetically - reverse": "alfabetycznie od tyłu", @@ -518,5 +516,10 @@ "Filipino (auto-generated)": "filipiński (wygenerowany automatycznie)", "First page": "Pierwsza strona", "channel_tab_posts_label": "Posty", - "channel_tab_courses_label": "Kursy" + "channel_tab_courses_label": "Kursy", + "timeline_parse_error_placeholder_message": "Invidious napotkał błąd podczas próby parsowania tego elementu. Aby uzyskać więcej informacji, zobacz poniżej:", + "timeline_parse_error_placeholder_heading": "Nie można przeanalizować elementu", + "timeline_parse_error_show_technical_details": "Pokaż szczegóły techniczne", + "preferences_default_playlist_none": "Brak domyślnej playlisty", + "preferences_default_playlist": "Domyślna playlista: " } From 003f462580c8b818a89679fa906f2c5c6cc1d18e Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:08 +0200 Subject: [PATCH 083/108] Update Italian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Random Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/it.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/locales/it.json b/locales/it.json index c7143ef6..3fc21562 100644 --- a/locales/it.json +++ b/locales/it.json @@ -48,8 +48,6 @@ "User ID": "ID utente", "Password": "Password", "Time (h:mm:ss):": "Orario (h:mm:ss):", - "Text CAPTCHA": "Testo del CAPTCHA", - "Image CAPTCHA": "Immagine CAPTCHA", "Sign In": "Accedi", "Register": "Registrati", "E-mail": "E-mail", @@ -129,7 +127,7 @@ "subscriptions_unseen_notifs_count_0": "{{count}} notifica non visualizzata", "subscriptions_unseen_notifs_count_1": "{{count}} notifiche non visualizzate", "subscriptions_unseen_notifs_count_2": "{{count}} notifiche non visualizzate", - "search": "Cerca", + "search": "cerca", "Log out": "Esci", "Source available here.": "Codice sorgente.", "View JavaScript license information.": "Guarda le informazioni di licenza del codice JavaScript.", @@ -518,5 +516,8 @@ "Filipino (auto-generated)": "Filippino (generati automaticamente)", "First page": "Prima pagina", "channel_tab_courses_label": "Corsi", - "channel_tab_posts_label": "Post" + "channel_tab_posts_label": "Post", + "timeline_parse_error_show_technical_details": "Mostra i dettagli tecnici", + "timeline_parse_error_placeholder_message": "Invidious ha riscontrato un errore tentando di leggere questo elemento. Per altre informazioni vedi di seguito:", + "timeline_parse_error_placeholder_heading": "Lettura elemento non riuscita" } From d4b8801bbf92add194744002c9bd1173ff62c32e Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:14 +0200 Subject: [PATCH 084/108] Update Arabic translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Rex_sa Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ar.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index 94103c29..dcc58ca7 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -39,8 +39,6 @@ "User ID": "مُعرِّف المُستخدم", "Password": "كلمة المرور", "Time (h:mm:ss):": "الوقت (h:mm:ss):", - "Text CAPTCHA": "نص الكابتشا", - "Image CAPTCHA": "صورة الكابتشا", "Sign In": "إنشاء حساب", "Register": "التسجيل", "E-mail": "البريد الإلكتروني", @@ -569,5 +567,8 @@ "Filipino (auto-generated)": "الفلبينية (المولدة تلقائيًا)", "channel_tab_courses_label": "الدورات", "channel_tab_posts_label": "المنشورات", - "First page": "الصفحة الأولى" + "First page": "الصفحة الأولى", + "timeline_parse_error_placeholder_heading": "غير قادر على تحليل العنصر", + "timeline_parse_error_placeholder_message": "واجه Invidious خطأ أثناء محاولة تحليل هذا العنصر. لمزيد من المعلومات انظر أدناه:", + "timeline_parse_error_show_technical_details": "عرض التفاصيل التقنية" } From 928b290fdb7dfbc242f032301769a34d622b997f Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:19 +0200 Subject: [PATCH 085/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ia.json | 1 - 1 file changed, 1 deletion(-) diff --git a/locales/ia.json b/locales/ia.json index 236ec4b4..c8a88206 100644 --- a/locales/ia.json +++ b/locales/ia.json @@ -5,7 +5,6 @@ "oldest": "plus ancian", "published": "data de publication", "invidious": "Invidious", - "Image CAPTCHA": "Imagine CAPTCHA", "newest": "plus nove", "generic_button_save": "Salveguardar", "Dark mode: ": "Modo obscur: ", From a2d48051e37a8be88606f69e4072bcb8184104e2 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:25 +0200 Subject: [PATCH 086/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/id.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/id.json b/locales/id.json index 4c6e8548..d52e31bf 100644 --- a/locales/id.json +++ b/locales/id.json @@ -44,8 +44,6 @@ "User ID": "ID Pengguna", "Password": "Kata Sandi", "Time (h:mm:ss):": "Waktu (j:mm:dd):", - "Text CAPTCHA": "Teks CAPTCHA", - "Image CAPTCHA": "Gambar CAPTCHA", "Sign In": "Masuk", "Register": "Daftar", "E-mail": "Surel", From 692a12336a014bd7848aa83b3f81e58050f61f77 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:33 +0200 Subject: [PATCH 087/108] Update Dutch translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Dick Groskamp Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/nl.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/nl.json b/locales/nl.json index e9ce7674..50446c82 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -39,8 +39,6 @@ "User ID": "Gebruikers-id", "Password": "Wachtwoord", "Time (h:mm:ss):": "Tijd (h:mm:ss):", - "Text CAPTCHA": "Tekst-CAPTCHA", - "Image CAPTCHA": "Afbeelding-CAPTCHA", "Sign In": "Inloggen", "Register": "Registreren", "E-mail": "E-mailadres", @@ -501,5 +499,8 @@ "Filipino (auto-generated)": "Filipijns (automatisch gegenereerd)", "channel_tab_courses_label": "Cursussen", "First page": "Eerste pagina", - "channel_tab_posts_label": "Gepost" + "channel_tab_posts_label": "Gepost", + "timeline_parse_error_placeholder_heading": "Kan item niet parsen", + "timeline_parse_error_placeholder_message": "Invidious kwam een fout tegen bij het proberen te parsen van dit item. Voor meer informatie, kijk hieronder:", + "timeline_parse_error_show_technical_details": "Technische details weergeven" } From 28cf74e32153f1799df8716b50aac836a8589975 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:40 +0200 Subject: [PATCH 088/108] Update Spanish translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Spanish translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: TransGecko Co-authored-by: Álvaro Alonso Ramírez Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/es.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/locales/es.json b/locales/es.json index 686e13f9..53b4b3b4 100644 --- a/locales/es.json +++ b/locales/es.json @@ -39,8 +39,6 @@ "User ID": "Nombre", "Password": "Contraseña", "Time (h:mm:ss):": "Hora (h:mm:ss):", - "Text CAPTCHA": "CAPTCHA en texto", - "Image CAPTCHA": "CAPTCHA en imagen", "Sign In": "Iniciar sesión", "Register": "Registrarse", "E-mail": "Correo", @@ -319,7 +317,7 @@ "`x` marked it with a ❤": "`x` lo ha marcado con un ❤", "Audio mode": "Modo de audio", "Video mode": "Modo de video", - "channel_tab_videos_label": "Videos", + "channel_tab_videos_label": "Vídeos", "Playlists": "Listas de reproducción", "channel_tab_community_label": "Comunidad", "search_filters_sort_option_relevance": "Relevancia", @@ -439,7 +437,7 @@ "generic_count_seconds_2": "{{count}} segundos", "crash_page_before_reporting": "Antes de notificar un error asegúrate de que has:", "crash_page_switch_instance": "probado a usar otra instancia", - "crash_page_read_the_faq": "leído las Preguntas Frecuentes", + "crash_page_read_the_faq": "lee las Preguntas Frecuentes", "crash_page_search_issue": "buscado problemas existentes en GitHub", "crash_page_you_found_a_bug": "¡Parece que has encontrado un error en Invidious!", "crash_page_refresh": "probado a recargar la página", @@ -482,7 +480,7 @@ "tokens_count_2": "{{count}} tokens", "search_message_use_another_instance": "También puedes buscar en otra instancia.", "Popular enabled: ": "¿Habilitar la sección popular? ", - "error_video_not_in_playlist": "El video que solicitaste no existe en esta lista de reproducción. Haz clic aquí para acceder a la página de inicio de la lista de reproducción.", + "error_video_not_in_playlist": "El vídeo que has solicitado no existe en esta lista de reproducción. Haz clic aquí para acceder a la página de inicio de la lista de reproducción.", "channel_tab_streams_label": "Directos", "channel_tab_channels_label": "Canales", "channel_tab_shorts_label": "Cortos", @@ -520,5 +518,8 @@ "Filipino (auto-generated)": "Filipino (generados automáticamente)", "channel_tab_posts_label": "Publicaciones", "First page": "Primera página", - "channel_tab_courses_label": "Cursos" + "channel_tab_courses_label": "Cursos", + "timeline_parse_error_show_technical_details": "Enseñar detalles técnicos", + "timeline_parse_error_placeholder_message": "Invidious ha encontrado un error al tratar de procesar este elemento. Para más información ver abajo:", + "timeline_parse_error_placeholder_heading": "Imposible procesar este elemento" } From 2c7e513c636f641a4e9fe8196d1efdb77de33c64 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:44 +0200 Subject: [PATCH 089/108] Update French translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Tristan B Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/fr.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/locales/fr.json b/locales/fr.json index 49aa09df..88f3a94f 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -62,8 +62,6 @@ "User ID": "Identifiant utilisateur", "Password": "Mot de passe", "Time (h:mm:ss):": "Heure (h:mm:ss) :", - "Text CAPTCHA": "CAPTCHA textuel", - "Image CAPTCHA": "CAPTCHA pictural", "Sign In": "S'identifier", "Register": "S'inscrire", "E-mail": "Courriel", @@ -518,5 +516,6 @@ "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" + "channel_tab_posts_label": "Messages", + "timeline_parse_error_show_technical_details": "Afficher les détails techniques" } From fc76964c87c760c546010d45a20b9ad208f83114 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:48 +0200 Subject: [PATCH 090/108] Update translation files Updated by "Cleanup translation files" 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 | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/sv-SE.json b/locales/sv-SE.json index 8f050d98..0f0808c2 100644 --- a/locales/sv-SE.json +++ b/locales/sv-SE.json @@ -39,8 +39,6 @@ "User ID": "Användar-ID", "Password": "Lösenord", "Time (h:mm:ss):": "Tid (h:mm:ss):", - "Text CAPTCHA": "Text-CAPTCHA", - "Image CAPTCHA": "Bild-CAPTCHA", "Sign In": "Inloggning", "Register": "Registrera", "E-mail": "E-post", From 7ab925e45b3f678e9dbe5c9aaea7a67a0a3a2ddb Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:51 +0200 Subject: [PATCH 091/108] Update Persian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Atur Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/fa.json | 82 ++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/locales/fa.json b/locales/fa.json index 2326370d..b5b72b4d 100644 --- a/locales/fa.json +++ b/locales/fa.json @@ -1,12 +1,12 @@ { "generic_views_count": "{{count}} بازدید", "generic_views_count_plural": "{{count}} بازدید", - "generic_videos_count": "{{count}} ویدئو", - "generic_videos_count_plural": "{{count}} ویدئو", + "generic_videos_count": "{{count}} ویدیو", + "generic_videos_count_plural": "{{count}} ویدیو", "generic_playlists_count": "{{count}} فهرست پخش", "generic_playlists_count_plural": "{{count}} فهرست پخش", - "generic_subscribers_count": "{{count}} دنبال کننده", - "generic_subscribers_count_plural": "{{count}} دنبال کننده", + "generic_subscribers_count": "{{count}} دنبال‌کننده", + "generic_subscribers_count_plural": "{{count}} دنبال‌کننده", "generic_subscriptions_count": "{{count}} اشتراک", "generic_subscriptions_count_plural": "{{count}} اشتراک", "LIVE": "زنده", @@ -24,21 +24,21 @@ "Clear watch history?": "پاک کردن تاریخچه نمایش؟", "New password": "گذرواژه تازه", "New passwords must match": "گذارواژه های تازه باید باهم همخوانی داشته باشند", - "Authorize token?": "توکن دسترسی؟", - "Authorize token for `x`?": "توکن دسترسی برای `x`؟", - "Yes": "بله", - "No": "خیر", + "Authorize token?": "اجازه دادن به توکن؟", + "Authorize token for `x`?": "اجازه دادن به توکن برای `x`؟", + "Yes": "آری", + "No": "نه", "Import and Export Data": "درون‌برد و برون‌برد داده", "Import": "درون‌برد", - "Import Invidious data": "وارد کردن داده JSON اینویدیوس", - "Import YouTube subscriptions": "وارد کردن فایل CSV یا OPML سابسکرایب های یوتیوب", + "Import Invidious data": "درون‌برد داده JSON اینویدیوس", + "Import YouTube subscriptions": "درون‌برد پروندهٔ CSV یا OPML اشتراک‌های یوتیوب", "Import FreeTube subscriptions (.db)": "درون‌برد اشتراک‌های فری‌تیوب (.db)", "Import NewPipe subscriptions (.json)": "درون‌برد اشتراک‌های نیوپایپ (.json)", "Import NewPipe data (.zip)": "درون‌برد داده نیوپایپ (.zip)", "Export": "برون‌برد", "Export subscriptions as OPML": "برون‌برد اشتراک‌ها در قالب OPML", "Export subscriptions as OPML (for NewPipe & FreeTube)": "برون‌برد اشتراک‌ها در قالب OPML (برای نیوپایپ و فری‌تیوب)", - "Export data as JSON": "گرفتن(خارج کردن) اطلاعات اینویدیوس با فرمت JSON", + "Export data as JSON": "برون‌برد دادهٔ اینویدیوس به‌عنوان JSON", "Delete account?": "حذف حساب کاربری؟", "History": "تاریخچه", "An alternative front-end to YouTube": "یک پیشانه جایگزین برای یوتیوب", @@ -49,15 +49,13 @@ "User ID": "شناسه کاربری", "Password": "گذرواژه", "Time (h:mm:ss):": "زمان (h:mm:ss):", - "Text CAPTCHA": "کپچای متنی", - "Image CAPTCHA": "کپچای تصویری", "Sign In": "ورود", "Register": "ثبت نام", "E-mail": "ایمیل", "Preferences": "ترجیحات", "preferences_category_player": "ترجیحات نمایش‌دهنده", - "preferences_video_loop_label": "همواره ویدئو را بازپخش کن ", - "preferences_autoplay_label": "نمایش خودکار: ", + "preferences_video_loop_label": "همیشه بازپخش کن: ", + "preferences_autoplay_label": "پخش خودکار: ", "preferences_continue_label": "پخش بعدی به طور پیشفرض: ", "preferences_continue_autoplay_label": "پخش خودکار ویدیو بعدی: ", "preferences_listen_label": "گوش کردن به طور پیشفرض: ", @@ -68,14 +66,14 @@ "preferences_comments_label": "نظرات پیشفرض: ", "youtube": "یوتیوب", "reddit": "ردیت", - "preferences_captions_label": "زیرنویس های پیشفرض: ", - "Fallback captions: ": "عقب گرد زیرنویس ها: ", - "preferences_related_videos_label": "نمایش ویدیو های مرتبط: ", - "preferences_annotations_label": "نمایش حاشیه نویسی ها به طور پیشفرض: ", - "preferences_extend_desc_label": "گسترش خودکار توضیحات ویدئو: ", - "preferences_vr_mode_label": "ویدئوها ۳۶۰ درجه تعاملی(نیازمند WebGL): ", + "preferences_captions_label": "زیرنویس‌های پیشفرض: ", + "Fallback captions: ": "عقب‌گرد زیرنویس‌ها: ", + "preferences_related_videos_label": "نمایش ویدیوهای مرتبط: ", + "preferences_annotations_label": "نمایش حاشیه‌نویسی‌ها به‌طور پیشفرض: ", + "preferences_extend_desc_label": "گسترش خودکار توضیحات ویدیو: ", + "preferences_vr_mode_label": "ویدیوهای ۳۶۰ درجهٔ تعاملی (نیازمند WebGL): ", "preferences_category_visual": "ترجیحات بصری", - "preferences_player_style_label": "حالت پخش کننده: ", + "preferences_player_style_label": "حالت پخش‌کننده: ", "Dark mode: ": "حالت تاریک: ", "preferences_dark_mode_label": "تم: ", "dark": "تاریک", @@ -84,7 +82,7 @@ "preferences_category_misc": "ترجیحات متفرقه", "preferences_automatic_instance_redirect_label": "هدایت خودکار نمونه (انتقال به redirect.invidious.io): ", "preferences_category_subscription": "ترجیحات اشتراک", - "preferences_annotations_subscribed_label": "نمایش حاشیه نویسی ها به طور پیشفرض برای کانال های مشترک شده: ", + "preferences_annotations_subscribed_label": "نمایش حاشیه‌نویسی‌ها به‌طور پیشفرض برای کانال‌های مشترک‌شده: ", "Redirect homepage to feed: ": "تغییر مسیر صفحه خانه به خوراک: ", "preferences_max_results_label": "تعداد ویدیو های نمایش داده شده در خوراک: ", "preferences_sort_label": "مرتب سازی ویدیو ها بر اساس: ", @@ -383,21 +381,21 @@ "next_steps_error_message_refresh": "تازه‌سازی", "next_steps_error_message_go_to_youtube": "رفتن به یوتیوب", "preferences_quality_option_hd720": "HD720", - "preferences_quality_option_dash": "DASH (کیفیت تطبیفی)", + "preferences_quality_option_dash": "DASH (کیفیت سازگارشونده)", "preferences_quality_option_medium": "میانه", "preferences_quality_option_small": "پایین", "preferences_quality_dash_option_auto": "خودکار", "preferences_quality_dash_option_best": "بهترین", "preferences_quality_dash_option_worst": "بدترین", - "preferences_quality_dash_option_4320p": "4320p", - "preferences_quality_dash_option_2160p": "2160p", - "preferences_quality_dash_option_1440p": "1440p", - "preferences_quality_dash_option_1080p": "1080p", - "preferences_quality_dash_option_720p": "720p", - "preferences_quality_dash_option_480p": "480p", - "preferences_quality_dash_option_360p": "360p", - "preferences_quality_dash_option_240p": "240p", - "preferences_quality_dash_option_144p": "144p", + "preferences_quality_dash_option_4320p": "۴۳۲۰p", + "preferences_quality_dash_option_2160p": "۲۱۶۰p", + "preferences_quality_dash_option_1440p": "۱۴۴۰p", + "preferences_quality_dash_option_1080p": "۱۰۸۰p", + "preferences_quality_dash_option_720p": "۷۲۰p", + "preferences_quality_dash_option_480p": "۴۸۰p", + "preferences_quality_dash_option_360p": "۳۶۰p", + "preferences_quality_dash_option_240p": "۲۴۰p", + "preferences_quality_dash_option_144p": "۱۴۴p", "invidious": "اینویدیوس", "search_filters_features_option_three_sixty": "360°", "footer_donate_page": "کمک مالی", @@ -476,8 +474,8 @@ "generic_button_rss": "خوراک RSS", "crash_page_read_the_faq": "که سوالات بیشتر پرسیده شده (FAQ) را خوانده‌اید", "generic_button_delete": "حذف", - "Import YouTube playlist (.csv)": "واردکردن فهرست‌پخش YouTube (.csv)", - "Import YouTube watch history (.json)": "وارد کردن فهرست پخش YouTube (.json)", + "Import YouTube playlist (.csv)": "درون‌برد فهرست‌پخش YouTube (.csv)", + "Import YouTube watch history (.json)": "درون‌برد تاریخچهٔ تماشای یوتیوب (.json)", "crash_page_you_found_a_bug": "به نظر می‌رسد که ایرادی در Invidious پیدا کرده‌اید!", "channel_tab_podcasts_label": "پادکست‌ها", "channel_tab_streams_label": "پخش زنده‌ها", @@ -485,10 +483,10 @@ "channel_tab_playlists_label": "فهرست‌های پخش", "channel_tab_channels_label": "کانال‌ها", "error_video_not_in_playlist": "ویدیوی درخواستی معلق به این فهرست پخش نیست. کلیک کنید تا به صفحهٔ اصلی فهرست پخش بروید.", - "Add to playlist": "به لیست پخش افزوده شود", + "Add to playlist": "افزودن به فهرست پخش", "Answer": "پاسخ", - "Search for videos": "جست و جو برای ویدیوها", - "Add to playlist: ": "افزودن به لیست پخش ", + "Search for videos": "جست‌وجو برای ویدیوها", + "Add to playlist: ": "افزودن به فهرست پخش ", "The Popular feed has been disabled by the administrator.": "بخش ویدیوهای پرطرفدار توسط مدیر غیرفعال شده است.", "carousel_slide": "اسلاید {{current}} از {{total}}", "carousel_skip": "رد شدن از گرداننده", @@ -497,5 +495,11 @@ "crash_page_report_issue": "اگر هیچ یک از روش های بالا کمکی نکردند لطفا (ترجیحا به انگلیسی) یک سوال جدید در گیت هاب بپرسید و طوری که سوالتون شامل متن زیر باشه:", "channel_tab_releases_label": "آثار", "toggle_theme": "تغییر وضعیت تم", - "preferences_preload_label": "پیش بار کردن داده‌های ویدیو: " + "preferences_preload_label": "پیش بار کردن داده‌های ویدیو: ", + "First page": "نخستین صفحه", + "Filipino (auto-generated)": "فیلیپنی (تولید خودکار)", + "channel_tab_posts_label": "فرسته‌ها", + "timeline_parse_error_placeholder_heading": "ناتوانی در تجزیهٔ مورد", + "timeline_parse_error_placeholder_message": "اینویدیوس هنگام کوشش برای تجزیهٔ این مورد به خطایی برخورد. برای اطلاعات بیشتر زیر را ببینید:", + "timeline_parse_error_show_technical_details": "نمایش جزئیات فنی" } From 39c930145a86c83a657f49db82c4146b03696a2e Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:05:57 +0200 Subject: [PATCH 092/108] Update Finnish translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Jiri Grönroos Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/fi.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/fi.json b/locales/fi.json index 13fef6de..db30b396 100644 --- a/locales/fi.json +++ b/locales/fi.json @@ -39,8 +39,6 @@ "User ID": "Käyttäjätunnus", "Password": "Salasana", "Time (h:mm:ss):": "Aika (h:mm:ss):", - "Text CAPTCHA": "Teksti-CAPTCHA", - "Image CAPTCHA": "Kuva-CAPTCHA", "Sign In": "Kirjaudu sisään", "Register": "Rekisteröidy", "E-mail": "Sähköposti", @@ -497,5 +495,7 @@ "The Popular feed has been disabled by the administrator.": "Järjestelmänvalvoja on poistanut Suositut-syötteen.", "Import YouTube watch history (.json)": "Tuo Youtube-katseluhistoria (.json)", "toggle_theme": "Vaihda teemaa", - "preferences_preload_label": "Esilataa video data. " + "preferences_preload_label": "Esilataa video data. ", + "timeline_parse_error_show_technical_details": "Näytä tekniset yksityiskohdat", + "First page": "Ensimmäinen sivu" } From 6928be1298a9e9b5c88a99fc8d7e141c473844ea Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:00 +0200 Subject: [PATCH 093/108] Update Serbian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: NEXI Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sr.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/sr.json b/locales/sr.json index c6614ba5..c5f444a7 100644 --- a/locales/sr.json +++ b/locales/sr.json @@ -39,8 +39,6 @@ "User ID": "ID korisnika", "Password": "Lozinka", "Time (h:mm:ss):": "Vreme (č:mm:ss):", - "Text CAPTCHA": "Tekst CAPTCHA", - "Image CAPTCHA": "Slika CAPTCHA", "Sign In": "Prijava", "Register": "Registracija", "E-mail": "Imejl", @@ -518,5 +516,8 @@ "Filipino (auto-generated)": "Filipinski (automatski generisano)", "channel_tab_posts_label": "Objave", "First page": "Prva stranica", - "channel_tab_courses_label": "Kursevi" + "channel_tab_courses_label": "Kursevi", + "timeline_parse_error_placeholder_heading": "Nije moguće raščlaniti predmet", + "timeline_parse_error_show_technical_details": "Prikaži tehničke detalje", + "timeline_parse_error_placeholder_message": "Invidious je naišao na grešku prilikom pokušaja raščlanjivanja ovog predmeta. Za više informacija pogledajte ispod:" } From 8ffbed0d386c61538b4c59ef692bbff3f50a9c77 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:02 +0200 Subject: [PATCH 094/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sq.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/sq.json b/locales/sq.json index cdf4b605..3ef91537 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -42,8 +42,6 @@ "User ID": "ID Përdoruesi", "Password": "Fjalëkalim", "Time (h:mm:ss):": "Kohë (h:mm:ss):", - "Text CAPTCHA": "CAPTCHA Tekst", - "Image CAPTCHA": "CAPTCHA Figurë", "Sign In": "Hyni", "Register": "Regjistrohuni", "E-mail": "Email", From 5a1d39683bdcf8253b26847f4745a0de08d4edb3 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:05 +0200 Subject: [PATCH 095/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/ko.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/ko.json b/locales/ko.json index 0224955f..09728684 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -36,8 +36,6 @@ "Register": "회원가입", "Sign In": "로그인", "preferences_category_misc": "기타 설정", - "Image CAPTCHA": "이미지 캡차", - "Text CAPTCHA": "텍스트 캡차", "Time (h:mm:ss):": "시각 (h:mm:ss):", "Password": "비밀번호", "User ID": "사용자 ID", From 5643cb1c4dab9c4c8d3c6ef061d8151b0552554f Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:08 +0200 Subject: [PATCH 096/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sk.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/sk.json b/locales/sk.json index 8add0f57..d9bca619 100644 --- a/locales/sk.json +++ b/locales/sk.json @@ -36,8 +36,6 @@ "User ID": "ID používateľa", "Password": "Heslo", "Time (h:mm:ss):": "Čas (h:mm:ss):", - "Text CAPTCHA": "Textové CAPTCHA", - "Image CAPTCHA": "Obrázkové CAPTCHA", "Sign In": "Prihlásiť sa", "Register": "Registrovať", "E-mail": "E-mail", From 4c57aba1f33b3fd1307c1a3a9bb339abbbc566e8 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:11 +0200 Subject: [PATCH 097/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/si.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/si.json b/locales/si.json index 4637cbd2..c0d2ccb0 100644 --- a/locales/si.json +++ b/locales/si.json @@ -82,8 +82,6 @@ "Export subscriptions as OPML": "දායකත්වයන් OPML ලෙස අපනයනය කරන්න", "JavaScript license information": "JavaScript බලපත්‍ර තොරතුරු", "User ID": "පරිශීලක කේතය", - "Text CAPTCHA": "CAPTCHA පෙල", - "Image CAPTCHA": "CAPTCHA රූපය", "E-mail": "විද්‍යුත් තැපෑල", "preferences_quality_label": "කැමති වීඩියෝ ගුණත්වය: ", "preferences_quality_option_hd720": "HD720", From aa1f8d0e63596629220e72f5243b7b6ddae70c7a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:14 +0200 Subject: [PATCH 098/108] Update Slovenian translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Damjan Gerl Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sl.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/locales/sl.json b/locales/sl.json index c36ad522..63798f21 100644 --- a/locales/sl.json +++ b/locales/sl.json @@ -24,9 +24,7 @@ "User ID": "ID uporabnika", "Password": "Geslo", "Time (h:mm:ss):": "Čas (h:mm:ss):", - "Text CAPTCHA": "Besedilo CAPTCHA", "source": "izvorna koda", - "Image CAPTCHA": "Slika CAPTCHA", "Sign In": "Prijavi se", "Register": "Registriraj se", "E-mail": "E-pošta", @@ -532,5 +530,11 @@ "carousel_slide": "Diapozitiv {{current}} od {{total}}", "carousel_skip": "Preskoči galerijo", "carousel_go_to": "Pojdi na diapozitiv `x`", - "preferences_preload_label": "Predhodno naloži video podatke: " + "preferences_preload_label": "Predhodno naloži video podatke: ", + "First page": "Prva stran", + "channel_tab_courses_label": "Tečaji", + "channel_tab_posts_label": "Objave", + "timeline_parse_error_placeholder_heading": "Elementa ni mogoče razčleniti", + "timeline_parse_error_placeholder_message": "Invidious je naletel na napako pri poskusu razčlenitve tega elementa. Za več informacij glej spodaj:", + "timeline_parse_error_show_technical_details": "Pokaži tehnične podrobnosti" } From 4ce4faec13d9a3c152958f6a52bdc56402842336 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:18 +0200 Subject: [PATCH 099/108] Update Portuguese (Portugal) translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: ssantos Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/pt-PT.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/pt-PT.json b/locales/pt-PT.json index 449bde77..65c662c6 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -39,8 +39,6 @@ "User ID": "Utilizador", "Password": "Palavra-passe", "Time (h:mm:ss):": "Tempo (h:mm:ss):", - "Text CAPTCHA": "Texto CAPTCHA", - "Image CAPTCHA": "Imagem CAPTCHA", "Sign In": "Entrar", "Register": "Registar", "E-mail": "E-mail", @@ -518,5 +516,8 @@ "Filipino (auto-generated)": "Filipino (gerado automaticamente)", "channel_tab_courses_label": "Cursos", "channel_tab_posts_label": "Publicações", - "toggle_theme": "Trocar tema" + "toggle_theme": "Trocar tema", + "timeline_parse_error_placeholder_heading": "Incapaz de processar o elemento", + "timeline_parse_error_placeholder_message": "O Invidious encontrou um problema ao processar este elemento. Para mais informações, veja abaixo:", + "timeline_parse_error_show_technical_details": "Mostrar detalhes técnicos" } From a35fa2bd3c28c819022167f0063023563fba7bed Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:21 +0200 Subject: [PATCH 100/108] Update Chinese (Traditional Han script) translation Update Chinese (Traditional Han script) translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: Jeff Huang Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/zh-TW.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 77805349..e2649c7b 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -44,8 +44,6 @@ "User ID": "使用者 ID", "Password": "密碼", "Time (h:mm:ss):": "時間 (h:mm:ss):", - "Text CAPTCHA": "文字 CAPTCHA", - "Image CAPTCHA": "圖片 CAPTCHA", "Sign In": "登入", "Register": "註冊", "E-mail": "電子郵件", @@ -484,5 +482,10 @@ "Filipino (auto-generated)": "菲律賓語(自動產生)", "channel_tab_courses_label": "課程", "First page": "第一頁", - "channel_tab_posts_label": "貼文" + "channel_tab_posts_label": "貼文", + "timeline_parse_error_show_technical_details": "顯示技術細節", + "timeline_parse_error_placeholder_heading": "無法解析項目", + "timeline_parse_error_placeholder_message": "Invidious 在嘗試解析此項目時遇到錯誤。要取得更多資訊,請見下方:", + "preferences_default_playlist": "預設播放清單: ", + "preferences_default_playlist_none": "未設定預設播放清單" } From 87d3bd0ab85d8743792ccb20a913ab87e0a8fe52 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:23 +0200 Subject: [PATCH 101/108] Update Chinese (Simplified Han script) translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Chinese (Simplified Han script) translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: 大王叫我来巡山 Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/zh-CN.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/zh-CN.json b/locales/zh-CN.json index f3bc660b..5c32caaa 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -44,8 +44,6 @@ "User ID": "用户 ID", "Password": "密码", "Time (h:mm:ss):": "时间 (h:mm:ss):", - "Text CAPTCHA": "文本验证码", - "Image CAPTCHA": "图片验证码", "Sign In": "登录", "Register": "注册", "E-mail": "E-mail", @@ -484,5 +482,10 @@ "Filipino (auto-generated)": "菲律宾语 (自动生成)", "channel_tab_posts_label": "帖子", "First page": "第一页", - "channel_tab_courses_label": "课程" + "channel_tab_courses_label": "课程", + "timeline_parse_error_show_technical_details": "显示技术细节", + "timeline_parse_error_placeholder_heading": "无法解析项目", + "timeline_parse_error_placeholder_message": "Invidious 在尝试解析此项目时遇到一个错误。更多信息请见下方:", + "preferences_default_playlist": "默认播放列表: ", + "preferences_default_playlist_none": "尚无默认播放列表" } From d047a686a4e1a5964b67d885154aaf9f77904b57 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:27 +0200 Subject: [PATCH 102/108] Update Serbian (Cyrillic script) translation Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Co-authored-by: NEXI Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/sr_Cyrl.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/locales/sr_Cyrl.json b/locales/sr_Cyrl.json index e6ab0f35..872bd00e 100644 --- a/locales/sr_Cyrl.json +++ b/locales/sr_Cyrl.json @@ -39,8 +39,6 @@ "User ID": "ID корисника", "Password": "Лозинка", "Time (h:mm:ss):": "Време (ч:мм:сс):", - "Text CAPTCHA": "Текст CAPTCHA", - "Image CAPTCHA": "Слика CAPTCHA", "Sign In": "Пријава", "Register": "Регистрација", "E-mail": "Имејл", @@ -518,5 +516,8 @@ "Filipino (auto-generated)": "Филипински (аутоматски генерисано)", "channel_tab_courses_label": "Курсеви", "First page": "Прва страница", - "channel_tab_posts_label": "Објаве" + "channel_tab_posts_label": "Објаве", + "timeline_parse_error_show_technical_details": "Прикажи техничке детаље", + "timeline_parse_error_placeholder_heading": "Није могуће рашчланити предмет", + "timeline_parse_error_placeholder_message": "Invidious је наишао на грешку приликом покушаја рашчлањивања овог предмета. За више информација погледајте испод:" } From fce446c10ed61f68ee74174a0a6355d50d71b0aa Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:30 +0200 Subject: [PATCH 103/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/bn_BD.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/bn_BD.json b/locales/bn_BD.json index a82b0da7..8ed58216 100644 --- a/locales/bn_BD.json +++ b/locales/bn_BD.json @@ -39,8 +39,6 @@ "User ID": "ইউজার আইডি", "Password": "পাসওয়ার্ড", "Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):", - "Text CAPTCHA": "টেক্সট ক্যাপচা", - "Image CAPTCHA": "চিত্র ক্যাপচা", "Sign In": "সাইন ইন", "Register": "নিবন্ধন", "E-mail": "ই-মেইল", From 6ce4717ed010d0124a3c476cf2fb0aadfa80ea0a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:34 +0200 Subject: [PATCH 104/108] Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Update Alemannic translation Add Alemannic translation Co-authored-by: Hosted Weblate Co-authored-by: Lenny Angst --- locales/gsw.json | 506 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 506 insertions(+) create mode 100644 locales/gsw.json diff --git a/locales/gsw.json b/locales/gsw.json new file mode 100644 index 00000000..cf131de5 --- /dev/null +++ b/locales/gsw.json @@ -0,0 +1,506 @@ +{ + "Add to playlist": "Enere Widergabelischte hinzuefüege", + "Add to playlist: ": "Enere Widergabelischte hinzuefüege: ", + "Answer": "Antwort", + "Search for videos": "Nach Videos sueche", + "The Popular feed has been disabled by the administrator.": "De Feed für beliebti Inhält isch vom Administrator deaktiviert worde.", + "generic_channels_count": "{{count}} Kanal", + "generic_channels_count_plural": "{{count}} Kanäl", + "generic_views_count": "{{count}} Uufruef", + "generic_views_count_plural": "{{count}} Uufrüef", + "generic_videos_count": "{{count}} Video", + "generic_videos_count_plural": "{{count}} Videos", + "generic_playlists_count": "{{count}} Widergabelischte", + "generic_playlists_count_plural": "{{count}} Widergabelischtene", + "generic_subscribers_count": "{{count}} Abonnent", + "generic_subscribers_count_plural": "{{count}} Abonnente", + "generic_subscriptions_count": "{{count}} Abo", + "generic_subscriptions_count_plural": "{{count}} Abos", + "generic_button_delete": "Lösche", + "generic_button_edit": "Bearbeite", + "generic_button_save": "Speichere", + "generic_button_cancel": "Abbreche", + "generic_button_rss": "RSS", + "LIVE": "LIVE", + "Shared `x` ago": "Vor `x` teilt", + "Unsubscribe": "Abo beende", + "Subscribe": "Abonniere", + "View channel on YouTube": "Kanal uf YouTube aazeige", + "View playlist on YouTube": "Widergabelischte uf YouTube aazeige", + "newest": "neusti", + "oldest": "ältisti", + "popular": "beliebtisti", + "last": "neusti", + "Next page": "Nächsti Siite", + "Previous page": "Vorherigi Siite", + "First page": "Ersti Siite", + "Clear watch history?": "Widergabeverlauf lösche?", + "New password": "Neus Passwort", + "New passwords must match": "Neui Passwörter müend übereinstimme", + "Authorize token?": "Token autorisiere?", + "Authorize token for `x`?": "Token für `x` autorisiere?", + "Yes": "Ja", + "No": "Nei", + "Import and Export Data": "Date importiere und exportiere", + "Import": "Importiere", + "Import Invidious data": "Invidious-JSON-Date importiere", + "Import YouTube subscriptions": "YouTube-CSV/OPML-Abonnements importiere", + "Import YouTube playlist (.csv)": "YouTube-Widergabelischte importiere (.csv)", + "Import YouTube watch history (.json)": "YouTube-Widergabeverlauf importiere (.json)", + "Import FreeTube subscriptions (.db)": "FreeTube Abonnements importiere (.db)", + "Import NewPipe subscriptions (.json)": "NewPipe Abonnements importiere (.json)", + "Import NewPipe data (.zip)": "NewPipe Date importiere (.zip)", + "Export": "Exportiere", + "Export subscriptions as OPML": "Abonnements als OPML exportiere", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportiere (für NewPipe & FreeTube)", + "Export data as JSON": "Invidious-Date als JSON exportiere", + "Delete account?": "Konto lösche?", + "History": "Verlauf", + "An alternative front-end to YouTube": "En alternativi Oberflächi für YouTube", + "JavaScript license information": "JavaScript Lizenzinformatione", + "source": "Quelle", + "Log in": "Aamelde", + "Log in/register": "Aamelde/registriere", + "User ID": "Benutzer-ID", + "Password": "Passwort", + "Time (h:mm:ss):": "Ziit (h:mm:ss):", + "Sign In": "Aamelde", + "Register": "Registriere", + "E-mail": "E-Mail", + "Preferences": "Iistellige", + "preferences_category_player": "Widergabeiistellige", + "preferences_video_loop_label": "Immer widerhole: ", + "preferences_preload_label": "Videodate vorlade: ", + "preferences_autoplay_label": "Automatisch abspiele: ", + "preferences_continue_label": "Immer automatisch nächsts Video abspiele: ", + "preferences_continue_autoplay_label": "Nächsts Video automatisch abspiele: ", + "preferences_listen_label": "Nur Ton als Standard: ", + "preferences_local_label": "Videos dur Proxy leite: ", + "preferences_watch_history_label": "Widergabeverlauf aktiviere: ", + "preferences_speed_label": "Standardgschwindigkeit: ", + "preferences_quality_label": "Bevorzugti Videoqualität: ", + "preferences_quality_option_dash": "DASH (adaptivi Qualität)", + "preferences_quality_option_hd720": "HD720", + "preferences_quality_option_medium": "Mittel", + "preferences_quality_option_small": "Niedrig", + "preferences_quality_dash_label": "Bevorzugti DASH-Videoqualität: ", + "preferences_quality_dash_option_auto": "Auto", + "preferences_quality_dash_option_best": "Höchsti", + "preferences_quality_dash_option_worst": "Niedrigsti", + "preferences_quality_dash_option_4320p": "4320p", + "preferences_quality_dash_option_2160p": "2160p", + "preferences_quality_dash_option_1440p": "1440p", + "preferences_quality_dash_option_1080p": "1080p", + "preferences_quality_dash_option_720p": "720p", + "preferences_quality_dash_option_480p": "480p", + "preferences_quality_dash_option_360p": "360p", + "preferences_quality_dash_option_240p": "240p", + "preferences_quality_dash_option_144p": "144p", + "preferences_volume_label": "Widergabeluutstärchi: ", + "preferences_comments_label": "Standardkommentär: ", + "youtube": "YouTube", + "reddit": "Reddit", + "invidious": "Invidious", + "preferences_captions_label": "Standarduntertitel: ", + "Fallback captions: ": "Ersatzuntertitel: ", + "preferences_related_videos_label": "Ähnlichi Videos aazeige: ", + "preferences_annotations_label": "Aamerkige standardmässig aazeige: ", + "preferences_extend_desc_label": "Videobeschriibig automatisch erwiitere: ", + "preferences_vr_mode_label": "Interaktivi 360-Grad-Videos (bruucht WebGL): ", + "preferences_category_visual": "Aazeigeiistellige", + "preferences_region_label": "Land vo de Inhält: ", + "preferences_player_style_label": "Player-Stil: ", + "Dark mode: ": "Nachtmodus: ", + "preferences_dark_mode_label": "Modus: ", + "dark": "Nachtmodus", + "light": "hell", + "preferences_thin_mode_label": "Schlanke Modus: ", + "preferences_category_misc": "Suschtigi Iistellige", + "preferences_automatic_instance_redirect_label": "Automatischi Instanzwiiterleitig (über redirect.invidious.io): ", + "preferences_category_subscription": "Abonnementiistellige", + "preferences_annotations_subscribed_label": "Aamerkige für abonnierti Kanäl standardmässig aazeige? ", + "Redirect homepage to feed: ": "Startsiite zu Feed umleite: ", + "preferences_max_results_label": "Aazahl vo Videos wo im Feed aazeigt werded: ", + "preferences_sort_label": "Videos sortiere nach: ", + "published": "veröffentlicht", + "published - reverse": "veröffentlicht - invertiert", + "alphabetically": "alphabetisch", + "alphabetically - reverse": "alphabetisch - invertiert", + "channel name": "Kanalname", + "channel name - reverse": "Kanalname - invertiert", + "Only show latest video from channel: ": "Nur neusti Videos vom Kanal aazeige: ", + "Only show latest unwatched video from channel: ": "Neu neusti ungseheni Videos vom Kanal aazeige: ", + "preferences_unseen_only_label": "Nur ungseheni aazeige: ", + "preferences_notifications_only_label": "Nur Benachrichtigunge aazeige (wenns welchi git): ", + "Enable web notifications": "Webbenachrichtigunge aktiviere", + "`x` uploaded a video": "`x` het es Video ufeglade", + "`x` is live": "`x` isch live", + "preferences_category_data": "Dateiistellige", + "Clear watch history": "Verlauf lösche", + "Import/export data": "Date importiere/exportiere", + "Change password": "Passwort ändere", + "Manage subscriptions": "Abonnements verwalte", + "Manage tokens": "Tokens verwalte", + "Watch history": "Widergabeverlauf", + "Delete account": "Account lösche", + "preferences_category_admin": "Administrator-Iistellige", + "preferences_default_home_label": "Standard-Startsiite: ", + "preferences_feed_menu_label": "Feed-Menü: ", + "preferences_show_nick_label": "Nutzernäme obe aazeige: ", + "Popular enabled: ": "„Beliebt“-Siite aktiviert: ", + "Top enabled: ": "Top aktiviert? ", + "CAPTCHA enabled: ": "CAPTCHA aktiviert? ", + "Login enabled: ": "Aameldig aktiviert: ", + "Registration enabled: ": "Registrierig aktiviert: ", + "Report statistics: ": "Statistike brichte: ", + "Save preferences": "Iistellige speichere", + "Subscription manager": "Abonnementsverwaltig", + "Token manager": "Tokenverwaltig", + "Token": "Token", + "tokens_count": "{{count}} Token", + "tokens_count_plural": "{{count}} Tokens", + "Import/export": "Importiere/Exportiere", + "unsubscribe": "abbstelle", + "revoke": "widerrüefe", + "Subscriptions": "Abonnements", + "subscriptions_unseen_notifs_count": "{{count}} ungsehni Benachrichtigung", + "subscriptions_unseen_notifs_count_plural": "{{count}} ungsehni Benachrichtigunge", + "search": "Sueche", + "Log out": "Abmelde", + "Released under the AGPLv3 on Github.": "Uf GitHub under de AGPLv3 Lizenz veröffentlicht.", + "Source available here.": "Quellcode da verfüegbar.", + "View JavaScript license information.": "JavaScript-Lizenzinformatione aazeige.", + "View privacy policy.": "Dateschutzerchlärig iigseh.", + "Trending": "Aagseit", + "Public": "Öffentlich", + "Unlisted": "Nöd glischtet", + "Private": "Privat", + "View all playlists": "Alli Widergabelischtene aazeige", + "Updated `x` ago": "Aktualisiert vor `x`", + "Delete playlist `x`?": "Widergabelischte `x` lösche?", + "Delete playlist": "Widergabelischte lösche", + "Create playlist": "Widergabelischte erstelle", + "Title": "Titel", + "Playlist privacy": "Widergabelischte-Privatsphäri", + "Editing playlist `x`": "Widergabelischte `x` bearbeite", + "playlist_button_add_items": "Videos hinzuefüege", + "Show more": "Meh aazeige", + "Show less": "Weniger aazeige", + "Watch on YouTube": "Video uf YouTube aaluege", + "Switch Invidious Instance": "Invidious Instanz wechsle", + "search_message_no_results": "Kei Ergebnis gfunde.", + "search_message_change_filters_or_query": "Versuech, dini Suechaafrag z erwiitere und/oder d Filter z ändere.", + "search_message_use_another_instance": "Du chasch au uf ere andere Instanz sueche.", + "Hide annotations": "Aamerkige uusblende", + "Show annotations": "Aamerkige aazeige", + "Genre: ": "Genre: ", + "License: ": "Lizenz: ", + "Standard YouTube license": "Standard YouTube-Lizenz", + "Family friendly? ": "Familiefründlich? ", + "Wilson score: ": "Wilson-Score: ", + "Engagement: ": "Engagement: ", + "Whitelisted regions: ": "Erlaubti Regione: ", + "Blacklisted regions: ": "Unerlaubti Regione: ", + "Music in this video": "Musig i dem Video", + "Artist: ": "Künschtler: ", + "Song: ": "Musig: ", + "Album: ": "Album: ", + "Shared `x`": "Teilt `x`", + "Premieres in `x`": "Premiere i `x`", + "Premieres `x`": "Premiere `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.": "Hallo! Anschinend hesch du JavaScript deaktiviert. Klick da, zum Kommentär aazzeige, beacht, dass es chli länger duure cha, zum sie z lade.", + "View YouTube comments": "YouTube Kommentär aazeige", + "View more comments on Reddit": "Meh Kommentär uf Reddit aazeige", + "View `x` comments": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` Kommentar aazeige", + "": "`x` Kommentär aazeige" + }, + "View Reddit comments": "Reddit-Kommentär aazeige", + "Hide replies": "Antworte verstecke", + "Show replies": "Antworte aazeige", + "Incorrect password": "Falschs Passwort", + "Wrong answer": "Ungültigi Antwort", + "Erroneous CAPTCHA": "Ungültigs CAPTCHA", + "CAPTCHA is a required field": "CAPTCHA isch en erforderlichi Iigab", + "User ID is a required field": "Benutzer ID isch en erforderlichi Iigab", + "Password is a required field": "Passwort isch en erforderlichi Iigab", + "Wrong username or password": "Ungültige Benutzername oder Passwort", + "Password cannot be empty": "Passwort derf nöd leer sii", + "Password cannot be longer than 55 characters": "Passwort derf nöd länger als 55 Zeiche sii", + "Please log in": "Bitte aamelde", + "Invidious Private Feed for `x`": "Invidious Persönliche Feed für `x`", + "channel:`x`": "Kanal:`x`", + "Deleted or invalid channel": "Glöschte oder ungültige Kanal", + "This channel does not exist.": "De Kanal existiert nöd.", + "Could not get channel info.": "Kanalinformatione hend nöd chönne glade werde.", + "Could not fetch comments": "Kommentär hend nöd chönne glade werde", + "comments_view_x_replies": "{{count}} Antwort aazeige", + "comments_view_x_replies_plural": "{{count}} Antworte aazeige", + "`x` ago": "vor `x`", + "Load more": "Meh lade", + "comments_points_count": "{{count}} Punkt", + "comments_points_count_plural": "{{count}} Pünkt", + "Could not create mix.": "Mix het nöd chönne erstellt werde.", + "Empty playlist": "Widergabelischte isch leer", + "Not a playlist.": "Ungültigi Widergabelischte.", + "Playlist does not exist.": "Widergabelischte existiert nöd.", + "Could not pull trending pages.": "Beliebt-Siitene hend nöd chönne glade werde.", + "Hidden field \"challenge\" is a required field": "Versteckts Feld „challenge“ isch en erforderlichi Iigab", + "Hidden field \"token\" is a required field": "Versteckts Feld „token“ isch en erforderlichi Iigab", + "Erroneous challenge": "Ungültige Test", + "Erroneous token": "Ungültige Token", + "No such user": "Ungültige Benutzer", + "Token is expired, please try again": "Token isch abgloffe, bitte nomal versueche", + "generic_count_years": "{{count}} Jahr", + "generic_count_years_plural": "{{count}} Jahr", + "generic_count_months": "{{count}} Monet", + "generic_count_months_plural": "{{count}} Mönet", + "generic_count_weeks": "{{count}} Wuche", + "generic_count_weeks_plural": "{{count}} Wuche", + "generic_count_days": "{{count}} Tag", + "generic_count_days_plural": "{{count}} Täg", + "generic_count_hours": "{{count}} Stund", + "generic_count_hours_plural": "{{count}} Stunde", + "generic_count_minutes": "{{count}} Minute", + "generic_count_minutes_plural": "{{count}} Minute", + "generic_count_seconds": "{{count}} Sekunde", + "generic_count_seconds_plural": "{{count}} Sekunde", + "Fallback comments: ": "Alternativi Kommentär: ", + "Popular": "Populär", + "Search": "Sueche", + "Top": "Top", + "About": "Über", + "Rating: ": "Bewertig: ", + "preferences_locale_label": "Spraach: ", + "View as playlist": "Als Widergabelischte aazeige", + "Default": "Standard", + "Music": "Musig", + "Gaming": "Videospiel", + "News": "Neuigkeite", + "Movies": "Film", + "Download": "Abelade", + "Download as: ": "Abelade als: ", + "Download is disabled": "Abelade isch deaktiviert", + "%A %B %-d, %Y": "%A %-d %B %Y", + "(edited)": "(bearbeitet)", + "YouTube comment permalink": "YouTube-Kommentar Permalink", + "permalink": "Permalink", + "`x` marked it with a ❤": "`x` hets mitme ❤ markiert", + "Channel Sponsor": "Kanalsponsor", + "Audio mode": "Audiomodus", + "Video mode": "Videomodus", + "Playlists": "Widergabelischtene", + "search_filters_title": "Filtere", + "search_filters_date_label": "Upload-Datum", + "search_filters_date_option_none": "Bliebigs Datum", + "search_filters_date_option_hour": "Letschti Stund", + "search_filters_date_option_today": "Hüt", + "search_filters_date_option_week": "Die Wuche", + "search_filters_date_option_month": "De Monet", + "search_filters_date_option_year": "Das Jahr", + "search_filters_type_label": "Inhaltstyp", + "search_filters_type_option_all": "Bliebige Typ", + "search_filters_type_option_video": "Video", + "search_filters_type_option_channel": "Kanal", + "search_filters_type_option_playlist": "Widergabelischte", + "search_filters_type_option_movie": "Film", + "search_filters_type_option_show": "Aazeige", + "search_filters_duration_label": "Duur", + "search_filters_duration_option_none": "Bliebigi Längi", + "search_filters_duration_option_short": "Churz (< 4 Minute)", + "search_filters_duration_option_medium": "Mittel (4 - 20 Minute)", + "search_filters_duration_option_long": "Lang (> 20 Minute)", + "search_filters_features_label": "Eigeschafte", + "search_filters_features_option_live": "Live", + "search_filters_features_option_four_k": "4K", + "search_filters_features_option_hd": "HD", + "search_filters_features_option_subtitles": "Untertitel/CC", + "search_filters_features_option_c_commons": "Creative Commons", + "search_filters_features_option_three_sixty": "360°", + "search_filters_features_option_vr180": "VR180", + "search_filters_features_option_three_d": "3D", + "search_filters_features_option_hdr": "HDR", + "search_filters_features_option_location": "Standort", + "search_filters_features_option_purchased": "Kauft", + "search_filters_sort_label": "Sortiere nach", + "search_filters_sort_option_relevance": "Relevanz", + "search_filters_sort_option_rating": "Bewertig", + "search_filters_sort_option_date": "Ueladedatum", + "search_filters_sort_option_views": "Uufrüef", + "search_filters_apply_button": "Uusgwählti Filter aawende", + "Current version: ": "Aktuelli Version: ", + "next_steps_error_message": "Nachher das versueche: ", + "next_steps_error_message_refresh": "Aktualisiere", + "next_steps_error_message_go_to_youtube": "Zu YouTube gah", + "footer_donate_page": "Spende", + "footer_documentation": "Dokumentation", + "footer_source_code": "Quellcode", + "footer_original_source_code": "Original Quellcode", + "footer_modfied_source_code": "Modifizierte Quellcode", + "adminprefs_modified_source_code_url_label": "URL zum Repository vom modifizierte Quellcode", + "none": "kei", + "videoinfo_started_streaming_x_ago": "Stream het vor `x` aagfange", + "videoinfo_watch_on_youTube": "Uf YouTube aaluege", + "videoinfo_youTube_embed_link": "Iibettet", + "videoinfo_invidious_embed_link": "Link zum Iibette", + "download_subtitles": "Untertitel - `x` (.vtt)", + "user_created_playlists": "`x` Widergabelischtene erstellt", + "user_saved_playlists": "`x` Widergabelischtene gspeicheret", + "Video unavailable": "Video nöd verfüegbar", + "preferences_save_player_pos_label": "Widergabeposition speichere: ", + "crash_page_you_found_a_bug": "Anschinend hesch du en Fehler in Invidious gfunde!", + "crash_page_before_reporting": "Bevor du en Bug meldsch, stell sicher, dass du:", + "crash_page_refresh": "Versuecht hesch, d Siite neu z lade", + "crash_page_switch_instance": "En anderi Instanz versuecht hesch", + "crash_page_read_the_faq": "S FAQ glese hesch", + "crash_page_search_issue": "Nach scho gmeldete Bugs uf GitHub gsuecht hesch", + "crash_page_report_issue": "Wenn all das nöd ghulfe het, öffne bitte es neus Problem (issue) uf GitHub (vorzugswiis uf Englisch) und füeg de folgendi Text i dini Nachricht ii (bitte übersetz de Text NÖD):", + "error_video_not_in_playlist": "S agforderete Video existiert nöd i dere Widergabelischte. Klick da, zum zur Startsiite vo de Widergabelischte z cho.", + "channel_tab_videos_label": "Videos", + "channel_tab_shorts_label": "Shorts", + "channel_tab_streams_label": "Livestreams", + "channel_tab_podcasts_label": "Podcasts", + "channel_tab_releases_label": "Veröffentlichige", + "channel_tab_courses_label": "Kürs", + "channel_tab_playlists_label": "Widergabelischtene", + "channel_tab_community_label": "Community", + "channel_tab_posts_label": "Biiträg", + "channel_tab_channels_label": "Kanäl", + "toggle_theme": "Thema wechsle", + "carousel_slide": "Siite {{current}} vo {{total}}", + "carousel_skip": "Galerie überspringe", + "carousel_go_to": "Zu Element `x` springe", + "timeline_parse_error_placeholder_heading": "Element cha nöd parsed werde", + "timeline_parse_error_placeholder_message": "Invidious isch bim Parse vo dem Element uf en Fehler gstosse. Für wiiteri Information lueg da une:", + "timeline_parse_error_show_technical_details": "Technischi Details aazeige", + "English": "Englisch", + "English (United Kingdom)": "Englisch (Vereinigts Königriich)", + "English (United States)": "Englisch (Vereinigti Staate)", + "English (auto-generated)": "Englisch (automatisch generiert)", + "Afrikaans": "Afrikaans", + "Albanian": "Albanisch", + "Amharic": "Amharisch", + "Arabic": "Arabisch", + "Armenian": "Armenisch", + "Azerbaijani": "Aserbaidschanisch", + "Bangla": "Bengalisch", + "Basque": "Baskisch", + "Belarusian": "Wiissrussisch", + "Bosnian": "Bosnisch", + "Bulgarian": "Bulgarisch", + "Burmese": "Burmesisch", + "Cantonese (Hong Kong)": "Kantonesisch (Hong Kong)", + "Catalan": "Katalanisch", + "Cebuano": "Cebuano", + "Chinese": "Chinesisch", + "Chinese (China)": "Chinesisch (China)", + "Chinese (Hong Kong)": "Chinesisch (Hong Kong)", + "Chinese (Simplified)": "Chinesisch (vereifacht)", + "Chinese (Taiwan)": "Chinesisch (Taiwan)", + "Chinese (Traditional)": "Chinesisch (traditionell)", + "Corsican": "Korsisch", + "Croatian": "Kroatisch", + "Czech": "Tschechisch", + "Danish": "Dänisch", + "Dutch": "Niederländisch", + "Dutch (auto-generated)": "Niederländisch (automatisch generiert)", + "Esperanto": "Esperanto", + "Estonian": "Estnisch", + "Filipino": "Philippinisch", + "Filipino (auto-generated)": "Philippinisch (automatisch generiert)", + "Finnish": "Finnisch", + "French": "Französisch", + "French (auto-generated)": "Französisch (automatisch generiert)", + "Galician": "Galizisch", + "Georgian": "Gerogisch", + "German": "Dütsch", + "German (auto-generated)": "Dütsch (automatisch generiert)", + "Greek": "Griechisch", + "Gujarati": "Gujarati", + "Haitian Creole": "Haitianischs Kreolisch", + "Hausa": "Hausa", + "Hawaiian": "Hawaiianisch", + "Hebrew": "Hebräisch", + "Hindi": "Hindi", + "Hmong": "Hmong", + "Hungarian": "Ungarisch", + "Icelandic": "Isländisch", + "Igbo": "Igbo", + "Indonesian": "Indonesisch", + "Indonesian (auto-generated)": "Indonesisch (automatisch generiert)", + "Interlingue": "Interlingue", + "Irish": "Irisch", + "Italian": "Italienisch", + "Italian (auto-generated)": "Italienisch (automatisch generiert)", + "Japanese": "Japanisch", + "Japanese (auto-generated)": "Japanisch (automatisch generiert)", + "Javanese": "Javanisch", + "Kannada": "Kannada", + "Kazakh": "Kasachisch", + "Khmer": "Khmer", + "Korean": "Koreanisch", + "Korean (auto-generated)": "Koreanisch (automatisch generiert)", + "Kurdish": "Kurdisch", + "Kyrgyz": "Kirgisisch", + "Lao": "Laotisch", + "Latin": "Latinisch", + "Latvian": "Lettisch", + "Lithuanian": "Litauisch", + "Luxembourgish": "Luxeburgisch", + "Macedonian": "Mazedonisch", + "Malagasy": "Madagassisch", + "Malay": "Malaiisch", + "Malayalam": "Malayalam", + "Maltese": "Maltesisch", + "Maori": "Maori", + "Marathi": "Marathi", + "Mongolian": "Mongolisch", + "Nepali": "Nepalesisch", + "Norwegian Bokmål": "Norwegisch", + "Nyanja": "Nyanja", + "Pashto": "Paschtunisch", + "Persian": "Persisch", + "Polish": "Polnisch", + "Portuguese": "Portugiesisch", + "Portuguese (auto-generated)": "Portugiesisch (automatisch generiert)", + "Portuguese (Brazil)": "Portugiesisch (Brasilie)", + "Punjabi": "Pandschabi", + "Romanian": "Rumänisch", + "Russian": "Russisch", + "Russian (auto-generated)": "Russisch (automatisch generiert)", + "Samoan": "Samoanisch", + "Scottish Gaelic": "Schottischs Gällisch", + "Serbian": "Serbisch", + "Shona": "Schona", + "Sindhi": "Sindhi", + "Sinhala": "Singhalesisch", + "Slovak": "Slowakisch", + "Slovenian": "Slowenisch", + "Somali": "Somali", + "Southern Sotho": "Südlichs Sotho", + "Spanish": "Spanisch", + "Spanish (auto-generated)": "Spanisch (automatisch generiert)", + "Spanish (Latin America)": "Spanisch (Latinamerika)", + "Spanish (Mexico)": "Spanisch (Mexiko)", + "Spanish (Spain)": "Spanisch (Spanie)", + "Sundanese": "Sundanesisch", + "Swahili": "Suaheli", + "Swedish": "Schwedisch", + "Tajik": "Tadschikisch", + "Tamil": "Tamilisch", + "Telugu": "Telugu", + "Thai": "Thailändisch", + "Turkish": "Türkisch", + "Turkish (auto-generated)": "Türkisch (automatisch generiert)", + "Ukrainian": "Ukrainisch", + "Urdu": "Urdu", + "Uzbek": "Usbekisch", + "Vietnamese": "Vietnamesisch", + "Vietnamese (auto-generated)": "Vietnamesisch (automatisch generiert)", + "Welsh": "Walisisch", + "Western Frisian": "Weschtfriesisch", + "Xhosa": "Xhosa", + "Yiddish": "Jiddisch", + "Yoruba": "Joruba", + "Zulu": "Zulu" +} From 5405320b969ca3dd5a077a66ec303a56cf4d54b8 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:40 +0200 Subject: [PATCH 105/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/nb-NO.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/nb-NO.json b/locales/nb-NO.json index 38402fed..a75383c0 100644 --- a/locales/nb-NO.json +++ b/locales/nb-NO.json @@ -39,8 +39,6 @@ "User ID": "Bruker-ID", "Password": "Passord", "Time (h:mm:ss):": "Tid (h:mm:ss):", - "Text CAPTCHA": "Tekst-CAPTCHA", - "Image CAPTCHA": "Bilde-CAPTCHA", "Sign In": "Innlogging", "Register": "Registrer", "E-mail": "E-post", From 36086ce08301640349f5127fe77edab1eb78de35 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 12 Sep 2025 17:06:44 +0200 Subject: [PATCH 106/108] Update translation files Updated by "Cleanup translation files" hook in Weblate. Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/invidious/translations/ Translation: Invidious/Invidious Translations --- locales/lmo.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/locales/lmo.json b/locales/lmo.json index 9d2fe2a8..521451b5 100644 --- a/locales/lmo.json +++ b/locales/lmo.json @@ -44,8 +44,6 @@ "JavaScript license information": "Informaziòn su la licensa JavaScript", "source": "font", "Log in": "Và dent", - "Text CAPTCHA": "Tèst del CAPTCHA", - "Image CAPTCHA": "Imàgen del CAPTCHA", "Sign In": "Ven denter", "Register": "Registres", "E-mail": "E-mail", From cf019e3b45fea1c8cacfd05637e1db0874751b5f Mon Sep 17 00:00:00 2001 From: syeopite <70992037+syeopite@users.noreply.github.com> Date: Sat, 13 Sep 2025 17:44:38 +0000 Subject: [PATCH 107/108] Release v2.20250913.0 (#5463) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This release primarily marks Invidious companion's ascend out of beta and its stable integration thereof into Invidious! For those unaware Invidious companion is the successor to the `inv-sig-helper` tool, designed to securely pass YouTube's attestation checks and allow for the efficient retrieval and playback of video streams reliably. Companion delivers YouTube fixes faster since it’s built on the community-driven [YouTube.js](https://github.com/LuanRT/YouTube.js) project, used by many open source projects such as [FreeTube](https://github.com/FreeTubeApp/FreeTube). For more information see https://github.com/iv-org/invidious-companion and https://docs.invidious.io/installation/ But companion isn't the only new thing in this release! Invidious will no longer error out completely as soon as a single item failed to parse in search results, channel pages, etc. Instead it now handles it gracefully by substituting those problematic items with an error card and rendering the page normally. The player has gained some quality of life features such as being able to choose a default playlist for videos to be added to, or persisting caption appearance settings across the session. Base Invidious video retrieval without Invidious companion has also been made more stable. And finally a significant amount of bugs were fixed alongside many other minor improvements. Co-authored-by: Émilien (perso) <4016501+unixfox@users.noreply.github.com> --- CHANGELOG.md | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++ shard.yml | 2 +- 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56fbe7f3..fe0c7a1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,140 @@ ## vX.Y.0 (future) +## v2.20250913.0 + +### Wrap-up + +This release primarily marks Invidious companion's ascend out of beta and its stable integration thereof into Invidious! + +For those unaware Invidious companion is the successor to the `inv-sig-helper` tool, designed to securely pass YouTube's attestation checks and allow for the efficient retrieval and playback of video streams reliably. + +Companion delivers YouTube fixes faster since it’s built on the community-driven [YouTube.js](https://github.com/LuanRT/YouTube.js) project, used by many open source projects such as [FreeTube](https://github.com/FreeTubeApp/FreeTube). + +For more information see https://github.com/iv-org/invidious-companion and https://docs.invidious.io/installation/ + +But companion isn't the only new thing in this release! + +Invidious will no longer error out completely as soon as a single item failed to parse in search results, channel pages, etc. Instead it now handles it gracefully by substituting those problematic items with an error card and rendering the page normally. + +The player has gained some quality of life features such as being able to choose a default playlist for videos to be added to, or persisting caption appearance settings across the session. + +Base Invidious video retrieval without Invidious companion has also been made more stable. + +And finally a significant amount of bugs were fixed alongside many other minor improvements. + +### New features & important changes +#### For Users + - DASH is now enabled by default due to YouTube's removal of the 720p non-dash streams + - Javascript licencing info has been added to all of Invidious' scripts, restoring full compatibility with LibreJS + - There is no longer an option for a text captcha during registration due to the shutdown (presumably) of the upstream service + - Parse errors in feeds will no longer render the entire feed unusable and instead will substitute only the broken items with error cards + - Keyboard shortcuts have been added to configure caption styles: + - `-`,`=` can be used to change the font size + - `o` can be used to cycle the opacity of the caption text + - `w` can be used to cycle the opacity of the caption box + - Caption styles changed through the VideoJS menu will now persist + - You can now choose a default playlist to add videos to instead of needing to manually select one each time + +#### For instance owners + - Invidious companion support has been added to replace the deprecated inv-sig-helper + - **DASH is now the default resolution! Please ensure that your instances can withstand the significantly higher bandwidth usage or manually configure your instance to use non-dash streams by default** + - Invidious will now warn when it is unable to connect to the database instead of failing silently + - **The text captcha during registration has been removed due to the shutdown (presumably) of the upstream service** + +#### For developers + - Dependabot has been added to keep Github Actions and Docker dependencies up-to-date. + - CI version matrix has been bumped to the latest patch release for each minor version + - The versions of Crystal that we test in CI/CD are now: `1.12.2`, `1.13.3`, `1.14.1`, `1.15.1`, `1.16.3` + - `Kilt` is no longer a dependency of Invidious + - The ARM64 docker image builds (and the test CI) has been changed to use Github's ARM64 runner instead of QEMU + - **An "error" JSON object can now be returned in various API responses in-place of an item that has failed to parse**: + + ```json + { + "type": "parse-error", + "errorMessage": "...", + "errorBacktrace": "..." + } + ``` + +### Bugs fixed +#### User-side + - Livestream will now be properly proxied again allowing playback from the UI + - The proxy video preference for logged-in users will no longer get ignored when a default value is set by the instance + - Fixes the missing `label` key error on select search results and other feeds + - Invidious will no longer strip out spaces from search queries when navigating back from the preferences page + - Restores functionality to the `subscriptions:true` search keyword + - The channel RSS feeds will no longer have an empty title + - Individual community posts can be viewed again + - The playlists tab of channels can be viewed again + - Fix incorrect dates, region, etc of videos + - Various minor fixes were made to how video info is extracted in setups without Invidious companion to improve resiliency and chances of success + - Fix issue where the notification count becomes `TRUE` rather than an actual number +#### For instance owners + - Fixed a minor typo in config.example.yml (`effet` -> `effect`) +#### For developers + - The docker image test CI will now properly check whether Invidious has started + +### Full list of pull requests merged since the last release (newest first) + +* Add Invidious companion support (https://github.com/iv-org/invidious/pull/4985, by @unixfox) +* Bump shards.yml version to dev version (https://github.com/iv-org/invidious/pull/5206, by @syeopite) +* chore: enforce 16 characters for invidious_companion_key (https://github.com/iv-org/invidious/pull/5220, by @unixfox) +* chore: set dash by default (https://github.com/iv-org/invidious/pull/5216, by @unixfox) +* Fix minor casing issues in brand names (https://github.com/iv-org/invidious/pull/5258, thanks @efb4f5ff-1298-471a-8973-3d47447115dc) +* feat: route to invidious companion on downloads (https://github.com/iv-org/invidious/pull/5224, by @alexmaras) +* Fix proxying live DASH streams (https://github.com/iv-org/invidious/pull/4589, thanks @absidue) +* Reflect companion secret character limit in example config comment (https://github.com/iv-org/invidious/pull/5269, thanks @Vyquos) +* chore: Add dependabot for docker and github actions (https://github.com/iv-org/invidious/pull/5285, by @unixfox) +* Bump actions/stale from 8 to 9 (https://github.com/iv-org/invidious/pull/5291, thanks @dependabot[bot]) +* Bump actions/cache from 3 to 4 (https://github.com/iv-org/invidious/pull/5289, thanks @dependabot[bot]) +* Bump alpine from 3.20 to 3.21 in /docker (https://github.com/iv-org/invidious/pull/5288, thanks @dependabot[bot]) +* Bump docker/build-push-action from 5 to 6 (https://github.com/iv-org/invidious/pull/5287, thanks @dependabot[bot]) +* Bump crystal-lang/install-crystal from 1.8.0 to 1.8.2 (https://github.com/iv-org/invidious/pull/5286, thanks @dependabot[bot]) +* Bump crystallang/crystal from 1.12.2-alpine to 1.16.2-alpine in /docker (https://github.com/iv-org/invidious/pull/5290, thanks @dependabot[bot]) +* Bump crystallang/crystal from 1.16.2-alpine to 1.16.3-alpine in /docker (https://github.com/iv-org/invidious/pull/5301, thanks @dependabot[bot]) +* CI: Bump Crystal version matrix (https://github.com/iv-org/invidious/pull/5293, by @Fijxu) +* fix(typo): 'Salect' -> 'Select' (https://github.com/iv-org/invidious/pull/5242, by @Fijxu) +* fix: set CSP header after setting preferences of registered users (https://github.com/iv-org/invidious/pull/5275, by @Fijxu) +* fix: safely access "label" key (https://github.com/iv-org/invidious/pull/5282, by @Fijxu) +* Add missing javascript licenses (https://github.com/iv-org/invidious/pull/5292, by @Fijxu) +* Add Javascript licence information automatically (https://github.com/iv-org/invidious/pull/5297, by @syeopite) +* Remove text captcha due to textcaptcha.com being down (https://github.com/iv-org/invidious/pull/5308, by @Fijxu) +* Release versioning maintenance (https://github.com/iv-org/invidious/pull/5310, by @syeopite) +* Update Kemal to 1.6.0 and remove Kilt (https://github.com/iv-org/invidious/pull/5120, by @syeopite) +* Translations update from Hosted Weblate (https://github.com/iv-org/invidious/pull/5192, thanks @weblate) +* require base_job before the other jobs (https://github.com/iv-org/invidious/pull/5194, by @Fijxu) +* Handle parse errors gracefully on timeline items (https://github.com/iv-org/invidious/pull/5196, by @syeopite) +* fix: do not strip '+' character from referer (https://github.com/iv-org/invidious/pull/5276, by @Fijxu) +* fix: pass user to `query.process` if present. (https://github.com/iv-org/invidious/pull/5277, by @Fijxu) +* Add missing xml.text on "title" element for channels RSS (https://github.com/iv-org/invidious/pull/5320, by @Fijxu) +* Remove `@iv-org/developers` from codeowners (https://github.com/iv-org/invidious/pull/5314, by @syeopite) +* Make base-Invidious video info extraction more resilient (https://github.com/iv-org/invidious/pull/5312, by @syeopite) +* Bump actions/checkout from 4 to 5 (https://github.com/iv-org/invidious/pull/5415, thanks @dependabot[bot]) +* Player: Add keyboard shortcuts to configure captions (https://github.com/iv-org/invidious/pull/5188, thanks @epicsam123) +* CI: Use public ARM64 Github actions runners for ARM64 builds. (https://github.com/iv-org/invidious/pull/5305, by @Fijxu) +* CI: Fix docker ci job not checking if Invidious starts successfully or not (https://github.com/iv-org/invidious/pull/5306, by @Fijxu) +* YtAPI: Bump client versions (https://github.com/iv-org/invidious/pull/5325, by @Fijxu) +* YTAPI: Add `TvSimply` client (https://github.com/iv-org/invidious/pull/5344, by @Fijxu) +* Videos: Add fallback to TvSimply client (https://github.com/iv-org/invidious/pull/5345, by @Fijxu) +* Show message when connection to the database is not possible (https://github.com/iv-org/invidious/pull/5346, by @Fijxu) +* Channels: Fix fetching of individual community posts (https://github.com/iv-org/invidious/pull/5361, thanks @ChunkyProgrammer) +* Videos: Fix missing .id to retrieve first playlist video ID (https://github.com/iv-org/invidious/pull/5366, by @SamantazFox) +* HTML: Add Missing Noreferrers (https://github.com/iv-org/invidious/pull/5368, thanks @epicsam123) +* Documentation: Fix typo (effet -> effect) (https://github.com/iv-org/invidious/pull/5369, thanks @nsunami) +* Frontend: Fix notification count of `TRUE` (https://github.com/iv-org/invidious/pull/5391, thanks @fieryhenry) +* Player: Persist caption settings (https://github.com/iv-org/invidious/pull/5417, thanks @p-himik) +* Channels: Fix fetching channel playlists (https://github.com/iv-org/invidious/pull/5418, thanks @KrisVos130) +* CI: fix wrong if statement for build-docker job (https://github.com/iv-org/invidious/pull/5442, by @Fijxu) +* initial base_url companion support + proxy companion (https://github.com/iv-org/invidious/pull/5266, by @unixfox) +* Prevent player microformat from being overwritten by the next microformat (https://github.com/iv-org/invidious/pull/5453, by @Fijxu) +* Bump actions/stale from 9 to 10 (https://github.com/iv-org/invidious/pull/5457, thanks @dependabot[bot]) +* Better documentation for the specific case public_url with companion (https://github.com/iv-org/invidious/pull/5461, by @unixfox) +* Add default playlist preference (https://github.com/iv-org/invidious/pull/5449, by @Fijxu) +* Translations update from Hosted Weblate (https://github.com/iv-org/invidious/pull/5313, thanks to our many translators) +* Release `v2.20250913.0` (https://github.com/iv-org/invidious/pull/5463, by @syeopite) + ## v2.20250517.0 Inverse fallback for the YouTube client from TVHTML then MWEB. Fixes https://github.com/iv-org/invidious/issues/5273 diff --git a/shard.yml b/shard.yml index 839ebca5..f6b9ef86 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 2.20250517.0-dev +version: 2.20250913.0 authors: - Invidious team From 325e013e0d9e5670fa0df7635ff30a0ee029e05e Mon Sep 17 00:00:00 2001 From: syeopite Date: Sat, 13 Sep 2025 11:55:10 -0700 Subject: [PATCH 108/108] Prepare for the next release --- shard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shard.yml b/shard.yml index f6b9ef86..4dc8aa02 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 2.20250913.0 +version: 2.20250913.0-dev authors: - Invidious team