mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-12-19 18:29:37 +00:00
Merge branch 'master' into inode-bug-fix
This commit is contained in:
commit
d6fed92b11
87 changed files with 4539 additions and 751 deletions
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
|
|
@ -47,7 +47,7 @@ jobs:
|
|||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
|
|
@ -60,7 +60,7 @@ jobs:
|
|||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
|
@ -73,6 +73,6 @@ jobs:
|
|||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: '/language:${{matrix.language}}'
|
||||
|
|
|
|||
|
|
@ -93,10 +93,10 @@ export default {
|
|||
editAuthor(author) {
|
||||
this.$store.commit('globals/showEditAuthorModal', author)
|
||||
},
|
||||
editItem(libraryItem) {
|
||||
editItem(libraryItem, tab = 'details') {
|
||||
var itemIds = this.shelf.entities.map((e) => e.id)
|
||||
this.$store.commit('setBookshelfBookIds', itemIds)
|
||||
this.$store.commit('showEditModal', libraryItem)
|
||||
this.$store.commit('showEditModalOnTab', { libraryItem, tab: tab || 'details' })
|
||||
},
|
||||
editEpisode({ libraryItem, episode }) {
|
||||
this.$store.commit('setEpisodeTableEpisodeIds', [episode.id])
|
||||
|
|
|
|||
|
|
@ -232,11 +232,11 @@ export default {
|
|||
clearFilter() {
|
||||
this.$store.dispatch('user/updateUserSettings', { filterBy: 'all' })
|
||||
},
|
||||
editEntity(entity) {
|
||||
editEntity(entity, tab = 'details') {
|
||||
if (this.entityName === 'items' || this.entityName === 'series-books') {
|
||||
const bookIds = this.entities.map((e) => e.id)
|
||||
this.$store.commit('setBookshelfBookIds', bookIds)
|
||||
this.$store.commit('showEditModal', entity)
|
||||
this.$store.commit('showEditModalOnTab', { libraryItem: entity, tab: tab || 'details' })
|
||||
} else if (this.entityName === 'collections') {
|
||||
this.$store.commit('globals/setEditCollection', entity)
|
||||
} else if (this.entityName === 'playlists') {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,24 @@
|
|||
</widgets-alert>
|
||||
|
||||
<div v-if="isNonInteractable" class="absolute top-0 left-0 w-full h-full bg-black/50 flex items-center justify-center z-20">
|
||||
<ui-loading-indicator :text="nonInteractionLabel" />
|
||||
<ui-loading-indicator>
|
||||
<div class="mb-4">
|
||||
<span class="text-lg font-medium text-white">
|
||||
{{ nonInteractionLabel }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-if="isUploading" class="w-64 mx-auto mb-2">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<span class="text-sm font-medium text-white/60 text-center w-full">
|
||||
{{ uploadProgressText }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="w-full bg-primary/20 rounded-full h-2.5">
|
||||
<div class="bg-green-500 h-2.5 rounded-full transition-all duration-300 ease-out" :style="{ width: uploadProgressPercent + '%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</ui-loading-indicator>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -91,7 +108,11 @@ export default {
|
|||
isUploading: false,
|
||||
uploadFailed: false,
|
||||
uploadSuccess: false,
|
||||
isFetchingMetadata: false
|
||||
isFetchingMetadata: false,
|
||||
uploadProgress: {
|
||||
loaded: 0,
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -116,6 +137,15 @@ export default {
|
|||
} else if (this.isFetchingMetadata) {
|
||||
return this.$strings.LabelFetchingMetadata
|
||||
}
|
||||
},
|
||||
uploadProgressPercent() {
|
||||
if (this.uploadProgress.total === 0) return 0
|
||||
return Math.min(100, Math.round((this.uploadProgress.loaded / this.uploadProgress.total) * 100))
|
||||
},
|
||||
uploadProgressText() {
|
||||
const loaded = this.$bytesPretty(this.uploadProgress.loaded)
|
||||
const total = this.$bytesPretty(this.uploadProgress.total)
|
||||
return `${this.uploadProgressPercent}% (${loaded} / ${total})`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -123,6 +153,21 @@ export default {
|
|||
this.isUploading = status === 'uploading'
|
||||
this.uploadFailed = status === 'failed'
|
||||
this.uploadSuccess = status === 'success'
|
||||
|
||||
if (status !== 'uploading') {
|
||||
this.uploadProgress = {
|
||||
loaded: 0,
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
setUploadProgress(progress) {
|
||||
if (this.isUploading && progress) {
|
||||
this.uploadProgress = {
|
||||
loaded: progress.loaded || 0,
|
||||
total: progress.total || 0
|
||||
}
|
||||
}
|
||||
},
|
||||
titleUpdated() {
|
||||
this.error = ''
|
||||
|
|
|
|||
|
|
@ -788,11 +788,11 @@ export default {
|
|||
},
|
||||
showEditModalFiles() {
|
||||
// More menu func
|
||||
this.store.commit('showEditModalOnTab', { libraryItem: this.libraryItem, tab: 'files' })
|
||||
this.$emit('edit', this.libraryItem, 'files')
|
||||
},
|
||||
showEditModalMatch() {
|
||||
// More menu func
|
||||
this.store.commit('showEditModalOnTab', { libraryItem: this.libraryItem, tab: 'match' })
|
||||
this.$emit('edit', this.libraryItem, 'match')
|
||||
},
|
||||
sendToDevice(deviceName) {
|
||||
// More menu func
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ export default {
|
|||
},
|
||||
providers() {
|
||||
if (this.isPodcast) return this.$store.state.scanners.podcastProviders
|
||||
return this.$store.state.scanners.providers
|
||||
return this.$store.state.scanners.bookProviders
|
||||
},
|
||||
libraryProvider() {
|
||||
return this.$store.getters['libraries/getLibraryProvider'](this.currentLibraryId) || 'google'
|
||||
|
|
@ -96,6 +96,9 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
init() {
|
||||
// Fetch providers when modal is shown
|
||||
this.$store.dispatch('scanners/fetchProviders')
|
||||
|
||||
// If we don't have a set provider (first open of dialog) or we've switched library, set
|
||||
// the selected provider to the current library default provider
|
||||
if (!this.options.provider || this.lastUsedLibrary != this.currentLibraryId) {
|
||||
|
|
@ -127,8 +130,7 @@ export default {
|
|||
this.show = false
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,19 +51,21 @@
|
|||
<form @submit.prevent="submitSearchForm">
|
||||
<div class="flex flex-wrap sm:flex-nowrap items-center justify-start -mx-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 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 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>
|
||||
<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>
|
||||
</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">
|
||||
<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">
|
||||
<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" />
|
||||
|
|
@ -105,7 +107,10 @@ export default {
|
|||
showLocalCovers: false,
|
||||
previewUpload: null,
|
||||
selectedFile: null,
|
||||
provider: 'google'
|
||||
provider: 'google',
|
||||
currentSearchRequestId: null,
|
||||
searchInProgress: false,
|
||||
socketListenersActive: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -128,8 +133,8 @@ export default {
|
|||
}
|
||||
},
|
||||
providers() {
|
||||
if (this.isPodcast) return this.$store.state.scanners.podcastProviders
|
||||
return [{ text: 'All', value: 'all' }, ...this.$store.state.scanners.providers, ...this.$store.state.scanners.coverOnlyProviders]
|
||||
if (this.isPodcast) return this.$store.state.scanners.podcastCoverProviders
|
||||
return this.$store.state.scanners.bookCoverProviders
|
||||
},
|
||||
searchTitleLabel() {
|
||||
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}`
|
||||
return _file
|
||||
})
|
||||
},
|
||||
socket() {
|
||||
return this.$root.socket
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -235,7 +243,19 @@ export default {
|
|||
this.searchTitle = this.mediaMetadata.title || ''
|
||||
this.searchAuthor = this.mediaMetadata.authorName || ''
|
||||
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() {
|
||||
if (!this.coverPath) {
|
||||
|
|
@ -291,22 +311,116 @@ export default {
|
|||
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() {
|
||||
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
|
||||
this.persistProvider()
|
||||
|
||||
this.isProcessing = true
|
||||
const searchQuery = this.getSearchQuery()
|
||||
const results = await this.$axios
|
||||
.$get(`/api/search/covers?${searchQuery}`)
|
||||
.then((res) => res.results)
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
return []
|
||||
})
|
||||
this.coversFound = results
|
||||
this.isProcessing = false
|
||||
// Setup socket listeners if not already done
|
||||
this.addSocketListeners()
|
||||
|
||||
// Clear previous results
|
||||
this.coversFound = []
|
||||
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) {
|
||||
this.isProcessing = true
|
||||
|
|
@ -320,6 +434,20 @@ export default {
|
|||
this.isProcessing = false
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// Setup socket listeners when component is mounted
|
||||
this.addSocketListeners()
|
||||
// Fetch providers if not already loaded
|
||||
this.$store.dispatch('scanners/fetchProviders')
|
||||
},
|
||||
beforeDestroy() {
|
||||
// Cancel any ongoing search when component is destroyed
|
||||
if (this.searchInProgress) {
|
||||
this.cancelCurrentSearch()
|
||||
}
|
||||
// Remove socket listeners
|
||||
this.removeSocketListeners()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div id="match-wrapper" class="w-full h-full overflow-hidden px-2 md:px-4 py-4 md:py-6 relative">
|
||||
<form @submit.prevent="submitSearch">
|
||||
<div class="flex flex-wrap md:flex-nowrap items-center justify-start -mx-1">
|
||||
<div class="w-36 px-1">
|
||||
<div v-if="providersLoaded" class="w-36 px-1">
|
||||
<ui-dropdown v-model="provider" :items="providers" :label="$strings.LabelProvider" small />
|
||||
</div>
|
||||
<div class="grow md:w-72 px-1">
|
||||
|
|
@ -253,6 +253,7 @@ export default {
|
|||
hasSearched: false,
|
||||
selectedMatch: null,
|
||||
selectedMatchOrig: null,
|
||||
waitingForProviders: false,
|
||||
selectedMatchUsage: {
|
||||
title: true,
|
||||
subtitle: true,
|
||||
|
|
@ -285,9 +286,19 @@ export default {
|
|||
handler(newVal) {
|
||||
if (newVal) this.init()
|
||||
}
|
||||
},
|
||||
providersLoaded(isLoaded) {
|
||||
// Complete initialization once providers are loaded
|
||||
if (isLoaded && this.waitingForProviders) {
|
||||
this.waitingForProviders = false
|
||||
this.initProviderAndSearch()
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
providersLoaded() {
|
||||
return this.$store.getters['scanners/areProvidersLoaded']
|
||||
},
|
||||
isProcessing: {
|
||||
get() {
|
||||
return this.processing
|
||||
|
|
@ -319,7 +330,7 @@ export default {
|
|||
},
|
||||
providers() {
|
||||
if (this.isPodcast) return this.$store.state.scanners.podcastProviders
|
||||
return this.$store.state.scanners.providers
|
||||
return this.$store.state.scanners.bookProviders
|
||||
},
|
||||
searchTitleLabel() {
|
||||
if (this.provider.startsWith('audible')) return this.$strings.LabelSearchTitleOrASIN
|
||||
|
|
@ -478,6 +489,24 @@ export default {
|
|||
|
||||
this.checkboxToggled()
|
||||
},
|
||||
initProviderAndSearch() {
|
||||
// Set provider based on media type
|
||||
if (this.isPodcast) {
|
||||
this.provider = 'itunes'
|
||||
} else {
|
||||
this.provider = this.getDefaultBookProvider()
|
||||
}
|
||||
|
||||
// Prefer using ASIN if set and using audible provider
|
||||
if (this.provider.startsWith('audible') && this.libraryItem.media.metadata.asin) {
|
||||
this.searchTitle = this.libraryItem.media.metadata.asin
|
||||
this.searchAuthor = ''
|
||||
}
|
||||
|
||||
if (this.searchTitle) {
|
||||
this.submitSearch()
|
||||
}
|
||||
},
|
||||
init() {
|
||||
this.clearSelectedMatch()
|
||||
this.initSelectedMatchUsage()
|
||||
|
|
@ -495,19 +524,13 @@ export default {
|
|||
}
|
||||
this.searchTitle = this.libraryItem.media.metadata.title
|
||||
this.searchAuthor = this.libraryItem.media.metadata.authorName || ''
|
||||
if (this.isPodcast) this.provider = 'itunes'
|
||||
else {
|
||||
this.provider = this.getDefaultBookProvider()
|
||||
}
|
||||
|
||||
// Prefer using ASIN if set and using audible provider
|
||||
if (this.provider.startsWith('audible') && this.libraryItem.media.metadata.asin) {
|
||||
this.searchTitle = this.libraryItem.media.metadata.asin
|
||||
this.searchAuthor = ''
|
||||
}
|
||||
|
||||
if (this.searchTitle) {
|
||||
this.submitSearch()
|
||||
// Wait for providers to be loaded before setting provider and searching
|
||||
if (this.providersLoaded || this.isPodcast) {
|
||||
this.waitingForProviders = false
|
||||
this.initProviderAndSearch()
|
||||
} else {
|
||||
this.waitingForProviders = true
|
||||
}
|
||||
},
|
||||
selectMatch(match) {
|
||||
|
|
@ -637,6 +660,10 @@ export default {
|
|||
this.selectedMatch = null
|
||||
this.selectedMatchOrig = null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// Fetch providers if not already loaded
|
||||
this.$store.dispatch('scanners/fetchProviders')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export default {
|
|||
},
|
||||
providers() {
|
||||
if (this.mediaType === 'podcast') return this.$store.state.scanners.podcastProviders
|
||||
return this.$store.state.scanners.providers
|
||||
return this.$store.state.scanners.bookProviders
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -156,6 +156,8 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
// Fetch providers if not already loaded
|
||||
this.$store.dispatch('scanners/fetchProviders')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
provider: null,
|
||||
useSquareBookCovers: false,
|
||||
enableWatcher: false,
|
||||
skipMatchingMediaWithAsin: false,
|
||||
|
|
@ -134,10 +133,6 @@ export default {
|
|||
isPodcastLibrary() {
|
||||
return this.mediaType === 'podcast'
|
||||
},
|
||||
providers() {
|
||||
if (this.mediaType === 'podcast') return this.$store.state.scanners.podcastProviders
|
||||
return this.$store.state.scanners.providers
|
||||
},
|
||||
maskAsFinishedWhenItems() {
|
||||
return [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -186,10 +186,16 @@ export default {
|
|||
daysInARow() {
|
||||
var count = 0
|
||||
while (true) {
|
||||
var _date = this.$addDaysToToday(count * -1)
|
||||
var datestr = this.$formatJsDate(_date, 'yyyy-MM-dd')
|
||||
const _date = this.$addDaysToToday(count * -1 - 1)
|
||||
const datestr = this.$formatJsDate(_date, 'yyyy-MM-dd')
|
||||
|
||||
if (!this.listeningStatsDays[datestr] || this.listeningStatsDays[datestr] === 0) {
|
||||
// don't require listening today to count towards days in a row, but do count it if already listened today
|
||||
const today = this.$formatJsDate(new Date(), 'yyyy-MM-dd')
|
||||
if (this.listeningStatsDays[today]) {
|
||||
count++
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
count++
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="w-40">
|
||||
<div :class="hasSlotContent ? 'w-auto' : 'w-40'">
|
||||
<div class="bg-bg border border-gray-500 py-2 px-5 rounded-lg flex items-center flex-col box-shadow-md">
|
||||
<div class="loader-dots block relative w-20 h-5 mt-2">
|
||||
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
||||
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<div class="text-gray-200 text-xs font-light mt-2 text-center">{{ message }}</div>
|
||||
<slot>
|
||||
<div class="text-gray-200 text-xs font-light mt-2 text-center">{{ message }}</div>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -23,6 +25,9 @@ export default {
|
|||
computed: {
|
||||
message() {
|
||||
return this.text || this.$strings.MessagePleaseWait
|
||||
},
|
||||
hasSlotContent() {
|
||||
return this.$slots.default && this.$slots.default.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
<div ref="wrapper" class="relative">
|
||||
<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 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 }">
|
||||
<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>
|
||||
{{ item }}
|
||||
</div>
|
||||
|
|
@ -259,8 +260,9 @@ export default {
|
|||
}
|
||||
this.focus()
|
||||
},
|
||||
removeItem(item) {
|
||||
var remaining = this.selected.filter((i) => i !== item)
|
||||
removeItem(item, idx) {
|
||||
var remaining = this.selected.slice()
|
||||
remaining.splice(idx, 1)
|
||||
this.$emit('input', remaining)
|
||||
this.$emit('removedItem', item)
|
||||
this.$nextTick(() => {
|
||||
|
|
|
|||
|
|
@ -132,10 +132,10 @@ export default {
|
|||
editAuthor(author) {
|
||||
this.$store.commit('globals/showEditAuthorModal', author)
|
||||
},
|
||||
editItem(libraryItem) {
|
||||
editItem(libraryItem, tab = 'details') {
|
||||
var itemIds = this.items.map((e) => e.id)
|
||||
this.$store.commit('setBookshelfBookIds', itemIds)
|
||||
this.$store.commit('showEditModal', libraryItem)
|
||||
this.$store.commit('showEditModalOnTab', { libraryItem, tab: tab || 'details' })
|
||||
},
|
||||
selectItem(payload) {
|
||||
this.$emit('selectEntity', payload)
|
||||
|
|
|
|||
|
|
@ -371,11 +371,13 @@ export default {
|
|||
},
|
||||
customMetadataProviderAdded(provider) {
|
||||
if (!provider?.id) return
|
||||
this.$store.commit('scanners/addCustomMetadataProvider', provider)
|
||||
// Refresh providers cache
|
||||
this.$store.dispatch('scanners/refreshProviders')
|
||||
},
|
||||
customMetadataProviderRemoved(provider) {
|
||||
if (!provider?.id) return
|
||||
this.$store.commit('scanners/removeCustomMetadataProvider', provider)
|
||||
// Refresh providers cache
|
||||
this.$store.dispatch('scanners/refreshProviders')
|
||||
},
|
||||
initializeSocket() {
|
||||
if (this.$root.socket) {
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@ export default {
|
|||
propsData: props,
|
||||
parent: this,
|
||||
created() {
|
||||
this.$on('edit', (entity) => {
|
||||
if (_this.editEntity) _this.editEntity(entity)
|
||||
this.$on('edit', (entity, tab) => {
|
||||
if (_this.editEntity) _this.editEntity(entity, tab)
|
||||
})
|
||||
this.$on('select', ({ entity, shiftKey }) => {
|
||||
if (_this.selectEntity) _this.selectEntity(entity, shiftKey)
|
||||
|
|
|
|||
4
client/package-lock.json
generated
4
client/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.29.0",
|
||||
"version": "2.31.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.29.0",
|
||||
"version": "2.31.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nuxtjs/axios": "^5.13.6",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.29.0",
|
||||
"version": "2.31.0",
|
||||
"buildNumber": 1,
|
||||
"description": "Self-hosted audiobook and podcast client",
|
||||
"main": "index.js",
|
||||
|
|
|
|||
|
|
@ -12,24 +12,24 @@
|
|||
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
||||
</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="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>
|
||||
<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" />
|
||||
<div class="w-32 hidden lg:block" />
|
||||
<div class="w-32 hidden min-[1120px]:block" />
|
||||
</div>
|
||||
<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="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>
|
||||
<div class="grow" />
|
||||
<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>
|
||||
<div class="w-32 hidden lg:block" />
|
||||
<div class="w-32 hidden min-[1120px]:block" />
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden">
|
||||
|
|
@ -117,10 +117,10 @@
|
|||
</button>
|
||||
</ui-tooltip>
|
||||
<ui-tooltip :text="selectedChapterId === chapter.id && isPlayingChapter ? $strings.MessagePauseChapter : $strings.MessagePlayChapter" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150" @click="playChapter(chapter)">
|
||||
<button :disabled="!getAudioTrackForTime(chapter.start)" class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150 disabled:opacity-50 disabled:cursor-not-allowed" @click="playChapter(chapter)">
|
||||
<widgets-loading-spinner v-if="selectedChapterId === chapter.id && isLoadingChapter" />
|
||||
<span v-else-if="selectedChapterId === chapter.id && isPlayingChapter" class="material-symbols text-base">pause</span>
|
||||
<span v-else class="material-symbols text-base">play_arrow</span>
|
||||
<span v-else class="material-symbols text-xl">play_arrow</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
<ui-tooltip v-if="selectedChapterId === chapter.id && (isPlayingChapter || isLoadingChapter)" :text="$strings.TooltipAdjustChapterStart" direction="bottom">
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
</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">
|
||||
<p class="text-lg font-semibold">{{ $strings.HeaderAudioTracks }}</p>
|
||||
<div class="grow" />
|
||||
|
|
@ -160,13 +160,13 @@
|
|||
</ui-tooltip>
|
||||
</div>
|
||||
<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 hidden md:block text-center">{{ $strings.HeaderChapters }}</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 class="grow max-w-[calc(100%-80px)] pr-2">
|
||||
<p class="text-xs truncate max-w-sm">{{ track.metadata.filename }}</p>
|
||||
<div class="pr-2 grow min-[1120px]:max-w-64 xl:max-w-sm">
|
||||
<p class="text-xs truncate">{{ track.metadata.filename }}</p>
|
||||
</div>
|
||||
<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>
|
||||
|
|
@ -594,6 +594,14 @@ export default {
|
|||
|
||||
this.hasChanges = hasChanges
|
||||
},
|
||||
getAudioTrackForTime(time) {
|
||||
if (typeof time !== 'number') {
|
||||
return null
|
||||
}
|
||||
return this.tracks.find((at) => {
|
||||
return time >= at.startOffset && time < at.startOffset + at.duration
|
||||
})
|
||||
},
|
||||
playChapter(chapter) {
|
||||
console.log('Play Chapter', chapter.id)
|
||||
if (this.selectedChapterId === chapter.id) {
|
||||
|
|
@ -608,9 +616,12 @@ export default {
|
|||
this.destroyAudioEl()
|
||||
}
|
||||
|
||||
const audioTrack = this.tracks.find((at) => {
|
||||
return chapter.start >= at.startOffset && chapter.start < at.startOffset + at.duration
|
||||
})
|
||||
const audioTrack = this.getAudioTrackForTime(chapter.start)
|
||||
if (!audioTrack) {
|
||||
console.error('No audio track found for chapter', chapter)
|
||||
return
|
||||
}
|
||||
|
||||
this.selectedChapter = chapter
|
||||
this.isLoadingChapter = true
|
||||
|
||||
|
|
@ -697,11 +708,7 @@ export default {
|
|||
this.saving = false
|
||||
if (data.updated) {
|
||||
this.$toast.success(this.$strings.ToastChaptersUpdated)
|
||||
if (this.previousRoute) {
|
||||
this.$router.push(this.previousRoute)
|
||||
} else {
|
||||
this.$router.push(`/item/${this.libraryItem.id}`)
|
||||
}
|
||||
this.reloadLibraryItem()
|
||||
} else {
|
||||
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
||||
}
|
||||
|
|
@ -874,11 +881,7 @@ export default {
|
|||
.then((data) => {
|
||||
if (data.updated) {
|
||||
this.$toast.success(this.$strings.ToastChaptersRemoved)
|
||||
if (this.previousRoute) {
|
||||
this.$router.push(this.previousRoute)
|
||||
} else {
|
||||
this.$router.push(`/item/${this.libraryItem.id}`)
|
||||
}
|
||||
this.reloadLibraryItem()
|
||||
} else {
|
||||
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
||||
}
|
||||
|
|
@ -983,6 +986,18 @@ export default {
|
|||
}
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -247,7 +247,8 @@ export default {
|
|||
return this.$store.state.serverSettings
|
||||
},
|
||||
providers() {
|
||||
return this.$store.state.scanners.providers
|
||||
// Use book cover providers for the cover provider dropdown
|
||||
return this.$store.state.scanners.bookCoverProviders || []
|
||||
},
|
||||
dateFormats() {
|
||||
return this.$store.state.globals.dateFormats
|
||||
|
|
@ -416,6 +417,8 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.initServerSettings()
|
||||
// Fetch providers if not already loaded (for cover provider dropdown)
|
||||
this.$store.dispatch('scanners/fetchProviders')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ export default {
|
|||
require('@/plugins/chromecast.js').default(this)
|
||||
}
|
||||
|
||||
this.$store.commit('libraries/setLastLoad', 0) // Ensure libraries get loaded again when switching users
|
||||
this.$store.commit('libraries/setCurrentLibrary', { id: userDefaultLibraryId })
|
||||
this.$store.commit('user/setUser', user)
|
||||
// Access token only returned from login, not authorize
|
||||
|
|
@ -298,8 +299,8 @@ export default {
|
|||
}
|
||||
|
||||
if (authMethods.includes('openid')) {
|
||||
// Auto redirect unless query string ?autoLaunch=0
|
||||
if (this.authFormData?.authOpenIDAutoLaunch && this.$route.query?.autoLaunch !== '0') {
|
||||
// Auto redirect unless query string ?autoLaunch=0 OR when explicity requested through ?autoLaunch=1
|
||||
if ((this.authFormData?.authOpenIDAutoLaunch && this.$route.query?.autoLaunch !== '0') || this.$route.query?.autoLaunch == '1') {
|
||||
window.location.href = this.openidAuthUri
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ export default {
|
|||
},
|
||||
providers() {
|
||||
if (this.selectedLibraryIsPodcast) return this.$store.state.scanners.podcastProviders
|
||||
return this.$store.state.scanners.providers
|
||||
return this.$store.state.scanners.bookProviders
|
||||
},
|
||||
canFetchMetadata() {
|
||||
return !this.selectedLibraryIsPodcast && this.fetchMetadata.enabled
|
||||
|
|
@ -297,6 +297,15 @@ export default {
|
|||
ref.setUploadStatus(status)
|
||||
}
|
||||
},
|
||||
updateItemCardProgress(index, progress) {
|
||||
var ref = this.$refs[`itemCard-${index}`]
|
||||
if (ref && ref.length) ref = ref[0]
|
||||
if (!ref) {
|
||||
console.error('Book card ref not found', index, this.$refs)
|
||||
} else {
|
||||
ref.setUploadProgress(progress)
|
||||
}
|
||||
},
|
||||
async uploadItem(item) {
|
||||
var form = new FormData()
|
||||
form.set('title', item.title)
|
||||
|
|
@ -312,8 +321,20 @@ export default {
|
|||
form.set(`${index++}`, file)
|
||||
})
|
||||
|
||||
const config = {
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.lengthComputable) {
|
||||
const progress = {
|
||||
loaded: progressEvent.loaded,
|
||||
total: progressEvent.total
|
||||
}
|
||||
this.updateItemCardProgress(item.index, progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.$axios
|
||||
.$post('/api/upload', form)
|
||||
.$post('/api/upload', form, config)
|
||||
.then(() => true)
|
||||
.catch((error) => {
|
||||
console.error('Failed to upload item', error)
|
||||
|
|
@ -394,6 +415,8 @@ export default {
|
|||
this.setMetadataProvider()
|
||||
|
||||
this.setDefaultFolder()
|
||||
// Fetch providers if not already loaded
|
||||
this.$store.dispatch('scanners/fetchProviders')
|
||||
window.addEventListener('dragenter', this.dragenter)
|
||||
window.addEventListener('dragleave', this.dragleave)
|
||||
window.addEventListener('dragover', this.dragover)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const languageCodeMap = {
|
|||
it: { label: 'Italiano', dateFnsLocale: 'it' },
|
||||
lt: { label: 'Lietuvių', dateFnsLocale: 'lt' },
|
||||
hu: { label: 'Magyar', dateFnsLocale: 'hu' },
|
||||
ko: { label: '한국어', dateFnsLocale: 'ko' },
|
||||
nl: { label: 'Nederlands', dateFnsLocale: 'nl' },
|
||||
no: { label: 'Norsk', dateFnsLocale: 'no' },
|
||||
pl: { label: 'Polski', dateFnsLocale: 'pl' },
|
||||
|
|
@ -29,6 +30,7 @@ const languageCodeMap = {
|
|||
ru: { label: 'Русский', dateFnsLocale: 'ru' },
|
||||
sl: { label: 'Slovenščina', dateFnsLocale: 'sl' },
|
||||
sv: { label: 'Svenska', dateFnsLocale: 'sv' },
|
||||
tr: { label: 'Türkçe', dateFnsLocale: 'tr' },
|
||||
uk: { label: 'Українська', dateFnsLocale: 'uk' },
|
||||
'vi-vn': { label: 'Tiếng Việt', dateFnsLocale: 'vi' },
|
||||
'zh-cn': { label: '简体中文 (Simplified Chinese)', dateFnsLocale: 'zhCN' },
|
||||
|
|
|
|||
|
|
@ -117,7 +117,6 @@ export const actions = {
|
|||
const library = data.library
|
||||
const filterData = data.filterdata
|
||||
const issues = data.issues || 0
|
||||
const customMetadataProviders = data.customMetadataProviders || []
|
||||
const numUserPlaylists = data.numUserPlaylists
|
||||
|
||||
dispatch('user/checkUpdateLibrarySortFilter', library.mediaType, { root: true })
|
||||
|
|
@ -131,8 +130,6 @@ export const actions = {
|
|||
commit('setLibraryIssues', issues)
|
||||
commit('setLibraryFilterData', filterData)
|
||||
commit('setNumUserPlaylists', numUserPlaylists)
|
||||
commit('scanners/setCustomMetadataProviders', customMetadataProviders, { root: true })
|
||||
|
||||
commit('setCurrentLibrary', { id: libraryId })
|
||||
return data
|
||||
})
|
||||
|
|
@ -159,7 +156,7 @@ export const actions = {
|
|||
.$get(`/api/libraries`)
|
||||
.then((data) => {
|
||||
commit('set', data.libraries)
|
||||
commit('setLastLoad')
|
||||
commit('setLastLoad', new Date())
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
|
|
@ -176,8 +173,8 @@ export const mutations = {
|
|||
setFoldersLastUpdate(state) {
|
||||
state.folderLastUpdate = Date.now()
|
||||
},
|
||||
setLastLoad(state) {
|
||||
state.lastLoad = Date.now()
|
||||
setLastLoad(state, date) {
|
||||
state.lastLoad = date
|
||||
},
|
||||
setLibraryIssues(state, val) {
|
||||
state.issues = val
|
||||
|
|
|
|||
|
|
@ -1,126 +1,60 @@
|
|||
export const state = () => ({
|
||||
providers: [
|
||||
{
|
||||
text: 'Google Books',
|
||||
value: 'google'
|
||||
},
|
||||
{
|
||||
text: 'Open Library',
|
||||
value: 'openlibrary'
|
||||
},
|
||||
{
|
||||
text: 'iTunes',
|
||||
value: 'itunes'
|
||||
},
|
||||
{
|
||||
text: 'Audible.com',
|
||||
value: 'audible'
|
||||
},
|
||||
{
|
||||
text: 'Audible.ca',
|
||||
value: 'audible.ca'
|
||||
},
|
||||
{
|
||||
text: 'Audible.co.uk',
|
||||
value: 'audible.uk'
|
||||
},
|
||||
{
|
||||
text: 'Audible.com.au',
|
||||
value: 'audible.au'
|
||||
},
|
||||
{
|
||||
text: 'Audible.fr',
|
||||
value: 'audible.fr'
|
||||
},
|
||||
{
|
||||
text: 'Audible.de',
|
||||
value: 'audible.de'
|
||||
},
|
||||
{
|
||||
text: 'Audible.co.jp',
|
||||
value: 'audible.jp'
|
||||
},
|
||||
{
|
||||
text: 'Audible.it',
|
||||
value: 'audible.it'
|
||||
},
|
||||
{
|
||||
text: 'Audible.co.in',
|
||||
value: 'audible.in'
|
||||
},
|
||||
{
|
||||
text: 'Audible.es',
|
||||
value: 'audible.es'
|
||||
},
|
||||
{
|
||||
text: 'FantLab.ru',
|
||||
value: 'fantlab'
|
||||
}
|
||||
],
|
||||
podcastProviders: [
|
||||
{
|
||||
text: 'iTunes',
|
||||
value: 'itunes'
|
||||
}
|
||||
],
|
||||
coverOnlyProviders: [
|
||||
{
|
||||
text: 'AudiobookCovers.com',
|
||||
value: 'audiobookcovers'
|
||||
}
|
||||
]
|
||||
bookProviders: [],
|
||||
podcastProviders: [],
|
||||
bookCoverProviders: [],
|
||||
podcastCoverProviders: [],
|
||||
providersLoaded: false
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
checkBookProviderExists: state => (providerValue) => {
|
||||
return state.providers.some(p => p.value === providerValue)
|
||||
checkBookProviderExists: (state) => (providerValue) => {
|
||||
return state.bookProviders.some((p) => p.value === providerValue)
|
||||
},
|
||||
checkPodcastProviderExists: state => (providerValue) => {
|
||||
return state.podcastProviders.some(p => p.value === providerValue)
|
||||
checkPodcastProviderExists: (state) => (providerValue) => {
|
||||
return state.podcastProviders.some((p) => p.value === providerValue)
|
||||
},
|
||||
areProvidersLoaded: (state) => state.providersLoaded
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
async fetchProviders({ commit, state }) {
|
||||
// Only fetch if not already loaded
|
||||
if (state.providersLoaded) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.$get('/api/search/providers')
|
||||
if (response?.providers) {
|
||||
commit('setAllProviders', response.providers)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch providers', error)
|
||||
}
|
||||
},
|
||||
async refreshProviders({ commit, state }) {
|
||||
// if providers are not loaded, do nothing - they will be fetched when required (
|
||||
if (!state.providersLoaded) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.$get('/api/search/providers')
|
||||
if (response?.providers) {
|
||||
commit('setAllProviders', response.providers)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh providers', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {}
|
||||
|
||||
export const mutations = {
|
||||
addCustomMetadataProvider(state, provider) {
|
||||
if (provider.mediaType === 'book') {
|
||||
if (state.providers.some(p => p.value === provider.slug)) return
|
||||
state.providers.push({
|
||||
text: provider.name,
|
||||
value: provider.slug
|
||||
})
|
||||
} else {
|
||||
if (state.podcastProviders.some(p => p.value === provider.slug)) return
|
||||
state.podcastProviders.push({
|
||||
text: provider.name,
|
||||
value: provider.slug
|
||||
})
|
||||
}
|
||||
},
|
||||
removeCustomMetadataProvider(state, provider) {
|
||||
if (provider.mediaType === 'book') {
|
||||
state.providers = state.providers.filter(p => p.value !== provider.slug)
|
||||
} else {
|
||||
state.podcastProviders = state.podcastProviders.filter(p => p.value !== provider.slug)
|
||||
}
|
||||
},
|
||||
setCustomMetadataProviders(state, providers) {
|
||||
if (!providers?.length) return
|
||||
|
||||
const mediaType = providers[0].mediaType
|
||||
if (mediaType === 'book') {
|
||||
// clear previous values, and add new values to the end
|
||||
state.providers = state.providers.filter((p) => !p.value.startsWith('custom-'))
|
||||
state.providers = [
|
||||
...state.providers,
|
||||
...providers.map((p) => ({
|
||||
text: p.name,
|
||||
value: p.slug
|
||||
}))
|
||||
]
|
||||
} else {
|
||||
// Podcast providers not supported yet
|
||||
}
|
||||
setAllProviders(state, providers) {
|
||||
state.bookProviders = providers.books || []
|
||||
state.podcastProviders = providers.podcasts || []
|
||||
state.bookCoverProviders = providers.booksCovers || []
|
||||
state.podcastCoverProviders = providers.podcasts || [] // Use same as bookCovers since podcasts use iTunes only
|
||||
state.providersLoaded = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "إضافة",
|
||||
"ButtonAddApiKey": "إضافة مفتاح واجهة برمجة التطبيقات",
|
||||
"ButtonAddChapters": "إضافة الفصول",
|
||||
"ButtonAddDevice": "إضافة جهاز",
|
||||
"ButtonAddLibrary": "إضافة مكتبة",
|
||||
|
|
@ -20,7 +21,8 @@
|
|||
"ButtonChooseAFolder": "اختر المجلد",
|
||||
"ButtonChooseFiles": "اختر الملفات",
|
||||
"ButtonClearFilter": "تصفية الفرز",
|
||||
"ButtonCloseFeed": "إغلاق",
|
||||
"ButtonClose": "إغلاق",
|
||||
"ButtonCloseFeed": "إغلاق الموجز",
|
||||
"ButtonCloseSession": "إغلاق الجلسة المفتوحة",
|
||||
"ButtonCollections": "المجموعات",
|
||||
"ButtonConfigureScanner": "إعدادات الماسح الضوئي",
|
||||
|
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "الحساب",
|
||||
"HeaderAddCustomMetadataProvider": "إضافة موفر بيانات تعريفية مخصص",
|
||||
"HeaderAdvanced": "متقدم",
|
||||
"HeaderApiKeys": "مفاتيح API",
|
||||
"HeaderAppriseNotificationSettings": "إعدادات الإشعارات",
|
||||
"HeaderAudioTracks": "المقاطع الصوتية",
|
||||
"HeaderAudiobookTools": "أدوات إدارة ملفات الكتب الصوتية",
|
||||
"HeaderAuthentication": "المصادقة",
|
||||
"HeaderBackups": "النسخ الاحتياطية",
|
||||
"HeaderBulkChapterModal": "أضف فصولاً متعددة",
|
||||
"HeaderChangePassword": "تغيير كلمة المرور",
|
||||
"HeaderChapters": "الفصول",
|
||||
"HeaderChooseAFolder": "اختيار المجلد",
|
||||
|
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "ترتيب أولوية البيانات الوصفية",
|
||||
"HeaderMetadataToEmbed": "البيانات الوصفية المراد تضمينها",
|
||||
"HeaderNewAccount": "حساب جديد",
|
||||
"HeaderNewApiKey": "مفتاح API جديد",
|
||||
"HeaderNewLibrary": "مكتبة جديدة",
|
||||
"HeaderNotificationCreate": "إنشاء إشعار",
|
||||
"HeaderNotificationUpdate": "تحديث إشعار",
|
||||
|
|
@ -195,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "ميزات تجريبية",
|
||||
"HeaderSettingsGeneral": "عام",
|
||||
"HeaderSettingsScanner": "إعدادات المسح",
|
||||
"HeaderSettingsSecurity": "الأمان",
|
||||
"HeaderSettingsWebClient": "عميل الويب",
|
||||
"HeaderSleepTimer": "مؤقت النوم",
|
||||
"HeaderStatsLargestItems": "أكبر العناصر حجماً",
|
||||
|
|
@ -206,6 +212,7 @@
|
|||
"HeaderTableOfContents": "جدول المحتويات",
|
||||
"HeaderTools": "أدوات",
|
||||
"HeaderUpdateAccount": "تحديث الحساب",
|
||||
"HeaderUpdateApiKey": "تحديث مفتاح API",
|
||||
"HeaderUpdateAuthor": "تحديث المؤلف",
|
||||
"HeaderUpdateDetails": "تحديث التفاصيل",
|
||||
"HeaderUpdateLibrary": "تحديث المكتبة",
|
||||
|
|
@ -235,6 +242,8 @@
|
|||
"LabelAllUsersExcludingGuests": "جميع المستخدمين باستثناء الضيوف",
|
||||
"LabelAllUsersIncludingGuests": "جميع المستخدمين بما في ذلك الضيوف",
|
||||
"LabelAlreadyInYourLibrary": "موجود بالفعل في مكتبتك",
|
||||
"LabelApiKeyCreated": "تم إنشاء مفتاح API \"{0}\" بنجاح.",
|
||||
"LabelApiKeyCreatedDescription": "تأكد من نسخ مفتاح API الآن، لن تتمكن من رؤيته مرة أخرى.",
|
||||
"LabelApiToken": "رمز API",
|
||||
"LabelAppend": "إلحاق",
|
||||
"LabelAudioBitrate": "معدل بت الصوت (على سبيل المثال 128 كيلو بايت)",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "যোগ করুন",
|
||||
"ButtonAddApiKey": "এপিআই কী যোগ করুন",
|
||||
"ButtonAddChapters": "অধ্যায় যোগ করুন",
|
||||
"ButtonAddDevice": "ডিভাইস যোগ করুন",
|
||||
"ButtonAddLibrary": "লাইব্রেরি যোগ করুন",
|
||||
|
|
@ -10,6 +11,8 @@
|
|||
"ButtonApplyChapters": "অধ্যায় প্রয়োগ করুন",
|
||||
"ButtonAuthors": "লেখকগণ",
|
||||
"ButtonBack": "পেছনে যান",
|
||||
"ButtonBatchEditPopulateFromExisting": "বিদ্যমান থেকে পূরণ করুন",
|
||||
"ButtonBatchEditPopulateMapDetails": "ম্যাপ থেকে পূরণ করুন",
|
||||
"ButtonBrowseForFolder": "ফোল্ডারের জন্য ব্রাউজ করুন",
|
||||
"ButtonCancel": "বাতিল করুন",
|
||||
"ButtonCancelEncode": "এনকোড বাতিল করুন",
|
||||
|
|
@ -18,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "একটি ফোল্ডার চয়ন করুন",
|
||||
"ButtonChooseFiles": "ফাইল চয়ন করুন",
|
||||
"ButtonClearFilter": "ফিল্টার পরিষ্কার করুন",
|
||||
"ButtonClose": "বন্ধ করুন",
|
||||
"ButtonCloseFeed": "ফিড বন্ধ করুন",
|
||||
"ButtonCloseSession": "খোলা সেশন বন্ধ করুন",
|
||||
"ButtonCollections": "সংগ্রহ",
|
||||
|
|
@ -117,11 +121,13 @@
|
|||
"HeaderAccount": "অ্যাকাউন্ট",
|
||||
"HeaderAddCustomMetadataProvider": "কাস্টম মেটাডেটা সরবরাহকারী যোগ করুন",
|
||||
"HeaderAdvanced": "অ্যাডভান্সড",
|
||||
"HeaderApiKeys": "এপিআই কী সমূহ",
|
||||
"HeaderAppriseNotificationSettings": "বিজ্ঞপ্তি সেটিংস অবহিত করুন",
|
||||
"HeaderAudioTracks": "অডিও ট্র্যাকসগুলো",
|
||||
"HeaderAudiobookTools": "অডিওবই ফাইল ম্যানেজমেন্ট টুলস",
|
||||
"HeaderAuthentication": "প্রমাণীকরণ",
|
||||
"HeaderBackups": "ব্যাকআপ",
|
||||
"HeaderBulkChapterModal": "একাধিক অধ্যায় যোগ করুন",
|
||||
"HeaderChangePassword": "পাসওয়ার্ড পরিবর্তন করুন",
|
||||
"HeaderChapters": "অধ্যায়",
|
||||
"HeaderChooseAFolder": "একটি ফোল্ডার চয়ন করুন",
|
||||
|
|
@ -160,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "মেটাডেটা অগ্রাধিকারের ক্রম",
|
||||
"HeaderMetadataToEmbed": "এম্বেড করার জন্য মেটাডেটা",
|
||||
"HeaderNewAccount": "নতুন অ্যাকাউন্ট",
|
||||
"HeaderNewApiKey": "নতুন API কী",
|
||||
"HeaderNewLibrary": "নতুন লাইব্রেরি",
|
||||
"HeaderNotificationCreate": "বিজ্ঞপ্তি তৈরি করুন",
|
||||
"HeaderNotificationUpdate": "বিজ্ঞপ্তি আপডেট করুন",
|
||||
|
|
@ -175,6 +182,7 @@
|
|||
"HeaderPlaylist": "প্লেলিস্ট",
|
||||
"HeaderPlaylistItems": "প্লেলিস্ট আইটেম",
|
||||
"HeaderPodcastsToAdd": "যোগ করার জন্য পডকাস্ট",
|
||||
"HeaderPresets": "প্রিসেট",
|
||||
"HeaderPreviewCover": "কভার ্দেখুন",
|
||||
"HeaderRSSFeedGeneral": "আরএসএস বিবরণ",
|
||||
"HeaderRSSFeedIsOpen": "আরএসএস ফিড খোলা আছে",
|
||||
|
|
@ -192,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "পরীক্ষামূলক ফিচার",
|
||||
"HeaderSettingsGeneral": "সাধারণ",
|
||||
"HeaderSettingsScanner": "স্ক্যানার",
|
||||
"HeaderSettingsSecurity": "নিরাপত্তা",
|
||||
"HeaderSettingsWebClient": "ওয়েব ক্লায়েন্ট",
|
||||
"HeaderSleepTimer": "স্লিপ টাইমার",
|
||||
"HeaderStatsLargestItems": "সবচেয়ে বড় আইটেম",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Afegeix",
|
||||
"ButtonAddApiKey": "Afegeix clau API",
|
||||
"ButtonAddChapters": "Afegeix capítols",
|
||||
"ButtonAddDevice": "Afegeix un aparell",
|
||||
"ButtonAddLibrary": "Afegeix una biblioteca",
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Trieu una carpeta",
|
||||
"ButtonChooseFiles": "Trieu fitxers",
|
||||
"ButtonClearFilter": "Neteja el filtre",
|
||||
"ButtonClose": "Tanca",
|
||||
"ButtonCloseFeed": "Tanca el canal",
|
||||
"ButtonCloseSession": "Tanca la sessió oberta",
|
||||
"ButtonCollections": "Col·leccions",
|
||||
|
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Compte",
|
||||
"HeaderAddCustomMetadataProvider": "Afegeix un proveïdor de metadades personalitzat",
|
||||
"HeaderAdvanced": "Avançat",
|
||||
"HeaderApiKeys": "Claus API",
|
||||
"HeaderAppriseNotificationSettings": "Paràmetres de notificacions Apprise",
|
||||
"HeaderAudioTracks": "Pistes d'àudio",
|
||||
"HeaderAudiobookTools": "Eines de gestió de fitxers de l'audiollibre",
|
||||
"HeaderAuthentication": "Autenticació",
|
||||
"HeaderBackups": "Còpies de Seguretat",
|
||||
"HeaderBulkChapterModal": "Afegeix capítols múltiples",
|
||||
"HeaderChangePassword": "Canvia Contrasenya",
|
||||
"HeaderChapters": "Capítols",
|
||||
"HeaderChooseAFolder": "Tria una Carpeta",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"ButtonApplyChapters": "Aplikovat kapitoly",
|
||||
"ButtonAuthors": "Autoři",
|
||||
"ButtonBack": "Zpět",
|
||||
"ButtonBatchEditPopulateFromExisting": "Vytvořit z existujících",
|
||||
"ButtonBatchEditPopulateFromExisting": "Předvyplnit z existujících",
|
||||
"ButtonBatchEditPopulateMapDetails": "Předvyplnit podrobnosti mapování",
|
||||
"ButtonBrowseForFolder": "Vyhledat složku",
|
||||
"ButtonCancel": "Zrušit",
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
"ButtonPause": "Pozastavit",
|
||||
"ButtonPlay": "Přehrát",
|
||||
"ButtonPlayAll": "Přehrát vše",
|
||||
"ButtonPlaying": "Hraje",
|
||||
"ButtonPlaying": "Přehrává",
|
||||
"ButtonPlaylists": "Seznamy skladeb",
|
||||
"ButtonPrevious": "Předchozí",
|
||||
"ButtonPreviousChapter": "Předchozí Kapitola",
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
"ButtonQueueAddItem": "Přidat do fronty",
|
||||
"ButtonQueueRemoveItem": "Odstranit z fronty",
|
||||
"ButtonQuickEmbed": "Rychle Zapsat",
|
||||
"ButtonQuickEmbedMetadata": "Rychle zapsat Metadata",
|
||||
"ButtonQuickEmbedMetadata": "Rychle Vložit Metadata",
|
||||
"ButtonQuickMatch": "Rychlé přiřazení",
|
||||
"ButtonReScan": "Znovu prohledat",
|
||||
"ButtonRead": "Číst",
|
||||
|
|
@ -127,6 +127,7 @@
|
|||
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
|
||||
"HeaderAuthentication": "Autentizace",
|
||||
"HeaderBackups": "Zálohy",
|
||||
"HeaderBulkChapterModal": "Přidat více kapitol",
|
||||
"HeaderChangePassword": "Změnit heslo",
|
||||
"HeaderChapters": "Kapitoly",
|
||||
"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)",
|
||||
"LabelDescription": "Popis",
|
||||
"LabelDeselectAll": "Odznačit vše",
|
||||
"LabelDetectedPattern": "Detekovaný vzor:",
|
||||
"LabelDevice": "Zařízení",
|
||||
"LabelDeviceInfo": "Informace o zařízení",
|
||||
"LabelDeviceIsAvailableTo": "Zařízení je dostupné pro...",
|
||||
|
|
@ -361,7 +363,7 @@
|
|||
"LabelExpiresAt": "Expiruje v",
|
||||
"LabelExpiresInSeconds": "Expiruje za (sekundy)",
|
||||
"LabelExpiresNever": "Nikdy",
|
||||
"LabelExplicit": "Explicitně",
|
||||
"LabelExplicit": "Explicitní",
|
||||
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
|
||||
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
|
||||
"LabelExportOPML": "Export OPML",
|
||||
|
|
@ -376,6 +378,7 @@
|
|||
"LabelFilterByUser": "Filtrovat podle uživatele",
|
||||
"LabelFindEpisodes": "Najít epizody",
|
||||
"LabelFinished": "Dokončeno",
|
||||
"LabelFinishedDate": "Dokončeno {0}",
|
||||
"LabelFolder": "Složka",
|
||||
"LabelFolders": "Složky",
|
||||
"LabelFontBold": "Tučně",
|
||||
|
|
@ -389,8 +392,8 @@
|
|||
"LabelGenre": "Žánr",
|
||||
"LabelGenres": "Žánry",
|
||||
"LabelHardDeleteFile": "Trvale smazat soubor",
|
||||
"LabelHasEbook": "Obsahuje elektronickou knihu",
|
||||
"LabelHasSupplementaryEbook": "Obsahuje doplňkovou elektronickou knihu",
|
||||
"LabelHasEbook": "Má e-knihu",
|
||||
"LabelHasSupplementaryEbook": "Obsahuje doplňkovou e-knihu",
|
||||
"LabelHideSubtitles": "Skrýt titulky",
|
||||
"LabelHighestPriority": "Nejvyšší priorita",
|
||||
"LabelHost": "Hostitel",
|
||||
|
|
@ -433,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Žádné {0}",
|
||||
"LabelLibraryItem": "Položka knihovny",
|
||||
"LabelLibraryName": "Název knihovny",
|
||||
"LabelLibrarySortByProgress": "Aktualizace pokroku",
|
||||
"LabelLibrarySortByProgress": "Pokrok: naposledy aktualizováno",
|
||||
"LabelLibrarySortByProgressFinished": "Pokrok: dokončeno",
|
||||
"LabelLibrarySortByProgressStarted": "Pokrok: začato",
|
||||
"LabelLimit": "Omezit",
|
||||
"LabelLineSpacing": "Řádkování",
|
||||
"LabelListenAgain": "Poslouchat znovu",
|
||||
|
|
@ -446,7 +451,7 @@
|
|||
"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",
|
||||
"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í",
|
||||
"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í",
|
||||
|
|
@ -472,6 +477,7 @@
|
|||
"LabelNewestAuthors": "Nejnovější autoři",
|
||||
"LabelNewestEpisodes": "Nejnovější epizody",
|
||||
"LabelNextBackupDate": "Datum příští zálohy",
|
||||
"LabelNextChapters": "Další kapitola bude:",
|
||||
"LabelNextScheduledRun": "Další naplánované spuštění",
|
||||
"LabelNoApiKeys": "Žádné API klíče",
|
||||
"LabelNoCustomMetadataProviders": "Žádní vlastní poskytovatelé metadat",
|
||||
|
|
@ -489,6 +495,7 @@
|
|||
"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í.",
|
||||
"LabelNumberOfBooks": "Počet knih",
|
||||
"LabelNumberOfChapters": "Počet kapitol:",
|
||||
"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:",
|
||||
"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\".",
|
||||
|
|
@ -582,7 +589,7 @@
|
|||
"LabelSettingsChromecastSupport": "Podpora Chromecastu",
|
||||
"LabelSettingsDateFormat": "Formát data",
|
||||
"LabelSettingsEnableWatcher": "Automaticky skenovat změny v knihovnách",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automaticky skenovat změny v knihovně",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automaticky sledovat změny v knihovně",
|
||||
"LabelSettingsEnableWatcherHelp": "Povoluje automatické přidávání/aktualizaci položek, když jsou zjištěny změny souborů. *Vyžaduje restart serveru",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Povolení skriptovaného obsahu v epubu",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Povolení spouštění skriptů v souborech epub. Doporučujeme toto nastavení vypnout, pokud nedůvěřujete zdroji souborů epub.",
|
||||
|
|
@ -631,6 +638,7 @@
|
|||
"LabelStartTime": "Čas Spuštění",
|
||||
"LabelStarted": "Spuštěno",
|
||||
"LabelStartedAt": "Spuštěno v",
|
||||
"LabelStartedDate": "Spuštěno {0}",
|
||||
"LabelStatsAudioTracks": "Zvukové stopy",
|
||||
"LabelStatsAuthors": "Autoři",
|
||||
"LabelStatsBestDay": "Nejlepší den",
|
||||
|
|
@ -660,6 +668,7 @@
|
|||
"LabelTheme": "Téma",
|
||||
"LabelThemeDark": "Tmavé",
|
||||
"LabelThemeLight": "Světlé",
|
||||
"LabelThemeSepia": "Hnědé",
|
||||
"LabelTimeBase": "Časová základna",
|
||||
"LabelTimeDurationXHours": "{0} hodin",
|
||||
"LabelTimeDurationXMinutes": "{0} minut",
|
||||
|
|
@ -744,6 +753,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Filtr \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Žádné výsledky pro dotaz",
|
||||
"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",
|
||||
"MessageChapterErrorFirstNotZero": "První kapitola musí začínat na 0",
|
||||
"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é?",
|
||||
"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é?",
|
||||
"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?",
|
||||
"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?",
|
||||
|
|
@ -844,7 +854,7 @@
|
|||
"MessageNoItems": "Žádné položky",
|
||||
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
|
||||
"MessageNoListeningSessions": "Žádné poslechové relace",
|
||||
"MessageNoLogs": "Žádné logy",
|
||||
"MessageNoLogs": "Žádné záznamy událostí",
|
||||
"MessageNoMediaProgress": "Žádný průběh médií",
|
||||
"MessageNoNotifications": "Žádná oznámení",
|
||||
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
|
||||
|
|
@ -874,7 +884,7 @@
|
|||
"MessageRemoveEpisodes": "Odstranit {0} epizodu",
|
||||
"MessageRemoveFromPlayerQueue": "Odstranit z fronty přehrávače",
|
||||
"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?",
|
||||
"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.",
|
||||
|
|
@ -907,7 +917,7 @@
|
|||
"MessageTaskNoFilesToScan": "Žádné soubory k prohledání",
|
||||
"MessageTaskOpmlImport": "Import OPML",
|
||||
"MessageTaskOpmlImportDescription": "Vytváření podcastů z {0} RSS feedů",
|
||||
"MessageTaskOpmlImportFeed": "Importní zdroj OPML",
|
||||
"MessageTaskOpmlImportFeed": "Import OPML feedu",
|
||||
"MessageTaskOpmlImportFeedDescription": "Importování RSS feedu \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedFailed": "Nepodařilo se získat kanál podcastu",
|
||||
"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ů",
|
||||
"NotificationOnRSSFeedFailedDescription": "Aktivováno když selže RSS kanál pro stahování epizod",
|
||||
"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",
|
||||
"PlaceholderNewFolderPath": "Nová cesta ke složce",
|
||||
"PlaceholderNewPlaylist": "Nový název seznamu přehrávání",
|
||||
|
|
@ -1000,8 +1011,12 @@
|
|||
"ToastBookmarkCreateFailed": "Vytvoření záložky se nezdařilo",
|
||||
"ToastBookmarkCreateSuccess": "Přidána záložka",
|
||||
"ToastBookmarkRemoveSuccess": "Záložka odstraněna",
|
||||
"ToastBulkChapterInvalidCount": "Zadejte číslo mezi 1 a 150",
|
||||
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
|
||||
"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",
|
||||
"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.",
|
||||
|
|
@ -1011,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Přidávání položek do kolekce selhalo",
|
||||
"ToastCollectionRemoveSuccess": "Kolekce odstraněna",
|
||||
"ToastCollectionUpdateSuccess": "Kolekce aktualizována",
|
||||
"ToastConnectionNotAvailable": "Připojení není k dispozici. Zkuste to prosím znovu později",
|
||||
"ToastCoverSearchFailed": "Hledání obálky se nezdařilo",
|
||||
"ToastCoverUpdateFailed": "Aktualizace obálky selhala",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Datum a čas jsou chybné nebo nekompletní",
|
||||
"ToastDeleteFileFailed": "Nepodařilo se smazat soubor",
|
||||
|
|
@ -1020,7 +1037,7 @@
|
|||
"ToastDeviceTestEmailFailed": "Odeslání testovacího emailu selhalo",
|
||||
"ToastDeviceTestEmailSuccess": "Testovací email byl odeslán",
|
||||
"ToastEmailSettingsUpdateSuccess": "Nastavení emailu aktualizována",
|
||||
"ToastEncodeCancelFailed": "Chyba zrušení kódování",
|
||||
"ToastEncodeCancelFailed": "Zrušení encodování selhalo",
|
||||
"ToastEncodeCancelSucces": "Kódování zrušeno",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Vyčištění fronty selhalo",
|
||||
"ToastEpisodeDownloadQueueClearSuccess": "Fronta stahování epizod je prázdná",
|
||||
|
|
@ -1085,6 +1102,7 @@
|
|||
"ToastPlaylistUpdateSuccess": "Seznam přehrávání aktualizován",
|
||||
"ToastPodcastCreateFailed": "Vytvoření podcastu se nezdařilo",
|
||||
"ToastPodcastCreateSuccess": "Podcast byl úspěšně vytvořen",
|
||||
"ToastPodcastEpisodeUpdated": "Epizoda aktualizována",
|
||||
"ToastPodcastGetFeedFailed": "Chyba při získání podcastového feedu",
|
||||
"ToastPodcastNoEpisodesInFeed": "Žádné epizody nenalezeny v RSS feedu",
|
||||
"ToastPodcastNoRssFeed": "Podcast nemá RSS feed",
|
||||
|
|
@ -1117,7 +1135,7 @@
|
|||
"ToastSessionDeleteFailed": "Nepodařilo se smazat relaci",
|
||||
"ToastSessionDeleteSuccess": "Relace smazána",
|
||||
"ToastSleepTimerDone": "Uspání knížky ... zZzzZz",
|
||||
"ToastSlugMustChange": "Slug (URL) obsahuje chybné znaky",
|
||||
"ToastSlugMustChange": "Slug obsahuje chybné znaky",
|
||||
"ToastSlugRequired": "Slug (URL) je vyžadována",
|
||||
"ToastSocketConnected": "Socket připojen",
|
||||
"ToastSocketDisconnected": "Socket odpojen",
|
||||
|
|
@ -1135,5 +1153,13 @@
|
|||
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",
|
||||
"ToastUserPasswordMismatch": "Hesla se neschodují",
|
||||
"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)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1001,13 +1001,14 @@
|
|||
"ToastCollectionItemsAddFailed": "Genstand(e) tilføjet til kollektion fejlet",
|
||||
"ToastCollectionRemoveSuccess": "Samling fjernet",
|
||||
"ToastCollectionUpdateSuccess": "Samling opdateret",
|
||||
"ToastConnectionNotAvailable": "Forbindelse mislykkedes. Prøv igen senere",
|
||||
"ToastCoverUpdateFailed": "Cover opdatering fejlede",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Dato og tid er forkert eller ufærdig",
|
||||
"ToastDeleteFileFailed": "Slet fil fejlede",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Dato og tid er ugyldig eller ufærdig",
|
||||
"ToastDeleteFileFailed": "Sletning af fil fejlede",
|
||||
"ToastDeleteFileSuccess": "Fil slettet",
|
||||
"ToastDeviceAddFailed": "Fejlede at tilføje enhed",
|
||||
"ToastDeviceNameAlreadyExists": "Elæser enhed med det navn eksistere allerede",
|
||||
"ToastDeviceTestEmailFailed": "Fejlede at sende test mail",
|
||||
"ToastDeviceAddFailed": "Tilføjelse af enhed Fejlede",
|
||||
"ToastDeviceNameAlreadyExists": "E-læser enhed med det navn eksistere allerede",
|
||||
"ToastDeviceTestEmailFailed": "Afsendelse af test mail fejlede",
|
||||
"ToastDeviceTestEmailSuccess": "Test mail sendt",
|
||||
"ToastEmailSettingsUpdateSuccess": "Mail indstillinger opdateret",
|
||||
"ToastEncodeCancelFailed": "Fejlede at afbryde indkodning",
|
||||
|
|
@ -1017,21 +1018,23 @@
|
|||
"ToastEpisodeUpdateSuccess": "{0} afsnit opdateret",
|
||||
"ToastErrorCannotShare": "Kan ikke dele på denne enhed",
|
||||
"ToastFailedToCreate": "Oprettelsen mislykkedes",
|
||||
"ToastFailedToLoadData": "Fejlede at indlæse data",
|
||||
"ToastFailedToDelete": "Sletning fejlede",
|
||||
"ToastFailedToLoadData": "Indlæsning af data fejlede",
|
||||
"ToastFailedToMatch": "Fejlet match",
|
||||
"ToastFailedToShare": "Fejlet deling",
|
||||
"ToastFailedToShare": "Deling fejlede",
|
||||
"ToastFailedToUpdate": "Fejlet opdatering",
|
||||
"ToastInvalidImageUrl": "Forkert billede URL",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Forkert maks afsnit at hente",
|
||||
"ToastInvalidUrl": "Forkert URL",
|
||||
"ToastItemCoverUpdateSuccess": "Varens omslag opdateret",
|
||||
"ToastItemDeletedFailed": "Fejlede at slette genstand",
|
||||
"ToastInvalidImageUrl": "Ugyldig billede URL",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Ugyldigt maks afsnit at hente",
|
||||
"ToastInvalidUrl": "Ugyldig URL",
|
||||
"ToastInvalidUrls": "En eller flere URLer er ugyldige",
|
||||
"ToastItemCoverUpdateSuccess": "Omslag opdateret",
|
||||
"ToastItemDeletedFailed": "Sletning af genstand fejlede",
|
||||
"ToastItemDeletedSuccess": "Genstand slettet",
|
||||
"ToastItemDetailsUpdateSuccess": "Varedetaljer opdateret",
|
||||
"ToastItemMarkedAsFinishedFailed": "Mislykkedes markering som afsluttet",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Vare markeret som afsluttet",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "Mislykkedes markering som ikke afsluttet",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Vare markeret som ikke afsluttet",
|
||||
"ToastItemDetailsUpdateSuccess": "Detaljer opdateret",
|
||||
"ToastItemMarkedAsFinishedFailed": "Markering som afsluttet mislykkedes",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Element markeret som afsluttet",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "Markering som ikke afsluttet mislykkedes",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Element markeret som ikke afsluttet",
|
||||
"ToastItemUpdateSuccess": "Genstand opdateret",
|
||||
"ToastLibraryCreateFailed": "Oprettelse af bibliotek mislykkedes",
|
||||
"ToastLibraryCreateSuccess": "Bibliotek \"{0}\" oprettet",
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
"ButtonNext": "Vor",
|
||||
"ButtonNextChapter": "Nächstes Kapitel",
|
||||
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
|
||||
"ButtonOk": "Ok",
|
||||
"ButtonOk": "OK",
|
||||
"ButtonOpenFeed": "Feed öffnen",
|
||||
"ButtonOpenManager": "Manager öffnen",
|
||||
"ButtonPause": "Pausieren",
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
"ButtonQuickMatch": "Schnellabgleich",
|
||||
"ButtonReScan": "Neu scannen",
|
||||
"ButtonRead": "Lesen",
|
||||
"ButtonReadLess": "weniger Anzeigen",
|
||||
"ButtonReadLess": "Weniger Anzeigen",
|
||||
"ButtonReadMore": "Mehr Anzeigen",
|
||||
"ButtonRefresh": "Neu Laden",
|
||||
"ButtonRemove": "Entfernen",
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
"ButtonStartM4BEncode": "M4B-Kodierung starten",
|
||||
"ButtonStartMetadataEmbed": "Metadateneinbettung starten",
|
||||
"ButtonStats": "Statistiken",
|
||||
"ButtonSubmit": "Ok",
|
||||
"ButtonSubmit": "Absenden",
|
||||
"ButtonTest": "Test",
|
||||
"ButtonUnlinkOpenId": "OpenID trennen",
|
||||
"ButtonUpload": "Hochladen",
|
||||
|
|
@ -116,7 +116,7 @@
|
|||
"ButtonViewAll": "Alles anzeigen",
|
||||
"ButtonYes": "Ja",
|
||||
"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",
|
||||
"HeaderAccount": "Konto",
|
||||
"HeaderAddCustomMetadataProvider": "Benutzerdefinierten Metadatenanbieter hinzufügen",
|
||||
|
|
@ -138,13 +138,13 @@
|
|||
"HeaderCustomMessageOnLogin": "Benutzerdefinierte Nachricht für die Anmeldung",
|
||||
"HeaderCustomMetadataProviders": "Benutzerdefinierte Metadatenanbieter",
|
||||
"HeaderDetails": "Details",
|
||||
"HeaderDownloadQueue": "Download Warteschlange",
|
||||
"HeaderEbookFiles": "E-Buch-Dateien",
|
||||
"HeaderDownloadQueue": "Download-Warteschlange",
|
||||
"HeaderEbookFiles": "E-Book-Dateien",
|
||||
"HeaderEmail": "E-Mail",
|
||||
"HeaderEmailSettings": "E-Mail-Einstellungen",
|
||||
"HeaderEpisodes": "Episoden",
|
||||
"HeaderEreaderDevices": "E-Reader Geräte",
|
||||
"HeaderEreaderSettings": "Einstellungen zum Lesen",
|
||||
"HeaderEreaderSettings": "E-Reader-Einstellungen",
|
||||
"HeaderFiles": "Dateien",
|
||||
"HeaderFindChapters": "Kapitel suchen",
|
||||
"HeaderIgnoredFiles": "Ignorierte Dateien",
|
||||
|
|
@ -378,6 +378,7 @@
|
|||
"LabelFilterByUser": "Nach Benutzern filtern",
|
||||
"LabelFindEpisodes": "Episoden suchen",
|
||||
"LabelFinished": "Beendet",
|
||||
"LabelFinishedDate": "Beendet {0}",
|
||||
"LabelFolder": "Ordner",
|
||||
"LabelFolders": "Verzeichnisse",
|
||||
"LabelFontBold": "Fett",
|
||||
|
|
@ -435,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Keine {0}",
|
||||
"LabelLibraryItem": "Bibliothekseintrag",
|
||||
"LabelLibraryName": "Bibliotheksname",
|
||||
"LabelLibrarySortByProgress": "Fortschritt aktualisiert",
|
||||
"LabelLibrarySortByProgress": "Fortschritt: Zuletzt aktualisiert",
|
||||
"LabelLibrarySortByProgressFinished": "Fortschritt: Beendet",
|
||||
"LabelLibrarySortByProgressStarted": "Fortschritt: Gestartet",
|
||||
"LabelLimit": "Begrenzung",
|
||||
"LabelLineSpacing": "Zeilenabstand",
|
||||
"LabelListenAgain": "Erneut anhören",
|
||||
|
|
@ -585,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeumorphes Design mit Holzeinlegeböden",
|
||||
"LabelSettingsChromecastSupport": "Chromecastunterstützung",
|
||||
"LabelSettingsDateFormat": "Datumsformat",
|
||||
"LabelSettingsEnableWatcher": "Bibliotheken automatisch nach Änderungen durchsuchen",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Bibliothek automatisch nach Änderungen durchsuchen",
|
||||
"LabelSettingsEnableWatcher": "Bibliotheken automatisch nach Änderungen überwachen",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Bibliothek automatisch auf Änderungen überwachen",
|
||||
"LabelSettingsEnableWatcherHelp": "Aktiviert das automatische Hinzufügen/Aktualisieren von Elementen, wenn Dateiänderungen erkannt werden. *Erfordert einen Server-Neustart",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Skriptinhalte in Epubs zulassen",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Erlaube Epub-Dateien, Skripte auszuführen. Es wird empfohlen, diese Einstellung deaktiviert zu lassen, es sei denn, du vertraust der Quelle der Epub-Dateien.",
|
||||
|
|
@ -635,6 +638,7 @@
|
|||
"LabelStartTime": "Startzeit",
|
||||
"LabelStarted": "Gestartet",
|
||||
"LabelStartedAt": "Gestartet am",
|
||||
"LabelStartedDate": "Angefangen am {0}",
|
||||
"LabelStatsAudioTracks": "Audiodateien",
|
||||
"LabelStatsAuthors": "Autoren",
|
||||
"LabelStatsBestDay": "Bester Tag",
|
||||
|
|
@ -884,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Kapitel und vorgenommenen Änderungen werden zurückgesetzt und rückgängig gemacht! Bist du dir sicher?",
|
||||
"MessageRestoreBackupConfirm": "Bist du dir sicher, dass du die Sicherung wiederherstellen willst, welche am",
|
||||
"MessageRestoreBackupWarning": "Bei der Wiederherstellung einer Sicherung wird die gesamte Datenbank unter /config und die Titelbilder in /metadata/items und /metadata/authors überschrieben.<br /><br />Bei der Sicherung werden keine Dateien in deinen Bibliotheksordnern verändert. Wenn du die Servereinstellungen aktiviert hast, um Cover und Metadaten in deinen Bibliotheksordnern zu speichern, werden diese nicht gesichert oder überschrieben.<br /><br />Alle Clients, die Ihren Server nutzen, werden automatisch aktualisiert.",
|
||||
"MessageScheduleLibraryScanNote": "Für die meisten Anwender wird empfohlen, diese Funktion deaktiviert und die Ordnerüberwachung aktiviert zu lassen. Die Ordnerüberwachung wird Änderungen in den Bibliotheksordnern automatisch erkennen. Die Ordnerüberwachung funktioniert nicht mit allen Dateisystemen (wie NFS), hier kann stattdessen die automatischen Bibliothekssuchen verwendet werden.",
|
||||
"MessageScheduleLibraryScanNote": "Für die meisten Benutzer wird empfohlen, diese Funktion deaktiviert und die Einstellung „Bibliothek automatisch auf Änderungen überwachen“ aktiviert zu lassen – dadurch werden Änderungen in Ihren Bibliotheksordnern automatisch erkannt. Aktivieren Sie diese Funktion, wenn „Bibliothek automatisch auf Änderungen überwachen“ für Ihr Dateisystem (wie NFS) nicht funktioniert.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Immer {0} um {1} ausführen",
|
||||
"MessageSearchResultsFor": "Suchergebnisse für",
|
||||
"MessageSelected": "{0} ausgewählt",
|
||||
|
|
@ -1022,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Das Hinzufügen von Element(en) zur Sammlung ist fehlgeschlagen",
|
||||
"ToastCollectionRemoveSuccess": "Sammlung entfernt",
|
||||
"ToastCollectionUpdateSuccess": "Sammlung aktualisiert",
|
||||
"ToastConnectionNotAvailable": "Verbindung nicht möglich. Bitte später erneut versuchen",
|
||||
"ToastCoverSearchFailed": "Cover-Suche fehlgeschlagen",
|
||||
"ToastCoverUpdateFailed": "Cover-Update fehlgeschlagen",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Datum und Zeit sind ungültig oder unvollständig",
|
||||
"ToastDeleteFileFailed": "Die Datei konnte nicht gelöscht werden",
|
||||
|
|
@ -1096,6 +1102,7 @@
|
|||
"ToastPlaylistUpdateSuccess": "Wiedergabeliste aktualisiert",
|
||||
"ToastPodcastCreateFailed": "Podcast konnte nicht erstellt werden",
|
||||
"ToastPodcastCreateSuccess": "Podcast erstellt",
|
||||
"ToastPodcastEpisodeUpdated": "Podcast-Folge aktualisiert",
|
||||
"ToastPodcastGetFeedFailed": "Fehler beim abrufen des Podcast Feeds",
|
||||
"ToastPodcastNoEpisodesInFeed": "Keine Episoden in RSS Feed gefunden",
|
||||
"ToastPodcastNoRssFeed": "Podcast enthält keinen RSS Feed",
|
||||
|
|
|
|||
|
|
@ -588,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeumorphic design with wooden shelves",
|
||||
"LabelSettingsChromecastSupport": "Chromecast support",
|
||||
"LabelSettingsDateFormat": "Date Format",
|
||||
"LabelSettingsEnableWatcher": "Automatically scan libraries for changes",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automatically scan library for changes",
|
||||
"LabelSettingsEnableWatcher": "Automatically watch libraries for changes",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automatically watch library for changes",
|
||||
"LabelSettingsEnableWatcherHelp": "Enables the automatic adding/updating of items when file changes are detected. *Requires server restart",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
|
||||
|
|
@ -888,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Are you sure you want to reset chapters and undo the changes you made?",
|
||||
"MessageRestoreBackupConfirm": "Are you sure you want to restore the backup created on",
|
||||
"MessageRestoreBackupWarning": "Restoring a backup will overwrite the entire database located at /config and cover images in /metadata/items & /metadata/authors.<br /><br />Backups do not modify any files in your library folders. If you have enabled server settings to store cover art and metadata in your library folders then those are not backed up or overwritten.<br /><br />All clients using your server will be automatically refreshed.",
|
||||
"MessageScheduleLibraryScanNote": "For most users, it is recommended to leave this feature disabled and keep the folder watcher setting enabled. The folder watcher will automatically detect changes in your library folders. The folder watcher doesn't work for every file system (like NFS) so scheduled library scans can be used instead.",
|
||||
"MessageScheduleLibraryScanNote": "For most users, it is recommended to leave this feature disabled and keep the \"Automatically watch library for changes\" setting enabled - it will automatically detect changes in your library folders. Enable this feature if \"Automatically watch library for changes\" does not work for your file system (like NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Run every {0} at {1}",
|
||||
"MessageSearchResultsFor": "Search results for",
|
||||
"MessageSelected": "{0} selected",
|
||||
|
|
@ -1026,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Item(s) added to collection failed",
|
||||
"ToastCollectionRemoveSuccess": "Collection removed",
|
||||
"ToastCollectionUpdateSuccess": "Collection updated",
|
||||
"ToastConnectionNotAvailable": "Connection not available. Please try again later",
|
||||
"ToastCoverSearchFailed": "Cover search failed",
|
||||
"ToastCoverUpdateFailed": "Cover update failed",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Date and time is invalid or incomplete",
|
||||
"ToastDeleteFileFailed": "Failed to delete file",
|
||||
|
|
|
|||
|
|
@ -490,13 +490,13 @@
|
|||
"LabelStatsDaysListened": "Kuulatud päevad",
|
||||
"LabelStatsHours": "Tunnid",
|
||||
"LabelStatsInARow": "järjest",
|
||||
"LabelStatsItemsFinished": "Lõpetatud üksused",
|
||||
"LabelStatsItemsFinished": "Lõpetatud raamatud",
|
||||
"LabelStatsItemsInLibrary": "Üksused raamatukogus",
|
||||
"LabelStatsMinutes": "minuteid",
|
||||
"LabelStatsMinutesListening": "Kuulamise minutid",
|
||||
"LabelStatsOverallDays": "Kokku päevad",
|
||||
"LabelStatsOverallHours": "Kokku tunnid",
|
||||
"LabelStatsWeekListening": "Nädala kuulamine",
|
||||
"LabelStatsWeekListening": "Nädala keskmine",
|
||||
"LabelSubtitle": "Alapealkiri",
|
||||
"LabelSupportedFileTypes": "Toetatud failitüübid",
|
||||
"LabelTag": "Silt",
|
||||
|
|
@ -561,7 +561,8 @@
|
|||
"MessageAppriseDescription": "Selle funktsiooni kasutamiseks peate käivitama <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> eksemplari või API, mis töötleb samu päringuid. <br />Apprise API URL peaks olema täielik URL-rada teatise saatmiseks, näiteks kui teie API eksemplar töötab aadressil <code>http://192.168.1.1:8337</code>, siis peaksite sisestama <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageBackupsDescription": "Varukoopiad hõlmavad kasutajaid, kasutajate edenemist, raamatukogu üksikasju, serveri seadeid ja kaustades <code>/metadata/items</code> ja <code>/metadata/authors</code> salvestatud pilte. Varukoopiad ei hõlma ühtegi teie raamatukogu kaustades olevat faili.",
|
||||
"MessageBatchQuickMatchDescription": "Kiire sobitamine üritab lisada valitud üksustele puuduvad kaaned ja metaandmed. Luba allpool olevad valikud, et lubada Kiire sobitamine'il üle kirjutada olemasolevaid kaasi ja/või metaandmeid.",
|
||||
"MessageBookshelfNoCollections": "Te pole veel ühtegi kogumit teinud",
|
||||
"MessageBookshelfNoCollections": "Te pole veel ühtegi kollektsiooni teinud",
|
||||
"MessageBookshelfNoCollectionsHelp": "Kollektsioonid on avalikud. Kõik kasutajad kellel on olemas ligipääs raamatukogule saavad neid näha.",
|
||||
"MessageBookshelfNoRSSFeeds": "Ühtegi RSS-i voogu pole avatud",
|
||||
"MessageBookshelfNoResultsForFilter": "Filtrile \"{0}: {1}\" pole tulemusi",
|
||||
"MessageBookshelfNoSeries": "Teil pole ühtegi seeriat",
|
||||
|
|
@ -600,6 +601,7 @@
|
|||
"MessageConfirmRenameTagMergeNote": "Märkus: See silt on juba olemas, nii et need ühendatakse.",
|
||||
"MessageConfirmRenameTagWarning": "Hoiatus! Sarnane silt erineva puhvriga on juba olemas \"{0}\".",
|
||||
"MessageConfirmSendEbookToDevice": "Olete kindel, et soovite saata {0} e-raamatu \"{1}\" seadmesse \"{2}\"?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} päeva kuuldud viimase aasta jooksul",
|
||||
"MessageDownloadingEpisode": "Episoodi allalaadimine",
|
||||
"MessageDragFilesIntoTrackOrder": "Lohistage failid õigesse järjekorda",
|
||||
"MessageEmbedFinished": "Manustamine lõpetatud!",
|
||||
|
|
|
|||
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ää",
|
||||
"ButtonAddApiKey": "Lisää API avain",
|
||||
"ButtonAddChapters": "Lisää lukuja",
|
||||
"ButtonAddDevice": "Lisää laite",
|
||||
"ButtonAddLibrary": "Lisää kirjasto",
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Valitse kansio",
|
||||
"ButtonChooseFiles": "Valitse tiedostot",
|
||||
"ButtonClearFilter": "Poista suodatus",
|
||||
"ButtonClose": "Sulje",
|
||||
"ButtonCloseFeed": "Sulje syöte",
|
||||
"ButtonCloseSession": "Sulje Avoin Sessio",
|
||||
"ButtonCollections": "Kokoelmat",
|
||||
|
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Tili",
|
||||
"HeaderAddCustomMetadataProvider": "Lisää mukautettu metadata tarjoaja",
|
||||
"HeaderAdvanced": "Edistynyt",
|
||||
"HeaderApiKeys": "API avaimet",
|
||||
"HeaderAppriseNotificationSettings": "Apprise-ilmoitusasetukset",
|
||||
"HeaderAudioTracks": "Ääniraidat",
|
||||
"HeaderAudiobookTools": "Äänikirjojen tiedostonhallintatyökalut",
|
||||
"HeaderAuthentication": "Todennus",
|
||||
"HeaderBackups": "Varmuuskopiot",
|
||||
"HeaderBulkChapterModal": "Lisää useita kappaleita",
|
||||
"HeaderChangePassword": "Vaihda salasana",
|
||||
"HeaderChapters": "Luvut",
|
||||
"HeaderChooseAFolder": "Valitse kansio",
|
||||
|
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Metadatan tärkeysjärjestys",
|
||||
"HeaderMetadataToEmbed": "Sisällytettävä metadata",
|
||||
"HeaderNewAccount": "Uusi tili",
|
||||
"HeaderNewApiKey": "Uusi API avain",
|
||||
"HeaderNewLibrary": "Uusi kirjasto",
|
||||
"HeaderNotificationCreate": "Luo ilmoitus",
|
||||
"HeaderNotificationUpdate": "Päivitä ilmoitus",
|
||||
|
|
@ -177,6 +182,7 @@
|
|||
"HeaderPlaylist": "Soittolista",
|
||||
"HeaderPlaylistItems": "Soittolistan kohteet",
|
||||
"HeaderPodcastsToAdd": "Lisättävät podcastit",
|
||||
"HeaderPresets": "Esivalinnat",
|
||||
"HeaderPreviewCover": "Esikatsele kansikuvaa",
|
||||
"HeaderRSSFeedGeneral": "RSS yksityiskohdat",
|
||||
"HeaderRSSFeedIsOpen": "RSS syöte on avoinna",
|
||||
|
|
@ -194,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Kokeelliset ominaisuudet",
|
||||
"HeaderSettingsGeneral": "Yleiset",
|
||||
"HeaderSettingsScanner": "Skannaaja",
|
||||
"HeaderSettingsSecurity": "Turvallisuus",
|
||||
"HeaderSettingsWebClient": "Webasiakasohjelma",
|
||||
"HeaderSleepTimer": "Uniajastin",
|
||||
"HeaderStatsLargestItems": "Suurimmat kohteet",
|
||||
|
|
@ -205,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Sisällysluettelo",
|
||||
"HeaderTools": "Työkalut",
|
||||
"HeaderUpdateAccount": "Päivitä tili",
|
||||
"HeaderUpdateApiKey": "Päivitä API avain",
|
||||
"HeaderUpdateAuthor": "Päivitä tekijä",
|
||||
"HeaderUpdateDetails": "Päivitä yksityiskohdat",
|
||||
"HeaderUpdateLibrary": "Päivitä kirjasto",
|
||||
|
|
@ -214,7 +222,7 @@
|
|||
"LabelAbridged": "Lyhennetty",
|
||||
"LabelAbridgedChecked": "Lyhennetty (tarkistettu)",
|
||||
"LabelAbridgedUnchecked": "Lyhentämätön (tarkistamaton)",
|
||||
"LabelAccessibleBy": "Saavutettavissa:",
|
||||
"LabelAccessibleBy": "Saavutettavissa",
|
||||
"LabelAccountType": "Tilin tyyppi",
|
||||
"LabelAccountTypeAdmin": "Järjestelmänvalvoja",
|
||||
"LabelAccountTypeGuest": "Vieras",
|
||||
|
|
@ -234,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Kaikki käyttäjät vieraita lukuun ottamatta",
|
||||
"LabelAllUsersIncludingGuests": "Kaikki käyttäjät mukaan lukien vieraat",
|
||||
"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.",
|
||||
"LabelApiKeyUser": "Toimi käyttäjän puolesta",
|
||||
"LabelApiKeyUserDescription": "Tällä API-avaimella on samat käyttöoikeudet kuin käyttäjällä, jonka puolesta se toimii. Tämä näkyy lokeissa samalla tavalla kuin jos käyttäjä itse tekisi pyynnön.",
|
||||
"LabelApiToken": "Sovellusliittymätunnus",
|
||||
"LabelAppend": "Lisää loppuun",
|
||||
"LabelAudioBitrate": "Äänen bittinopeus (esim. 128k)",
|
||||
|
|
@ -283,6 +295,7 @@
|
|||
"LabelContinueListening": "Jatka kuuntelua",
|
||||
"LabelContinueReading": "Jatka lukemista",
|
||||
"LabelContinueSeries": "Jatka sarjoja",
|
||||
"LabelCorsAllowed": "Salli CORS Origins",
|
||||
"LabelCover": "Kansikuva",
|
||||
"LabelCoverImageURL": "Kansikuvan URL-osoite",
|
||||
"LabelCoverProvider": "Kansikuvan tarjoaja",
|
||||
|
|
@ -296,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Poista tiedostojärjestelmästä (poista merkintä, jos haluat poistaa vain tietokannasta)",
|
||||
"LabelDescription": "Kuvaus",
|
||||
"LabelDeselectAll": "Poista valinta kaikista",
|
||||
"LabelDetectedPattern": "Tunnista malli:",
|
||||
"LabelDevice": "Laite",
|
||||
"LabelDeviceInfo": "Laitteen tiedot",
|
||||
"LabelDeviceIsAvailableTo": "Laite on saatavilla...",
|
||||
|
|
@ -345,7 +359,11 @@
|
|||
"LabelExample": "Esimerkki",
|
||||
"LabelExpandSeries": "Laajenna sarja",
|
||||
"LabelExpandSubSeries": "Laajenna alisarja",
|
||||
"LabelExplicit": "Yksiselitteinen",
|
||||
"LabelExpired": "Vanhentunut",
|
||||
"LabelExpiresAt": "Vanhentuu",
|
||||
"LabelExpiresInSeconds": "Vanhentuu (sekunnissa)",
|
||||
"LabelExpiresNever": "Ei koskaan",
|
||||
"LabelExplicit": "Sopimaton",
|
||||
"LabelExplicitChecked": "Yksiselitteinen (valittu)",
|
||||
"LabelExplicitUnchecked": "Ei yksiselitteinen (ei valittu)",
|
||||
"LabelExportOPML": "Vie OPML",
|
||||
|
|
@ -360,11 +378,12 @@
|
|||
"LabelFilterByUser": "Suodata käyttäjien perusteella",
|
||||
"LabelFindEpisodes": "Etsi jaksoja",
|
||||
"LabelFinished": "Valmis",
|
||||
"LabelFinishedDate": "Valmis {0}",
|
||||
"LabelFolder": "Kansio",
|
||||
"LabelFolders": "Kansiot",
|
||||
"LabelFontBold": "Lihavoitu",
|
||||
"LabelFontBoldness": "Kirjasintyyppien lihavointi",
|
||||
"LabelFontFamily": "Kirjasinperhe",
|
||||
"LabelFontFamily": "Fonttiperhe",
|
||||
"LabelFontItalic": "Kursiivi",
|
||||
"LabelFontScale": "Kirjasintyyppien skaalautuminen",
|
||||
"LabelFontStrikethrough": "Yliviivattu",
|
||||
|
|
@ -404,6 +423,7 @@
|
|||
"LabelLanguages": "Kielet",
|
||||
"LabelLastBookAdded": "Viimeisin lisätty kirja",
|
||||
"LabelLastBookUpdated": "Viimeisin päivitetty kirja",
|
||||
"LabelLastProgressDate": "Viimeisin edistyminen {0}",
|
||||
"LabelLastSeen": "Nähty viimeksi",
|
||||
"LabelLastTime": "Viimeinen kerta",
|
||||
"LabelLastUpdate": "Viimeisin päivitys",
|
||||
|
|
@ -416,6 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Ei {0}",
|
||||
"LabelLibraryItem": "Kirjaston kohde",
|
||||
"LabelLibraryName": "Kirjaston nimi",
|
||||
"LabelLibrarySortByProgress": "Edistyminen: Viimeksi päivitetty",
|
||||
"LabelLibrarySortByProgressFinished": "Edistyminen: Valmis",
|
||||
"LabelLibrarySortByProgressStarted": "Edistyminen: Aloitettu",
|
||||
"LabelLimit": "Raja",
|
||||
"LabelLineSpacing": "Riviväli",
|
||||
"LabelListenAgain": "Kuuntele uudelleen",
|
||||
|
|
@ -424,6 +447,7 @@
|
|||
"LabelLogLevelWarn": "Varoitus",
|
||||
"LabelLookForNewEpisodesAfterDate": "Etsi uusia jaksoja tämän päivämäärän jälkeen",
|
||||
"LabelLowestPriority": "Vähiten tärkeä",
|
||||
"LabelMatchConfidence": "Varmuus",
|
||||
"LabelMatchExistingUsersBy": "Vastaa olemassa olevia käyttäjiä mukaan",
|
||||
"LabelMatchExistingUsersByDescription": "Käytetään olemassa olevien käyttäjien yhdistämiseen. Kun yhteys on muodostettu, käyttäjät saavat yksilöllisen tunnuksen SSO-palveluntarjoajaltasi",
|
||||
"LabelMaxEpisodesToDownload": "Jaksojen maksimilatausmäärä. 0 poistaa rajoituksen.",
|
||||
|
|
@ -453,7 +477,9 @@
|
|||
"LabelNewestAuthors": "Uusimmat tekijät",
|
||||
"LabelNewestEpisodes": "Uusimmat jaksot",
|
||||
"LabelNextBackupDate": "Seuraava varmuuskopiointipäivämäärä",
|
||||
"LabelNextChapters": "Seuraavat luvut:",
|
||||
"LabelNextScheduledRun": "Seuraava ajastettu suorittaminen",
|
||||
"LabelNoApiKeys": "Ei API-avaimia",
|
||||
"LabelNoCustomMetadataProviders": "Ei mukautettuja kuvailutietojen toimittajia",
|
||||
"LabelNoEpisodesSelected": "Jaksoja ei ole valittu",
|
||||
"LabelNotFinished": "Ei valmis",
|
||||
|
|
@ -469,6 +495,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Ilmoitustapahtumajonon enimmäispituus",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Tapahtumat on rajoitettu ampumaan yksi sekunnissa. Tapahtumat ohitetaan, jos jono on enimmäiskoko. Tämä estää ilmoitusten roskapostin.",
|
||||
"LabelNumberOfBooks": "Kirjojen määrä",
|
||||
"LabelNumberOfChapters": "Lukujen lukumäärä:",
|
||||
"LabelNumberOfEpisodes": "# jaksoja",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "OpenID-vaatimuksen nimi, joka sisältää lisäoikeudet sovelluksen käyttäjän toimiin, joita sovelletaan muihin kuin järjestelmänvalvojan rooleihin (<b>jos määritetty</b>). Jos vaatimus puuttuu vastauksesta, pääsy ABS:iin evätään. Jos yksittäinen vaihtoehto puuttuu, sitä käsitellään <code>false</code>-arvona. Varmista, että identiteetin tarjoajan vaatimus vastaa odotettua rakennetta:",
|
||||
"LabelOpenIDClaims": "Jätä seuraavat vaihtoehdot tyhjiksi, jos haluat poistaa edistyneen ryhmän ja lupien määrityksen käytöstä ja määrittää sitten automaattisesti käyttäjäryhmän.",
|
||||
|
|
@ -513,7 +540,7 @@
|
|||
"LabelPublishers": "Julkaisijat",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Mukautettu omistajan sähköposti",
|
||||
"LabelRSSFeedCustomOwnerName": "Mukautettu omistajan nimi",
|
||||
"LabelRSSFeedOpen": "RSS-syöte avoin",
|
||||
"LabelRSSFeedOpen": "RSS Syöte Avoin",
|
||||
"LabelRSSFeedPreventIndexing": "Estä indeksointi",
|
||||
"LabelRSSFeedSlug": "RSS-syöte Slug",
|
||||
"LabelRSSFeedURL": "RSS-syötteen URL-osoite",
|
||||
|
|
@ -523,7 +550,7 @@
|
|||
"LabelReadAgain": "Lue uudelleen",
|
||||
"LabelReadEbookWithoutProgress": "Lue s-kirja tallentamatta edistymistietoja",
|
||||
"LabelRecentSeries": "Viimeisimmät sarjat",
|
||||
"LabelRecentlyAdded": "Viimeeksi lisätyt",
|
||||
"LabelRecentlyAdded": "Viimeksi lisätyt",
|
||||
"LabelRecommended": "Suositeltu",
|
||||
"LabelRedo": "Tee uudelleen",
|
||||
"LabelRegion": "Alue",
|
||||
|
|
@ -543,6 +570,7 @@
|
|||
"LabelSelectAll": "Valitse kaikki",
|
||||
"LabelSelectAllEpisodes": "Valitse kaikki jaksot",
|
||||
"LabelSelectEpisodesShowing": "Valitse {0} näytettävää jaksoa",
|
||||
"LabelSelectUser": "Valitse käyttäjä",
|
||||
"LabelSelectUsers": "Valitse käyttäjät",
|
||||
"LabelSendEbookToDevice": "Lähetä s-kirja kohteeseen...",
|
||||
"LabelSequence": "Sekvenssi",
|
||||
|
|
@ -560,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeuomorfinen muotoilu puisilla hyllyillä",
|
||||
"LabelSettingsChromecastSupport": "Chromecast-tuki",
|
||||
"LabelSettingsDateFormat": "Päivämäärän muoto",
|
||||
"LabelSettingsEnableWatcher": "Skannaa kirjastot automaattisesti muutoksien varalta",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Skannaa kirjastot automaattisesti muutoksien varalta",
|
||||
"LabelSettingsEnableWatcher": "Vahdi kirjastoja automaattisesti muutoksien varalta",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Vahdi kirjastoja automaattisesti muutoksien varalta",
|
||||
"LabelSettingsEnableWatcherHelp": "Ottaa käyttöön kohteiden automaattisen lisäämisen ja päivityksen kun tiedostomuutoksia havaitaan. *Tarvitsee palvelimen uudelleenkäynnistyksen",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Salli komentosarjamuotoinen sisältö epubissa",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Salli epub-tiedostojen suorittaa komentosarjoja. On suositeltavaa pitää tämä asetus pois käytöstä, ellet luota epub-tiedostojen lähteeseen.",
|
||||
|
|
@ -610,6 +638,7 @@
|
|||
"LabelStartTime": "Aloitusaika",
|
||||
"LabelStarted": "Aloitettu",
|
||||
"LabelStartedAt": "Aloitettu",
|
||||
"LabelStartedDate": "Aloitettu {0}",
|
||||
"LabelStatsAudioTracks": "Ääniraidat",
|
||||
"LabelStatsAuthors": "Tekijät",
|
||||
"LabelStatsBestDay": "Paras päivä",
|
||||
|
|
@ -639,6 +668,7 @@
|
|||
"LabelTheme": "Teema",
|
||||
"LabelThemeDark": "Tumma",
|
||||
"LabelThemeLight": "Kirkas",
|
||||
"LabelThemeSepia": "Seepia",
|
||||
"LabelTimeBase": "Aika-alusta",
|
||||
"LabelTimeDurationXHours": "{0} tuntia",
|
||||
"LabelTimeDurationXMinutes": "{0} minuuttia",
|
||||
|
|
@ -706,6 +736,10 @@
|
|||
"LabelYourProgress": "Edistymisesi",
|
||||
"MessageAddToPlayerQueue": "Lisää soittimen jonoon",
|
||||
"MessageAppriseDescription": "Käyttääksesi tätä toimintoa tarvitset <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> -instanssin tai rajapinnan joka käsittelee samoja pyyntöjä. <br />Apprise rajapinnan osoite tulee olla täysi URL polku ilmoituksen lähetykseen, esim. jos rajapinta on osoitteessa <code>http://192.168.1.1:8337</code>,niin arvoksi tulee antaa <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Varmista, että käytät ASIN-tunnusta oikealta Audible-alueelta, ei Amazonista.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Vanhat API-tunnukset poistetaan tulevaisuudessa. Käytä sen sijaan <a href=\"/config/api-keys\">API-avaimia</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Käynnistä palvelin uudelleen tallennuksen jälkeen ottaaksesi OIDC-muutokset käyttöön.",
|
||||
"MessageAuthenticationSecurityMessage": "Tunnistautumisen tietoturvaa on parannettu. Kaikkien käyttäjien tulee kirjautua sisään uudelleen.",
|
||||
"MessageBackupsDescription": "Varmuuskopiot sisältävät käyttäjät, käyttäjien edistymisen, kirjastokohteiden tiedot, palvelinasetukset ja <code>/metadata/items</code>- ja <code>/metadata/authors</code> -kansioihin tallennetut kuvat. Varmuuskopiot <strong>eivät sisällä</strong> kirjastosi kansioihin tallennettuja tiedostoja.",
|
||||
"MessageBackupsLocationEditNote": "Huomautus: Varmuuskopion sijainnin päivittäminen ei siirrä tai muokkaa olemassa olevia varmuuskopioita",
|
||||
"MessageBackupsLocationNoEditNote": "Huomautus: Varmuuskopion sijainti asetetaan ympäristömuuttujan kautta, eikä sitä voi muuttaa tässä.",
|
||||
|
|
@ -719,6 +753,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Ei tuloksia suodattimelle \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Ei tuloksia kyselylle",
|
||||
"MessageBookshelfNoSeries": "Sinulla ei ole sarjoja",
|
||||
"MessageBulkChapterPattern": "Kuinka monta lukua haluaisit lisätä tällä numerointimallilla?",
|
||||
"MessageChapterEndIsAfter": "Luvun loppu sijaitsee äänikirjan lopun jälkeen",
|
||||
"MessageChapterErrorFirstNotZero": "Ensimmäisen luvun tulee alkaa nollasta",
|
||||
"MessageChapterErrorStartGteDuration": "Epäkelvollinen aloitusaika; on oltava lyhyempi kuin äänikirjan kesto",
|
||||
|
|
@ -727,6 +762,7 @@
|
|||
"MessageChaptersNotFound": "Kappaleita ei löydy",
|
||||
"MessageCheckingCron": "Tarkistetaan cronia...",
|
||||
"MessageConfirmCloseFeed": "Oletko varma, että haluat sulkea tämän syötteen?",
|
||||
"MessageConfirmDeleteApiKey": "Haluatko varmasti poistaa API-avaimen \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Oletko varma, että haluat poistaa varmuuskopion {0}:lle?",
|
||||
"MessageConfirmDeleteDevice": "Oletko varma, että haluat poistaa s-lukulaitteen \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Tämä poistaa tiedoston tiedostojärjestelmästäsi. Oletko varma?",
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
"ButtonReScan": "Nouvelle analyse",
|
||||
"ButtonRead": "Lire",
|
||||
"ButtonReadLess": "Lire moins",
|
||||
"ButtonReadMore": "Lire la suite",
|
||||
"ButtonReadMore": "Lire plus",
|
||||
"ButtonRefresh": "Rafraîchir",
|
||||
"ButtonRemove": "Retirer",
|
||||
"ButtonRemoveAll": "Supprimer tout",
|
||||
|
|
@ -172,7 +172,7 @@
|
|||
"HeaderNotificationUpdate": "Mise à jour de la notification",
|
||||
"HeaderNotifications": "Notifications",
|
||||
"HeaderOpenIDConnectAuthentication": "Authentification via OpenID Connect",
|
||||
"HeaderOpenListeningSessions": "Ouvrir les sessions d'écoutes",
|
||||
"HeaderOpenListeningSessions": "Sessions d'écoute ouvertes",
|
||||
"HeaderOpenRSSFeed": "Ouvrir le flux RSS",
|
||||
"HeaderOtherFiles": "Autres fichiers",
|
||||
"HeaderPasswordAuthentication": "Authentification par mot de passe",
|
||||
|
|
@ -378,13 +378,14 @@
|
|||
"LabelFilterByUser": "Filtrer par utilisateur",
|
||||
"LabelFindEpisodes": "Trouver des épisodes",
|
||||
"LabelFinished": "Terminé le",
|
||||
"LabelFinishedDate": "Terminé {0}",
|
||||
"LabelFolder": "Dossier",
|
||||
"LabelFolders": "Dossiers",
|
||||
"LabelFontBold": "Gras",
|
||||
"LabelFontBoldness": "Graisse de la police",
|
||||
"LabelFontFamily": "Polices de caractères",
|
||||
"LabelFontFamily": "Famille de caractères",
|
||||
"LabelFontItalic": "Italique",
|
||||
"LabelFontScale": "Taille de la police de caractère",
|
||||
"LabelFontScale": "Taille de la police",
|
||||
"LabelFontStrikethrough": "Barrer",
|
||||
"LabelFormat": "Format",
|
||||
"LabelFull": "Complet",
|
||||
|
|
@ -435,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Aucun {0}",
|
||||
"LabelLibraryItem": "Élément de 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",
|
||||
"LabelLineSpacing": "Espacement des lignes",
|
||||
"LabelListenAgain": "Écouter à nouveau",
|
||||
|
|
@ -585,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Interface skeumorphique avec étagères en bois",
|
||||
"LabelSettingsChromecastSupport": "Support du Chromecast",
|
||||
"LabelSettingsDateFormat": "Format de date",
|
||||
"LabelSettingsEnableWatcher": "Analyser automatiquement les bibliothèques pour détecter les modifications",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Analyser automatiquement la bibliothèque pour détecter les modifications",
|
||||
"LabelSettingsEnableWatcher": "Surveiller automatiquement les bibliothèques pour détecter les modifications",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Surveiller automatiquement la bibliothèque pour détecter les modifications",
|
||||
"LabelSettingsEnableWatcherHelp": "Active la mise à jour automatique d'éléments lorsque des modifications de fichiers sont détectées. * Nécessite le redémarrage du serveur",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Autoriser le contenu scénarisé pour les fichiers EPUB",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Autoriser les fichiers EPUB à exécuter des scripts. Il est recommandé de laisser ce paramètre désactivé, sauf si vous faites confiance à la source des fichiers EPUB.",
|
||||
|
|
@ -635,6 +638,7 @@
|
|||
"LabelStartTime": "Heure de démarrage",
|
||||
"LabelStarted": "Démarré",
|
||||
"LabelStartedAt": "Démarré à",
|
||||
"LabelStartedDate": "Commencé {0}",
|
||||
"LabelStatsAudioTracks": "Pistes audio",
|
||||
"LabelStatsAuthors": "Auteurs",
|
||||
"LabelStatsBestDay": "Meilleur jour",
|
||||
|
|
@ -740,7 +744,7 @@
|
|||
"MessageBackupsLocationEditNote": "Remarque : Mettre à jour l'emplacement de sauvegarde ne déplacera pas ou ne modifiera pas les sauvegardes existantes",
|
||||
"MessageBackupsLocationNoEditNote": "Remarque : l’emplacement de sauvegarde est défini via une variable d’environnement et ne peut pas être modifié ici.",
|
||||
"MessageBackupsLocationPathEmpty": "L'emplacement de secours ne peut pas être vide",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Remplir les champs disponibles avec les données de tous les éléments. Les champs avec des valeurs multiples seront fusionnés.",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Renseignez les champs activés avec les données de tous les éléments. Les champs comportant plusieurs valeurs seront fusionnés.",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "Renseigner les champs de la carte active avec les informations de cet élément",
|
||||
"MessageBatchQuickMatchDescription": "La recherche par correspondance rapide tentera d’ajouter les couvertures et métadonnées manquantes pour les éléments sélectionnés. Activez les options ci-dessous pour permettre la Recherche par correspondance d’écraser les couvertures et/ou métadonnées existantes.",
|
||||
"MessageBookshelfNoCollections": "Vous n’avez pas encore de collections",
|
||||
|
|
@ -871,7 +875,7 @@
|
|||
"MessagePlaylistCreateFromCollection": "Créer une liste de lecture depuis la collection",
|
||||
"MessagePleaseWait": "Merci de patienter…",
|
||||
"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",
|
||||
"MessageQuickEmbedQueue": "En file d'attente pour une intégration rapide ({0} dans la file d'attente)",
|
||||
"MessageQuickMatchAllEpisodes": "Associer rapidement tous les épisodes",
|
||||
|
|
@ -884,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Êtes-vous sûr·e de vouloir réinitialiser les chapitres et annuler les changements effectués ?",
|
||||
"MessageRestoreBackupConfirm": "Êtes-vous sûr·e de vouloir restaurer la sauvegarde créée le",
|
||||
"MessageRestoreBackupWarning": "Restaurer la sauvegarde écrasera la base de donnée située dans le dossier /config ainsi que les images sur /metadata/items et /metadata/authors.<br><br>Les sauvegardes ne touchent pas aux fichiers de la bibliothèque. Si vous avez activé le paramètre pour sauvegarder les métadonnées et les images de couverture dans le même dossier que les fichiers, ceux-ci ne ni sauvegardés, ni écrasés lors de la restauration.<br><br>Tous les clients utilisant votre serveur seront automatiquement mis à jour.",
|
||||
"MessageScheduleLibraryScanNote": "Pour la plupart des utilisateurs, il est recommandé de laisser cette fonctionnalité désactivée et de maintenir le réglage du moniteur de dossier activé. Le moniteur de dossier détectera automatiquement les changements dans vos dossiers de bibliothèque. Le moniteur de dossier ne fonctionne pas pour chaque système de fichiers (comme NFS) afin que les scans de bibliothèques programmés puissent être utilisés à la place.",
|
||||
"MessageScheduleLibraryScanNote": "Pour la plupart des utilisateurs, il est recommandé de laisser cette fonctionnalité désactivée et de maintenir le paramètre « Surveiller automatiquement la bibliothèque pour détecter les modifications » activé – il détectera automatiquement les modifications dans les dossiers de votre bibliothèque. Activez cette fonctionnalité si l'option « Surveiller automatiquement la bibliothèque pour détecter les modifications » ne fonctionne pas pour votre système de fichiers (comme NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Exécuté tous les {0} à {1}",
|
||||
"MessageSearchResultsFor": "Résultats de recherche pour",
|
||||
"MessageSelected": "{0} sélectionnés",
|
||||
|
|
@ -958,7 +962,7 @@
|
|||
"PlaceholderNewFolderPath": "Nouveau chemin de dossier",
|
||||
"PlaceholderNewPlaylist": "Nouveau nom de liste de lecture",
|
||||
"PlaceholderSearch": "Recherche…",
|
||||
"PlaceholderSearchEpisode": "Rechercher un épisode…",
|
||||
"PlaceholderSearchEpisode": "Rechercher un épisode..",
|
||||
"StatsAuthorsAdded": "auteurs ajoutés",
|
||||
"StatsBooksAdded": "livres ajoutés",
|
||||
"StatsBooksAdditional": "Les ajouts comprennent…",
|
||||
|
|
@ -1010,6 +1014,8 @@
|
|||
"ToastBulkChapterInvalidCount": "Veuillez entrer un nombre valide entre 1 et 150",
|
||||
"ToastCachePurgeFailed": "Échec de la purge du cache",
|
||||
"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.",
|
||||
"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.",
|
||||
|
|
@ -1020,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Échec de l’ajout de(s) élément(s) à la collection",
|
||||
"ToastCollectionRemoveSuccess": "Collection supprimée",
|
||||
"ToastCollectionUpdateSuccess": "Collection mise à jour",
|
||||
"ToastConnectionNotAvailable": "Connexion indisponible. Veuillez réessayer plus tard.",
|
||||
"ToastCoverSearchFailed": "La recherche de la couverture a échoué",
|
||||
"ToastCoverUpdateFailed": "Échec de la mise à jour de la couverture",
|
||||
"ToastDateTimeInvalidOrIncomplete": "La date et l'heure sont invalides ou incomplètes",
|
||||
"ToastDeleteFileFailed": "Échec de la suppression du fichier",
|
||||
|
|
@ -1094,6 +1102,7 @@
|
|||
"ToastPlaylistUpdateSuccess": "Liste de lecture mise à jour",
|
||||
"ToastPodcastCreateFailed": "Échec de la création du podcast",
|
||||
"ToastPodcastCreateSuccess": "Podcast créé avec succès",
|
||||
"ToastPodcastEpisodeUpdated": "Épisode mis à jour",
|
||||
"ToastPodcastGetFeedFailed": "Échec de la récupération du flux du podcast",
|
||||
"ToastPodcastNoEpisodesInFeed": "Aucun épisode trouvé dans le flux RSS",
|
||||
"ToastPodcastNoRssFeed": "Le podcast n’a pas de flux RSS",
|
||||
|
|
@ -1147,6 +1156,7 @@
|
|||
"ToastUserRootRequireName": "Vous devez entrer un nom d’utilisateur root",
|
||||
"TooltipAddChapters": "Ajouter chapitre(s)",
|
||||
"TooltipAddOneSecond": "Ajouter 1 seconde",
|
||||
"TooltipAdjustChapterStart": "Cliquez pour régler l'heure de début",
|
||||
"TooltipLockAllChapters": "Verrouiller tous les chapitres",
|
||||
"TooltipLockChapter": "Verrouiller le chapitre (Maj+clic pour plage)",
|
||||
"TooltipSubtractOneSecond": "Soustraire 1 seconde",
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@
|
|||
"LabelExample": "דוגמה",
|
||||
"LabelExpandSeries": "הרחב סדרה",
|
||||
"LabelExpandSubSeries": "הרחב תת סדרה",
|
||||
"LabelExplicit": "בוטה",
|
||||
"LabelExplicit": "מפורש",
|
||||
"LabelExplicitChecked": "בוטה (מסומן)",
|
||||
"LabelExplicitUnchecked": "לא בוטה (לא מסומן)",
|
||||
"LabelExportOPML": "ייצוא OPML",
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
"ButtonApplyChapters": "Primijeni poglavlja",
|
||||
"ButtonAuthors": "Autori",
|
||||
"ButtonBack": "Natrag",
|
||||
"ButtonBatchEditPopulateFromExisting": "Popuni iz postojećeg",
|
||||
"ButtonBatchEditPopulateMapDetails": "Popuni mapirane pojedinosti",
|
||||
"ButtonBatchEditPopulateFromExisting": "Popuni iz postojećih",
|
||||
"ButtonBatchEditPopulateMapDetails": "Popuni detalje karte",
|
||||
"ButtonBrowseForFolder": "Pronađi mapu",
|
||||
"ButtonCancel": "Odustani",
|
||||
"ButtonCancelEncode": "Otkaži kodiranje",
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
"ButtonRemoveAllLibraryItems": "Ukloni sve stavke iz knjižnice",
|
||||
"ButtonRemoveFromContinueListening": "Ukloni iz Nastavi slušati",
|
||||
"ButtonRemoveFromContinueReading": "Ukloni iz Nastavi čitati",
|
||||
"ButtonRemoveSeriesFromContinueSeries": "Ukloni seriju iz Nastavi seriju",
|
||||
"ButtonRemoveSeriesFromContinueSeries": "Ukloni serijal iz popisa „Nastavi serijal”",
|
||||
"ButtonReset": "Poništi",
|
||||
"ButtonResetToDefault": "Vrati na početne postavke",
|
||||
"ButtonRestore": "Vraćanje",
|
||||
|
|
@ -107,17 +107,17 @@
|
|||
"ButtonSubmit": "Pošalji",
|
||||
"ButtonTest": "Test",
|
||||
"ButtonUnlinkOpenId": "Prekini vezu s OpenID-jem",
|
||||
"ButtonUpload": "Učitaj",
|
||||
"ButtonUploadBackup": "Učitaj sigurnosnu kopiju",
|
||||
"ButtonUploadCover": "Učitaj naslovnicu",
|
||||
"ButtonUploadOPMLFile": "Učitaj OPML datoteku",
|
||||
"ButtonUpload": "Prenesi",
|
||||
"ButtonUploadBackup": "Prenesi sigurnosnu kopiju",
|
||||
"ButtonUploadCover": "Prenesi naslovnicu",
|
||||
"ButtonUploadOPMLFile": "Prenesi OPML datoteku",
|
||||
"ButtonUserDelete": "Izbriši korisnika {0}",
|
||||
"ButtonUserEdit": "Uredi korisnika {0}",
|
||||
"ButtonViewAll": "Prikaži sve",
|
||||
"ButtonYes": "Da",
|
||||
"ErrorUploadFetchMetadataAPI": "Pogreška pri dohvatu meta-podataka",
|
||||
"ErrorUploadFetchMetadataNoResults": "Dohvat meta-podataka nije uspio - pokušajte ispraviti naslov i/ili autora",
|
||||
"ErrorUploadLacksTitle": "Naslov je obavezan",
|
||||
"ErrorUploadFetchMetadataAPI": "Pogreška pri dohvaćanju meta-podataka",
|
||||
"ErrorUploadFetchMetadataNoResults": "Nije bilo moguće dohvatiti meta-podatake – pokušajte aktualizirati naslov i/ili autora",
|
||||
"ErrorUploadLacksTitle": "Mora imati naslov",
|
||||
"HeaderAccount": "Korisnički račun",
|
||||
"HeaderAddCustomMetadataProvider": "Dodaj prilagođenog pružatelja meta-podataka",
|
||||
"HeaderAdvanced": "Napredno",
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"HeaderCollection": "Zbirka",
|
||||
"HeaderCollectionItems": "Stavke u zbirci",
|
||||
"HeaderCover": "Naslovnica",
|
||||
"HeaderCurrentDownloads": "Preuzimanja u tijeku",
|
||||
"HeaderCurrentDownloads": "Trenutačna preuzimanja",
|
||||
"HeaderCustomMessageOnLogin": "Prilagođena poruka prilikom prijave",
|
||||
"HeaderCustomMetadataProviders": "Prilagođeni pružatelji meta-podataka",
|
||||
"HeaderDetails": "Pojedinosti",
|
||||
|
|
@ -197,7 +197,7 @@
|
|||
"HeaderSetBackupSchedule": "Zakazivanje sigurnosne pohrane",
|
||||
"HeaderSettings": "Postavke",
|
||||
"HeaderSettingsDisplay": "Prikaz",
|
||||
"HeaderSettingsExperimental": "Eksperimentalne značajke",
|
||||
"HeaderSettingsExperimental": "Eksperimentalne funkcije",
|
||||
"HeaderSettingsGeneral": "Općenito",
|
||||
"HeaderSettingsScanner": "Skener",
|
||||
"HeaderSettingsSecurity": "Sigurnost",
|
||||
|
|
@ -257,7 +257,7 @@
|
|||
"LabelAuthors": "Autori",
|
||||
"LabelAutoDownloadEpisodes": "Automatski preuzmi nastavke",
|
||||
"LabelAutoFetchMetadata": "Automatski dohvati meta-podatke",
|
||||
"LabelAutoFetchMetadataHelp": "Dohvaća meta-podatke o naslovu, autoru i serijalu kako bi pojednostavnio učitavanje. Dodatni meta-podatci će se možda morati dohvatiti nakon učitavanja.",
|
||||
"LabelAutoFetchMetadataHelp": "Dohvaća meta-podatke o naslovu, autoru i serijalu kako bi pojednostavnio prijenos. Dodatni meta-podatci će se možda morati usporediti nakon prijenosa.",
|
||||
"LabelAutoLaunch": "Automatsko pokretanje",
|
||||
"LabelAutoLaunchDescription": "Automatski preusmjeri na pružatelja autentifikacijskih usluga prilikom otvaranja stranice za prijavu (putanja za ručno zaobilaženje opcije <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Automatska registracija",
|
||||
|
|
@ -286,8 +286,8 @@
|
|||
"LabelClickToUseCurrentValue": "Kliknite za trenutnu vrijednost",
|
||||
"LabelClosePlayer": "Zatvori reproduktor",
|
||||
"LabelCodec": "Kodek",
|
||||
"LabelCollapseSeries": "Serijale prikaži sažeto",
|
||||
"LabelCollapseSubSeries": "Podserijale prikaži sažeto",
|
||||
"LabelCollapseSeries": "Sažmi serijal",
|
||||
"LabelCollapseSubSeries": "Sažmi podserijale",
|
||||
"LabelCollection": "Zbirka",
|
||||
"LabelCollections": "Zbirke",
|
||||
"LabelComplete": "Potpuno",
|
||||
|
|
@ -303,7 +303,7 @@
|
|||
"LabelCronExpression": "Cron izraz",
|
||||
"LabelCurrent": "Trenutan",
|
||||
"LabelCurrently": "Trenutno:",
|
||||
"LabelCustomCronExpression": "Prilagođeni CRON izraz:",
|
||||
"LabelCustomCronExpression": "Prilagođeni cron izraz:",
|
||||
"LabelDatetime": "Datum i vrijeme",
|
||||
"LabelDays": "Dani",
|
||||
"LabelDeleteFromFileSystemCheckbox": "Izbriši datoteke (uklonite kvačicu ako stavku želite izbrisati samo iz baze podataka)",
|
||||
|
|
@ -312,7 +312,7 @@
|
|||
"LabelDetectedPattern": "Prepoznat obrazac:",
|
||||
"LabelDevice": "Uređaj",
|
||||
"LabelDeviceInfo": "O uređaju",
|
||||
"LabelDeviceIsAvailableTo": "Uređaj je dostupan...",
|
||||
"LabelDeviceIsAvailableTo": "Uređaj je dostupan za...",
|
||||
"LabelDirectory": "Direktorij",
|
||||
"LabelDiscFromFilename": "Disk iz imena datoteke",
|
||||
"LabelDiscFromMetadata": "Disk iz metapodataka",
|
||||
|
|
@ -340,7 +340,7 @@
|
|||
"LabelEncodingBackupLocation": "Sigurnosna kopija vaših izvornih zvučnih datoteka čuvat će se u mapi:",
|
||||
"LabelEncodingChaptersNotEmbedded": "Poglavlja se ne ugrađuju u zvučne knjige koje se sastoje od više zvučnih zapisa.",
|
||||
"LabelEncodingClearItemCache": "Svakako redovito praznite predmemoriju stavki.",
|
||||
"LabelEncodingFinishedM4B": "Stvorene M4B datoteke spremit će se u vašu mapu sa zvučnim knjigama:",
|
||||
"LabelEncodingFinishedM4B": "Gotove M4B datoteke spremit će se u vašu mapu sa zvučnim knjigama:",
|
||||
"LabelEncodingInfoEmbedded": "Meta-podatci će se ugraditi u zvučne zapise u vašoj mapi sa zvučnim knjigama.",
|
||||
"LabelEncodingStartedNavigation": "Nakon pokretanja zadatka možete napustiti ovu stranicu.",
|
||||
"LabelEncodingTimeWarning": "Kodiranje može potrajati do 30 minuta.",
|
||||
|
|
@ -357,8 +357,8 @@
|
|||
"LabelEpisodes": "Nastavci",
|
||||
"LabelEpisodic": "U nastavcima",
|
||||
"LabelExample": "Primjer",
|
||||
"LabelExpandSeries": "Serijal prikaži prošireno",
|
||||
"LabelExpandSubSeries": "Podserijal prikaži prošireno",
|
||||
"LabelExpandSeries": "Proširi serijal",
|
||||
"LabelExpandSubSeries": "Proširi podserijal",
|
||||
"LabelExpired": "Istekao",
|
||||
"LabelExpiresAt": "Istječe",
|
||||
"LabelExpiresInSeconds": "Istječe za (sekundi)",
|
||||
|
|
@ -374,10 +374,11 @@
|
|||
"LabelFileBornDate": "Stvoreno {0}",
|
||||
"LabelFileModified": "Datoteka izmijenjena",
|
||||
"LabelFileModifiedDate": "Izmijenjeno {0}",
|
||||
"LabelFilename": "Naziv datoteke",
|
||||
"LabelFilename": "Ime datoteke",
|
||||
"LabelFilterByUser": "Filtriraj po korisniku",
|
||||
"LabelFindEpisodes": "Pronađi nastavke",
|
||||
"LabelFinished": "Dovršeno",
|
||||
"LabelFinished": "Završeno",
|
||||
"LabelFinishedDate": "Završeno {0}",
|
||||
"LabelFolder": "Mapa",
|
||||
"LabelFolders": "Mape",
|
||||
"LabelFontBold": "Podebljano",
|
||||
|
|
@ -393,7 +394,7 @@
|
|||
"LabelHardDeleteFile": "Izbriši datoteku zauvijek",
|
||||
"LabelHasEbook": "Ima e-knjigu",
|
||||
"LabelHasSupplementaryEbook": "Ima dopunsku e-knjigu",
|
||||
"LabelHideSubtitles": "Skrij podnaslove",
|
||||
"LabelHideSubtitles": "Sakrij podnaslove",
|
||||
"LabelHighestPriority": "Najviši prioritet",
|
||||
"LabelHost": "Poslužitelj",
|
||||
"LabelHour": "Sat",
|
||||
|
|
@ -401,7 +402,7 @@
|
|||
"LabelIcon": "Ikona",
|
||||
"LabelImageURLFromTheWeb": "URL slike s weba",
|
||||
"LabelInProgress": "U tijeku",
|
||||
"LabelIncludeInTracklist": "Uključi u popisu zvučnih zapisa",
|
||||
"LabelIncludeInTracklist": "Uključi u popis zvučnih zapisa",
|
||||
"LabelIncomplete": "Nepotpuno",
|
||||
"LabelInterval": "Interval",
|
||||
"LabelIntervalCustomDailyWeekly": "Prilagođeno dnevno/tjedno",
|
||||
|
|
@ -435,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Br {0}",
|
||||
"LabelLibraryItem": "Stavka knjižnice",
|
||||
"LabelLibraryName": "Ime knjižnice",
|
||||
"LabelLibrarySortByProgress": "Napredak ažuriran",
|
||||
"LabelLibrarySortByProgress": "Napredak: zadnje ažurirano",
|
||||
"LabelLibrarySortByProgressFinished": "Napredak: završeno",
|
||||
"LabelLibrarySortByProgressStarted": "Napredak: započeto",
|
||||
"LabelLimit": "Ograničenje",
|
||||
"LabelLineSpacing": "Razmak između redaka",
|
||||
"LabelListenAgain": "Ponovno poslušaj",
|
||||
|
|
@ -448,8 +451,8 @@
|
|||
"LabelMatchExistingUsersBy": "Prepoznaj postojeće korisnike pomoću",
|
||||
"LabelMatchExistingUsersByDescription": "Rabi se za povezivanje postojećih korisnika. Nakon što se spoje, korisnike se prepoznaje temeljem jedinstvene oznake vašeg pružatelja SSO usluga",
|
||||
"LabelMaxEpisodesToDownload": "Najveći broj nastavaka za preuzimanje. 0 za neograničeno.",
|
||||
"LabelMaxEpisodesToDownloadPerCheck": "Najviše novih nastavaka za preuzimanje po provjeri",
|
||||
"LabelMaxEpisodesToKeep": "Najviše nastavaka za čuvanje",
|
||||
"LabelMaxEpisodesToDownloadPerCheck": "Najveći broj novih nastavaka za preuzimanje po provjeri",
|
||||
"LabelMaxEpisodesToKeep": "Najveći broj nastavaka za čuvanje",
|
||||
"LabelMaxEpisodesToKeepHelp": "Ako je vrijednost 0, nema ograničenja broja. Nakon automatskog preuzimanja novog nastavka ova funkcija briše najstariji nastavak ako ih ima više od zadanog broja. Ovo briše samo jedan nastavak po novom preuzetom nastavku.",
|
||||
"LabelMediaPlayer": "Reproduktor medijskih sadržaja",
|
||||
"LabelMediaType": "Vrsta medija",
|
||||
|
|
@ -479,7 +482,7 @@
|
|||
"LabelNoApiKeys": "Nema API ključeva",
|
||||
"LabelNoCustomMetadataProviders": "Nema prilagođenih pružatelja meta-podataka",
|
||||
"LabelNoEpisodesSelected": "Nema odabranih nastavaka",
|
||||
"LabelNotFinished": "Nije dovršeno",
|
||||
"LabelNotFinished": "Nezavršeno",
|
||||
"LabelNotStarted": "Nije započeto",
|
||||
"LabelNotes": "Bilješke",
|
||||
"LabelNotificationAppriseURL": "Apprise URL(ovi)",
|
||||
|
|
@ -494,9 +497,9 @@
|
|||
"LabelNumberOfBooks": "Broj knjiga",
|
||||
"LabelNumberOfChapters": "Broj poglavljâ:",
|
||||
"LabelNumberOfEpisodes": "broj nastavaka",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Naziv OpenID zahtjeva koji sadrži napredna dopuštenja za korisničke radnje u aplikaciji koje će se primijeniti na ne-administratorske uloge (<b>ako su konfigurirane</b>). Ako zahtjev nedostaje u odgovoru, pristup ABS-u neće se odobriti. Ako i jedna opcija nedostaje, smatrat će se da je <code>false</code>. Pripazite da zahtjev pružatelja identiteta uvijek odgovara očekivanoj strukturi:",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Ime OpenID zahtjeva koji sadrži napredna dopuštenja za korisničke radnje u aplikaciji koje će se primijeniti na ne-administratorske uloge (<b>ako su konfigurirane</b>). Ako zahtjev nedostaje u odgovoru, pristup ABS-u će se odbiti. Ako jedna opcija nedostaje, smatrat će se da je <code>false</code>. Pripazite da zahtjev pružatelja identiteta uvijek odgovara očekivanoj strukturi:",
|
||||
"LabelOpenIDClaims": "Sljedeće opcije ostavite praznima ako želite onemogućiti napredno dodjeljivanje grupa i dozvola, odnosno ako želite automatski dodijeliti grupu 'korisnik'.",
|
||||
"LabelOpenIDGroupClaimDescription": "Naziv OpenID zahtjeva koji sadrži popis korisnikovih grupa. Često se naziva <code>groups</code>. <b>Ako se konfigurira</b>, aplikacija će automatski dodijeliti uloge temeljem korisnikovih članstava u grupama, pod uvjetom da se iste zovu 'admin', 'user' ili 'guest' u zahtjevu (ne razlikuju se velika i mala slova). Zahtjev treba sadržavati popis i ako je korisnik član više grupa, aplikacija će dodijeliti ulogu koja odgovara najvišoj razini pristupa. Ukoliko se niti jedna grupa ne podudara, pristup će biti onemogućen.",
|
||||
"LabelOpenIDGroupClaimDescription": "Ime OpenID zahtjeva koji sadrži popis grupa korisnika. Često se zove <code>groups</code>. <b>Ako se konfigurira</b>, aplikacija će automatski dodijeliti uloge temeljem korisničkih članstava u grupama, pod uvjetom da se iste zovu 'admin', 'user' ili 'guest' u zahtjevu (ne razlikuju se velika i mala slova). Zahtjev treba sadržavati popis i ako je korisnik član više grupa, aplikacija će dodijeliti ulogu koja odgovara najvišoj razini pristupa. Ukoliko se niti jedna grupa ne podudara, pristup će se odbiti.",
|
||||
"LabelOpenRSSFeed": "Otvori RSS Feed",
|
||||
"LabelOverwrite": "Prepiši",
|
||||
"LabelPaginationPageXOfY": "Stranica {0} od {1}",
|
||||
|
|
@ -510,7 +513,7 @@
|
|||
"LabelPermissionsDelete": "Smije brisati",
|
||||
"LabelPermissionsDownload": "Smije preuzimati",
|
||||
"LabelPermissionsUpdate": "Smije ažurirati",
|
||||
"LabelPermissionsUpload": "Smije učitavati",
|
||||
"LabelPermissionsUpload": "Smije prenositi",
|
||||
"LabelPersonalYearReview": "Vaš godišnji pregled ({0})",
|
||||
"LabelPhotoPathURL": "Putanja ili URL fotografije",
|
||||
"LabelPlayMethod": "Način reprodukcije",
|
||||
|
|
@ -542,11 +545,11 @@
|
|||
"LabelRSSFeedSlug": "Slug RSS izvora",
|
||||
"LabelRSSFeedURL": "URL RSS izvora",
|
||||
"LabelRandomly": "Nasumično",
|
||||
"LabelReAddSeriesToContinueListening": "Ponovno dodaj serijal u Nastavi slušati",
|
||||
"LabelReAddSeriesToContinueListening": "Ponovo dodaj serijal u „Nastavi slušati”",
|
||||
"LabelRead": "Čitaj",
|
||||
"LabelReadAgain": "Ponovno čitaj",
|
||||
"LabelReadEbookWithoutProgress": "Čitaj e-knjige bez praćenja napretka",
|
||||
"LabelRecentSeries": "Najnoviji serijali",
|
||||
"LabelRecentSeries": "Nedavni serijali",
|
||||
"LabelRecentlyAdded": "Nedavno dodano",
|
||||
"LabelRecommended": "Preporučeno",
|
||||
"LabelRedo": "Ponovi",
|
||||
|
|
@ -569,7 +572,7 @@
|
|||
"LabelSelectEpisodesShowing": "Prikazujem {0} odabranih nastavaka",
|
||||
"LabelSelectUser": "Odaberite korisnika",
|
||||
"LabelSelectUsers": "Označi korisnike",
|
||||
"LabelSendEbookToDevice": "Pošalji e-knjigu …",
|
||||
"LabelSendEbookToDevice": "Pošalji e-knjigu na…",
|
||||
"LabelSequence": "Slijed",
|
||||
"LabelSerial": "Serijal",
|
||||
"LabelSeries": "Serijal",
|
||||
|
|
@ -585,36 +588,36 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeumorfni dizajn sa drvenim policama",
|
||||
"LabelSettingsChromecastSupport": "Podrška za Chromecast",
|
||||
"LabelSettingsDateFormat": "Format datuma",
|
||||
"LabelSettingsEnableWatcher": "Automatski pretražuj ima li promjena u knjižnicama",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automatski traži promjene u knjižnicama",
|
||||
"LabelSettingsEnableWatcher": "Automatski prati promjene u knjižnicama",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automatski prati promjene u knjižnici",
|
||||
"LabelSettingsEnableWatcherHelp": "Omogućuje automatsko dodavanje/ažuriranje stavki kada se uoče izmjene datoteka. *Potrebno je ponovno pokretanje poslužitelja",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Omogući skripte u epub datotekama",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Omogućuje epub datotekama izvođenje skripti. Preporučamo isključiti ovu mogućnost ukoliko nemate povjerenja u izvore epub datoteka.",
|
||||
"LabelSettingsExperimentalFeatures": "Eksperimentalne značajke",
|
||||
"LabelSettingsExperimentalFeaturesHelp": "Značajke u razvoju za koje trebamo vaše povratne informacije i pomoć u testiranju. Kliknite za otvaranje rasprave na githubu.",
|
||||
"LabelSettingsExperimentalFeatures": "Eksperimentalne funkcije",
|
||||
"LabelSettingsExperimentalFeaturesHelp": "Funkcije u razvoju za koje trebamo vaše povratne informacije i pomoć u testiranju. Kliknite za otvaranje rasprave na githubu.",
|
||||
"LabelSettingsFindCovers": "Pronađi naslovnice",
|
||||
"LabelSettingsFindCoversHelp": "Ako vaša zvučna knjiga nema ugrađenu naslovnicu ili sliku naslovnice u mapi, skener će pokušati pronaći naslovnicu.<br>Napomena: ovo će produžiti trajanje skeniranja",
|
||||
"LabelSettingsHideSingleBookSeries": "Skrij serijale sa samo jednom knjigom",
|
||||
"LabelSettingsHideSingleBookSeries": "Sakrij serijale sa samo jednom knjigom",
|
||||
"LabelSettingsHideSingleBookSeriesHelp": "Serijali koji se sastoje od samo jedne knjige neće se prikazivati na stranici serijala i na policama početne stranice.",
|
||||
"LabelSettingsHomePageBookshelfView": "Prikaži početnu stranicu kao policu s knjigama",
|
||||
"LabelSettingsLibraryBookshelfView": "Prikaži knjižnicu kao policu s knjigama",
|
||||
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Postotak dovršenosti veći od",
|
||||
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Preostalo vrijeme je manje od (sekundi)",
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Označi medij dovršenim kada",
|
||||
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Postotak završenosti je veći od",
|
||||
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Preostalo vrijeme je manje od (sekunde)",
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Označi medij kao završen kada",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Preskoči ranije knjige u funkciji Nastavi serijal",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Na polici početne stranice Nastavi serijal prikazuje se prva nezapočeta knjiga serijala koji imaju barem jednu dovršenu knjigu i nijednu započetu knjigu. Ako se ova opcija uključi serijal će nastaviti od zadnje dovršene knjige umjesto od prve nezapočete knjige.",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Na polici početne stranice Nastavi serijal prikazuje se prva nezapočeta knjiga serijala koji imaju barem jednu završenu knjigu i nijednu započetu knjigu. Ako se ova opcija uključi serijal će nastaviti od zadnje završene knjige umjesto od prve nezapočete knjige.",
|
||||
"LabelSettingsParseSubtitles": "Raščlani podnaslove",
|
||||
"LabelSettingsParseSubtitlesHelp": "Iz naziva mape zvučne knjige raščlanjuje podnaslov.<br>Podnaslov mora biti odvojen s \" - \"<br>npr. \"Naslov knjige - Ovo je podnaslov\" imat će podnaslov \"Ovo je podnaslov\"",
|
||||
"LabelSettingsParseSubtitlesHelp": "Raščlani podnaslove iz imena mape zvučne knjige.<br>Podnaslov mora biti odvojen sa \" - \"<br>npr. \"Naslov knjige - Ovo je podnaslov\" imat će podnaslov \"Ovo je podnaslov\"",
|
||||
"LabelSettingsPreferMatchedMetadata": "Daj prednost meta-podatcima prepoznatih stavki",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Podatci prepoznatog naslova nadjačat će postojeće informacije kod korištenja funkcije Brzog prepoznavanja. Zadana funkcionalnost je da Brzo prepoznavanje samo dopuni podatke koji nedostaju.",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Podatci prepoznatog naslova će nadjačati postojeće informacije pri korištenju funkcije „Brzo prepoznavanje”. Zadana funkcionalnost je da „Brzo prepoznavanje” samo doda nedostajuće podatke.",
|
||||
"LabelSettingsSkipMatchingBooksWithASIN": "Preskoči prepoznavanje knjiga koje već imaju ASIN",
|
||||
"LabelSettingsSkipMatchingBooksWithISBN": "Preskoči prepoznavanje knjiga koje već imaju ISBN",
|
||||
"LabelSettingsSortingIgnorePrefixes": "Zanemari prefikse kod sortiranja",
|
||||
"LabelSettingsSortingIgnorePrefixesHelp": "npr. za prefiks \"the\" naslov knjige \"The Book Title\" sortirat će se \"Book Title, The\"",
|
||||
"LabelSettingsSquareBookCovers": "Koristi pravokutne naslovnice knjiga",
|
||||
"LabelSettingsSquareBookCoversHelp": "Koristi pravokutne naslovnice umjesto uobičajenih naslovnica omjera 1,6:1",
|
||||
"LabelSettingsStoreCoversWithItem": "Spremi naslovnice uz stavke",
|
||||
"LabelSettingsStoreCoversWithItemHelp": "Naslovnice se obično spremaju u /metadata/items, ako uključite ovu opciju naslovnice će se spremati u mapu knjižničke stavke. Čuva se samo jedna datoteka naziva \"cover\"",
|
||||
"LabelSettingsStoreCoversWithItem": "Spremi naslovnice sa stavkom",
|
||||
"LabelSettingsStoreCoversWithItemHelp": "Naslovnice se obično spremaju u /metadata/items. Uključivanjem ove opcije naslovnice će se spremati u mapu stavki vaše knjižnice. Čuva se samo jedna datoteka s imenom \"cover\"",
|
||||
"LabelSettingsStoreMetadataWithItem": "Spremi metapodatke uz stavku",
|
||||
"LabelSettingsStoreMetadataWithItemHelp": "Meta-podatci se obično spremaju u /metadata/items; ako uključite ovu postavku meta-podatci će se čuvati u mapama knjižničkih stavki",
|
||||
"LabelSettingsTimeFormat": "Format vremena",
|
||||
|
|
@ -635,6 +638,7 @@
|
|||
"LabelStartTime": "Vrijeme početka",
|
||||
"LabelStarted": "Započeto",
|
||||
"LabelStartedAt": "Započeto",
|
||||
"LabelStartedDate": "Započeto {0}",
|
||||
"LabelStatsAudioTracks": "Zvučni zapisi",
|
||||
"LabelStatsAuthors": "Autori",
|
||||
"LabelStatsBestDay": "Najbolji dan",
|
||||
|
|
@ -643,7 +647,7 @@
|
|||
"LabelStatsDaysListened": "Dana slušano",
|
||||
"LabelStatsHours": "Sati",
|
||||
"LabelStatsInARow": "uzastopno",
|
||||
"LabelStatsItemsFinished": "Dovršenih stavki",
|
||||
"LabelStatsItemsFinished": "Završene stavke",
|
||||
"LabelStatsItemsInLibrary": "Stavke u knjižnici",
|
||||
"LabelStatsMinutes": "minute",
|
||||
"LabelStatsMinutesListening": "Minuta odslušano",
|
||||
|
|
@ -702,12 +706,12 @@
|
|||
"LabelUpdateDetails": "Ažuriraj pojedinosti",
|
||||
"LabelUpdateDetailsHelp": "Dopusti prepisivanje postojećih podataka za odabrane knjige kada se prepoznaju",
|
||||
"LabelUpdatedAt": "Ažurirano",
|
||||
"LabelUploaderDragAndDrop": "Pritisni i prevuci datoteke ili mape",
|
||||
"LabelUploaderDragAndDropFilesOnly": "Pritisni i prevuci datoteke",
|
||||
"LabelUploaderDragAndDrop": "Povuci i ispusti datoteke ili mape",
|
||||
"LabelUploaderDragAndDropFilesOnly": "Povuci i ispusti datoteke",
|
||||
"LabelUploaderDropFiles": "Ispusti datoteke",
|
||||
"LabelUploaderItemFetchMetadataHelp": "Automatski dohvati naslov, autora i serijal",
|
||||
"LabelUseAdvancedOptions": "Koristi se naprednim opcijama",
|
||||
"LabelUseChapterTrack": "Upravljaj trakom poglavlja",
|
||||
"LabelUseAdvancedOptions": "Koristi napredne opcije",
|
||||
"LabelUseChapterTrack": "Koristi zvučni zapis poglavlja",
|
||||
"LabelUseFullTrack": "Koristi cijeli zvučni zapis",
|
||||
"LabelUseZeroForUnlimited": "0 za neograničeno",
|
||||
"LabelUser": "Korisnik",
|
||||
|
|
@ -731,12 +735,12 @@
|
|||
"LabelYourPlaylists": "Vaši popisi za izvođenje",
|
||||
"LabelYourProgress": "Vaš napredak",
|
||||
"MessageAddToPlayerQueue": "Dodaj u redoslijed izvođenja",
|
||||
"MessageAppriseDescription": "Da biste se koristili ovom značajkom, treba vam instanca <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API-ja</a> ili API koji može rukovati istom vrstom zahtjeva.<br />The Adresa Apprise API-ja treba biti puna URL putanja za slanje obavijesti, npr. ako vam se API instanca poslužuje na adresi <code>http://192.168.1.1:8337</code> trebate upisati <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAppriseDescription": "Za korištnje ove funkcije, treba vam instanca <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API-ja</a> ili API koji može rukovati istom vrstom zahtjeva.<br />URL Apprise API-ja mora biti potpuna URL putanja za slanje obavijesti, npr. ako vam se API instanca poslužuje na adresi <code>http://192.168.1.1:8337</code> morate upisati <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Upišite ASIN iz odgovarajuće Audibleove regije, ne s Amazonov.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Starije API tokene ćemo ukloniti. Umjesto njih, koristite se <a href=\"/config/api-keys\">API ključevima</a> .",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Ponovno pokrenite poslužitelj da biste primijenili OIDC promjene.",
|
||||
"MessageAuthenticationSecurityMessage": "Provjera autentičnosti poboljšana je radi sigurnosti. Svi se korisnici moraju ponovno prijaviti.",
|
||||
"MessageBackupsDescription": "Sigurnosne kopije sadrže korisnike, korisnikov napredak medija, pojedinosti knjižničke građe, postavke poslužitelja i slike koje se spremaju u <code>/metadata/items</code> & <code>/metadata/authors</code>. Sigurnosne kopije ne sadrže niti jednu datoteku iz mapa knjižnice.",
|
||||
"MessageBackupsDescription": "Sigurnosne kopije sadrže korisnike, napredak korisnika, pojedinosti knjižničke građe, postavke poslužitelja i slike koje se spremaju u <code>/metadata/items</code> i <code>/metadata/authors</code>. Sigurnosne kopije ne sadrže niti jednu datoteku iz mapa knjižnice.",
|
||||
"MessageBackupsLocationEditNote": "Napomena: Uređivanje lokacije za sigurnosne kopije ne premješta ili mijenja postojeće sigurnosne kopije",
|
||||
"MessageBackupsLocationNoEditNote": "Napomena: Lokacija za sigurnosne kopije zadana je kroz varijablu okoline i ovdje se ne može izmijeniti.",
|
||||
"MessageBackupsLocationPathEmpty": "Putanja do lokacije za sigurnosne kopije ne može ostati prazna",
|
||||
|
|
@ -756,7 +760,7 @@
|
|||
"MessageChapterErrorStartLtPrev": "Netočno vrijeme početka, mora biti veće ili jednako vremenu početka prethodnog poglavlja",
|
||||
"MessageChapterStartIsAfter": "Početak poglavlja je nakon kraja zvučne knjige",
|
||||
"MessageChaptersNotFound": "Poglavlja nisu pronađena",
|
||||
"MessageCheckingCron": "Provjeravam cron...",
|
||||
"MessageCheckingCron": "Provjeravanje cron izraza...",
|
||||
"MessageConfirmCloseFeed": "Sigurno želite zatvoriti ovaj izvor?",
|
||||
"MessageConfirmDeleteApiKey": "Sigurno želite izbrisati API ključ \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Sigurno želite izbrisati sigurnosnu kopiju za {0}?",
|
||||
|
|
@ -770,12 +774,12 @@
|
|||
"MessageConfirmDeleteSession": "Sigurno želite izbrisati ovu sesiju?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Sigurno želite ugraditi meta-podatke u {0} zvučnih datoteka?",
|
||||
"MessageConfirmForceReScan": "Sigurno želite ponovno pokrenuti skeniranje?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Sigurno želite označiti sve nastavke dovršenima?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Sigurno želite označiti sve nastavke nedovršenima?",
|
||||
"MessageConfirmMarkItemFinished": "Sigurno želite označiti \"{0}\" dovršenim?",
|
||||
"MessageConfirmMarkItemNotFinished": "Sigurno želite označiti \"{0}\" nedovršenim?",
|
||||
"MessageConfirmMarkSeriesFinished": "Sigurno želite označiti sve knjige u ovom serijalu dovršenima?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Sigurno želite označiti sve knjige u ovom serijalu nedovršenima?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Sigurno želite označiti sve nastavke kao završene?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Sigurno želite označiti sve nastavke kao nezavršene?",
|
||||
"MessageConfirmMarkItemFinished": "Sigurno želite označiti stavku \"{0}\" kao završenu?",
|
||||
"MessageConfirmMarkItemNotFinished": "Sigurno želite označiti stavku \"{0}\" kao nezavršenu?",
|
||||
"MessageConfirmMarkSeriesFinished": "Sigurno želite označiti sve knjige u ovom serijalu kao završene?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Sigurno želite označiti sve knjige u ovom serijalu kao nezavršene?",
|
||||
"MessageConfirmNotificationTestTrigger": "Želite li okinuti ovu obavijest s probnim podatcima?",
|
||||
"MessageConfirmPurgeCache": "Brisanje predmemorije izbrisat će cijelu mapu <code>/metadata/cache</code>. <br /><br />Sigurno želite izbrisati mapu predmemorije?",
|
||||
"MessageConfirmPurgeItemsCache": "Brisanje predmemorije stavki izbrisat će cijelu mapu <code>/metadata/cache/items</code>.<br />Jeste li sigurni?",
|
||||
|
|
@ -803,14 +807,14 @@
|
|||
"MessageConfirmUnlinkOpenId": "Sigurno želite odspojiti ovog korisnika s OpenID-ja?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} dana slušanja u posljednjih godinu dana",
|
||||
"MessageDownloadingEpisode": "Preuzimam nastavak",
|
||||
"MessageDragFilesIntoTrackOrder": "Prevlačenjem datoteka složite pravilan redoslijed",
|
||||
"MessageDragFilesIntoTrackOrder": "Povlači datoteke u ispravan redoslijed",
|
||||
"MessageEmbedFailed": "Ugrađivanje nije uspjelo!",
|
||||
"MessageEmbedFinished": "Ugrađivanje je dovršeno!",
|
||||
"MessageEmbedFinished": "Ugrađivanje je završeno!",
|
||||
"MessageEmbedQueue": "Ugrađivanje meta-podataka dodano u red obrade ({0} u redu)",
|
||||
"MessageEpisodesQueuedForDownload": "{0} nastavak(a) u redu za preuzimanje",
|
||||
"MessageEreaderDevices": "Da biste osigurali isporuku e-knjiga, možda ćete morati gornju adresu e-pošte dodati kao dopuštenog pošiljatelja za svaki od donjih uređaja.",
|
||||
"MessageFeedURLWillBe": "URL izvora bit će {0}",
|
||||
"MessageFetching": "Dohvaćam...",
|
||||
"MessageFetching": "Dohvaćanje...",
|
||||
"MessageForceReScanDescription": "će ponovno skenirati sve datoteke kao nove datoteke. ID3 tagovi zvučnih datoteka, OPF datoteke i tekstualne datoteke skenirat će se kao da su nove.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} sluša</strong> na {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Nema sesija slušanja na {0}",
|
||||
|
|
@ -820,27 +824,27 @@
|
|||
"MessageItemsSelected": "{0} odabranih stavki",
|
||||
"MessageItemsUpdated": "{0} stavki ažurirano",
|
||||
"MessageJoinUsOn": "Pridruži nam se na",
|
||||
"MessageLoading": "Učitavam...",
|
||||
"MessageLoadingFolders": "Učitavam mape...",
|
||||
"MessageLoading": "Učitavanje...",
|
||||
"MessageLoadingFolders": "Učitavanje mape...",
|
||||
"MessageLogsDescription": "Zapisnici se čuvaju u <code>/metadata/logs</code> u obliku JSON datoteka. Zapisnici pada sustava čuvaju se u datoteci <code>/metadata/logs/crash_logs.txt</code>.",
|
||||
"MessageM4BFailed": "M4B neuspješan!",
|
||||
"MessageM4BFinished": "M4B završio!",
|
||||
"MessageMapChapterTitles": "Mapiraj nazive poglavlja postojećim poglavljima zvučne knjige bez uređivanja vremenskih identifikatora",
|
||||
"MessageMarkAllEpisodesFinished": "Označi sve nastavke dovršenima",
|
||||
"MessageMarkAllEpisodesNotFinished": "Označi sve nastavke nedovršenima",
|
||||
"MessageMarkAsFinished": "Označi kao dovršeno",
|
||||
"MessageMarkAsNotFinished": "Označi kao nedovršeno",
|
||||
"MessageMatchBooksDescription": "će pokušati prepoznati knjige iz knjižnice u katalogu odabranog pružatelja podatka te nadopuniti podatke koji nedostaju i naslovnice. Ne prepisuje preko postojećih podataka.",
|
||||
"MessageM4BFailed": "M4B datoteka neuspjela!",
|
||||
"MessageM4BFinished": "M4B datoteka je završena!",
|
||||
"MessageMapChapterTitles": "Mapiraj imana poglavlja s vašim postojećim poglavljima zvučne knjige bez podešavanja vremenskih identifikatora",
|
||||
"MessageMarkAllEpisodesFinished": "Označi sve nastavke kao završene",
|
||||
"MessageMarkAllEpisodesNotFinished": "Označi sve nastavke kao nezavršene",
|
||||
"MessageMarkAsFinished": "Označi kao završeno",
|
||||
"MessageMarkAsNotFinished": "Označi kao nezavršeno",
|
||||
"MessageMatchBooksDescription": "će pokušati prepoznati knjige iz knjižnice u katalogu odabranog pružatelja podatka te nadopuniti podatke koji nedostaju i naslovnice. Ne prepisuje postojeće podatke.",
|
||||
"MessageNoAudioTracks": "Nema zvučnih zapisa",
|
||||
"MessageNoAuthors": "Nema autora",
|
||||
"MessageNoBackups": "Nema sigurnosnih kopija",
|
||||
"MessageNoBookmarks": "Nema knjižnih oznaka",
|
||||
"MessageNoChapters": "Nema poglavlja",
|
||||
"MessageNoCollections": "Nema zbirki",
|
||||
"MessageNoCoversFound": "Naslovnice nisu pronađene",
|
||||
"MessageNoCoversFound": "Nije pronađena nijedna naslovnica",
|
||||
"MessageNoDescription": "Nema opisa",
|
||||
"MessageNoDevices": "Nema uređaja",
|
||||
"MessageNoDownloadsInProgress": "Nema preuzimanja u tijeku",
|
||||
"MessageNoDownloadsInProgress": "Trenutačno nema preuzimanja u tijeku",
|
||||
"MessageNoDownloadsQueued": "Nema preuzimanja u redu",
|
||||
"MessageNoEpisodeMatchesFound": "Nije pronađen ni jedan odgovarajući nastavak",
|
||||
"MessageNoEpisodes": "Nema nastavaka",
|
||||
|
|
@ -869,28 +873,28 @@
|
|||
"MessagePauseChapter": "Pauziraj reprodukciju poglavlja",
|
||||
"MessagePlayChapter": "Slušaj početak poglavlja",
|
||||
"MessagePlaylistCreateFromCollection": "Stvori popis za izvođenje od zbirke",
|
||||
"MessagePleaseWait": "Molimo pričekajte...",
|
||||
"MessagePleaseWait": "Pričekajte...",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "Podcast nema adresu RSS izvora za prepoznavanje",
|
||||
"MessagePodcastSearchField": "Upišite izraz za pretraživanje ili URL RSS izvora",
|
||||
"MessageQuickEmbedInProgress": "Brzo ugrađivanje u tijeku",
|
||||
"MessageQuickEmbedQueue": "Dodano u red za brzo ugrađivanje ({0} u redu izvođenja)",
|
||||
"MessageQuickMatchAllEpisodes": "Brzo prepoznavanje svih nastavaka",
|
||||
"MessageQuickMatchDescription": "Popuni pojedinosti i naslovnice koji nedostaju prvim pronađenim rezultatom za '{0}'. Ne prepisuje podatke osim ako ne uključite mogućnost 'Daj prednost meta-podatcima prepoznatih stavki'.",
|
||||
"MessageQuickMatchDescription": "Popuni pojedinosti i naslovnice koji nedostaju prvim pronađenim rezultatom za '{0}'. Ne prepisuje podatke osim ako je postavka poslužitelja „Daj prednost meta-podatcima prepoznatih stavki” uključena.",
|
||||
"MessageRemoveChapter": "Ukloni poglavlje",
|
||||
"MessageRemoveEpisodes": "Ukloni {0} nastavaka",
|
||||
"MessageRemoveFromPlayerQueue": "Ukloni iz redoslijeda izvođenja",
|
||||
"MessageRemoveUserWarning": "Sigurno želite trajno izbrisati korisnika \"{0}\"?",
|
||||
"MessageReportBugsAndContribute": "Prijavite pogreške, zatražite funkcionalnosti i doprinesite na",
|
||||
"MessageReportBugsAndContribute": "Prijavite pogreške, zatražite funkcije i doprinesite na",
|
||||
"MessageResetChaptersConfirm": "Sigurno želite vratiti poglavlja na prethodno stanje i poništiti učinjene promjene?",
|
||||
"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.",
|
||||
"MessageScheduleLibraryScanNote": "Za većinu korisnika se preporučuje ostaviti ovu funkciju deaktiviranom i ostaviti postavku promatrača mape aktiviranom. Promatrač mapa će automatski otkriti promjene u mapama vaše knjižnice. Promatrač mapa ne radi na svakom datotečnom sustavu (kao što je NFS) pa se umjesto njega mogu koristiti planirana pretraživanja knjižnice.",
|
||||
"MessageScheduleLibraryScanNote": "Za većinu korisnika se preporučuje ostaviti ovu funkciju deaktiviranom kao i fukciju „Automatski prati promjene u knjižnici” koja automatski otkriva promjene u mapama vaše knjižnice. Fukcija „Automatski prati promjene u knjižnici” ne radi na svakom datotečnom sustavu (kao što je NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Pokreni svaki {0} u {1}",
|
||||
"MessageSearchResultsFor": "Rezultati pretrage za",
|
||||
"MessageSelected": "{0} odabrano",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Slijed serijala ne može sadržavati praznine",
|
||||
"MessageServerCouldNotBeReached": "Nije moguće pristupiti poslužitelju",
|
||||
"MessageSetChaptersFromTracksDescription": "Postavi poglavlja koristeći se zvučnom datotekom kao poglavljem i nazivom datoteke kao naslovom poglavlja",
|
||||
"MessageServerCouldNotBeReached": "Nije bilo moguće pristupiti poslužitelju",
|
||||
"MessageSetChaptersFromTracksDescription": "Postavi poglavlja koristeći svaku zvučnu datoteku kao poglavlje, a naslov poglavlja kao ime datoteke",
|
||||
"MessageShareExpirationWillBe": "Vrijeme isteka će biti <strong>{0}</strong>",
|
||||
"MessageShareExpiresIn": "Istječe za {0}",
|
||||
"MessageShareURLWillBe": "URL za dijeljenje bit će <strong>{0}</strong>",
|
||||
|
|
@ -919,7 +923,7 @@
|
|||
"MessageTaskOpmlImportFeedPodcastDescription": "Stvaranje podcasta \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "Podcast već postoji u putanji",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Stvaranje podcasta nije uspjelo",
|
||||
"MessageTaskOpmlImportFinished": "Dodano {0} podcasta",
|
||||
"MessageTaskOpmlImportFinished": "Broj dodanih podcasta: {0}",
|
||||
"MessageTaskOpmlParseFailed": "Raščlanjivanje OPML datoteke nije uspjelo",
|
||||
"MessageTaskOpmlParseFastFail": "Neispravna OPML datoteka, oznaka <opml> nije pronađena ILI oznaka <outline> nije pronađena",
|
||||
"MessageTaskOpmlParseNoneFound": "U OPML datoteci nisu pronađeni izvori",
|
||||
|
|
@ -930,10 +934,10 @@
|
|||
"MessageTaskScanningFileChanges": "Skeniranje izmijenjenih datoteka u \"{0}\"",
|
||||
"MessageTaskScanningLibrary": "Skeniranje knjižnice \"{0}\"",
|
||||
"MessageTaskTargetDirectoryNotWritable": "U odredišnu mapu nije moguće pisati",
|
||||
"MessageThinking": "Razmišljam...",
|
||||
"MessageUploaderItemFailed": "Učitavanje nije uspjelo",
|
||||
"MessageUploaderItemSuccess": "Uspješno učitano!",
|
||||
"MessageUploading": "Učitavam...",
|
||||
"MessageThinking": "Razmišljanje...",
|
||||
"MessageUploaderItemFailed": "Prijenos nije uspio",
|
||||
"MessageUploaderItemSuccess": "Uspješno preneseno!",
|
||||
"MessageUploading": "Prijenos...",
|
||||
"MessageValidCronExpression": "Ispravan cron izraz",
|
||||
"MessageWatcherIsDisabledGlobally": "Praćenje datotečnog sustava globalno je isključen u postavkama poslužitelja",
|
||||
"MessageXLibraryIsEmpty": "{0} Knjižnica je prazna!",
|
||||
|
|
@ -945,8 +949,8 @@
|
|||
"NoteRSSFeedPodcastAppsHttps": "Pripazite: Većina aplikacija za podcaste iziskuje URL RSS izvora koji se koristi HTTPS protokolom",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Upozorenje: jedan ili više vaših nastavaka nemaju datum objavljivanja. To je obavezno kod nekih aplikacija za podcaste.",
|
||||
"NoteUploaderFoldersWithMediaFiles": "Mape s medijskim datotekama smatrat će se zasebnim stavkama knjižnice.",
|
||||
"NoteUploaderOnlyAudioFiles": "Ako učitavate samo zvučne datoteke svaka će se zvučna datoteka uvesti kao zasebna zvučna knjiga.",
|
||||
"NoteUploaderUnsupportedFiles": "Nepodržane vrste datoteka zanemaruju se. Kada odabirete datoteke ili ispuštate mapu, sve datoteke koje nisu u mapi stavke zanemarit će se.",
|
||||
"NoteUploaderOnlyAudioFiles": "Ako prenosite samo zvučne datoteke svaka će se zvučna datoteka uvesti kao zasebna zvučna knjiga.",
|
||||
"NoteUploaderUnsupportedFiles": "Nepodržane vrste datoteka se zanemaruju. Kada birate datoteke ili ispuštate mapu, sve datoteke koje nisu u mapi stavke će se zanemariti.",
|
||||
"NotificationOnBackupCompletedDescription": "Pokreće se po završetku sigurnosnog kopiranja",
|
||||
"NotificationOnBackupFailedDescription": "Pokreće se kada sigurnosno kopiranje ne uspije",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Pokreće se kada se nastavak podcasta automatski preuzme",
|
||||
|
|
@ -956,14 +960,14 @@
|
|||
"PlaceholderBulkChapterInput": "Upišite naslov poglavlja ili ga numerirajte (npr. '1. nastavak', 'Poglavlje 10', '1.')",
|
||||
"PlaceholderNewCollection": "Ime nove zbirke",
|
||||
"PlaceholderNewFolderPath": "Nova putanja mape",
|
||||
"PlaceholderNewPlaylist": "Naziv novog popisa za izvođenje",
|
||||
"PlaceholderNewPlaylist": "Ime novog popisa za izvođenje",
|
||||
"PlaceholderSearch": "Traži...",
|
||||
"PlaceholderSearchEpisode": "Traži nastavak...",
|
||||
"StatsAuthorsAdded": "autora dodano",
|
||||
"StatsBooksAdded": "knjiga dodano",
|
||||
"StatsBooksAdditional": "Novi naslovi uključuju…",
|
||||
"StatsBooksFinished": "knjiga dovršeno",
|
||||
"StatsBooksFinishedThisYear": "Neke knjige dovršene ove godine…",
|
||||
"StatsBooksFinished": "završene knjige",
|
||||
"StatsBooksFinishedThisYear": "Neke završene knjige ove godine…",
|
||||
"StatsBooksListenedTo": "knjiga slušano",
|
||||
"StatsCollectionGrewTo": "Vaša je zbirka knjiga narasla na…",
|
||||
"StatsSessions": "sesija",
|
||||
|
|
@ -995,8 +999,8 @@
|
|||
"ToastBackupInvalidMaxKeep": "Neispravan broj sigurnosnih kopija za čuvanje",
|
||||
"ToastBackupInvalidMaxSize": "Neispravna najveća veličina sigurnosne kopije",
|
||||
"ToastBackupRestoreFailed": "Vraćanje sigurnosne kopije nije uspjelo",
|
||||
"ToastBackupUploadFailed": "Učitavanje sigurnosne kopije nije uspjelo",
|
||||
"ToastBackupUploadSuccess": "Sigurnosna kopija učitana",
|
||||
"ToastBackupUploadFailed": "Prijenos sigurnosne kopije nije uspio",
|
||||
"ToastBackupUploadSuccess": "Sigurnosna kopija je prenesea",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Pojedinosti primijenjene stavkama",
|
||||
"ToastBatchDeleteFailed": "Grupno brisanje nije uspjelo",
|
||||
"ToastBatchDeleteSuccess": "Grupno brisanje je uspjelo",
|
||||
|
|
@ -1019,21 +1023,23 @@
|
|||
"ToastChaptersMustHaveTitles": "Poglavlja moraju imati naslove",
|
||||
"ToastChaptersRemoved": "Poglavlja uklonjena",
|
||||
"ToastChaptersUpdated": "Poglavlja su ažurirana",
|
||||
"ToastCollectionItemsAddFailed": "Neuspješno dodavanje stavki u zbirku",
|
||||
"ToastCollectionItemsAddFailed": "Neuspjelo dodavanje stavki u zbirku",
|
||||
"ToastCollectionRemoveSuccess": "Zbirka izbrisana",
|
||||
"ToastCollectionUpdateSuccess": "Zbirka ažurirana",
|
||||
"ToastConnectionNotAvailable": "Veza nije dostupna. Pokušaj ponovo kasnije",
|
||||
"ToastCoverSearchFailed": "Pretraga naslovnice neuspjela",
|
||||
"ToastCoverUpdateFailed": "Ažuriranje naslovnice nije uspjelo",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Datum i vrijeme su neispravni ili nepotpuni",
|
||||
"ToastDeleteFileFailed": "Brisanje datoteke nije uspjelo",
|
||||
"ToastDeleteFileSuccess": "Datoteka izbrisana",
|
||||
"ToastDeviceAddFailed": "Dodavanje uređaja nije uspjelo",
|
||||
"ToastDeviceNameAlreadyExists": "E-čitač s tim nazivom već postoji",
|
||||
"ToastDeviceNameAlreadyExists": "E-čitač s tim imenom već postoji",
|
||||
"ToastDeviceTestEmailFailed": "Slanje probne poruke e-pošte nije uspjelo",
|
||||
"ToastDeviceTestEmailSuccess": "Probna poruka e-pošte poslana",
|
||||
"ToastEmailSettingsUpdateSuccess": "Postavke e-pošte ažurirane",
|
||||
"ToastEncodeCancelFailed": "Kodiranje nije uspješno otkazano",
|
||||
"ToastEncodeCancelFailed": "Prekidanje kodiranja nije uspjelo",
|
||||
"ToastEncodeCancelSucces": "Kodiranje otkazano",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Redoslijed izvođenja nije uspješno očišćen",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Brisanje redoslijeda izvođenja nije uspjelo",
|
||||
"ToastEpisodeDownloadQueueClearSuccess": "Redoslijed preuzimanja nastavaka očišćen",
|
||||
"ToastEpisodeUpdateSuccess": "{0} nastavak/a ažurirano",
|
||||
"ToastErrorCannotShare": "Dijeljenje na ovaj uređaj nije moguće",
|
||||
|
|
@ -1051,10 +1057,10 @@
|
|||
"ToastItemDeletedFailed": "Brisanje stavke nije uspjelo",
|
||||
"ToastItemDeletedSuccess": "Stavka je izbrisana",
|
||||
"ToastItemDetailsUpdateSuccess": "Pojedinosti stavke su ažurirane",
|
||||
"ToastItemMarkedAsFinishedFailed": "Označavanje kao Dovršeno nije uspjelo",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Stavka označena kao dovršena",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "Označavanje kao Nije dovršeno nije uspjelo",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Stavka označena kao nedovršena",
|
||||
"ToastItemMarkedAsFinishedFailed": "Označavanje kao „Završeno” nije uspjelo",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Stavka je označena kao završena",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "Označavanje kao „Nezavršeno” nije uspjelo",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Stavka je označena kao nezavršena",
|
||||
"ToastItemUpdateSuccess": "Stavka ažurirana",
|
||||
"ToastLibraryCreateFailed": "Stvaranje knjižnice nije uspjelo",
|
||||
"ToastLibraryCreateSuccess": "Knjižnica \"{0}\" stvorena",
|
||||
|
|
@ -1063,17 +1069,17 @@
|
|||
"ToastLibraryScanFailedToStart": "Skeniranje nije uspjelo",
|
||||
"ToastLibraryScanStarted": "Skeniranje knjižnice započelo",
|
||||
"ToastLibraryUpdateSuccess": "Knjižnica \"{0}\" ažurirana",
|
||||
"ToastMatchAllAuthorsFailed": "Nisu prepoznati svi autori",
|
||||
"ToastMatchAllAuthorsFailed": "Prepoznavanje svih autora nije uspjelo",
|
||||
"ToastMetadataFilesRemovedError": "Pogreška kod uklanjanja datoteka metadata.{0}",
|
||||
"ToastMetadataFilesRemovedNoneFound": "U knjižnici nisu pronađene datoteke metadata.{0}",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "Datoteke metadata.{0} nisu uklonjenje",
|
||||
"ToastMetadataFilesRemovedSuccess": "uklonjeno {0} datoteka metadata.{1}",
|
||||
"ToastMustHaveAtLeastOnePath": "Mora postojati barem jedna putanja",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "Nijedna datoteka metadata.{0} nije uklonjenja",
|
||||
"ToastMetadataFilesRemovedSuccess": "Broj uklonjenih datoteka metadata.{1}: {0}",
|
||||
"ToastMustHaveAtLeastOnePath": "Mora imati barem jednu putanju",
|
||||
"ToastNameEmailRequired": "Ime i adresa e-pošte su obavezni",
|
||||
"ToastNameRequired": "Ime je obavezno",
|
||||
"ToastNewApiKeyUserError": "Morate odabrati korisnika",
|
||||
"ToastNewEpisodesFound": "pronađeno {0} novih nastavaka",
|
||||
"ToastNewUserCreatedFailed": "Račun \"{0}\" nije uspješno izrađen",
|
||||
"ToastNewUserCreatedFailed": "Stvaranje računa nije uspjelo: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Novi račun izrađen",
|
||||
"ToastNewUserLibraryError": "Treba odabrati barem jednu knjižnicu",
|
||||
"ToastNewUserPasswordError": "Mora imati zaporku, samo korisnik root može imati praznu zaporku",
|
||||
|
|
@ -1084,19 +1090,20 @@
|
|||
"ToastNoUpdatesNecessary": "Ažuriranja nisu potrebna",
|
||||
"ToastNotificationCreateFailed": "Stvaranje obavijesti nije uspjelo",
|
||||
"ToastNotificationDeleteFailed": "Brisanje obavijesti nije uspjelo",
|
||||
"ToastNotificationFailedMaximum": "Najveći broj neuspješnih pokušaja mora biti >= 0",
|
||||
"ToastNotificationFailedMaximum": "Najveći broj neuspjelih pokušaja mora biti >= 0",
|
||||
"ToastNotificationQueueMaximum": "Najveći broj obavijesti u redu mora biti >= 0",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Postavke obavijesti ažurirane",
|
||||
"ToastNotificationTestTriggerFailed": "Okidanje probne obavijesti nije uspjelo",
|
||||
"ToastNotificationTestTriggerSuccess": "Okinuta je probna obavijest",
|
||||
"ToastNotificationUpdateSuccess": "Obavijest ažurirana",
|
||||
"ToastPlaylistCreateFailed": "Popis za izvođenje nije izrađen",
|
||||
"ToastPlaylistCreateFailed": "Izrada popisa za izvođenje nije uspjela",
|
||||
"ToastPlaylistCreateSuccess": "Popis za izvođenje izrađen",
|
||||
"ToastPlaylistRemoveSuccess": "Popis za izvođenje uklonjen",
|
||||
"ToastPlaylistUpdateSuccess": "Popis za izvođenje ažuriran",
|
||||
"ToastPodcastCreateFailed": "Podcast nije izrađen",
|
||||
"ToastPodcastCreateFailed": "Stvaranje podcasta nije uspjelo",
|
||||
"ToastPodcastCreateSuccess": "Podcast uspješno izrađen",
|
||||
"ToastPodcastGetFeedFailed": "Dohvat izvora podcasta nije uspio",
|
||||
"ToastPodcastEpisodeUpdated": "Nastavak ažuriran",
|
||||
"ToastPodcastGetFeedFailed": "Dohvaćanje izvora podcasta nije uspjelo",
|
||||
"ToastPodcastNoEpisodesInFeed": "U RSS izvoru nisu pronađeni nastavci",
|
||||
"ToastPodcastNoRssFeed": "Podcast nema RSS izvor",
|
||||
"ToastProgressIsNotBeingSynced": "Napredak se ne sinkronizira, ponovno pokrenite reprodukciju",
|
||||
|
|
@ -1104,7 +1111,7 @@
|
|||
"ToastProviderCreatedSuccess": "Novi pružatelj dodan",
|
||||
"ToastProviderNameAndUrlRequired": "Ime i URL su obavezni",
|
||||
"ToastProviderRemoveSuccess": "Pružatelj uklonjen",
|
||||
"ToastRSSFeedCloseFailed": "RSS izvor nije uspješno zatvoren",
|
||||
"ToastRSSFeedCloseFailed": "Zatvaranje RSS izvora nije uspjelo",
|
||||
"ToastRSSFeedCloseSuccess": "RSS izvor zatvoren",
|
||||
"ToastRemoveFailed": "Uklanjanje nije uspjelo",
|
||||
"ToastRemoveItemFromCollectionFailed": "Uklanjanje stavke iz zbirke nije uspjelo",
|
||||
|
|
@ -1112,7 +1119,7 @@
|
|||
"ToastRemoveItemsWithIssuesFailed": "Uklanjanje knjižničkih stavki s problemima nije uspjelo",
|
||||
"ToastRemoveItemsWithIssuesSuccess": "Uspješno uklonjene knjižničke stavke s problemima",
|
||||
"ToastRenameFailed": "Preimenovanje nije uspjelo",
|
||||
"ToastRescanFailed": "Ponovno skeniranje {0} nije uspjelo",
|
||||
"ToastRescanFailed": "Ponovno skeniranje nije uspjelo za {0}",
|
||||
"ToastRescanRemoved": "Ponovno skeniranje dovršene stavke je uklonjeno",
|
||||
"ToastRescanUpToDate": "Ponovno skeniranje dovršene stavke bilo je ažurno",
|
||||
"ToastRescanUpdated": "Ponovno skeniranje dovršene stavke je ažurirano",
|
||||
|
|
@ -1127,7 +1134,7 @@
|
|||
"ToastSessionCloseFailed": "Zatvaranje sesije nije uspjelo",
|
||||
"ToastSessionDeleteFailed": "Brisanje sesije nije uspjelo",
|
||||
"ToastSessionDeleteSuccess": "Sesija izbrisana",
|
||||
"ToastSleepTimerDone": "Timer za spavanje istječe... zZzzZz",
|
||||
"ToastSleepTimerDone": "Timer za spavanje gotov... zZzzZz",
|
||||
"ToastSlugMustChange": "Slug sadrži nedozvoljene znakove",
|
||||
"ToastSlugRequired": "Slug je obavezan",
|
||||
"ToastSocketConnected": "Socket priključen",
|
||||
|
|
@ -1139,8 +1146,8 @@
|
|||
"ToastUnknownError": "Nepoznata pogreška",
|
||||
"ToastUnlinkOpenIdFailed": "Uklanjanje OpenID veze korisnika nije uspjelo",
|
||||
"ToastUnlinkOpenIdSuccess": "Korisnik odspojen od OpenID-ja",
|
||||
"ToastUploaderFilepathExistsError": "Putanja \"{0}\" već postoji na poslužitelju",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Stavka \"{0}\" koristi se podmapom u putanje za učitavanje.",
|
||||
"ToastUploaderFilepathExistsError": "Datotečna putanja \"{0}\" već postoji na poslužitelju",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Stavka \"{0}\" koristi podmapu putanje za prijenos.",
|
||||
"ToastUserDeleteFailed": "Brisanje korisnika nije uspjelo",
|
||||
"ToastUserDeleteSuccess": "Korisnik izbrisan",
|
||||
"ToastUserPasswordChangeSuccess": "Zaporka je uspješno promijenjena",
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@
|
|||
"LabelClickToUseCurrentValue": "Kattintson az aktuális érték használatához",
|
||||
"LabelClosePlayer": "Lejátszó bezárása",
|
||||
"LabelCodec": "Kodek",
|
||||
"LabelCollapseSeries": "Sorozat összecsukása",
|
||||
"LabelCollapseSeries": "Sorozatok összecsukása",
|
||||
"LabelCollapseSubSeries": "Alszéria összecsukása",
|
||||
"LabelCollection": "Gyűjtemény",
|
||||
"LabelCollections": "Gyűjtemények",
|
||||
|
|
@ -378,11 +378,12 @@
|
|||
"LabelFilterByUser": "Szűrés felhasználó szerint",
|
||||
"LabelFindEpisodes": "Epizódok keresése",
|
||||
"LabelFinished": "Befejezett",
|
||||
"LabelFinishedDate": "Befejezve {0}",
|
||||
"LabelFolder": "Mappa",
|
||||
"LabelFolders": "Mappák",
|
||||
"LabelFontBold": "Félkövér",
|
||||
"LabelFontBoldness": "Betű vastagság",
|
||||
"LabelFontFamily": "Betűtípus család",
|
||||
"LabelFontFamily": "Betűcsalád",
|
||||
"LabelFontItalic": "Dőlt",
|
||||
"LabelFontScale": "Betűméret skála",
|
||||
"LabelFontStrikethrough": "Áthúzott",
|
||||
|
|
@ -435,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Nem {0}",
|
||||
"LabelLibraryItem": "Könyvtári elem",
|
||||
"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",
|
||||
"LabelLineSpacing": "Sorköz",
|
||||
"LabelListenAgain": "Újrahallgatás",
|
||||
|
|
@ -585,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeuomorfikus dizájn fa polcokkal",
|
||||
"LabelSettingsChromecastSupport": "Chromecast támogatás",
|
||||
"LabelSettingsDateFormat": "Dátumformátum",
|
||||
"LabelSettingsEnableWatcher": "Változások automatikus vizsgálata a könyvtárakban",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Változások automatikus vizsgálata a könyvtárban",
|
||||
"LabelSettingsEnableWatcher": "Változások automatikus figyelése a könyvtárakban",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Változások automatikus figyelése a könyvtárban",
|
||||
"LabelSettingsEnableWatcherHelp": "Engedélyezi az automatikus elem hozzáadás/frissítés funkciót, amikor fájlváltozásokat észlel. *Szerver újraindítása szükséges",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Szkriptelt tartalmak engedélyezése epub-okban",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Megengedi, hogy az epub fájlok szkripteket hajtsanak végre. Ezt a beállítást kikapcsolva ajánlott tartani, kivéve, ha megbízik az epub fájlok forrásában.",
|
||||
|
|
@ -635,6 +638,7 @@
|
|||
"LabelStartTime": "Kezdési idő",
|
||||
"LabelStarted": "Elkezdődött",
|
||||
"LabelStartedAt": "Kezdés ideje",
|
||||
"LabelStartedDate": "Elindítva {0}",
|
||||
"LabelStatsAudioTracks": "Audiósáv",
|
||||
"LabelStatsAuthors": "Szerző",
|
||||
"LabelStatsBestDay": "Legjobb nap",
|
||||
|
|
@ -884,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Biztosan alaphelyzetbe szeretné állítani a fejezeteket és visszavonni a módosításokat?",
|
||||
"MessageRestoreBackupConfirm": "Biztosan vissza szeretné állítani a biztonsági másolatot, amely ekkor készült:",
|
||||
"MessageRestoreBackupWarning": "A biztonsági mentés visszaállítása felülírja az egész adatbázist, amely a /config mappában található, valamint a borítóképeket a /metadata/items és /metadata/authors mappákban.<br /><br />A biztonsági mentések nem módosítják a könyvtár mappáiban található fájlokat. Ha engedélyezte a szerverbeállításokat a borítóképek és a metaadatok könyvtármappákban való tárolására, akkor ezek nem kerülnek biztonsági mentésre vagy felülírásra.<br /><br />A szerver használó összes kliens automatikusan frissül.",
|
||||
"MessageScheduleLibraryScanNote": "A legtöbb felhasználó számára ajánlott ezt a funkciót kikapcsolva hagyni, és engedélyezni a mappafigyelő beállítást. A mappafigyelő automatikusan észleli a könyvtári mappák változásait. A mappafigyelő nem működik minden fájlrendszernél (mint például az NFS), ezért helyette ütemezett könyvtárellenőrzéseket lehet használni.",
|
||||
"MessageScheduleLibraryScanNote": "A legtöbb felhasználó számára ajánlott ezt a funkciót kikapcsolva hagyni, és engedélyezni a mappafigyelő beállítást. A mappafigyelő automatikusan észleli a könyvtári mappák változásait. Kapcsolja be ezt a funkciót, ha az „Automatikus könyvtárfigyelés” nem működik a fájlrendszerén (például NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Futás minden {1} óra {0}-kor",
|
||||
"MessageSearchResultsFor": "Keresési eredmények",
|
||||
"MessageSelected": "{0} kiválasztva",
|
||||
|
|
@ -1022,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "A tétel(ek) hozzáadása gyűjteményhez sikertelen",
|
||||
"ToastCollectionRemoveSuccess": "Gyűjtemény eltávolítva",
|
||||
"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",
|
||||
"ToastDateTimeInvalidOrIncomplete": "A dátum és az időpont érvénytelen vagy hiányos",
|
||||
"ToastDeleteFileFailed": "Nem sikerült törölni a fájlt",
|
||||
|
|
|
|||
1
client/strings/is.json
Normal file
1
client/strings/is.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -309,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Elimina dal file system (togli la spunta per eliminarla solo dal DB)",
|
||||
"LabelDescription": "Descrizione",
|
||||
"LabelDeselectAll": "Deseleziona Tutto",
|
||||
"LabelDetectedPattern": "Trovato pattern:",
|
||||
"LabelDevice": "Dispositivo",
|
||||
"LabelDeviceInfo": "Info dispositivo",
|
||||
"LabelDeviceIsAvailableTo": "Il dispositivo e disponibile su…",
|
||||
|
|
@ -377,6 +378,7 @@
|
|||
"LabelFilterByUser": "Filtro per Utente",
|
||||
"LabelFindEpisodes": "Trova Episodi",
|
||||
"LabelFinished": "Finita",
|
||||
"LabelFinishedDate": "Finito {0}",
|
||||
"LabelFolder": "Cartella",
|
||||
"LabelFolders": "Cartelle",
|
||||
"LabelFontBold": "Grassetto",
|
||||
|
|
@ -434,8 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Nessuno {0}",
|
||||
"LabelLibraryItem": "Elementi della biblioteca",
|
||||
"LabelLibraryName": "Nome della biblioteca",
|
||||
"LabelLibrarySortByProgress": "Aggiornamento dei progressi",
|
||||
"LabelLibrarySortByProgressStarted": "Data di inizio",
|
||||
"LabelLibrarySortByProgress": "Progressi: Ultimi aggiornamenti",
|
||||
"LabelLibrarySortByProgressFinished": "Progressi: Completati",
|
||||
"LabelLibrarySortByProgressStarted": "Progressi: Iniziati",
|
||||
"LabelLimit": "Limiti",
|
||||
"LabelLineSpacing": "Interlinea",
|
||||
"LabelListenAgain": "Ascolta ancora",
|
||||
|
|
@ -635,6 +638,7 @@
|
|||
"LabelStartTime": "Tempo di inizio",
|
||||
"LabelStarted": "Iniziato",
|
||||
"LabelStartedAt": "Iniziato al",
|
||||
"LabelStartedDate": "Iniziati {0}",
|
||||
"LabelStatsAudioTracks": "Tracce Audio",
|
||||
"LabelStatsAuthors": "Autori",
|
||||
"LabelStatsBestDay": "Giorno migliore",
|
||||
|
|
@ -1022,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "l'aggiunta dell'elemento(i) alla raccolta non è riuscito",
|
||||
"ToastCollectionRemoveSuccess": "Collezione rimossa",
|
||||
"ToastCollectionUpdateSuccess": "Raccolta aggiornata",
|
||||
"ToastConnectionNotAvailable": "Connessione non disponibile. Provare più tardi",
|
||||
"ToastCoverSearchFailed": "Ricerca Cover fallita",
|
||||
"ToastCoverUpdateFailed": "Aggiornamento cover fallito",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Data e ora non sono valide o incomplete",
|
||||
"ToastDeleteFileFailed": "Impossibile eliminare il file",
|
||||
|
|
|
|||
|
|
@ -11,15 +11,19 @@
|
|||
"ButtonApplyChapters": "チャプターを確定する",
|
||||
"ButtonAuthors": "作者",
|
||||
"ButtonBack": "戻る",
|
||||
"ButtonBatchEditPopulateFromExisting": "既存のものから取り込む",
|
||||
"ButtonBatchEditPopulateMapDetails": "チャプター情報を読み込む",
|
||||
"ButtonBrowseForFolder": "フォルダーを選択する",
|
||||
"ButtonCancel": "キャンセル",
|
||||
"ButtonCancelEncode": "エンコードを取り消す",
|
||||
"ButtonChangeRootPassword": "Rootのパスワードを変更する",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "新しいエピソードを確認してダウンロード",
|
||||
"ButtonChooseAFolder": "フォルダーを選ぶ",
|
||||
"ButtonChooseFiles": "ファイルを選ぶ",
|
||||
"ButtonClearFilter": "絞り込みを解除",
|
||||
"ButtonClose": "閉じる",
|
||||
"ButtonCloseFeed": "フィードを閉じる",
|
||||
"ButtonCloseSession": "開いているセッションを閉じる",
|
||||
"ButtonCollections": "コレクション",
|
||||
"ButtonConfigureScanner": "スキャナーの設定",
|
||||
"ButtonCreate": "作成",
|
||||
|
|
@ -30,21 +34,30 @@
|
|||
"ButtonEditChapters": "チャプターの編集",
|
||||
"ButtonEditPodcast": "ポッドキャストの編集",
|
||||
"ButtonEnable": "オンにする",
|
||||
"ButtonFireAndFail": "エラーを無視して実行",
|
||||
"ButtonFireOnTest": "テストを実行",
|
||||
"ButtonForceReScan": "強制的に再スキャンする",
|
||||
"ButtonFullPath": "絶対パス",
|
||||
"ButtonHide": "非表示",
|
||||
"ButtonHome": "ホーム",
|
||||
"ButtonIssues": "問題",
|
||||
"ButtonJumpBackward": "巻き戻し",
|
||||
"ButtonJumpForward": "早送り",
|
||||
"ButtonLatest": "最新",
|
||||
"ButtonLibrary": "ライブラリー",
|
||||
"ButtonLogout": "ログアウト",
|
||||
"ButtonLookup": "参照",
|
||||
"ButtonManageTracks": "トラックの管理",
|
||||
"ButtonMapChapterTitles": "チャプターのタイトルを割り当て",
|
||||
"ButtonMatchAllAuthors": "すべての作者と紐付け",
|
||||
"ButtonMatchBooks": "本と紐付け",
|
||||
"ButtonNevermind": "中止",
|
||||
"ButtonNext": "次",
|
||||
"ButtonNextChapter": "次のチャプター",
|
||||
"ButtonNextItemInQueue": "キューの中の次のアイテム",
|
||||
"ButtonOk": "はい",
|
||||
"ButtonOpenFeed": "フィードを開く",
|
||||
"ButtonOpenManager": "管理画面を開く",
|
||||
"ButtonPause": "一時停止",
|
||||
"ButtonPlay": "再生",
|
||||
"ButtonPlayAll": "全て再生",
|
||||
|
|
@ -52,11 +65,13 @@
|
|||
"ButtonPlaylists": "プレイリスト",
|
||||
"ButtonPrevious": "先",
|
||||
"ButtonPreviousChapter": "前のチャプター",
|
||||
"ButtonProbeAudioFile": "オーディオファイルを解析",
|
||||
"ButtonPurgeAllCache": "全てのキャッシュを削除",
|
||||
"ButtonPurgeItemsCache": "項目のキャッシュを削除",
|
||||
"ButtonQueueAddItem": "次に再生する",
|
||||
"ButtonQueueRemoveItem": "次に再生から削除",
|
||||
"ButtonQuickEmbed": "クイック埋め込み",
|
||||
"ButtonQuickEmbedMetadata": "メタデータの埋め込み",
|
||||
"ButtonReScan": "再スキャン",
|
||||
"ButtonRead": "読む",
|
||||
"ButtonReadLess": "閉じる",
|
||||
|
|
@ -76,8 +91,11 @@
|
|||
"ButtonScrollRight": "右にスクロール",
|
||||
"ButtonSearch": "検索",
|
||||
"ButtonSeries": "シリーズ",
|
||||
"ButtonSubmit": "送信",
|
||||
"ButtonYes": "はい",
|
||||
"HeaderAccount": "アカウント",
|
||||
"HeaderAdvanced": "上級者向け",
|
||||
"HeaderAudioTracks": "オーディオトラック",
|
||||
"HeaderChapters": "チャプター",
|
||||
"HeaderCollection": "コレクション",
|
||||
"HeaderCollectionItems": "コレクションの項目",
|
||||
|
|
@ -87,19 +105,68 @@
|
|||
"HeaderEreaderSettings": "電子書籍リーダーの設定",
|
||||
"HeaderLatestEpisodes": "最新のエピソード",
|
||||
"HeaderLibraries": "ライブラリー",
|
||||
"HeaderOpenRSSFeed": "RSS Feedを開く",
|
||||
"HeaderPlayerSettings": "プレーヤーの設定",
|
||||
"HeaderPlaylist": "プレイリスト",
|
||||
"HeaderPlaylistItems": "プレイリストアイテム",
|
||||
"HeaderRSSFeedGeneral": "RSS 詳細",
|
||||
"HeaderSettings": "設定",
|
||||
"HeaderSettingsGeneral": "一般",
|
||||
"HeaderSettingsScanner": "スキャナー",
|
||||
"HeaderSleepTimer": "スリープタイマー",
|
||||
"HeaderStatsMinutesListeningChart": "過去7日間の視聴時間(分)",
|
||||
"LabelAddToPlaylist": "プレイリストの追加",
|
||||
"LabelAuthor": "著者",
|
||||
"LabelAuthorFirstLast": "著者(名 氏)",
|
||||
"LabelAuthorLastFirst": "著者(氏 名)",
|
||||
"LabelAuthors": "著者",
|
||||
"LabelAutoDownloadEpisodes": "エピソードの自動ダウンロード",
|
||||
"LabelBooks": "ほん",
|
||||
"LabelChapters": "チャプター",
|
||||
"LabelClosePlayer": "プレイヤーを閉じる",
|
||||
"LabelComplete": "完了",
|
||||
"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": "言語",
|
||||
"LabelLanguages": "言語",
|
||||
"LabelLayout": "レイアウト",
|
||||
"LabelLayoutSinglePage": "単ページ",
|
||||
"LabelLineSpacing": "行間",
|
||||
"LabelListenAgain": "再度視聴",
|
||||
"LabelMediaType": "メディアの種類",
|
||||
"LabelMoreInfo": "追加情報",
|
||||
"LabelName": "名",
|
||||
"LabelNarrator": "ナレーター",
|
||||
"LabelNarrators": "ナレーター",
|
||||
"LabelNew": "新しい",
|
||||
"LabelNewPassword": "新しいのパスワード",
|
||||
"LabelNewestAuthors": "最新の著者",
|
||||
"LabelNewestEpisodes": "最新エピソード",
|
||||
"LabelPassword": "パスワード",
|
||||
"LabelPath": "パス",
|
||||
"LabelPlaylists": "プレイリスト",
|
||||
"LabelPodcast": "ポッドキャスト",
|
||||
"LabelPodcasts": "ポッドキャスト",
|
||||
"LabelPreventIndexing": "フィードがiTunesおよびGoogleのポッドキャストディレクトリにインデックス登録されるのを防ぎます",
|
||||
"LabelPublishYear": "公開年",
|
||||
"LabelSettingsFindCovers": "表紙を探す",
|
||||
"LabelSettingsFindCoversHelp": "もしオーディオブックに表紙が埋め込まれていない、もしくは表紙画像がフォルダー内に見つからなければ、スキャナーは表紙を探そうとします。<br>注記: これによってスキャン時間が長くなります",
|
||||
"LabelSettingsParseSubtitles": "サブタイトルを抽出する",
|
||||
|
|
|
|||
1165
client/strings/ko.json
Normal file
1165
client/strings/ko.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -18,6 +18,7 @@
|
|||
"ButtonChooseAFolder": "Pasirinkite aplanką",
|
||||
"ButtonChooseFiles": "Pasirinkite failus",
|
||||
"ButtonClearFilter": "Valyti filtrą",
|
||||
"ButtonClose": "Uždaryti",
|
||||
"ButtonCloseFeed": "Uždaryti srautą",
|
||||
"ButtonCloseSession": "Uždaryti Atidarytą sesiją",
|
||||
"ButtonCollections": "Kolekcijos",
|
||||
|
|
@ -251,7 +252,7 @@
|
|||
"LabelDuration": "Trukmė",
|
||||
"LabelDurationFound": "Rasta trukmė:",
|
||||
"LabelEbook": "Elektroninė knyga",
|
||||
"LabelEbooks": "Elektroninės knygos",
|
||||
"LabelEbooks": "El. knygos",
|
||||
"LabelEdit": "Redaguoti",
|
||||
"LabelEmail": "El. paštas",
|
||||
"LabelEmailSettingsFromAddress": "Siuntėjo adresas",
|
||||
|
|
@ -261,6 +262,7 @@
|
|||
"LabelEmbeddedCover": "Įterptas viršelis",
|
||||
"LabelEnable": "Įjungti",
|
||||
"LabelEnd": "Pabaiga",
|
||||
"LabelEndOfChapter": "Skyriaus pabaiga",
|
||||
"LabelEpisode": "Epizodas",
|
||||
"LabelEpisodeTitle": "Epizodo pavadinimas",
|
||||
"LabelEpisodeType": "Epizodo tipas",
|
||||
|
|
@ -282,8 +284,8 @@
|
|||
"LabelGenre": "Žanras",
|
||||
"LabelGenres": "Žanrai",
|
||||
"LabelHardDeleteFile": "Galutinai ištrinti failą",
|
||||
"LabelHasEbook": "Turi e-knygą",
|
||||
"LabelHasSupplementaryEbook": "Turi papildomą e-knygą",
|
||||
"LabelHasEbook": "Turi el. knygą",
|
||||
"LabelHasSupplementaryEbook": "Turi papildomą el. knygą",
|
||||
"LabelHost": "Serveris",
|
||||
"LabelHour": "Valanda",
|
||||
"LabelIcon": "Piktograma",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"ButtonApplyChapters": "Bruk kapittel",
|
||||
"ButtonAuthors": "Forfattere",
|
||||
"ButtonBack": "Tilbake",
|
||||
"ButtonBatchEditPopulateFromExisting": "Opprett fra eksisterende",
|
||||
"ButtonBatchEditPopulateFromExisting": "Fyll ut fra eksisterende",
|
||||
"ButtonBatchEditPopulateMapDetails": "Legg til detaljer",
|
||||
"ButtonBrowseForFolder": "Bla gjennom mappe",
|
||||
"ButtonCancel": "Avbryt",
|
||||
|
|
@ -127,6 +127,7 @@
|
|||
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
|
||||
"HeaderAuthentication": "Autentisering",
|
||||
"HeaderBackups": "Sikkerhetskopier",
|
||||
"HeaderBulkChapterModal": "Legg til flere kapitler",
|
||||
"HeaderChangePassword": "Bytt passord",
|
||||
"HeaderChapters": "Kapittel",
|
||||
"HeaderChooseAFolder": "Velg en mappe",
|
||||
|
|
@ -433,13 +434,13 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Ingen {0}",
|
||||
"LabelLibraryItem": "Bibliotek enhet",
|
||||
"LabelLibraryName": "Bibliotek navn",
|
||||
"LabelLibrarySortByProgress": "Fremgang oppdatert",
|
||||
"LabelLibrarySortByProgress": "Fremgang: Sist oppdatert",
|
||||
"LabelLimit": "Begrensning",
|
||||
"LabelLineSpacing": "Linjemellomrom",
|
||||
"LabelListenAgain": "Lytt igjen",
|
||||
"LabelLogLevelDebug": "Debug",
|
||||
"LabelLogLevelInfo": "Info",
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLogLevelWarn": "Varsel",
|
||||
"LabelLookForNewEpisodesAfterDate": "Se etter nye episoder etter denne datoen",
|
||||
"LabelLowestPriority": "Laveste prioritet",
|
||||
"LabelMatchExistingUsersBy": "Knytt sammen eksisterende brukere basert på",
|
||||
|
|
@ -490,6 +491,7 @@
|
|||
"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:",
|
||||
"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",
|
||||
"LabelOverwrite": "Overskriv",
|
||||
"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?",
|
||||
"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?",
|
||||
"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?",
|
||||
"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?",
|
||||
|
|
@ -939,6 +941,7 @@
|
|||
"ToastCollectionItemsAddFailed": "Feil med å legge til element(er)",
|
||||
"ToastCollectionRemoveSuccess": "Samling fjernet",
|
||||
"ToastCollectionUpdateSuccess": "samlingupdated",
|
||||
"ToastCoverSearchFailed": "Finner ikke bokomslag",
|
||||
"ToastCoverUpdateFailed": "Oppdatering av bilde feilet",
|
||||
"ToastDeleteFileFailed": "Kunne ikke slette fil",
|
||||
"ToastDeleteFileSuccess": "Fil slettet",
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
"ButtonReScan": "Ponowne skanowanie",
|
||||
"ButtonRead": "Czytaj",
|
||||
"ButtonReadLess": "Pokaż mniej",
|
||||
"ButtonReadMore": "Pokaż więcej",
|
||||
"ButtonReadMore": "Czytaj więcej",
|
||||
"ButtonRefresh": "Odśwież",
|
||||
"ButtonRemove": "Usuń",
|
||||
"ButtonRemoveAll": "Usuń wszystko",
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
"ButtonScrollRight": "Przewiń w prawo",
|
||||
"ButtonSearch": "Szukaj",
|
||||
"ButtonSelectFolderPath": "Wybierz ścieżkę folderu",
|
||||
"ButtonSeries": "Seria",
|
||||
"ButtonSeries": "Serial",
|
||||
"ButtonSetChaptersFromTracks": "Ustawiaj rozdziały na podstawie utworów",
|
||||
"ButtonShare": "Udostępnij",
|
||||
"ButtonShiftTimes": "Przesunięcie czasowe",
|
||||
|
|
@ -127,6 +127,7 @@
|
|||
"HeaderAudiobookTools": "Narzędzia do zarządzania audiobookami",
|
||||
"HeaderAuthentication": "Uwierzytelnianie",
|
||||
"HeaderBackups": "Kopie zapasowe",
|
||||
"HeaderBulkChapterModal": "Dodaj wiele rozdziałów",
|
||||
"HeaderChangePassword": "Zmień hasło",
|
||||
"HeaderChapters": "Rozdziały",
|
||||
"HeaderChooseAFolder": "Wybierz folder",
|
||||
|
|
@ -199,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Funkcje eksperymentalne",
|
||||
"HeaderSettingsGeneral": "Ogólne",
|
||||
"HeaderSettingsScanner": "Skanowanie",
|
||||
"HeaderSettingsSecurity": "Bezpieczeństwo",
|
||||
"HeaderSettingsWebClient": "Klient webowy",
|
||||
"HeaderSleepTimer": "Wyłącznik czasowy",
|
||||
"HeaderStatsLargestItems": "Największe pozycje",
|
||||
|
|
@ -231,8 +233,8 @@
|
|||
"LabelAddToCollectionBatch": "Dodaj {0} książki do kolekcji",
|
||||
"LabelAddToPlaylist": "Dodaj do playlisty",
|
||||
"LabelAddToPlaylistBatch": "Dodaj {0} pozycji do playlisty",
|
||||
"LabelAddedAt": "Dodano",
|
||||
"LabelAddedDate": "Dodano {0}",
|
||||
"LabelAddedAt": "Dodano w",
|
||||
"LabelAddedDate": "Dodano",
|
||||
"LabelAdminUsersOnly": "Tylko użytkownicy administracyjni",
|
||||
"LabelAll": "Wszystkie",
|
||||
"LabelAllEpisodesDownloaded": "Wszystkie odcinki pobrane",
|
||||
|
|
@ -242,6 +244,8 @@
|
|||
"LabelAlreadyInYourLibrary": "Już istnieje w twojej bibliotece",
|
||||
"LabelApiKeyCreated": "Klucz API \"{0}\" został pomyślnie utworzony.",
|
||||
"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",
|
||||
"LabelAppend": "Dołącz",
|
||||
"LabelAudioBitrate": "Audio Bitrate (np. 128k)",
|
||||
|
|
@ -291,6 +295,7 @@
|
|||
"LabelContinueListening": "Kontynuuj słuchanie",
|
||||
"LabelContinueReading": "Kontynuuj czytanie",
|
||||
"LabelContinueSeries": "Kontynuuj serię",
|
||||
"LabelCorsAllowed": "Dozwolone źródła CORS",
|
||||
"LabelCover": "Okładka",
|
||||
"LabelCoverImageURL": "URL okładki",
|
||||
"LabelCoverProvider": "Dostawca okładki",
|
||||
|
|
@ -304,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Usuń z systemu plików (odznacz, aby usunąć tylko z bazy danych)",
|
||||
"LabelDescription": "Opis",
|
||||
"LabelDeselectAll": "Odznacz wszystko",
|
||||
"LabelDetectedPattern": "Wykryty schemat:",
|
||||
"LabelDevice": "Urządzenie",
|
||||
"LabelDeviceInfo": "Informacja o urządzeniu",
|
||||
"LabelDeviceIsAvailableTo": "Urządzenie jest dostępne do...",
|
||||
|
|
@ -353,9 +359,11 @@
|
|||
"LabelExample": "Przykład",
|
||||
"LabelExpandSeries": "Rozwiń serie",
|
||||
"LabelExpandSubSeries": "Rozwiń podserie",
|
||||
"LabelExpired": "Przeterminowane",
|
||||
"LabelExpiresAt": "Wygasa w",
|
||||
"LabelExpiresInSeconds": "Wygasa za (sekund)",
|
||||
"LabelExpiresNever": "Nigdy",
|
||||
"LabelExplicit": "Nieprzyzwoite",
|
||||
"LabelExplicit": "18+",
|
||||
"LabelExplicitChecked": "Nieprzyzwoite (sprawdzone)",
|
||||
"LabelExplicitUnchecked": "Przyzwoite (niesprawdzone)",
|
||||
"LabelExportOPML": "Wyeksportuj OPML",
|
||||
|
|
@ -370,11 +378,12 @@
|
|||
"LabelFilterByUser": "Filtruj według danego użytkownika",
|
||||
"LabelFindEpisodes": "Znajdź odcinki",
|
||||
"LabelFinished": "Zakończone",
|
||||
"LabelFinishedDate": "Ukończone {0}",
|
||||
"LabelFolder": "Katalog",
|
||||
"LabelFolders": "Foldery",
|
||||
"LabelFontBold": "Pogrubiony",
|
||||
"LabelFontBoldness": "Grubość czcionki",
|
||||
"LabelFontFamily": "Rodzina czcionek",
|
||||
"LabelFontFamily": "Krój pisma",
|
||||
"LabelFontItalic": "Kursywa",
|
||||
"LabelFontScale": "Rozmiar czcionki",
|
||||
"LabelFontStrikethrough": "Przekreślony",
|
||||
|
|
@ -392,7 +401,7 @@
|
|||
"LabelHours": "Godziny",
|
||||
"LabelIcon": "Ikona",
|
||||
"LabelImageURLFromTheWeb": "Link do obrazu w sieci",
|
||||
"LabelInProgress": "W trakcie",
|
||||
"LabelInProgress": "W toku",
|
||||
"LabelIncludeInTracklist": "Dołącz do listy odtwarzania",
|
||||
"LabelIncomplete": "Nieukończone",
|
||||
"LabelInterval": "Interwał",
|
||||
|
|
@ -427,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Brak {0}",
|
||||
"LabelLibraryItem": "Element 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",
|
||||
"LabelLineSpacing": "Odstęp między wierszami",
|
||||
"LabelListenAgain": "Słuchaj ponownie",
|
||||
|
|
@ -436,6 +447,7 @@
|
|||
"LabelLogLevelWarn": "Ostrzeżenie",
|
||||
"LabelLookForNewEpisodesAfterDate": "Szukaj nowych odcinków po dacie",
|
||||
"LabelLowestPriority": "Najniższy priorytet",
|
||||
"LabelMatchConfidence": "Zaufanie",
|
||||
"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",
|
||||
"LabelMaxEpisodesToDownload": "Maksymalna liczba odcinków do pobrania. Użyj 0, aby wyłączyć ograniczenie.",
|
||||
|
|
@ -465,6 +477,7 @@
|
|||
"LabelNewestAuthors": "Najnowsi autorzy",
|
||||
"LabelNewestEpisodes": "Najnowsze odcinki",
|
||||
"LabelNextBackupDate": "Data kolejnej kopii zapasowej",
|
||||
"LabelNextChapters": "Następny odcinek:",
|
||||
"LabelNextScheduledRun": "Następne uruchomienie",
|
||||
"LabelNoApiKeys": "Brak kluczy API",
|
||||
"LabelNoCustomMetadataProviders": "Brak niestandardowych dostawców metadanych",
|
||||
|
|
@ -482,6 +495,7 @@
|
|||
"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.",
|
||||
"LabelNumberOfBooks": "Liczba książek",
|
||||
"LabelNumberOfChapters": "Liczba rozdziałó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ą:",
|
||||
"LabelOpenIDClaims": "Pozostaw poniższe opcje puste, aby wyłączyć zaawansowane przypisywanie grup i uprawnień. Automatycznie zostanie przypisana grupa „Użytkownik”.",
|
||||
|
|
@ -559,9 +573,11 @@
|
|||
"LabelSelectUsers": "Wybór użytkowników",
|
||||
"LabelSendEbookToDevice": "Wyślij ebook do...",
|
||||
"LabelSequence": "Kolejność",
|
||||
"LabelSerial": "Seria",
|
||||
"LabelSeries": "Serie",
|
||||
"LabelSeriesName": "Nazwy serii",
|
||||
"LabelSeriesProgress": "Postęp w serii",
|
||||
"LabelServerLogLevel": "Poziom logowania servera",
|
||||
"LabelServerYearReview": "Podsumowanie serwera w roku ({0})",
|
||||
"LabelSetEbookAsPrimary": "Ustaw jako pierwszy",
|
||||
"LabelSetEbookAsSupplementary": "Ustaw jako dodatkowy",
|
||||
|
|
@ -571,8 +587,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Widok półki z książkami",
|
||||
"LabelSettingsChromecastSupport": "Wsparcie Chromecast",
|
||||
"LabelSettingsDateFormat": "Format daty",
|
||||
"LabelSettingsEnableWatcher": "Automatyczne skanowanie bibliotek w poszukiwaniu zmian",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automatyczne skanowanie biblioteki w poszukiwaniu zmian",
|
||||
"LabelSettingsEnableWatcher": "Automatyczne monitorowanie bibliotek w poszukiwaniu zmian",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Automatyczne monitorowanie biblioteki w poszukiwaniu zmian",
|
||||
"LabelSettingsEnableWatcherHelp": "Włącza automatyczne dodawanie/aktualizację pozycji gdy wykryte zostaną zmiany w plikach. Wymaga restartu serwera",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Zezwalanie na skrypty w plikach epub",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Zezwala plikom epub na wykonywanie skryptów. Zaleca się mieć to ustawienie wyłączone, chyba że ma się zaufanie do źródła plików epub.",
|
||||
|
|
@ -605,6 +621,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",
|
||||
"LabelSettingsTimeFormat": "Format czasu",
|
||||
"LabelShare": "Udostępnij",
|
||||
"LabelShareDownloadableHelp": "Użytkownicy mogą przy pomocy linka ściągnąć archiwum ZIP pozycji biblioteki",
|
||||
"LabelShareOpen": "Otwórz udział",
|
||||
"LabelShareURL": "Link do udziału",
|
||||
"LabelShowAll": "Pokaż wszystko",
|
||||
|
|
@ -612,6 +629,7 @@
|
|||
"LabelShowSubtitles": "Pokaż Napisy",
|
||||
"LabelSize": "Rozmiar",
|
||||
"LabelSleepTimer": "Wyłącznik czasowy",
|
||||
"LabelSlug": "slug (części URL która identyfikuje konkretny zasób)",
|
||||
"LabelSortAscending": "Rosnąco",
|
||||
"LabelSortDescending": "Malejąco",
|
||||
"LabelSortPubDate": "Sortuj według daty publikacji",
|
||||
|
|
@ -619,6 +637,7 @@
|
|||
"LabelStartTime": "Czas rozpoczęcia",
|
||||
"LabelStarted": "Rozpoczęty",
|
||||
"LabelStartedAt": "Rozpoczęto",
|
||||
"LabelStartedDate": "Rozpoczęto {0}",
|
||||
"LabelStatsAudioTracks": "Ścieżki audio",
|
||||
"LabelStatsAuthors": "Autorzy",
|
||||
"LabelStatsBestDay": "Najlepszy dzień",
|
||||
|
|
@ -641,11 +660,15 @@
|
|||
"LabelTagsAccessibleToUser": "Tagi dostępne dla użytkownika",
|
||||
"LabelTagsNotAccessibleToUser": "Znaczniki niedostępne dla użytkownika",
|
||||
"LabelTasks": "Uruchomione zadania",
|
||||
"LabelTextEditorBulletedList": "Lista punktowana",
|
||||
"LabelTextEditorLink": "Link",
|
||||
"LabelTextEditorNumberedList": "Lista numerowana",
|
||||
"LabelTextEditorUnlink": "Usuń link",
|
||||
"LabelTheme": "Kompozycja",
|
||||
"LabelThemeDark": "Ciemny",
|
||||
"LabelThemeLight": "Jasny",
|
||||
"LabelThemeSepia": "Sepia",
|
||||
"LabelTimeBase": "Podstawa czasu",
|
||||
"LabelTimeDurationXHours": "{0} godzin",
|
||||
"LabelTimeDurationXMinutes": "{0} minuty",
|
||||
"LabelTimeDurationXSeconds": "{0} sekundy",
|
||||
|
|
@ -668,7 +691,12 @@
|
|||
"LabelTrackFromFilename": "Ścieżka z nazwy pliku",
|
||||
"LabelTrackFromMetadata": "Ścieżka z metadanych",
|
||||
"LabelTracks": "Ścieżki",
|
||||
"LabelTracksMultiTrack": "Wielościeżkowy",
|
||||
"LabelTracksNone": "Brak ścieżek",
|
||||
"LabelTracksSingleTrack": "Pojedyncza ścieżka",
|
||||
"LabelTrailer": "Zwiastun",
|
||||
"LabelType": "Typ",
|
||||
"LabelUnabridged": "Pełna wersja",
|
||||
"LabelUndo": "Wycofaj",
|
||||
"LabelUnknown": "Nieznany",
|
||||
"LabelUnknownPublishDate": "Nieznana data publikacji",
|
||||
|
|
@ -681,8 +709,10 @@
|
|||
"LabelUploaderDragAndDropFilesOnly": "Przeciągnij i upuść pliki",
|
||||
"LabelUploaderDropFiles": "Puść pliki",
|
||||
"LabelUploaderItemFetchMetadataHelp": "Automatycznie pobierz tytuł, autora i serie",
|
||||
"LabelUseAdvancedOptions": "Opcje zaawansowane",
|
||||
"LabelUseChapterTrack": "Użyj ścieżki rozdziału",
|
||||
"LabelUseFullTrack": "Użycie ścieżki rozdziału",
|
||||
"LabelUseZeroForUnlimited": "Użyj 0, aby wyłączyć ograniczenia",
|
||||
"LabelUser": "Użytkownik",
|
||||
"LabelUsername": "Nazwa użytkownika",
|
||||
"LabelValue": "Wartość",
|
||||
|
|
@ -692,6 +722,7 @@
|
|||
"LabelViewPlayerSettings": "Zobacz ustawienia odtwarzacza",
|
||||
"LabelViewQueue": "Wyświetlaj kolejkę odtwarzania",
|
||||
"LabelVolume": "Głośność",
|
||||
"LabelWebRedirectURLsDescription": "Zezwól na te adresy URL w swoim dostawcy OAuth, aby umożliwić przekierowanie z powrotem do aplikacji internetowej po zalogowaniu:",
|
||||
"LabelWeekdaysToRun": "Dni tygodnia",
|
||||
"LabelXBooks": "{0} książek",
|
||||
"LabelXItems": "{0} elementów",
|
||||
|
|
@ -701,14 +732,18 @@
|
|||
"LabelYourBookmarks": "Twoje zakładki",
|
||||
"LabelYourPlaylists": "Twoje playlisty",
|
||||
"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>.",
|
||||
"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>.",
|
||||
"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ć.",
|
||||
"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",
|
||||
"MessageBackupsLocationNoEditNote": "Uwaga: Lokalizacja kopii zapasowej jest ustawiona poprzez zmienną środowiskową i nie może być tutaj zmieniona.",
|
||||
"MessageBackupsLocationPathEmpty": "Ścieżka do kopii zapasowej nie może być pusta",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Wypełnij włączone pola danymi ze wszystkich elementów. Pola z wieloma wartościami zostaną scalone.",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "Wypełnij pola szczegółów mapy włączonej danymi z tego elementu",
|
||||
"MessageBatchQuickMatchDescription": "Quick Match będzie próbował dodać brakujące okładki i metadane dla wybranych elementów. Włącz poniższe opcje, aby umożliwić Quick Match nadpisanie istniejących okładek i/lub metadanych.",
|
||||
"MessageBookshelfNoCollections": "Nie posiadasz jeszcze żadnych kolekcji",
|
||||
"MessageBookshelfNoCollectionsHelp": "Kolekcje są publiczne. Wszyscy użytkownicy mający dostęp do biblioteki mogą je zobaczyć.",
|
||||
|
|
@ -716,6 +751,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Nie znaleziono żadnych pozycji przy aktualnym filtrowaniu \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Brak wyników zapytania",
|
||||
"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",
|
||||
"MessageChapterErrorFirstNotZero": "Pierwszy rozdział musi rozpoczynać się na 0",
|
||||
"MessageChapterErrorStartGteDuration": "Nieprawidłowy czas rozpoczęcia, musi być krótszy niż długość audiobooka",
|
||||
|
|
@ -778,6 +814,8 @@
|
|||
"MessageFeedURLWillBe": "URL kanału: {0}",
|
||||
"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.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} słucha</strong> na {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Brak sesji słuchania na {0}",
|
||||
"MessageImportantNotice": "Ważna informacja!",
|
||||
"MessageInsertChapterBelow": "Wstaw rozdział poniżej",
|
||||
"MessageInvalidAsin": "Nieprawidłowy ASIN",
|
||||
|
|
@ -848,13 +886,40 @@
|
|||
"MessageResetChaptersConfirm": "Czy na pewno chcesz zresetować rozdziały i cofnąć wprowadzone zmiany?",
|
||||
"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.",
|
||||
"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",
|
||||
"MessageSelected": "{0} wybranych",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Sekwencja serii nie może zawierać spacji",
|
||||
"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>",
|
||||
"MessageShareExpiresIn": "Wygaśnie za {0}",
|
||||
"MessageShareURLWillBe": "Udostępnione pod linkiem <strong>{0}</strong>",
|
||||
"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}\"",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Nie udało się połączyć plików audio",
|
||||
"MessageTaskFailedToMoveM4bFile": "Nie udało się przenieść pliku m4b",
|
||||
"MessageTaskFailedToWriteMetadataFile": "Niepowodzenie zapisania pliku metadanych",
|
||||
"MessageTaskMatchingBooksInLibrary": "Pasujące książki w bibliotece \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Brak plików do skanowania",
|
||||
"MessageTaskOpmlImport": "Importuj OPML",
|
||||
"MessageTaskOpmlImportDescription": "Tworzenie {0} podcastów z kanałów RSS",
|
||||
"MessageTaskScanItemsAdded": "Dodano {0}",
|
||||
"MessageTaskScanItemsMissing": "Brakuje {0}",
|
||||
"MessageTaskScanItemsUpdated": "Zaktualizowano {0}",
|
||||
"MessageTaskScanNoChangesNeeded": "Brak zmian",
|
||||
"MessageTaskTargetDirectoryNotWritable": "Brak prawa zapisu do folderu docelowego",
|
||||
"MessageThinking": "Myślę...",
|
||||
"MessageUploaderItemFailed": "Nie udało się przesłać",
|
||||
"MessageUploaderItemSuccess": "Przesłanie powiodło się!",
|
||||
|
|
@ -912,6 +977,21 @@
|
|||
"ToastBookmarkRemoveSuccess": "Zakładka została usunięta",
|
||||
"ToastCollectionRemoveSuccess": "Kolekcja usunięta",
|
||||
"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ę",
|
||||
"ToastItemDetailsUpdateSuccess": "Zaktualizowano szczegóły",
|
||||
"ToastItemMarkedAsFinishedFailed": "Nie udało się oznaczyć jako ukończone",
|
||||
|
|
@ -925,12 +1005,28 @@
|
|||
"ToastLibraryScanFailedToStart": "Nie udało się rozpocząć skanowania",
|
||||
"ToastLibraryScanStarted": "Rozpoczęto skanowanie biblioteki",
|
||||
"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",
|
||||
"ToastPlaylistCreateSuccess": "Playlista utworzona",
|
||||
"ToastPlaylistRemoveSuccess": "Playlista usunięta",
|
||||
"ToastPlaylistUpdateSuccess": "Playlista zaktualizowana",
|
||||
"ToastPodcastCreateFailed": "Nie udało się utworzyć podcastu",
|
||||
"ToastPodcastCreateSuccess": "Podcast został pomyślnie utworzony",
|
||||
"ToastPodcastEpisodeUpdated": "Zaktualizowano odcinki",
|
||||
"ToastRSSFeedCloseFailed": "Zamknięcie kanału RSS nie powiodło się",
|
||||
"ToastRSSFeedCloseSuccess": "Zamknięcie kanału RSS powiodło się",
|
||||
"ToastRemoveItemFromCollectionFailed": "Nie udało się usunąć elementu z kolekcji",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Adicionar",
|
||||
"ButtonAddApiKey": "Adicionar chave de API",
|
||||
"ButtonAddChapters": "Adicionar Capítulos",
|
||||
"ButtonAddDevice": "Adicionar Dispositivo",
|
||||
"ButtonAddLibrary": "Adicionar Biblioteca",
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Escolha uma pasta",
|
||||
"ButtonChooseFiles": "Escolha arquivos",
|
||||
"ButtonClearFilter": "Limpar Filtro",
|
||||
"ButtonClose": "Fechar",
|
||||
"ButtonCloseFeed": "Fechar Feed",
|
||||
"ButtonCloseSession": "Fechar Sessão Aberta",
|
||||
"ButtonCollections": "Coleções",
|
||||
|
|
@ -52,7 +54,7 @@
|
|||
"ButtonNevermind": "Cancelar",
|
||||
"ButtonNext": "Próximo",
|
||||
"ButtonNextChapter": "Próximo Capítulo",
|
||||
"ButtonNextItemInQueue": "Próximo Item da Fila",
|
||||
"ButtonNextItemInQueue": "Próximo Item na Fila",
|
||||
"ButtonOk": "Ok",
|
||||
"ButtonOpenFeed": "Abrir Feed",
|
||||
"ButtonOpenManager": "Abrir Gerenciador",
|
||||
|
|
@ -119,10 +121,13 @@
|
|||
"HeaderAccount": "Conta",
|
||||
"HeaderAddCustomMetadataProvider": "Adicionar Provedor de Metadados Personalizado",
|
||||
"HeaderAdvanced": "Avançado",
|
||||
"HeaderApiKeys": "Chaves de API",
|
||||
"HeaderAppriseNotificationSettings": "Configuração de notificações Apprise",
|
||||
"HeaderAudioTracks": "Trilhas de áudio",
|
||||
"HeaderAudiobookTools": "Ferramentas de Gerenciamento de Arquivos de Audiobooks",
|
||||
"HeaderAuthentication": "Autenticação",
|
||||
"HeaderBackups": "Backups",
|
||||
"HeaderBulkChapterModal": "Adicionar vários capítulos",
|
||||
"HeaderChangePassword": "Trocar Senha",
|
||||
"HeaderChapters": "Capítulos",
|
||||
"HeaderChooseAFolder": "Escolha uma Pasta",
|
||||
|
|
@ -135,10 +140,11 @@
|
|||
"HeaderDetails": "Detalhes",
|
||||
"HeaderDownloadQueue": "Fila de Download",
|
||||
"HeaderEbookFiles": "Arquivos Ebook",
|
||||
"HeaderEmail": "Email",
|
||||
"HeaderEmailSettings": "Configurações de Email",
|
||||
"HeaderEpisodes": "Episódios",
|
||||
"HeaderEreaderDevices": "Dispositivos Ereader",
|
||||
"HeaderEreaderSettings": "Configurações Ereader",
|
||||
"HeaderEreaderDevices": "Dispositivos leitores de ebook",
|
||||
"HeaderEreaderSettings": "Configurações do leitor de ebook",
|
||||
"HeaderFiles": "Arquivos",
|
||||
"HeaderFindChapters": "Localizar Capítulos",
|
||||
"HeaderIgnoredFiles": "Arquivos Ignorados",
|
||||
|
|
@ -151,6 +157,8 @@
|
|||
"HeaderLibraryStats": "Estatísticas da Biblioteca",
|
||||
"HeaderListeningSessions": "Sessões",
|
||||
"HeaderListeningStats": "Estatísticas",
|
||||
"HeaderLogin": "Login",
|
||||
"HeaderLogs": "Logs",
|
||||
"HeaderManageGenres": "Gerenciar Gêneros",
|
||||
"HeaderManageTags": "Gerenciar Etiquetas",
|
||||
"HeaderMapDetails": "Designar Detalhes",
|
||||
|
|
@ -158,17 +166,23 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Ordem de Prioridade dos Metadados",
|
||||
"HeaderMetadataToEmbed": "Metadados a Serem Incluídos",
|
||||
"HeaderNewAccount": "Nova Conta",
|
||||
"HeaderNewApiKey": "Nova chave de API",
|
||||
"HeaderNewLibrary": "Nova Biblioteca",
|
||||
"HeaderNotificationCreate": "Criar Notificação",
|
||||
"HeaderNotificationUpdate": "Atualizar Notificação",
|
||||
"HeaderNotifications": "Notificações",
|
||||
"HeaderOpenIDConnectAuthentication": "Autenticação via OpenID Connect",
|
||||
"HeaderOpenListeningSessions": "Abrir Sessões de Escuta",
|
||||
"HeaderOpenRSSFeed": "Abrir Feed RSS",
|
||||
"HeaderOtherFiles": "Outros Arquivos",
|
||||
"HeaderPasswordAuthentication": "Autenticação por Senha",
|
||||
"HeaderPermissions": "Permissões",
|
||||
"HeaderPlayerQueue": "Fila do reprodutor",
|
||||
"HeaderPlayerSettings": "Configurações do Reprodutor",
|
||||
"HeaderPlaylist": "Lista de Reprodução",
|
||||
"HeaderPlaylistItems": "Itens da lista de reprodução",
|
||||
"HeaderPodcastsToAdd": "Podcasts para Adicionar",
|
||||
"HeaderPresets": "Valores predefinidos",
|
||||
"HeaderPreviewCover": "Visualização da Capa",
|
||||
"HeaderRSSFeedGeneral": "Detalhes RSS",
|
||||
"HeaderRSSFeedIsOpen": "Feed RSS está Aberto",
|
||||
|
|
@ -177,6 +191,7 @@
|
|||
"HeaderRemoveEpisodes": "Remover {0} Episódios",
|
||||
"HeaderSavedMediaProgress": "Progresso da gravação das mídias",
|
||||
"HeaderSchedule": "Programação",
|
||||
"HeaderScheduleEpisodeDownloads": "Programar Download Automático de Episódios",
|
||||
"HeaderScheduleLibraryScans": "Programar Verificação Automática da Biblioteca",
|
||||
"HeaderSession": "Sessão",
|
||||
"HeaderSetBackupSchedule": "Definir Programação de Backup",
|
||||
|
|
@ -185,6 +200,8 @@
|
|||
"HeaderSettingsExperimental": "Funcionalidades experimentais",
|
||||
"HeaderSettingsGeneral": "Geral",
|
||||
"HeaderSettingsScanner": "Verificador",
|
||||
"HeaderSettingsSecurity": "Segurança",
|
||||
"HeaderSettingsWebClient": "Cliente Web",
|
||||
"HeaderSleepTimer": "Timer",
|
||||
"HeaderStatsLargestItems": "Maiores Itens",
|
||||
"HeaderStatsLongestItems": "Itens mais longos (hrs)",
|
||||
|
|
@ -195,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Sumário",
|
||||
"HeaderTools": "Ferramentas",
|
||||
"HeaderUpdateAccount": "Atualizar Conta",
|
||||
"HeaderUpdateApiKey": "Atualizar Chave de API",
|
||||
"HeaderUpdateAuthor": "Atualizar Autor",
|
||||
"HeaderUpdateDetails": "Atualizar Detalhes",
|
||||
"HeaderUpdateLibrary": "Atualizar Biblioteca",
|
||||
|
|
@ -209,6 +227,7 @@
|
|||
"LabelAccountTypeAdmin": "Administrador",
|
||||
"LabelAccountTypeGuest": "Convidado",
|
||||
"LabelAccountTypeUser": "Usuário",
|
||||
"LabelActivities": "Atividades",
|
||||
"LabelActivity": "Atividade",
|
||||
"LabelAddToCollection": "Adicionar à Coleção",
|
||||
"LabelAddToCollectionBatch": "Adicionar {0} Livros à Coleção",
|
||||
|
|
@ -218,11 +237,20 @@
|
|||
"LabelAddedDate": "Adicionado {0}",
|
||||
"LabelAdminUsersOnly": "Apenas usuários administradores",
|
||||
"LabelAll": "Todos",
|
||||
"LabelAllEpisodesDownloaded": "Todos os episódios baixados",
|
||||
"LabelAllUsers": "Todos Usuários",
|
||||
"LabelAllUsersExcludingGuests": "Todos usuários exceto convidados",
|
||||
"LabelAllUsersIncludingGuests": "Todos usuários incluindo convidados",
|
||||
"LabelAlreadyInYourLibrary": "Já na sua biblioteca",
|
||||
"LabelApiKeyCreated": "Chave de API \"{0}\" criada com sucesso.",
|
||||
"LabelApiKeyCreatedDescription": "Certifique-se de copiar a chave de API agora pois não será possível vê-la novamente.",
|
||||
"LabelApiKeyUser": "Agir em nome do usuário",
|
||||
"LabelApiKeyUserDescription": "Esta chave de API terá as mesmas permissões que o usuário em nome de quem ela está agindo. Isso aparecerá nos logs como se o usuário estivesse fazendo a solicitação.",
|
||||
"LabelApiToken": "Token de API",
|
||||
"LabelAppend": "Acrescentar",
|
||||
"LabelAudioBitrate": "Bitrate de áudio (por exemplo, 128k)",
|
||||
"LabelAudioChannels": "Canais de áudio (1 ou 2)",
|
||||
"LabelAudioCodec": "Codec de áudio",
|
||||
"LabelAuthor": "Autor",
|
||||
"LabelAuthorFirstLast": "Autor (Nome Sobrenome)",
|
||||
"LabelAuthorLastFirst": "Autor (Sobrenome, Nome)",
|
||||
|
|
@ -235,24 +263,31 @@
|
|||
"LabelAutoRegister": "Registrar Automaticamente",
|
||||
"LabelAutoRegisterDescription": "Registra automaticamente novos usuários após login",
|
||||
"LabelBackToUser": "Voltar para Usuário",
|
||||
"LabelBackupAudioFiles": "Backup dos Arquivos de Áudio",
|
||||
"LabelBackupLocation": "Localização do Backup",
|
||||
"LabelBackupsEnableAutomaticBackups": "Ativar backups automáticos",
|
||||
"LabelBackupsEnableAutomaticBackups": "Backups automáticos",
|
||||
"LabelBackupsEnableAutomaticBackupsHelp": "Backups salvos em /metadata/backups",
|
||||
"LabelBackupsMaxBackupSize": "Tamanho máximo do backup (em GB)",
|
||||
"LabelBackupsMaxBackupSize": "Tamanho máximo do backup (em GB) (0 para ilimitado)",
|
||||
"LabelBackupsMaxBackupSizeHelp": "Como proteção contra uma configuração incorreta, backups darão erro se excederem o tamanho configurado.",
|
||||
"LabelBackupsNumberToKeep": "Número de backups para guardar",
|
||||
"LabelBackupsNumberToKeepHelp": "Apenas 1 backup será removido por vez, então, se já existem mais backups, você deve apagá-los manualmente.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBonus": "Bônus",
|
||||
"LabelBooks": "Livros",
|
||||
"LabelButtonText": "Texto do botão",
|
||||
"LabelByAuthor": "por {0}",
|
||||
"LabelChangePassword": "Trocar Senha",
|
||||
"LabelChannels": "Canais",
|
||||
"LabelChapterCount": "{0} Capítulos",
|
||||
"LabelChapterTitle": "Título do Capítulo",
|
||||
"LabelChapters": "Capítulos",
|
||||
"LabelChaptersFound": "capítulos encontrados",
|
||||
"LabelClickForMoreInfo": "Clique para mais informações",
|
||||
"LabelClickToUseCurrentValue": "Clique para usar o valor atual",
|
||||
"LabelClosePlayer": "Fechar Reprodutor",
|
||||
"LabelCodec": "Codec",
|
||||
"LabelCollapseSeries": "Fechar Série",
|
||||
"LabelCollapseSubSeries": "Fechar Sub Séries",
|
||||
"LabelCollection": "Coleção",
|
||||
"LabelCollections": "Coleções",
|
||||
"LabelComplete": "Concluído",
|
||||
|
|
@ -260,17 +295,21 @@
|
|||
"LabelContinueListening": "Continuar Escutando",
|
||||
"LabelContinueReading": "Continuar Lendo",
|
||||
"LabelContinueSeries": "Continuar Série",
|
||||
"LabelCorsAllowed": "Origens Permitidas para CORS",
|
||||
"LabelCover": "Capa",
|
||||
"LabelCoverImageURL": "URL da Imagem da Capa",
|
||||
"LabelCoverProvider": "Provedor de Capas",
|
||||
"LabelCreatedAt": "Criado em",
|
||||
"LabelCronExpression": "Expressão para o Cron",
|
||||
"LabelCurrent": "Atual",
|
||||
"LabelCurrently": "Atualmente:",
|
||||
"LabelCustomCronExpression": "Expressão personalizada para o Cron:",
|
||||
"LabelDatetime": "Data e Hora",
|
||||
"LabelDays": "Dias",
|
||||
"LabelDeleteFromFileSystemCheckbox": "Apagar do sistema de arquivos (desmarcar para remover apenas da base de dados)",
|
||||
"LabelDescription": "Descrição",
|
||||
"LabelDeselectAll": "Desmarcar tudo",
|
||||
"LabelDetectedPattern": "Padrão detectado:",
|
||||
"LabelDevice": "Dispositivo",
|
||||
"LabelDeviceInfo": "Informação do Dispositivo",
|
||||
"LabelDeviceIsAvailableTo": "Dispositivo está disponível para...",
|
||||
|
|
@ -280,6 +319,7 @@
|
|||
"LabelDiscover": "Descobrir",
|
||||
"LabelDownload": "Download",
|
||||
"LabelDownloadNEpisodes": "Download de {0} Episódios",
|
||||
"LabelDownloadable": "Baixável",
|
||||
"LabelDuration": "Duração",
|
||||
"LabelDurationComparisonExactMatch": "(exato)",
|
||||
"LabelDurationComparisonLonger": "({0} maior)",
|
||||
|
|
@ -288,6 +328,7 @@
|
|||
"LabelEbook": "Ebook",
|
||||
"LabelEbooks": "Ebooks",
|
||||
"LabelEdit": "Editar",
|
||||
"LabelEmail": "Email",
|
||||
"LabelEmailSettingsFromAddress": "Remetente",
|
||||
"LabelEmailSettingsRejectUnauthorized": "Rejeitar certificados não autorizados",
|
||||
"LabelEmailSettingsRejectUnauthorizedHelp": "Desativar a validação de certificados SSL pode expor sua conexão a riscos de segurança, como ataques \"man-in-the-middle\". Desative essa opção apenas se entender suas consequências e se puder confiar no servidor de email ao qual você está se conectando.",
|
||||
|
|
@ -296,23 +337,48 @@
|
|||
"LabelEmailSettingsTestAddress": "Endereço de teste",
|
||||
"LabelEmbeddedCover": "Capa Integrada",
|
||||
"LabelEnable": "Habilitar",
|
||||
"LabelEncodingBackupLocation": "Um backup dos seus arquivos de áudio original será gravado em:",
|
||||
"LabelEncodingChaptersNotEmbedded": "Capítulos não são integrados em audiobooks com várias trilhas.",
|
||||
"LabelEncodingClearItemCache": "Certifique-se de, periodicamente, apagar os itens do cache.",
|
||||
"LabelEncodingFinishedM4B": "O arquivo M4B final será colocado na sua pasta de audiobooks em:",
|
||||
"LabelEncodingInfoEmbedded": "Os metadados serão integrados nas trilhas de áudio dentro da sua pasta de audiobooks.",
|
||||
"LabelEncodingStartedNavigation": "Assim que a tarefa for iniciada você pode sair dessa página.",
|
||||
"LabelEncodingTimeWarning": "A codificação pode durar até 30 minutos.",
|
||||
"LabelEncodingWarningAdvancedSettings": "Aviso: não atualize essas configurações se não estiver familiarizado com as opções de codificação do ffmpeg.",
|
||||
"LabelEncodingWatcherDisabled": "Se você desabilitou o monitoramento, será necessário fazer uma nova verificação deste audiobook depois.",
|
||||
"LabelEnd": "Fim",
|
||||
"LabelEndOfChapter": "Fim do Capítulo",
|
||||
"LabelEpisode": "Episódio",
|
||||
"LabelEpisodeNotLinkedToRssFeed": "Episódio não vinculado ao feed RSS",
|
||||
"LabelEpisodeNumber": "Episódio #{0}",
|
||||
"LabelEpisodeTitle": "Título do Episódio",
|
||||
"LabelEpisodeType": "Tipo do Episódio",
|
||||
"LabelEpisodeUrlFromRssFeed": "URL do episódio a partir do feed RSS",
|
||||
"LabelEpisodes": "Episódios",
|
||||
"LabelEpisodic": "Episódico",
|
||||
"LabelExample": "Exemplo",
|
||||
"LabelExpandSeries": "Expandir Série",
|
||||
"LabelExpandSubSeries": "Expandir Subséries",
|
||||
"LabelExpired": "Expirado",
|
||||
"LabelExpiresAt": "Expira às",
|
||||
"LabelExpiresInSeconds": "Expira em (segundos)",
|
||||
"LabelExpiresNever": "Nunca",
|
||||
"LabelExplicit": "Explícito",
|
||||
"LabelExplicitChecked": "Explícito (verificado)",
|
||||
"LabelExplicitUnchecked": "Não explícito (não verificado)",
|
||||
"LabelExportOPML": "Exportar OPML",
|
||||
"LabelFeedURL": "URL do Feed",
|
||||
"LabelFetchingMetadata": "Buscando Metadados",
|
||||
"LabelFile": "Arquivo",
|
||||
"LabelFileBirthtime": "Criação do Arquivo",
|
||||
"LabelFileBornDate": "Criado {0}",
|
||||
"LabelFileModified": "Modificação do Arquivo",
|
||||
"LabelFileModifiedDate": "Modificado {0}",
|
||||
"LabelFilename": "Nome do Arquivo",
|
||||
"LabelFilterByUser": "Filtrar por Usuário",
|
||||
"LabelFindEpisodes": "Localizar Episódios",
|
||||
"LabelFinished": "Concluído",
|
||||
"LabelFinishedDate": "Concluído {0}",
|
||||
"LabelFolder": "Pasta",
|
||||
"LabelFolders": "Pastas",
|
||||
"LabelFontBold": "Negrito",
|
||||
|
|
@ -322,13 +388,17 @@
|
|||
"LabelFontScale": "Escala de fonte",
|
||||
"LabelFontStrikethrough": "Tachado",
|
||||
"LabelFormat": "Formato",
|
||||
"LabelFull": "Cheio",
|
||||
"LabelGenre": "Gênero",
|
||||
"LabelGenres": "Gêneros",
|
||||
"LabelHardDeleteFile": "Apagar definitivamente",
|
||||
"LabelHasEbook": "Tem ebook",
|
||||
"LabelHasSupplementaryEbook": "Tem ebook complementar",
|
||||
"LabelHideSubtitles": "Esconder Legendas",
|
||||
"LabelHighestPriority": "Prioridade mais alta",
|
||||
"LabelHost": "Host",
|
||||
"LabelHour": "Hora",
|
||||
"LabelHours": "Horas",
|
||||
"LabelIcon": "Ícone",
|
||||
"LabelImageURLFromTheWeb": "URL da imagem na internet",
|
||||
"LabelInProgress": "Em Andamento",
|
||||
|
|
@ -343,30 +413,47 @@
|
|||
"LabelIntervalEvery6Hours": "A cada 6 horas",
|
||||
"LabelIntervalEveryDay": "Todo dia",
|
||||
"LabelIntervalEveryHour": "Toda hora",
|
||||
"LabelIntervalEveryMinute": "A cada minuto",
|
||||
"LabelInvert": "Inverter",
|
||||
"LabelItem": "Item",
|
||||
"LabelJumpBackwardAmount": "Tempo de retrocesso",
|
||||
"LabelJumpForwardAmount": "Tempo de avanço",
|
||||
"LabelLanguage": "Idioma",
|
||||
"LabelLanguageDefaultServer": "Idioma Padrão do Servidor",
|
||||
"LabelLanguages": "Idiomas",
|
||||
"LabelLastBookAdded": "Último Livro Acrescentado",
|
||||
"LabelLastBookUpdated": "Último Livro Atualizado",
|
||||
"LabelLastProgressDate": "Último progresso: {0}",
|
||||
"LabelLastSeen": "Visto pela Última Vez",
|
||||
"LabelLastTime": "Progresso",
|
||||
"LabelLastUpdate": "Última Atualização",
|
||||
"LabelLayout": "Layout",
|
||||
"LabelLayoutSinglePage": "Uma página",
|
||||
"LabelLayoutSplitPage": "Página dividida",
|
||||
"LabelLess": "Menos",
|
||||
"LabelLibrariesAccessibleToUser": "Bibliotecas Acessíveis ao Usuário",
|
||||
"LabelLibrary": "Biblioteca",
|
||||
"LabelLibraryFilterSublistEmpty": "Sem {0}",
|
||||
"LabelLibraryItem": "Item da Biblioteca",
|
||||
"LabelLibraryName": "Nome da Biblioteca",
|
||||
"LabelLibrarySortByProgress": "Última Atualização",
|
||||
"LabelLibrarySortByProgressFinished": "Concluído",
|
||||
"LabelLibrarySortByProgressStarted": "Progresso: Iniciado",
|
||||
"LabelLimit": "Limite",
|
||||
"LabelLineSpacing": "Espaçamento entre linhas",
|
||||
"LabelListenAgain": "Escutar novamente",
|
||||
"LabelLogLevelDebug": "Debug",
|
||||
"LabelLogLevelInfo": "Info",
|
||||
"LabelLogLevelWarn": "Atenção",
|
||||
"LabelLookForNewEpisodesAfterDate": "Procurar por novos Episódios após essa data",
|
||||
"LabelLowestPriority": "Prioridade mais baixa",
|
||||
"LabelMatchConfidence": "Confiabilidade",
|
||||
"LabelMatchExistingUsersBy": "Consultar usuários existentes usando",
|
||||
"LabelMatchExistingUsersByDescription": "Utilizado para conectar usuários já existentes. Uma vez conectados, usuários serão consultados utilizando uma identificação única do seu provedor de SSO",
|
||||
"LabelMaxEpisodesToDownload": "Número máximo de episódios para baixar. Use 0 para download ilimitado.",
|
||||
"LabelMaxEpisodesToDownloadPerCheck": "Número máximo de novos episódios para baixar por verificação",
|
||||
"LabelMaxEpisodesToKeep": "Número máximo de episódios para manter",
|
||||
"LabelMaxEpisodesToKeepHelp": "O valor 0 define que não há limite máximo. Após um novo episódio ser baixado automaticamente, o episódio mais antigo será excluído caso você tenha mais de X episódios. Apenas um episódio será excluído a cada novo download.",
|
||||
"LabelMediaPlayer": "Reprodutor de mídia",
|
||||
"LabelMediaType": "Tipo de Mídia",
|
||||
"LabelMetaTag": "Etiqueta Meta",
|
||||
|
|
@ -374,6 +461,7 @@
|
|||
"LabelMetadataOrderOfPrecedenceDescription": "Fontes de metadados de alta prioridade terão preferência sobre as fontes de metadados de prioridade baixa",
|
||||
"LabelMetadataProvider": "Fonte de Metadados",
|
||||
"LabelMinute": "Minuto",
|
||||
"LabelMinutes": "Minutos",
|
||||
"LabelMissing": "Ausente",
|
||||
"LabelMissingEbook": "Ebook não existe",
|
||||
"LabelMissingSupplementaryEbook": "Ebook complementar não existe",
|
||||
|
|
@ -389,7 +477,9 @@
|
|||
"LabelNewestAuthors": "Novos Autores",
|
||||
"LabelNewestEpisodes": "Episódios mais recentes",
|
||||
"LabelNextBackupDate": "Data do próximo backup",
|
||||
"LabelNextChapters": "Próximo capítulo será:",
|
||||
"LabelNextScheduledRun": "Próxima execução programada",
|
||||
"LabelNoApiKeys": "Sem chaves de API",
|
||||
"LabelNoCustomMetadataProviders": "Não existem fontes de metadados customizados",
|
||||
"LabelNoEpisodesSelected": "Nenhum episódio selecionado",
|
||||
"LabelNotFinished": "Não concluído",
|
||||
|
|
@ -405,17 +495,21 @@
|
|||
"LabelNotificationsMaxQueueSize": "Tamanho máximo da fila de eventos de notificação",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Eventos estão limitados a um disparo por segundo. Eventos serão ignorados se a fila estiver no tamanho máximo. Isso evita o excesso de notificações.",
|
||||
"LabelNumberOfBooks": "Número de Livros",
|
||||
"LabelNumberOfChapters": "Número de capítulos:",
|
||||
"LabelNumberOfEpisodes": "# de Episódios",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nome do claim OpenID contendo as permissões avançadas para ações do usuário na aplicação para serem aplicadas aos perfis não-administradores (<b>se configurados</b>). Se o claim não estiver presente na resposta, acesso ao ABS será negado. Se apenas uma opção estiver ausente, ela será tratada como <code>false</code>. Garanta que o claim do provedor de identidade segue a estrutura esperada:",
|
||||
"LabelOpenIDClaims": "Deixe as opções a seguir em branco para desativar a atribuição de grupos e permissões avançadas; nesse caso, o grupo 'Usuário' será atribuído automaticamente.",
|
||||
"LabelOpenIDGroupClaimDescription": "Nome do claim OpenID contendo a lista de grupos do usuário, normalmente chamada de <code>groups</code>. <b>Se configurada</b>, a aplicação atribuirá automaticamente os perfis com base na participação do usuário nos grupos, contanto que os nomes desses grupos no claim, sem distinção entre maiúsculas e minúsculas, sejam 'admin', 'user' ou 'guest'. O claim deve conter uma lista e, se o usuário pertencer a múltiplos grupos, a aplicação atribuirá o perfil correspondendo ao maior nível de acesso. Se não houver correspondência a qualquer grupo, o acesso será negado.",
|
||||
"LabelOpenRSSFeed": "Abrir Feed RSS",
|
||||
"LabelOverwrite": "Sobrescrever",
|
||||
"LabelPaginationPageXOfY": "Página {0} de {1}",
|
||||
"LabelPassword": "Senha",
|
||||
"LabelPath": "Caminho",
|
||||
"LabelPermanent": "Permanente",
|
||||
"LabelPermissionsAccessAllLibraries": "Pode Acessar Todas Bibliotecas",
|
||||
"LabelPermissionsAccessAllTags": "Pode Acessar Todas as Etiquetas",
|
||||
"LabelPermissionsAccessExplicitContent": "Pode Acessar Conteúdos Explícitos",
|
||||
"LabelPermissionsCreateEreader": "Pode criar leitor de ebooks",
|
||||
"LabelPermissionsDelete": "Pode Apagar",
|
||||
"LabelPermissionsDownload": "Pode Fazer Download",
|
||||
"LabelPermissionsUpdate": "Pode Atualizar",
|
||||
|
|
@ -423,25 +517,35 @@
|
|||
"LabelPersonalYearReview": "Sua Retrospectiva Anual ({0})",
|
||||
"LabelPhotoPathURL": "Caminho/URL para Foto",
|
||||
"LabelPlayMethod": "Método de Reprodução",
|
||||
"LabelPlaybackRateIncrementDecrement": "Valor de incremento/decremento da taxa de reprodução",
|
||||
"LabelPlayerChapterNumberMarker": "{0} de {1}",
|
||||
"LabelPlaylists": "Listas de Reprodução",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcastSearchRegion": "Região de busca do podcast",
|
||||
"LabelPodcastType": "Tipo de Podcast",
|
||||
"LabelPodcasts": "Podcasts",
|
||||
"LabelPort": "Porta",
|
||||
"LabelPrefixesToIgnore": "Prefixos para Ignorar (sem distinção entre maiúsculas e minúsculas)",
|
||||
"LabelPreventIndexing": "Evitar que o seu feed seja indexado pelos diretórios de podcast do iTunes e Google",
|
||||
"LabelPrimaryEbook": "Ebook principal",
|
||||
"LabelProgress": "Progresso",
|
||||
"LabelProvider": "Fonte",
|
||||
"LabelProviderAuthorizationValue": "Valor do Cabeçalho de Autorização",
|
||||
"LabelPubDate": "Data de Publicação",
|
||||
"LabelPublishYear": "Ano de Publicação",
|
||||
"LabelPublishedDate": "Publicado {0}",
|
||||
"LabelPublishedDecade": "Década de Publicação",
|
||||
"LabelPublishedDecades": "Décadas de Publicação",
|
||||
"LabelPublisher": "Editora",
|
||||
"LabelPublishers": "Editoras",
|
||||
"LabelRSSFeedCustomOwnerEmail": "E-mail do dono personalizado",
|
||||
"LabelRSSFeedCustomOwnerName": "Nome do dono personalizado",
|
||||
"LabelRSSFeedOpen": "Feed RSS Aberto",
|
||||
"LabelRSSFeedOpen": "Feed de RSS Aberto",
|
||||
"LabelRSSFeedPreventIndexing": "Impedir Indexação",
|
||||
"LabelRSSFeedSlug": "Slug do Feed RSS",
|
||||
"LabelRSSFeedURL": "URL do Feed RSS",
|
||||
"LabelRandomly": "Aleatoriamente",
|
||||
"LabelReAddSeriesToContinueListening": "Adicionar novamente a série à \"Continuar ouvindo\"",
|
||||
"LabelRead": "Lido",
|
||||
"LabelReadAgain": "Ler novamente",
|
||||
"LabelReadEbookWithoutProgress": "Ler ebook sem armazenar progresso",
|
||||
|
|
@ -451,29 +555,41 @@
|
|||
"LabelRedo": "Refazer",
|
||||
"LabelRegion": "Região",
|
||||
"LabelReleaseDate": "Data de Lançamento",
|
||||
"LabelRemoveAllMetadataAbs": "Remover todos os arquivos metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Remover todos os arquivos metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Remover introdução e encerramento da Audible dos capítulos",
|
||||
"LabelRemoveCover": "Remover capa",
|
||||
"LabelRemoveMetadataFile": "Remover arquivos de metadados nas pastas da biblioteca",
|
||||
"LabelRemoveMetadataFileHelp": "Remover todos os arquivos metadata.json e metadata.abs em suas {0} pastas.",
|
||||
"LabelRowsPerPage": "Linhas por Página",
|
||||
"LabelSearchTerm": "Busca por Termo",
|
||||
"LabelSearchTitle": "Busca por Título",
|
||||
"LabelSearchTitleOrASIN": "Busca por Título ou ASIN",
|
||||
"LabelSeason": "Temporada",
|
||||
"LabelSeasonNumber": "Temporada #{0}",
|
||||
"LabelSelectAll": "Selecionar todos",
|
||||
"LabelSelectAllEpisodes": "Selecionar todos os Episódios",
|
||||
"LabelSelectEpisodesShowing": "Selecionar os {0} Episódios Visíveis",
|
||||
"LabelSelectUser": "Selecionar usuário",
|
||||
"LabelSelectUsers": "Selecionar usuários",
|
||||
"LabelSendEbookToDevice": "Enviar Ebook para...",
|
||||
"LabelSequence": "Sequência",
|
||||
"LabelSerial": "Serial",
|
||||
"LabelSeries": "Série",
|
||||
"LabelSeriesName": "Nome da Série",
|
||||
"LabelSeriesProgress": "Progresso da Série",
|
||||
"LabelServerLogLevel": "Nível de Logs do Servidor",
|
||||
"LabelServerYearReview": "Retrospectiva Anual do Servidor ({0})",
|
||||
"LabelSetEbookAsPrimary": "Definir como principal",
|
||||
"LabelSetEbookAsSupplementary": "Definir como complementar",
|
||||
"LabelSettingsAllowIframe": "Permitir incorporação em iframe",
|
||||
"LabelSettingsAudiobooksOnly": "Apenas Audiobooks",
|
||||
"LabelSettingsAudiobooksOnlyHelp": "Ao ativar essa configuração os arquivos de ebooks serão ignorados a não ser que estejam dentro de uma pasta com um audiobook. Nesse caso eles serão definidos como ebooks complementares",
|
||||
"LabelSettingsBookshelfViewHelp": "Aparência esqueomorfa com prateleiras de madeira",
|
||||
"LabelSettingsChromecastSupport": "Suporte ao Chromecast",
|
||||
"LabelSettingsDateFormat": "Formato de data",
|
||||
"LabelSettingsEnableWatcher": "Monitorar automaticamente alterações nas bibliotecas",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Monitorar automaticamente alterações na biblioteca",
|
||||
"LabelSettingsEnableWatcherHelp": "Ativa o acréscimo/atualização de itens quando forem detectadas mudanças no arquivo. *Requer reiniciar o servidor",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Permitir scripts em epubs",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Permitir que arquivos epub executem scripts. É recomendado manter essa configuração desativada, a não ser que confie na fonte dos arquivos epub.",
|
||||
|
|
@ -485,6 +601,9 @@
|
|||
"LabelSettingsHideSingleBookSeriesHelp": "Séries com um só livro serão ocultadas na página de séries e na prateleira de séries na página principal.",
|
||||
"LabelSettingsHomePageBookshelfView": "Usar visão estante na página principal",
|
||||
"LabelSettingsLibraryBookshelfView": "Usar visão estante na página da biblioteca",
|
||||
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "O percentual de conclusão é maior que",
|
||||
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "O tempo restante é inferior a (segundos)",
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Marcar o item de mídia como concluído quando",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Pular livros anteriores em Continuar Série",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "A prateleira Continuar Série na página principal de exibe o primeiro livro não iniciado em uma série que tem pelo menos um livro concluído e nenhum livro em andamento. Ativar essa configuração irá continuar a série a partir do livro mais recentemente concluído ao invés do primeiro livro não iniciado.",
|
||||
"LabelSettingsParseSubtitles": "Analisar subtítulos",
|
||||
|
|
@ -502,14 +621,24 @@
|
|||
"LabelSettingsStoreMetadataWithItem": "Armazenar metadados com o item",
|
||||
"LabelSettingsStoreMetadataWithItemHelp": "Por padrão os arquivos de metadados são armazenados em /metadata/items. Ao ativar essa configuração os arquivos de metadados serão armazenadas nas pastas dos itens na sua biblioteca",
|
||||
"LabelSettingsTimeFormat": "Formato da Tempo",
|
||||
"LabelShare": "Compartilhar",
|
||||
"LabelShareDownloadableHelp": "Permitir que os usuários com o link de compartilhamento baixem um arquivo zip do item da biblioteca.",
|
||||
"LabelShareOpen": "Abrir compartilhamento",
|
||||
"LabelShareURL": "Compartilhar URL",
|
||||
"LabelShowAll": "Exibir Todos",
|
||||
"LabelShowSeconds": "Exibir segundos",
|
||||
"LabelShowSubtitles": "Mostrar Legendas",
|
||||
"LabelSize": "Tamanho",
|
||||
"LabelSleepTimer": "Timer",
|
||||
"LabelSlug": "Slug",
|
||||
"LabelSortAscending": "Crescente",
|
||||
"LabelSortDescending": "Decrescente",
|
||||
"LabelSortPubDate": "Ordenar por data de publicação",
|
||||
"LabelStart": "Iniciar",
|
||||
"LabelStartTime": "Horário do Início",
|
||||
"LabelStarted": "Iniciado",
|
||||
"LabelStartedAt": "Iniciado Em",
|
||||
"LabelStartedDate": "Iniciado {0}",
|
||||
"LabelStatsAudioTracks": "Trilhas de Áudio",
|
||||
"LabelStatsAuthors": "Autores",
|
||||
"LabelStatsBestDay": "Melhor Dia",
|
||||
|
|
@ -533,12 +662,19 @@
|
|||
"LabelTagsNotAccessibleToUser": "Etiquetas não Acessíveis Usuário",
|
||||
"LabelTasks": "Tarefas em Execuçào",
|
||||
"LabelTextEditorBulletedList": "Lista com marcadores",
|
||||
"LabelTextEditorLink": "Link",
|
||||
"LabelTextEditorNumberedList": "Lista numerada",
|
||||
"LabelTextEditorUnlink": "Remover link",
|
||||
"LabelTheme": "Tema",
|
||||
"LabelThemeDark": "Escuro",
|
||||
"LabelThemeLight": "Claro",
|
||||
"LabelThemeSepia": "Sépia",
|
||||
"LabelTimeBase": "Base de tempo",
|
||||
"LabelTimeDurationXHours": "{0} horas",
|
||||
"LabelTimeDurationXMinutes": "{0} minutos",
|
||||
"LabelTimeDurationXSeconds": "{0} segundos",
|
||||
"LabelTimeInMinutes": "Tempo em minutos",
|
||||
"LabelTimeLeft": "{0} restante",
|
||||
"LabelTimeListened": "Tempo de escuta",
|
||||
"LabelTimeListenedToday": "Tempo de escuta hoje",
|
||||
"LabelTimeRemaining": "{0} restantes",
|
||||
|
|
@ -546,6 +682,7 @@
|
|||
"LabelTitle": "Título",
|
||||
"LabelToolsEmbedMetadata": "Incluir Metadados",
|
||||
"LabelToolsEmbedMetadataDescription": "Incluir metadados no arquivo de áudio, com imagem da capa e capítulos.",
|
||||
"LabelToolsM4bEncoder": "Codificador M4B",
|
||||
"LabelToolsMakeM4b": "Gerar audiobook no formato M4B",
|
||||
"LabelToolsMakeM4bDescription": "Gerar um arquivo de audiobook no formato .M4B com metadados, imagem da capa e capítulos.",
|
||||
"LabelToolsSplitM4b": "Dividir um M4B em MP3s",
|
||||
|
|
@ -558,71 +695,105 @@
|
|||
"LabelTracksMultiTrack": "Várias trilhas",
|
||||
"LabelTracksNone": "Sem trilha",
|
||||
"LabelTracksSingleTrack": "Trilha única",
|
||||
"LabelTrailer": "Trailer",
|
||||
"LabelType": "Tipo",
|
||||
"LabelUnabridged": "Não Abreviada",
|
||||
"LabelUndo": "Desfazer",
|
||||
"LabelUnknown": "Desconhecido",
|
||||
"LabelUnknownPublishDate": "Data de publicação desconhecida",
|
||||
"LabelUpdateCover": "Atualizar Capa",
|
||||
"LabelUpdateCoverHelp": "Permite sobrescrever capas existentes para os livros selecionados quando uma consulta for localizada",
|
||||
"LabelUpdateDetails": "Atualizar Detalhes",
|
||||
"LabelUpdateDetailsHelp": "Permite sobrescrever detalhes existentes para os livros selecionados quando uma consulta for localizada",
|
||||
"LabelUpdatedAt": "Atualizado em",
|
||||
"LabelUploaderDragAndDrop": "Arraste e solte arquivos ou pastas",
|
||||
"LabelUploaderDragAndDropFilesOnly": "Arraste e solte arquivos",
|
||||
"LabelUploaderDropFiles": "Solte os arquivos",
|
||||
"LabelUploaderItemFetchMetadataHelp": "Busca título, autor e série automaticamente",
|
||||
"LabelUseAdvancedOptions": "Usar Opções Avançadas",
|
||||
"LabelUseChapterTrack": "Usar a trilha do capítulo",
|
||||
"LabelUseFullTrack": "Usar a trilha toda",
|
||||
"LabelUseZeroForUnlimited": "Use 0 para ilimitado",
|
||||
"LabelUser": "Usuário",
|
||||
"LabelUsername": "Nome do usuário",
|
||||
"LabelValue": "Valor",
|
||||
"LabelVersion": "Versão",
|
||||
"LabelViewBookmarks": "Ver marcadores",
|
||||
"LabelViewChapters": "Ver capítulos",
|
||||
"LabelViewPlayerSettings": "Ver configurações do reprodutor",
|
||||
"LabelViewQueue": "Ver fila do reprodutor",
|
||||
"LabelVolume": "Volume",
|
||||
"LabelWebRedirectURLsDescription": "Autorize esses URLs em seu provedor OAuth para permitir o redirecionamento de volta ao aplicativo web após o login:",
|
||||
"LabelWebRedirectURLsSubfolder": "Subpasta de URLs de redirecionamento",
|
||||
"LabelWeekdaysToRun": "Dias da semana para executar",
|
||||
"LabelYearReviewHide": "Ocultar Retrospectiva Anual",
|
||||
"LabelYearReviewShow": "Exibir Retrospectiva Anual",
|
||||
"LabelXBooks": "{0} livros",
|
||||
"LabelXItems": "{0} itens",
|
||||
"LabelYearReviewHide": "Ocultar Retrospectiva",
|
||||
"LabelYearReviewShow": "Exibir Retrospectiva",
|
||||
"LabelYourAudiobookDuration": "Duração do seu audiobook",
|
||||
"LabelYourBookmarks": "Seus Marcadores",
|
||||
"LabelYourPlaylists": "Suas Listas de Reprodução",
|
||||
"LabelYourProgress": "Seu Progresso",
|
||||
"MessageAddToPlayerQueue": "Adicionar à lista do reprodutor",
|
||||
"MessageAppriseDescription": "Para utilizar essa funcionalidade é preciso ter uma instância da <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API do Apprise</a> em execução ou uma api que possa tratar esses mesmos chamados. <br />A URL da API do Apprise deve conter o caminho completo da URL para enviar as notificações. Ex: se a sua instância da API estiver em <code>http://192.168.1.1:8337</code> você deve utilizar <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAppriseDescription": "Para utilizar essa funcionalidade é preciso ter uma instância da <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API do Apprise</a> em execução ou uma API que possa tratar esses mesmos chamados. <br />A URL da API do Apprise deve conter o caminho completo da URL para enviar as notificações. Ex: se a sua instância da API estiver em <code>http://192.168.1.1:8337</code> você deve utilizar <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Certifique-se de estar usando o ASIN da região correta da Audible, e não da Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Os tokens de API legados serão removidos no futuro. Use <a href=\"/config/api-keys\">Chaves de API</a> em vez disso.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Reinicie o servidor após salvar para aplicar as alterações do OIDC.",
|
||||
"MessageAuthenticationSecurityMessage": "A autenticação foi aprimorada para maior segurança. Todos os usuários precisam fazer login novamente.",
|
||||
"MessageBackupsDescription": "Backups incluem usuários, progresso dos usuários, detalhes dos itens da biblioteca, configurações do servidor e imagens armazenadas em <code>/metadata/items</code> & <code>/metadata/authors</code>. Backups <strong>não</strong> incluem quaisquer arquivos armazenados nas pastas da sua biblioteca.",
|
||||
"MessageBackupsLocationEditNote": "Observação: Atualizar o local de backup não moverá nem modificará os backups existentes",
|
||||
"MessageBackupsLocationNoEditNote": "Observação: o local de backup é definido por meio de uma variável de ambiente e não pode ser alterado aqui.",
|
||||
"MessageBackupsLocationPathEmpty": "O caminho do local de backup não pode ser vazio",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Preencha os campos habilitados com dados de todos os itens. Os campos com múltiplos valores serão mesclados",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "Preencha os campos de detalhes do mapa habilitados com dados deste item",
|
||||
"MessageBatchQuickMatchDescription": "Consulta Rápida tentará adicionar capas e metadados ausentes para os itens selecionados. Ative as opções abaixo para permitir que a Consulta Rápida sobrescreva capas e/ou metadados existentes.",
|
||||
"MessageBookshelfNoCollections": "Você ainda não criou coleções",
|
||||
"MessageBookshelfNoCollectionsHelp": "As coleções são públicas. Todos os usuários com acesso à biblioteca podem vê-las.",
|
||||
"MessageBookshelfNoRSSFeeds": "Não existem feeds RSS abertos",
|
||||
"MessageBookshelfNoResultsForFilter": "Sem Resultados para o filtro \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Sem resultados para a consulta",
|
||||
"MessageBookshelfNoSeries": "Você não tem séries",
|
||||
"MessageBulkChapterPattern": "Quantos capítulos você gostaria de adicionar seguindo esse padrão de numeração?",
|
||||
"MessageChapterEndIsAfter": "O final do capítulo está além do final do seu audiobook",
|
||||
"MessageChapterErrorFirstNotZero": "O primeiro capítulo precisa começar no 0",
|
||||
"MessageChapterErrorStartGteDuration": "Tempo de início não é válido pois precisa ser menor do que a duração do audioboook",
|
||||
"MessageChapterErrorStartLtPrev": "Tempo de início não é válido pois precisa ser igual ou maior que o tempo de início do capítulo anterior",
|
||||
"MessageChapterStartIsAfter": "Início do capítulo está além do final do seu audiobook",
|
||||
"MessageChaptersNotFound": "Capítulos não encontrados",
|
||||
"MessageCheckingCron": "Verificando o cron...",
|
||||
"MessageConfirmCloseFeed": "Tem certeza de que deseja fechar esse feed?",
|
||||
"MessageConfirmDeleteApiKey": "Tem certeza de que deseja excluir a chave de API \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Tem certeza de que deseja apagar o backup {0}?",
|
||||
"MessageConfirmDeleteDevice": "Tem certeza de que deseja excluir o leitor de ebook \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Essa ação apagará o arquivo do seu sistema de arquivos. Tem certeza?",
|
||||
"MessageConfirmDeleteLibrary": "Tem certeza de que deseja apagar a biblioteca \"{0}\" definitivamente?",
|
||||
"MessageConfirmDeleteLibraryItem": "Essa ação apagará o item da biblioteca do banco de dados e do seu sistema de arquivos. Tem certeza?",
|
||||
"MessageConfirmDeleteLibraryItems": "Essa ação apagará {0} itens da biblioteca do banco de dados e do seu sistema de arquivos. Tem certeza?",
|
||||
"MessageConfirmDeleteMetadataProvider": "Tem certeza de que deseja excluir o provedor de metadados personalizado \"{0}\"?",
|
||||
"MessageConfirmDeleteNotification": "Tem certeza de que deseja excluir esta notificação?",
|
||||
"MessageConfirmDeleteSession": "Tem certeza de que deseja apagar essa sessão?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Tem certeza de que deseja incorporar metadados em arquivos de áudio {0}?",
|
||||
"MessageConfirmForceReScan": "Tem certeza de que deseja forçar a nova verificação?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Tem certeza de que deseja marcar todos os episódios como concluídos?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Tem certeza de que deseja marcar todos os episódios como não concluídos?",
|
||||
"MessageConfirmMarkItemFinished": "Tem certeza de que deseja marcar \"{0}\" como concluído?",
|
||||
"MessageConfirmMarkItemNotFinished": "Tem certeza de que deseja marcar \"{0}\" como não concluído?",
|
||||
"MessageConfirmMarkSeriesFinished": "Tem certeza de que deseja marcar todos os livros nesta série como concluídos?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Tem certeza de que deseja marcar todos os livros nesta série como não concluídos?",
|
||||
"MessageConfirmNotificationTestTrigger": "Acionar esta notificação com dados de teste?",
|
||||
"MessageConfirmPurgeCache": "Apagar o cache irá apagar o diretório todo localizado em <code>/metadata/cache</code>. <br /><br />Tem certeza que deseja apagar o diretório de cache?",
|
||||
"MessageConfirmPurgeItemsCache": "Apagar o cache de itens irá apagar todo conteúdo da pasta <code>/metadata/cache/items</code>.<br />Tem certeza?",
|
||||
"MessageConfirmQuickEmbed": "Aviso! Inclusão rápida não fará backup dos seus arquivos de áudio. Verifique se tem um backup dos seus arquivos de áudio. <br><br>Quer continuar?",
|
||||
"MessageConfirmQuickMatchEpisodes": "A correspondência rápida de episódios sobrescreverá os detalhes se uma correspondência for encontrada. Somente os episódios sem correspondência serão atualizados. Tem certeza?",
|
||||
"MessageConfirmReScanLibraryItems": "Tem certeza de que deseja uma nova verificação de {0} itens?",
|
||||
"MessageConfirmRemoveAllChapters": "Tem certeza de que deseja remover todos os capítulos?",
|
||||
"MessageConfirmRemoveAuthor": "Tem certeza de que deseja remover o autor \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Tem certeza de que deseja remover a coleção \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Tem certeza de que deseja remover o episódio \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodeNote": "Observação: Isso não exclui o arquivo de áudio, a menos que você ative a opção \"Excluir arquivo permanentemente\"",
|
||||
"MessageConfirmRemoveEpisodes": "Tem certeza de que deseja remover os {0} episódios?",
|
||||
"MessageConfirmRemoveListeningSessions": "Tem certeza de que deseja remover as {0} sessões de escuta?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Tem certeza de que deseja remover todos os arquivos metadata.{0} nas pastas dos itens da sua biblioteca?",
|
||||
"MessageConfirmRemoveNarrator": "Tem certeza de que deseja remover o narrador \"{0}\"?",
|
||||
"MessageConfirmRemovePlaylist": "Tem certeza de que deseja remover a sua lista de reprodução \"{0}\"?",
|
||||
"MessageConfirmRenameGenre": "Tem certeza de que deseja renomear o gênero \"{0}\" para \"{1}\" em todos os itens?",
|
||||
|
|
@ -631,19 +802,27 @@
|
|||
"MessageConfirmRenameTag": "Tem certeza de que deseja renomear a etiqueta \"{0}\" para \"{1}\" em todos os itens?",
|
||||
"MessageConfirmRenameTagMergeNote": "Aviso: Esta etiqueta já existe então elas serão combinadas.",
|
||||
"MessageConfirmRenameTagWarning": "Atenção! Uma etiqueta com um nome semelhante já existe \"{0}\".",
|
||||
"MessageConfirmResetProgress": "Tem certeza de que deseja redefinir seu progresso?",
|
||||
"MessageConfirmSendEbookToDevice": "Tem certeza de que deseja enviar {0} ebook(s) \"{1}\" para o dispositivo \"{2}\"?",
|
||||
"MessageConfirmUnlinkOpenId": "Tem certeza de que deseja desvincular este usuário do OpenID?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} dias ouvidos no último ano",
|
||||
"MessageDownloadingEpisode": "Realizando o download do episódio",
|
||||
"MessageDragFilesIntoTrackOrder": "Arraste os arquivos para ordenar as trilhas corretamente",
|
||||
"MessageEmbedFailed": "Falha ao incorporar!",
|
||||
"MessageEmbedFinished": "Inclusão Concluída!",
|
||||
"MessageEmbedQueue": "Enfileirado para incorporação de metadados ({0} na fila)",
|
||||
"MessageEpisodesQueuedForDownload": "{0} Episódio(s) na fila de download",
|
||||
"MessageEreaderDevices": "Para garantir a entrega dos ebooks, você pode precisar adicionar o endereço de email acima como um remetente válido para cada um dos dispositivos listados abaixo.",
|
||||
"MessageFeedURLWillBe": "URL do Feed será {0}",
|
||||
"MessageFetching": "Buscando...",
|
||||
"MessageForceReScanDescription": "verificará todos os arquivos, como uma verificação nova. Etiquetas ID3 de arquivos de áudio, arquivos OPF e arquivos de texto serão tratados como novos.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} ouvindo</strong> em {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Nenhuma sessão de reprodução em {0}",
|
||||
"MessageImportantNotice": "Aviso Importante!",
|
||||
"MessageInsertChapterBelow": "Inserir capítulo abaixo",
|
||||
"MessageItemsSelected": "{0} Itens Selecionados",
|
||||
"MessageItemsUpdated": "{0} Itens Atualizados",
|
||||
"MessageInvalidAsin": "ASIN inválido",
|
||||
"MessageItemsSelected": "{0} itens selecionados",
|
||||
"MessageItemsUpdated": "{0} itens atualizados",
|
||||
"MessageJoinUsOn": "Junte-se a nós",
|
||||
"MessageLoading": "Carregando...",
|
||||
"MessageLoadingFolders": "Carregando pastas...",
|
||||
|
|
@ -664,6 +843,7 @@
|
|||
"MessageNoCollections": "Sem Coleções",
|
||||
"MessageNoCoversFound": "Nenhuma Capa Encontrada",
|
||||
"MessageNoDescription": "Sem Descrições",
|
||||
"MessageNoDevices": "Nenhum dispositivo",
|
||||
"MessageNoDownloadsInProgress": "Não existem downloads em andamento",
|
||||
"MessageNoDownloadsQueued": "Não existem itens na fila de download",
|
||||
"MessageNoEpisodeMatchesFound": "Não existem episódios correspondentes",
|
||||
|
|
@ -677,6 +857,7 @@
|
|||
"MessageNoLogs": "Sem Logs",
|
||||
"MessageNoMediaProgress": "Sem Progresso de Mídia",
|
||||
"MessageNoNotifications": "Sem Notificações",
|
||||
"MessageNoPodcastFeed": "Podcast inválido: Sem feed",
|
||||
"MessageNoPodcastsFound": "Nenhum podcast encontrado",
|
||||
"MessageNoResults": "Sem resultados",
|
||||
"MessageNoSearchResultsFor": "Sem resultados para \"{0}\"",
|
||||
|
|
@ -685,12 +866,19 @@
|
|||
"MessageNoTasksRunning": "Sem Tarefas em Execução",
|
||||
"MessageNoUpdatesWereNecessary": "Nenhuma atualização é necessária",
|
||||
"MessageNoUserPlaylists": "Você não tem listas de reprodução",
|
||||
"MessageNoUserPlaylistsHelp": "As listas de reprodução são privadas. Somente o usuário que as criou pode vê-las.",
|
||||
"MessageNotYetImplemented": "Ainda não implementado",
|
||||
"MessageOpmlPreviewNote": "Nota: esta é uma visualização do arquivo OPML processado. O título verdadeiro do podcast será recuperado do feed RSS.",
|
||||
"MessageOr": "ou",
|
||||
"MessagePauseChapter": "Pausar reprodução do capítulo",
|
||||
"MessagePlayChapter": "Escutar o início do capítulo",
|
||||
"MessagePlaylistCreateFromCollection": "Criar uma lista de reprodução a partir da coleção",
|
||||
"MessagePleaseWait": "Por favor, aguarde...",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "Podcast não tem uma URL do feed RSS para ser usada na consulta",
|
||||
"MessagePodcastSearchField": "Digite um termo para a busca ou a URL de um feed RSS",
|
||||
"MessageQuickEmbedInProgress": "Incorporação rápida em andamento",
|
||||
"MessageQuickEmbedQueue": "Enfileirado para incorporação rápida ({0} na fila)",
|
||||
"MessageQuickMatchAllEpisodes": "Correspondência Rápida de Todos os Episódios",
|
||||
"MessageQuickMatchDescription": "Preenche detalhes vazios do item & capa com o primeiro resultado de '{0}'. Não sobrescreve detalhes a não ser que a configuração 'Preferir metadados consultados' do servidor esteja ativa.",
|
||||
"MessageRemoveChapter": "Remover capítulo",
|
||||
"MessageRemoveEpisodes": "Remover {0} episódio(s)",
|
||||
|
|
@ -700,11 +888,52 @@
|
|||
"MessageResetChaptersConfirm": "Tem certeza de que deseja resetar os capítulos e desfazer as alterações realizadas?",
|
||||
"MessageRestoreBackupConfirm": "Tem certeza de que deseja restaurar o backup criado em",
|
||||
"MessageRestoreBackupWarning": "Restaurar um backup sobrescreverá totalmente o banco de dados localizado em /config e as imagens de capa em /metadata/items & /metadata/authors.<br /><br />Backups não alteram quaisquer arquivos nas pastas da sua biblioteca. Se a configuração do servidor de armazenar a arte da capa e os metadados nas pastas da sua biblioteca estiver ativa, esses itens não estão no backup e não serão sobrescritos.<br /><br />Todos os clientes usando o seu servidor serão atualizados automaticamente.",
|
||||
"MessageScheduleLibraryScanNote": "Para a maioria dos usuários, é recomendável deixar este recurso desativado e manter a configuração \"Monitorar automaticamente alterações na biblioteca\" ativada. Dessa forma alterações nas pastas da sua biblioteca serão automáticamente detectadas. Habilite essa opção se \"Monitorar automaticamente alterações na biblioteca\" não fucnionara para o seu sistema de arquivos (Como NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Executar a cada {0} às {1}",
|
||||
"MessageSearchResultsFor": "Resultado da busca por",
|
||||
"MessageSelected": "{0} selecionado(s)",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "O identificador da série não pode conter espaços",
|
||||
"MessageServerCouldNotBeReached": "Não foi possível estabelecer conexão com o servidor",
|
||||
"MessageSetChaptersFromTracksDescription": "Definir os capítulos usando cada arquivo de áudio como um capítulo e o nome do arquivo como o título do capítulo",
|
||||
"MessageShareExpirationWillBe": "Válido até <strong>{0}</strong>",
|
||||
"MessageShareExpiresIn": "Expira em {0}",
|
||||
"MessageShareURLWillBe": "A URL de compartilhamento será <strong>{0}</strong>",
|
||||
"MessageStartPlaybackAtTime": "Iniciar a reprodução de \"{0}\" em {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "O arquivo de áudio \"{0}\" não pode ser gravado",
|
||||
"MessageTaskCanceledByUser": "Tarefa cancelada pelo usuário",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Baixando episódio \"{0}\"",
|
||||
"MessageTaskEmbeddingMetadata": "Incorporação de metadados",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Incorporando metadados no audiolivro \"{0}\"",
|
||||
"MessageTaskEncodingM4b": "Codificação M4B",
|
||||
"MessageTaskEncodingM4bDescription": "Codificação do audiolivro \"{0}\" em um único arquivo m4b",
|
||||
"MessageTaskFailed": "Falhou",
|
||||
"MessageTaskFailedToBackupAudioFile": "Falha ao fazer backup do arquivo de áudio \"{0}\"",
|
||||
"MessageTaskFailedToCreateCacheDirectory": "Falha ao criar o diretório de cache",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "Falha ao incorporar metadados no arquivo \"{0}\"",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Falha ao mesclar arquivos de áudio",
|
||||
"MessageTaskFailedToMoveM4bFile": "Falha ao mover o arquivo m4b",
|
||||
"MessageTaskFailedToWriteMetadataFile": "Falha ao gravar o arquivo de metadados",
|
||||
"MessageTaskMatchingBooksInLibrary": "Livros correspondentes na biblioteca \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Não há arquivos para verificar",
|
||||
"MessageTaskOpmlImport": "Importação OPML",
|
||||
"MessageTaskOpmlImportDescription": "Criando podcasts a partir de feeds RSS {0}",
|
||||
"MessageTaskOpmlImportFeed": "Feed de importação OPML",
|
||||
"MessageTaskOpmlImportFeedDescription": "Importando o feed RSS \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedFailed": "Não foi possível obter o feed do podcast",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Criando podcast \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "O podcast já existe no caminho",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Falha ao criar o podcast",
|
||||
"MessageTaskOpmlImportFinished": "Adicionados {0} podcasts",
|
||||
"MessageTaskOpmlParseFailed": "Falha ao analisar o arquivo OPML",
|
||||
"MessageTaskOpmlParseFastFail": "Arquivo OPML inválido. Tag <opml> não encontrada OU tag <outline> não encontrada",
|
||||
"MessageTaskOpmlParseNoneFound": "Nenhum feed encontrado no arquivo OPML",
|
||||
"MessageTaskScanItemsAdded": "{0} adicionado",
|
||||
"MessageTaskScanItemsMissing": "{0} não encontrado",
|
||||
"MessageTaskScanItemsUpdated": "{0} atualizado",
|
||||
"MessageTaskScanNoChangesNeeded": "Nenhuma alteração necessária",
|
||||
"MessageTaskScanningFileChanges": "Verificando alterações de arquivo em \"{0}\"",
|
||||
"MessageTaskScanningLibrary": "Analisando a biblioteca \"{0}\"",
|
||||
"MessageTaskTargetDirectoryNotWritable": "Diretório de destino sem permissão de escrita",
|
||||
"MessageThinking": "Pensando...",
|
||||
"MessageUploaderItemFailed": "Falha no upload",
|
||||
"MessageUploaderItemSuccess": "Upload realizado!",
|
||||
|
|
@ -722,43 +951,117 @@
|
|||
"NoteUploaderFoldersWithMediaFiles": "Pastas com arquivos de mídia serão tratadas como itens de biblioteca distintos.",
|
||||
"NoteUploaderOnlyAudioFiles": "Ao subir apenas arquivos de áudio, cada arquivo será tratado como um audiobook distinto.",
|
||||
"NoteUploaderUnsupportedFiles": "Arquivos não suportados serão ignorados. Ao escolher ou arrastar uma pasta, outros arquivos que não estão em uma pasta dentro do item serão ignorados.",
|
||||
"NotificationOnBackupCompletedDescription": "Acionado quando um backup é concluído",
|
||||
"NotificationOnBackupFailedDescription": "Acionado quando um backup falha",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Acionado quando um episódio de podcast é baixado automaticamente",
|
||||
"NotificationOnRSSFeedDisabledDescription": "Acionado quando os downloads automáticos de episódios são desativados devido a muitas tentativas falhas",
|
||||
"NotificationOnRSSFeedFailedDescription": "Acionado quando a solicitação do feed RSS falha durante o download automático de um episódio",
|
||||
"NotificationOnTestDescription": "Evento para testar o sistema de notificação",
|
||||
"PlaceholderBulkChapterInput": "Digite o título de um capítulo ou use uma numeração (por exemplo, 'Episódio 1', 'Capítulo 10', '1.')",
|
||||
"PlaceholderNewCollection": "Novo nome da coleção",
|
||||
"PlaceholderNewFolderPath": "Novo caminho para a pasta",
|
||||
"PlaceholderNewPlaylist": "Novo nome da lista de reprodução",
|
||||
"PlaceholderSearch": "Buscar..",
|
||||
"PlaceholderSearchEpisode": "Buscar Episódio..",
|
||||
"StatsAuthorsAdded": "autores adicionados",
|
||||
"StatsBooksAdded": "livros adicionados",
|
||||
"StatsBooksAdditional": "Algumas adições incluem…",
|
||||
"StatsBooksFinished": "livros concluídos",
|
||||
"StatsBooksFinishedThisYear": "Alguns livros foram finalizados este ano…",
|
||||
"StatsBooksListenedTo": "livros ouvidos",
|
||||
"StatsCollectionGrewTo": "Sua coleção de livros cresceu para…",
|
||||
"StatsSessions": "sessões",
|
||||
"StatsSpentListening": "tempo gasto ouvindo",
|
||||
"StatsTopAuthor": "TOP AUTOR",
|
||||
"StatsTopAuthors": "TOP AUTORES",
|
||||
"StatsTopGenre": "PRINCIPAL GÊNERO",
|
||||
"StatsTopGenres": "PRINCIPAL GÊNEROS",
|
||||
"StatsTopMonth": "PRINCIPAL MÊS",
|
||||
"StatsTopNarrator": "PRINCIPAL NARRADOR",
|
||||
"StatsTopNarrators": "PRINCIPAIS NARRADORES",
|
||||
"StatsTotalDuration": "Com duração total de…",
|
||||
"StatsYearInReview": "RESUMO DO ANO",
|
||||
"ToastAccountUpdateSuccess": "Conta atualizada",
|
||||
"ToastAppriseUrlRequired": "É preciso digitar uma URL Apprise",
|
||||
"ToastAsinRequired": "É necessário o ASIN",
|
||||
"ToastAuthorImageRemoveSuccess": "Imagem do autor removida",
|
||||
"ToastAuthorNotFound": "Autor \"{0}\" não encontrado",
|
||||
"ToastAuthorRemoveSuccess": "Autor removido",
|
||||
"ToastAuthorSearchNotFound": "Autor não encontrado",
|
||||
"ToastAuthorUpdateMerged": "Autor combinado",
|
||||
"ToastAuthorUpdateSuccess": "Autor atualizado",
|
||||
"ToastAuthorUpdateSuccessNoImageFound": "Autor atualizado (nenhuma imagem encontrada)",
|
||||
"ToastBackupAppliedSuccess": "Backup aplicado",
|
||||
"ToastBackupCreateFailed": "Falha ao criar backup",
|
||||
"ToastBackupCreateSuccess": "Backup criado",
|
||||
"ToastBackupDeleteFailed": "Falha ao apagar backup",
|
||||
"ToastBackupDeleteSuccess": "Backup apagado",
|
||||
"ToastBackupInvalidMaxKeep": "Número inválido de backups a serem mantidos",
|
||||
"ToastBackupInvalidMaxSize": "Tamanho máximo de backup inválido",
|
||||
"ToastBackupRestoreFailed": "Falha ao restaurar backup",
|
||||
"ToastBackupUploadFailed": "Falha no upload do backup",
|
||||
"ToastBackupUploadSuccess": "Upload do backup realizado",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Detalhes aplicados aos itens",
|
||||
"ToastBatchDeleteFailed": "A exclusão em lote falhou",
|
||||
"ToastBatchDeleteSuccess": "Exclusão em lote concluída com sucesso",
|
||||
"ToastBatchQuickMatchFailed": "A correspondência rápida em lote falhou!",
|
||||
"ToastBatchQuickMatchStarted": "Correspondência rápida em lote de {0} livros iniciada!",
|
||||
"ToastBatchUpdateFailed": "Falha na atualização em lote",
|
||||
"ToastBatchUpdateSuccess": "Atualização em lote realizada",
|
||||
"ToastBookmarkCreateFailed": "Falha ao criar marcador",
|
||||
"ToastBookmarkCreateSuccess": "Marcador adicionado",
|
||||
"ToastBookmarkRemoveSuccess": "Marcador removido",
|
||||
"ToastBulkChapterInvalidCount": "Digite um número entre 1 e 150",
|
||||
"ToastCachePurgeFailed": "Falha ao apagar o cache",
|
||||
"ToastCachePurgeSuccess": "Cache apagado com sucesso",
|
||||
"ToastChapterLocked": "Capítulo bloqueado.",
|
||||
"ToastChapterStartTimeAdjusted": "O horário de início do capítulo foi ajustado em {0} segundos",
|
||||
"ToastChaptersAllLocked": "Todos os capítulos estão bloqueados. Desbloqueie alguns capítulos para alterar seus horários.",
|
||||
"ToastChaptersHaveErrors": "Capítulos com erro",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Quantidade de deslocamento inválida. O horário de início do último capítulo ultrapassaria a duração deste audiolivro.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Valor de deslocamento inválido. O primeiro capítulo teria duração zero ou negativa e seria sobrescrito pelo segundo capítulo. Aumente a duração inicial do segundo capítulo.",
|
||||
"ToastChaptersMustHaveTitles": "Capítulos precisam ter títulos",
|
||||
"ToastChaptersRemoved": "Capítulos removidos",
|
||||
"ToastChaptersUpdated": "Capítulos atualizados",
|
||||
"ToastCollectionItemsAddFailed": "Falha ao adicionar itens à coleção",
|
||||
"ToastCollectionRemoveSuccess": "Coleção removida",
|
||||
"ToastCollectionUpdateSuccess": "Coleção atualizada",
|
||||
"ToastConnectionNotAvailable": "Conexão indisponível. Tente novamente mais tarde",
|
||||
"ToastCoverSearchFailed": "A busca pela capa falhou",
|
||||
"ToastCoverUpdateFailed": "Falha na atualização da capa",
|
||||
"ToastDateTimeInvalidOrIncomplete": "A data e a hora são inválidas ou estão incompletas",
|
||||
"ToastDeleteFileFailed": "Falha ao apagar arquivo",
|
||||
"ToastDeleteFileSuccess": "Arquivo apagado",
|
||||
"ToastDeviceAddFailed": "Falha ao adicionar dispositivo",
|
||||
"ToastDeviceNameAlreadyExists": "Já existe um leitor de ebook com esse nome",
|
||||
"ToastDeviceTestEmailFailed": "Falha ao enviar o e-mail de teste",
|
||||
"ToastDeviceTestEmailSuccess": "E-mail de teste enviado",
|
||||
"ToastEmailSettingsUpdateSuccess": "Configurações de e-mail atualizadas",
|
||||
"ToastEncodeCancelFailed": "Falha ao cancelar a codificação",
|
||||
"ToastEncodeCancelSucces": "Codificação cancelada",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Falha ao limpar a fila",
|
||||
"ToastEpisodeDownloadQueueClearSuccess": "Fila de downloads de episódios limpa",
|
||||
"ToastEpisodeUpdateSuccess": "{0} episódios atualizados",
|
||||
"ToastErrorCannotShare": "Não é possível compartilhar nativamente neste dispositivo",
|
||||
"ToastFailedToCreate": "Falha ao criar",
|
||||
"ToastFailedToDelete": "Falha ao excluir",
|
||||
"ToastFailedToLoadData": "Falha ao carregar dados",
|
||||
"ToastFailedToMatch": "Não foi possível encontrar correspondência",
|
||||
"ToastFailedToShare": "Não foi possível compartilhar",
|
||||
"ToastFailedToUpdate": "Falha ao atualizar",
|
||||
"ToastInvalidImageUrl": "URL de imagem inválida",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Número máximo de episódios para baixar inválido",
|
||||
"ToastInvalidUrl": "URL inválida",
|
||||
"ToastInvalidUrls": "Um ou mais URLs são inválidos",
|
||||
"ToastItemCoverUpdateSuccess": "Capa do item atualizada",
|
||||
"ToastItemDeletedFailed": "Falha ao excluir o item",
|
||||
"ToastItemDeletedSuccess": "Item excluído",
|
||||
"ToastItemDetailsUpdateSuccess": "Detalhes do item atualizados",
|
||||
"ToastItemMarkedAsFinishedFailed": "Falha ao marcar como Concluído",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Item marcado como Concluído",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "Falha ao marcar como Não Concluído",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Item marcado como Não Concluído",
|
||||
"ToastItemUpdateSuccess": "Item atualizado",
|
||||
"ToastLibraryCreateFailed": "Falha ao criar biblioteca",
|
||||
"ToastLibraryCreateSuccess": "Biblioteca \"{0}\" criada",
|
||||
"ToastLibraryDeleteFailed": "Falha ao apagar biblioteca",
|
||||
|
|
@ -766,28 +1069,97 @@
|
|||
"ToastLibraryScanFailedToStart": "Falha ao iniciar verificação",
|
||||
"ToastLibraryScanStarted": "Verificação da biblioteca iniciada",
|
||||
"ToastLibraryUpdateSuccess": "Biblioteca \"{0}\" atualizada",
|
||||
"ToastMatchAllAuthorsFailed": "Não foi possível encontrar correspondência para todos os autores",
|
||||
"ToastMetadataFilesRemovedError": "Erro ao remover arquivos de metadados.{0}",
|
||||
"ToastMetadataFilesRemovedNoneFound": "Nenhum arquivo metadados.{0} encontrado na biblioteca",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "Nenhum arquivo metadados.{0} removido",
|
||||
"ToastMetadataFilesRemovedSuccess": "{0} arquivos metadados.{1} removidos",
|
||||
"ToastMustHaveAtLeastOnePath": "Deve ter pelo menos um caminho",
|
||||
"ToastNameEmailRequired": "Nome e e-mail são obrigatórios",
|
||||
"ToastNameRequired": "O nome é obrigatório",
|
||||
"ToastNewApiKeyUserError": "É necessário selecionar um usuário",
|
||||
"ToastNewEpisodesFound": "{0} novos episódios encontrados",
|
||||
"ToastNewUserCreatedFailed": "Falha ao criar a conta: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Nova conta criada",
|
||||
"ToastNewUserLibraryError": "É necessário selecionar pelo menos uma biblioteca",
|
||||
"ToastNewUserPasswordError": "É obrigatória a criação de uma senha; somente o usuário root pode ter uma senha vazia",
|
||||
"ToastNewUserTagError": "É necessário selecionar pelo menos uma etiqueta",
|
||||
"ToastNewUserUsernameError": "Digite um nome de usuário",
|
||||
"ToastNoNewEpisodesFound": "Nenhum episódio novo encontrado",
|
||||
"ToastNoRSSFeed": "O Podcast não possui um feed RSS",
|
||||
"ToastNoUpdatesNecessary": "Nenhuma atualização necessária",
|
||||
"ToastNotificationCreateFailed": "Falha ao criar notificação",
|
||||
"ToastNotificationDeleteFailed": "Falha ao excluir a notificação",
|
||||
"ToastNotificationFailedMaximum": "O número máximo de tentativas falhas deve ser >= 0",
|
||||
"ToastNotificationQueueMaximum": "A fila máxima de notificações deve ser >= 0",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Configurações de notificação atualizadas",
|
||||
"ToastNotificationTestTriggerFailed": "Falha ao acionar a notificação de teste",
|
||||
"ToastNotificationTestTriggerSuccess": "Notificação de teste acionada",
|
||||
"ToastNotificationUpdateSuccess": "Notificação atualizada",
|
||||
"ToastPlaylistCreateFailed": "Falha ao criar lista de reprodução",
|
||||
"ToastPlaylistCreateSuccess": "Lista de reprodução criada",
|
||||
"ToastPlaylistRemoveSuccess": "Lista de reprodução removida",
|
||||
"ToastPlaylistUpdateSuccess": "Lista de reprodução atualizada",
|
||||
"ToastPodcastCreateFailed": "Falha ao criar podcast",
|
||||
"ToastPodcastCreateSuccess": "Podcast criado",
|
||||
"ToastPodcastEpisodeUpdated": "Episódio atualizado",
|
||||
"ToastPodcastGetFeedFailed": "Não foi possível obter o feed do podcast",
|
||||
"ToastPodcastNoEpisodesInFeed": "Nenhum episódio encontrado no feed RSS",
|
||||
"ToastPodcastNoRssFeed": "O podcast não possui um feed RSS",
|
||||
"ToastProgressIsNotBeingSynced": "O progresso não está sendo sincronizado, reinicie a reprodução",
|
||||
"ToastProviderCreatedFailed": "Falha ao adicionar o provedor",
|
||||
"ToastProviderCreatedSuccess": "Novo provedor adicionado",
|
||||
"ToastProviderNameAndUrlRequired": "Nome e URL obrigatórios",
|
||||
"ToastProviderRemoveSuccess": "Fornecedor removido",
|
||||
"ToastRSSFeedCloseFailed": "Falha ao fechar feed RSS",
|
||||
"ToastRSSFeedCloseSuccess": "Feed RSS fechado",
|
||||
"ToastRemoveFailed": "Falha ao remover",
|
||||
"ToastRemoveItemFromCollectionFailed": "Falha ao remover item da coleção",
|
||||
"ToastRemoveItemFromCollectionSuccess": "Item removido da coleção",
|
||||
"ToastRemoveItemsWithIssuesFailed": "Falha ao remover itens da biblioteca com problemas",
|
||||
"ToastRemoveItemsWithIssuesSuccess": "Itens da biblioteca com problemas foram removidos",
|
||||
"ToastRenameFailed": "Falha ao renomear",
|
||||
"ToastRescanFailed": "Falha na nova verificação para {0}",
|
||||
"ToastRescanRemoved": "O item foi removido após a digitalização ser concluída",
|
||||
"ToastRescanUpToDate": "A nova verificação completou o item, que estava atualizado",
|
||||
"ToastRescanUpdated": "O item foi atualizado após a digitalização",
|
||||
"ToastScanFailed": "Falha ao digitalizar o item da biblioteca",
|
||||
"ToastSelectAtLeastOneUser": "Selecione pelo menos um usuário",
|
||||
"ToastSendEbookToDeviceFailed": "Falha ao enviar ebook para dispositivo",
|
||||
"ToastSendEbookToDeviceSuccess": "Ebook enviado para o dispositivo \"{0}\"",
|
||||
"ToastSeriesSubmitFailedSameName": "Não é possível adicionar duas séries com o mesmo nome",
|
||||
"ToastSeriesUpdateFailed": "Falha ao atualizar série",
|
||||
"ToastSeriesUpdateSuccess": "Série atualizada",
|
||||
"ToastServerSettingsUpdateSuccess": "Configurações do servidor atualizadas",
|
||||
"ToastSessionCloseFailed": "Falha ao encerrar a sessão",
|
||||
"ToastSessionDeleteFailed": "Falha ao apagar sessão",
|
||||
"ToastSessionDeleteSuccess": "Sessão apagada",
|
||||
"ToastSleepTimerDone": "Temporizador de sono concluído... zZzzZz",
|
||||
"ToastSlugMustChange": "O slug possui caracteres inválidos",
|
||||
"ToastSlugRequired": "Slug é necessário",
|
||||
"ToastSocketConnected": "Socket conectado",
|
||||
"ToastSocketDisconnected": "Socket desconectado",
|
||||
"ToastSocketFailedToConnect": "Falha na conexão do socket",
|
||||
"ToastSortingPrefixesEmptyError": "É preciso ter pelo menos um prefixo de ordenação",
|
||||
"ToastSortingPrefixesUpdateSuccess": "Prefixos de ordenação atualizados ({0} item(ns))",
|
||||
"ToastTitleRequired": "É necessário ter um título",
|
||||
"ToastUnknownError": "Erro desconhecido",
|
||||
"ToastUnlinkOpenIdFailed": "Falha ao desvincular o usuário do OpenID",
|
||||
"ToastUnlinkOpenIdSuccess": "Usuário desvinculado do OpenID",
|
||||
"ToastUploaderFilepathExistsError": "O caminho de arquivo \"{0}\" já existe no servidor",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "O item \"{0}\" está usando um subdiretório do caminho de upload.",
|
||||
"ToastUserDeleteFailed": "Falha ao apagar usuário",
|
||||
"ToastUserDeleteSuccess": "Usuário apagado"
|
||||
"ToastUserDeleteSuccess": "Usuário apagado",
|
||||
"ToastUserPasswordChangeSuccess": "Senha alterada com sucesso",
|
||||
"ToastUserPasswordMismatch": "As senhas não coincidem",
|
||||
"ToastUserPasswordMustChange": "A nova senha não pode ser igual à senha antiga",
|
||||
"ToastUserRootRequireName": "É preciso entrar com um nome de usuário root",
|
||||
"TooltipAddChapters": "Adicionar capítulo(s)",
|
||||
"TooltipAddOneSecond": "Adicionar 1 segundo",
|
||||
"TooltipAdjustChapterStart": "Clique para ajustar a hora de início",
|
||||
"TooltipLockAllChapters": "Bloquear todos os capítulos",
|
||||
"TooltipLockChapter": "Bloquear capítulo (Shift+clique para selecionar o intervalo)",
|
||||
"TooltipSubtractOneSecond": "Subtrair 1 segundo",
|
||||
"TooltipUnlockAllChapters": "Desbloqueie todos os capítulos",
|
||||
"TooltipUnlockChapter": "Desbloquear capítulo (Shift + clique para selecionar o intervalo)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,204 @@
|
|||
{}
|
||||
{
|
||||
"ButtonAdd": "Adaugă",
|
||||
"ButtonAddApiKey": "Adaugă cheia API",
|
||||
"ButtonAddChapters": "Adaugă Capitole",
|
||||
"ButtonAddDevice": "Adaugă Dispozitiv",
|
||||
"ButtonAddLibrary": "Adaugă Librărie",
|
||||
"ButtonAddPodcasts": "Adaugă Podcasturi",
|
||||
"ButtonAddUser": "Adaugă Utilizator",
|
||||
"ButtonAddYourFirstLibrary": "Adaugă prima librărie",
|
||||
"ButtonApply": "Aplică",
|
||||
"ButtonApplyChapters": "Aplică Capitole",
|
||||
"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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@
|
|||
"LabelFolders": "Папки",
|
||||
"LabelFontBold": "Жирный",
|
||||
"LabelFontBoldness": "Жирность шрифта",
|
||||
"LabelFontFamily": "Семейство шрифтов",
|
||||
"LabelFontFamily": "Семейство шрифта",
|
||||
"LabelFontItalic": "Курсив",
|
||||
"LabelFontScale": "Масштаб шрифта",
|
||||
"LabelFontStrikethrough": "Зачеркнутый",
|
||||
|
|
@ -436,9 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Нет {0}",
|
||||
"LabelLibraryItem": "Элемент библиотеки",
|
||||
"LabelLibraryName": "Имя библиотеки",
|
||||
"LabelLibrarySortByProgress": "Прогресс обновлён",
|
||||
"LabelLibrarySortByProgressFinished": "Дата завершения",
|
||||
"LabelLibrarySortByProgressStarted": "Дата начала",
|
||||
"LabelLibrarySortByProgress": "Прогресс: Последнее обновление",
|
||||
"LabelLibrarySortByProgressFinished": "Прогресс: Завершено",
|
||||
"LabelLibrarySortByProgressStarted": "Прогресс: Начато",
|
||||
"LabelLimit": "Лимит",
|
||||
"LabelLineSpacing": "Межстрочный интервал",
|
||||
"LabelListenAgain": "Послушать снова",
|
||||
|
|
@ -588,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Конструкция с деревянными полками",
|
||||
"LabelSettingsChromecastSupport": "Поддержка Chromecast",
|
||||
"LabelSettingsDateFormat": "Формат даты",
|
||||
"LabelSettingsEnableWatcher": "Автоматическое сканирование библиотек на изменение",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Автоматическое сканирование библиотеки на изменение",
|
||||
"LabelSettingsEnableWatcher": "Автоматически отслеживать изменения в библиотеках",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Автоматический просмотр библиотеки на изменение",
|
||||
"LabelSettingsEnableWatcherHelp": "Включает автоматическое добавление/обновление элементов при обнаружении изменений файлов. *Требуется перезапуск сервера",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Разрешение содержимого epub с скриптами",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Разрешить файлам epub выполнять скрипты. Рекомендуется отключать этот параметр, если вы не доверяете источнику файлов epub.",
|
||||
|
|
@ -888,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Вы уверены, что хотите сбросить главы и отменить внесенные изменения?",
|
||||
"MessageRestoreBackupConfirm": "Вы уверены, что хотите восстановить резервную копию, созданную",
|
||||
"MessageRestoreBackupWarning": "Восстановление резервной копии перезапишет всю базу данных, расположенную в /config, и обложки изображений в /metadata/items и /metadata/authors.<br/><br/>Бэкапы не изменяют файлы в папках библиотеки. Если вы включили параметры сервера для хранения обложек и метаданных в папках библиотеки, то они не резервируются и не перезаписываются.<br/><br/>Все клиенты, использующие ваш сервер, будут автоматически обновлены.",
|
||||
"MessageScheduleLibraryScanNote": "Большинству пользователей рекомендуется отключить эту функцию и включить функцию просмотра папок. Программа просмотра папок автоматически обнаружит изменения в папках вашей библиотеки. Программа просмотра папок работает не для каждой файловой системы (например, NFS), поэтому вместо этого можно использовать запланированные проверки библиотеки.",
|
||||
"MessageScheduleLibraryScanNote": "Большинству пользователей рекомендуется отключить эту функцию и оставить включённой функцию \"Автоматически отслеживать изменения в библиотеках\" - она будет автоматически обнаруживать изменения в папках вашей библиотеки. Включите эту функцию если \"Автоматически отслеживать изменения в библиотеках\" не работает для вашей файловой системы (например, NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Запуск каждые {0} по {1}",
|
||||
"MessageSearchResultsFor": "Результаты поиска для",
|
||||
"MessageSelected": "{0} выбрано",
|
||||
|
|
@ -1026,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Не удалось добавить элемент(ы) в коллекцию",
|
||||
"ToastCollectionRemoveSuccess": "Коллекция удалена",
|
||||
"ToastCollectionUpdateSuccess": "Коллекция обновлена",
|
||||
"ToastConnectionNotAvailable": "Подключение недоступно. Пожалуйста попробуйте позже",
|
||||
"ToastCoverSearchFailed": "Ошибка поиска обложки",
|
||||
"ToastCoverUpdateFailed": "Не удалось обновить обложку",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Дата и время указаны неверно или не до конца",
|
||||
"ToastDeleteFileFailed": "Не удалось удалить файл",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
{
|
||||
"ButtonAdd": "Pridať",
|
||||
"ButtonAddApiKey": "Pridať kľúč API",
|
||||
"ButtonAddChapters": "Pridať kapitoly",
|
||||
"ButtonAddDevice": "Pridať zariadenie",
|
||||
"ButtonAddLibrary": "Pridať knižnicu",
|
||||
"ButtonAddPodcasts": "Pridať podcasty",
|
||||
"ButtonAddUser": "Pridať užívateľa",
|
||||
"ButtonAddUser": "Pridať používateľa",
|
||||
"ButtonAddYourFirstLibrary": "Pridajte vašu prvú knižnicu",
|
||||
"ButtonApply": "Použiť",
|
||||
"ButtonApplyChapters": "Použiť kapitoly",
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Vyberte priečinok",
|
||||
"ButtonChooseFiles": "Vyberte súbory",
|
||||
"ButtonClearFilter": "Zrušiť filter",
|
||||
"ButtonClose": "Uzavrieť",
|
||||
"ButtonCloseFeed": "Zatvoriť zdroj",
|
||||
"ButtonCloseSession": "Ukončiť otvorené pripojenie",
|
||||
"ButtonCollections": "Kolekcie",
|
||||
|
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Účet",
|
||||
"HeaderAddCustomMetadataProvider": "Pridať vastný zdroj metadát",
|
||||
"HeaderAdvanced": "Pokročilé",
|
||||
"HeaderApiKeys": "Kľúče API",
|
||||
"HeaderAppriseNotificationSettings": "Nastavenie Apprise notifikácií",
|
||||
"HeaderAudioTracks": "Zvukové stopy",
|
||||
"HeaderAudiobookTools": "Nástroje na správu súborov audiokníh",
|
||||
"HeaderAuthentication": "Overenie",
|
||||
"HeaderBackups": "Zálohy",
|
||||
"HeaderBulkChapterModal": "Pridať viaceré kapitoly",
|
||||
"HeaderChangePassword": "Zmeniť heslo",
|
||||
"HeaderChapters": "Kapitoly",
|
||||
"HeaderChooseAFolder": "Vybrať priečinok",
|
||||
|
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Metadáta pravidiel poradia",
|
||||
"HeaderMetadataToEmbed": "Metadáta na vloženie",
|
||||
"HeaderNewAccount": "Nový účet",
|
||||
"HeaderNewApiKey": "Nový kľúč API",
|
||||
"HeaderNewLibrary": "Nová knižnica",
|
||||
"HeaderNotificationCreate": "Vytvoriť notifikáciu",
|
||||
"HeaderNotificationUpdate": "Aktualizovať notifikáciu",
|
||||
|
|
@ -195,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Experimentálne funkcie",
|
||||
"HeaderSettingsGeneral": "Hlavné",
|
||||
"HeaderSettingsScanner": "Skener",
|
||||
"HeaderSettingsSecurity": "Zabezpečenie",
|
||||
"HeaderSettingsWebClient": "Webový klient",
|
||||
"HeaderSleepTimer": "Časovač spánku",
|
||||
"HeaderStatsLargestItems": "Najväčšie položky",
|
||||
|
|
@ -206,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Obsah",
|
||||
"HeaderTools": "Nástroje",
|
||||
"HeaderUpdateAccount": "Aktualizovať účet",
|
||||
"HeaderUpdateApiKey": "Aktualizovať kľúč API",
|
||||
"HeaderUpdateAuthor": "Aktualizovať autora",
|
||||
"HeaderUpdateDetails": "Aktualizovať detaily",
|
||||
"HeaderUpdateLibrary": "Aktualizovať knižnicu",
|
||||
|
|
@ -235,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Všetci užívatelia okrem hostí",
|
||||
"LabelAllUsersIncludingGuests": "Všetci užívatelia vrátane hostí",
|
||||
"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",
|
||||
"LabelAppend": "Pridať",
|
||||
"LabelAudioBitrate": "Bitrate audio stopy (napr. 128k)",
|
||||
|
|
@ -284,6 +295,7 @@
|
|||
"LabelContinueListening": "Pokračovať v počúvaní",
|
||||
"LabelContinueReading": "Pokračovať v čítaní",
|
||||
"LabelContinueSeries": "Pokračovať v sérii",
|
||||
"LabelCorsAllowed": "CORS Origins povolené",
|
||||
"LabelCover": "Prebal",
|
||||
"LabelCoverImageURL": "URL obrázku prebalu",
|
||||
"LabelCoverProvider": "Poskytovateľ prebalu",
|
||||
|
|
@ -297,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Zmazať zo systému (odškrtni len pre odstránenie z databázy)",
|
||||
"LabelDescription": "Popis",
|
||||
"LabelDeselectAll": "Odznačiť všetko",
|
||||
"LabelDetectedPattern": "Identifikovaný vzor:",
|
||||
"LabelDevice": "Zariadenie",
|
||||
"LabelDeviceInfo": "Informácie o zariadení",
|
||||
"LabelDeviceIsAvailableTo": "Zariadenie je k dispozícii...",
|
||||
|
|
@ -346,6 +359,10 @@
|
|||
"LabelExample": "Príklad",
|
||||
"LabelExpandSeries": "Rozbaliť série",
|
||||
"LabelExpandSubSeries": "Rozbaliť podsérie",
|
||||
"LabelExpired": "Vypršal",
|
||||
"LabelExpiresAt": "Vyprší",
|
||||
"LabelExpiresInSeconds": "Vyprší za (sekúnd)",
|
||||
"LabelExpiresNever": "Nikdy",
|
||||
"LabelExplicit": "Explicitný obsah",
|
||||
"LabelExplicitChecked": "Explicitné (zaškrtnuté)",
|
||||
"LabelExplicitUnchecked": "Ne-explicitné (nezaškrtnuté)",
|
||||
|
|
@ -361,6 +378,7 @@
|
|||
"LabelFilterByUser": "Užívateľský filter",
|
||||
"LabelFindEpisodes": "Nájsť epizódy",
|
||||
"LabelFinished": "Ukončené",
|
||||
"LabelFinishedDate": "Dokončené {0}",
|
||||
"LabelFolder": "Priečinok",
|
||||
"LabelFolders": "Priečinky",
|
||||
"LabelFontBold": "Tučné",
|
||||
|
|
@ -405,6 +423,7 @@
|
|||
"LabelLanguages": "Jazyky",
|
||||
"LabelLastBookAdded": "Posledná pridaná kniha",
|
||||
"LabelLastBookUpdated": "Posledná aktualizovaná kniha",
|
||||
"LabelLastProgressDate": "Posledný pokrok: {0}",
|
||||
"LabelLastSeen": "Posledne videné",
|
||||
"LabelLastTime": "Posledný čas",
|
||||
"LabelLastUpdate": "Posledná aktualizácia",
|
||||
|
|
@ -417,6 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Žiadne {0}",
|
||||
"LabelLibraryItem": "Položka knižnice",
|
||||
"LabelLibraryName": "Názov knižnice",
|
||||
"LabelLibrarySortByProgress": "Pokrok: Aktualizované",
|
||||
"LabelLibrarySortByProgressFinished": "Pokrok: Dokončené",
|
||||
"LabelLibrarySortByProgressStarted": "Pokrok: Začiatok",
|
||||
"LabelLimit": "Limit",
|
||||
"LabelLineSpacing": "Riadkovanie",
|
||||
"LabelListenAgain": "Počúvať znova",
|
||||
|
|
@ -425,6 +447,7 @@
|
|||
"LabelLogLevelWarn": "Varovanie",
|
||||
"LabelLookForNewEpisodesAfterDate": "Hľadať nové epizódy od uvedeného dátumu",
|
||||
"LabelLowestPriority": "Najnižšia priorita",
|
||||
"LabelMatchConfidence": "Istota",
|
||||
"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",
|
||||
"LabelMaxEpisodesToDownload": "Stiahnuť maximálne # epizód. Pre neobmedzené sťahovanie zadajte 0.",
|
||||
|
|
@ -454,7 +477,9 @@
|
|||
"LabelNewestAuthors": "Najnovší autori",
|
||||
"LabelNewestEpisodes": "Najnovšie epizódy",
|
||||
"LabelNextBackupDate": "Ďalší dátum zálohovania",
|
||||
"LabelNextChapters": "Nasledujúce kapitoly:",
|
||||
"LabelNextScheduledRun": "Ďalší plánovaný beh",
|
||||
"LabelNoApiKeys": "Žiadne API kľúče",
|
||||
"LabelNoCustomMetadataProviders": "Žiadne vlastné zdroje metadát",
|
||||
"LabelNoEpisodesSelected": "Neboli vybrané žiadne epizódy",
|
||||
"LabelNotFinished": "Nedokončené",
|
||||
|
|
@ -470,6 +495,7 @@
|
|||
"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.",
|
||||
"LabelNumberOfBooks": "Počet kníh",
|
||||
"LabelNumberOfChapters": "Počet kapitol:",
|
||||
"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:",
|
||||
"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",
|
||||
"LabelSelectAllEpisodes": "Vybrať všetky epizódy",
|
||||
"LabelSelectEpisodesShowing": "Vybrať {0} zobrazených epizód",
|
||||
"LabelSelectUser": "Vyberte používateľa",
|
||||
"LabelSelectUsers": "Vybrať užívateľov",
|
||||
"LabelSendEbookToDevice": "Poslať e-knihu do...",
|
||||
"LabelSequence": "Postupnosť",
|
||||
|
|
@ -611,6 +638,7 @@
|
|||
"LabelStartTime": "Čas spustenia",
|
||||
"LabelStarted": "Začaté",
|
||||
"LabelStartedAt": "Začaté v",
|
||||
"LabelStartedDate": "Začaté {0}",
|
||||
"LabelStatsAudioTracks": "Zvukové stopy",
|
||||
"LabelStatsAuthors": "Autori",
|
||||
"LabelStatsBestDay": "Najlepší deň",
|
||||
|
|
@ -640,6 +668,7 @@
|
|||
"LabelTheme": "Téma",
|
||||
"LabelThemeDark": "Tmavá",
|
||||
"LabelThemeLight": "Svetlá",
|
||||
"LabelThemeSepia": "Sépia",
|
||||
"LabelTimeBase": "Časová základňa",
|
||||
"LabelTimeDurationXHours": "{0} hodín",
|
||||
"LabelTimeDurationXMinutes": "{0} minút",
|
||||
|
|
@ -708,7 +737,9 @@
|
|||
"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>.",
|
||||
"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.",
|
||||
"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.",
|
||||
"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.",
|
||||
|
|
@ -722,6 +753,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Žiadny výsledok filtrovania \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Žiadne výsledky dopytu",
|
||||
"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",
|
||||
"MessageChapterErrorFirstNotZero": "Prvá kapitola musí začínať na 0",
|
||||
"MessageChapterErrorStartGteDuration": "Neplatný čas začiatku musí byť menší ako celkové trvanie audioknihy",
|
||||
|
|
@ -730,6 +762,7 @@
|
|||
"MessageChaptersNotFound": "Kapitoly nenájdené",
|
||||
"MessageCheckingCron": "Kontrola cron-u...",
|
||||
"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}?",
|
||||
"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ý?",
|
||||
|
|
@ -783,6 +816,8 @@
|
|||
"MessageFeedURLWillBe": "URL zdroja bude {0}",
|
||||
"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é.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} počúvajúcich</strong> na {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Žiadne relácie počúvania na {0}",
|
||||
"MessageImportantNotice": "Dôležité upozornenie!",
|
||||
"MessageInsertChapterBelow": "Vložte kapitolu nižšie",
|
||||
"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í",
|
||||
"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í",
|
||||
"PlaceholderBulkChapterInput": "Zadajte názov kapitoly alebo použite číslovanie (napr., 'Epizóda 1', 'Kapitola 10', '1.')",
|
||||
"PlaceholderNewCollection": "Názov novej zbierky",
|
||||
"PlaceholderNewFolderPath": "Umiestnenie nového priečinka",
|
||||
"PlaceholderNewPlaylist": "Názov nového playlistu",
|
||||
|
|
@ -975,8 +1011,12 @@
|
|||
"ToastBookmarkCreateFailed": "Vytvorenie záložky zlyhalo",
|
||||
"ToastBookmarkCreateSuccess": "Záložka pridaná",
|
||||
"ToastBookmarkRemoveSuccess": "Záložka odstránená",
|
||||
"ToastBulkChapterInvalidCount": "Zadajte číslo medzi 1 a 150",
|
||||
"ToastCachePurgeFailed": "Vyčistenie vyrovnávacej pamäte zlyhalo",
|
||||
"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",
|
||||
"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.",
|
||||
|
|
@ -1001,6 +1041,8 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Poradie sťahovania bolo vyčistené",
|
||||
"ToastEpisodeUpdateSuccess": "{0} epizód bolo aktualizovaných",
|
||||
"ToastErrorCannotShare": "Na tomto zariadení nie je možné zdielať vybraným spôsobom",
|
||||
"ToastFailedToCreate": "Vytvorenie zlyhalo",
|
||||
"ToastFailedToDelete": "Zmazanie zlyhalo",
|
||||
"ToastFailedToLoadData": "Načítanie údajov zlyhalo",
|
||||
"ToastFailedToMatch": "Spárovanie zlyhalo",
|
||||
"ToastFailedToShare": "Zdieľanie zlyhalo",
|
||||
|
|
@ -1008,6 +1050,7 @@
|
|||
"ToastInvalidImageUrl": "Neplatná URL obrázku",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Neplatný maximálny počet epizód na stiahnutie",
|
||||
"ToastInvalidUrl": "Neplatná URL",
|
||||
"ToastInvalidUrls": "Jedna alebo viac URL liniek sú neplatné",
|
||||
"ToastItemCoverUpdateSuccess": "Prebal položky bol aktualizovaný",
|
||||
"ToastItemDeletedFailed": "Odstránenie položky zlyhalo",
|
||||
"ToastItemDeletedSuccess": "Položka bola odstránená",
|
||||
|
|
@ -1032,6 +1075,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Musí mať aspoň jednu cestu umiestnenia",
|
||||
"ToastNameEmailRequired": "Meno a e-mail sú povinné",
|
||||
"ToastNameRequired": "Meno je povinné",
|
||||
"ToastNewApiKeyUserError": "Musíte vybrať používateľa",
|
||||
"ToastNewEpisodesFound": "Bolo nájdených {0} nových epizód",
|
||||
"ToastNewUserCreatedFailed": "Vytvorenie účtu zlyhalo: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Nový účet bol vytvorený",
|
||||
|
|
@ -1056,6 +1100,7 @@
|
|||
"ToastPlaylistUpdateSuccess": "Playlist bol aktualizovaný",
|
||||
"ToastPodcastCreateFailed": "Vytvorenie podcastu zlyhalo",
|
||||
"ToastPodcastCreateSuccess": "Podcast bol vytvorený",
|
||||
"ToastPodcastEpisodeUpdated": "Epizóda bola aktualizovaná",
|
||||
"ToastPodcastGetFeedFailed": "Získanie zdroja podcastu zlyhalo",
|
||||
"ToastPodcastNoEpisodesInFeed": "Na RSS zdroji neboli nájdené žiadne epizódy",
|
||||
"ToastPodcastNoRssFeed": "Podcast nemá RSS zdroj",
|
||||
|
|
@ -1106,5 +1151,13 @@
|
|||
"ToastUserPasswordChangeSuccess": "Zmena hesla prebehla úspešne",
|
||||
"ToastUserPasswordMismatch": "Heslá sa nezhodujú",
|
||||
"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",
|
||||
"LabelFindEpisodes": "Poišči epizode",
|
||||
"LabelFinished": "Zaključeno",
|
||||
"LabelFinishedDate": "Končano {0}",
|
||||
"LabelFolder": "Mapa",
|
||||
"LabelFolders": "Mape",
|
||||
"LabelFontBold": "Krepko",
|
||||
|
|
@ -435,7 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Ne {0}",
|
||||
"LabelLibraryItem": "Element knjižnice",
|
||||
"LabelLibraryName": "Ime knjižnice",
|
||||
"LabelLibrarySortByProgress": "Napredek posodobljen",
|
||||
"LabelLibrarySortByProgress": "Napredek: Nazadnje posodobljen",
|
||||
"LabelLibrarySortByProgressFinished": "Napredej: Končano",
|
||||
"LabelLibrarySortByProgressStarted": "Napredek: Začeto",
|
||||
"LabelLimit": "Omejitev",
|
||||
"LabelLineSpacing": "Vrstični razmak",
|
||||
"LabelListenAgain": "Poslušaj znova",
|
||||
|
|
@ -585,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeuomorfna oblika z lesenimi policami",
|
||||
"LabelSettingsChromecastSupport": "Podpora za Chromecast",
|
||||
"LabelSettingsDateFormat": "Oblika datuma",
|
||||
"LabelSettingsEnableWatcher": "Samodejno preglej knjižnice za spremembe",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Samodejno preglej knjižnico za spremembe",
|
||||
"LabelSettingsEnableWatcher": "Samodejno preišči knjižnice za spremembe",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Samodejno preišči knjižnico za spremembe",
|
||||
"LabelSettingsEnableWatcherHelp": "Omogoča samodejno dodajanje/posodabljanje elementov, ko so zaznane spremembe datoteke. *Potreben je ponovni zagon strežnika",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Dovoli skriptirano vsebino v epubih",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Dovoli datotekam epub izvajanje skript. Priporočljivo je, da to nastavitev pustite onemogočeno, razen če zaupate viru datotek epub.",
|
||||
|
|
@ -635,6 +638,7 @@
|
|||
"LabelStartTime": "Čas začetka",
|
||||
"LabelStarted": "Začeto",
|
||||
"LabelStartedAt": "Začeto ob",
|
||||
"LabelStartedDate": "Začeto {0}",
|
||||
"LabelStatsAudioTracks": "Zvočni posnetki",
|
||||
"LabelStatsAuthors": "Avtorji",
|
||||
"LabelStatsBestDay": "Najboljši dan",
|
||||
|
|
@ -884,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Ali ste prepričani, da želite ponastaviti poglavja in razveljaviti spremembe, ki ste jih naredili?",
|
||||
"MessageRestoreBackupConfirm": "Ali ste prepričani, da želite obnoviti varnostno kopijo, ustvarjeno ob",
|
||||
"MessageRestoreBackupWarning": "Obnovitev varnostne kopije bo prepisala celotno zbirko podatkov, ki se nahaja v /config, in zajema slike v /metadata/items in /metadata/authors.<br /><br />Varnostne kopije ne spreminjajo nobenih datotek v mapah vaše knjižnice. Če ste omogočili nastavitve strežnika za shranjevanje naslovnic in metapodatkov v mapah vaše knjižnice, potem ti niso varnostno kopirani ali prepisani.<br /><br />Vsi odjemalci, ki uporabljajo vaš strežnik, bodo samodejno osveženi.",
|
||||
"MessageScheduleLibraryScanNote": "Za večino uporabnikov je priporočljivo, da to funkcijo pustite onemogočeno in ohranite nastavitev pregledovalnika map omogočeno. Pregledovalnik map bo samodejno zaznal spremembe v mapah vaše knjižnice. Pregledovalnik map ne deluje za vse datotečne sisteme (na primer NFS), zato lahko namesto tega uporabite načrtovane preglede knjižnic.",
|
||||
"MessageScheduleLibraryScanNote": "Za večino uporabnikov je priporočljivo, da to funkcijo pustijo onemogočeno in ohranijo nastavitev »Samodejno spremljaj knjižnico za spremembe« omogočeno – samodejno bo zaznala spremembe v mapah vaše knjižnice. Omogočite to funkcijo, če »Samodejno spremljaj knjižnico za spremembe« ne deluje za vaš datotečni sistem (kot je NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Zaženi vsakih {0} ob {1}",
|
||||
"MessageSearchResultsFor": "Rezultati iskanja za",
|
||||
"MessageSelected": "{0} izbrano",
|
||||
|
|
@ -1022,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Dodajanje elementov v zbirko ni uspelo",
|
||||
"ToastCollectionRemoveSuccess": "Zbirka je bila odstranjena",
|
||||
"ToastCollectionUpdateSuccess": "Zbirka je bila posodobljena",
|
||||
"ToastConnectionNotAvailable": "Povezava ni na voljo. Poskusite znova pozneje",
|
||||
"ToastCoverSearchFailed": "Iskanje naslovnice ni uspelo",
|
||||
"ToastCoverUpdateFailed": "Posodobitev naslovnice ni uspela",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Datum in čas sta neveljavna ali nepopolna",
|
||||
"ToastDeleteFileFailed": "Brisanje datoteke ni uspelo",
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@
|
|||
"ButtonStartM4BEncode": "Starta M4B-omkodning",
|
||||
"ButtonStartMetadataEmbed": "Infoga metadata",
|
||||
"ButtonStats": "Statistik",
|
||||
"ButtonSubmit": "Skicka",
|
||||
"ButtonSubmit": "Spara",
|
||||
"ButtonTest": "Testa",
|
||||
"ButtonUnlinkOpenId": "Koppla ifrån OpenID",
|
||||
"ButtonUpload": "Ladda upp",
|
||||
|
|
@ -301,7 +301,7 @@
|
|||
"LabelCoverProvider": "Källa för omslag",
|
||||
"LabelCreatedAt": "Skapad",
|
||||
"LabelCronExpression": "Schemaläggning med hjälp av Cron (Cron Expression)",
|
||||
"LabelCurrent": "Nuvarande omslag",
|
||||
"LabelCurrent": "Nuvarande",
|
||||
"LabelCurrently": "För närvarande:",
|
||||
"LabelCustomCronExpression": "Anpassat Cron-uttryck:",
|
||||
"LabelDatetime": "Datum och klockslag",
|
||||
|
|
@ -385,13 +385,13 @@
|
|||
"LabelFontBoldness": "Fetstil",
|
||||
"LabelFontFamily": "Typsnittsfamilj",
|
||||
"LabelFontItalic": "Kursiv",
|
||||
"LabelFontScale": "Skala på typsnitt",
|
||||
"LabelFontScale": "Storlek på typsnitt",
|
||||
"LabelFontStrikethrough": "Genomstruken",
|
||||
"LabelFormat": "Format",
|
||||
"LabelFull": "Komplett",
|
||||
"LabelGenre": "Kategori",
|
||||
"LabelGenres": "Kategorier",
|
||||
"LabelHardDeleteFile": "Hård radering av fil",
|
||||
"LabelHardDeleteFile": "Permanent radering av fil",
|
||||
"LabelHasEbook": "Har e-bok",
|
||||
"LabelHasSupplementaryEbook": "Har kompletterande e-bok",
|
||||
"LabelHideSubtitles": "Dölj underrubriker",
|
||||
|
|
@ -436,9 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Ingen {0}",
|
||||
"LabelLibraryItem": "Objekt",
|
||||
"LabelLibraryName": "Biblioteksnamn",
|
||||
"LabelLibrarySortByProgress": "Framsteg uppdaterat",
|
||||
"LabelLibrarySortByProgressFinished": "Avslutsdag",
|
||||
"LabelLibrarySortByProgressStarted": "Startdag",
|
||||
"LabelLibrarySortByProgress": "Framsteg: senast uppdaterat",
|
||||
"LabelLibrarySortByProgressFinished": "Framsteg: avslutad",
|
||||
"LabelLibrarySortByProgressStarted": "Framsteg: påbörjad",
|
||||
"LabelLimit": "Begränsning",
|
||||
"LabelLineSpacing": "Radavstånd",
|
||||
"LabelListenAgain": "Lyssna igen",
|
||||
|
|
@ -462,7 +462,7 @@
|
|||
"LabelMetadataProvider": "Källa för metadata",
|
||||
"LabelMinute": "Minut",
|
||||
"LabelMinutes": "Minuter",
|
||||
"LabelMissing": "Saknas",
|
||||
"LabelMissing": "Saknar",
|
||||
"LabelMissingEbook": "Saknar e-bok",
|
||||
"LabelMissingSupplementaryEbook": "Saknar kompletterande e-bok",
|
||||
"LabelMobileRedirectURIs": "Tillåtna mobila omdirigerings-URI:er",
|
||||
|
|
@ -472,7 +472,7 @@
|
|||
"LabelName": "Namn",
|
||||
"LabelNarrator": "Uppläsare",
|
||||
"LabelNarrators": "Uppläsare",
|
||||
"LabelNew": "Nytt omslag",
|
||||
"LabelNew": "Nytt",
|
||||
"LabelNewPassword": "Nytt lösenord",
|
||||
"LabelNewestAuthors": "Senaste författarna",
|
||||
"LabelNewestEpisodes": "Senaste avsnitten",
|
||||
|
|
@ -588,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Bakgrund med ett utseende liknande en bokhylla i trä",
|
||||
"LabelSettingsChromecastSupport": "Stöd för Chromecast",
|
||||
"LabelSettingsDateFormat": "Datumformat",
|
||||
"LabelSettingsEnableWatcher": "Upptäck automatiskt förändringar i biblioteket",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Upptäck automatiskt förändringar i biblioteket",
|
||||
"LabelSettingsEnableWatcher": "Bevaka automatiskt förändringar i biblioteken",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Bevaka biblioteket automatiskt efter ändringar",
|
||||
"LabelSettingsEnableWatcherHelp": "Aktiverar automatik att upptäcka när objekt<br>adderas, uppdateras eller raderas.<br>OBS: Kräver en omstart av servern",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Tillåt e-böcker i epubs-format som innehåller script",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Tillåt att epub-filer får innehålla script.<br>Det rekommenderas att denna inställning är<br>avstängd när du inte litar på källan för epub-filerna.",
|
||||
|
|
@ -724,6 +724,7 @@
|
|||
"LabelViewQueue": "Visa spellista",
|
||||
"LabelVolume": "Volym",
|
||||
"LabelWebRedirectURLsDescription": "Auktorisera dessa URLer i din OAuth-leverantör för att tillåta omdirigering tillbaka till webbappen efter inloggning:",
|
||||
"LabelWebRedirectURLsSubfolder": "Undermappar för omdirigeringslänkar",
|
||||
"LabelWeekdaysToRun": "Veckodagar att köra skanning",
|
||||
"LabelXBooks": "{0} böcker",
|
||||
"LabelXItems": "{0} objekt",
|
||||
|
|
@ -752,6 +753,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Inga resultat för filter \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Sökningen gav inget resultat",
|
||||
"MessageBookshelfNoSeries": "Du har inga serier",
|
||||
"MessageBulkChapterPattern": "Hur många kapitel vill du lägga till med detta numreringsmönster?",
|
||||
"MessageChapterEndIsAfter": "Kapitelns slut är efter din ljudboks slut",
|
||||
"MessageChapterErrorFirstNotZero": "Första kapitlet måste börja vid 0",
|
||||
"MessageChapterErrorStartGteDuration": "Ogiltig starttid, måste vara mindre än ljudbokens längd",
|
||||
|
|
@ -778,6 +780,7 @@
|
|||
"MessageConfirmMarkItemNotFinished": "Är du säker på att du vill markera \"{0}\" som ej avslutad?",
|
||||
"MessageConfirmMarkSeriesFinished": "Är du säker på att du vill markera alla böcker i denna serie som avslutade?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Är du säker på att du vill markera alla böcker i denna serie som ej avslutade?",
|
||||
"MessageConfirmNotificationTestTrigger": "Trigga denna avisering med testdata?",
|
||||
"MessageConfirmPurgeCache": "När du rensar cashen kommer katalogen <code>/metadata/cache</code> att raderas. <br /><br />Är du säker på att du vill radera katalogen?",
|
||||
"MessageConfirmPurgeItemsCache": "När du rensar cashen för objekten kommer katalogen <code>/metadata/cache/items</code> att raderas. <br /><br />Är du säker på att du vill radera katalogen?",
|
||||
"MessageConfirmQuickEmbed": "VARNING! När du infogar metadata i dina ljudfiler kommer INGEN SÄKERHETSKOPIA av filerna att göras. Se därför till att först säkerhetskopiera ljudfilerna. <br><br>Vill du fortsätta?",
|
||||
|
|
@ -787,6 +790,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Är du säker på att du vill ta bort författaren \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Är du säker på att du vill ta bort samlingen \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Är du säker på att du vill radera avsnittet \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodeNote": "OBSERERA: Detta tar inte bort ljudfilen om inte \"Permanent radering av fil\" är aktiverad",
|
||||
"MessageConfirmRemoveEpisodes": "Är du säker på att du vill radera {0} avsnitt?",
|
||||
"MessageConfirmRemoveListeningSessions": "Är du säker på att du vill radera {0} lyssningstillfällen?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Är du säker på att du vill radera filerna 'metadata.{0}' i alla mappar i ditt bibliotek?",
|
||||
|
|
@ -804,12 +808,16 @@
|
|||
"MessageDaysListenedInTheLastYear": "{0} dagars lyssnande det senaste året",
|
||||
"MessageDownloadingEpisode": "Laddar ner avsnitt",
|
||||
"MessageDragFilesIntoTrackOrder": "Ändra ordningen genom att klicka och dra filerna till rätt plats",
|
||||
"MessageEmbedFailed": "Inbäddning misslyckades!",
|
||||
"MessageEmbedFinished": "Inbäddning genomförd!",
|
||||
"MessageEmbedQueue": "Köad för inbäddning av metadata plats ({0} i kön)",
|
||||
"MessageEpisodesQueuedForDownload": "{0} avsnitt i kö för nedladdning",
|
||||
"MessageEreaderDevices": "För att säkerställa överföring av e-böcker kan du bli tvungen<br>att addera ovanstående e-postadress som godkänd avsändare<br>för varje enhet angiven nedan.",
|
||||
"MessageFeedURLWillBe": "Flödes-URL kommer att vara {0}",
|
||||
"MessageFetching": "Hämtar...",
|
||||
"MessageForceReScanDescription": "kommer att göra en omgångssökning av alla filer som en färsk sökning. ID3-taggar för ljudfiler, OPF-filer och textfiler kommer att sökas som nya.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} lyssnar</strong> på {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Inga lyssningssessioner på {0}",
|
||||
"MessageImportantNotice": "Viktig meddelande!",
|
||||
"MessageInsertChapterBelow": "Infoga kapitel nedanför",
|
||||
"MessageInvalidAsin": "Felaktig ASIN-kod",
|
||||
|
|
@ -826,7 +834,7 @@
|
|||
"MessageMarkAllEpisodesNotFinished": "Markera alla avsnitt som ej avslutade",
|
||||
"MessageMarkAsFinished": "Markera som 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",
|
||||
"MessageNoAuthors": "Inga författare",
|
||||
"MessageNoBackups": "Inga säkerhetskopior",
|
||||
|
|
@ -849,6 +857,7 @@
|
|||
"MessageNoLogs": "Inga loggningsinformation finns",
|
||||
"MessageNoMediaProgress": "Ingen medieförlopp",
|
||||
"MessageNoNotifications": "Inga aviseringar",
|
||||
"MessageNoPodcastFeed": "Felaktig podcast: ingen ström",
|
||||
"MessageNoPodcastsFound": "Inga podcasts hittade",
|
||||
"MessageNoResults": "Inga resultat",
|
||||
"MessageNoSearchResultsFor": "Inga sökresultat för \"{0}\"",
|
||||
|
|
@ -859,6 +868,7 @@
|
|||
"MessageNoUserPlaylists": "Du har inga spellistor",
|
||||
"MessageNoUserPlaylistsHelp": "Spellistor är privata. Endast den användare som skapat listan kan se den.",
|
||||
"MessageNotYetImplemented": "Ännu inte implementerad",
|
||||
"MessageOpmlPreviewNote": "Obs: Detta är en förhandsvisning av den analyserade OPML-filen. Den faktiska podcasttiteln kommer att hämtas från RSS-flödet.",
|
||||
"MessageOr": "eller",
|
||||
"MessagePauseChapter": "Pausa kapiteluppspelning",
|
||||
"MessagePlayChapter": "Lyssna på kapitlets början",
|
||||
|
|
@ -878,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Är du säker på att du vill återställa alla kapitel och ångra de ändringarna du gjort?",
|
||||
"MessageRestoreBackupConfirm": "Är du säker på att du vill läsa in säkerhetskopian som skapades den",
|
||||
"MessageRestoreBackupWarning": "Att återställa en säkerhetskopia kommer att skriva över hela databasen som finns i /config och omslagsbilder i /metadata/items & /metadata/authors.<br /><br />Säkerhetskopior ändrar inte några filer i dina biblioteksmappar. Om du har aktiverat serverinställningar för att lagra omslagskonst och metadata i dina biblioteksmappar säkerhetskopieras eller skrivs de inte över.<br /><br />Alla klienter som använder din server kommer att uppdateras automatiskt.",
|
||||
"MessageScheduleLibraryScanNote": "För de flesta användare rekommenderas att denna funktion ej aktiveras. Istället bör funktionen som automatisk upptäcker ändringar i biblioteket vara aktiverad. För vissa filsystem (som t.ex. NFS) fungerar inte denna funktion. Då kan schemalagda skanningar av biblioteken användas istället.",
|
||||
"MessageScheduleLibraryScanNote": "För de flesta användare rekommenderas det att låta den här funktionen vara inaktiverad och att inställningen \"Bevaka biblioteket automatiskt efter ändringar\" är aktiverad – den kommer automatiskt att upptäcka ändringar i dina biblioteksmappar. Aktivera den här funktionen om \"Bevaka biblioteket automatiskt efter ändringar\" inte fungerar för ditt filsystem (som NFS).",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Startar varje {0} klockan {1}",
|
||||
"MessageSearchResultsFor": "Sökresultat för",
|
||||
"MessageSelected": "{0} valda",
|
||||
|
|
@ -887,12 +897,14 @@
|
|||
"MessageSetChaptersFromTracksDescription": "Använd varje ljudfil som ett kapitel och ljudfilens namn som kapitlets rubrik",
|
||||
"MessageShareExpirationWillBe": "Giltig till kommer att bli <strong>{0}</strong>",
|
||||
"MessageShareExpiresIn": "Upphör om {0}",
|
||||
"MessageShareURLWillBe": "Delningslänken kommer att vara <strong>{0}</strong>",
|
||||
"MessageStartPlaybackAtTime": "Starta uppspelning av \"{0}\" från tidpunkt {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "Det går inte att skriva till ljudfilen \"{0}\"",
|
||||
"MessageTaskCanceledByUser": "Uppgiften avslutades av användaren",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Laddar ner avsnitt \"{0}\"",
|
||||
"MessageTaskEmbeddingMetadata": "Infogar metadata",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Infogar metadata i ljudboken \"{0}\"",
|
||||
"MessageTaskEncodingM4b": "Kodar M4B",
|
||||
"MessageTaskEncodingM4bDescription": "Omkodning av ljudbok \"{0}\" till en M4B-fil",
|
||||
"MessageTaskFailed": "Misslyckades",
|
||||
"MessageTaskFailedToBackupAudioFile": "Misslyckades med att göra backup på ljudfil \"{0}\"",
|
||||
|
|
@ -903,8 +915,11 @@
|
|||
"MessageTaskFailedToWriteMetadataFile": "Misslyckades med att skapa filen med metadata",
|
||||
"MessageTaskMatchingBooksInLibrary": "Matchar böcker i biblioteket \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Inga filer finns tillgängliga för skanning",
|
||||
"MessageTaskOpmlImport": "OPML-import",
|
||||
"MessageTaskOpmlImportDescription": "Skapar podcasts från {0} RSS-flöden",
|
||||
"MessageTaskOpmlImportFeed": "OPML importflöde",
|
||||
"MessageTaskOpmlImportFeedDescription": "Importerar RSS-flödet \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedFailed": "Det gick inte att hämta poddflödet",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Skapar podcast \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "En podcast finns redan med den adressen",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Misslyckades med att skapa podcast",
|
||||
|
|
@ -921,7 +936,7 @@
|
|||
"MessageTaskTargetDirectoryNotWritable": "Det är inte tillåtet att skriva i den angivna katalogen",
|
||||
"MessageThinking": "Tänker...",
|
||||
"MessageUploaderItemFailed": "Misslyckades med att ladda upp",
|
||||
"MessageUploaderItemSuccess": "har blivit uppladdat!",
|
||||
"MessageUploaderItemSuccess": "har blivit uppladdad!",
|
||||
"MessageUploading": "Laddar upp...",
|
||||
"MessageValidCronExpression": "Giltigt cron-uttryck",
|
||||
"MessageWatcherIsDisabledGlobally": "Automatisk bevakning av förändringar är inaktiverad under rubriken 'Inställningar'",
|
||||
|
|
@ -987,6 +1002,9 @@
|
|||
"ToastBackupUploadFailed": "Det gick inte att ladda upp säkerhetskopian",
|
||||
"ToastBackupUploadSuccess": "Säkerhetskopian har laddats upp",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Informationen har adderats till alla objekt",
|
||||
"ToastBatchDeleteFailed": "Det gick inte att radera batch",
|
||||
"ToastBatchDeleteSuccess": "Batch borttagning lyckades",
|
||||
"ToastBatchQuickMatchFailed": "Snabbmatchning av batch misslyckades!",
|
||||
"ToastBatchQuickMatchStarted": "Snabbmatchning av {0} böcker har påbörjats!",
|
||||
"ToastBatchUpdateFailed": "Batchuppdateringen misslyckades",
|
||||
"ToastBatchUpdateSuccess": "Batchuppdateringen lyckades",
|
||||
|
|
@ -1008,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Misslyckades med att addera böcker till samlingen",
|
||||
"ToastCollectionRemoveSuccess": "Samlingen har raderats",
|
||||
"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",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Datum och klockslag är felaktigt eller ej komplett",
|
||||
"ToastDeleteFileFailed": "Misslyckades att radera filen",
|
||||
|
|
@ -1022,6 +1042,7 @@
|
|||
"ToastEpisodeDownloadQueueClearFailed": "Misslyckades med att tömma kön",
|
||||
"ToastEpisodeDownloadQueueClearSuccess": "Kö för nedladdning av avsnitt har tömts",
|
||||
"ToastEpisodeUpdateSuccess": "{0} avsnitt uppdaterades",
|
||||
"ToastErrorCannotShare": "Kan inte dela direkt på den här enheten",
|
||||
"ToastFailedToCreate": "Misslyckades med att addera",
|
||||
"ToastFailedToDelete": "Misslyckades med att radera",
|
||||
"ToastFailedToLoadData": "Misslyckades med att ladda data",
|
||||
|
|
@ -1053,6 +1074,7 @@
|
|||
"ToastMetadataFilesRemovedNoneFound": "Inga 'metadata.{0}' filer hittades i biblioteket",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "Inga 'metadata.{0}' filer raderades",
|
||||
"ToastMetadataFilesRemovedSuccess": "{0} 'metadata.{1}' raderades",
|
||||
"ToastMustHaveAtLeastOnePath": "Måste ha minst en sökväg",
|
||||
"ToastNameEmailRequired": "Ett namn och en e-postadress måste anges",
|
||||
"ToastNameRequired": "Ett namn måste anges",
|
||||
"ToastNewApiKeyUserError": "En användare måste väljas",
|
||||
|
|
@ -1069,8 +1091,10 @@
|
|||
"ToastNotificationCreateFailed": "Misslyckades med att skapa meddelandet",
|
||||
"ToastNotificationDeleteFailed": "Misslyckades med att radera meddelandet",
|
||||
"ToastNotificationFailedMaximum": "Maximalt antal misslyckade försök måste vara större än eller lika med 0",
|
||||
"ToastNotificationQueueMaximum": "Maximala antalet aviseringsköer måste vara >= 0",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Inställningarna för meddelanden har ändrats",
|
||||
"ToastNotificationTestTriggerFailed": "Misslyckades med att skicka testmeddelandet",
|
||||
"ToastNotificationTestTriggerSuccess": "Triggade testavisering",
|
||||
"ToastNotificationUpdateSuccess": "Meddelandet har uppdaterats",
|
||||
"ToastPlaylistCreateFailed": "Det gick inte att skapa spellistan",
|
||||
"ToastPlaylistCreateSuccess": "Spellistan skapad",
|
||||
|
|
@ -1079,8 +1103,10 @@
|
|||
"ToastPodcastCreateFailed": "Misslyckades med att skapa podcasten",
|
||||
"ToastPodcastCreateSuccess": "Podcasten skapades framgångsrikt",
|
||||
"ToastPodcastEpisodeUpdated": "Avsnittet har uppdaterats",
|
||||
"ToastPodcastGetFeedFailed": "Det gick inte att hämta poddflödet",
|
||||
"ToastPodcastNoEpisodesInFeed": "Inga avsnitt finns i RSS-flödet",
|
||||
"ToastPodcastNoRssFeed": "Denna podcast har ingen RSS-flöde",
|
||||
"ToastProgressIsNotBeingSynced": "Förloppet synkroniseras inte, starta om uppspelningen",
|
||||
"ToastProviderCreatedFailed": "Misslyckades med att addera en källa",
|
||||
"ToastProviderCreatedSuccess": "En ny källa har adderats",
|
||||
"ToastProviderNameAndUrlRequired": "Ett namn och en URL-adress krävs",
|
||||
|
|
@ -1105,9 +1131,12 @@
|
|||
"ToastSeriesUpdateFailed": "Misslyckades med att uppdatera serien",
|
||||
"ToastSeriesUpdateSuccess": "Uppdateringen av serierna lyckades",
|
||||
"ToastServerSettingsUpdateSuccess": "Inställningarna för servern har uppdaterats",
|
||||
"ToastSessionCloseFailed": "Misslyckades med att avsluta sessionen",
|
||||
"ToastSessionDeleteFailed": "Misslyckades med att ta bort sessionen",
|
||||
"ToastSessionDeleteSuccess": "Sessionen borttagen",
|
||||
"ToastSleepTimerDone": "Timer har stängt av lyssning. Sov gott... zZzzZz",
|
||||
"ToastSlugMustChange": "Slug innehåller ogiltiga tecken",
|
||||
"ToastSlugRequired": "Slug krävs",
|
||||
"ToastSocketConnected": "Socket ansluten",
|
||||
"ToastSocketDisconnected": "Socket frånkopplad",
|
||||
"ToastSocketFailedToConnect": "Socket misslyckades med att ansluta",
|
||||
|
|
@ -1118,6 +1147,7 @@
|
|||
"ToastUnlinkOpenIdFailed": "Misslyckades med att koppla bort användaren från OpenID",
|
||||
"ToastUnlinkOpenIdSuccess": "Användaren har kopplats bort från OpenID",
|
||||
"ToastUploaderFilepathExistsError": "En fil med namnet \"{0}\" finns redan på servern",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Objektet \"{0}\" använder en underkatalog till uppladdningssökvägen.",
|
||||
"ToastUserDeleteFailed": "Misslyckades med att ta bort användaren",
|
||||
"ToastUserDeleteSuccess": "Användaren borttagen",
|
||||
"ToastUserPasswordChangeSuccess": "Lösenordet har ändrats",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -383,7 +383,7 @@
|
|||
"LabelFolders": "Теки",
|
||||
"LabelFontBold": "Жирний",
|
||||
"LabelFontBoldness": "Товщина шрифту",
|
||||
"LabelFontFamily": "Гарнітура",
|
||||
"LabelFontFamily": "Сімейство шрифтів",
|
||||
"LabelFontItalic": "Курсив",
|
||||
"LabelFontScale": "Розмір шрифту",
|
||||
"LabelFontStrikethrough": "Закреслений",
|
||||
|
|
@ -436,9 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Ні {0}",
|
||||
"LabelLibraryItem": "Елемент бібліотеки",
|
||||
"LabelLibraryName": "Назва бібліотеки",
|
||||
"LabelLibrarySortByProgress": "Прогрес оновлено",
|
||||
"LabelLibrarySortByProgressFinished": "Дата завершення",
|
||||
"LabelLibrarySortByProgressStarted": "Дата початку",
|
||||
"LabelLibrarySortByProgress": "Прогрес: Останнє оновлення",
|
||||
"LabelLibrarySortByProgressFinished": "Прогрес: Завершено",
|
||||
"LabelLibrarySortByProgressStarted": "Прогрес: Розпочато",
|
||||
"LabelLimit": "Обмеження",
|
||||
"LabelLineSpacing": "Відстань між рядками",
|
||||
"LabelListenAgain": "Слухати знову",
|
||||
|
|
@ -588,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Імітує вигляд дерев'яних полиць",
|
||||
"LabelSettingsChromecastSupport": "Підтримка Chromecast",
|
||||
"LabelSettingsDateFormat": "Формат дати",
|
||||
"LabelSettingsEnableWatcher": "Автоматично сканувати бібліотеки на наявність змін",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Автоматично сканувати бібліотеку на наявність змін",
|
||||
"LabelSettingsEnableWatcher": "Автоматично відстежувати зміни в бібліотеках",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Автоматично відстежувати зміни в бібліотеці",
|
||||
"LabelSettingsEnableWatcherHelp": "Вмикає автоматичне додавання/оновлення елементів, коли спостерігаються зміни файлів. *Потребує перезавантаження сервера",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Дозволити JavaScript-вміст у epub",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Дозволяти epub-файлам виконувати код. Вмикайте цей параметр лише якщо ви довіряєте джерелу epub-файлів.",
|
||||
|
|
@ -888,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "Ви впевнені, що хочете скинути глави та скасувати внесені зміни?",
|
||||
"MessageRestoreBackupConfirm": "Ви впевнені, що хочете відновити резервну копію, створену",
|
||||
"MessageRestoreBackupWarning": "Відновлення резервної копії перезапише всю базу даних у /config і зображення обкладинок у /metadata/items та /metadata/authors.<br /><br />Резервні копії не змінюють файли у теках бібліотеки. Якщо у налаштуваннях сервера увімкнено збереження обкладинок і метаданих у теках бібліотеки, вони не створюються під час резервного копіювання і не перезаписуються.<br /><br />Всі клієнти, що користуються вашим сервером, будуть автоматично оновлені.",
|
||||
"MessageScheduleLibraryScanNote": "Для більшості користувачів рекомендується залишити цю функцію вимкненою та залишити параметр перегляду папок увімкненим. Засіб спостереження за папками автоматично виявить зміни в папках вашої бібліотеки. Засіб спостереження за папками не працює для кожної файлової системи (наприклад, NFS), тому замість нього можна використовувати сканування бібліотек за розкладом.",
|
||||
"MessageScheduleLibraryScanNote": "Для більшості користувачів рекомендується відключити цю функцію та підтримувати налаштування \"Автоматично переглядати бібліотеку для змін\" - вона автоматично виявить зміни в ваших папках бібліотеки. Звісніть цю функцію, якщо для вашої файлової системи (наприклад, NFS) не працює \"Автоматично переглядати бібліотеку.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Запуск кожні {0} о {1}",
|
||||
"MessageSearchResultsFor": "Результати пошуку для",
|
||||
"MessageSelected": "Вибрано: {0}",
|
||||
|
|
@ -1026,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "Не вдалося додати елемент(и) до колекції",
|
||||
"ToastCollectionRemoveSuccess": "Добірку видалено",
|
||||
"ToastCollectionUpdateSuccess": "Добірку оновлено",
|
||||
"ToastConnectionNotAvailable": "З’єднання недоступне. Спробуйте пізніше",
|
||||
"ToastCoverSearchFailed": "Пошук обкладинки не вдався",
|
||||
"ToastCoverUpdateFailed": "Не вдалося оновити обкладинку",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Дата й час недійсні або неповні",
|
||||
"ToastDeleteFileFailed": "Не вдалося видалити файл",
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@
|
|||
"LabelFolders": "文件夹",
|
||||
"LabelFontBold": "加粗",
|
||||
"LabelFontBoldness": "字体粗细",
|
||||
"LabelFontFamily": "字体系列",
|
||||
"LabelFontFamily": "字体",
|
||||
"LabelFontItalic": "斜体",
|
||||
"LabelFontScale": "字体比例",
|
||||
"LabelFontStrikethrough": "删除线",
|
||||
|
|
@ -436,9 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "没有 {0}",
|
||||
"LabelLibraryItem": "媒体库项目",
|
||||
"LabelLibraryName": "媒体库名称",
|
||||
"LabelLibrarySortByProgress": "进度更新时间",
|
||||
"LabelLibrarySortByProgressFinished": "完成日期",
|
||||
"LabelLibrarySortByProgressStarted": "开始日期",
|
||||
"LabelLibrarySortByProgress": "收听进度: 上次收听时间",
|
||||
"LabelLibrarySortByProgressFinished": "收听进度: 已完成的",
|
||||
"LabelLibrarySortByProgressStarted": "收听进度: 已开始的",
|
||||
"LabelLimit": "限制",
|
||||
"LabelLineSpacing": "行间距",
|
||||
"LabelListenAgain": "再次收听",
|
||||
|
|
@ -588,8 +588,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "带有木架子的拟物化设计",
|
||||
"LabelSettingsChromecastSupport": "Chromecast 支持",
|
||||
"LabelSettingsDateFormat": "日期格式",
|
||||
"LabelSettingsEnableWatcher": "自动扫描库以查找更改",
|
||||
"LabelSettingsEnableWatcherForLibrary": "自动扫描库以查找更改",
|
||||
"LabelSettingsEnableWatcher": "自动检测媒体库变化",
|
||||
"LabelSettingsEnableWatcherForLibrary": "自动检测媒体库变化",
|
||||
"LabelSettingsEnableWatcherHelp": "当检测到文件更改时, 启用项目的自动添加/更新. *需要重新启动服务器",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "允许 epubs 中包含脚本内容",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "允许 epub 文件执行脚本. 建议将此设置保持禁用, 除非你信任 epub 文件的来源.",
|
||||
|
|
@ -888,7 +888,7 @@
|
|||
"MessageResetChaptersConfirm": "你确定要重置章节并撤消你所做的更改吗?",
|
||||
"MessageRestoreBackupConfirm": "你确定要恢复创建的这个备份",
|
||||
"MessageRestoreBackupWarning": "恢复备份将覆盖位于 /config 的整个数据库并覆盖 /metadata/items & /metadata/authors 中的图像.<br /><br />备份不会修改媒体库文件夹中的任何文件. 如果你已启用服务器设置将封面和元数据存储在库文件夹中,则不会备份或覆盖这些内容.<br /><br />将自动刷新使用服务器的所有客户端.",
|
||||
"MessageScheduleLibraryScanNote": "对于大多数用户, 建议禁用此功能并保持文件夹监视程序设置启用. 文件夹监视程序将自动检测库文件夹中的更改. 文件夹监视程序不适用于每个文件系统 (如 NFS), 因此可以使用计划库扫描.",
|
||||
"MessageScheduleLibraryScanNote": "对于大多数用户, 建议保持此功能关闭并启用 \"自动检测媒体库变化\" 选项, 它会自动检测媒体库文件夹中的更改. 如果 \"自动检测媒体库变化\" 在你的文件系统 (例如 NFS) 上无法正常工作, 请启用此功能.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "每 {0} 的 {1} 执行",
|
||||
"MessageSearchResultsFor": "搜索结果",
|
||||
"MessageSelected": "{0} 已选择",
|
||||
|
|
@ -1026,6 +1026,8 @@
|
|||
"ToastCollectionItemsAddFailed": "项目添加到收藏夹失败",
|
||||
"ToastCollectionRemoveSuccess": "收藏夹已删除",
|
||||
"ToastCollectionUpdateSuccess": "收藏夹已更新",
|
||||
"ToastConnectionNotAvailable": "连接不可用. 请稍后重试",
|
||||
"ToastCoverSearchFailed": "封面搜索失败",
|
||||
"ToastCoverUpdateFailed": "封面更新失败",
|
||||
"ToastDateTimeInvalidOrIncomplete": "日期和时间无效或不完整",
|
||||
"ToastDeleteFileFailed": "删除文件失败",
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "audiobookshelf",
|
||||
"version": "2.29.0",
|
||||
"version": "2.31.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "audiobookshelf",
|
||||
"version": "2.29.0",
|
||||
"version": "2.31.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"axios": "^0.27.2",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "audiobookshelf",
|
||||
"version": "2.29.0",
|
||||
"version": "2.31.0",
|
||||
"buildNumber": 1,
|
||||
"description": "Self-hosted audiobook and podcast server",
|
||||
"main": "index.js",
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
"client": "cd client && npm ci && npm run generate",
|
||||
"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-no-compress": "npm run client && pkg -t node20-win-x64 -o ./dist/win/audiobookshelf .",
|
||||
"build-linux": "build/linuxpackager",
|
||||
"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",
|
||||
|
|
|
|||
|
|
@ -407,8 +407,7 @@ class Server {
|
|||
const nextApp = next({ dev: Logger.isDev, dir: ReactClientPath })
|
||||
const handle = nextApp.getRequestHandler()
|
||||
await nextApp.prepare()
|
||||
router.get('*', (req, res) => handle(req, res))
|
||||
router.post('/internal-api/*', (req, res) => handle(req, res))
|
||||
router.all('*', (req, res) => handle(req, res))
|
||||
}
|
||||
|
||||
const unixSocketPrefix = 'unix/'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const SocketIO = require('socket.io')
|
|||
const Logger = require('./Logger')
|
||||
const Database = require('./Database')
|
||||
const TokenManager = require('./auth/TokenManager')
|
||||
const CoverSearchManager = require('./managers/CoverSearchManager')
|
||||
|
||||
/**
|
||||
* @typedef SocketClient
|
||||
|
|
@ -180,6 +181,10 @@ class SocketAuthority {
|
|||
// Scanning
|
||||
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
|
||||
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
||||
socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id))
|
||||
|
|
@ -200,6 +205,10 @@ class SocketAuthority {
|
|||
|
||||
const disconnectTime = Date.now() - _client.connected_at
|
||||
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]
|
||||
}
|
||||
})
|
||||
|
|
@ -300,5 +309,100 @@ class SocketAuthority {
|
|||
Logger.debug('[SocketAuthority] Cancel scan', 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()
|
||||
|
|
|
|||
|
|
@ -527,7 +527,16 @@ class OidcAuthStrategy {
|
|||
|
||||
// For absolute URLs, ensure they point to the same origin
|
||||
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')
|
||||
|
||||
// Check if protocol and host match exactly
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ class TokenManager {
|
|||
|
||||
constructor() {
|
||||
/** @type {number} Refresh token expiry in seconds */
|
||||
this.RefreshTokenExpiry = parseInt(process.env.REFRESH_TOKEN_EXPIRY) || 7 * 24 * 60 * 60 // 7 days
|
||||
this.RefreshTokenExpiry = parseInt(process.env.REFRESH_TOKEN_EXPIRY) || 30 * 24 * 60 * 60 // 30 days
|
||||
/** @type {number} Access token expiry in seconds */
|
||||
this.AccessTokenExpiry = parseInt(process.env.ACCESS_TOKEN_EXPIRY) || 12 * 60 * 60 // 12 hours
|
||||
this.AccessTokenExpiry = parseInt(process.env.ACCESS_TOKEN_EXPIRY) || 1 * 60 * 60 // 1 hour
|
||||
|
||||
if (parseInt(process.env.REFRESH_TOKEN_EXPIRY) > 0) {
|
||||
Logger.info(`[TokenManager] Refresh token expiry set from ENV variable to ${this.RefreshTokenExpiry} seconds`)
|
||||
|
|
|
|||
|
|
@ -221,13 +221,11 @@ class LibraryController {
|
|||
const includeArray = (req.query.include || '').split(',')
|
||||
if (includeArray.includes('filterdata')) {
|
||||
const filterdata = await libraryFilters.getFilterData(req.library.mediaType, req.library.id)
|
||||
const customMetadataProviders = await Database.customMetadataProviderModel.getForClientByMediaType(req.library.mediaType)
|
||||
|
||||
return res.json({
|
||||
filterdata,
|
||||
issues: filterdata.numIssues,
|
||||
numUserPlaylists: await Database.playlistModel.getNumPlaylistsForUserAndLibrary(req.user.id, req.library.id),
|
||||
customMetadataProviders,
|
||||
library: req.library.toOldJSON()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,9 @@ class MiscController {
|
|||
Logger.warn('Cannot disable iframe when ALLOW_IFRAME is enabled in environment')
|
||||
return res.status(400).send('Cannot disable iframe when ALLOW_IFRAME is enabled in environment')
|
||||
}
|
||||
if (settingsUpdate.allowedOrigins && !Array.isArray(settingsUpdate.allowedOrigins)) {
|
||||
return res.status(400).send('allowedOrigins must be an array')
|
||||
}
|
||||
|
||||
const madeUpdates = Database.serverSettings.update(settingsUpdate)
|
||||
if (madeUpdates) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,29 @@ const BookFinder = require('../finders/BookFinder')
|
|||
const PodcastFinder = require('../finders/PodcastFinder')
|
||||
const AuthorFinder = require('../finders/AuthorFinder')
|
||||
const Database = require('../Database')
|
||||
const { isValidASIN } = require('../utils')
|
||||
const { isValidASIN, getQueryParamAsString, ValidationError, NotFoundError } = require('../utils')
|
||||
|
||||
// Provider name mappings for display purposes
|
||||
const providerMap = {
|
||||
all: 'All',
|
||||
best: 'Best',
|
||||
google: 'Google Books',
|
||||
itunes: 'iTunes',
|
||||
openlibrary: 'Open Library',
|
||||
fantlab: 'FantLab.ru',
|
||||
audiobookcovers: 'AudiobookCovers.com',
|
||||
audible: 'Audible.com',
|
||||
'audible.ca': 'Audible.ca',
|
||||
'audible.uk': 'Audible.co.uk',
|
||||
'audible.au': 'Audible.com.au',
|
||||
'audible.fr': 'Audible.fr',
|
||||
'audible.de': 'Audible.de',
|
||||
'audible.jp': 'Audible.co.jp',
|
||||
'audible.it': 'Audible.it',
|
||||
'audible.in': 'Audible.in',
|
||||
'audible.es': 'Audible.es',
|
||||
audnexus: 'Audnexus'
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef RequestUserObject
|
||||
|
|
@ -16,6 +38,44 @@ const { isValidASIN } = require('../utils')
|
|||
class SearchController {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Fetches a library item by ID
|
||||
* @param {string} id - Library item ID
|
||||
* @param {string} methodName - Name of the calling method for logging
|
||||
* @returns {Promise<import('../models/LibraryItem').LibraryItemExpanded>}
|
||||
*/
|
||||
static async fetchLibraryItem(id) {
|
||||
const libraryItem = await Database.libraryItemModel.getExpandedById(id)
|
||||
if (!libraryItem) {
|
||||
throw new NotFoundError(`library item "${id}" not found`)
|
||||
}
|
||||
return libraryItem
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps custom metadata providers to standardized format
|
||||
* @param {Array} providers - Array of custom provider objects
|
||||
* @returns {Array<{value: string, text: string}>}
|
||||
*/
|
||||
static mapCustomProviders(providers) {
|
||||
return providers.map((provider) => ({
|
||||
value: provider.getSlug(),
|
||||
text: provider.name
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper method to format provider for client (for use in array methods)
|
||||
* @param {string} providerValue - Provider identifier
|
||||
* @returns {{value: string, text: string}}
|
||||
*/
|
||||
static formatProvider(providerValue) {
|
||||
return {
|
||||
value: providerValue,
|
||||
text: providerMap[providerValue] || providerValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/search/books
|
||||
*
|
||||
|
|
@ -23,19 +83,25 @@ class SearchController {
|
|||
* @param {Response} res
|
||||
*/
|
||||
async findBooks(req, res) {
|
||||
const id = req.query.id
|
||||
const libraryItem = await Database.libraryItemModel.getExpandedById(id)
|
||||
const provider = req.query.provider || 'google'
|
||||
const title = req.query.title || ''
|
||||
const author = req.query.author || ''
|
||||
try {
|
||||
const query = req.query
|
||||
const provider = getQueryParamAsString(query, 'provider', 'google')
|
||||
const title = getQueryParamAsString(query, 'title', '')
|
||||
const author = getQueryParamAsString(query, 'author', '')
|
||||
const id = getQueryParamAsString(query, 'id', undefined)
|
||||
|
||||
if (typeof provider !== 'string' || typeof title !== 'string' || typeof author !== 'string') {
|
||||
Logger.error(`[SearchController] findBooks: Invalid request query params`)
|
||||
return res.status(400).send('Invalid request query params')
|
||||
// Fetch library item
|
||||
const libraryItem = id ? await SearchController.fetchLibraryItem(id) : null
|
||||
|
||||
const results = await BookFinder.search(libraryItem, provider, title, author)
|
||||
res.json(results)
|
||||
} catch (error) {
|
||||
Logger.error(`[SearchController] findBooks: ${error.message}`)
|
||||
if (error instanceof ValidationError || error instanceof NotFoundError) {
|
||||
return res.status(error.status).json({ error: error.message })
|
||||
}
|
||||
return res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
|
||||
const results = await BookFinder.search(libraryItem, provider, title, author)
|
||||
res.json(results)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -45,20 +111,24 @@ class SearchController {
|
|||
* @param {Response} res
|
||||
*/
|
||||
async findCovers(req, res) {
|
||||
const query = req.query
|
||||
const podcast = query.podcast == 1
|
||||
try {
|
||||
const query = req.query
|
||||
const podcast = query.podcast === '1' || query.podcast === 1
|
||||
const title = getQueryParamAsString(query, 'title', '', true)
|
||||
const author = getQueryParamAsString(query, 'author', '')
|
||||
const provider = getQueryParamAsString(query, 'provider', 'google')
|
||||
|
||||
if (!query.title || typeof query.title !== 'string') {
|
||||
Logger.error(`[SearchController] findCovers: Invalid title sent in query`)
|
||||
return res.sendStatus(400)
|
||||
let results = null
|
||||
if (podcast) results = await PodcastFinder.findCovers(title)
|
||||
else results = await BookFinder.findCovers(provider, title, author)
|
||||
res.json({ results })
|
||||
} catch (error) {
|
||||
Logger.error(`[SearchController] findCovers: ${error.message}`)
|
||||
if (error instanceof ValidationError) {
|
||||
return res.status(error.status).json({ error: error.message })
|
||||
}
|
||||
return res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
|
||||
let results = null
|
||||
if (podcast) results = await PodcastFinder.findCovers(query.title)
|
||||
else results = await BookFinder.findCovers(query.provider || 'google', query.title, query.author || '')
|
||||
res.json({
|
||||
results
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -69,34 +139,42 @@ class SearchController {
|
|||
* @param {Response} res
|
||||
*/
|
||||
async findPodcasts(req, res) {
|
||||
const term = req.query.term
|
||||
const country = req.query.country || 'us'
|
||||
if (!term) {
|
||||
Logger.error('[SearchController] Invalid request query param "term" is required')
|
||||
return res.status(400).send('Invalid request query param "term" is required')
|
||||
}
|
||||
try {
|
||||
const query = req.query
|
||||
const term = getQueryParamAsString(query, 'term', '', true)
|
||||
const country = getQueryParamAsString(query, 'country', 'us')
|
||||
|
||||
const results = await PodcastFinder.search(term, {
|
||||
country
|
||||
})
|
||||
res.json(results)
|
||||
const results = await PodcastFinder.search(term, { country })
|
||||
res.json(results)
|
||||
} catch (error) {
|
||||
Logger.error(`[SearchController] findPodcasts: ${error.message}`)
|
||||
if (error instanceof ValidationError) {
|
||||
return res.status(error.status).json({ error: error.message })
|
||||
}
|
||||
return res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/search/authors
|
||||
* Note: This endpoint is not currently used in the web client.
|
||||
*
|
||||
* @param {RequestWithUser} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
async findAuthor(req, res) {
|
||||
const query = req.query.q
|
||||
if (!query || typeof query !== 'string') {
|
||||
Logger.error(`[SearchController] findAuthor: Invalid query param`)
|
||||
return res.status(400).send('Invalid query param')
|
||||
}
|
||||
try {
|
||||
const query = getQueryParamAsString(req.query, 'q', '', true)
|
||||
|
||||
const author = await AuthorFinder.findAuthorByName(query)
|
||||
res.json(author)
|
||||
const author = await AuthorFinder.findAuthorByName(query)
|
||||
res.json(author)
|
||||
} catch (error) {
|
||||
Logger.error(`[SearchController] findAuthor: ${error.message}`)
|
||||
if (error instanceof ValidationError) {
|
||||
return res.status(error.status).json({ error: error.message })
|
||||
}
|
||||
return res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -106,16 +184,55 @@ class SearchController {
|
|||
* @param {Response} res
|
||||
*/
|
||||
async findChapters(req, res) {
|
||||
const asin = req.query.asin
|
||||
if (!isValidASIN(asin.toUpperCase())) {
|
||||
return res.json({ error: 'Invalid ASIN', stringKey: 'MessageInvalidAsin' })
|
||||
try {
|
||||
const query = req.query
|
||||
const asin = getQueryParamAsString(query, 'asin', '', true)
|
||||
const region = getQueryParamAsString(query, 'region', 'us').toLowerCase()
|
||||
|
||||
if (!isValidASIN(asin.toUpperCase())) throw new ValidationError('asin', 'is invalid')
|
||||
|
||||
const chapterData = await BookFinder.findChapters(asin, region)
|
||||
if (!chapterData) {
|
||||
return res.json({ error: 'Chapters not found', stringKey: 'MessageChaptersNotFound' })
|
||||
}
|
||||
res.json(chapterData)
|
||||
} catch (error) {
|
||||
Logger.error(`[SearchController] findChapters: ${error.message}`)
|
||||
if (error instanceof ValidationError) {
|
||||
if (error.paramName === 'asin') {
|
||||
return res.json({ error: 'Invalid ASIN', stringKey: 'MessageInvalidAsin' })
|
||||
}
|
||||
if (error.paramName === 'region') {
|
||||
return res.json({ error: 'Invalid region', stringKey: 'MessageInvalidRegion' })
|
||||
}
|
||||
}
|
||||
return res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
const region = (req.query.region || 'us').toLowerCase()
|
||||
const chapterData = await BookFinder.findChapters(asin, region)
|
||||
if (!chapterData) {
|
||||
return res.json({ error: 'Chapters not found', stringKey: 'MessageChaptersNotFound' })
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/search/providers
|
||||
* Get all available metadata providers
|
||||
*
|
||||
* @param {RequestWithUser} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
async getAllProviders(req, res) {
|
||||
const customProviders = await Database.customMetadataProviderModel.findAll()
|
||||
|
||||
const customBookProviders = customProviders.filter((p) => p.mediaType === 'book')
|
||||
const customPodcastProviders = customProviders.filter((p) => p.mediaType === 'podcast')
|
||||
|
||||
const bookProviders = BookFinder.providers.filter((p) => p !== 'audiobookcovers')
|
||||
|
||||
// Build minimized payload with custom providers merged in
|
||||
const providers = {
|
||||
books: [...bookProviders.map((p) => SearchController.formatProvider(p)), ...SearchController.mapCustomProviders(customBookProviders)],
|
||||
booksCovers: [SearchController.formatProvider('best'), ...BookFinder.providers.map((p) => SearchController.formatProvider(p)), ...SearchController.mapCustomProviders(customBookProviders), SearchController.formatProvider('all')],
|
||||
podcasts: [SearchController.formatProvider('itunes'), ...SearchController.mapCustomProviders(customPodcastProviders)]
|
||||
}
|
||||
res.json(chapterData)
|
||||
|
||||
res.json({ providers })
|
||||
}
|
||||
}
|
||||
module.exports = new SearchController()
|
||||
|
|
|
|||
|
|
@ -339,9 +339,9 @@ class SessionController {
|
|||
var playbackSession = this.playbackSessionManager.getSession(req.params.id)
|
||||
if (!playbackSession) return res.sendStatus(404)
|
||||
|
||||
if (playbackSession.userId !== req.user.id) {
|
||||
Logger.error(`[SessionController] User "${req.user.username}" attempting to access session belonging to another user "${req.params.id}"`)
|
||||
return res.sendStatus(404)
|
||||
if (playbackSession.userId !== req.user.id && !req.user.isAdminOrUp) {
|
||||
Logger.error(`[SessionController] Non-admin user "${req.user.username}" attempting to access session belonging to another user "${req.params.id}"`)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
req.playbackSession = playbackSession
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const { levenshteinDistance, levenshteinSimilarity, escapeRegExp, isValidASIN }
|
|||
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||
|
||||
class BookFinder {
|
||||
#providerResponseTimeout = 30000
|
||||
#providerResponseTimeout = 10000
|
||||
|
||||
constructor() {
|
||||
this.openLibrary = new OpenLibrary()
|
||||
|
|
@ -385,6 +385,11 @@ class BookFinder {
|
|||
|
||||
if (!title) return books
|
||||
|
||||
// Truncate excessively long inputs to prevent ReDoS attacks
|
||||
const MAX_INPUT_LENGTH = 500
|
||||
title = title.substring(0, MAX_INPUT_LENGTH)
|
||||
author = author?.substring(0, MAX_INPUT_LENGTH) || author
|
||||
|
||||
const isTitleAsin = isValidASIN(title.toUpperCase())
|
||||
|
||||
let actualTitleQuery = title
|
||||
|
|
@ -402,7 +407,8 @@ class BookFinder {
|
|||
let authorCandidates = new BookFinder.AuthorCandidates(cleanAuthor, this.audnexus)
|
||||
|
||||
// Remove underscores and parentheses with their contents, and replace with a separator
|
||||
const cleanTitle = title.replace(/\[.*?\]|\(.*?\)|{.*?}|_/g, ' - ')
|
||||
// Use negated character classes to prevent ReDoS vulnerability (input length validated at entry point)
|
||||
const cleanTitle = title.replace(/\[[^\]]*\]|\([^)]*\)|{[^}]*}|_/g, ' - ')
|
||||
// Split title into hypen-separated parts
|
||||
const titleParts = cleanTitle.split(/ - | -|- /)
|
||||
for (const titlePart of titleParts) authorCandidates.add(titlePart)
|
||||
|
|
@ -422,7 +428,7 @@ class BookFinder {
|
|||
}
|
||||
}
|
||||
|
||||
if (books.length) {
|
||||
if (books.length && libraryItem) {
|
||||
const isAudibleProvider = provider.startsWith('audible')
|
||||
const libraryItemDurationMinutes = libraryItem?.media?.duration ? libraryItem.media.duration / 60 : null
|
||||
|
||||
|
|
@ -608,6 +614,14 @@ class BookFinder {
|
|||
Logger.debug(`[BookFinder] Found ${providerResults.length} covers from ${providerString}`)
|
||||
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 {
|
||||
searchResults = await this.search(null, provider, title, author, options)
|
||||
}
|
||||
|
|
@ -660,7 +674,9 @@ function cleanTitleForCompares(title, keepSubtitle = false) {
|
|||
let stripped = keepSubtitle ? title : stripSubtitle(title)
|
||||
|
||||
// Remove text in paranthesis (i.e. "Ender's Game (Ender's Saga)" becomes "Ender's Game")
|
||||
let cleaned = stripped.replace(/ *\([^)]*\) */g, '')
|
||||
// Use negated character class to prevent ReDoS vulnerability (input length validated at entry point)
|
||||
let cleaned = stripped.replace(/\([^)]*\)/g, '') // Remove parenthetical content
|
||||
cleaned = cleaned.replace(/\s+/g, ' ').trim() // Clean up any resulting multiple spaces
|
||||
|
||||
// Remove single quotes (i.e. "Ender's Game" becomes "Enders Game")
|
||||
cleaned = cleaned.replace(/'/g, '')
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ class PodcastFinder {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} term
|
||||
* @param {{country:string}} options
|
||||
*
|
||||
* @param {string} term
|
||||
* @param {{country:string}} options
|
||||
* @returns {Promise<import('../providers/iTunes').iTunesPodcastSearchResult[]>}
|
||||
*/
|
||||
async search(term, options = {}) {
|
||||
|
|
@ -20,12 +20,16 @@ class PodcastFinder {
|
|||
return results
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} term
|
||||
* @returns {Promise<string[]>}
|
||||
*/
|
||||
async findCovers(term) {
|
||||
if (!term) return null
|
||||
Logger.debug(`[iTunes] Searching for podcast covers with term "${term}"`)
|
||||
var results = await this.iTunesApi.searchPodcasts(term)
|
||||
const results = await this.iTunesApi.searchPodcasts(term)
|
||||
if (!results) return []
|
||||
return results.map(r => r.cover).filter(r => r)
|
||||
return results.map((r) => r.cover).filter((r) => r)
|
||||
}
|
||||
}
|
||||
module.exports = new PodcastFinder()
|
||||
module.exports = new PodcastFinder()
|
||||
|
|
|
|||
|
|
@ -48,9 +48,14 @@ class BackupManager {
|
|||
}
|
||||
|
||||
async init() {
|
||||
const backupsDirExists = await fs.pathExists(this.backupPath)
|
||||
if (!backupsDirExists) {
|
||||
await fs.ensureDir(this.backupPath)
|
||||
try {
|
||||
const backupsDirExists = await fs.pathExists(this.backupPath)
|
||||
if (!backupsDirExists) {
|
||||
await fs.ensureDir(this.backupPath)
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.error(`[BackupManager] Failed to ensure backup directory at "${this.backupPath}": ${error.message}`)
|
||||
throw new Error(`[BackupManager] Failed to ensure backup directory at "${this.backupPath}"`, { cause: error })
|
||||
}
|
||||
|
||||
await this.loadBackups()
|
||||
|
|
|
|||
|
|
@ -24,10 +24,15 @@ class CacheManager {
|
|||
this.ImageCachePath = Path.join(this.CachePath, 'images')
|
||||
this.ItemCachePath = Path.join(this.CachePath, 'items')
|
||||
|
||||
await fs.ensureDir(this.CachePath)
|
||||
await fs.ensureDir(this.CoverCachePath)
|
||||
await fs.ensureDir(this.ImageCachePath)
|
||||
await fs.ensureDir(this.ItemCachePath)
|
||||
try {
|
||||
await fs.ensureDir(this.CachePath)
|
||||
await fs.ensureDir(this.CoverCachePath)
|
||||
await fs.ensureDir(this.ImageCachePath)
|
||||
await fs.ensureDir(this.ItemCachePath)
|
||||
} catch (error) {
|
||||
Logger.error(`[CacheManager] Failed to create cache directories at "${this.CachePath}": ${error.message}`)
|
||||
throw new Error(`[CacheManager] Failed to create cache directories at "${this.CachePath}"`, { cause: error })
|
||||
}
|
||||
}
|
||||
|
||||
async handleCoverCache(res, libraryItemId, options = {}) {
|
||||
|
|
|
|||
254
server/managers/CoverSearchManager.js
Normal file
254
server/managers/CoverSearchManager.js
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
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 (typeof result === 'string') {
|
||||
covers.push(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()
|
||||
|
|
@ -37,8 +37,13 @@ class LogManager {
|
|||
}
|
||||
|
||||
async ensureLogDirs() {
|
||||
await fs.ensureDir(this.DailyLogPath)
|
||||
await fs.ensureDir(this.ScanLogPath)
|
||||
try {
|
||||
await fs.ensureDir(this.DailyLogPath)
|
||||
await fs.ensureDir(this.ScanLogPath)
|
||||
} catch (error) {
|
||||
console.error(`[LogManager] Failed to create log directories at "${this.DailyLogPath}": ${error.message}`)
|
||||
throw new Error(`[LogManager] Failed to create log directories at "${this.DailyLogPath}"`, { cause: error })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -169,7 +174,7 @@ class LogManager {
|
|||
/**
|
||||
* Most recent 5000 daily logs
|
||||
*
|
||||
* @returns {LogObject[]}
|
||||
* @returns {string}
|
||||
*/
|
||||
getMostRecentCurrentDailyLogs() {
|
||||
return this.currentDailyLog?.logs.slice(-5000) || []
|
||||
|
|
|
|||
|
|
@ -38,7 +38,12 @@ class MigrationManager {
|
|||
if (!(await fs.pathExists(this.configPath))) throw new Error(`Config path does not exist: ${this.configPath}`)
|
||||
|
||||
this.migrationsDir = path.join(this.configPath, 'migrations')
|
||||
await fs.ensureDir(this.migrationsDir)
|
||||
try {
|
||||
await fs.ensureDir(this.migrationsDir)
|
||||
} catch (error) {
|
||||
Logger.error(`[MigrationManager] Failed to create migrations directory at "${this.migrationsDir}": ${error.message}`)
|
||||
throw new Error(`[MigrationManager] Failed to create migrations directory at "${this.migrationsDir}"`, { cause: error })
|
||||
}
|
||||
|
||||
this.serverVersion = this.extractVersionFromTag(serverVersion)
|
||||
if (!this.serverVersion) throw new Error(`Invalid server version: ${serverVersion}. Expected a version tag like v1.2.3.`)
|
||||
|
|
|
|||
|
|
@ -459,7 +459,12 @@ class PlaybackSessionManager {
|
|||
* Remove all stream folders in `/metadata/streams`
|
||||
*/
|
||||
async removeOrphanStreams() {
|
||||
await fs.ensureDir(this.StreamsPath)
|
||||
try {
|
||||
await fs.ensureDir(this.StreamsPath)
|
||||
} catch (error) {
|
||||
Logger.error(`[PlaybackSessionManager] Failed to create streams directory at "${this.StreamsPath}": ${error.message}`)
|
||||
throw new Error(`[PlaybackSessionManager] Failed to create streams directory at "${this.StreamsPath}"`, { cause: error })
|
||||
}
|
||||
try {
|
||||
const streamsInPath = await fs.readdir(this.StreamsPath)
|
||||
for (const streamId of streamsInPath) {
|
||||
|
|
|
|||
|
|
@ -127,10 +127,20 @@ class PodcastManager {
|
|||
})
|
||||
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
|
||||
// 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`)
|
||||
// Download episode only
|
||||
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
|
||||
|
|
@ -139,23 +149,20 @@ class PodcastManager {
|
|||
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
||||
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) {
|
||||
success = await this.scanAddPodcastEpisodeAudioFile()
|
||||
if (!success) {
|
||||
await fs.remove(this.currentDownload.targetPath)
|
||||
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()
|
||||
}
|
||||
Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.episodeTitle}"`)
|
||||
this.currentDownload.setFinished(true)
|
||||
task.setFinished()
|
||||
} else {
|
||||
const taskFailedString = {
|
||||
text: 'Failed',
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class Stream extends EventEmitter {
|
|||
return [AudioMimeType.FLAC, AudioMimeType.OPUS, AudioMimeType.WMA, AudioMimeType.AIFF, AudioMimeType.WEBM, AudioMimeType.WEBMA, AudioMimeType.AWB, AudioMimeType.CAF]
|
||||
}
|
||||
get codecsToForceAAC() {
|
||||
return ['alac']
|
||||
return ['alac', 'ac3', 'eac3']
|
||||
}
|
||||
get userToken() {
|
||||
return this.user.token
|
||||
|
|
@ -273,7 +273,16 @@ class Stream extends EventEmitter {
|
|||
audioCodec = 'aac'
|
||||
}
|
||||
|
||||
this.ffmpeg.addOption([`-loglevel ${logLevel}`, '-map 0:a', `-c:a ${audioCodec}`])
|
||||
const codecOptions = [`-loglevel ${logLevel}`, '-map 0:a']
|
||||
|
||||
if (['ac3', 'eac3'].includes(this.tracksCodec) && this.tracks.length > 0 && this.tracks[0].bitRate && this.tracks[0].channels) {
|
||||
// In case for ac3/eac3 it needs to be passed the bitrate and channels to avoid ffmpeg errors
|
||||
codecOptions.push(`-c:a ${audioCodec}`, `-b:a ${this.tracks[0].bitRate}`, `-ac ${this.tracks[0].channels}`)
|
||||
} else {
|
||||
codecOptions.push(`-c:a ${audioCodec}`)
|
||||
}
|
||||
|
||||
this.ffmpeg.addOption(codecOptions)
|
||||
const hlsOptions = ['-f hls', '-copyts', '-avoid_negative_ts make_non_negative', '-max_delay 5000000', '-max_muxing_queue_size 2048', `-hls_time 6`, `-hls_segment_type ${this.hlsSegmentType}`, `-start_number ${this.segmentStartNumber}`, '-hls_playlist_type vod', '-hls_list_size 0', '-hls_allow_cache 0']
|
||||
this.ffmpeg.addOption(hlsOptions)
|
||||
if (this.hlsSegmentType === 'fmp4') {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const Logger = require('../Logger')
|
|||
const { isValidASIN } = require('../utils/index')
|
||||
|
||||
class Audible {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
|
||||
constructor() {
|
||||
this.regionMap = {
|
||||
|
|
@ -106,7 +106,7 @@ class Audible {
|
|||
return res.data
|
||||
})
|
||||
.catch((error) => {
|
||||
Logger.error('[Audible] ASIN search error', error)
|
||||
Logger.error('[Audible] ASIN search error', error.message)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ class Audible {
|
|||
return Promise.all(res.data.products.map((result) => this.asinSearch(result.asin, region, timeout)))
|
||||
})
|
||||
.catch((error) => {
|
||||
Logger.error('[Audible] query search error', error)
|
||||
Logger.error('[Audible] query search error', error.message)
|
||||
return []
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const axios = require('axios')
|
|||
const Logger = require('../Logger')
|
||||
|
||||
class AudiobookCovers {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
|
||||
constructor() {}
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ class AudiobookCovers {
|
|||
})
|
||||
.then((res) => res?.data || [])
|
||||
.catch((error) => {
|
||||
Logger.error('[AudiobookCovers] Cover search error', error)
|
||||
Logger.error('[AudiobookCovers] Cover search error', error.message)
|
||||
return []
|
||||
})
|
||||
return items.map((item) => ({ cover: item.versions.png.original }))
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class Audnexus {
|
|||
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl)))
|
||||
.then((res) => res.data || [])
|
||||
.catch((error) => {
|
||||
Logger.error(`[Audnexus] Author ASIN request failed for ${name}`, error)
|
||||
Logger.error(`[Audnexus] Author ASIN request failed for ${name}`, error.message)
|
||||
return []
|
||||
})
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ class Audnexus {
|
|||
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl.toString())))
|
||||
.then((res) => res.data)
|
||||
.catch((error) => {
|
||||
Logger.error(`[Audnexus] Author request failed for ${asin}`, error)
|
||||
Logger.error(`[Audnexus] Author request failed for ${asin}`, error.message)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ class Audnexus {
|
|||
return this._processRequest(this.limiter(() => axios.get(chaptersRequestUrl.toString())))
|
||||
.then((res) => res.data)
|
||||
.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
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const Logger = require('../Logger')
|
|||
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||
|
||||
class CustomProviderAdapter {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
|
||||
constructor() {}
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ class CustomProviderAdapter {
|
|||
return res.data.matches
|
||||
})
|
||||
.catch((error) => {
|
||||
Logger.error('[CustomMetadataProvider] Search error', error)
|
||||
Logger.error('[CustomMetadataProvider] Search error', error.message)
|
||||
return []
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const axios = require('axios')
|
|||
const Logger = require('../Logger')
|
||||
|
||||
class FantLab {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
// 7 - other
|
||||
// 11 - essay
|
||||
// 12 - article
|
||||
|
|
@ -48,7 +48,7 @@ class FantLab {
|
|||
return res.data || []
|
||||
})
|
||||
.catch((error) => {
|
||||
Logger.error('[FantLab] search error', error)
|
||||
Logger.error('[FantLab] search error', error.message)
|
||||
return []
|
||||
})
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ class FantLab {
|
|||
return resp.data || null
|
||||
})
|
||||
.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
|
||||
})
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ class FantLab {
|
|||
return resp.data || null
|
||||
})
|
||||
.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
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const axios = require('axios')
|
|||
const Logger = require('../Logger')
|
||||
|
||||
class GoogleBooks {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
|
||||
constructor() {}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ class GoogleBooks {
|
|||
return res.data.items
|
||||
})
|
||||
.catch((error) => {
|
||||
Logger.error('[GoogleBooks] Volume search error', error)
|
||||
Logger.error('[GoogleBooks] Volume search error', error.message)
|
||||
return []
|
||||
})
|
||||
return items.map((item) => this.cleanResult(item))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const axios = require('axios').default
|
||||
|
||||
class OpenLibrary {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
|
||||
constructor() {
|
||||
this.baseUrl = 'https://openlibrary.org'
|
||||
|
|
@ -23,7 +23,7 @@ class OpenLibrary {
|
|||
return res.data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
console.error('Failed', error.message)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const htmlSanitizer = require('../utils/htmlSanitizer')
|
|||
*/
|
||||
|
||||
class iTunes {
|
||||
#responseTimeout = 30000
|
||||
#responseTimeout = 10000
|
||||
|
||||
constructor() {}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ class iTunes {
|
|||
return response.data.results || []
|
||||
})
|
||||
.catch((error) => {
|
||||
Logger.error(`[iTunes] search request error`, error)
|
||||
Logger.error(`[iTunes] search request error`, error.message)
|
||||
return []
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,6 +283,7 @@ class ApiRouter {
|
|||
this.router.get('/search/podcast', SearchController.findPodcasts.bind(this))
|
||||
this.router.get('/search/authors', SearchController.findAuthor.bind(this))
|
||||
this.router.get('/search/chapters', SearchController.findChapters.bind(this))
|
||||
this.router.get('/search/providers', SearchController.getAllProviders.bind(this))
|
||||
|
||||
//
|
||||
// Cache Routes (Admin and up)
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ module.exports.resizeImage = resizeImage
|
|||
/**
|
||||
*
|
||||
* @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload
|
||||
* @returns {Promise<{success: boolean, isFfmpegError?: boolean}>}
|
||||
* @returns {Promise<{success: boolean, isRequestError?: boolean}>}
|
||||
*/
|
||||
module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
||||
return new Promise(async (resolve) => {
|
||||
|
|
@ -118,7 +118,7 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
|||
method: 'GET',
|
||||
responseType: 'stream',
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
Accept: '*/*',
|
||||
'User-Agent': userAgent
|
||||
},
|
||||
timeout: global.PodcastDownloadTimeout
|
||||
|
|
@ -139,7 +139,8 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
|
|||
|
||||
if (!response) {
|
||||
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')}`)
|
||||
}
|
||||
resolve({
|
||||
success: false,
|
||||
isFfmpegError: true
|
||||
success: false
|
||||
})
|
||||
})
|
||||
ffmpeg.on('progress', (progress) => {
|
||||
|
|
|
|||
|
|
@ -277,3 +277,57 @@ module.exports.timestampToSeconds = (timestamp) => {
|
|||
}
|
||||
return null
|
||||
}
|
||||
|
||||
class ValidationError extends Error {
|
||||
constructor(paramName, message, status = 400) {
|
||||
super(`Query parameter "${paramName}" ${message}`)
|
||||
this.name = 'ValidationError'
|
||||
this.paramName = paramName
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
module.exports.ValidationError = ValidationError
|
||||
|
||||
class NotFoundError extends Error {
|
||||
constructor(message, status = 404) {
|
||||
super(message)
|
||||
this.name = 'NotFoundError'
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
module.exports.NotFoundError = NotFoundError
|
||||
|
||||
/**
|
||||
* Safely extracts a query parameter as a string, rejecting arrays to prevent type confusion
|
||||
* Express query parameters can be arrays if the same parameter appears multiple times
|
||||
* @example ?author=Smith => "Smith"
|
||||
* @example ?author=Smith&author=Jones => throws error
|
||||
*
|
||||
* @param {Object} query - Query object
|
||||
* @param {string} paramName - Parameter name
|
||||
* @param {string} defaultValue - Default value if undefined/null
|
||||
* @param {boolean} required - Whether the parameter is required
|
||||
* @param {number} maxLength - Optional maximum length (defaults to 10000 to prevent ReDoS attacks)
|
||||
* @returns {string} String value
|
||||
* @throws {ValidationError} If value is an array
|
||||
* @throws {ValidationError} If value is too long
|
||||
* @throws {ValidationError} If value is required but not provided
|
||||
*/
|
||||
module.exports.getQueryParamAsString = (query, paramName, defaultValue = '', required = false, maxLength = 1000) => {
|
||||
const value = query[paramName]
|
||||
if (value === undefined || value === null) {
|
||||
if (required) {
|
||||
throw new ValidationError(paramName, 'is required')
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
// Explicitly reject arrays to prevent type confusion
|
||||
if (Array.isArray(value)) {
|
||||
throw new ValidationError(paramName, 'is an array')
|
||||
}
|
||||
// Reject excessively long strings to prevent ReDoS attacks
|
||||
if (typeof value === 'string' && value.length > maxLength) {
|
||||
throw new ValidationError(paramName, 'is too long')
|
||||
}
|
||||
return String(value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ function extractEpisodeData(item) {
|
|||
|
||||
// Full description with html
|
||||
if (item['content:encoded']) {
|
||||
const rawDescription = (extractFirstArrayItem(item, 'content:encoded') || '').trim()
|
||||
const rawDescription = (extractFirstArrayItemString(item, 'content:encoded') || '').trim()
|
||||
episode.description = htmlSanitizer.sanitize(rawDescription)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue