mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-12-31 11:38:47 -05:00
Compare commits
92 Commits
audiobook_
...
check_path
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ce1806359 | ||
|
|
f05a513767 | ||
|
|
d03c338b48 | ||
|
|
5e5a988f7a | ||
|
|
6d1f0b27df | ||
|
|
d01a7cb756 | ||
|
|
cae874ef05 | ||
|
|
733afc3e29 | ||
|
|
0772730336 | ||
|
|
8b02fe07c8 | ||
|
|
98f93a665c | ||
|
|
754566b221 | ||
|
|
f4f9adad35 | ||
|
|
16f7f1166e | ||
|
|
f527b0f4d5 | ||
|
|
4f41df53c9 | ||
|
|
8a15f775a2 | ||
|
|
5e83bcd283 | ||
|
|
2fd5dfcb66 | ||
|
|
872ce4fa38 | ||
|
|
ba792d91e5 | ||
|
|
4997c716db | ||
|
|
fd72d05280 | ||
|
|
241b56ad45 | ||
|
|
635c384952 | ||
|
|
ef930fd1b4 | ||
|
|
49997a1336 | ||
|
|
8d0434143c | ||
|
|
8e0319994e | ||
|
|
0ed6045d1e | ||
|
|
25c7e95a64 | ||
|
|
1781c4bbcb | ||
|
|
c4ce72d44e | ||
|
|
78813c4b28 | ||
|
|
990baa2dc6 | ||
|
|
c85f4467d2 | ||
|
|
59f7609054 | ||
|
|
2ef827e3fa | ||
|
|
5cadc8d90f | ||
|
|
40e7e36ef6 | ||
|
|
d60ad96f8a | ||
|
|
46ba342d49 | ||
|
|
ace6b2b81f | ||
|
|
fa7e2dfafe | ||
|
|
015310c15d | ||
|
|
f624f04dec | ||
|
|
7c13cfcda2 | ||
|
|
fc265dadae | ||
|
|
f9905f887e | ||
|
|
eb72bfbbc0 | ||
|
|
c268cace09 | ||
|
|
9666caf7a3 | ||
|
|
9e01e5c24e | ||
|
|
25e613a867 | ||
|
|
fe23a86eaa | ||
|
|
cb5a7d6aef | ||
|
|
7deb89ce7a | ||
|
|
1e300c77c9 | ||
|
|
ed7cc42959 | ||
|
|
f681ff68a1 | ||
|
|
ba112bf9c2 | ||
|
|
718434545a | ||
|
|
0e9a4c95a9 | ||
|
|
3c997c8468 | ||
|
|
eb49646256 | ||
|
|
c54b5eadfd | ||
|
|
659c671c25 | ||
|
|
0df5a7816d | ||
|
|
26c976b6b9 | ||
|
|
bdeb22615e | ||
|
|
257bf2ebe0 | ||
|
|
fc33da447a | ||
|
|
df45347690 | ||
|
|
b876256736 | ||
|
|
3ce6e45761 | ||
|
|
5ac6b85da1 | ||
|
|
69e0a0732a | ||
|
|
087835a9f3 | ||
|
|
1f7b181b7b | ||
|
|
1afb8840db | ||
|
|
d9531166b6 | ||
|
|
336de49d8d | ||
|
|
3cc527484d | ||
|
|
45987ffd63 | ||
|
|
1a1ef9c378 | ||
|
|
a1074e69ac | ||
|
|
65aec6a099 | ||
|
|
38957d4f32 | ||
|
|
a2dc76e190 | ||
|
|
dc3c978f8d | ||
|
|
13fac2d5bc | ||
|
|
fd0af6b2dd |
50
Dockerfile
50
Dockerfile
@@ -1,34 +1,32 @@
|
||||
ARG NUSQLITE3_DIR="/usr/local/lib/nusqlite3"
|
||||
ARG NUSQLITE3_PATH="${NUSQLITE3_DIR}/libnusqlite3.so"
|
||||
|
||||
### STAGE 0: Build client ###
|
||||
FROM node:20-alpine AS build
|
||||
FROM node:20-alpine AS build-client
|
||||
|
||||
WORKDIR /client
|
||||
COPY /client /client
|
||||
RUN npm ci && npm cache clean --force
|
||||
RUN npm run generate
|
||||
|
||||
### STAGE 1: Build server ###
|
||||
FROM node:20-alpine
|
||||
FROM node:20-alpine AS build-server
|
||||
|
||||
ARG NUSQLITE3_DIR
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN apk update && \
|
||||
apk add --no-cache --update \
|
||||
RUN apk add --no-cache --update \
|
||||
curl \
|
||||
tzdata \
|
||||
ffmpeg \
|
||||
make \
|
||||
python3 \
|
||||
g++ \
|
||||
tini \
|
||||
unzip
|
||||
|
||||
COPY --from=build /client/dist /client/dist
|
||||
COPY index.js package* /
|
||||
COPY server server
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
ENV NUSQLITE3_DIR="/usr/local/lib/nusqlite3"
|
||||
ENV NUSQLITE3_PATH="${NUSQLITE3_DIR}/libnusqlite3.so"
|
||||
WORKDIR /server
|
||||
COPY index.js package* /server
|
||||
COPY /server /server/server
|
||||
|
||||
RUN case "$TARGETPLATFORM" in \
|
||||
"linux/amd64") \
|
||||
@@ -42,14 +40,34 @@ RUN case "$TARGETPLATFORM" in \
|
||||
|
||||
RUN npm ci --only=production
|
||||
|
||||
RUN apk del make python3 g++
|
||||
### STAGE 2: Create minimal runtime image ###
|
||||
FROM node:20-alpine
|
||||
|
||||
ARG NUSQLITE3_DIR
|
||||
ARG NUSQLITE3_PATH
|
||||
|
||||
# Install only runtime dependencies
|
||||
RUN apk add --no-cache --update \
|
||||
tzdata \
|
||||
ffmpeg \
|
||||
tini
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy compiled frontend and server from build stages
|
||||
COPY --from=build-client /client/dist /app/client/dist
|
||||
COPY --from=build-server /server /app
|
||||
COPY --from=build-server /usr/local/lib/nusqlite3 /usr/local/lib/nusqlite3
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENV PORT=80
|
||||
ENV NODE_ENV=production
|
||||
ENV CONFIG_PATH="/config"
|
||||
ENV METADATA_PATH="/metadata"
|
||||
ENV SOURCE="docker"
|
||||
ENV NUSQLITE3_DIR=${NUSQLITE3_DIR}
|
||||
ENV NUSQLITE3_PATH=${NUSQLITE3_PATH}
|
||||
|
||||
ENTRYPOINT ["tini", "--"]
|
||||
CMD ["node", "index.js"]
|
||||
|
||||
@@ -217,6 +217,16 @@ export default {
|
||||
})
|
||||
}
|
||||
|
||||
if (this.results.episodes?.length) {
|
||||
shelves.push({
|
||||
id: 'episodes',
|
||||
label: 'Episodes',
|
||||
labelStringKey: 'LabelEpisodes',
|
||||
type: 'episode',
|
||||
entities: this.results.episodes.map((res) => res.libraryItem)
|
||||
})
|
||||
}
|
||||
|
||||
if (this.results.series?.length) {
|
||||
shelves.push({
|
||||
id: 'series',
|
||||
|
||||
@@ -274,15 +274,10 @@ export default {
|
||||
isAuthorsPage() {
|
||||
return this.page === 'authors'
|
||||
},
|
||||
isAlbumsPage() {
|
||||
return this.page === 'albums'
|
||||
},
|
||||
numShowing() {
|
||||
return this.totalEntities
|
||||
},
|
||||
entityName() {
|
||||
if (this.isAlbumsPage) return 'Albums'
|
||||
|
||||
if (this.isPodcastLibrary) return this.$strings.LabelPodcasts
|
||||
if (!this.page) return this.$strings.LabelBooks
|
||||
if (this.isSeriesPage) return this.$strings.LabelSeries
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="flex items-center h-full px-1 overflow-hidden">
|
||||
<covers-book-cover :library-item="libraryItem" :width="coverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||
<div class="grow px-2 episodeSearchCardContent">
|
||||
<p class="truncate text-sm">{{ episodeTitle }}</p>
|
||||
<p class="text-xs text-gray-200 truncate">{{ podcastTitle }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
libraryItem: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
episode: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
bookCoverAspectRatio() {
|
||||
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
||||
},
|
||||
coverWidth() {
|
||||
if (this.bookCoverAspectRatio === 1) return 50 * 1.2
|
||||
return 50
|
||||
},
|
||||
media() {
|
||||
return this.libraryItem?.media || {}
|
||||
},
|
||||
mediaMetadata() {
|
||||
return this.media.metadata || {}
|
||||
},
|
||||
episodeTitle() {
|
||||
return this.episode.title || 'No Title'
|
||||
},
|
||||
podcastTitle() {
|
||||
return this.mediaMetadata.title || 'No Title'
|
||||
}
|
||||
},
|
||||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.episodeSearchCardContent {
|
||||
width: calc(100% - 80px);
|
||||
height: 75px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
<template>
|
||||
<div ref="card" :id="`album-card-${index}`" :style="{ width: cardWidth + 'px' }" class="absolute top-0 left-0 rounded-xs z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard">
|
||||
<div class="relative" :style="{ height: coverHeight + 'px' }">
|
||||
<div class="absolute top-0 left-0 w-full box-shadow-book shadow-height" />
|
||||
<div class="w-full h-full bg-primary relative rounded-sm overflow-hidden">
|
||||
<covers-preview-cover ref="cover" :src="coverSrc" :width="cardWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative w-full">
|
||||
<div v-if="!isAlternativeBookshelfView" class="categoryPlacard absolute z-30 left-0 right-0 mx-auto -bottom-6e h-6e rounded-md text-center" :style="{ width: Math.min(200, cardWidth) + 'px' }">
|
||||
<div class="w-full h-full shinyBlack flex items-center justify-center rounded-xs border" :style="{ padding: `0em ${0.5}em` }">
|
||||
<p class="truncate" :style="{ fontSize: labelFontSize + 'em' }">{{ title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="absolute z-30 left-0 right-0 mx-auto -bottom-8e h-8e py-1e rounded-md text-center">
|
||||
<p class="truncate" :style="{ fontSize: labelFontSize + 'em' }">{{ title }}</p>
|
||||
<p class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ artist || ' ' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
index: Number,
|
||||
width: Number,
|
||||
height: {
|
||||
type: Number,
|
||||
default: 192
|
||||
},
|
||||
bookshelfView: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
albumMount: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
album: null,
|
||||
isSelectionMode: false,
|
||||
selected: false,
|
||||
isHovering: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bookCoverAspectRatio() {
|
||||
return this.store.getters['libraries/getBookCoverAspectRatio']
|
||||
},
|
||||
cardWidth() {
|
||||
return this.width || this.coverHeight
|
||||
},
|
||||
coverHeight() {
|
||||
return this.height * this.sizeMultiplier
|
||||
},
|
||||
/*
|
||||
cardHeight() {
|
||||
return this.coverHeight + this.bottomTextHeight
|
||||
},
|
||||
bottomTextHeight() {
|
||||
if (!this.isAlternativeBookshelfView) return 0
|
||||
const lineHeight = 1.5
|
||||
const remSize = 16
|
||||
const baseHeight = this.sizeMultiplier * lineHeight * remSize
|
||||
const titleHeight = this.labelFontSize * baseHeight
|
||||
const paddingHeight = 4 * 2 * this.sizeMultiplier // py-1
|
||||
return titleHeight + paddingHeight
|
||||
},
|
||||
*/
|
||||
coverSrc() {
|
||||
const config = this.$config || this.$nuxt.$config
|
||||
if (!this.album || !this.album.libraryItemId) return `${config.routerBasePath}/book_placeholder.jpg`
|
||||
return this.store.getters['globals/getLibraryItemCoverSrcById'](this.album.libraryItemId)
|
||||
},
|
||||
labelFontSize() {
|
||||
if (this.width < 160) return 0.75
|
||||
return 0.9
|
||||
},
|
||||
sizeMultiplier() {
|
||||
return this.store.getters['user/getSizeMultiplier']
|
||||
},
|
||||
title() {
|
||||
return this.album ? this.album.title : ''
|
||||
},
|
||||
artist() {
|
||||
return this.album ? this.album.artist : ''
|
||||
},
|
||||
store() {
|
||||
return this.$store || this.$nuxt.$store
|
||||
},
|
||||
currentLibraryId() {
|
||||
return this.store.state.libraries.currentLibraryId
|
||||
},
|
||||
isAlternativeBookshelfView() {
|
||||
const constants = this.$constants || this.$nuxt.$constants
|
||||
return this.bookshelfView == constants.BookshelfView.DETAIL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setEntity(album) {
|
||||
this.album = album
|
||||
},
|
||||
setSelectionMode(val) {
|
||||
this.isSelectionMode = val
|
||||
},
|
||||
mouseover() {
|
||||
this.isHovering = true
|
||||
},
|
||||
mouseleave() {
|
||||
this.isHovering = false
|
||||
},
|
||||
clickCard() {
|
||||
if (!this.album) return
|
||||
// const router = this.$router || this.$nuxt.$router
|
||||
// router.push(`/album/${this.$encode(this.title)}`)
|
||||
},
|
||||
clickEdit() {
|
||||
this.$emit('edit', this.album)
|
||||
},
|
||||
destroy() {
|
||||
// destroy the vue listeners, etc
|
||||
this.$destroy()
|
||||
|
||||
// remove the element from the DOM
|
||||
if (this.$el && this.$el.parentNode) {
|
||||
this.$el.parentNode.removeChild(this.$el)
|
||||
} else if (this.$el && this.$el.remove) {
|
||||
this.$el.remove()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.albumMount) {
|
||||
this.setEntity(this.albumMount)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -39,6 +39,15 @@
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<p v-if="episodeResults.length" class="uppercase text-xs text-gray-400 my-1 px-1 font-semibold">{{ $strings.LabelEpisodes }}</p>
|
||||
<template v-for="item in episodeResults">
|
||||
<li :key="item.libraryItem.recentEpisode.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||
<nuxt-link :to="`/item/${item.libraryItem.id}`">
|
||||
<cards-episode-search-card :episode="item.libraryItem.recentEpisode" :library-item="item.libraryItem" />
|
||||
</nuxt-link>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<p v-if="authorResults.length" class="uppercase text-xs text-gray-400 mb-1 mt-3 px-1 font-semibold">{{ $strings.LabelAuthors }}</p>
|
||||
<template v-for="item in authorResults">
|
||||
<li :key="item.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||
@@ -100,6 +109,7 @@ export default {
|
||||
isFetching: false,
|
||||
search: null,
|
||||
podcastResults: [],
|
||||
episodeResults: [],
|
||||
bookResults: [],
|
||||
authorResults: [],
|
||||
seriesResults: [],
|
||||
@@ -115,7 +125,7 @@ export default {
|
||||
return this.$store.state.libraries.currentLibraryId
|
||||
},
|
||||
totalResults() {
|
||||
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length
|
||||
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length + this.episodeResults.length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -132,6 +142,7 @@ export default {
|
||||
this.search = null
|
||||
this.lastSearch = null
|
||||
this.podcastResults = []
|
||||
this.episodeResults = []
|
||||
this.bookResults = []
|
||||
this.authorResults = []
|
||||
this.seriesResults = []
|
||||
@@ -175,6 +186,7 @@ export default {
|
||||
if (!this.isFetching) return
|
||||
|
||||
this.podcastResults = searchResults.podcast || []
|
||||
this.episodeResults = searchResults.episodes || []
|
||||
this.bookResults = searchResults.book || []
|
||||
this.authorResults = searchResults.authors || []
|
||||
this.seriesResults = searchResults.series || []
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<ui-text-input-with-label ref="sequenceInput" v-model="selectedSeries.sequence" :label="$strings.LabelSequence" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="error" class="text-error text-sm mt-2 p-1">{{ error }}</div>
|
||||
<div class="flex justify-end mt-2 p-1">
|
||||
<ui-btn type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
|
||||
</div>
|
||||
@@ -34,12 +35,17 @@ export default {
|
||||
existingSeriesNames: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
originalSeriesSequence: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
el: null,
|
||||
content: null
|
||||
content: null,
|
||||
error: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -85,10 +91,17 @@ export default {
|
||||
}
|
||||
},
|
||||
submitSeriesForm() {
|
||||
this.error = null
|
||||
|
||||
if (this.$refs.newSeriesSelect) {
|
||||
this.$refs.newSeriesSelect.blur()
|
||||
}
|
||||
|
||||
if (this.selectedSeries.sequence !== this.originalSeriesSequence && this.selectedSeries.sequence.includes(' ')) {
|
||||
this.error = this.$strings.MessageSeriesSequenceCannotContainSpaces
|
||||
return
|
||||
}
|
||||
|
||||
this.$emit('submit')
|
||||
},
|
||||
clickClose() {
|
||||
@@ -100,6 +113,7 @@ export default {
|
||||
}
|
||||
},
|
||||
setShow() {
|
||||
this.error = null
|
||||
if (!this.el || !this.content) {
|
||||
this.init()
|
||||
}
|
||||
|
||||
@@ -74,19 +74,12 @@ export default {
|
||||
mediaTracks() {
|
||||
return this.media.tracks || []
|
||||
},
|
||||
isSingleM4b() {
|
||||
return this.mediaTracks.length === 1 && this.mediaTracks[0].metadata.ext.toLowerCase() === '.m4b'
|
||||
},
|
||||
chapters() {
|
||||
return this.media.chapters || []
|
||||
},
|
||||
showM4bDownload() {
|
||||
if (!this.mediaTracks.length) return false
|
||||
return !this.isSingleM4b
|
||||
},
|
||||
showMp3Split() {
|
||||
if (!this.mediaTracks.length) return false
|
||||
return this.isSingleM4b && this.chapters.length
|
||||
return true
|
||||
},
|
||||
queuedEmbedLIds() {
|
||||
return this.$store.state.tasks.queuedEmbedLIds || []
|
||||
|
||||
@@ -244,8 +244,8 @@ export default {
|
||||
const sizeInMb = payloadSize / 1024 / 1024
|
||||
const sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
|
||||
console.log('Request size', sizeInMb)
|
||||
if (sizeInMb > 4.99) {
|
||||
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 5Mb`)
|
||||
if (sizeInMb > 9.99) {
|
||||
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 10Mb`)
|
||||
}
|
||||
|
||||
this.processing = true
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<template>
|
||||
<div id="lazy-episodes-table" class="w-full py-6">
|
||||
<div class="flex flex-wrap flex-col md:flex-row md:items-center mb-4">
|
||||
@@ -176,6 +175,13 @@ export default {
|
||||
return episodeProgress && !episodeProgress.isFinished
|
||||
})
|
||||
.sort((a, b) => {
|
||||
// Swap values if sort descending
|
||||
if (this.sortDesc) {
|
||||
const temp = a
|
||||
a = b
|
||||
b = temp
|
||||
}
|
||||
|
||||
let aValue
|
||||
let bValue
|
||||
|
||||
@@ -194,10 +200,23 @@ export default {
|
||||
if (!bValue) bValue = Number.MAX_VALUE
|
||||
}
|
||||
|
||||
if (this.sortDesc) {
|
||||
return String(bValue).localeCompare(String(aValue), undefined, { numeric: true, sensitivity: 'base' })
|
||||
const primaryCompare = String(aValue).localeCompare(String(bValue), undefined, { numeric: true, sensitivity: 'base' })
|
||||
if (primaryCompare !== 0 || this.sortKey === 'publishedAt') return primaryCompare
|
||||
|
||||
// When sorting by season, secondary sort is by episode number
|
||||
if (this.sortKey === 'season') {
|
||||
const aEpisode = a.episode || ''
|
||||
const bEpisode = b.episode || ''
|
||||
|
||||
const secondaryCompare = String(aEpisode).localeCompare(String(bEpisode), undefined, { numeric: true, sensitivity: 'base' })
|
||||
if (secondaryCompare !== 0) return secondaryCompare
|
||||
}
|
||||
return String(aValue).localeCompare(String(bValue), undefined, { numeric: true, sensitivity: 'base' })
|
||||
|
||||
// Final sort by publishedAt
|
||||
let aPubDate = a.publishedAt || Number.MAX_VALUE
|
||||
let bPubDate = b.publishedAt || Number.MAX_VALUE
|
||||
|
||||
return String(aPubDate).localeCompare(String(bPubDate), undefined, { numeric: true, sensitivity: 'base' })
|
||||
})
|
||||
},
|
||||
episodesList() {
|
||||
|
||||
@@ -162,7 +162,7 @@ export default {
|
||||
} else {
|
||||
// Find closest bitrate rounding up
|
||||
const bitratesToMatch = [32, 64, 128, 192]
|
||||
const closestBitrate = bitratesToMatch.find((bitrate) => bitrate >= this.currentBitrate)
|
||||
const closestBitrate = bitratesToMatch.find((bitrate) => bitrate >= this.currentBitrate) || 192
|
||||
this.selectedBitrate = closestBitrate + 'k'
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<ui-multi-select-query-input v-model="seriesItems" text-key="displayName" :label="$strings.LabelSeries" :disabled="disabled" readonly show-edit @edit="editSeriesItem" @add="addNewSeries" />
|
||||
|
||||
<modals-edit-series-input-inner-modal v-model="showSeriesForm" :selected-series="selectedSeries" :existing-series-names="existingSeriesNames" @submit="submitSeriesForm" />
|
||||
<modals-edit-series-input-inner-modal v-model="showSeriesForm" :selected-series="selectedSeries" :existing-series-names="existingSeriesNames" :original-series-sequence="originalSeriesSequence" @submit="submitSeriesForm" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -18,6 +18,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
selectedSeries: null,
|
||||
originalSeriesSequence: null,
|
||||
showSeriesForm: false
|
||||
}
|
||||
},
|
||||
@@ -59,6 +60,7 @@ export default {
|
||||
..._series
|
||||
}
|
||||
|
||||
this.originalSeriesSequence = _series.sequence
|
||||
this.showSeriesForm = true
|
||||
},
|
||||
addNewSeries() {
|
||||
@@ -68,6 +70,7 @@ export default {
|
||||
sequence: ''
|
||||
}
|
||||
|
||||
this.originalSeriesSequence = null
|
||||
this.showSeriesForm = true
|
||||
},
|
||||
submitSeriesForm() {
|
||||
|
||||
@@ -3,7 +3,6 @@ import LazyBookCard from '@/components/cards/LazyBookCard'
|
||||
import LazySeriesCard from '@/components/cards/LazySeriesCard'
|
||||
import LazyCollectionCard from '@/components/cards/LazyCollectionCard'
|
||||
import LazyPlaylistCard from '@/components/cards/LazyPlaylistCard'
|
||||
import LazyAlbumCard from '@/components/cards/LazyAlbumCard'
|
||||
import AuthorCard from '@/components/cards/AuthorCard'
|
||||
|
||||
export default {
|
||||
@@ -20,7 +19,6 @@ export default {
|
||||
if (this.entityName === 'series') return Vue.extend(LazySeriesCard)
|
||||
if (this.entityName === 'collections') return Vue.extend(LazyCollectionCard)
|
||||
if (this.entityName === 'playlists') return Vue.extend(LazyPlaylistCard)
|
||||
if (this.entityName === 'albums') return Vue.extend(LazyAlbumCard)
|
||||
if (this.entityName === 'authors') return Vue.extend(AuthorCard)
|
||||
return Vue.extend(LazyBookCard)
|
||||
},
|
||||
@@ -28,7 +26,6 @@ export default {
|
||||
if (this.entityName === 'series') return 'cards-lazy-series-card'
|
||||
if (this.entityName === 'collections') return 'cards-lazy-collection-card'
|
||||
if (this.entityName === 'playlists') return 'cards-lazy-playlist-card'
|
||||
if (this.entityName === 'albums') return 'cards-lazy-album-card'
|
||||
if (this.entityName === 'authors') return 'cards-author-card'
|
||||
return 'cards-lazy-book-card'
|
||||
},
|
||||
|
||||
4
client/package-lock.json
generated
4
client/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.21.0",
|
||||
"version": "2.23.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.21.0",
|
||||
"version": "2.23.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nuxtjs/axios": "^5.13.6",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.21.0",
|
||||
"version": "2.23.0",
|
||||
"buildNumber": 1,
|
||||
"description": "Self-hosted audiobook and podcast client",
|
||||
"main": "index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="page-wrapper" class="bg-bg page overflow-y-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
||||
<div class="flex items-center py-4 px-2 md:px-0 max-w-7xl mx-auto">
|
||||
<div class="flex items-center py-4 px-4 max-w-7xl mx-auto">
|
||||
<nuxt-link :to="`/item/${libraryItem.id}`" class="hover:underline">
|
||||
<h1 class="text-lg lg:text-xl">{{ title }}</h1>
|
||||
</nuxt-link>
|
||||
@@ -12,7 +12,7 @@
|
||||
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap-reverse justify-center py-4 px-2">
|
||||
<div class="flex flex-wrap-reverse lg: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" />
|
||||
@@ -23,8 +23,8 @@
|
||||
</div>
|
||||
<div class="flex items-center mb-3 py-1 -mx-1">
|
||||
<div class="w-12 hidden lg:block" />
|
||||
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
||||
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg' : 'primary'" class="mx-1" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
||||
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1 whitespace-nowrap" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
||||
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg-bg' : 'bg-primary'" class="mx-1 whitespace-nowrap" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
||||
<ui-btn 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>
|
||||
@@ -65,7 +65,7 @@
|
||||
<ui-time-picker v-else class="text-xs" v-model="chapter.start" :show-three-digit-hour="mediaDuration >= 360000" @change="checkChapters" />
|
||||
</div>
|
||||
<div class="grow px-1">
|
||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs" />
|
||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs min-w-52" />
|
||||
</div>
|
||||
<div class="w-32 min-w-32 px-2 py-1">
|
||||
<div class="flex items-center">
|
||||
@@ -144,17 +144,18 @@
|
||||
<div v-if="!chapterData" class="flex flex-col items-center justify-center p-20">
|
||||
<div class="relative">
|
||||
<div class="flex items-end space-x-2">
|
||||
<ui-text-input-with-label v-model.trim="asinInput" label="ASIN" />
|
||||
<ui-dropdown v-model="regionInput" :label="$strings.LabelRegion" small :items="audibleRegions" class="w-32" />
|
||||
<ui-btn small color="bg-primary" @click="findChapters">{{ $strings.ButtonSearch }}</ui-btn>
|
||||
<ui-text-input-with-label v-model.trim="asinInput" label="ASIN" class="flex-grow" />
|
||||
<ui-dropdown v-model="regionInput" :label="$strings.LabelRegion" small :items="audibleRegions" class="w-20 max-w-20" />
|
||||
<ui-btn color="bg-primary" @click="findChapters">{{ $strings.ButtonSearch }}</ui-btn>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<ui-checkbox v-model="removeBranding" :label="$strings.LabelRemoveAudibleBranding" small checkbox-bg="bg" label-class="pl-2 text-base text-sm" @click="toggleRemoveBranding" />
|
||||
</div>
|
||||
|
||||
<div class="absolute left-0 mt-1.5 text-error text-s h-5">
|
||||
<p v-if="asinError">{{ asinError }}</p>
|
||||
<p v-if="asinError">{{ $strings.MessageAsinCheck }}</p>
|
||||
</div>
|
||||
|
||||
<div class="invisible h-5 mt-1 text-xs"></div>
|
||||
<div class="invisible mt-1 text-xs"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="w-full p-4">
|
||||
@@ -261,6 +262,7 @@ export default {
|
||||
showFindChaptersModal: false,
|
||||
chapterData: null,
|
||||
asinError: null,
|
||||
removeBranding: false,
|
||||
showSecondInputs: false,
|
||||
audibleRegions: ['US', 'CA', 'UK', 'AU', 'FR', 'DE', 'JP', 'IT', 'IN', 'ES'],
|
||||
hasChanges: false
|
||||
@@ -322,6 +324,9 @@ export default {
|
||||
|
||||
this.checkChapters()
|
||||
},
|
||||
toggleRemoveBranding() {
|
||||
this.removeBranding = !this.removeBranding
|
||||
},
|
||||
shiftChapterTimes() {
|
||||
if (!this.shiftAmount || isNaN(this.shiftAmount) || this.newChapters.length <= 1) {
|
||||
return
|
||||
@@ -331,12 +336,12 @@ export default {
|
||||
|
||||
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
||||
if (lastChapter.start + amount > this.mediaDurationRounded) {
|
||||
this.$toast.error('Invalid shift amount. Last chapter start time would extend beyond the duration of this audiobook.')
|
||||
this.$toast.error(this.$strings.ToastChaptersInvalidShiftAmountLast)
|
||||
return
|
||||
}
|
||||
|
||||
if (this.newChapters[0].end + amount <= 0) {
|
||||
this.$toast.error('Invalid shift amount. First chapter would have zero or negative length.')
|
||||
if (this.newChapters[1].start + amount <= 0) {
|
||||
this.$toast.error(this.$strings.ToastChaptersInvalidShiftAmountStart)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -568,7 +573,7 @@ export default {
|
||||
this.asinError = this.$getString(data.stringKey)
|
||||
} else {
|
||||
console.log('Chapter data', data)
|
||||
this.chapterData = data
|
||||
this.chapterData = this.removeBranding ? this.removeBrandingFromData(data) : data
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -578,6 +583,37 @@ export default {
|
||||
this.showFindChaptersModal = false
|
||||
})
|
||||
},
|
||||
removeBrandingFromData(data) {
|
||||
if (!data) return data
|
||||
try {
|
||||
const introDuration = data.brandIntroDurationMs
|
||||
const outroDuration = data.brandOutroDurationMs
|
||||
|
||||
for (let i = 0; i < data.chapters.length; i++) {
|
||||
const chapter = data.chapters[i]
|
||||
if (chapter.startOffsetMs < introDuration) {
|
||||
// This should never happen, as the intro is not longer than the first chapter
|
||||
// If this happens set to the next second
|
||||
// Will be 0 for the first chapter anayways
|
||||
chapter.startOffsetMs = i * 1000
|
||||
chapter.startOffsetSec = i
|
||||
} else {
|
||||
chapter.startOffsetMs -= introDuration
|
||||
chapter.startOffsetSec = Math.floor(chapter.startOffsetMs / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
const lastChapter = data.chapters[data.chapters.length - 1]
|
||||
// If there is an outro that's in the outro duration, remove it
|
||||
if (lastChapter && lastChapter.lengthMs <= outroDuration) {
|
||||
data.chapters.pop()
|
||||
}
|
||||
|
||||
return data
|
||||
} catch {
|
||||
return data
|
||||
}
|
||||
},
|
||||
resetChapters() {
|
||||
const payload = {
|
||||
message: this.$strings.MessageResetChaptersConfirm,
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
<div id="page-wrapper" class="bg-bg page p-8 overflow-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
||||
<div class="flex items-center justify-center mb-6">
|
||||
<div class="w-full max-w-2xl">
|
||||
<p class="text-2xl mb-2">{{ $strings.HeaderAudiobookTools }}</p>
|
||||
<div class="flex items-center mb-4">
|
||||
<nuxt-link :to="`/item/${libraryItem.id}`" class="hover:underline">
|
||||
<h1 class="text-lg lg:text-xl">{{ mediaMetadata.title }}</h1>
|
||||
</nuxt-link>
|
||||
<button class="w-7 h-7 flex items-center justify-center mx-4 hover:scale-110 duration-100 transform text-gray-200 hover:text-white" @click="editItem">
|
||||
<span class="material-symbols text-base">edit</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full max-w-2xl">
|
||||
<div class="flex justify-end">
|
||||
@@ -13,7 +20,7 @@
|
||||
|
||||
<div class="flex justify-center mb-2">
|
||||
<div class="w-full max-w-2xl">
|
||||
<p class="text-xl">{{ $strings.HeaderMetadataToEmbed }}</p>
|
||||
<p class="text-lg">{{ $strings.HeaderMetadataToEmbed }}</p>
|
||||
</div>
|
||||
<div class="w-full max-w-2xl"></div>
|
||||
</div>
|
||||
@@ -266,9 +273,6 @@ export default {
|
||||
audioFiles() {
|
||||
return (this.media.audioFiles || []).filter((af) => !af.exclude)
|
||||
},
|
||||
isSingleM4b() {
|
||||
return this.audioFiles.length === 1 && this.audioFiles[0].metadata.ext.toLowerCase() === '.m4b'
|
||||
},
|
||||
streamLibraryItem() {
|
||||
return this.$store.state.streamLibraryItem
|
||||
},
|
||||
@@ -276,14 +280,10 @@ export default {
|
||||
return this.media.chapters || []
|
||||
},
|
||||
availableTools() {
|
||||
if (this.isSingleM4b) {
|
||||
return [{ value: 'embed', text: this.$strings.LabelToolsEmbedMetadata }]
|
||||
} else {
|
||||
return [
|
||||
{ value: 'embed', text: this.$strings.LabelToolsEmbedMetadata },
|
||||
{ value: 'm4b', text: this.$strings.LabelToolsM4bEncoder }
|
||||
]
|
||||
}
|
||||
return [
|
||||
{ value: 'embed', text: this.$strings.LabelToolsEmbedMetadata },
|
||||
{ value: 'm4b', text: this.$strings.LabelToolsM4bEncoder }
|
||||
]
|
||||
},
|
||||
taskFailed() {
|
||||
return this.isTaskFinished && this.task.isFailed
|
||||
@@ -431,10 +431,24 @@ export default {
|
||||
},
|
||||
taskUpdated(task) {
|
||||
this.processing = !task.isFinished
|
||||
},
|
||||
editItem() {
|
||||
this.$store.commit('showEditModal', this.libraryItem)
|
||||
},
|
||||
libraryItemUpdated(libraryItem) {
|
||||
if (libraryItem.id === this.libraryItem.id) {
|
||||
this.libraryItem = libraryItem
|
||||
this.fetchMetadataEmbedObject()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
|
||||
this.$eventBus.$on(`${this.libraryItem.id}_updated`, this.libraryItemUpdated)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$eventBus.$off(`${this.libraryItem.id}_updated`, this.libraryItemUpdated)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -122,7 +122,8 @@
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="w-full flex items-center justify-end p-4">
|
||||
<div class="w-full flex items-center justify-between p-4">
|
||||
<p v-if="enableOpenIDAuth" class="text-sm text-warning">{{ $strings.MessageAuthenticationOIDCChangesRestart }}</p>
|
||||
<ui-btn color="bg-success" :padding-x="8" small class="text-base" :loading="savingSettings" @click="saveSettings">{{ $strings.ButtonSave }}</ui-btn>
|
||||
</div>
|
||||
</app-settings-content>
|
||||
|
||||
@@ -22,6 +22,7 @@ export default {
|
||||
})
|
||||
results = {
|
||||
podcasts: results?.podcast || [],
|
||||
episodes: results?.episodes || [],
|
||||
books: results?.book || [],
|
||||
authors: results?.authors || [],
|
||||
series: results?.series || [],
|
||||
@@ -61,6 +62,7 @@ export default {
|
||||
})
|
||||
this.results = {
|
||||
podcasts: results?.podcast || [],
|
||||
episodes: results?.episodes || [],
|
||||
books: results?.book || [],
|
||||
authors: results?.authors || [],
|
||||
series: results?.series || [],
|
||||
|
||||
@@ -359,15 +359,14 @@ export default {
|
||||
// Check if path already exists before starting upload
|
||||
// uploading fails if path already exists
|
||||
for (const item of items) {
|
||||
const filepath = Path.join(this.selectedFolder.fullPath, item.directory)
|
||||
const exists = await this.$axios
|
||||
.$post(`/api/filesystem/pathexists`, { filepath, directory: item.directory, folderPath: this.selectedFolder.fullPath })
|
||||
.$post(`/api/filesystem/pathexists`, { directory: item.directory, folderPath: this.selectedFolder.fullPath })
|
||||
.then((data) => {
|
||||
if (data.exists) {
|
||||
if (data.libraryItemTitle) {
|
||||
this.$toast.error(this.$getString('ToastUploaderItemExistsInSubdirectoryError', [data.libraryItemTitle]))
|
||||
} else {
|
||||
this.$toast.error(this.$getString('ToastUploaderFilepathExistsError', [filepath]))
|
||||
this.$toast.error(this.$getString('ToastUploaderFilepathExistsError', [Path.join(this.selectedFolder.fullPath, item.directory)]))
|
||||
}
|
||||
}
|
||||
return data.exists
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export default class AudioTrack {
|
||||
constructor(track, userToken, routerBasePath) {
|
||||
constructor(track, sessionId, routerBasePath) {
|
||||
this.index = track.index || 0
|
||||
this.startOffset = track.startOffset || 0 // Total time of all previous tracks
|
||||
this.duration = track.duration || 0
|
||||
@@ -8,28 +8,29 @@ export default class AudioTrack {
|
||||
this.mimeType = track.mimeType
|
||||
this.metadata = track.metadata || {}
|
||||
|
||||
this.userToken = userToken
|
||||
this.sessionId = sessionId
|
||||
this.routerBasePath = routerBasePath || ''
|
||||
if (this.contentUrl?.startsWith('/hls')) {
|
||||
this.sessionTrackUrl = this.contentUrl
|
||||
} else {
|
||||
this.sessionTrackUrl = `/public/session/${sessionId}/track/${this.index}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for CastPlayer
|
||||
*/
|
||||
get fullContentUrl() {
|
||||
if (!this.contentUrl || this.contentUrl.startsWith('http')) return this.contentUrl
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return `${process.env.serverUrl}${this.contentUrl}?token=${this.userToken}`
|
||||
return `${process.env.serverUrl}${this.sessionTrackUrl}`
|
||||
}
|
||||
return `${window.location.origin}${this.routerBasePath}${this.contentUrl}?token=${this.userToken}`
|
||||
return `${window.location.origin}${this.routerBasePath}${this.sessionTrackUrl}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for LocalPlayer
|
||||
*/
|
||||
get relativeContentUrl() {
|
||||
if (!this.contentUrl || this.contentUrl.startsWith('http')) return this.contentUrl
|
||||
|
||||
return `${this.routerBasePath}${this.contentUrl}?token=${this.userToken}`
|
||||
return `${this.routerBasePath}${this.sessionTrackUrl}`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,6 @@ export default class PlayerHandler {
|
||||
get isPlayingLocalItem() {
|
||||
return this.libraryItem && this.player instanceof LocalAudioPlayer
|
||||
}
|
||||
get userToken() {
|
||||
return this.ctx.$store.getters['user/getToken']
|
||||
}
|
||||
get playerPlaying() {
|
||||
return this.playerState === 'PLAYING'
|
||||
}
|
||||
@@ -226,7 +223,7 @@ export default class PlayerHandler {
|
||||
|
||||
console.log('[PlayerHandler] Preparing Session', session)
|
||||
|
||||
var audioTracks = session.audioTracks.map((at) => new AudioTrack(at, this.userToken, this.ctx.$config.routerBasePath))
|
||||
var audioTracks = session.audioTracks.map((at) => new AudioTrack(at, session.id, this.ctx.$config.routerBasePath))
|
||||
|
||||
this.ctx.playerLoading = true
|
||||
this.isHlsTranscode = true
|
||||
|
||||
@@ -212,5 +212,60 @@
|
||||
"LabelLayoutSinglePage": "صفحة واحدة",
|
||||
"LabelLineSpacing": "تباعد الأسطر",
|
||||
"LabelListenAgain": "الاستماع مجدداً",
|
||||
"LabelMediaType": "نوع الوسائط"
|
||||
"LabelMediaType": "نوع الوسائط",
|
||||
"LabelMissing": "مفقود",
|
||||
"LabelMore": "أكثر",
|
||||
"LabelMoreInfo": "معلومات أكثر",
|
||||
"LabelName": "الاسم",
|
||||
"LabelNarrator": "الراوي",
|
||||
"LabelNarrators": "الرواة",
|
||||
"LabelNewestAuthors": "أجدد المؤلفين",
|
||||
"LabelNewestEpisodes": "أجدد الحلقات",
|
||||
"LabelNotFinished": "لم يتم الانتهاء",
|
||||
"LabelNotStarted": "لم يتم البدء",
|
||||
"LabelNumberOfEpisodes": "# من الحلقات",
|
||||
"LabelPassword": "كلمة المرور",
|
||||
"LabelPath": "مسار",
|
||||
"LabelPodcast": "مدونة صوتية",
|
||||
"LabelPodcasts": "مدونات صوتية",
|
||||
"LabelPreventIndexing": "منع فهرسة تغذيتك بواسطة دليل آيتونز وقوقل بودكاست",
|
||||
"LabelProgress": "تقدم",
|
||||
"LabelPubDate": "تاريخ النشر",
|
||||
"LabelPublishYear": "سنة النشر",
|
||||
"LabelPublishedDate": "منشور {0}",
|
||||
"LabelRSSFeedCustomOwnerEmail": "البريد الالكتروني المخصص للمالك",
|
||||
"LabelRSSFeedCustomOwnerName": "الاسم المخصص للمالك",
|
||||
"LabelRSSFeedPreventIndexing": "منع الفهرسة",
|
||||
"LabelRSSFeedSlug": "رابط تغذية RSS",
|
||||
"LabelRandomly": "عشوائياً",
|
||||
"LabelRead": "اقرأ",
|
||||
"LabelReadAgain": "اقرأ مرة أخرى",
|
||||
"LabelRecentSeries": "المسلسلات الحديثة",
|
||||
"LabelRecentlyAdded": "المضافة حديثاً",
|
||||
"LabelSeason": "الموسم",
|
||||
"LabelSeries": "المسلسلات",
|
||||
"LabelSetEbookAsPrimary": "تعيين كرئيسي",
|
||||
"LabelSetEbookAsSupplementary": "تعيين كتكميلي",
|
||||
"LabelShowAll": "اظهار الكل",
|
||||
"LabelSize": "الحجم",
|
||||
"LabelSleepTimer": "مؤقت النوم",
|
||||
"LabelStart": "ابدأ",
|
||||
"LabelStatsBestDay": "أفضل يوم",
|
||||
"LabelStatsDailyAverage": "المتوسط اليومي",
|
||||
"LabelStatsDays": "أيام",
|
||||
"LabelStatsDaysListened": "أيام الاستماع",
|
||||
"LabelStatsInARow": "على التوالي",
|
||||
"LabelStatsItemsFinished": "العناصر المنتهية",
|
||||
"LabelStatsMinutes": "دقائق",
|
||||
"LabelStatsMinutesListening": "دقائق الاستماع",
|
||||
"NoteRSSFeedPodcastAppsHttps": "تحذير: تتطلب معظم تطبيقات البث الصوتي أن يكون عنوان URL لخلاصة RSS يستخدم HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "تحذير: حلقة واحدة أو أكثر من حلقاتك ليس لها تاريخ نشر. بعض تطبيقات البودكاست تتطلب هذا.",
|
||||
"ToastBookmarkCreateFailed": "فشل في إنشاء الإشارة المرجعية",
|
||||
"ToastItemMarkedAsFinishedFailed": "فشل في وضع علامة على الانتهاء",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "فشل في وضع علامة \"غير مكتمل\"",
|
||||
"ToastPlaylistCreateFailed": "فشل إنشاء قائمة التشغيل",
|
||||
"ToastPodcastCreateFailed": "فشل في إنشاء البودكاست",
|
||||
"ToastPodcastCreateSuccess": "تم إنشاء البودكاست بنجاح",
|
||||
"ToastRSSFeedCloseFailed": "فشل في إغلاق موجز RSS",
|
||||
"ToastRSSFeedCloseSuccess": "تم إغلاق موجز RSS"
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
{
|
||||
"ButtonAdd": "Afegeix",
|
||||
"ButtonAddChapters": "Afegeix",
|
||||
"ButtonAddDevice": "Afegeix Dispositiu",
|
||||
"ButtonAddLibrary": "Crea Biblioteca",
|
||||
"ButtonAddChapters": "Afegeix capítols",
|
||||
"ButtonAddDevice": "Afegeix un aparell",
|
||||
"ButtonAddLibrary": "Afegeix una biblioteca",
|
||||
"ButtonAddPodcasts": "Afegeix pòdcasts",
|
||||
"ButtonAddUser": "Crea Usuari",
|
||||
"ButtonAddYourFirstLibrary": "Crea la teva Primera Biblioteca",
|
||||
"ButtonAddUser": "Afegeix un usuari",
|
||||
"ButtonAddYourFirstLibrary": "Afegiu la vostra primera biblioteca",
|
||||
"ButtonApply": "Aplica",
|
||||
"ButtonApplyChapters": "Aplica Capítols",
|
||||
"ButtonApplyChapters": "Aplica capítols",
|
||||
"ButtonAuthors": "Autors",
|
||||
"ButtonBack": "Enrere",
|
||||
"ButtonBatchEditPopulateFromExisting": "Omplir des d'existent",
|
||||
"ButtonBatchEditPopulateMapDetails": "Omplir detalls del mapa",
|
||||
"ButtonBrowseForFolder": "Cerca Carpeta",
|
||||
"ButtonBatchEditPopulateMapDetails": "Omple els detalls del mapa",
|
||||
"ButtonBrowseForFolder": "Cerca una carpeta",
|
||||
"ButtonCancel": "Cancel·la",
|
||||
"ButtonCancelEncode": "Cancel·la Codificador",
|
||||
"ButtonCancelEncode": "Cancel·la la codificació",
|
||||
"ButtonChangeRootPassword": "Canvia Contrasenya Root",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "Verifica i Descarrega Nous Episodis",
|
||||
"ButtonChooseAFolder": "Tria una Carpeta",
|
||||
"ButtonChooseFiles": "Tria un Fitxer",
|
||||
"ButtonClearFilter": "Elimina Filtres",
|
||||
"ButtonCloseFeed": "Tanca Font",
|
||||
"ButtonChooseAFolder": "Trieu una carpeta",
|
||||
"ButtonChooseFiles": "Trieu fitxers",
|
||||
"ButtonClearFilter": "Neteja el filtre",
|
||||
"ButtonCloseFeed": "Tanca el canal",
|
||||
"ButtonCloseSession": "Tanca la sessió oberta",
|
||||
"ButtonCollections": "Col·leccions",
|
||||
"ButtonConfigureScanner": "Configura Escàner",
|
||||
"ButtonCreate": "Crea",
|
||||
"ButtonCreateBackup": "Crea Còpia de Seguretat",
|
||||
"ButtonDelete": "Elimina",
|
||||
"ButtonDelete": "Suprimeix",
|
||||
"ButtonDownloadQueue": "Cua",
|
||||
"ButtonEdit": "Edita",
|
||||
"ButtonEditChapters": "Edita Capítol",
|
||||
"ButtonEditChapters": "Edita capítols",
|
||||
"ButtonEditPodcast": "Edita el pòdcast",
|
||||
"ButtonEnable": "Habilita",
|
||||
"ButtonFireAndFail": "Executat i fallat",
|
||||
@@ -192,7 +192,7 @@
|
||||
"HeaderSettings": "Paràmetres",
|
||||
"HeaderSettingsDisplay": "Interfície",
|
||||
"HeaderSettingsExperimental": "Funcionalitats experimentals",
|
||||
"HeaderSettingsGeneral": "General",
|
||||
"HeaderSettingsGeneral": "Generals",
|
||||
"HeaderSettingsScanner": "Escàner",
|
||||
"HeaderSettingsWebClient": "Client web",
|
||||
"HeaderSleepTimer": "Temporitzador de son",
|
||||
@@ -221,10 +221,10 @@
|
||||
"LabelAccountTypeUser": "Usuari",
|
||||
"LabelActivities": "Activitats",
|
||||
"LabelActivity": "Activitat",
|
||||
"LabelAddToCollection": "Afegit a la Col·lecció",
|
||||
"LabelAddToCollectionBatch": "S'han Afegit {0} Llibres a la Col·lecció",
|
||||
"LabelAddToPlaylist": "Afegit a la llista de reproducció",
|
||||
"LabelAddToPlaylistBatch": "S'han Afegit {0} Elements a la Llista de Reproducció",
|
||||
"LabelAddToCollection": "Afegeix a la col·lecció",
|
||||
"LabelAddToCollectionBatch": "Afegeix {0} llibres a la col·lecció",
|
||||
"LabelAddToPlaylist": "Afegeix a la llista de reproducció",
|
||||
"LabelAddToPlaylistBatch": "Afegeix {0} elements a la llista de reproducció",
|
||||
"LabelAddedAt": "Afegit",
|
||||
"LabelAddedDate": "{0} Afegit",
|
||||
"LabelAdminUsersOnly": "Només usuaris administradors",
|
||||
@@ -233,7 +233,7 @@
|
||||
"LabelAllUsers": "Tots els usuaris",
|
||||
"LabelAllUsersExcludingGuests": "Tots els usuaris excepte convidats",
|
||||
"LabelAllUsersIncludingGuests": "Tots els usuaris i convidats",
|
||||
"LabelAlreadyInYourLibrary": "Ja existeix a la Biblioteca",
|
||||
"LabelAlreadyInYourLibrary": "Ja existeix a la biblioteca",
|
||||
"LabelApiToken": "Testimoni de l'API",
|
||||
"LabelAppend": "Adjuntar",
|
||||
"LabelAudioBitrate": "Taxa de bits d'àudio (per exemple, 128k)",
|
||||
@@ -290,14 +290,14 @@
|
||||
"LabelCronExpression": "Expressió de Cron",
|
||||
"LabelCurrent": "Actual",
|
||||
"LabelCurrently": "En aquest moment:",
|
||||
"LabelCustomCronExpression": "Expressió de Cron Personalitzada:",
|
||||
"LabelDatetime": "Hora i Data",
|
||||
"LabelCustomCronExpression": "Expressió del Cron personalitzada:",
|
||||
"LabelDatetime": "Data i hora",
|
||||
"LabelDays": "Dies",
|
||||
"LabelDeleteFromFileSystemCheckbox": "Suprimeix del sistema de fitxers (desmarqueu per a eliminar de la base de dades només)",
|
||||
"LabelDescription": "Descripció",
|
||||
"LabelDeselectAll": "Desseleccionar Tots",
|
||||
"LabelDevice": "Dispositiu",
|
||||
"LabelDeviceInfo": "Informació del Dispositiu",
|
||||
"LabelDeviceInfo": "Informació de l'aparell",
|
||||
"LabelDeviceIsAvailableTo": "El dispositiu està disponible per a...",
|
||||
"LabelDirectory": "Directori",
|
||||
"LabelDiscFromFilename": "Disc a partir del nom de fitxer",
|
||||
@@ -335,11 +335,11 @@
|
||||
"LabelEnd": "Fi",
|
||||
"LabelEndOfChapter": "Fi del capítol",
|
||||
"LabelEpisode": "Episodi",
|
||||
"LabelEpisodeNotLinkedToRssFeed": "Episodi no enllaçat al feed RSS",
|
||||
"LabelEpisodeNotLinkedToRssFeed": "Episodi no enllaçat al canal RSS",
|
||||
"LabelEpisodeNumber": "Episodi #{0}",
|
||||
"LabelEpisodeTitle": "Títol de l'Episodi",
|
||||
"LabelEpisodeType": "Tipus d'Episodi",
|
||||
"LabelEpisodeUrlFromRssFeed": "URL de l'episodi del feed RSS",
|
||||
"LabelEpisodeUrlFromRssFeed": "URL de l'episodi del canal RSS",
|
||||
"LabelEpisodes": "Episodis",
|
||||
"LabelEpisodic": "Episodis",
|
||||
"LabelExample": "Exemple",
|
||||
@@ -352,7 +352,7 @@
|
||||
"LabelFeedURL": "Font de URL",
|
||||
"LabelFetchingMetadata": "Obtenció de metadades",
|
||||
"LabelFile": "Fitxer",
|
||||
"LabelFileBirthtime": "Arxiu creat a",
|
||||
"LabelFileBirthtime": "Fitxer creat a",
|
||||
"LabelFileBornDate": "Creat {0}",
|
||||
"LabelFileModified": "Fitxer modificat",
|
||||
"LabelFileModifiedDate": "Modificat {0}",
|
||||
@@ -473,6 +473,7 @@
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nom de la notificació de OpenID que conté permisos avançats per accions d'usuari dins l'aplicació que s'aplicaran a rols que no siguin d'administrador (<b>si estan configurats</b>). Si el reclam no apareix en la resposta, es denegarà l'accés a ABS. Si manca una sola opció, es tractarà com a <code>falsa</code>. Assegura't que la notificació del proveïdor d'identitats coincideixi amb l'estructura esperada:",
|
||||
"LabelOpenIDClaims": "Deixa les següents opcions buides per desactivar l'assignació avançada de grups i permisos, el que assignaria automàticament al grup 'Usuari'.",
|
||||
"LabelOpenIDGroupClaimDescription": "Nom de la declaració OpenID que conté una llista de grups de l'usuari. Comunament coneguts com <code>grups</code>. <b>Si es configura</b>, l'aplicació assignarà automàticament rols basats en la pertinença a grups de l'usuari, sempre que aquests grups es denominen 'admin', 'user' o 'guest' en la notificació. La sol·licitud ha de contenir una llista, i si un usuari pertany a diversos grups, l'aplicació assignarà el rol corresponent al major nivell d'accés. Si cap grup coincideix, es denegarà l'accés.",
|
||||
"LabelOpenRSSFeed": "Obre el canal RSS",
|
||||
"LabelOverwrite": "Sobreescriure",
|
||||
"LabelPaginationPageXOfY": "Pàgina {0} de {1}",
|
||||
"LabelPassword": "Contrasenya",
|
||||
@@ -497,7 +498,7 @@
|
||||
"LabelPodcasts": "Pòdcasts",
|
||||
"LabelPort": "Port",
|
||||
"LabelPrefixesToIgnore": "Prefixos per Ignorar (no distingeix entre majúscules i minúscules.)",
|
||||
"LabelPreventIndexing": "Evita que la teva font sigui indexada pels directoris de podcasts d'iTunes i Google",
|
||||
"LabelPreventIndexing": "Evita que el vostre canal l'indexin els directoris de pòdcasts de l'iTunes i Google",
|
||||
"LabelPrimaryEbook": "Ebook Principal",
|
||||
"LabelProgress": "Progrés",
|
||||
"LabelProvider": "Proveïdor",
|
||||
@@ -530,7 +531,7 @@
|
||||
"LabelRemoveAllMetadataJson": "Eliminar tots els fitxers metadata.json",
|
||||
"LabelRemoveCover": "Eliminar Coberta",
|
||||
"LabelRemoveMetadataFile": "Eliminar fitxers de metadades en carpetes d'elements de biblioteca",
|
||||
"LabelRemoveMetadataFileHelp": "Elimina tots els fitxers metadata.json i metadata.abs de les teves carpetes {0}.",
|
||||
"LabelRemoveMetadataFileHelp": "Elimina tots els fitxers metadata.json i metadata.abs de les vostres carpetes {0}.",
|
||||
"LabelRowsPerPage": "Files per Pàgina",
|
||||
"LabelSearchTerm": "Cercar Terme",
|
||||
"LabelSearchTitle": "Cercar Títol",
|
||||
@@ -562,7 +563,13 @@
|
||||
"LabelSettingsExperimentalFeatures": "Funcions Experimentals",
|
||||
"LabelSettingsExperimentalFeaturesHelp": "Funcions en desenvolupament que es beneficiarien dels teus comentaris i experiències de prova. Feu clic aquí per obrir una conversa a Github.",
|
||||
"LabelSettingsFindCovers": "Troba cobertes",
|
||||
"LabelSettingsHideSingleBookSeries": "Amaga les sèries amb un sol llibre",
|
||||
"LabelSettingsParseSubtitles": "Analitza els subtítols",
|
||||
"LabelSettingsSortingIgnorePrefixes": "Ignora els prefixos en ordenar",
|
||||
"LabelSettingsTimeFormat": "Format d'hora",
|
||||
"LabelShare": "Comparteix",
|
||||
"LabelShareDownloadableHelp": "Permet els usuaris amb l'enllaç de compartició de baixar un fitxer ZIP amb l'element de la biblioteca.",
|
||||
"LabelShareURL": "URL de compartició",
|
||||
"LabelShowAll": "Mostra-ho tot",
|
||||
"LabelShowSeconds": "Mostra segons",
|
||||
"LabelShowSubtitles": "Mostra subtítols",
|
||||
@@ -656,89 +663,98 @@
|
||||
"LabelViewPlayerSettings": "Mostra els ajustaments del reproductor",
|
||||
"LabelViewQueue": "Mostra cua del reproductor",
|
||||
"LabelVolume": "Volum",
|
||||
"LabelWebRedirectURLsDescription": "Autoritza aquestes URL al teu proveïdor OAuth per permetre redirecció a l'aplicació web després d'iniciar sessió:",
|
||||
"LabelWebRedirectURLsDescription": "Autoritzeu aquests URL al vostre proveïdor OAuth per a permetre redirigir a l’aplicació web després d'iniciar sessió:",
|
||||
"LabelWebRedirectURLsSubfolder": "Subcarpeta per a URL de redirecció",
|
||||
"LabelWeekdaysToRun": "Executar en dies de la setmana",
|
||||
"LabelXBooks": "{0} llibres",
|
||||
"LabelXItems": "{0} elements",
|
||||
"LabelYearReviewHide": "Oculta resum de l'any",
|
||||
"LabelYearReviewShow": "Mostra resum de l'any",
|
||||
"LabelYourAudiobookDuration": "Duració del teu audiollibre",
|
||||
"LabelYourAudiobookDuration": "Duració del vostre audiollibre",
|
||||
"LabelYourBookmarks": "Els vostres marcadors",
|
||||
"LabelYourPlaylists": "Les teves llistes",
|
||||
"LabelYourPlaylists": "Les vostres llistes",
|
||||
"LabelYourProgress": "El vostre progrés",
|
||||
"MessageAddToPlayerQueue": "Afegeix a la cua del reproductor",
|
||||
"MessageAppriseDescription": "Per utilitzar aquesta funció, hauràs de tenir l'<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API d'Apprise</a> en funcionament o una API que gestioni resultats similars. <br/>La URL de l'API d'Apprise ha de tenir la mateixa ruta d'arxius que on s'envien les notificacions. Per exemple: si la teva API és a <code>http://192.168.1.1:8337</code>, llavors posaries <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Reengegueu el servidor després de desar perquè s'hi apliquin els canvis d'OIDC.",
|
||||
"MessageBackupsDescription": "Les còpies de seguretat inclouen: usuaris, progrés dels usuaris, detalls dels elements de la biblioteca, configuració del servidor i imatges a <code>/metadata/items</code> i <code>/metadata/authors</code>. Les còpies de seguretat <strong>NO</strong> inclouen cap fitxer guardat a la carpeta de la teva biblioteca.",
|
||||
"MessageBackupsLocationEditNote": "Nota: Actualitzar la ubicació de la còpia de seguretat no mourà ni modificarà les còpies existents",
|
||||
"MessageBackupsLocationNoEditNote": "Nota: La ubicació de la còpia de seguretat es defineix mitjançant una variable d'entorn i no es pot modificar aquí.",
|
||||
"MessageBackupsLocationPathEmpty": "La ruta de la còpia de seguretat no pot estar buida",
|
||||
"MessageBatchQuickMatchDescription": "La funció \"Troba Ràpid\" intentarà afegir portades i metadades que falten als elements seleccionats. Activa l'opció següent perquè \"Troba Ràpid\" pugui sobreescriure portades i/o metadades existents.",
|
||||
"MessageBookshelfNoCollections": "No tens cap col·lecció",
|
||||
"MessageBookshelfNoCollections": "Encara no heu fet cap col·lecció",
|
||||
"MessageBookshelfNoCollectionsHelp": "Les col·leccions són públiques. Tots els usuaris amb accés a la biblioteca les podran veure.",
|
||||
"MessageBookshelfNoRSSFeeds": "Cap font RSS està oberta",
|
||||
"MessageBookshelfNoResultsForFilter": "Cap resultat per al filtre \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForFilter": "Cap resultat per al filtre «{0}: {1}»",
|
||||
"MessageBookshelfNoResultsForQuery": "Cap resultat per a la consulta",
|
||||
"MessageBookshelfNoSeries": "No tens cap sèrie",
|
||||
"MessageBookshelfNoSeries": "No teniu cap sèrie",
|
||||
"MessageChapterEndIsAfter": "El final del capítol és després del final del teu audiollibre",
|
||||
"MessageChapterErrorFirstNotZero": "El primer capítol ha de començar a 0",
|
||||
"MessageChapterErrorStartGteDuration": "El temps d'inici no és vàlid: ha de ser inferior a la durada de l'audiollibre",
|
||||
"MessageChapterErrorStartLtPrev": "El temps d'inici no és vàlid: ha de ser igual o més gran que el temps d'inici del capítol anterior",
|
||||
"MessageChapterStartIsAfter": "L'inici del capítol és després del final del teu audiollibre",
|
||||
"MessageChaptersNotFound": "No s'han trobat els capítols",
|
||||
"MessageCheckingCron": "Comprovant cron...",
|
||||
"MessageConfirmCloseFeed": "Estàs segur que vols tancar aquesta font?",
|
||||
"MessageConfirmDeleteBackup": "Estàs segur que vols eliminar la còpia de seguretat {0}?",
|
||||
"MessageConfirmDeleteDevice": "Estàs segur que vols eliminar el lector electrònic \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Això eliminarà el fitxer del teu sistema. Estàs segur?",
|
||||
"MessageConfirmDeleteLibrary": "Estàs segur que vols eliminar permanentment la biblioteca \"{0}\"?",
|
||||
"MessageConfirmDeleteLibraryItem": "Això eliminarà l'element de la base de dades i del sistema. Estàs segur?",
|
||||
"MessageConfirmDeleteLibraryItems": "Això eliminarà {0} element(s) de la base de dades i del sistema. Estàs segur?",
|
||||
"MessageConfirmDeleteMetadataProvider": "Estàs segur que vols eliminar el proveïdor de metadades personalitzat \"{0}\"?",
|
||||
"MessageConfirmDeleteNotification": "Estàs segur que vols eliminar aquesta notificació?",
|
||||
"MessageConfirmDeleteSession": "Estàs segur que vols eliminar aquesta sessió?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Estàs segur que vols incrustar metadades a {0} fitxer(s) d'àudio?",
|
||||
"MessageConfirmForceReScan": "Estàs segur que vols forçar un reescaneig?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Estàs segur que vols marcar tots els episodis com a acabats?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Estàs segur que vols marcar tots els episodis com a no acabats?",
|
||||
"MessageConfirmMarkItemFinished": "Estàs segur que vols marcar \"{0}\" com a acabat?",
|
||||
"MessageConfirmMarkItemNotFinished": "Estàs segur que vols marcar \"{0}\" com a no acabat?",
|
||||
"MessageConfirmMarkSeriesFinished": "Estàs segur que vols marcar tots els llibres d'aquesta sèrie com a acabats?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Estàs segur que vols marcar tots els llibres d'aquesta sèrie com a no acabats?",
|
||||
"MessageConfirmNotificationTestTrigger": "Vols activar aquesta notificació amb dades de prova?",
|
||||
"MessageConfirmPurgeCache": "Esborrar la memòria cau eliminarà tot el directori localitzat a <code>/metadata/cache</code>. <br /><br />Estàs segur que vols eliminar-lo?",
|
||||
"MessageConfirmCloseFeed": "Segur que voleu tancar aquest canal?",
|
||||
"MessageConfirmDeleteBackup": "Segur que voleu suprimir la còpia de seguretat de {0}?",
|
||||
"MessageConfirmDeleteDevice": "Segur que voleu suprimir el lector electrònic «{0}»?",
|
||||
"MessageConfirmDeleteFile": "Això suprimirà el fitxer del vostre sistema de fitxers. N'esteu segur?",
|
||||
"MessageConfirmDeleteLibrary": "Segur que voleu suprimir permanentment la biblioteca «{0}»?",
|
||||
"MessageConfirmDeleteLibraryItem": "Això suprimirà l’element de la base de dades i del sistema de fitxers. N’esteu segur?",
|
||||
"MessageConfirmDeleteLibraryItems": "Això suprimirà {0} element(s) de la base de dades i del sistema de fitxers. N'esteu segur?",
|
||||
"MessageConfirmDeleteMetadataProvider": "Segur que voleu suprimir el proveïdor de metadades personalitzat «{0}»?",
|
||||
"MessageConfirmDeleteNotification": "Segur que voleu suprimir aquesta notificació?",
|
||||
"MessageConfirmDeleteSession": "Segur que voleu suprimir aquesta sessió?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Segur que voleu incrustar metadades a {0} fitxer(s) d'àudio?",
|
||||
"MessageConfirmForceReScan": "Segur que voleu forçar un reescaneig?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Segur que voleu marcar tots els episodis com a acabats?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Segur que voleu marcar tots els episodis com a no acabats?",
|
||||
"MessageConfirmMarkItemFinished": "Segur que voleu marcar «{0}» com a acabat?",
|
||||
"MessageConfirmMarkItemNotFinished": "Segur que voleu marcar «{0}» com a no acabat?",
|
||||
"MessageConfirmMarkSeriesFinished": "Segur que voleu marcar tots els llibres d'aquesta sèrie com a acabats?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Segur que voleu marcar tots els llibres d'aquesta sèrie com a no acabats?",
|
||||
"MessageConfirmNotificationTestTrigger": "Voleu activar aquesta notificació amb dades de prova?",
|
||||
"MessageConfirmPurgeCache": "Purgar la memòria cau suprimirà tot el directori localitzat a <code>/metadata/cache</code>. <br /><br />Segur que voleu eliminar-lo?",
|
||||
"MessageConfirmPurgeItemsCache": "Esborrar la memòria cau dels elements eliminarà el directori <code>/metadata/cache/items</code>.<br />Estàs segur?",
|
||||
"MessageConfirmQuickEmbed": "Advertència! La integració ràpida no fa còpies de seguretat dels teus fitxers d'àudio. Assegura't d'haver-ne fet una còpia abans. <br><br>Vols continuar?",
|
||||
"MessageConfirmQuickEmbed": "Avís: la incrustació ràpida no fa còpies de seguretat dels vostres fitxers d'àudio. Assegureu-vos d'haver-ne fet una còpia abans. <br><br>Voleu continuar?",
|
||||
"MessageConfirmQuickMatchEpisodes": "El reconeixement ràpid sobreescriurà els detalls si es troba una coincidència. Estàs segur?",
|
||||
"MessageConfirmReScanLibraryItems": "Estàs segur que vols reescanejar {0} element(s)?",
|
||||
"MessageConfirmRemoveAllChapters": "Estàs segur que vols eliminar tots els capítols?",
|
||||
"MessageConfirmRemoveAuthor": "Estàs segur que vols eliminar l'autor \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Estàs segur que vols eliminar la col·lecció \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Estàs segur que vols eliminar l'episodi \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodes": "Estàs segur que vols eliminar {0} episodis?",
|
||||
"MessageConfirmRemoveListeningSessions": "Estàs segur que vols eliminar {0} sessions d'escolta?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Estàs segur que vols eliminar tots els fitxers de metadades.{0} de les carpetes dels elements de la teva biblioteca?",
|
||||
"MessageConfirmRemoveNarrator": "Estàs segur que vols eliminar el narrador \"{0}\"?",
|
||||
"MessageConfirmRemovePlaylist": "Estàs segur que vols eliminar la llista de reproducció \"{0}\"?",
|
||||
"MessageConfirmRenameGenre": "Estàs segur que vols canviar el gènere \"{0}\" a \"{1}\" per a tots els elements?",
|
||||
"MessageConfirmReScanLibraryItems": "Segur que voleu reescanejar {0} element(s)?",
|
||||
"MessageConfirmRemoveAllChapters": "Segur que voleu eliminar tots els capítols?",
|
||||
"MessageConfirmRemoveAuthor": "Segur que voleu eliminar l'autor «{0}»?",
|
||||
"MessageConfirmRemoveCollection": "Segur que voleu eliminar la col·lecció «{0}»?",
|
||||
"MessageConfirmRemoveEpisode": "Segur que voleu eliminar l'episodi «{0}»?",
|
||||
"MessageConfirmRemoveEpisodes": "Segur que voleu eliminar {0} episodis?",
|
||||
"MessageConfirmRemoveListeningSessions": "Segur que voleu eliminar {0} sessions d'escolta?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Segur que voleu eliminar tots els fitxers metadata.{0} de les carpetes dels elements de la vostra biblioteca?",
|
||||
"MessageConfirmRemoveNarrator": "Segur que voleu eliminar el narrador «{0}»?",
|
||||
"MessageConfirmRemovePlaylist": "Segur que voleu eliminar la llista de reproducció «{0}»?",
|
||||
"MessageConfirmRenameGenre": "Segur que voleu canviar el nom del gènere «{0}» a «{1}» per a tots els elements?",
|
||||
"MessageConfirmRenameGenreMergeNote": "Nota: Aquest gènere ja existeix, i es fusionarà.",
|
||||
"MessageConfirmRenameGenreWarning": "Advertència! Ja existeix un gènere similar \"{0}\".",
|
||||
"MessageConfirmRenameTag": "Estàs segur que vols canviar l'etiqueta \"{0}\" a \"{1}\" per a tots els elements?",
|
||||
"MessageConfirmRenameTag": "Segur que voleu canviar el nom de l'etiqueta «{0}» a «{1}» per a tots els elements?",
|
||||
"MessageConfirmRenameTagMergeNote": "Nota: Aquesta etiqueta ja existeix, i es fusionarà.",
|
||||
"MessageConfirmRenameTagWarning": "Advertència! Ja existeix una etiqueta similar \"{0}\".",
|
||||
"MessageConfirmResetProgress": "Estàs segur que vols reiniciar el teu progrés?",
|
||||
"MessageConfirmSendEbookToDevice": "Estàs segur que vols enviar {0} ebook(s) \"{1}\" al dispositiu \"{2}\"?",
|
||||
"MessageConfirmUnlinkOpenId": "Estàs segur que vols desvincular aquest usuari d'OpenID?",
|
||||
"MessageConfirmResetProgress": "Segur que voleu reinicialitzar el vostre progrés?",
|
||||
"MessageConfirmSendEbookToDevice": "Segur que voleu enviar {0} llibre(s) «{1}» al dispositiu «{2}»?",
|
||||
"MessageConfirmUnlinkOpenId": "Segur que voleu desenllaçar aquest usuari d'OpenID?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} dies escoltats l'any passat",
|
||||
"MessageDownloadingEpisode": "S'està baixant l'episodi",
|
||||
"MessageDragFilesIntoTrackOrder": "Arrossega els fitxers en l'ordre correcte de les pistes",
|
||||
"MessageEmbedFailed": "Error en incrustar!",
|
||||
"MessageEmbedFinished": "Incrustació acabada!",
|
||||
"MessageEmbedQueue": "En cua per incrustar metadades ({0} en cua)",
|
||||
"MessageFeedURLWillBe": "L'URL del canal serà {0}",
|
||||
"MessageFetching": "S'està recuperant...",
|
||||
"MessageImportantNotice": "Avís important",
|
||||
"MessageInsertChapterBelow": "Insereix un capítol a sota",
|
||||
"MessageInvalidAsin": "L'ASIN no és vàlid",
|
||||
"MessageItemsSelected": "{0} elements seleccionats",
|
||||
"MessageItemsUpdated": "{0} elements actualitzats",
|
||||
"MessageJoinUsOn": "Uniu-vos a nosaltres a",
|
||||
"MessageLoading": "S'està carregant...",
|
||||
"MessageLoadingFolders": "S'estan carregant les carpetes...",
|
||||
"MessageMarkAllEpisodesFinished": "Marca tots els episodis com a acabats",
|
||||
"MessageMarkAllEpisodesNotFinished": "Marca tots els episodis com a inacabats",
|
||||
"MessageMarkAsFinished": "Marcar com acabat",
|
||||
"MessageMarkAsNotFinished": "Marcar com no acabat",
|
||||
"MessageMatchBooksDescription": "S'intentarà fer coincidir els llibres de la biblioteca amb un llibre del proveïdor de cerca seleccionat, i s'ompliran els detalls buits i la portada. No sobreescriu els detalls.",
|
||||
@@ -779,9 +795,9 @@
|
||||
"MessagePauseChapter": "Pausar la reproducció del capítol",
|
||||
"MessagePlayChapter": "Escoltar l'inici del capítol",
|
||||
"MessagePlaylistCreateFromCollection": "Crear una llista de reproducció a partir d'una col·lecció",
|
||||
"MessagePleaseWait": "Espera si us plau...",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "El podcast no té una URL de font RSS que es pugui utilitzar",
|
||||
"MessagePodcastSearchField": "Introdueix el terme de cerca o la URL de la font RSS",
|
||||
"MessagePleaseWait": "Espereu...",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "El pòdcast no té un URL de canal RSS que es pugui utilitzar",
|
||||
"MessagePodcastSearchField": "Introduïu el terme de cerca o l'URL del canal RSS",
|
||||
"MessageQuickEmbedInProgress": "Integració ràpida en procés",
|
||||
"MessageQuickEmbedQueue": "En cua per a inserció ràpida ({0} en cua)",
|
||||
"MessageQuickMatchAllEpisodes": "Combina ràpidament tots els episodis",
|
||||
@@ -789,10 +805,10 @@
|
||||
"MessageRemoveChapter": "Eliminar capítols",
|
||||
"MessageRemoveEpisodes": "Eliminar {0} episodi(s)",
|
||||
"MessageRemoveFromPlayerQueue": "Eliminar de la cua del reproductor",
|
||||
"MessageRemoveUserWarning": "Estàs segur que vols eliminar l'usuari \"{0}\"?",
|
||||
"MessageRemoveUserWarning": "Segur que voleu suprimir permanentment l'usuari «{0}»?",
|
||||
"MessageReportBugsAndContribute": "Informa d'errors, sol·licita funcions i contribueix a",
|
||||
"MessageResetChaptersConfirm": "Estàs segur que vols desfer els canvis i revertir els capítols al seu estat original?",
|
||||
"MessageRestoreBackupConfirm": "Estàs segur que vols restaurar la còpia de seguretat creada a",
|
||||
"MessageResetChaptersConfirm": "Segur que voleu desfer els canvis i revertir els capítols al seu estat original?",
|
||||
"MessageRestoreBackupConfirm": "Segur que voleu restaurar la còpia de seguretat creada a",
|
||||
"MessageRestoreBackupWarning": "Restaurar sobreescriurà tota la base de dades situada a /config i les imatges de portades a /metadata/items i /metadata/authors.<br /><br />La còpia de seguretat no modifica cap fitxer a les carpetes de la teva biblioteca. Si has activat l'opció del servidor per guardar portades i metadades a les carpetes de la biblioteca, aquests fitxers no es guarden ni sobreescriuen.<br /><br />Tots els clients que utilitzin el teu servidor s'actualitzaran automàticament.",
|
||||
"MessageSearchResultsFor": "Resultats de la cerca de",
|
||||
"MessageSelected": "{0} seleccionat(s)",
|
||||
@@ -802,15 +818,15 @@
|
||||
"MessageShareExpiresIn": "Caduca en {0}",
|
||||
"MessageShareURLWillBe": "La URL per compartir serà <strong>{0}</strong>",
|
||||
"MessageStartPlaybackAtTime": "Començar la reproducció per a \"{0}\" a {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "El fitxer d'àudio \"{0}\" no es pot escriure",
|
||||
"MessageTaskAudioFileNotWritable": "El fitxer d'àudio «{0}» no es pot escriure",
|
||||
"MessageTaskCanceledByUser": "Tasca cancel·lada per l'usuari",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Descarregant l'episodi \"{0}\"",
|
||||
"MessageTaskDownloadingEpisodeDescription": "S'està baixant l'episodi «{0}»",
|
||||
"MessageTaskEmbeddingMetadata": "Inserint metadades",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Inserint metadades en l'audiollibre \"{0}\"",
|
||||
"MessageTaskEncodingM4b": "Codificant M4B",
|
||||
"MessageTaskEncodingM4bDescription": "Codificant l'audiollibre \"{0}\" en un únic fitxer M4B",
|
||||
"MessageTaskEncodingM4bDescription": "S'està codificant l'audiollibre «{0}» en un únic fitxer M4B",
|
||||
"MessageTaskFailed": "Fallada",
|
||||
"MessageTaskFailedToBackupAudioFile": "Error en fer una còpia de seguretat del fitxer d'àudio \"{0}\"",
|
||||
"MessageTaskFailedToBackupAudioFile": "No s'ha pogut fer una còpia de seguretat del fitxer d'àudio «{0}»",
|
||||
"MessageTaskFailedToCreateCacheDirectory": "Error en crear el directori de la memòria cau",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "Error en incrustar metadades en el fitxer \"{0}\"",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Error en fusionar fitxers d'àudio",
|
||||
@@ -819,14 +835,14 @@
|
||||
"MessageTaskMatchingBooksInLibrary": "Coincidint llibres a la biblioteca \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Sense fitxers per escanejar",
|
||||
"MessageTaskOpmlImport": "Importar OPML",
|
||||
"MessageTaskOpmlImportDescription": "Creant podcasts a partir de {0} fonts RSS",
|
||||
"MessageTaskOpmlImportFeed": "Importació de feed OPML",
|
||||
"MessageTaskOpmlImportFeedDescription": "Importació del feed RSS \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedFailed": "No es pot obtenir el podcast",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Creant el podcast \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "El podcast ja existeix a la ruta",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Error en crear el podcast",
|
||||
"MessageTaskOpmlImportFinished": "Afegit {0} podcasts",
|
||||
"MessageTaskOpmlImportDescription": "S'estan creant pòdcasts a partir de {0} canals RSS",
|
||||
"MessageTaskOpmlImportFeed": "Importació d'un canal OPML",
|
||||
"MessageTaskOpmlImportFeedDescription": "S'està important el canal RSS «{0}»",
|
||||
"MessageTaskOpmlImportFeedFailed": "No s'ha pogut obtenir el canal del pòdcast",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "S'està creant el pòdcast «{0}»",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "El pòdcast ja existeix al camí",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "No s'ha pogut crear el pòdcast",
|
||||
"MessageTaskOpmlImportFinished": "S'han afegit {0} pòdcasts",
|
||||
"MessageTaskOpmlParseFailed": "No s'ha pogut analitzar el fitxer OPML",
|
||||
"MessageTaskOpmlParseFastFail": "No s'ha trobat l'etiqueta <opml> o <outline> al fitxer OPML",
|
||||
"MessageTaskOpmlParseNoneFound": "No s'han trobat fonts al fitxer OPML",
|
||||
@@ -844,13 +860,13 @@
|
||||
"MessageValidCronExpression": "Expressió de cron vàlida",
|
||||
"MessageWatcherIsDisabledGlobally": "El watcher està desactivat globalment a la configuració del servidor",
|
||||
"MessageXLibraryIsEmpty": "La biblioteca {0} està buida!",
|
||||
"MessageYourAudiobookDurationIsLonger": "La durada del teu audiollibre és més llarga que la durada trobada",
|
||||
"MessageYourAudiobookDurationIsShorter": "La durada del teu audiollibre és més curta que la durada trobada",
|
||||
"MessageYourAudiobookDurationIsLonger": "La durada del vostre audiollibre és major que la durada trobada",
|
||||
"MessageYourAudiobookDurationIsShorter": "La durada del vostre audiollibre és menor que la durada trobada",
|
||||
"NoteChangeRootPassword": "L'usuari Root és l'únic usuari que pot no tenir una contrasenya",
|
||||
"NoteChapterEditorTimes": "Nota: El temps d'inici del primer capítol ha de romandre a 0:00, i el temps d'inici de l'últim capítol no pot superar la durada de l'audiollibre.",
|
||||
"NoteFolderPicker": "Nota: Les carpetes ja assignades no es mostraran",
|
||||
"NoteRSSFeedPodcastAppsHttps": "Advertència: La majoria d'aplicacions de podcast requereixen que la URL de la font RSS utilitzi HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Advertència: Un o més dels teus episodis no tenen data de publicació. Algunes aplicacions de podcast ho requereixen.",
|
||||
"NoteChapterEditorTimes": "Nota: el temps d'inici del primer capítol ha de romandre a 0:00, i el temps d'inici de l'últim capítol no pot superar la durada de l'audiollibre.",
|
||||
"NoteFolderPicker": "Nota: les carpetes ja assignades no es mostraran",
|
||||
"NoteRSSFeedPodcastAppsHttps": "Avís: la majoria d'aplicacions de pòdcast requereixen que l'URL del canal RSS utilitzi HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Avís: un o més dels vostres episodis no tenen data de publicació. Algunes aplicacions de pòdcast ho requereixen.",
|
||||
"NoteUploaderFoldersWithMediaFiles": "Les carpetes amb fitxers multimèdia es gestionaran com a elements separats a la biblioteca.",
|
||||
"NoteUploaderOnlyAudioFiles": "Si només puges fitxers d'àudio, cada fitxer es gestionarà com un audiollibre separat.",
|
||||
"NoteUploaderUnsupportedFiles": "Els fitxers no compatibles seran ignorats. Si selecciona o arrossega una carpeta, els fitxers que no estiguin dins d'una subcarpeta seran ignorats.",
|
||||
@@ -859,7 +875,7 @@
|
||||
"NotificationOnEpisodeDownloadedDescription": "S'activa quan es descarrega automàticament un episodi d'un podcast",
|
||||
"NotificationOnTestDescription": "Esdeveniment per provar el sistema de notificacions",
|
||||
"PlaceholderNewCollection": "Nou nom de la col·lecció",
|
||||
"PlaceholderNewFolderPath": "Nova ruta de carpeta",
|
||||
"PlaceholderNewFolderPath": "Camí de carpeta nou",
|
||||
"PlaceholderNewPlaylist": "Nou nom de la llista de reproducció",
|
||||
"PlaceholderSearch": "Cerca...",
|
||||
"PlaceholderSearchEpisode": "Cerca d'episodis...",
|
||||
@@ -885,7 +901,7 @@
|
||||
"ToastAppriseUrlRequired": "Cal introduir una URL de Apprise",
|
||||
"ToastAsinRequired": "ASIN requerit",
|
||||
"ToastAuthorImageRemoveSuccess": "S'ha eliminat la imatge de l'autor",
|
||||
"ToastAuthorNotFound": "No s'ha trobat l'autor \"{0}\"",
|
||||
"ToastAuthorNotFound": "No s'ha trobat l'autor «{0}»",
|
||||
"ToastAuthorRemoveSuccess": "Autor eliminat",
|
||||
"ToastAuthorSearchNotFound": "No s'ha trobat l'autor",
|
||||
"ToastAuthorUpdateMerged": "Autor combinat",
|
||||
@@ -913,6 +929,7 @@
|
||||
"ToastCachePurgeFailed": "Error en purgar la memòria cau",
|
||||
"ToastCachePurgeSuccess": "Memòria cau purgada amb èxit",
|
||||
"ToastChaptersHaveErrors": "Els capítols tenen errors",
|
||||
"ToastChaptersInvalidShiftAmountLast": "La quantitat de desplaçament no és vàlida. L'hora d'inici de l'últim capítol s'estendria més enllà de la durada d'aquest audiollibre.",
|
||||
"ToastChaptersMustHaveTitles": "Els capítols han de tenir un títol",
|
||||
"ToastChaptersRemoved": "Capítols eliminats",
|
||||
"ToastChaptersUpdated": "Capítols actualitzats",
|
||||
@@ -950,34 +967,35 @@
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Element marcat com a no acabat",
|
||||
"ToastItemUpdateSuccess": "Element actualitzat",
|
||||
"ToastLibraryCreateFailed": "Error en crear la biblioteca",
|
||||
"ToastLibraryCreateSuccess": "Biblioteca \"{0}\" creada",
|
||||
"ToastLibraryCreateSuccess": "S'ha creat la biblioteca «{0}»",
|
||||
"ToastLibraryDeleteFailed": "Error en eliminar la biblioteca",
|
||||
"ToastLibraryDeleteSuccess": "Biblioteca eliminada",
|
||||
"ToastLibraryScanFailedToStart": "Error en iniciar l'escaneig",
|
||||
"ToastLibraryScanStarted": "S'ha iniciat l'escaneig de la biblioteca",
|
||||
"ToastLibraryUpdateSuccess": "Biblioteca \"{0}\" actualitzada",
|
||||
"ToastLibraryUpdateSuccess": "S'ha actualitzat la biblioteca «{0}»",
|
||||
"ToastMatchAllAuthorsFailed": "No coincideix amb tots els autors",
|
||||
"ToastMetadataFilesRemovedError": "Error en eliminar metadades de {0} arxius",
|
||||
"ToastMetadataFilesRemovedNoneFound": "No s'han trobat metadades en {0} arxius",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "Cap metadada eliminada en {0} arxius",
|
||||
"ToastMetadataFilesRemovedError": "S’ha produït un error en eliminar els fitxers metadata.{0}",
|
||||
"ToastMetadataFilesRemovedNoneFound": "No hi ha cap fitxer metadata.{0} a la biblioteca",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "No s'ha eliminat cap fitxer metadata.{0}",
|
||||
"ToastMetadataFilesRemovedSuccess": "{0} metadades eliminades en {1} arxius",
|
||||
"ToastMustHaveAtLeastOnePath": "Ha de tenir almenys una ruta",
|
||||
"ToastNameEmailRequired": "El nom i el correu electrònic són obligatoris",
|
||||
"ToastNameRequired": "Nom obligatori",
|
||||
"ToastNewEpisodesFound": "{0} episodi(s) nou(s) trobat(s)",
|
||||
"ToastNewUserCreatedFailed": "Error en crear el compte: \"{0}\"",
|
||||
"ToastNewUserCreatedFailed": "No s'ha pogut crear el compte: «{0}»",
|
||||
"ToastNewUserCreatedSuccess": "Nou compte creat",
|
||||
"ToastNewUserLibraryError": "Ha de seleccionar almenys una biblioteca",
|
||||
"ToastNewUserLibraryError": "S'ha de seleccionar almenys una biblioteca",
|
||||
"ToastNewUserPasswordError": "Necessites una contrasenya, només el root pot estar sense contrasenya",
|
||||
"ToastNewUserTagError": "Selecciona almenys una etiqueta",
|
||||
"ToastNewUserUsernameError": "Introdueix un nom d'usuari",
|
||||
"ToastNewUserTagError": "S'ha de seleccionar almenys una etiqueta",
|
||||
"ToastNewUserUsernameError": "Introduïu un nom d'usuari",
|
||||
"ToastNoNewEpisodesFound": "No s'han trobat nous episodis",
|
||||
"ToastNoRSSFeed": "El pòdcast no té canal RSS",
|
||||
"ToastNoUpdatesNecessary": "No cal actualitzar",
|
||||
"ToastNotificationCreateFailed": "Error en crear la notificació",
|
||||
"ToastNotificationDeleteFailed": "Error en eliminar la notificació",
|
||||
"ToastNotificationCreateFailed": "No s'ha pogut crear la notificació",
|
||||
"ToastNotificationDeleteFailed": "No s'ha pogut suprimir la notificació",
|
||||
"ToastNotificationFailedMaximum": "El nombre màxim d'intents fallits ha de ser ≥ 0",
|
||||
"ToastNotificationQueueMaximum": "La cua de notificació màxima ha de ser ≥ 0",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Configuració de notificació actualitzada",
|
||||
"ToastNotificationSettingsUpdateSuccess": "S'han actualitzat els paràmetres de notificacions",
|
||||
"ToastNotificationTestTriggerFailed": "No s'ha pogut activar la notificació de prova",
|
||||
"ToastNotificationTestTriggerSuccess": "Notificació de prova activada",
|
||||
"ToastNotificationUpdateSuccess": "Notificació actualitzada",
|
||||
@@ -987,16 +1005,16 @@
|
||||
"ToastPlaylistUpdateSuccess": "Llista de reproducció actualitzada",
|
||||
"ToastPodcastCreateFailed": "No s'ha pogut crear el pòdcast",
|
||||
"ToastPodcastCreateSuccess": "S'ha creat el pòdcast correctament",
|
||||
"ToastPodcastGetFeedFailed": "No s'ha pogut obtenir el podcast",
|
||||
"ToastPodcastNoEpisodesInFeed": "No s'han trobat episodis en el feed RSS",
|
||||
"ToastPodcastNoRssFeed": "El podcast no té un feed RSS",
|
||||
"ToastPodcastGetFeedFailed": "No s'ha pogut obtenir el canal del pòdcast",
|
||||
"ToastPodcastNoEpisodesInFeed": "No s'ha trobat cap episodi al canal RSS",
|
||||
"ToastPodcastNoRssFeed": "El pòdcast no té un canal RSS",
|
||||
"ToastProgressIsNotBeingSynced": "El progrés no s'està sincronitzant, reinicia la reproducció",
|
||||
"ToastProviderCreatedFailed": "Error en afegir el proveïdor",
|
||||
"ToastProviderCreatedSuccess": "Nou proveïdor afegit",
|
||||
"ToastProviderNameAndUrlRequired": "Nom i URL obligatoris",
|
||||
"ToastProviderRemoveSuccess": "Proveïdor eliminat",
|
||||
"ToastRSSFeedCloseFailed": "Error en tancar el feed RSS",
|
||||
"ToastRSSFeedCloseSuccess": "Feed RSS tancat",
|
||||
"ToastRSSFeedCloseFailed": "No s'ha pogut tancar el canal RSS",
|
||||
"ToastRSSFeedCloseSuccess": "Canal RSS tancat",
|
||||
"ToastRemoveFailed": "Error en eliminar",
|
||||
"ToastRemoveItemFromCollectionFailed": "Error en eliminar l'element de la col·lecció",
|
||||
"ToastRemoveItemFromCollectionSuccess": "Element eliminat de la col·lecció",
|
||||
@@ -1011,6 +1029,7 @@
|
||||
"ToastSelectAtLeastOneUser": "Selecciona almenys un usuari",
|
||||
"ToastSendEbookToDeviceFailed": "Error en enviar l'ebook al dispositiu",
|
||||
"ToastSendEbookToDeviceSuccess": "Ebook enviat al dispositiu \"{0}\"",
|
||||
"ToastSeriesSubmitFailedSameName": "No és possible afegir dues sèries amb el mateix nom",
|
||||
"ToastSeriesUpdateFailed": "Error en actualitzar la sèrie",
|
||||
"ToastSeriesUpdateSuccess": "Sèrie actualitzada",
|
||||
"ToastServerSettingsUpdateSuccess": "Configuració del servidor actualitzada",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Wiedergabeliste",
|
||||
"HeaderPlaylistItems": "Einträge in der Wiedergabeliste",
|
||||
"HeaderPodcastsToAdd": "Podcasts zum Hinzufügen",
|
||||
"HeaderPresets": "Voreinstellungen",
|
||||
"HeaderPreviewCover": "Vorschau Titelbild",
|
||||
"HeaderRSSFeedGeneral": "RSS Details",
|
||||
"HeaderRSSFeedIsOpen": "RSS-Feed ist geöffnet",
|
||||
@@ -530,6 +531,7 @@
|
||||
"LabelReleaseDate": "Veröffentlichungsdatum",
|
||||
"LabelRemoveAllMetadataAbs": "Alle metadata.abs Dateien löschen",
|
||||
"LabelRemoveAllMetadataJson": "Alle metadata.json Dateien löschen",
|
||||
"LabelRemoveAudibleBranding": "Audible Intro sowie Outro aus Kapiteln entfernen",
|
||||
"LabelRemoveCover": "Entferne Titelbild",
|
||||
"LabelRemoveMetadataFile": "Metadaten-Dateien in Bibliotheksordnern löschen",
|
||||
"LabelRemoveMetadataFileHelp": "Alle metadata.json und metadata.abs Dateien aus den Ordnern {0} löschen.",
|
||||
@@ -705,6 +707,8 @@
|
||||
"LabelYourProgress": "Fortschritt",
|
||||
"MessageAddToPlayerQueue": "Zur Abspielwarteliste hinzufügen",
|
||||
"MessageAppriseDescription": "Um diese Funktion nutzen zu können, musst du eine Instanz von <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> laufen haben oder eine API verwenden welche dieselbe Anfragen bearbeiten kann. <br />Die Apprise API Url muss der vollständige URL-Pfad sein, an den die Benachrichtigung gesendet werden soll, z.B. wenn Ihre API-Instanz unter <code>http://192.168.1.1:8337</code> läuft, würdest du <code>http://192.168.1.1:8337/notify</code> eingeben.",
|
||||
"MessageAsinCheck": "Stellen Sie sicher, dass Sie die ASIN aus der richtigen Audible Region verwenden, nicht Amazon.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Nach dem Speichern muß der Server neugestartet werden um die OIDC Änderungen zu übernehmen.",
|
||||
"MessageBackupsDescription": "In einer Sicherung werden Benutzer, Benutzerfortschritte, Details zu den Bibliotheksobjekten, Servereinstellungen und Bilder welche in <code>/metadata/items</code> & <code>/metadata/authors</code> gespeichert sind gespeichert. Sicherungen enthalten keine Dateien welche in den einzelnen Bibliotheksordnern (Medien-Ordnern) gespeichert sind.",
|
||||
"MessageBackupsLocationEditNote": "Hinweis: Durch das Aktualisieren des Backup-Speicherorts werden vorhandene Sicherungen nicht verschoben oder geändert",
|
||||
"MessageBackupsLocationNoEditNote": "Hinweis: Der Sicherungsspeicherort wird über eine Umgebungsvariable festgelegt und kann hier nicht geändert werden.",
|
||||
@@ -723,6 +727,7 @@
|
||||
"MessageChapterErrorStartGteDuration": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumlänge (Kapitelanfang liegt zeitlich nach dem Ende des Mediums -> Lösung: Kapitelanfang < Mediumlänge)",
|
||||
"MessageChapterErrorStartLtPrev": "Ungültige Kapitelstartzeit: Kapitelanfang < Kapitelanfang vorheriges Kapitel (Kapitelanfang liegt zeitlich vor dem Beginn des vorherigen Kapitels -> Lösung: Kapitelanfang >= Startzeit des vorherigen Kapitels)",
|
||||
"MessageChapterStartIsAfter": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumende (Kapitelanfang liegt nach dem Ende des Mediums)",
|
||||
"MessageChaptersNotFound": "Kapitel gefunden nicht",
|
||||
"MessageCheckingCron": "Überprüfe Cron...",
|
||||
"MessageConfirmCloseFeed": "Feed wird geschlossen! Bist du dir sicher?",
|
||||
"MessageConfirmDeleteBackup": "Sicherung für {0} wird gelöscht! Bist du dir sicher?",
|
||||
@@ -779,6 +784,7 @@
|
||||
"MessageForceReScanDescription": "Durchsucht alle Dateien erneut, wie bei einem frischen Scan. ID3-Tags von Audiodateien, OPF-Dateien und Textdateien werden neu durchsucht.",
|
||||
"MessageImportantNotice": "Wichtiger Hinweis!",
|
||||
"MessageInsertChapterBelow": "Kapitel unten einfügen",
|
||||
"MessageInvalidAsin": "Ungültige ASIN",
|
||||
"MessageItemsSelected": "{0} ausgewählte Medien",
|
||||
"MessageItemsUpdated": "{0} Medien aktualisiert",
|
||||
"MessageJoinUsOn": "Besuche uns auf",
|
||||
|
||||
@@ -531,6 +531,7 @@
|
||||
"LabelReleaseDate": "Release Date",
|
||||
"LabelRemoveAllMetadataAbs": "Remove all metadata.abs files",
|
||||
"LabelRemoveAllMetadataJson": "Remove all metadata.json files",
|
||||
"LabelRemoveAudibleBranding": "Remove Audible intro and outro from chapters",
|
||||
"LabelRemoveCover": "Remove cover",
|
||||
"LabelRemoveMetadataFile": "Remove metadata files in library item folders",
|
||||
"LabelRemoveMetadataFileHelp": "Remove all metadata.json and metadata.abs files in your {0} folders.",
|
||||
@@ -707,6 +708,7 @@
|
||||
"MessageAddToPlayerQueue": "Add to player queue",
|
||||
"MessageAppriseDescription": "To use this feature you will need to have an instance of <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> running or an api that will handle those same requests. <br />The Apprise API Url should be the full URL path to send the notification, e.g., if your API instance is served at <code>http://192.168.1.1:8337</code> then you would put <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Ensure you are using the ASIN from the correct Audible region, not Amazon.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Restart your server after saving to apply OIDC changes.",
|
||||
"MessageBackupsDescription": "Backups include users, user progress, library item details, server settings, and images stored in <code>/metadata/items</code> & <code>/metadata/authors</code>. Backups <strong>do not</strong> include any files stored in your library folders.",
|
||||
"MessageBackupsLocationEditNote": "Note: Updating the backup location will not move or modify existing backups",
|
||||
"MessageBackupsLocationNoEditNote": "Note: The backup location is set through an environment variable and cannot be changed here.",
|
||||
@@ -854,6 +856,7 @@
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Run every {0} at {1}",
|
||||
"MessageSearchResultsFor": "Search results for",
|
||||
"MessageSelected": "{0} selected",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Series sequence cannot contain spaces",
|
||||
"MessageServerCouldNotBeReached": "Server could not be reached",
|
||||
"MessageSetChaptersFromTracksDescription": "Set chapters using each audio file as a chapter and chapter title as the audio file name",
|
||||
"MessageShareExpirationWillBe": "Expiration will be <strong>{0}</strong>",
|
||||
@@ -972,6 +975,8 @@
|
||||
"ToastCachePurgeFailed": "Failed to purge cache",
|
||||
"ToastCachePurgeSuccess": "Cache purged successfully",
|
||||
"ToastChaptersHaveErrors": "Chapters have errors",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Invalid shift amount. The last chapter start time would extend beyond the duration of this audiobook.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Invalid shift amount. The first chapter would have zero or negative length and would be overwritten by the second chapter. Increase the start duration of second chapter.",
|
||||
"ToastChaptersMustHaveTitles": "Chapters must have titles",
|
||||
"ToastChaptersRemoved": "Chapters removed",
|
||||
"ToastChaptersUpdated": "Chapters updated",
|
||||
|
||||
@@ -10,13 +10,15 @@
|
||||
"ButtonApplyChapters": "Aplicar capítulos",
|
||||
"ButtonAuthors": "Autores",
|
||||
"ButtonBack": "Atrás",
|
||||
"ButtonBatchEditPopulateFromExisting": "Rellenar desde existentes",
|
||||
"ButtonBatchEditPopulateMapDetails": "Rellenar detalles de mapa",
|
||||
"ButtonBrowseForFolder": "Buscar carpeta",
|
||||
"ButtonCancel": "Cancelar",
|
||||
"ButtonCancelEncode": "Cancelar Codificador",
|
||||
"ButtonCancelEncode": "Cancelar codificación",
|
||||
"ButtonChangeRootPassword": "Cambiar contraseña administrativa",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "Comprobar y descargar episodios nuevos",
|
||||
"ButtonChooseAFolder": "Escoger una Carpeta",
|
||||
"ButtonChooseFiles": "Escoger un Archivo",
|
||||
"ButtonChooseAFolder": "Elegir una carpeta",
|
||||
"ButtonChooseFiles": "Elegir archivos",
|
||||
"ButtonClearFilter": "Quitar filtros",
|
||||
"ButtonCloseFeed": "Cerrar suministro",
|
||||
"ButtonCloseSession": "Cerrar la sesión abierta",
|
||||
@@ -87,7 +89,7 @@
|
||||
"ButtonSaveAndClose": "Guardar y cerrar",
|
||||
"ButtonSaveTracklist": "Guardar lista de pistas",
|
||||
"ButtonScan": "Escanear",
|
||||
"ButtonScanLibrary": "Escanear Biblioteca",
|
||||
"ButtonScanLibrary": "Escanear biblioteca",
|
||||
"ButtonScrollLeft": "Desplazarse hacia la izquierda",
|
||||
"ButtonScrollRight": "Desplazarse hacia la derecha",
|
||||
"ButtonSearch": "Buscar",
|
||||
@@ -147,7 +149,7 @@
|
||||
"HeaderLastListeningSession": "Última sesión de escucha",
|
||||
"HeaderLatestEpisodes": "Episodios más recientes",
|
||||
"HeaderLibraries": "Bibliotecas",
|
||||
"HeaderLibraryFiles": "Archivos de Biblioteca",
|
||||
"HeaderLibraryFiles": "Archivos de biblioteca",
|
||||
"HeaderLibraryStats": "Estadísticas de biblioteca",
|
||||
"HeaderListeningSessions": "Sesión",
|
||||
"HeaderListeningStats": "Estadísticas de Tiempo Escuchado",
|
||||
@@ -175,6 +177,7 @@
|
||||
"HeaderPlaylist": "Lista de reproducción",
|
||||
"HeaderPlaylistItems": "Elementos de lista de reproducción",
|
||||
"HeaderPodcastsToAdd": "Pódcast para añadir",
|
||||
"HeaderPresets": "Preconfiguraciones",
|
||||
"HeaderPreviewCover": "Previsualizar cubierta",
|
||||
"HeaderRSSFeedGeneral": "Detalles de RSS",
|
||||
"HeaderRSSFeedIsOpen": "El suministro RSS está abierto",
|
||||
@@ -190,7 +193,7 @@
|
||||
"HeaderSettings": "Configuración",
|
||||
"HeaderSettingsDisplay": "Interfaz",
|
||||
"HeaderSettingsExperimental": "Funcionalidades experimentales",
|
||||
"HeaderSettingsGeneral": "General",
|
||||
"HeaderSettingsGeneral": "Generales",
|
||||
"HeaderSettingsScanner": "Escáner",
|
||||
"HeaderSettingsWebClient": "Cliente web",
|
||||
"HeaderSleepTimer": "Temporizador de apagado",
|
||||
@@ -262,14 +265,14 @@
|
||||
"LabelBooks": "Libros",
|
||||
"LabelButtonText": "Texto del botón",
|
||||
"LabelByAuthor": "por {0}",
|
||||
"LabelChangePassword": "Cambiar Contraseña",
|
||||
"LabelChangePassword": "Cambiar contraseña",
|
||||
"LabelChannels": "Canales",
|
||||
"LabelChapterCount": "{0} capítulos",
|
||||
"LabelChapterTitle": "Titulo del Capítulo",
|
||||
"LabelChapterTitle": "Título del capítulo",
|
||||
"LabelChapters": "Capítulos",
|
||||
"LabelChaptersFound": "Capítulo Encontrado",
|
||||
"LabelClickForMoreInfo": "Click para más información",
|
||||
"LabelClickToUseCurrentValue": "Haz clic para utilizar el valor actual",
|
||||
"LabelChaptersFound": "capítulos encontrados",
|
||||
"LabelClickForMoreInfo": "Pulse para más información",
|
||||
"LabelClickToUseCurrentValue": "Pulse para utilizar el valor actual",
|
||||
"LabelClosePlayer": "Cerrar reproductor",
|
||||
"LabelCodec": "Codec",
|
||||
"LabelCollapseSeries": "Colapsar serie",
|
||||
@@ -277,7 +280,7 @@
|
||||
"LabelCollection": "Colección",
|
||||
"LabelCollections": "Colecciones",
|
||||
"LabelComplete": "Completo",
|
||||
"LabelConfirmPassword": "Confirmar Contraseña",
|
||||
"LabelConfirmPassword": "Confirmar contraseña",
|
||||
"LabelContinueListening": "Seguir escuchando",
|
||||
"LabelContinueReading": "Continuar leyendo",
|
||||
"LabelContinueSeries": "Continuar series",
|
||||
@@ -288,8 +291,8 @@
|
||||
"LabelCronExpression": "Expresión de Cron",
|
||||
"LabelCurrent": "Actual",
|
||||
"LabelCurrently": "En este momento:",
|
||||
"LabelCustomCronExpression": "Expresión de Cron Personalizada:",
|
||||
"LabelDatetime": "Hora y Fecha",
|
||||
"LabelCustomCronExpression": "Expresión de Cron personalizada:",
|
||||
"LabelDatetime": "Hora y fecha",
|
||||
"LabelDays": "Días",
|
||||
"LabelDeleteFromFileSystemCheckbox": "Eliminar del sistema de archivos (desmarque para quitar de la base de datos solamente)",
|
||||
"LabelDescription": "Descripción",
|
||||
@@ -368,7 +371,7 @@
|
||||
"LabelFontStrikethrough": "Tachado",
|
||||
"LabelFormat": "Formato",
|
||||
"LabelFull": "Completo",
|
||||
"LabelGenre": "Genero",
|
||||
"LabelGenre": "Género",
|
||||
"LabelGenres": "Géneros",
|
||||
"LabelHardDeleteFile": "Eliminar Definitivamente",
|
||||
"LabelHasEbook": "Tiene un libro",
|
||||
@@ -459,17 +462,17 @@
|
||||
"LabelNotes": "Notas",
|
||||
"LabelNotificationAppriseURL": "URL(s) de Apprise",
|
||||
"LabelNotificationAvailableVariables": "Variables disponibles",
|
||||
"LabelNotificationBodyTemplate": "Plantilla de Cuerpo",
|
||||
"LabelNotificationEvent": "Evento de Notificación",
|
||||
"LabelNotificationTitleTemplate": "Plantilla de Titulo",
|
||||
"LabelNotificationsMaxFailedAttempts": "Máximo de Intentos Fallidos",
|
||||
"LabelNotificationBodyTemplate": "Plantilla de cuerpo",
|
||||
"LabelNotificationEvent": "Evento de notificación",
|
||||
"LabelNotificationTitleTemplate": "Plantilla de título",
|
||||
"LabelNotificationsMaxFailedAttempts": "Máximo de intentos fallidos",
|
||||
"LabelNotificationsMaxFailedAttemptsHelp": "Las notificaciones se desactivan después de fallar este número de veces",
|
||||
"LabelNotificationsMaxQueueSize": "Tamaño máximo de la cola de notificaciones",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Las notificaciones están limitadas a 1 por segundo. Las notificaciones serán ignoradas si llegan al numero máximo de cola para prevenir spam de eventos.",
|
||||
"LabelNumberOfBooks": "Número de libros",
|
||||
"LabelNumberOfEpisodes": "N.º de episodios",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nombre de la notificación de OpenID que contiene permisos avanzados para acciones de usuario dentro de la aplicación que se aplicarán a roles que no sean de administrador (<b>si están configurados</b>). Si el reclamo no aparece en la respuesta, se denegará el acceso a ABS. Si falta una sola opción, se tratará como <code>falsa</code>. Asegúrese de que la notificación del proveedor de identidades coincida con la estructura esperada:",
|
||||
"LabelOpenIDClaims": "Deje las siguientes opciones vacías para deshabilitar la asignación avanzada de grupos y permisos, lo que asignaría de manera automática al grupo 'Usuario'.",
|
||||
"LabelOpenIDClaims": "Deje las siguientes opciones vacías para desactivar la asignación avanzada de grupos y permisos, lo que asignaría de manera automática al grupo «Usuario».",
|
||||
"LabelOpenIDGroupClaimDescription": "Nombre de la declaración OpenID que contiene una lista de grupos del usuario. Comúnmente conocidos como <code>grupos</code>. <b>Si se configura</b>, la aplicación asignará automáticamente roles en función de la pertenencia a grupos del usuario, siempre que estos grupos se denominen \"admin\", \"user\" o \"guest\" en la notificación. La solicitud debe contener una lista, y si un usuario pertenece a varios grupos, la aplicación asignará el rol correspondiente al mayor nivel de acceso. Si ningún grupo coincide, se denegará el acceso.",
|
||||
"LabelOpenRSSFeed": "Abrir suministro RSS",
|
||||
"LabelOverwrite": "Sobrescribir",
|
||||
@@ -576,7 +579,7 @@
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Saltar libros anteriores de la serie Continuada",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "El estante de la página de inicio de Continuar Serie muestra el primer libro no iniciado de una serie que tenga por lo menos un libro finalizado y no tenga libros en progreso. Habilitar esta opción le permitirá continuar series desde el último libro que ha completado en vez del primer libro que no ha empezado.",
|
||||
"LabelSettingsParseSubtitles": "Extraer Subtítulos",
|
||||
"LabelSettingsParseSubtitlesHelp": "Extraer subtítulos de los nombres de las carpetas de los audiolibros.<br>Los subtítulos deben estar separados por \" - \"<br>Por ejemplo: \"Ejemplo de Título - Subtítulo Aquí\" tiene el subtítulo \"Subtítulo Aquí\"",
|
||||
"LabelSettingsParseSubtitlesHelp": "Extraer subtítulos de los nombres de las carpetas de los audiolibros.<br>Los subtítulos deben estar separados por « - »<br>Así, «Título de libro - Un subtítulo aquí» tiene el subtítulo «Un subtítulo aquí»",
|
||||
"LabelSettingsPreferMatchedMetadata": "Preferir metadatos encontrados",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Los datos encontrados sobreescribirán los detalles del elemento cuando se use \"Encontrar Rápido\". Por defecto, \"Encontrar Rápido\" sólo completará los detalles faltantes.",
|
||||
"LabelSettingsSkipMatchingBooksWithASIN": "Omitir libros coincidentes que ya tengan un ASIN",
|
||||
@@ -594,7 +597,7 @@
|
||||
"LabelShareDownloadableHelp": "Permite a quienes posean el enlace de compartición descargar un archivo ZIP del elemento de la biblioteca.",
|
||||
"LabelShareOpen": "abrir un recurso compartido",
|
||||
"LabelShareURL": "Compartir la URL",
|
||||
"LabelShowAll": "Mostrar Todos",
|
||||
"LabelShowAll": "Mostrar todo",
|
||||
"LabelShowSeconds": "Mostrar segundos",
|
||||
"LabelShowSubtitles": "Mostrar subtítulos",
|
||||
"LabelSize": "Tamaño",
|
||||
@@ -602,33 +605,34 @@
|
||||
"LabelSlug": "Slug",
|
||||
"LabelSortAscending": "Ascendente",
|
||||
"LabelSortDescending": "Descendente",
|
||||
"LabelSortPubDate": "Ord. fecha pub.",
|
||||
"LabelStart": "Iniciar",
|
||||
"LabelStartTime": "Tiempo de Inicio",
|
||||
"LabelStarted": "Iniciado",
|
||||
"LabelStartedAt": "Iniciado En",
|
||||
"LabelStatsAudioTracks": "Pistas de Audio",
|
||||
"LabelStatsAuthors": "Autores",
|
||||
"LabelStatsBestDay": "Mejor Día",
|
||||
"LabelStatsDailyAverage": "Promedio Diario",
|
||||
"LabelStatsBestDay": "Mejor día",
|
||||
"LabelStatsDailyAverage": "Promedio diario",
|
||||
"LabelStatsDays": "Días",
|
||||
"LabelStatsDaysListened": "Días Escuchando",
|
||||
"LabelStatsDaysListened": "Días escuchando",
|
||||
"LabelStatsHours": "Horas",
|
||||
"LabelStatsInARow": "seguidos",
|
||||
"LabelStatsItemsFinished": "Elementos Terminados",
|
||||
"LabelStatsItemsFinished": "Elementos terminados",
|
||||
"LabelStatsItemsInLibrary": "Elementos en biblioteca",
|
||||
"LabelStatsMinutes": "minutos",
|
||||
"LabelStatsMinutesListening": "Minutos Escuchando",
|
||||
"LabelStatsOverallDays": "Total de Dias",
|
||||
"LabelStatsOverallHours": "Total de Horas",
|
||||
"LabelStatsWeekListening": "Tiempo escuchando en la Semana",
|
||||
"LabelStatsMinutesListening": "Minutos escuchando",
|
||||
"LabelStatsOverallDays": "Total de días",
|
||||
"LabelStatsOverallHours": "Total de horas",
|
||||
"LabelStatsWeekListening": "Tiempo escuchando en la semana",
|
||||
"LabelSubtitle": "Subtítulo",
|
||||
"LabelSupportedFileTypes": "Tipos de archivo admitidos",
|
||||
"LabelTag": "Etiqueta",
|
||||
"LabelTags": "Etiquetas",
|
||||
"LabelTagsAccessibleToUser": "Etiquetas Accessibles al Usuario",
|
||||
"LabelTagsNotAccessibleToUser": "Etiquetas no Accesibles al Usuario",
|
||||
"LabelTasks": "Tareas Corriendo",
|
||||
"LabelTextEditorBulletedList": "Lista con viñetas",
|
||||
"LabelTagsAccessibleToUser": "Etiquetas accessibles al usuario",
|
||||
"LabelTagsNotAccessibleToUser": "Etiquetas no accesibles al usuario",
|
||||
"LabelTasks": "Tareas en ejecución",
|
||||
"LabelTextEditorBulletedList": "Lista con bolos",
|
||||
"LabelTextEditorLink": "Enlazar",
|
||||
"LabelTextEditorNumberedList": "Lista numerada",
|
||||
"LabelTextEditorUnlink": "Desenlazar",
|
||||
@@ -681,7 +685,7 @@
|
||||
"LabelUseFullTrack": "Usar pista completa",
|
||||
"LabelUseZeroForUnlimited": "Utilice 0 para ilimitado",
|
||||
"LabelUser": "Usuario",
|
||||
"LabelUsername": "Nombre de Usuario",
|
||||
"LabelUsername": "Nombre de usuario",
|
||||
"LabelValue": "Valor",
|
||||
"LabelVersion": "Versión",
|
||||
"LabelViewBookmarks": "Ver Marcadores",
|
||||
@@ -694,23 +698,27 @@
|
||||
"LabelWeekdaysToRun": "Correr en Días de la Semana",
|
||||
"LabelXBooks": "{0} libros",
|
||||
"LabelXItems": "{0} elementos",
|
||||
"LabelYearReviewHide": "Ocultar Resumen del año",
|
||||
"LabelYearReviewShow": "Resumen del año",
|
||||
"LabelYearReviewHide": "Ocultar resumen del año",
|
||||
"LabelYearReviewShow": "Ver resumen del año",
|
||||
"LabelYourAudiobookDuration": "Duración de tu Audiolibro",
|
||||
"LabelYourBookmarks": "Tus Marcadores",
|
||||
"LabelYourBookmarks": "Sus marcadores",
|
||||
"LabelYourPlaylists": "Tus Listas",
|
||||
"LabelYourProgress": "Su progreso",
|
||||
"MessageAddToPlayerQueue": "Agregar a fila del Reproductor",
|
||||
"MessageAppriseDescription": "Para usar esta función deberás tener <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">la API de Apprise</a> corriendo o una API que maneje los mismos resultados. <br/>La URL de la API de Apprise debe tener la misma ruta de archivos que donde se envían las notificaciones. Por ejemplo: si su API esta en <code>http://192.168.1.1:8337</code> entonces pondría <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Cerciórese de usar el ASIN de la región correcta de Audible, no de Amazon.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Reinicie el servidor tras el guardado para aplicar los cambios de OIDC.",
|
||||
"MessageBackupsDescription": "Los respaldos incluyen: usuarios, el progreso del los usuarios, los detalles de los elementos de la biblioteca, la configuración del servidor y las imágenes en <code>/metadata/items</code> y <code>/metadata/authors</code>. Los Respaldos <strong>NO</strong> incluyen ningún archivo guardado en la carpeta de tu biblioteca.",
|
||||
"MessageBackupsLocationEditNote": "Nota: actualizar la ubicación de la copia de respaldo no moverá ni modificará los respaldos existentes",
|
||||
"MessageBackupsLocationNoEditNote": "Nota: la ubicación de la copia de respaldo se establece a través de una variable de entorno y no se puede cambiar aquí.",
|
||||
"MessageBackupsLocationPathEmpty": "La ruta de la copia de seguridad no puede estar vacía",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Rellenar campos activados con datos de todos los elementos. Los campos con varios valores se combinarán",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "Rellenar campos de detalles de mapa con datos de este elemento",
|
||||
"MessageBatchQuickMatchDescription": "\"Encontrar Rápido\" tratará de agregar portadas y metadatos faltantes de los elementos seleccionados. Habilite la opción de abajo para que \"Encontrar Rápido\" pueda sobrescribir portadas y/o metadatos existentes.",
|
||||
"MessageBookshelfNoCollections": "Aún no ha hecho ninguna colección",
|
||||
"MessageBookshelfNoCollectionsHelp": "Las colecciones son públicas. Cualquiera que pueda acceder a la biblioteca las podrá ver.",
|
||||
"MessageBookshelfNoRSSFeeds": "Ningún suministro RSS está abierto",
|
||||
"MessageBookshelfNoResultsForFilter": "Ningún Resultado para el filtro \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForFilter": "El filtro «{0}: {1}» no produjo ningún resultado",
|
||||
"MessageBookshelfNoResultsForQuery": "No hay resultados para la consulta",
|
||||
"MessageBookshelfNoSeries": "No tiene ninguna serie",
|
||||
"MessageChapterEndIsAfter": "El final del capítulo es después del final de tu audiolibro",
|
||||
@@ -718,30 +726,31 @@
|
||||
"MessageChapterErrorStartGteDuration": "El tiempo de inicio no es válido: debe ser inferior a la duración del audiolibro",
|
||||
"MessageChapterErrorStartLtPrev": "El tiempo de inicio no es válido: debe ser mayor o igual que el tiempo de inicio del capítulo anterior",
|
||||
"MessageChapterStartIsAfter": "El comienzo del capítulo es después del final de su audiolibro",
|
||||
"MessageChaptersNotFound": "Capítulos no encontrados",
|
||||
"MessageCheckingCron": "Revisando cron...",
|
||||
"MessageConfirmCloseFeed": "¿Confirma que quiere cerrar este suministro?",
|
||||
"MessageConfirmDeleteBackup": "¿Está seguro de que desea eliminar el respaldo {0}?",
|
||||
"MessageConfirmDeleteBackup": "¿Confirma que quiere eliminar el respaldo de {0}?",
|
||||
"MessageConfirmDeleteDevice": "¿Confirma que quiere eliminar el lector electrónico «{0}»?",
|
||||
"MessageConfirmDeleteFile": "Esto eliminará el archivo de su sistema de archivos. ¿Está seguro?",
|
||||
"MessageConfirmDeleteFile": "Esto eliminará el archivo del sistema de archivos. ¿Quiere continuar?",
|
||||
"MessageConfirmDeleteLibrary": "¿Confirma que quiere eliminar permanentemente la biblioteca «{0}»?",
|
||||
"MessageConfirmDeleteLibraryItem": "Esto eliminará el elemento de la biblioteca de la base de datos y del sistema de archivos. ¿Confirma que quiere hacerlo?",
|
||||
"MessageConfirmDeleteLibraryItems": "Esto eliminará {0} elementos de la biblioteca de la base de datos y del sistema de archivos. ¿Confirma que quiere hacerlo?",
|
||||
"MessageConfirmDeleteMetadataProvider": "¿Confirma que quiere eliminar el proveedor de metadatos personalizado «{0}»?",
|
||||
"MessageConfirmDeleteNotification": "¿Confirma que quiere eliminar esta notificación?",
|
||||
"MessageConfirmDeleteSession": "¿Está seguro de que desea eliminar esta sesión?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "¿Está seguro de que desea incrustar metadatos en {0} archivos de audio?",
|
||||
"MessageConfirmForceReScan": "¿Está seguro de que desea forzar un re-escaneo?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "¿Está seguro de que desea marcar todos los episodios como terminados?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "¿Está seguro de que desea marcar todos los episodios como no terminados?",
|
||||
"MessageConfirmMarkItemFinished": "¿Estás seguro de que deseas marcar \"{0}\" como terminado?",
|
||||
"MessageConfirmMarkItemNotFinished": "¿Estás seguro de que deseas marcar \"{0}\" como no acabado?",
|
||||
"MessageConfirmMarkSeriesFinished": "¿Está seguro de que desea marcar todos los libros en esta serie como terminados?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "¿Está seguro de que desea marcar todos los libros en esta serie como no terminados?",
|
||||
"MessageConfirmDeleteSession": "¿Confirma que quiere eliminar esta sesión?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "¿Confirma que quiere incrustar metadatos en {0} archivos de audio?",
|
||||
"MessageConfirmForceReScan": "¿Confirma que quiere forzar un reescaneo?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "¿Confirma que quiere marcar todos los episodios como terminados?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "¿Confirma que quiere marcar todos los episodios como no terminados?",
|
||||
"MessageConfirmMarkItemFinished": "¿Confirma que quiere marcar «{0}» como terminado?",
|
||||
"MessageConfirmMarkItemNotFinished": "¿Confirma que quiere marcar «{0}» como no terminado?",
|
||||
"MessageConfirmMarkSeriesFinished": "¿Confirma que quiere marcar todos los libros de esta serie como terminados?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "¿Confirma que quiere marcar todos los libros de esta serie como no terminados?",
|
||||
"MessageConfirmNotificationTestTrigger": "¿Activar esta notificación con datos de prueba?",
|
||||
"MessageConfirmPurgeCache": "Purgar el caché eliminará el directorio completo ubicado en <code>/metadata/cache</code>. <br /><br />¿Está seguro que desea eliminar el directorio del caché?",
|
||||
"MessageConfirmPurgeItemsCache": "Purgar la caché de los elementos eliminará todo el directorio <code>/metadata/cache/items</code>.<br />¿Estás seguro?",
|
||||
"MessageConfirmPurgeCache": "Purgar la antememoria eliminará el directorio completo ubicado en <code>/metadata/cache</code>. <br /><br />¿Confirma que quiere eliminar el directorio de antememoria?",
|
||||
"MessageConfirmPurgeItemsCache": "Purgar la antememoria de elementos eliminará el directorio completo ubicado en <code>/metadata/cache/items</code>.<br />¿Lo confirma?",
|
||||
"MessageConfirmQuickEmbed": "¡Advertencia! La integración rápida no realiza copias de seguridad a ninguno de tus archivos de audio. Asegúrate de haber realizado una copia de los mismos previamente. <br><br>¿Deseas continuar?",
|
||||
"MessageConfirmQuickMatchEpisodes": "El reconocimiento rápido de extensiones sobrescribirá los detalles si se encuentra una coincidencia. Se actualizarán las extensiones no reconocidas. ¿Está seguro?",
|
||||
"MessageConfirmQuickMatchEpisodes": "El reconocimiento rápido de extensiones sobrescribirá los detalles si se encuentra una coincidencia. Se actualizarán las extensiones no reconocidas. ¿Quiere continuar?",
|
||||
"MessageConfirmReScanLibraryItems": "¿Confirma que quiere volver a analizar {0} elementos?",
|
||||
"MessageConfirmRemoveAllChapters": "¿Confirma que quiere quitar todos los capítulos?",
|
||||
"MessageConfirmRemoveAuthor": "¿Confirma que quiere quitar el autor «{0}»?",
|
||||
@@ -749,34 +758,35 @@
|
||||
"MessageConfirmRemoveEpisode": "¿Confirma que quiere quitar el episodio «{0}»?",
|
||||
"MessageConfirmRemoveEpisodes": "¿Confirma que quiere quitar {0} episodios?",
|
||||
"MessageConfirmRemoveListeningSessions": "¿Confirma que quiere quitar {0} sesiones de escucha?",
|
||||
"MessageConfirmRemoveMetadataFiles": "¿Está seguro de que desea eliminar todos los archivos de metadatos.{0} en las carpetas de elementos de su biblioteca?",
|
||||
"MessageConfirmRemoveMetadataFiles": "¿Confirma que quiere quitar todos los archivos metadata.{0} en las carpetas de elementos de su biblioteca?",
|
||||
"MessageConfirmRemoveNarrator": "¿Confirma que quiere quitar el narrador «{0}»?",
|
||||
"MessageConfirmRemovePlaylist": "¿Confirma que quiere quitar la lista de reproducción «{0}»?",
|
||||
"MessageConfirmRenameGenre": "¿Está seguro de que desea renombrar el genero \"{0}\" a \"{1}\" de todos los elementos?",
|
||||
"MessageConfirmRenameGenre": "¿Confirma que quiere cambiar el nombre del género «{0}» a «{1}» en todos los elementos?",
|
||||
"MessageConfirmRenameGenreMergeNote": "Nota: Este género ya existe, por lo que se fusionarán.",
|
||||
"MessageConfirmRenameGenreWarning": "Advertencia! Un genero similar ya existe \"{0}\".",
|
||||
"MessageConfirmRenameTag": "¿Está seguro de que desea renombrar la etiqueta \"{0}\" a \"{1}\" de todos los elementos?",
|
||||
"MessageConfirmRenameTagMergeNote": "Nota: Esta etiqueta ya existe, por lo que se fusionarán.",
|
||||
"MessageConfirmRenameTagWarning": "Advertencia! Una etiqueta similar ya existe \"{0}\".",
|
||||
"MessageConfirmRenameGenreWarning": "¡Atención! Ya existe un género similar con distinta mayusculación, «{0}».",
|
||||
"MessageConfirmRenameTag": "¿Confirma que quiere cambiar el nombre de la etiqueta «{0}» a «{1}» en todos los elementos?",
|
||||
"MessageConfirmRenameTagMergeNote": "Nota: esta etiqueta ya existe, por lo que se fusionarán.",
|
||||
"MessageConfirmRenameTagWarning": "¡Atención! Ya existe una etiqueta similar con distinta mayusculación, «{0}».",
|
||||
"MessageConfirmResetProgress": "¿Confirma que quiere restablecer su progreso?",
|
||||
"MessageConfirmSendEbookToDevice": "¿Confirma que quiere enviar el libro electrónico {0} «{1}» al dispositivo «{2}»?",
|
||||
"MessageConfirmUnlinkOpenId": "¿Estás seguro de que deseas desvincular este usuario de OpenID?",
|
||||
"MessageConfirmUnlinkOpenId": "¿Confirma que quiere desenlazar este usuario de OpenID?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} días escuchados el año pasado",
|
||||
"MessageDownloadingEpisode": "Descargando episodio",
|
||||
"MessageDragFilesIntoTrackOrder": "Arrastra los archivos al orden correcto de las pistas",
|
||||
"MessageEmbedFailed": "¡Error al insertar!",
|
||||
"MessageEmbedFinished": "Incrustación Terminada!",
|
||||
"MessageDragFilesIntoTrackOrder": "Arrastre los archivos al orden correcto de las pistas",
|
||||
"MessageEmbedFailed": "Falló la incrustación.",
|
||||
"MessageEmbedFinished": "Finalizó la incrustación.",
|
||||
"MessageEmbedQueue": "En cola para incrustar metadatos ({0} en cola)",
|
||||
"MessageEpisodesQueuedForDownload": "{0} Episodio(s) en cola para descargar",
|
||||
"MessageEpisodesQueuedForDownload": "{0} episodio(s) en cola para descargar",
|
||||
"MessageEreaderDevices": "Para garantizar la entrega de libros electrónicos, es posible que tenga que agregar la dirección de correo electrónico anterior como remitente válido para cada dispositivo enumerado a continuación.",
|
||||
"MessageFeedURLWillBe": "El URL del suministro será {0}",
|
||||
"MessageFetching": "Buscando...",
|
||||
"MessageFetching": "Recuperando...",
|
||||
"MessageForceReScanDescription": "Escaneará todos los archivos como un nuevo escaneo. Archivos de audio con etiquetas ID3, archivos OPF y archivos de texto serán escaneados como nuevos.",
|
||||
"MessageImportantNotice": "¡Notificación importante!",
|
||||
"MessageInsertChapterBelow": "Insertar Capítulo Abajo",
|
||||
"MessageInsertChapterBelow": "Insertar capítulo debajo",
|
||||
"MessageInvalidAsin": "ASIN no válido",
|
||||
"MessageItemsSelected": "{0} elementos seleccionados",
|
||||
"MessageItemsUpdated": "{0} elementos actualizados",
|
||||
"MessageJoinUsOn": "Únetenos en",
|
||||
"MessageJoinUsOn": "Únase a nosotros en",
|
||||
"MessageLoading": "Cargando...",
|
||||
"MessageLoadingFolders": "Cargando archivos...",
|
||||
"MessageLogsDescription": "Logs son almacenados en <code>/metadata/logs</code> en archivos bajo formato JSON. Logs de fallos son almacenados en <code>/metadata/logs/crash_logs.txt</code>.",
|
||||
@@ -800,19 +810,19 @@
|
||||
"MessageNoDownloadsInProgress": "No hay descargas actualmente en curso",
|
||||
"MessageNoDownloadsQueued": "Sin Lista de Descarga",
|
||||
"MessageNoEpisodeMatchesFound": "No se encontraron episodios que coinciden",
|
||||
"MessageNoEpisodes": "Sin Episodios",
|
||||
"MessageNoFoldersAvailable": "No Hay Carpetas Disponibles",
|
||||
"MessageNoGenres": "Sin Géneros",
|
||||
"MessageNoIssues": "Sin Problemas",
|
||||
"MessageNoItems": "Sin elementos",
|
||||
"MessageNoEpisodes": "Ningún episodio",
|
||||
"MessageNoFoldersAvailable": "Ninguna carpeta disponible",
|
||||
"MessageNoGenres": "Ningún género",
|
||||
"MessageNoIssues": "Ningún número",
|
||||
"MessageNoItems": "Ningún elemento",
|
||||
"MessageNoItemsFound": "Ningún elemento encontrado",
|
||||
"MessageNoListeningSessions": "Ninguna sesión escuchada",
|
||||
"MessageNoListeningSessions": "Ninguna sesión de escucha",
|
||||
"MessageNoLogs": "Ningún registro",
|
||||
"MessageNoMediaProgress": "Multimedia sin Progreso",
|
||||
"MessageNoNotifications": "Ninguna notificación",
|
||||
"MessageNoPodcastFeed": "Podcast no válido: Sin feed",
|
||||
"MessageNoPodcastFeed": "Pódcast no válido: no hay suministro",
|
||||
"MessageNoPodcastsFound": "No se encontró ningún pódcast",
|
||||
"MessageNoResults": "Sin Resultados",
|
||||
"MessageNoResults": "Ningún resultado",
|
||||
"MessageNoSearchResultsFor": "La búsqueda «{0}» no produjo ningún resultado",
|
||||
"MessageNoSeries": "Ninguna serie",
|
||||
"MessageNoTags": "Ninguna etiqueta",
|
||||
@@ -820,13 +830,13 @@
|
||||
"MessageNoUpdatesWereNecessary": "No fue necesario actualizar",
|
||||
"MessageNoUserPlaylists": "No tiene ninguna lista de reproducción",
|
||||
"MessageNoUserPlaylistsHelp": "Las listas de reproducción son privadas. Solo quien las cree podrá verlas.",
|
||||
"MessageNotYetImplemented": "Aun no implementado",
|
||||
"MessageNotYetImplemented": "Aún no implementado",
|
||||
"MessageOpmlPreviewNote": "Nota: Esta es una vista previa del archivo OPML analizado. El título real del podcast se obtendrá del canal RSS.",
|
||||
"MessageOr": "o",
|
||||
"MessagePauseChapter": "Pausar la reproducción del capítulo",
|
||||
"MessagePlayChapter": "Escuchar el comienzo del capítulo",
|
||||
"MessagePlaylistCreateFromCollection": "Crear una lista de reproducción a partir de una colección",
|
||||
"MessagePleaseWait": "Por favor, espera...",
|
||||
"MessagePleaseWait": "Espere…",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "El pódcast no tiene un URL de suministro RSS que pueda usarse para encontrar correspondencias",
|
||||
"MessagePodcastSearchField": "Introduzca el término de búsqueda o el URL del suministro RSS",
|
||||
"MessageQuickEmbedInProgress": "Integración rápida en proceso",
|
||||
@@ -837,11 +847,12 @@
|
||||
"MessageRemoveEpisodes": "Quitar {0} episodio(s)",
|
||||
"MessageRemoveFromPlayerQueue": "Quitar de la cola de reproducción",
|
||||
"MessageRemoveUserWarning": "¿Confirma que quiere eliminar permanentemente el usuario «{0}»?",
|
||||
"MessageReportBugsAndContribute": "Reporte erres, solicite funciones y contribuya en",
|
||||
"MessageResetChaptersConfirm": "¿Está seguro de que desea deshacer los cambios y revertir los capítulos a su estado original?",
|
||||
"MessageRestoreBackupConfirm": "¿Está seguro de que desea para restaurar del respaldo creado en",
|
||||
"MessageReportBugsAndContribute": "Informe de defectos, solicite funciones y contribuya en",
|
||||
"MessageResetChaptersConfirm": "¿Confirma que quiere deshacer los cambios y restablecer los capítulos a su estado original?",
|
||||
"MessageRestoreBackupConfirm": "¿Confirma que quiere restaurar el respaldo creado el",
|
||||
"MessageRestoreBackupWarning": "Restaurar sobrescribirá toda la base de datos localizada en /config y las imágenes de portadas en /metadata/items y /metadata/authors.<br /><br />El respaldo no modifica ningún archivo en las carpetas de su biblioteca. Si ha habilitado la opción del servidor para almacenar portadas y metadata en las carpetas de su biblioteca, esos archivos no se respaldan o sobrescriben.<br /><br />Todos los clientes que usen su servidor se actualizarán automáticamente.",
|
||||
"MessageScheduleLibraryScanNote": "Para la mayoría de los usuarios, se recomienda dejar esta función desactivada y mantener activada la configuración del observador de carpetas. El observador de carpetas detectará automáticamente los cambios en las carpetas de la biblioteca. El observador de carpetas no funciona para todos los sistemas de archivos (como NFS), por lo que se pueden utilizar exploraciones programadas de la biblioteca en su lugar.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Ejecutar cada {0} a las {1}",
|
||||
"MessageSearchResultsFor": "Resultados de la búsqueda de",
|
||||
"MessageSelected": "{0} seleccionado(s)",
|
||||
"MessageServerCouldNotBeReached": "No se pudo establecer la conexión con el servidor",
|
||||
@@ -849,18 +860,18 @@
|
||||
"MessageShareExpirationWillBe": "La caducidad será <strong>{0}</strong>",
|
||||
"MessageShareExpiresIn": "Caduduca en {0}",
|
||||
"MessageShareURLWillBe": "La URL para compartir será <strong> {0} </strong>",
|
||||
"MessageStartPlaybackAtTime": "Iniciar reproducción para \"{0}\" en {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "El archivo de audio \"{0}\" no se puede grabar",
|
||||
"MessageStartPlaybackAtTime": "¿Iniciar reproducción para «{0}» en {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "El archivo de audio «{0}» no se puede grabar",
|
||||
"MessageTaskCanceledByUser": "Tarea cancelada por el usuario",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Descargando el episodio «{0}»",
|
||||
"MessageTaskEmbeddingMetadata": "Inserción de metadatos",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Inserción de metadatos en el audiolibro \"{0}\"",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Incrustando metadatos en el audiolibro «{0}»",
|
||||
"MessageTaskEncodingM4b": "Codificación M4B",
|
||||
"MessageTaskEncodingM4bDescription": "Codificación del audiolibro \"{0}\" en un único archivo m4b",
|
||||
"MessageTaskEncodingM4bDescription": "Codificando el audiolibro «{0}» en un único archivo m4b",
|
||||
"MessageTaskFailed": "Fallida",
|
||||
"MessageTaskFailedToBackupAudioFile": "Error en la copia de seguridad del archivo de audio \"{0}\"",
|
||||
"MessageTaskFailedToBackupAudioFile": "No se pudo respaldar el archivo de audio «{0}»",
|
||||
"MessageTaskFailedToCreateCacheDirectory": "Error al crear el directorio de la caché",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "Error al incrustar metadatos en el archivo \"{0}\"",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "No se pudieron incrustar metadatos en el archivo «{0}»",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Error al fusionar archivos de audio",
|
||||
"MessageTaskFailedToMoveM4bFile": "Error al mover el archivo m4b",
|
||||
"MessageTaskFailedToWriteMetadataFile": "Error al escribir el archivo de metadatos",
|
||||
@@ -870,9 +881,9 @@
|
||||
"MessageTaskOpmlImportDescription": "Creando pódcast a partir de {0} suministros RSS",
|
||||
"MessageTaskOpmlImportFeed": "Feed de importación OPML",
|
||||
"MessageTaskOpmlImportFeedDescription": "Importando el suministro RSS «{0}»",
|
||||
"MessageTaskOpmlImportFeedFailed": "No se puede obtener el podcast",
|
||||
"MessageTaskOpmlImportFeedFailed": "No se pudo obtener el suministro del pódcast",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Creando pódcast «{0}»",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "Podcast ya existe en la ruta",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "El pódcast ya existe en la ruta",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "No se pudo crear el pódcast",
|
||||
"MessageTaskOpmlImportFinished": "Añadido {0} podcasts",
|
||||
"MessageTaskOpmlParseFailed": "No se pudo analizar el archivo OPML",
|
||||
@@ -882,8 +893,8 @@
|
||||
"MessageTaskScanItemsMissing": "Falta {0}",
|
||||
"MessageTaskScanItemsUpdated": "{0} actualizado",
|
||||
"MessageTaskScanNoChangesNeeded": "No se necesitan cambios",
|
||||
"MessageTaskScanningFileChanges": "Escaneando cambios en el archivo en \"{0}\"",
|
||||
"MessageTaskScanningLibrary": "Escaneando la biblioteca \"{0}\"",
|
||||
"MessageTaskScanningFileChanges": "Escaneando cambios en archivos en «{0}»",
|
||||
"MessageTaskScanningLibrary": "Escaneando la biblioteca «{0}»",
|
||||
"MessageTaskTargetDirectoryNotWritable": "El directorio de destino no se puede escribir",
|
||||
"MessageThinking": "Pensando...",
|
||||
"MessageUploaderItemFailed": "Error al Subir",
|
||||
@@ -933,7 +944,7 @@
|
||||
"ToastAppriseUrlRequired": "Debes ingresar una URL de Apprise",
|
||||
"ToastAsinRequired": "Se requiere ASIN",
|
||||
"ToastAuthorImageRemoveSuccess": "Se eliminó la imagen del autor",
|
||||
"ToastAuthorNotFound": "No se encontró el autor \"{0}\"",
|
||||
"ToastAuthorNotFound": "No se encontró el autor «{0}»",
|
||||
"ToastAuthorRemoveSuccess": "Autor eliminado",
|
||||
"ToastAuthorSearchNotFound": "No se encontró al autor",
|
||||
"ToastAuthorUpdateMerged": "Autor combinado",
|
||||
@@ -950,27 +961,28 @@
|
||||
"ToastBackupUploadFailed": "Error al subir el respaldo",
|
||||
"ToastBackupUploadSuccess": "Respaldo cargado",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Detalles aplicados a los elementos",
|
||||
"ToastBatchDeleteFailed": "Error al eliminar por lotes",
|
||||
"ToastBatchDeleteFailed": "Falló la eliminación por lotes",
|
||||
"ToastBatchDeleteSuccess": "Borrado por lotes correcto",
|
||||
"ToastBatchQuickMatchFailed": "¡Error en la sincronización rápida por lotes!",
|
||||
"ToastBatchQuickMatchStarted": "¡Se inició el lote de búsqueda rápida de {0} libros!",
|
||||
"ToastBatchUpdateFailed": "Subida masiva fallida",
|
||||
"ToastBatchUpdateSuccess": "Subida masiva exitosa",
|
||||
"ToastBookmarkCreateFailed": "Error al crear marcador",
|
||||
"ToastBookmarkCreateSuccess": "Marcador Agregado",
|
||||
"ToastBatchUpdateFailed": "Falló la actualización por lotes",
|
||||
"ToastBatchUpdateSuccess": "Se actualizó por lotes correctamente",
|
||||
"ToastBookmarkCreateFailed": "No se pudo crear el marcador",
|
||||
"ToastBookmarkCreateSuccess": "Marcador añadido",
|
||||
"ToastBookmarkRemoveSuccess": "Marcador eliminado",
|
||||
"ToastCachePurgeFailed": "Error al purgar el caché",
|
||||
"ToastCachePurgeSuccess": "Caché purgado de manera exitosa",
|
||||
"ToastCachePurgeFailed": "No se pudo purgar la antememoria",
|
||||
"ToastCachePurgeSuccess": "Se purgó la antememoria correctamente",
|
||||
"ToastChaptersHaveErrors": "Los capítulos tienen errores",
|
||||
"ToastChaptersMustHaveTitles": "Los capítulos tienen que tener un título",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Cantidad de desplazamiento no válida. La hora de inicio del último capítulo se extendería más allá de la duración de este audiolibro.",
|
||||
"ToastChaptersMustHaveTitles": "Los capítulos deben tener título",
|
||||
"ToastChaptersRemoved": "Capítulos eliminados",
|
||||
"ToastChaptersUpdated": "Capítulos actualizados",
|
||||
"ToastCollectionItemsAddFailed": "Artículo(s) añadido(s) a la colección fallido(s)",
|
||||
"ToastCollectionRemoveSuccess": "Colección quitada",
|
||||
"ToastCollectionUpdateSuccess": "Colección actualizada",
|
||||
"ToastCoverUpdateFailed": "Error al actualizar la cubierta",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Fecha y hora inválidas o incompletas",
|
||||
"ToastDeleteFileFailed": "Error el eliminar archivo",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Fecha y hora no válidas o incompletas",
|
||||
"ToastDeleteFileFailed": "Falló la eliminación del archivo",
|
||||
"ToastDeleteFileSuccess": "Archivo eliminado",
|
||||
"ToastDeviceAddFailed": "Error al añadir dispositivo",
|
||||
"ToastDeviceNameAlreadyExists": "Un libro electrónico ya existe con ese nombre",
|
||||
@@ -1040,7 +1052,7 @@
|
||||
"ToastPodcastCreateSuccess": "Se creó el pódcast correctamente",
|
||||
"ToastPodcastGetFeedFailed": "No se puede obtener el podcast",
|
||||
"ToastPodcastNoEpisodesInFeed": "No se han encontrado episodios en el feed del RSS",
|
||||
"ToastPodcastNoRssFeed": "El podcast no tiene feed RSS",
|
||||
"ToastPodcastNoRssFeed": "El pódcast no tiene suministro RSS",
|
||||
"ToastProgressIsNotBeingSynced": "El progreso no se sincroniza, reinicia la reproducción",
|
||||
"ToastProviderCreatedFailed": "Error al añadir el proveedor",
|
||||
"ToastProviderCreatedSuccess": "Nuevo proveedor añadido",
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
"LabelHardDeleteFile": "Kova tiedostojen poisto",
|
||||
"LabelHasEbook": "Sillä on s-kirja",
|
||||
"LabelHasSupplementaryEbook": "Sillä on täydentävän s-kirjan",
|
||||
"LabelHideSubtitles": "Piilota tekstitykset",
|
||||
"LabelHideSubtitles": "Piilota alaotsikot",
|
||||
"LabelHighestPriority": "Korkein etusija",
|
||||
"LabelHost": "Isäntä",
|
||||
"LabelHour": "Tunti",
|
||||
@@ -530,6 +530,7 @@
|
||||
"LabelReleaseDate": "Julkaisupäivä",
|
||||
"LabelRemoveAllMetadataAbs": "Poista kaikki metadata.abs-tiedostot",
|
||||
"LabelRemoveAllMetadataJson": "Poista kaikki metadata.json-tiedostot",
|
||||
"LabelRemoveAudibleBranding": "Poista Audiblen intro ja outro kappaleista",
|
||||
"LabelRemoveCover": "Poista kansikuva",
|
||||
"LabelRemoveMetadataFile": "Poista metatietotiedostot kirjaston kohdekansioista",
|
||||
"LabelRemoveMetadataFileHelp": "Poista kaikki metadata.json- ja metadata.abs-tiedostot {0} kansioistasi.",
|
||||
@@ -577,8 +578,8 @@
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Merkitse mediakohde valmiiksi, kun",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Ohita aiemmat kirjat Jatka sarjassa",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Jatka sarja -kotisivun hyllyssä näkyy ensimmäinen kirja, jota ei ole aloitettu sarjoissa, joissa on vähintään yksi kirja valmiina eikä yhtään kirjaa kesken. Tämän asetuksen ottaminen käyttöön jatkaa sarjaa kauimpana valmistuneesta kirjasta ensimmäisen aloittamattoman kirjan sijaan.",
|
||||
"LabelSettingsParseSubtitles": "Jäsennä tekstitykset",
|
||||
"LabelSettingsParseSubtitlesHelp": "Pura tekstitykset äänikirjojen kansioiden nimistä.<br>Tekstitys on erotettava toisistaan merkillä \"-\"<br>ts. \"Kirjan otsikko - Tekstitys täällä\" on alaotsikko \"Tekstitys täällä\"",
|
||||
"LabelSettingsParseSubtitles": "Jäsennä alaotsikot",
|
||||
"LabelSettingsParseSubtitlesHelp": "Pura alaotsikot äänikirjojen kansioiden nimistä.<br>Tekstitys on erotettava toisistaan merkillä \"-\"<br>ts. \"Kirjan otsikko - Tekstitys täällä\" on alaotsikko \"Tekstitys täällä\"",
|
||||
"LabelSettingsPreferMatchedMetadata": "Pidä mieluummin täsmäävät metatiedot",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Täsmäävät tiedot ohittavat kohteen tiedot käytettäessä Pikatäsmäystä. Oletuksena Pikatäsmäys täyttää vain puuttuvat tiedot.",
|
||||
"LabelSettingsSkipMatchingBooksWithASIN": "Ohita täsmäävät kirjat, joilla on jo ASIN",
|
||||
@@ -598,12 +599,13 @@
|
||||
"LabelShareURL": "Jaa URL-osoite",
|
||||
"LabelShowAll": "Näytä kaikki",
|
||||
"LabelShowSeconds": "Näytä sekunnit",
|
||||
"LabelShowSubtitles": "Näytä tekstitykset",
|
||||
"LabelShowSubtitles": "Näytä alaotsikot",
|
||||
"LabelSize": "Koko",
|
||||
"LabelSleepTimer": "Uniajastin",
|
||||
"LabelSlug": "Slug",
|
||||
"LabelSortAscending": "Nouseva",
|
||||
"LabelSortDescending": "Laskeva",
|
||||
"LabelSortPubDate": "Järjestä julkaisupäivän mukaan",
|
||||
"LabelStart": "Aloita",
|
||||
"LabelStartTime": "Aloitusaika",
|
||||
"LabelStarted": "Aloitettu",
|
||||
@@ -623,7 +625,7 @@
|
||||
"LabelStatsOverallDays": "Päivät kokonaisuudessaan",
|
||||
"LabelStatsOverallHours": "Tunnit kokonaisuudessaan",
|
||||
"LabelStatsWeekListening": "Viikon aikana kuunneltu",
|
||||
"LabelSubtitle": "Tekstitys",
|
||||
"LabelSubtitle": "Alaotsikko",
|
||||
"LabelSupportedFileTypes": "Tuetut tiedostotyypit",
|
||||
"LabelTag": "Tägi",
|
||||
"LabelTags": "Tägit",
|
||||
@@ -722,6 +724,7 @@
|
||||
"MessageChapterErrorStartGteDuration": "Epäkelvollinen aloitusaika; on oltava lyhyempi kuin äänikirjan kesto",
|
||||
"MessageChapterErrorStartLtPrev": "Epäkelvollinen aloitusaika; on oltava suurempi tai yhtä suuri kuin edellisen luvun aloitusaika",
|
||||
"MessageChapterStartIsAfter": "Luku alkaa äänikirjan lopun jälkeen",
|
||||
"MessageChaptersNotFound": "Kappaleita ei löydy",
|
||||
"MessageCheckingCron": "Tarkistetaan cronia...",
|
||||
"MessageConfirmCloseFeed": "Oletko varma, että haluat sulkea tämän syötteen?",
|
||||
"MessageConfirmDeleteBackup": "Oletko varma, että haluat poistaa varmuuskopion {0}:lle?",
|
||||
@@ -778,6 +781,7 @@
|
||||
"MessageForceReScanDescription": "skannaa kaikki tiedostot uudelleen kuten uusi tarkistus. Äänitiedoston ID3-tunnisteet, OPF-tiedostot ja tekstitiedostot skannataan uusina.",
|
||||
"MessageImportantNotice": "Tärkeä huomautus!",
|
||||
"MessageInsertChapterBelow": "Syötä luku alle",
|
||||
"MessageInvalidAsin": "Virheellinen ASIN",
|
||||
"MessageItemsSelected": "{0} kohdetta valittu",
|
||||
"MessageItemsUpdated": "{0} kohdetta päivitetty",
|
||||
"MessageJoinUsOn": "Liity meihin",
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
"LabelCollections": "Collections",
|
||||
"LabelComplete": "Complet",
|
||||
"LabelConfirmPassword": "Confirmer le mot de passe",
|
||||
"LabelContinueListening": "Continuer la lecture",
|
||||
"LabelContinueListening": "Continuer l'écoute",
|
||||
"LabelContinueReading": "Continuer la lecture",
|
||||
"LabelContinueSeries": "Continuer les séries",
|
||||
"LabelCover": "Couverture",
|
||||
@@ -303,7 +303,7 @@
|
||||
"LabelDiscFromFilename": "Depuis le fichier",
|
||||
"LabelDiscFromMetadata": "Depuis les métadonnées",
|
||||
"LabelDiscover": "Découvrir",
|
||||
"LabelDownload": "Téléchargement",
|
||||
"LabelDownload": "Télécharger",
|
||||
"LabelDownloadNEpisodes": "Télécharger {0} épisode(s)",
|
||||
"LabelDownloadable": "Téléchargeable",
|
||||
"LabelDuration": "Durée",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Popis za izvođenje",
|
||||
"HeaderPlaylistItems": "Stavke popisa za izvođenje",
|
||||
"HeaderPodcastsToAdd": "Podcasti za dodavanje",
|
||||
"HeaderPresets": "Predlošci postavki",
|
||||
"HeaderPreviewCover": "Pretpregled naslovnice",
|
||||
"HeaderRSSFeedGeneral": "RSS pojedinosti",
|
||||
"HeaderRSSFeedIsOpen": "RSS izvor je otvoren",
|
||||
@@ -530,6 +531,7 @@
|
||||
"LabelReleaseDate": "Datum izlaska",
|
||||
"LabelRemoveAllMetadataAbs": "Ukloni sve datoteke metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Ukloni sve datoteke metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Ukloni Audibleove najave i odjave iz poglavlja",
|
||||
"LabelRemoveCover": "Ukloni naslovnicu",
|
||||
"LabelRemoveMetadataFile": "Ukloni datoteke s meta-podatcima iz mapa knjižničkih stavki",
|
||||
"LabelRemoveMetadataFileHelp": "Uklanjanje svih datoteka metadata.json i metadata.abs u vaših {0} mapa.",
|
||||
@@ -706,6 +708,7 @@
|
||||
"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>.",
|
||||
"MessageAsinCheck": "Upišite ASIN iz odgovarajuće Audibleove regije, ne s Amazonov.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Ponovno pokrenite poslužitelj da biste primijenili OIDC promjene.",
|
||||
"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.",
|
||||
"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.",
|
||||
@@ -971,6 +974,8 @@
|
||||
"ToastCachePurgeFailed": "Čišćenje predmemorije nije uspjelo",
|
||||
"ToastCachePurgeSuccess": "Predmemorija uspješno očišćena",
|
||||
"ToastChaptersHaveErrors": "Poglavlja imaju pogreške",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Neispravna vrijednost pomaka. Početak zadnjeg poglavlja bio bi nakon duljine trajanja ove zvučne knjige.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Neispravna vrijednost pomaka. Trajanje prvog poglavlja bilo bi nula ili negativno i drugo poglavlje bi ga prepisalo. Povećajte vrijeme početka drugog poglavlja.",
|
||||
"ToastChaptersMustHaveTitles": "Poglavlja moraju imati naslove",
|
||||
"ToastChaptersRemoved": "Poglavlja uklonjena",
|
||||
"ToastChaptersUpdated": "Poglavlja su ažurirana",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"ButtonBatchEditPopulateFromExisting": "Popola da esistente",
|
||||
"ButtonBatchEditPopulateMapDetails": "Inserisci i dettagli della mappa",
|
||||
"ButtonBrowseForFolder": "Per Cartella",
|
||||
"ButtonCancel": "Cancella",
|
||||
"ButtonCancel": "Annulla",
|
||||
"ButtonCancelEncode": "Ferma la codifica",
|
||||
"ButtonChangeRootPassword": "Cambia la Password di root",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "Controlla & scarica i nuovi episodi",
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Playlist",
|
||||
"HeaderPlaylistItems": "Elementi della playlist",
|
||||
"HeaderPodcastsToAdd": "Podcasts da Aggiungere",
|
||||
"HeaderPresets": "Presets",
|
||||
"HeaderPreviewCover": "Anteprima Cover",
|
||||
"HeaderRSSFeedGeneral": "Dettagli RSS",
|
||||
"HeaderRSSFeedIsOpen": "RSS Feed è aperto",
|
||||
@@ -229,6 +230,7 @@
|
||||
"LabelAddedDate": "Aggiunti {0}",
|
||||
"LabelAdminUsersOnly": "Solo utenti Amministratori",
|
||||
"LabelAll": "Tutti",
|
||||
"LabelAllEpisodesDownloaded": "Tutti gli Episodi Scaricati",
|
||||
"LabelAllUsers": "Tutti gli Utenti",
|
||||
"LabelAllUsersExcludingGuests": "Tutti gli Utenti Esclusi gli ospiti",
|
||||
"LabelAllUsersIncludingGuests": "Tutti gli Utenti Inclusi gli ospiti",
|
||||
@@ -252,7 +254,7 @@
|
||||
"LabelBackToUser": "Torna a Utenti",
|
||||
"LabelBackupAudioFiles": "Backup file Audio",
|
||||
"LabelBackupLocation": "Percorso del Backup",
|
||||
"LabelBackupsEnableAutomaticBackups": "Abilita backup Automatico",
|
||||
"LabelBackupsEnableAutomaticBackups": "Backup Automatico",
|
||||
"LabelBackupsEnableAutomaticBackupsHelp": "I Backup saranno salvati in /metadata/backups",
|
||||
"LabelBackupsMaxBackupSize": "Dimensione massima backup (in GB) (0 Illimitato)",
|
||||
"LabelBackupsMaxBackupSizeHelp": "Come protezione contro gli errori di config, i backup falliranno se superano la dimensione configurata.",
|
||||
@@ -279,12 +281,12 @@
|
||||
"LabelCollections": "Raccolte",
|
||||
"LabelComplete": "Completo",
|
||||
"LabelConfirmPassword": "Conferma Password",
|
||||
"LabelContinueListening": "Continua ad Ascoltare",
|
||||
"LabelContinueReading": "Continua la Lettura",
|
||||
"LabelContinueListening": "Continua l'ascolto",
|
||||
"LabelContinueReading": "Continua la lettura",
|
||||
"LabelContinueSeries": "Continua serie",
|
||||
"LabelCover": "Copertina",
|
||||
"LabelCoverImageURL": "Indirizzo della cover URL",
|
||||
"LabelCoverProvider": "Cover Provider",
|
||||
"LabelCoverProvider": "Cover Sorgente",
|
||||
"LabelCreatedAt": "Creato A",
|
||||
"LabelCronExpression": "Espressione Cron",
|
||||
"LabelCurrent": "Attuale",
|
||||
@@ -529,6 +531,7 @@
|
||||
"LabelReleaseDate": "Data Release",
|
||||
"LabelRemoveAllMetadataAbs": "Remuovi tutti i metadata.abs files",
|
||||
"LabelRemoveAllMetadataJson": "Rimuovi tutti i metadata.json files",
|
||||
"LabelRemoveAudibleBranding": "Rimuovi l'intro e il termine Audible dai capitoli",
|
||||
"LabelRemoveCover": "Rimuovi cover",
|
||||
"LabelRemoveMetadataFile": "Rimuovi i file metadata nella cartella della libreria",
|
||||
"LabelRemoveMetadataFileHelp": "Rimuovi tutti i file metadata.json e i file metadata.abs nelle tue {0} cartelle.",
|
||||
@@ -558,6 +561,8 @@
|
||||
"LabelSettingsBookshelfViewHelp": "Design con scaffali in legno",
|
||||
"LabelSettingsChromecastSupport": "Supporto a Chromecast",
|
||||
"LabelSettingsDateFormat": "Formato Data",
|
||||
"LabelSettingsEnableWatcher": "Scansiona le librerie Automaticamente per trovare modifiche",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Scansiona la libreria Automaticamente per trovare modifiche",
|
||||
"LabelSettingsEnableWatcherHelp": "Abilita l'aggiunta/aggiornamento automatico degli elementi quando vengono rilevate modifiche ai file. *Richiede il riavvio del Server",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Consenti contenuti con script negli epub",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Consenti ai file epub di eseguire script. Si consiglia di mantenere questa impostazione disabilitata a meno che non si ritenga attendibile l'origine dei file epub.",
|
||||
@@ -601,6 +606,7 @@
|
||||
"LabelSlug": "Lento",
|
||||
"LabelSortAscending": "Crescente",
|
||||
"LabelSortDescending": "Discendente",
|
||||
"LabelSortPubDate": "Ordina per data di pubblicazione",
|
||||
"LabelStart": "Inizo",
|
||||
"LabelStartTime": "Tempo di inizio",
|
||||
"LabelStarted": "Iniziato",
|
||||
@@ -672,7 +678,7 @@
|
||||
"LabelUpdateDetailsHelp": "Consenti la sovrascrittura dei dettagli esistenti per i libri selezionati quando viene individuata una corrispondenza",
|
||||
"LabelUpdatedAt": "Aggiornato alle",
|
||||
"LabelUploaderDragAndDrop": "Drag & drop file o Cartelle",
|
||||
"LabelUploaderDragAndDropFilesOnly": "Drag & drop files",
|
||||
"LabelUploaderDragAndDropFilesOnly": "Drag & drop file",
|
||||
"LabelUploaderDropFiles": "Elimina file",
|
||||
"LabelUploaderItemFetchMetadataHelp": "Recupera automaticamente titolo, autore e serie",
|
||||
"LabelUseAdvancedOptions": "Usa le opzioni avanzate",
|
||||
@@ -701,6 +707,7 @@
|
||||
"LabelYourProgress": "Completato al",
|
||||
"MessageAddToPlayerQueue": "Aggiungi alla coda di riproduzione",
|
||||
"MessageAppriseDescription": "Per utilizzare questa funzione è necessario disporre di un'istanza di <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> in esecuzione o un'API che gestirà quelle stesse richieste. <br />L'API Url dovrebbe essere il percorso URL completo per inviare la notifica, ad esempio se la tua istanza API è servita cosi .<code>http://192.168.1.1:8337</code> Allora dovrai mettere <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Assicurati di utilizzare l'ASIN della regione Audible corretta, non di Amazon.",
|
||||
"MessageBackupsDescription": "I backup includono utenti, progressi degli utenti, dettagli sugli elementi della libreria, impostazioni del server e immagini archiviate in <code>/metadata/items</code> & <code>/metadata/authors</code>. I backup non includono i file archiviati nelle cartelle della libreria.",
|
||||
"MessageBackupsLocationEditNote": "Nota: l'aggiornamento della posizione di backup non sposterà o modificherà i backup esistenti",
|
||||
"MessageBackupsLocationNoEditNote": "Nota: la posizione del backup viene impostata tramite una variabile di ambiente e non può essere modificata qui.",
|
||||
@@ -719,6 +726,7 @@
|
||||
"MessageChapterErrorStartGteDuration": "L'ora di inizio non valida deve essere inferiore alla durata dell'audiolibro",
|
||||
"MessageChapterErrorStartLtPrev": "L'ora di inizio non valida deve essere maggiore o uguale all'ora di inizio del capitolo precedente",
|
||||
"MessageChapterStartIsAfter": "L'inizio del capitolo è dopo la fine del tuo audiolibro",
|
||||
"MessageChaptersNotFound": "Capitoli non trovati",
|
||||
"MessageCheckingCron": "Controllo cron...",
|
||||
"MessageConfirmCloseFeed": "Sei sicuro di voler chiudere questo feed?",
|
||||
"MessageConfirmDeleteBackup": "Sei sicuro di voler eliminare il backup {0}?",
|
||||
@@ -775,8 +783,9 @@
|
||||
"MessageForceReScanDescription": "eseguirà nuovamente la scansione di tutti i file come una nuova scansione. I tag ID3 dei file audio, i file OPF e i file di testo verranno scansionati come nuovi.",
|
||||
"MessageImportantNotice": "Avviso Importante!",
|
||||
"MessageInsertChapterBelow": "Inserisci capitolo sotto",
|
||||
"MessageItemsSelected": "{0} oggetti Selezionati",
|
||||
"MessageItemsUpdated": "{0} Oggetti aggiornati",
|
||||
"MessageInvalidAsin": "ASIN non Valido",
|
||||
"MessageItemsSelected": "{0} oggetti selezionati",
|
||||
"MessageItemsUpdated": "{0} oggetti aggiornati",
|
||||
"MessageJoinUsOn": "Unisciti a noi su",
|
||||
"MessageLoading": "Caricamento…",
|
||||
"MessageLoadingFolders": "Caricamento Cartelle...",
|
||||
@@ -808,7 +817,7 @@
|
||||
"MessageNoItems": "Nessun oggetto",
|
||||
"MessageNoItemsFound": "Nessun oggetto trovato",
|
||||
"MessageNoListeningSessions": "Nessuna sessione di ascolto",
|
||||
"MessageNoLogs": "Nessun Logs",
|
||||
"MessageNoLogs": "Nessun Log",
|
||||
"MessageNoMediaProgress": "Nessun progresso multimediale",
|
||||
"MessageNoNotifications": "Nessuna notifica",
|
||||
"MessageNoPodcastFeed": "Podcast non valido: nessun feed",
|
||||
@@ -843,6 +852,7 @@
|
||||
"MessageRestoreBackupConfirm": "Sei sicuro di voler ripristinare il backup creato su",
|
||||
"MessageRestoreBackupWarning": "Il ripristino di un backup sovrascriverà l'intero database situato in /config e sovrascrive le immagini in /metadata/items & /metadata/authors.<br /><br />I backup non modificano alcun file nelle cartelle della libreria. Se hai abilitato le impostazioni del server per archiviare copertine e metadati nelle cartelle della libreria, questi non vengono sottoposti a backup o sovrascritti.<br /><br />Tutti i client che utilizzano il tuo server verranno aggiornati automaticamente.",
|
||||
"MessageScheduleLibraryScanNote": "Per la maggior parte degli utenti, si consiglia di lasciare questa funzionalità disabilitata e di mantenere abilitata l'impostazione di folder watcher. Il folder watcher rileverà automaticamente le modifiche nelle cartelle della libreria. Il folder watcher non funziona per ogni file system (come NFS), quindi è possibile utilizzare le scansioni pianificate della libreria.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Esegui ogni {0} alle {1}",
|
||||
"MessageSearchResultsFor": "cerca risultati per",
|
||||
"MessageSelected": "{0} selezionati",
|
||||
"MessageServerCouldNotBeReached": "Impossibile raggiungere il server",
|
||||
@@ -950,6 +960,7 @@
|
||||
"ToastBackupRestoreFailed": "Ripristino fallito",
|
||||
"ToastBackupUploadFailed": "Caricamento backup fallito",
|
||||
"ToastBackupUploadSuccess": "Backup caricato",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Dettagli applicati agli articoli",
|
||||
"ToastBatchDeleteFailed": "Eliminazione batch non riuscita",
|
||||
"ToastBatchDeleteSuccess": "Eliminazione batch riuscita",
|
||||
"ToastBatchQuickMatchFailed": "Batch Quick Match non riuscito!",
|
||||
@@ -962,6 +973,8 @@
|
||||
"ToastCachePurgeFailed": "Impossibile eliminare la cache",
|
||||
"ToastCachePurgeSuccess": "Cache eliminata correttamente",
|
||||
"ToastChaptersHaveErrors": "I capitoli contengono errori",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Quantità di spostamento non valida. L'orario di inizio dell'ultimo capitolo si estenderebbe oltre la durata di questo audiolibro.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Quantità di spostamento non valida. Il primo capitolo avrebbe una lunghezza pari a zero o negativa e verrebbe sovrascritto dal secondo capitolo. Aumentare la durata iniziale del secondo capitolo.",
|
||||
"ToastChaptersMustHaveTitles": "I capitoli devono avere titoli",
|
||||
"ToastChaptersRemoved": "Capitoli rimossi",
|
||||
"ToastChaptersUpdated": "Capitoli aggiornati",
|
||||
@@ -1062,6 +1075,7 @@
|
||||
"ToastSelectAtLeastOneUser": "Seleziona almeno un utente",
|
||||
"ToastSendEbookToDeviceFailed": "Impossibile inviare il libro al dispositivo",
|
||||
"ToastSendEbookToDeviceSuccess": "Libro inviato al dispositivo «{0}»",
|
||||
"ToastSeriesSubmitFailedSameName": "Non è possibile aggiungere due serie con lo stesso nome",
|
||||
"ToastSeriesUpdateFailed": "Aggiornamento Serie Fallito",
|
||||
"ToastSeriesUpdateSuccess": "Serie Aggiornate",
|
||||
"ToastServerSettingsUpdateSuccess": "Impostazioni del server aggiornate",
|
||||
@@ -1080,6 +1094,8 @@
|
||||
"ToastUnknownError": "Errore sconosciuto",
|
||||
"ToastUnlinkOpenIdFailed": "Impossibile scollegare l'utente da OpenID",
|
||||
"ToastUnlinkOpenIdSuccess": "Utente scollegato da OpenID",
|
||||
"ToastUploaderFilepathExistsError": "Il percorso file \"{0}\" esiste già sul server",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "L'elemento \"{0}\" utilizza una sottodirectory del percorso di caricamento.",
|
||||
"ToastUserDeleteFailed": "Errore eliminazione utente",
|
||||
"ToastUserDeleteSuccess": "Utente eliminato",
|
||||
"ToastUserPasswordChangeSuccess": "Password modificata con successo",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Плейлист",
|
||||
"HeaderPlaylistItems": "Элементы списка воспроизведения",
|
||||
"HeaderPodcastsToAdd": "Подкасты для добавления",
|
||||
"HeaderPresets": "Пресеты",
|
||||
"HeaderPreviewCover": "Предпросмотр обложки",
|
||||
"HeaderRSSFeedGeneral": "Сведения о RSS",
|
||||
"HeaderRSSFeedIsOpen": "RSS-канал открыт",
|
||||
@@ -219,7 +220,7 @@
|
||||
"LabelAccountTypeAdmin": "Администратор",
|
||||
"LabelAccountTypeGuest": "Гость",
|
||||
"LabelAccountTypeUser": "Пользователь",
|
||||
"LabelActivities": "Мероприятия",
|
||||
"LabelActivities": "События",
|
||||
"LabelActivity": "Активность",
|
||||
"LabelAddToCollection": "Добавить в коллекцию",
|
||||
"LabelAddToCollectionBatch": "Добавить {0} книг в коллекцию",
|
||||
@@ -306,7 +307,7 @@
|
||||
"LabelDownload": "Скачать",
|
||||
"LabelDownloadNEpisodes": "Скачать {0} эпизодов",
|
||||
"LabelDownloadable": "Загружаемый",
|
||||
"LabelDuration": "Продолжительность",
|
||||
"LabelDuration": "Длительность",
|
||||
"LabelDurationComparisonExactMatch": "(точное совпадение)",
|
||||
"LabelDurationComparisonLonger": "({0} дольше)",
|
||||
"LabelDurationComparisonShorter": "({0} короче)",
|
||||
@@ -530,6 +531,7 @@
|
||||
"LabelReleaseDate": "Дата выхода",
|
||||
"LabelRemoveAllMetadataAbs": "Удалите все файлы metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Удалите все файлы metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Удалить вступление и концовку Audible из глав",
|
||||
"LabelRemoveCover": "Удалить обложку",
|
||||
"LabelRemoveMetadataFile": "Удаление файлов метаданных в папках элементов библиотеки",
|
||||
"LabelRemoveMetadataFileHelp": "Удалите все файлы metadata.json и metadata.abs из ваших папок {0}.",
|
||||
@@ -706,6 +708,7 @@
|
||||
"MessageAddToPlayerQueue": "Добавить в очередь проигрывателя",
|
||||
"MessageAppriseDescription": "Для использования этой функции необходимо иметь запущенный экземпляр <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> или api которое обрабатывает те же самые запросы. <br />URL-адрес API Apprise должен быть полным URL-адресом для отправки уведомления, т.е., если API запущено по адресу <code>http://192.168.1.1:8337</code> тогда нужно указать <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Убедитесь, что вы используете ASIN из правильной региональной зоны Audible, а не из Amazon.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Перезапустите ваш сервер после сохранения для применения изменений в OIDC.",
|
||||
"MessageBackupsDescription": "Бэкап включает пользователей, прогресс пользователей, данные элементов библиотеки, настройки сервера и изображения хранящиеся в <code>/metadata/items</code> и <code>/metadata/authors</code>. Бэкапы <strong>НЕ</strong> сохраняют файлы из папок библиотек.",
|
||||
"MessageBackupsLocationEditNote": "Примечание: Обновление местоположения резервной копии не приведет к перемещению или изменению существующих резервных копий",
|
||||
"MessageBackupsLocationNoEditNote": "Примечание: Местоположение резервного копирования задается с помощью переменной среды и не может быть изменено здесь.",
|
||||
@@ -971,6 +974,8 @@
|
||||
"ToastCachePurgeFailed": "Не удалось очистить кэш",
|
||||
"ToastCachePurgeSuccess": "Кэш успешно очищен",
|
||||
"ToastChaptersHaveErrors": "Главы имеют ошибки",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Некорректное значение сдвига. Начало последней главы будет превышать продолжительность этой аудиокниги.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Некорректное значение сдвига. Первая глава будет иметь нулевую или отрицательную длину и будет перезаписана второй главой. Увеличьте начальную продолжительность второй главы.",
|
||||
"ToastChaptersMustHaveTitles": "Главы должны содержать названия",
|
||||
"ToastChaptersRemoved": "Удалены главы",
|
||||
"ToastChaptersUpdated": "Обновленные главы",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"ButtonClearFilter": "Zrušiť filter",
|
||||
"ButtonCloseFeed": "Zatvoriť zdroj",
|
||||
"ButtonCloseSession": "Ukončiť otvorené pripojenie",
|
||||
"ButtonCollections": "Zbierky",
|
||||
"ButtonCollections": "Kolekcie",
|
||||
"ButtonConfigureScanner": "Nastaviť skener",
|
||||
"ButtonCreate": "Vytvoriť",
|
||||
"ButtonCreateBackup": "Vytvoriť zálohu",
|
||||
@@ -56,7 +56,7 @@
|
||||
"ButtonOk": "OK",
|
||||
"ButtonOpenFeed": "Otvoriť zdroj",
|
||||
"ButtonOpenManager": "Otvoriť správcu",
|
||||
"ButtonPause": "Zastaviť",
|
||||
"ButtonPause": "Pozastaviť",
|
||||
"ButtonPlay": "Prehrať",
|
||||
"ButtonPlayAll": "Prehrať všetko",
|
||||
"ButtonPlaying": "Prehráva sa",
|
||||
@@ -92,7 +92,7 @@
|
||||
"ButtonScanLibrary": "Skenovať knižnicu",
|
||||
"ButtonScrollLeft": "Doľava",
|
||||
"ButtonScrollRight": "Doprava",
|
||||
"ButtonSearch": "Vyhľadávanie",
|
||||
"ButtonSearch": "Vyhľadať",
|
||||
"ButtonSelectFolderPath": "Vybrať umiestnenie priečinku",
|
||||
"ButtonSeries": "Série",
|
||||
"ButtonSetChaptersFromTracks": "Nastaviť kapitoly podľa stôp",
|
||||
@@ -104,7 +104,7 @@
|
||||
"ButtonStats": "Štatistiky",
|
||||
"ButtonSubmit": "Odoslať",
|
||||
"ButtonTest": "Test",
|
||||
"ButtonUnlinkOpenId": "Odhlásiť OpenID",
|
||||
"ButtonUnlinkOpenId": "Zrušiť prepojenie OpenID",
|
||||
"ButtonUpload": "Nahrať",
|
||||
"ButtonUploadBackup": "Nahrať zálohu",
|
||||
"ButtonUploadCover": "Nahrať prebal",
|
||||
@@ -127,7 +127,7 @@
|
||||
"HeaderChangePassword": "Zmeniť heslo",
|
||||
"HeaderChapters": "Kapitoly",
|
||||
"HeaderChooseAFolder": "Vybrať priečinok",
|
||||
"HeaderCollection": "Zbierka",
|
||||
"HeaderCollection": "Zbierky",
|
||||
"HeaderCollectionItems": "Položky zbierky",
|
||||
"HeaderCover": "Prebal",
|
||||
"HeaderCurrentDownloads": "Aktuálne sťahovanie",
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Playlist",
|
||||
"HeaderPlaylistItems": "Položky playlistu",
|
||||
"HeaderPodcastsToAdd": "Podcasty na pridanie",
|
||||
"HeaderPresets": "Predvolené",
|
||||
"HeaderPreviewCover": "Ukážka prebalu",
|
||||
"HeaderRSSFeedGeneral": "Detaily RSS",
|
||||
"HeaderRSSFeedIsOpen": "RSS zdroj je otvorený",
|
||||
@@ -210,7 +211,7 @@
|
||||
"HeaderUpdateLibrary": "Aktualizovať knižnicu",
|
||||
"HeaderUsers": "Užívatelia",
|
||||
"HeaderYearReview": "Prehľad roka {0}",
|
||||
"HeaderYourStats": "Tvoje štatistiky",
|
||||
"HeaderYourStats": "Vaše štatistiky",
|
||||
"LabelAbridged": "Skrátená verzia",
|
||||
"LabelAbridgedChecked": "Skrátená verzia (zaškrtnuté)",
|
||||
"LabelAbridgedUnchecked": "Neskrátená verzia (nezaškrtnuté)",
|
||||
@@ -221,7 +222,7 @@
|
||||
"LabelAccountTypeUser": "Užívateľ",
|
||||
"LabelActivities": "Aktivity",
|
||||
"LabelActivity": "Aktivita",
|
||||
"LabelAddToCollection": "Pridať do kolekcie",
|
||||
"LabelAddToCollection": "Pridať do zbierky",
|
||||
"LabelAddToCollectionBatch": "Pridať {0} kníh do kolekcie",
|
||||
"LabelAddToPlaylist": "Pridať do playlistu",
|
||||
"LabelAddToPlaylistBatch": "Pridať {0} položie do playlistu",
|
||||
@@ -240,7 +241,7 @@
|
||||
"LabelAudioChannels": "Počet kanálov audio stopy (1 alebo 2)",
|
||||
"LabelAudioCodec": "Kodek audio stopy",
|
||||
"LabelAuthor": "Autor",
|
||||
"LabelAuthorFirstLast": "Autor (Meno, Priezvisko)",
|
||||
"LabelAuthorFirstLast": "Autor (Meno Priezvisko)",
|
||||
"LabelAuthorLastFirst": "Autor (Priezvisko, Meno)",
|
||||
"LabelAuthors": "Autori",
|
||||
"LabelAutoDownloadEpisodes": "Automaticky sťahovať epizódy",
|
||||
@@ -469,7 +470,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",
|
||||
"LabelNumberOfEpisodes": "# epizód",
|
||||
"LabelNumberOfEpisodes": "# z epizód",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Názov OpenID predpokladá prítomnosť pokročilých povolení pre užívateľské akcie v rámci aplikácie, ktoré sú aplikovateľné na ne-administrátorské role (<b>ak sú nakonfigurované</b>). Ak potvrdenie takýchto pokročilých povolení nie je v odozve prítomné, prístup do ABS bude automaticky zamietnutý. Ak v odozve chýba len niektoré z očakávaných nastavení, tak bude jeho hodnota automaticky nastavená na <code>false</code>. Uistite sa prosím, že forma odozvy poskytovateľa identity má nasledovnú štruktúru:",
|
||||
"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ľ'.",
|
||||
"LabelOpenIDGroupClaimDescription": "Pri názve požiadavky OpenID sa predpokladá, že obsahuje zoznam užívateľských skupín. Bežne označovaný ako <code>groups</code>. <b>Ak je správne nakonfigurovaný</b>, aplikácia automaticky pridelí role podľa príslušnosti k užívateľským skupinám pod podmienkou, že sú tieto skupiny v požiadavke nazvané (bez ohľadu na veľkosť písmen) ako 'admin', 'user' alebo 'guest'. Požiadavka musí obsahovať zoznam skupín a ak užívateľ patrí do viacerých skupín, aplikácia mu priradí rolu, ktorá zodpovedá skupine s najvyššími prístupovými právami. Ak sa žiadna z poskytnutých skupín nezhoduje, prístup bude zamietnutý.",
|
||||
@@ -499,12 +500,12 @@
|
||||
"LabelPodcasts": "Podcasty",
|
||||
"LabelPort": "Prístav",
|
||||
"LabelPrefixesToIgnore": "Ignorované predpony (bez ohľadu na veľkosť písmen)",
|
||||
"LabelPreventIndexing": "Zabráňte indexovaniu Vášho zdroja službami iTunes a Google podcasts directories",
|
||||
"LabelPreventIndexing": "Zabráni indexácii vašich zdrojov službami iTunes a Google podcast directories",
|
||||
"LabelPrimaryEbook": "Primárny e-book",
|
||||
"LabelProgress": "Pokrok",
|
||||
"LabelProgress": "Stav",
|
||||
"LabelProvider": "Poskytovateľ",
|
||||
"LabelProviderAuthorizationValue": "Obsah hlavičky autorizácie",
|
||||
"LabelPubDate": "Dátum vydania",
|
||||
"LabelPubDate": "Dátum publikovania",
|
||||
"LabelPublishYear": "Rok vydania",
|
||||
"LabelPublishedDate": "Vydané {0}",
|
||||
"LabelPublishedDecade": "Dekáda vydania",
|
||||
@@ -519,7 +520,7 @@
|
||||
"LabelRSSFeedURL": "URL RSS zdroja",
|
||||
"LabelRandomly": "Náhodne",
|
||||
"LabelReAddSeriesToContinueListening": "Znova pridať série do pokračujúceho počúvania",
|
||||
"LabelRead": "Čítať",
|
||||
"LabelRead": "Načítať",
|
||||
"LabelReadAgain": "Čítať znova",
|
||||
"LabelReadEbookWithoutProgress": "Čítať e-knihu bez sledovania pokroku",
|
||||
"LabelRecentSeries": "Posledné série",
|
||||
@@ -546,7 +547,7 @@
|
||||
"LabelSendEbookToDevice": "Poslať e-knihu do...",
|
||||
"LabelSequence": "Postupnosť",
|
||||
"LabelSerial": "Na pokračovanie",
|
||||
"LabelSeries": "Séria",
|
||||
"LabelSeries": "Série",
|
||||
"LabelSeriesName": "Názov série",
|
||||
"LabelSeriesProgress": "Pokrok série",
|
||||
"LabelServerLogLevel": "Úroveň logovania servera",
|
||||
@@ -576,7 +577,7 @@
|
||||
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Zostávajúci čas je menší ako (sekúnd)",
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Označiť položku média ako dokončenú",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Preskočiť predchádzajúce knihy v pokračujúcej sérii",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Polička pokračujúcich sérií na domácej stránke zobrazuje prvú nezačatú knihu série, ktorá má ukončenú aspoň jednu z kníh série a žiadne započaté knihy. Povolením tohto nastavenia bude pokračujúca séria začínať poslednou ukončenou knihou miesto prvej nepočúvanej.",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Polička pokračujúcich sérií na domácej stránke zobrazuje prvú nezačatú knihu série, ktorá má dokončenú aspoň jednu z kníh série a žiadne započaté knihy. Povolením tohto nastavenia bude pokračujúca séria začínať poslednou ukončenou knihou miesto prvej nepočúvanej.",
|
||||
"LabelSettingsParseSubtitles": "Parsovať podtituly",
|
||||
"LabelSettingsParseSubtitlesHelp": "Extrahovať podtituly z názvov priečinkov audiokníh.<br>Podtitul musí byť oddelený \" - \"<br>tj. \"Názov knihy - Podtitul knihy\" má podtitul \"Podtitul knihy\"",
|
||||
"LabelSettingsPreferMatchedMetadata": "Preferovať vyhľadané metadáta",
|
||||
@@ -605,7 +606,7 @@
|
||||
"LabelSortAscending": "Vzostupne",
|
||||
"LabelSortDescending": "Zostupne",
|
||||
"LabelSortPubDate": "Zoradiť podľa dátumu vydania",
|
||||
"LabelStart": "Začiatok",
|
||||
"LabelStart": "Spustiť",
|
||||
"LabelStartTime": "Čas spustenia",
|
||||
"LabelStarted": "Začaté",
|
||||
"LabelStartedAt": "Začaté v",
|
||||
@@ -613,7 +614,7 @@
|
||||
"LabelStatsAuthors": "Autori",
|
||||
"LabelStatsBestDay": "Najlepší deň",
|
||||
"LabelStatsDailyAverage": "Denný priemer",
|
||||
"LabelStatsDays": "Dni",
|
||||
"LabelStatsDays": "Dní",
|
||||
"LabelStatsDaysListened": "Dní počúvania",
|
||||
"LabelStatsHours": "Hodiny",
|
||||
"LabelStatsInARow": "v rade",
|
||||
@@ -632,9 +633,9 @@
|
||||
"LabelTagsNotAccessibleToUser": "Štítky nedostupné užívateľovi",
|
||||
"LabelTasks": "Bežiace úlohy",
|
||||
"LabelTextEditorBulletedList": "Zoznam s odrážkami",
|
||||
"LabelTextEditorLink": "Pripojiť",
|
||||
"LabelTextEditorLink": "Prepojiť",
|
||||
"LabelTextEditorNumberedList": "Očíslovaný zoznam",
|
||||
"LabelTextEditorUnlink": "Odpojiť",
|
||||
"LabelTextEditorUnlink": "Zrušiť prepojenie",
|
||||
"LabelTheme": "Téma",
|
||||
"LabelThemeDark": "Tmavá",
|
||||
"LabelThemeLight": "Svetlá",
|
||||
@@ -646,7 +647,7 @@
|
||||
"LabelTimeLeft": "{0} ponechaných",
|
||||
"LabelTimeListened": "Čas počúvania",
|
||||
"LabelTimeListenedToday": "Dnešný čas počúvania",
|
||||
"LabelTimeRemaining": "{0} zostávajúcich",
|
||||
"LabelTimeRemaining": "Zostáva {0}",
|
||||
"LabelTimeToShift": "Čas posunutia v sekundách",
|
||||
"LabelTitle": "Názov",
|
||||
"LabelToolsEmbedMetadata": "Vlož metadáta",
|
||||
@@ -683,7 +684,7 @@
|
||||
"LabelUseChapterTrack": "Použiť stopu kapitoly",
|
||||
"LabelUseFullTrack": "Použiť celú stopu",
|
||||
"LabelUseZeroForUnlimited": "Použito 0 pre neobmedzené",
|
||||
"LabelUser": "Užívateľ",
|
||||
"LabelUser": "Používateľ",
|
||||
"LabelUsername": "Prihlasovacie meno",
|
||||
"LabelValue": "Hodnota",
|
||||
"LabelVersion": "Verzia",
|
||||
@@ -702,9 +703,10 @@
|
||||
"LabelYourAudiobookDuration": "Dĺžka Vašej audioknihy",
|
||||
"LabelYourBookmarks": "Vaše záložky",
|
||||
"LabelYourPlaylists": "Vaše playlisty",
|
||||
"LabelYourProgress": "Váš pokrok",
|
||||
"LabelYourProgress": "Váš aktuálny stav",
|
||||
"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.",
|
||||
"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.",
|
||||
@@ -723,8 +725,378 @@
|
||||
"MessageChapterErrorStartGteDuration": "Neplatný čas začiatku musí byť menší ako celkové trvanie audioknihy",
|
||||
"MessageChapterErrorStartLtPrev": "Neplatný čas začiatku musí byť väčší alebo rovný času začiatku predchádzajúcej kapitoly",
|
||||
"MessageChapterStartIsAfter": "Začiatok kapitoly je až za koncom vašej audioknihy",
|
||||
"MessageChaptersNotFound": "Kapitoly nenájdené",
|
||||
"MessageCheckingCron": "Kontrola cron-u...",
|
||||
"MessageConfirmCloseFeed": "Ste si istý, že chcete zavrieť tento zdroj?",
|
||||
"MessageConfirmDeleteBackup": "Ste si istý, že chcete zmazať zálohu {0}?",
|
||||
"MessageConfirmDeleteDevice": "Ste si istý, že chcete zmazať zariadenie čítačky e-kníh \"{0}\"?"
|
||||
"MessageConfirmDeleteDevice": "Ste si istý, že chcete zmazať zariadenie čítačky e-kníh \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Týmto odstránite súbor z vášho súborového systému. Ste si istý?",
|
||||
"MessageConfirmDeleteLibrary": "Ste si istý, že chcete natrvalo odstrániť knižnicu \"{0}\"?",
|
||||
"MessageConfirmDeleteLibraryItem": "Týmto odstránite položku knižnice z databázy aj vášho súborového systému. Ste si istý?",
|
||||
"MessageConfirmDeleteLibraryItems": "Týmto odstránite {0} položiek knižnice z databázy a vášho súborového systému. Ste si istý?",
|
||||
"MessageConfirmDeleteMetadataProvider": "Ste si istý, že chcete odstrániť poskytovateľa metadát \"{0}\"?",
|
||||
"MessageConfirmDeleteNotification": "Ste si istý, že chcete odstrániť túto notifikáciu?",
|
||||
"MessageConfirmDeleteSession": "Ste si istý, že chcete zmazať túto reláciu?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Ste si istý, že chcete vložiť metadáta do {0} zvukových súborov?",
|
||||
"MessageConfirmForceReScan": "Ste si istý, že chcete spustiť vynútený re-sken?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Chcete označiť všetky epizódy ako dokončené?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Checte označiť všetky epizódy ako nedokončené?",
|
||||
"MessageConfirmMarkItemFinished": "Chcete označiť \"{0}\" ako dokončené?",
|
||||
"MessageConfirmMarkItemNotFinished": "Chcete označiť \"{0}\" ako nedokončené?",
|
||||
"MessageConfirmMarkSeriesFinished": "Ste si istý, že chcete označiť všetky knihy v tejto sérii ako dokončené?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Ste si istý, že chcete označiť všetky knihy v tejto sérii ako nedokončené?",
|
||||
"MessageConfirmNotificationTestTrigger": "Zapnúť túto notifikáciu pre testovacie dáta?",
|
||||
"MessageConfirmPurgeCache": "Vymazanie vyrovnávacej pamäte kompletne odstráni priečinok <code>/metadata/cache</code>.<br /><br />Ste si istý, že chcete vymazať priečinok vyrovnávacej pamäte?",
|
||||
"MessageConfirmPurgeItemsCache": "Vymazanie položiek vyrovnávacej pamäte kompletne odstráni priečinok <code>/metadata/cache/items</code>.<br />Ste si istý?",
|
||||
"MessageConfirmQuickEmbed": "Varovanie! Pri rýchlom vložení metadát nie sú vaše zvukové súbory zálohované. Uistite sa, že máte vaše zvukové súbory zálohované. <br><br>Chcete pokračovať?",
|
||||
"MessageConfirmQuickMatchEpisodes": "Pri rýchlom vyhľadávaní epizód sú v prípade zhody prepísané podrobnosti nájdených epizód. Nespárované epizódy budú len aktualizované. Ste si istý?",
|
||||
"MessageConfirmReScanLibraryItems": "Ste si istý, že chcete spustiť opakovaný sken {0} položiek?",
|
||||
"MessageConfirmRemoveAllChapters": "Ste si istý, že chcete odstrániť všetky kapitoly?",
|
||||
"MessageConfirmRemoveAuthor": "Ste si istý, že chcete odstrániť autora \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Ste si istý, že chcete odstrániť zbierku \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Ste si istý, že chcete odstrániť epizódu \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodes": "Ste si istý, že chcete odstrániť {0} epizód?",
|
||||
"MessageConfirmRemoveListeningSessions": "Ste si istý, že chcete odstrániť týchto {0} relácií?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Ste si istý, že chcete odstrániť všetky súbory metadata.{0} z priečinkov položiek vašej knižnice?",
|
||||
"MessageConfirmRemoveNarrator": "Ste si istý, že chcete odstrániť interpreta \"{0}\"?",
|
||||
"MessageConfirmRemovePlaylist": "Ste si istý, že chcete odstrániť váš playlist \"{0}\"?",
|
||||
"MessageConfirmRenameGenre": "Ste si istý, že chcete nahradiť žáner \"{0}\" vo všetkých položkách žánrom \"{0}\"?",
|
||||
"MessageConfirmRenameGenreMergeNote": "Poznámka: Tento žáner už existuje a preto bude zlúčený.",
|
||||
"MessageConfirmRenameGenreWarning": "Varovanie! Podobný žáner len s odlišným zápisom už existuje \"{0}\".",
|
||||
"MessageConfirmRenameTag": "Ste si istý, že chcete zmeniť štítok \"{0}\" za \"{1}\" vo všetkých položkách?",
|
||||
"MessageConfirmRenameTagMergeNote": "Poznámka: Tento štítok už existuje a preto bude zlúčený.",
|
||||
"MessageConfirmRenameTagWarning": "Varovanie! Štítok s podobným zápisom už existuje \"{0}\".",
|
||||
"MessageConfirmResetProgress": "Ste si istý, že chcete resetnúť váš aktuálny stav počúvania?",
|
||||
"MessageConfirmSendEbookToDevice": "Ste si istý, že chcete poslať {0} e-knihu \"{1}\" do zariadenia \"{2}\"?",
|
||||
"MessageConfirmUnlinkOpenId": "Ste si istý, že chcete odstrániť prepojenie tohto používateľa na OpenID?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} dní počúvania počas posledného roku",
|
||||
"MessageDownloadingEpisode": "Sťahovanie epizódy",
|
||||
"MessageDragFilesIntoTrackOrder": "Presuňte súbory do správneho poradia prehrávania",
|
||||
"MessageEmbedFailed": "Vloženie zlyhalo!",
|
||||
"MessageEmbedFinished": "Vloženie skončené!",
|
||||
"MessageEmbedQueue": "Zaradené do fronty na vloženie metadát ({0} v zozname)",
|
||||
"MessageEpisodesQueuedForDownload": "{0} epizód(a) v zozname na sťahovanie",
|
||||
"MessageEreaderDevices": "Na zaistenie dodania e-kníh môže byť nutné zadanie vyššie uvedenej e-mailovej adresy ako overeného odosielateľa v každom z nižšie vypísaných zariadení.",
|
||||
"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é.",
|
||||
"MessageImportantNotice": "Dôležité upozornenie!",
|
||||
"MessageInsertChapterBelow": "Vložte kapitolu nižšie",
|
||||
"MessageInvalidAsin": "Neplatné ASIN",
|
||||
"MessageItemsSelected": "{0} vybraných položiek",
|
||||
"MessageItemsUpdated": "{0} aktualizovaných položiek",
|
||||
"MessageJoinUsOn": "Pridajte sa k nám",
|
||||
"MessageLoading": "Načítanie...",
|
||||
"MessageLoadingFolders": "Načítanie priečinkov...",
|
||||
"MessageLogsDescription": "Záznamy logovania sú uložené v <code>/metadata/logs</code> vo forme JSON súborov. Záznamy kritických chýb sú uložené v <code>/metadata/logs/crash_logs.txt</code>.",
|
||||
"MessageM4BFailed": "M4B zlyhalo!",
|
||||
"MessageM4BFinished": "M4B skončené!",
|
||||
"MessageMapChapterTitles": "Prepojte názvy kapitol s vašimi už existujúcimi kapitolami audioknihy bez vplyvu na časové značky",
|
||||
"MessageMarkAllEpisodesFinished": "Označiť všetky epizódy ako dokončené",
|
||||
"MessageMarkAllEpisodesNotFinished": "Označiť všetky epizódy ako nedokončené",
|
||||
"MessageMarkAsFinished": "Označiť ako dokončené",
|
||||
"MessageMarkAsNotFinished": "Označiť ako nedokončené",
|
||||
"MessageMatchBooksDescription": "sa pokúsi spárovať knihy vo vašej knižnici s knihami nájdenými zvoleným poskytovateľom a doplniť chýbajúce údaje a prebal. aktuálne vyplnené údaje nebudú prepísané.",
|
||||
"MessageNoAudioTracks": "Žiadne zvukové stopy",
|
||||
"MessageNoAuthors": "Žiadni autori",
|
||||
"MessageNoBackups": "Žiadne zálohy",
|
||||
"MessageNoBookmarks": "Žiadne záložky",
|
||||
"MessageNoChapters": "Žiadne kapitoly",
|
||||
"MessageNoCollections": "Žiadne zbierky",
|
||||
"MessageNoCoversFound": "Neboli nájdené žiadne prebaly",
|
||||
"MessageNoDescription": "Žiadny popis",
|
||||
"MessageNoDevices": "Žiadne zariadenia",
|
||||
"MessageNoDownloadsInProgress": "Aktuálne neprebieha žiadne sťahovanie",
|
||||
"MessageNoDownloadsQueued": "Žiadne sťahovania v poradí",
|
||||
"MessageNoEpisodeMatchesFound": "Neboli spárované žiadne epizódy",
|
||||
"MessageNoEpisodes": "Žiadne eizódy",
|
||||
"MessageNoFoldersAvailable": "Žiadne priečinky nie sú dostupné",
|
||||
"MessageNoGenres": "Žiadne žánre",
|
||||
"MessageNoIssues": "Žiadne problémy",
|
||||
"MessageNoItems": "Žiadne položky",
|
||||
"MessageNoItemsFound": "Žiadne položky neboli nájdené",
|
||||
"MessageNoListeningSessions": "Žiadne relácie",
|
||||
"MessageNoLogs": "Žiadne záznamy udalostí",
|
||||
"MessageNoMediaProgress": "Žiadny stav médií",
|
||||
"MessageNoNotifications": "Žiadne upozornenia",
|
||||
"MessageNoPodcastFeed": "Chybný podcast: Žiadny zdroj",
|
||||
"MessageNoPodcastsFound": "Žiadne podcasty neboli nájdené",
|
||||
"MessageNoResults": "Žiadne výsledky",
|
||||
"MessageNoSearchResultsFor": "Žiadne výsledky vyhľadávania \"{0}\"",
|
||||
"MessageNoSeries": "Žiadne série",
|
||||
"MessageNoTags": "Žiadne štítky",
|
||||
"MessageNoTasksRunning": "Žiadne prebiehajúce úlohy",
|
||||
"MessageNoUpdatesWereNecessary": "Žiadne nutné aktualizácie",
|
||||
"MessageNoUserPlaylists": "Nemáte žiadny playlist",
|
||||
"MessageNoUserPlaylistsHelp": "Playlisty sú súkromné. Každý playlist môže vidieť iba používateľ, ktorý ho vytvoril.",
|
||||
"MessageNotYetImplemented": "Ešte neimplementované",
|
||||
"MessageOpmlPreviewNote": "Poznámka: Toto je náhľad pársovaného OPML súboru. Skutočný názov podcastu bude prevzatý zo RSS zdroja.",
|
||||
"MessageOr": "alebo",
|
||||
"MessagePauseChapter": "Pozastaviť prehrávanie kapitoly",
|
||||
"MessagePlayChapter": "Počúvať začiatok kapitoly",
|
||||
"MessagePlaylistCreateFromCollection": "Vytvoriť playlist zo zbierky",
|
||||
"MessagePleaseWait": "Prosím, počkajte...",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "Podcast nemá žiadnu URL RSS zdroja na spárovanie",
|
||||
"MessagePodcastSearchField": "Zadajte hľadaný výraz alebo URL RSS zdroja",
|
||||
"MessageQuickEmbedInProgress": "Prebieha rýchle vkladanie",
|
||||
"MessageQuickEmbedQueue": "Zadané na rýchle vloženie ({0} v rade)",
|
||||
"MessageQuickMatchAllEpisodes": "Rýchle vyhľadanie všetkých epizód",
|
||||
"MessageQuickMatchDescription": "Doplní všetky nevyplnené údaje a chýbajúci prebal z prvého výsledku vyhľdávania '{0}'. Neprepíše už existujúce údaje, vykoná tak iba v prípade, ak je zaškrtnutá voľba 'Preferovať vyhľadané metadáta'.",
|
||||
"MessageRemoveChapter": "Odstrániť kapitolu",
|
||||
"MessageRemoveEpisodes": "Odstrániť {0} epizódu(-y)",
|
||||
"MessageRemoveFromPlayerQueue": "Odstrániť zo zoznamu prehrávania",
|
||||
"MessageRemoveUserWarning": "Ste si istí, že chcete trvalo odstrániť užívateľa \"{0}\"?",
|
||||
"MessageReportBugsAndContribute": "Nahlásiť chyby, požiadavky na funkcie, a prispievať na",
|
||||
"MessageResetChaptersConfirm": "Ste si istý, že chcete resetnúť kapitoly a zahodiť zmeny, ktoré ste vykonali?",
|
||||
"MessageRestoreBackupConfirm": "Ste si istí, že chcete obnoviť zálohu vytvorenú",
|
||||
"MessageRestoreBackupWarning": "Obnovenie zálohy spôsobí kompletný prepis databázy umiestnenej v /config a obrázkov prebalov a autorov v /metadata/items a /metadata/authors.<br /><br />Zálohy nemenia žiadne súbory v priečinkoch vašej knižnice. Ak ste povolili v nastaveniach servera ukladanie obrázkov prebalov a metadát v priečinkoch knižnice, tieto nie sú zálohované a teda ani prepisované.<br /><br />Všetky klienti používajúci váš server budú automaticky obnovené.",
|
||||
"MessageScheduleLibraryScanNote": "Pre väčšinu používateľov sa odporúča ponechať túto funkciu vypnutú a povoliť nastavenia funkcie sledovania obsahu priečinku. Funkcia sledovania priečinku bude automaticky detekovať zmeny v priečinkoch knižnice. Táto funkcia však nefunguje pre všetky súborové systémy (ako napr. NFS), v tom prípade využite funkciu plánovaného skenovania knižnice.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Spustiť každú {0} o {1}",
|
||||
"MessageSearchResultsFor": "Výsledky vyhľadávania pre",
|
||||
"MessageSelected": "{0} vybrané",
|
||||
"MessageServerCouldNotBeReached": "Nepodarilo sa pripojiť na server",
|
||||
"MessageSetChaptersFromTracksDescription": "Nastaviť jednotlivé zvukové súbory ako kapitoly a názvy zvukových súborov ako názvy týchto kapitol",
|
||||
"MessageShareExpirationWillBe": "Expiruje <strong>{0}</strong>",
|
||||
"MessageShareExpiresIn": "Uplynie za {0}",
|
||||
"MessageShareURLWillBe": "URL na zdielanie bude <strong>{0}</strong>",
|
||||
"MessageStartPlaybackAtTime": "Spustiť prehrávanie \"{0}\" o {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "Do súboru \"{0}\" sa nedá zapisovať",
|
||||
"MessageTaskCanceledByUser": "Úloha zrušená používateľom",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Sťahuje sa diel \"{0}\"",
|
||||
"MessageTaskEmbeddingMetadata": "Vkladanie metadát",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Vkladanie metadát v audioknihe \"{0}\"",
|
||||
"MessageTaskEncodingM4b": "Kódovanie M4B",
|
||||
"MessageTaskEncodingM4bDescription": "Konverzia audioknihy \"{0}\" do jedného m4b súboru",
|
||||
"MessageTaskFailed": "Zlyhané",
|
||||
"MessageTaskFailedToBackupAudioFile": "Nepodarilo sa zazálohovať audio súbor \"{0}\"",
|
||||
"MessageTaskFailedToCreateCacheDirectory": "Nepodarilo sa vytvoriť adresár na cache",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "Vloženie metadát do \"{0}\" zlyhalo",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Nepodarilo sa pospájať audio súbory",
|
||||
"MessageTaskFailedToMoveM4bFile": "Nepodarilo sa presunúť m4b súbor",
|
||||
"MessageTaskFailedToWriteMetadataFile": "Nepodarilo sa zapísať súbor s metadátami",
|
||||
"MessageTaskMatchingBooksInLibrary": "Spárované knihy v knižnici \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Žiadne súbory k skenu",
|
||||
"MessageTaskOpmlImport": "OMPL import",
|
||||
"MessageTaskOpmlImportDescription": "Vytvorenie podcastov z {0} RSS zdrojov",
|
||||
"MessageTaskOpmlImportFeed": "Importný zdroj OPML",
|
||||
"MessageTaskOpmlImportFeedDescription": "Import RSS zdroja \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedFailed": "Získanie zdroja podcastu zlyhalo",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Vytvorenie podcastu \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "Na zadanom umiestnení už podcast existuje",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Vytvorenie podcastu zlyhalo",
|
||||
"MessageTaskOpmlImportFinished": "Pridaných {0} podcastov",
|
||||
"MessageTaskOpmlParseFailed": "Pársovanie OPML súboru zlyhalo",
|
||||
"MessageTaskOpmlParseFastFail": "Neplatný OPML súbor. <opml> tag ALEBO <outline> tag nebol nájdený",
|
||||
"MessageTaskOpmlParseNoneFound": "V OPML súbore neboli nájdené žiadne zdroje",
|
||||
"MessageTaskScanItemsAdded": "{0} pridaných",
|
||||
"MessageTaskScanItemsMissing": "{0} chýbajúcich",
|
||||
"MessageTaskScanItemsUpdated": "{0} aktualizovaných",
|
||||
"MessageTaskScanNoChangesNeeded": "Neboli potrebné žiadne zmeny",
|
||||
"MessageTaskScanningFileChanges": "Skenovanie zmien súborov v \"{0}\"",
|
||||
"MessageTaskScanningLibrary": "Skenovanie knižnice \"{0}\"",
|
||||
"MessageTaskTargetDirectoryNotWritable": "Cieľový priečinok nemá oprávnenie na zápis",
|
||||
"MessageThinking": "Premýšľam...",
|
||||
"MessageUploaderItemFailed": "Nahratie zlyhalo",
|
||||
"MessageUploaderItemSuccess": "Úspešne nahrané!",
|
||||
"MessageUploading": "Nahrávanie zmien...",
|
||||
"MessageValidCronExpression": "Platný cron výraz",
|
||||
"MessageWatcherIsDisabledGlobally": "Funkcia sledovania zmien je globálne vypnutá v nastaveniach servera",
|
||||
"MessageXLibraryIsEmpty": "Knižnica {0} je prázdna!",
|
||||
"MessageYourAudiobookDurationIsLonger": "Dĺžka vašej audioknihy je väčšia ako dĺžka nájdených súborov",
|
||||
"MessageYourAudiobookDurationIsShorter": "Dĺžka vašej audioknihy je menšia ako dĺžka nájdených súborov",
|
||||
"NoteChangeRootPassword": "Root používateľ je jediný používateľ, ktorý môže mať prázdne heslo",
|
||||
"NoteChapterEditorTimes": "Poznámka: Prvá kapitola musí vždy začínať v 0:00 a začiatok poslednej kapitoly nemôže prekročiť trvanie tejto audioknihy.",
|
||||
"NoteFolderPicker": "Poznámka: Priečinky, ktoré už boli priradené, sa ďalej nezobrazujú",
|
||||
"NoteRSSFeedPodcastAppsHttps": "Varovanie: Väčšina podcastových aplikácií vyžaduje, aby URL RSS zdroja vyžívala HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Varovanie: 1 alebo viacero vašich epizód neobsahuje infomáciu o dátume vydania. Niektoré podcastové aplikácie ju vyžadujú.",
|
||||
"NoteUploaderFoldersWithMediaFiles": "Priečinky obsahujúce súbory médií budú považované za samostatné položky knižnice.",
|
||||
"NoteUploaderOnlyAudioFiles": "Ak budú nahraté iba zvukové súbory, každý zvukový súbor bude považovaný za samostatnú audioknihu.",
|
||||
"NoteUploaderUnsupportedFiles": "Nepodporované súbory budú ignorované. Pri výbere alebo prenesení priečinka, budú všetky súbory, ktoré nie sú v priečinku niektorej z položiek, ignorované.",
|
||||
"NotificationOnBackupCompletedDescription": "Spustené po dokončení zálohovania",
|
||||
"NotificationOnBackupFailedDescription": "Spustené pri zlyhaní zálohovania",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Spustené po automatickom stiahnutí epizódy podcastu",
|
||||
"NotificationOnTestDescription": "Udalosť určená na testovanie systému notifikácií",
|
||||
"PlaceholderNewCollection": "Názov novej zbierky",
|
||||
"PlaceholderNewFolderPath": "Umiestnenie nového priečinka",
|
||||
"PlaceholderNewPlaylist": "Názov nového playlistu",
|
||||
"PlaceholderSearch": "Vyhľadávanie..",
|
||||
"PlaceholderSearchEpisode": "Vyhľadať epizódu..",
|
||||
"StatsAuthorsAdded": "autorov pridaných",
|
||||
"StatsBooksAdded": "kníh pridaných",
|
||||
"StatsBooksAdditional": "Niektoré prílohy zahŕňajú…",
|
||||
"StatsBooksFinished": "dokončených kníh",
|
||||
"StatsBooksFinishedThisYear": "Niektoré knihy dokončené tento rok…",
|
||||
"StatsBooksListenedTo": "vypočutých kníh",
|
||||
"StatsCollectionGrewTo": "Vaša knižná zbierka sa blíži k…",
|
||||
"StatsSessions": "relácie",
|
||||
"StatsSpentListening": "strávených počúvaním",
|
||||
"StatsTopAuthor": "TOP AUTOR",
|
||||
"StatsTopAuthors": "TOP AUTORI",
|
||||
"StatsTopGenre": "TOP ŽÁNER",
|
||||
"StatsTopGenres": "TOP ŽÁNRE",
|
||||
"StatsTopMonth": "TOP MESIAC",
|
||||
"StatsTopNarrator": "TOP INTERPRET",
|
||||
"StatsTopNarrators": "TOP INTERPRETI",
|
||||
"StatsTotalDuration": "S celkovou dĺžkou…",
|
||||
"StatsYearInReview": "ROK V PREHĽADE",
|
||||
"ToastAccountUpdateSuccess": "Účet bol aktualizovaný",
|
||||
"ToastAppriseUrlRequired": "Musíte zadať Apprise URL",
|
||||
"ToastAsinRequired": "Vyžaduje sa ASIN",
|
||||
"ToastAuthorImageRemoveSuccess": "Obrázok autora bol odstránený",
|
||||
"ToastAuthorNotFound": "Autor \"{0}\" nenájdený",
|
||||
"ToastAuthorRemoveSuccess": "Autor bol odstránený",
|
||||
"ToastAuthorSearchNotFound": "Autor nebol nájdený",
|
||||
"ToastAuthorUpdateMerged": "Autor bol zlúčený",
|
||||
"ToastAuthorUpdateSuccess": "Autor bol aktualizovaný",
|
||||
"ToastAuthorUpdateSuccessNoImageFound": "Autor bol aktualizovaný (obrázok nebol nájdený)",
|
||||
"ToastBackupAppliedSuccess": "Záloha bola aplikovaná",
|
||||
"ToastBackupCreateFailed": "Vytvorenie zálohy zlyhalo",
|
||||
"ToastBackupCreateSuccess": "Záloha bola vytvorená",
|
||||
"ToastBackupDeleteFailed": "Odstránenie zálohy zlyhalo",
|
||||
"ToastBackupDeleteSuccess": "Záloha bola odstránená",
|
||||
"ToastBackupInvalidMaxKeep": "Neplatný počet sledovaných záloh",
|
||||
"ToastBackupInvalidMaxSize": "Neplatná maximálna veľkosť zálohy",
|
||||
"ToastBackupRestoreFailed": "Obnovenie zo zálohy zlyhalo",
|
||||
"ToastBackupUploadFailed": "Nahratie zálohy zlyhalo",
|
||||
"ToastBackupUploadSuccess": "Záloha bola nahratá",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Dotknuté údaje položiek",
|
||||
"ToastBatchDeleteFailed": "Hromadné odstránenie zlyhalo",
|
||||
"ToastBatchDeleteSuccess": "Hromadné odstránenie bolo úspešné",
|
||||
"ToastBatchQuickMatchFailed": "Hromadné rýchle vyhľadanie zlyhalo!",
|
||||
"ToastBatchQuickMatchStarted": "Hromadné rýchle vyhľadanie {0} kníh začalo!",
|
||||
"ToastBatchUpdateFailed": "Hromadná aktualizácia zlyhala",
|
||||
"ToastBatchUpdateSuccess": "Hromadná aktualizácia prebehla úspešne",
|
||||
"ToastBookmarkCreateFailed": "Vytvorenie záložky zlyhalo",
|
||||
"ToastBookmarkCreateSuccess": "Záložka pridaná",
|
||||
"ToastBookmarkRemoveSuccess": "Záložka odstránená",
|
||||
"ToastCachePurgeFailed": "Vyčistenie vyrovnávacej pamäte zlyhalo",
|
||||
"ToastCachePurgeSuccess": "Vyrovnávacia pamäť vyčistená",
|
||||
"ToastChaptersHaveErrors": "Kapitoly obsahujú chyby",
|
||||
"ToastChaptersMustHaveTitles": "Kapitoly musia mať názvy",
|
||||
"ToastChaptersRemoved": "Kapitoly boli odstránené",
|
||||
"ToastChaptersUpdated": "Kapitoly boli aktualizované",
|
||||
"ToastCollectionItemsAddFailed": "Pridanie položky/-iek do zbierky zlyhalo",
|
||||
"ToastCollectionRemoveSuccess": "Zbierka odstránená",
|
||||
"ToastCollectionUpdateSuccess": "Zbierka aktualizovaná",
|
||||
"ToastCoverUpdateFailed": "Aktualizácia prebalu zlyhala",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Dátum a čas sú neplatné alebo neúplné",
|
||||
"ToastDeleteFileFailed": "Odstránenie súboru zlyhalo",
|
||||
"ToastDeleteFileSuccess": "Súbor bol odstránený",
|
||||
"ToastDeviceAddFailed": "Pridanie zariadenia zlyhalo",
|
||||
"ToastDeviceNameAlreadyExists": "Čítačka e-kníh s rovnakým názvom už existuje",
|
||||
"ToastDeviceTestEmailFailed": "Odoslanie testovacieho e-mailu zlyhalo",
|
||||
"ToastDeviceTestEmailSuccess": "Testovací e-mail bol odoslaný",
|
||||
"ToastEmailSettingsUpdateSuccess": "Nastavenia e-mailu boli aktualizované",
|
||||
"ToastEncodeCancelFailed": "Zrušenie znakového kódovania zlyhalo",
|
||||
"ToastEncodeCancelSucces": "Znakové kódovanie bolo zrušené",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Vyčistenie poradia zlyhalo",
|
||||
"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",
|
||||
"ToastFailedToLoadData": "Načítanie údajov zlyhalo",
|
||||
"ToastFailedToMatch": "Spárovanie zlyhalo",
|
||||
"ToastFailedToShare": "Zdieľanie zlyhalo",
|
||||
"ToastFailedToUpdate": "Aktualizácia zlyhala",
|
||||
"ToastInvalidImageUrl": "Neplatná URL obrázku",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Neplatný maximálny počet epizód na stiahnutie",
|
||||
"ToastInvalidUrl": "Neplatná URL",
|
||||
"ToastItemCoverUpdateSuccess": "Prebal položky bol aktualizovaný",
|
||||
"ToastItemDeletedFailed": "Odstránenie položky zlyhalo",
|
||||
"ToastItemDeletedSuccess": "Položka bola odstránená",
|
||||
"ToastItemDetailsUpdateSuccess": "Údaje položky boli aktualizované",
|
||||
"ToastItemMarkedAsFinishedFailed": "Označenie za Dokončené zlyhalo",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Položka bola označená ako Dokončená",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "Označenie za Nedokončené zlyhalo",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Položka bola označená ako Nedokončená",
|
||||
"ToastItemUpdateSuccess": "Položka bola aktualizovaná",
|
||||
"ToastLibraryCreateFailed": "Vytvorenie knižnice zlyhalo",
|
||||
"ToastLibraryCreateSuccess": "Knižnica \"{0}\" bola vytvorená",
|
||||
"ToastLibraryDeleteFailed": "Odstránenie knižnice zlyhalo",
|
||||
"ToastLibraryDeleteSuccess": "Knižnica bola odstránená",
|
||||
"ToastLibraryScanFailedToStart": "Spustenie skenovania zlyhalo",
|
||||
"ToastLibraryScanStarted": "Skenovanie knižnice sa začalo",
|
||||
"ToastLibraryUpdateSuccess": "Knižnica \"{0}\" bola aktualizovaná",
|
||||
"ToastMatchAllAuthorsFailed": "Spárovanie všetkých autorov zlyhalo",
|
||||
"ToastMetadataFilesRemovedError": "Chyba pri odstraňovaní súborov metadata.{0}",
|
||||
"ToastMetadataFilesRemovedNoneFound": "Žiadne súbory metadata.{0} neboli v knižnici nájdené",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "Žiadne súbory metadata.{0} neboli odstránené",
|
||||
"ToastMetadataFilesRemovedSuccess": "{0} súborov metadata.{1} bolo odstránených",
|
||||
"ToastMustHaveAtLeastOnePath": "Musí mať aspoň jednu cestu umiestnenia",
|
||||
"ToastNameEmailRequired": "Meno a e-mail sú povinné",
|
||||
"ToastNameRequired": "Meno je povinné",
|
||||
"ToastNewEpisodesFound": "Bolo nájdených {0} nových epizód",
|
||||
"ToastNewUserCreatedFailed": "Vytvorenie účtu zlyhalo: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Nový účet bol vytvorený",
|
||||
"ToastNewUserLibraryError": "Musíte vybrať aspoň jednu knižnicu",
|
||||
"ToastNewUserPasswordError": "Musí mať heslo, len root používateľ môže mať prázdne heslo",
|
||||
"ToastNewUserTagError": "Musíte vybrať aspoň jeden štítok",
|
||||
"ToastNewUserUsernameError": "Zadajte používateľské meno",
|
||||
"ToastNoNewEpisodesFound": "Žiadne nové epizódy neboli nájdené",
|
||||
"ToastNoRSSFeed": "Podcast nemá RSS zdroj",
|
||||
"ToastNoUpdatesNecessary": "Žiadne aktualizácie nie nutné",
|
||||
"ToastNotificationCreateFailed": "Vytvorenie notifikácie zlyhalo",
|
||||
"ToastNotificationDeleteFailed": "Odstránenie notifikácie zlyhalo",
|
||||
"ToastNotificationFailedMaximum": "Maximálny počet chybných pokusov musí byť >= 0",
|
||||
"ToastNotificationQueueMaximum": "Maximálny počet notifikácií v poradí musí byť >= 0",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Nastavenia notifikácií boli aktualizované",
|
||||
"ToastNotificationTestTriggerFailed": "Spustenie testovacej notifikácie zlyhalo",
|
||||
"ToastNotificationTestTriggerSuccess": "Testovacia notifikácia bola spustená",
|
||||
"ToastNotificationUpdateSuccess": "Notifikácia bola aktualizovaná",
|
||||
"ToastPlaylistCreateFailed": "Vytvorenie playlistu zlyhalo",
|
||||
"ToastPlaylistCreateSuccess": "Playlist bol vytvorený",
|
||||
"ToastPlaylistRemoveSuccess": "Playlist bol odstránený",
|
||||
"ToastPlaylistUpdateSuccess": "Playlist bol aktualizovaný",
|
||||
"ToastPodcastCreateFailed": "Vytvorenie podcastu zlyhalo",
|
||||
"ToastPodcastCreateSuccess": "Podcast bol vytvorený",
|
||||
"ToastPodcastGetFeedFailed": "Získanie zdroja podcastu zlyhalo",
|
||||
"ToastPodcastNoEpisodesInFeed": "Na RSS zdroji neboli nájdené žiadne epizódy",
|
||||
"ToastPodcastNoRssFeed": "Podcast nemá RSS zdroj",
|
||||
"ToastProgressIsNotBeingSynced": "Stav počúvania nie je synchronizovaný, reštartujte prehrávanie",
|
||||
"ToastProviderCreatedFailed": "Pridanie poskytovateľa zlyhalo",
|
||||
"ToastProviderCreatedSuccess": "Nový poskytovateľ bol pridaný",
|
||||
"ToastProviderNameAndUrlRequired": "Meno a URL sú povinné",
|
||||
"ToastProviderRemoveSuccess": "Poskytovateľ bol odstránený",
|
||||
"ToastRSSFeedCloseFailed": "Odstránenie RSS zdroja zlyhalo",
|
||||
"ToastRSSFeedCloseSuccess": "RSS zdroj bol odstránený",
|
||||
"ToastRemoveFailed": "Odstránenie zlyhalo",
|
||||
"ToastRemoveItemFromCollectionFailed": "Odstránenie položky zo zbierky zlyhalo",
|
||||
"ToastRemoveItemFromCollectionSuccess": "Položka bola zo zbierky odstránená",
|
||||
"ToastRemoveItemsWithIssuesFailed": "Odstránenie položiek s problémami zlyhalo",
|
||||
"ToastRemoveItemsWithIssuesSuccess": "Položky knižnice s problémami boli odstránené",
|
||||
"ToastRenameFailed": "Premenovanie zlyhalo",
|
||||
"ToastRescanFailed": "Opakované skenovanie {0} zlyhalo",
|
||||
"ToastRescanRemoved": "Opakovane skenovaná položka bola odstránená",
|
||||
"ToastRescanUpToDate": "Opakovane skenovaná položka bola aktuálna",
|
||||
"ToastRescanUpdated": "Opakovane skenovaná položka bola aktualizovaná",
|
||||
"ToastScanFailed": "Skenovanie položky knižnice zlyhalo",
|
||||
"ToastSelectAtLeastOneUser": "Vyberte aspoň jedného používateľa",
|
||||
"ToastSendEbookToDeviceFailed": "Odoslanie e-knihy do zariadenia zlyhalo",
|
||||
"ToastSendEbookToDeviceSuccess": "E-kniha bola odoslaná do zariadenia \"{0}\"",
|
||||
"ToastSeriesSubmitFailedSameName": "Nie je možné pridať dve série s rovnakým názvom",
|
||||
"ToastSeriesUpdateFailed": "Aktualizácia série zlyhala",
|
||||
"ToastSeriesUpdateSuccess": "Séria bola úspešne aktualizovaná",
|
||||
"ToastServerSettingsUpdateSuccess": "Nastavenia servera boli aktualizované",
|
||||
"ToastSessionCloseFailed": "Ukončenie relácie zlyhalo",
|
||||
"ToastSessionDeleteFailed": "Odstránenie relácie zlyhalo",
|
||||
"ToastSessionDeleteSuccess": "Relácia odstránená",
|
||||
"ToastSleepTimerDone": "Časovač spánku bol spustený... zZzzZz",
|
||||
"ToastSlugMustChange": "Slug obsahuje naplatné znaky",
|
||||
"ToastSlugRequired": "Slug je povinný",
|
||||
"ToastSocketConnected": "Socket je pripojený",
|
||||
"ToastSocketDisconnected": "Socket je odpojený",
|
||||
"ToastSocketFailedToConnect": "Pripojenie socketu zlyhalo",
|
||||
"ToastSortingPrefixesEmptyError": "Musí mať aspoň jednu triediacu predponu",
|
||||
"ToastSortingPrefixesUpdateSuccess": "Triediace predpony aktualizované ({0} položiek)",
|
||||
"ToastTitleRequired": "Názov je povinný",
|
||||
"ToastUnknownError": "Neznáma chyba",
|
||||
"ToastUnlinkOpenIdFailed": "Odstránenie prepojenia na OpenID zlyhalo",
|
||||
"ToastUnlinkOpenIdSuccess": "Prepojenie používateľa na OpenID bolo odstránené",
|
||||
"ToastUploaderFilepathExistsError": "Umiestnenie \"{0}\" na serveri už existuje",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Položka \"{0}\" používa podpriečinok umiestnenia pre nahrávanie.",
|
||||
"ToastUserDeleteFailed": "Odstránenie používateľa zlyhalo",
|
||||
"ToastUserDeleteSuccess": "Používateľ bol odstránený",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Seznam predvajanja",
|
||||
"HeaderPlaylistItems": "Elementi seznama predvajanja",
|
||||
"HeaderPodcastsToAdd": "Podcasti za dodajanje",
|
||||
"HeaderPresets": "Prednastavitve",
|
||||
"HeaderPreviewCover": "Naslovnica za predogled",
|
||||
"HeaderRSSFeedGeneral": "RSS podrobnosti",
|
||||
"HeaderRSSFeedIsOpen": "Vir RSS je odprt",
|
||||
@@ -530,6 +531,7 @@
|
||||
"LabelReleaseDate": "Datum izdaje",
|
||||
"LabelRemoveAllMetadataAbs": "Odstrani vse datoteke metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Odstrani vse datoteke metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Odstrani Audible uvod in zaključek iz poglavij",
|
||||
"LabelRemoveCover": "Odstrani naslovnico",
|
||||
"LabelRemoveMetadataFile": "Odstrani datoteke z metapodatki v mapah elementov knjižnice",
|
||||
"LabelRemoveMetadataFileHelp": "Odstrani vse datoteke metadata.json in metadata.abs v svojih mapah {0}.",
|
||||
@@ -705,6 +707,8 @@
|
||||
"LabelYourProgress": "Tvoj napredek",
|
||||
"MessageAddToPlayerQueue": "Dodaj v čakalno vrsto predvajalnika",
|
||||
"MessageAppriseDescription": "Če želite uporabljati to funkcijo, morate imeti zagnano namestitev <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API Apprise</a> ali API, ki bo obravnavala te iste zahteve. <br />Url API-ja Apprise mora biti celotna pot URL-ja za pošiljanje obvestila, npr. če je vaša namestitev API-ja postrežena na <code>http://192.168.1.1:8337</code>, bi morali vnesti <code >http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Prepričajte se, da uporabljate ASIN iz pravilne zvočne regije, ne iz Amazona.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Za uveljavitev OIDC sprememb, po shranjevanju znova zaženite strežnik.",
|
||||
"MessageBackupsDescription": "Varnostne kopije vključujejo uporabnike, napredek uporabnikov, podrobnosti elementov knjižnice, nastavitve strežnika in slike, shranjene v <code>/metadata/items</code> & <code>/metadata/authors</code>. Varnostne kopije <strong>ne</strong> vključujejo datotek, shranjenih v mapah vaše knjižnice.",
|
||||
"MessageBackupsLocationEditNote": "Opomba: Posodabljanje lokacije varnostne kopije ne bo premaknilo ali spremenilo obstoječih varnostnih kopij",
|
||||
"MessageBackupsLocationNoEditNote": "Opomba: Lokacija varnostne kopije je nastavljena s spremenljivko okolja in je tu ni mogoče spremeniti.",
|
||||
@@ -723,6 +727,7 @@
|
||||
"MessageChapterErrorStartGteDuration": "Neveljaven začetni čas, mora biti krajši od trajanja zvočne knjige",
|
||||
"MessageChapterErrorStartLtPrev": "Neveljaven začetni čas mora biti večji od ali enak začetnemu času prejšnjega poglavja",
|
||||
"MessageChapterStartIsAfter": "Začetek poglavja je po koncu vaše zvočne knjige",
|
||||
"MessageChaptersNotFound": "Poglavij ni bilo najdenih",
|
||||
"MessageCheckingCron": "Preverjam cron...",
|
||||
"MessageConfirmCloseFeed": "Ali ste prepričani, da želite zapreti ta vir?",
|
||||
"MessageConfirmDeleteBackup": "Ali ste prepričani, da želite izbrisati varnostno kopijo za {0}?",
|
||||
@@ -779,6 +784,7 @@
|
||||
"MessageForceReScanDescription": "bo znova pregledal vse datoteke kot pregled od začetka. Oznake ID3 zvočnih datotek, datoteke OPF in besedilne datoteke bodo pregledane kot nove.",
|
||||
"MessageImportantNotice": "Pomembno obvestilo!",
|
||||
"MessageInsertChapterBelow": "Spodaj vstavite poglavje",
|
||||
"MessageInvalidAsin": "Neveljaven ASIN",
|
||||
"MessageItemsSelected": "{0} izbranih elementov",
|
||||
"MessageItemsUpdated": "Št. posodobljenih elementov: {0}",
|
||||
"MessageJoinUsOn": "Pridružite se nam",
|
||||
@@ -968,6 +974,8 @@
|
||||
"ToastCachePurgeFailed": "Čiščenje predpomnilnika ni uspelo",
|
||||
"ToastCachePurgeSuccess": "Predpomnilnik je bil uspešno očiščen",
|
||||
"ToastChaptersHaveErrors": "Poglavja imajo napake",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Neveljavna vrednost zamika. Začetni čas zadnjega poglavja bi presegel trajanje te zvočne knjige.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Neveljavna vrednost zamika. Prvo poglavje bi imelo ničelno ali negativno dolžino in bi ga prepisalo drugo poglavje. Povečajte začetno trajanje drugega poglavja.",
|
||||
"ToastChaptersMustHaveTitles": "Poglavja morajo imeti naslove",
|
||||
"ToastChaptersRemoved": "Poglavja so odstranjena",
|
||||
"ToastChaptersUpdated": "Poglavja so posodobljena",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"HeaderPlaylist": "Список відтворення",
|
||||
"HeaderPlaylistItems": "Елементи списку відтворення",
|
||||
"HeaderPodcastsToAdd": "Додати подкасти",
|
||||
"HeaderPresets": "Пресети",
|
||||
"HeaderPreviewCover": "Попередній перегляд",
|
||||
"HeaderRSSFeedGeneral": "Подробиці RSS",
|
||||
"HeaderRSSFeedIsOpen": "RSS-канал відкрито",
|
||||
@@ -530,6 +531,7 @@
|
||||
"LabelReleaseDate": "Дата публікації",
|
||||
"LabelRemoveAllMetadataAbs": "Видалити всі файли metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Видалити всі файли metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Видалити звуковий вступ та завершення з розділів",
|
||||
"LabelRemoveCover": "Видалити обкладинку",
|
||||
"LabelRemoveMetadataFile": "Видалити файли метаданих у папках елементів бібліотеки",
|
||||
"LabelRemoveMetadataFileHelp": "Видалити всі файли metadata.json та metadata.abs у ваших папках {0}.",
|
||||
@@ -607,8 +609,8 @@
|
||||
"LabelSortPubDate": "Сортувати дату публікації",
|
||||
"LabelStart": "Початок",
|
||||
"LabelStartTime": "Час початку",
|
||||
"LabelStarted": "Почато",
|
||||
"LabelStartedAt": "Почато",
|
||||
"LabelStarted": "Стартував",
|
||||
"LabelStartedAt": "Почато з",
|
||||
"LabelStatsAudioTracks": "Аудіодоріжки",
|
||||
"LabelStatsAuthors": "Автори",
|
||||
"LabelStatsBestDay": "Найкращий день",
|
||||
@@ -706,6 +708,7 @@
|
||||
"MessageAddToPlayerQueue": "Додати до черги відтворення",
|
||||
"MessageAppriseDescription": "Щоб скористатися цією функцією, вам потрібно мати запущену <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> або API, що оброблятиме ті ж запити. <br />Аби надсилати сповіщення, URL-адреса API Apprise мусить бути повною, наприклад, якщо ваш API розміщено за адресою <code>http://192.168.1.1:8337</code>, то необхідно вказати адресу <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Переконайтесь, що ви використовуєте ASIN з правильної регіональної Audible зони, а не з Amazon.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Перезавантажте сервер після збереження, щоб застосувати зміни OIDC.",
|
||||
"MessageBackupsDescription": "Резервні копії містять користувачів, прогрес, подробиці елементів бібліотеки, налаштування сервера та зображення з <code>/metadata/items</code> та <code>/metadata/authors</code>. Резервні копії <strong>не</strong> містять жодних файлів з тек бібліотеки.",
|
||||
"MessageBackupsLocationEditNote": "Примітка: оновлення розташування резервної копії не переносить та не змінює існуючих копій",
|
||||
"MessageBackupsLocationNoEditNote": "Примітка: розташування резервної копії встановлюється за допомогою змінної середовища та не може бути змінене тут.",
|
||||
@@ -815,7 +818,7 @@
|
||||
"MessageNoItems": "Елементи відсутні",
|
||||
"MessageNoItemsFound": "Елементів не знайдено",
|
||||
"MessageNoListeningSessions": "Сеанси прослуховування відсутні",
|
||||
"MessageNoLogs": "Немає журналів",
|
||||
"MessageNoLogs": "Немає журнали",
|
||||
"MessageNoMediaProgress": "Прогрес відсутній",
|
||||
"MessageNoNotifications": "Сповіщення відсутні",
|
||||
"MessageNoPodcastFeed": "Невірний подкаст: Немає каналу",
|
||||
@@ -971,6 +974,8 @@
|
||||
"ToastCachePurgeFailed": "Не вдалося очистити кеш",
|
||||
"ToastCachePurgeSuccess": "Кеш очищено",
|
||||
"ToastChaptersHaveErrors": "Глави містять помилки",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Недійсна тривалість зсуву. Час початку останнього розділу перевищує тривалість цієї аудіокниги.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Недійсна величина зсуву. Перший розділ матиме нульову або від’ємну тривалість і буде перезаписаний другим розділом. Збільште початкову тривалість другого розділу.",
|
||||
"ToastChaptersMustHaveTitles": "Глави повинні мати назви",
|
||||
"ToastChaptersRemoved": "Розділи видалені",
|
||||
"ToastChaptersUpdated": "Розділи оновлені",
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "audiobookshelf",
|
||||
"version": "2.21.0",
|
||||
"version": "2.23.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "audiobookshelf",
|
||||
"version": "2.21.0",
|
||||
"version": "2.23.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"axios": "^0.27.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "audiobookshelf",
|
||||
"version": "2.21.0",
|
||||
"version": "2.23.0",
|
||||
"buildNumber": 1,
|
||||
"description": "Self-hosted audiobook and podcast server",
|
||||
"main": "index.js",
|
||||
|
||||
@@ -20,10 +20,7 @@ class Auth {
|
||||
// Map of openId sessions indexed by oauth2 state-variable
|
||||
this.openIdAuthSession = new Map()
|
||||
const escapedRouterBasePath = escapeRegExp(global.RouterBasePath)
|
||||
this.ignorePatterns = [
|
||||
new RegExp(`^(${escapedRouterBasePath}/api)?/items/[^/]+/cover$`),
|
||||
new RegExp(`^(${escapedRouterBasePath}/api)?/authors/[^/]+/image$`)
|
||||
]
|
||||
this.ignorePatterns = [new RegExp(`^(${escapedRouterBasePath}/api)?/items/[^/]+/cover$`), new RegExp(`^(${escapedRouterBasePath}/api)?/authors/[^/]+/image$`)]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -310,10 +310,10 @@ class Server {
|
||||
})
|
||||
)
|
||||
router.use(express.urlencoded({ extended: true, limit: '5mb' }))
|
||||
router.use(express.json({ limit: '5mb' }))
|
||||
router.use(express.json({ limit: '10mb' }))
|
||||
|
||||
router.use('/api', this.auth.ifAuthNeeded(this.authMiddleware.bind(this)), this.apiRouter.router)
|
||||
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
|
||||
router.use('/hls', this.hlsRouter.router)
|
||||
router.use('/public', this.publicRouter.router)
|
||||
|
||||
// Static path to generated nuxt
|
||||
@@ -395,10 +395,19 @@ class Server {
|
||||
})
|
||||
router.get('/healthcheck', (req, res) => res.sendStatus(200))
|
||||
|
||||
this.server.listen(this.Port, this.Host, () => {
|
||||
if (this.Host) Logger.info(`Listening on http://${this.Host}:${this.Port}`)
|
||||
else Logger.info(`Listening on port :${this.Port}`)
|
||||
})
|
||||
const unixSocketPrefix = 'unix/'
|
||||
if (this.Host?.startsWith(unixSocketPrefix)) {
|
||||
const sockPath = this.Host.slice(unixSocketPrefix.length)
|
||||
this.server.listen(sockPath, async () => {
|
||||
await fs.chmod(sockPath, 0o666)
|
||||
Logger.info(`Listening on unix socket ${sockPath}`)
|
||||
})
|
||||
} else {
|
||||
this.server.listen(this.Port, this.Host, () => {
|
||||
if (this.Host) Logger.info(`Listening on http://${this.Host}:${this.Port}`)
|
||||
else Logger.info(`Listening on port :${this.Port}`)
|
||||
})
|
||||
}
|
||||
|
||||
// Start listening for socket connections
|
||||
SocketAuthority.initialize(this)
|
||||
|
||||
@@ -84,49 +84,67 @@ class FileSystemController {
|
||||
*/
|
||||
async checkPathExists(req, res) {
|
||||
if (!req.user.canUpload) {
|
||||
Logger.error(`[FileSystemController] Non-admin user "${req.user.username}" attempting to check path exists`)
|
||||
Logger.error(`[FileSystemController] User "${req.user.username}" without upload permissions attempting to check path exists`)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
const { filepath, directory, folderPath } = req.body
|
||||
const { directory, folderPath } = req.body
|
||||
|
||||
if (!filepath?.length || typeof filepath !== 'string') {
|
||||
if (!directory?.length || typeof directory !== 'string' || !folderPath?.length || typeof folderPath !== 'string') {
|
||||
Logger.error(`[FileSystemController] Invalid request body: ${JSON.stringify(req.body)}`)
|
||||
return res.status(400).json({
|
||||
error: 'Invalid request body'
|
||||
})
|
||||
}
|
||||
|
||||
// Check that library folder exists
|
||||
const libraryFolder = await Database.libraryFolderModel.findOne({
|
||||
where: {
|
||||
path: folderPath
|
||||
}
|
||||
})
|
||||
|
||||
if (!libraryFolder) {
|
||||
Logger.error(`[FileSystemController] Library folder not found: ${folderPath}`)
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
||||
const filepath = Path.posix.join(libraryFolder.path, directory)
|
||||
// Ensure filepath is inside library folder (prevents directory traversal)
|
||||
if (!filepath.startsWith(libraryFolder.path)) {
|
||||
Logger.error(`[FileSystemController] Filepath is not inside library folder: ${filepath}`)
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
||||
const exists = await fs.pathExists(filepath)
|
||||
|
||||
if (exists) {
|
||||
if (await fs.pathExists(filepath)) {
|
||||
return res.json({
|
||||
exists: true
|
||||
})
|
||||
}
|
||||
|
||||
// If directory and folderPath are passed in, check if a library item exists in a subdirectory
|
||||
// Check if a library item exists in a subdirectory
|
||||
// See: https://github.com/advplyr/audiobookshelf/issues/4146
|
||||
if (typeof directory === 'string' && typeof folderPath === 'string' && directory.length > 0 && folderPath.length > 0) {
|
||||
const cleanedDirectory = directory.split('/').filter(Boolean).join('/')
|
||||
if (cleanedDirectory.includes('/')) {
|
||||
// Can only be 2 levels deep
|
||||
const possiblePaths = []
|
||||
const subdir = Path.dirname(directory)
|
||||
possiblePaths.push(fileUtils.filePathToPOSIX(Path.join(folderPath, subdir)))
|
||||
if (subdir.includes('/')) {
|
||||
possiblePaths.push(fileUtils.filePathToPOSIX(Path.join(folderPath, Path.dirname(subdir))))
|
||||
}
|
||||
const cleanedDirectory = directory.split('/').filter(Boolean).join('/')
|
||||
if (cleanedDirectory.includes('/')) {
|
||||
// Can only be 2 levels deep
|
||||
const possiblePaths = []
|
||||
const subdir = Path.dirname(directory)
|
||||
possiblePaths.push(fileUtils.filePathToPOSIX(Path.join(folderPath, subdir)))
|
||||
if (subdir.includes('/')) {
|
||||
possiblePaths.push(fileUtils.filePathToPOSIX(Path.join(folderPath, Path.dirname(subdir))))
|
||||
}
|
||||
|
||||
const libraryItem = await Database.libraryItemModel.findOne({
|
||||
where: {
|
||||
path: possiblePaths
|
||||
}
|
||||
const libraryItem = await Database.libraryItemModel.findOne({
|
||||
where: {
|
||||
path: possiblePaths
|
||||
}
|
||||
})
|
||||
|
||||
if (libraryItem) {
|
||||
return res.json({
|
||||
exists: true,
|
||||
libraryItemTitle: libraryItem.title
|
||||
})
|
||||
|
||||
if (libraryItem) {
|
||||
return res.json({
|
||||
exists: true,
|
||||
libraryItemTitle: libraryItem.title
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
const Path = require('path')
|
||||
const { Request, Response, NextFunction } = require('express')
|
||||
const Logger = require('../Logger')
|
||||
const Database = require('../Database')
|
||||
const { toNumber, isUUID } = require('../utils/index')
|
||||
const { getAudioMimeTypeFromExtname, encodeUriPath } = require('../utils/fileUtils')
|
||||
|
||||
const ShareManager = require('../managers/ShareManager')
|
||||
|
||||
@@ -266,6 +268,51 @@ class SessionController {
|
||||
this.playbackSessionManager.syncLocalSessionsRequest(req, res)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /public/session/:id/track/:index
|
||||
* While a session is open, this endpoint can be used to stream the audio track
|
||||
*
|
||||
* @this {import('../routers/PublicRouter')}
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
async getTrack(req, res) {
|
||||
const audioTrackIndex = toNumber(req.params.index, null)
|
||||
if (audioTrackIndex === null) {
|
||||
Logger.error(`[SessionController] Invalid audio track index "${req.params.index}"`)
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
||||
const playbackSession = this.playbackSessionManager.getSession(req.params.id)
|
||||
if (!playbackSession) {
|
||||
Logger.error(`[SessionController] Unable to find playback session with id=${req.params.id}`)
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
||||
const audioTrack = playbackSession.audioTracks.find((t) => t.index === audioTrackIndex)
|
||||
if (!audioTrack) {
|
||||
Logger.error(`[SessionController] Unable to find audio track with index=${audioTrackIndex}`)
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
||||
const user = await Database.userModel.getUserById(playbackSession.userId)
|
||||
Logger.debug(`[SessionController] Serving audio track ${audioTrack.index} for session "${req.params.id}" belonging to user "${user.username}"`)
|
||||
|
||||
if (global.XAccel) {
|
||||
const encodedURI = encodeUriPath(global.XAccel + audioTrack.metadata.path)
|
||||
Logger.debug(`Use X-Accel to serve static file ${encodedURI}`)
|
||||
return res.status(204).header({ 'X-Accel-Redirect': encodedURI }).send()
|
||||
}
|
||||
|
||||
// Express does not set the correct mimetype for m4b files so use our defined mimetypes if available
|
||||
const audioMimeType = getAudioMimeTypeFromExtname(Path.extname(audioTrack.metadata.path))
|
||||
if (audioMimeType) {
|
||||
res.setHeader('Content-Type', audioMimeType)
|
||||
}
|
||||
res.sendFile(audioTrack.metadata.path)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {RequestWithUser} req
|
||||
|
||||
@@ -26,6 +26,12 @@ class PlaybackSessionManager {
|
||||
this.sessions = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Get open session by id
|
||||
*
|
||||
* @param {string} sessionId
|
||||
* @returns {PlaybackSession}
|
||||
*/
|
||||
getSession(sessionId) {
|
||||
return this.sessions.find((s) => s.id === sessionId)
|
||||
}
|
||||
|
||||
@@ -246,9 +246,10 @@ class MediaProgress extends Model {
|
||||
// For local sync
|
||||
if (progressPayload.lastUpdate) {
|
||||
this.updatedAt = progressPayload.lastUpdate
|
||||
this.changed('updatedAt', true)
|
||||
}
|
||||
|
||||
return this.save()
|
||||
return this.save({ silent: !!progressPayload.lastUpdate })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const express = require('express')
|
||||
const ShareController = require('../controllers/ShareController')
|
||||
const SessionController = require('../controllers/SessionController')
|
||||
|
||||
class PublicRouter {
|
||||
constructor(playbackSessionManager) {
|
||||
@@ -17,6 +18,7 @@ class PublicRouter {
|
||||
this.router.get('/share/:slug/cover', ShareController.getMediaItemShareCoverImage.bind(this))
|
||||
this.router.get('/share/:slug/download', ShareController.downloadMediaItemShare.bind(this))
|
||||
this.router.patch('/share/:slug/progress', ShareController.updateMediaItemShareProgress.bind(this))
|
||||
this.router.get('/session/:id/track/:index', SessionController.getTrack.bind(this))
|
||||
}
|
||||
}
|
||||
module.exports = PublicRouter
|
||||
|
||||
@@ -242,7 +242,7 @@ module.exports.recurseFiles = async (path, relPathToReplace = null) => {
|
||||
})
|
||||
.filter((item) => {
|
||||
// Filter out items in ignore directories
|
||||
if (directoriesToIgnore.some((dir) => item.fullname.startsWith(dir))) {
|
||||
if (directoriesToIgnore.some((dir) => item.fullname.startsWith(dir + '/'))) {
|
||||
Logger.debug(`[fileUtils] Ignoring path in dir with .ignore "${item.fullname}"`)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ function extractEpisodeData(item) {
|
||||
} else if (typeof guidItem?._ === 'string') {
|
||||
episode.guid = guidItem._
|
||||
} else {
|
||||
Logger.error(`[podcastUtils] Invalid guid ${item['guid']} for ${episode.enclosure.url}`)
|
||||
Logger.error(`[podcastUtils] Invalid guid for ${episode.enclosure.url}`, item['guid'])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1195,10 +1195,12 @@ module.exports = {
|
||||
libraryItem.media.series = []
|
||||
return libraryItem.toOldJSON()
|
||||
})
|
||||
seriesMatches.push({
|
||||
series: series.toOldJSON(),
|
||||
books
|
||||
})
|
||||
if (books.length) {
|
||||
seriesMatches.push({
|
||||
series: series.toOldJSON(),
|
||||
books
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Search authors
|
||||
@@ -1247,7 +1249,12 @@ module.exports = {
|
||||
libraryId
|
||||
}
|
||||
})
|
||||
return statResults[0]
|
||||
return {
|
||||
totalSize: statResults?.[0]?.totalSize || 0,
|
||||
totalDuration: statResults?.[0]?.totalDuration || 0,
|
||||
numAudioFiles: statResults?.[0]?.numAudioFiles || 0,
|
||||
totalItems: statResults?.[0]?.totalItems || 0
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -411,6 +411,43 @@ module.exports = {
|
||||
})
|
||||
}
|
||||
|
||||
// Search podcast episode title
|
||||
const podcastEpisodes = await Database.podcastEpisodeModel.findAll({
|
||||
where: [
|
||||
Sequelize.literal(textSearchQuery.matchExpression('podcastEpisode.title')),
|
||||
{
|
||||
'$podcast.libraryItem.libraryId$': library.id
|
||||
}
|
||||
],
|
||||
replacements: userPermissionPodcastWhere.replacements,
|
||||
include: [
|
||||
{
|
||||
model: Database.podcastModel,
|
||||
where: [...userPermissionPodcastWhere.podcastWhere],
|
||||
include: [
|
||||
{
|
||||
model: Database.libraryItemModel
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
distinct: true,
|
||||
offset,
|
||||
limit
|
||||
})
|
||||
const episodeMatches = []
|
||||
for (const episode of podcastEpisodes) {
|
||||
const libraryItem = episode.podcast.libraryItem
|
||||
libraryItem.media = episode.podcast
|
||||
libraryItem.media.podcastEpisodes = []
|
||||
const oldPodcastEpisodeJson = episode.toOldJSONExpanded(libraryItem.id)
|
||||
const libraryItemJson = libraryItem.toOldJSONExpanded()
|
||||
libraryItemJson.recentEpisode = oldPodcastEpisodeJson
|
||||
episodeMatches.push({
|
||||
libraryItem: libraryItemJson
|
||||
})
|
||||
}
|
||||
|
||||
const matchJsonValue = textSearchQuery.matchExpression('json_each.value')
|
||||
|
||||
// Search tags
|
||||
@@ -450,7 +487,8 @@ module.exports = {
|
||||
return {
|
||||
podcast: itemMatches,
|
||||
tags: tagMatches,
|
||||
genres: genreMatches
|
||||
genres: genreMatches,
|
||||
episodes: episodeMatches
|
||||
}
|
||||
},
|
||||
|
||||
@@ -533,8 +571,10 @@ module.exports = {
|
||||
}
|
||||
})
|
||||
return {
|
||||
...statResults[0],
|
||||
totalSize: sizeResults[0].totalSize || 0
|
||||
totalDuration: statResults?.[0]?.totalDuration || 0,
|
||||
numAudioFiles: statResults?.[0]?.numAudioFiles || 0,
|
||||
totalItems: statResults?.[0]?.totalItems || 0,
|
||||
totalSize: sizeResults?.[0]?.totalSize || 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
0
tailwind.config.js
Normal file
0
tailwind.config.js
Normal file
@@ -47,7 +47,7 @@ describe('fileUtils', () => {
|
||||
|
||||
// Mock file structure with normalized paths
|
||||
const mockDirContents = new Map([
|
||||
['/test', ['file1.mp3', 'subfolder', 'ignoreme', 'temp.mp3.tmp']],
|
||||
['/test', ['file1.mp3', 'subfolder', 'ignoreme', 'ignoremenot.mp3', 'temp.mp3.tmp']],
|
||||
['/test/subfolder', ['file2.m4b']],
|
||||
['/test/ignoreme', ['.ignore', 'ignored.mp3']]
|
||||
])
|
||||
@@ -59,7 +59,8 @@ describe('fileUtils', () => {
|
||||
['/test/ignoreme', { isDirectory: () => true, size: 0, mtimeMs: Date.now(), ino: '4' }],
|
||||
['/test/ignoreme/.ignore', { isDirectory: () => false, size: 0, mtimeMs: Date.now(), ino: '5' }],
|
||||
['/test/ignoreme/ignored.mp3', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '6' }],
|
||||
['/test/temp.mp3.tmp', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '7' }]
|
||||
['/test/ignoremenot.mp3', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '7' }],
|
||||
['/test/temp.mp3.tmp', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '8' }]
|
||||
])
|
||||
|
||||
// Stub fs.readdir
|
||||
@@ -103,7 +104,7 @@ describe('fileUtils', () => {
|
||||
it('should return filtered file list', async () => {
|
||||
const files = await fileUtils.recurseFiles('/test')
|
||||
expect(files).to.be.an('array')
|
||||
expect(files).to.have.lengthOf(2)
|
||||
expect(files).to.have.lengthOf(3)
|
||||
|
||||
expect(files[0]).to.deep.equal({
|
||||
name: 'file1.mp3',
|
||||
@@ -115,6 +116,15 @@ describe('fileUtils', () => {
|
||||
})
|
||||
|
||||
expect(files[1]).to.deep.equal({
|
||||
name: 'ignoremenot.mp3',
|
||||
path: 'ignoremenot.mp3',
|
||||
reldirpath: '',
|
||||
fullpath: '/test/ignoremenot.mp3',
|
||||
extension: '.mp3',
|
||||
deep: 0
|
||||
})
|
||||
|
||||
expect(files[2]).to.deep.equal({
|
||||
name: 'file2.m4b',
|
||||
path: 'subfolder/file2.m4b',
|
||||
reldirpath: 'subfolder',
|
||||
|
||||
Reference in New Issue
Block a user