Merge branch 'development' into add-command-line-arg-to-search

This commit is contained in:
ChunkyProgrammer 2024-03-07 20:18:02 -05:00
commit 40c1c01b4b
105 changed files with 2687 additions and 1422 deletions

View File

@ -1 +1,17 @@
blank_issues_enabled: false
contact_links:
- name: Discussions
url: https://github.com/FreeTubeApp/FreeTube/discussions/categories/general
about: View discussions or start one yourself
- name: Questions
url: https://github.com/FreeTubeApp/FreeTube/discussions/categories/q-a
about: Ask and answer questions
- name: Matrix Community
url: https://matrix.to/#/+freetube:matrix.org
about: Join our Matrix chatroom - "Note: Bugs and Feature requests should be made on GitHub and not in the Matrix room"
- name: Translate FreeTube
url: https://hosted.weblate.org/engage/free-tube/
about: Help translate FreeTube on Weblate
- name: FreeTube Documentation
url: https://docs.freetubeapp.io/
about: View the Documentation to find all relevant information about FreeTube

View File

@ -1,6 +1,5 @@
process.env.NODE_ENV = 'development'
const open = require('open')
const electron = require('electron')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
@ -161,7 +160,8 @@ function startWeb (callback) {
if (!web) {
startRenderer(startMain)
} else {
startWeb(({ port }) => {
startWeb(async ({ port }) => {
const open = (await import('open')).default
open(`http://localhost:${port}`)
})
}

View File

@ -11,6 +11,8 @@ const CopyWebpackPlugin = require('copy-webpack-plugin')
const isDevMode = process.env.NODE_ENV === 'development'
const { version: swiperVersion } = JSON.parse(readFileSync(path.join(__dirname, '../node_modules/swiper/package.json')))
const processLocalesPlugin = new ProcessLocalesPlugin({
compress: !isDevMode,
inputDir: path.join(__dirname, '../static/locales'),
@ -118,7 +120,8 @@ const config = {
'process.env.IS_ELECTRON': true,
'process.env.IS_ELECTRON_MAIN': false,
'process.env.LOCALE_NAMES': JSON.stringify(processLocalesPlugin.localeNames),
'process.env.GEOLOCATION_NAMES': JSON.stringify(readdirSync(path.join(__dirname, '..', 'static', 'geolocations')).map(filename => filename.replace('.json', '')))
'process.env.GEOLOCATION_NAMES': JSON.stringify(readdirSync(path.join(__dirname, '..', 'static', 'geolocations')).map(filename => filename.replace('.json', ''))),
'process.env.SWIPER_VERSION': `'${swiperVersion}'`
}),
new HtmlWebpackPlugin({
excludeChunks: ['processTaskWorker'],
@ -137,7 +140,7 @@ const config = {
patterns: [
{
from: path.join(__dirname, '../node_modules/swiper/modules/{a11y,navigation,pagination}-element.css').replaceAll('\\', '/'),
to: 'swiper.css',
to: `swiper-${swiperVersion}.css`,
context: path.join(__dirname, '../node_modules/swiper/modules'),
transformAll: (assets) => {
return Buffer.concat(assets.map(asset => asset.data))

View File

@ -11,6 +11,8 @@ const ProcessLocalesPlugin = require('./ProcessLocalesPlugin')
const isDevMode = process.env.NODE_ENV === 'development'
const { version: swiperVersion } = JSON.parse(fs.readFileSync(path.join(__dirname, '../node_modules/swiper/package.json')))
const config = {
name: 'web',
mode: process.env.NODE_ENV,
@ -114,6 +116,7 @@ const config = {
new webpack.DefinePlugin({
'process.env.IS_ELECTRON': false,
'process.env.IS_ELECTRON_MAIN': false,
'process.env.SWIPER_VERSION': `'${swiperVersion}'`,
// video.js' vhs-utils supports both atob() in web browsers and Buffer in node
// As the FreeTube web build only runs in web browsers, we can override their check for atob() here: https://github.com/videojs/vhs-utils/blob/main/src/decode-b64-to-uint8-array.js#L3
@ -145,7 +148,7 @@ const config = {
patterns: [
{
from: path.join(__dirname, '../node_modules/swiper/modules/{a11y,navigation,pagination}-element.css').replaceAll('\\', '/'),
to: 'swiper.css',
to: `swiper-${swiperVersion}.css`,
context: path.join(__dirname, '../node_modules/swiper/modules'),
transformAll: (assets) => {
return Buffer.concat(assets.map(asset => asset.data))

View File

@ -62,10 +62,10 @@
"autolinker": "^4.0.0",
"electron-context-menu": "^3.6.1",
"lodash.debounce": "^4.0.8",
"marked": "^11.2.0",
"marked": "^12.0.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"swiper": "^11.0.6",
"swiper": "^11.0.7",
"video.js": "7.21.5",
"videojs-contrib-quality-levels": "^3.0.0",
"videojs-http-source-selector": "^1.1.6",
@ -77,21 +77,21 @@
"vue-observe-visibility": "^1.0.0",
"vue-router": "^3.6.5",
"vuex": "^3.6.2",
"youtubei.js": "^9.0.2"
"youtubei.js": "^9.1.0"
},
"devDependencies": {
"@babel/core": "^7.23.9",
"@babel/core": "^7.24.0",
"@babel/eslint-parser": "^7.23.10",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.23.9",
"@double-great/stylelint-a11y": "^3.0.1",
"@babel/preset-env": "^7.24.0",
"@double-great/stylelint-a11y": "^3.0.2",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^6.10.0",
"css-minimizer-webpack-plugin": "^6.0.0",
"electron": "^28.2.2",
"electron-builder": "^24.9.1",
"eslint": "^8.56.0",
"electron": "^29.1.0",
"electron-builder": "^24.13.3",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.29.1",
@ -100,21 +100,21 @@
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-unicorn": "^51.0.1",
"eslint-plugin-vue": "^9.21.1",
"eslint-plugin-vue": "^9.22.0",
"eslint-plugin-vuejs-accessibility": "^2.2.1",
"eslint-plugin-yml": "^1.12.2",
"html-webpack-plugin": "^5.6.0",
"js-yaml": "^4.1.0",
"json-minimizer-webpack-plugin": "^5.0.0",
"lefthook": "^1.6.1",
"mini-css-extract-plugin": "^2.8.0",
"lefthook": "^1.6.4",
"mini-css-extract-plugin": "^2.8.1",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.35",
"postcss-scss": "^4.0.9",
"prettier": "^2.8.8",
"rimraf": "^5.0.5",
"sass": "^1.70.0",
"sass-loader": "^14.1.0",
"sass": "^1.71.1",
"sass-loader": "^14.1.1",
"stylelint": "^16.2.1",
"stylelint-config-sass-guidelines": "^11.0.0",
"stylelint-config-standard": "^36.0.0",
@ -124,9 +124,9 @@
"vue-devtools": "^5.1.4",
"vue-eslint-parser": "^9.4.2",
"vue-loader": "^15.10.0",
"webpack": "^5.90.1",
"webpack": "^5.90.3",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-dev-server": "^5.0.2",
"webpack-watch-external-files-plugin": "^3.0.0",
"yaml-eslint-parser": "^1.2.2"
}

View File

@ -64,7 +64,9 @@ function runApp() {
const path = urlParts[1]
if (path) {
visible = ['/playlist', '/channel', '/watch'].some(p => path.startsWith(p))
visible = ['/channel', '/watch'].some(p => path.startsWith(p)) ||
// Only show copy link entry for non user playlists
(path.startsWith('/playlist') && !/playlistType=user/.test(path))
}
} else {
visible = true
@ -103,17 +105,17 @@ function runApp() {
let url
if (toYouTube) {
url = `https://youtu.be/${id}`
url = new URL(`https://youtu.be/${id}`)
} else {
url = `https://redirect.invidious.io/watch?v=${id}`
url = new URL(`https://redirect.invidious.io/watch?v=${id}`)
}
if (query) {
const params = new URLSearchParams(query)
const newParams = new URLSearchParams()
const newParams = new URLSearchParams(url.search)
let hasParams = false
if (params.has('playlistId')) {
if (params.has('playlistId') && params.get('playlistType') !== 'user') {
newParams.set('list', params.get('playlistId'))
hasParams = true
}
@ -124,11 +126,11 @@ function runApp() {
}
if (hasParams) {
url += '?' + newParams.toString()
url.search = newParams.toString()
}
}
return url
return url.toString()
}
}
}

View File

@ -882,7 +882,23 @@ export default defineComponent({
showToast(`${message}: ${err}`)
return
}
const playlists = JSON.parse(data)
let playlists = null
// for the sake of backwards compatibility,
// check if this is the old JSON array export (used until version 0.19.1),
// that didn't match the actual database format
const trimmedData = data.trim()
if (trimmedData[0] === '[' && trimmedData[trimmedData.length - 1] === ']') {
playlists = JSON.parse(trimmedData)
} else {
// otherwise assume this is the correct database format,
// which is also what we export now (used in 0.20.0 and later versions)
data = data.split('\n')
data.pop()
playlists = data.map(playlistJson => JSON.parse(playlistJson))
}
const requiredKeys = [
'playlistName',
@ -1015,7 +1031,11 @@ export default defineComponent({
]
}
await this.promptAndWriteToFile(options, JSON.stringify(this.allPlaylists), 'All playlists has been successfully exported')
const playlistsDb = this.allPlaylists.map(playlist => {
return JSON.stringify(playlist)
}).join('\n') + '\n'// a trailing line is expected
await this.promptAndWriteToFile(options, playlistsDb, 'All playlists has been successfully exported')
},
exportPlaylistsForOlderVersionsSometimes: function () {
@ -1133,7 +1153,7 @@ export default defineComponent({
})
if (process.env.IS_ELECTRON && this.backendFallback && this.backendPreference === 'invidious') {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
resolve(this.getChannelInfoLocal(channelId))
} else {
resolve([])

View File

@ -3,10 +3,14 @@ import { defineComponent } from 'vue'
export default defineComponent({
name: 'FtAgeRestricted',
props: {
contentTypeString: {
type: String,
required: true
}
isChannel: {
type: Boolean,
default: false,
},
isVideo: {
type: Boolean,
default: false,
},
},
computed: {
emoji: function () {
@ -15,8 +19,11 @@ export default defineComponent({
},
restrictedMessage: function () {
const contentType = this.$t('Age Restricted.Type.' + this.contentTypeString)
return this.$t('Age Restricted.This {videoOrPlaylist} is age restricted', { videoOrPlaylist: contentType })
if (this.isChannel) {
return this.$t('Age Restricted.This channel is age restricted')
}
return this.$t('Age Restricted.This video is age restricted:')
}
}
})

View File

@ -40,7 +40,6 @@ export default defineComponent({
voteCount: '',
postContent: '',
commentCount: '',
isLoading: true,
author: '',
authorId: '',
}
@ -73,7 +72,7 @@ export default defineComponent({
injectStylesUrls: [
// This file is created with the copy webpack plugin in the web and renderer webpack configs.
// If you add more modules, please remember to add their CSS files to the list in webpack config files.
createWebURL('/swiper.css')
createWebURL(`/swiper-${process.env.SWIPER_VERSION}.css`)
],
a11y: true,
@ -132,7 +131,6 @@ export default defineComponent({
this.type = (this.data.postContent !== null && this.data.postContent !== undefined) ? this.data.postContent.type : 'text'
this.author = this.data.author
this.authorId = this.data.authorId
this.isLoading = false
},
getBestQualityImage(imageArray) {

View File

@ -1,6 +1,5 @@
<template>
<div
v-if="!isLoading"
class="ft-list-post ft-list-item outside"
:appearance="appearance"
:class="{ list: listType === 'list', grid: listType === 'grid' }"

View File

@ -128,6 +128,11 @@ export default defineComponent({
handleResize: function () {
this.useModal = window.innerWidth <= 900
}
},
focus() {
// To be called by parent components
this.$refs.iconButton.focus()
},
}
})

View File

@ -1,6 +1,7 @@
<template>
<div class="ftIconButton">
<font-awesome-icon
ref="iconButton"
class="iconButton"
:title="title"
:icon="icon"

View File

@ -3,3 +3,8 @@
.thumbnailLink:hover {
outline: 3px solid var(--side-nav-hover-color);
}
.thumbnailImage {
// Makes img element sized correctly before image loading starts
aspect-ratio: 16/9 auto;
}

View File

@ -152,7 +152,7 @@
<ft-icon-button
class="optionsButton"
:icon="['fas', 'ellipsis-v']"
title="More Options"
:title="$t('Video.More Options')"
theme="base-no-default"
:size="16"
:use-shadow="false"

View File

@ -38,7 +38,7 @@
>
<ft-playlist-selector
tabindex="0"
:data="playlist"
:playlist="playlist"
:index="index"
:selected="selectedPlaylistIdList.includes(playlist._id)"
@selected="countSelected(playlist._id)"

View File

@ -8,7 +8,7 @@ export default defineComponent({
'ft-icon-button': FtIconButton
},
props: {
data: {
playlist: {
type: Object,
required: true,
},
@ -30,6 +30,8 @@ export default defineComponent({
title: '',
thumbnail: require('../../assets/img/thumbnail_placeholder.svg'),
videoCount: 0,
videoPresenceCountInPlaylistTextShouldBeVisible: false,
}
},
computed: {
@ -39,6 +41,9 @@ export default defineComponent({
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},
toBeAddedToPlaylistVideoList: function () {
return this.$store.getters.getToBeAddedToPlaylistVideoList
},
titleForDisplay: function () {
if (typeof this.title !== 'string') { return '' }
@ -46,28 +51,63 @@ export default defineComponent({
return `${this.title.substring(0, 255)}...`
},
loneToBeAddedToPlaylistVideo: function () {
if (this.toBeAddedToPlaylistVideoList.length !== 1) { return null }
return this.toBeAddedToPlaylistVideoList[0]
},
loneVideoPresenceCountInPlaylist() {
if (this.loneToBeAddedToPlaylistVideo == null) { return null }
const v = this.playlist.videos.reduce((accumulator, video) => {
return video.videoId === this.loneToBeAddedToPlaylistVideo.videoId
? accumulator + 1
: accumulator
}, 0)
// Don't display zero value
return v === 0 ? null : v
},
loneVideoPresenceCountInPlaylistText() {
if (this.loneVideoPresenceCountInPlaylist == null) { return null }
return this.$tc('User Playlists.AddVideoPrompt.Added {count} Times', this.loneVideoPresenceCountInPlaylist, {
count: this.loneVideoPresenceCountInPlaylist,
})
},
videoPresenceCountInPlaylistTextVisible() {
if (!this.videoPresenceCountInPlaylistTextShouldBeVisible) { return false }
return this.loneVideoPresenceCountInPlaylistText != null
},
},
created: function () {
this.parseUserData()
},
methods: {
parseUserData: function () {
this.title = this.data.playlistName
if (this.data.videos.length > 0) {
const thumbnailURL = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
this.title = this.playlist.playlistName
if (this.playlist.videos.length > 0) {
const thumbnailURL = `https://i.ytimg.com/vi/${this.playlist.videos[0].videoId}/mqdefault.jpg`
if (this.backendPreference === 'invidious') {
this.thumbnail = thumbnailURL.replace('https://i.ytimg.com', this.currentInvidiousInstance)
} else {
this.thumbnail = thumbnailURL
}
}
this.videoCount = this.data.videos.length
this.videoCount = this.playlist.videos.length
},
toggleSelection: function () {
this.$emit('selected', this.index)
},
onVisibilityChanged(visible) {
if (!visible) { return }
this.videoPresenceCountInPlaylistTextShouldBeVisible = true
},
...mapActions([
'openInExternalPlayer'
])

View File

@ -54,6 +54,10 @@
word-wrap: break-word;
word-break: break-word;
}
.videoPresenceCount {
margin-block-start: 4px;
}
}
&.grid {

View File

@ -29,12 +29,24 @@
</div>
</div>
</div>
<div class="info">
<span
<div
v-observe-visibility="{
callback: onVisibilityChanged,
once: true,
}"
class="info"
>
<div
class="title"
>
{{ titleForDisplay }}
</span>
</div>
<div
v-if="videoPresenceCountInPlaylistTextVisible"
class="videoPresenceCount"
>
{{ loneVideoPresenceCountInPlaylistText }}
</div>
</div>
</div>
</template>

View File

@ -9,18 +9,29 @@ export default defineComponent({
}
},
methods: {
catchTimestampClick: function(event) {
const match = event.detail.match(/(\d+):(\d+):?(\d+)?/)
if (match[3] !== undefined) { // HH:MM:SS
const seconds = 3600 * Number(match[1]) + 60 * Number(match[2]) + Number(match[3])
this.$emit('timestamp-event', seconds)
} else { // MM:SS
const seconds = 60 * Number(match[1]) + Number(match[2])
this.$emit('timestamp-event', seconds)
}
catchTimestampClick: function (event) {
this.$emit('timestamp-event', event.detail)
},
detectTimestamps: function (input) {
return input.replaceAll(/(\d+(:\d+)+)/g, '<a href="#" onclick="this.dispatchEvent(new CustomEvent(\'timestamp-clicked\',{bubbles:true, detail:\'$1\'}))">$1</a>')
const videoId = this.$route.params.id
return input.replaceAll(/(?:(\d+):)?(\d+):(\d+)/g, (timestamp, hours, minutes, seconds) => {
let time = 60 * Number(minutes) + Number(seconds)
if (hours) {
time += 3600 * Number(hours)
}
const url = this.$router.resolve({
path: `/watch/${videoId}`,
query: {
timestamp: time
}
}).href
// Adding the URL lets the user open the video in a new window at this timestamp
return `<a href="${url}" onclick="event.preventDefault();this.dispatchEvent(new CustomEvent('timestamp-clicked',{bubbles:true,detail:${time}}));window.scrollTo(0,0)">${timestamp}</a>`
})
}
}
})

View File

@ -1,6 +1,8 @@
import { defineComponent } from 'vue'
import FtToastEvents from './ft-toast-events.js'
let id = 0
export default defineComponent({
name: 'FtToast',
data: function () {
@ -15,7 +17,9 @@ export default defineComponent({
FtToastEvents.removeEventListener('toast-open', this.open)
},
methods: {
performAction: function (index) {
performAction: function (id) {
const index = this.toasts.findIndex(toast => id === toast.id)
this.toasts[index].action()
this.remove(index)
},
@ -26,7 +30,13 @@ export default defineComponent({
toast.isOpen = false
},
open: function ({ detail: { message, time, action } }) {
const toast = { message: message, action: action || (() => { }), isOpen: false, timeout: null }
const toast = {
message: message,
action: action || (() => { }),
isOpen: false,
timeout: null,
id: id++
}
toast.timeout = setTimeout(this.close, time || 3000, toast)
setTimeout(() => { toast.isOpen = true })
if (this.toasts.length > 4) {

View File

@ -1,15 +1,15 @@
<template>
<div class="toast-holder">
<div
v-for="(toast, index) in toasts"
:key="'toast-' + index"
v-for="toast in toasts"
:key="toast.id"
class="toast"
:class="{ closed: !toast.isOpen, open: toast.isOpen }"
tabindex="0"
role="status"
@click="performAction(index)"
@keydown.enter.prevent="performAction(index)"
@keydown.space.prevent="performAction(index)"
@click="performAction(toast.id)"
@keydown.enter.prevent="performAction(toast.id)"
@keydown.space.prevent="performAction(toast.id)"
>
<p class="message">
{{ toast.message }}

View File

@ -5,10 +5,12 @@ import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
import FtInput from '../ft-input/ft-input.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtButton from '../ft-button/ft-button.vue'
import {
formatNumber,
showToast,
} from '../../helpers/utils'
import debounce from 'lodash.debounce'
export default defineComponent({
name: 'PlaylistInfo',
@ -18,6 +20,7 @@ export default defineComponent({
'ft-icon-button': FtIconButton,
'ft-input': FtInput,
'ft-prompt': FtPrompt,
'ft-button': FtButton,
},
props: {
id: {
@ -83,6 +86,9 @@ export default defineComponent({
},
data: function () {
return {
searchVideoMode: false,
query: '',
updateQueryDebounce: function() {},
editMode: false,
showDeletePlaylistPrompt: false,
showRemoveVideosOnWatchPrompt: false,
@ -232,6 +238,8 @@ export default defineComponent({
created: function () {
this.newTitle = this.title
this.newDescription = this.description
this.updateQueryDebounce = debounce(this.updateQuery, 500)
},
methods: {
toggleCopyVideosPrompt: function (force = false) {
@ -373,6 +381,30 @@ export default defineComponent({
showToast(this.$t('User Playlists.SinglePlaylistView.Toast.Quick bookmark disabled'))
},
updateQuery(query) {
this.query = query
this.$emit('search-video-query-change', query)
},
enableVideoSearchMode() {
this.searchVideoMode = true
this.$emit('search-video-mode-on')
nextTick(() => {
// Some elements only present after rendering update
this.$refs.searchInput.focus()
})
},
disableVideoSearchMode() {
this.searchVideoMode = false
this.updateQuery('')
this.$emit('search-video-mode-off')
nextTick(() => {
// Some elements only present after rendering update
this.$refs.enableSearchModeButton?.focus()
})
},
...mapActions([
'showAddToPlaylistPromptForManyVideos',
'updatePlaylist',

View File

@ -72,3 +72,20 @@
column-gap: 8px;
justify-content: flex-end;
}
.searchInputsRow {
margin-block-start: 8px;
display: grid;
/* 2 columns */
grid-template-columns: 1fr auto;
column-gap: 8px;
}
@media only screen and (max-width: 1250px) {
:deep(.sharePlaylistIcon .iconDropdown) {
inset-inline-start: auto;
inset-inline-end: auto;
}
}

View File

@ -76,6 +76,7 @@
<hr>
<div
v-if="!searchVideoMode"
class="channelShareWrapper"
>
<router-link
@ -106,6 +107,14 @@
</div>
<div class="playlistOptions">
<ft-icon-button
v-if="isUserPlaylist && videoCount > 0 && !editMode"
ref="enableSearchModeButton"
:title="$t('User Playlists.SinglePlaylistView.Search for Videos')"
:icon="['fas', 'search']"
theme="secondary"
@click="enableVideoSearchMode"
/>
<ft-icon-button
v-if="editMode"
:title="$t('User Playlists.Save Changes')"
@ -166,6 +175,7 @@
<ft-share-button
v-if="sharePlaylistButtonVisible"
:id="id"
class="sharePlaylistIcon"
:dropdown-position-y="description ? 'top' : 'bottom'"
share-target-type="Playlist"
/>
@ -186,6 +196,28 @@
@click="handleRemoveVideosOnWatchPromptAnswer"
/>
</div>
<div
v-if="isUserPlaylist && searchVideoMode"
class="searchInputsRow"
>
<ft-input
ref="searchInput"
class="searchInput"
:placeholder="$t('User Playlists.SinglePlaylistView.Search for Videos')"
:show-clear-text-button="true"
:show-action-button="false"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
<ft-icon-button
v-if="isUserPlaylist && searchVideoMode"
:title="$t('User Playlists.Cancel')"
:icon="['fas', 'times']"
theme="secondary"
@click="disableVideoSearchMode"
/>
</div>
</div>
</template>

View File

@ -44,6 +44,7 @@
/>
</div>
<p
v-if="!hideLabelsSideBar"
id="channelLabel"
class="navLabel"
>

View File

@ -121,6 +121,8 @@ export default defineComponent({
this.attemptedFetch = true
this.errorChannels = []
const subscriptionUpdates = []
const postListFromRemote = (await Promise.all(channelsToLoadFromRemote.map(async (channel) => {
let posts = []
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
@ -137,6 +139,32 @@ export default defineComponent({
channelId: channel.id,
posts: posts,
})
if (posts.length > 0) {
const post = posts.find(post => post.authorId === channel.id)
if (post) {
const name = post.author
let thumbnailUrl = post.authorThumbnails?.[0]?.url
if (name || thumbnailUrl) {
if (thumbnailUrl) {
if (thumbnailUrl.startsWith('//')) {
thumbnailUrl = 'https:' + thumbnailUrl
} else if (thumbnailUrl.startsWith(`${this.currentInvidiousInstance}/ggpht`)) {
thumbnailUrl = thumbnailUrl.replace(`${this.currentInvidiousInstance}/ggpht`, 'https://yt3.googleusercontent.com')
}
}
subscriptionUpdates.push({
channelId: channel.id,
channelName: name,
channelThumbnailUrl: thumbnailUrl
})
}
}
}
return posts
}))).flatMap((o) => o)
postList.push(...postListFromRemote)
@ -147,6 +175,8 @@ export default defineComponent({
this.postList = postList
this.isLoading = false
this.updateShowProgressBar(false)
this.batchUpdateSubscriptionDetails(subscriptionUpdates)
},
maybeLoadPostsForSubscriptionsFromRemote: async function () {
@ -200,7 +230,7 @@ export default defineComponent({
copyToClipboard(err)
})
if (process.env.IS_ELECTRON && this.backendPreference === 'invidious' && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
resolve(this.getChannelPostsLocal(channel))
} else {
resolve([])
@ -211,6 +241,7 @@ export default defineComponent({
...mapActions([
'updateShowProgressBar',
'batchUpdateSubscriptionDetails',
'updateSubscriptionPostsCacheByChannel',
]),

View File

@ -129,19 +129,23 @@ export default defineComponent({
this.attemptedFetch = true
this.errorChannels = []
const subscriptionUpdates = []
const videoListFromRemote = (await Promise.all(channelsToLoadFromRemote.map(async (channel) => {
let videos = []
let name, thumbnailUrl
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
if (useRss) {
videos = await this.getChannelLiveInvidiousRSS(channel)
({ videos, name, thumbnailUrl } = await this.getChannelLiveInvidiousRSS(channel))
} else {
videos = await this.getChannelLiveInvidious(channel)
({ videos, name, thumbnailUrl } = await this.getChannelLiveInvidious(channel))
}
} else {
if (useRss) {
videos = await this.getChannelLiveLocalRSS(channel)
({ videos, name, thumbnailUrl } = await this.getChannelLiveLocalRSS(channel))
} else {
videos = await this.getChannelLiveLocal(channel)
({ videos, name, thumbnailUrl } = await this.getChannelLiveLocal(channel))
}
}
@ -152,6 +156,15 @@ export default defineComponent({
channelId: channel.id,
videos: videos,
})
if (name || thumbnailUrl) {
subscriptionUpdates.push({
channelId: channel.id,
channelName: name,
channelThumbnailUrl: thumbnailUrl
})
}
return videos
}))).flatMap((o) => o)
videoList.push(...videoListFromRemote)
@ -159,6 +172,8 @@ export default defineComponent({
this.videoList = updateVideoListAfterProcessing(videoList)
this.isLoading = false
this.updateShowProgressBar(false)
this.batchUpdateSubscriptionDetails(subscriptionUpdates)
},
maybeLoadVideosForSubscriptionsFromRemote: async function () {
@ -174,16 +189,18 @@ export default defineComponent({
getChannelLiveLocal: async function (channel, failedAttempts = 0) {
try {
const entries = await getLocalChannelLiveStreams(channel.id)
const result = await getLocalChannelLiveStreams(channel.id)
if (entries === null) {
if (result === null) {
this.errorChannels.push(channel)
return []
return {
videos: []
}
}
addPublishedDatesLocal(entries)
addPublishedDatesLocal(result.videos)
return entries
return result
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -198,12 +215,16 @@ export default defineComponent({
showToast(this.$t('Falling back to Invidious API'))
return await this.getChannelLiveInvidious(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
case 2:
return await this.getChannelLiveLocalRSS(channel, failedAttempts + 1)
default:
return []
return {
videos: []
}
}
}
},
@ -227,7 +248,9 @@ export default defineComponent({
this.errorChannels.push(channel)
}
return []
return {
videos: []
}
}
return await parseYouTubeRSSFeed(await response.text(), channel.id)
@ -245,12 +268,16 @@ export default defineComponent({
showToast(this.$t('Falling back to Invidious API'))
return this.getChannelLiveInvidiousRSS(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
case 2:
return this.getChannelLiveLocal(channel, failedAttempts + 1)
default:
return []
return {
videos: []
}
}
}
},
@ -269,7 +296,16 @@ export default defineComponent({
addPublishedDatesInvidious(videos)
resolve(videos)
let name
if (videos.length > 0) {
name = videos.find(video => video.author).author
}
resolve({
name,
videos
})
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
@ -282,17 +318,21 @@ export default defineComponent({
break
case 1:
if (process.env.IS_ELECTRON && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
resolve(this.getChannelLiveLocal(channel, failedAttempts + 1))
} else {
resolve([])
resolve({
videos: []
})
}
break
case 2:
resolve(this.getChannelLiveInvidiousRSS(channel, failedAttempts + 1))
break
default:
resolve([])
resolve({
videos: []
})
}
})
})
@ -306,7 +346,9 @@ export default defineComponent({
const response = await fetch(feedUrl)
if (response.status === 500 || response.status === 404) {
return []
return {
videos: []
}
}
return await parseYouTubeRSSFeed(await response.text(), channel.id)
@ -321,20 +363,25 @@ export default defineComponent({
return this.getChannelLiveInvidious(channel, failedAttempts + 1)
case 1:
if (process.env.IS_ELECTRON && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
return this.getChannelLiveLocalRSS(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
case 2:
return this.getChannelLiveInvidious(channel, failedAttempts + 1)
default:
return []
return {
videos: []
}
}
}
},
...mapActions([
'batchUpdateSubscriptionDetails',
'updateShowProgressBar',
'updateSubscriptionLiveCacheByChannel',
]),

View File

@ -114,12 +114,16 @@ export default defineComponent({
this.attemptedFetch = true
this.errorChannels = []
const subscriptionUpdates = []
const videoListFromRemote = (await Promise.all(channelsToLoadFromRemote.map(async (channel) => {
let videos = []
let name
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
videos = await this.getChannelShortsInvidious(channel)
({ videos, name } = await this.getChannelShortsInvidious(channel))
} else {
videos = await this.getChannelShortsLocal(channel)
({ videos, name } = await this.getChannelShortsLocal(channel))
}
channelCount++
@ -129,6 +133,14 @@ export default defineComponent({
channelId: channel.id,
videos: videos,
})
if (name) {
subscriptionUpdates.push({
channelId: channel.id,
channelName: name
})
}
return videos
}))).flatMap((o) => o)
videoList.push(...videoListFromRemote)
@ -136,6 +148,8 @@ export default defineComponent({
this.videoList = updateVideoListAfterProcessing(videoList)
this.isLoading = false
this.updateShowProgressBar(false)
this.batchUpdateSubscriptionDetails(subscriptionUpdates)
},
maybeLoadVideosForSubscriptionsFromRemote: async function () {
@ -168,7 +182,9 @@ export default defineComponent({
this.errorChannels.push(channel)
}
return []
return {
videos: []
}
}
return await parseYouTubeRSSFeed(await response.text(), channel.id)
@ -184,10 +200,14 @@ export default defineComponent({
showToast(this.$t('Falling back to Invidious API'))
return this.getChannelShortsInvidious(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
default:
return []
return {
videos: []
}
}
}
},
@ -200,7 +220,9 @@ export default defineComponent({
const response = await fetch(feedUrl)
if (response.status === 500 || response.status === 404) {
return []
return {
videos: []
}
}
return await parseYouTubeRSSFeed(await response.text(), channel.id)
@ -213,18 +235,23 @@ export default defineComponent({
switch (failedAttempts) {
case 0:
if (process.env.IS_ELECTRON && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
return this.getChannelShortsLocal(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
default:
return []
return {
videos: []
}
}
}
},
...mapActions([
'batchUpdateSubscriptionDetails',
'updateShowProgressBar',
'updateSubscriptionShortsCacheByChannel',
]),

View File

@ -129,19 +129,23 @@ export default defineComponent({
this.attemptedFetch = true
this.errorChannels = []
const subscriptionUpdates = []
const videoListFromRemote = (await Promise.all(channelsToLoadFromRemote.map(async (channel) => {
let videos = []
let name, thumbnailUrl
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
if (useRss) {
videos = await this.getChannelVideosInvidiousRSS(channel)
({ videos, name, thumbnailUrl } = await this.getChannelVideosInvidiousRSS(channel))
} else {
videos = await this.getChannelVideosInvidiousScraper(channel)
({ videos, name, thumbnailUrl } = await this.getChannelVideosInvidiousScraper(channel))
}
} else {
if (useRss) {
videos = await this.getChannelVideosLocalRSS(channel)
({ videos, name, thumbnailUrl } = await this.getChannelVideosLocalRSS(channel))
} else {
videos = await this.getChannelVideosLocalScraper(channel)
({ videos, name, thumbnailUrl } = await this.getChannelVideosLocalScraper(channel))
}
}
@ -152,6 +156,15 @@ export default defineComponent({
channelId: channel.id,
videos: videos,
})
if (name || thumbnailUrl) {
subscriptionUpdates.push({
channelId: channel.id,
channelName: name,
channelThumbnailUrl: thumbnailUrl
})
}
return videos
}))).flatMap((o) => o)
videoList.push(...videoListFromRemote)
@ -159,6 +172,8 @@ export default defineComponent({
this.videoList = updateVideoListAfterProcessing(videoList)
this.isLoading = false
this.updateShowProgressBar(false)
this.batchUpdateSubscriptionDetails(subscriptionUpdates)
},
maybeLoadVideosForSubscriptionsFromRemote: async function () {
@ -174,16 +189,18 @@ export default defineComponent({
getChannelVideosLocalScraper: async function (channel, failedAttempts = 0) {
try {
const videos = await getLocalChannelVideos(channel.id)
const result = await getLocalChannelVideos(channel.id)
if (videos === null) {
if (result === null) {
this.errorChannels.push(channel)
return []
return {
videos: []
}
}
addPublishedDatesLocal(videos)
addPublishedDatesLocal(result.videos)
return videos
return result
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -198,12 +215,16 @@ export default defineComponent({
showToast(this.$t('Falling back to Invidious API'))
return await this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
case 2:
return await this.getChannelVideosLocalRSS(channel, failedAttempts + 1)
default:
return []
return {
videos: []
}
}
}
},
@ -227,7 +248,9 @@ export default defineComponent({
this.errorChannels.push(channel)
}
return []
return {
videos: []
}
}
return await parseYouTubeRSSFeed(await response.text(), channel.id)
@ -245,12 +268,16 @@ export default defineComponent({
showToast(this.$t('Falling back to Invidious API'))
return this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
case 2:
return this.getChannelVideosLocalScraper(channel, failedAttempts + 1)
default:
return []
return {
videos: []
}
}
}
},
@ -266,7 +293,16 @@ export default defineComponent({
invidiousAPICall(subscriptionsPayload).then((result) => {
addPublishedDatesInvidious(result.videos)
resolve(result.videos)
let name
if (result.videos.length > 0) {
name = result.videos.find(video => video.type === 'video' && video.author).author
}
resolve({
name,
videos: result.videos
})
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
@ -279,17 +315,21 @@ export default defineComponent({
break
case 1:
if (process.env.IS_ELECTRON && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
} else {
resolve([])
resolve({
videos: []
})
}
break
case 2:
resolve(this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1))
break
default:
resolve([])
resolve({
videos: []
})
}
})
})
@ -304,7 +344,9 @@ export default defineComponent({
if (response.status === 500 || response.status === 404) {
this.errorChannels.push(channel)
return []
return {
videos: []
}
}
return await parseYouTubeRSSFeed(await response.text(), channel.id)
@ -319,20 +361,25 @@ export default defineComponent({
return this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1)
case 1:
if (process.env.IS_ELECTRON && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
showToast(this.$t('Falling back to Local API'))
return this.getChannelVideosLocalRSS(channel, failedAttempts + 1)
} else {
return []
return {
videos: []
}
}
case 2:
return this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1)
default:
return []
return {
videos: []
}
}
}
},
...mapActions([
'batchUpdateSubscriptionDetails',
'updateShowProgressBar',
'updateSubscriptionVideosCacheByChannel',
]),

View File

@ -54,7 +54,6 @@
.chapterThumbnail {
grid-area: thumbnail;
inline-size: 130px;
block-size: auto;
margin: 3px;
}

View File

@ -49,6 +49,7 @@ export default defineComponent({
changeChapter: function(index) {
this.currentIndex = index
this.$emit('timestamp-event', this.chapters[index].startSeconds)
window.scrollTo(0, 0)
},
navigateChapters(direction) {

View File

@ -46,13 +46,15 @@
@keydown.space.stop.prevent="changeChapter(index)"
@keydown.enter.stop.prevent="changeChapter(index)"
>
<!-- Setting the aspect ratio avoids layout shifts when the images load -->
<img
v-if="!compact"
alt=""
aria-hidden="true"
class="chapterThumbnail"
loading="lazy"
:src="chapter.thumbnail"
:src="chapter.thumbnail.url"
:style="{ aspectRatio: chapter.thumbnail.width / chapter.thumbnail.height }"
>
<div class="chapterTimestamp">
{{ chapter.timestamp }}

View File

@ -293,7 +293,7 @@ export default defineComponent({
copyToClipboard(err)
})
if (process.env.IS_ELECTRON && this.backendFallback && this.backendPreference === 'invidious') {
showToast(this.$t('Falling back to local API'))
showToast(this.$t('Falling back to Local API'))
this.getCommentDataLocal()
} else {
this.isLoading = false

View File

@ -268,7 +268,7 @@
v-else-if="showComments && !isLoading"
>
<h3 class="noCommentMsg">
{{ $t("There are no comments available for this video") }}
{{ $t("Comments.There are no comments available for this video") }}
</h3>
</div>
<h4

View File

@ -64,6 +64,19 @@
inset-inline-end: calc(50% - 20px);
}
}
@media screen and (max-width: 460px) {
flex-wrap: nowrap;
:deep(.iconDropdown) {
inset-inline-start: auto;
inset-inline-end: auto;
}
}
}
@media screen and (max-width: 460px) {
flex-direction: column;
align-items: flex-start;
margin-block-start: 10px;
}
}
@ -72,29 +85,43 @@
color: var(--tertiary-text-color);
.likeSection {
color: var(--tertiary-text-color);
display: flex;
flex-direction: column;
margin-inline-start: auto;
margin-block-start: 4px;
max-inline-size: 210px;
text-align: end;
@media screen and (max-width: 680px) {
margin-inline-start: 0;
text-align: start;
}
.likeBar {
border-radius: 4px;
block-size: 8px;
margin-block-end: 4px;
}
.likeCount {
margin-inline-end: 0;
color: var(--tertiary-text-color);
display: flex;
gap: 3px;
flex-direction: column;
margin-inline-start: auto;
margin-block-start: 4px;
max-inline-size: 210px;
text-align: end;
@media screen and (max-width: 680px) {
margin-inline-start: 0;
text-align: start;
}
.likeBar {
border-radius: 4px;
block-size: 8px;
margin-block-end: 4px;
}
.likeCount {
margin-inline-end: 0;
display: flex;
gap: 3px;
}
}
.datePublishedAndViewCount {
@media only screen and (max-width: 460px) {
display: flex;
justify-content: left;
flex-direction: column;
.seperator {
display: none;
}
}
}
.videoViews {
white-space: nowrap;
}
}
}

View File

@ -9,7 +9,12 @@
</div>
<div class="videoMetrics">
<div class="datePublishedAndViewCount">
{{ publishedString }} {{ dateString }} {{ parsedViewCount }}
{{ publishedString }} {{ dateString }}
<template
v-if="!hideVideoViews"
>
<span class="seperator"> </span><span class="videoViews">{{ parsedViewCount }}</span>
</template>
</div>
<div
v-if="!hideVideoLikesAndDislikes"

View File

@ -367,7 +367,7 @@ export async function generateInvidiousDashManifestLocally(formats) {
return await FormatUtils.toDash({
adaptive_formats: formats
}, urlTransformer, undefined, undefined, player)
}, false, urlTransformer, undefined, undefined, player)
}
export function convertInvidiousToLocalFormat(format) {

View File

@ -35,23 +35,23 @@ const TRACKING_PARAM_NAMES = [
* @param {boolean} options.generateSessionLocally generate the session locally or let YouTube generate it (local is faster, remote is more accurate)
* @returns the Innertube instance
*/
async function createInnertube(options = { withPlayer: false, location: undefined, safetyMode: false, clientType: undefined, generateSessionLocally: true }) {
async function createInnertube({ withPlayer = false, location = undefined, safetyMode = false, clientType = undefined, generateSessionLocally = true } = {}) {
let cache
if (options.withPlayer) {
if (withPlayer) {
const userData = await getUserDataPath()
cache = new PlayerCache(join(userData, 'player_cache'))
}
return await Innertube.create({
retrieve_player: !!options.withPlayer,
location: options.location,
enable_safety_mode: !!options.safetyMode,
client_type: options.clientType,
retrieve_player: !!withPlayer,
location: location,
enable_safety_mode: !!safetyMode,
client_type: clientType,
// use browser fetch
fetch: (input, init) => fetch(input, init),
cache,
generate_session_locally: !!options.generateSessionLocally
generate_session_locally: !!generateSessionLocally
})
}
@ -274,6 +274,9 @@ export async function getLocalChannel(id) {
return result
}
/**
* @param {string} id
*/
export async function getLocalChannelVideos(id) {
const innertube = await createInnertube()
@ -286,15 +289,22 @@ export async function getLocalChannelVideos(id) {
}))
const videosTab = new YT.Channel(null, response)
const { id: channelId = id, name, thumbnailUrl } = parseLocalChannelHeader(videosTab)
let videos
// if the channel doesn't have a videos tab, YouTube returns the home tab instead
// so we need to check that we got the right tab
if (videosTab.current_tab?.endpoint.metadata.url?.endsWith('/videos')) {
const { id: channelId = id, name } = parseLocalChannelHeader(videosTab)
return parseLocalChannelVideos(videosTab.videos, channelId, name)
videos = parseLocalChannelVideos(videosTab.videos, channelId, name)
} else {
return []
videos = []
}
return {
name,
thumbnailUrl,
videos
}
} catch (error) {
console.error(error)
@ -306,6 +316,9 @@ export async function getLocalChannelVideos(id) {
}
}
/**
* @param {string} id
*/
export async function getLocalChannelLiveStreams(id) {
const innertube = await createInnertube()
@ -318,15 +331,22 @@ export async function getLocalChannelLiveStreams(id) {
}))
const liveStreamsTab = new YT.Channel(null, response)
const { id: channelId = id, name, thumbnailUrl } = parseLocalChannelHeader(liveStreamsTab)
let videos
// if the channel doesn't have a live tab, YouTube returns the home tab instead
// so we need to check that we got the right tab
if (liveStreamsTab.current_tab?.endpoint.metadata.url?.endsWith('/streams')) {
const { id: channelId = id, name } = parseLocalChannelHeader(liveStreamsTab)
return parseLocalChannelVideos(liveStreamsTab.videos, channelId, name)
videos = parseLocalChannelVideos(liveStreamsTab.videos, channelId, name)
} else {
return []
videos = []
}
return {
name,
thumbnailUrl,
videos
}
} catch (error) {
console.error(error)
@ -539,7 +559,7 @@ export function parseLocalChannelShorts(shorts, channelId, channelName) {
title: short.title.text,
author: channelName,
authorId: channelId,
viewCount: parseLocalSubscriberCount(short.views.text),
viewCount: short.views.isEmpty() ? null : parseLocalSubscriberCount(short.views.text),
lengthSeconds: ''
}
})

View File

@ -80,9 +80,14 @@ export async function parseYouTubeRSSFeed(rssString, channelId) {
promises.push(parseRSSEntry(entry, channelId, channelName))
}
return await Promise.all(promises)
return {
name: channelName,
videos: await Promise.all(promises)
}
} catch (e) {
return []
return {
videos: []
}
}
}

View File

@ -616,9 +616,10 @@ export function getVideoParamsFromUrl(url) {
/**
* This will match sequences of upper case characters and convert them into title cased words.
* This will also match excessive strings of punctionation and convert them to one representative character
* @param {string} title the title to process
* @param {number} minUpperCase the minimum number of consecutive upper case characters to match
* @returns {string} the title with upper case characters removed
* @returns {string} the title with upper case characters removed and punctuation normalized
*/
export function toDistractionFreeTitle(title, minUpperCase = 3) {
const firstValidCharIndex = (word) => {
@ -634,7 +635,10 @@ export function toDistractionFreeTitle(title, minUpperCase = 3) {
}
const reg = RegExp(`[\\p{Lu}|']{${minUpperCase},}`, 'ug')
return title.replace(reg, x => capitalizedWord(x.toLowerCase()))
return title
.replaceAll(/!{2,}/g, '!')
.replaceAll(/[!?]{2,}/g, '?')
.replace(reg, x => capitalizedWord(x.toLowerCase()))
}
export function formatNumber(number, options = undefined) {

View File

@ -39,6 +39,7 @@ const actions = {
console.error(err)
}
}
// If the invidious instance fetch isn't returning anything interpretable
if (instances.length === 0) {
// Fallback: read from static file
@ -46,15 +47,13 @@ const actions = {
/* eslint-disable-next-line n/no-path-concat */
const fileLocation = process.env.NODE_ENV === 'development' ? './static/' : `${__dirname}/static/`
const filePath = `${fileLocation}${fileName}`
if (!process.env.IS_ELECTRON) {
console.warn('reading static file for invidious instances')
const fileData = process.env.IS_ELECTRON ? await fs.readFile(filePath, 'utf8') : await (await fetch(createWebURL(filePath))).text()
instances = JSON.parse(fileData).filter(e => {
return process.env.IS_ELECTRON || e.cors
}).map(e => {
return e.url
})
}
console.warn('reading static file for invidious instances')
const fileData = process.env.IS_ELECTRON ? await fs.readFile(filePath, 'utf8') : await (await fetch(createWebURL(filePath))).text()
instances = JSON.parse(fileData).filter(e => {
return process.env.IS_ELECTRON || e.cors
}).map(e => {
return e.url
})
}
commit('setInvidiousInstancesList', instances)
},

View File

@ -91,6 +91,43 @@ const actions = {
commit('setProfileList', profiles)
},
async batchUpdateSubscriptionDetails({ getters, dispatch }, channels) {
if (channels.length === 0) { return }
const profileList = getters.getProfileList
for (const profile of profileList) {
const currentProfileCopy = deepCopy(profile)
let profileUpdated = false
for (const { channelThumbnailUrl, channelName, channelId } of channels) {
const channel = currentProfileCopy.subscriptions.find((channel) => {
return channel.id === channelId
}) ?? null
if (channel === null) { continue }
if (channel.name !== channelName && channelName != null) {
channel.name = channelName
profileUpdated = true
}
if (channelThumbnailUrl) {
const thumbnail = channelThumbnailUrl.replace(/=s\d*/, '=s176') // change thumbnail size if different
if (channel.thumbnail !== thumbnail) {
channel.thumbnail = thumbnail
profileUpdated = true
}
}
}
if (profileUpdated) {
await dispatch('updateProfile', currentProfileCopy)
}
}
},
async updateSubscriptionDetails({ getters, dispatch }, { channelThumbnailUrl, channelName, channelId }) {
const thumbnail = channelThumbnailUrl?.replace(/=s\d*/, '=s176') ?? null // change thumbnail size if different
const profileList = getters.getProfileList

View File

@ -289,7 +289,7 @@ const state = {
videoPlaybackRateInterval: 0.25,
downloadAskPath: true,
downloadFolderPath: '',
downloadBehavior: 'download',
downloadBehavior: 'open',
enableScreenshot: false,
screenshotFormat: 'png',
screenshotQuality: 95,

View File

@ -54,6 +54,10 @@ const actions = {
commit('updateShortsCacheByChannel', payload)
},
updateSubscriptionShortsCacheWithChannelPageShorts: ({ commit }, payload) => {
commit('updateShortsCacheWithChannelPageShorts', payload)
},
updateSubscriptionLiveCacheByChannel: ({ commit }, payload) => {
commit('updateLiveCacheByChannel', payload)
},
@ -86,6 +90,31 @@ const mutations = {
if (videos != null) { newObject.videos = videos }
state.shortsCache[channelId] = newObject
},
updateShortsCacheWithChannelPageShorts(state, { channelId, videos }) {
const cachedObject = state.shortsCache[channelId]
if (cachedObject && cachedObject.videos.length > 0) {
cachedObject.videos.forEach(cachedVideo => {
const channelVideo = videos.find(short => cachedVideo.videoId === short.videoId)
if (channelVideo) {
// authorId probably never changes, so we don't need to update that
cachedVideo.title = channelVideo.title
cachedVideo.author = channelVideo.author
// as the channel shorts page only has compact view counts for numbers above 1000 e.g. 12k
// and the RSS feeds include an exact value, we only want to overwrite it when the number is larger than the cached value
// 12345 vs 12000 => 12345
// 12345 vs 15000 => 15000
if (channelVideo.viewCount > cachedVideo.viewCount) {
cachedVideo.viewCount = channelVideo.viewCount
}
}
})
}
},
clearShortsCache(state) {
state.shortsCache = {}
},

View File

@ -33,6 +33,10 @@ import {
parseLocalListVideo,
parseLocalSubscriberCount
} from '../../helpers/api/local'
import {
addPublishedDatesInvidious,
addPublishedDatesLocal
} from '../../helpers/subscriptions'
export default defineComponent({
name: 'Channel',
@ -171,6 +175,13 @@ export default defineComponent({
return this.subscriptionInfo !== null
},
isSubscribedInAnyProfile: function () {
const profileList = this.$store.getters.getProfileList
// check the all channels profile
return profileList[0].subscriptions.some((channel) => channel.id === this.id)
},
videoLiveSelectNames: function () {
return [
this.$t('Channel.Videos.Sort Types.Newest'),
@ -767,6 +778,17 @@ export default defineComponent({
this.latestVideos = parseLocalChannelVideos(videosTab.videos, this.id, this.channelName)
this.videoContinuationData = videosTab.has_continuation ? videosTab : null
this.isElementListLoading = false
if (this.isSubscribedInAnyProfile && this.latestVideos.length > 0 && this.videoSortBy === 'newest') {
addPublishedDatesLocal(this.latestVideos)
this.updateSubscriptionVideosCacheByChannel({
channelId: this.id,
// create a copy so that we only cache the first page
// if we use the same array, the store will get angry at us for modifying it outside of the store,
// when the user clicks load more
videos: [...this.latestVideos]
})
}
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -825,6 +847,16 @@ export default defineComponent({
this.latestShorts = parseLocalChannelShorts(shortsTab.videos, this.id, this.channelName)
this.shortContinuationData = shortsTab.has_continuation ? shortsTab : null
this.isElementListLoading = false
if (this.isSubscribedInAnyProfile && this.latestShorts.length > 0 && this.shortSortBy === 'newest') {
// As the shorts tab API response doesn't include the published dates,
// we can't just write the results to the subscriptions cache like we do with videos and live (can't sort chronologically without the date).
// However we can still update the metadata in the cache such as the view count and title that might have changed since it was cached
this.updateSubscriptionShortsCacheWithChannelPageShorts({
channelId: this.id,
videos: this.latestShorts
})
}
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -883,6 +915,17 @@ export default defineComponent({
this.latestLive = parseLocalChannelVideos(liveTab.videos, this.id, this.channelName)
this.liveContinuationData = liveTab.has_continuation ? liveTab : null
this.isElementListLoading = false
if (this.isSubscribedInAnyProfile && this.latestLive.length > 0 && this.liveSortBy === 'newest') {
addPublishedDatesLocal(this.latestLive)
this.updateSubscriptionLiveCacheByChannel({
channelId: this.id,
// create a copy so that we only cache the first page
// if we use the same array, the store will get angry at us for modifying it outside of the store,
// when the user clicks load more
videos: [...this.latestLive]
})
}
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -1052,6 +1095,16 @@ export default defineComponent({
}
this.videoContinuationData = response.continuation || null
this.isElementListLoading = false
if (this.isSubscribedInAnyProfile && !more && this.latestVideos.length > 0 && this.videoSortBy === 'newest') {
addPublishedDatesInvidious(this.latestVideos)
this.updateSubscriptionVideosCacheByChannel({
channelId: this.id,
// create a copy so that we only cache the first page
// if we use the same array, it will also contain all the next pages
videos: [...this.latestVideos]
})
}
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
@ -1101,6 +1154,17 @@ export default defineComponent({
}
this.shortContinuationData = response.continuation || null
this.isElementListLoading = false
if (this.isSubscribedInAnyProfile && !more && this.latestShorts.length > 0 && this.shortSortBy === 'newest') {
// As the shorts tab API response doesn't include the published dates,
// we can't just write the results to the subscriptions cache like we do with videos and live (can't sort chronologically without the date).
// However we can still update the metadata in the cache e.g. adding the duration, as that isn't included in the RSS feeds
// and updating the view count and title that might have changed since it was cached
this.updateSubscriptionShortsCacheWithChannelPageShorts({
channelId: this.id,
videos: this.latestShorts
})
}
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
@ -1142,6 +1206,17 @@ export default defineComponent({
}
this.liveContinuationData = response.continuation || null
this.isElementListLoading = false
if (this.isSubscribedInAnyProfile && !more && this.latestLive.length > 0 && this.liveSortBy === 'newest') {
addPublishedDatesInvidious(this.latestLive)
this.updateSubscriptionLiveCacheByChannel({
channelId: this.id,
// create a copy so that we only cache the first page
// if we use the same array, the store will get angry at us for modifying it outside of the store,
// when the user clicks load more
videos: [...this.latestLive]
})
}
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
@ -1444,7 +1519,7 @@ export default defineComponent({
})
if (this.backendPreference === 'local' && this.backendFallback) {
showToast(this.$t('Falling back to Invidious API'))
this.getChannelPodcastsInvidious()
this.channelInvidiousPodcasts()
} else {
this.isLoading = false
}
@ -1559,6 +1634,19 @@ export default defineComponent({
this.latestCommunityPosts = parseLocalCommunityPosts(posts)
this.communityContinuationData = communityTab.has_continuation ? communityTab : null
if (this.latestCommunityPosts.length > 0) {
this.latestCommunityPosts.forEach(post => {
post.authorId = this.id
})
this.updateSubscriptionPostsCacheByChannel({
channelId: this.id,
// create a copy so that we only cache the first page
// if we use the same array, the store will get angry at us for modifying it outside of the store,
// when the user clicks load more
posts: [...this.latestCommunityPosts]
})
}
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -1610,6 +1698,19 @@ export default defineComponent({
this.latestCommunityPosts = posts
}
this.communityContinuationData = continuation
if (this.isSubscribedInAnyProfile && !more && this.latestCommunityPosts.length > 0) {
this.latestCommunityPosts.forEach(post => {
post.authorId = this.id
})
this.updateSubscriptionPostsCacheByChannel({
channelId: this.id,
// create a copy so that we only cache the first page
// if we use the same array, the store will get angry at us for modifying it outside of the store,
// when the user clicks load more
posts: [...this.latestCommunityPosts]
})
}
}).catch(async (err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
@ -1849,7 +1950,11 @@ export default defineComponent({
...mapActions([
'showOutlines',
'updateSubscriptionDetails'
'updateSubscriptionDetails',
'updateSubscriptionVideosCacheByChannel',
'updateSubscriptionLiveCacheByChannel',
'updateSubscriptionShortsCacheWithChannelPageShorts',
'updateSubscriptionPostsCacheByChannel'
])
}
})

View File

@ -417,7 +417,7 @@
<ft-age-restricted
v-else-if="!isLoading && (!isFamilyFriendly && showFamilyFriendlyOnly)"
class="ageRestricted"
:content-type-string="'Channel'"
:is-channel="true"
/>
</div>
</template>

View File

@ -60,6 +60,9 @@ export default defineComponent({
getPlaylistInfoDebounce: function() {},
playlistInEditMode: false,
playlistInVideoSearchMode: false,
videoSearchQuery: '',
promptOpen: false,
}
},
@ -104,7 +107,7 @@ export default defineComponent({
moreVideoDataAvailable() {
if (this.isUserPlaylistRequested) {
return this.userPlaylistVisibleLimit < this.videoCount
return this.userPlaylistVisibleLimit < this.sometimesFilteredUserPlaylistItems.length
} else {
return this.continuationData !== null
}
@ -123,17 +126,29 @@ export default defineComponent({
return this.selectedUserPlaylist?._id !== this.quickBookmarkPlaylistId
},
sometimesFilteredUserPlaylistItems() {
if (!this.isUserPlaylistRequested) { return this.playlistItems }
if (this.processedVideoSearchQuery === '') { return this.playlistItems }
return this.playlistItems.filter((v) => {
return v.title.toLowerCase().includes(this.processedVideoSearchQuery)
})
},
visiblePlaylistItems: function () {
if (!this.isUserPlaylistRequested) {
// No filtering for non user playlists yet
return this.playlistItems
}
if (this.userPlaylistVisibleLimit < this.videoCount) {
return this.playlistItems.slice(0, this.userPlaylistVisibleLimit)
if (this.userPlaylistVisibleLimit < this.sometimesFilteredUserPlaylistItems.length) {
return this.sometimesFilteredUserPlaylistItems.slice(0, this.userPlaylistVisibleLimit)
} else {
return this.playlistItems
return this.sometimesFilteredUserPlaylistItems
}
}
},
processedVideoSearchQuery() {
return this.videoSearchQuery.trim().toLowerCase()
},
},
watch: {
$route () {
@ -269,7 +284,7 @@ export default defineComponent({
const dateString = new Date(result.updated * 1000)
this.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' })
this.allPlaylistItems = result.videos
this.playlistItems = result.videos
this.isLoading = false
}).catch((err) => {

View File

@ -7,7 +7,6 @@
box-sizing: border-box;
block-size: calc(100vh - 132px);
margin-inline-end: 1em;
overflow-y: auto;
padding: 10px;
position: sticky;
inset-block-start: 96px;

View File

@ -28,6 +28,9 @@
}"
@enter-edit-mode="playlistInEditMode = true"
@exit-edit-mode="playlistInEditMode = false"
@search-video-mode-on="playlistInVideoSearchMode = true"
@search-video-mode-off="playlistInVideoSearchMode = false"
@search-video-query-change="(v) => videoSearchQuery = v"
@prompt-open="promptOpen = true"
@prompt-close="promptOpen = false"
/>
@ -39,48 +42,59 @@
<template
v-if="playlistItems.length > 0"
>
<transition-group
name="playlistItem"
tag="span"
<template
v-if="visiblePlaylistItems.length > 0"
>
<ft-list-video-numbered
v-for="(item, index) in visiblePlaylistItems"
:key="`${item.videoId}-${item.playlistItemId || index}`"
class="playlistItem"
:data="item"
:playlist-id="playlistId"
:playlist-type="infoSource"
:playlist-index="index"
:playlist-item-id="item.playlistItemId"
appearance="result"
:always-show-add-to-playlist-button="true"
:quick-bookmark-button-enabled="quickBookmarkButtonEnabled"
:can-move-video-up="index > 0"
:can-move-video-down="index < visiblePlaylistItems.length - 1"
:can-remove-from-playlist="true"
:video-index="index"
:initial-visible-state="index < 10"
@move-video-up="moveVideoUp(item.videoId, item.playlistItemId)"
@move-video-down="moveVideoDown(item.videoId, item.playlistItemId)"
@remove-from-playlist="removeVideoFromPlaylist(item.videoId, item.playlistItemId)"
/>
</transition-group>
<transition-group
name="playlistItem"
tag="span"
>
<ft-list-video-numbered
v-for="(item, index) in visiblePlaylistItems"
:key="`${item.videoId}-${item.playlistItemId || index}`"
class="playlistItem"
:data="item"
:playlist-id="playlistId"
:playlist-type="infoSource"
:playlist-index="playlistInVideoSearchMode ? playlistItems.findIndex(i => i === item) : index"
:playlist-item-id="item.playlistItemId"
appearance="result"
:always-show-add-to-playlist-button="true"
:quick-bookmark-button-enabled="quickBookmarkButtonEnabled"
:can-move-video-up="index > 0 && !playlistInVideoSearchMode"
:can-move-video-down="index < playlistItems.length - 1 && !playlistInVideoSearchMode"
:can-remove-from-playlist="true"
:video-index="playlistInVideoSearchMode ? playlistItems.findIndex(i => i === item) : index"
:initial-visible-state="index < 10"
@move-video-up="moveVideoUp(item.videoId, item.playlistItemId)"
@move-video-down="moveVideoDown(item.videoId, item.playlistItemId)"
@remove-from-playlist="removeVideoFromPlaylist(item.videoId, item.playlistItemId)"
/>
</transition-group>
<ft-flex-box
v-if="moreVideoDataAvailable && !isLoadingMore"
>
<ft-button
:label="$t('Subscriptions.Load More Videos')"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
@click="getNextPage"
/>
</ft-flex-box>
<div
v-if="isLoadingMore"
class="loadNextPageWrapper"
>
<ft-loader />
</div>
</template>
<ft-flex-box
v-if="moreVideoDataAvailable && !isLoadingMore"
v-else
>
<ft-button
:label="$t('Subscriptions.Load More Videos')"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
@click="getNextPage"
/>
<p class="message">
{{ $t("User Playlists['Empty Search Message']") }}
</p>
</ft-flex-box>
<div
v-if="isLoadingMore"
class="loadNextPageWrapper"
>
<ft-loader />
</div>
</template>
<ft-flex-box
v-else

View File

@ -450,7 +450,7 @@ export default defineComponent({
timestamp: formatDurationAsTimestamp(start),
startSeconds: start,
endSeconds: 0,
thumbnail: chapter.thumbnail[0].url
thumbnail: chapter.thumbnail[0]
})
}
} else {

View File

@ -87,7 +87,7 @@
<ft-age-restricted
v-if="(!isLoading && !isFamilyFriendly && showFamilyFriendlyOnly)"
class="ageRestricted"
:content-type-string="'Video'"
:is-video="true"
/>
<div
v-if="(isFamilyFriendly || !showFamilyFriendlyOnly)"

View File

@ -1,5 +1,5 @@
# Put the name of your locale in the same language
Locale Name: 'الإنجليزية (الولايات المتحدة)'
Locale Name: 'العربية'
FreeTube: 'فري تيوب'
# Currently on Subscriptions, Playlists, and History
'This part of the app is not ready yet. Come back later when progress has been made.': >-
@ -173,6 +173,7 @@ User Playlists:
Reverted to use {oldPlaylistName} for quick bookmark: تمت العودة لاستخدام {oldPlaylistName}
للإشارة المرجعية السريعة
Quick bookmark disabled: تم تعطيل الإشارة المرجعية السريعة
Search for Videos: ‬البحث عن مقاطع الفيديو
AddVideoPrompt:
Select a playlist to add your N videos to: حدد قائمة تشغيل لإضافة الفيديو الخاص
بك إلى | حدد قائمة تشغيل لإضافة مقاطع الفيديو {videoCount} إليها
@ -186,6 +187,7 @@ User Playlists:
Save: حفظ
Search in Playlists: البحث في قوائم التشغيل
N playlists selected: تم تحديد {playlistCount}
Added {count} Times: تمت إضافة {count} الوقت | تمت إضافة {count} مرة
CreatePlaylistPrompt:
Toast:
There is already a playlist with this name. Please pick a different name.: توجد
@ -518,8 +520,8 @@ Settings:
Hide Upcoming Premieres: إخفاء العروض الأولى القادمة
Hide Channels: إخفاء مقاطع الفيديو من القنوات
Hide Channels Placeholder: معرف القناة
Display Titles Without Excessive Capitalisation: عرض العناوين بدون احرف كبيرة
بشكل مفرط
Display Titles Without Excessive Capitalisation: عرض العناوين بدون استخدام الأحرف
الكبيرة وعلامات الترقيم بشكل مفرط
Hide Featured Channels: إخفاء القنوات المميزة
Hide Channel Playlists: إخفاء قوائم تشغيل القناة
Hide Channel Community: إخفاء مجتمع القناة
@ -931,6 +933,7 @@ Video:
Pause on Current Video: توقف مؤقتًا على الفيديو الحالي
Unhide Channel: عرض القناة
Hide Channel: إخفاء القناة
More Options: المزيد من الخيارات
Videos:
#& Sort By
Sort By:
@ -1007,7 +1010,7 @@ Up Next: 'التالي'
Local API Error (Click to copy): 'خطأ API المحلي (انقر للنسخ)'
Invidious API Error (Click to copy): 'خطأ Invidious API ( انقر للنسخ)'
Falling back to Invidious API: 'التراجع إلى Invidious API'
Falling back to the local API: 'التراجع إلى API المحلي'
Falling back to Local API: 'التراجع إلى API المحلي'
Subscriptions have not yet been implemented: 'لم يتم تنفيذ الاشتراكات بعد'
Loop is now disabled: 'تم تعطيل التكرار'
Loop is now enabled: 'تم تمكين التكرار'
@ -1131,11 +1134,6 @@ Starting download: بدء تنزيل "{videoTitle}"
Screenshot Success: تم حفظ لقطة الشاشة كا"{filePath}"
Screenshot Error: فشل أخذ لقطة للشاشة. {error}
New Window: نافذة جديدة
Age Restricted:
Type:
Channel: القناة
Video: فيديو
This {videoOrPlaylist} is age restricted: 'هذا {videoOrPlaylist} مقيد بالعمر'
Channels:
Count: تم العثور على قناة (قنوات) {number}.
Unsubscribed: 'تمت إزالة {channelName} من اشتراكاتك'
@ -1172,3 +1170,7 @@ Trimmed input must be at least N characters long: يجب أن يكون طول ا
حرفًا واحدًا على الأقل | يجب أن يبلغ طول الإدخال المقتطع {length} من الأحرف على
الأقل
Tag already exists: العلامة "{tagName}" موجودة بالفعل
Age Restricted:
This channel is age restricted: هذه القناة مقيدة بالعمر
This video is age restricted: هذا الفيديو مقيد بالفئة العمرية
Close Banner: إغلاق الشعار

View File

@ -813,7 +813,7 @@ Tooltips:
Local API Error (Click to copy): ''
Invidious API Error (Click to copy): ''
Falling back to Invidious API: ''
Falling back to the local API: ''
Falling back to Local API: ''
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
Subscriptions have not yet been implemented: ''
Unknown YouTube url type, cannot be opened in app: ''
@ -833,11 +833,6 @@ Canceled next video autoplay: ''
Default Invidious instance has been set to {instance}: ''
Default Invidious instance has been cleared: ''
'The playlist has ended. Enable loop to continue playing': ''
Age Restricted:
This {videoOrPlaylist} is age restricted: ''
Type:
Channel: ''
Video: ''
External link opening has been disabled in the general settings: ''
Downloading has completed: ''
Starting download: ''

View File

@ -1023,7 +1023,7 @@ Up Next: 'Следващ'
Local API Error (Click to copy): 'Грешка в локалния интерфейс (щракнете за копиране)'
Invidious API Error (Click to copy): 'Грешка в Invidious интерфейса (щракнете за копиране)'
Falling back to Invidious API: 'Връщане към Invidious интерфейса'
Falling back to the local API: 'Връщане към локалния интерфейс'
Falling back to Local API: 'Връщане към локалния интерфейс'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Видеото
не е достъпно поради липсващи формати. Това може да се дължи на ограничен достъп
за страната.'
@ -1148,12 +1148,6 @@ Downloading failed: Имаше проблем при изтеглянето на
Screenshot Error: Снимката на екрана е неуспешна. {error}
Screenshot Success: Запазена снимка на екрана като "{filePath}"
New Window: Нов прозорец
Age Restricted:
This {videoOrPlaylist} is age restricted: Този {videoOrPlaylist} е с възрастово
ограничение
Type:
Channel: Канал
Video: Видео
Channels:
Count: Намерени са {number} канала.
Unsubscribe: Отписване

View File

@ -135,10 +135,6 @@ External link opening has been disabled in the general settings: সাধার
বহিঃসংযোগ খোলা নিষ্ক্রিয় রাখা হয়েছে
Are you sure you want to open this link?: তুমি কি এই সংযোগটি খোলার ব্যাপারে নিশ্চিত?
Preferences: পছন্দসমূহ
Age Restricted:
Type:
Channel: চ্যানেল
Video: ভিডিও
Most Popular: অতিপরিচিত
Channels:
Search bar placeholder: চ্যানেল খুঁজুন

View File

@ -829,7 +829,7 @@ Tooltips:
Local API Error (Click to copy): ''
Invidious API Error (Click to copy): ''
Falling back to Invidious API: ''
Falling back to the local API: ''
Falling back to Local API: ''
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
Subscriptions have not yet been implemented: ''
Unknown YouTube url type, cannot be opened in app: ''
@ -849,11 +849,6 @@ Canceled next video autoplay: ''
Default Invidious instance has been set to {instance}: ''
Default Invidious instance has been cleared: ''
'The playlist has ended. Enable loop to continue playing': ''
Age Restricted:
This {videoOrPlaylist} is age restricted: ''
Type:
Channel: 'کەناڵ'
Video: 'ڤیدیۆ'
External link opening has been disabled in the general settings: ''
Downloading has completed: ''
Starting download: ''

View File

@ -146,6 +146,7 @@ User Playlists:
Select a playlist to add your N videos to: Vyberte playlist, do kterého přidat
vaše video | Vyberte playlist, do kterého přidat vašich {videoCount} videí
N playlists selected: Vybráno {playlistCount}
Added {count} Times: Přidáno {count}krát | Přidáno {count}krát
SinglePlaylistView:
Toast:
There were no videos to remove.: Nejsou zde žádná videa k odstranění.
@ -175,6 +176,7 @@ User Playlists:
This playlist is now used for quick bookmark: Tento playlist bude nyní použit
pro rychlé uložení
Quick bookmark disabled: Rychlé uložení vypnuto
Search for Videos: Hledat videa
Are you sure you want to delete this playlist? This cannot be undone: Opravdu chcete
odstranit tento playlist? Tato akce je nevratná.
Sort By:
@ -234,7 +236,7 @@ Settings:
General Settings:
General Settings: 'Obecné nastavení'
Check for Updates: 'Kontrolovat aktualizace'
Check for Latest Blog Posts: 'Kontrolovat nejnovější příspěvky blogů'
Check for Latest Blog Posts: 'Kontrolovat nejnovější příspěvky na blogu'
Fallback to Non-Preferred Backend on Failure: 'Při chybě přepnout na nepreferovaný
backend'
Enable Search Suggestions: 'Zapnout návrhy vyhledávání'
@ -444,7 +446,7 @@ Settings:
Hide Channels: Skrýt videa z kanálů
Hide Channels Placeholder: ID kanálu
Display Titles Without Excessive Capitalisation: Zobrazit názvy bez nadměrného
použití velkých písmen
použití velkých písmen a interpunkce
Hide Featured Channels: Skrýt doporučené kanály
Hide Channel Playlists: Skrýt playlisty kanálu
Hide Channel Community: Skrýt komunitu kanálu
@ -926,6 +928,7 @@ Video:
Pause on Current Video: Pozastavit na současném videu
Unhide Channel: Zobrazit kanál
Hide Channel: Skrýt kanál
More Options: Další možnosti
Videos:
#& Sort By
Sort By:
@ -1025,10 +1028,10 @@ Tooltips:
otevřít ve FreeTube.\nVe výchozím nastavení otevře FreeTube odkaz ve vašem výchozím
prohlížeči.\n"
Player Settings:
Force Local Backend for Legacy Formats: 'Funguje pouze v případě, že je výchozím
nastavením API Invidious. Je-li povoleno, spustí se místní API a použije starší
Force Local Backend for Legacy Formats: 'Funguje pouze v případě, že je jako výchozí
nastaveno API Invidious. Je-li povoleno, spustí se místní API a použije starší
formáty místo těch, které vrátí Invidious. Může pomoci, pokud videa z Invidious
nemohou být přehrána kvůli regionálnímu omezení.'
nemohou být přehrána z důvodu regionálních omezení.'
Proxy Videos Through Invidious: 'Připojí se k Invidious, aby poskytoval videa
namísto přímého připojení k YouTube. Toto přepíše předvolby API.'
Default Video Format: 'Nastavte formáty použité při přehrávání videa. Formáty
@ -1090,7 +1093,7 @@ Tooltips:
Local API Error (Click to copy): 'Chyba lokálního API (kliknutím zkopírujete)'
Invidious API Error (Click to copy): 'Chyba Invidious API (kliknutím zkopírujete)'
Falling back to Invidious API: 'Přepínám na Invidious API'
Falling back to the local API: 'Přepínám na lokální API'
Falling back to Local API: 'Přepínám na lokální API'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Toto
video není k dispozici z důvodu chybějících formátů. K tomu může dojít z důvodu
nedostupnosti země.'
@ -1129,11 +1132,6 @@ Downloading has completed: Bylo dokončeno stahování "{videoTitle}"
Downloading failed: Došlo k problému při stahování "{videoTitle}"
Starting download: Zahájení stahování "{videoTitle}"
New Window: Nové okno
Age Restricted:
This {videoOrPlaylist} is age restricted: Toto {videoOrPlaylist} je omezeno věkem
Type:
Channel: kanál
Video: Video
Channels:
Channels: Kanály
Title: Seznam kanálů
@ -1170,3 +1168,7 @@ Channel Unhidden: Kanál {channel} odebrán z filtrů kanálů
Trimmed input must be at least N characters long: Oříznutý vstup musí být dlouhý alespoň
1 znak | Oříznutý vstup musí být dlouhý alespoň {length} znaků
Tag already exists: Štítek „{tagName}“ již existuje
Close Banner: Zavřít panel
Age Restricted:
This channel is age restricted: Tento kanál je omezen věkem
This video is age restricted: Toto video je omezeno věkem

View File

@ -831,7 +831,7 @@ Tooltips:
Local API Error (Click to copy): ''
Invidious API Error (Click to copy): ''
Falling back to Invidious API: ''
Falling back to the local API: ''
Falling back to Local API: ''
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
Subscriptions have not yet been implemented: ''
Unknown YouTube url type, cannot be opened in app: ''
@ -851,11 +851,6 @@ Canceled next video autoplay: ''
Default Invidious instance has been set to {instance}: ''
Default Invidious instance has been cleared: ''
'The playlist has ended. Enable loop to continue playing': ''
Age Restricted:
This {videoOrPlaylist} is age restricted: ''
Type:
Channel: 'Sianel'
Video: 'Fideo'
External link opening has been disabled in the general settings: ''
Downloading has completed: ''
Starting download: ''

View File

@ -769,7 +769,7 @@ Up Next: 'Næste'
Local API Error (Click to copy): 'Lokal API-Fejl (Klik for at kopiere)'
Invidious API Error (Click to copy): 'Invidious-API-Fejl (Klik for at kopiere)'
Falling back to Invidious API: 'Falder tilbage til Invidious-API'
Falling back to the local API: 'Falder tilbage til den lokale API'
Falling back to Local API: 'Falder tilbage til den lokale API'
Subscriptions have not yet been implemented: 'Abonnementer er endnu ikke blevet implementerede'
Loop is now disabled: 'Gentagelse er nu deaktiveret'
Loop is now enabled: 'Gentagelse er nu aktiveret'
@ -858,11 +858,6 @@ Default Invidious instance has been cleared: Standard Invidious-instans er bleve
Are you sure you want to open this link?: Er du sikker på at du vil åbne dette link?
Search Bar:
Clear Input: Ryd Input
Age Restricted:
Type:
Video: Video
Channel: Kanal
This {videoOrPlaylist} is age restricted: Denne {videoOrPlaylist} er aldersbegrænset
Downloading failed: Der var et problem med at downloade "{videoTitle}"
Unknown YouTube url type, cannot be opened in app: Ukendt YouTube URL-type, kan ikke
åbnes i appen

View File

@ -1014,7 +1014,7 @@ Up Next: Nächster Titel
Local API Error (Click to copy): Lokaler API-Fehler (Zum Kopieren anklicken)
Invidious API Error (Click to copy): Invidious-API-Fehler (Zum Kopieren anklicken)
Falling back to Invidious API: Rückgriff auf Invidious-API
Falling back to the local API: Rückgriff auf lokale API
Falling back to Local API: Rückgriff auf lokale API
This video is unavailable because of missing formats. This can happen due to country unavailability.: Dieses
Video ist aufgrund fehlender Formate nicht verfügbar. Zugriffsbeschränkungen im
Land kann dafür der Grund sein.
@ -1204,11 +1204,6 @@ Downloading failed: Beim Herunterladen von „{videoTitle}“ gab es ein Problem
Screenshot Success: Bildschirmfoto als „{filePath}“ gespeichert
Screenshot Error: Bildschirmfoto fehlgeschlagen. {error}
New Window: Neues Fenster
Age Restricted:
Type:
Video: Video
Channel: Kanal
This {videoOrPlaylist} is age restricted: Dieses {videoOrPlaylist} ist altersbeschränkt
Channels:
Channels: Kanäle
Title: Kanalliste

View File

@ -945,7 +945,7 @@ Local API Error (Click to copy): 'Τοπικό σφάλμα Διεπαφής π
Invidious API Error (Click to copy): 'Σφάλμα Διεπαφής προγραμματισμού εφαρμογής Invidious(*API)
(Κάντε κλικ για αντιγραφή)'
Falling back to Invidious API: 'Επιστροφή στο Invidious API'
Falling back to the local API: 'Επιστροφή στη τοπική Διεπαφή προγραμματισμού εφαρμογής
Falling back to Local API: 'Επιστροφή στη τοπική Διεπαφή προγραμματισμού εφαρμογής
(API)'
Subscriptions have not yet been implemented: 'Οι συνδρομές δεν έχουν ακόμη υλοποιηθεί'
Loop is now disabled: 'Η επανάληψη είναι πλέον απενεργοποιημένη'
@ -1097,12 +1097,6 @@ Chapters:
Chapters: Κεφάλαια
'Chapters list visible, current chapter: {chapterName}': 'Ορατή λίστα κεφαλαίων,
τρέχον κεφάλαιο: {chapterName}'
Age Restricted:
This {videoOrPlaylist} is age restricted: Αυτό το {videoOrPlaylist} έχει περιορισμό
ηλικίας
Type:
Channel: Κανάλι
Video: Βίντεο
Ok: Εντάξει
Preferences: Προτιμήσεις
Screenshot Success: Αποθηκευμένο στιγμιότυπο οθόνης ως "{filePath}"

View File

@ -32,6 +32,7 @@ Back: Back
Forward: Forward
Open New Window: Open New Window
Go to page: Go to {page}
Close Banner: Close Banner
Version {versionNumber} is now available! Click for more details: Version {versionNumber} is now available! Click
for more details
@ -186,6 +187,8 @@ User Playlists:
EarliestPlayedFirst: 'Earliest Played'
SinglePlaylistView:
Search for Videos: Search for Videos
Toast:
This video cannot be moved up.: This video cannot be moved up.
This video cannot be moved down.: This video cannot be moved down.
@ -213,6 +216,8 @@ User Playlists:
Search in Playlists: Search in Playlists
Save: Save
Added {count} Times: 'Added {count} Time | Added {count} Times'
Toast:
You haven't selected any playlist yet.: You haven't selected any playlist yet.
"{videoCount} video(s) added to 1 playlist": "1 video added to 1 playlist | {videoCount} videos added to 1 playlist"
@ -451,7 +456,7 @@ Settings:
Hide Video Description: Hide Video Description
Hide Comments: Hide Comments
Hide Profile Pictures in Comments: Hide Profile Pictures in Comments
Display Titles Without Excessive Capitalisation: Display Titles Without Excessive Capitalisation
Display Titles Without Excessive Capitalisation: Display Titles Without Excessive Capitalisation And Punctuation
Hide Live Streams: Hide Live Streams
Hide Upcoming Premieres: Hide Upcoming Premieres
Hide Sharing Actions: Hide Sharing Actions
@ -722,6 +727,7 @@ Channel:
Hide Answers: Hide Answers
Video hidden by FreeTube: Video hidden by FreeTube
Video:
More Options: More Options
Mark As Watched: Mark As Watched
Remove From History: Remove From History
Video has been marked as watched: Video has been marked as watched
@ -955,7 +961,7 @@ Tooltips:
By default FreeTube will open the clicked link in your default browser.
Player Settings:
Force Local Backend for Legacy Formats: Only works when the Invidious API is your
default. When enabled, the local API will run and use the legacy formats returned
default. When enabled, the Local API will run and use the legacy formats returned
by that instead of the ones returned by Invidious. Helps when the videos returned
by Invidious don't play due to country restrictions.
Proxy Videos Through Invidious: Will connect to Invidious to serve videos instead
@ -1009,7 +1015,7 @@ Tooltips:
Local API Error (Click to copy): Local API Error (Click to copy)
Invidious API Error (Click to copy): Invidious API Error (Click to copy)
Falling back to Invidious API: Falling back to Invidious API
Falling back to the local API: Falling back to the local API
Falling back to Local API: Falling back to Local API
This video is unavailable because of missing formats. This can happen due to country unavailability.: This
video is unavailable because of missing formats. This can happen due to country
unavailability.
@ -1033,10 +1039,8 @@ Default Invidious instance has been cleared: Default Invidious instance has been
'The playlist has ended. Enable loop to continue playing': 'The playlist has ended. Enable
loop to continue playing'
Age Restricted:
This {videoOrPlaylist} is age restricted: This {videoOrPlaylist} is age restricted
Type:
Channel: Channel
Video: Video
This channel is age restricted: This channel is age restricted
This video is age restricted: This video is age restricted
External link opening has been disabled in the general settings: 'External link opening has been disabled in the general settings'
Downloading has completed: '"{videoTitle}" has finished downloading'
Starting download: 'Starting download of "{videoTitle}"'

View File

@ -121,14 +121,14 @@ Playlists: 'Playlists'
User Playlists:
Your Playlists: 'Your playlists'
Playlist Message: This page is not reflective of fully working playlists. It only
lists videos that you have saved or favourited. When the work has finished, all
videos currently here will be migrated to a Favourites playlist.
lists videos that you have saved or made a Favourite. When the work has finished,
all videos currently here will be migrated to a Favourites playlist.
Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: Your
saved videos are empty. Click on the save button on the corner of a video to have
it listed here
Search bar placeholder: Search in playlist
Empty Search Message: There are no videos in this playlist that match your search
Create New Playlist: Create new playlist
Create New Playlist: Create new Playlist
Add to Playlist: Add to playlist
This playlist currently has no videos.: This playlist currently has no videos.
Move Video Down: Move video down
@ -185,11 +185,21 @@ User Playlists:
"{videoCount} video(s) added to 1 playlist": 1 video added to 1 playlist | {videoCount}
videos added to 1 playlist
You haven't selected any playlist yet.: You haven't selected any playlist yet.
"{videoCount} video(s) added to {playlistCount} playlists": 1 video added to
{playlistCount} playlists | {videoCount} videos added to {playlistCount}
playlists
Select a playlist to add your N videos to: Select a playlist to add your video
to | Select a playlist to add your {videoCount} videos to
CreatePlaylistPrompt:
New Playlist Name: New playlist name
New Playlist Name: New Playlist name
Create: Create
Toast:
Playlist {playlistName} has been successfully created.: Playlist {playlistName}
has been successfully created.
There was an issue with creating the playlist.: There was an problem when creating
the playlist.
There is already a playlist with this name. Please pick a different name.: There
is already a Playlist with this name. Please pick a different name.
You have no playlists. Click on the create new playlist button to create a new one.: You
have no playlists. Click on the create new playlist button to create a new one.
Move Video Up: Move video up
@ -252,7 +262,7 @@ Settings:
Clear Default Instance: Clear default instance
Set Current Instance as Default: Set current instance as default
Current instance will be randomized on startup: Current instance will be randomised
on startup
on Startup
No default instance has been set: No default instance has been set
The currently set default instance is {instance}: The currently set default instance
is {instance}
@ -966,7 +976,7 @@ Up Next: 'Up Next'
Local API Error (Click to copy): 'Local API Error (Click to copy)'
Invidious API Error (Click to copy): 'Invidious API Error (Click to copy)'
Falling back to Invidious API: 'Falling back to Invidious API'
Falling back to the local API: 'Falling back to the local API'
Falling back to Local API: 'Falling back to Local API'
Subscriptions have not yet been implemented: 'Subscriptions have not yet been implemented'
Loop is now disabled: 'Loop is now disabled'
Loop is now enabled: 'Loop is now enabled'
@ -998,7 +1008,7 @@ Tooltips:
Proxy Videos Through Invidious: Will connect to Invidious to serve videos instead
of making a direct connection to YouTube. Overrides API preference.
Force Local Backend for Legacy Formats: Only works when the Invidious API is your
default. When enabled, the local API will run and use the legacy formats returned
default. When enabled, the Local API will run and use the legacy formats returned
by that instead of the ones returned by Invidious. Helps when the videos returned
by Invidious dont play due to country restrictions.
Scroll Playback Rate Over Video Player: While the cursor is over the video, press
@ -1082,17 +1092,15 @@ New Window: New window
Channels:
Empty: Your channel list is currently empty.
Unsubscribe: Unsubscribe
Unsubscribed: '{channelName} has been removed from your subscriptions'
Unsubscribe Prompt: Are you sure you want to unsubscribe from {channelName}?
Unsubscribed: '{channelName} has been removed from your Subscriptions'
Unsubscribe Prompt: Are you sure you want to Unsubscribe from {channelName}?
Title: Channel list
Search bar placeholder: Search channels
Channels: Channels
Count: '{number} channel(s) found.'
Age Restricted:
This {videoOrPlaylist} is age restricted: This {videoOrPlaylist} is age restricted
Type:
Video: Video
Channel: Channel
This channel is age restricted: This channel is age restricted
This video is age restricted: This video is age restricted
Chapters:
'Chapters list visible, current chapter: {chapterName}': 'Chapters list visible,
current chapter: {chapterName}'
@ -1115,3 +1123,4 @@ Playlist will not pause when current video is finished: Playlist will not pause
current video is finished
Go to page: Go to {page}
Tag already exists: {tagName} tag already exists
Close Banner: Close Banner

View File

@ -678,7 +678,7 @@ Local API Error (Click to copy): 'Error de la API local (Presione para copiar)'
Invidious API Error (Click to copy): 'Error de la API de Invidious (Presione para
copiar)'
Falling back to Invidious API: 'Recurriendo a la API de Invidious'
Falling back to the local API: 'Recurriendo a la API local'
Falling back to Local API: 'Recurriendo a la API local'
Subscriptions have not yet been implemented: 'Las suscripciones aún no se han implementado'
Loop is now disabled: 'El bucle esta desactivado'
Loop is now enabled: 'El bucle esta activado'

View File

@ -142,6 +142,7 @@ User Playlists:
a la que añadir su vídeo | Seleccione una lista de reproducción a la que añadir
sus {videoCount} vídeos
N playlists selected: '{playlistCount} seleccionada'
Added {count} Times: Añadido {count} vez | Añadido {count} veces
SinglePlaylistView:
Toast:
There were no videos to remove.: No había vídeos que eliminar.
@ -532,8 +533,8 @@ Settings:
Hide Upcoming Premieres: Ocultar los próximos estrenos
Hide Channels: Ocultar vídeos de los canales
Hide Channels Placeholder: ID del canal
Display Titles Without Excessive Capitalisation: Mostrar títulos sin demasiadas
mayúsculas
Display Titles Without Excessive Capitalisation: Mostrar títulos sin mayúsculas
ni signos de puntuación excesivos
Hide Featured Channels: Ocultar canales recomendados
Hide Channel Playlists: Ocultar las listas de reproducción de los canales
Hide Channel Community: Ocultar canales de la comunidad
@ -955,6 +956,7 @@ Video:
Pause on Current Video: Pausa en el vídeo actual
Unhide Channel: Mostrar el canal
Hide Channel: Ocultar el canal
More Options: Más opciones
Videos:
#& Sort By
Sort By:
@ -1038,7 +1040,7 @@ Local API Error (Click to copy): 'Error de la API local (Clic para copiar el có
Invidious API Error (Click to copy): 'Error de la API de Invidious (Clic para copiar
el código)'
Falling back to Invidious API: 'Recurriendo a la API de Invidious'
Falling back to the local API: 'Recurriendo a la API local'
Falling back to Local API: 'Recurriendo a la API local'
Subscriptions have not yet been implemented: 'Todavía no se han implementado las suscripciones'
Loop is now disabled: 'Reproducción en bucle desactivada'
Loop is now enabled: 'Reproducción en bucle activada'
@ -1077,10 +1079,11 @@ Tooltips:
Proxy Videos Through Invidious: Se conectará a Invidious para obtener vídeos en
lugar de conectar directamente con YouTube. Sobreescribirá la preferencia de
API.
Force Local Backend for Legacy Formats: Solo funciona cuando la API de Invidious
es la predeterminada. la API local se ejecutará y usará los formatos heredados
en lugar de Invidious. Esto ayudará cuando Invidious no pueda reproducir un
vídeo por culpa de las restricciones regionales.
Force Local Backend for Legacy Formats: Sólo funciona cuando la API de Invidious
es la predeterminada. Si está activada, la API local se ejecutará y utilizará
los formatos heredados devueltos por ella en lugar de los devueltos por Invidious.
Es útil cuando los vídeos devueltos por Invidious no se reproducen debido a
restricciones nacionales.
Scroll Playback Rate Over Video Player: Cuando el cursor esté sobre el vídeo,
presiona y mantén la tecla Control (Comando en Mac) y desplaza la rueda del
ratón hacia arriba o abajo para cambiar la velocidad de reproducción. Presiona
@ -1184,12 +1187,6 @@ Channels:
Unsubscribe: Cancelar la suscripción
Unsubscribed: '{channelName} ha sido eliminado de tus suscripciones'
Unsubscribe Prompt: ¿Está seguro/segura de querer desuscribirse de «{channelName}»?
Age Restricted:
Type:
Channel: Canal
Video: Vídeo
This {videoOrPlaylist} is age restricted: Este {videoOrPlaylist} tiene restricción
de edad
Clipboard:
Copy failed: Error al copiar al portapapeles
Cannot access clipboard without a secure connection: No se puede acceder al portapapeles
@ -1216,3 +1213,7 @@ Channel Unhidden: '{channel} eliminado del filtro de canales'
Tag already exists: La etiqueta "{tagName}" ya existe
Trimmed input must be at least N characters long: La entrada recortada debe tener
al menos 1 carácter | La entrada recortada debe tener al menos {length} caracteres
Close Banner: Cerrar el banner
Age Restricted:
This channel is age restricted: Este canal está restringido por edad
This video is age restricted: Este vídeo está restringido por edad

View File

@ -161,6 +161,7 @@ User Playlists:
Select a playlist to add your N videos to: Vali esitusloend, kuhu soovid oma video
lisada | Vali esitusloend, kuhu soovid oma {videoCount} videot lisada
N playlists selected: '{playlistCount} valitud'
Added {count} Times: Lisatud {count} kord | Lisatud {count} korda
SinglePlaylistView:
Toast:
There were no videos to remove.: Ei leidnud ühtegi videot, mida saaks eemaldada.
@ -497,7 +498,7 @@ Settings:
Hide Channels: Peida kanalites leiduvad videod
Hide Channels Placeholder: Kanali tunnus
Display Titles Without Excessive Capitalisation: Näita pealkirju ilma liigsete
suurtähtedeta
suurtähtede ja kirjavahemärkideta
Sections:
General: Üldist
Side Bar: Külgpaan
@ -884,6 +885,7 @@ Video:
Pause on Current Video: Peata hetkel esitatav video
Unhide Channel: Näita kanalit
Hide Channel: Peida kanal
More Options: Veel valikuid
Videos:
#& Sort By
Sort By:
@ -964,7 +966,7 @@ Up Next: 'Järgmisena'
Local API Error (Click to copy): 'Kohaliku API viga (kopeerimiseks klõpsi)'
Invidious API Error (Click to copy): 'Invidious''e API viga (kopeerimiseks klõpsi)'
Falling back to Invidious API: 'Varuvariandina kasutan Invidious''e API''t'
Falling back to the local API: 'Varuvariandina kasutan kohalikku API''t'
Falling back to Local API: 'Varuvariandina kasutan kohalikku API''t'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Kuna
vajalikke vorminguid ei leidu, siis see video pole saadaval. Niisugune viga võib
juhtuda ka maapiirangute tõttu.'
@ -1093,11 +1095,6 @@ Channels:
Unsubscribe: Loobu tellimusest
Unsubscribed: '{channelName} on sinu tellimustest eemaldatud'
Unsubscribe Prompt: Kas oled kindel, et soovid „{channelName}“ tellimusest loobuda?
Age Restricted:
This {videoOrPlaylist} is age restricted: See {videoOrPlaylist} on vanusepiiranguga
Type:
Channel: Kanal
Video: Video
Screenshot Success: Kuvatõmmis on salvestatud faili „{filePath}“
Clipboard:
Copy failed: Lõikelauale kopeerimine ei õnnestunud
@ -1125,3 +1122,7 @@ Channel Unhidden: '{channel} on eemaldatud kanalite filtrist'
Tag already exists: Silt „{tagName}“ on juba olemas
Trimmed input must be at least N characters long: Kärbitud sisend peab olema vähemalt
1 tähemärgi pikkune | Kärbitud sisend peab olema vähemalt {length} tähemärgi pikkune
Age Restricted:
This channel is age restricted: Kanali vaatamisel on vanusepiirang
This video is age restricted: Video vaatamisel on vanusepiirang
Close Banner: Sulge rekaampilt

View File

@ -34,6 +34,17 @@ Forward: 'Aurrera'
Global:
Videos: 'Bideoak'
Counts:
Subscriber Count: 1.harpideduna| {count} harpidedun
Watching Count: 1. ikuslea | {count} ikusle
Channel Count: 1. kanala ! {count} kanal
Video Count: 1. bideoa | {count} bideo
View Count: 1. ikustaldia | {count} ikustaldi
Live: Zuzenekoa
Shorts: Laburrak
Input Tags:
Length Requirement: Etiketak {zenbaki} karaktere izan behar ditu gutxienez
Community: Komunitatea
Version {versionNumber} is now available! Click for more details: '{versionNumber}
bertsioa erabilgarri! Klikatu azalpen gehiagorako'
Download From Site: 'Webgunetik jaitsi'
@ -90,6 +101,14 @@ Subscriptions:
Refresh Subscriptions: 'Harpidetzak freskatu'
Load More Videos: 'Bideo gehiago kargatu'
Error Channels: Akatsak dituzten kateak
Disabled Automatic Fetching: Harpidetza-bilaketa automatikoa desgaitu duzu. Freskatu
harpidetzak hemen ikusteko.
Empty Channels: Harpidetutako kanalek ez dute bideorik.
Empty Posts: Harpidetutako kanalek ez dute argitalpenik.
Load More Posts: Kargatu mezu gehiago
Subscriptions Tabs: Harpidetzen fitxak
All Subscription Tabs Hidden: Harpidetza fitxa guztiak ezkutatuta daude. Hemen edukia
ikusteko, erakutsi fitxa batzuk "{azpisection}" ataleko "{settingsSection}"-ean.
More: 'Gehiago'
Trending:
Trending: 'Joerak'
@ -111,6 +130,100 @@ User Playlists:
Search bar placeholder: Bilatu Erreprodukzio-zerrendan
Empty Search Message: Erreprodukzio-zerrenda honetan ez dago zure bilaketarekin
bat datorren bideorik
Remove Watched Videos: Kendu ikusitako bideoak
You have no playlists. Click on the create new playlist button to create a new one.: Ez
duzu erreprodukzio-zerrendarik. Egin klik sortu erreprodukzio-zerrenda berria
botoian berri bat sortzeko.
This playlist currently has no videos.: Erreprodukzio-zerrenda honek ez du bideorik.
Create New Playlist: Sortu erreprodukzio zerrenda berria
Add to Playlist: Gehitu erreprodukzio zerrendara
Add to Favorites: Gehitu {playlistName}-ra
Remove from Favorites: Kendu {playlistName}tik
Move Video Up: Mugitu bideoa gora
Move Video Down: Mugitu bideoa behera
Remove from Playlist: Kendu erreprodukzio zerrendatik
Playlist Name: Erreprodukzio zerrendaren izena
Playlist Description: Erreprodukzio-zerrendaren deskribapena
Save Changes: Gorde aldaketak
Cancel: Utzi
Edit Playlist Info: Editatu erreprodukzio zerrendaren informazioa
Copy Playlist: Kopiatu Erreprodukzio zerrenda
CreatePlaylistPrompt:
New Playlist Name: Erreprodukzio-zerrendaren izen berria
Toast:
Playlist {playlistName} has been successfully created.: '{playlistName} erreprodukzio-zerrenda
behar bezala sortu da.'
There was an issue with creating the playlist.: Arazo bat izan da erreprodukzio-zerrenda
sortzearekin.
There is already a playlist with this name. Please pick a different name.: Badago
dagoeneko izen honekin erreprodukzio-zerrenda bat. Mesedez, aukeratu beste
izen bat.
Create: Sortu
Enable Quick Bookmark With This Playlist: Gaitu laster-marka azkarra erreprodukzio-zerrenda
honekin
Disable Quick Bookmark: Desgaitu laster-marka azkarra
Sort By:
NameDescending: Z-A
LatestCreatedFirst: Sortu berria
EarliestCreatedFirst: Lehenen sortuak
LatestPlayedFirst: Duela gutxi erreproduzitua
EarliestPlayedFirst: Lehenen erreproduzitua
Sort By: Ordenatu honen arabera
NameAscending: A-Z
EarliestUpdatedFirst: Lehenen eguneratuak
LatestUpdatedFirst: Eguneratu berriak
Delete Playlist: Ezabatu erreprodukzio zerrenda
Are you sure you want to delete this playlist? This cannot be undone: Ziur erreprodukzio-zerrenda
ezabatu nahi duzula? Hau ezin da desegin.
SinglePlaylistView:
Toast:
Playlist has been updated.: Erreprodukzio-zerrenda eguneratu da.
"{videoCount} video(s) have been removed": bideo 1 kendu da | {videoCount} bideo
kendu dira
This video cannot be moved up.: Bideo hau ezin da gora eraman.
This video cannot be moved down.: Bideoa ezin da behera eraman.
Video has been removed: Bideoa kendu da
There was a problem with removing this video: Arazo bat izan da bideoa kentzean
This playlist is now used for quick bookmark: Erreprodukzio-zerrenda hau laster-markak
egiteko erabiltzen da orain
Quick bookmark disabled: Laster-marka azkarra desgaituta dago
This playlist is now used for quick bookmark instead of {oldPlaylistName}. Click here to undo: Erreprodukzio-zerrenda
hau laster-marketarako erabiltzen da orain {oldPlaylistName}-ren ordez. Egin
klik hemen desegiteko
Reverted to use {oldPlaylistName} for quick bookmark: '{oldPlaylistName} erabili
da berriro azkar markatzeko'
Some videos in the playlist are not loaded yet. Click here to copy anyway.: Erreprodukzio-zerrendako
bideo batzuk oraindik ez dira kargatu. Egin klik hemen kopiatzeko hala ere.
Playlist name cannot be empty. Please input a name.: Erreprodukzio zerrendaren
izena ezin da hutsik egon. Mesedez, idatzi izena.
There was an issue with updating this playlist.: Arazo bat izan da erreprodukzio-zerrenda
eguneratzean.
There were no videos to remove.: Ez zegoen kentzeko bideorik.
This playlist is protected and cannot be removed.: Erreprodukzio-zerrenda hau
babestuta dago eta ezin da kendu.
Playlist {playlistName} has been deleted.: '{playlistName} erreprodukzio-zerrenda
ezabatu da.'
This playlist does not exist: Erreprodukzio-zerrenda hau ez da existitzen
Search for Videos: Bilatu bideoak
AddVideoPrompt:
Added {count} Times: Gehitu da {count} Time | {count} aldiz gehitu da
Toast:
"{videoCount} video(s) added to 1 playlist": Bideo 1 gehitu da erreprodukzio-zerrenda
batera | {videoCount} bideo gehitu dira erreprodukzio-zerrenda batera
You haven't selected any playlist yet.: Oraindik ez duzu erreprodukzio zerrendarik
hautatu.
"{videoCount} video(s) added to {playlistCount} playlists": Bideo 1 gehitu da
{playlistCount} erreprodukzio zerrendetan | {videoCount} bideo gehitu dira
{playlistCount} erreprodukzio-zerrendetan
Select a playlist to add your N videos to: Hautatu erreprodukzio-zerrenda zure
bideoa -ra gehitzeko | Hautatu erreprodukzio-zerrenda zure {videoCount} bideoak
gehitzeko
N playlists selected: '{playlistCount} hautatuta'
Search in Playlists: Bilatu erreprodukzio-zerrendetan
Save: Gorde
Are you sure you want to remove all watched videos from this playlist? This cannot be undone: Ziur
ikusitako bideo guztiak erreprodukzio-zerrenda honetatik kendu nahi dituzula?
Hau ezin da desegin.
History:
# On History Page
History: 'Historikoa'
@ -147,6 +260,8 @@ Settings:
Beginning: 'Hasiera'
Middle: 'Erdian'
End: 'Bukaera'
Hidden: Ezkutatuta
Blur: Lausotzea
View all Invidious instance information: 'Invidious instantzia guztien informazioa
ikusi'
Region for Trending: 'Joeren eskualdea'
@ -179,6 +294,9 @@ Settings:
Dracula: Drakula
System Default: Sistemak lehenetsia
Catppuccin Mocha: Catppuccin Motxa
Nordic: nordikoa
Pastel Pink: Pastel arrosa
Hot Pink: Arrosa beroa
Main Color Theme:
Main Color Theme: 'Oinarrizko koloreen gaia'
Red: 'Gorria'
@ -221,6 +339,7 @@ Settings:
Secondary Color Theme: 'Gaiaren bigarren mailako kolorea'
#* Main Color Theme
Hide Side Bar Labels: Ezkutatu alboko barraren etiketak
Hide FreeTube Header Logo: Ezkutatu FreeTube goiburuko logotipoa
Player Settings:
Player Settings: 'Erreprodukzioaren ezarpenak'
Force Local Backend for Legacy Formats: 'Behartu backend lokala Legacy formatuentzat'
@ -272,6 +391,11 @@ Settings:
Display Play Button In Video Player: Bistaratu Erreproduzitzeko botoia bideo erreproduzitzailean
Max Video Playback Rate: Gehienezko bideoen erreprodukzio-tasa
Video Playback Rate Interval: Bideo Erreprodukzio-tasa tartea
Comment Auto Load:
Comment Auto Load: Iruzkin karga automatikoa
Skip by Scrolling Over Video Player: Saltatu bideo-erreproduzitzailean korrituz
Enter Fullscreen on Display Rotate: Sartu pantaila osoko pantaila biratu pantailan
Allow DASH AV1 formats: Baimendu DASH AV1 formatuak
Privacy Settings:
Privacy Settings: 'Pribatutasunari buruzko ezarpenak'
Remember History: 'Historikoa oroitu'
@ -289,11 +413,20 @@ Settings:
Are you sure you want to remove all subscriptions and profiles? This cannot be undone.: 'Ziur
al zaude zure profil eta harpidetza guztiak ezabatu nahi dituzula? Ezingo duzu
atzera egin.'
All playlists have been removed: Erreprodukzio-zerrenda guztiak kendu dira
Save Watched Videos With Last Viewed Playlist: Gorde ikusitako bideoak ikusitako
azken erreprodukzio-zerrendarekin
Remove All Playlists: Kendu erreprodukzio-zerrenda guztiak
Are you sure you want to remove all your playlists?: Ziur erreprodukzio-zerrenda
guztiak kendu nahi dituzula?
Subscription Settings:
Subscription Settings: 'Harpidetzen ezarpenak'
Hide Videos on Watch: 'Ikusten ari zaren bideoa ezkutatu'
Fetch Feeds from RSS: 'RSS jarioak eskuratu'
Manage Subscriptions: 'Harpidetzak kudeatu'
Fetch Automatically: Eskuratu jarioa automatikoki
Only Show Latest Video for Each Channel: Erakutsi soilik kanal bakoitzeko azken
bideoa
Distraction Free Settings:
Distraction Free Settings: 'Oharkabetasunak ekiditeko ezarpenak'
Hide Video Views: 'Bideoen ikustaldi kopurua ezkutatu'
@ -310,6 +443,38 @@ Settings:
Hide Video Description: Bideoaren deskribapena ezkutatu
Hide Comments: Iruzkinak ezkutatu
Hide Live Streams: Zuzeneko emanaldiak ezkutatu
Sections:
Side Bar: Alboko Barra
Subscriptions Page: Harpidetzak Orria
Channel Page: Kanalaren Orria
General: Orokorra
Watch Page: Ikusi Orria
Hide Profile Pictures in Comments: Ezkutatu profileko argazkiak iruzkinetan
Display Titles Without Excessive Capitalisation: Bistaratu izenburuak gehiegizko
letra larriz eta puntuaziorik gabe
Hide Channels Placeholder: Kanalaren IDa
Hide Channel Playlists: Ezkutatu kanaleko erreprodukzio-zerrendak
Hide Channel Community: Ezkutatu kanalaren komunitatea
Hide Channel Podcasts: Ezkutatu kanaleko podcastak
Hide Videos and Playlists Containing Text: Ezkutatu testua duten bideoak eta erreprodukzio-zerrendak
Hide Channels: Ezkutatu bideoak kanaletatik
Hide Upcoming Premieres: Ezkutatu datozen estreinaldiak
Hide Subscriptions Videos: Ezkutatu harpidetza-bideoak
Hide Subscriptions Shorts: Ezkutatu bideo laburren harpidetzak
Hide Channel Releases: Ezkutatu kanalen kaleratzeak
Hide Chapters: Ezkutatu kapituluak
Hide Channels Invalid: Emandako kanalaren IDa baliogabea da
Hide Channels API Error: Errore bat gertatu da emandako IDa duen erabiltzailea
berreskuratzean. Mesedez, egiaztatu berriro IDa zuzena den.
Hide Channels Already Exists: Kanalaren IDa badago jada
Hide Channel Shorts: Ezkutatu kanalaren bideo laburrak
Hide Videos and Playlists Containing Text Placeholder: Hitza, Hitzaren zatia edo
esaldia
Hide Subscriptions Live: Ezkutatu zuzenekoen harpidetzak
Hide Subscriptions Community: Ezkutatu harpidetzen komunitateak
Hide Featured Channels: Ezkutatu nabarmendutako kanalak
Hide Channels Disabled Message: Kanal batzuk IDa erabiliz blokeatu dira eta ez
dira prozesatu. Eginbidea blokeatuta dago ID horiek eguneratzen ari diren bitartean
Data Settings:
Data Settings: 'Datuen ezarpenak'
Select Import Type: 'Hautatu Inportazio mota'
@ -357,6 +522,18 @@ Settings:
esportatu dira
Playlist insufficient data: Ez da datu nahikorik "{playlist}" erreprodukzio zerrendarentzat,
elementutik ateratzen
History File: Historikoaren fitxategia
Playlist File: Erreprodukzio-zerrendaren fitxategia
Export Playlists For Older FreeTube Versions:
Label: Esportatu erreprodukzio zerrendak FreeTube bertsio zaharretarako
Tooltip: "Aukera honek erreprodukzio-zerrenda guztietako bideoak \"Gogokoak\"\
\ izeneko erreprodukzio-zerrenda batera esportatzen ditu.\nNola esportatu
eta inportatu bideoak erreprodukzio-zerrendetan FreeTube-ren bertsio zaharrago
baterako:\n 1. Esportatu zure erreprodukzio zerrendak aukera hau gaituta.\n
2. Ezabatu lehendik dituzun erreprodukzio-zerrenda guztiak Pribatutasun-ezarpenetan
dagoen Kendu zerrenda guztiak aukera erabiliz.\n 3. Abiarazi FreeTube-ren
bertsio zaharra eta inportatu esportatutako erreprodukzio-zerrendak.\""
Subscription File: Harpidetza Fitxategia
Proxy Settings:
Proxy Settings: 'Proxy-aren ezarpenak'
Enable Tor / Proxy: 'Tor / Proxy ahalbidetu'
@ -381,6 +558,10 @@ Settings:
External Player: Kanpoko erreproduzitzailea
Custom External Player Executable: Lehenetsitako kanpo erreproduzitzailea exekutagarria
Custom External Player Arguments: Lehenetsitako kanpo erreproduzitzailea argudioak
Ignore Default Arguments: Ez ikusi lehenetsitako argudioak
Players:
None:
Name: Bat ere ez
Download Settings:
Download Settings: Deskargen ezarpenak
Ask Download Path: Deskargaren ibilbidea galdetu
@ -402,11 +583,31 @@ Settings:
'SponsorBlock API Url (Default is https://sponsor.ajay.app)': Babesleak blokeatzeko
API Url (lehenetsia https://sponsor.ajay.app da)
SponsorBlock Settings: Babesleak blokeatzeko ezarpenak
UseDeArrowTitles: Erabili DeArrow bideo-izenburuak
UseDeArrowThumbnails: Erabili DeArrow irudi txikietarako
'DeArrow Thumbnail Generator API Url (Default is https://dearrow-thumb.ajay.app)': DeArrow
Thumbnail Generator API URLa (lehenetsia https://dearrow-thumb.ajay.app da)
Parental Control Settings:
Show Family Friendly Only: Erakutsi familientzat aproposa dena bakarrik
Hide Unsubscribe Button: Harpidetza kendu botoia ezkutatu
Parental Control Settings: Gurasoen kontrolaren ezarpenak
Hide Search Bar: Bilaketa barra ezkutatu
Password Dialog:
Password: Pasahitza
Password Incorrect: Pasahitza okerra
Unlock: Desblokeatu
Enter Password To Unlock: Sartu pasahitza ezarpenak desblokeatzeko
Experimental Settings:
Replace HTTP Cache: Ordeztu HTTP cachea
Experimental Settings: Ezarpen esperimentalak
Warning: Ezarpen hauek esperimentalak dira, aktibatuta dauden bitartean hutsegiteak
eragin ditzakete. Oso gomendagarria da babeskopiak egitea. Erabili zure ardurapean!
Password Settings:
Password Settings: Pasahitz ezarpenak
Set Password To Prevent Access: Ezarri pasahitz bat ezarpenetara sarbidea galarazteko
Remove Password: Pasahitza ezabatu
Set Password: Ezarri pasahitza
Expand All Settings Sections: Zabaldu ezarpen guztien atalak
About:
#On About page
About: 'Honi buruz'
@ -436,6 +637,7 @@ About:
these people and projects: 'Hurrengo pertsonak eta proiektuak'
Donate: 'Donazioa egin'
Discussions: Eztabaidak
Profile:
Profile Select: 'Hautatu profila'
Profile Filter: 'Profilaren iragazkiak'
@ -480,6 +682,12 @@ Profile:
batetik ezabatuko.'
#On Channel Page
Profile Settings: Profilaren ezarpenak
Close Profile Dropdown: Itxi goitibeherako profila
Open Profile Dropdown: Ireki goitibeherako profila
Toggle Profile List: Aldatu profilen zerrenda
Edit Profile Name: Editatu profilaren izena
Create Profile Name: Sortu profilaren izena
Profile Name: Profilaren izena
Channel:
Subscribe: 'Harpidetu'
Unsubscribe: 'Harpidetza kendu'
@ -510,6 +718,39 @@ Channel:
About: 'Honi buruz'
Channel Description: 'Kanalaren deskribapena'
Featured Channels: 'Nabarmendutako kanalak'
Joined: Bat eginda
Location: Kokapena
Tags:
Tags: Etiketak
Search for: Bilatu "{tag}"
Details: Xehetasunak
This channel does not exist: Kanal hau ez da existitzen
This channel is age-restricted and currently cannot be viewed in FreeTube.: Kanal
hau adin mugatuta dago eta une honetan ezin da ikusi FreeTube-n.
Shorts:
This channel does not currently have any shorts: Une honetan kanal honek ez du
bideo laburrik
Releases:
This channel does not currently have any releases: Une honetan kanal honek ez
du argitalpenik
Releases: Argitalpenak
Community:
Hide Answers: Erantzunak ezkutatu
votes: '{votes} bozka'
This channel currently does not have any posts: Une honetan kanal honek ez du
argitalpenik
Reveal Answers: Erantzunak agerian utzi
Video hidden by FreeTube: FreeTube-k ezkutatutako bideoa
Channel Tabs: Kanalaren fitxak
This channel does not allow searching: Kanal honek ez du bilaketarik onartzen
Live:
Live: Zuzenekoak
This channel does not currently have any live streams: Kanal honek ez du zuzeneko
erreprodukziorik
Podcasts:
Podcasts: Podcastak
This channel does not currently have any podcasts: Une honetan kanal honek ez
du podcastik
Video:
Mark As Watched: 'Ikusitako gisa jarri'
Remove From History: 'Historikotik ezabatu'
@ -592,6 +833,7 @@ Video:
Years: 'Urteak'
Ago: 'Duela'
Upcoming: 'Estreinaldiak'
In less than a minute: Minutu bat baino gutxiagoan
Published on: 'Noiz argitaratua'
Streamed on: 'Noiz zuzenean emana'
Started streaming on: 'Noiz hasi zen zuzenekoa'
@ -636,6 +878,16 @@ Video:
intro: Sarrera
Skipped segment: Saltatu egin da segmentua
Premieres on: Estreinaldiak
Hide Channel: Kanala ezkutatu
Unhide Channel: Kanala erakutsi
Premieres: Estreinaldiak
'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Zuzeneko
txata ez dago erabilgarri zuzeneko honentzat. Baliteke igo duenak desgaitu izana.
Show Super Chat Comment: Erakutsi Super txat iruzkina
Pause on Current Video: Gelditu uneko bideoa
More Options: Aukera gehiago
Upcoming: Datozenak
Scroll to Bottom: Joan Beherantz
Videos:
#& Sort By
Sort By:
@ -685,6 +937,7 @@ Share:
YouTube Channel URL copied to clipboard: 'Youtube-ko kanalaren URL-a arbelean itsatsi
da'
Share Channel: Kanala partekatu
Mini Player: 'Erreproduzitzaile txikia'
Comments:
Comments: 'Iruzkinak'
@ -710,6 +963,10 @@ Comments:
Show More Replies: Erantzun gehiago erakutsi
And others: eta bestelakoak
Pinned by: Honengatik ainguratuta
Hearted: Bihotzez
From {channelName}: '{channelName}-tik'
View {replyCount} replies: Ikusi {replyCount} erantzunak
Subscribed: Harpidetuta
Up Next: 'Hurrengoa'
#Tooltips
@ -749,11 +1006,19 @@ Tooltips:
eta mantendu (Komando tekla MAC-etan) eta ondoren saguaren ezkerreko botoia
sakatu, lehenetsitako erreprodukzio tasara itzultzeko (1x baldin eta ezarpenetan
aldaketarik egin ez bada).
Skip by Scrolling Over Video Player: Erabili korritze-gurpila bideoa saltatzeko,
MPV estiloa.
Allow DASH AV1 formats: DASH AV1 formatuak DASH H.264 formatuak baino itxura hobea
izan dezake. DASH AV1 formatuek potentzia gehiago behar dute erreproduzitzeko!
Ez daude bideo guztietan eskuragarri, kasu horietan erreproduzitzaileak DASH
H.264 formatuak erabiliko ditu ordez.
Subscription Settings:
Fetch Feeds from RSS: 'Posible denean, Freetube-k bere lehenetsitako metodoa erabili
beharrean RSS-ak baliatuko ditu zure harpidetzen jariora konektatzeko. RSS arinagoa
izateaz gain, IP-en blokeoak saihesten ditu. Aldiz, zuzenekoaren egoeraren edo
bideoaren iraupenaren informaziorik ez du ematen, besteak beste'
Fetch Automatically: Gaituta dagoenean, FreeTubek automatikoki eskuratuko du zure
harpidetza-jarioa leiho berri bat irekitzen denean eta profila aldatzean.
Privacy Settings:
Remove Video Meta Files: 'Gaituta dagoenean, FreeTube-k automatikoki ezabatzen
ditu bideoen erreprodukzioan sortutako metafitxategiak, bistaratze orria ixten
@ -772,11 +1037,34 @@ Tooltips:
Individious-en ezarpenek ez dituzte kanpo erreproduzitzaileak trabatzen.
Custom External Player Arguments: Komando-lerroko argumentu pertsonalizatuak,
puntu eta komaz bereizita (';'), kanpoko erreproduzitzailera pasatzea nahi duzu.
Ignore Default Arguments: Ez bidali argumentu lehenetsirik kanpoko erreproduzitzaileari
bideoaren URLaz gain (adibidez, erreprodukzio-tasa, erreprodukzio-zerrendaren
URLa, etab.). Argumentu pertsonalizatuak transmitituko dira oraindik.
Distraction Free Settings:
Hide Channels: Sartu kanalaren ID bat bideo, erreprodukzio-zerrenda eta kanala
bera bilaketetan, joeran, ezagunenetan eta gomendagarrienetan ager ez dadin
ezkutatzeko. Sartutako kanalaren IDak guztiz bat etorri behar du eta maiuskulak
eta minuskulak bereizten ditu.
Hide Videos and Playlists Containing Text: Idatzi hitz bat, hitz-zati bat edo
esaldi bat (maiuskulak eta minuskulak bereizten ez diren) jatorrizko izenburuak
FreeTube osoan duten bideo eta erreprodukzio-zerrenda guztiak ezkutatzeko, historia,
zure erreprodukzio-zerrendak eta erreprodukzio-zerrenden barneko bideoak soilik
kenduta.
Hide Subscriptions Live: Ezarpen hau aplikazio osorako "{appWideSetting}" ezarpenak
ordezkatzen du, "{settingsSection}" ataleko "{azpisekzioa}" atalean
Experimental Settings:
Replace HTTP Cache: Electron-en diskoan oinarritutako HTTP cachea desgaitzen du
eta memoriako irudien cache pertsonalizatua gaitu. RAM erabilera handitzea ekarriko
du.
SponsorBlock Settings:
UseDeArrowThumbnails: Ordeztu bideoaren miniaturak DeArrow-en miniaturaz.
UseDeArrowTitles: Ordeztu bideoen izenburuak DeArrow-en erabiltzaileek bidalitako
tituluekin.
Local API Error (Click to copy): 'Tokiko API-ak huts egin du (klikatu kopiatzeko)'
Invidious API Error (Click to copy): 'Individious-eko APIak huts egin du (klikatu
kopiatzeko)'
Falling back to Invidious API: 'Individious-eko APIra itzultzen'
Falling back to the local API: 'Tokiko APIra itzultzen'
Falling back to Local API: 'Tokiko APIra itzultzen'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Bideo
hau ez dago erabilgarri, zenbait formatu eskas baitira. Honakoa zure herrialdean
erabilgarri ez dagoelako gerta daiteke.'
@ -827,9 +1115,34 @@ Channels:
Unsubscribe Prompt: Ziur al zaude "{channelName}"-ren harpidetza kendu nahi duzula?
Count: '{number} kanal aurkitu dira.'
Empty: Zure kanalen zerrenda hutsik da.
Age Restricted:
This {videoOrPlaylist} is age restricted: Honako {videoOrPlaylist} adin muga du
Type:
Channel: Kanala
Video: Bideoa
Preferences: Hobespenak
Go to page: Joan {page}-ra
Close Banner: Itxi iragarkia
Age Restricted:
This channel is age restricted: Kanal hau adin mugatuta dago
This video is age restricted: Bideo hau adin mugatuta dago
Playlist will not pause when current video is finished: Erreprodukzio-zerrenda ez
da etengo uneko bideoa amaitzen denean
Playlist will pause when current video is finished: Erreprodukzio-zerrenda pausatu
egingo da uneko bideoa amaitzen denean
Channel Unhidden: '{channel} kanalaren iragazkitik kendu da'
Clipboard:
Cannot access clipboard without a secure connection: Ezin da arbelera sartu konexio
segururik gabe
Copy failed: Ezin izan da kopiatu arbelean
Tag already exists: '"{tagName}" etiketa badago jada'
Trimmed input must be at least N characters long: Moztutako sarrerak karaktere bat
izan behar du gutxienez | Moztutako sarrerak gutxienez {length} karaktere izan behar
ditu
Chapters:
'Chapters list hidden, current chapter: {chapterName}': 'Kapituluen zerrenda ezkutatuta
dago, uneko kapitulua: {chapterName}'
Chapters: Kapituluak
'Chapters list visible, current chapter: {chapterName}': 'Kapituluen zerrenda ikusgai,
uneko kapitulua: {chapterName}'
Hashtag:
Hashtag: Traola
This hashtag does not currently have any videos: Traola honek ez du bideorik une
honetan
Ok: Ados
Channel Hidden: '{channel} gehitu da kanalaren iragazkian'

View File

@ -900,12 +900,6 @@ Screenshot Success: اسکرین شات به عنوان «{filePath}» ذخیر
Ok: تایید
Downloading has completed: دانلود '{videoTitle}' به پایان رسید
Loop is now enabled: حلقه اکنون فعال است
Age Restricted:
Type:
Video: ویدیو
Channel: کانال
This {videoOrPlaylist} is age restricted: این {videoOrPlaylist} دارای محدودیت سنی
است
Shuffle is now enabled: Shuffle اکنون فعال است
Falling back to Invidious API: بازگشت به Invidious API
Local API Error (Click to copy): خطای Local API (برای کپی کلیک کنید)
@ -913,7 +907,7 @@ Shuffle is now disabled: Shuffle اکنون غیرفعال است
Canceled next video autoplay: پخش خودکار ویدیوی بعدی لغو شد
Unknown YouTube url type, cannot be opened in app: نوع URL ناشناخته YouTube، در برنامه
باز نمی شود
Falling back to the local API: بازگشت به API محلی
Falling back to Local API: بازگشت به API محلی
This video is unavailable because of missing formats. This can happen due to country unavailability.: این
ویدیو به دلیل عدم وجود قالب در دسترس نیست. این ممکن است به دلیل در دسترس نبودن کشور
اتفاق بیفتد.

View File

@ -904,7 +904,7 @@ Up Next: 'Seuraavaksi'
Local API Error (Click to copy): 'Paikallinen API-virhe (Kopioi napsauttamalla)'
Invidious API Error (Click to copy): 'Invidious API-virhe (Kopioi napsauttamalla)'
Falling back to Invidious API: 'Palaa takaisin Invidious-sovellusliittymään'
Falling back to the local API: 'Palaa takaisin paikalliseen sovellusliittymään'
Falling back to Local API: 'Palaa takaisin paikalliseen sovellusliittymään'
Subscriptions have not yet been implemented: 'Tilauksia ei ole vielä jalkautettu'
Loop is now disabled: 'Silmukka on poistettu käytöstä'
Loop is now enabled: 'Silmukka on nyt käytössä'
@ -1064,11 +1064,6 @@ Downloading has completed: Videon "{videoTitle}" lataus on valmis
Starting download: Aloitetaan lataamaan "{videoTitle}"
Screenshot Success: Kuvakaappaus tallennettu nimellä ”{filePath}”
New Window: Uusi Ikkuna
Age Restricted:
This {videoOrPlaylist} is age restricted: Tämä {videoOrPlaylist} on ikärajoitettu
Type:
Video: Video
Channel: Kanava
Screenshot Error: Ruutukaappaus epäonnistui. {error}
Channels:
Channels: Kanavat

View File

@ -148,6 +148,7 @@ User Playlists:
à {playlistCount} listes de lecture | {videoCount} vidéos ajoutées à {playlistCount}
listes de lecture
N playlists selected: '{playlistCount} Sélectionnée(s)'
Added {count} Times: Ajouté {count} Fois | Ajouté {count} Fois
SinglePlaylistView:
Toast:
There were no videos to remove.: Il n'y avait aucune vidéo à supprimer.
@ -557,7 +558,7 @@ Settings:
Hide Channels: Masquer les vidéos des chaînes
Hide Channels Placeholder: Identifiant de la chaîne
Display Titles Without Excessive Capitalisation: Afficher les titres sans majuscules
excessives
ni ponctuation excessives
Hide Channel Playlists: Masquer les listes de lecture des chaînes
Hide Featured Channels: Masquer les chaînes en vedette
Hide Channel Community: Masquer la communauté de la chaîne
@ -946,6 +947,7 @@ Video:
Pause on Current Video: Pause sur la vidéo en cours
Hide Channel: Cacher la chaîne
Unhide Channel: Rétablir la chaîne
More Options: Plus d'options
Videos:
#& Sort By
Sort By:
@ -1030,7 +1032,7 @@ Up Next: 'À suivre'
Local API Error (Click to copy): 'Erreur d''API locale (Cliquez pour copier)'
Invidious API Error (Click to copy): 'Erreur d''API Invidious (Cliquez pour copier)'
Falling back to Invidious API: 'Revenir à l''API Invidious'
Falling back to the local API: 'Revenir à l''API locale'
Falling back to Local API: 'Revenir à l''API locale'
Subscriptions have not yet been implemented: 'Les abonnements n''ont pas encore été
implémentés'
Loop is now disabled: 'La boucle est maintenant désactivée'
@ -1226,12 +1228,6 @@ Download folder does not exist: 'Le répertoire "$" de téléchargement n''exist
Screenshot Success: Capture d'écran enregistrée sous « {filePath} »
Screenshot Error: La capture d'écran a échoué. {error}
New Window: Nouvelle fenêtre
Age Restricted:
Type:
Video: Vidéo
Channel: Chaîne
This {videoOrPlaylist} is age restricted: Ce {videoOrPlaylist} est soumis à une
limite d'âge
Channels:
Channels: Chaînes
Title: Liste des chaînes
@ -1267,3 +1263,7 @@ Channel Unhidden: '{channel} retiré du filtre de chaîne'
Trimmed input must be at least N characters long: L'entrée tronquée doit comporter
au moins 1 caractère | L'entrée tronquée doit comporter au moins {length} caractères
Tag already exists: L'étiquette « {tagName} » existe déjà
Age Restricted:
This channel is age restricted: Cette chaîne est soumise à des restrictions d'âge
This video is age restricted: Cette vidéo est soumise à des restrictions d'âge
Close Banner: Fermer la bannière

View File

@ -911,7 +911,7 @@ Tooltips:
Local API Error (Click to copy): 'Erro de API local (Preme para copiar)'
Invidious API Error (Click to copy): 'Erro de API Invidious (Preme para copiar)'
Falling back to Invidious API: 'Recorrendo á API Invidious'
Falling back to the local API: 'Recorrendo á API local'
Falling back to Local API: 'Recorrendo á API local'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Este
vídeo non está dispoñible porque faltan formatos. Isto pode ocorrer debido á non
dispoñibilidade do país.'
@ -958,12 +958,6 @@ Downloading has completed: '"{videoTitle}" rematou de descargarse'
External link opening has been disabled in the general settings: A apertura das ligazóns
externas desactivouse na configuración xeral
Starting download: Comenzando a descarga de "{videoTitle}"
Age Restricted:
Type:
Channel: Canle
Video: Vídeo
This {videoOrPlaylist} is age restricted: Esta {videoOrPlaylist} ten restricións
de idade
Default Invidious instance has been cleared: Borrouse a instancia predeterminada de
Invidious
Screenshot Error: Produciuse un erro na captura de pantalla. {error}

View File

@ -49,4 +49,3 @@ Settings:
SponsorBlock Settings: {}
Channel: {}
Tooltips: {}
Age Restricted: {}

View File

@ -874,7 +874,7 @@ Up Next: 'הסרטון הבא'
Local API Error (Click to copy): 'בעיה ב־API המקומי (יש ללחוץ להעתקה)'
Invidious API Error (Click to copy): 'בעיה ב־API של Invidious (יש ללחוץ להעתקה)'
Falling back to Invidious API: 'מתבצעת נסיגה ל־API של Invidious'
Falling back to the local API: 'מתבצעת נסיגה ל־API המקומי'
Falling back to Local API: 'מתבצעת נסיגה ל־API המקומי'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'חסרות
תצורות לסרטון הזה. הדבר יכול להיגרם בגלל חוסר זמינות למדינה.'
Subscriptions have not yet been implemented: 'מנגנון המינויים עדיין לא מוכן'
@ -980,11 +980,6 @@ Playing Next Video Interval: הסרטון הבא יתחיל מייד. לחיצה
Screenshot Success: צילום המסך נשמר בתור „{filePath}”
Screenshot Error: צילום המסך נכשל. {error}
New Window: חלון חדש
Age Restricted:
Type:
Channel: ערוץ
Video: סרטון
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} זה מוגבל בגיל'
Channels:
Search bar placeholder: חיפוש ערוצים
Empty: רשימת הערוצים שלך ריקה כרגע.

View File

@ -195,6 +195,7 @@ User Playlists:
videa dodana u 1 zbirku
Select a playlist to add your N videos to: Odaberi zbirku za dodavanje tvog videa
| Odaberi zbirku za dodavanje tvojih {videoCount} videa
Added {count} Times: Dodano {count} puta | Dodano {count} puta
CreatePlaylistPrompt:
Create: Stvori
Toast:
@ -272,11 +273,12 @@ Settings:
Black: 'Crna'
Dark: 'Tamna'
Light: 'Svijetla'
Dracula: 'Drakula'
Dracula: 'Dracula'
System Default: Standard sustava
Catppuccin Mocha: Catppuccin Mocha
Pastel Pink: Pastelno ružičasta
Hot Pink: Vruća ružičasta
Nordic: Nordic
Main Color Theme:
Main Color Theme: 'Glavna boja teme'
Red: 'Crvena'
@ -521,7 +523,7 @@ Settings:
Hide Channels: Sakrij videa iz kanala
Hide Channels Placeholder: ID kanala
Display Titles Without Excessive Capitalisation: Prikaži naslove bez pretjeranog
korištenja velikih slova
korištenja velikih slova i interpunkcije
Hide Featured Channels: Sakrij istaknute kanale
Hide Channel Playlists: Sakrij kanal zbirki
Hide Channel Community: Sakrij kanal zajednice
@ -927,7 +929,7 @@ Video:
Resolution: Razlučivost
Player Dimensions: Dimenzije playera
Bitrate: Brzina prijenosa
Volume: Glasnoća
Volume: Direktorij
Bandwidth: Propusnost
Buffered: Učitano u memoriju
Mimetype: Mimetype
@ -942,6 +944,7 @@ Video:
Pause on Current Video: Zaustavi trenutačni video
Unhide Channel: Prikaži kanal
Hide Channel: Sakrij kanal
More Options: Više opcija
Videos:
#& Sort By
Sort By:
@ -1022,7 +1025,7 @@ Up Next: 'Sljedeći'
Local API Error (Click to copy): 'Greška lokalnog sučelja (pritisni za kopiranje)'
Invidious API Error (Click to copy): 'Greška Invidious sučelja (pritisni za kopiranje)'
Falling back to Invidious API: 'Koristit će se Invidious sučelje'
Falling back to the local API: 'Koristit će se lokalno sučelje'
Falling back to Local API: 'Koristit će se lokalno sučelje'
Subscriptions have not yet been implemented: 'Pretplate još nisu implementirane'
Loop is now disabled: 'Ponavljanje je sada deaktivirano'
Loop is now enabled: 'Ponavljanje je sada aktivirano'
@ -1053,7 +1056,7 @@ Tooltips:
Proxy Videos Through Invidious: Za reprodukciju videa povezat će se s Invidiousom
umjesto izravnog povezivanja s YouTubeom. Zanemaruje postavke sučelja.
Force Local Backend for Legacy Formats: Radi samo, kad se Invidious postavi kao
standardno sučelje. Kada je aktivirano, lokalno sučelje će pokretati i koristiti
standardno sučelje. Kada je aktivirano, lokalno API sučelje će pokretati i koristiti
stare formate umjesto onih koje dostavlja Invidious. Pomaže u slučajevima, kad
je reprodukcija videa koje dostavlja Invidious u zemlji zabranjena/ograničena.
Scroll Playback Rate Over Video Player: Dok se pokazivač nalazi na videu, pritisni
@ -1148,11 +1151,6 @@ Starting download: Početak preuzimanja „{videoTitle}”
Screenshot Success: Snimka ekrana je spremljena pod „{filePath}”
Screenshot Error: Neuspjela snimka ekrana. {error}
New Window: Novi prozor
Age Restricted:
This {videoOrPlaylist} is age restricted: Ovaj {videoOrPlaylist} je dobno ograničen
Type:
Channel: Kanal
Video: Video
Channels:
Channels: Kanali
Title: Popis kanala
@ -1187,3 +1185,7 @@ Channel Unhidden: '{channel} je uklonjen iz filtra kanala'
Trimmed input must be at least N characters long: Skraćeni unos mora imati barem 1
znak | Skraćeni unos mora imati barem {length} znaka
Tag already exists: Oznaka „{tagName}” već postoji
Age Restricted:
This channel is age restricted: Ovaj je dobno ograničeni kanal
This video is age restricted: Ovaj je dobno ograničeni video
Close Banner: Zatvori natpis

View File

@ -1,5 +1,5 @@
# Put the name of your locale in the same language
Locale Name: 'English (US)'
Locale Name: 'Magyar'
FreeTube: 'FreeTube'
# Currently on Subscriptions, Playlists, and History
'This part of the app is not ready yet. Come back later when progress has been made.': >-
@ -147,12 +147,13 @@ User Playlists:
lejátszási listákhoz
"{videoCount} video(s) added to 1 playlist": 1 videó hozzáadva 1 lejátszási
listához | {videoCount} videó hozzáadása 1 lejátszási listához
You haven't selected any playlist yet.: Még nem választott ki lejátszási listát
sem.
You haven't selected any playlist yet.: Még nem választott ki egyetlen lejátszási
listát sem.
Select a playlist to add your N videos to: Válasszon ki egy lejátszási listát
a videó hozzáadásához | Válasszon ki egy lejátszási listát a {videoCount} videó
hozzáadásához
N playlists selected: '{playlistCount} Kiválasztott'
Added {count} Times: Hozzáadva {count} Alkalommal | Hozzáadva {count} Alkalommal
SinglePlaylistView:
Toast:
There were no videos to remove.: Nem voltak eltávolítható videók.
@ -183,6 +184,7 @@ User Playlists:
Kattints ide a visszavonáshoz
Reverted to use {oldPlaylistName} for quick bookmark: Visszaállítva a(z) {oldPlaylistName}
használatára a gyors könyvjelzőhöz
Search for Videos: Videók keresése
Are you sure you want to delete this playlist? This cannot be undone: Biztos, hogy
törölni szeretné ezt a lejátszási listát? Ezt nem lehet visszacsinálni.
Sort By:
@ -534,14 +536,14 @@ Settings:
Hide Playlists: Lejátszási listák elrejtése
Hide Video Description: Videó leírásának elrejtése
Hide Comments: Megjegyzések elrejtése
Hide Live Streams: Élő adatfolyamok elrejtése
Hide Live Streams: Élő közvetítések elrejtése
Hide Sharing Actions: Megosztási műveletek elrejtése
Hide Chapters: Fejezetek elrejtése
Hide Upcoming Premieres: Közelgő első előadások elrejtése
Hide Channels: Videók elrejtése a csatornákból
Hide Channels Placeholder: Csatornaazonosító
Display Titles Without Excessive Capitalisation: Címek megjelenítése túlzott nagybetűk
nélkül
Display Titles Without Excessive Capitalisation: Jelenítse meg a címeket túlzott
nagybetűs írás és írásjelek nélkül
Hide Featured Channels: Kiemelt csatornák elrejtése
Hide Channel Playlists: Csatorna lejátszási listák elrejtése
Hide Channel Community: Csatornaközösség elrejtése
@ -953,6 +955,7 @@ Video:
Pause on Current Video: Jelenlegi videó szüneteltetése
Unhide Channel: Csatorna megjelenítése
Hide Channel: Csatorna elrejtése
More Options: További beállítások
Videos:
#& Sort By
Sort By:
@ -1037,7 +1040,7 @@ Up Next: 'Következő'
Local API Error (Click to copy): 'Helyi-API hiba (kattintson a másoláshoz)'
Invidious API Error (Click to copy): 'Invidious-API hiba (Kattintson a másoláshoz)'
Falling back to Invidious API: 'Invidious-API visszatérve'
Falling back to the local API: 'Helyi-API visszatérve'
Falling back to Local API: 'Helyi-API visszatérve'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Ez
a videó hiányzó formátumok miatt nem érhető el. Ez az ország nem elérhetősége miatt
következhet be.'
@ -1089,10 +1092,10 @@ Tooltips:
videókat szolgáltasson, ahelyett, hogy közvetlen kapcsolatot létesítene a YouTube
szolgáltatással. Felülbírálja az API beállítást.
Force Local Backend for Legacy Formats: Csak akkor működik, ha az Invidious API
az alapértelmezett. Ha engedélyezve van, a helyi API futni fog, és az általa
visszaadott örökölt formátumokat fogja használni az Invidious által visszaadottak
helyett. Segít, ha az Invidious által visszaküldött videókat nem lehet lejátszani
az ország korlátozása miatt.
az alapértelmezett. Ha engedélyezve van, a helyi API fut, és az általa visszaadott
régi formátumokat használja az Invidious által visszaadottak helyett. Segít,
ha az Invidious által visszaküldött videók nem játszódnak le az országos korlátozások
miatt.
Scroll Playback Rate Over Video Player: Amíg a kurzor a videó felett van, nyomja
meg és tartsa lenyomva a Control billentyűt (Mac gépen a Command billentyű),
és görgesse az egér görgőjét előre vagy hátra a lejátszási sebesség szabályozásához.
@ -1171,11 +1174,6 @@ Channels:
Unsubscribe: Leiratkozás
Unsubscribed: '{channelName} eltávolítva az feliratkozásáiból'
Unsubscribe Prompt: Biztosan le szeretne iratkozni a(z) „{channelName}” csatornáról?
Age Restricted:
Type:
Video: Videó
Channel: Csatorna
This {videoOrPlaylist} is age restricted: A(z) {videoOrPlaylist} korhatáros
Downloading failed: Hiba történt a(z) „{videoTitle}” letöltése során
Starting download: „{videoTitle}” letöltésének indítása
Downloading has completed: A(z) „{videoTitle}” letöltése befejeződött
@ -1208,3 +1206,7 @@ Trimmed input must be at least N characters long: A vágott bemenetnek legalább
hosszúnak kell lennie | A vágott bemenetnek legalább {length} karakter hosszúnak
kell lennie
Tag already exists: '„{tagName}” címke már létezik'
Close Banner: Banner bezárása
Age Restricted:
This channel is age restricted: Ez a csatorna korhatáros
This video is age restricted: Ez a videó korhatáros

View File

@ -753,7 +753,7 @@ Up Next: 'Akan Datang'
Local API Error (Click to copy): 'API Lokal Galat (Klik untuk menyalin)'
Invidious API Error (Click to copy): 'API Invidious Galat (Klik untuk menyalin)'
Falling back to Invidious API: 'Kembali ke API Invidious'
Falling back to the local API: 'Kembali ke API lokal'
Falling back to Local API: 'Kembali ke API lokal'
Subscriptions have not yet been implemented: 'Langganan masih belum diterapkan'
Loop is now disabled: 'Putar-Ulang sekarang dimatikan'
Loop is now enabled: 'Putar-Ulang sekarang diaktifkan'

View File

@ -44,6 +44,8 @@ Global:
Subscriber Count: 1 áskrifandi | {count} áskrifendur
View Count: 1 áhorf | {count} áhorf
Watching Count: 1 að horfa | {count} að horfa
Input Tags:
Length Requirement: Merki þarf að vera a.m.k. {number} stafa langt
Version {versionNumber} is now available! Click for more details: 'Útgáfa {versionNumber}
er tiltæk! Smelltu til að skoða nánar'
Download From Site: 'Sækja af vefsvæði'
@ -174,6 +176,14 @@ User Playlists:
Some videos in the playlist are not loaded yet. Click here to copy anyway.: Sum
myndskeið í spilunarlistanum hafa ekki enn hlaðist inn. Smelltu hér til að
afrita samt.
This playlist is now used for quick bookmark: Þessi spilunarlisti er núna notaður
undir flýtibókamerki
Quick bookmark disabled: Flýtibókamerki óvirk
This playlist is now used for quick bookmark instead of {oldPlaylistName}. Click here to undo: Þessi
spilunarlisti er núna notaður undir flýtibókamerki í stað {oldPlaylistName}.
Smelltu hér til að afturkalla
Reverted to use {oldPlaylistName} for quick bookmark: Snéri aftur í að nota
{oldPlaylistName} undir flýtibókamerki
AddVideoPrompt:
N playlists selected: '{playlistCount} valin'
Search in Playlists: Leita í spilunarlistum
@ -187,6 +197,7 @@ User Playlists:
| {videoCount} myndskeiðum bætt við 1 spilunarlista
Select a playlist to add your N videos to: Veldu spilunarlista til að bæta myndskeiðinu
þínu á | Veldu spilunarlista til að bæta {videoCount}̣ myndskeiðunum þínum á
Added {count} Times: Bætt við {count} sinni | Bætt við {count} sinnum
CreatePlaylistPrompt:
Create: Búa til
New Playlist Name: Heiti á nýjum spilunarlista
@ -209,6 +220,10 @@ User Playlists:
Delete Playlist: Eyða spilunarlista
Are you sure you want to delete this playlist? This cannot be undone: Ertu viss
um að þú viljir eyða þessum spilunarlista? Aðgerðin er ekki afturkallanleg.
Add to Favorites: Bæta á {playlistName}
Remove from Favorites: Fjarlægja af {playlistName}
Enable Quick Bookmark With This Playlist: Virkja flýtibókamerki með þessum spilunarlista
Disable Quick Bookmark: Eyða flýtibókamerki
History:
# On History Page
History: 'Áhorf'
@ -283,6 +298,7 @@ Settings:
Catppuccin Mocha: Catppuccin Mocha
Pastel Pink: Pastelbleikt
Hot Pink: Dimmbleikt
Nordic: Norrænt
Main Color Theme:
Main Color Theme: 'Aðallitur þema'
Red: 'Rautt'
@ -436,6 +452,7 @@ Settings:
Hide Channels: Fela myndskeið úr rásum
Hide Channels Placeholder: Auðkenni rásar
Display Titles Without Excessive Capitalisation: Birta titla án umfram-hástafa
og greinarmerkja
Sections:
Side Bar: Hliðarspjald
Channel Page: Rásasíða
@ -461,6 +478,9 @@ Settings:
Hide Channels Already Exists: Auðkenni rásar er þegar til
Hide Channels API Error: Villa við að ná í notanda með uppgefið auðkenni. Athugaðu
aftur hvort auðkennið ré rétt.
Hide Videos and Playlists Containing Text: Fela myndskeið og spilunarlista sem
innihalda texta
Hide Videos and Playlists Containing Text Placeholder: Orð, orðhluti eða setning
Data Settings:
Data Settings: 'Stillingar gagna'
Select Import Type: 'Veldu tegund innflutnings'
@ -721,6 +741,7 @@ Channel:
Reveal Answers: Birta svör
Hide Answers: Fela svör
votes: '{votes} atkvæði'
Video hidden by FreeTube: Myndskeið falið af FreeTube
Shorts:
This channel does not currently have any shorts: Þessi rás er í augnablikinu ekki
með neinar stuttmyndir
@ -878,6 +899,7 @@ Video:
Pause on Current Video: Setja núverandi myndskeið í bið
Unhide Channel: Birta rás
Hide Channel: Fela rás
More Options: Fleiri valkostir
Videos:
#& Sort By
Sort By:
@ -1043,7 +1065,7 @@ Local API Error (Click to copy): 'Villa í staðværu API-kerfisviðmóti (smell
Invidious API Error (Click to copy): 'Villa í Invidious API-kerfisviðmóti (smella
til að afrita)'
Falling back to Invidious API: 'Nota til vara Invidious API-kerfisviðmót'
Falling back to the local API: 'Nota til vara staðvært API-kerfisviðmót'
Falling back to Local API: 'Nota til vara staðvært API-kerfisviðmót'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Þetta
myndskeiðer ekki tiltækt vegna þess að það vantar skráasnið. Þetta getur gest ef
þau eru ekki tiltæk í viðkomandi landi.'
@ -1084,11 +1106,6 @@ Starting download: Byrja að sækja "{videoTitle}"
Downloading failed: Vandamál kom upp við að sækja "{videoTitle}"
Screenshot Error: Skjámyndataka mistókst. {error}
Screenshot Success: Vistaði skjámynd sem "{filePath}"
Age Restricted:
Type:
Channel: Rás
Video: Myndskeið
This {videoOrPlaylist} is age restricted: Þetta {videoOrPlaylist} er með aldurstakmörkunum
New Window: Nýr gluggi
Channels:
Search bar placeholder: Leita í rásum
@ -1122,3 +1139,8 @@ Playlist will not pause when current video is finished: Spilunarlisti mun ekki f
Go to page: Fara á {page}
Channel Hidden: '{channel} bætt við rásasíu'
Channel Unhidden: '{channel} fjarlægt úr rásasíu'
Close Banner: Loka borða
Age Restricted:
This video is age restricted: Þetta myndskeið er með aldurstakmörkunum
This channel is age restricted: Þessi rás er með aldurstakmörkunum
Tag already exists: '"{tagName}" merkið er þegar til staðar'

View File

@ -143,6 +143,7 @@ User Playlists:
Select a playlist to add your N videos to: Seleziona una playlist a cui aggiungere
il tuo video | Seleziona una playlist a cui aggiungere i tuoi {videoCount} video
N playlists selected: '{playlistCount} selezionate'
Added {count} Times: Aggiunto {count} volta | Aggiunti {count} volte
SinglePlaylistView:
Toast:
There were no videos to remove.: Non c'erano video da rimuovere.
@ -175,6 +176,7 @@ User Playlists:
This playlist is now used for quick bookmark instead of {oldPlaylistName}. Click here to undo: Questa
playlist è ora usata per i segnalibri rapidi al posto di {oldPlaylistName}.
Fai clic qui per annullare
Search for Videos: Cerca video
Are you sure you want to delete this playlist? This cannot be undone: Sei sicuro
di voler eliminare questa playlist? Questa operazione non può essere annullata.
Sort By:
@ -537,8 +539,8 @@ Settings:
Hide Upcoming Premieres: Nascondi le prossime Première
Hide Channels: Nascondi i video dai canali
Hide Channels Placeholder: ID del canale
Display Titles Without Excessive Capitalisation: Visualizza i titoli senza un
uso eccessivo di maiuscole
Display Titles Without Excessive Capitalisation: Visualizza i titoli senza maiuscole
e punteggiatura eccessive
Hide Featured Channels: Nascondi i canali in evidenza
Hide Channel Playlists: Nascondi le playlist del canale
Hide Channel Community: Nascondi la comunità del canale
@ -914,6 +916,7 @@ Video:
Pause on Current Video: Pausa sul video attuale
Unhide Channel: Mostra canale
Hide Channel: Nascondi canale
More Options: Più opzioni
Videos:
#& Sort By
Sort By:
@ -997,7 +1000,7 @@ Up Next: 'Prossimi video'
Local API Error (Click to copy): 'Errore API Locale (Clicca per copiare)'
Invidious API Error (Click to copy): 'Errore API Invidious (Clicca per copiare)'
Falling back to Invidious API: 'Torno alle API Invidious'
Falling back to the local API: 'Torno alle API locali'
Falling back to Local API: 'Torno alle API locali'
Subscriptions have not yet been implemented: 'Le Iscrizioni non sono ancora state
implementate'
Loop is now disabled: 'Il loop è ora disabilitato'
@ -1178,13 +1181,6 @@ Starting download: Avvio del download di "{videoTitle}"
Downloading failed: Si è verificato un problema durante il download di "{videoTitle}"
Screenshot Success: Screenshot salvato come "{filePath}"
Screenshot Error: Screenshot non riuscito. {error}
Age Restricted:
The currently set default instance is {instance}: Questo {instance} è limitato dall'età
Type:
Channel: Canale
Video: Video
This {videoOrPlaylist} is age restricted: Questo {videoOrPlaylist} ha limiti di
età
New Window: Nuova finestra
Channels:
Unsubscribed: '{channelName} è stato rimosso dalle tue iscrizioni'
@ -1221,3 +1217,7 @@ Channel Unhidden: '{channel} rimosso dal filtro canali'
Tag already exists: Il tag "{tagName}" esiste già
Trimmed input must be at least N characters long: L'input troncato deve essere lungo
almeno 1 carattere | L'input troncato deve essere lungo almeno {length} caratteri
Age Restricted:
This video is age restricted: Questo video è soggetto a limiti di età
This channel is age restricted: Questo canale è soggetto a limiti di età
Close Banner: Chiudi banner

View File

@ -114,6 +114,10 @@ User Playlists:
このページは、完全に動作する動画リストではありません。保存またはお気に入りと設定した動画のみが表示されます。操作が完了すると、現在ここにあるすべての動画は「お気に入り」の動画リストに移動します。
Search bar placeholder: 動画リスト内の検索
Empty Search Message: この再生リストに、検索に一致する動画はありません
This playlist currently has no videos.: 存在、この再生リストには動画があっていません。
Create New Playlist: 新規再生リストを作られる
Sort By:
NameAscending: A-Z
History:
# On History Page
History: '履歴'
@ -276,7 +280,7 @@ Settings:
Folder Button: フォルダーの選択
Enter Fullscreen on Display Rotate: 横画面時にフルスクリーンにする
Skip by Scrolling Over Video Player: 動画プレーヤーでスクロールしてスキップ可能にする
Allow DASH AV1 formats: DASH AV1形式を許可する
Allow DASH AV1 formats: DASH AV1形式を許可
Comment Auto Load:
Comment Auto Load: コメント自動読み込み
Subscription Settings:
@ -794,7 +798,7 @@ Up Next: '次の動画'
Local API Error (Click to copy): '内部 API エラー(クリックするとコピー)'
Invidious API Error (Click to copy): 'Invidious API エラー(クリックするとコピー)'
Falling back to Invidious API: '代替の Invidious API に切替'
Falling back to the local API: '代替の内部 API に切替'
Falling back to Local API: '代替の内部 API に切替'
Subscriptions have not yet been implemented: '登録チャンネルは未実装です'
Loop is now disabled: 'ループ再生を無効にしました'
Loop is now enabled: 'ループ再生を有効にしました'
@ -850,7 +854,7 @@ The playlist has been reversed: 再生リストを逆順にしました
A new blog is now available, {blogTitle}. Click to view more: '新着ブログ公開、{blogTitle}。クリックしてブログを読む'
Download From Site: サイトからダウンロード
Version {versionNumber} is now available! Click for more details: 最新バージョン {versionNumber}
配信中! 詳細はクリックして確認してください
配信中!詳細はクリックして確認してください
This video is unavailable because of missing formats. This can happen due to country unavailability.: この動画は、動画形式の情報が利用できないため再生できません。再生が許可されていない国で発生します。
Tooltips:
Subscription Settings:
@ -866,8 +870,8 @@ Tooltips:
Scroll Playback Rate Over Video Player: カーソルが動画上にあるとき、Ctrl キーMac では Command キーを押したまま、マウスホイールを前後にスクロールして再生速度を調整します。Control
キーMac では Command キー)を押したままマウスを左クリックすると、すぐにデフォルトの再生速度(設定を変更していない場合は 1 xに戻ります。
Skip by Scrolling Over Video Player: スクロール ホイールを使用して、ビデオ、MPV スタイルをスキップします。
Allow DASH AV1 formats: DASH H.264形式よりDASH AV1形式の方がきれいに見える可能性があるけど、再生には必要な電力がより多い。全ての動画でDASH
AV1を利用できないため、プレイヤーはDASH H.264形式に自動変更する場合があります。
Allow DASH AV1 formats: DASH H.264形式よりDASH AV1形式の方がきれいに見える可能性がありますが、再生にはより多くの処理能力が必要となります。DASH
AV1形式を使用できない場合、プレイヤーはDASH H.264形式を自動で使用します。
General Settings:
Invidious Instance: FreeTube が使用する Invidious API の接続先サーバーです。
Preferred API Backend: FreeTube が youtube からデータを取得する方法を選択します。「内部 API」とはアプリから取得する方法です。「Invidious
@ -913,12 +917,6 @@ Are you sure you want to open this link?: このリンクを開きますか?
Starting download: '"{videoTitle}" のダウンロードを開始します'
Downloading has completed: '"{videoTitle}" のダウンロードが終了しました'
Downloading failed: '"{videoTitle}" のダウンロード中に問題が発生しました'
Age Restricted:
The currently set default instance is {instance}: '{instance} は 18 歳以上の視聴者向け動画です'
Type:
Channel: チャンネル
Video: 動画
This {videoOrPlaylist} is age restricted: この {videoOrPlaylist} は年齢制限があります
Channels:
Channels: チャンネル
Unsubscribe: 登録解除
@ -947,3 +945,5 @@ Hashtag:
This hashtag does not currently have any videos: このハッシュタグには現在動画がありません
Playlist will pause when current video is finished: 現在のビデオが終了すると、プレイリストは停止します
Playlist will not pause when current video is finished: 現在のビデオが終了しても、プレイリストは停止しません
Close Banner: バナーを閉じる
Go to page: '{page}に行く'

View File

@ -761,7 +761,7 @@ Tooltips:
Local API Error (Click to copy): '로컬 API 오류(복사하려면 클릭)'
Invidious API Error (Click to copy): 'Invidious API 오류(복사하려면 클릭)'
Falling back to Invidious API: 'Invidious API로 대체'
Falling back to the local API: '로컬 API로 대체'
Falling back to Local API: '로컬 API로 대체'
This video is unavailable because of missing formats. This can happen due to country unavailability.: '이
동영상은 형식이 누락되어 사용할 수 없습니다. 이는 국가를 사용할 수 없기 때문에 발생할 수 있습니다.'
Subscriptions have not yet been implemented: '구독이 아직 구현되지 않았습니다'
@ -804,11 +804,6 @@ Channels:
Unsubscribe Prompt: '"{channelName}"에서 구독을 취소하시겠습니까?'
Count: '{number} 채널이 발견되었습니다.'
Unsubscribed: '{channelName} 구독에서 제거되었습니다'
Age Restricted:
Type:
Video: 비디오
Channel: 채널
The currently set default instance is {instance}: 이 {instance}는 연령 제한입니다
Downloading has completed: '"{videoTitle}" 다운로드가 완료되었습니다'
Starting download: '"{videoTitle}" 다운로드를 시작하는 중'
Downloading failed: '"{videoTitle}"를 다운로드하는 동안 문제가 발생했습니다'

View File

@ -41,6 +41,9 @@ Global:
Counts:
Subscriber Count: 1 prenumeruoti | {count} prenumeratorių
Channel Count: 1 kanalas | {count} kanalai
Video Count: 1 vaizdo įrašas | {count} vaizdo įrašai
View Count: 1 peržiūrėti | {count} peržiūrų
Watching Count: 1 žiūri | {count} žiūri
Version {versionNumber} is now available! Click for more details: 'Versija {versionNumber}
jau prieinama! Spustelėkite, jei norite gauti daugiau informacijos'
Download From Site: 'Atsisiųsti iš svetainės'
@ -842,7 +845,7 @@ Local API Error (Click to copy): 'Vietinė API klaida (spustelėkite, jei norite
Invidious API Error (Click to copy): 'Invidious API klaida (spustelėkite, jei norite
kopijuoti)'
Falling back to Invidious API: 'Grįžtama prie Invidious API'
Falling back to the local API: 'Grįžtama prie vietinio API'
Falling back to Local API: 'Grįžtama prie vietinio API'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Šis
vaizdo įrašas nepasiekiamas, nes trūksta formatų. Tai gali nutikti dėl to, kad šalis
yra nepasiekiama.'
@ -887,12 +890,6 @@ Channels:
Unsubscribe: Atšaukti prenumeratą
Unsubscribed: '{channelName} buvo pašalintas iš jūsų prenumeratų'
Unsubscribe Prompt: Ar tikrai norite atšaukti {channelName} prenumeratą?
Age Restricted:
Type:
Channel: Kanalas
Video: Vaizdo įrašas
This {videoOrPlaylist} is age restricted: Šis {videoOrPlaylist} ribojamas pagal
amžių
Downloading has completed: „{videoTitle}“ atsisiuntimas baigtas
Starting download: Pradedamas „{videoTitle}“ atsisiuntimas
Downloading failed: Atsisiunčiant „{videoTitle}“ kilo problema
@ -910,3 +907,4 @@ Clipboard:
be saugaus ryšio
Preferences: Nuostatos
Go to page: Eiti į {page}
Close Banner: Uždaryti baneris

View File

@ -828,7 +828,7 @@ Tooltips:
Local API Error (Click to copy): ''
Invidious API Error (Click to copy): ''
Falling back to Invidious API: ''
Falling back to the local API: ''
Falling back to Local API: ''
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
Subscriptions have not yet been implemented: ''
Unknown YouTube url type, cannot be opened in app: ''
@ -848,11 +848,6 @@ Canceled next video autoplay: ''
Default Invidious instance has been set to {instance}: ''
Default Invidious instance has been cleared: ''
'The playlist has ended. Enable loop to continue playing': ''
Age Restricted:
This {videoOrPlaylist} is age restricted: ''
Type:
Channel: ''
Video: ''
External link opening has been disabled in the general settings: ''
Downloading has completed: ''
Starting download: ''

View File

@ -784,7 +784,7 @@ Up Next: 'Neste'
Local API Error (Click to copy): 'Lokal API-feil (Klikk her for å kopiere)'
Invidious API Error (Click to copy): 'Invidious-API-feil (Klikk her for å kopiere)'
Falling back to Invidious API: 'Faller tilbake til Invidious-API-et'
Falling back to the local API: 'Faller tilbake til det lokale API-et'
Falling back to Local API: 'Faller tilbake til det lokale API-et'
Subscriptions have not yet been implemented: 'Abonnement har ikke blitt implementert
enda'
Loop is now disabled: 'Gjenta er nå deaktivert'
@ -947,11 +947,6 @@ Channels:
Unsubscribe: Opphev abonnement
Unsubscribed: '{channelName} ble fjernet fra dine abonnementer'
Unsubscribe Prompt: Opphev abonnement på «{channelName}»?
Age Restricted:
Type:
Channel: Kanal
Video: Video
This {videoOrPlaylist} is age restricted: Denne {videoOrPlaylist} er aldersbegrenset
Chapters:
Chapters: Kapitler
'Chapters list visible, current chapter: {chapterName}': 'Kapittelliste synlig.

View File

@ -45,6 +45,8 @@ Global:
Watching Count: 1 aan het kijken | {count} aan het kijken
Channel Count: 1 kanaal | {count} kanalen
Community: Gemeenschap
Input Tags:
Length Requirement: Tag moet minstens {number} tekens lang zijn
Search / Go to URL: 'Zoeken / Ga naar URL'
# In Filter Button
Search Filters:
@ -143,10 +145,28 @@ User Playlists:
CreatePlaylistPrompt:
Create: Aanmaken
New Playlist Name: Naam voor nieuwe afspeel­lijst
Toast:
Playlist {playlistName} has been successfully created.: Afspeel­lijst {playlistName}
is succes­vol aan­gemaakt.
There was an issue with creating the playlist.: Er is een probleem opgetreden
bij het maken van de afspeel­lijst.
There is already a playlist with this name. Please pick a different name.: Er
is al een afspeel­lijst met deze naam. Kies een andere naam.
AddVideoPrompt:
Save: Opslaan
N playlists selected: '{playlistCount} geselecteerd'
Search in Playlists: Zoeken in afspeel­lijsten
Toast:
You haven't selected any playlist yet.: U heeft nog geen afspeel­lijst geselecteerd.
"{videoCount} video(s) added to 1 playlist": 1 video toegevoegd aan een afspeellijst
| {videoCount} video's toegevoegd aan een afspeellijst
"{videoCount} video(s) added to {playlistCount} playlists": 1 video toe­gevoegd
aan {playlistCount} afspeel­lijsten | {videoCount} video's toe­gevoegd aan
{playlistCount} afspeel­lijsten
Select a playlist to add your N videos to: Selecteer een afspeellijst om uw video
aan toe te voegen | Selecteer een afspeellijst om uw {videoCount} video's aan
toe te voegen
Added {count} Times: '{count} keer toe­gevoegd | {count} keer toe­gevoegd'
Save Changes: Wijzigingen opslaan
Copy Playlist: Afspeel­lijst kopiëren
Create New Playlist: Nieuwe afspeel­lijst aanmaken
@ -164,6 +184,41 @@ User Playlists:
Video has been removed: Video is verwijderd
Quick bookmark disabled: Snelle bladwijzers uitgeschakeld
Playlist has been updated.: De afspeel­lijst is bijgewerkt.
This video cannot be moved up.: Deze video kan niet omhoog verplaatst worden.
This video cannot be moved down.: Deze video kan niet omlaag verplaatst worden.
Playlist {playlistName} has been deleted.: Afspeel­lijst {playlistName} is
verwijderd.
This playlist does not exist: Deze afspeel­lijst bestaat niet
There were no videos to remove.: Er zijn geen video's om te verwijderen.
There was a problem with removing this video: Er is een probleem opgetreden
bij het verwijderen van deze video
This playlist is now used for quick bookmark: Deze afspeel­lijst wordt nu gebruikt
voor snelle blad­wijzers
This playlist is now used for quick bookmark instead of {oldPlaylistName}. Click here to undo: Deze
afspeellijst wordt nu gebruikt voor snelle bladwijzers in plaats van {oldPlaylistName}.
Druk hier om ongedaan te maken
Reverted to use {oldPlaylistName} for quick bookmark: Terug­gekeerd naar het
gebruik van {oldPlaylistName} voor snelle blad­wijzers
Some videos in the playlist are not loaded yet. Click here to copy anyway.: Sommige
video's in de afspeel­lijst zijn nog niet geladen. Druk hier om toch te kopiëren.
"{videoCount} video(s) have been removed": 1 video verwijderd | {videoCount}
video's verwijderd
This playlist is protected and cannot be removed.: Deze afspeel­lijst is beschermd
en kan niet worden verwijderd.
Playlist name cannot be empty. Please input a name.: De naam van de afspeel­lijst
mag niet leeg zijn. Voer een naam in.
There was an issue with updating this playlist.: Er is een probleem opgetreden
bij het bij­werken van deze afspeel­lijst.
You have no playlists. Click on the create new playlist button to create a new one.: U
heeft geen afspeellijsten. Druk op de knop om er één aan te maken.
This playlist currently has no videos.: Deze afspeel­lijst bevat geen video's.
Enable Quick Bookmark With This Playlist: Snelle blad­wijzers inschakelen voor deze
afspeel­lijst
Are you sure you want to remove all watched videos from this playlist? This cannot be undone: Weet
u zeker dat u alle bekeken video's uit deze afspeel­lijst wilt verwijderen? Dit
kan niet ongedaan gemaakt worden.
Are you sure you want to delete this playlist? This cannot be undone: Weet u zeker
dat u deze afspeel­lijst wilt verwijderen? Dit kan niet ongedaan gemaakt worden.
History:
# On History Page
History: 'Geschiedenis'
@ -358,12 +413,17 @@ Settings:
Save Watched Videos With Last Viewed Playlist: Houd bekeken video's bij met de
afspeellijst Laatst bekeken
Remove All Playlists: Alle afspeel­lijsten verwijderen
All playlists have been removed: Alle afspeel­lijsten zijn verwijderd
Are you sure you want to remove all your playlists?: Weet u zeker dat u al uw
afspeel­lijsten wilt verwijderen?
Subscription Settings:
Subscription Settings: 'Abonnement­instellingen'
Hide Videos on Watch: 'Bekeken video''s verbergen'
Manage Subscriptions: 'Abonnementen beheren'
Fetch Feeds from RSS: Verzamel feeds via RSS
Fetch Automatically: Haal feed automatisch op
Only Show Latest Video for Each Channel: Alleen nieuwste video voor elk kanaal
tonen
Advanced Settings:
Advanced Settings: 'Geavanceerde Instellingen'
Enable Debug Mode (Prints data to the console): 'Schakel Debug Modus in (Print
@ -440,6 +500,14 @@ Settings:
Subscription File: Abonnementenbestand
History File: Geschiedenisbestand
Playlist File: Afspeellijstbestand
Export Playlists For Older FreeTube Versions:
Label: Afspeel­lijsten exporteren voor oudere FreeTube-versies
Tooltip: "Deze optie exporteert video's van alle afspeel­lijsten naar één afspeel­lijst
met de naam Favorieten.\nVideo's exporteren en importeren in afspeel­lijsten
voor een oudere versie van FreeTube:\n1. Exporteer uw afspeel­lijsten met
deze optie ingeschakeld.\n2. Verwijder al uw bestaande afspeel­lijsten met
de optie Alle afspeel­lijsten verwijderen onder Privacy­instellingen.\n
3. Start de oudere versie van FreeTube en importeer de geëxporteerde afspeel­lijsten."
Distraction Free Settings:
Hide Live Chat: Livechat verbergen
Hide Popular Videos: Populaire video's verbergen
@ -456,8 +524,8 @@ Settings:
Hide Video Description: Video-omschrijving verbergen
Hide Comments: Opmerkingen verbergen
Hide Live Streams: Verberg rechtstreekse uitzendingen
Display Titles Without Excessive Capitalisation: Toon titels zonder overmatig
hoofdlettergebruik
Display Titles Without Excessive Capitalisation: Titels tonen zonder overmatig
hoofdletter­gebruik en inter­punctie
Sections:
Side Bar: Zijbalk
General: Algemeen
@ -481,6 +549,16 @@ Settings:
Hide Profile Pictures in Comments: Profielfoto's in opmerkingen verbergen
Hide Subscriptions Community: Abonnement­gemeenschappen verbergen
Hide Channels Already Exists: Kanaal ID bestaat reeds
Hide Channels Invalid: Opgegeven kanaal-id is ongeldig
Hide Videos and Playlists Containing Text Placeholder: Woord, woord­fragment of
zin
Hide Videos and Playlists Containing Text: Video's en afspeel­lijsten die tekst
bevatten verbergen
Hide Channels API Error: Fout bij het ophalen van de gebruiker met de opgegeven
ID. Controleer nog­maals of de ID correct is.
Hide Channels Disabled Message: Sommige kanalen zijn geblokkeerd met behulp van
ID en zijn niet verwerkt. De functie is geblokkeerd terwijl deze ID's worden
bij­gewerkt
The app needs to restart for changes to take effect. Restart and apply change?: De
app moet opnieuw worden gestart om veranderingen aan te brengen. Wilt u de app
opnieuw starten en veranderingen toepassen?
@ -515,6 +593,9 @@ Settings:
Do Nothing: Niets doen
Category Color: Categorie­kleur
UseDeArrowTitles: DeArrow-videotitels gebruiken
UseDeArrowThumbnails: DeArrow gebruiken voor miniaturen
'DeArrow Thumbnail Generator API Url (Default is https://dearrow-thumb.ajay.app)': API-URL
van DeArrow-miniatuur­generator (standaard is https://dearrow-thumb.ajay.app)
External Player Settings:
Custom External Player Arguments: Aangepaste argumenten voor externe videospeler
Custom External Player Executable: Uitvoerbaar bestand van externe videospeler
@ -668,6 +749,7 @@ Channel:
votes: '{votes} stemmen'
This channel currently does not have any posts: Dit kanaal heeft momenteel geen
posts
Video hidden by FreeTube: Video verborgen door FreeTube
Releases:
Releases: Uitgaven
This channel does not currently have any releases: Dit kanaal heeft momenteel
@ -821,6 +903,7 @@ Video:
is niet beschikbaar voor deze stream. Mogelijk is deze uitgeschakeld door de uploader.
Hide Channel: Kanaal verbergen
Unhide Channel: Kanaal tonen
More Options: Meer opties
Videos:
#& Sort By
Sort By:
@ -904,7 +987,7 @@ Up Next: 'Volgende'
Local API Error (Click to copy): 'Fout in lokale API (Klik om te kopiëren)'
Invidious API Error (Click to copy): 'Fout in API van Invidious (Klik op te kopiëren)'
Falling back to Invidious API: 'Terugvallen op Invidious API'
Falling back to the local API: 'Terugvallen op lokale API'
Falling back to Local API: 'Terugvallen op lokale API'
Subscriptions have not yet been implemented: 'Abonnementen zijn nog niet geïmplementeerd'
Loop is now disabled: 'Herhalen is nu uitgeschakeld'
Loop is now enabled: 'Herhalen is nu ingeschakeld'
@ -983,10 +1066,10 @@ Tooltips:
Legacy gaat niet hoger dan 720p maar gebruikt minder bandbreedte. Audio zal
alleen het geluid streamen.
Force Local Backend for Legacy Formats: Dit zal alleen werken wanneer Invidious
is geselecteerd als de standaard API. Wanneer ingeschakeld zal de lokale API
legacy video indelingen gebruiken in plaats van de video indeling die worden
teruggegeven door Invidious. Dit kan helpen wanneer een video die wordt gestreamed
via Invidious niet afspeelt in verband met regio restricties.
is geselecteerd als de standaard-API. Wanneer ingeschakeld zal de lokale API
legacy video­indelingen gebruiken in plaats van de video­indeling die worden
terug­gegeven door Invidious. Dit kan helpen wanneer een video die wordt gestreamed
via Invidious niet afspeelt in verband met regio­restricties.
Proxy Videos Through Invidious: FreeTube zal verbinden met Invidious en daar de
video's downloaden in de plaats van de video's rechtstreeks bij YouTube vandaan
te halen. Dit overschrijft de ingestelde API voorkeur.
@ -1041,16 +1124,23 @@ Tooltips:
in de gekozen externe videospeler kan worden geopend. Let op: Invidious-instellingen
beïnvloeden externe videospelers niet.'
DefaultCustomArgumentsTemplate: "(standaard: {defaultCustomArguments})"
Ignore Default Arguments: Stuurt geen standaard­argumenten naar de externe speler,
afgezien van de video-URL (bij­voorbeeld afspeel­snelheid, afspeellijst-URL,
enz.). Aan­gepaste argumenten worden nog steeds door­gegeven.
Distraction Free Settings:
Hide Channels: Voer een kanaalnaam of kanaal-ID in om alle video's, afspeellijsten
en het kanaal zelf te verbergen zodat ze niet worden weergegeven in zoeken,
trending, populairst en aanbevolen. De ingevoerde kanaalnaam moet volledig overeenkomen
en is hoofdlettergevoelig.
Hide Channels: Voer een kanaal-ID in om alle video's, afspeel­lijsten en het kanaal
zelf te verbergen zodat ze niet worden weer­gegeven in zoeken, trending, populairst
en aan­bevolen. De ingevoerde kanaal-ID moet volledig overeen­komen en is hoofdletter­gevoelig.
Hide Subscriptions Live: Deze instelling wordt overschreven door de app-brede
instelling {appWideSetting}, in het gedeelte {subsection} van {settingsSection}
Hide Videos and Playlists Containing Text: Voer een woord, woord­fragment of woord­groep
in (niet hoofdletter­gevoelig) om alle video's en afspeel­lijsten waarvan de
oorspronkelijke titel dit bevat, in heel FreeTube te verbergen, met uit­zondering
van alleen geschiedenis, uw afspeel­lijsten en video's in afspeel­lijsten.
SponsorBlock Settings:
UseDeArrowTitles: Vervangt videotitels met door gebruikers ingediende titels van
DeArrow.
UseDeArrowThumbnails: Video­miniaturen vervangen met miniaturen van DeArrow.
Experimental Settings:
Replace HTTP Cache: Schakelt de schijfgebaseerde HTTP-cache van Electron uit en
schakelt een aangepaste afbeeldings­cache in het geheugen in. Zal leiden tot
@ -1079,12 +1169,6 @@ Downloading failed: Probleem bij download van "{videoTitle}"
Download folder does not exist: De download map "$" bestaat niet. Valt terug op "vraag
map" modus.
New Window: Nieuw venster
Age Restricted:
The currently set default instance is {instance}: Deze {instance} is leeftijdsbeperkt
Type:
Channel: Kanaal
Video: Video
This {videoOrPlaylist} is age restricted: Deze {videoOrPlaylist} heeft een leeftijdsbeperking
Screenshot Success: Schermafbeelding opgeslagen als "{filePath}"
Channels:
Title: Kanaal­lijst
@ -1117,3 +1201,12 @@ Playlist will pause when current video is finished: Afspeellijst zal pauzeren wa
Playlist will not pause when current video is finished: Afspeellijst zal niet pauzeren
wanneer de huidige video is afgelopen
Go to page: Ga naar {page}
Tag already exists: Tag {tagName} bestaat al
Channel Unhidden: {channel} verwijderd uit kanaal­filter
Channel Hidden: {channel} toe­gevoegd aan kanaal­filter
Close Banner: Banier sluiten
Age Restricted:
This channel is age restricted: Dit kanaal heeft een leeftijds­beperking
This video is age restricted: Deze video heeft een leeftijds­beperking
Trimmed input must be at least N characters long: Bij­gesneden invoer moet minimaal
1 teken lang zijn | Bij­gesneden invoer moet minimaal {length} tekens lang zijn

View File

@ -770,9 +770,9 @@ Tooltips:
Invidious Instance: 'Invidious-førekomsten som FreeTube vil kople til for API-kall.'
Region for Trending: 'Trendsregionen lar deg enkelt velje kva lands populære videoar
du ynskjer å vise.'
External Link Handling: "Vel kva FreeTube skal gjer, når ein trykker på ei lenke,\
\ som ikkje kan bli opna av FreeTube. \nFreeTube vil vanlegvis opne lenka i\
\ din standardnettlesar.\n"
External Link Handling: "Vel kva FreeTube skal gjer, når ein trykker på ei lenke,
som ikkje kan bli opna av FreeTube. \nFreeTube vil vanlegvis opne lenka i din
standardnettlesar.\n"
Player Settings:
Force Local Backend for Legacy Formats: 'Fungerer berre med Invidious-API-et som
standard. Når det er påslått, vil det lokale API-et køyre og bruke dei utdaterte
@ -825,7 +825,7 @@ Tooltips:
Local API Error (Click to copy): 'Lokal API-feil (Klikk her for å kopiere)'
Invidious API Error (Click to copy): 'Invidious-API-feil (Klikk her for å kopiere)'
Falling back to Invidious API: 'Faller tilbake til Invidious-API-et'
Falling back to the local API: 'Faller tilbake til det lokale API-et'
Falling back to Local API: 'Faller tilbake til det lokale API-et'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Denne
videoen er utilgjengeleg grunna manglande format. Dette kan skuldast tilgangsavgrensingar
i ditt land.'
@ -868,11 +868,6 @@ Channels:
Unsubscribe Prompt: Er du sikker på at du vil avslutte abonnementet på "{channelName}"?
Unsubscribe: Opphev abonnement
Screenshot Success: Lagra skjermbilete som "{filePath}"
Age Restricted:
This {videoOrPlaylist} is age restricted: Denne {videoOrPlaylist} er alderavgrensa
Type:
Video: Video
Channel: Kanal
Screenshot Error: Skjermbilete feila. {error}
Downloading has completed: Nedlastinga av "{videoTitle}" er fullført
Ok: OK

View File

@ -109,4 +109,3 @@ Channel:
Video:
External Player: {}
Tooltips: {}
Age Restricted: {}

View File

@ -143,6 +143,7 @@ User Playlists:
dodać swój film | Wybierz playlistę, do której chcesz dodać swoje {videoCount}
film(y/ów)
N playlists selected: Zaznaczono {playlistCount}
Added {count} Times: Dodano {count} raz | Dodano {count} razy
SinglePlaylistView:
Toast:
There were no videos to remove.: Nie było żadnych filmów do usunięcia.
@ -534,8 +535,8 @@ Settings:
Hide Upcoming Premieres: Schowaj nadchodzące premiery
Hide Channels: Schowaj filmy z kanałów
Hide Channels Placeholder: ID kanału
Display Titles Without Excessive Capitalisation: Wyświetlaj tytuły bez nadmiernych
wielkich liter
Display Titles Without Excessive Capitalisation: Wyświetlaj tytuły nie nadużywając
wielkich liter i interpunkcji
Hide Channel Community: Schowaj społeczność kanału
Hide Channel Shorts: Schowaj filmy Short kanału
Hide Featured Channels: Schowaj polecane kanały
@ -917,6 +918,7 @@ Video:
Pause on Current Video: Zatrzymaj po tym filmie
Unhide Channel: Pokaż kanał
Hide Channel: Ukryj kanał
More Options: Więcej opcji
Videos:
#& Sort By
Sort By:
@ -999,7 +1001,7 @@ Up Next: 'Następne'
Local API Error (Click to copy): 'Błąd lokalnego API (kliknij by skopiować)'
Invidious API Error (Click to copy): 'Błąd API Invidious (kliknij by skopiować)'
Falling back to Invidious API: 'Wycofywanie do API Invidious'
Falling back to the local API: 'Wycofywanie do lokalnego API'
Falling back to Local API: 'Wycofywanie do lokalnego API'
Subscriptions have not yet been implemented: 'Subskrypcje nie zostały jeszcze wprowadzone'
Loop is now disabled: 'Zapętlenie jest teraz wyłączone'
Loop is now enabled: 'Zapętlenie jest teraz włączone'
@ -1181,13 +1183,6 @@ Download folder does not exist: Katalog pobierania "$" nie istnieje. Przełączo
tryb "pytaj o folder".
Screenshot Error: Wykonanie zrzutu nie powiodło się. {error}
Screenshot Success: Zapisano zrzut ekranu jako „{filePath}”
Age Restricted:
Type:
Channel: kanał
Video: film
The currently set default instance is {instance}: Ten {instance} ma ograniczenie
wiekowe
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} ma ograniczenie wiekowe'
New Window: Nowe okno
Channels:
Title: Lista kanałów
@ -1224,3 +1219,7 @@ Channel Unhidden: '{channel} usunięty z filtra kanału'
Tag already exists: Tag „{tagName}” już istnieje
Trimmed input must be at least N characters long: Przycięte wyrażenie musi mieć przynajmniej
1 znak | Przycięte wyrażenie musi mieć przynajmniej {length} znaki/ów
Age Restricted:
This video is age restricted: Ten film ma ograniczenie wiekowe
This channel is age restricted: Ten kanał ma ograniczenie wiekowe
Close Banner: Zamknij Baner

File diff suppressed because it is too large Load Diff

View File

@ -1035,7 +1035,7 @@ Tooltips:
Local API Error (Click to copy): Erro na API local (clique para copiar)
Invidious API Error (Click to copy): Erro na API Invidious (clique para copiar)
Falling back to Invidious API: Ocorreu um erro e vamos usar a API Invidious
Falling back to the local API: Ocorreu um erro e vamos usar a API local
Falling back to Local API: Ocorreu um erro e vamos usar a API local
This video is unavailable because of missing formats. This can happen due to country unavailability.: Este
vídeo não está disponível porque faltam formatos. Isto pode acontecer devido à indisponibilidade
no seu país.
@ -1083,13 +1083,6 @@ Channels:
Unsubscribe: Anular subscrição
Unsubscribed: '{channelName} foi removido das suas subscrições'
Unsubscribe Prompt: Tem a certeza de que pretende anular a subscrição de "{channelName}"?
Age Restricted:
The currently set default instance is {instance}: Este {instance} tem restrição
de idade
Type:
Channel: Canal
Video: Vídeo
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} tem restrição de idade'
Downloading has completed: '"{videoTitle}" foi descarregado'
Starting download: A descarregar "{videoTitle}"
Downloading failed: Ocorreu um erro ao descarregar "{videoTitle}"

View File

@ -1037,7 +1037,7 @@ Up Next: 'A seguir'
Local API Error (Click to copy): 'Erro na API local (clique para copiar)'
Invidious API Error (Click to copy): 'Erro na API Invidious (clique para copiar)'
Falling back to Invidious API: 'Ocorreu um erro e vamos usar a API Invidious'
Falling back to the local API: 'Ocorreu um erro e vamos usar a API local'
Falling back to Local API: 'Ocorreu um erro e vamos usar a API local'
Subscriptions have not yet been implemented: 'As subscrições ainda não foram implementadas'
Loop is now disabled: 'Repetição desativada'
Loop is now enabled: 'Repetição ativada'
@ -1153,13 +1153,6 @@ Downloading failed: Ocorreu um erro ao descarregar "{videoTitle}"
Downloading has completed: '"{videoTitle}" foi descarregado'
Screenshot Success: Captura de ecrã guardada como "{filePath}"
Screenshot Error: Erro ao capturar o ecrã. {error}
Age Restricted:
The currently set default instance is {instance}: Este {instance} tem restrição
de idade
Type:
Channel: Canal
Video: Vídeo
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} tem restrição de idade'
New Window: Nova janela
Channels:
Count: '{number} canais encontrados.'

View File

@ -42,6 +42,8 @@ Global:
View Count: 1 vizionare | {count} vizionări
Channel Count: 1 canal | {count} canale
Watching Count: 1 se uită | {count} se uită
Input Tags:
Length Requirement: Tag-ul trebuie să aibă cel puțin {number} caractere
Version {versionNumber} is now available! Click for more details: 'Versiunea {versionNumber}
este acum disponibilă! Click pentru mai multe detalii'
Download From Site: 'Descărcați de pe site'
@ -108,6 +110,8 @@ Subscriptions:
All Subscription Tabs Hidden: Toate filele de abonament sunt ascunse. Pentru a vedea
conținutul aici, vă rugăm să afișați unele file din secțiunea "{subsection}” din
"{settingsSection}”.
Empty Posts: Canalele tale abonate nu au momentan nicio postare.
Load More Posts: Încarcă mai multe postări
Trending:
Trending: 'Tendințe'
Trending Tabs: File în tendințe
@ -853,7 +857,7 @@ Up Next: 'În continuare'
Local API Error (Click to copy): 'Eroare API locală (Faceți clic pentru a copia)'
Invidious API Error (Click to copy): 'Eroare API Invidious (Faceți clic pentru a copia)'
Falling back to Invidious API: 'Revenine la Invidious API'
Falling back to the local API: 'Revenire la API-ul local'
Falling back to Local API: 'Revenire la API-ul local'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Acest
videoclip nu este disponibil din cauza lipsei de formate. Acest lucru se poate întâmpla
din cauza indisponibilității țării.'
@ -972,14 +976,6 @@ Starting download: Se începe descărcarea a "{videoTitle}"
Downloading failed: A existat o problemă la descărcarea "{videoTitle}"
Downloading has completed: '"{videoTitle}" s-a terminat de descărcat'
New Window: Fereastră nouă
Age Restricted:
The currently set default instance is {instance}: Acest {instance} este restricționat
datorită vârstei
Type:
Channel: Canal
Video: Video
This {videoOrPlaylist} is age restricted: Acest {videoOrPlaylist} are restricții
de vârstă
Channels:
Channels: Canale
Title: Listă de canale
@ -1011,3 +1007,5 @@ Playlist will pause when current video is finished: Lista de redare se va între
când videoclipul curent este terminat
Playlist will not pause when current video is finished: Lista de redare nu se va întrerupe
când videoclipul curent este terminat
Go to page: Mergeți la {page}
Close Banner: Închideți bannerul

View File

@ -955,7 +955,7 @@ Local API Error (Click to copy): 'Ошибка локального набора
Invidious API Error (Click to copy): 'Ошибка набора функций Invidious (Нажмите, чтобы
скопировать)'
Falling back to Invidious API: 'Возврат к набору функций Invidious'
Falling back to the local API: 'Возврат к локальному набору функций'
Falling back to Local API: 'Возврат к локальному набору функций'
Subscriptions have not yet been implemented: 'Подписки еще не реализованы'
Loop is now disabled: 'Повторение теперь отключено'
Loop is now enabled: 'Повторение теперь включено'
@ -1128,13 +1128,6 @@ Downloading failed: Возникла проблема с загрузкой «{v
Screenshot Success: Снимок экрана сохранён как «{filePath}»
Screenshot Error: Снимок экрана не удался. {error}
New Window: Новое окно
Age Restricted:
The currently set default instance is {instance}: У {instance} ограничение по возрасту
Type:
Channel: Канал
Video: Видео
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} имеет ограничение по
возрасту'
Channels:
Title: Список каналов
Count: '{number} канал(ов) найдено.'

View File

@ -646,7 +646,7 @@ Up Next: 'Nasledujúci'
Local API Error (Click to copy): 'Local API chyba (kliknutím skopírujete)'
Invidious API Error (Click to copy): 'Invidious API chyba (kliknutím skopírujete)'
Falling back to Invidious API: 'Návrat k Invidious API'
Falling back to the local API: 'Návrat k local API'
Falling back to Local API: 'Návrat k local API'
Subscriptions have not yet been implemented: 'Odbery ešte nie sú implementované'
Loop is now disabled: 'Opakovanie je teraz deaktivované'
Loop is now enabled: 'Opakovanie je teraz povolené'

View File

@ -709,7 +709,7 @@ Up Next: 'Naslednje na sporedu'
Local API Error (Click to copy): 'Napaka lokalnega APV (kliknite za kopiranje)'
Invidious API Error (Click to copy): 'Napaka Invidious APV (kliknite za kopiranje)'
Falling back to Invidious API: 'Začasno bo uporabljen Invidious APV'
Falling back to the local API: 'Začasno bo uporabljen lokalni APV'
Falling back to Local API: 'Začasno bo uporabljen lokalni APV'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Videoposnetek
zaradi mankajočih oblik ni dostopen. To se lahko zgodi, ko v vaši državi ni na razpolago.'
Subscriptions have not yet been implemented: 'Naročnine še niso bile implementirane'

View File

@ -814,7 +814,7 @@ Tooltips:
Local API Error (Click to copy): ''
Invidious API Error (Click to copy): ''
Falling back to Invidious API: ''
Falling back to the local API: ''
Falling back to Local API: ''
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
Subscriptions have not yet been implemented: ''
Unknown YouTube url type, cannot be opened in app: ''
@ -834,11 +834,6 @@ Canceled next video autoplay: ''
Default Invidious instance has been set to {instance}: ''
Default Invidious instance has been cleared: ''
'The playlist has ended. Enable loop to continue playing': ''
Age Restricted:
This {videoOrPlaylist} is age restricted: ''
Type:
Channel: ''
Video: ''
External link opening has been disabled in the general settings: ''
Downloading has completed: ''
Starting download: ''

View File

@ -149,6 +149,7 @@ User Playlists:
да додате видео снимак | Изаберите плејлисту на коју желите да додате {videoCount}
видео снимака
N playlists selected: 'Изабрано: {playlistCount}'
Added {count} Times: Додато {count} пут | Додато {count} пута
SinglePlaylistView:
Toast:
There were no videos to remove.: Није било видео снимака за уклањање.
@ -296,6 +297,7 @@ Settings:
Hot Pink: Врућа розе
Catppuccin Mocha: Catppuccin Mocha
System Default: Системски подразумевано
Nordic: Нордичка
Main Color Theme:
Main Color Theme: 'Главна тема боја'
Red: 'Црвена'
@ -466,7 +468,7 @@ Settings:
Hide Subscriptions Live: Сакриј стримове уживо канала које пратите
Hide Subscriptions Shorts: Сакриј Shorts снимке канала које пратите
Display Titles Without Excessive Capitalisation: Прикажи наслове без претераног
коришћења великих слова
писања великих слова и интерпункције
Hide Featured Channels: Сакриј истакнуте канале
Hide Profile Pictures in Comments: Сакриј слике профила у коментарима
Hide Upcoming Premieres: Сакриј предстојеће премијере
@ -883,6 +885,7 @@ Video:
уживо није доступно за овај стрим. Можда га је онемогућио аутор.
Unhide Channel: Прикажи канал
Hide Channel: Сакриј канал
More Options: Више опција
Tooltips:
Subscription Settings:
Fetch Feeds from RSS: 'Када је омогућено, FreeTube ће користити RSS уместо свог
@ -970,11 +973,6 @@ Tooltips:
Subscriptions have not yet been implemented: 'Праћења још увек нису имплементирана'
Open New Window: Отвори нови прозор
Shuffle is now disabled: Мешање је сада онемогућено
Age Restricted:
Type:
Video: Видео снимак
Channel: Канал
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} је старосно ограничен(а)'
New Window: Нови прозор
Clipboard:
Copy failed: Копирање у привремену меморију није успело
@ -1044,7 +1042,7 @@ Share:
меморију
YouTube Embed URL copied to clipboard: YouTube уграђени URL је копиран у привремену
меморију
Falling back to the local API: Повратак на локални API
Falling back to Local API: Повратак на локални API
Unknown YouTube url type, cannot be opened in app: Непозната врста YouTube URL адресе,
не може се отворити у апликацији
Search Bar:
@ -1118,3 +1116,7 @@ Channel Unhidden: '{channel} је уклоњен из филтера канал
Trimmed input must be at least N characters long: Исечени унос мора да има најмање
1 знак | Исечени унос мора да има најмање {length} знакова
Tag already exists: Ознака „{tagName}“ већ постоји
Close Banner: Затвори банер
Age Restricted:
This channel is age restricted: Овај канал је ограничен према узрасту
This video is age restricted: Овај видео снимак је ограничен према узрасту

View File

@ -916,7 +916,7 @@ Up Next: 'Kommer härnäst'
Local API Error (Click to copy): 'Lokalt API-fel (Klicka för att kopiera koden)'
Invidious API Error (Click to copy): 'Invidious API-fel (Klicka för att kopiera koden)'
Falling back to Invidious API: 'Faller tillbaka till Invidious API'
Falling back to the local API: 'Faller tillbaka till lokal API'
Falling back to Local API: 'Faller tillbaka till lokal API'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Den
här videon är inte tillgänglig på grund av format som saknas. Detta kan hända på
grund av landets otillgänglighet.'
@ -1037,11 +1037,6 @@ Preferences: Preferenser
Ok: Okej
Screenshot Success: Sparade skärmdump som "{filePath}"
Screenshot Error: Skärmdump misslyckades {felkod}
Age Restricted:
Type:
Channel: Kanal
Video: Video
This {videoOrPlaylist} is age restricted: Denna {videoOrPlaylist} är åldersbegränsad
Clipboard:
Cannot access clipboard without a secure connection: Har inte tillgång till urklipp
utan en säker anslutning

View File

@ -11,4 +11,3 @@ Channel:
About: {}
Video: {}
Tooltips: {}
Age Restricted: {}

View File

@ -178,6 +178,7 @@ User Playlists:
kullanımına geri dönüldü
This playlist is now used for quick bookmark: Bu oynatma listesi artık hızlı
yer imi için kullanılıyor
Search for Videos: Video Ara
AddVideoPrompt:
Select a playlist to add your N videos to: Videonuzu eklemek için bir oynatma
listesi seçin | {videoCount} videonuzu eklemek için bir oynatma listesi seçin
@ -191,6 +192,7 @@ User Playlists:
| {videoCount} video 1 oynatma listesine eklendi
N playlists selected: '{playlistCount} Seçildi'
Search in Playlists: Oynatma Listelerinde Ara
Added {count} Times: '{count} Defa Eklendi | {count} Defa Eklendi'
CreatePlaylistPrompt:
New Playlist Name: Yeni Oynatma Listesi Adı
Create: Oluştur
@ -532,8 +534,8 @@ Settings:
Hide Upcoming Premieres: Yaklaşan İlk Gösterimleri Gizle
Hide Channels Placeholder: Kanal Kimliği
Hide Channels: Kanallardan Videoları Gizle
Display Titles Without Excessive Capitalisation: Başlıklarıırı Büyük Harf Kullanmadan
Görüntüle
Display Titles Without Excessive Capitalisation: Başlıklarıırı Büyük Harf ve
Noktalama İşaretleri Kullanmadan Görüntüle
Hide Featured Channels: Öne Çıkan Kanalları Gizle
Hide Channel Playlists: Kanal Oynatma Listelerini Gizle
Hide Channel Community: Kanal Topluluğunu Gizle
@ -960,6 +962,7 @@ Video:
Pause on Current Video: Geçerli Videoda Duraklat
Unhide Channel: Kanalı Göster
Hide Channel: Kanalı Gizle
More Options: Daha Fazla Seçenek
Videos:
#& Sort By
Sort By:
@ -1040,7 +1043,7 @@ Up Next: 'Sonraki'
Local API Error (Click to copy): 'Yerel API Hatası (Kopyalamak için tıklayın)'
Invidious API Error (Click to copy): 'Invidious API Hatası (Kopyalamak için tıklayın)'
Falling back to Invidious API: 'Invidious API''ye geri dönülüyor'
Falling back to the local API: 'Yerel API''ye geri dönülüyor'
Falling back to Local API: 'Yerel API''ye geri dönülüyor'
Subscriptions have not yet been implemented: 'Abonelikler henüz uygulanmadı'
Loop is now disabled: 'Döngü artık devre dışı'
Loop is now enabled: 'Döngü artık etkin'
@ -1171,12 +1174,6 @@ Download folder does not exist: İndirme dizini "$" mevcut değil. "Klasör sor"
Screenshot Success: Ekran görüntüsü "{filePath}" olarak kaydedildi
Screenshot Error: Ekran görüntüsü başarısız oldu. {error}
New Window: Yeni Pencere
Age Restricted:
The currently set default instance is {instance}: Bu {instance} yaş kısıtlamalıdır
Type:
Channel: Kanal
Video: Video
This {videoOrPlaylist} is age restricted: Bu {videoOrPlaylist} yaş kısıtlamalıdır
Channels:
Empty: Kanal listeniz şu anda boş.
Channels: Kanallar
@ -1212,3 +1209,7 @@ Channel Unhidden: '{channel} kanal filtresinden kaldırıldı'
Trimmed input must be at least N characters long: Kırpılan girdi en az 1 karakter
uzunluğunda olmalıdır | Kırpılan girdi en az {length} karakter uzunluğunda olmalıdır
Tag already exists: '"{tagName}" etiketi zaten var'
Close Banner: Afişi Kapat
Age Restricted:
This video is age restricted: Bu videoda yaş sınırlaması var
This channel is age restricted: Bu kanalda yaş sınırlaması var

View File

@ -43,6 +43,8 @@ Global:
Subscriber Count: 1 підписник | {count} підписників
View Count: 1 перегляд | {count} переглядів
Watching Count: 1 глядач | {count} глядачів
Input Tags:
Length Requirement: Тег повинен мати довжину не менше {number} символів
Version {versionNumber} is now available! Click for more details: 'Доступна нова
версія {versionNumber}! Натисніть, щоб переглянути подробиці'
Download From Site: 'Завантажити з сайту'
@ -116,17 +118,36 @@ Trending:
Music: Музика
Default: Типово
Most Popular: 'Найпопулярніші'
Playlists: 'Добірки'
Playlists: 'Списки відтворення'
User Playlists:
Your Playlists: 'Ваші добірки'
Your Playlists: 'Ваші списки відтворення'
Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: Збережені
відео порожні. Клацніть на кнопку збереження у куті відео, щоб воно було перелічено
тут
Playlist Message: Ця сторінка не показує повністю робочих добірок. На ній перелічено
лише відео, які ви зберегли або вибрали. Коли робота завершиться, усі відео, які
зараз знаходяться тут, буде переміщено до добірки "Вибране".
Playlist Message: Ця сторінка не показує повністю робочих списків відтворення. На
ній перелічено лише відео, які ви зберегли або вибрали. Коли робота завершиться,
усі відео, які зараз знаходяться тут, буде переміщено до списку відтворення "Вибране".
Search bar placeholder: Шукати у добірці
Empty Search Message: Немає відео в цій добірці, які відповідають вашому запиту
Create New Playlist: Створити новий список відтворення
Add to Playlist: Додати список відтворення
Remove from Favorites: Вилучити з {playlistName}
Move Video Up: Посунути відео вгору
Move Video Down: Посунути відео вниз
Remove from Playlist: Вилучити зі списку відтворення
Playlist Description: Опис списку відтворення
Save Changes: Зберегти зміни
Cancel: Скасувати
Copy Playlist: Скопіювати список відтворення
You have no playlists. Click on the create new playlist button to create a new one.: У
вас немає списків відтворення. Натисніть на кнопку створити новий список відтворення,
щоб створити його.
This playlist currently has no videos.: Наразі у цьому списку відтворення немає
відео.
Add to Favorites: Додати до {playlistName}
Playlist Name: Назва списку відтворення
Edit Playlist Info: Змінити інформацію списку відтворення
Remove Watched Videos: Вилучити з переглянутих відео
History:
# On History Page
History: 'Історія'
@ -321,8 +342,8 @@ Settings:
Are you sure you want to remove all subscriptions and profiles? This cannot be undone.: 'Справді
хочете вилучити всі підписки та профілі? Цю дію не можна скасувати.'
Automatically Remove Video Meta Files: Автоматично вилучати метафайли відео
Save Watched Videos With Last Viewed Playlist: Зберегти переглянуті відео в добірку,
яку ви переглядали останнім часом
Save Watched Videos With Last Viewed Playlist: Зберегти переглянуті відео у список
відтворення, який ви переглядали останнім часом
Subscription Settings:
Subscription Settings: 'Налаштування підписки'
Hide Videos on Watch: 'Ховати відео при перегляді'
@ -342,7 +363,7 @@ Settings:
Hide Popular Videos: 'Не показувати популярні відео'
Hide Live Chat: 'Не показувати живий чат'
Hide Active Subscriptions: Сховати активні підписки
Hide Playlists: Сховати добірки
Hide Playlists: Сховати списки відтворення
Hide Video Description: Сховати опис відео
Hide Comments: Сховати коментарі
Hide Sharing Actions: Сховати дії поширення
@ -354,7 +375,7 @@ Settings:
Display Titles Without Excessive Capitalisation: Показувати заголовки без надмірно
великих літер
Hide Featured Channels: Сховати пропоновані канали
Hide Channel Playlists: Сховати добірки з каналів
Hide Channel Playlists: Сховати списки відтворення каналу
Hide Channel Community: Сховати спільноту каналу
Hide Channel Shorts: Сховати Shorts каналу
Sections:
@ -414,13 +435,13 @@ Settings:
Unknown data key: 'Невідомий ключ даних'
How do I import my subscriptions?: 'Як імпортувати свої підписки?'
Manage Subscriptions: Керування підписками
Playlist insufficient data: Недостатньо даних для добірки "{playlist}", пропуск
елемента
All playlists has been successfully exported: Усі добірки успішно експортовано
Playlist insufficient data: Недостатньо даних для списку відтворення "{playlist}",
пропуск елемента
All playlists has been successfully exported: Усі списки відтворення успішно експортовано
Import Playlists: Імпорт добірок
Export Playlists: Експорт добірок
All playlists has been successfully imported: Усі добірки успішно імпортовано
Playlist File: Файл добірки
All playlists has been successfully imported: Усі списки відтворення успішно імпортовано
Playlist File: Файл списку відтворення
Subscription File: Файл підписки
History File: Файл історії
Advanced Settings: {}
@ -590,7 +611,7 @@ Channel:
Oldest: 'Найдавніші'
Most Popular: 'Найпопулярніші'
Playlists:
Playlists: 'Добірки'
Playlists: 'Списки відтворення'
This channel does not currently have any playlists: 'Цей канал наразі не має добірок'
Sort Types:
Last Video Added: 'Останнє додане відео'
@ -646,9 +667,9 @@ Video:
Open Channel in Invidious: 'Відкрити канал у Invidious'
Copy Invidious Channel Link: 'Копіювати посилання на канал Invidious'
Views: 'Перегляди'
Loop Playlist: 'Зациклити добірку'
Shuffle Playlist: 'Перемішати добірку'
Reverse Playlist: 'Змінити напрямок добірки'
Loop Playlist: 'Повторювати список відтворення'
Shuffle Playlist: 'Перемішати список відтворення'
Reverse Playlist: 'Зворотний напрямок списку відтворення'
Play Next Video: 'Відтворити наступне відео'
Play Previous Video: 'Відтворити попереднє відео'
Watched: 'Переглянуто'
@ -739,7 +760,7 @@ Video:
starting video at offset: запуск відео зі зміщенням
UnsupportedActionTemplate: '{externalPlayer} не підтримує: {action}'
OpeningTemplate: Відкриття {videoOrPlaylist} у {externalPlayer}...
playlist: добірка
playlist: список відтворення
video: відео
OpenInTemplate: Відкрити у {externalPlayer}
Premieres on: Прем'єри
@ -782,7 +803,7 @@ Videos:
#& Playlists
Playlist:
#& About
View Full Playlist: 'Переглянути всю добірку'
View Full Playlist: 'Переглянути весь список відтворення'
Videos: 'Відео'
View: 'Перегляд'
Views: 'Переглядів'
@ -791,7 +812,7 @@ Playlist:
# On Video Watch Page
#* Published
#& Views
Playlist: Добірка
Playlist: Список відтворення
Toggle Theatre Mode: 'Перемкнути режим театру'
Change Format:
Change Media Formats: 'Зміна форматів відео'
@ -804,7 +825,7 @@ Change Format:
відео'
Share:
Share Video: 'Поділитися відео'
Share Playlist: 'Поділитися добіркою'
Share Playlist: 'Поділитися списком відтворення'
Include Timestamp: 'Включити позначку часу'
Copy Link: 'Копіювати посилання'
Open Link: 'Відкрити посилання'
@ -915,8 +936,8 @@ Tooltips:
програвач можна знайти за допомогою змінної середовища PATH. Якщо потрібно,
тут можна призначити нетиповий шлях.
External Player: Якщо обрано зовнішній програвач, з'явиться піктограма для відкриття
відео (добірка, якщо підтримується) у зовнішньому програвачі, на мініатюрі.
Увага, налаштування Invidious не застосовуються до сторонніх програвачів.
відео (список відтворення, якщо підтримується) у зовнішньому програвачі, на
мініатюрі. Увага, налаштування Invidious не застосовуються до сторонніх програвачів.
DefaultCustomArgumentsTemplate: "(Типово: '{defaultCustomArguments}')"
Experimental Settings:
Replace HTTP Cache: Вимикає дисковий HTTP-кеш Electron і вмикає власний кеш зображень
@ -932,7 +953,7 @@ Tooltips:
Local API Error (Click to copy): 'Помилка локального API (натисніть, щоб скопіювати)'
Invidious API Error (Click to copy): 'Помилка Invidious API (натисніть, щоб скопіювати)'
Falling back to Invidious API: 'Повернення до API Invidious'
Falling back to the local API: 'Повернення до локального API'
Falling back to Local API: 'Повернення до локального API'
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Це
відео недоступне через відсутність форматів. Це може статися через недоступність
країни.'
@ -941,12 +962,12 @@ Loop is now disabled: 'Цикл вимкнено'
Loop is now enabled: 'Цикл увімкнено'
Shuffle is now disabled: 'Випадковий порядок вимкнено'
Shuffle is now enabled: 'Випадковий порядок увімкнено'
The playlist has been reversed: 'Добірку обернено'
The playlist has been reversed: 'Список відтворення обернено'
Playing Next Video: 'Відтворення наступного відео'
Playing Previous Video: 'Відтворення попереднього відео'
Canceled next video autoplay: 'Скасовано автовідтворення наступного відео'
'The playlist has ended. Enable loop to continue playing': 'Добірка завершилася. Увімкніть
цикл, щоб продовжити відтворення'
'The playlist has ended. Enable loop to continue playing': 'Список відтворення завершився.
Увімкніть повторення, щоб продовжити відтворення'
Yes: 'Так'
No: 'Ні'
@ -977,13 +998,6 @@ Download folder does not exist: Каталог завантаження "$" не
Screenshot Success: Знімок екрана збережено як «{filePath}»
Screenshot Error: Не вдалося зробити знімок екрана. {error}
New Window: Нове вікно
Age Restricted:
The currently set default instance is {instance}: Цей {instance} має обмеження за
віком
Type:
Video: Відео
Channel: Канал
This {videoOrPlaylist} is age restricted: '{videoOrPlaylist} має вікове обмеження'
Channels:
Count: 'Знайдено каналів: {number}.'
Empty: Ваш список каналів наразі порожній.
@ -1008,10 +1022,11 @@ Ok: Гаразд
Hashtag:
Hashtag: Хештег
This hashtag does not currently have any videos: За цим хештегом наразі немає відео
Playlist will pause when current video is finished: Добірка призупиняється, коли поточне
відео завершено
Playlist will not pause when current video is finished: Добірка не призупиняється,
Playlist will pause when current video is finished: Список відтворення призупиняється,
коли поточне відео завершено
Playlist will not pause when current video is finished: Список відтворення не призупиняється,
коли поточне відео завершено
Channel Hidden: '{channel} додано до фільтра каналу'
Go to page: Перейти до {page}
Channel Unhidden: '{channel} вилучено з фільтра каналу'
Close Banner: Закрити банер

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