mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-03 22:49:42 +00:00
Merge remote-tracking branch 'remotes/upstream/master'
This commit is contained in:
commit
b1dfd2f2a7
44 changed files with 2144 additions and 284 deletions
|
|
@ -51,19 +51,21 @@
|
||||||
<form @submit.prevent="submitSearchForm">
|
<form @submit.prevent="submitSearchForm">
|
||||||
<div class="flex flex-wrap sm:flex-nowrap items-center justify-start -mx-1">
|
<div class="flex flex-wrap sm:flex-nowrap items-center justify-start -mx-1">
|
||||||
<div class="w-48 grow p-1">
|
<div class="w-48 grow p-1">
|
||||||
<ui-dropdown v-model="provider" :items="providers" :label="$strings.LabelProvider" small />
|
<ui-dropdown v-model="provider" :items="providers" :disabled="searchInProgress" :label="$strings.LabelProvider" small />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-72 grow p-1">
|
<div class="w-72 grow p-1">
|
||||||
<ui-text-input-with-label v-model="searchTitle" :label="searchTitleLabel" :placeholder="$strings.PlaceholderSearch" />
|
<ui-text-input-with-label v-model="searchTitle" :disabled="searchInProgress" :label="searchTitleLabel" :placeholder="$strings.PlaceholderSearch" />
|
||||||
</div>
|
</div>
|
||||||
<div v-show="provider != 'itunes' && provider != 'audiobookcovers'" class="w-72 grow p-1">
|
<div v-show="provider != 'itunes' && provider != 'audiobookcovers'" class="w-72 grow p-1">
|
||||||
<ui-text-input-with-label v-model="searchAuthor" :label="$strings.LabelAuthor" />
|
<ui-text-input-with-label v-model="searchAuthor" :disabled="searchInProgress" :label="$strings.LabelAuthor" />
|
||||||
</div>
|
</div>
|
||||||
<ui-btn class="mt-5 ml-1 md:min-w-24" :padding-x="4" type="submit">{{ $strings.ButtonSearch }}</ui-btn>
|
<ui-btn v-if="!searchInProgress" class="mt-5 ml-1 md:min-w-24" :padding-x="4" type="submit">{{ $strings.ButtonSearch }}</ui-btn>
|
||||||
|
<ui-btn v-else class="mt-5 ml-1 md:min-w-24" :padding-x="4" type="button" color="bg-error" @click.prevent="cancelCurrentSearch">{{ $strings.ButtonCancel }}</ui-btn>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div v-if="hasSearched" class="flex items-center flex-wrap justify-center sm:max-h-80 sm:overflow-y-scroll mt-2 max-w-full">
|
<div v-if="hasSearched" class="flex items-center flex-wrap justify-center sm:max-h-80 sm:overflow-y-scroll mt-2 max-w-full">
|
||||||
<p v-if="!coversFound.length">{{ $strings.MessageNoCoversFound }}</p>
|
<p v-if="searchInProgress && !coversFound.length" class="text-gray-300 py-4">{{ $strings.MessageLoading }}</p>
|
||||||
|
<p v-else-if="!searchInProgress && !coversFound.length" class="text-gray-300 py-4">{{ $strings.MessageNoCoversFound }}</p>
|
||||||
<template v-for="cover in coversFound">
|
<template v-for="cover in coversFound">
|
||||||
<div :key="cover" class="m-0.5 mb-5 border-2 border-transparent hover:border-yellow-300 cursor-pointer" :class="cover === coverPath ? 'border-yellow-300' : ''" @click="updateCover(cover)">
|
<div :key="cover" class="m-0.5 mb-5 border-2 border-transparent hover:border-yellow-300 cursor-pointer" :class="cover === coverPath ? 'border-yellow-300' : ''" @click="updateCover(cover)">
|
||||||
<covers-preview-cover :src="cover" :width="80" show-open-new-tab :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
<covers-preview-cover :src="cover" :width="80" show-open-new-tab :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||||
|
|
@ -105,7 +107,10 @@ export default {
|
||||||
showLocalCovers: false,
|
showLocalCovers: false,
|
||||||
previewUpload: null,
|
previewUpload: null,
|
||||||
selectedFile: null,
|
selectedFile: null,
|
||||||
provider: 'google'
|
provider: 'google',
|
||||||
|
currentSearchRequestId: null,
|
||||||
|
searchInProgress: false,
|
||||||
|
socketListenersActive: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -129,7 +134,7 @@ export default {
|
||||||
},
|
},
|
||||||
providers() {
|
providers() {
|
||||||
if (this.isPodcast) return this.$store.state.scanners.podcastProviders
|
if (this.isPodcast) return this.$store.state.scanners.podcastProviders
|
||||||
return [{ text: 'All', value: 'all' }, ...this.$store.state.scanners.providers, ...this.$store.state.scanners.coverOnlyProviders]
|
return [{ text: 'Best', value: 'best' }, ...this.$store.state.scanners.providers, ...this.$store.state.scanners.coverOnlyProviders, { text: 'All', value: 'all' }]
|
||||||
},
|
},
|
||||||
searchTitleLabel() {
|
searchTitleLabel() {
|
||||||
if (this.provider.startsWith('audible')) return this.$strings.LabelSearchTitleOrASIN
|
if (this.provider.startsWith('audible')) return this.$strings.LabelSearchTitleOrASIN
|
||||||
|
|
@ -186,6 +191,9 @@ export default {
|
||||||
_file.localPath = `${process.env.serverUrl}/api/items/${this.libraryItemId}/file/${file.ino}?token=${this.userToken}`
|
_file.localPath = `${process.env.serverUrl}/api/items/${this.libraryItemId}/file/${file.ino}?token=${this.userToken}`
|
||||||
return _file
|
return _file
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
socket() {
|
||||||
|
return this.$root.socket
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -235,7 +243,19 @@ export default {
|
||||||
this.searchTitle = this.mediaMetadata.title || ''
|
this.searchTitle = this.mediaMetadata.title || ''
|
||||||
this.searchAuthor = this.mediaMetadata.authorName || ''
|
this.searchAuthor = this.mediaMetadata.authorName || ''
|
||||||
if (this.isPodcast) this.provider = 'itunes'
|
if (this.isPodcast) this.provider = 'itunes'
|
||||||
else this.provider = localStorage.getItem('book-cover-provider') || localStorage.getItem('book-provider') || 'google'
|
else {
|
||||||
|
// Migrate from 'all' to 'best' (only once)
|
||||||
|
const migrationKey = 'book-cover-provider-migrated'
|
||||||
|
const currentProvider = localStorage.getItem('book-cover-provider') || localStorage.getItem('book-provider') || 'google'
|
||||||
|
|
||||||
|
if (!localStorage.getItem(migrationKey) && currentProvider === 'all') {
|
||||||
|
localStorage.setItem('book-cover-provider', 'best')
|
||||||
|
localStorage.setItem(migrationKey, 'true')
|
||||||
|
this.provider = 'best'
|
||||||
|
} else {
|
||||||
|
this.provider = currentProvider
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
removeCover() {
|
removeCover() {
|
||||||
if (!this.coverPath) {
|
if (!this.coverPath) {
|
||||||
|
|
@ -291,22 +311,116 @@ export default {
|
||||||
console.error('PersistProvider', error)
|
console.error('PersistProvider', error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
generateRequestId() {
|
||||||
|
return `cover-search-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||||
|
},
|
||||||
|
addSocketListeners() {
|
||||||
|
if (!this.socket || this.socketListenersActive) return
|
||||||
|
|
||||||
|
this.socket.on('cover_search_result', this.handleSearchResult)
|
||||||
|
this.socket.on('cover_search_complete', this.handleSearchComplete)
|
||||||
|
this.socket.on('cover_search_error', this.handleSearchError)
|
||||||
|
this.socket.on('cover_search_provider_error', this.handleProviderError)
|
||||||
|
this.socket.on('cover_search_cancelled', this.handleSearchCancelled)
|
||||||
|
this.socket.on('disconnect', this.handleSocketDisconnect)
|
||||||
|
this.socketListenersActive = true
|
||||||
|
},
|
||||||
|
removeSocketListeners() {
|
||||||
|
if (!this.socket || !this.socketListenersActive) return
|
||||||
|
|
||||||
|
this.socket.off('cover_search_result', this.handleSearchResult)
|
||||||
|
this.socket.off('cover_search_complete', this.handleSearchComplete)
|
||||||
|
this.socket.off('cover_search_error', this.handleSearchError)
|
||||||
|
this.socket.off('cover_search_provider_error', this.handleProviderError)
|
||||||
|
this.socket.off('cover_search_cancelled', this.handleSearchCancelled)
|
||||||
|
this.socket.off('disconnect', this.handleSocketDisconnect)
|
||||||
|
this.socketListenersActive = false
|
||||||
|
},
|
||||||
|
handleSearchResult(data) {
|
||||||
|
if (data.requestId !== this.currentSearchRequestId) return
|
||||||
|
|
||||||
|
// Add new covers to the list (avoiding duplicates)
|
||||||
|
const newCovers = data.covers.filter((cover) => !this.coversFound.includes(cover))
|
||||||
|
this.coversFound.push(...newCovers)
|
||||||
|
},
|
||||||
|
handleSearchComplete(data) {
|
||||||
|
if (data.requestId !== this.currentSearchRequestId) return
|
||||||
|
|
||||||
|
this.searchInProgress = false
|
||||||
|
this.currentSearchRequestId = null
|
||||||
|
},
|
||||||
|
handleSearchError(data) {
|
||||||
|
if (data.requestId !== this.currentSearchRequestId) return
|
||||||
|
|
||||||
|
console.error('[Cover Search] Search error:', data.error)
|
||||||
|
this.$toast.error(this.$strings.ToastCoverSearchFailed)
|
||||||
|
this.searchInProgress = false
|
||||||
|
this.currentSearchRequestId = null
|
||||||
|
},
|
||||||
|
handleProviderError(data) {
|
||||||
|
if (data.requestId !== this.currentSearchRequestId) return
|
||||||
|
|
||||||
|
console.warn(`[Cover Search] Provider ${data.provider} failed:`, data.error)
|
||||||
|
},
|
||||||
|
handleSearchCancelled(data) {
|
||||||
|
if (data.requestId !== this.currentSearchRequestId) return
|
||||||
|
|
||||||
|
this.searchInProgress = false
|
||||||
|
this.currentSearchRequestId = null
|
||||||
|
},
|
||||||
|
handleSocketDisconnect() {
|
||||||
|
// If we were in the middle of a search, cancel it (server can't send results anymore)
|
||||||
|
if (this.searchInProgress && this.currentSearchRequestId) {
|
||||||
|
this.searchInProgress = false
|
||||||
|
this.currentSearchRequestId = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelCurrentSearch() {
|
||||||
|
if (!this.currentSearchRequestId || !this.socket?.connected) {
|
||||||
|
console.error('[Cover Search] Socket not connected')
|
||||||
|
this.$toast.error(this.$strings.ToastConnectionNotAvailable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.socket.emit('cancel_cover_search', this.currentSearchRequestId)
|
||||||
|
this.currentSearchRequestId = null
|
||||||
|
this.searchInProgress = false
|
||||||
|
},
|
||||||
async submitSearchForm() {
|
async submitSearchForm() {
|
||||||
|
if (!this.socket?.connected) {
|
||||||
|
console.error('[Cover Search] Socket not connected')
|
||||||
|
this.$toast.error(this.$strings.ToastConnectionNotAvailable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel any existing search
|
||||||
|
if (this.searchInProgress) {
|
||||||
|
this.cancelCurrentSearch()
|
||||||
|
}
|
||||||
|
|
||||||
// Store provider in local storage
|
// Store provider in local storage
|
||||||
this.persistProvider()
|
this.persistProvider()
|
||||||
|
|
||||||
this.isProcessing = true
|
// Setup socket listeners if not already done
|
||||||
const searchQuery = this.getSearchQuery()
|
this.addSocketListeners()
|
||||||
const results = await this.$axios
|
|
||||||
.$get(`/api/search/covers?${searchQuery}`)
|
// Clear previous results
|
||||||
.then((res) => res.results)
|
this.coversFound = []
|
||||||
.catch((error) => {
|
|
||||||
console.error('Failed', error)
|
|
||||||
return []
|
|
||||||
})
|
|
||||||
this.coversFound = results
|
|
||||||
this.isProcessing = false
|
|
||||||
this.hasSearched = true
|
this.hasSearched = true
|
||||||
|
this.searchInProgress = true
|
||||||
|
|
||||||
|
// Generate unique request ID
|
||||||
|
const requestId = this.generateRequestId()
|
||||||
|
this.currentSearchRequestId = requestId
|
||||||
|
|
||||||
|
// Emit search request via WebSocket
|
||||||
|
this.socket.emit('search_covers', {
|
||||||
|
requestId,
|
||||||
|
title: this.searchTitle,
|
||||||
|
author: this.searchAuthor || '',
|
||||||
|
provider: this.provider,
|
||||||
|
podcast: this.isPodcast
|
||||||
|
})
|
||||||
},
|
},
|
||||||
setCover(coverFile) {
|
setCover(coverFile) {
|
||||||
this.isProcessing = true
|
this.isProcessing = true
|
||||||
|
|
@ -320,6 +434,18 @@ export default {
|
||||||
this.isProcessing = false
|
this.isProcessing = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// Setup socket listeners when component is mounted
|
||||||
|
this.addSocketListeners()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// Cancel any ongoing search when component is destroyed
|
||||||
|
if (this.searchInProgress) {
|
||||||
|
this.cancelCurrentSearch()
|
||||||
|
}
|
||||||
|
// Remove socket listeners
|
||||||
|
this.removeSocketListeners()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@
|
||||||
<div ref="wrapper" class="relative">
|
<div ref="wrapper" class="relative">
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<div ref="inputWrapper" role="list" style="min-height: 36px" class="flex-wrap relative w-full shadow-xs flex items-center border border-gray-600 rounded-sm px-2 py-1" :class="wrapperClass" @click.stop.prevent="clickWrapper" @mouseup.stop.prevent @mousedown.prevent>
|
<div ref="inputWrapper" role="list" style="min-height: 36px" class="flex-wrap relative w-full shadow-xs flex items-center border border-gray-600 rounded-sm px-2 py-1" :class="wrapperClass" @click.stop.prevent="clickWrapper" @mouseup.stop.prevent @mousedown.prevent>
|
||||||
<div v-for="item in selected" :key="item" role="listitem" class="rounded-full px-2 py-1 mx-0.5 my-0.5 text-xs bg-bg flex flex-nowrap break-all items-center relative">
|
<!-- Use index in v-for and key in case the same key exists multiple times -->
|
||||||
|
<div v-for="(item, idx) in selected" :key="item + '-' + idx" role="listitem" class="rounded-full px-2 py-1 mx-0.5 my-0.5 text-xs bg-bg flex flex-nowrap break-all items-center relative">
|
||||||
<div v-if="!disabled" class="w-full h-full rounded-full absolute top-0 left-0 px-1 bg-bg/75 flex items-center justify-end opacity-0 hover:opacity-100" :class="{ 'opacity-100': inputFocused }">
|
<div v-if="!disabled" class="w-full h-full rounded-full absolute top-0 left-0 px-1 bg-bg/75 flex items-center justify-end opacity-0 hover:opacity-100" :class="{ 'opacity-100': inputFocused }">
|
||||||
<button v-if="showEdit" type="button" :aria-label="$strings.ButtonEdit" class="material-symbols text-white hover:text-warning cursor-pointer" style="font-size: 1.1rem" @click.stop="editItem(item)">edit</button>
|
<button v-if="showEdit" type="button" :aria-label="$strings.ButtonEdit" class="material-symbols text-white hover:text-warning cursor-pointer" style="font-size: 1.1rem" @click.stop="editItem(item)">edit</button>
|
||||||
<button type="button" :aria-label="$strings.ButtonRemove" class="material-symbols text-white hover:text-error focus:text-error cursor-pointer" style="font-size: 1.1rem" @click.stop="removeItem(item)" @keydown.enter.stop.prevent="removeItem(item)" @focus="setInputFocused(true)" @blur="setInputFocused(false)" tabindex="0">close</button>
|
<button type="button" :aria-label="$strings.ButtonRemove" class="material-symbols text-white hover:text-error focus:text-error cursor-pointer" style="font-size: 1.1rem" @click.stop="removeItem(item, idx)" @keydown.enter.stop.prevent="removeItem(item, idx)" @focus="setInputFocused(true)" @blur="setInputFocused(false)" tabindex="0">close</button>
|
||||||
</div>
|
</div>
|
||||||
{{ item }}
|
{{ item }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -259,8 +260,9 @@ export default {
|
||||||
}
|
}
|
||||||
this.focus()
|
this.focus()
|
||||||
},
|
},
|
||||||
removeItem(item) {
|
removeItem(item, idx) {
|
||||||
var remaining = this.selected.filter((i) => i !== item)
|
var remaining = this.selected.slice()
|
||||||
|
remaining.splice(idx, 1)
|
||||||
this.$emit('input', remaining)
|
this.$emit('input', remaining)
|
||||||
this.$emit('removedItem', item)
|
this.$emit('removedItem', item)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
|
||||||
4
client/package-lock.json
generated
4
client/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "2.29.0",
|
"version": "2.30.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "2.29.0",
|
"version": "2.30.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxtjs/axios": "^5.13.6",
|
"@nuxtjs/axios": "^5.13.6",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "2.29.0",
|
"version": "2.30.0",
|
||||||
"buildNumber": 1,
|
"buildNumber": 1,
|
||||||
"description": "Self-hosted audiobook and podcast client",
|
"description": "Self-hosted audiobook and podcast client",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|
|
||||||
|
|
@ -12,24 +12,24 @@
|
||||||
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap-reverse lg:flex-nowrap justify-center py-4 px-4">
|
<div class="flex flex-wrap-reverse min-[1120px]:flex-nowrap justify-center py-4 px-4">
|
||||||
<div class="w-full max-w-3xl py-4">
|
<div class="w-full max-w-3xl py-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="w-12 hidden lg:block" />
|
<div class="w-12 hidden min-w-[1120px]:block" />
|
||||||
<p class="text-lg mb-4 font-semibold">{{ $strings.HeaderChapters }}</p>
|
<p class="text-lg mb-4 font-semibold">{{ $strings.HeaderChapters }}</p>
|
||||||
<div class="grow" />
|
<div class="grow" />
|
||||||
<ui-checkbox v-model="showSecondInputs" checkbox-bg="primary" small label-class="text-sm text-gray-200 pl-1" :label="$strings.LabelShowSeconds" class="mx-2" />
|
<ui-checkbox v-model="showSecondInputs" checkbox-bg="primary" small label-class="text-sm text-gray-200 pl-1" :label="$strings.LabelShowSeconds" class="mx-2" />
|
||||||
<div class="w-32 hidden lg:block" />
|
<div class="w-32 hidden min-[1120px]:block" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center mb-3 py-1 -mx-1">
|
<div class="flex items-center mb-3 py-1 -mx-1">
|
||||||
<div class="w-12 hidden lg:block" />
|
<div class="w-12 hidden min-[1120px]:block" />
|
||||||
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1 whitespace-nowrap" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1 whitespace-nowrap" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
||||||
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg-bg' : 'bg-primary'" class="mx-1 whitespace-nowrap" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg-bg' : 'bg-primary'" class="mx-1 whitespace-nowrap" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
||||||
<ui-btn color="bg-primary" small :class="{ 'mx-1': newChapters.length > 1 }" @click="showFindChaptersModal = true">{{ $strings.ButtonLookup }}</ui-btn>
|
<ui-btn color="bg-primary" small :class="{ 'mx-1': newChapters.length > 1 }" @click="showFindChaptersModal = true">{{ $strings.ButtonLookup }}</ui-btn>
|
||||||
<div class="grow" />
|
<div class="grow" />
|
||||||
<ui-btn v-if="hasChanges" small class="mx-1" @click.stop="resetChapters">{{ $strings.ButtonReset }}</ui-btn>
|
<ui-btn v-if="hasChanges" small class="mx-1" @click.stop="resetChapters">{{ $strings.ButtonReset }}</ui-btn>
|
||||||
<ui-btn v-if="hasChanges" color="bg-success" class="mx-1" :disabled="!hasChanges" small @click="saveChapters">{{ $strings.ButtonSave }}</ui-btn>
|
<ui-btn v-if="hasChanges" color="bg-success" class="mx-1" :disabled="!hasChanges" small @click="saveChapters">{{ $strings.ButtonSave }}</ui-btn>
|
||||||
<div class="w-32 hidden lg:block" />
|
<div class="w-32 hidden min-[1120px]:block" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="overflow-hidden">
|
<div class="overflow-hidden">
|
||||||
|
|
@ -150,7 +150,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full max-w-xl py-4 px-2">
|
<div class="w-full max-w-3xl min-[1120px]:max-w-xl py-4 px-2">
|
||||||
<div class="flex items-center mb-4 py-1">
|
<div class="flex items-center mb-4 py-1">
|
||||||
<p class="text-lg font-semibold">{{ $strings.HeaderAudioTracks }}</p>
|
<p class="text-lg font-semibold">{{ $strings.HeaderAudioTracks }}</p>
|
||||||
<div class="grow" />
|
<div class="grow" />
|
||||||
|
|
@ -160,13 +160,13 @@
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex text-xs uppercase text-gray-300 font-semibold mb-2">
|
<div class="flex text-xs uppercase text-gray-300 font-semibold mb-2">
|
||||||
<div class="grow">{{ $strings.LabelFilename }}</div>
|
<div class="grow min-[1120px]:max-w-64 xl:max-w-sm">{{ $strings.LabelFilename }}</div>
|
||||||
<div class="w-20">{{ $strings.LabelDuration }}</div>
|
<div class="w-20">{{ $strings.LabelDuration }}</div>
|
||||||
<div class="w-20 hidden md:block text-center">{{ $strings.HeaderChapters }}</div>
|
<div class="w-20 hidden md:block text-center">{{ $strings.HeaderChapters }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="track in audioTracks" :key="track.ino" class="flex items-center py-2" :class="currentTrackIndex === track.index && isPlayingChapter ? 'bg-success/10' : ''">
|
<div v-for="track in audioTracks" :key="track.ino" class="flex items-center py-2" :class="currentTrackIndex === track.index && isPlayingChapter ? 'bg-success/10' : ''">
|
||||||
<div class="grow max-w-[calc(100%-80px)] pr-2">
|
<div class="pr-2 grow min-[1120px]:max-w-64 xl:max-w-sm">
|
||||||
<p class="text-xs truncate max-w-sm">{{ track.metadata.filename }}</p>
|
<p class="text-xs truncate">{{ track.metadata.filename }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-20" style="min-width: 80px">
|
<div class="w-20" style="min-width: 80px">
|
||||||
<p class="text-xs font-mono text-gray-200">{{ $secondsToTimestamp(Math.round(track.duration), false, true) }}</p>
|
<p class="text-xs font-mono text-gray-200">{{ $secondsToTimestamp(Math.round(track.duration), false, true) }}</p>
|
||||||
|
|
@ -697,11 +697,7 @@ export default {
|
||||||
this.saving = false
|
this.saving = false
|
||||||
if (data.updated) {
|
if (data.updated) {
|
||||||
this.$toast.success(this.$strings.ToastChaptersUpdated)
|
this.$toast.success(this.$strings.ToastChaptersUpdated)
|
||||||
if (this.previousRoute) {
|
this.reloadLibraryItem()
|
||||||
this.$router.push(this.previousRoute)
|
|
||||||
} else {
|
|
||||||
this.$router.push(`/item/${this.libraryItem.id}`)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
||||||
}
|
}
|
||||||
|
|
@ -874,11 +870,7 @@ export default {
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.updated) {
|
if (data.updated) {
|
||||||
this.$toast.success(this.$strings.ToastChaptersRemoved)
|
this.$toast.success(this.$strings.ToastChaptersRemoved)
|
||||||
if (this.previousRoute) {
|
this.reloadLibraryItem()
|
||||||
this.$router.push(this.previousRoute)
|
|
||||||
} else {
|
|
||||||
this.$router.push(`/item/${this.libraryItem.id}`)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
||||||
}
|
}
|
||||||
|
|
@ -983,6 +975,18 @@ export default {
|
||||||
}
|
}
|
||||||
this.libraryItem = libraryItem
|
this.libraryItem = libraryItem
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
reloadLibraryItem() {
|
||||||
|
this.$axios
|
||||||
|
.$get(`/api/items/${this.libraryItem.id}?expanded=1`)
|
||||||
|
.then((data) => {
|
||||||
|
this.libraryItem = data
|
||||||
|
this.initChapters()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Failed to reload library item', error)
|
||||||
|
this.$toast.error(this.$strings.ToastFailedToLoadData)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"ButtonAdd": "إضافة",
|
"ButtonAdd": "إضافة",
|
||||||
|
"ButtonAddApiKey": "إضافة مفتاح واجهة برمجة التطبيقات",
|
||||||
"ButtonAddChapters": "إضافة الفصول",
|
"ButtonAddChapters": "إضافة الفصول",
|
||||||
"ButtonAddDevice": "إضافة جهاز",
|
"ButtonAddDevice": "إضافة جهاز",
|
||||||
"ButtonAddLibrary": "إضافة مكتبة",
|
"ButtonAddLibrary": "إضافة مكتبة",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"ButtonApplyChapters": "Aplikovat kapitoly",
|
"ButtonApplyChapters": "Aplikovat kapitoly",
|
||||||
"ButtonAuthors": "Autoři",
|
"ButtonAuthors": "Autoři",
|
||||||
"ButtonBack": "Zpět",
|
"ButtonBack": "Zpět",
|
||||||
"ButtonBatchEditPopulateFromExisting": "Vytvořit z existujících",
|
"ButtonBatchEditPopulateFromExisting": "Předvyplnit z existujících",
|
||||||
"ButtonBatchEditPopulateMapDetails": "Předvyplnit podrobnosti mapování",
|
"ButtonBatchEditPopulateMapDetails": "Předvyplnit podrobnosti mapování",
|
||||||
"ButtonBrowseForFolder": "Vyhledat složku",
|
"ButtonBrowseForFolder": "Vyhledat složku",
|
||||||
"ButtonCancel": "Zrušit",
|
"ButtonCancel": "Zrušit",
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
"ButtonPause": "Pozastavit",
|
"ButtonPause": "Pozastavit",
|
||||||
"ButtonPlay": "Přehrát",
|
"ButtonPlay": "Přehrát",
|
||||||
"ButtonPlayAll": "Přehrát vše",
|
"ButtonPlayAll": "Přehrát vše",
|
||||||
"ButtonPlaying": "Hraje",
|
"ButtonPlaying": "Přehrává",
|
||||||
"ButtonPlaylists": "Seznamy skladeb",
|
"ButtonPlaylists": "Seznamy skladeb",
|
||||||
"ButtonPrevious": "Předchozí",
|
"ButtonPrevious": "Předchozí",
|
||||||
"ButtonPreviousChapter": "Předchozí Kapitola",
|
"ButtonPreviousChapter": "Předchozí Kapitola",
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
"ButtonQueueAddItem": "Přidat do fronty",
|
"ButtonQueueAddItem": "Přidat do fronty",
|
||||||
"ButtonQueueRemoveItem": "Odstranit z fronty",
|
"ButtonQueueRemoveItem": "Odstranit z fronty",
|
||||||
"ButtonQuickEmbed": "Rychle Zapsat",
|
"ButtonQuickEmbed": "Rychle Zapsat",
|
||||||
"ButtonQuickEmbedMetadata": "Rychle zapsat Metadata",
|
"ButtonQuickEmbedMetadata": "Rychle Vložit Metadata",
|
||||||
"ButtonQuickMatch": "Rychlé přiřazení",
|
"ButtonQuickMatch": "Rychlé přiřazení",
|
||||||
"ButtonReScan": "Znovu prohledat",
|
"ButtonReScan": "Znovu prohledat",
|
||||||
"ButtonRead": "Číst",
|
"ButtonRead": "Číst",
|
||||||
|
|
@ -127,6 +127,7 @@
|
||||||
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
|
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
|
||||||
"HeaderAuthentication": "Autentizace",
|
"HeaderAuthentication": "Autentizace",
|
||||||
"HeaderBackups": "Zálohy",
|
"HeaderBackups": "Zálohy",
|
||||||
|
"HeaderBulkChapterModal": "Přidat více kapitol",
|
||||||
"HeaderChangePassword": "Změnit heslo",
|
"HeaderChangePassword": "Změnit heslo",
|
||||||
"HeaderChapters": "Kapitoly",
|
"HeaderChapters": "Kapitoly",
|
||||||
"HeaderChooseAFolder": "Zvolte složku",
|
"HeaderChooseAFolder": "Zvolte složku",
|
||||||
|
|
@ -308,6 +309,7 @@
|
||||||
"LabelDeleteFromFileSystemCheckbox": "Smazat ze souborového systému (zrušte zaškrtnutí pro odstranění pouze z databáze)",
|
"LabelDeleteFromFileSystemCheckbox": "Smazat ze souborového systému (zrušte zaškrtnutí pro odstranění pouze z databáze)",
|
||||||
"LabelDescription": "Popis",
|
"LabelDescription": "Popis",
|
||||||
"LabelDeselectAll": "Odznačit vše",
|
"LabelDeselectAll": "Odznačit vše",
|
||||||
|
"LabelDetectedPattern": "Detekovaný vzor:",
|
||||||
"LabelDevice": "Zařízení",
|
"LabelDevice": "Zařízení",
|
||||||
"LabelDeviceInfo": "Informace o zařízení",
|
"LabelDeviceInfo": "Informace o zařízení",
|
||||||
"LabelDeviceIsAvailableTo": "Zařízení je dostupné pro...",
|
"LabelDeviceIsAvailableTo": "Zařízení je dostupné pro...",
|
||||||
|
|
@ -361,7 +363,7 @@
|
||||||
"LabelExpiresAt": "Expiruje v",
|
"LabelExpiresAt": "Expiruje v",
|
||||||
"LabelExpiresInSeconds": "Expiruje za (sekundy)",
|
"LabelExpiresInSeconds": "Expiruje za (sekundy)",
|
||||||
"LabelExpiresNever": "Nikdy",
|
"LabelExpiresNever": "Nikdy",
|
||||||
"LabelExplicit": "Explicitně",
|
"LabelExplicit": "Explicitní",
|
||||||
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
|
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
|
||||||
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
|
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
|
||||||
"LabelExportOPML": "Export OPML",
|
"LabelExportOPML": "Export OPML",
|
||||||
|
|
@ -376,6 +378,7 @@
|
||||||
"LabelFilterByUser": "Filtrovat podle uživatele",
|
"LabelFilterByUser": "Filtrovat podle uživatele",
|
||||||
"LabelFindEpisodes": "Najít epizody",
|
"LabelFindEpisodes": "Najít epizody",
|
||||||
"LabelFinished": "Dokončeno",
|
"LabelFinished": "Dokončeno",
|
||||||
|
"LabelFinishedDate": "Dokončeno {0}",
|
||||||
"LabelFolder": "Složka",
|
"LabelFolder": "Složka",
|
||||||
"LabelFolders": "Složky",
|
"LabelFolders": "Složky",
|
||||||
"LabelFontBold": "Tučně",
|
"LabelFontBold": "Tučně",
|
||||||
|
|
@ -390,7 +393,7 @@
|
||||||
"LabelGenres": "Žánry",
|
"LabelGenres": "Žánry",
|
||||||
"LabelHardDeleteFile": "Trvale smazat soubor",
|
"LabelHardDeleteFile": "Trvale smazat soubor",
|
||||||
"LabelHasEbook": "Obsahuje elektronickou knihu",
|
"LabelHasEbook": "Obsahuje elektronickou knihu",
|
||||||
"LabelHasSupplementaryEbook": "Obsahuje doplňkovou elektronickou knihu",
|
"LabelHasSupplementaryEbook": "Obsahuje doplňkovou e-knihu",
|
||||||
"LabelHideSubtitles": "Skrýt titulky",
|
"LabelHideSubtitles": "Skrýt titulky",
|
||||||
"LabelHighestPriority": "Nejvyšší priorita",
|
"LabelHighestPriority": "Nejvyšší priorita",
|
||||||
"LabelHost": "Hostitel",
|
"LabelHost": "Hostitel",
|
||||||
|
|
@ -433,7 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Žádné {0}",
|
"LabelLibraryFilterSublistEmpty": "Žádné {0}",
|
||||||
"LabelLibraryItem": "Položka knihovny",
|
"LabelLibraryItem": "Položka knihovny",
|
||||||
"LabelLibraryName": "Název knihovny",
|
"LabelLibraryName": "Název knihovny",
|
||||||
"LabelLibrarySortByProgress": "Aktualizace pokroku",
|
"LabelLibrarySortByProgress": "Pokrok: naposledy aktualizováno",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Pokrok: dokončeno",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Pokrok: začato",
|
||||||
"LabelLimit": "Omezit",
|
"LabelLimit": "Omezit",
|
||||||
"LabelLineSpacing": "Řádkování",
|
"LabelLineSpacing": "Řádkování",
|
||||||
"LabelListenAgain": "Poslouchat znovu",
|
"LabelListenAgain": "Poslouchat znovu",
|
||||||
|
|
@ -446,7 +451,7 @@
|
||||||
"LabelMatchExistingUsersBy": "Přiřadit stávající uživatele podle",
|
"LabelMatchExistingUsersBy": "Přiřadit stávající uživatele podle",
|
||||||
"LabelMatchExistingUsersByDescription": "Slouží k propojení stávajících uživatelů. Po propojení budou uživatelé přiřazeni k jedinečnému ID od poskytovatele SSO",
|
"LabelMatchExistingUsersByDescription": "Slouží k propojení stávajících uživatelů. Po propojení budou uživatelé přiřazeni k jedinečnému ID od poskytovatele SSO",
|
||||||
"LabelMaxEpisodesToDownload": "Maximální # epizod pro stažení. Použijte 0 pro bez omezení.",
|
"LabelMaxEpisodesToDownload": "Maximální # epizod pro stažení. Použijte 0 pro bez omezení.",
|
||||||
"LabelMaxEpisodesToDownloadPerCheck": "Maximální počet nových epizod ke stažení při jedné kontrole",
|
"LabelMaxEpisodesToDownloadPerCheck": "Maximální # nových epizod ke stažení při jedné kontrole",
|
||||||
"LabelMaxEpisodesToKeep": "Maximální počet epizod k zachování",
|
"LabelMaxEpisodesToKeep": "Maximální počet epizod k zachování",
|
||||||
"LabelMaxEpisodesToKeepHelp": "Hodnotou 0 není nastaven žádný maximální limit. Po automatickém stažení nové epizody se odstraní nejstarší epizoda, pokud máte více než X epizod. Při každém novém stažení se odstraní pouze 1 epizoda.",
|
"LabelMaxEpisodesToKeepHelp": "Hodnotou 0 není nastaven žádný maximální limit. Po automatickém stažení nové epizody se odstraní nejstarší epizoda, pokud máte více než X epizod. Při každém novém stažení se odstraní pouze 1 epizoda.",
|
||||||
"LabelMediaPlayer": "Přehrávač médií",
|
"LabelMediaPlayer": "Přehrávač médií",
|
||||||
|
|
@ -472,6 +477,7 @@
|
||||||
"LabelNewestAuthors": "Nejnovější autoři",
|
"LabelNewestAuthors": "Nejnovější autoři",
|
||||||
"LabelNewestEpisodes": "Nejnovější epizody",
|
"LabelNewestEpisodes": "Nejnovější epizody",
|
||||||
"LabelNextBackupDate": "Datum příští zálohy",
|
"LabelNextBackupDate": "Datum příští zálohy",
|
||||||
|
"LabelNextChapters": "Další kapitola bude:",
|
||||||
"LabelNextScheduledRun": "Další naplánované spuštění",
|
"LabelNextScheduledRun": "Další naplánované spuštění",
|
||||||
"LabelNoApiKeys": "Žádné API klíče",
|
"LabelNoApiKeys": "Žádné API klíče",
|
||||||
"LabelNoCustomMetadataProviders": "Žádní vlastní poskytovatelé metadat",
|
"LabelNoCustomMetadataProviders": "Žádní vlastní poskytovatelé metadat",
|
||||||
|
|
@ -489,6 +495,7 @@
|
||||||
"LabelNotificationsMaxQueueSize": "Maximální velikost fronty pro oznamovací události",
|
"LabelNotificationsMaxQueueSize": "Maximální velikost fronty pro oznamovací události",
|
||||||
"LabelNotificationsMaxQueueSizeHelp": "Události jsou omezeny na 1 za sekundu. Události budou ignorovány, pokud je fronta v maximální velikosti. Tím se zabrání spamování oznámení.",
|
"LabelNotificationsMaxQueueSizeHelp": "Události jsou omezeny na 1 za sekundu. Události budou ignorovány, pokud je fronta v maximální velikosti. Tím se zabrání spamování oznámení.",
|
||||||
"LabelNumberOfBooks": "Počet knih",
|
"LabelNumberOfBooks": "Počet knih",
|
||||||
|
"LabelNumberOfChapters": "Počet kapitol:",
|
||||||
"LabelNumberOfEpisodes": "Počet epizod",
|
"LabelNumberOfEpisodes": "Počet epizod",
|
||||||
"LabelOpenIDAdvancedPermsClaimDescription": "Název požadavku OpenID, který obsahuje rozšířená oprávnění pro akce uživatele v rámci aplikace, která se budou vztahovat na role, které nejsou administrátory (<b>pokud jsou nakonfigurovány</b>). Pokud požadavek v odpovědi chybí, přístup do systému ABS bude zamítnut. Pokud chybí jediná možnost, bude považována za <code>false</code>. Ujistěte se, že deklarace poskytovatele identity odpovídá očekávané struktuře:",
|
"LabelOpenIDAdvancedPermsClaimDescription": "Název požadavku OpenID, který obsahuje rozšířená oprávnění pro akce uživatele v rámci aplikace, která se budou vztahovat na role, které nejsou administrátory (<b>pokud jsou nakonfigurovány</b>). Pokud požadavek v odpovědi chybí, přístup do systému ABS bude zamítnut. Pokud chybí jediná možnost, bude považována za <code>false</code>. Ujistěte se, že deklarace poskytovatele identity odpovídá očekávané struktuře:",
|
||||||
"LabelOpenIDClaims": "Následující možnosti ponechte prázdné, abyste zakázali pokročilé přiřazování skupin a oprávnění a automatické přiřazení skupiny \"User\".",
|
"LabelOpenIDClaims": "Následující možnosti ponechte prázdné, abyste zakázali pokročilé přiřazování skupin a oprávnění a automatické přiřazení skupiny \"User\".",
|
||||||
|
|
@ -631,6 +638,7 @@
|
||||||
"LabelStartTime": "Čas Spuštění",
|
"LabelStartTime": "Čas Spuštění",
|
||||||
"LabelStarted": "Spuštěno",
|
"LabelStarted": "Spuštěno",
|
||||||
"LabelStartedAt": "Spuštěno v",
|
"LabelStartedAt": "Spuštěno v",
|
||||||
|
"LabelStartedDate": "Spuštěno {0}",
|
||||||
"LabelStatsAudioTracks": "Zvukové stopy",
|
"LabelStatsAudioTracks": "Zvukové stopy",
|
||||||
"LabelStatsAuthors": "Autoři",
|
"LabelStatsAuthors": "Autoři",
|
||||||
"LabelStatsBestDay": "Nejlepší den",
|
"LabelStatsBestDay": "Nejlepší den",
|
||||||
|
|
@ -660,6 +668,7 @@
|
||||||
"LabelTheme": "Téma",
|
"LabelTheme": "Téma",
|
||||||
"LabelThemeDark": "Tmavé",
|
"LabelThemeDark": "Tmavé",
|
||||||
"LabelThemeLight": "Světlé",
|
"LabelThemeLight": "Světlé",
|
||||||
|
"LabelThemeSepia": "Hnědé",
|
||||||
"LabelTimeBase": "Časová základna",
|
"LabelTimeBase": "Časová základna",
|
||||||
"LabelTimeDurationXHours": "{0} hodin",
|
"LabelTimeDurationXHours": "{0} hodin",
|
||||||
"LabelTimeDurationXMinutes": "{0} minut",
|
"LabelTimeDurationXMinutes": "{0} minut",
|
||||||
|
|
@ -744,6 +753,7 @@
|
||||||
"MessageBookshelfNoResultsForFilter": "Filtr \"{0}: {1}\"",
|
"MessageBookshelfNoResultsForFilter": "Filtr \"{0}: {1}\"",
|
||||||
"MessageBookshelfNoResultsForQuery": "Žádné výsledky pro dotaz",
|
"MessageBookshelfNoResultsForQuery": "Žádné výsledky pro dotaz",
|
||||||
"MessageBookshelfNoSeries": "Nemáte žádnou sérii",
|
"MessageBookshelfNoSeries": "Nemáte žádnou sérii",
|
||||||
|
"MessageBulkChapterPattern": "Kolik kapitol chcete přidat s tímto vzorem číslování?",
|
||||||
"MessageChapterEndIsAfter": "Konec kapitoly přesahuje konec audioknihy",
|
"MessageChapterEndIsAfter": "Konec kapitoly přesahuje konec audioknihy",
|
||||||
"MessageChapterErrorFirstNotZero": "První kapitola musí začínat na 0",
|
"MessageChapterErrorFirstNotZero": "První kapitola musí začínat na 0",
|
||||||
"MessageChapterErrorStartGteDuration": "Neplatný čas začátku, musí být kratší než doba trvání audioknihy",
|
"MessageChapterErrorStartGteDuration": "Neplatný čas začátku, musí být kratší než doba trvání audioknihy",
|
||||||
|
|
@ -770,7 +780,7 @@
|
||||||
"MessageConfirmMarkItemNotFinished": "Opravdu chcete označit \"{0}\" jako nedokončené?",
|
"MessageConfirmMarkItemNotFinished": "Opravdu chcete označit \"{0}\" jako nedokončené?",
|
||||||
"MessageConfirmMarkSeriesFinished": "Opravdu chcete označit všechny knihy z této série jako dokončené?",
|
"MessageConfirmMarkSeriesFinished": "Opravdu chcete označit všechny knihy z této série jako dokončené?",
|
||||||
"MessageConfirmMarkSeriesNotFinished": "Opravdu chcete označit všechny knihy z této série jako nedokončené?",
|
"MessageConfirmMarkSeriesNotFinished": "Opravdu chcete označit všechny knihy z této série jako nedokončené?",
|
||||||
"MessageConfirmNotificationTestTrigger": "Spustit toto oznámení s testovacími daty?",
|
"MessageConfirmNotificationTestTrigger": "Vyvolat tuto notifikaci s testovacími daty?",
|
||||||
"MessageConfirmPurgeCache": "Vyčistit mezipaměť odstraní celý adresář na adrese <code>/metadata/cache</code>. <br /><br />Určitě chcete odstranit adresář mezipaměti?",
|
"MessageConfirmPurgeCache": "Vyčistit mezipaměť odstraní celý adresář na adrese <code>/metadata/cache</code>. <br /><br />Určitě chcete odstranit adresář mezipaměti?",
|
||||||
"MessageConfirmPurgeItemsCache": "Vyčištění mezipaměti položek odstraní celý adresář <code>/metadata/cache/items</code>.<br />Jste si jistí?",
|
"MessageConfirmPurgeItemsCache": "Vyčištění mezipaměti položek odstraní celý adresář <code>/metadata/cache/items</code>.<br />Jste si jistí?",
|
||||||
"MessageConfirmQuickEmbed": "Varování! Rychlé vložení nezálohuje vaše zvukové soubory. Ujistěte se, že máte zálohu zvukových souborů. <br><br>Chcete pokračovat?",
|
"MessageConfirmQuickEmbed": "Varování! Rychlé vložení nezálohuje vaše zvukové soubory. Ujistěte se, že máte zálohu zvukových souborů. <br><br>Chcete pokračovat?",
|
||||||
|
|
@ -844,7 +854,7 @@
|
||||||
"MessageNoItems": "Žádné položky",
|
"MessageNoItems": "Žádné položky",
|
||||||
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
|
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
|
||||||
"MessageNoListeningSessions": "Žádné poslechové relace",
|
"MessageNoListeningSessions": "Žádné poslechové relace",
|
||||||
"MessageNoLogs": "Žádné logy",
|
"MessageNoLogs": "Žádné záznamy událostí",
|
||||||
"MessageNoMediaProgress": "Žádný průběh médií",
|
"MessageNoMediaProgress": "Žádný průběh médií",
|
||||||
"MessageNoNotifications": "Žádná oznámení",
|
"MessageNoNotifications": "Žádná oznámení",
|
||||||
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
|
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
|
||||||
|
|
@ -874,7 +884,7 @@
|
||||||
"MessageRemoveEpisodes": "Odstranit {0} epizodu",
|
"MessageRemoveEpisodes": "Odstranit {0} epizodu",
|
||||||
"MessageRemoveFromPlayerQueue": "Odstranit z fronty přehrávače",
|
"MessageRemoveFromPlayerQueue": "Odstranit z fronty přehrávače",
|
||||||
"MessageRemoveUserWarning": "Opravdu chcete trvale smazat uživatele \"{0}\"?",
|
"MessageRemoveUserWarning": "Opravdu chcete trvale smazat uživatele \"{0}\"?",
|
||||||
"MessageReportBugsAndContribute": "Hlásit chyby, žádat o funkce a přispívat",
|
"MessageReportBugsAndContribute": "Nahlašte chyby, vyžádejte si funkce a přispěte na",
|
||||||
"MessageResetChaptersConfirm": "Opravdu chcete resetovat kapitoly a vrátit zpět provedené změny?",
|
"MessageResetChaptersConfirm": "Opravdu chcete resetovat kapitoly a vrátit zpět provedené změny?",
|
||||||
"MessageRestoreBackupConfirm": "Opravdu chcete obnovit zálohu vytvořenou dne",
|
"MessageRestoreBackupConfirm": "Opravdu chcete obnovit zálohu vytvořenou dne",
|
||||||
"MessageRestoreBackupWarning": "Obnovení zálohy přepíše celou databázi umístěnou v /config a obálku obrázků v /metadata/items & /metadata/authors.<br /><br />Backups nezmění žádné soubory ve složkách knihovny. Pokud jste povolili nastavení serveru pro ukládání obrázků obalu a metadat do složek knihovny, nebudou zálohovány ani přepsány.<br /><br />Všichni klienti používající váš server budou automaticky obnoveni.",
|
"MessageRestoreBackupWarning": "Obnovení zálohy přepíše celou databázi umístěnou v /config a obálku obrázků v /metadata/items & /metadata/authors.<br /><br />Backups nezmění žádné soubory ve složkách knihovny. Pokud jste povolili nastavení serveru pro ukládání obrázků obalu a metadat do složek knihovny, nebudou zálohovány ani přepsány.<br /><br />Všichni klienti používající váš server budou automaticky obnoveni.",
|
||||||
|
|
@ -907,7 +917,7 @@
|
||||||
"MessageTaskNoFilesToScan": "Žádné soubory k prohledání",
|
"MessageTaskNoFilesToScan": "Žádné soubory k prohledání",
|
||||||
"MessageTaskOpmlImport": "Import OPML",
|
"MessageTaskOpmlImport": "Import OPML",
|
||||||
"MessageTaskOpmlImportDescription": "Vytváření podcastů z {0} RSS feedů",
|
"MessageTaskOpmlImportDescription": "Vytváření podcastů z {0} RSS feedů",
|
||||||
"MessageTaskOpmlImportFeed": "Importní zdroj OPML",
|
"MessageTaskOpmlImportFeed": "Import OPML feedu",
|
||||||
"MessageTaskOpmlImportFeedDescription": "Importování RSS feedu \"{0}\"",
|
"MessageTaskOpmlImportFeedDescription": "Importování RSS feedu \"{0}\"",
|
||||||
"MessageTaskOpmlImportFeedFailed": "Nepodařilo se získat kanál podcastu",
|
"MessageTaskOpmlImportFeedFailed": "Nepodařilo se získat kanál podcastu",
|
||||||
"MessageTaskOpmlImportFeedPodcastDescription": "Vytváření podcastu \"{0}\"",
|
"MessageTaskOpmlImportFeedPodcastDescription": "Vytváření podcastu \"{0}\"",
|
||||||
|
|
@ -947,6 +957,7 @@
|
||||||
"NotificationOnRSSFeedDisabledDescription": "Aktivováno když je automatické stahování pozastaveno z důvodu příliš mnoho neůspěšných pokusů",
|
"NotificationOnRSSFeedDisabledDescription": "Aktivováno když je automatické stahování pozastaveno z důvodu příliš mnoho neůspěšných pokusů",
|
||||||
"NotificationOnRSSFeedFailedDescription": "Aktivováno když selže RSS kanál pro stahování epizod",
|
"NotificationOnRSSFeedFailedDescription": "Aktivováno když selže RSS kanál pro stahování epizod",
|
||||||
"NotificationOnTestDescription": "Akce pro otestování upozorňovacího systému",
|
"NotificationOnTestDescription": "Akce pro otestování upozorňovacího systému",
|
||||||
|
"PlaceholderBulkChapterInput": "Zadejte název kapitoly nebo použije číslování (např. 'Epizoda 1', 'Kapitola 10', '1.')",
|
||||||
"PlaceholderNewCollection": "Nový název kolekce",
|
"PlaceholderNewCollection": "Nový název kolekce",
|
||||||
"PlaceholderNewFolderPath": "Nová cesta ke složce",
|
"PlaceholderNewFolderPath": "Nová cesta ke složce",
|
||||||
"PlaceholderNewPlaylist": "Nový název seznamu přehrávání",
|
"PlaceholderNewPlaylist": "Nový název seznamu přehrávání",
|
||||||
|
|
@ -1000,8 +1011,12 @@
|
||||||
"ToastBookmarkCreateFailed": "Vytvoření záložky se nezdařilo",
|
"ToastBookmarkCreateFailed": "Vytvoření záložky se nezdařilo",
|
||||||
"ToastBookmarkCreateSuccess": "Přidána záložka",
|
"ToastBookmarkCreateSuccess": "Přidána záložka",
|
||||||
"ToastBookmarkRemoveSuccess": "Záložka odstraněna",
|
"ToastBookmarkRemoveSuccess": "Záložka odstraněna",
|
||||||
|
"ToastBulkChapterInvalidCount": "Zadejte číslo mezi 1 a 150",
|
||||||
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
|
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
|
||||||
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
|
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
|
||||||
|
"ToastChapterLocked": "Kapitola je uzamčena.",
|
||||||
|
"ToastChapterStartTimeAdjusted": "Začátek kapitoly posunut o {0} sekund",
|
||||||
|
"ToastChaptersAllLocked": "Všechny kapitoly jsou uzamčeny. Pro posun kapitol některé odemkněte.",
|
||||||
"ToastChaptersHaveErrors": "Kapitoly obsahují chyby",
|
"ToastChaptersHaveErrors": "Kapitoly obsahují chyby",
|
||||||
"ToastChaptersInvalidShiftAmountLast": "Nesprávná délka posunu. Čas začátku poslední kapitoly by přesáhl dobu trvání této audioknihy.",
|
"ToastChaptersInvalidShiftAmountLast": "Nesprávná délka posunu. Čas začátku poslední kapitoly by přesáhl dobu trvání této audioknihy.",
|
||||||
"ToastChaptersInvalidShiftAmountStart": "Nesprávná délka posunu. První kapitola by měla nulovou nebo zápornou délku a byla by přepsána druhou kapitolou. Zvětšete čas začátku druhé kapitoly.",
|
"ToastChaptersInvalidShiftAmountStart": "Nesprávná délka posunu. První kapitola by měla nulovou nebo zápornou délku a byla by přepsána druhou kapitolou. Zvětšete čas začátku druhé kapitoly.",
|
||||||
|
|
@ -1020,7 +1035,7 @@
|
||||||
"ToastDeviceTestEmailFailed": "Odeslání testovacího emailu selhalo",
|
"ToastDeviceTestEmailFailed": "Odeslání testovacího emailu selhalo",
|
||||||
"ToastDeviceTestEmailSuccess": "Testovací email byl odeslán",
|
"ToastDeviceTestEmailSuccess": "Testovací email byl odeslán",
|
||||||
"ToastEmailSettingsUpdateSuccess": "Nastavení emailu aktualizována",
|
"ToastEmailSettingsUpdateSuccess": "Nastavení emailu aktualizována",
|
||||||
"ToastEncodeCancelFailed": "Chyba zrušení kódování",
|
"ToastEncodeCancelFailed": "Zrušení encodování selhalo",
|
||||||
"ToastEncodeCancelSucces": "Kódování zrušeno",
|
"ToastEncodeCancelSucces": "Kódování zrušeno",
|
||||||
"ToastEpisodeDownloadQueueClearFailed": "Vyčištění fronty selhalo",
|
"ToastEpisodeDownloadQueueClearFailed": "Vyčištění fronty selhalo",
|
||||||
"ToastEpisodeDownloadQueueClearSuccess": "Fronta stahování epizod je prázdná",
|
"ToastEpisodeDownloadQueueClearSuccess": "Fronta stahování epizod je prázdná",
|
||||||
|
|
@ -1085,6 +1100,7 @@
|
||||||
"ToastPlaylistUpdateSuccess": "Seznam přehrávání aktualizován",
|
"ToastPlaylistUpdateSuccess": "Seznam přehrávání aktualizován",
|
||||||
"ToastPodcastCreateFailed": "Vytvoření podcastu se nezdařilo",
|
"ToastPodcastCreateFailed": "Vytvoření podcastu se nezdařilo",
|
||||||
"ToastPodcastCreateSuccess": "Podcast byl úspěšně vytvořen",
|
"ToastPodcastCreateSuccess": "Podcast byl úspěšně vytvořen",
|
||||||
|
"ToastPodcastEpisodeUpdated": "Epizoda aktualizována",
|
||||||
"ToastPodcastGetFeedFailed": "Chyba při získání podcastového feedu",
|
"ToastPodcastGetFeedFailed": "Chyba při získání podcastového feedu",
|
||||||
"ToastPodcastNoEpisodesInFeed": "Žádné epizody nenalezeny v RSS feedu",
|
"ToastPodcastNoEpisodesInFeed": "Žádné epizody nenalezeny v RSS feedu",
|
||||||
"ToastPodcastNoRssFeed": "Podcast nemá RSS feed",
|
"ToastPodcastNoRssFeed": "Podcast nemá RSS feed",
|
||||||
|
|
@ -1117,7 +1133,7 @@
|
||||||
"ToastSessionDeleteFailed": "Nepodařilo se smazat relaci",
|
"ToastSessionDeleteFailed": "Nepodařilo se smazat relaci",
|
||||||
"ToastSessionDeleteSuccess": "Relace smazána",
|
"ToastSessionDeleteSuccess": "Relace smazána",
|
||||||
"ToastSleepTimerDone": "Uspání knížky ... zZzzZz",
|
"ToastSleepTimerDone": "Uspání knížky ... zZzzZz",
|
||||||
"ToastSlugMustChange": "Slug (URL) obsahuje chybné znaky",
|
"ToastSlugMustChange": "Slug obsahuje chybné znaky",
|
||||||
"ToastSlugRequired": "Slug (URL) je vyžadována",
|
"ToastSlugRequired": "Slug (URL) je vyžadována",
|
||||||
"ToastSocketConnected": "Socket připojen",
|
"ToastSocketConnected": "Socket připojen",
|
||||||
"ToastSocketDisconnected": "Socket odpojen",
|
"ToastSocketDisconnected": "Socket odpojen",
|
||||||
|
|
@ -1135,5 +1151,13 @@
|
||||||
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",
|
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",
|
||||||
"ToastUserPasswordMismatch": "Hesla se neschodují",
|
"ToastUserPasswordMismatch": "Hesla se neschodují",
|
||||||
"ToastUserPasswordMustChange": "Nové heslo se musí lišit od předchozího",
|
"ToastUserPasswordMustChange": "Nové heslo se musí lišit od předchozího",
|
||||||
"ToastUserRootRequireName": "Musíte zadat uživatelské jméno root"
|
"ToastUserRootRequireName": "Musíte zadat uživatelské jméno root",
|
||||||
|
"TooltipAddChapters": "Přidat kapitolu/y",
|
||||||
|
"TooltipAddOneSecond": "Přidat 1 sekundu",
|
||||||
|
"TooltipAdjustChapterStart": "Kliknutím upravte začátek",
|
||||||
|
"TooltipLockAllChapters": "Uzamknout všechny kapitoly",
|
||||||
|
"TooltipLockChapter": "Uzamknout kapitolu (Shift+klik pro rozsah)",
|
||||||
|
"TooltipSubtractOneSecond": "Odečíst 1 sekundu",
|
||||||
|
"TooltipUnlockAllChapters": "Odemknout všechny kapitoly",
|
||||||
|
"TooltipUnlockChapter": "Odemknout kapitolu (Shift+klik pro rozsah)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
"ButtonNext": "Vor",
|
"ButtonNext": "Vor",
|
||||||
"ButtonNextChapter": "Nächstes Kapitel",
|
"ButtonNextChapter": "Nächstes Kapitel",
|
||||||
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
|
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
|
||||||
"ButtonOk": "Ok",
|
"ButtonOk": "OK",
|
||||||
"ButtonOpenFeed": "Feed öffnen",
|
"ButtonOpenFeed": "Feed öffnen",
|
||||||
"ButtonOpenManager": "Manager öffnen",
|
"ButtonOpenManager": "Manager öffnen",
|
||||||
"ButtonPause": "Pausieren",
|
"ButtonPause": "Pausieren",
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
"ButtonQuickMatch": "Schnellabgleich",
|
"ButtonQuickMatch": "Schnellabgleich",
|
||||||
"ButtonReScan": "Neu scannen",
|
"ButtonReScan": "Neu scannen",
|
||||||
"ButtonRead": "Lesen",
|
"ButtonRead": "Lesen",
|
||||||
"ButtonReadLess": "weniger Anzeigen",
|
"ButtonReadLess": "Weniger Anzeigen",
|
||||||
"ButtonReadMore": "Mehr Anzeigen",
|
"ButtonReadMore": "Mehr Anzeigen",
|
||||||
"ButtonRefresh": "Neu Laden",
|
"ButtonRefresh": "Neu Laden",
|
||||||
"ButtonRemove": "Entfernen",
|
"ButtonRemove": "Entfernen",
|
||||||
|
|
@ -104,7 +104,7 @@
|
||||||
"ButtonStartM4BEncode": "M4B-Kodierung starten",
|
"ButtonStartM4BEncode": "M4B-Kodierung starten",
|
||||||
"ButtonStartMetadataEmbed": "Metadateneinbettung starten",
|
"ButtonStartMetadataEmbed": "Metadateneinbettung starten",
|
||||||
"ButtonStats": "Statistiken",
|
"ButtonStats": "Statistiken",
|
||||||
"ButtonSubmit": "Ok",
|
"ButtonSubmit": "Absenden",
|
||||||
"ButtonTest": "Test",
|
"ButtonTest": "Test",
|
||||||
"ButtonUnlinkOpenId": "OpenID trennen",
|
"ButtonUnlinkOpenId": "OpenID trennen",
|
||||||
"ButtonUpload": "Hochladen",
|
"ButtonUpload": "Hochladen",
|
||||||
|
|
@ -116,7 +116,7 @@
|
||||||
"ButtonViewAll": "Alles anzeigen",
|
"ButtonViewAll": "Alles anzeigen",
|
||||||
"ButtonYes": "Ja",
|
"ButtonYes": "Ja",
|
||||||
"ErrorUploadFetchMetadataAPI": "Fehler beim Abrufen der Metadaten",
|
"ErrorUploadFetchMetadataAPI": "Fehler beim Abrufen der Metadaten",
|
||||||
"ErrorUploadFetchMetadataNoResults": "Metadaten konnten nicht abgerufen werden. Versuche den Titel und oder den Autor zu aktualisieren",
|
"ErrorUploadFetchMetadataNoResults": "Metadaten konnten nicht abgerufen werden. Versuche den Titel und/oder den Autor zu aktualisieren.",
|
||||||
"ErrorUploadLacksTitle": "Es muss ein Titel eingegeben werden",
|
"ErrorUploadLacksTitle": "Es muss ein Titel eingegeben werden",
|
||||||
"HeaderAccount": "Konto",
|
"HeaderAccount": "Konto",
|
||||||
"HeaderAddCustomMetadataProvider": "Benutzerdefinierten Metadatenanbieter hinzufügen",
|
"HeaderAddCustomMetadataProvider": "Benutzerdefinierten Metadatenanbieter hinzufügen",
|
||||||
|
|
@ -138,13 +138,13 @@
|
||||||
"HeaderCustomMessageOnLogin": "Benutzerdefinierte Nachricht für die Anmeldung",
|
"HeaderCustomMessageOnLogin": "Benutzerdefinierte Nachricht für die Anmeldung",
|
||||||
"HeaderCustomMetadataProviders": "Benutzerdefinierte Metadatenanbieter",
|
"HeaderCustomMetadataProviders": "Benutzerdefinierte Metadatenanbieter",
|
||||||
"HeaderDetails": "Details",
|
"HeaderDetails": "Details",
|
||||||
"HeaderDownloadQueue": "Download Warteschlange",
|
"HeaderDownloadQueue": "Download-Warteschlange",
|
||||||
"HeaderEbookFiles": "E-Buch-Dateien",
|
"HeaderEbookFiles": "E-Book-Dateien",
|
||||||
"HeaderEmail": "E-Mail",
|
"HeaderEmail": "E-Mail",
|
||||||
"HeaderEmailSettings": "E-Mail-Einstellungen",
|
"HeaderEmailSettings": "E-Mail-Einstellungen",
|
||||||
"HeaderEpisodes": "Episoden",
|
"HeaderEpisodes": "Episoden",
|
||||||
"HeaderEreaderDevices": "E-Reader Geräte",
|
"HeaderEreaderDevices": "E-Reader Geräte",
|
||||||
"HeaderEreaderSettings": "Einstellungen zum Lesen",
|
"HeaderEreaderSettings": "E-Reader-Einstellungen",
|
||||||
"HeaderFiles": "Dateien",
|
"HeaderFiles": "Dateien",
|
||||||
"HeaderFindChapters": "Kapitel suchen",
|
"HeaderFindChapters": "Kapitel suchen",
|
||||||
"HeaderIgnoredFiles": "Ignorierte Dateien",
|
"HeaderIgnoredFiles": "Ignorierte Dateien",
|
||||||
|
|
@ -378,6 +378,7 @@
|
||||||
"LabelFilterByUser": "Nach Benutzern filtern",
|
"LabelFilterByUser": "Nach Benutzern filtern",
|
||||||
"LabelFindEpisodes": "Episoden suchen",
|
"LabelFindEpisodes": "Episoden suchen",
|
||||||
"LabelFinished": "Beendet",
|
"LabelFinished": "Beendet",
|
||||||
|
"LabelFinishedDate": "Beendet {0}",
|
||||||
"LabelFolder": "Ordner",
|
"LabelFolder": "Ordner",
|
||||||
"LabelFolders": "Verzeichnisse",
|
"LabelFolders": "Verzeichnisse",
|
||||||
"LabelFontBold": "Fett",
|
"LabelFontBold": "Fett",
|
||||||
|
|
@ -435,7 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Keine {0}",
|
"LabelLibraryFilterSublistEmpty": "Keine {0}",
|
||||||
"LabelLibraryItem": "Bibliothekseintrag",
|
"LabelLibraryItem": "Bibliothekseintrag",
|
||||||
"LabelLibraryName": "Bibliotheksname",
|
"LabelLibraryName": "Bibliotheksname",
|
||||||
"LabelLibrarySortByProgress": "Fortschritt aktualisiert",
|
"LabelLibrarySortByProgress": "Fortschritt: Zuletzt aktualisiert",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Fortschritt: Beendet",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Fortschritt: Gestartet",
|
||||||
"LabelLimit": "Begrenzung",
|
"LabelLimit": "Begrenzung",
|
||||||
"LabelLineSpacing": "Zeilenabstand",
|
"LabelLineSpacing": "Zeilenabstand",
|
||||||
"LabelListenAgain": "Erneut anhören",
|
"LabelListenAgain": "Erneut anhören",
|
||||||
|
|
@ -635,6 +638,7 @@
|
||||||
"LabelStartTime": "Startzeit",
|
"LabelStartTime": "Startzeit",
|
||||||
"LabelStarted": "Gestartet",
|
"LabelStarted": "Gestartet",
|
||||||
"LabelStartedAt": "Gestartet am",
|
"LabelStartedAt": "Gestartet am",
|
||||||
|
"LabelStartedDate": "Angefangen am {0}",
|
||||||
"LabelStatsAudioTracks": "Audiodateien",
|
"LabelStatsAudioTracks": "Audiodateien",
|
||||||
"LabelStatsAuthors": "Autoren",
|
"LabelStatsAuthors": "Autoren",
|
||||||
"LabelStatsBestDay": "Bester Tag",
|
"LabelStatsBestDay": "Bester Tag",
|
||||||
|
|
@ -1096,6 +1100,7 @@
|
||||||
"ToastPlaylistUpdateSuccess": "Wiedergabeliste aktualisiert",
|
"ToastPlaylistUpdateSuccess": "Wiedergabeliste aktualisiert",
|
||||||
"ToastPodcastCreateFailed": "Podcast konnte nicht erstellt werden",
|
"ToastPodcastCreateFailed": "Podcast konnte nicht erstellt werden",
|
||||||
"ToastPodcastCreateSuccess": "Podcast erstellt",
|
"ToastPodcastCreateSuccess": "Podcast erstellt",
|
||||||
|
"ToastPodcastEpisodeUpdated": "Podcast-Folge aktualisiert",
|
||||||
"ToastPodcastGetFeedFailed": "Fehler beim abrufen des Podcast Feeds",
|
"ToastPodcastGetFeedFailed": "Fehler beim abrufen des Podcast Feeds",
|
||||||
"ToastPodcastNoEpisodesInFeed": "Keine Episoden in RSS Feed gefunden",
|
"ToastPodcastNoEpisodesInFeed": "Keine Episoden in RSS Feed gefunden",
|
||||||
"ToastPodcastNoRssFeed": "Podcast enthält keinen RSS Feed",
|
"ToastPodcastNoRssFeed": "Podcast enthält keinen RSS Feed",
|
||||||
|
|
|
||||||
|
|
@ -1026,6 +1026,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "Item(s) added to collection failed",
|
"ToastCollectionItemsAddFailed": "Item(s) added to collection failed",
|
||||||
"ToastCollectionRemoveSuccess": "Collection removed",
|
"ToastCollectionRemoveSuccess": "Collection removed",
|
||||||
"ToastCollectionUpdateSuccess": "Collection updated",
|
"ToastCollectionUpdateSuccess": "Collection updated",
|
||||||
|
"ToastConnectionNotAvailable": "Connection not available. Please try again later",
|
||||||
|
"ToastCoverSearchFailed": "Cover search failed",
|
||||||
"ToastCoverUpdateFailed": "Cover update failed",
|
"ToastCoverUpdateFailed": "Cover update failed",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "Date and time is invalid or incomplete",
|
"ToastDateTimeInvalidOrIncomplete": "Date and time is invalid or incomplete",
|
||||||
"ToastDeleteFileFailed": "Failed to delete file",
|
"ToastDeleteFileFailed": "Failed to delete file",
|
||||||
|
|
|
||||||
28
client/strings/fa.json
Normal file
28
client/strings/fa.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"ButtonAdd": "افزودن",
|
||||||
|
"ButtonAuthors": "ناشر",
|
||||||
|
"ButtonBack": "بازگشت",
|
||||||
|
"ButtonCancel": "انصراف",
|
||||||
|
"ButtonClearFilter": "حذف صافی",
|
||||||
|
"ButtonCloseFeed": "بستن فید",
|
||||||
|
"ButtonCollections": "مجموعه ها",
|
||||||
|
"ButtonCreate": "ساختن",
|
||||||
|
"ButtonDelete": "حذف",
|
||||||
|
"ButtonHome": "خانه",
|
||||||
|
"ButtonIssues": "مشکلات",
|
||||||
|
"ButtonLatest": "جدیدترین",
|
||||||
|
"ButtonLibrary": "کتابخانه",
|
||||||
|
"ButtonOk": "تایید",
|
||||||
|
"ButtonOpenFeed": "باز کردن فید",
|
||||||
|
"ButtonPause": "توقف",
|
||||||
|
"ButtonPlay": "پخش",
|
||||||
|
"ButtonPlaylists": "لیست پخش",
|
||||||
|
"ButtonRead": "خواندن",
|
||||||
|
"ButtonReadLess": "خواندن کمتر",
|
||||||
|
"ButtonReadMore": "خواندن بیشتر",
|
||||||
|
"ButtonRemove": "حذف",
|
||||||
|
"ButtonSave": "ذخیره",
|
||||||
|
"ButtonSearch": "جستجو",
|
||||||
|
"ButtonSeries": "مجموعه",
|
||||||
|
"ButtonSubmit": "ثبت"
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"ButtonAdd": "Lisää",
|
"ButtonAdd": "Lisää",
|
||||||
|
"ButtonAddApiKey": "Lisää API avain",
|
||||||
"ButtonAddChapters": "Lisää lukuja",
|
"ButtonAddChapters": "Lisää lukuja",
|
||||||
"ButtonAddDevice": "Lisää laite",
|
"ButtonAddDevice": "Lisää laite",
|
||||||
"ButtonAddLibrary": "Lisää kirjasto",
|
"ButtonAddLibrary": "Lisää kirjasto",
|
||||||
|
|
@ -20,6 +21,7 @@
|
||||||
"ButtonChooseAFolder": "Valitse kansio",
|
"ButtonChooseAFolder": "Valitse kansio",
|
||||||
"ButtonChooseFiles": "Valitse tiedostot",
|
"ButtonChooseFiles": "Valitse tiedostot",
|
||||||
"ButtonClearFilter": "Poista suodatus",
|
"ButtonClearFilter": "Poista suodatus",
|
||||||
|
"ButtonClose": "Sulje",
|
||||||
"ButtonCloseFeed": "Sulje syöte",
|
"ButtonCloseFeed": "Sulje syöte",
|
||||||
"ButtonCloseSession": "Sulje Avoin Sessio",
|
"ButtonCloseSession": "Sulje Avoin Sessio",
|
||||||
"ButtonCollections": "Kokoelmat",
|
"ButtonCollections": "Kokoelmat",
|
||||||
|
|
@ -119,11 +121,13 @@
|
||||||
"HeaderAccount": "Tili",
|
"HeaderAccount": "Tili",
|
||||||
"HeaderAddCustomMetadataProvider": "Lisää mukautettu metadata tarjoaja",
|
"HeaderAddCustomMetadataProvider": "Lisää mukautettu metadata tarjoaja",
|
||||||
"HeaderAdvanced": "Edistynyt",
|
"HeaderAdvanced": "Edistynyt",
|
||||||
|
"HeaderApiKeys": "API avaimet",
|
||||||
"HeaderAppriseNotificationSettings": "Apprise-ilmoitusasetukset",
|
"HeaderAppriseNotificationSettings": "Apprise-ilmoitusasetukset",
|
||||||
"HeaderAudioTracks": "Ääniraidat",
|
"HeaderAudioTracks": "Ääniraidat",
|
||||||
"HeaderAudiobookTools": "Äänikirjojen tiedostonhallintatyökalut",
|
"HeaderAudiobookTools": "Äänikirjojen tiedostonhallintatyökalut",
|
||||||
"HeaderAuthentication": "Todennus",
|
"HeaderAuthentication": "Todennus",
|
||||||
"HeaderBackups": "Varmuuskopiot",
|
"HeaderBackups": "Varmuuskopiot",
|
||||||
|
"HeaderBulkChapterModal": "Lisää useita kappaleita",
|
||||||
"HeaderChangePassword": "Vaihda salasana",
|
"HeaderChangePassword": "Vaihda salasana",
|
||||||
"HeaderChapters": "Luvut",
|
"HeaderChapters": "Luvut",
|
||||||
"HeaderChooseAFolder": "Valitse kansio",
|
"HeaderChooseAFolder": "Valitse kansio",
|
||||||
|
|
@ -162,6 +166,7 @@
|
||||||
"HeaderMetadataOrderOfPrecedence": "Metadatan tärkeysjärjestys",
|
"HeaderMetadataOrderOfPrecedence": "Metadatan tärkeysjärjestys",
|
||||||
"HeaderMetadataToEmbed": "Sisällytettävä metadata",
|
"HeaderMetadataToEmbed": "Sisällytettävä metadata",
|
||||||
"HeaderNewAccount": "Uusi tili",
|
"HeaderNewAccount": "Uusi tili",
|
||||||
|
"HeaderNewApiKey": "Uusi API avain",
|
||||||
"HeaderNewLibrary": "Uusi kirjasto",
|
"HeaderNewLibrary": "Uusi kirjasto",
|
||||||
"HeaderNotificationCreate": "Luo ilmoitus",
|
"HeaderNotificationCreate": "Luo ilmoitus",
|
||||||
"HeaderNotificationUpdate": "Päivitä ilmoitus",
|
"HeaderNotificationUpdate": "Päivitä ilmoitus",
|
||||||
|
|
@ -194,6 +199,7 @@
|
||||||
"HeaderSettingsExperimental": "Kokeelliset ominaisuudet",
|
"HeaderSettingsExperimental": "Kokeelliset ominaisuudet",
|
||||||
"HeaderSettingsGeneral": "Yleiset",
|
"HeaderSettingsGeneral": "Yleiset",
|
||||||
"HeaderSettingsScanner": "Skannaaja",
|
"HeaderSettingsScanner": "Skannaaja",
|
||||||
|
"HeaderSettingsSecurity": "Turvallisuus",
|
||||||
"HeaderSettingsWebClient": "Webasiakasohjelma",
|
"HeaderSettingsWebClient": "Webasiakasohjelma",
|
||||||
"HeaderSleepTimer": "Uniajastin",
|
"HeaderSleepTimer": "Uniajastin",
|
||||||
"HeaderStatsLargestItems": "Suurimmat kohteet",
|
"HeaderStatsLargestItems": "Suurimmat kohteet",
|
||||||
|
|
@ -205,6 +211,7 @@
|
||||||
"HeaderTableOfContents": "Sisällysluettelo",
|
"HeaderTableOfContents": "Sisällysluettelo",
|
||||||
"HeaderTools": "Työkalut",
|
"HeaderTools": "Työkalut",
|
||||||
"HeaderUpdateAccount": "Päivitä tili",
|
"HeaderUpdateAccount": "Päivitä tili",
|
||||||
|
"HeaderUpdateApiKey": "Päivitä API avain",
|
||||||
"HeaderUpdateAuthor": "Päivitä tekijä",
|
"HeaderUpdateAuthor": "Päivitä tekijä",
|
||||||
"HeaderUpdateDetails": "Päivitä yksityiskohdat",
|
"HeaderUpdateDetails": "Päivitä yksityiskohdat",
|
||||||
"HeaderUpdateLibrary": "Päivitä kirjasto",
|
"HeaderUpdateLibrary": "Päivitä kirjasto",
|
||||||
|
|
@ -234,6 +241,8 @@
|
||||||
"LabelAllUsersExcludingGuests": "Kaikki käyttäjät vieraita lukuun ottamatta",
|
"LabelAllUsersExcludingGuests": "Kaikki käyttäjät vieraita lukuun ottamatta",
|
||||||
"LabelAllUsersIncludingGuests": "Kaikki käyttäjät mukaan lukien vieraat",
|
"LabelAllUsersIncludingGuests": "Kaikki käyttäjät mukaan lukien vieraat",
|
||||||
"LabelAlreadyInYourLibrary": "Jo kirjastossasi",
|
"LabelAlreadyInYourLibrary": "Jo kirjastossasi",
|
||||||
|
"LabelApiKeyCreated": "API avain \"{0}\" luotu onnistuneesti.",
|
||||||
|
"LabelApiKeyCreatedDescription": "Varmista, että kopioit API avaimen. Sitä ei näytetä enää tämän jälkeen.",
|
||||||
"LabelApiToken": "Sovellusliittymätunnus",
|
"LabelApiToken": "Sovellusliittymätunnus",
|
||||||
"LabelAppend": "Lisää loppuun",
|
"LabelAppend": "Lisää loppuun",
|
||||||
"LabelAudioBitrate": "Äänen bittinopeus (esim. 128k)",
|
"LabelAudioBitrate": "Äänen bittinopeus (esim. 128k)",
|
||||||
|
|
@ -283,6 +292,7 @@
|
||||||
"LabelContinueListening": "Jatka kuuntelua",
|
"LabelContinueListening": "Jatka kuuntelua",
|
||||||
"LabelContinueReading": "Jatka lukemista",
|
"LabelContinueReading": "Jatka lukemista",
|
||||||
"LabelContinueSeries": "Jatka sarjoja",
|
"LabelContinueSeries": "Jatka sarjoja",
|
||||||
|
"LabelCorsAllowed": "Salli CORS Origins",
|
||||||
"LabelCover": "Kansikuva",
|
"LabelCover": "Kansikuva",
|
||||||
"LabelCoverImageURL": "Kansikuvan URL-osoite",
|
"LabelCoverImageURL": "Kansikuvan URL-osoite",
|
||||||
"LabelCoverProvider": "Kansikuvan tarjoaja",
|
"LabelCoverProvider": "Kansikuvan tarjoaja",
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
"ButtonReScan": "Nouvelle analyse",
|
"ButtonReScan": "Nouvelle analyse",
|
||||||
"ButtonRead": "Lire",
|
"ButtonRead": "Lire",
|
||||||
"ButtonReadLess": "Lire moins",
|
"ButtonReadLess": "Lire moins",
|
||||||
"ButtonReadMore": "Lire la suite",
|
"ButtonReadMore": "Lire plus",
|
||||||
"ButtonRefresh": "Rafraîchir",
|
"ButtonRefresh": "Rafraîchir",
|
||||||
"ButtonRemove": "Retirer",
|
"ButtonRemove": "Retirer",
|
||||||
"ButtonRemoveAll": "Supprimer tout",
|
"ButtonRemoveAll": "Supprimer tout",
|
||||||
|
|
@ -378,6 +378,7 @@
|
||||||
"LabelFilterByUser": "Filtrer par utilisateur",
|
"LabelFilterByUser": "Filtrer par utilisateur",
|
||||||
"LabelFindEpisodes": "Trouver des épisodes",
|
"LabelFindEpisodes": "Trouver des épisodes",
|
||||||
"LabelFinished": "Terminé le",
|
"LabelFinished": "Terminé le",
|
||||||
|
"LabelFinishedDate": "Terminé {0}",
|
||||||
"LabelFolder": "Dossier",
|
"LabelFolder": "Dossier",
|
||||||
"LabelFolders": "Dossiers",
|
"LabelFolders": "Dossiers",
|
||||||
"LabelFontBold": "Gras",
|
"LabelFontBold": "Gras",
|
||||||
|
|
@ -435,7 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Aucun {0}",
|
"LabelLibraryFilterSublistEmpty": "Aucun {0}",
|
||||||
"LabelLibraryItem": "Élément de bibliothèque",
|
"LabelLibraryItem": "Élément de bibliothèque",
|
||||||
"LabelLibraryName": "Nom de la bibliothèque",
|
"LabelLibraryName": "Nom de la bibliothèque",
|
||||||
"LabelLibrarySortByProgress": "Progression mise à jour",
|
"LabelLibrarySortByProgress": "Progression : dernière mise à jour",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Progression : Terminé",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Progression : Commencé",
|
||||||
"LabelLimit": "Limite",
|
"LabelLimit": "Limite",
|
||||||
"LabelLineSpacing": "Espacement des lignes",
|
"LabelLineSpacing": "Espacement des lignes",
|
||||||
"LabelListenAgain": "Écouter à nouveau",
|
"LabelListenAgain": "Écouter à nouveau",
|
||||||
|
|
@ -635,6 +638,7 @@
|
||||||
"LabelStartTime": "Heure de démarrage",
|
"LabelStartTime": "Heure de démarrage",
|
||||||
"LabelStarted": "Démarré",
|
"LabelStarted": "Démarré",
|
||||||
"LabelStartedAt": "Démarré à",
|
"LabelStartedAt": "Démarré à",
|
||||||
|
"LabelStartedDate": "Commencé {0}",
|
||||||
"LabelStatsAudioTracks": "Pistes audio",
|
"LabelStatsAudioTracks": "Pistes audio",
|
||||||
"LabelStatsAuthors": "Auteurs",
|
"LabelStatsAuthors": "Auteurs",
|
||||||
"LabelStatsBestDay": "Meilleur jour",
|
"LabelStatsBestDay": "Meilleur jour",
|
||||||
|
|
@ -871,7 +875,7 @@
|
||||||
"MessagePlaylistCreateFromCollection": "Créer une liste de lecture depuis la collection",
|
"MessagePlaylistCreateFromCollection": "Créer une liste de lecture depuis la collection",
|
||||||
"MessagePleaseWait": "Merci de patienter…",
|
"MessagePleaseWait": "Merci de patienter…",
|
||||||
"MessagePodcastHasNoRSSFeedForMatching": "Le Podcast n’a pas d’URL de flux RSS à utiliser pour la correspondance",
|
"MessagePodcastHasNoRSSFeedForMatching": "Le Podcast n’a pas d’URL de flux RSS à utiliser pour la correspondance",
|
||||||
"MessagePodcastSearchField": "Saisissez le terme de recherche ou l'URL du flux RSS",
|
"MessagePodcastSearchField": "Saisir un terme de recherche ou l'URL d'un flux RSS",
|
||||||
"MessageQuickEmbedInProgress": "Intégration rapide en cours",
|
"MessageQuickEmbedInProgress": "Intégration rapide en cours",
|
||||||
"MessageQuickEmbedQueue": "En file d'attente pour une intégration rapide ({0} dans la file d'attente)",
|
"MessageQuickEmbedQueue": "En file d'attente pour une intégration rapide ({0} dans la file d'attente)",
|
||||||
"MessageQuickMatchAllEpisodes": "Associer rapidement tous les épisodes",
|
"MessageQuickMatchAllEpisodes": "Associer rapidement tous les épisodes",
|
||||||
|
|
@ -958,7 +962,7 @@
|
||||||
"PlaceholderNewFolderPath": "Nouveau chemin de dossier",
|
"PlaceholderNewFolderPath": "Nouveau chemin de dossier",
|
||||||
"PlaceholderNewPlaylist": "Nouveau nom de liste de lecture",
|
"PlaceholderNewPlaylist": "Nouveau nom de liste de lecture",
|
||||||
"PlaceholderSearch": "Recherche…",
|
"PlaceholderSearch": "Recherche…",
|
||||||
"PlaceholderSearchEpisode": "Rechercher un épisode…",
|
"PlaceholderSearchEpisode": "Rechercher un épisode..",
|
||||||
"StatsAuthorsAdded": "auteurs ajoutés",
|
"StatsAuthorsAdded": "auteurs ajoutés",
|
||||||
"StatsBooksAdded": "livres ajoutés",
|
"StatsBooksAdded": "livres ajoutés",
|
||||||
"StatsBooksAdditional": "Les ajouts comprennent…",
|
"StatsBooksAdditional": "Les ajouts comprennent…",
|
||||||
|
|
@ -1010,6 +1014,8 @@
|
||||||
"ToastBulkChapterInvalidCount": "Veuillez entrer un nombre valide entre 1 et 150",
|
"ToastBulkChapterInvalidCount": "Veuillez entrer un nombre valide entre 1 et 150",
|
||||||
"ToastCachePurgeFailed": "Échec de la purge du cache",
|
"ToastCachePurgeFailed": "Échec de la purge du cache",
|
||||||
"ToastCachePurgeSuccess": "Cache purgé avec succès",
|
"ToastCachePurgeSuccess": "Cache purgé avec succès",
|
||||||
|
"ToastChapterLocked": "Le chapitre est verrouillé.",
|
||||||
|
"ToastChapterStartTimeAdjusted": "Début du chapitre ajusté de {0} secondes",
|
||||||
"ToastChaptersAllLocked": "Tous les chapitres sont verrouillés. Déverrouillez certains chapitres pour décaler leurs temps.",
|
"ToastChaptersAllLocked": "Tous les chapitres sont verrouillés. Déverrouillez certains chapitres pour décaler leurs temps.",
|
||||||
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
|
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
|
||||||
"ToastChaptersInvalidShiftAmountLast": "Durée de décalage non valide. L’heure de début du dernier chapitre pourrait dépasser la durée de ce livre audio.",
|
"ToastChaptersInvalidShiftAmountLast": "Durée de décalage non valide. L’heure de début du dernier chapitre pourrait dépasser la durée de ce livre audio.",
|
||||||
|
|
@ -1094,6 +1100,7 @@
|
||||||
"ToastPlaylistUpdateSuccess": "Liste de lecture mise à jour",
|
"ToastPlaylistUpdateSuccess": "Liste de lecture mise à jour",
|
||||||
"ToastPodcastCreateFailed": "Échec de la création du podcast",
|
"ToastPodcastCreateFailed": "Échec de la création du podcast",
|
||||||
"ToastPodcastCreateSuccess": "Podcast créé avec succès",
|
"ToastPodcastCreateSuccess": "Podcast créé avec succès",
|
||||||
|
"ToastPodcastEpisodeUpdated": "Épisode mis à jour",
|
||||||
"ToastPodcastGetFeedFailed": "Échec de la récupération du flux du podcast",
|
"ToastPodcastGetFeedFailed": "Échec de la récupération du flux du podcast",
|
||||||
"ToastPodcastNoEpisodesInFeed": "Aucun épisode trouvé dans le flux RSS",
|
"ToastPodcastNoEpisodesInFeed": "Aucun épisode trouvé dans le flux RSS",
|
||||||
"ToastPodcastNoRssFeed": "Le podcast n’a pas de flux RSS",
|
"ToastPodcastNoRssFeed": "Le podcast n’a pas de flux RSS",
|
||||||
|
|
@ -1147,6 +1154,7 @@
|
||||||
"ToastUserRootRequireName": "Vous devez entrer un nom d’utilisateur root",
|
"ToastUserRootRequireName": "Vous devez entrer un nom d’utilisateur root",
|
||||||
"TooltipAddChapters": "Ajouter chapitre(s)",
|
"TooltipAddChapters": "Ajouter chapitre(s)",
|
||||||
"TooltipAddOneSecond": "Ajouter 1 seconde",
|
"TooltipAddOneSecond": "Ajouter 1 seconde",
|
||||||
|
"TooltipAdjustChapterStart": "Cliquez pour régler l'heure de début",
|
||||||
"TooltipLockAllChapters": "Verrouiller tous les chapitres",
|
"TooltipLockAllChapters": "Verrouiller tous les chapitres",
|
||||||
"TooltipLockChapter": "Verrouiller le chapitre (Maj+clic pour plage)",
|
"TooltipLockChapter": "Verrouiller le chapitre (Maj+clic pour plage)",
|
||||||
"TooltipSubtractOneSecond": "Soustraire 1 seconde",
|
"TooltipSubtractOneSecond": "Soustraire 1 seconde",
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@
|
||||||
"LabelExample": "דוגמה",
|
"LabelExample": "דוגמה",
|
||||||
"LabelExpandSeries": "הרחב סדרה",
|
"LabelExpandSeries": "הרחב סדרה",
|
||||||
"LabelExpandSubSeries": "הרחב תת סדרה",
|
"LabelExpandSubSeries": "הרחב תת סדרה",
|
||||||
"LabelExplicit": "בוטה",
|
"LabelExplicit": "מפורש",
|
||||||
"LabelExplicitChecked": "בוטה (מסומן)",
|
"LabelExplicitChecked": "בוטה (מסומן)",
|
||||||
"LabelExplicitUnchecked": "לא בוטה (לא מסומן)",
|
"LabelExplicitUnchecked": "לא בוטה (לא מסומן)",
|
||||||
"LabelExportOPML": "ייצוא OPML",
|
"LabelExportOPML": "ייצוא OPML",
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,8 @@
|
||||||
"LabelFilename": "Naziv datoteke",
|
"LabelFilename": "Naziv datoteke",
|
||||||
"LabelFilterByUser": "Filtriraj po korisniku",
|
"LabelFilterByUser": "Filtriraj po korisniku",
|
||||||
"LabelFindEpisodes": "Pronađi nastavke",
|
"LabelFindEpisodes": "Pronađi nastavke",
|
||||||
"LabelFinished": "Dovršeno",
|
"LabelFinished": "Završeno",
|
||||||
|
"LabelFinishedDate": "Završeno {0}",
|
||||||
"LabelFolder": "Mapa",
|
"LabelFolder": "Mapa",
|
||||||
"LabelFolders": "Mape",
|
"LabelFolders": "Mape",
|
||||||
"LabelFontBold": "Podebljano",
|
"LabelFontBold": "Podebljano",
|
||||||
|
|
@ -435,7 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Br {0}",
|
"LabelLibraryFilterSublistEmpty": "Br {0}",
|
||||||
"LabelLibraryItem": "Stavka knjižnice",
|
"LabelLibraryItem": "Stavka knjižnice",
|
||||||
"LabelLibraryName": "Ime knjižnice",
|
"LabelLibraryName": "Ime knjižnice",
|
||||||
"LabelLibrarySortByProgress": "Napredak ažuriran",
|
"LabelLibrarySortByProgress": "Napredak: zadnje ažurirano",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Napredak: dovršeno",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Napredak: započeto",
|
||||||
"LabelLimit": "Ograničenje",
|
"LabelLimit": "Ograničenje",
|
||||||
"LabelLineSpacing": "Razmak između redaka",
|
"LabelLineSpacing": "Razmak između redaka",
|
||||||
"LabelListenAgain": "Ponovno poslušaj",
|
"LabelListenAgain": "Ponovno poslušaj",
|
||||||
|
|
@ -635,6 +638,7 @@
|
||||||
"LabelStartTime": "Vrijeme početka",
|
"LabelStartTime": "Vrijeme početka",
|
||||||
"LabelStarted": "Započeto",
|
"LabelStarted": "Započeto",
|
||||||
"LabelStartedAt": "Započeto",
|
"LabelStartedAt": "Započeto",
|
||||||
|
"LabelStartedDate": "Započeto {0}",
|
||||||
"LabelStatsAudioTracks": "Zvučni zapisi",
|
"LabelStatsAudioTracks": "Zvučni zapisi",
|
||||||
"LabelStatsAuthors": "Autori",
|
"LabelStatsAuthors": "Autori",
|
||||||
"LabelStatsBestDay": "Najbolji dan",
|
"LabelStatsBestDay": "Najbolji dan",
|
||||||
|
|
@ -880,7 +884,7 @@
|
||||||
"MessageRemoveEpisodes": "Ukloni {0} nastavaka",
|
"MessageRemoveEpisodes": "Ukloni {0} nastavaka",
|
||||||
"MessageRemoveFromPlayerQueue": "Ukloni iz redoslijeda izvođenja",
|
"MessageRemoveFromPlayerQueue": "Ukloni iz redoslijeda izvođenja",
|
||||||
"MessageRemoveUserWarning": "Sigurno želite trajno izbrisati korisnika \"{0}\"?",
|
"MessageRemoveUserWarning": "Sigurno želite trajno izbrisati korisnika \"{0}\"?",
|
||||||
"MessageReportBugsAndContribute": "Prijavite pogreške, zatražite funkcionalnosti i doprinesite na",
|
"MessageReportBugsAndContribute": "Prijavite pogreške, zatražite značajke i doprinesite na",
|
||||||
"MessageResetChaptersConfirm": "Sigurno želite vratiti poglavlja na prethodno stanje i poništiti učinjene promjene?",
|
"MessageResetChaptersConfirm": "Sigurno želite vratiti poglavlja na prethodno stanje i poništiti učinjene promjene?",
|
||||||
"MessageRestoreBackupConfirm": "Sigurno želite vratiti sigurnosnu kopiju izrađenu",
|
"MessageRestoreBackupConfirm": "Sigurno želite vratiti sigurnosnu kopiju izrađenu",
|
||||||
"MessageRestoreBackupWarning": "Vraćanjem sigurnosne kopije prepisat ćete cijelu bazu podataka koja se nalazi u /config i slike naslovnice u /metadata/items i /metadata/authors.<br /><br />Sigurnosne kopije ne mijenjaju datoteke koje se nalaze u mapama vaših knjižnica. Ako ste u postavkama poslužitelja uključili mogućnost spremanja naslovnica i meta-podataka u mape knjižnice, te se datoteke neće niti sigurnosno pohraniti niti prepisati. <br /><br />Svi klijenti koji se spajaju na vaš poslužitelj automatski će se osvježiti.",
|
"MessageRestoreBackupWarning": "Vraćanjem sigurnosne kopije prepisat ćete cijelu bazu podataka koja se nalazi u /config i slike naslovnice u /metadata/items i /metadata/authors.<br /><br />Sigurnosne kopije ne mijenjaju datoteke koje se nalaze u mapama vaših knjižnica. Ako ste u postavkama poslužitelja uključili mogućnost spremanja naslovnica i meta-podataka u mape knjižnice, te se datoteke neće niti sigurnosno pohraniti niti prepisati. <br /><br />Svi klijenti koji se spajaju na vaš poslužitelj automatski će se osvježiti.",
|
||||||
|
|
@ -1022,6 +1026,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "Neuspješno dodavanje stavki u zbirku",
|
"ToastCollectionItemsAddFailed": "Neuspješno dodavanje stavki u zbirku",
|
||||||
"ToastCollectionRemoveSuccess": "Zbirka izbrisana",
|
"ToastCollectionRemoveSuccess": "Zbirka izbrisana",
|
||||||
"ToastCollectionUpdateSuccess": "Zbirka ažurirana",
|
"ToastCollectionUpdateSuccess": "Zbirka ažurirana",
|
||||||
|
"ToastConnectionNotAvailable": "Veza nije dostupna. Pokušaj ponovo kasnije",
|
||||||
|
"ToastCoverSearchFailed": "Pretraga naslovnice neuspjela",
|
||||||
"ToastCoverUpdateFailed": "Ažuriranje naslovnice nije uspjelo",
|
"ToastCoverUpdateFailed": "Ažuriranje naslovnice nije uspjelo",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "Datum i vrijeme su neispravni ili nepotpuni",
|
"ToastDateTimeInvalidOrIncomplete": "Datum i vrijeme su neispravni ili nepotpuni",
|
||||||
"ToastDeleteFileFailed": "Brisanje datoteke nije uspjelo",
|
"ToastDeleteFileFailed": "Brisanje datoteke nije uspjelo",
|
||||||
|
|
@ -1096,6 +1102,7 @@
|
||||||
"ToastPlaylistUpdateSuccess": "Popis za izvođenje ažuriran",
|
"ToastPlaylistUpdateSuccess": "Popis za izvođenje ažuriran",
|
||||||
"ToastPodcastCreateFailed": "Podcast nije izrađen",
|
"ToastPodcastCreateFailed": "Podcast nije izrađen",
|
||||||
"ToastPodcastCreateSuccess": "Podcast uspješno izrađen",
|
"ToastPodcastCreateSuccess": "Podcast uspješno izrađen",
|
||||||
|
"ToastPodcastEpisodeUpdated": "Nastavak ažuriran",
|
||||||
"ToastPodcastGetFeedFailed": "Dohvat izvora podcasta nije uspio",
|
"ToastPodcastGetFeedFailed": "Dohvat izvora podcasta nije uspio",
|
||||||
"ToastPodcastNoEpisodesInFeed": "U RSS izvoru nisu pronađeni nastavci",
|
"ToastPodcastNoEpisodesInFeed": "U RSS izvoru nisu pronađeni nastavci",
|
||||||
"ToastPodcastNoRssFeed": "Podcast nema RSS izvor",
|
"ToastPodcastNoRssFeed": "Podcast nema RSS izvor",
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,7 @@
|
||||||
"LabelFilterByUser": "Szűrés felhasználó szerint",
|
"LabelFilterByUser": "Szűrés felhasználó szerint",
|
||||||
"LabelFindEpisodes": "Epizódok keresése",
|
"LabelFindEpisodes": "Epizódok keresése",
|
||||||
"LabelFinished": "Befejezett",
|
"LabelFinished": "Befejezett",
|
||||||
|
"LabelFinishedDate": "Befejezve {0}",
|
||||||
"LabelFolder": "Mappa",
|
"LabelFolder": "Mappa",
|
||||||
"LabelFolders": "Mappák",
|
"LabelFolders": "Mappák",
|
||||||
"LabelFontBold": "Félkövér",
|
"LabelFontBold": "Félkövér",
|
||||||
|
|
@ -435,7 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Nem {0}",
|
"LabelLibraryFilterSublistEmpty": "Nem {0}",
|
||||||
"LabelLibraryItem": "Könyvtári elem",
|
"LabelLibraryItem": "Könyvtári elem",
|
||||||
"LabelLibraryName": "Könyvtár neve",
|
"LabelLibraryName": "Könyvtár neve",
|
||||||
"LabelLibrarySortByProgress": "Haladás frissítve",
|
"LabelLibrarySortByProgress": "Folyamat: Legutóbbi frissítés",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Folyamat: Befejezve",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Folyamat: Elindult",
|
||||||
"LabelLimit": "Korlát",
|
"LabelLimit": "Korlát",
|
||||||
"LabelLineSpacing": "Sorköz",
|
"LabelLineSpacing": "Sorköz",
|
||||||
"LabelListenAgain": "Újrahallgatás",
|
"LabelListenAgain": "Újrahallgatás",
|
||||||
|
|
@ -635,6 +638,7 @@
|
||||||
"LabelStartTime": "Kezdési idő",
|
"LabelStartTime": "Kezdési idő",
|
||||||
"LabelStarted": "Elkezdődött",
|
"LabelStarted": "Elkezdődött",
|
||||||
"LabelStartedAt": "Kezdés ideje",
|
"LabelStartedAt": "Kezdés ideje",
|
||||||
|
"LabelStartedDate": "Elindítva {0}",
|
||||||
"LabelStatsAudioTracks": "Audiósáv",
|
"LabelStatsAudioTracks": "Audiósáv",
|
||||||
"LabelStatsAuthors": "Szerző",
|
"LabelStatsAuthors": "Szerző",
|
||||||
"LabelStatsBestDay": "Legjobb nap",
|
"LabelStatsBestDay": "Legjobb nap",
|
||||||
|
|
@ -1022,6 +1026,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "A tétel(ek) hozzáadása gyűjteményhez sikertelen",
|
"ToastCollectionItemsAddFailed": "A tétel(ek) hozzáadása gyűjteményhez sikertelen",
|
||||||
"ToastCollectionRemoveSuccess": "Gyűjtemény eltávolítva",
|
"ToastCollectionRemoveSuccess": "Gyűjtemény eltávolítva",
|
||||||
"ToastCollectionUpdateSuccess": "Gyűjtemény frissítve",
|
"ToastCollectionUpdateSuccess": "Gyűjtemény frissítve",
|
||||||
|
"ToastConnectionNotAvailable": "A kapcsolat nem elérhető. Kérem, próbálkozzon később",
|
||||||
|
"ToastCoverSearchFailed": "A borítók keresése sikertelen",
|
||||||
"ToastCoverUpdateFailed": "A borító frissítése nem sikerült",
|
"ToastCoverUpdateFailed": "A borító frissítése nem sikerült",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "A dátum és az időpont érvénytelen vagy hiányos",
|
"ToastDateTimeInvalidOrIncomplete": "A dátum és az időpont érvénytelen vagy hiányos",
|
||||||
"ToastDeleteFileFailed": "Nem sikerült törölni a fájlt",
|
"ToastDeleteFileFailed": "Nem sikerült törölni a fájlt",
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,19 @@
|
||||||
"ButtonApplyChapters": "チャプターを確定する",
|
"ButtonApplyChapters": "チャプターを確定する",
|
||||||
"ButtonAuthors": "作者",
|
"ButtonAuthors": "作者",
|
||||||
"ButtonBack": "戻る",
|
"ButtonBack": "戻る",
|
||||||
|
"ButtonBatchEditPopulateFromExisting": "既存のものから取り込む",
|
||||||
|
"ButtonBatchEditPopulateMapDetails": "チャプター情報を読み込む",
|
||||||
"ButtonBrowseForFolder": "フォルダーを選択する",
|
"ButtonBrowseForFolder": "フォルダーを選択する",
|
||||||
"ButtonCancel": "キャンセル",
|
"ButtonCancel": "キャンセル",
|
||||||
"ButtonCancelEncode": "エンコードを取り消す",
|
"ButtonCancelEncode": "エンコードを取り消す",
|
||||||
"ButtonChangeRootPassword": "Rootのパスワードを変更する",
|
"ButtonChangeRootPassword": "Rootのパスワードを変更する",
|
||||||
|
"ButtonCheckAndDownloadNewEpisodes": "新しいエピソードを確認してダウンロード",
|
||||||
"ButtonChooseAFolder": "フォルダーを選ぶ",
|
"ButtonChooseAFolder": "フォルダーを選ぶ",
|
||||||
"ButtonChooseFiles": "ファイルを選ぶ",
|
"ButtonChooseFiles": "ファイルを選ぶ",
|
||||||
"ButtonClearFilter": "絞り込みを解除",
|
"ButtonClearFilter": "絞り込みを解除",
|
||||||
"ButtonClose": "閉じる",
|
"ButtonClose": "閉じる",
|
||||||
"ButtonCloseFeed": "フィードを閉じる",
|
"ButtonCloseFeed": "フィードを閉じる",
|
||||||
|
"ButtonCloseSession": "開いているセッションを閉じる",
|
||||||
"ButtonCollections": "コレクション",
|
"ButtonCollections": "コレクション",
|
||||||
"ButtonConfigureScanner": "スキャナーの設定",
|
"ButtonConfigureScanner": "スキャナーの設定",
|
||||||
"ButtonCreate": "作成",
|
"ButtonCreate": "作成",
|
||||||
|
|
@ -30,21 +34,30 @@
|
||||||
"ButtonEditChapters": "チャプターの編集",
|
"ButtonEditChapters": "チャプターの編集",
|
||||||
"ButtonEditPodcast": "ポッドキャストの編集",
|
"ButtonEditPodcast": "ポッドキャストの編集",
|
||||||
"ButtonEnable": "オンにする",
|
"ButtonEnable": "オンにする",
|
||||||
|
"ButtonFireAndFail": "エラーを無視して実行",
|
||||||
|
"ButtonFireOnTest": "テストを実行",
|
||||||
"ButtonForceReScan": "強制的に再スキャンする",
|
"ButtonForceReScan": "強制的に再スキャンする",
|
||||||
"ButtonFullPath": "絶対パス",
|
"ButtonFullPath": "絶対パス",
|
||||||
"ButtonHide": "非表示",
|
"ButtonHide": "非表示",
|
||||||
"ButtonHome": "ホーム",
|
"ButtonHome": "ホーム",
|
||||||
|
"ButtonIssues": "問題",
|
||||||
"ButtonJumpBackward": "巻き戻し",
|
"ButtonJumpBackward": "巻き戻し",
|
||||||
"ButtonJumpForward": "早送り",
|
"ButtonJumpForward": "早送り",
|
||||||
"ButtonLatest": "最新",
|
"ButtonLatest": "最新",
|
||||||
"ButtonLibrary": "ライブラリー",
|
"ButtonLibrary": "ライブラリー",
|
||||||
"ButtonLogout": "ログアウト",
|
"ButtonLogout": "ログアウト",
|
||||||
|
"ButtonLookup": "参照",
|
||||||
"ButtonManageTracks": "トラックの管理",
|
"ButtonManageTracks": "トラックの管理",
|
||||||
|
"ButtonMapChapterTitles": "チャプターのタイトルを割り当て",
|
||||||
|
"ButtonMatchAllAuthors": "すべての作者と紐付け",
|
||||||
|
"ButtonMatchBooks": "本と紐付け",
|
||||||
"ButtonNevermind": "中止",
|
"ButtonNevermind": "中止",
|
||||||
"ButtonNext": "次",
|
"ButtonNext": "次",
|
||||||
"ButtonNextChapter": "次のチャプター",
|
"ButtonNextChapter": "次のチャプター",
|
||||||
|
"ButtonNextItemInQueue": "キューの中の次のアイテム",
|
||||||
"ButtonOk": "はい",
|
"ButtonOk": "はい",
|
||||||
"ButtonOpenFeed": "フィードを開く",
|
"ButtonOpenFeed": "フィードを開く",
|
||||||
|
"ButtonOpenManager": "管理画面を開く",
|
||||||
"ButtonPause": "一時停止",
|
"ButtonPause": "一時停止",
|
||||||
"ButtonPlay": "再生",
|
"ButtonPlay": "再生",
|
||||||
"ButtonPlayAll": "全て再生",
|
"ButtonPlayAll": "全て再生",
|
||||||
|
|
@ -52,11 +65,13 @@
|
||||||
"ButtonPlaylists": "プレイリスト",
|
"ButtonPlaylists": "プレイリスト",
|
||||||
"ButtonPrevious": "先",
|
"ButtonPrevious": "先",
|
||||||
"ButtonPreviousChapter": "前のチャプター",
|
"ButtonPreviousChapter": "前のチャプター",
|
||||||
|
"ButtonProbeAudioFile": "オーディオファイルを解析",
|
||||||
"ButtonPurgeAllCache": "全てのキャッシュを削除",
|
"ButtonPurgeAllCache": "全てのキャッシュを削除",
|
||||||
"ButtonPurgeItemsCache": "項目のキャッシュを削除",
|
"ButtonPurgeItemsCache": "項目のキャッシュを削除",
|
||||||
"ButtonQueueAddItem": "次に再生する",
|
"ButtonQueueAddItem": "次に再生する",
|
||||||
"ButtonQueueRemoveItem": "次に再生から削除",
|
"ButtonQueueRemoveItem": "次に再生から削除",
|
||||||
"ButtonQuickEmbed": "クイック埋め込み",
|
"ButtonQuickEmbed": "クイック埋め込み",
|
||||||
|
"ButtonQuickEmbedMetadata": "メタデータの埋め込み",
|
||||||
"ButtonReScan": "再スキャン",
|
"ButtonReScan": "再スキャン",
|
||||||
"ButtonRead": "読む",
|
"ButtonRead": "読む",
|
||||||
"ButtonReadLess": "閉じる",
|
"ButtonReadLess": "閉じる",
|
||||||
|
|
@ -76,8 +91,11 @@
|
||||||
"ButtonScrollRight": "右にスクロール",
|
"ButtonScrollRight": "右にスクロール",
|
||||||
"ButtonSearch": "検索",
|
"ButtonSearch": "検索",
|
||||||
"ButtonSeries": "シリーズ",
|
"ButtonSeries": "シリーズ",
|
||||||
|
"ButtonSubmit": "送信",
|
||||||
"ButtonYes": "はい",
|
"ButtonYes": "はい",
|
||||||
"HeaderAccount": "アカウント",
|
"HeaderAccount": "アカウント",
|
||||||
|
"HeaderAdvanced": "上級者向け",
|
||||||
|
"HeaderAudioTracks": "オーディオトラック",
|
||||||
"HeaderChapters": "チャプター",
|
"HeaderChapters": "チャプター",
|
||||||
"HeaderCollection": "コレクション",
|
"HeaderCollection": "コレクション",
|
||||||
"HeaderCollectionItems": "コレクションの項目",
|
"HeaderCollectionItems": "コレクションの項目",
|
||||||
|
|
@ -87,19 +105,68 @@
|
||||||
"HeaderEreaderSettings": "電子書籍リーダーの設定",
|
"HeaderEreaderSettings": "電子書籍リーダーの設定",
|
||||||
"HeaderLatestEpisodes": "最新のエピソード",
|
"HeaderLatestEpisodes": "最新のエピソード",
|
||||||
"HeaderLibraries": "ライブラリー",
|
"HeaderLibraries": "ライブラリー",
|
||||||
|
"HeaderOpenRSSFeed": "RSS Feedを開く",
|
||||||
"HeaderPlayerSettings": "プレーヤーの設定",
|
"HeaderPlayerSettings": "プレーヤーの設定",
|
||||||
|
"HeaderPlaylist": "プレイリスト",
|
||||||
|
"HeaderPlaylistItems": "プレイリストアイテム",
|
||||||
|
"HeaderRSSFeedGeneral": "RSS 詳細",
|
||||||
|
"HeaderSettings": "設定",
|
||||||
"HeaderSettingsGeneral": "一般",
|
"HeaderSettingsGeneral": "一般",
|
||||||
"HeaderSettingsScanner": "スキャナー",
|
"HeaderSettingsScanner": "スキャナー",
|
||||||
|
"HeaderSleepTimer": "スリープタイマー",
|
||||||
|
"HeaderStatsMinutesListeningChart": "過去7日間の視聴時間(分)",
|
||||||
|
"LabelAddToPlaylist": "プレイリストの追加",
|
||||||
|
"LabelAuthor": "著者",
|
||||||
|
"LabelAuthorFirstLast": "著者(名 氏)",
|
||||||
|
"LabelAuthorLastFirst": "著者(氏 名)",
|
||||||
|
"LabelAuthors": "著者",
|
||||||
|
"LabelAutoDownloadEpisodes": "エピソードの自動ダウンロード",
|
||||||
"LabelBooks": "ほん",
|
"LabelBooks": "ほん",
|
||||||
|
"LabelChapters": "チャプター",
|
||||||
|
"LabelClosePlayer": "プレイヤーを閉じる",
|
||||||
|
"LabelComplete": "完了",
|
||||||
"LabelContinueListening": "続きから聞く",
|
"LabelContinueListening": "続きから聞く",
|
||||||
|
"LabelDescription": "説明",
|
||||||
|
"LabelDownload": "ダウンロード",
|
||||||
|
"LabelDuration": "長さ",
|
||||||
|
"LabelEbook": "Eブック",
|
||||||
|
"LabelEbooks": "Eブック",
|
||||||
|
"LabelEnable": "有効",
|
||||||
|
"LabelEndOfChapter": "チャプターの最後",
|
||||||
|
"LabelEpisode": "エピソード",
|
||||||
|
"LabelFeedURL": "Feed URL",
|
||||||
|
"LabelFile": "ファイル",
|
||||||
|
"LabelFilename": "ファイル名",
|
||||||
|
"LabelFinished": "完了",
|
||||||
|
"LabelFolder": "フォルダ",
|
||||||
|
"LabelFontBoldness": "フォントの太さ",
|
||||||
|
"LabelFontScale": "フォントサイズ",
|
||||||
|
"LabelGenre": "ジャンル",
|
||||||
|
"LabelGenres": "ジャンル",
|
||||||
|
"LabelHost": "ホスト",
|
||||||
|
"LabelInProgress": "進行中",
|
||||||
"LabelLanguage": "言語",
|
"LabelLanguage": "言語",
|
||||||
"LabelLanguages": "言語",
|
"LabelLanguages": "言語",
|
||||||
|
"LabelLayout": "レイアウト",
|
||||||
|
"LabelLayoutSinglePage": "単ページ",
|
||||||
|
"LabelLineSpacing": "行間",
|
||||||
|
"LabelListenAgain": "再度視聴",
|
||||||
|
"LabelMediaType": "メディアの種類",
|
||||||
|
"LabelMoreInfo": "追加情報",
|
||||||
"LabelName": "名",
|
"LabelName": "名",
|
||||||
|
"LabelNarrator": "ナレーター",
|
||||||
|
"LabelNarrators": "ナレーター",
|
||||||
"LabelNew": "新しい",
|
"LabelNew": "新しい",
|
||||||
"LabelNewPassword": "新しいのパスワード",
|
"LabelNewPassword": "新しいのパスワード",
|
||||||
|
"LabelNewestAuthors": "最新の著者",
|
||||||
|
"LabelNewestEpisodes": "最新エピソード",
|
||||||
"LabelPassword": "パスワード",
|
"LabelPassword": "パスワード",
|
||||||
|
"LabelPath": "パス",
|
||||||
"LabelPlaylists": "プレイリスト",
|
"LabelPlaylists": "プレイリスト",
|
||||||
"LabelPodcast": "ポッドキャスト",
|
"LabelPodcast": "ポッドキャスト",
|
||||||
|
"LabelPodcasts": "ポッドキャスト",
|
||||||
|
"LabelPreventIndexing": "フィードがiTunesおよびGoogleのポッドキャストディレクトリにインデックス登録されるのを防ぎます",
|
||||||
|
"LabelPublishYear": "公開年",
|
||||||
"LabelSettingsFindCovers": "表紙を探す",
|
"LabelSettingsFindCovers": "表紙を探す",
|
||||||
"LabelSettingsFindCoversHelp": "もしオーディオブックに表紙が埋め込まれていない、もしくは表紙画像がフォルダー内に見つからなければ、スキャナーは表紙を探そうとします。<br>注記: これによってスキャン時間が長くなります",
|
"LabelSettingsFindCoversHelp": "もしオーディオブックに表紙が埋め込まれていない、もしくは表紙画像がフォルダー内に見つからなければ、スキャナーは表紙を探そうとします。<br>注記: これによってスキャン時間が長くなります",
|
||||||
"LabelSettingsParseSubtitles": "サブタイトルを抽出する",
|
"LabelSettingsParseSubtitles": "サブタイトルを抽出する",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"ButtonApplyChapters": "Bruk kapittel",
|
"ButtonApplyChapters": "Bruk kapittel",
|
||||||
"ButtonAuthors": "Forfattere",
|
"ButtonAuthors": "Forfattere",
|
||||||
"ButtonBack": "Tilbake",
|
"ButtonBack": "Tilbake",
|
||||||
"ButtonBatchEditPopulateFromExisting": "Opprett fra eksisterende",
|
"ButtonBatchEditPopulateFromExisting": "Fyll ut fra eksisterende",
|
||||||
"ButtonBatchEditPopulateMapDetails": "Legg til detaljer",
|
"ButtonBatchEditPopulateMapDetails": "Legg til detaljer",
|
||||||
"ButtonBrowseForFolder": "Bla gjennom mappe",
|
"ButtonBrowseForFolder": "Bla gjennom mappe",
|
||||||
"ButtonCancel": "Avbryt",
|
"ButtonCancel": "Avbryt",
|
||||||
|
|
@ -127,6 +127,7 @@
|
||||||
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
|
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
|
||||||
"HeaderAuthentication": "Autentisering",
|
"HeaderAuthentication": "Autentisering",
|
||||||
"HeaderBackups": "Sikkerhetskopier",
|
"HeaderBackups": "Sikkerhetskopier",
|
||||||
|
"HeaderBulkChapterModal": "Legg til flere kapitler",
|
||||||
"HeaderChangePassword": "Bytt passord",
|
"HeaderChangePassword": "Bytt passord",
|
||||||
"HeaderChapters": "Kapittel",
|
"HeaderChapters": "Kapittel",
|
||||||
"HeaderChooseAFolder": "Velg en mappe",
|
"HeaderChooseAFolder": "Velg en mappe",
|
||||||
|
|
@ -433,13 +434,13 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Ingen {0}",
|
"LabelLibraryFilterSublistEmpty": "Ingen {0}",
|
||||||
"LabelLibraryItem": "Bibliotek enhet",
|
"LabelLibraryItem": "Bibliotek enhet",
|
||||||
"LabelLibraryName": "Bibliotek navn",
|
"LabelLibraryName": "Bibliotek navn",
|
||||||
"LabelLibrarySortByProgress": "Fremgang oppdatert",
|
"LabelLibrarySortByProgress": "Fremgang: Sist oppdatert",
|
||||||
"LabelLimit": "Begrensning",
|
"LabelLimit": "Begrensning",
|
||||||
"LabelLineSpacing": "Linjemellomrom",
|
"LabelLineSpacing": "Linjemellomrom",
|
||||||
"LabelListenAgain": "Lytt igjen",
|
"LabelListenAgain": "Lytt igjen",
|
||||||
"LabelLogLevelDebug": "Debug",
|
"LabelLogLevelDebug": "Debug",
|
||||||
"LabelLogLevelInfo": "Info",
|
"LabelLogLevelInfo": "Info",
|
||||||
"LabelLogLevelWarn": "Warn",
|
"LabelLogLevelWarn": "Varsel",
|
||||||
"LabelLookForNewEpisodesAfterDate": "Se etter nye episoder etter denne datoen",
|
"LabelLookForNewEpisodesAfterDate": "Se etter nye episoder etter denne datoen",
|
||||||
"LabelLowestPriority": "Laveste prioritet",
|
"LabelLowestPriority": "Laveste prioritet",
|
||||||
"LabelMatchExistingUsersBy": "Knytt sammen eksisterende brukere basert på",
|
"LabelMatchExistingUsersBy": "Knytt sammen eksisterende brukere basert på",
|
||||||
|
|
@ -490,6 +491,7 @@
|
||||||
"LabelNumberOfEpisodes": "# episoder",
|
"LabelNumberOfEpisodes": "# episoder",
|
||||||
"LabelOpenIDAdvancedPermsClaimDescription": "Navnet på OpenID claim'et som inneholder avanserte tilganger for brukerhandlinger i applikasjonen som vil brukes for ikke-administratorroller (<b>hvis konfigurert</b>). Hvis claim'et mangler fra responsen, nektes tilgang til ABS. Hvis en enkelt opsjon mangler, blir behandlet som <code>false</code>. Påse at identitetstilbyderens claim stemmer overens med den forventede strukturen:",
|
"LabelOpenIDAdvancedPermsClaimDescription": "Navnet på OpenID claim'et som inneholder avanserte tilganger for brukerhandlinger i applikasjonen som vil brukes for ikke-administratorroller (<b>hvis konfigurert</b>). Hvis claim'et mangler fra responsen, nektes tilgang til ABS. Hvis en enkelt opsjon mangler, blir behandlet som <code>false</code>. Påse at identitetstilbyderens claim stemmer overens med den forventede strukturen:",
|
||||||
"LabelOpenIDClaims": "La følge valg være tomme for å slå av avanserte gruppe og tillatelser. Gruppen \"Bruker\" vil da også automatisk legges til.",
|
"LabelOpenIDClaims": "La følge valg være tomme for å slå av avanserte gruppe og tillatelser. Gruppen \"Bruker\" vil da også automatisk legges til.",
|
||||||
|
"LabelOpenIDGroupClaimDescription": "Navn på OpenID-forespørsel som inneholder en lite over brukerens grupper. Vanligvis kalt <code>grupper</code>. <b>Om konfigurert</b>, vil applikasjonen tildele roller baseret på brukerens gruppemedlemsskaper, gitt disse grupper er navngitt (uten forbehold for store og små bokstaver) 'admin', 'user' eller 'guest' i forespørsel. Forespørselen burde inneholde en liste (og hvis brukeren tilhører flere grupper), applikasjonen vil tildele rolle med høyeste adgangsnivå. Hvis ingen grupper matcher vil adgang bli nektet.",
|
||||||
"LabelOpenRSSFeed": "Åpne RSS Feed",
|
"LabelOpenRSSFeed": "Åpne RSS Feed",
|
||||||
"LabelOverwrite": "Overskriv",
|
"LabelOverwrite": "Overskriv",
|
||||||
"LabelPaginationPageXOfY": "Side {0} av {1}",
|
"LabelPaginationPageXOfY": "Side {0} av {1}",
|
||||||
|
|
@ -759,7 +761,7 @@
|
||||||
"MessageConfirmMarkSeriesFinished": "Er du sikker på at du vil markere alle bøkene i serien som fullført?",
|
"MessageConfirmMarkSeriesFinished": "Er du sikker på at du vil markere alle bøkene i serien som fullført?",
|
||||||
"MessageConfirmMarkSeriesNotFinished": "Er du sikker på at du vil markere alle bøkene i serien som ikke fullført?",
|
"MessageConfirmMarkSeriesNotFinished": "Er du sikker på at du vil markere alle bøkene i serien som ikke fullført?",
|
||||||
"MessageConfirmNotificationTestTrigger": "Utløs dette varselet med test-data?",
|
"MessageConfirmNotificationTestTrigger": "Utløs dette varselet med test-data?",
|
||||||
"MessageConfirmPurgeCache": "(Purge cache) Dette vil sletter hele mappen <code>/metadata/cache</code>. <br /><br />Er du sikker på at du du vil slette cache-mappen?",
|
"MessageConfirmPurgeCache": "Tømming av mellomlagring vil slette hele mappen <code>/metadata/cache</code>. <br /><br />Er du sikker på at du du vil slette mappen?",
|
||||||
"MessageConfirmPurgeItemsCache": "(Purge items cache) Dette vil sletter hele mappen <code>/metadata/cache/items</code>.<br />Er du sikker?",
|
"MessageConfirmPurgeItemsCache": "(Purge items cache) Dette vil sletter hele mappen <code>/metadata/cache/items</code>.<br />Er du sikker?",
|
||||||
"MessageConfirmQuickEmbed": "Advarsel! Rask innbygging av metadata tar ikke backup av lyd-filene først. Forsikre deg om at du har sikkerhetskopi av filene. <br><br> Fortsett?",
|
"MessageConfirmQuickEmbed": "Advarsel! Rask innbygging av metadata tar ikke backup av lyd-filene først. Forsikre deg om at du har sikkerhetskopi av filene. <br><br> Fortsett?",
|
||||||
"MessageConfirmQuickMatchEpisodes": "Hurtig gjenkjenning av episoder overskriver detaljene hvis en match blir funnet. Kun episoder som ikke allerede er matchet blir oppdatert. Er du sikker?",
|
"MessageConfirmQuickMatchEpisodes": "Hurtig gjenkjenning av episoder overskriver detaljene hvis en match blir funnet. Kun episoder som ikke allerede er matchet blir oppdatert. Er du sikker?",
|
||||||
|
|
@ -939,6 +941,7 @@
|
||||||
"ToastCollectionItemsAddFailed": "Feil med å legge til element(er)",
|
"ToastCollectionItemsAddFailed": "Feil med å legge til element(er)",
|
||||||
"ToastCollectionRemoveSuccess": "Samling fjernet",
|
"ToastCollectionRemoveSuccess": "Samling fjernet",
|
||||||
"ToastCollectionUpdateSuccess": "samlingupdated",
|
"ToastCollectionUpdateSuccess": "samlingupdated",
|
||||||
|
"ToastCoverSearchFailed": "Finner ikke bokomslag",
|
||||||
"ToastCoverUpdateFailed": "Oppdatering av bilde feilet",
|
"ToastCoverUpdateFailed": "Oppdatering av bilde feilet",
|
||||||
"ToastDeleteFileFailed": "Kunne ikke slette fil",
|
"ToastDeleteFileFailed": "Kunne ikke slette fil",
|
||||||
"ToastDeleteFileSuccess": "Fil slettet",
|
"ToastDeleteFileSuccess": "Fil slettet",
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@
|
||||||
"HeaderAudiobookTools": "Narzędzia do zarządzania audiobookami",
|
"HeaderAudiobookTools": "Narzędzia do zarządzania audiobookami",
|
||||||
"HeaderAuthentication": "Uwierzytelnianie",
|
"HeaderAuthentication": "Uwierzytelnianie",
|
||||||
"HeaderBackups": "Kopie zapasowe",
|
"HeaderBackups": "Kopie zapasowe",
|
||||||
|
"HeaderBulkChapterModal": "Dodaj wiele rozdziałów",
|
||||||
"HeaderChangePassword": "Zmień hasło",
|
"HeaderChangePassword": "Zmień hasło",
|
||||||
"HeaderChapters": "Rozdziały",
|
"HeaderChapters": "Rozdziały",
|
||||||
"HeaderChooseAFolder": "Wybierz folder",
|
"HeaderChooseAFolder": "Wybierz folder",
|
||||||
|
|
@ -199,6 +200,7 @@
|
||||||
"HeaderSettingsExperimental": "Funkcje eksperymentalne",
|
"HeaderSettingsExperimental": "Funkcje eksperymentalne",
|
||||||
"HeaderSettingsGeneral": "Ogólne",
|
"HeaderSettingsGeneral": "Ogólne",
|
||||||
"HeaderSettingsScanner": "Skanowanie",
|
"HeaderSettingsScanner": "Skanowanie",
|
||||||
|
"HeaderSettingsSecurity": "Bezpieczeństwo",
|
||||||
"HeaderSettingsWebClient": "Klient webowy",
|
"HeaderSettingsWebClient": "Klient webowy",
|
||||||
"HeaderSleepTimer": "Wyłącznik czasowy",
|
"HeaderSleepTimer": "Wyłącznik czasowy",
|
||||||
"HeaderStatsLargestItems": "Największe pozycje",
|
"HeaderStatsLargestItems": "Największe pozycje",
|
||||||
|
|
@ -242,6 +244,8 @@
|
||||||
"LabelAlreadyInYourLibrary": "Już istnieje w twojej bibliotece",
|
"LabelAlreadyInYourLibrary": "Już istnieje w twojej bibliotece",
|
||||||
"LabelApiKeyCreated": "Klucz API \"{0}\" został pomyślnie utworzony.",
|
"LabelApiKeyCreated": "Klucz API \"{0}\" został pomyślnie utworzony.",
|
||||||
"LabelApiKeyCreatedDescription": "Pamiętaj o skopiowaniu klucza API, ponieważ nie będziesz już mógł go zobaczyć.",
|
"LabelApiKeyCreatedDescription": "Pamiętaj o skopiowaniu klucza API, ponieważ nie będziesz już mógł go zobaczyć.",
|
||||||
|
"LabelApiKeyUser": "Wykonaj w imieniu innego użytkownika",
|
||||||
|
"LabelApiKeyUserDescription": "Ten klucz API będzie miał te same uprawnienia co użytkownik, w którego imieniu ma być używany. Wpisy w logach będą identyczne z tymi, wywołanymi przez samego użytkownika.",
|
||||||
"LabelApiToken": "API Token",
|
"LabelApiToken": "API Token",
|
||||||
"LabelAppend": "Dołącz",
|
"LabelAppend": "Dołącz",
|
||||||
"LabelAudioBitrate": "Audio Bitrate (np. 128k)",
|
"LabelAudioBitrate": "Audio Bitrate (np. 128k)",
|
||||||
|
|
@ -304,6 +308,7 @@
|
||||||
"LabelDeleteFromFileSystemCheckbox": "Usuń z systemu plików (odznacz, aby usunąć tylko z bazy danych)",
|
"LabelDeleteFromFileSystemCheckbox": "Usuń z systemu plików (odznacz, aby usunąć tylko z bazy danych)",
|
||||||
"LabelDescription": "Opis",
|
"LabelDescription": "Opis",
|
||||||
"LabelDeselectAll": "Odznacz wszystko",
|
"LabelDeselectAll": "Odznacz wszystko",
|
||||||
|
"LabelDetectedPattern": "Wykryty schemat:",
|
||||||
"LabelDevice": "Urządzenie",
|
"LabelDevice": "Urządzenie",
|
||||||
"LabelDeviceInfo": "Informacja o urządzeniu",
|
"LabelDeviceInfo": "Informacja o urządzeniu",
|
||||||
"LabelDeviceIsAvailableTo": "Urządzenie jest dostępne do...",
|
"LabelDeviceIsAvailableTo": "Urządzenie jest dostępne do...",
|
||||||
|
|
@ -353,6 +358,8 @@
|
||||||
"LabelExample": "Przykład",
|
"LabelExample": "Przykład",
|
||||||
"LabelExpandSeries": "Rozwiń serie",
|
"LabelExpandSeries": "Rozwiń serie",
|
||||||
"LabelExpandSubSeries": "Rozwiń podserie",
|
"LabelExpandSubSeries": "Rozwiń podserie",
|
||||||
|
"LabelExpired": "Przeterminowane",
|
||||||
|
"LabelExpiresAt": "Wygasa w",
|
||||||
"LabelExpiresInSeconds": "Wygasa za (sekund)",
|
"LabelExpiresInSeconds": "Wygasa za (sekund)",
|
||||||
"LabelExpiresNever": "Nigdy",
|
"LabelExpiresNever": "Nigdy",
|
||||||
"LabelExplicit": "Nieprzyzwoite",
|
"LabelExplicit": "Nieprzyzwoite",
|
||||||
|
|
@ -370,6 +377,7 @@
|
||||||
"LabelFilterByUser": "Filtruj według danego użytkownika",
|
"LabelFilterByUser": "Filtruj według danego użytkownika",
|
||||||
"LabelFindEpisodes": "Znajdź odcinki",
|
"LabelFindEpisodes": "Znajdź odcinki",
|
||||||
"LabelFinished": "Zakończone",
|
"LabelFinished": "Zakończone",
|
||||||
|
"LabelFinishedDate": "Ukończone {0}",
|
||||||
"LabelFolder": "Katalog",
|
"LabelFolder": "Katalog",
|
||||||
"LabelFolders": "Foldery",
|
"LabelFolders": "Foldery",
|
||||||
"LabelFontBold": "Pogrubiony",
|
"LabelFontBold": "Pogrubiony",
|
||||||
|
|
@ -427,7 +435,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Brak {0}",
|
"LabelLibraryFilterSublistEmpty": "Brak {0}",
|
||||||
"LabelLibraryItem": "Element biblioteki",
|
"LabelLibraryItem": "Element biblioteki",
|
||||||
"LabelLibraryName": "Nazwa biblioteki",
|
"LabelLibraryName": "Nazwa biblioteki",
|
||||||
"LabelLibrarySortByProgress": "Postęp zaktualizowany",
|
"LabelLibrarySortByProgress": "Postęp: Ostatnio zaktualizowane",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Postęp: Ukończone",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Postęp: Rozpoczęte",
|
||||||
"LabelLimit": "Limit",
|
"LabelLimit": "Limit",
|
||||||
"LabelLineSpacing": "Odstęp między wierszami",
|
"LabelLineSpacing": "Odstęp między wierszami",
|
||||||
"LabelListenAgain": "Słuchaj ponownie",
|
"LabelListenAgain": "Słuchaj ponownie",
|
||||||
|
|
@ -436,6 +446,7 @@
|
||||||
"LabelLogLevelWarn": "Ostrzeżenie",
|
"LabelLogLevelWarn": "Ostrzeżenie",
|
||||||
"LabelLookForNewEpisodesAfterDate": "Szukaj nowych odcinków po dacie",
|
"LabelLookForNewEpisodesAfterDate": "Szukaj nowych odcinków po dacie",
|
||||||
"LabelLowestPriority": "Najniższy priorytet",
|
"LabelLowestPriority": "Najniższy priorytet",
|
||||||
|
"LabelMatchConfidence": "Zaufanie",
|
||||||
"LabelMatchExistingUsersBy": "Dopasuje istniejących użytkowników poprzez",
|
"LabelMatchExistingUsersBy": "Dopasuje istniejących użytkowników poprzez",
|
||||||
"LabelMatchExistingUsersByDescription": "Służy do łączenia istniejących użytkowników. Po połączeniu użytkownicy zostaną dopasowani za pomocą unikalnego identyfikatora od dostawcy SSO",
|
"LabelMatchExistingUsersByDescription": "Służy do łączenia istniejących użytkowników. Po połączeniu użytkownicy zostaną dopasowani za pomocą unikalnego identyfikatora od dostawcy SSO",
|
||||||
"LabelMaxEpisodesToDownload": "Maksymalna liczba odcinków do pobrania. Użyj 0, aby wyłączyć ograniczenie.",
|
"LabelMaxEpisodesToDownload": "Maksymalna liczba odcinków do pobrania. Użyj 0, aby wyłączyć ograniczenie.",
|
||||||
|
|
@ -465,6 +476,7 @@
|
||||||
"LabelNewestAuthors": "Najnowsi autorzy",
|
"LabelNewestAuthors": "Najnowsi autorzy",
|
||||||
"LabelNewestEpisodes": "Najnowsze odcinki",
|
"LabelNewestEpisodes": "Najnowsze odcinki",
|
||||||
"LabelNextBackupDate": "Data kolejnej kopii zapasowej",
|
"LabelNextBackupDate": "Data kolejnej kopii zapasowej",
|
||||||
|
"LabelNextChapters": "Następny odcinek:",
|
||||||
"LabelNextScheduledRun": "Następne uruchomienie",
|
"LabelNextScheduledRun": "Następne uruchomienie",
|
||||||
"LabelNoApiKeys": "Brak kluczy API",
|
"LabelNoApiKeys": "Brak kluczy API",
|
||||||
"LabelNoCustomMetadataProviders": "Brak niestandardowych dostawców metadanych",
|
"LabelNoCustomMetadataProviders": "Brak niestandardowych dostawców metadanych",
|
||||||
|
|
@ -482,6 +494,7 @@
|
||||||
"LabelNotificationsMaxQueueSize": "Maksymalny rozmiar kolejki dla powiadomień",
|
"LabelNotificationsMaxQueueSize": "Maksymalny rozmiar kolejki dla powiadomień",
|
||||||
"LabelNotificationsMaxQueueSizeHelp": "Zdarzenia są ograniczone do 1 na sekundę. Zdarzenia będą ignorowane jeśli kolejka ma maksymalny rozmiar. Zapobiega to spamowaniu powiadomieniami.",
|
"LabelNotificationsMaxQueueSizeHelp": "Zdarzenia są ograniczone do 1 na sekundę. Zdarzenia będą ignorowane jeśli kolejka ma maksymalny rozmiar. Zapobiega to spamowaniu powiadomieniami.",
|
||||||
"LabelNumberOfBooks": "Liczba książek",
|
"LabelNumberOfBooks": "Liczba książek",
|
||||||
|
"LabelNumberOfChapters": "Liczba rozdziałów:",
|
||||||
"LabelNumberOfEpisodes": "# Odcinków",
|
"LabelNumberOfEpisodes": "# Odcinków",
|
||||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nazwa deklaracji OpenID zawierającej zaawansowane uprawnienia do działań użytkownika w aplikacji, które będą miały zastosowanie do ról innych niż administracyjne (<b>jeśli skonfigurowano</b>). Jeśli deklaracja nie zostanie uwzględniona w odpowiedzi, dostęp do ABS zostanie zablokowany. Brak jednej opcji zostanie uznany za <code>fałsz</code>. Upewnij się, że deklaracja dostawcy tożsamości jest zgodna z oczekiwaną strukturą:",
|
"LabelOpenIDAdvancedPermsClaimDescription": "Nazwa deklaracji OpenID zawierającej zaawansowane uprawnienia do działań użytkownika w aplikacji, które będą miały zastosowanie do ról innych niż administracyjne (<b>jeśli skonfigurowano</b>). Jeśli deklaracja nie zostanie uwzględniona w odpowiedzi, dostęp do ABS zostanie zablokowany. Brak jednej opcji zostanie uznany za <code>fałsz</code>. Upewnij się, że deklaracja dostawcy tożsamości jest zgodna z oczekiwaną strukturą:",
|
||||||
"LabelOpenIDClaims": "Pozostaw poniższe opcje puste, aby wyłączyć zaawansowane przypisywanie grup i uprawnień. Automatycznie zostanie przypisana grupa „Użytkownik”.",
|
"LabelOpenIDClaims": "Pozostaw poniższe opcje puste, aby wyłączyć zaawansowane przypisywanie grup i uprawnień. Automatycznie zostanie przypisana grupa „Użytkownik”.",
|
||||||
|
|
@ -559,9 +572,11 @@
|
||||||
"LabelSelectUsers": "Wybór użytkowników",
|
"LabelSelectUsers": "Wybór użytkowników",
|
||||||
"LabelSendEbookToDevice": "Wyślij ebook do...",
|
"LabelSendEbookToDevice": "Wyślij ebook do...",
|
||||||
"LabelSequence": "Kolejność",
|
"LabelSequence": "Kolejność",
|
||||||
|
"LabelSerial": "Seria",
|
||||||
"LabelSeries": "Serie",
|
"LabelSeries": "Serie",
|
||||||
"LabelSeriesName": "Nazwy serii",
|
"LabelSeriesName": "Nazwy serii",
|
||||||
"LabelSeriesProgress": "Postęp w serii",
|
"LabelSeriesProgress": "Postęp w serii",
|
||||||
|
"LabelServerLogLevel": "Poziom logowania servera",
|
||||||
"LabelServerYearReview": "Podsumowanie serwera w roku ({0})",
|
"LabelServerYearReview": "Podsumowanie serwera w roku ({0})",
|
||||||
"LabelSetEbookAsPrimary": "Ustaw jako pierwszy",
|
"LabelSetEbookAsPrimary": "Ustaw jako pierwszy",
|
||||||
"LabelSetEbookAsSupplementary": "Ustaw jako dodatkowy",
|
"LabelSetEbookAsSupplementary": "Ustaw jako dodatkowy",
|
||||||
|
|
@ -605,6 +620,7 @@
|
||||||
"LabelSettingsStoreMetadataWithItemHelp": "Domyślnie metadane są przechowywane w folderze /metadata/items, włączenie tej opcji spowoduje, że okładka będzie przechowywana w folderze ksiązki. Tylko jedna okładka o nazwie pliku \"cover\" będzie przechowywana",
|
"LabelSettingsStoreMetadataWithItemHelp": "Domyślnie metadane są przechowywane w folderze /metadata/items, włączenie tej opcji spowoduje, że okładka będzie przechowywana w folderze ksiązki. Tylko jedna okładka o nazwie pliku \"cover\" będzie przechowywana",
|
||||||
"LabelSettingsTimeFormat": "Format czasu",
|
"LabelSettingsTimeFormat": "Format czasu",
|
||||||
"LabelShare": "Udostępnij",
|
"LabelShare": "Udostępnij",
|
||||||
|
"LabelShareDownloadableHelp": "Użytkownicy mogą przy pomocy linka ściągnąć archiwum ZIP pozycji biblioteki",
|
||||||
"LabelShareOpen": "Otwórz udział",
|
"LabelShareOpen": "Otwórz udział",
|
||||||
"LabelShareURL": "Link do udziału",
|
"LabelShareURL": "Link do udziału",
|
||||||
"LabelShowAll": "Pokaż wszystko",
|
"LabelShowAll": "Pokaż wszystko",
|
||||||
|
|
@ -619,6 +635,7 @@
|
||||||
"LabelStartTime": "Czas rozpoczęcia",
|
"LabelStartTime": "Czas rozpoczęcia",
|
||||||
"LabelStarted": "Rozpoczęty",
|
"LabelStarted": "Rozpoczęty",
|
||||||
"LabelStartedAt": "Rozpoczęto",
|
"LabelStartedAt": "Rozpoczęto",
|
||||||
|
"LabelStartedDate": "Rozpoczęto {0}",
|
||||||
"LabelStatsAudioTracks": "Ścieżki audio",
|
"LabelStatsAudioTracks": "Ścieżki audio",
|
||||||
"LabelStatsAuthors": "Autorzy",
|
"LabelStatsAuthors": "Autorzy",
|
||||||
"LabelStatsBestDay": "Najlepszy dzień",
|
"LabelStatsBestDay": "Najlepszy dzień",
|
||||||
|
|
@ -641,11 +658,14 @@
|
||||||
"LabelTagsAccessibleToUser": "Tagi dostępne dla użytkownika",
|
"LabelTagsAccessibleToUser": "Tagi dostępne dla użytkownika",
|
||||||
"LabelTagsNotAccessibleToUser": "Znaczniki niedostępne dla użytkownika",
|
"LabelTagsNotAccessibleToUser": "Znaczniki niedostępne dla użytkownika",
|
||||||
"LabelTasks": "Uruchomione zadania",
|
"LabelTasks": "Uruchomione zadania",
|
||||||
|
"LabelTextEditorBulletedList": "Lista punktowana",
|
||||||
"LabelTextEditorLink": "Link",
|
"LabelTextEditorLink": "Link",
|
||||||
"LabelTextEditorNumberedList": "Lista numerowana",
|
"LabelTextEditorNumberedList": "Lista numerowana",
|
||||||
"LabelTextEditorUnlink": "Usuń link",
|
"LabelTextEditorUnlink": "Usuń link",
|
||||||
|
"LabelTheme": "Kompozycja",
|
||||||
"LabelThemeDark": "Ciemny",
|
"LabelThemeDark": "Ciemny",
|
||||||
"LabelThemeLight": "Jasny",
|
"LabelThemeLight": "Jasny",
|
||||||
|
"LabelThemeSepia": "Sepia",
|
||||||
"LabelTimeDurationXHours": "{0} godzin",
|
"LabelTimeDurationXHours": "{0} godzin",
|
||||||
"LabelTimeDurationXMinutes": "{0} minuty",
|
"LabelTimeDurationXMinutes": "{0} minuty",
|
||||||
"LabelTimeDurationXSeconds": "{0} sekundy",
|
"LabelTimeDurationXSeconds": "{0} sekundy",
|
||||||
|
|
@ -668,7 +688,12 @@
|
||||||
"LabelTrackFromFilename": "Ścieżka z nazwy pliku",
|
"LabelTrackFromFilename": "Ścieżka z nazwy pliku",
|
||||||
"LabelTrackFromMetadata": "Ścieżka z metadanych",
|
"LabelTrackFromMetadata": "Ścieżka z metadanych",
|
||||||
"LabelTracks": "Ścieżki",
|
"LabelTracks": "Ścieżki",
|
||||||
|
"LabelTracksMultiTrack": "Wielościeżkowy",
|
||||||
|
"LabelTracksNone": "Brak ścieżek",
|
||||||
|
"LabelTracksSingleTrack": "Pojedyncza ścieżka",
|
||||||
|
"LabelTrailer": "Zwiastun",
|
||||||
"LabelType": "Typ",
|
"LabelType": "Typ",
|
||||||
|
"LabelUnabridged": "Pełna wersja",
|
||||||
"LabelUndo": "Wycofaj",
|
"LabelUndo": "Wycofaj",
|
||||||
"LabelUnknown": "Nieznany",
|
"LabelUnknown": "Nieznany",
|
||||||
"LabelUnknownPublishDate": "Nieznana data publikacji",
|
"LabelUnknownPublishDate": "Nieznana data publikacji",
|
||||||
|
|
@ -681,8 +706,10 @@
|
||||||
"LabelUploaderDragAndDropFilesOnly": "Przeciągnij i upuść pliki",
|
"LabelUploaderDragAndDropFilesOnly": "Przeciągnij i upuść pliki",
|
||||||
"LabelUploaderDropFiles": "Puść pliki",
|
"LabelUploaderDropFiles": "Puść pliki",
|
||||||
"LabelUploaderItemFetchMetadataHelp": "Automatycznie pobierz tytuł, autora i serie",
|
"LabelUploaderItemFetchMetadataHelp": "Automatycznie pobierz tytuł, autora i serie",
|
||||||
|
"LabelUseAdvancedOptions": "Opcje zaawansowane",
|
||||||
"LabelUseChapterTrack": "Użyj ścieżki rozdziału",
|
"LabelUseChapterTrack": "Użyj ścieżki rozdziału",
|
||||||
"LabelUseFullTrack": "Użycie ścieżki rozdziału",
|
"LabelUseFullTrack": "Użycie ścieżki rozdziału",
|
||||||
|
"LabelUseZeroForUnlimited": "Użyj 0, aby wyłączyć ograniczenia",
|
||||||
"LabelUser": "Użytkownik",
|
"LabelUser": "Użytkownik",
|
||||||
"LabelUsername": "Nazwa użytkownika",
|
"LabelUsername": "Nazwa użytkownika",
|
||||||
"LabelValue": "Wartość",
|
"LabelValue": "Wartość",
|
||||||
|
|
@ -701,8 +728,11 @@
|
||||||
"LabelYourBookmarks": "Twoje zakładki",
|
"LabelYourBookmarks": "Twoje zakładki",
|
||||||
"LabelYourPlaylists": "Twoje playlisty",
|
"LabelYourPlaylists": "Twoje playlisty",
|
||||||
"LabelYourProgress": "Twój postęp",
|
"LabelYourProgress": "Twój postęp",
|
||||||
|
"MessageAddToPlayerQueue": "Dodaj do kolejki odtwarzania",
|
||||||
"MessageAppriseDescription": "Aby użyć tej funkcji, konieczne jest posiadanie instancji <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> albo innego rozwiązania, które obsługuje schemat zapytań Apprise. <br />URL do interfejsu API powinno być całkowitą ścieżką, np., jeśli Twoje API do powiadomień jest dostępne pod adresem <code>http://192.168.1.1:8337</code> to wpisany tutaj URL powinien mieć postać: <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "Aby użyć tej funkcji, konieczne jest posiadanie instancji <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> albo innego rozwiązania, które obsługuje schemat zapytań Apprise. <br />URL do interfejsu API powinno być całkowitą ścieżką, np., jeśli Twoje API do powiadomień jest dostępne pod adresem <code>http://192.168.1.1:8337</code> to wpisany tutaj URL powinien mieć postać: <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAsinCheck": "Upewnij się, że używasz ASIN z poprawnego regionu Audible, nie Amazona.",
|
||||||
"MessageAuthenticationLegacyTokenWarning": "Starsze tokeny API zostaną w przyszłości usunięte. Zamiast nich należy używać <a href=\"/config/api-keys\">kluczy API</a>.",
|
"MessageAuthenticationLegacyTokenWarning": "Starsze tokeny API zostaną w przyszłości usunięte. Zamiast nich należy używać <a href=\"/config/api-keys\">kluczy API</a>.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Zrestartuj serwer aby zastosować zmiany w OIDC.",
|
||||||
"MessageAuthenticationSecurityMessage": "Uwierzytelnianie zostało ulepszone ze względów bezpieczeństwa. Wszyscy użytkownicy muszą się ponownie zalogować.",
|
"MessageAuthenticationSecurityMessage": "Uwierzytelnianie zostało ulepszone ze względów bezpieczeństwa. Wszyscy użytkownicy muszą się ponownie zalogować.",
|
||||||
"MessageBackupsDescription": "Kopie zapasowe obejmują użytkowników, postępy użytkowników, szczegóły pozycji biblioteki, ustawienia serwera i obrazy przechowywane w <code>/metadata/items</code> & <code>/metadata/authors</code>. Kopie zapasowe nie obejmują żadnych plików przechowywanych w folderach biblioteki.",
|
"MessageBackupsDescription": "Kopie zapasowe obejmują użytkowników, postępy użytkowników, szczegóły pozycji biblioteki, ustawienia serwera i obrazy przechowywane w <code>/metadata/items</code> & <code>/metadata/authors</code>. Kopie zapasowe nie obejmują żadnych plików przechowywanych w folderach biblioteki.",
|
||||||
"MessageBackupsLocationEditNote": "Uwaga: Zmiana lokalizacji kopii zapasowej nie przenosi ani nie modyfikuje istniejących kopii zapasowych",
|
"MessageBackupsLocationEditNote": "Uwaga: Zmiana lokalizacji kopii zapasowej nie przenosi ani nie modyfikuje istniejących kopii zapasowych",
|
||||||
|
|
@ -716,6 +746,7 @@
|
||||||
"MessageBookshelfNoResultsForFilter": "Nie znaleziono żadnych pozycji przy aktualnym filtrowaniu \"{0}: {1}\"",
|
"MessageBookshelfNoResultsForFilter": "Nie znaleziono żadnych pozycji przy aktualnym filtrowaniu \"{0}: {1}\"",
|
||||||
"MessageBookshelfNoResultsForQuery": "Brak wyników zapytania",
|
"MessageBookshelfNoResultsForQuery": "Brak wyników zapytania",
|
||||||
"MessageBookshelfNoSeries": "Nie masz jeszcze żadnych serii",
|
"MessageBookshelfNoSeries": "Nie masz jeszcze żadnych serii",
|
||||||
|
"MessageBulkChapterPattern": "Ile rozdziałów chcesz dodać przy pomocy tego wzorca numeracji?",
|
||||||
"MessageChapterEndIsAfter": "Koniec rozdziału następuje po zakończeniu audiobooka",
|
"MessageChapterEndIsAfter": "Koniec rozdziału następuje po zakończeniu audiobooka",
|
||||||
"MessageChapterErrorFirstNotZero": "Pierwszy rozdział musi rozpoczynać się na 0",
|
"MessageChapterErrorFirstNotZero": "Pierwszy rozdział musi rozpoczynać się na 0",
|
||||||
"MessageChapterErrorStartGteDuration": "Nieprawidłowy czas rozpoczęcia, musi być krótszy niż długość audiobooka",
|
"MessageChapterErrorStartGteDuration": "Nieprawidłowy czas rozpoczęcia, musi być krótszy niż długość audiobooka",
|
||||||
|
|
@ -778,6 +809,7 @@
|
||||||
"MessageFeedURLWillBe": "URL kanału: {0}",
|
"MessageFeedURLWillBe": "URL kanału: {0}",
|
||||||
"MessageFetching": "Pobieranie...",
|
"MessageFetching": "Pobieranie...",
|
||||||
"MessageForceReScanDescription": "przeskanuje wszystkie pliki ponownie, jak przy świeżym skanowaniu. Tagi ID3 plików audio, pliki OPF i pliki tekstowe będą skanowane jak nowe.",
|
"MessageForceReScanDescription": "przeskanuje wszystkie pliki ponownie, jak przy świeżym skanowaniu. Tagi ID3 plików audio, pliki OPF i pliki tekstowe będą skanowane jak nowe.",
|
||||||
|
"MessageHeatmapListeningTimeTooltip": "<strong>{0} słucha</strong> na {1}",
|
||||||
"MessageImportantNotice": "Ważna informacja!",
|
"MessageImportantNotice": "Ważna informacja!",
|
||||||
"MessageInsertChapterBelow": "Wstaw rozdział poniżej",
|
"MessageInsertChapterBelow": "Wstaw rozdział poniżej",
|
||||||
"MessageInvalidAsin": "Nieprawidłowy ASIN",
|
"MessageInvalidAsin": "Nieprawidłowy ASIN",
|
||||||
|
|
@ -848,13 +880,34 @@
|
||||||
"MessageResetChaptersConfirm": "Czy na pewno chcesz zresetować rozdziały i cofnąć wprowadzone zmiany?",
|
"MessageResetChaptersConfirm": "Czy na pewno chcesz zresetować rozdziały i cofnąć wprowadzone zmiany?",
|
||||||
"MessageRestoreBackupConfirm": "Czy na pewno chcesz przywrócić kopię zapasową utworzoną w dniu",
|
"MessageRestoreBackupConfirm": "Czy na pewno chcesz przywrócić kopię zapasową utworzoną w dniu",
|
||||||
"MessageRestoreBackupWarning": "Przywrócenie kopii zapasowej spowoduje nadpisanie bazy danych w folderze /config oraz okładek w folderze /metadata/items & /metadata/authors.<br /><br />Kopie zapasowe nie modyfikują żadnego pliku w folderach z plikami audio. Jeśli włączyłeś ustawienia serwera, aby przechowywać okładki i metadane w folderach biblioteki, to nie są one zapisywane w kopii zapasowej lub nadpisywane<br /><br />Wszyscy klienci korzystający z Twojego serwera będą automatycznie odświeżani.",
|
"MessageRestoreBackupWarning": "Przywrócenie kopii zapasowej spowoduje nadpisanie bazy danych w folderze /config oraz okładek w folderze /metadata/items & /metadata/authors.<br /><br />Kopie zapasowe nie modyfikują żadnego pliku w folderach z plikami audio. Jeśli włączyłeś ustawienia serwera, aby przechowywać okładki i metadane w folderach biblioteki, to nie są one zapisywane w kopii zapasowej lub nadpisywane<br /><br />Wszyscy klienci korzystający z Twojego serwera będą automatycznie odświeżani.",
|
||||||
|
"MessageScheduleLibraryScanNote": "W przypadku większości użytkowników zaleca się pozostawienie tej funkcji wyłączonej i włączenie opcji monitorowania folderów. Monitor folderów automatycznie wykrywa zmiany w folderach biblioteki. Monitor folderów nie działa w przypadku wszystkich systemów plików (np. NFS), dlatego zamiast niego można używać zaplanowanych skanowań biblioteki.",
|
||||||
|
"MessageScheduleRunEveryWeekdayAtTime": "Uruchom w każdy {0} o {1}",
|
||||||
"MessageSearchResultsFor": "Wyniki wyszukiwania dla",
|
"MessageSearchResultsFor": "Wyniki wyszukiwania dla",
|
||||||
"MessageSelected": "{0} wybranych",
|
"MessageSelected": "{0} wybranych",
|
||||||
"MessageServerCouldNotBeReached": "Nie udało się uzyskać połączenia z serwerem",
|
"MessageServerCouldNotBeReached": "Nie udało się uzyskać połączenia z serwerem",
|
||||||
|
"MessageSetChaptersFromTracksDescription": "Ustaw rozdziały, używając każdego pliku audio jako rozdziału, a tytuł rozdziału jako nazwy pliku audio.",
|
||||||
"MessageShareExpirationWillBe": "Czas udostępniania <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "Czas udostępniania <strong>{0}</strong>",
|
||||||
"MessageShareExpiresIn": "Wygaśnie za {0}",
|
"MessageShareExpiresIn": "Wygaśnie za {0}",
|
||||||
"MessageShareURLWillBe": "Udostępnione pod linkiem <strong>{0}</strong>",
|
"MessageShareURLWillBe": "Udostępnione pod linkiem <strong>{0}</strong>",
|
||||||
"MessageStartPlaybackAtTime": "Rozpoczęcie odtwarzania \"{0}\" od {1}?",
|
"MessageStartPlaybackAtTime": "Rozpoczęcie odtwarzania \"{0}\" od {1}?",
|
||||||
|
"MessageTaskAudioFileNotWritable": "Plik audio \"{0}\" jest niemodyfikowalny",
|
||||||
|
"MessageTaskCanceledByUser": "Zadanie anulowane przez użytkownika",
|
||||||
|
"MessageTaskDownloadingEpisodeDescription": "Ściąganie odcinka \"{0}\"",
|
||||||
|
"MessageTaskEmbeddingMetadata": "Wbudowywanie medatanych",
|
||||||
|
"MessageTaskEmbeddingMetadataDescription": "Wbudowywanie metadanych do audiobooka \"{0}\"",
|
||||||
|
"MessageTaskEncodingM4b": "Kodowanie M4B",
|
||||||
|
"MessageTaskEncodingM4bDescription": "Konwersja audiobooka \"{0}\" do pojedynczego pliku m4b",
|
||||||
|
"MessageTaskFailed": "Niepowodzenie",
|
||||||
|
"MessageTaskFailedToBackupAudioFile": "Nieudana próba wykonania kopii zapasowego pliku audio \"{0}\"",
|
||||||
|
"MessageTaskFailedToCreateCacheDirectory": "Nie udało się utworzyć katalogu cache",
|
||||||
|
"MessageTaskFailedToEmbedMetadataInFile": "Nie udało się wbudować metadanych do pliku \"{0}\"",
|
||||||
|
"MessageTaskFailedToWriteMetadataFile": "Niepowodzenie zapisania pliku metadanych",
|
||||||
|
"MessageTaskNoFilesToScan": "Brak plików do skanowania",
|
||||||
|
"MessageTaskScanItemsAdded": "Dodano {0}",
|
||||||
|
"MessageTaskScanItemsMissing": "Brakuje {0}",
|
||||||
|
"MessageTaskScanItemsUpdated": "Zaktualizowano {0}",
|
||||||
|
"MessageTaskScanNoChangesNeeded": "Brak zmian",
|
||||||
|
"MessageTaskTargetDirectoryNotWritable": "Brak prawa zapisu do folderu docelowego",
|
||||||
"MessageThinking": "Myślę...",
|
"MessageThinking": "Myślę...",
|
||||||
"MessageUploaderItemFailed": "Nie udało się przesłać",
|
"MessageUploaderItemFailed": "Nie udało się przesłać",
|
||||||
"MessageUploaderItemSuccess": "Przesłanie powiodło się!",
|
"MessageUploaderItemSuccess": "Przesłanie powiodło się!",
|
||||||
|
|
@ -912,6 +965,21 @@
|
||||||
"ToastBookmarkRemoveSuccess": "Zakładka została usunięta",
|
"ToastBookmarkRemoveSuccess": "Zakładka została usunięta",
|
||||||
"ToastCollectionRemoveSuccess": "Kolekcja usunięta",
|
"ToastCollectionRemoveSuccess": "Kolekcja usunięta",
|
||||||
"ToastCollectionUpdateSuccess": "Zaktualizowano kolekcję",
|
"ToastCollectionUpdateSuccess": "Zaktualizowano kolekcję",
|
||||||
|
"ToastCoverSearchFailed": "Nieudane wyszukiwanie okładki",
|
||||||
|
"ToastCoverUpdateFailed": "Nieudana aktualizacja okładki",
|
||||||
|
"ToastDateTimeInvalidOrIncomplete": "Niepoprawna data i czas",
|
||||||
|
"ToastDeleteFileFailed": "Usunięcie pliku nie powiodło się",
|
||||||
|
"ToastDeleteFileSuccess": "Plik został usunięty",
|
||||||
|
"ToastDeviceAddFailed": "Nieudana próba dodania urządzenia",
|
||||||
|
"ToastDeviceNameAlreadyExists": "Czytnik z taką nazwą już istnieje",
|
||||||
|
"ToastDeviceTestEmailFailed": "NIeudana próba wysłania testowego maila",
|
||||||
|
"ToastDeviceTestEmailSuccess": "Testowy email został wysłany",
|
||||||
|
"ToastEmailSettingsUpdateSuccess": "Ustawienia email zaktualizowane",
|
||||||
|
"ToastEpisodeDownloadQueueClearSuccess": "Wyczyszczono kolejkę epizodów do ściągnięcia",
|
||||||
|
"ToastEpisodeUpdateSuccess": "Zaktualizowano {0} odcinków",
|
||||||
|
"ToastInvalidImageUrl": "Nieprawidłowy URL obrazu",
|
||||||
|
"ToastInvalidUrl": "Nieprawidłowy URL",
|
||||||
|
"ToastInvalidUrls": "Jeden lub więcej URL-i są nieprawidłowe",
|
||||||
"ToastItemCoverUpdateSuccess": "Zaktualizowano okładkę",
|
"ToastItemCoverUpdateSuccess": "Zaktualizowano okładkę",
|
||||||
"ToastItemDetailsUpdateSuccess": "Zaktualizowano szczegóły",
|
"ToastItemDetailsUpdateSuccess": "Zaktualizowano szczegóły",
|
||||||
"ToastItemMarkedAsFinishedFailed": "Nie udało się oznaczyć jako ukończone",
|
"ToastItemMarkedAsFinishedFailed": "Nie udało się oznaczyć jako ukończone",
|
||||||
|
|
@ -925,12 +993,28 @@
|
||||||
"ToastLibraryScanFailedToStart": "Nie udało się rozpocząć skanowania",
|
"ToastLibraryScanFailedToStart": "Nie udało się rozpocząć skanowania",
|
||||||
"ToastLibraryScanStarted": "Rozpoczęto skanowanie biblioteki",
|
"ToastLibraryScanStarted": "Rozpoczęto skanowanie biblioteki",
|
||||||
"ToastLibraryUpdateSuccess": "Zaktualizowano \"{0}\" pozycji",
|
"ToastLibraryUpdateSuccess": "Zaktualizowano \"{0}\" pozycji",
|
||||||
|
"ToastMatchAllAuthorsFailed": "Nie udało się dopasować wszystkich autorów",
|
||||||
|
"ToastMustHaveAtLeastOnePath": "Musi mieć przynajmniej jedną ścieżkę",
|
||||||
|
"ToastNameEmailRequired": "Nazwa i email są wymagane",
|
||||||
|
"ToastNameRequired": "Imię jest wymagane",
|
||||||
|
"ToastNewApiKeyUserError": "Trzeba wybrać użytkownika",
|
||||||
|
"ToastNewEpisodesFound": "Znaleziono {0} nowych odcinków",
|
||||||
|
"ToastNewUserCreatedFailed": "Nie udało się utworzyć konta: \"{0}\"",
|
||||||
|
"ToastNewUserCreatedSuccess": "Utworzono nowe konto",
|
||||||
|
"ToastNewUserLibraryError": "Trzeba wybrać co najmniej jedną bibliotekę",
|
||||||
|
"ToastNewUserPasswordError": "Hasło jest wymagane, jedynie użytkownik \"root\" może posiadać puste hasło",
|
||||||
|
"ToastNewUserTagError": "Trzeba wybrać chociaż jeden tag",
|
||||||
|
"ToastNewUserUsernameError": "Wprowadź nazwę użytkownika",
|
||||||
|
"ToastNoNewEpisodesFound": "Nie znaleziono nowych odcinków",
|
||||||
|
"ToastNoRSSFeed": "Podcast nie posiada RSS Feed",
|
||||||
|
"ToastNotificationFailedMaximum": "Maks. ilość nieudanych prób musi być >= 0",
|
||||||
"ToastPlaylistCreateFailed": "Nie udało się utworzyć playlisty",
|
"ToastPlaylistCreateFailed": "Nie udało się utworzyć playlisty",
|
||||||
"ToastPlaylistCreateSuccess": "Playlista utworzona",
|
"ToastPlaylistCreateSuccess": "Playlista utworzona",
|
||||||
"ToastPlaylistRemoveSuccess": "Playlista usunięta",
|
"ToastPlaylistRemoveSuccess": "Playlista usunięta",
|
||||||
"ToastPlaylistUpdateSuccess": "Playlista zaktualizowana",
|
"ToastPlaylistUpdateSuccess": "Playlista zaktualizowana",
|
||||||
"ToastPodcastCreateFailed": "Nie udało się utworzyć podcastu",
|
"ToastPodcastCreateFailed": "Nie udało się utworzyć podcastu",
|
||||||
"ToastPodcastCreateSuccess": "Podcast został pomyślnie utworzony",
|
"ToastPodcastCreateSuccess": "Podcast został pomyślnie utworzony",
|
||||||
|
"ToastPodcastEpisodeUpdated": "Zaktualizowano odcinki",
|
||||||
"ToastRSSFeedCloseFailed": "Zamknięcie kanału RSS nie powiodło się",
|
"ToastRSSFeedCloseFailed": "Zamknięcie kanału RSS nie powiodło się",
|
||||||
"ToastRSSFeedCloseSuccess": "Zamknięcie kanału RSS powiodło się",
|
"ToastRSSFeedCloseSuccess": "Zamknięcie kanału RSS powiodło się",
|
||||||
"ToastRemoveItemFromCollectionFailed": "Nie udało się usunąć elementu z kolekcji",
|
"ToastRemoveItemFromCollectionFailed": "Nie udało się usunąć elementu z kolekcji",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"ButtonAdd": "Adicionar",
|
"ButtonAdd": "Adicionar",
|
||||||
|
"ButtonAddApiKey": "Adicionar Chave API",
|
||||||
"ButtonAddChapters": "Adicionar Capítulos",
|
"ButtonAddChapters": "Adicionar Capítulos",
|
||||||
"ButtonAddDevice": "Adicionar Dispositivo",
|
"ButtonAddDevice": "Adicionar Dispositivo",
|
||||||
"ButtonAddLibrary": "Adicionar Biblioteca",
|
"ButtonAddLibrary": "Adicionar Biblioteca",
|
||||||
|
|
|
||||||
|
|
@ -1 +1,200 @@
|
||||||
{}
|
{
|
||||||
|
"ButtonAdd": "Adaugă",
|
||||||
|
"ButtonAddApiKey": "Adaugă cheia API",
|
||||||
|
"ButtonAddChapters": "Adaugă Capitole",
|
||||||
|
"ButtonAddDevice": "Adaugă Dispozitiv",
|
||||||
|
"ButtonAddLibrary": "Adaugă Librărie",
|
||||||
|
"ButtonAddUser": "Adaugă Utilizator",
|
||||||
|
"ButtonAuthors": "Autori",
|
||||||
|
"ButtonBack": "Înapoi",
|
||||||
|
"ButtonCancel": "Anulează",
|
||||||
|
"ButtonClearFilter": "Șterge filtrul",
|
||||||
|
"ButtonClose": "Închide",
|
||||||
|
"ButtonCloseFeed": "Închide sursa",
|
||||||
|
"ButtonCloseSession": "Închide Sesiunea Curentă",
|
||||||
|
"ButtonCollections": "Colecții",
|
||||||
|
"ButtonCreate": "Creează",
|
||||||
|
"ButtonDelete": "Șterge",
|
||||||
|
"ButtonHide": "Ascunde",
|
||||||
|
"ButtonHome": "Acasă",
|
||||||
|
"ButtonIssues": "Erori",
|
||||||
|
"ButtonLatest": "Noutăți",
|
||||||
|
"ButtonLibrary": "Bibliotecă",
|
||||||
|
"ButtonOk": "OK",
|
||||||
|
"ButtonOpenFeed": "Vezi noutățile",
|
||||||
|
"ButtonPause": "Pauză",
|
||||||
|
"ButtonPlay": "Redă",
|
||||||
|
"ButtonPlaylists": "Liste",
|
||||||
|
"ButtonRead": "Citește",
|
||||||
|
"ButtonReadLess": "Mai puțin",
|
||||||
|
"ButtonReadMore": "Afișează mai mult",
|
||||||
|
"ButtonRemove": "Elimină",
|
||||||
|
"ButtonSave": "Salvează",
|
||||||
|
"ButtonSearch": "Caută",
|
||||||
|
"ButtonSeries": "Serii",
|
||||||
|
"ButtonSubmit": "Trimite",
|
||||||
|
"ButtonYes": "Da",
|
||||||
|
"HeaderAccount": "Cont",
|
||||||
|
"HeaderAdvanced": "Avansat",
|
||||||
|
"HeaderAudioTracks": "Înregistrări audio",
|
||||||
|
"HeaderChapters": "Capitole",
|
||||||
|
"HeaderCollection": "Colecție",
|
||||||
|
"HeaderCollectionItems": "Conținutul colecției",
|
||||||
|
"HeaderDetails": "Detalii",
|
||||||
|
"HeaderEbookFiles": "Ebook-uri",
|
||||||
|
"HeaderEpisodes": "Episoade",
|
||||||
|
"HeaderEreaderSettings": "Setări eReader",
|
||||||
|
"HeaderLatestEpisodes": "Episoade recente",
|
||||||
|
"HeaderLibraries": "Biblioteci",
|
||||||
|
"HeaderOpenRSSFeed": "Deschide flux RSS",
|
||||||
|
"HeaderPlaylist": "Listă de redare",
|
||||||
|
"HeaderPlaylistItems": "Conținut listă",
|
||||||
|
"HeaderRSSFeedGeneral": "Date RSS",
|
||||||
|
"HeaderRSSFeedIsOpen": "RSS activ",
|
||||||
|
"HeaderSettings": "Setări",
|
||||||
|
"HeaderSleepTimer": "Timer de somn",
|
||||||
|
"HeaderStatsMinutesListeningChart": "Minute ascultate (ultimele 7 zile)",
|
||||||
|
"HeaderStatsRecentSessions": "Sesiuni recente",
|
||||||
|
"HeaderTableOfContents": "Cuprins",
|
||||||
|
"HeaderYourStats": "Progresul tău",
|
||||||
|
"LabelAddToPlaylist": "Adaugă în listă",
|
||||||
|
"LabelAddedAt": "Adăugat la",
|
||||||
|
"LabelAddedDate": "Adăugat {0}",
|
||||||
|
"LabelAll": "Toate",
|
||||||
|
"LabelAuthor": "Autor",
|
||||||
|
"LabelAuthorFirstLast": "Autor (Prenume Nume)",
|
||||||
|
"LabelAuthorLastFirst": "Autor (Nume, Prenume)",
|
||||||
|
"LabelAuthors": "Autori",
|
||||||
|
"LabelAutoDownloadEpisodes": "Descarcă automat episoadele",
|
||||||
|
"LabelBooks": "Cărți",
|
||||||
|
"LabelChapters": "Capitole",
|
||||||
|
"LabelClosePlayer": "Închide playerul",
|
||||||
|
"LabelCollapseSeries": "Restrânge seriile",
|
||||||
|
"LabelComplete": "Finalizat",
|
||||||
|
"LabelContinueListening": "Ascultă în continuare",
|
||||||
|
"LabelContinueReading": "Continuă lectura",
|
||||||
|
"LabelContinueSeries": "Continuă seria",
|
||||||
|
"LabelDescription": "Descriere",
|
||||||
|
"LabelDiscover": "Descoperă",
|
||||||
|
"LabelDownload": "Descarcă",
|
||||||
|
"LabelDuration": "Durată",
|
||||||
|
"LabelEbook": "Carte electronică",
|
||||||
|
"LabelEbooks": "Cărți electronice",
|
||||||
|
"LabelEnable": "Activează",
|
||||||
|
"LabelEnd": "Sfârșit",
|
||||||
|
"LabelEndOfChapter": "Sfârșitul capitolului",
|
||||||
|
"LabelEpisode": "Episod",
|
||||||
|
"LabelExplicit": "Explicit",
|
||||||
|
"LabelFeedURL": "URL flux",
|
||||||
|
"LabelFile": "Fișier",
|
||||||
|
"LabelFileBirthtime": "Data creării fișierului",
|
||||||
|
"LabelFileModified": "Fișier modificat",
|
||||||
|
"LabelFilename": "Nume fișier",
|
||||||
|
"LabelFinished": "Finalizat",
|
||||||
|
"LabelFolder": "Dosar",
|
||||||
|
"LabelFontBoldness": "Grosimea fontului",
|
||||||
|
"LabelFontScale": "Mărimea fontului",
|
||||||
|
"LabelGenre": "Gen",
|
||||||
|
"LabelGenres": "Genuri",
|
||||||
|
"LabelHasEbook": "Are carte electronică",
|
||||||
|
"LabelHasSupplementaryEbook": "Are carte electronică suplimentară",
|
||||||
|
"LabelHost": "Gazdă",
|
||||||
|
"LabelInProgress": "În desfășurare",
|
||||||
|
"LabelIncomplete": "Incomplet",
|
||||||
|
"LabelLanguage": "Limbă",
|
||||||
|
"LabelLayout": "Aspect",
|
||||||
|
"LabelLayoutSinglePage": "Pagină unică",
|
||||||
|
"LabelLineSpacing": "Spațiere între rânduri",
|
||||||
|
"LabelListenAgain": "Ascultă din nou",
|
||||||
|
"LabelMediaType": "Tip media",
|
||||||
|
"LabelMissing": "Lipsă",
|
||||||
|
"LabelMore": "Mai multe",
|
||||||
|
"LabelMoreInfo": "Mai multe informații",
|
||||||
|
"LabelName": "Nume",
|
||||||
|
"LabelNarrator": "Narator",
|
||||||
|
"LabelNarrators": "Naratori",
|
||||||
|
"LabelNewestAuthors": "Autori noi",
|
||||||
|
"LabelNewestEpisodes": "Episoade noi",
|
||||||
|
"LabelNotFinished": "Nefinalizat",
|
||||||
|
"LabelNotStarted": "Neînceput",
|
||||||
|
"LabelNumberOfEpisodes": "# de Episoade",
|
||||||
|
"LabelPassword": "Parolă",
|
||||||
|
"LabelPath": "Cale",
|
||||||
|
"LabelPodcast": "Podcast",
|
||||||
|
"LabelPodcasts": "Podcasturi",
|
||||||
|
"LabelPreventIndexing": "Împiedică indexarea fluxului în directoarele iTunes și Google Podcasts",
|
||||||
|
"LabelProgress": "Progres",
|
||||||
|
"LabelPubDate": "Data publicării",
|
||||||
|
"LabelPublishYear": "Anul publicării",
|
||||||
|
"LabelPublishedDate": "Publicat la {0}",
|
||||||
|
"LabelRSSFeedCustomOwnerEmail": "Email personalizat al proprietarului",
|
||||||
|
"LabelRSSFeedCustomOwnerName": "Nume personalizat al proprietarului",
|
||||||
|
"LabelRSSFeedOpen": "Flux RSS deschis",
|
||||||
|
"LabelRSSFeedPreventIndexing": "Previne indexarea",
|
||||||
|
"LabelRSSFeedSlug": "Identificator flux RSS",
|
||||||
|
"LabelRandomly": "Aleatoriu",
|
||||||
|
"LabelRead": "Citește",
|
||||||
|
"LabelReadAgain": "Citește din nou",
|
||||||
|
"LabelRecentSeries": "Serii recente",
|
||||||
|
"LabelRecentlyAdded": "Adăugate recent",
|
||||||
|
"LabelSeason": "Sezon",
|
||||||
|
"LabelSeries": "Serii",
|
||||||
|
"LabelSetEbookAsPrimary": "Setează ca principală",
|
||||||
|
"LabelSetEbookAsSupplementary": "Setează ca suplimentară",
|
||||||
|
"LabelShowAll": "Afișează tot",
|
||||||
|
"LabelSize": "Dimensiune",
|
||||||
|
"LabelSleepTimer": "Timer de somn",
|
||||||
|
"LabelStart": "Pornește",
|
||||||
|
"LabelStatsBestDay": "Ziua cea mai bună",
|
||||||
|
"LabelStatsDailyAverage": "Medie zilnică",
|
||||||
|
"LabelStatsDays": "Zile",
|
||||||
|
"LabelStatsDaysListened": "Zile ascultate",
|
||||||
|
"LabelStatsInARow": "la rând",
|
||||||
|
"LabelStatsItemsFinished": "Finalizate",
|
||||||
|
"LabelStatsMinutes": "minute",
|
||||||
|
"LabelStatsMinutesListening": "Minute ascultate",
|
||||||
|
"LabelStatsWeekListening": "Ascultare săptămânală",
|
||||||
|
"LabelTag": "Etichetă",
|
||||||
|
"LabelTags": "Etichete",
|
||||||
|
"LabelTheme": "Temă",
|
||||||
|
"LabelThemeDark": "Întunecat",
|
||||||
|
"LabelThemeLight": "Deschis",
|
||||||
|
"LabelTimeRemaining": "{0} rămase",
|
||||||
|
"LabelTitle": "Titlu",
|
||||||
|
"LabelTracks": "Fișiere audio",
|
||||||
|
"LabelType": "Tip",
|
||||||
|
"LabelUnknown": "Necunoscut",
|
||||||
|
"LabelUser": "Utilizator",
|
||||||
|
"LabelUsername": "Nume utilizator",
|
||||||
|
"LabelYearReviewHide": "Ascunde retrospectiva anului",
|
||||||
|
"LabelYearReviewShow": "Vezi retrospectiva anului",
|
||||||
|
"LabelYourBookmarks": "Semnele tale de carte",
|
||||||
|
"LabelYourProgress": "Progresul tău",
|
||||||
|
"MessageDownloadingEpisode": "Se descarcă episodul",
|
||||||
|
"MessageEpisodesQueuedForDownload": "{0} episod(e) în așteptare pentru descărcare",
|
||||||
|
"MessageFeedURLWillBe": "Adresa fluxului va fi {0}",
|
||||||
|
"MessageFetching": "Se preiau date…",
|
||||||
|
"MessageLoading": "Se încarcă…",
|
||||||
|
"MessageMarkAsFinished": "Marchează ca finalizat",
|
||||||
|
"MessageNoBookmarks": "Fără semne de carte",
|
||||||
|
"MessageNoChapters": "Fără capitole",
|
||||||
|
"MessageNoCollections": "Fără colecții",
|
||||||
|
"MessageNoItems": "Niciun element",
|
||||||
|
"MessageNoItemsFound": "Nu s-au găsit elemente",
|
||||||
|
"MessageNoListeningSessions": "Nicio sesiune de ascultare",
|
||||||
|
"MessageNoPodcastsFound": "Nu s-au găsit podcasturi",
|
||||||
|
"MessageNoUpdatesWereNecessary": "Nu au fost necesare actualizări",
|
||||||
|
"MessageNoUserPlaylists": "Nu ai nicio listă de redare",
|
||||||
|
"MessagePodcastSearchField": "Introdu termenul de căutare sau URL-ul unui flux RSS",
|
||||||
|
"MessageReportBugsAndContribute": "Raportează erori, cere funcții noi și contribuie pe",
|
||||||
|
"NoteRSSFeedPodcastAppsHttps": "Atenționare: Majoritatea aplicațiilor de podcast cer ca URL-ul fluxului RSS să folosească HTTPS",
|
||||||
|
"NoteRSSFeedPodcastAppsPubDate": "Atenționare: unul sau mai multe episoade nu au data publicării (Pub Date). Unele aplicații de podcast o cer.",
|
||||||
|
"ToastBookmarkCreateFailed": "Nu s-a putut crea semnul de carte",
|
||||||
|
"ToastItemMarkedAsFinishedFailed": "Nu s-a putut marca drept finalizat",
|
||||||
|
"ToastItemMarkedAsNotFinishedFailed": "Nu s-a putut marca drept nefinalizat",
|
||||||
|
"ToastPlaylistCreateFailed": "Nu s-a putut crea lista de redare",
|
||||||
|
"ToastPodcastCreateFailed": "Nu s-a putut crea podcastul",
|
||||||
|
"ToastPodcastCreateSuccess": "Podcast creat cu succes",
|
||||||
|
"ToastRSSFeedCloseFailed": "Nu s-a putut închide fluxul RSS",
|
||||||
|
"ToastRSSFeedCloseSuccess": "Flux RSS închis"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -436,9 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Нет {0}",
|
"LabelLibraryFilterSublistEmpty": "Нет {0}",
|
||||||
"LabelLibraryItem": "Элемент библиотеки",
|
"LabelLibraryItem": "Элемент библиотеки",
|
||||||
"LabelLibraryName": "Имя библиотеки",
|
"LabelLibraryName": "Имя библиотеки",
|
||||||
"LabelLibrarySortByProgress": "Прогресс обновлён",
|
"LabelLibrarySortByProgress": "Прогресс: Последнее обновление",
|
||||||
"LabelLibrarySortByProgressFinished": "Дата завершения",
|
"LabelLibrarySortByProgressFinished": "Прогресс: Завершено",
|
||||||
"LabelLibrarySortByProgressStarted": "Дата начала",
|
"LabelLibrarySortByProgressStarted": "Прогресс: Начато",
|
||||||
"LabelLimit": "Лимит",
|
"LabelLimit": "Лимит",
|
||||||
"LabelLineSpacing": "Межстрочный интервал",
|
"LabelLineSpacing": "Межстрочный интервал",
|
||||||
"LabelListenAgain": "Послушать снова",
|
"LabelListenAgain": "Послушать снова",
|
||||||
|
|
@ -1026,6 +1026,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "Не удалось добавить элемент(ы) в коллекцию",
|
"ToastCollectionItemsAddFailed": "Не удалось добавить элемент(ы) в коллекцию",
|
||||||
"ToastCollectionRemoveSuccess": "Коллекция удалена",
|
"ToastCollectionRemoveSuccess": "Коллекция удалена",
|
||||||
"ToastCollectionUpdateSuccess": "Коллекция обновлена",
|
"ToastCollectionUpdateSuccess": "Коллекция обновлена",
|
||||||
|
"ToastConnectionNotAvailable": "Подключение недоступно. Пожалуйста попробуйте позже",
|
||||||
|
"ToastCoverSearchFailed": "Ошибка поиска обложки",
|
||||||
"ToastCoverUpdateFailed": "Не удалось обновить обложку",
|
"ToastCoverUpdateFailed": "Не удалось обновить обложку",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "Дата и время указаны неверно или не до конца",
|
"ToastDateTimeInvalidOrIncomplete": "Дата и время указаны неверно или не до конца",
|
||||||
"ToastDeleteFileFailed": "Не удалось удалить файл",
|
"ToastDeleteFileFailed": "Не удалось удалить файл",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
{
|
{
|
||||||
"ButtonAdd": "Pridať",
|
"ButtonAdd": "Pridať",
|
||||||
|
"ButtonAddApiKey": "Pridať kľúč API",
|
||||||
"ButtonAddChapters": "Pridať kapitoly",
|
"ButtonAddChapters": "Pridať kapitoly",
|
||||||
"ButtonAddDevice": "Pridať zariadenie",
|
"ButtonAddDevice": "Pridať zariadenie",
|
||||||
"ButtonAddLibrary": "Pridať knižnicu",
|
"ButtonAddLibrary": "Pridať knižnicu",
|
||||||
"ButtonAddPodcasts": "Pridať podcasty",
|
"ButtonAddPodcasts": "Pridať podcasty",
|
||||||
"ButtonAddUser": "Pridať užívateľa",
|
"ButtonAddUser": "Pridať používateľa",
|
||||||
"ButtonAddYourFirstLibrary": "Pridajte vašu prvú knižnicu",
|
"ButtonAddYourFirstLibrary": "Pridajte vašu prvú knižnicu",
|
||||||
"ButtonApply": "Použiť",
|
"ButtonApply": "Použiť",
|
||||||
"ButtonApplyChapters": "Použiť kapitoly",
|
"ButtonApplyChapters": "Použiť kapitoly",
|
||||||
|
|
@ -20,6 +21,7 @@
|
||||||
"ButtonChooseAFolder": "Vyberte priečinok",
|
"ButtonChooseAFolder": "Vyberte priečinok",
|
||||||
"ButtonChooseFiles": "Vyberte súbory",
|
"ButtonChooseFiles": "Vyberte súbory",
|
||||||
"ButtonClearFilter": "Zrušiť filter",
|
"ButtonClearFilter": "Zrušiť filter",
|
||||||
|
"ButtonClose": "Uzavrieť",
|
||||||
"ButtonCloseFeed": "Zatvoriť zdroj",
|
"ButtonCloseFeed": "Zatvoriť zdroj",
|
||||||
"ButtonCloseSession": "Ukončiť otvorené pripojenie",
|
"ButtonCloseSession": "Ukončiť otvorené pripojenie",
|
||||||
"ButtonCollections": "Kolekcie",
|
"ButtonCollections": "Kolekcie",
|
||||||
|
|
@ -119,11 +121,13 @@
|
||||||
"HeaderAccount": "Účet",
|
"HeaderAccount": "Účet",
|
||||||
"HeaderAddCustomMetadataProvider": "Pridať vastný zdroj metadát",
|
"HeaderAddCustomMetadataProvider": "Pridať vastný zdroj metadát",
|
||||||
"HeaderAdvanced": "Pokročilé",
|
"HeaderAdvanced": "Pokročilé",
|
||||||
|
"HeaderApiKeys": "Kľúče API",
|
||||||
"HeaderAppriseNotificationSettings": "Nastavenie Apprise notifikácií",
|
"HeaderAppriseNotificationSettings": "Nastavenie Apprise notifikácií",
|
||||||
"HeaderAudioTracks": "Zvukové stopy",
|
"HeaderAudioTracks": "Zvukové stopy",
|
||||||
"HeaderAudiobookTools": "Nástroje na správu súborov audiokníh",
|
"HeaderAudiobookTools": "Nástroje na správu súborov audiokníh",
|
||||||
"HeaderAuthentication": "Overenie",
|
"HeaderAuthentication": "Overenie",
|
||||||
"HeaderBackups": "Zálohy",
|
"HeaderBackups": "Zálohy",
|
||||||
|
"HeaderBulkChapterModal": "Pridať viaceré kapitoly",
|
||||||
"HeaderChangePassword": "Zmeniť heslo",
|
"HeaderChangePassword": "Zmeniť heslo",
|
||||||
"HeaderChapters": "Kapitoly",
|
"HeaderChapters": "Kapitoly",
|
||||||
"HeaderChooseAFolder": "Vybrať priečinok",
|
"HeaderChooseAFolder": "Vybrať priečinok",
|
||||||
|
|
@ -162,6 +166,7 @@
|
||||||
"HeaderMetadataOrderOfPrecedence": "Metadáta pravidiel poradia",
|
"HeaderMetadataOrderOfPrecedence": "Metadáta pravidiel poradia",
|
||||||
"HeaderMetadataToEmbed": "Metadáta na vloženie",
|
"HeaderMetadataToEmbed": "Metadáta na vloženie",
|
||||||
"HeaderNewAccount": "Nový účet",
|
"HeaderNewAccount": "Nový účet",
|
||||||
|
"HeaderNewApiKey": "Nový kľúč API",
|
||||||
"HeaderNewLibrary": "Nová knižnica",
|
"HeaderNewLibrary": "Nová knižnica",
|
||||||
"HeaderNotificationCreate": "Vytvoriť notifikáciu",
|
"HeaderNotificationCreate": "Vytvoriť notifikáciu",
|
||||||
"HeaderNotificationUpdate": "Aktualizovať notifikáciu",
|
"HeaderNotificationUpdate": "Aktualizovať notifikáciu",
|
||||||
|
|
@ -195,6 +200,7 @@
|
||||||
"HeaderSettingsExperimental": "Experimentálne funkcie",
|
"HeaderSettingsExperimental": "Experimentálne funkcie",
|
||||||
"HeaderSettingsGeneral": "Hlavné",
|
"HeaderSettingsGeneral": "Hlavné",
|
||||||
"HeaderSettingsScanner": "Skener",
|
"HeaderSettingsScanner": "Skener",
|
||||||
|
"HeaderSettingsSecurity": "Zabezpečenie",
|
||||||
"HeaderSettingsWebClient": "Webový klient",
|
"HeaderSettingsWebClient": "Webový klient",
|
||||||
"HeaderSleepTimer": "Časovač spánku",
|
"HeaderSleepTimer": "Časovač spánku",
|
||||||
"HeaderStatsLargestItems": "Najväčšie položky",
|
"HeaderStatsLargestItems": "Najväčšie položky",
|
||||||
|
|
@ -206,6 +212,7 @@
|
||||||
"HeaderTableOfContents": "Obsah",
|
"HeaderTableOfContents": "Obsah",
|
||||||
"HeaderTools": "Nástroje",
|
"HeaderTools": "Nástroje",
|
||||||
"HeaderUpdateAccount": "Aktualizovať účet",
|
"HeaderUpdateAccount": "Aktualizovať účet",
|
||||||
|
"HeaderUpdateApiKey": "Aktualizovať kľúč API",
|
||||||
"HeaderUpdateAuthor": "Aktualizovať autora",
|
"HeaderUpdateAuthor": "Aktualizovať autora",
|
||||||
"HeaderUpdateDetails": "Aktualizovať detaily",
|
"HeaderUpdateDetails": "Aktualizovať detaily",
|
||||||
"HeaderUpdateLibrary": "Aktualizovať knižnicu",
|
"HeaderUpdateLibrary": "Aktualizovať knižnicu",
|
||||||
|
|
@ -235,6 +242,10 @@
|
||||||
"LabelAllUsersExcludingGuests": "Všetci užívatelia okrem hostí",
|
"LabelAllUsersExcludingGuests": "Všetci užívatelia okrem hostí",
|
||||||
"LabelAllUsersIncludingGuests": "Všetci užívatelia vrátane hostí",
|
"LabelAllUsersIncludingGuests": "Všetci užívatelia vrátane hostí",
|
||||||
"LabelAlreadyInYourLibrary": "Už v tvojej knižnici",
|
"LabelAlreadyInYourLibrary": "Už v tvojej knižnici",
|
||||||
|
"LabelApiKeyCreated": "Kľúč API \"{0}\" bol úspešne vytvorený.",
|
||||||
|
"LabelApiKeyCreatedDescription": "Skopírujte si kľúč API teraz, neskôr ho už neuvidíte.",
|
||||||
|
"LabelApiKeyUser": "Vykonáva v mene používateľa",
|
||||||
|
"LabelApiKeyUserDescription": "Uvedená API bude mať rovnaké práva ako používateľ, v mene ktorého koná. Rovnako v záznamoch budú jednotlivé krky uvedené, ako keby ich vykonal samotný používateľ.",
|
||||||
"LabelApiToken": "API Token",
|
"LabelApiToken": "API Token",
|
||||||
"LabelAppend": "Pridať",
|
"LabelAppend": "Pridať",
|
||||||
"LabelAudioBitrate": "Bitrate audio stopy (napr. 128k)",
|
"LabelAudioBitrate": "Bitrate audio stopy (napr. 128k)",
|
||||||
|
|
@ -284,6 +295,7 @@
|
||||||
"LabelContinueListening": "Pokračovať v počúvaní",
|
"LabelContinueListening": "Pokračovať v počúvaní",
|
||||||
"LabelContinueReading": "Pokračovať v čítaní",
|
"LabelContinueReading": "Pokračovať v čítaní",
|
||||||
"LabelContinueSeries": "Pokračovať v sérii",
|
"LabelContinueSeries": "Pokračovať v sérii",
|
||||||
|
"LabelCorsAllowed": "CORS Origins povolené",
|
||||||
"LabelCover": "Prebal",
|
"LabelCover": "Prebal",
|
||||||
"LabelCoverImageURL": "URL obrázku prebalu",
|
"LabelCoverImageURL": "URL obrázku prebalu",
|
||||||
"LabelCoverProvider": "Poskytovateľ prebalu",
|
"LabelCoverProvider": "Poskytovateľ prebalu",
|
||||||
|
|
@ -297,6 +309,7 @@
|
||||||
"LabelDeleteFromFileSystemCheckbox": "Zmazať zo systému (odškrtni len pre odstránenie z databázy)",
|
"LabelDeleteFromFileSystemCheckbox": "Zmazať zo systému (odškrtni len pre odstránenie z databázy)",
|
||||||
"LabelDescription": "Popis",
|
"LabelDescription": "Popis",
|
||||||
"LabelDeselectAll": "Odznačiť všetko",
|
"LabelDeselectAll": "Odznačiť všetko",
|
||||||
|
"LabelDetectedPattern": "Identifikovaný vzor:",
|
||||||
"LabelDevice": "Zariadenie",
|
"LabelDevice": "Zariadenie",
|
||||||
"LabelDeviceInfo": "Informácie o zariadení",
|
"LabelDeviceInfo": "Informácie o zariadení",
|
||||||
"LabelDeviceIsAvailableTo": "Zariadenie je k dispozícii...",
|
"LabelDeviceIsAvailableTo": "Zariadenie je k dispozícii...",
|
||||||
|
|
@ -346,6 +359,10 @@
|
||||||
"LabelExample": "Príklad",
|
"LabelExample": "Príklad",
|
||||||
"LabelExpandSeries": "Rozbaliť série",
|
"LabelExpandSeries": "Rozbaliť série",
|
||||||
"LabelExpandSubSeries": "Rozbaliť podsérie",
|
"LabelExpandSubSeries": "Rozbaliť podsérie",
|
||||||
|
"LabelExpired": "Vypršal",
|
||||||
|
"LabelExpiresAt": "Vyprší",
|
||||||
|
"LabelExpiresInSeconds": "Vyprší za (sekúnd)",
|
||||||
|
"LabelExpiresNever": "Nikdy",
|
||||||
"LabelExplicit": "Explicitný obsah",
|
"LabelExplicit": "Explicitný obsah",
|
||||||
"LabelExplicitChecked": "Explicitné (zaškrtnuté)",
|
"LabelExplicitChecked": "Explicitné (zaškrtnuté)",
|
||||||
"LabelExplicitUnchecked": "Ne-explicitné (nezaškrtnuté)",
|
"LabelExplicitUnchecked": "Ne-explicitné (nezaškrtnuté)",
|
||||||
|
|
@ -361,6 +378,7 @@
|
||||||
"LabelFilterByUser": "Užívateľský filter",
|
"LabelFilterByUser": "Užívateľský filter",
|
||||||
"LabelFindEpisodes": "Nájsť epizódy",
|
"LabelFindEpisodes": "Nájsť epizódy",
|
||||||
"LabelFinished": "Ukončené",
|
"LabelFinished": "Ukončené",
|
||||||
|
"LabelFinishedDate": "Dokončené {0}",
|
||||||
"LabelFolder": "Priečinok",
|
"LabelFolder": "Priečinok",
|
||||||
"LabelFolders": "Priečinky",
|
"LabelFolders": "Priečinky",
|
||||||
"LabelFontBold": "Tučné",
|
"LabelFontBold": "Tučné",
|
||||||
|
|
@ -405,6 +423,7 @@
|
||||||
"LabelLanguages": "Jazyky",
|
"LabelLanguages": "Jazyky",
|
||||||
"LabelLastBookAdded": "Posledná pridaná kniha",
|
"LabelLastBookAdded": "Posledná pridaná kniha",
|
||||||
"LabelLastBookUpdated": "Posledná aktualizovaná kniha",
|
"LabelLastBookUpdated": "Posledná aktualizovaná kniha",
|
||||||
|
"LabelLastProgressDate": "Posledný pokrok: {0}",
|
||||||
"LabelLastSeen": "Posledne videné",
|
"LabelLastSeen": "Posledne videné",
|
||||||
"LabelLastTime": "Posledný čas",
|
"LabelLastTime": "Posledný čas",
|
||||||
"LabelLastUpdate": "Posledná aktualizácia",
|
"LabelLastUpdate": "Posledná aktualizácia",
|
||||||
|
|
@ -417,6 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Žiadne {0}",
|
"LabelLibraryFilterSublistEmpty": "Žiadne {0}",
|
||||||
"LabelLibraryItem": "Položka knižnice",
|
"LabelLibraryItem": "Položka knižnice",
|
||||||
"LabelLibraryName": "Názov knižnice",
|
"LabelLibraryName": "Názov knižnice",
|
||||||
|
"LabelLibrarySortByProgress": "Pokrok: Aktualizované",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Pokrok: Dokončené",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Pokrok: Začiatok",
|
||||||
"LabelLimit": "Limit",
|
"LabelLimit": "Limit",
|
||||||
"LabelLineSpacing": "Riadkovanie",
|
"LabelLineSpacing": "Riadkovanie",
|
||||||
"LabelListenAgain": "Počúvať znova",
|
"LabelListenAgain": "Počúvať znova",
|
||||||
|
|
@ -425,6 +447,7 @@
|
||||||
"LabelLogLevelWarn": "Varovanie",
|
"LabelLogLevelWarn": "Varovanie",
|
||||||
"LabelLookForNewEpisodesAfterDate": "Hľadať nové epizódy od uvedeného dátumu",
|
"LabelLookForNewEpisodesAfterDate": "Hľadať nové epizódy od uvedeného dátumu",
|
||||||
"LabelLowestPriority": "Najnižšia priorita",
|
"LabelLowestPriority": "Najnižšia priorita",
|
||||||
|
"LabelMatchConfidence": "Istota",
|
||||||
"LabelMatchExistingUsersBy": "Vyhľadaj vytvorených užívateľov podľa",
|
"LabelMatchExistingUsersBy": "Vyhľadaj vytvorených užívateľov podľa",
|
||||||
"LabelMatchExistingUsersByDescription": "Používané na pripájanie vytvorených užívateľov. Po pripojení budú užívatelia vyhľadaní na základe jedinečného id poskytnutého Vaším poskytovateľom SSO",
|
"LabelMatchExistingUsersByDescription": "Používané na pripájanie vytvorených užívateľov. Po pripojení budú užívatelia vyhľadaní na základe jedinečného id poskytnutého Vaším poskytovateľom SSO",
|
||||||
"LabelMaxEpisodesToDownload": "Stiahnuť maximálne # epizód. Pre neobmedzené sťahovanie zadajte 0.",
|
"LabelMaxEpisodesToDownload": "Stiahnuť maximálne # epizód. Pre neobmedzené sťahovanie zadajte 0.",
|
||||||
|
|
@ -454,7 +477,9 @@
|
||||||
"LabelNewestAuthors": "Najnovší autori",
|
"LabelNewestAuthors": "Najnovší autori",
|
||||||
"LabelNewestEpisodes": "Najnovšie epizódy",
|
"LabelNewestEpisodes": "Najnovšie epizódy",
|
||||||
"LabelNextBackupDate": "Ďalší dátum zálohovania",
|
"LabelNextBackupDate": "Ďalší dátum zálohovania",
|
||||||
|
"LabelNextChapters": "Nasledujúce kapitoly:",
|
||||||
"LabelNextScheduledRun": "Ďalší plánovaný beh",
|
"LabelNextScheduledRun": "Ďalší plánovaný beh",
|
||||||
|
"LabelNoApiKeys": "Žiadne API kľúče",
|
||||||
"LabelNoCustomMetadataProviders": "Žiadne vlastné zdroje metadát",
|
"LabelNoCustomMetadataProviders": "Žiadne vlastné zdroje metadát",
|
||||||
"LabelNoEpisodesSelected": "Neboli vybrané žiadne epizódy",
|
"LabelNoEpisodesSelected": "Neboli vybrané žiadne epizódy",
|
||||||
"LabelNotFinished": "Nedokončené",
|
"LabelNotFinished": "Nedokončené",
|
||||||
|
|
@ -470,6 +495,7 @@
|
||||||
"LabelNotificationsMaxQueueSize": "Maximálna dĺžka fronty oznámení",
|
"LabelNotificationsMaxQueueSize": "Maximálna dĺžka fronty oznámení",
|
||||||
"LabelNotificationsMaxQueueSizeHelp": "Odosielanie udalostí je ohraničené na jedno oznámenie za sekundu. Novovzniknuté udalosti budú ignorované, ak bude fronta oznámení naplnená. Toto nastavenie zabraňuje nevyžiadanému zahlteniu oznámeniami.",
|
"LabelNotificationsMaxQueueSizeHelp": "Odosielanie udalostí je ohraničené na jedno oznámenie za sekundu. Novovzniknuté udalosti budú ignorované, ak bude fronta oznámení naplnená. Toto nastavenie zabraňuje nevyžiadanému zahlteniu oznámeniami.",
|
||||||
"LabelNumberOfBooks": "Počet kníh",
|
"LabelNumberOfBooks": "Počet kníh",
|
||||||
|
"LabelNumberOfChapters": "Počet kapitol:",
|
||||||
"LabelNumberOfEpisodes": "# z epizód",
|
"LabelNumberOfEpisodes": "# z epizód",
|
||||||
"LabelOpenIDAdvancedPermsClaimDescription": "Názov OpenID predpokladá prítomnosť pokročilých povolení pre užívateľské akcie v rámci aplikácie, ktoré sú aplikovateľné na ne-administrátorské role (<b>ak sú nakonfigurované</b>). Ak potvrdenie takýchto pokročilých povolení nie je v odozve prítomné, prístup do ABS bude automaticky zamietnutý. Ak v odozve chýba len niektoré z očakávaných nastavení, tak bude jeho hodnota automaticky nastavená na <code>false</code>. Uistite sa prosím, že forma odozvy poskytovateľa identity má nasledovnú štruktúru:",
|
"LabelOpenIDAdvancedPermsClaimDescription": "Názov OpenID predpokladá prítomnosť pokročilých povolení pre užívateľské akcie v rámci aplikácie, ktoré sú aplikovateľné na ne-administrátorské role (<b>ak sú nakonfigurované</b>). Ak potvrdenie takýchto pokročilých povolení nie je v odozve prítomné, prístup do ABS bude automaticky zamietnutý. Ak v odozve chýba len niektoré z očakávaných nastavení, tak bude jeho hodnota automaticky nastavená na <code>false</code>. Uistite sa prosím, že forma odozvy poskytovateľa identity má nasledovnú štruktúru:",
|
||||||
"LabelOpenIDClaims": "Ak ponecháte nasledujúce nastavenia prázdne, pokročilé nastavenia skupín a povolení nebudú aktivované a automaticky bude nastavená skupina 'Užívateľ'.",
|
"LabelOpenIDClaims": "Ak ponecháte nasledujúce nastavenia prázdne, pokročilé nastavenia skupín a povolení nebudú aktivované a automaticky bude nastavená skupina 'Užívateľ'.",
|
||||||
|
|
@ -544,6 +570,7 @@
|
||||||
"LabelSelectAll": "Vybrať všetko",
|
"LabelSelectAll": "Vybrať všetko",
|
||||||
"LabelSelectAllEpisodes": "Vybrať všetky epizódy",
|
"LabelSelectAllEpisodes": "Vybrať všetky epizódy",
|
||||||
"LabelSelectEpisodesShowing": "Vybrať {0} zobrazených epizód",
|
"LabelSelectEpisodesShowing": "Vybrať {0} zobrazených epizód",
|
||||||
|
"LabelSelectUser": "Vyberte používateľa",
|
||||||
"LabelSelectUsers": "Vybrať užívateľov",
|
"LabelSelectUsers": "Vybrať užívateľov",
|
||||||
"LabelSendEbookToDevice": "Poslať e-knihu do...",
|
"LabelSendEbookToDevice": "Poslať e-knihu do...",
|
||||||
"LabelSequence": "Postupnosť",
|
"LabelSequence": "Postupnosť",
|
||||||
|
|
@ -611,6 +638,7 @@
|
||||||
"LabelStartTime": "Čas spustenia",
|
"LabelStartTime": "Čas spustenia",
|
||||||
"LabelStarted": "Začaté",
|
"LabelStarted": "Začaté",
|
||||||
"LabelStartedAt": "Začaté v",
|
"LabelStartedAt": "Začaté v",
|
||||||
|
"LabelStartedDate": "Začaté {0}",
|
||||||
"LabelStatsAudioTracks": "Zvukové stopy",
|
"LabelStatsAudioTracks": "Zvukové stopy",
|
||||||
"LabelStatsAuthors": "Autori",
|
"LabelStatsAuthors": "Autori",
|
||||||
"LabelStatsBestDay": "Najlepší deň",
|
"LabelStatsBestDay": "Najlepší deň",
|
||||||
|
|
@ -640,6 +668,7 @@
|
||||||
"LabelTheme": "Téma",
|
"LabelTheme": "Téma",
|
||||||
"LabelThemeDark": "Tmavá",
|
"LabelThemeDark": "Tmavá",
|
||||||
"LabelThemeLight": "Svetlá",
|
"LabelThemeLight": "Svetlá",
|
||||||
|
"LabelThemeSepia": "Sépia",
|
||||||
"LabelTimeBase": "Časová základňa",
|
"LabelTimeBase": "Časová základňa",
|
||||||
"LabelTimeDurationXHours": "{0} hodín",
|
"LabelTimeDurationXHours": "{0} hodín",
|
||||||
"LabelTimeDurationXMinutes": "{0} minút",
|
"LabelTimeDurationXMinutes": "{0} minút",
|
||||||
|
|
@ -708,7 +737,9 @@
|
||||||
"MessageAddToPlayerQueue": "Pridať do zoznamu prehrávania",
|
"MessageAddToPlayerQueue": "Pridať do zoznamu prehrávania",
|
||||||
"MessageAppriseDescription": "Aby ste mohli používať túto funkciumusíte mať k dispozícii inštanciu <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> alebo inú, ktorá dokáže spracovávať rovnaké požiadavky/requesty.<br/>Apprise URL musí byť úplná URL určená na zasielanie notifikácií, tj. ak napr. vaša APi beží na <code>http://192.168.1.1:8337</code>, vložte do daného poľa <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "Aby ste mohli používať túto funkciumusíte mať k dispozícii inštanciu <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> alebo inú, ktorá dokáže spracovávať rovnaké požiadavky/requesty.<br/>Apprise URL musí byť úplná URL určená na zasielanie notifikácií, tj. ak napr. vaša APi beží na <code>http://192.168.1.1:8337</code>, vložte do daného poľa <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
"MessageAsinCheck": "Uistite sa, že používate ASIN zo správneho regiónu Audible, nie Amazonu.",
|
"MessageAsinCheck": "Uistite sa, že používate ASIN zo správneho regiónu Audible, nie Amazonu.",
|
||||||
|
"MessageAuthenticationLegacyTokenWarning": "Zastaralé API toleny budú v budúcnosti odstránené. Použite miesto nich <a href=\"/config/api-keys\">API kľúče</a>.",
|
||||||
"MessageAuthenticationOIDCChangesRestart": "Reštartujte svoj server po uložení, aby mohli byť použité zmeny OIDC.",
|
"MessageAuthenticationOIDCChangesRestart": "Reštartujte svoj server po uložení, aby mohli byť použité zmeny OIDC.",
|
||||||
|
"MessageAuthenticationSecurityMessage": "Overovanie bolo kvôli bezpečnosti vylepšené. Všetci používatelia sa musia znova prihlásiť.",
|
||||||
"MessageBackupsDescription": "Zálohy pokrývajú používateľov, ich aktuálne stavy počúvania, detaily položiek knižnice, nastavenia servera a obrázky uložené v <code>/metadata/items</code> a <code>/metadata/authors</code>. Zálohy <strong>neobsahujú</strong> súbory v priečinkoch vašich knižníc.",
|
"MessageBackupsDescription": "Zálohy pokrývajú používateľov, ich aktuálne stavy počúvania, detaily položiek knižnice, nastavenia servera a obrázky uložené v <code>/metadata/items</code> a <code>/metadata/authors</code>. Zálohy <strong>neobsahujú</strong> súbory v priečinkoch vašich knižníc.",
|
||||||
"MessageBackupsLocationEditNote": "Poznámka: Zmena umiestnenia záloh nepresunie ani nezmení existujúce zálohy",
|
"MessageBackupsLocationEditNote": "Poznámka: Zmena umiestnenia záloh nepresunie ani nezmení existujúce zálohy",
|
||||||
"MessageBackupsLocationNoEditNote": "Poznámka: Umietnenie záloh je nastavené prostredníctvom premennej prostredia a nie je ho možné zmeniť z tohto miesta.",
|
"MessageBackupsLocationNoEditNote": "Poznámka: Umietnenie záloh je nastavené prostredníctvom premennej prostredia a nie je ho možné zmeniť z tohto miesta.",
|
||||||
|
|
@ -722,6 +753,7 @@
|
||||||
"MessageBookshelfNoResultsForFilter": "Žiadny výsledok filtrovania \"{0}: {1}\"",
|
"MessageBookshelfNoResultsForFilter": "Žiadny výsledok filtrovania \"{0}: {1}\"",
|
||||||
"MessageBookshelfNoResultsForQuery": "Žiadne výsledky dopytu",
|
"MessageBookshelfNoResultsForQuery": "Žiadne výsledky dopytu",
|
||||||
"MessageBookshelfNoSeries": "Nemáte žiadne série",
|
"MessageBookshelfNoSeries": "Nemáte žiadne série",
|
||||||
|
"MessageBulkChapterPattern": "Koľko ďalších kapitol si želáte pridať s týmto spôsobom číslovania?",
|
||||||
"MessageChapterEndIsAfter": "Koniec kapitoly je až za koncom vašej audioknihy",
|
"MessageChapterEndIsAfter": "Koniec kapitoly je až za koncom vašej audioknihy",
|
||||||
"MessageChapterErrorFirstNotZero": "Prvá kapitola musí začínať na 0",
|
"MessageChapterErrorFirstNotZero": "Prvá kapitola musí začínať na 0",
|
||||||
"MessageChapterErrorStartGteDuration": "Neplatný čas začiatku musí byť menší ako celkové trvanie audioknihy",
|
"MessageChapterErrorStartGteDuration": "Neplatný čas začiatku musí byť menší ako celkové trvanie audioknihy",
|
||||||
|
|
@ -730,6 +762,7 @@
|
||||||
"MessageChaptersNotFound": "Kapitoly nenájdené",
|
"MessageChaptersNotFound": "Kapitoly nenájdené",
|
||||||
"MessageCheckingCron": "Kontrola cron-u...",
|
"MessageCheckingCron": "Kontrola cron-u...",
|
||||||
"MessageConfirmCloseFeed": "Ste si istý, že chcete zavrieť tento zdroj?",
|
"MessageConfirmCloseFeed": "Ste si istý, že chcete zavrieť tento zdroj?",
|
||||||
|
"MessageConfirmDeleteApiKey": "Ste si istý, že chcete zmazať API kľúč \"{0}\"?",
|
||||||
"MessageConfirmDeleteBackup": "Ste si istý, že chcete zmazať zálohu {0}?",
|
"MessageConfirmDeleteBackup": "Ste si istý, že chcete zmazať zálohu {0}?",
|
||||||
"MessageConfirmDeleteDevice": "Ste si istý, že chcete zmazať zariadenie čítačky e-kníh \"{0}\"?",
|
"MessageConfirmDeleteDevice": "Ste si istý, že chcete zmazať zariadenie čítačky e-kníh \"{0}\"?",
|
||||||
"MessageConfirmDeleteFile": "Týmto odstránite súbor z vášho súborového systému. Ste si istý?",
|
"MessageConfirmDeleteFile": "Týmto odstránite súbor z vášho súborového systému. Ste si istý?",
|
||||||
|
|
@ -783,6 +816,8 @@
|
||||||
"MessageFeedURLWillBe": "URL zdroja bude {0}",
|
"MessageFeedURLWillBe": "URL zdroja bude {0}",
|
||||||
"MessageFetching": "Získavam...",
|
"MessageFetching": "Získavam...",
|
||||||
"MessageForceReScanDescription": "preskenuje všetky súbory ako pri prvom skenovaní. ID3 štítky zvukových súborov, OPF súbory a textové súbory budú nanovo naskenované.",
|
"MessageForceReScanDescription": "preskenuje všetky súbory ako pri prvom skenovaní. ID3 štítky zvukových súborov, OPF súbory a textové súbory budú nanovo naskenované.",
|
||||||
|
"MessageHeatmapListeningTimeTooltip": "<strong>{0} počúvajúcich</strong> na {1}",
|
||||||
|
"MessageHeatmapNoListeningSessions": "Žiadne relácie počúvania na {0}",
|
||||||
"MessageImportantNotice": "Dôležité upozornenie!",
|
"MessageImportantNotice": "Dôležité upozornenie!",
|
||||||
"MessageInsertChapterBelow": "Vložte kapitolu nižšie",
|
"MessageInsertChapterBelow": "Vložte kapitolu nižšie",
|
||||||
"MessageInvalidAsin": "Neplatné ASIN",
|
"MessageInvalidAsin": "Neplatné ASIN",
|
||||||
|
|
@ -922,6 +957,7 @@
|
||||||
"NotificationOnRSSFeedDisabledDescription": "Spustí sa, keď je automatické sťahovanie epizód pozastavené z dôvodu veľkého počtu zlyhaní",
|
"NotificationOnRSSFeedDisabledDescription": "Spustí sa, keď je automatické sťahovanie epizód pozastavené z dôvodu veľkého počtu zlyhaní",
|
||||||
"NotificationOnRSSFeedFailedDescription": "Spustí sa v prípade, keď zlyhá požiadavka RSS zdroja na automatické stiahnutie epizódy",
|
"NotificationOnRSSFeedFailedDescription": "Spustí sa v prípade, keď zlyhá požiadavka RSS zdroja na automatické stiahnutie epizódy",
|
||||||
"NotificationOnTestDescription": "Udalosť určená na testovanie systému notifikácií",
|
"NotificationOnTestDescription": "Udalosť určená na testovanie systému notifikácií",
|
||||||
|
"PlaceholderBulkChapterInput": "Zadajte názov kapitoly alebo použite číslovanie (napr., 'Epizóda 1', 'Kapitola 10', '1.')",
|
||||||
"PlaceholderNewCollection": "Názov novej zbierky",
|
"PlaceholderNewCollection": "Názov novej zbierky",
|
||||||
"PlaceholderNewFolderPath": "Umiestnenie nového priečinka",
|
"PlaceholderNewFolderPath": "Umiestnenie nového priečinka",
|
||||||
"PlaceholderNewPlaylist": "Názov nového playlistu",
|
"PlaceholderNewPlaylist": "Názov nového playlistu",
|
||||||
|
|
@ -975,8 +1011,12 @@
|
||||||
"ToastBookmarkCreateFailed": "Vytvorenie záložky zlyhalo",
|
"ToastBookmarkCreateFailed": "Vytvorenie záložky zlyhalo",
|
||||||
"ToastBookmarkCreateSuccess": "Záložka pridaná",
|
"ToastBookmarkCreateSuccess": "Záložka pridaná",
|
||||||
"ToastBookmarkRemoveSuccess": "Záložka odstránená",
|
"ToastBookmarkRemoveSuccess": "Záložka odstránená",
|
||||||
|
"ToastBulkChapterInvalidCount": "Zadajte číslo medzi 1 a 150",
|
||||||
"ToastCachePurgeFailed": "Vyčistenie vyrovnávacej pamäte zlyhalo",
|
"ToastCachePurgeFailed": "Vyčistenie vyrovnávacej pamäte zlyhalo",
|
||||||
"ToastCachePurgeSuccess": "Vyrovnávacia pamäť vyčistená",
|
"ToastCachePurgeSuccess": "Vyrovnávacia pamäť vyčistená",
|
||||||
|
"ToastChapterLocked": "Kapitola je zamknutá.",
|
||||||
|
"ToastChapterStartTimeAdjusted": "Čas začiatku kapitoly upravený o {0} sek.",
|
||||||
|
"ToastChaptersAllLocked": "Všetky kapitoly sú zamknuté. Odomknite niektoré kapitoly, aby ste posunuli ich časy.",
|
||||||
"ToastChaptersHaveErrors": "Kapitoly obsahujú chyby",
|
"ToastChaptersHaveErrors": "Kapitoly obsahujú chyby",
|
||||||
"ToastChaptersInvalidShiftAmountLast": "Neplatná hodnota veľkosti posunutia. Začiatok poslednej kapitoly by ležal za koncom audioknihy.",
|
"ToastChaptersInvalidShiftAmountLast": "Neplatná hodnota veľkosti posunutia. Začiatok poslednej kapitoly by ležal za koncom audioknihy.",
|
||||||
"ToastChaptersInvalidShiftAmountStart": "Nesprávna hodnota posunutia. Prvá kapitola by mala nulovú alebo zápornú dĺžku a bola by nahradená nasledujúcou kapitolou. Navýšte čas začiatku druhej kapitoly.",
|
"ToastChaptersInvalidShiftAmountStart": "Nesprávna hodnota posunutia. Prvá kapitola by mala nulovú alebo zápornú dĺžku a bola by nahradená nasledujúcou kapitolou. Navýšte čas začiatku druhej kapitoly.",
|
||||||
|
|
@ -1001,6 +1041,8 @@
|
||||||
"ToastEpisodeDownloadQueueClearSuccess": "Poradie sťahovania bolo vyčistené",
|
"ToastEpisodeDownloadQueueClearSuccess": "Poradie sťahovania bolo vyčistené",
|
||||||
"ToastEpisodeUpdateSuccess": "{0} epizód bolo aktualizovaných",
|
"ToastEpisodeUpdateSuccess": "{0} epizód bolo aktualizovaných",
|
||||||
"ToastErrorCannotShare": "Na tomto zariadení nie je možné zdielať vybraným spôsobom",
|
"ToastErrorCannotShare": "Na tomto zariadení nie je možné zdielať vybraným spôsobom",
|
||||||
|
"ToastFailedToCreate": "Vytvorenie zlyhalo",
|
||||||
|
"ToastFailedToDelete": "Zmazanie zlyhalo",
|
||||||
"ToastFailedToLoadData": "Načítanie údajov zlyhalo",
|
"ToastFailedToLoadData": "Načítanie údajov zlyhalo",
|
||||||
"ToastFailedToMatch": "Spárovanie zlyhalo",
|
"ToastFailedToMatch": "Spárovanie zlyhalo",
|
||||||
"ToastFailedToShare": "Zdieľanie zlyhalo",
|
"ToastFailedToShare": "Zdieľanie zlyhalo",
|
||||||
|
|
@ -1008,6 +1050,7 @@
|
||||||
"ToastInvalidImageUrl": "Neplatná URL obrázku",
|
"ToastInvalidImageUrl": "Neplatná URL obrázku",
|
||||||
"ToastInvalidMaxEpisodesToDownload": "Neplatný maximálny počet epizód na stiahnutie",
|
"ToastInvalidMaxEpisodesToDownload": "Neplatný maximálny počet epizód na stiahnutie",
|
||||||
"ToastInvalidUrl": "Neplatná URL",
|
"ToastInvalidUrl": "Neplatná URL",
|
||||||
|
"ToastInvalidUrls": "Jedna alebo viac URL liniek sú neplatné",
|
||||||
"ToastItemCoverUpdateSuccess": "Prebal položky bol aktualizovaný",
|
"ToastItemCoverUpdateSuccess": "Prebal položky bol aktualizovaný",
|
||||||
"ToastItemDeletedFailed": "Odstránenie položky zlyhalo",
|
"ToastItemDeletedFailed": "Odstránenie položky zlyhalo",
|
||||||
"ToastItemDeletedSuccess": "Položka bola odstránená",
|
"ToastItemDeletedSuccess": "Položka bola odstránená",
|
||||||
|
|
@ -1032,6 +1075,7 @@
|
||||||
"ToastMustHaveAtLeastOnePath": "Musí mať aspoň jednu cestu umiestnenia",
|
"ToastMustHaveAtLeastOnePath": "Musí mať aspoň jednu cestu umiestnenia",
|
||||||
"ToastNameEmailRequired": "Meno a e-mail sú povinné",
|
"ToastNameEmailRequired": "Meno a e-mail sú povinné",
|
||||||
"ToastNameRequired": "Meno je povinné",
|
"ToastNameRequired": "Meno je povinné",
|
||||||
|
"ToastNewApiKeyUserError": "Musíte vybrať používateľa",
|
||||||
"ToastNewEpisodesFound": "Bolo nájdených {0} nových epizód",
|
"ToastNewEpisodesFound": "Bolo nájdených {0} nových epizód",
|
||||||
"ToastNewUserCreatedFailed": "Vytvorenie účtu zlyhalo: \"{0}\"",
|
"ToastNewUserCreatedFailed": "Vytvorenie účtu zlyhalo: \"{0}\"",
|
||||||
"ToastNewUserCreatedSuccess": "Nový účet bol vytvorený",
|
"ToastNewUserCreatedSuccess": "Nový účet bol vytvorený",
|
||||||
|
|
@ -1056,6 +1100,7 @@
|
||||||
"ToastPlaylistUpdateSuccess": "Playlist bol aktualizovaný",
|
"ToastPlaylistUpdateSuccess": "Playlist bol aktualizovaný",
|
||||||
"ToastPodcastCreateFailed": "Vytvorenie podcastu zlyhalo",
|
"ToastPodcastCreateFailed": "Vytvorenie podcastu zlyhalo",
|
||||||
"ToastPodcastCreateSuccess": "Podcast bol vytvorený",
|
"ToastPodcastCreateSuccess": "Podcast bol vytvorený",
|
||||||
|
"ToastPodcastEpisodeUpdated": "Epizóda bola aktualizovaná",
|
||||||
"ToastPodcastGetFeedFailed": "Získanie zdroja podcastu zlyhalo",
|
"ToastPodcastGetFeedFailed": "Získanie zdroja podcastu zlyhalo",
|
||||||
"ToastPodcastNoEpisodesInFeed": "Na RSS zdroji neboli nájdené žiadne epizódy",
|
"ToastPodcastNoEpisodesInFeed": "Na RSS zdroji neboli nájdené žiadne epizódy",
|
||||||
"ToastPodcastNoRssFeed": "Podcast nemá RSS zdroj",
|
"ToastPodcastNoRssFeed": "Podcast nemá RSS zdroj",
|
||||||
|
|
@ -1106,5 +1151,13 @@
|
||||||
"ToastUserPasswordChangeSuccess": "Zmena hesla prebehla úspešne",
|
"ToastUserPasswordChangeSuccess": "Zmena hesla prebehla úspešne",
|
||||||
"ToastUserPasswordMismatch": "Heslá sa nezhodujú",
|
"ToastUserPasswordMismatch": "Heslá sa nezhodujú",
|
||||||
"ToastUserPasswordMustChange": "Nové heslo sa nesmie zhodovať so starým",
|
"ToastUserPasswordMustChange": "Nové heslo sa nesmie zhodovať so starým",
|
||||||
"ToastUserRootRequireName": "Musíte zadať používateľské meno root používateľa"
|
"ToastUserRootRequireName": "Musíte zadať používateľské meno root používateľa",
|
||||||
|
"TooltipAddChapters": "Pridať kapitolu(-y)",
|
||||||
|
"TooltipAddOneSecond": "Pridať 1 sekundu",
|
||||||
|
"TooltipAdjustChapterStart": "Kliknite, ak chcete zmeniť začiatočný čas",
|
||||||
|
"TooltipLockAllChapters": "Zamknúť všetky kapitoly",
|
||||||
|
"TooltipLockChapter": "Zamknúť kapitolu (Shift+klik pre skupinu)",
|
||||||
|
"TooltipSubtractOneSecond": "Odobrať 1 sekundu",
|
||||||
|
"TooltipUnlockAllChapters": "Odomknúť všetky kapitoly",
|
||||||
|
"TooltipUnlockChapter": "Odomknúť kapitolu (Shift+klik pre skupinu)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,7 @@
|
||||||
"LabelFilterByUser": "Filtriraj po uporabniku",
|
"LabelFilterByUser": "Filtriraj po uporabniku",
|
||||||
"LabelFindEpisodes": "Poišči epizode",
|
"LabelFindEpisodes": "Poišči epizode",
|
||||||
"LabelFinished": "Zaključeno",
|
"LabelFinished": "Zaključeno",
|
||||||
|
"LabelFinishedDate": "Končano {0}",
|
||||||
"LabelFolder": "Mapa",
|
"LabelFolder": "Mapa",
|
||||||
"LabelFolders": "Mape",
|
"LabelFolders": "Mape",
|
||||||
"LabelFontBold": "Krepko",
|
"LabelFontBold": "Krepko",
|
||||||
|
|
@ -435,7 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Ne {0}",
|
"LabelLibraryFilterSublistEmpty": "Ne {0}",
|
||||||
"LabelLibraryItem": "Element knjižnice",
|
"LabelLibraryItem": "Element knjižnice",
|
||||||
"LabelLibraryName": "Ime knjižnice",
|
"LabelLibraryName": "Ime knjižnice",
|
||||||
"LabelLibrarySortByProgress": "Napredek posodobljen",
|
"LabelLibrarySortByProgress": "Napredek: Nazadnje posodobljen",
|
||||||
|
"LabelLibrarySortByProgressFinished": "Napredej: Končano",
|
||||||
|
"LabelLibrarySortByProgressStarted": "Napredek: Začeto",
|
||||||
"LabelLimit": "Omejitev",
|
"LabelLimit": "Omejitev",
|
||||||
"LabelLineSpacing": "Vrstični razmak",
|
"LabelLineSpacing": "Vrstični razmak",
|
||||||
"LabelListenAgain": "Poslušaj znova",
|
"LabelListenAgain": "Poslušaj znova",
|
||||||
|
|
@ -635,6 +638,7 @@
|
||||||
"LabelStartTime": "Čas začetka",
|
"LabelStartTime": "Čas začetka",
|
||||||
"LabelStarted": "Začeto",
|
"LabelStarted": "Začeto",
|
||||||
"LabelStartedAt": "Začeto ob",
|
"LabelStartedAt": "Začeto ob",
|
||||||
|
"LabelStartedDate": "Začeto {0}",
|
||||||
"LabelStatsAudioTracks": "Zvočni posnetki",
|
"LabelStatsAudioTracks": "Zvočni posnetki",
|
||||||
"LabelStatsAuthors": "Avtorji",
|
"LabelStatsAuthors": "Avtorji",
|
||||||
"LabelStatsBestDay": "Najboljši dan",
|
"LabelStatsBestDay": "Najboljši dan",
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@
|
||||||
"ButtonStartM4BEncode": "Starta M4B-omkodning",
|
"ButtonStartM4BEncode": "Starta M4B-omkodning",
|
||||||
"ButtonStartMetadataEmbed": "Infoga metadata",
|
"ButtonStartMetadataEmbed": "Infoga metadata",
|
||||||
"ButtonStats": "Statistik",
|
"ButtonStats": "Statistik",
|
||||||
"ButtonSubmit": "Skicka",
|
"ButtonSubmit": "Spara",
|
||||||
"ButtonTest": "Testa",
|
"ButtonTest": "Testa",
|
||||||
"ButtonUnlinkOpenId": "Koppla ifrån OpenID",
|
"ButtonUnlinkOpenId": "Koppla ifrån OpenID",
|
||||||
"ButtonUpload": "Ladda upp",
|
"ButtonUpload": "Ladda upp",
|
||||||
|
|
@ -301,7 +301,7 @@
|
||||||
"LabelCoverProvider": "Källa för omslag",
|
"LabelCoverProvider": "Källa för omslag",
|
||||||
"LabelCreatedAt": "Skapad",
|
"LabelCreatedAt": "Skapad",
|
||||||
"LabelCronExpression": "Schemaläggning med hjälp av Cron (Cron Expression)",
|
"LabelCronExpression": "Schemaläggning med hjälp av Cron (Cron Expression)",
|
||||||
"LabelCurrent": "Nuvarande omslag",
|
"LabelCurrent": "Nuvarande",
|
||||||
"LabelCurrently": "För närvarande:",
|
"LabelCurrently": "För närvarande:",
|
||||||
"LabelCustomCronExpression": "Anpassat Cron-uttryck:",
|
"LabelCustomCronExpression": "Anpassat Cron-uttryck:",
|
||||||
"LabelDatetime": "Datum och klockslag",
|
"LabelDatetime": "Datum och klockslag",
|
||||||
|
|
@ -462,7 +462,7 @@
|
||||||
"LabelMetadataProvider": "Källa för metadata",
|
"LabelMetadataProvider": "Källa för metadata",
|
||||||
"LabelMinute": "Minut",
|
"LabelMinute": "Minut",
|
||||||
"LabelMinutes": "Minuter",
|
"LabelMinutes": "Minuter",
|
||||||
"LabelMissing": "Saknas",
|
"LabelMissing": "Saknar",
|
||||||
"LabelMissingEbook": "Saknar e-bok",
|
"LabelMissingEbook": "Saknar e-bok",
|
||||||
"LabelMissingSupplementaryEbook": "Saknar kompletterande e-bok",
|
"LabelMissingSupplementaryEbook": "Saknar kompletterande e-bok",
|
||||||
"LabelMobileRedirectURIs": "Tillåtna mobila omdirigerings-URI:er",
|
"LabelMobileRedirectURIs": "Tillåtna mobila omdirigerings-URI:er",
|
||||||
|
|
@ -472,7 +472,7 @@
|
||||||
"LabelName": "Namn",
|
"LabelName": "Namn",
|
||||||
"LabelNarrator": "Uppläsare",
|
"LabelNarrator": "Uppläsare",
|
||||||
"LabelNarrators": "Uppläsare",
|
"LabelNarrators": "Uppläsare",
|
||||||
"LabelNew": "Nytt omslag",
|
"LabelNew": "Nytt",
|
||||||
"LabelNewPassword": "Nytt lösenord",
|
"LabelNewPassword": "Nytt lösenord",
|
||||||
"LabelNewestAuthors": "Senaste författarna",
|
"LabelNewestAuthors": "Senaste författarna",
|
||||||
"LabelNewestEpisodes": "Senaste avsnitten",
|
"LabelNewestEpisodes": "Senaste avsnitten",
|
||||||
|
|
@ -826,7 +826,7 @@
|
||||||
"MessageMarkAllEpisodesNotFinished": "Markera alla avsnitt som ej avslutade",
|
"MessageMarkAllEpisodesNotFinished": "Markera alla avsnitt som ej avslutade",
|
||||||
"MessageMarkAsFinished": "Markera som avslutad",
|
"MessageMarkAsFinished": "Markera som avslutad",
|
||||||
"MessageMarkAsNotFinished": "Markera som ej avslutad",
|
"MessageMarkAsNotFinished": "Markera som ej avslutad",
|
||||||
"MessageMatchBooksDescription": "kommer att försöka matcha böcker i biblioteket med en bok från den valda källan och fylla i uppgifter som saknas och omslag som saknas. Inga befintliga uppgifter kommer att ersättas.",
|
"MessageMatchBooksDescription": "kommer att försöka matcha böcker i biblioteket med en bok från den valda källan och fylla i de uppgifter som saknas och addera omslag som saknas. Inga befintliga uppgifter kommer att ersättas.",
|
||||||
"MessageNoAudioTracks": "Inga ljudfiler har hittats",
|
"MessageNoAudioTracks": "Inga ljudfiler har hittats",
|
||||||
"MessageNoAuthors": "Inga författare",
|
"MessageNoAuthors": "Inga författare",
|
||||||
"MessageNoBackups": "Inga säkerhetskopior",
|
"MessageNoBackups": "Inga säkerhetskopior",
|
||||||
|
|
@ -921,7 +921,7 @@
|
||||||
"MessageTaskTargetDirectoryNotWritable": "Det är inte tillåtet att skriva i den angivna katalogen",
|
"MessageTaskTargetDirectoryNotWritable": "Det är inte tillåtet att skriva i den angivna katalogen",
|
||||||
"MessageThinking": "Tänker...",
|
"MessageThinking": "Tänker...",
|
||||||
"MessageUploaderItemFailed": "Misslyckades med att ladda upp",
|
"MessageUploaderItemFailed": "Misslyckades med att ladda upp",
|
||||||
"MessageUploaderItemSuccess": "har blivit uppladdat!",
|
"MessageUploaderItemSuccess": "har blivit uppladdad!",
|
||||||
"MessageUploading": "Laddar upp...",
|
"MessageUploading": "Laddar upp...",
|
||||||
"MessageValidCronExpression": "Giltigt cron-uttryck",
|
"MessageValidCronExpression": "Giltigt cron-uttryck",
|
||||||
"MessageWatcherIsDisabledGlobally": "Automatisk bevakning av förändringar är inaktiverad under rubriken 'Inställningar'",
|
"MessageWatcherIsDisabledGlobally": "Automatisk bevakning av förändringar är inaktiverad under rubriken 'Inställningar'",
|
||||||
|
|
@ -1008,6 +1008,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "Misslyckades med att addera böcker till samlingen",
|
"ToastCollectionItemsAddFailed": "Misslyckades med att addera böcker till samlingen",
|
||||||
"ToastCollectionRemoveSuccess": "Samlingen har raderats",
|
"ToastCollectionRemoveSuccess": "Samlingen har raderats",
|
||||||
"ToastCollectionUpdateSuccess": "Samlingen har uppdaterats",
|
"ToastCollectionUpdateSuccess": "Samlingen har uppdaterats",
|
||||||
|
"ToastConnectionNotAvailable": "Uppkopplingen är inte tillgänglig. Var vänlig försök senare.",
|
||||||
|
"ToastCoverSearchFailed": "Sökningen efter omslag misslyckades",
|
||||||
"ToastCoverUpdateFailed": "Uppdatering av omslag misslyckades",
|
"ToastCoverUpdateFailed": "Uppdatering av omslag misslyckades",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "Datum och klockslag är felaktigt eller ej komplett",
|
"ToastDateTimeInvalidOrIncomplete": "Datum och klockslag är felaktigt eller ej komplett",
|
||||||
"ToastDeleteFileFailed": "Misslyckades att radera filen",
|
"ToastDeleteFileFailed": "Misslyckades att radera filen",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -436,9 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "Ні {0}",
|
"LabelLibraryFilterSublistEmpty": "Ні {0}",
|
||||||
"LabelLibraryItem": "Елемент бібліотеки",
|
"LabelLibraryItem": "Елемент бібліотеки",
|
||||||
"LabelLibraryName": "Назва бібліотеки",
|
"LabelLibraryName": "Назва бібліотеки",
|
||||||
"LabelLibrarySortByProgress": "Прогрес оновлено",
|
"LabelLibrarySortByProgress": "Прогрес: Останнє оновлення",
|
||||||
"LabelLibrarySortByProgressFinished": "Дата завершення",
|
"LabelLibrarySortByProgressFinished": "Прогрес: Завершено",
|
||||||
"LabelLibrarySortByProgressStarted": "Дата початку",
|
"LabelLibrarySortByProgressStarted": "Прогрес: Розпочато",
|
||||||
"LabelLimit": "Обмеження",
|
"LabelLimit": "Обмеження",
|
||||||
"LabelLineSpacing": "Відстань між рядками",
|
"LabelLineSpacing": "Відстань між рядками",
|
||||||
"LabelListenAgain": "Слухати знову",
|
"LabelListenAgain": "Слухати знову",
|
||||||
|
|
@ -1026,6 +1026,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "Не вдалося додати елемент(и) до колекції",
|
"ToastCollectionItemsAddFailed": "Не вдалося додати елемент(и) до колекції",
|
||||||
"ToastCollectionRemoveSuccess": "Добірку видалено",
|
"ToastCollectionRemoveSuccess": "Добірку видалено",
|
||||||
"ToastCollectionUpdateSuccess": "Добірку оновлено",
|
"ToastCollectionUpdateSuccess": "Добірку оновлено",
|
||||||
|
"ToastConnectionNotAvailable": "З’єднання недоступне. Спробуйте пізніше",
|
||||||
|
"ToastCoverSearchFailed": "Пошук обкладинки не вдався",
|
||||||
"ToastCoverUpdateFailed": "Не вдалося оновити обкладинку",
|
"ToastCoverUpdateFailed": "Не вдалося оновити обкладинку",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "Дата й час недійсні або неповні",
|
"ToastDateTimeInvalidOrIncomplete": "Дата й час недійсні або неповні",
|
||||||
"ToastDeleteFileFailed": "Не вдалося видалити файл",
|
"ToastDeleteFileFailed": "Не вдалося видалити файл",
|
||||||
|
|
|
||||||
|
|
@ -436,9 +436,9 @@
|
||||||
"LabelLibraryFilterSublistEmpty": "没有 {0}",
|
"LabelLibraryFilterSublistEmpty": "没有 {0}",
|
||||||
"LabelLibraryItem": "媒体库项目",
|
"LabelLibraryItem": "媒体库项目",
|
||||||
"LabelLibraryName": "媒体库名称",
|
"LabelLibraryName": "媒体库名称",
|
||||||
"LabelLibrarySortByProgress": "进度更新时间",
|
"LabelLibrarySortByProgress": "收听进度: 上次收听时间",
|
||||||
"LabelLibrarySortByProgressFinished": "完成日期",
|
"LabelLibrarySortByProgressFinished": "收听进度: 已完成的",
|
||||||
"LabelLibrarySortByProgressStarted": "开始日期",
|
"LabelLibrarySortByProgressStarted": "收听进度: 已开始的",
|
||||||
"LabelLimit": "限制",
|
"LabelLimit": "限制",
|
||||||
"LabelLineSpacing": "行间距",
|
"LabelLineSpacing": "行间距",
|
||||||
"LabelListenAgain": "再次收听",
|
"LabelListenAgain": "再次收听",
|
||||||
|
|
@ -1026,6 +1026,8 @@
|
||||||
"ToastCollectionItemsAddFailed": "项目添加到收藏夹失败",
|
"ToastCollectionItemsAddFailed": "项目添加到收藏夹失败",
|
||||||
"ToastCollectionRemoveSuccess": "收藏夹已删除",
|
"ToastCollectionRemoveSuccess": "收藏夹已删除",
|
||||||
"ToastCollectionUpdateSuccess": "收藏夹已更新",
|
"ToastCollectionUpdateSuccess": "收藏夹已更新",
|
||||||
|
"ToastConnectionNotAvailable": "连接不可用. 请稍后重试",
|
||||||
|
"ToastCoverSearchFailed": "封面搜索失败",
|
||||||
"ToastCoverUpdateFailed": "封面更新失败",
|
"ToastCoverUpdateFailed": "封面更新失败",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "日期和时间无效或不完整",
|
"ToastDateTimeInvalidOrIncomplete": "日期和时间无效或不完整",
|
||||||
"ToastDeleteFileFailed": "删除文件失败",
|
"ToastDeleteFileFailed": "删除文件失败",
|
||||||
|
|
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "audiobookshelf",
|
"name": "audiobookshelf",
|
||||||
"version": "2.29.0",
|
"version": "2.30.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "audiobookshelf",
|
"name": "audiobookshelf",
|
||||||
"version": "2.29.0",
|
"version": "2.30.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "audiobookshelf",
|
"name": "audiobookshelf",
|
||||||
"version": "2.29.0",
|
"version": "2.30.0",
|
||||||
"buildNumber": 1,
|
"buildNumber": 1,
|
||||||
"description": "Self-hosted audiobook and podcast server",
|
"description": "Self-hosted audiobook and podcast server",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
"client": "cd client && npm ci && npm run generate",
|
"client": "cd client && npm ci && npm run generate",
|
||||||
"prod": "npm run client && npm ci && node index.js",
|
"prod": "npm run client && npm ci && node index.js",
|
||||||
"build-win": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip .",
|
"build-win": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf -C GZip .",
|
||||||
|
"build-win-no-compress": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf .",
|
||||||
"build-linux": "build/linuxpackager",
|
"build-linux": "build/linuxpackager",
|
||||||
"docker": "docker buildx build --platform linux/amd64,linux/arm64 --push . -t advplyr/audiobookshelf",
|
"docker": "docker buildx build --platform linux/amd64,linux/arm64 --push . -t advplyr/audiobookshelf",
|
||||||
"docker-amd64-local": "docker buildx build --platform linux/amd64 --load . -t advplyr/audiobookshelf-amd64-local",
|
"docker-amd64-local": "docker buildx build --platform linux/amd64 --load . -t advplyr/audiobookshelf-amd64-local",
|
||||||
|
|
|
||||||
|
|
@ -407,8 +407,7 @@ class Server {
|
||||||
const nextApp = next({ dev: Logger.isDev, dir: ReactClientPath })
|
const nextApp = next({ dev: Logger.isDev, dir: ReactClientPath })
|
||||||
const handle = nextApp.getRequestHandler()
|
const handle = nextApp.getRequestHandler()
|
||||||
await nextApp.prepare()
|
await nextApp.prepare()
|
||||||
router.get('*', (req, res) => handle(req, res))
|
router.all('*', (req, res) => handle(req, res))
|
||||||
router.post('/internal-api/*', (req, res) => handle(req, res))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unixSocketPrefix = 'unix/'
|
const unixSocketPrefix = 'unix/'
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ const SocketIO = require('socket.io')
|
||||||
const Logger = require('./Logger')
|
const Logger = require('./Logger')
|
||||||
const Database = require('./Database')
|
const Database = require('./Database')
|
||||||
const TokenManager = require('./auth/TokenManager')
|
const TokenManager = require('./auth/TokenManager')
|
||||||
|
const CoverSearchManager = require('./managers/CoverSearchManager')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef SocketClient
|
* @typedef SocketClient
|
||||||
|
|
@ -180,6 +181,10 @@ class SocketAuthority {
|
||||||
// Scanning
|
// Scanning
|
||||||
socket.on('cancel_scan', (libraryId) => this.cancelScan(libraryId))
|
socket.on('cancel_scan', (libraryId) => this.cancelScan(libraryId))
|
||||||
|
|
||||||
|
// Cover search streaming
|
||||||
|
socket.on('search_covers', (payload) => this.handleCoverSearch(socket, payload))
|
||||||
|
socket.on('cancel_cover_search', (requestId) => this.handleCancelCoverSearch(socket, requestId))
|
||||||
|
|
||||||
// Logs
|
// Logs
|
||||||
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
||||||
socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id))
|
socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id))
|
||||||
|
|
@ -200,6 +205,10 @@ class SocketAuthority {
|
||||||
|
|
||||||
const disconnectTime = Date.now() - _client.connected_at
|
const disconnectTime = Date.now() - _client.connected_at
|
||||||
Logger.info(`[SocketAuthority] Socket ${socket.id} disconnected from client "${_client.user.username}" after ${disconnectTime}ms (Reason: ${reason})`)
|
Logger.info(`[SocketAuthority] Socket ${socket.id} disconnected from client "${_client.user.username}" after ${disconnectTime}ms (Reason: ${reason})`)
|
||||||
|
|
||||||
|
// Cancel any active cover searches for this socket
|
||||||
|
this.cancelSocketCoverSearches(socket.id)
|
||||||
|
|
||||||
delete this.clients[socket.id]
|
delete this.clients[socket.id]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -300,5 +309,100 @@ class SocketAuthority {
|
||||||
Logger.debug('[SocketAuthority] Cancel scan', id)
|
Logger.debug('[SocketAuthority] Cancel scan', id)
|
||||||
this.Server.cancelLibraryScan(id)
|
this.Server.cancelLibraryScan(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle cover search request via WebSocket
|
||||||
|
* @param {SocketIO.Socket} socket
|
||||||
|
* @param {Object} payload
|
||||||
|
*/
|
||||||
|
async handleCoverSearch(socket, payload) {
|
||||||
|
const client = this.clients[socket.id]
|
||||||
|
if (!client?.user) {
|
||||||
|
Logger.error('[SocketAuthority] Unauthorized cover search request')
|
||||||
|
socket.emit('cover_search_error', {
|
||||||
|
requestId: payload.requestId,
|
||||||
|
error: 'Unauthorized'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { requestId, title, author, provider, podcast } = payload
|
||||||
|
|
||||||
|
if (!requestId || !title) {
|
||||||
|
Logger.error('[SocketAuthority] Invalid cover search request')
|
||||||
|
socket.emit('cover_search_error', {
|
||||||
|
requestId,
|
||||||
|
error: 'Invalid request parameters'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.info(`[SocketAuthority] User ${client.user.username} initiated cover search ${requestId}`)
|
||||||
|
|
||||||
|
// Callback for streaming results to client
|
||||||
|
const onResult = (result) => {
|
||||||
|
socket.emit('cover_search_result', {
|
||||||
|
requestId,
|
||||||
|
provider: result.provider,
|
||||||
|
covers: result.covers,
|
||||||
|
total: result.total
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback when search completes
|
||||||
|
const onComplete = () => {
|
||||||
|
Logger.info(`[SocketAuthority] Cover search ${requestId} completed`)
|
||||||
|
socket.emit('cover_search_complete', { requestId })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for provider errors
|
||||||
|
const onError = (provider, errorMessage) => {
|
||||||
|
socket.emit('cover_search_provider_error', {
|
||||||
|
requestId,
|
||||||
|
provider,
|
||||||
|
error: errorMessage
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the search
|
||||||
|
CoverSearchManager.startSearch(requestId, { title, author, provider, podcast }, onResult, onComplete, onError).catch((error) => {
|
||||||
|
Logger.error(`[SocketAuthority] Cover search ${requestId} failed:`, error)
|
||||||
|
socket.emit('cover_search_error', {
|
||||||
|
requestId,
|
||||||
|
error: error.message
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle cancel cover search request
|
||||||
|
* @param {SocketIO.Socket} socket
|
||||||
|
* @param {string} requestId
|
||||||
|
*/
|
||||||
|
handleCancelCoverSearch(socket, requestId) {
|
||||||
|
const client = this.clients[socket.id]
|
||||||
|
if (!client?.user) {
|
||||||
|
Logger.error('[SocketAuthority] Unauthorized cancel cover search request')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.info(`[SocketAuthority] User ${client.user.username} cancelled cover search ${requestId}`)
|
||||||
|
|
||||||
|
const cancelled = CoverSearchManager.cancelSearch(requestId)
|
||||||
|
if (cancelled) {
|
||||||
|
socket.emit('cover_search_cancelled', { requestId })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel all cover searches associated with a socket (called on disconnect)
|
||||||
|
* @param {string} socketId
|
||||||
|
*/
|
||||||
|
cancelSocketCoverSearches(socketId) {
|
||||||
|
// Get all active search request IDs and cancel those that might belong to this socket
|
||||||
|
// Since we don't track socket-to-request mapping, we log this for debugging
|
||||||
|
// The client will handle reconnection gracefully
|
||||||
|
Logger.debug(`[SocketAuthority] Socket ${socketId} disconnected, any active searches will timeout`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
module.exports = new SocketAuthority()
|
module.exports = new SocketAuthority()
|
||||||
|
|
|
||||||
|
|
@ -527,7 +527,16 @@ class OidcAuthStrategy {
|
||||||
|
|
||||||
// For absolute URLs, ensure they point to the same origin
|
// For absolute URLs, ensure they point to the same origin
|
||||||
const callbackUrlObj = new URL(callbackUrl)
|
const callbackUrlObj = new URL(callbackUrl)
|
||||||
const currentProtocol = req.secure || req.get('x-forwarded-proto') === 'https' ? 'https' : 'http'
|
// NPM appends both http and https in x-forwarded-proto sometimes, so we need to check for both
|
||||||
|
const xfp = (req.get('x-forwarded-proto') || '').toLowerCase()
|
||||||
|
const currentProtocol =
|
||||||
|
req.secure ||
|
||||||
|
xfp
|
||||||
|
.split(',')
|
||||||
|
.map((s) => s.trim())
|
||||||
|
.includes('https')
|
||||||
|
? 'https'
|
||||||
|
: 'http'
|
||||||
const currentHost = req.get('host')
|
const currentHost = req.get('host')
|
||||||
|
|
||||||
// Check if protocol and host match exactly
|
// Check if protocol and host match exactly
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ const { levenshteinDistance, levenshteinSimilarity, escapeRegExp, isValidASIN }
|
||||||
const htmlSanitizer = require('../utils/htmlSanitizer')
|
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||||
|
|
||||||
class BookFinder {
|
class BookFinder {
|
||||||
#providerResponseTimeout = 30000
|
#providerResponseTimeout = 10000
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.openLibrary = new OpenLibrary()
|
this.openLibrary = new OpenLibrary()
|
||||||
|
|
@ -608,6 +608,14 @@ class BookFinder {
|
||||||
Logger.debug(`[BookFinder] Found ${providerResults.length} covers from ${providerString}`)
|
Logger.debug(`[BookFinder] Found ${providerResults.length} covers from ${providerString}`)
|
||||||
searchResults.push(...providerResults)
|
searchResults.push(...providerResults)
|
||||||
}
|
}
|
||||||
|
} else if (provider === 'best') {
|
||||||
|
// Best providers: google, fantlab, and audible.com
|
||||||
|
const bestProviders = ['google', 'fantlab', 'audible']
|
||||||
|
for (const providerString of bestProviders) {
|
||||||
|
const providerResults = await this.search(null, providerString, title, author, options)
|
||||||
|
Logger.debug(`[BookFinder] Found ${providerResults.length} covers from ${providerString}`)
|
||||||
|
searchResults.push(...providerResults)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
searchResults = await this.search(null, provider, title, author, options)
|
searchResults = await this.search(null, provider, title, author, options)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
251
server/managers/CoverSearchManager.js
Normal file
251
server/managers/CoverSearchManager.js
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
const { setMaxListeners } = require('events')
|
||||||
|
const Logger = require('../Logger')
|
||||||
|
const BookFinder = require('../finders/BookFinder')
|
||||||
|
const PodcastFinder = require('../finders/PodcastFinder')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager for handling streaming cover search across multiple providers
|
||||||
|
*/
|
||||||
|
class CoverSearchManager {
|
||||||
|
constructor() {
|
||||||
|
/** @type {Map<string, AbortController>} Map of requestId to AbortController */
|
||||||
|
this.activeSearches = new Map()
|
||||||
|
|
||||||
|
// Default timeout for each provider search
|
||||||
|
this.providerTimeout = 10000 // 10 seconds
|
||||||
|
|
||||||
|
// Set to 0 to disable the max listeners limit
|
||||||
|
// We need one listener per provider (15+) and may have multiple concurrent searches
|
||||||
|
this.maxListeners = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a streaming cover search
|
||||||
|
* @param {string} requestId - Unique identifier for this search request
|
||||||
|
* @param {Object} searchParams - Search parameters
|
||||||
|
* @param {string} searchParams.title - Title to search for
|
||||||
|
* @param {string} searchParams.author - Author to search for (optional)
|
||||||
|
* @param {string} searchParams.provider - Provider to search (or 'all')
|
||||||
|
* @param {boolean} searchParams.podcast - Whether this is a podcast search
|
||||||
|
* @param {Function} onResult - Callback for each result chunk
|
||||||
|
* @param {Function} onComplete - Callback when search completes
|
||||||
|
* @param {Function} onError - Callback for errors
|
||||||
|
*/
|
||||||
|
async startSearch(requestId, searchParams, onResult, onComplete, onError) {
|
||||||
|
if (this.activeSearches.has(requestId)) {
|
||||||
|
Logger.warn(`[CoverSearchManager] Search with requestId ${requestId} already exists`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const abortController = new AbortController()
|
||||||
|
|
||||||
|
// Increase max listeners on this signal to accommodate parallel provider searches
|
||||||
|
// AbortSignal is an EventTarget, so we use the events module's setMaxListeners
|
||||||
|
setMaxListeners(this.maxListeners, abortController.signal)
|
||||||
|
|
||||||
|
this.activeSearches.set(requestId, abortController)
|
||||||
|
|
||||||
|
Logger.info(`[CoverSearchManager] Starting search ${requestId} with params:`, searchParams)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { title, author, provider, podcast } = searchParams
|
||||||
|
|
||||||
|
if (podcast) {
|
||||||
|
await this.searchPodcastCovers(requestId, title, abortController.signal, onResult, onError)
|
||||||
|
} else {
|
||||||
|
await this.searchBookCovers(requestId, provider, title, author, abortController.signal, onResult, onError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!abortController.signal.aborted) {
|
||||||
|
onComplete()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name === 'AbortError') {
|
||||||
|
Logger.info(`[CoverSearchManager] Search ${requestId} was cancelled`)
|
||||||
|
} else {
|
||||||
|
Logger.error(`[CoverSearchManager] Search ${requestId} failed:`, error)
|
||||||
|
onError(error.message)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.activeSearches.delete(requestId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel an active search
|
||||||
|
* @param {string} requestId - Request ID to cancel
|
||||||
|
*/
|
||||||
|
cancelSearch(requestId) {
|
||||||
|
const abortController = this.activeSearches.get(requestId)
|
||||||
|
if (abortController) {
|
||||||
|
Logger.info(`[CoverSearchManager] Cancelling search ${requestId}`)
|
||||||
|
abortController.abort()
|
||||||
|
this.activeSearches.delete(requestId)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for podcast covers
|
||||||
|
*/
|
||||||
|
async searchPodcastCovers(requestId, title, signal, onResult, onError) {
|
||||||
|
try {
|
||||||
|
const results = await this.executeWithTimeout(() => PodcastFinder.findCovers(title), this.providerTimeout, signal)
|
||||||
|
|
||||||
|
if (signal.aborted) return
|
||||||
|
|
||||||
|
const covers = this.extractCoversFromResults(results)
|
||||||
|
if (covers.length > 0) {
|
||||||
|
onResult({
|
||||||
|
provider: 'itunes',
|
||||||
|
covers,
|
||||||
|
total: covers.length
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name !== 'AbortError') {
|
||||||
|
Logger.error(`[CoverSearchManager] Podcast search failed:`, error)
|
||||||
|
onError('itunes', error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for book covers across providers
|
||||||
|
*/
|
||||||
|
async searchBookCovers(requestId, provider, title, author, signal, onResult, onError) {
|
||||||
|
let providers = []
|
||||||
|
|
||||||
|
if (provider === 'all') {
|
||||||
|
providers = [...BookFinder.providers]
|
||||||
|
} else if (provider === 'best') {
|
||||||
|
// Best providers: google, fantlab, and audible.com
|
||||||
|
providers = ['google', 'fantlab', 'audible']
|
||||||
|
} else {
|
||||||
|
providers = [provider]
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug(`[CoverSearchManager] Searching ${providers.length} providers in parallel`)
|
||||||
|
|
||||||
|
// Search all providers in parallel
|
||||||
|
const searchPromises = providers.map(async (providerName) => {
|
||||||
|
if (signal.aborted) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const searchResults = await this.executeWithTimeout(() => BookFinder.search(null, providerName, title, author || ''), this.providerTimeout, signal)
|
||||||
|
|
||||||
|
if (signal.aborted) return
|
||||||
|
|
||||||
|
const covers = this.extractCoversFromResults(searchResults)
|
||||||
|
|
||||||
|
Logger.debug(`[CoverSearchManager] Found ${covers.length} covers from ${providerName}`)
|
||||||
|
|
||||||
|
if (covers.length > 0) {
|
||||||
|
onResult({
|
||||||
|
provider: providerName,
|
||||||
|
covers,
|
||||||
|
total: covers.length
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.name !== 'AbortError') {
|
||||||
|
Logger.warn(`[CoverSearchManager] Provider ${providerName} failed:`, error.message)
|
||||||
|
onError(providerName, error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.allSettled(searchPromises)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a promise with timeout and abort signal
|
||||||
|
*/
|
||||||
|
async executeWithTimeout(fn, timeout, signal) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
let abortHandler = null
|
||||||
|
let timeoutId = null
|
||||||
|
|
||||||
|
// Cleanup function to ensure we always remove listeners
|
||||||
|
const cleanup = () => {
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
timeoutId = null
|
||||||
|
}
|
||||||
|
if (abortHandler) {
|
||||||
|
signal.removeEventListener('abort', abortHandler)
|
||||||
|
abortHandler = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up timeout
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
cleanup()
|
||||||
|
const error = new Error('Provider timeout')
|
||||||
|
error.name = 'TimeoutError'
|
||||||
|
reject(error)
|
||||||
|
}, timeout)
|
||||||
|
|
||||||
|
// Check if already aborted
|
||||||
|
if (signal.aborted) {
|
||||||
|
cleanup()
|
||||||
|
const error = new Error('Search cancelled')
|
||||||
|
error.name = 'AbortError'
|
||||||
|
reject(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up abort handler
|
||||||
|
abortHandler = () => {
|
||||||
|
cleanup()
|
||||||
|
const error = new Error('Search cancelled')
|
||||||
|
error.name = 'AbortError'
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
signal.addEventListener('abort', abortHandler)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await fn()
|
||||||
|
cleanup()
|
||||||
|
resolve(result)
|
||||||
|
} catch (error) {
|
||||||
|
cleanup()
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract cover URLs from search results
|
||||||
|
*/
|
||||||
|
extractCoversFromResults(results) {
|
||||||
|
const covers = []
|
||||||
|
if (!Array.isArray(results)) return covers
|
||||||
|
|
||||||
|
results.forEach((result) => {
|
||||||
|
if (result.covers && Array.isArray(result.covers)) {
|
||||||
|
covers.push(...result.covers)
|
||||||
|
}
|
||||||
|
if (result.cover) {
|
||||||
|
covers.push(result.cover)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove duplicates
|
||||||
|
return [...new Set(covers)]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel all active searches (cleanup on server shutdown)
|
||||||
|
*/
|
||||||
|
cancelAllSearches() {
|
||||||
|
Logger.info(`[CoverSearchManager] Cancelling ${this.activeSearches.size} active searches`)
|
||||||
|
for (const [requestId, abortController] of this.activeSearches.entries()) {
|
||||||
|
abortController.abort()
|
||||||
|
}
|
||||||
|
this.activeSearches.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new CoverSearchManager()
|
||||||
|
|
@ -127,10 +127,20 @@ class PodcastManager {
|
||||||
})
|
})
|
||||||
let success = !!ffmpegDownloadResponse?.success
|
let success = !!ffmpegDownloadResponse?.success
|
||||||
|
|
||||||
// If failed due to ffmpeg error, retry without tagging
|
if (success) {
|
||||||
|
// Attempt to ffprobe and add podcast episode audio file
|
||||||
|
success = await this.scanAddPodcastEpisodeAudioFile()
|
||||||
|
if (!success) {
|
||||||
|
Logger.error(`[PodcastManager] Failed to scan and add podcast episode audio file - removing file`)
|
||||||
|
await fs.remove(this.currentDownload.targetPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If failed due to ffmpeg or ffprobe error, retry without tagging
|
||||||
// e.g. RSS feed may have incorrect file extension and file type
|
// e.g. RSS feed may have incorrect file extension and file type
|
||||||
// See https://github.com/advplyr/audiobookshelf/issues/3837
|
// See https://github.com/advplyr/audiobookshelf/issues/3837
|
||||||
if (!success && ffmpegDownloadResponse?.isFfmpegError) {
|
// e.g. Ffmpeg may be download the file without streams causing the ffprobe to fail
|
||||||
|
if (!success && !ffmpegDownloadResponse?.isRequestError) {
|
||||||
Logger.info(`[PodcastManager] Retrying episode download without tagging`)
|
Logger.info(`[PodcastManager] Retrying episode download without tagging`)
|
||||||
// Download episode only
|
// Download episode only
|
||||||
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
|
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
|
||||||
|
|
@ -139,23 +149,20 @@ class PodcastManager {
|
||||||
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
success = await this.scanAddPodcastEpisodeAudioFile()
|
||||||
|
if (!success) {
|
||||||
|
Logger.error(`[PodcastManager] Failed to scan and add podcast episode audio file - removing file`)
|
||||||
|
await fs.remove(this.currentDownload.targetPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
success = await this.scanAddPodcastEpisodeAudioFile()
|
Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.episodeTitle}"`)
|
||||||
if (!success) {
|
this.currentDownload.setFinished(true)
|
||||||
await fs.remove(this.currentDownload.targetPath)
|
task.setFinished()
|
||||||
this.currentDownload.setFinished(false)
|
|
||||||
const taskFailedString = {
|
|
||||||
text: 'Failed',
|
|
||||||
key: 'MessageTaskFailed'
|
|
||||||
}
|
|
||||||
task.setFailed(taskFailedString)
|
|
||||||
} else {
|
|
||||||
Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.episodeTitle}"`)
|
|
||||||
this.currentDownload.setFinished(true)
|
|
||||||
task.setFinished()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const taskFailedString = {
|
const taskFailedString = {
|
||||||
text: 'Failed',
|
text: 'Failed',
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ const Logger = require('../Logger')
|
||||||
const { isValidASIN } = require('../utils/index')
|
const { isValidASIN } = require('../utils/index')
|
||||||
|
|
||||||
class Audible {
|
class Audible {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.regionMap = {
|
this.regionMap = {
|
||||||
|
|
@ -106,7 +106,7 @@ class Audible {
|
||||||
return res.data
|
return res.data
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error('[Audible] ASIN search error', error)
|
Logger.error('[Audible] ASIN search error', error.message)
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +158,7 @@ class Audible {
|
||||||
return Promise.all(res.data.products.map((result) => this.asinSearch(result.asin, region, timeout)))
|
return Promise.all(res.data.products.map((result) => this.asinSearch(result.asin, region, timeout)))
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error('[Audible] query search error', error)
|
Logger.error('[Audible] query search error', error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ const axios = require('axios')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
|
|
||||||
class AudiobookCovers {
|
class AudiobookCovers {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ class AudiobookCovers {
|
||||||
})
|
})
|
||||||
.then((res) => res?.data || [])
|
.then((res) => res?.data || [])
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error('[AudiobookCovers] Cover search error', error)
|
Logger.error('[AudiobookCovers] Cover search error', error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
return items.map((item) => ({ cover: item.versions.png.original }))
|
return items.map((item) => ({ cover: item.versions.png.original }))
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class Audnexus {
|
||||||
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl)))
|
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl)))
|
||||||
.then((res) => res.data || [])
|
.then((res) => res.data || [])
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error(`[Audnexus] Author ASIN request failed for ${name}`, error)
|
Logger.error(`[Audnexus] Author ASIN request failed for ${name}`, error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ class Audnexus {
|
||||||
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl.toString())))
|
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl.toString())))
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error(`[Audnexus] Author request failed for ${asin}`, error)
|
Logger.error(`[Audnexus] Author request failed for ${asin}`, error.message)
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +158,7 @@ class Audnexus {
|
||||||
return this._processRequest(this.limiter(() => axios.get(chaptersRequestUrl.toString())))
|
return this._processRequest(this.limiter(() => axios.get(chaptersRequestUrl.toString())))
|
||||||
.then((res) => res.data)
|
.then((res) => res.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error(`[Audnexus] Chapter ASIN request failed for ${asin}/${region}`, error)
|
Logger.error(`[Audnexus] Chapter ASIN request failed for ${asin}/${region}`, error.message)
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const Logger = require('../Logger')
|
||||||
const htmlSanitizer = require('../utils/htmlSanitizer')
|
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||||
|
|
||||||
class CustomProviderAdapter {
|
class CustomProviderAdapter {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ class CustomProviderAdapter {
|
||||||
return res.data.matches
|
return res.data.matches
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error('[CustomMetadataProvider] Search error', error)
|
Logger.error('[CustomMetadataProvider] Search error', error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ const axios = require('axios')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
|
|
||||||
class FantLab {
|
class FantLab {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
// 7 - other
|
// 7 - other
|
||||||
// 11 - essay
|
// 11 - essay
|
||||||
// 12 - article
|
// 12 - article
|
||||||
|
|
@ -48,7 +48,7 @@ class FantLab {
|
||||||
return res.data || []
|
return res.data || []
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error('[FantLab] search error', error)
|
Logger.error('[FantLab] search error', error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ class FantLab {
|
||||||
return resp.data || null
|
return resp.data || null
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error(`[FantLab] work info request for url "${url}" error`, error)
|
Logger.error(`[FantLab] work info request for url "${url}" error`, error.message)
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ class FantLab {
|
||||||
return resp.data || null
|
return resp.data || null
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error(`[FantLab] search cover from edition with url "${url}" error`, error)
|
Logger.error(`[FantLab] search cover from edition with url "${url}" error`, error.message)
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ const axios = require('axios')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
|
|
||||||
class GoogleBooks {
|
class GoogleBooks {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ class GoogleBooks {
|
||||||
return res.data.items
|
return res.data.items
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error('[GoogleBooks] Volume search error', error)
|
Logger.error('[GoogleBooks] Volume search error', error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
return items.map((item) => this.cleanResult(item))
|
return items.map((item) => this.cleanResult(item))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const axios = require('axios').default
|
const axios = require('axios').default
|
||||||
|
|
||||||
class OpenLibrary {
|
class OpenLibrary {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.baseUrl = 'https://openlibrary.org'
|
this.baseUrl = 'https://openlibrary.org'
|
||||||
|
|
@ -23,7 +23,7 @@ class OpenLibrary {
|
||||||
return res.data
|
return res.data
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Failed', error)
|
console.error('Failed', error.message)
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class iTunes {
|
class iTunes {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 10000
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ class iTunes {
|
||||||
return response.data.results || []
|
return response.data.results || []
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
Logger.error(`[iTunes] search request error`, error)
|
Logger.error(`[iTunes] search request error`, error.message)
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ module.exports.resizeImage = resizeImage
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload
|
* @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload
|
||||||
* @returns {Promise<{success: boolean, isFfmpegError?: boolean}>}
|
* @returns {Promise<{success: boolean, isRequestError?: boolean}>}
|
||||||
*/
|
*/
|
||||||
module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
|
|
@ -118,7 +118,7 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
responseType: 'stream',
|
responseType: 'stream',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': '*/*',
|
Accept: '*/*',
|
||||||
'User-Agent': userAgent
|
'User-Agent': userAgent
|
||||||
},
|
},
|
||||||
timeout: global.PodcastDownloadTimeout
|
timeout: global.PodcastDownloadTimeout
|
||||||
|
|
@ -139,7 +139,8 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
return resolve({
|
return resolve({
|
||||||
success: false
|
success: false,
|
||||||
|
isRequestError: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,8 +205,7 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
||||||
Logger.error(`Full stderr dump for episode url "${podcastEpisodeDownload.url}": ${stderrLines.join('\n')}`)
|
Logger.error(`Full stderr dump for episode url "${podcastEpisodeDownload.url}": ${stderrLines.join('\n')}`)
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
success: false,
|
success: false
|
||||||
isFfmpegError: true
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
ffmpeg.on('progress', (progress) => {
|
ffmpeg.on('progress', (progress) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue