Merge branch 'iv-org:master' into master

This commit is contained in:
Theo Luis Fischer 2025-09-15 22:17:49 +02:00 committed by GitHub
commit 189e6aab11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
90 changed files with 1669 additions and 578 deletions

View File

@ -17,17 +17,27 @@ on:
jobs: jobs:
release: release:
runs-on: ubuntu-latest strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
name: "AMD64"
dockerfile: "docker/Dockerfile"
tag_suffix: ""
# GitHub doesn't have a ubuntu-latest-arm runner
- os: ubuntu-24.04-arm
platform: linux/arm64/v8
name: "ARM64"
dockerfile: "docker/Dockerfile.arm64"
tag_suffix: "-arm64"
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v5
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@ -43,45 +53,22 @@ jobs:
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: quay.io/invidious/invidious images: quay.io/invidious/invidious
flavor: |
suffix=${{ matrix.tag_suffix }}
tags: | tags: |
type=sha,format=short,prefix={{date 'YYYY.MM.DD'}}-,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} 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') }} type=raw,value=master,enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
labels: | labels: |
quay.expires-after=12w 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 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: docker/Dockerfile file: ${{ matrix.dockerfile }}
platforms: linux/amd64 platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
build-args: | build-args: |
"release=1" "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"

View File

@ -8,17 +8,27 @@ on:
jobs: jobs:
release: release:
runs-on: ubuntu-latest strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
name: "AMD64"
dockerfile: "docker/Dockerfile"
tag_suffix: ""
# GitHub doesn't have a ubuntu-latest-arm runner
- os: ubuntu-24.04-arm
platform: linux/arm64/v8
name: "ARM64"
dockerfile: "docker/Dockerfile.arm64"
tag_suffix: "-arm64"
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v5
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@ -36,46 +46,21 @@ jobs:
images: quay.io/invidious/invidious images: quay.io/invidious/invidious
flavor: | flavor: |
latest=false latest=false
suffix=${{ matrix.tag_suffix }}
tags: | tags: |
type=semver,pattern={{version}} type=semver,pattern={{version}}
type=raw,value=latest type=raw,value=latest
labels: | labels: |
quay.expires-after=12w 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 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: docker/Dockerfile file: ${{ matrix.dockerfile }}
platforms: linux/amd64 platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
build-args: | build-args: |
"release=1" "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"

View File

@ -83,46 +83,43 @@ jobs:
run: crystal build --warnings all --error-on-warnings --error-trace src/invidious.cr run: crystal build --warnings all --error-on-warnings --error-trace src/invidious.cr
build-docker: build-docker:
strategy:
matrix:
include:
- os: ubuntu-latest
name: "AMD64"
# GitHub doesn't have a ubuntu-latest-arm runner
- os: ubuntu-24.04-arm
name: "ARM64"
runs-on: ubuntu-latest name: Test ${{ matrix.name }} Docker build
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- name: Use ARM64 Dockerfile if ARM64
if: ${{ matrix.name == 'ARM64' }}
run: sed -i 's/Dockerfile/Dockerfile.arm64/' docker-compose.yml
- name: Build Docker - name: Build Docker
run: docker compose build --build-arg release=0 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 - name: Run Docker
run: docker compose up -d run: docker compose up -d
- name: Test Docker - 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
build-docker-arm64: - name: Print Invidious container logs
# Tells Github Actions to always run this step regardless of whether the previous step has failed
runs-on: ubuntu-latest # Without this expression this step would simply be skipped when the previous step fails.
if: success() || steps.test.conclusion == 'failure'
steps: run: docker compose logs
- uses: actions/checkout@v5
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- 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: Test Docker
run: while curl -Isf http://localhost:3000; do sleep 1; done
lint: lint:

View File

@ -10,7 +10,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v10
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 730 days-before-stale: 730

View File

@ -2,6 +2,140 @@
## vX.Y.0 (future) ## 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 its 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 ## v2.20250517.0
Inverse fallback for the YouTube client from TVHTML then MWEB. Fixes https://github.com/iv-org/invidious/issues/5273 Inverse fallback for the YouTube client from TVHTML then MWEB. Fixes https://github.com/iv-org/invidious/issues/5273

View File

@ -86,6 +86,7 @@ ul.vjs-menu-content::-webkit-scrollbar {
background-color: rgba(0, 0, 0, 0.75) !important; background-color: rgba(0, 0, 0, 0.75) !important;
border-radius: 9px !important; border-radius: 9px !important;
padding: 5px !important; padding: 5px !important;
line-height: 1.5 !important;
} }
.vjs-play-control, .vjs-play-control,

View File

@ -77,7 +77,7 @@ function create_notification_stream(subscriptions) {
function update_ticker_count() { function update_ticker_count() {
var notification_ticker = document.getElementById('notification_ticker'); 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) || 0;
if (notification_count > 0) { if (notification_count > 0) {
notification_ticker.innerHTML = notification_ticker.innerHTML =
'<span id="notification_count">' + notification_count + '</span> <i class="icon ion-ios-notifications"></i>'; '<span id="notification_count">' + notification_count + '</span> <i class="icon ion-ios-notifications"></i>';

View File

@ -5,6 +5,10 @@ var video_data = JSON.parse(document.getElementById('video_data').textContent);
var options = { var options = {
liveui: true, liveui: true,
playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0], playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0],
fontPercent: [0.5, 0.75, 1.25, 1.5, 1.75, 2, 3, 4],
windowOpacity: ['0', '0.5', '1'],
textOpacity: ['0.5', '1'],
persistTextTrackSettings: true,
controlBar: { controlBar: {
children: [ children: [
'playToggle', 'playToggle',
@ -180,7 +184,7 @@ var shareOptions = {
}; };
if (location.pathname.startsWith('/embed/')) { if (location.pathname.startsWith('/embed/')) {
var overlay_content = '<h1><a rel="noopener" target="_blank" href="' + location.origin + '/watch?v=' + video_data.id + '">' + player_data.title + '</a></h1>'; var overlay_content = '<h1><a rel="noopener noreferrer" target="_blank" href="' + location.origin + '/watch?v=' + video_data.id + '">' + player_data.title + '</a></h1>';
player.overlay({ player.overlay({
overlays: [ overlays: [
{ start: 'loadstart', content: overlay_content, end: 'playing', align: 'top'}, { start: 'loadstart', content: overlay_content, end: 'playing', align: 'top'},
@ -450,7 +454,7 @@ if (!video_data.params.listen && video_data.params.annotations) {
if (target === 'current') { if (target === 'current') {
location.href = path; location.href = path;
} else if (target === 'new') { } else if (target === 'new') {
open(path, '_blank'); open(path, '_blank', 'noopener,noreferrer');
} }
}); });
@ -585,6 +589,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() { function toggle_fullscreen() {
player.isFullscreen() ? player.exitFullscreen() : player.requestFullscreen(); player.isFullscreen() ? player.exitFullscreen() : player.requestFullscreen();
} }
@ -597,6 +608,34 @@ function increase_playback_rate(steps) {
player.playbackRate(options.playbackRates[newIndex]); player.playbackRate(options.playbackRates[newIndex]);
} }
function increase_caption_size(steps) {
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);
player.textTrackSettings.setValues({ fontPercent: options.fontPercent[newIndex] });
update_captions();
}
function toggle_caption_window() {
const numOptions = options.windowOpacity.length;
const windowOpacity = player.textTrackSettings.getValues().windowOpacity || '0';
const curIndex = options.windowOpacity.indexOf(windowOpacity);
const newIndex = (curIndex + 1) % numOptions;
player.textTrackSettings.setValues({ windowOpacity: options.windowOpacity[newIndex] });
update_captions();
}
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;
player.textTrackSettings.setValues({ textOpacity: options.textOpacity[newIndex] });
update_captions();
}
addEventListener('keydown', function (e) { addEventListener('keydown', function (e) {
if (e.target.tagName.toLowerCase() === 'input') { if (e.target.tagName.toLowerCase() === 'input') {
// Ignore input when focus is on certain elements, e.g. form fields. // Ignore input when focus is on certain elements, e.g. form fields.
@ -693,6 +732,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_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: default:
console.info('Unhandled key down event: %s:', decoratedKey, e); console.info('Unhandled key down event: %s:', decoratedKey, e);
break; break;

View File

@ -141,7 +141,7 @@ function get_reddit_comments() {
</b> \ </b> \
</p> \ </p> \
<b> \ <b> \
<a rel="noopener" target="_blank" href="https://reddit.com{permalink}">{redditPermalinkText}</a> \ <a rel="noopener noreferrer" target="_blank" href="https://reddit.com{permalink}">{redditPermalinkText}</a> \
</b> \ </b> \
</div> \ </div> \
<div>{contentHtml}</div> \ <div>{contentHtml}</div> \

View File

@ -61,31 +61,32 @@ db:
## When this setting is commented out, Invidious companion is not used. ## When this setting is commented out, Invidious companion is not used.
## Otherwise, Invidious will proxy the requests to Invidious companion. ## 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 ## 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 ## 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 ## to work. Once said cache has expired, requesting that video's data
## again will cause a new companion URL to be picked. ## again will cause a new companion URL to be picked.
## ##
## The parameter private_url needs to be configured for the internal ## The parameter private_url is required for the internal communication
## communication between the companion and Invidious. ## between Invidious companion and Invidious.
## And public_url is the public URL from which companion is listening
## to the requests from the user(s).
## ##
## If you are using a reverse proxy then you will probably need to ## The optional parameter public_url is the public URL from which
## configure the public_url to be the same as the domain used for Invidious. ## Invidious companion is listening to the requests from the user(s).
## Also apply when used from an external IP address (without a domain). ## When this setting is commented out, Invidious proxy all requests to
## Examples: https://MYINVIDIOUSDOMAIN or http://192.168.1.100:8282 ## Invidious companion. Useful for simple setups.
## ## Otherwise, requests from the user(s) will reach Invidious companion directly.
## Both parameter can have identical URL when Invidious is hosted in ## And you will need to configure a reverse proxy with separate routes
## an internal network or at home or locally (localhost). ## 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)://<IP-HOSTNAME>:<Port>" ## Accepted values: "http(s)://<IP-HOSTNAME>:<Port>"
## Default: <none> ## Default: <none>
## ##
#invidious_companion: #invidious_companion:
# - private_url: "http://localhost:8282" # - private_url: "http://localhost:8282/companion"
# public_url: "http://localhost:8282" # # Uncomment for advanced reverse proxy configuration (see above).
# # public_url: "http://localhost:8282/companion"
## ##
## API key for Invidious companion, used for securing the communication ## API key for Invidious companion, used for securing the communication
@ -865,7 +866,7 @@ default_user_preferences:
## ##
## Default dash video quality. ## 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". ## 'quality' parameter is set to "dash".
## ##
## Accepted values: ## Accepted values:

View File

@ -14,6 +14,10 @@ services:
restart: unless-stopped restart: unless-stopped
ports: ports:
- "127.0.0.1:3000:3000" - "127.0.0.1:3000:3000"
depends_on:
invidious-db:
condition: service_healthy
restart: true
environment: environment:
# Please read the following file for a comprehensive list of all available # Please read the following file for a comprehensive list of all available
# configuration options and their associated syntax: # configuration options and their associated syntax:

View File

@ -39,8 +39,6 @@
"User ID": "مُعرِّف المُستخدم", "User ID": "مُعرِّف المُستخدم",
"Password": "كلمة المرور", "Password": "كلمة المرور",
"Time (h:mm:ss):": "الوقت (h:mm:ss):", "Time (h:mm:ss):": "الوقت (h:mm:ss):",
"Text CAPTCHA": "نص الكابتشا",
"Image CAPTCHA": "صورة الكابتشا",
"Sign In": "إنشاء حساب", "Sign In": "إنشاء حساب",
"Register": "التسجيل", "Register": "التسجيل",
"E-mail": "البريد الإلكتروني", "E-mail": "البريد الإلكتروني",
@ -569,5 +567,8 @@
"Filipino (auto-generated)": "الفلبينية (المولدة تلقائيًا)", "Filipino (auto-generated)": "الفلبينية (المولدة تلقائيًا)",
"channel_tab_courses_label": "الدورات", "channel_tab_courses_label": "الدورات",
"channel_tab_posts_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": "عرض التفاصيل التقنية"
} }

View File

@ -102,7 +102,6 @@
"Spanish (Spain)": "Испански (Испания)", "Spanish (Spain)": "Испански (Испания)",
"invidious": "Invidious", "invidious": "Invidious",
"crash_page_refresh": "пробвал да <a href=\"`x`\">опресниш страницата</a>", "crash_page_refresh": "пробвал да <a href=\"`x`\">опресниш страницата</a>",
"Image CAPTCHA": "CAPTCHA с Изображение",
"search_filters_features_option_hd": "HD", "search_filters_features_option_hd": "HD",
"Chinese (Hong Kong)": "Китайски (Хонг Конг)", "Chinese (Hong Kong)": "Китайски (Хонг Конг)",
"Import Invidious data": "Импортиране на Invidious JSON информацията", "Import Invidious data": "Импортиране на Invidious JSON информацията",
@ -457,7 +456,6 @@
"next_steps_error_message": "След което можеш да пробваш да: ", "next_steps_error_message": "След което можеш да пробваш да: ",
"Hide annotations": "Скрий анотации", "Hide annotations": "Скрий анотации",
"Standard YouTube license": "Стандартен YouTube лиценз", "Standard YouTube license": "Стандартен YouTube лиценз",
"Text CAPTCHA": "Текст CAPTCHA",
"Log in/register": "Вход/регистрация", "Log in/register": "Вход/регистрация",
"Punjabi": "Пенджаби", "Punjabi": "Пенджаби",
"Change password": "Смяна на паролата", "Change password": "Смяна на паролата",

View File

@ -36,8 +36,6 @@
"User ID": "ইউজার আইডি", "User ID": "ইউজার আইডি",
"Password": "পাসওয়ার্ড", "Password": "পাসওয়ার্ড",
"Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):", "Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):",
"Text CAPTCHA": "টেক্সট ক্যাপচা",
"Image CAPTCHA": "চিত্র ক্যাপচা",
"Sign In": "সাইন ইন", "Sign In": "সাইন ইন",
"Register": "নিবন্ধন", "Register": "নিবন্ধন",
"E-mail": "ই-মেইল", "E-mail": "ই-মেইল",

View File

@ -39,8 +39,6 @@
"User ID": "ইউজার আইডি", "User ID": "ইউজার আইডি",
"Password": "পাসওয়ার্ড", "Password": "পাসওয়ার্ড",
"Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):", "Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):",
"Text CAPTCHA": "টেক্সট ক্যাপচা",
"Image CAPTCHA": "চিত্র ক্যাপচা",
"Sign In": "সাইন ইন", "Sign In": "সাইন ইন",
"Register": "নিবন্ধন", "Register": "নিবন্ধন",
"E-mail": "ই-মেইল", "E-mail": "ই-মেইল",

View File

@ -167,7 +167,6 @@
"comments_points_count_plural": "{{count}} punts", "comments_points_count_plural": "{{count}} punts",
"%A %B %-d, %Y": "%A %B %-d, %Y", "%A %B %-d, %Y": "%A %B %-d, %Y",
"Create playlist": "Crear llista de reproducció", "Create playlist": "Crear llista de reproducció",
"Text CAPTCHA": "Text CAPTCHA",
"Next page": "Pàgina següent", "Next page": "Pàgina següent",
"preferences_category_visual": "Preferències visuals", "preferences_category_visual": "Preferències visuals",
"preferences_unseen_only_label": "Mostra només no vistos: ", "preferences_unseen_only_label": "Mostra només no vistos: ",
@ -387,7 +386,6 @@
"Delete account?": "Esborrar compte?", "Delete account?": "Esborrar compte?",
"Please log in": "Si us plau inicieu sessió", "Please log in": "Si us plau inicieu sessió",
"Import NewPipe data (.zip)": "Importar dades de NewPipe (.zip)", "Import NewPipe data (.zip)": "Importar dades de NewPipe (.zip)",
"Image CAPTCHA": "Imatge CAPTCHA",
"channel_tab_streams_label": "Transmissions en directe", "channel_tab_streams_label": "Transmissions en directe",
"preferences_category_misc": "Preferències diverses", "preferences_category_misc": "Preferències diverses",
"preferences_annotations_subscribed_label": "Mostra les anotacions per defecte dels canals subscrits? ", "preferences_annotations_subscribed_label": "Mostra les anotacions per defecte dels canals subscrits? ",

View File

@ -39,8 +39,6 @@
"User ID": "ID uživatele", "User ID": "ID uživatele",
"Password": "Heslo", "Password": "Heslo",
"Time (h:mm:ss):": "Čas (h:mm:ss):", "Time (h:mm:ss):": "Čas (h:mm:ss):",
"Text CAPTCHA": "Textové CAPTCHA",
"Image CAPTCHA": "Obrázkové CAPTCHA",
"Sign In": "Přihlásit se", "Sign In": "Přihlásit se",
"Register": "Vytvořit účet", "Register": "Vytvořit účet",
"E-mail": "E-mail", "E-mail": "E-mail",
@ -518,5 +516,10 @@
"Filipino (auto-generated)": "Filipínština (vytvořeno automaticky)", "Filipino (auto-generated)": "Filipínština (vytvořeno automaticky)",
"First page": "První stránka", "First page": "První stránka",
"channel_tab_courses_label": "Kurzy", "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"
} }

View File

@ -162,8 +162,6 @@
"preferences_quality_dash_option_1080p": "1080p", "preferences_quality_dash_option_1080p": "1080p",
"preferences_quality_dash_option_720p": "720p", "preferences_quality_dash_option_720p": "720p",
"invidious": "Invidious", "invidious": "Invidious",
"Text CAPTCHA": "CAPTCHA testun",
"Image CAPTCHA": "CAPTCHA delwedd",
"preferences_continue_label": "Chwarae'r fideo nesaf fel rhagosodiad: ", "preferences_continue_label": "Chwarae'r fideo nesaf fel rhagosodiad: ",
"preferences_continue_autoplay_label": "Chwarae'r fideo nesaf yn awtomatig: ", "preferences_continue_autoplay_label": "Chwarae'r fideo nesaf yn awtomatig: ",
"preferences_listen_label": "Sain yn unig: ", "preferences_listen_label": "Sain yn unig: ",

View File

@ -39,8 +39,6 @@
"User ID": "Bruger ID", "User ID": "Bruger ID",
"Password": "Kodeord", "Password": "Kodeord",
"Time (h:mm:ss):": "Tid (t:mm:ss):", "Time (h:mm:ss):": "Tid (t:mm:ss):",
"Text CAPTCHA": "Tekst CAPTCHA",
"Image CAPTCHA": "Billede CAPTCHA",
"Sign In": "Log ind", "Sign In": "Log ind",
"Register": "Registrer", "Register": "Registrer",
"E-mail": "E-mail", "E-mail": "E-mail",

View File

@ -12,7 +12,7 @@
"Next page": "Nächste Seite", "Next page": "Nächste Seite",
"Previous page": "Vorherige Seite", "Previous page": "Vorherige Seite",
"First page": "Erste Seite", "First page": "Erste Seite",
"Clear watch history?": "Verlauf löschen?", "Clear watch history?": "Wiedergabeverlauf löschen?",
"New password": "Neues Passwort", "New password": "Neues Passwort",
"New passwords must match": "Neue Passwörter müssen übereinstimmen", "New passwords must match": "Neue Passwörter müssen übereinstimmen",
"Authorize token?": "Token autorisieren?", "Authorize token?": "Token autorisieren?",
@ -40,8 +40,6 @@
"User ID": "Benutzer-ID", "User ID": "Benutzer-ID",
"Password": "Passwort", "Password": "Passwort",
"Time (h:mm:ss):": "Zeit (h:mm:ss):", "Time (h:mm:ss):": "Zeit (h:mm:ss):",
"Text CAPTCHA": "Text CAPTCHA",
"Image CAPTCHA": "Bild CAPTCHA",
"Sign In": "Anmelden", "Sign In": "Anmelden",
"Register": "Registrieren", "Register": "Registrieren",
"E-mail": "E-Mail", "E-mail": "E-Mail",
@ -108,11 +106,11 @@
"Top enabled: ": "Top aktiviert? ", "Top enabled: ": "Top aktiviert? ",
"CAPTCHA enabled: ": "CAPTCHA aktiviert? ", "CAPTCHA enabled: ": "CAPTCHA aktiviert? ",
"Login enabled: ": "Anmeldung aktiviert: ", "Login enabled: ": "Anmeldung aktiviert: ",
"Registration enabled: ": "Registrierung aktiviert? ", "Registration enabled: ": "Registrierung aktiviert: ",
"Report statistics: ": "Statistiken berichten? ", "Report statistics: ": "Statistiken berichten: ",
"Save preferences": "Einstellungen speichern", "Save preferences": "Einstellungen speichern",
"Subscription manager": "Abonnementverwaltung", "Subscription manager": "Abonnementverwaltung",
"Token manager": "Tokenverwalter", "Token manager": "Tokenverwaltung",
"Token": "Token", "Token": "Token",
"Import/export": "Importieren/Exportieren", "Import/export": "Importieren/Exportieren",
"unsubscribe": "abbestellen", "unsubscribe": "abbestellen",
@ -122,20 +120,20 @@
"Log out": "Abmelden", "Log out": "Abmelden",
"Released under the AGPLv3 on Github.": "Auf GitHub unter der AGPLv3 Lizenz veröffentlicht.", "Released under the AGPLv3 on Github.": "Auf GitHub unter der AGPLv3 Lizenz veröffentlicht.",
"Source available here.": "Quellcode verfügbar hier.", "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.", "View privacy policy.": "Datenschutzerklärung einsehen.",
"Trending": "Angesagt", "Trending": "Angesagt",
"Public": "Öffentlich", "Public": "Öffentlich",
"Unlisted": "Nicht aufgeführt", "Unlisted": "Nicht gelistet",
"Private": "Privat", "Private": "Privat",
"View all playlists": "Alle Wiedergabelisten anzeigen", "View all playlists": "Alle Wiedergabelisten anzeigen",
"Updated `x` ago": "Aktualisiert `x` vor", "Updated `x` ago": "Aktualisiert vor `x`",
"Delete playlist `x`?": "Wiedergabeliste löschen `x`?", "Delete playlist `x`?": "Wiedergabeliste `x` löschen?",
"Delete playlist": "Wiedergabeliste löschen", "Delete playlist": "Wiedergabeliste löschen",
"Create playlist": "Wiedergabeliste erstellen", "Create playlist": "Wiedergabeliste erstellen",
"Title": "Titel", "Title": "Titel",
"Playlist privacy": "Vertrauliche Wiedergabeliste", "Playlist privacy": "Wiedergabelisten-Privatsphäre",
"Editing playlist `x`": "Wiedergabeliste bearbeiten `x`", "Editing playlist `x`": "Wiedergabeliste `x` bearbeiten",
"Show more": "Mehr anzeigen", "Show more": "Mehr anzeigen",
"Show less": "Weniger anzeigen", "Show less": "Weniger anzeigen",
"Watch on YouTube": "Video auf YouTube ansehen", "Watch on YouTube": "Video auf YouTube ansehen",
@ -151,12 +149,12 @@
"Blacklisted regions: ": "Unerlaubte Regionen: ", "Blacklisted regions: ": "Unerlaubte Regionen: ",
"Shared `x`": "Geteilt `x`", "Shared `x`": "Geteilt `x`",
"Premieres in `x`": "Premiere in `x`", "Premieres in `x`": "Premiere in `x`",
"Premieres `x`": "Erster Start `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! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.", "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 YouTube comments": "YouTube Kommentare anzeigen",
"View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen", "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen",
"View `x` comments": { "View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` Kommentare anzeigen", "([^.,0-9]|^)1([^.,0-9]|$)": "`x` Kommentar anzeigen",
"": "`x` Kommentare anzeigen" "": "`x` Kommentare anzeigen"
}, },
"View Reddit comments": "Reddit Kommentare anzeigen", "View Reddit comments": "Reddit Kommentare anzeigen",
@ -184,7 +182,7 @@
"Empty playlist": "Wiedergabeliste ist leer", "Empty playlist": "Wiedergabeliste ist leer",
"Not a playlist.": "Ungültige Wiedergabeliste.", "Not a playlist.": "Ungültige Wiedergabeliste.",
"Playlist does not exist.": "Wiedergabeliste existiert nicht.", "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 \"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", "Hidden field \"token\" is a required field": "Verstecktes Feld „token“ ist eine erforderliche Eingabe",
"Erroneous challenge": "Ungültiger Test", "Erroneous challenge": "Ungültiger Test",
@ -192,7 +190,7 @@
"No such user": "Ungültiger Benutzer", "No such user": "Ungültiger Benutzer",
"Token is expired, please try again": "Token ist abgelaufen, bitte erneut versuchen", "Token is expired, please try again": "Token ist abgelaufen, bitte erneut versuchen",
"English": "Englisch", "English": "Englisch",
"English (auto-generated)": "Englisch (automatisch erzeugt)", "English (auto-generated)": "Englisch (automatisch generiert)",
"Afrikaans": "Afrikaans", "Afrikaans": "Afrikaans",
"Albanian": "Albanisch", "Albanian": "Albanisch",
"Amharic": "Amharisch", "Amharic": "Amharisch",
@ -313,7 +311,7 @@
"Download": "Herunterladen", "Download": "Herunterladen",
"Download as: ": "Herunterladen als: ", "Download as: ": "Herunterladen als: ",
"%A %B %-d, %Y": "%A %-d %B %Y", "%A %B %-d, %Y": "%A %-d %B %Y",
"(edited)": "(editiert)", "(edited)": "(bearbeitet)",
"YouTube comment permalink": "YouTube-Kommentar Permalink", "YouTube comment permalink": "YouTube-Kommentar Permalink",
"permalink": "Permalink", "permalink": "Permalink",
"`x` marked it with a ❤": "`x` markierte es mit einem ❤", "`x` marked it with a ❤": "`x` markierte es mit einem ❤",
@ -321,7 +319,7 @@
"Video mode": "Videomodus", "Video mode": "Videomodus",
"channel_tab_videos_label": "Videos", "channel_tab_videos_label": "Videos",
"Playlists": "Wiedergabelisten", "Playlists": "Wiedergabelisten",
"channel_tab_community_label": "Gemeinschaft", "channel_tab_community_label": "Community",
"search_filters_sort_option_relevance": "Relevanz", "search_filters_sort_option_relevance": "Relevanz",
"search_filters_sort_option_rating": "Bewertung", "search_filters_sort_option_rating": "Bewertung",
"search_filters_sort_option_date": "Hochladedatum", "search_filters_sort_option_date": "Hochladedatum",
@ -329,7 +327,7 @@
"search_filters_type_label": "Inhaltstyp", "search_filters_type_label": "Inhaltstyp",
"search_filters_duration_label": "Dauer", "search_filters_duration_label": "Dauer",
"search_filters_features_label": "Eigenschaften", "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_hour": "Letzte Stunde",
"search_filters_date_option_today": "Heute", "search_filters_date_option_today": "Heute",
"search_filters_date_option_week": "Diese Woche", "search_filters_date_option_week": "Diese Woche",
@ -341,7 +339,7 @@
"search_filters_type_option_movie": "Film", "search_filters_type_option_movie": "Film",
"search_filters_type_option_show": "Anzeigen", "search_filters_type_option_show": "Anzeigen",
"search_filters_features_option_hd": "HD", "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_c_commons": "Creative Commons",
"search_filters_features_option_three_d": "3D", "search_filters_features_option_three_d": "3D",
"search_filters_features_option_live": "Live", "search_filters_features_option_live": "Live",
@ -358,7 +356,7 @@
"footer_modfied_source_code": "Modifizierter Quellcode", "footer_modfied_source_code": "Modifizierter Quellcode",
"footer_documentation": "Dokumentation", "footer_documentation": "Dokumentation",
"footer_source_code": "Quellcode", "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)", "search_filters_duration_option_short": "Kurz (< 4 Minuten)",
"preferences_region_label": "Land der Inhalte: ", "preferences_region_label": "Land der Inhalte: ",
"preferences_quality_option_dash": "DASH (adaptive Qualität)", "preferences_quality_option_dash": "DASH (adaptive Qualität)",
@ -397,7 +395,7 @@
"generic_videos_count_plural": "{{count}} Videos", "generic_videos_count_plural": "{{count}} Videos",
"subscriptions_unseen_notifs_count": "{{count}} ungesehene Benachrichtung", "subscriptions_unseen_notifs_count": "{{count}} ungesehene Benachrichtung",
"subscriptions_unseen_notifs_count_plural": "{{count}} ungesehene Benachrichtungen", "subscriptions_unseen_notifs_count_plural": "{{count}} ungesehene Benachrichtungen",
"crash_page_refresh": "Versucht haben, <a href=\"`x`\">die Seite neu zu laden</a>", "crash_page_refresh": "Versucht hast, <a href=\"`x`\">die Seite neu zu laden</a>",
"comments_view_x_replies": "{{count}} Antwort anzeigen", "comments_view_x_replies": "{{count}} Antwort anzeigen",
"comments_view_x_replies_plural": "{{count}} Antworten anzeigen", "comments_view_x_replies_plural": "{{count}} Antworten anzeigen",
"generic_count_years": "{{count}} Jahr", "generic_count_years": "{{count}} Jahr",
@ -406,15 +404,15 @@
"generic_count_weeks_plural": "{{count}} Wochen", "generic_count_weeks_plural": "{{count}} Wochen",
"generic_count_days": "{{count}} Tag", "generic_count_days": "{{count}} Tag",
"generic_count_days_plural": "{{count}} Tage", "generic_count_days_plural": "{{count}} Tage",
"crash_page_before_reporting": "Bevor Sie einen Bug melden, stellen Sie sicher, dass Sie:", "crash_page_before_reporting": "Bevor du einen Bug meldest, stelle sicher, dass du:",
"crash_page_switch_instance": "Eine <a href=\"`x`\">andere Instanz</a> versucht haben", "crash_page_switch_instance": "Eine <a href=\"`x`\">andere Instanz</a> versucht hast",
"generic_count_hours": "{{count}} Stunde", "generic_count_hours": "{{count}} Stunde",
"generic_count_hours_plural": "{{count}} Stunden", "generic_count_hours_plural": "{{count}} Stunden",
"generic_count_minutes": "{{count}} Minute", "generic_count_minutes": "{{count}} Minute",
"generic_count_minutes_plural": "{{count}} Minuten", "generic_count_minutes_plural": "{{count}} Minuten",
"crash_page_read_the_faq": "Das <a href=\"`x`\">FAQ</a> gelesen haben", "crash_page_read_the_faq": "Das <a href=\"`x`\">FAQ</a> gelesen hast",
"crash_page_search_issue": "Nach <a href=\"`x`\">bereits gemeldeten Bugs auf GitHub</a> gesucht haben", "crash_page_search_issue": "Nach <a href=\"`x`\">bereits gemeldeten Bugs auf GitHub</a> gesucht hast",
"crash_page_report_issue": "Wenn all dies nicht geholfen hat, <a href=\"`x`\">öffnen Sie bitte ein neues Problem (issue) auf Github</a> (vorzugsweise auf Englisch) und fügen Sie den folgenden Text in Ihre Nachricht ein (bitte übersetzen Sie diesen Text NICHT):", "crash_page_report_issue": "Wenn all dies nicht geholfen hat, <a href=\"`x`\">öffne bitte ein neues Problem (issue) auf GitHub</a> (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": "{{count}} Aufruf",
"generic_views_count_plural": "{{count}} Aufrufe", "generic_views_count_plural": "{{count}} Aufrufe",
"generic_count_seconds": "{{count}} Sekunde", "generic_count_seconds": "{{count}} Sekunde",
@ -425,7 +423,7 @@
"tokens_count_plural": "{{count}} Tokens", "tokens_count_plural": "{{count}} Tokens",
"comments_points_count": "{{count}} Punkt", "comments_points_count": "{{count}} Punkt",
"comments_points_count_plural": "{{count}} Punkte", "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": "{{count}} Monat",
"generic_count_months_plural": "{{count}} Monaten", "generic_count_months_plural": "{{count}} Monaten",
"Cantonese (Hong Kong)": "Kantonesisch (Hong Kong)", "Cantonese (Hong Kong)": "Kantonesisch (Hong Kong)",
@ -455,8 +453,8 @@
"Korean (auto-generated)": "Koreanisch (automatisch generiert)", "Korean (auto-generated)": "Koreanisch (automatisch generiert)",
"Portuguese (auto-generated)": "Portugiesisch (automatisch generiert)", "Portuguese (auto-generated)": "Portugiesisch (automatisch generiert)",
"search_filters_title": "Filtern", "search_filters_title": "Filtern",
"search_message_change_filters_or_query": "Versuchen Sie, Ihre Suchanfrage zu erweitern und/oder die Filter zu ändern.", "search_message_change_filters_or_query": "Versuche, deine Suchanfrage zu erweitern und/oder die Filter zu ändern.",
"search_message_use_another_instance": "Sie können auch <a href=\"`x`\">auf einer anderen Instanz suchen</a>.", "search_message_use_another_instance": "Du kannst auch <a href=\"`x`\">auf einer anderen Instanz suchen</a>.",
"Popular enabled: ": "„Beliebt“-Seite aktiviert: ", "Popular enabled: ": "„Beliebt“-Seite aktiviert: ",
"search_message_no_results": "Keine Ergebnisse gefunden.", "search_message_no_results": "Keine Ergebnisse gefunden.",
"search_filters_duration_option_medium": "Mittel (4 - 20 Minuten)", "search_filters_duration_option_medium": "Mittel (4 - 20 Minuten)",
@ -466,7 +464,7 @@
"search_filters_duration_option_none": "Beliebige Länge", "search_filters_duration_option_none": "Beliebige Länge",
"search_filters_date_label": "Upload-Datum", "search_filters_date_label": "Upload-Datum",
"search_filters_date_option_none": "Beliebiges Datum", "search_filters_date_option_none": "Beliebiges Datum",
"error_video_not_in_playlist": "Das angeforderte Video existiert nicht in dieser Wiedergabeliste. <a href=\"`x`\">Klicken Sie hier, um zur Startseite der Wiedergabeliste zu gelangen.</a>", "error_video_not_in_playlist": "Das angeforderte Video existiert nicht in dieser Wiedergabeliste. <a href=\"`x`\">Klicke hier, um zur Startseite der Wiedergabeliste zu gelangen.</a>",
"channel_tab_shorts_label": "Shorts", "channel_tab_shorts_label": "Shorts",
"channel_tab_streams_label": "Livestreams", "channel_tab_streams_label": "Livestreams",
"Music in this video": "Musik in diesem Video", "Music in this video": "Musik in diesem Video",
@ -501,5 +499,8 @@
"carousel_skip": "Galerie überspringen", "carousel_skip": "Galerie überspringen",
"Filipino (auto-generated)": "Philippinisch (automatisch generiert)", "Filipino (auto-generated)": "Philippinisch (automatisch generiert)",
"channel_tab_courses_label": "Kurse", "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:"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Ταυτότητα χρήστη", "User ID": "Ταυτότητα χρήστη",
"Password": "Κωδικός πρόσβασης", "Password": "Κωδικός πρόσβασης",
"Time (h:mm:ss):": "Ώρα (ω:λλ:δδ):", "Time (h:mm:ss):": "Ώρα (ω:λλ:δδ):",
"Text CAPTCHA": "Κείμενο CAPTCHA",
"Image CAPTCHA": "Εικόνα CAPTCHA",
"Sign In": "Εγγραφή", "Sign In": "Εγγραφή",
"Register": "Εγγραφή", "Register": "Εγγραφή",
"E-mail": "Ηλεκτρονικό ταχυδρομείο", "E-mail": "Ηλεκτρονικό ταχυδρομείο",

View File

@ -122,6 +122,8 @@
"Redirect homepage to feed: ": "Redirect homepage to feed: ", "Redirect homepage to feed: ": "Redirect homepage to feed: ",
"preferences_max_results_label": "Number of videos shown in feed: ", "preferences_max_results_label": "Number of videos shown in feed: ",
"preferences_sort_label": "Sort videos by: ", "preferences_sort_label": "Sort videos by: ",
"preferences_default_playlist": "Default playlist: ",
"preferences_default_playlist_none": "No default playlist set",
"published": "published", "published": "published",
"published - reverse": "published - reverse", "published - reverse": "published - reverse",
"alphabetically": "alphabetically", "alphabetically": "alphabetically",

View File

@ -39,8 +39,6 @@
"User ID": "Uzula identigilo", "User ID": "Uzula identigilo",
"Password": "Pasvorto", "Password": "Pasvorto",
"Time (h:mm:ss):": "Horo (h:mm:ss):", "Time (h:mm:ss):": "Horo (h:mm:ss):",
"Text CAPTCHA": "Teksta CAPTCHA",
"Image CAPTCHA": "Bilda CAPTCHA",
"Sign In": "Ensaluti", "Sign In": "Ensaluti",
"Register": "Registriĝi", "Register": "Registriĝi",
"E-mail": "Retpoŝto", "E-mail": "Retpoŝto",

View File

@ -39,8 +39,6 @@
"User ID": "Nombre", "User ID": "Nombre",
"Password": "Contraseña", "Password": "Contraseña",
"Time (h:mm:ss):": "Hora (h:mm:ss):", "Time (h:mm:ss):": "Hora (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA en texto",
"Image CAPTCHA": "CAPTCHA en imagen",
"Sign In": "Iniciar sesión", "Sign In": "Iniciar sesión",
"Register": "Registrarse", "Register": "Registrarse",
"E-mail": "Correo", "E-mail": "Correo",
@ -78,6 +76,8 @@
"Redirect homepage to feed: ": "Redirigir la página de inicio a la fuente: ", "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_max_results_label": "Número de videos mostrados en la fuente: ",
"preferences_sort_label": "Ordenar los videos por: ", "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": "fecha de publicación",
"published - reverse": "fecha de publicación: orden inverso", "published - reverse": "fecha de publicación: orden inverso",
"alphabetically": "alfabéticamente", "alphabetically": "alfabéticamente",
@ -317,7 +317,7 @@
"`x` marked it with a ❤": "`x` lo ha marcado con un ❤", "`x` marked it with a ❤": "`x` lo ha marcado con un ❤",
"Audio mode": "Modo de audio", "Audio mode": "Modo de audio",
"Video mode": "Modo de video", "Video mode": "Modo de video",
"channel_tab_videos_label": "Videos", "channel_tab_videos_label": "Vídeos",
"Playlists": "Listas de reproducción", "Playlists": "Listas de reproducción",
"channel_tab_community_label": "Comunidad", "channel_tab_community_label": "Comunidad",
"search_filters_sort_option_relevance": "Relevancia", "search_filters_sort_option_relevance": "Relevancia",
@ -437,7 +437,7 @@
"generic_count_seconds_2": "{{count}} segundos", "generic_count_seconds_2": "{{count}} segundos",
"crash_page_before_reporting": "Antes de notificar un error asegúrate de que has:", "crash_page_before_reporting": "Antes de notificar un error asegúrate de que has:",
"crash_page_switch_instance": "probado a <a href=\"`x`\">usar otra instancia</a>", "crash_page_switch_instance": "probado a <a href=\"`x`\">usar otra instancia</a>",
"crash_page_read_the_faq": "leído las <a href=\"`x`\">Preguntas Frecuentes</a>", "crash_page_read_the_faq": "lee las <a href=\"`x`\">Preguntas Frecuentes</a>",
"crash_page_search_issue": "buscado <a href=\"`x`\">problemas existentes en GitHub</a>", "crash_page_search_issue": "buscado <a href=\"`x`\">problemas existentes en GitHub</a>",
"crash_page_you_found_a_bug": "¡Parece que has encontrado un error en Invidious!", "crash_page_you_found_a_bug": "¡Parece que has encontrado un error en Invidious!",
"crash_page_refresh": "probado a <a href=\"`x`\">recargar la página</a>", "crash_page_refresh": "probado a <a href=\"`x`\">recargar la página</a>",
@ -480,7 +480,7 @@
"tokens_count_2": "{{count}} tokens", "tokens_count_2": "{{count}} tokens",
"search_message_use_another_instance": "También puedes <a href=\"`x`\">buscar en otra instancia</a>.", "search_message_use_another_instance": "También puedes <a href=\"`x`\">buscar en otra instancia</a>.",
"Popular enabled: ": "¿Habilitar la sección popular? ", "Popular enabled: ": "¿Habilitar la sección popular? ",
"error_video_not_in_playlist": "El video que solicitaste no existe en esta lista de reproducción. <a href=\"`x`\">Haz clic aquí para acceder a la página de inicio de la lista de reproducción.</a>", "error_video_not_in_playlist": "El vídeo que has solicitado no existe en esta lista de reproducción. <a href=\"`x`\">Haz clic aquí para acceder a la página de inicio de la lista de reproducción.</a>",
"channel_tab_streams_label": "Directos", "channel_tab_streams_label": "Directos",
"channel_tab_channels_label": "Canales", "channel_tab_channels_label": "Canales",
"channel_tab_shorts_label": "Cortos", "channel_tab_shorts_label": "Cortos",
@ -518,5 +518,8 @@
"Filipino (auto-generated)": "Filipino (generados automáticamente)", "Filipino (auto-generated)": "Filipino (generados automáticamente)",
"channel_tab_posts_label": "Publicaciones", "channel_tab_posts_label": "Publicaciones",
"First page": "Primera página", "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"
} }

View File

@ -5,7 +5,7 @@
"View channel on YouTube": "Vaata kanalit YouTube'is", "View channel on YouTube": "Vaata kanalit YouTube'is",
"Log in": "Logi sisse", "Log in": "Logi sisse",
"Log in/register": "Logi sisse/registreeru", "Log in/register": "Logi sisse/registreeru",
"Dark mode: ": "Tume režiim: ", "Dark mode: ": "Tume kujundus: ",
"generic_videos_count": "{{count}} video", "generic_videos_count": "{{count}} video",
"generic_videos_count_plural": "{{count}} videot", "generic_videos_count_plural": "{{count}} videot",
"generic_subscribers_count": "{{count}} tellija", "generic_subscribers_count": "{{count}} tellija",
@ -22,12 +22,12 @@
"last": "viimane", "last": "viimane",
"Next page": "Järgmine leht", "Next page": "Järgmine leht",
"Previous page": "Eelmine leht", "Previous page": "Eelmine leht",
"Clear watch history?": "Kustuta vaatamiste ajalugu?", "Clear watch history?": "Kas kustutame vaatamiste ajaloo?",
"New password": "Uus salasõna", "New password": "Uus salasõna",
"New passwords must match": "Uued salasõnad peavad ühtima", "New passwords must match": "Uued salasõnad peavad ühtima",
"Import and Export Data": "Impordi ja ekspordi andmed", "Import and Export Data": "Impordi ja ekspordi andmed",
"Import": "Impordi", "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 FreeTube subscriptions (.db)": "Impordi tellimused FreeTube'ist (.db)",
"Import NewPipe data (.zip)": "Impordi NewPipe'i andmed (.zip)", "Import NewPipe data (.zip)": "Impordi NewPipe'i andmed (.zip)",
"Export": "Ekspordi", "Export": "Ekspordi",
@ -37,11 +37,9 @@
"History": "Ajalugu", "History": "Ajalugu",
"JavaScript license information": "JavaScripti litsentsi info", "JavaScript license information": "JavaScripti litsentsi info",
"source": "allikas", "source": "allikas",
"User ID": "Kasutada ID", "User ID": "Kasutajatunnus",
"Password": "Salasõna", "Password": "Salasõna",
"Time (h:mm:ss):": "Aeg (h:mm:ss):", "Time (h:mm:ss):": "Aeg (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA-tekst",
"Image CAPTCHA": "CAPTCHA-foto",
"Sign In": "Logi sisse", "Sign In": "Logi sisse",
"Register": "Registreeru", "Register": "Registreeru",
"E-mail": "E-post", "E-mail": "E-post",
@ -57,48 +55,48 @@
"preferences_quality_dash_option_auto": "Automaatne", "preferences_quality_dash_option_auto": "Automaatne",
"preferences_quality_dash_option_best": "Parim", "preferences_quality_dash_option_best": "Parim",
"preferences_quality_dash_option_worst": "Halvim", "preferences_quality_dash_option_worst": "Halvim",
"preferences_volume_label": "Video helitugevus: ", "preferences_volume_label": "Video helivaljus: ",
"youtube": "YouTube", "youtube": "YouTube",
"reddit": "Reddit", "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_vr_mode_label": "Interaktiivne 360-kraadine video (vajalik WebGL): ",
"preferences_dark_mode_label": "Teema: ", "preferences_dark_mode_label": "Kujundus: ",
"dark": "tume", "dark": "tume",
"light": "hele", "light": "hele",
"preferences_category_subscription": "Tellimuse seaded", "preferences_category_subscription": "Tellimuse eelistused",
"preferences_max_results_label": "Avalehel näidatavate videote arv: ", "preferences_max_results_label": "Avalehel näidatavate videote arv: ",
"preferences_sort_label": "Sorteeri: ", "preferences_sort_label": "Sorteeri: ",
"published": "avaldatud", "published": "avaldatud",
"alphabetically": "tähestikulises järjekorras", "alphabetically": "tähestikulises järjekorras",
"alphabetically - reverse": "vastupidi tähestikulises järjekorras", "alphabetically - reverse": "vastupidi tähestikulises järjekorras",
"channel name": "kanali nimi", "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: ", "Only show latest video from channel: ": "Näita ainult viimast videot: ",
"preferences_notifications_only_label": "Näita ainult teavitusi (kui neid on): ", "preferences_notifications_only_label": "Näita ainult teavitusi (kui neid on): ",
"Enable web notifications": "Luba veebiteavitused", "Enable web notifications": "Luba veebiteavitused",
"`x` uploaded a video": "`x` laadis video üles", "`x` uploaded a video": "`x` laadis video üles",
"`x` is live": "`x` teeb otseülekannet", "`x` is live": "`x` teeb otseülekannet",
"preferences_category_data": "Andme-eelistused", "preferences_category_data": "Andme-eelistused",
"Clear watch history": "Puhasta vaatamisajalugu", "Clear watch history": "Kustuta vaatamisajalugu",
"Import/export data": "Impordi/ekspordi andmed", "Import/export data": "Impordi/ekspordi andmed",
"Change password": "Muuda salasõna", "Change password": "Muuda salasõna",
"Watch history": "Vaatamisajalugu", "Watch history": "Vaatamisajalugu",
"Delete account": "Kustuta kasutaja", "Delete account": "Kustuta kasutaja",
"Save preferences": "Salvesta eelistused", "Save preferences": "Salvesta eelistused",
"Token": "Token", "Token": "Tunnusluba",
"Import/export": "Imprort/eksport", "Import/export": "Imprort/eksport",
"unsubscribe": "loobu tellimusest", "unsubscribe": "loobu tellimusest",
"Subscriptions": "Tellimused", "Subscriptions": "Tellimused",
"search": "otsi", "search": "otsi",
"Source available here.": "Allikas on kättesaadaval siin.", "Source available here.": "Lähtekood on kättesaadaval siin.",
"View privacy policy.": "Vaata privaatsuspoliitikat.", "View privacy policy.": "Vaata andmekaitsepõhimõtteid.",
"Public": "Avalik", "Public": "Avalik",
"Private": "Privaatne", "Private": "Privaatne",
"View all playlists": "Vaata kõiki esitusloendeid", "View all playlists": "Vaata kõiki esitusloendeid",
"Updated `x` ago": "Uuendas `x` tagasi", "Updated `x` ago": "Uuendas `x` tagasi",
"Delete playlist `x`?": "Kustuta esitusloend `x`?", "Delete playlist `x`?": "Kustuta esitusloend `x`?",
"Delete playlist": "Kustuta esitusloend", "Delete playlist": "Kustuta esitusloend",
"Create playlist": "Loo esitlusloend", "Create playlist": "Koosta esitlusloend",
"Title": "Pealkiri", "Title": "Pealkiri",
"Playlist privacy": "Esitusloendi privaatsus", "Playlist privacy": "Esitusloendi privaatsus",
"Show more": "Näita rohkem", "Show more": "Näita rohkem",
@ -117,14 +115,14 @@
"Show replies": "Näita vastuseid", "Show replies": "Näita vastuseid",
"Incorrect password": "Vale salasõna", "Incorrect password": "Vale salasõna",
"Wrong answer": "Vale vastus", "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", "Password is a required field": "Salasõna on kohustuslik väli",
"Wrong username or password": "Vale kasutajanimi või salasõna", "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 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", "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`", "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.", "This channel does not exist.": "Sellist kanalit pole olemas.",
"comments_view_x_replies": "{{count}} vastus", "comments_view_x_replies": "{{count}} vastus",
"comments_view_x_replies_plural": "{{count}} vastust", "comments_view_x_replies_plural": "{{count}} vastust",
@ -134,86 +132,86 @@
"Not a playlist.": "Tegu pole esitusloendiga.", "Not a playlist.": "Tegu pole esitusloendiga.",
"Playlist does not exist.": "Seda esitusloendit pole olemas.", "Playlist does not exist.": "Seda esitusloendit pole olemas.",
"No such user": "Sellist kasutajat pole", "No such user": "Sellist kasutajat pole",
"English": "Inglise", "English": "inglise",
"English (United Kingdom)": "Inglise (Suurbritannia)", "English (United Kingdom)": "inglise (Suurbritannia)",
"English (United States)": "Inglise (USA)", "English (United States)": "inglise (USA)",
"English (auto-generated)": "Inglise (automaatselt koostatud)", "English (auto-generated)": "inglise (automaatselt koostatud)",
"Afrikaans": "Afrikaani", "Afrikaans": "afrikaani",
"Albanian": "Albaania", "Albanian": "albaania",
"Arabic": "Araabia", "Arabic": "araabia",
"Armenian": "Armeenia", "Armenian": "armeenia",
"Bangla": "Bengali", "Bangla": "bengali",
"Basque": "Baski", "Basque": "baski",
"Belarusian": "Valgevene", "Belarusian": "valgevene",
"Bulgarian": "Bulgaaria", "Bulgarian": "bulgaaria",
"Burmese": "Birma", "Burmese": "birma",
"Cantonese (Hong Kong)": "Kantoni (Hong Konk)", "Cantonese (Hong Kong)": "kantoni (Hongkong)",
"Chinese (China)": "Hiina (Hiina)", "Chinese (China)": "hiina (Hiina)",
"Chinese (Hong Kong)": "Hiina (Hong Kong)", "Chinese (Hong Kong)": "hiina (Hongkong)",
"Chinese (Simplified)": "Hiina (lihtsustatud)", "Chinese (Simplified)": "hiina (lihtsustatud)",
"Chinese (Taiwan)": "Hiina (Taiwan)", "Chinese (Taiwan)": "hiina (Taiwan)",
"Croatian": "Horvaatia", "Croatian": "horvaadi",
"Czech": "Tšehhi", "Czech": "tšehhi",
"Danish": "Taani", "Danish": "taani",
"Dutch": "Hollandi", "Dutch": "hollandi",
"Esperanto": "Esperanto", "Esperanto": "esperanto",
"Estonian": "Eesti", "Estonian": "eesti",
"Filipino": "Filipiini", "Filipino": "filipiini",
"Finnish": "Soome", "Finnish": "soome",
"French": "Prantsuse", "French": "prantsuse",
"French (auto-generated)": "Prantsuse (automaatne)", "French (auto-generated)": "prantsuse (automaatselt koostatud)",
"Dutch (auto-generated)": "Hollandi (automaatne)", "Dutch (auto-generated)": "hollandi (automaatne)",
"Galician": "Kaliitsia", "Galician": "galeegi",
"Georgian": "Gruusia", "Georgian": "gruusia",
"Haitian Creole": "Haiti kreool", "Haitian Creole": "haiti kreooli",
"Hausa": "Hausa", "Hausa": "hausa",
"Hawaiian": "Havaii", "Hawaiian": "havaii",
"Hebrew": "Heebrea", "Hebrew": "heebrea",
"Hindi": "Hindi", "Hindi": "hindi",
"Hungarian": "Ungari", "Hungarian": "ungari",
"Icelandic": "Islandi", "Icelandic": "islandi",
"Indonesian": "Indoneesia", "Indonesian": "indoneesia",
"Japanese (auto-generated)": "Jaapani (automaatne)", "Japanese (auto-generated)": "jaapani (automaatselt koostatud)",
"Kannada": "Kannada", "Kannada": "kannada",
"Kazakh": "Kasahhi", "Kazakh": "kasahhi",
"Luxembourgish": "Luksemburgi", "Luxembourgish": "letseburgi",
"Macedonian": "Makedoonia", "Macedonian": "makedoonia",
"Malay": "Malai", "Malay": "malai",
"Maltese": "Malta", "Maltese": "malta",
"Maori": "Maori", "Maori": "maoori",
"Marathi": "Marathi", "Marathi": "marathi",
"Mongolian": "Mongoli", "Mongolian": "mongoli",
"Nepali": "Nepaali", "Nepali": "nepaali",
"Norwegian Bokmål": "Norra (Bokmål)", "Norwegian Bokmål": "norra (Bokmål)",
"Persian": "Pärsia", "Persian": "pärsia",
"Polish": "Poola", "Polish": "poola",
"Portuguese": "Portugali", "Portuguese": "portugali",
"Portuguese (auto-generated)": "Portugali (automaatne)", "Portuguese (auto-generated)": "portugali (automaatne)",
"Portuguese (Brazil)": "Portugali (Brasiilia)", "Portuguese (Brazil)": "portugali (Brasiilia)",
"Romanian": "Rumeenia", "Romanian": "rumeenia",
"Russian": "Vene", "Russian": "vene",
"Russian (auto-generated)": "Vene (automaatne)", "Russian (auto-generated)": "vene (automaatne)",
"Scottish Gaelic": "Šoti (Gaeli)", "Scottish Gaelic": "gaeli",
"Serbian": "Serbia", "Serbian": "serbia",
"Slovak": "Slovaki", "Slovak": "slovaki",
"Slovenian": "Sloveeni", "Slovenian": "sloveeni",
"Somali": "Somaali", "Somali": "somaali",
"Spanish": "Hispaania", "Spanish": "hispaania",
"Spanish (auto-generated)": "Hispaania (automaatne)", "Spanish (auto-generated)": "hispaania (automaatne)",
"Spanish (Latin America)": "Hispaania (Ladina-Ameerika)", "Spanish (Latin America)": "hispaania (Ladina-Ameerika)",
"Spanish (Mexico)": "Hispaania (Mehhiko)", "Spanish (Mexico)": "hispaania (Mehhiko)",
"Spanish (Spain)": "Hispaania (Hispaania)", "Spanish (Spain)": "hispaania (Hispaania)",
"Swahili": "Suahili", "Swahili": "suahiili",
"Swedish": "Rootsi", "Swedish": "rootsi",
"Tajik": "Tadžiki", "Tajik": "tadžiki",
"Tamil": "Tamiili", "Tamil": "tamili",
"Thai": "Tai", "Thai": "tai",
"Turkish": "Türgi", "Turkish": "türgi",
"Turkish (auto-generated)": "Türgi (automaatne)", "Turkish (auto-generated)": "türgi (automaatne)",
"Ukrainian": "Ukraina", "Ukrainian": "ukraina",
"Uzbek": "Usbeki", "Uzbek": "usbeki",
"Vietnamese": "Vietnami", "Vietnamese": "vietnami",
"Vietnamese (auto-generated)": "Vietnami (automaatne)", "Vietnamese (auto-generated)": "vietnami (automaatne)",
"generic_count_years": "{{count}} aasta", "generic_count_years": "{{count}} aasta",
"generic_count_years_plural": "{{count}} aastat", "generic_count_years_plural": "{{count}} aastat",
"generic_count_months": "{{count}} kuu", "generic_count_months": "{{count}} kuu",
@ -228,15 +226,15 @@
"generic_count_minutes_plural": "{{count}} minutit", "generic_count_minutes_plural": "{{count}} minutit",
"Popular": "Populaarne", "Popular": "Populaarne",
"Search": "Otsi", "Search": "Otsi",
"Top": "Top", "Top": "Parimad",
"About": "Leheküljest", "About": "Saidi teave",
"preferences_locale_label": "Keel: ", "preferences_locale_label": "Keel: ",
"View as playlist": "Vaata esitusloendina", "View as playlist": "Vaata esitusloendina",
"Movies": "Filmid", "Movies": "Filmid",
"Download as: ": "Laadi kui: ", "Download as: ": "Laadi alla kui: ",
"(edited)": "(muudetud)", "(edited)": "(muudetud)",
"`x` marked it with a ❤": "`x` märkis ❤", "`x` marked it with a ❤": "`x` märkis ❤",
"Audio mode": "Audiorežiim", "Audio mode": "Helirežiim",
"Video mode": "Videorežiim", "Video mode": "Videorežiim",
"search_filters_date_label": "Üleslaadimise kuupäev", "search_filters_date_label": "Üleslaadimise kuupäev",
"search_filters_date_option_none": "Ükskõik mis 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_month": "Sel kuul",
"search_filters_date_option_year": "Sel aastal", "search_filters_date_option_year": "Sel aastal",
"search_filters_type_label": "Tüüp", "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_duration_label": "Kestus",
"search_filters_type_option_show": "Näita", "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_short": "Lühike (alla 4 minuti)",
"search_filters_duration_option_medium": "Keskmine (4 - 20 minutit)", "search_filters_duration_option_medium": "Keskmine (4 - 20 minutit)",
"search_filters_duration_option_long": "Pikk (üle 20 minuti)", "search_filters_duration_option_long": "Pikk (üle 20 minuti)",
@ -258,9 +256,9 @@
"search_filters_features_option_hd": "HD", "search_filters_features_option_hd": "HD",
"search_filters_features_option_subtitles": "Subtiitrid", "search_filters_features_option_subtitles": "Subtiitrid",
"search_filters_features_option_location": "Asukoht", "search_filters_features_option_location": "Asukoht",
"search_filters_sort_label": "Sorteeri", "search_filters_sort_label": "Järjestus",
"search_filters_sort_option_views": "Vaatamiste arv", "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", "videoinfo_started_streaming_x_ago": "Alustas otseülekannet `x` tagasi",
"Yes": "Jah", "Yes": "Jah",
"generic_views_count": "{{count}} vaatamine", "generic_views_count": "{{count}} vaatamine",
@ -270,48 +268,48 @@
"preferences_region_label": "Riik: ", "preferences_region_label": "Riik: ",
"View YouTube comments": "Vaata YouTube'i kommentaare", "View YouTube comments": "Vaata YouTube'i kommentaare",
"preferences_extend_desc_label": "Ava video kirjeldus automaatselt: ", "preferences_extend_desc_label": "Ava video kirjeldus automaatselt: ",
"German (auto-generated)": "Saksa (automaatne)", "German (auto-generated)": "saksa (automaatselt koostatud)",
"Italian": "Itaalia", "Italian": "itaalia",
"preferences_player_style_label": "Mängija stiil: ", "preferences_player_style_label": "Meediaesitaja stiil: ",
"subscriptions_unseen_notifs_count": "{{count}} lugemata teavitus", "subscriptions_unseen_notifs_count": "{{count}} lugemata teavitus",
"subscriptions_unseen_notifs_count_plural": "{{count}} lugemata teavitust", "subscriptions_unseen_notifs_count_plural": "{{count}} lugemata teavitust",
"View more comments on Reddit": "Vaata teisi kommentaare Redditis", "View more comments on Reddit": "Vaata teisi kommentaare Redditis",
"Only show latest unwatched video from channel: ": "Näita ainult viimast vaatamata videot: ", "Only show latest unwatched video from channel: ": "Näita ainult viimast vaatamata videot: ",
"tokens_count": "{{count}} token", "tokens_count": "{{count}} tunnusluba",
"tokens_count_plural": "{{count}} tokenit", "tokens_count_plural": "{{count}} tunnusluba",
"Log out": "Logi välja", "Log out": "Logi välja",
"Premieres `x`": "Linastub`x`", "Premieres `x`": "Linastub`x`",
"View `x` comments": { "View `x` comments": {
"([^.,0-9]|^)1([^.,0-9]|$)": "Vaata `x` kommentaari", "([^.,0-9]|^)1([^.,0-9]|$)": "Vaata `x` kommentaari",
"": "Vaata `x` kommentaare" "": "Vaata `x` kommentaare"
}, },
"Khmer": "Khmeeri", "Khmer": "khmeeri",
"Bosnian": "Bosnia", "Bosnian": "bosnia",
"Corsican": "Korsika", "Corsican": "korsika",
"Javanese": "Jaava", "Javanese": "jaava",
"Lithuanian": "Leedu", "Lithuanian": "leedu",
"channel_tab_videos_label": "Videod", "channel_tab_videos_label": "Videod",
"channel_tab_community_label": "Kogukond", "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": "{{count}} punkt",
"comments_points_count_plural": "{{count}} punkti", "comments_points_count_plural": "{{count}} punkti",
"Chinese": "Hiina", "Chinese": "hiina",
"German": "Saksa", "German": "saksa",
"Indonesian (auto-generated)": "Indoneesia (automaatne)", "Indonesian (auto-generated)": "indoneesia (automaatselt koostatud)",
"Italian (auto-generated)": "Itaalia (automaatne)", "Italian (auto-generated)": "itaalia (automaatselt koostatud)",
"Kyrgyz": "Kirkiisi", "Kyrgyz": "kirgiisi",
"Latin": "Ladina", "Latin": "ladina",
"generic_count_seconds": "{{count}} sekund", "generic_count_seconds": "{{count}} sekund",
"generic_count_seconds_plural": "{{count}} sekundit", "generic_count_seconds_plural": "{{count}} sekundit",
"Catalan": "Katalaani", "Catalan": "katalaani",
"Chinese (Traditional)": "Hiina (traditsiooniline)", "Chinese (Traditional)": "hiina (traditsiooniline)",
"Greek": "Kreeka", "Greek": "kreeka",
"Kurdish": "Kurdi", "Kurdish": "kurdi",
"Latvian": "Läti", "Latvian": "läti",
"Irish": "Iiri", "Irish": "iiri",
"Korean": "Korea", "Korean": "korea",
"Japanese": "Jaapani", "Japanese": "jaapani",
"Korean (auto-generated)": "Korea (automaatne)", "Korean (auto-generated)": "korea (automaatselt koostatud)",
"Music": "Muusika", "Music": "Muusika",
"Playlists": "Esitusloendid", "Playlists": "Esitusloendid",
"search_filters_type_option_video": "Video", "search_filters_type_option_video": "Video",
@ -325,8 +323,186 @@
"search_filters_type_option_channel": "Kanal", "search_filters_type_option_channel": "Kanal",
"search_filters_type_option_playlist": "Esitusloend", "search_filters_type_option_playlist": "Esitusloend",
"search_filters_type_option_movie": "Film", "search_filters_type_option_movie": "Film",
"next_steps_error_message_go_to_youtube": "Minna YouTube'i", "next_steps_error_message_go_to_youtube": "Mine YouTube'i",
"next_steps_error_message_refresh": "Laadida uuesti", "next_steps_error_message_refresh": "Laadi uuesti",
"footer_donate_page": "Anneta", "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 <a href=\"`x`\">otsida teisest serverist</a>.",
"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 <a href=\"`x`\">lehte uuesti laadida</a>",
"crash_page_switch_instance": "proovinud <a href=\"`x`\">kasutada mõnda muud Invidiouse serverit</a>",
"crash_page_read_the_faq": "lugenud <a href=\"`x`\">Korduma kippuvaid küsimusi (KKK)</a>",
"crash_page_search_issue": "otsinud <a href=\"`x`\">GitHubist sarnaseid ja juba teaeatud vigu</a>",
"crash_page_report_issue": "Kui ükski ülaltoodud võimalustest seda viga ei lahendanud, siis palun <a href=\"`x`\">koosta GitHubis meie veahalduses uus veateade</a> (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. <a href=\"`x`\">Siit pääsed esitusloendi avalehele.</a>",
"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"
} }

View File

@ -38,8 +38,6 @@
"User ID": "Erabiltzaile IDa", "User ID": "Erabiltzaile IDa",
"Password": "Pasahitza", "Password": "Pasahitza",
"Time (h:mm:ss):": "Denbora (h:mm:ss):", "Time (h:mm:ss):": "Denbora (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA testua",
"Image CAPTCHA": "CAPTCHA irudia",
"Sign In": "Hasi saioa", "Sign In": "Hasi saioa",
"Register": "Eman izena", "Register": "Eman izena",
"E-mail": "E-posta", "E-mail": "E-posta",

View File

@ -1,12 +1,12 @@
{ {
"generic_views_count": "{{count}} بازدید", "generic_views_count": "{{count}} بازدید",
"generic_views_count_plural": "{{count}} بازدید", "generic_views_count_plural": "{{count}} بازدید",
"generic_videos_count": "{{count}} ویدئو", "generic_videos_count": "{{count}} ویدیو",
"generic_videos_count_plural": "{{count}} ویدئو", "generic_videos_count_plural": "{{count}} ویدیو",
"generic_playlists_count": "{{count}} فهرست پخش", "generic_playlists_count": "{{count}} فهرست پخش",
"generic_playlists_count_plural": "{{count}} فهرست پخش", "generic_playlists_count_plural": "{{count}} فهرست پخش",
"generic_subscribers_count": "{{count}} دنبال کننده", "generic_subscribers_count": "{{count}} دنبالکننده",
"generic_subscribers_count_plural": "{{count}} دنبال کننده", "generic_subscribers_count_plural": "{{count}} دنبالکننده",
"generic_subscriptions_count": "{{count}} اشتراک", "generic_subscriptions_count": "{{count}} اشتراک",
"generic_subscriptions_count_plural": "{{count}} اشتراک", "generic_subscriptions_count_plural": "{{count}} اشتراک",
"LIVE": "زنده", "LIVE": "زنده",
@ -24,21 +24,21 @@
"Clear watch history?": "پاک کردن تاریخچه نمایش؟", "Clear watch history?": "پاک کردن تاریخچه نمایش؟",
"New password": "گذرواژه تازه", "New password": "گذرواژه تازه",
"New passwords must match": "گذارواژه های تازه باید باهم همخوانی داشته باشند", "New passwords must match": "گذارواژه های تازه باید باهم همخوانی داشته باشند",
"Authorize token?": "توکن دسترسی؟", "Authorize token?": "اجازه دادن به توکن؟",
"Authorize token for `x`?": "توکن دسترسی برای `x`؟", "Authorize token for `x`?": "اجازه دادن به توکن برای `x`؟",
"Yes": "بله", "Yes": "آری",
"No": "خیر", "No": "نه",
"Import and Export Data": "درون‌برد و برون‌برد داده", "Import and Export Data": "درون‌برد و برون‌برد داده",
"Import": "درون‌برد", "Import": "درون‌برد",
"Import Invidious data": "وارد کردن داده JSON اینویدیوس", "Import Invidious data": "درون‌برد داده JSON اینویدیوس",
"Import YouTube subscriptions": "وارد کردن فایل CSV یا OPML سابسکرایب های یوتیوب", "Import YouTube subscriptions": "درون‌برد پروندهٔ CSV یا OPML اشتراک‌های یوتیوب",
"Import FreeTube subscriptions (.db)": "درون‌برد اشتراک‌های فری‌تیوب (.db)", "Import FreeTube subscriptions (.db)": "درون‌برد اشتراک‌های فری‌تیوب (.db)",
"Import NewPipe subscriptions (.json)": "درون‌برد اشتراک‌های نیوپایپ (.json)", "Import NewPipe subscriptions (.json)": "درون‌برد اشتراک‌های نیوپایپ (.json)",
"Import NewPipe data (.zip)": "درون‌برد داده نیوپایپ (.zip)", "Import NewPipe data (.zip)": "درون‌برد داده نیوپایپ (.zip)",
"Export": "برون‌برد", "Export": "برون‌برد",
"Export subscriptions as OPML": "برون‌برد اشتراک‌ها در قالب OPML", "Export subscriptions as OPML": "برون‌برد اشتراک‌ها در قالب OPML",
"Export subscriptions as OPML (for NewPipe & FreeTube)": "برون‌برد اشتراک‌ها در قالب OPML (برای نیوپایپ و فری‌تیوب)", "Export subscriptions as OPML (for NewPipe & FreeTube)": "برون‌برد اشتراک‌ها در قالب OPML (برای نیوپایپ و فری‌تیوب)",
"Export data as JSON": "گرفتن(خارج کردن) اطلاعات اینویدیوس با فرمت JSON", "Export data as JSON": "برون‌برد دادهٔ اینویدیوس به‌عنوان JSON",
"Delete account?": "حذف حساب کاربری؟", "Delete account?": "حذف حساب کاربری؟",
"History": "تاریخچه", "History": "تاریخچه",
"An alternative front-end to YouTube": "یک پیشانه جایگزین برای یوتیوب", "An alternative front-end to YouTube": "یک پیشانه جایگزین برای یوتیوب",
@ -49,15 +49,13 @@
"User ID": "شناسه کاربری", "User ID": "شناسه کاربری",
"Password": "گذرواژه", "Password": "گذرواژه",
"Time (h:mm:ss):": "زمان (h:mm:ss):", "Time (h:mm:ss):": "زمان (h:mm:ss):",
"Text CAPTCHA": "کپچای متنی",
"Image CAPTCHA": "کپچای تصویری",
"Sign In": "ورود", "Sign In": "ورود",
"Register": "ثبت نام", "Register": "ثبت نام",
"E-mail": "ایمیل", "E-mail": "ایمیل",
"Preferences": "ترجیحات", "Preferences": "ترجیحات",
"preferences_category_player": "ترجیحات نمایش‌دهنده", "preferences_category_player": "ترجیحات نمایش‌دهنده",
"preferences_video_loop_label": "همواره ویدئو را بازپخش کن ", "preferences_video_loop_label": "همیشه بازپخش کن: ",
"preferences_autoplay_label": "نمایش خودکار: ", "preferences_autoplay_label": "پخش خودکار: ",
"preferences_continue_label": "پخش بعدی به طور پیشفرض: ", "preferences_continue_label": "پخش بعدی به طور پیشفرض: ",
"preferences_continue_autoplay_label": "پخش خودکار ویدیو بعدی: ", "preferences_continue_autoplay_label": "پخش خودکار ویدیو بعدی: ",
"preferences_listen_label": "گوش کردن به طور پیشفرض: ", "preferences_listen_label": "گوش کردن به طور پیشفرض: ",
@ -68,14 +66,14 @@
"preferences_comments_label": "نظرات پیشفرض: ", "preferences_comments_label": "نظرات پیشفرض: ",
"youtube": "یوتیوب", "youtube": "یوتیوب",
"reddit": "ردیت", "reddit": "ردیت",
"preferences_captions_label": "زیرنویس های پیشفرض: ", "preferences_captions_label": "زیرنویسهای پیشفرض: ",
"Fallback captions: ": "عقب گرد زیرنویس ها: ", "Fallback captions: ": "عقب‌گرد زیرنویس‌ها: ",
"preferences_related_videos_label": "نمایش ویدیو های مرتبط: ", "preferences_related_videos_label": "نمایش ویدیوهای مرتبط: ",
"preferences_annotations_label": "نمایش حاشیه نویسی ها به طور پیشفرض: ", "preferences_annotations_label": "نمایش حاشیه‌نویسی‌ها به‌طور پیشفرض: ",
"preferences_extend_desc_label": "گسترش خودکار توضیحات ویدئو: ", "preferences_extend_desc_label": "گسترش خودکار توضیحات ویدیو: ",
"preferences_vr_mode_label": "ویدئوها ۳۶۰ درجه تعاملی(نیازمند WebGL): ", "preferences_vr_mode_label": "ویدیوهای ۳۶۰ درجهٔ تعاملی (نیازمند WebGL): ",
"preferences_category_visual": "ترجیحات بصری", "preferences_category_visual": "ترجیحات بصری",
"preferences_player_style_label": "حالت پخش کننده: ", "preferences_player_style_label": "حالت پخشکننده: ",
"Dark mode: ": "حالت تاریک: ", "Dark mode: ": "حالت تاریک: ",
"preferences_dark_mode_label": "تم: ", "preferences_dark_mode_label": "تم: ",
"dark": "تاریک", "dark": "تاریک",
@ -84,7 +82,7 @@
"preferences_category_misc": "ترجیحات متفرقه", "preferences_category_misc": "ترجیحات متفرقه",
"preferences_automatic_instance_redirect_label": "هدایت خودکار نمونه (انتقال به redirect.invidious.io): ", "preferences_automatic_instance_redirect_label": "هدایت خودکار نمونه (انتقال به redirect.invidious.io): ",
"preferences_category_subscription": "ترجیحات اشتراک", "preferences_category_subscription": "ترجیحات اشتراک",
"preferences_annotations_subscribed_label": "نمایش حاشیه نویسی ها به طور پیشفرض برای کانال های مشترک شده: ", "preferences_annotations_subscribed_label": "نمایش حاشیه‌نویسی‌ها به‌طور پیشفرض برای کانال‌های مشترک‌شده: ",
"Redirect homepage to feed: ": "تغییر مسیر صفحه خانه به خوراک: ", "Redirect homepage to feed: ": "تغییر مسیر صفحه خانه به خوراک: ",
"preferences_max_results_label": "تعداد ویدیو های نمایش داده شده در خوراک: ", "preferences_max_results_label": "تعداد ویدیو های نمایش داده شده در خوراک: ",
"preferences_sort_label": "مرتب سازی ویدیو ها بر اساس: ", "preferences_sort_label": "مرتب سازی ویدیو ها بر اساس: ",
@ -383,21 +381,21 @@
"next_steps_error_message_refresh": "تازه‌سازی", "next_steps_error_message_refresh": "تازه‌سازی",
"next_steps_error_message_go_to_youtube": "رفتن به یوتیوب", "next_steps_error_message_go_to_youtube": "رفتن به یوتیوب",
"preferences_quality_option_hd720": "HD720", "preferences_quality_option_hd720": "HD720",
"preferences_quality_option_dash": "DASH (کیفیت تطبیفی)", "preferences_quality_option_dash": "DASH (کیفیت سازگارشونده)",
"preferences_quality_option_medium": "میانه", "preferences_quality_option_medium": "میانه",
"preferences_quality_option_small": "پایین", "preferences_quality_option_small": "پایین",
"preferences_quality_dash_option_auto": "خودکار", "preferences_quality_dash_option_auto": "خودکار",
"preferences_quality_dash_option_best": "بهترین", "preferences_quality_dash_option_best": "بهترین",
"preferences_quality_dash_option_worst": "بدترین", "preferences_quality_dash_option_worst": "بدترین",
"preferences_quality_dash_option_4320p": "4320p", "preferences_quality_dash_option_4320p": "۴۳۲۰p",
"preferences_quality_dash_option_2160p": "2160p", "preferences_quality_dash_option_2160p": "۲۱۶۰p",
"preferences_quality_dash_option_1440p": "1440p", "preferences_quality_dash_option_1440p": "۱۴۴۰p",
"preferences_quality_dash_option_1080p": "1080p", "preferences_quality_dash_option_1080p": "۱۰۸۰p",
"preferences_quality_dash_option_720p": "720p", "preferences_quality_dash_option_720p": "۷۲۰p",
"preferences_quality_dash_option_480p": "480p", "preferences_quality_dash_option_480p": "۴۸۰p",
"preferences_quality_dash_option_360p": "360p", "preferences_quality_dash_option_360p": "۳۶۰p",
"preferences_quality_dash_option_240p": "240p", "preferences_quality_dash_option_240p": "۲۴۰p",
"preferences_quality_dash_option_144p": "144p", "preferences_quality_dash_option_144p": "۱۴۴p",
"invidious": "اینویدیوس", "invidious": "اینویدیوس",
"search_filters_features_option_three_sixty": "360°", "search_filters_features_option_three_sixty": "360°",
"footer_donate_page": "کمک مالی", "footer_donate_page": "کمک مالی",
@ -476,8 +474,8 @@
"generic_button_rss": "خوراک RSS", "generic_button_rss": "خوراک RSS",
"crash_page_read_the_faq": "که <a href=\"`x`\">سوالات بیشتر پرسیده شده (FAQ)</a> را خوانده‌اید", "crash_page_read_the_faq": "که <a href=\"`x`\">سوالات بیشتر پرسیده شده (FAQ)</a> را خوانده‌اید",
"generic_button_delete": "حذف", "generic_button_delete": "حذف",
"Import YouTube playlist (.csv)": "واردکردن فهرست‌پخش YouTube (.csv)", "Import YouTube playlist (.csv)": "درون‌برد فهرست‌پخش YouTube (.csv)",
"Import YouTube watch history (.json)": "وارد کردن فهرست پخش YouTube (.json)", "Import YouTube watch history (.json)": "درون‌برد تاریخچهٔ تماشای یوتیوب (.json)",
"crash_page_you_found_a_bug": "به نظر می‌رسد که ایرادی در Invidious پیدا کرده‌اید!", "crash_page_you_found_a_bug": "به نظر می‌رسد که ایرادی در Invidious پیدا کرده‌اید!",
"channel_tab_podcasts_label": "پادکست‌ها", "channel_tab_podcasts_label": "پادکست‌ها",
"channel_tab_streams_label": "پخش زنده‌ها", "channel_tab_streams_label": "پخش زنده‌ها",
@ -485,10 +483,10 @@
"channel_tab_playlists_label": "فهرست‌های پخش", "channel_tab_playlists_label": "فهرست‌های پخش",
"channel_tab_channels_label": "کانال‌ها", "channel_tab_channels_label": "کانال‌ها",
"error_video_not_in_playlist": "ویدیوی درخواستی معلق به این فهرست پخش نیست. <a href=\"`x`\">کلیک کنید تا به صفحهٔ اصلی فهرست پخش بروید.</a>", "error_video_not_in_playlist": "ویدیوی درخواستی معلق به این فهرست پخش نیست. <a href=\"`x`\">کلیک کنید تا به صفحهٔ اصلی فهرست پخش بروید.</a>",
"Add to playlist": "به لیست پخش افزوده شود", "Add to playlist": "افزودن به فهرست پخش",
"Answer": "پاسخ", "Answer": "پاسخ",
"Search for videos": "جست و جو برای ویدیوها", "Search for videos": "جست‌وجو برای ویدیوها",
"Add to playlist: ": "افزودن به لیست پخش ", "Add to playlist: ": "افزودن به فهرست پخش ",
"The Popular feed has been disabled by the administrator.": "بخش ویدیوهای پرطرفدار توسط مدیر غیرفعال شده است.", "The Popular feed has been disabled by the administrator.": "بخش ویدیوهای پرطرفدار توسط مدیر غیرفعال شده است.",
"carousel_slide": "اسلاید {{current}} از {{total}}", "carousel_slide": "اسلاید {{current}} از {{total}}",
"carousel_skip": "رد شدن از گرداننده", "carousel_skip": "رد شدن از گرداننده",
@ -497,5 +495,11 @@
"crash_page_report_issue": "اگر هیچ یک از روش های بالا کمکی نکردند لطفا <a href=\"`x`\"> (ترجیحا به انگلیسی) یک سوال جدید در گیت هاب بپرسید و </a> طوری که سوالتون شامل متن زیر باشه:", "crash_page_report_issue": "اگر هیچ یک از روش های بالا کمکی نکردند لطفا <a href=\"`x`\"> (ترجیحا به انگلیسی) یک سوال جدید در گیت هاب بپرسید و </a> طوری که سوالتون شامل متن زیر باشه:",
"channel_tab_releases_label": "آثار", "channel_tab_releases_label": "آثار",
"toggle_theme": "تغییر وضعیت تم", "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": "نمایش جزئیات فنی"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Käyttäjätunnus", "User ID": "Käyttäjätunnus",
"Password": "Salasana", "Password": "Salasana",
"Time (h:mm:ss):": "Aika (h:mm:ss):", "Time (h:mm:ss):": "Aika (h:mm:ss):",
"Text CAPTCHA": "Teksti-CAPTCHA",
"Image CAPTCHA": "Kuva-CAPTCHA",
"Sign In": "Kirjaudu sisään", "Sign In": "Kirjaudu sisään",
"Register": "Rekisteröidy", "Register": "Rekisteröidy",
"E-mail": "Sähköposti", "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.", "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)", "Import YouTube watch history (.json)": "Tuo Youtube-katseluhistoria (.json)",
"toggle_theme": "Vaihda teemaa", "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"
} }

View File

@ -62,8 +62,6 @@
"User ID": "Identifiant utilisateur", "User ID": "Identifiant utilisateur",
"Password": "Mot de passe", "Password": "Mot de passe",
"Time (h:mm:ss):": "Heure (h:mm:ss) :", "Time (h:mm:ss):": "Heure (h:mm:ss) :",
"Text CAPTCHA": "CAPTCHA textuel",
"Image CAPTCHA": "CAPTCHA pictural",
"Sign In": "S'identifier", "Sign In": "S'identifier",
"Register": "S'inscrire", "Register": "S'inscrire",
"E-mail": "Courriel", "E-mail": "Courriel",
@ -518,5 +516,6 @@
"preferences_preload_label": "Précharger les données de la vidéo : ", "preferences_preload_label": "Précharger les données de la vidéo : ",
"First page": "Première page", "First page": "Première page",
"channel_tab_courses_label": "Cours", "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"
} }

506
locales/gsw.json Normal file
View File

@ -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 <a href=\"`x`\">uf ere andere Instanz sueche</a>.",
"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, <a href=\"`x`\">d Siite neu z lade</a>",
"crash_page_switch_instance": "En <a href=\"`x`\">anderi Instanz</a> versuecht hesch",
"crash_page_read_the_faq": "S <a href=\"`x`\">FAQ</a> glese hesch",
"crash_page_search_issue": "Nach <a href=\"`x`\">scho gmeldete Bugs uf GitHub</a> gsuecht hesch",
"crash_page_report_issue": "Wenn all das nöd ghulfe het, <a href=\"`x`\">öffne bitte es neus Problem (issue) uf GitHub</a> (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. <a href=\"`x`\">Klick da, zum zur Startsiite vo de Widergabelischte z cho.</a>",
"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"
}

View File

@ -39,8 +39,6 @@
"User ID": "שם משתמש", "User ID": "שם משתמש",
"Password": "סיסמה", "Password": "סיסמה",
"Time (h:mm:ss):": "זמן (h:mm:ss):", "Time (h:mm:ss):": "זמן (h:mm:ss):",
"Text CAPTCHA": "Text CAPTCHA",
"Image CAPTCHA": "Image CAPTCHA",
"Sign In": "התחברות", "Sign In": "התחברות",
"Register": "הרשמה", "Register": "הרשמה",
"E-mail": "דוא״ל", "E-mail": "דוא״ל",

View File

@ -80,8 +80,6 @@
"Register": "पंजीकृत करें", "Register": "पंजीकृत करें",
"E-mail": "ईमेल", "E-mail": "ईमेल",
"Time (h:mm:ss):": "समय (घं:मिमि:सेसे):", "Time (h:mm:ss):": "समय (घं:मिमि:सेसे):",
"Text CAPTCHA": "टेक्स्ट CAPTCHA",
"Image CAPTCHA": "चित्र CAPTCHA",
"Sign In": "साइन इन करें", "Sign In": "साइन इन करें",
"Preferences": "प्राथमिकताएँ", "Preferences": "प्राथमिकताएँ",
"preferences_category_player": "प्लेयर की प्राथमिकताएँ", "preferences_category_player": "प्लेयर की प्राथमिकताएँ",
@ -199,7 +197,7 @@
"Switch Invidious Instance": "Invidious उदाहरण बदलें", "Switch Invidious Instance": "Invidious उदाहरण बदलें",
"search_message_no_results": "कोई परिणाम नहीं मिला।", "search_message_no_results": "कोई परिणाम नहीं मिला।",
"search_message_change_filters_or_query": "अपने खोज क्वेरी को और चौड़ा करें और/या फ़िल्टर बदलें।", "search_message_change_filters_or_query": "अपने खोज क्वेरी को और चौड़ा करें और/या फ़िल्टर बदलें।",
"search_message_use_another_instance": " आप <a href=\"`x`\">दूसरे उदाहरण पर भी खोज सकते हैं</a>।", "search_message_use_another_instance": "आप <a href=\"`x`\">दूसरे उदाहरण पर भी खोज सकते हैं</a>।",
"Hide annotations": "टिप्पणियाँ छिपाएँ", "Hide annotations": "टिप्पणियाँ छिपाएँ",
"Show annotations": "टिप्पणियाँ दिखाएँ", "Show annotations": "टिप्पणियाँ दिखाएँ",
"Genre: ": "श्रेणी: ", "Genre: ": "श्रेणी: ",
@ -434,7 +432,7 @@
"search_filters_features_option_location": "जगह", "search_filters_features_option_location": "जगह",
"search_filters_features_option_purchased": "खरीदा गया", "search_filters_features_option_purchased": "खरीदा गया",
"search_filters_sort_label": "इस क्रम से लगाएँ", "search_filters_sort_label": "इस क्रम से लगाएँ",
"search_filters_sort_option_date": "अपलोड की ताीख", "search_filters_sort_option_date": "अपलोड की ताीख",
"search_filters_sort_option_views": "देखे जाने की संख्या", "search_filters_sort_option_views": "देखे जाने की संख्या",
"search_filters_apply_button": "चयनित फ़िल्टर लागू करें", "search_filters_apply_button": "चयनित फ़िल्टर लागू करें",
"footer_documentation": "प्रलेख", "footer_documentation": "प्रलेख",
@ -476,7 +474,7 @@
"generic_button_cancel": "रद्द करें", "generic_button_cancel": "रद्द करें",
"generic_button_rss": "आरएसएस", "generic_button_rss": "आरएसएस",
"generic_button_edit": "संपादित करें", "generic_button_edit": "संपादित करें",
"generic_button_delete": "हटाए", "generic_button_delete": "हटाए",
"playlist_button_add_items": "वीडियो जोड़ें", "playlist_button_add_items": "वीडियो जोड़ें",
"Song: ": "गाना: ", "Song: ": "गाना: ",
"channel_tab_podcasts_label": "पाॅडकास्ट", "channel_tab_podcasts_label": "पाॅडकास्ट",
@ -496,5 +494,13 @@
"carousel_skip": "कैरोसेल छोड़ें", "carousel_skip": "कैरोसेल छोड़ें",
"Add to playlist: ": "प्लेलिस्ट में जोड़ें: ", "Add to playlist: ": "प्लेलिस्ट में जोड़ें: ",
"Search for videos": "वीडियो खोजें", "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": "तकनीकी जानकारी दिखाएँ"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Korisnički ID", "User ID": "Korisnički ID",
"Password": "Lozinka", "Password": "Lozinka",
"Time (h:mm:ss):": "Vrijeme (h:mm:ss):", "Time (h:mm:ss):": "Vrijeme (h:mm:ss):",
"Text CAPTCHA": "Tekstualni CAPTCHA",
"Image CAPTCHA": "Slikovni CAPTCHA",
"Sign In": "Prijavi se", "Sign In": "Prijavi se",
"Register": "Registriraj se", "Register": "Registriraj se",
"E-mail": "E-mail adresa", "E-mail": "E-mail adresa",
@ -515,5 +513,11 @@
"carousel_go_to": "Idi na kadar `x`", "carousel_go_to": "Idi na kadar `x`",
"carousel_skip": "Preskoči vrtuljak", "carousel_skip": "Preskoči vrtuljak",
"Filipino (auto-generated)": "Filipinski (automatski generirano)", "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"
} }

View File

@ -49,8 +49,6 @@
"User ID": "Felhasználói azonosító", "User ID": "Felhasználói azonosító",
"Password": "Jelszó", "Password": "Jelszó",
"Time (h:mm:ss):": "A pontos idő (ó:pp:mm):", "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", "Sign In": "Bejelentkezés",
"Register": "Regisztrálás", "Register": "Regisztrálás",
"E-mail": "E-mail-cím", "E-mail": "E-mail-cím",

View File

@ -5,7 +5,6 @@
"oldest": "plus ancian", "oldest": "plus ancian",
"published": "data de publication", "published": "data de publication",
"invidious": "Invidious", "invidious": "Invidious",
"Image CAPTCHA": "Imagine CAPTCHA",
"newest": "plus nove", "newest": "plus nove",
"generic_button_save": "Salveguardar", "generic_button_save": "Salveguardar",
"Dark mode: ": "Modo obscur: ", "Dark mode: ": "Modo obscur: ",

View File

@ -44,8 +44,6 @@
"User ID": "ID Pengguna", "User ID": "ID Pengguna",
"Password": "Kata Sandi", "Password": "Kata Sandi",
"Time (h:mm:ss):": "Waktu (j:mm:dd):", "Time (h:mm:ss):": "Waktu (j:mm:dd):",
"Text CAPTCHA": "Teks CAPTCHA",
"Image CAPTCHA": "Gambar CAPTCHA",
"Sign In": "Masuk", "Sign In": "Masuk",
"Register": "Daftar", "Register": "Daftar",
"E-mail": "Surel", "E-mail": "Surel",

View File

@ -39,8 +39,6 @@
"User ID": "Auðkenni notanda", "User ID": "Auðkenni notanda",
"Password": "Lykilorð", "Password": "Lykilorð",
"Time (h:mm:ss):": "Tími (h:mm: ss):", "Time (h:mm:ss):": "Tími (h:mm: ss):",
"Text CAPTCHA": "CAPTCHA-texti",
"Image CAPTCHA": "CAPTCHA-mynd",
"Sign In": "Skrá inn", "Sign In": "Skrá inn",
"Register": "Nýskrá", "Register": "Nýskrá",
"E-mail": "Tölvupóstur", "E-mail": "Tölvupóstur",
@ -501,5 +499,8 @@
"Filipino (auto-generated)": "Filippínska (sjálfvirkt útbúin)", "Filipino (auto-generated)": "Filippínska (sjálfvirkt útbúin)",
"channel_tab_posts_label": "Færslur", "channel_tab_posts_label": "Færslur",
"First page": "Fyrsta síða", "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"
} }

View File

@ -48,8 +48,6 @@
"User ID": "ID utente", "User ID": "ID utente",
"Password": "Password", "Password": "Password",
"Time (h:mm:ss):": "Orario (h:mm:ss):", "Time (h:mm:ss):": "Orario (h:mm:ss):",
"Text CAPTCHA": "Testo del CAPTCHA",
"Image CAPTCHA": "Immagine CAPTCHA",
"Sign In": "Accedi", "Sign In": "Accedi",
"Register": "Registrati", "Register": "Registrati",
"E-mail": "E-mail", "E-mail": "E-mail",
@ -129,7 +127,7 @@
"subscriptions_unseen_notifs_count_0": "{{count}} notifica non visualizzata", "subscriptions_unseen_notifs_count_0": "{{count}} notifica non visualizzata",
"subscriptions_unseen_notifs_count_1": "{{count}} notifiche non visualizzate", "subscriptions_unseen_notifs_count_1": "{{count}} notifiche non visualizzate",
"subscriptions_unseen_notifs_count_2": "{{count}} notifiche non visualizzate", "subscriptions_unseen_notifs_count_2": "{{count}} notifiche non visualizzate",
"search": "Cerca", "search": "cerca",
"Log out": "Esci", "Log out": "Esci",
"Source available here.": "Codice sorgente.", "Source available here.": "Codice sorgente.",
"View JavaScript license information.": "Guarda le informazioni di licenza del codice JavaScript.", "View JavaScript license information.": "Guarda le informazioni di licenza del codice JavaScript.",
@ -518,5 +516,8 @@
"Filipino (auto-generated)": "Filippino (generati automaticamente)", "Filipino (auto-generated)": "Filippino (generati automaticamente)",
"First page": "Prima pagina", "First page": "Prima pagina",
"channel_tab_courses_label": "Corsi", "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"
} }

View File

@ -44,8 +44,6 @@
"User ID": "ユーザー ID", "User ID": "ユーザー ID",
"Password": "パスワード", "Password": "パスワード",
"Time (h:mm:ss):": "時間 (時:分分:秒秒):", "Time (h:mm:ss):": "時間 (時:分分:秒秒):",
"Text CAPTCHA": "テキスト CAPTCHA",
"Image CAPTCHA": "画像 CAPTCHA",
"Sign In": "サインイン", "Sign In": "サインイン",
"Register": "登録", "Register": "登録",
"E-mail": "メールアドレス", "E-mail": "メールアドレス",
@ -484,5 +482,10 @@
"Filipino (auto-generated)": "フィリピノ語 (自動生成)", "Filipino (auto-generated)": "フィリピノ語 (自動生成)",
"First page": "最初のページ", "First page": "最初のページ",
"channel_tab_posts_label": "投稿", "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": "デフォルトのプレイリストは設定されていません"
} }

View File

@ -36,8 +36,6 @@
"Register": "회원가입", "Register": "회원가입",
"Sign In": "로그인", "Sign In": "로그인",
"preferences_category_misc": "기타 설정", "preferences_category_misc": "기타 설정",
"Image CAPTCHA": "이미지 캡차",
"Text CAPTCHA": "텍스트 캡차",
"Time (h:mm:ss):": "시각 (h:mm:ss):", "Time (h:mm:ss):": "시각 (h:mm:ss):",
"Password": "비밀번호", "Password": "비밀번호",
"User ID": "사용자 ID", "User ID": "사용자 ID",

View File

@ -44,8 +44,6 @@
"JavaScript license information": "Informaziòn su la licensa JavaScript", "JavaScript license information": "Informaziòn su la licensa JavaScript",
"source": "font", "source": "font",
"Log in": "Và dent", "Log in": "Và dent",
"Text CAPTCHA": "Tèst del CAPTCHA",
"Image CAPTCHA": "Imàgen del CAPTCHA",
"Sign In": "Ven denter", "Sign In": "Ven denter",
"Register": "Registres", "Register": "Registres",
"E-mail": "E-mail", "E-mail": "E-mail",

View File

@ -39,8 +39,6 @@
"User ID": "Naudotojo ID", "User ID": "Naudotojo ID",
"Password": "Slaptažodis", "Password": "Slaptažodis",
"Time (h:mm:ss):": "Laikas (h:mm:ss):", "Time (h:mm:ss):": "Laikas (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA tekstas",
"Image CAPTCHA": "CAPTCHA paveikslėlis",
"Sign In": "Prisijungti", "Sign In": "Prisijungti",
"Register": "Registruotis", "Register": "Registruotis",
"E-mail": "El. paštas", "E-mail": "El. paštas",

View File

@ -65,5 +65,79 @@
"youtube": "YouTube", "youtube": "YouTube",
"Add to playlist: ": "Pievienot atskaņošanas sarakstam: ", "Add to playlist: ": "Pievienot atskaņošanas sarakstam: ",
"Subscribe": "Abonēt", "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"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Bruker-ID", "User ID": "Bruker-ID",
"Password": "Passord", "Password": "Passord",
"Time (h:mm:ss):": "Tid (h:mm:ss):", "Time (h:mm:ss):": "Tid (h:mm:ss):",
"Text CAPTCHA": "Tekst-CAPTCHA",
"Image CAPTCHA": "Bilde-CAPTCHA",
"Sign In": "Innlogging", "Sign In": "Innlogging",
"Register": "Registrer", "Register": "Registrer",
"E-mail": "E-post", "E-mail": "E-post",

View File

@ -39,8 +39,6 @@
"User ID": "Gebruikers-id", "User ID": "Gebruikers-id",
"Password": "Wachtwoord", "Password": "Wachtwoord",
"Time (h:mm:ss):": "Tijd (h:mm:ss):", "Time (h:mm:ss):": "Tijd (h:mm:ss):",
"Text CAPTCHA": "Tekst-CAPTCHA",
"Image CAPTCHA": "Afbeelding-CAPTCHA",
"Sign In": "Inloggen", "Sign In": "Inloggen",
"Register": "Registreren", "Register": "Registreren",
"E-mail": "E-mailadres", "E-mail": "E-mailadres",
@ -501,5 +499,8 @@
"Filipino (auto-generated)": "Filipijns (automatisch gegenereerd)", "Filipino (auto-generated)": "Filipijns (automatisch gegenereerd)",
"channel_tab_courses_label": "Cursussen", "channel_tab_courses_label": "Cursussen",
"First page": "Eerste pagina", "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"
} }

View File

@ -39,8 +39,6 @@
"User ID": "ID użytkownika", "User ID": "ID użytkownika",
"Password": "Hasło", "Password": "Hasło",
"Time (h:mm:ss):": "Godzina (h:mm:ss):", "Time (h:mm:ss):": "Godzina (h:mm:ss):",
"Text CAPTCHA": "Tekst CAPTCHA",
"Image CAPTCHA": "Obraz CAPTCHA",
"Sign In": "Zaloguj się", "Sign In": "Zaloguj się",
"Register": "Zarejestruj się", "Register": "Zarejestruj się",
"E-mail": "E-mail", "E-mail": "E-mail",
@ -78,7 +76,7 @@
"Redirect homepage to feed: ": "Przekieruj stronę główną do subskrybcji: ", "Redirect homepage to feed: ": "Przekieruj stronę główną do subskrybcji: ",
"preferences_max_results_label": "Liczba filmów widoczna na stronie subskrybcji: ", "preferences_max_results_label": "Liczba filmów widoczna na stronie subskrybcji: ",
"preferences_sort_label": "Sortuj filmy: ", "preferences_sort_label": "Sortuj filmy: ",
"published": "po czasie publikacji", "published": "opublikowano",
"published - reverse": "po czasie publikacji od najstarszych", "published - reverse": "po czasie publikacji od najstarszych",
"alphabetically": "alfabetycznie", "alphabetically": "alfabetycznie",
"alphabetically - reverse": "alfabetycznie od tyłu", "alphabetically - reverse": "alfabetycznie od tyłu",
@ -518,5 +516,10 @@
"Filipino (auto-generated)": "filipiński (wygenerowany automatycznie)", "Filipino (auto-generated)": "filipiński (wygenerowany automatycznie)",
"First page": "Pierwsza strona", "First page": "Pierwsza strona",
"channel_tab_posts_label": "Posty", "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: "
} }

View File

@ -18,7 +18,7 @@
"Authorize token for `x`?": "Autorizar token para `x`?", "Authorize token for `x`?": "Autorizar token para `x`?",
"Yes": "Sim", "Yes": "Sim",
"No": "Não", "No": "Não",
"Import and Export Data": "Importar/exportar dados", "Import and Export Data": "Importar e exportar dados",
"Import": "Importar", "Import": "Importar",
"Import Invidious data": "Importar dados JSON do Invidious", "Import Invidious data": "Importar dados JSON do Invidious",
"Import YouTube subscriptions": "Importar inscrições no formato CSV ou OPML do YouTube", "Import YouTube subscriptions": "Importar inscrições no formato CSV ou OPML do YouTube",
@ -39,8 +39,6 @@
"User ID": "Usuário", "User ID": "Usuário",
"Password": "Senha", "Password": "Senha",
"Time (h:mm:ss):": "Hora (h:mm:ss):", "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", "Sign In": "Fazer login",
"Register": "Criar conta", "Register": "Criar conta",
"E-mail": "E-mail", "E-mail": "E-mail",
@ -484,7 +482,7 @@
"channel_tab_channels_label": "Canais", "channel_tab_channels_label": "Canais",
"channel_tab_playlists_label": "Playlists", "channel_tab_playlists_label": "Playlists",
"channel_tab_shorts_label": "Shorts", "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", "Music in this video": "Música neste vídeo",
"Artist: ": "Artista: ", "Artist: ": "Artista: ",
"Album: ": "Álbum: ", "Album: ": "Álbum: ",
@ -518,5 +516,8 @@
"Filipino (auto-generated)": "Filipino (gerado automaticamente)", "Filipino (auto-generated)": "Filipino (gerado automaticamente)",
"channel_tab_posts_label": "Postagens", "channel_tab_posts_label": "Postagens",
"First page": "Primeira página", "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"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Utilizador", "User ID": "Utilizador",
"Password": "Palavra-passe", "Password": "Palavra-passe",
"Time (h:mm:ss):": "Tempo (h:mm:ss):", "Time (h:mm:ss):": "Tempo (h:mm:ss):",
"Text CAPTCHA": "Texto CAPTCHA",
"Image CAPTCHA": "Imagem CAPTCHA",
"Sign In": "Entrar", "Sign In": "Entrar",
"Register": "Registar", "Register": "Registar",
"E-mail": "E-mail", "E-mail": "E-mail",
@ -518,5 +516,8 @@
"Filipino (auto-generated)": "Filipino (gerado automaticamente)", "Filipino (auto-generated)": "Filipino (gerado automaticamente)",
"channel_tab_courses_label": "Cursos", "channel_tab_courses_label": "Cursos",
"channel_tab_posts_label": "Publicações", "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"
} }

View File

@ -236,8 +236,6 @@
"Preferences": "Preferências", "Preferences": "Preferências",
"E-mail": "E-mail", "E-mail": "E-mail",
"Register": "Registar", "Register": "Registar",
"Image CAPTCHA": "Imagem CAPTCHA",
"Text CAPTCHA": "Texto CAPTCHA",
"Time (h:mm:ss):": "Tempo (h:mm:ss):", "Time (h:mm:ss):": "Tempo (h:mm:ss):",
"Password": "Palavra-passe", "Password": "Palavra-passe",
"User ID": "Utilizador", "User ID": "Utilizador",

View File

@ -39,8 +39,6 @@
"User ID": "ID Utilizator", "User ID": "ID Utilizator",
"Password": "Parolă", "Password": "Parolă",
"Time (h:mm:ss):": "Ora (h:mm:ss) :", "Time (h:mm:ss):": "Ora (h:mm:ss) :",
"Text CAPTCHA": "Text CAPTCHA",
"Image CAPTCHA": "Imagine CAPTCHA",
"Sign In": "Conectați-vă", "Sign In": "Conectați-vă",
"Register": "Înregistrați-vă", "Register": "Înregistrați-vă",
"E-mail": "E-mail", "E-mail": "E-mail",

View File

@ -22,7 +22,7 @@
"Import and Export Data": "Импорт и экспорт данных", "Import and Export Data": "Импорт и экспорт данных",
"Import": "Импорт", "Import": "Импорт",
"Import Invidious data": "Импортировать JSON с данными Invidious", "Import Invidious data": "Импортировать JSON с данными Invidious",
"Import YouTube subscriptions": "Импортировать подписки из CSV или OPML", "Import YouTube subscriptions": "Импортировать подписки из YouTube через файлы CSV или OPML",
"Import FreeTube subscriptions (.db)": "Импортировать подписки из FreeTube (.db)", "Import FreeTube subscriptions (.db)": "Импортировать подписки из FreeTube (.db)",
"Import NewPipe subscriptions (.json)": "Импортировать подписки из NewPipe (.json)", "Import NewPipe subscriptions (.json)": "Импортировать подписки из NewPipe (.json)",
"Import NewPipe data (.zip)": "Импортировать данные из NewPipe (.zip)", "Import NewPipe data (.zip)": "Импортировать данные из NewPipe (.zip)",
@ -40,8 +40,6 @@
"User ID": "ИД пользователя", "User ID": "ИД пользователя",
"Password": "Пароль", "Password": "Пароль",
"Time (h:mm:ss):": "Время (ч:мм:сс):", "Time (h:mm:ss):": "Время (ч:мм:сс):",
"Text CAPTCHA": "Текстовая капча (англ.)",
"Image CAPTCHA": "Капча-картинка",
"Sign In": "Войти", "Sign In": "Войти",
"Register": "Регистрация", "Register": "Регистрация",
"E-mail": "Эл. почта", "E-mail": "Эл. почта",
@ -511,11 +509,17 @@
"Answer": "Ответить", "Answer": "Ответить",
"Search for videos": "Поиск видео", "Search for videos": "Поиск видео",
"The Popular feed has been disabled by the administrator.": "Лента популярного была отключена администратором.", "The Popular feed has been disabled by the administrator.": "Лента популярного была отключена администратором.",
"toggle_theme": "Переключатель тем", "toggle_theme": "Переключить тему оформления",
"carousel_slide": "Пролистано {{current}} из {{total}}", "carousel_slide": "Слайд {{current}} из {{total}}",
"carousel_skip": "Пропустить всё", "carousel_skip": "Пропустить всё",
"carousel_go_to": "Перейти к странице `x`", "carousel_go_to": "Перейти на слайд `x`",
"preferences_preload_label": "Предзагрузка видеоданных: ", "preferences_preload_label": "Предзагрузка видеоданных: ",
"channel_tab_courses_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": "Плейлист по умолчанию не указан"
} }

View File

@ -82,8 +82,6 @@
"Export subscriptions as OPML": "දායකත්වයන් OPML ලෙස අපනයනය කරන්න", "Export subscriptions as OPML": "දායකත්වයන් OPML ලෙස අපනයනය කරන්න",
"JavaScript license information": "JavaScript බලපත්‍ර තොරතුරු", "JavaScript license information": "JavaScript බලපත්‍ර තොරතුරු",
"User ID": "පරිශීලක කේතය", "User ID": "පරිශීලක කේතය",
"Text CAPTCHA": "CAPTCHA පෙල",
"Image CAPTCHA": "CAPTCHA රූපය",
"E-mail": "විද්‍යුත් තැපෑල", "E-mail": "විද්‍යුත් තැපෑල",
"preferences_quality_label": "කැමති වීඩියෝ ගුණත්වය: ", "preferences_quality_label": "කැමති වීඩියෝ ගුණත්වය: ",
"preferences_quality_option_hd720": "HD720", "preferences_quality_option_hd720": "HD720",

View File

@ -36,8 +36,6 @@
"User ID": "ID používateľa", "User ID": "ID používateľa",
"Password": "Heslo", "Password": "Heslo",
"Time (h:mm:ss):": "Čas (h:mm:ss):", "Time (h:mm:ss):": "Čas (h:mm:ss):",
"Text CAPTCHA": "Textové CAPTCHA",
"Image CAPTCHA": "Obrázkové CAPTCHA",
"Sign In": "Prihlásiť sa", "Sign In": "Prihlásiť sa",
"Register": "Registrovať", "Register": "Registrovať",
"E-mail": "E-mail", "E-mail": "E-mail",

View File

@ -24,9 +24,7 @@
"User ID": "ID uporabnika", "User ID": "ID uporabnika",
"Password": "Geslo", "Password": "Geslo",
"Time (h:mm:ss):": "Čas (h:mm:ss):", "Time (h:mm:ss):": "Čas (h:mm:ss):",
"Text CAPTCHA": "Besedilo CAPTCHA",
"source": "izvorna koda", "source": "izvorna koda",
"Image CAPTCHA": "Slika CAPTCHA",
"Sign In": "Prijavi se", "Sign In": "Prijavi se",
"Register": "Registriraj se", "Register": "Registriraj se",
"E-mail": "E-pošta", "E-mail": "E-pošta",
@ -532,5 +530,11 @@
"carousel_slide": "Diapozitiv {{current}} od {{total}}", "carousel_slide": "Diapozitiv {{current}} od {{total}}",
"carousel_skip": "Preskoči galerijo", "carousel_skip": "Preskoči galerijo",
"carousel_go_to": "Pojdi na diapozitiv `x`", "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"
} }

View File

@ -42,8 +42,6 @@
"User ID": "ID Përdoruesi", "User ID": "ID Përdoruesi",
"Password": "Fjalëkalim", "Password": "Fjalëkalim",
"Time (h:mm:ss):": "Kohë (h:mm:ss):", "Time (h:mm:ss):": "Kohë (h:mm:ss):",
"Text CAPTCHA": "CAPTCHA Tekst",
"Image CAPTCHA": "CAPTCHA Figurë",
"Sign In": "Hyni", "Sign In": "Hyni",
"Register": "Regjistrohuni", "Register": "Regjistrohuni",
"E-mail": "Email", "E-mail": "Email",

View File

@ -39,8 +39,6 @@
"User ID": "ID korisnika", "User ID": "ID korisnika",
"Password": "Lozinka", "Password": "Lozinka",
"Time (h:mm:ss):": "Vreme (č:mm:ss):", "Time (h:mm:ss):": "Vreme (č:mm:ss):",
"Text CAPTCHA": "Tekst CAPTCHA",
"Image CAPTCHA": "Slika CAPTCHA",
"Sign In": "Prijava", "Sign In": "Prijava",
"Register": "Registracija", "Register": "Registracija",
"E-mail": "Imejl", "E-mail": "Imejl",
@ -518,5 +516,8 @@
"Filipino (auto-generated)": "Filipinski (automatski generisano)", "Filipino (auto-generated)": "Filipinski (automatski generisano)",
"channel_tab_posts_label": "Objave", "channel_tab_posts_label": "Objave",
"First page": "Prva stranica", "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:"
} }

View File

@ -39,8 +39,6 @@
"User ID": "ID корисника", "User ID": "ID корисника",
"Password": "Лозинка", "Password": "Лозинка",
"Time (h:mm:ss):": "Време (ч:мм:сс):", "Time (h:mm:ss):": "Време (ч:мм:сс):",
"Text CAPTCHA": "Текст CAPTCHA",
"Image CAPTCHA": "Слика CAPTCHA",
"Sign In": "Пријава", "Sign In": "Пријава",
"Register": "Регистрација", "Register": "Регистрација",
"E-mail": "Имејл", "E-mail": "Имејл",
@ -518,5 +516,8 @@
"Filipino (auto-generated)": "Филипински (аутоматски генерисано)", "Filipino (auto-generated)": "Филипински (аутоматски генерисано)",
"channel_tab_courses_label": "Курсеви", "channel_tab_courses_label": "Курсеви",
"First page": "Прва страница", "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 је наишао на грешку приликом покушаја рашчлањивања овог предмета. За више информација погледајте испод:"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Användar-ID", "User ID": "Användar-ID",
"Password": "Lösenord", "Password": "Lösenord",
"Time (h:mm:ss):": "Tid (h:mm:ss):", "Time (h:mm:ss):": "Tid (h:mm:ss):",
"Text CAPTCHA": "Text-CAPTCHA",
"Image CAPTCHA": "Bild-CAPTCHA",
"Sign In": "Inloggning", "Sign In": "Inloggning",
"Register": "Registrera", "Register": "Registrera",
"E-mail": "E-post", "E-mail": "E-post",

View File

@ -282,8 +282,6 @@
"Import": "இறக்குமதி", "Import": "இறக்குமதி",
"Import NewPipe subscriptions (.json)": "நியூபிப்பிப் சந்தாக்களை இறக்குமதி செய்யுங்கள் (.json)", "Import NewPipe subscriptions (.json)": "நியூபிப்பிப் சந்தாக்களை இறக்குமதி செய்யுங்கள் (.json)",
"Export": "ஏற்றுமதி", "Export": "ஏற்றுமதி",
"Text CAPTCHA": "உரை கேப்ட்சா",
"Image CAPTCHA": "பட கேப்ட்சா",
"preferences_category_player": "பிளேயர் விருப்பத்தேர்வுகள்", "preferences_category_player": "பிளேயர் விருப்பத்தேர்வுகள்",
"preferences_video_loop_label": "எப்போதும் லூப்: ", "preferences_video_loop_label": "எப்போதும் லூப்: ",
"preferences_continue_autoplay_label": "தன்னியக்க அடுத்த வீடியோ: ", "preferences_continue_autoplay_label": "தன்னியக்க அடுத்த வீடியோ: ",
@ -498,5 +496,11 @@
"channel_tab_channels_label": "சேனல்கள்", "channel_tab_channels_label": "சேனல்கள்",
"toggle_theme": "கருப்பொருளை மாற்றவும்", "toggle_theme": "கருப்பொருளை மாற்றவும்",
"carousel_slide": "{{total}} இன் ச்லைடு {{current}}", "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": "தொழில்நுட்ப விவரங்களைக் காட்டு"
} }

View File

@ -1,7 +1,26 @@
{ {
"Add to playlist": "Aýdym sanawyna goş", "Add to playlist": "Pleýer Sanawa goş",
"Add to playlist: ": "Pleýliste goş: ", "Add to playlist: ": "Pleýliste goş: ",
"Answer": "Jogap", "Answer": "Jogap",
"Search for videos": "Wideo gözläň", "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"
} }

View File

@ -39,8 +39,6 @@
"User ID": "Kullanıcı Kimliği", "User ID": "Kullanıcı Kimliği",
"Password": "Parola", "Password": "Parola",
"Time (h:mm:ss):": "Zaman (h:mm:ss):", "Time (h:mm:ss):": "Zaman (h:mm:ss):",
"Text CAPTCHA": "Metin CAPTCHA",
"Image CAPTCHA": "Resim CAPTCHA",
"Sign In": "Oturum Aç", "Sign In": "Oturum Aç",
"Register": "Kayıt Ol", "Register": "Kayıt Ol",
"E-mail": "E-Posta", "E-mail": "E-Posta",
@ -501,5 +499,8 @@
"First page": "İlk sayfa", "First page": "İlk sayfa",
"Filipino (auto-generated)": "Filipince (oto-oluşturuldu)", "Filipino (auto-generated)": "Filipince (oto-oluşturuldu)",
"channel_tab_courses_label": "Kurslar", "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"
} }

View File

@ -39,8 +39,6 @@
"User ID": "ID користувача", "User ID": "ID користувача",
"Password": "Пароль", "Password": "Пароль",
"Time (h:mm:ss):": "Час (г:хх:сс):", "Time (h:mm:ss):": "Час (г:хх:сс):",
"Text CAPTCHA": "Текст CAPTCHA",
"Image CAPTCHA": "Зображення CAPTCHA",
"Sign In": "Увійти", "Sign In": "Увійти",
"Register": "Зареєструватися", "Register": "Зареєструватися",
"E-mail": "Електронна пошта", "E-mail": "Електронна пошта",
@ -518,5 +516,8 @@
"Filipino (auto-generated)": "Філіппінська (згенеровано автоматично)", "Filipino (auto-generated)": "Філіппінська (згенеровано автоматично)",
"First page": "Перша сторінка", "First page": "Перша сторінка",
"channel_tab_courses_label": "Курси", "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 зіткнувся з помилкою під час спроби розібрати цей елемент. Докладнішу інформацію читайте нижче:"
} }

View File

@ -41,8 +41,6 @@
"User ID": "Mã nhận dạng người dùng", "User ID": "Mã nhận dạng người dùng",
"Password": "Mật khẩu", "Password": "Mật khẩu",
"Time (h:mm:ss):": "Thời gian (h:mm:ss):", "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", "Sign In": "Đăng nhập",
"Register": "Đăng ký", "Register": "Đăng ký",
"E-mail": "E-mail", "E-mail": "E-mail",

View File

@ -44,8 +44,6 @@
"User ID": "用户 ID", "User ID": "用户 ID",
"Password": "密码", "Password": "密码",
"Time (h:mm:ss):": "时间 (h:mm:ss):", "Time (h:mm:ss):": "时间 (h:mm:ss):",
"Text CAPTCHA": "文本验证码",
"Image CAPTCHA": "图片验证码",
"Sign In": "登录", "Sign In": "登录",
"Register": "注册", "Register": "注册",
"E-mail": "E-mail", "E-mail": "E-mail",
@ -484,5 +482,10 @@
"Filipino (auto-generated)": "菲律宾语 (自动生成)", "Filipino (auto-generated)": "菲律宾语 (自动生成)",
"channel_tab_posts_label": "帖子", "channel_tab_posts_label": "帖子",
"First page": "第一页", "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": "尚无默认播放列表"
} }

View File

@ -44,8 +44,6 @@
"User ID": "使用者 ID", "User ID": "使用者 ID",
"Password": "密碼", "Password": "密碼",
"Time (h:mm:ss):": "時間 (h:mm:ss):", "Time (h:mm:ss):": "時間 (h:mm:ss):",
"Text CAPTCHA": "文字 CAPTCHA",
"Image CAPTCHA": "圖片 CAPTCHA",
"Sign In": "登入", "Sign In": "登入",
"Register": "註冊", "Register": "註冊",
"E-mail": "電子郵件", "E-mail": "電子郵件",
@ -484,5 +482,10 @@
"Filipino (auto-generated)": "菲律賓語(自動產生)", "Filipino (auto-generated)": "菲律賓語(自動產生)",
"channel_tab_courses_label": "課程", "channel_tab_courses_label": "課程",
"First page": "第一頁", "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": "未設定預設播放清單"
} }

View File

@ -1,5 +1,5 @@
name: invidious name: invidious
version: 2.20250517.0-dev version: 2.20250913.0-dev
authors: authors:
- Invidious team <contact@invidious.io> - Invidious team <contact@invidious.io>

View File

@ -60,7 +60,13 @@ alias IV = Invidious
CONFIG = Config.load CONFIG = Config.load
HMAC_KEY = CONFIG.hmac_key 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") ARCHIVE_URL = URI.parse("https://archive.org")
PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com") PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com")
REDDIT_URL = URI.parse("https://www.reddit.com") REDDIT_URL = URI.parse("https://www.reddit.com")
@ -221,8 +227,8 @@ error 404 do |env|
Invidious::Routes::ErrorRoutes.error_404(env) Invidious::Routes::ErrorRoutes.error_404(env)
end end
error 500 do |env, ex| error 500 do |env, exception|
error_template(500, ex) error_template(500, exception)
end end
static_headers do |env| static_headers do |env|

View File

@ -3,8 +3,8 @@ private IMAGE_QUALITIES = {320, 560, 640, 1280, 2000}
# TODO: Add "sort_by" # TODO: Add "sort_by"
def fetch_channel_community(ucid, cursor, locale, format, thin_mode) def fetch_channel_community(ucid, cursor, locale, format, thin_mode)
if cursor.nil? if cursor.nil?
# Egljb21tdW5pdHk%3D is the protobuf object to load "community" # EgVwb3N0c_IGBAoCSgA%3D is the protobuf object to load "posts"
initial_data = YoutubeAPI.browse(ucid, params: "Egljb21tdW5pdHk%3D") initial_data = YoutubeAPI.browse(ucid, params: "EgVwb3N0c_IGBAoCSgA%3D")
items = [] of JSON::Any items = [] of JSON::Any
extract_items(initial_data) do |item| extract_items(initial_data) do |item|
@ -24,15 +24,21 @@ 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) return extract_channel_community(items, ucid: ucid, locale: locale, format: format, thin_mode: thin_mode)
end 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) def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode)
object = { object = {
"2:string" => "community", "56:embedded" => {
"25:embedded" => { "2:string" => ucid,
"22:string" => post_id.to_s, "3:string" => post_id.to_s,
}, "11:string" => ucid,
"45:embedded" => {
"2:varint" => 1_i64,
"3:varint" => 1_i64,
}, },
} }
params = object.try { |i| Protodec::Any.cast_json(i) } params = object.try { |i| Protodec::Any.cast_json(i) }
@ -40,7 +46,7 @@ def fetch_channel_community_post(ucid, post_id, locale, format, thin_mode)
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(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 items = [] of JSON::Any
extract_items(initial_data) do |item| extract_items(initial_data) do |item|

View File

@ -6,19 +6,19 @@ def fetch_channel_playlists(ucid, author, continuation, sort_by)
case sort_by case sort_by
when "last", "last_added" when "last", "last_added"
# Equivalent to "&sort=lad" # Equivalent to "&sort=lad"
# {"2:string": "playlists", "3:varint": 4, "4:varint": 1, "6:varint": 1} # {"2:string": "playlists", "3:varint": 4, "4:varint": 1, "6:varint": 1, "110:embedded": {"1:embedded": {"8:string": ""}}}
"EglwbGF5bGlzdHMYBCABMAE%3D" "EglwbGF5bGlzdHMYBCABMAHyBgQKAkIA"
when "oldest", "oldest_created" when "oldest", "oldest_created"
# formerly "&sort=da" # formerly "&sort=da"
# Not available anymore :c or maybe ?? # Not available anymore :c or maybe ??
# {"2:string": "playlists", "3:varint": 2, "4:varint": 1, "6:varint": 1} # {"2:string": "playlists", "3:varint": 2, "4:varint": 1, "6:varint": 1, "110:embedded": {"1:embedded": {"8:string": ""}}}
"EglwbGF5bGlzdHMYAiABMAE%3D" "EglwbGF5bGlzdHMYAiABMAHyBgQKAkIA"
# {"2:string": "playlists", "3:varint": 1, "4:varint": 1, "6:varint": 1} # {"2:string": "playlists", "3:varint": 1, "4:varint": 1, "6:varint": 1}
# "EglwbGF5bGlzdHMYASABMAE%3D" # "EglwbGF5bGlzdHMYASABMAE%3D"
when "newest", "newest_created" when "newest", "newest_created"
# Formerly "&sort=dd" # Formerly "&sort=dd"
# {"2:string": "playlists", "3:varint": 3, "4:varint": 1, "6:varint": 1} # {"2:string": "playlists", "3:varint": 3, "4:varint": 1, "6:varint": 1, "110:embedded": {"1:embedded": {"8:string": ""}}}
"EglwbGF5bGlzdHMYAyABMAE%3D" "EglwbGF5bGlzdHMYAyABMAHyBgQKAkIA"
end end
initial_data = YoutubeAPI.browse(ucid, params: params || "") initial_data = YoutubeAPI.browse(ucid, params: params || "")

View File

@ -16,23 +16,27 @@ module Invidious::Comments
return parse_youtube(id, response, format, locale, thin_mode, sort_by) return parse_youtube(id, response, format, locale, thin_mode, sort_by)
end end
def fetch_community_post_comments(ucid, post_id) 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 = { object = {
"2:string" => "community", "2:string" => "posts",
"25:embedded" => {
"22:string" => post_id,
},
"45:embedded" => {
"2:varint" => 1_i64,
"3:varint" => 1_i64,
},
"53:embedded" => { "53:embedded" => {
"4:embedded" => { "4:embedded" => {
"6:varint" => 0_i64, "6:varint" => sort_by_val,
"27:varint" => 1_i64, "15:varint" => 2_i64,
"25:varint" => 0_i64,
"29:string" => post_id, "29:string" => post_id,
"30:string" => ucid, "30:string" => ucid,
}, },
"7:varint" => 0_i64,
"8:string" => "comments-section", "8:string" => "comments-section",
}, },
} }
@ -43,7 +47,7 @@ module Invidious::Comments
object2 = { object2 = {
"80226972:embedded" => { "80226972:embedded" => {
"2:string" => ucid, "2:string" => "FEcomment_post_detail_page_web_top_level",
"3:string" => object_parsed, "3:string" => object_parsed,
}, },
} }
@ -320,6 +324,15 @@ module Invidious::Comments
end end
def produce_continuation(video_id, cursor = "", sort_by = "top") 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 = { object = {
"2:embedded" => { "2:embedded" => {
"2:string" => video_id, "2:string" => video_id,
@ -340,21 +353,12 @@ module Invidious::Comments
"1:string" => cursor, "1:string" => cursor,
"4:embedded" => { "4:embedded" => {
"4:string" => video_id, "4:string" => video_id,
"6:varint" => 0_i64, "6:varint" => sort_by_val,
}, },
"5:varint" => 20_i64, "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) } continuation = object.try { |i| Protodec::Any.cast_json(i) }
.try { |i| Protodec::Any.from_json(i) } .try { |i| Protodec::Any.from_json(i) }
.try { |i| Base64.urlsafe_encode(i) } .try { |i| Base64.urlsafe_encode(i) }

View File

@ -52,6 +52,8 @@ struct ConfigPreferences
property vr_mode : Bool = true property vr_mode : Bool = true
property show_nick : Bool = true property show_nick : Bool = true
property save_player_pos : Bool = false property save_player_pos : Bool = false
@[YAML::Field(ignore: true)]
property default_playlist : String? = nil
def to_tuple def to_tuple
{% begin %} {% begin %}
@ -82,6 +84,9 @@ class Config
@[YAML::Field(converter: Preferences::URIConverter)] @[YAML::Field(converter: Preferences::URIConverter)]
property public_url : URI = URI.parse("") property public_url : URI = URI.parse("")
# Indicates if this companion instance uses the built-in proxy
property builtin_proxy : Bool = false
end end
# Number of threads to use for crawling videos from channels (for updating subscriptions) # Number of threads to use for crawling videos from channels (for updating subscriptions)
@ -271,6 +276,14 @@ class Config
puts "Config: The value of 'invidious_companion_key' needs to be a size of 16 characters." puts "Config: The value of 'invidious_companion_key' needs to be a size of 16 characters."
exit(1) exit(1)
end 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 elsif config.signature_server
puts("WARNING: inv-sig-helper is deprecated. Please switch to Invidious companion: https://docs.invidious.io/companion-installation/") puts("WARNING: inv-sig-helper is deprecated. Please switch to Invidious companion: https://docs.invidious.io/companion-installation/")
else else

View File

@ -34,7 +34,7 @@ module Invidious::Frontend::WatchPage
str << " class=\"pure-form pure-form-stacked\"" str << " class=\"pure-form pure-form-stacked\""
str << " action='#{url}'" str << " action='#{url}'"
str << " method='post'" str << " method='post'"
str << " rel='noopener'" str << " rel='noopener noreferrer'"
str << " target='_blank'>" str << " target='_blank'>"
str << '\n' str << '\n'

View File

@ -61,28 +61,13 @@ class Kemal::ExceptionHandler
end end
end end
class FilteredCompressHandler < Kemal::Handler class FilteredCompressHandler < HTTP::CompressHandler
exclude ["/videoplayback", "/videoplayback/*", "/vi/*", "/sb/*", "/ggpht/*", "/api/v1/auth/notifications"] exclude ["/videoplayback", "/videoplayback/*", "/vi/*", "/sb/*", "/ggpht/*", "/api/v1/auth/notifications"]
exclude ["/api/v1/auth/notifications", "/data_control"], "POST" exclude ["/api/v1/auth/notifications", "/data_control"], "POST"
def call(env) def call(context)
return call_next env if exclude_match? env return call_next context if exclude_match? context
super
{% 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 %}
end end
end end

View File

@ -436,7 +436,7 @@ module Invidious::Routes::API::V1::Channels
if ucid.nil? if ucid.nil?
response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}") response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}")
return error_json(400, "Invalid post ID") if response["error"]? 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 else
ucid = ucid.to_s ucid = ucid.to_s
end end
@ -460,13 +460,15 @@ module Invidious::Routes::API::V1::Channels
format = env.params.query["format"]? format = env.params.query["format"]?
format ||= "json" format ||= "json"
sort_by = env.params.query["sort_by"]?.try &.downcase
sort_by ||= "top"
continuation = env.params.query["continuation"]? continuation = env.params.query["continuation"]?
case continuation case continuation
when nil, "" when nil, ""
ucid = env.params.query["ucid"] 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 else
comments = YoutubeAPI.browse(continuation: continuation) comments = YoutubeAPI.browse(continuation: continuation)
end end

View File

@ -190,15 +190,30 @@ module Invidious::Routes::API::V1::Misc
sub_endpoint = endpoint["watchEndpoint"]? || endpoint["browseEndpoint"]? || endpoint sub_endpoint = endpoint["watchEndpoint"]? || endpoint["browseEndpoint"]? || endpoint
params = sub_endpoint.try &.dig?("params") 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 rescue ex
return error_json(500, ex) return error_json(500, ex)
end end
JSON.build do |json| JSON.build do |json|
json.object do 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 "videoId", sub_endpoint["videoId"].as_s if sub_endpoint["videoId"]?
json.field "playlistId", sub_endpoint["playlistId"].as_s if sub_endpoint["playlistId"]? 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 "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 "params", params.try &.as_s
json.field "pageType", page_type json.field "pageType", page_type
end end

View File

@ -63,6 +63,7 @@ module Invidious::Routes::BeforeAll
"/videoplayback", "/videoplayback",
"/latest_version", "/latest_version",
"/download", "/download",
"/companion/",
}.any? { |r| env.request.resource.starts_with? r } }.any? { |r| env.request.resource.starts_with? r }
if env.request.cookies.has_key? "SID" if env.request.cookies.has_key? "SID"

View File

@ -284,7 +284,7 @@ module Invidious::Routes::Channels
response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}") response = YoutubeAPI.resolve_url("https://www.youtube.com/post/#{id}")
return error_template(400, "Invalid post ID") if response["error"]? 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) post_response = fetch_channel_community_post(ucid, id, locale, "json", thin_mode)
end end

View File

@ -0,0 +1,43 @@
module Invidious::Routes::Companion
# /companion
def self.get_companion(env)
url = env.request.path
if env.request.query
url += "?#{env.request.query}"
end
begin
COMPANION_POOL.client do |wrapper|
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
if env.request.query
url += "?#{env.request.query}"
end
begin
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
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
return IO.copy response.body_io, env.response
end
end

View File

@ -20,7 +20,7 @@ module Invidious::Routes::Embed
return error_template(500, ex) return error_template(500, ex)
end end
url = "/embed/#{first_playlist_video}?#{env.params.query}" url = "/embed/#{first_playlist_video.id}?#{env.params.query}"
if env.params.query.size > 0 if env.params.query.size > 0
url += "?#{env.params.query}" url += "?#{env.params.query}"
@ -209,10 +209,17 @@ module Invidious::Routes::Embed
if CONFIG.invidious_companion.present? if CONFIG.invidious_companion.present?
invidious_companion = CONFIG.invidious_companion.sample invidious_companion = CONFIG.invidious_companion.sample
env.response.headers["Content-Security-Policy"] = invidious_companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion|
env.response.headers["Content-Security-Policy"] uri =
.gsub("media-src", "media-src #{invidious_companion.public_url}") "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}"
.gsub("connect-src", "connect-src #{invidious_companion.public_url}") end.join(" ")
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 end
rendered "embed" rendered "embed"

View File

@ -144,6 +144,8 @@ module Invidious::Routes::PreferencesRoute
notifications_only ||= "off" notifications_only ||= "off"
notifications_only = notifications_only == "on" 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 # Convert to JSON and back again to take advantage of converters used for compatibility
preferences = Preferences.from_json({ preferences = Preferences.from_json({
annotations: annotations, annotations: annotations,
@ -180,6 +182,7 @@ module Invidious::Routes::PreferencesRoute
vr_mode: vr_mode, vr_mode: vr_mode,
show_nick: show_nick, show_nick: show_nick,
save_player_pos: save_player_pos, save_player_pos: save_player_pos,
default_playlist: default_playlist,
}.to_json) }.to_json)
if user = env.get? "user" if user = env.get? "user"

View File

@ -194,10 +194,17 @@ module Invidious::Routes::Watch
if CONFIG.invidious_companion.present? if CONFIG.invidious_companion.present?
invidious_companion = CONFIG.invidious_companion.sample invidious_companion = CONFIG.invidious_companion.sample
env.response.headers["Content-Security-Policy"] = invidious_companion_urls = CONFIG.invidious_companion.reject(&.builtin_proxy).map do |companion|
env.response.headers["Content-Security-Policy"] uri =
.gsub("media-src", "media-src #{invidious_companion.public_url}") "#{companion.public_url.scheme}://#{companion.public_url.host}#{companion.public_url.port ? ":#{companion.public_url.port}" : ""}"
.gsub("connect-src", "connect-src #{invidious_companion.public_url}") end.join(" ")
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 end
templated "watch" templated "watch"

View File

@ -46,6 +46,7 @@ module Invidious::Routing
self.register_api_v1_routes self.register_api_v1_routes
self.register_api_manifest_routes self.register_api_manifest_routes
self.register_video_playback_routes self.register_video_playback_routes
self.register_companion_routes
end end
# ------------------- # -------------------
@ -188,7 +189,7 @@ module Invidious::Routing
end end
# ------------------- # -------------------
# Media proxy routes # Proxy routes
# ------------------- # -------------------
def register_api_manifest_routes def register_api_manifest_routes
@ -223,6 +224,13 @@ module Invidious::Routing
get "/vi/:id/:name", Routes::Images, :thumbnails get "/vi/:id/:name", Routes::Images, :thumbnails
end 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 # API routes
# ------------------- # -------------------

View File

@ -56,6 +56,7 @@ struct Preferences
property extend_desc : Bool = CONFIG.default_user_preferences.extend_desc property extend_desc : Bool = CONFIG.default_user_preferences.extend_desc
property volume : Int32 = CONFIG.default_user_preferences.volume property volume : Int32 = CONFIG.default_user_preferences.volume
property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos
property default_playlist : String? = nil
module BoolToString module BoolToString
def self.to_json(value : String, json : JSON::Builder) def self.to_json(value : String, json : JSON::Builder)

View File

@ -102,6 +102,9 @@ def extract_video_info(video_id : String)
# Don't fetch the next endpoint if the video is unavailable. # Don't fetch the next endpoint if the video is unavailable.
if {"OK", "LIVE_STREAM_OFFLINE", "LOGIN_REQUIRED"}.any?(playability_status) if {"OK", "LIVE_STREAM_OFFLINE", "LOGIN_REQUIRED"}.any?(playability_status)
next_response = YoutubeAPI.next({"videoId": video_id, "params": ""}) 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) player_response = player_response.merge(next_response)
end end
@ -111,16 +114,17 @@ def extract_video_info(video_id : String)
if !CONFIG.invidious_companion.present? if !CONFIG.invidious_companion.present?
if player_response.dig?("streamingData", "adaptiveFormats", 0, "url").nil? if player_response.dig?("streamingData", "adaptiveFormats", 0, "url").nil?
LOGGER.warn("Missing URLs for adaptive formats, falling back to other YT clients.") 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::TvSimply, YoutubeAPI::ClientType::WebMobile}
players_fallback.each do |player_fallback| players_fallback.each do |player_fallback|
client_config.client_type = player_fallback client_config.client_type = player_fallback
next if !(player_fallback_response = try_fetch_streaming_data(video_id, client_config)) next if !(player_fallback_response = try_fetch_streaming_data(video_id, client_config))
if player_fallback_response.dig?("streamingData", "adaptiveFormats", 0, "url") 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 = 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) player_response["streamingData"] = JSON::Any.new(streaming_data)
break break
end end
@ -146,7 +150,11 @@ def extract_video_info(video_id : String)
if streaming_data = player_response["streamingData"]? if streaming_data = player_response["streamingData"]?
%w[formats adaptiveFormats].each do |key| %w[formats adaptiveFormats].each do |key|
streaming_data.as_h[key]?.try &.as_a.each do |format| streaming_data.as_h[key]?.try &.as_a.each do |format|
format.as_h["url"] = JSON::Any.new(convert_url(format)) format = format.as_h
if format["url"]?.nil?
format["url"] = format["signatureCipher"]
end
format["url"] = JSON::Any.new(convert_url(format))
end end
end end

View File

@ -65,12 +65,18 @@
<% end %> <% end %>
<% end %> <% end %>
<% preferred_captions.each do |caption| %> <% preferred_captions.each do |caption|
<track kind="captions" src="/api/v1/captions/<%= video.id %>?label=<%= caption.name %>" label="<%= caption.name %>"> api_captions_url = "/api/v1/captions/"
api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion)
%>
<track kind="captions" src="<%= api_captions_url %><%= video.id %>?label=<%= caption.name %>" label="<%= caption.name %>">
<% end %> <% end %>
<% captions.each do |caption| %> <% captions.each do |caption|
<track kind="captions" src="/api/v1/captions/<%= video.id %>?label=<%= caption.name %>" label="<%= caption.name %>"> api_captions_url = "/api/v1/captions/"
api_captions_url = invidious_companion.public_url.to_s + api_captions_url if (invidious_companion)
%>
<track kind="captions" src="<%= api_captions_url %><%= video.id %>?label=<%= caption.name %>" label="<%= caption.name %>">
<% end %> <% end %>
<% end %> <% end %>
</video> </video>

View File

@ -14,7 +14,7 @@
<div class="pure-control-group"> <div class="pure-control-group">
<label for="import_youtube"> <label for="import_youtube">
<a rel="noopener" target="_blank" href="https://github.com/iv-org/documentation/blob/master/docs/export-youtube-subscriptions.md"> <a rel="noopener noreferrer" target="_blank" href="https://github.com/iv-org/documentation/blob/master/docs/export-youtube-subscriptions.md">
<%= translate(locale, "Import YouTube subscriptions") %> <%= translate(locale, "Import YouTube subscriptions") %>
</a> </a>
</label> </label>

View File

@ -126,6 +126,19 @@
<input name="save_player_pos" id="save_player_pos" type="checkbox" <% if preferences.save_player_pos %>checked<% end %>> <input name="save_player_pos" id="save_player_pos" type="checkbox" <% if preferences.save_player_pos %>checked<% end %>>
</div> </div>
<% if user = env.get?("user").try &.as(User) %>
<% playlists = Invidious::Database::Playlists.select_user_created_playlists(user.email) %>
<div class="pure-control-group">
<label for="default_playlist"><%= translate(locale, "preferences_default_playlist") %></label>
<select name="default_playlist" id="default_playlist">
<option value=""><%= translate(locale, "preferences_default_playlist_none") %></option>
<% playlists.each do |plid, playlist_title| %>
<option value="<%= plid %>" <%= "selected" if user.preferences.default_playlist == plid %>><%= HTML.escape(playlist_title) %></option>
<% end %>
</select>
</div>
<% end %>
<legend><%= translate(locale, "preferences_category_visual") %></legend> <legend><%= translate(locale, "preferences_category_visual") %></legend>
<div class="pure-control-group"> <div class="pure-control-group">

View File

@ -163,7 +163,7 @@ we're going to need to do it here in order to allow for translations.
<label for="playlist_id"><%= translate(locale, "Add to playlist: ") %></label> <label for="playlist_id"><%= translate(locale, "Add to playlist: ") %></label>
<select style="width:100%" name="playlist_id" id="playlist_id"> <select style="width:100%" name="playlist_id" id="playlist_id">
<% playlists.each do |plid, playlist_title| %> <% playlists.each do |plid, playlist_title| %>
<option data-plid="<%= plid %>" value="<%= plid %>"><%= HTML.escape(playlist_title) %></option> <option data-plid="<%= plid %>" value="<%= plid %>" <%= "selected" if user.preferences.default_playlist == plid %>><%= HTML.escape(playlist_title) %></option>
<% end %> <% end %>
</select> </select>
</div> </div>

View File

@ -46,8 +46,27 @@ struct YoutubeConnectionPool
end end
end 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.
struct CompanionWrapper
property client : HTTP::Client
property companion : Config::CompanionConfig
def initialize(companion : Config::CompanionConfig)
@companion = companion
@client = make_client(companion.private_url, use_http_proxy: false)
end
def close
@client.close
end
end
struct CompanionConnectionPool struct CompanionConnectionPool
property pool : DB::Pool(HTTP::Client) property pool : DB::Pool(CompanionWrapper)
def initialize(capacity = 5, timeout = 5.0) def initialize(capacity = 5, timeout = 5.0)
options = DB::Pool::Options.new( options = DB::Pool::Options.new(
@ -57,26 +76,28 @@ struct CompanionConnectionPool
checkout_timeout: timeout checkout_timeout: timeout
) )
@pool = DB::Pool(HTTP::Client).new(options) do @pool = DB::Pool(CompanionWrapper).new(options) do
companion = CONFIG.invidious_companion.sample companion = CONFIG.invidious_companion.sample
next make_client(companion.private_url, use_http_proxy: false) make_client(companion.private_url, use_http_proxy: false)
CompanionWrapper.new(companion: companion)
end end
end end
def client(&) def client(&)
conn = pool.checkout wrapper = pool.checkout
begin begin
response = yield conn response = yield wrapper
rescue ex rescue ex
conn.close wrapper.close
companion = CONFIG.invidious_companion.sample companion = CONFIG.invidious_companion.sample
conn = 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 conn response = yield wrapper
ensure ensure
pool.release(conn) pool.release(wrapper)
end end
response response

View File

@ -6,10 +6,10 @@ module YoutubeAPI
extend self extend self
# For Android versions, see https://en.wikipedia.org/wiki/Android_version_history # For Android versions, see https://en.wikipedia.org/wiki/Android_version_history
private ANDROID_APP_VERSION = "19.32.34" private ANDROID_APP_VERSION = "19.35.36"
private ANDROID_VERSION = "12" 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 = 31_i64 private ANDROID_SDK_VERSION = 33_i64
private ANDROID_TS_APP_VERSION = "1.9" private ANDROID_TS_APP_VERSION = "1.9"
private ANDROID_TS_USER_AGENT = "com.google.android.youtube/1.9 (Linux; U; Android 12; US) gzip" private ANDROID_TS_USER_AGENT = "com.google.android.youtube/1.9 (Linux; U; Android 12; US) gzip"
@ -17,9 +17,9 @@ module YoutubeAPI
# For Apple device names, see https://gist.github.com/adamawolf/3048717 # For Apple device names, see https://gist.github.com/adamawolf/3048717
# For iOS versions, see https://en.wikipedia.org/wiki/IOS_version_history#Releases, # 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. # 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_USER_AGENT = "com.google.ios.youtube/#{IOS_APP_VERSION} (iPhone14,5; U; CPU iOS 18_5 like Mac OS X;)"
private IOS_VERSION = "17.6.1.21G93" # Major.Minor.Patch.Build private IOS_VERSION = "18.5.0.22F76" # Major.Minor.Patch.Build
private WINDOWS_VERSION = "10.0" private WINDOWS_VERSION = "10.0"
@ -42,6 +42,7 @@ module YoutubeAPI
TvHtml5 TvHtml5
TvHtml5ScreenEmbed TvHtml5ScreenEmbed
TvSimply
end end
# List of hard-coded values used by the different clients # List of hard-coded values used by the different clients
@ -49,7 +50,7 @@ module YoutubeAPI
ClientType::Web => { ClientType::Web => {
name: "WEB", name: "WEB",
name_proto: "1", name_proto: "1",
version: "2.20240814.00.00", version: "2.20250222.10.00",
screen: "WATCH_FULL_SCREEN", screen: "WATCH_FULL_SCREEN",
os_name: "Windows", os_name: "Windows",
os_version: WINDOWS_VERSION, os_version: WINDOWS_VERSION,
@ -58,7 +59,7 @@ module YoutubeAPI
ClientType::WebEmbeddedPlayer => { ClientType::WebEmbeddedPlayer => {
name: "WEB_EMBEDDED_PLAYER", name: "WEB_EMBEDDED_PLAYER",
name_proto: "56", name_proto: "56",
version: "1.20240812.01.00", version: "1.20250219.01.00",
screen: "EMBED", screen: "EMBED",
os_name: "Windows", os_name: "Windows",
os_version: WINDOWS_VERSION, os_version: WINDOWS_VERSION,
@ -67,7 +68,7 @@ module YoutubeAPI
ClientType::WebMobile => { ClientType::WebMobile => {
name: "MWEB", name: "MWEB",
name_proto: "2", name_proto: "2",
version: "2.20240813.02.00", version: "2.20250224.01.00",
os_name: "Android", os_name: "Android",
os_version: ANDROID_VERSION, os_version: ANDROID_VERSION,
platform: "MOBILE", platform: "MOBILE",
@ -75,7 +76,7 @@ module YoutubeAPI
ClientType::WebScreenEmbed => { ClientType::WebScreenEmbed => {
name: "WEB", name: "WEB",
name_proto: "1", name_proto: "1",
version: "2.20240814.00.00", version: "2.20250222.10.00",
screen: "EMBED", screen: "EMBED",
os_name: "Windows", os_name: "Windows",
os_version: WINDOWS_VERSION, os_version: WINDOWS_VERSION,
@ -84,7 +85,7 @@ module YoutubeAPI
ClientType::WebCreator => { ClientType::WebCreator => {
name: "WEB_CREATOR", name: "WEB_CREATOR",
name_proto: "62", name_proto: "62",
version: "1.20240918.03.00", version: "1.20241203.01.00",
os_name: "Windows", os_name: "Windows",
os_version: WINDOWS_VERSION, os_version: WINDOWS_VERSION,
platform: "DESKTOP", platform: "DESKTOP",
@ -170,7 +171,7 @@ module YoutubeAPI
ClientType::TvHtml5 => { ClientType::TvHtml5 => {
name: "TVHTML5", name: "TVHTML5",
name_proto: "7", name_proto: "7",
version: "7.20240813.07.00", version: "7.20250219.14.00",
}, },
ClientType::TvHtml5ScreenEmbed => { ClientType::TvHtml5ScreenEmbed => {
name: "TVHTML5_SIMPLY_EMBEDDED_PLAYER", name: "TVHTML5_SIMPLY_EMBEDDED_PLAYER",
@ -178,6 +179,11 @@ module YoutubeAPI
version: "2.0", version: "2.0",
screen: "EMBED", screen: "EMBED",
}, },
ClientType::TvSimply => {
name: "TVHTML5_SIMPLY",
name_proto: "74",
version: "1.0",
},
} }
#################################################################### ####################################################################
@ -695,22 +701,20 @@ module YoutubeAPI
# Send the POST request # Send the POST request
begin begin
response = COMPANION_POOL.client &.post(endpoint, headers: headers, body: data.to_json) response_body = Hash(String, JSON::Any).new
body = response.body
if (response.status_code != 200) COMPANION_POOL.client do |wrapper|
raise Exception.new( companion_base_url = wrapper.companion.private_url.path
"Error while communicating with Invidious companion: \
status code: #{response.status_code} and body: #{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 end
return response_body
rescue ex rescue ex
raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found")) raise InfoException.new("Error while communicating with Invidious companion: " + (ex.message || "no extra info found"))
end end
# Convert result to Hash
initial_data = JSON.parse(body).as_h
return initial_data
end end
#################################################################### ####################################################################