Merge branch 'advplyr:master' into bookshelf-refactor-2

This commit is contained in:
mikiher 2024-06-25 10:03:18 +03:00 committed by GitHub
commit 9bf4bd9bfa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
97 changed files with 10529 additions and 3391 deletions

View File

@ -20,11 +20,11 @@ jobs:
- name: Set up node
uses: actions/setup-node@v4
with:
node-version: "20"
node-version: '20'
# The only argument is the `directory`, which is where the i18n files are
# stored.
- name: Run Update JSON Files action
uses: audiobookshelf/audiobookshelf-i18n-updater@v1.2.0
uses: audiobookshelf/audiobookshelf-i18n-updater@v1.3.0
with:
directory: "client/strings/" # Adjust the directory path as needed
directory: 'client/strings/' # Adjust the directory path as needed

30
.github/workflows/lint-openapi.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: API linting
# Run on pull requests or pushes when there is a change to the OpenAPI file
on:
push:
paths:
- docs/
pull_request:
paths:
- docs/
jobs:
build:
runs-on: ubuntu-latest
steps:
# Check out the repository
- name: Checkout
uses: actions/checkout@v4
# Set up node to run the javascript
- name: Set up node
uses: actions/setup-node@v4
# Install Redocly CLI
- name: Install Redocly CLI
run: npm install -g @redocly/cli@latest
# Perform linting for exploded spec
- name: Run linting for exploded spec
run: redocly lint docs/root.yaml --format=github-actions
# Perform linting for bundled spec
- name: Run linting for bundled spec
run: redocly lint docs/openapi.json --format=github-actions

View File

@ -11,7 +11,7 @@
</div>
</div>
<div v-else-if="loaded && !shelves.length && search" class="w-full h-40 flex items-center justify-center">
<p class="text-center text-xl py-4">No results for query</p>
<p class="text-center text-xl py-4">{{ $strings.MessageBookshelfNoResultsForQuery }}</p>
</div>
<!-- Alternate plain view -->
<div v-else-if="isAlternativeBookshelfView" class="w-full mb-24e">

View File

@ -5,23 +5,21 @@
<covers-book-cover expand-on-click :library-item="streamLibraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="coverAspectRatio" />
</div>
<div class="flex items-start mb-6 lg:mb-0" :class="playerHandler.isVideo ? 'ml-4 pl-96' : isSquareCover ? 'pl-18 sm:pl-24' : 'pl-12 sm:pl-16'">
<div class="min-w-0">
<div class="min-w-0 w-full">
<div class="flex items-center">
<nuxt-link :to="`/item/${streamLibraryItem.id}`" class="hover:underline cursor-pointer text-sm sm:text-lg block truncate">
{{ title }}
</nuxt-link>
<widgets-explicit-indicator v-if="isExplicit" />
</div>
<div v-if="!playerHandler.isVideo" class="text-gray-400 flex items-center">
<div v-if="!playerHandler.isVideo" class="text-gray-400 flex items-center w-1/2 sm:w-4/5 lg:w-2/5">
<span class="material-icons text-sm">person</span>
<div class="flex items-center">
<div v-if="podcastAuthor" class="pl-1 sm:pl-1.5 text-xs sm:text-base">{{ podcastAuthor }}</div>
<div v-else-if="musicArtists" class="pl-1 sm:pl-1.5 text-xs sm:text-base">{{ musicArtists }}</div>
<div v-else-if="authors.length" class="pl-1 sm:pl-1.5 text-xs sm:text-base">
<nuxt-link v-for="(author, index) in authors" :key="index" :to="`/author/${author.id}`" class="hover:underline">{{ author.name }}<span v-if="index < authors.length - 1">,&nbsp;</span></nuxt-link>
</div>
<div v-else class="text-xs sm:text-base cursor-pointer pl-1 sm:pl-1.5">{{ $strings.LabelUnknown }}</div>
<div v-if="podcastAuthor" class="pl-1 sm:pl-1.5 text-xs sm:text-base">{{ podcastAuthor }}</div>
<div v-else-if="musicArtists" class="pl-1 sm:pl-1.5 text-xs sm:text-base">{{ musicArtists }}</div>
<div v-else-if="authors.length" class="pl-1 sm:pl-1.5 text-xs sm:text-base truncate">
<nuxt-link v-for="(author, index) in authors" :key="index" :to="`/author/${author.id}`" class="hover:underline">{{ author.name }}<span v-if="index < authors.length - 1">,&nbsp;</span></nuxt-link>
</div>
<div v-else class="text-xs sm:text-base cursor-pointer pl-1 sm:pl-1.5">{{ $strings.LabelUnknown }}</div>
</div>
<div class="text-gray-400 flex items-center">

View File

@ -37,12 +37,12 @@
<span class="material-icons text-2xl">arrow_left</span>
</div>
<div class="flex items-center justify-between">
<span class="font-normal block truncate">Back</span>
<span class="font-normal block truncate">{{ $strings.ButtonBack }}</span>
</div>
</li>
<li v-if="!sublistItems.length" class="text-gray-400 select-none relative px-2" role="option">
<div class="flex items-center justify-center">
<span class="font-normal block truncate py-2">No {{ sublist }}</span>
<span class="font-normal block truncate py-2">{{ $getString('LabelLibraryFilterSublistEmpty', [selectedSublistText]) }}</span>
</div>
</li>
<template v-for="item in sublistItems">
@ -106,31 +106,37 @@ export default {
},
{
text: this.$strings.LabelGenre,
textPlural: this.$strings.LabelGenres,
value: 'genres',
sublist: true
},
{
text: this.$strings.LabelTag,
textPlural: this.$strings.LabelTags,
value: 'tags',
sublist: true
},
{
text: this.$strings.LabelAuthor,
textPlural: this.$strings.LabelAuthors,
value: 'authors',
sublist: true
},
{
text: this.$strings.LabelNarrator,
textPlural: this.$strings.LabelNarrators,
value: 'narrators',
sublist: true
},
{
text: this.$strings.LabelPublisher,
textPlural: this.$strings.LabelPublishers,
value: 'publishers',
sublist: true
},
{
text: this.$strings.LabelLanguage,
textPlural: this.$strings.LabelLanguages,
value: 'languages',
sublist: true
},
@ -149,36 +155,43 @@ export default {
},
{
text: this.$strings.LabelGenre,
textPlural: this.$strings.LabelGenres,
value: 'genres',
sublist: true
},
{
text: this.$strings.LabelTag,
textPlural: this.$strings.LabelTags,
value: 'tags',
sublist: true
},
{
text: this.$strings.LabelSeries,
textPlural: this.$strings.LabelSeries,
value: 'series',
sublist: true
},
{
text: this.$strings.LabelAuthor,
textPlural: this.$strings.LabelAuthors,
value: 'authors',
sublist: true
},
{
text: this.$strings.LabelNarrator,
textPlural: this.$strings.LabelNarrators,
value: 'narrators',
sublist: true
},
{
text: this.$strings.LabelPublisher,
textPlural: this.$strings.LabelPublishers,
value: 'publishers',
sublist: true
},
{
text: this.$strings.LabelLanguage,
textPlural: this.$strings.LabelLanguages,
value: 'languages',
sublist: true
},
@ -227,16 +240,19 @@ export default {
},
{
text: this.$strings.LabelGenre,
textPlural: this.$strings.LabelGenres,
value: 'genres',
sublist: true
},
{
text: this.$strings.LabelTag,
textPlural: this.$strings.LabelTags,
value: 'tags',
sublist: true
},
{
text: this.$strings.LabelLanguage,
textPlural: this.$strings.LabelLanguages,
value: 'languages',
sublist: true
},
@ -255,11 +271,13 @@ export default {
},
{
text: this.$strings.LabelGenre,
textPlural: this.$strings.LabelGenres,
value: 'genres',
sublist: true
},
{
text: this.$strings.LabelTag,
textPlural: this.$strings.LabelTags,
value: 'tags',
sublist: true
},
@ -279,6 +297,13 @@ export default {
selectedItemSublist() {
return this.selected?.includes('.') ? this.selected.split('.')[0] : null
},
selectedSublistText() {
if (!this.sublist) {
return ''
}
const sublistItem = this.selectItems.find((i) => i.value === this.sublist)
return sublistItem?.textPlural || sublistItem?.text || ''
},
selectedText() {
if (!this.selected) return ''
const parts = this.selected.split('.')
@ -505,4 +530,4 @@ export default {
.libraryFilterMenu {
max-height: calc(100vh - 125px);
}
</style>
</style>

View File

@ -0,0 +1,195 @@
<template>
<modals-modal ref="modal" v-model="show" name="share" :width="600" :height="'unset'" :processing="processing">
<template #outer>
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
<p class="text-3xl text-white truncate">Share media item</p>
</div>
</template>
<div class="px-6 py-8 w-full text-sm rounded-lg bg-bg shadow-lg border border-black-300 overflow-y-auto overflow-x-hidden" style="max-height: 80vh">
<template v-if="currentShare">
<div class="w-full py-2">
<label class="px-1 text-sm font-semibold block">Share URL</label>
<ui-text-input v-model="currentShareUrl" readonly class="text-base h-10" />
</div>
<div class="w-full py-2 px-1">
<p v-if="currentShare.expiresAt" class="text-base">Expires in {{ currentShareTimeRemaining }}</p>
<p v-else>Permanent</p>
</div>
</template>
<template v-else>
<div class="flex items-center justify-between space-x-4">
<div class="w-40">
<label class="px-1 text-sm font-semibold block">Slug</label>
<ui-text-input v-model="newShareSlug" class="text-base h-10" />
</div>
<div class="flex-grow" />
<div class="w-80">
<label class="px-1 text-sm font-semibold block">Share Duration</label>
<div class="inline-flex items-center space-x-2">
<div>
<ui-icon-btn icon="remove" :size="10" @click="clickMinus" />
</div>
<ui-text-input v-model="newShareDuration" type="number" text-center no-spinner class="text-center w-28 h-10 text-base" />
<div>
<ui-icon-btn icon="add" :size="10" @click="clickPlus" />
</div>
<ui-dropdown v-model="shareDurationUnit" :items="durationUnits" />
</div>
</div>
</div>
<p class="text-sm text-gray-300 py-4 px-1">
Share URL will be: <span class="">{{ demoShareUrl }}</span>
</p>
</template>
<div class="flex items-center pt-6">
<div class="flex-grow" />
<ui-btn v-if="currentShare" color="error" small @click="deleteShare">{{ $strings.ButtonDelete }}</ui-btn>
<ui-btn v-if="!currentShare" color="success" small @click="openShare">{{ $strings.ButtonShare }}</ui-btn>
</div>
</div>
</modals-modal>
</template>
<script>
export default {
props: {
value: Boolean,
libraryItem: {
type: Object,
default: () => null
},
mediaItemShare: {
type: Object,
default: () => null
}
},
data() {
return {
processing: false,
newShareSlug: '',
newShareDuration: 0,
currentShare: null,
shareDurationUnit: 'minutes',
durationUnits: [
{
text: 'Minutes',
value: 'minutes'
},
{
text: 'Hours',
value: 'hours'
},
{
text: 'Days',
value: 'days'
}
]
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.init()
}
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
user() {
return this.$store.state.user.user
},
demoShareUrl() {
return `${window.origin}/share/${this.newShareSlug}`
},
currentShareUrl() {
if (!this.currentShare) return ''
return `${window.origin}/share/${this.currentShare.slug}`
},
currentShareTimeRemaining() {
if (!this.currentShare) return 'Error'
if (!this.currentShare.expiresAt) return 'Permanent'
const msRemaining = new Date(this.currentShare.expiresAt).valueOf() - Date.now()
if (msRemaining <= 0) return 'Expired'
return this.$elapsedPretty(msRemaining / 1000, true)
},
expireDurationSeconds() {
let shareDuration = Number(this.newShareDuration)
if (!shareDuration || isNaN(shareDuration)) return 0
return this.newShareDuration * (this.shareDurationUnit === 'minutes' ? 60 : this.shareDurationUnit === 'hours' ? 3600 : 86400)
}
},
methods: {
clickPlus() {
this.newShareDuration++
},
clickMinus() {
if (this.newShareDuration > 0) {
this.newShareDuration--
}
},
deleteShare() {
if (!this.currentShare) return
this.processing = true
this.$axios
.$delete(`/api/share/mediaitem/${this.currentShare.id}`)
.then(() => {
this.currentShare = null
this.$emit('removed')
})
.catch((error) => {
console.error('deleteShare', error)
let errorMsg = error.response?.data || 'Failed to delete share'
this.$toast.error(errorMsg)
})
.finally(() => {
this.processing = false
})
},
openShare() {
if (!this.newShareSlug) {
this.$toast.error('Slug is required')
return
}
const payload = {
slug: this.newShareSlug,
mediaItemType: 'book',
mediaItemId: this.libraryItem.media.id,
expiresAt: this.expireDurationSeconds ? Date.now() + this.expireDurationSeconds * 1000 : 0
}
this.processing = true
this.$axios
.$post(`/api/share/mediaitem`, payload)
.then((data) => {
this.currentShare = data
this.$emit('opened', data)
})
.catch((error) => {
console.error('openShare', error)
let errorMsg = error.response?.data || 'Failed to share item'
this.$toast.error(errorMsg)
})
.finally(() => {
this.processing = false
})
},
init() {
this.newShareSlug = this.$randomId(10)
if (this.mediaItemShare) {
this.currentShare = { ...this.mediaItemShare }
} else {
this.currentShare = null
}
}
},
mounted() {}
}
</script>

View File

@ -53,7 +53,7 @@
<p class="font-mono text-sm hidden sm:block text-gray-100 pointer-events-auto">&nbsp;/&nbsp;{{ progressPercent }}%</p>
<div class="flex-grow" />
<p class="text-xs sm:text-sm text-gray-300 pt-0.5">
{{ currentChapterName }} <span v-if="useChapterTrack" class="text-xs text-gray-400">&nbsp;({{ currentChapterIndex + 1 }} of {{ chapters.length }})</span>
{{ currentChapterName }} <span v-if="useChapterTrack" class="text-xs text-gray-400">&nbsp;({{ $getString('LabelPlayerChapterNumberMarker', [currentChapterIndex + 1, chapters.length]) }})</span>
</p>
<div class="flex-grow" />
<p class="font-mono text-xxs sm:text-sm text-gray-100 pointer-events-auto">{{ timeRemainingPretty }}</p>

View File

@ -3,7 +3,7 @@
<div class="absolute top-0 left-0 right-0 w-full h-36 bg-gradient-to-t from-transparent via-black-500 to-black-700 opacity-90 pointer-events-none" />
<div ref="content" class="relative text-white" :style="{ height: modalHeight, width: modalWidth }" v-click-outside="clickedOutside">
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300">
<p class="text-lg mb-6 mt-2 px-1" v-html="message" />
<p id="confirm-prompt-message" class="text-lg mb-6 mt-2 px-1" v-html="message" />
<ui-checkbox v-if="checkboxLabel" v-model="checkboxValue" checkbox-bg="bg" :label="checkboxLabel" label-class="pl-2 text-base" class="mb-6 px-1" />
@ -131,4 +131,14 @@ export default {
}
}
}
</script>
</script>
<style>
#confirm-prompt-message code {
font-size: 1rem;
border-radius: 6px;
background-color: rgb(82, 82, 82);
color: white;
padding: 2px 4px;
}
</style>

View File

@ -179,7 +179,7 @@ export default {
ebookLocation: this.page,
ebookProgress: Math.max(0, Math.min(1, (Number(this.page) - 1) / Number(this.numPages)))
}
this.$axios.$patch(`/api/me/progress/${this.libraryItemId}`, payload).catch((error) => {
this.$axios.$patch(`/api/me/progress/${this.libraryItemId}`, payload, { progress: false }).catch((error) => {
console.error('ComicReader.updateProgress failed:', error)
})
},
@ -386,4 +386,4 @@ export default {
.pagemenu {
max-height: calc(100% - 48px);
}
</style>
</style>

View File

@ -46,7 +46,8 @@ export default {
font: 'serif',
fontScale: 100,
lineSpacing: 115,
spread: 'auto'
spread: 'auto',
textStroke: 0
}
}
},
@ -109,11 +110,14 @@ export default {
const fontScale = this.ereaderSettings.fontScale / 100
const textStroke = this.ereaderSettings.textStroke / 100
return {
'*': {
color: `${fontColor}!important`,
'background-color': `${backgroundColor}!important`,
'line-height': lineSpacing * fontScale + 'rem!important'
'line-height': lineSpacing * fontScale + 'rem!important',
'-webkit-text-stroke': textStroke + 'px ' + fontColor + '!important'
},
a: {
color: `${fontColor}!important`
@ -195,7 +199,7 @@ export default {
*/
updateProgress(payload) {
if (!this.keepProgress) return
this.$axios.$patch(`/api/me/progress/${this.libraryItemId}`, payload).catch((error) => {
this.$axios.$patch(`/api/me/progress/${this.libraryItemId}`, payload, { progress: false }).catch((error) => {
console.error('EpubReader.updateProgress failed:', error)
})
},

View File

@ -23,13 +23,10 @@
<div class="flex items-center justify-center">
<div :style="{ width: pdfWidth + 'px', height: pdfHeight + 'px' }" class="overflow-auto">
<div v-if="loadedRatio > 0 && loadedRatio < 1" style="background-color: green; color: white; text-align: center" :style="{ width: loadedRatio * 100 + '%' }">{{ Math.floor(loadedRatio * 100) }}%</div>
<pdf ref="pdf" class="m-auto z-10 border border-black border-opacity-20 shadow-md" :src="pdfDocInitParams" :page="page" :rotate="rotate" @progress="progressEvt" @error="error" @num-pages="numPagesLoaded" @link-clicked="page = $event" @loaded="loadedEvt"></pdf>
<pdf v-if="pdfDocInitParams" ref="pdf" class="m-auto z-10 border border-black border-opacity-20 shadow-md" :src="pdfDocInitParams" :page="page" :rotate="rotate" @progress="progressEvt" @error="error" @num-pages="numPagesLoaded" @link-clicked="page = $event" @loaded="loadedEvt"></pdf>
</div>
</div>
</div>
<!-- <div class="text-center py-2 text-lg">
<p>{{ page }} / {{ numPages }}</p>
</div> -->
</div>
</template>
@ -57,7 +54,8 @@ export default {
rotate: 0,
loadedRatio: 0,
page: 1,
numPages: 0
numPages: 0,
pdfDocInitParams: null
}
},
computed: {
@ -108,14 +106,6 @@ export default {
return `/api/items/${this.libraryItemId}/ebook/${this.fileId}`
}
return `/api/items/${this.libraryItemId}/ebook`
},
pdfDocInitParams() {
return {
url: this.ebookUrl,
httpHeaders: {
Authorization: `Bearer ${this.userToken}`
}
}
}
},
methods: {
@ -136,7 +126,7 @@ export default {
ebookLocation: this.page,
ebookProgress: Math.max(0, Math.min(1, (Number(this.page) - 1) / Number(this.numPages)))
}
this.$axios.$patch(`/api/me/progress/${this.libraryItemId}`, payload).catch((error) => {
this.$axios.$patch(`/api/me/progress/${this.libraryItemId}`, payload, { progress: false }).catch((error) => {
console.error('EpubReader.updateProgress failed:', error)
})
},
@ -149,6 +139,7 @@ export default {
this.loadedRatio = progress
},
numPagesLoaded(e) {
if (!e) return
this.numPages = e
},
prev() {
@ -167,15 +158,25 @@ export default {
resize() {
this.windowWidth = window.innerWidth
this.windowHeight = window.innerHeight
},
init() {
this.pdfDocInitParams = {
url: this.ebookUrl,
httpHeaders: {
Authorization: `Bearer ${this.userToken}`
}
}
}
},
mounted() {
this.windowWidth = window.innerWidth
this.windowHeight = window.innerHeight
window.addEventListener('resize', this.resize)
this.init()
},
beforeDestroy() {
window.removeEventListener('resize', this.resize)
}
}
</script>
</script>

View File

@ -98,6 +98,12 @@
</div>
<ui-range-input v-model="ereaderSettings.lineSpacing" :min="100" :max="300" :step="5" @input="settingsUpdated" />
</div>
<div class="flex items-center mb-4">
<div class="w-40">
<p class="text-lg">{{ $strings.LabelFontBoldness }}:</p>
</div>
<ui-range-input v-model="ereaderSettings.textStroke" :min="0" :max="300" :step="5" @input="settingsUpdated" />
</div>
<div class="flex items-center">
<div class="w-40">
<p class="text-lg">{{ $strings.LabelLayout }}:</p>
@ -130,7 +136,9 @@ export default {
font: 'serif',
fontScale: 100,
lineSpacing: 115,
spread: 'auto'
fontBoldness: 100,
spread: 'auto',
textStroke: 0
}
}
},
@ -378,7 +386,12 @@ export default {
try {
const settings = localStorage.getItem('ereaderSettings')
if (settings) {
this.ereaderSettings = JSON.parse(settings)
const _ereaderSettings = JSON.parse(settings)
for (const key in this.ereaderSettings) {
if (_ereaderSettings[key] !== undefined) {
this.ereaderSettings[key] = _ereaderSettings[key]
}
}
this.settingsUpdated()
}
} catch (error) {
@ -416,4 +429,4 @@ export default {
height: 100%;
}
}
</style>
</style>

View File

@ -15,7 +15,7 @@
<th class="text-left w-16"><span class="px-4">Id</span></th>
<th class="text-left">{{ $strings.LabelTitle }}</th>
<th class="text-center">{{ $strings.LabelStart }}</th>
<th class="text-center">{{ $strings.LabelEnd }}</th>
<th class="text-center">{{ $strings.LabelDuration }}</th>
</tr>
<tr v-for="chapter in chapters" :key="chapter.id">
<td class="text-left">
@ -27,8 +27,8 @@
<td class="font-mono text-center hover:underline cursor-pointer" @click.stop="goToTimestamp(chapter.start)">
{{ $secondsToTimestamp(chapter.start) }}
</td>
<td class="font-mono text-center hover:underline cursor-pointer" @click.stop="goToTimestamp(chapter.start)">
{{ $secondsToTimestamp(chapter.end) }}
<td class="font-mono text-center">
{{ $secondsToTimestamp(Math.max(0, chapter.end - chapter.start)) }}
</td>
</tr>
</table>

View File

@ -21,7 +21,7 @@
</tr>
</table>
<div v-else-if="!processing" class="text-center py-8">
<p class="text-lg">No custom metadata providers</p>
<p class="text-lg">{{ $strings.LabelNoCustomMetadataProviders }}</p>
</div>
<div v-if="processing" class="absolute inset-0 h-full flex items-center justify-center bg-black/40 rounded-md">

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
<div class="w-full border border-white/10 rounded-xl p-4 my-4 bg-primary/25">
<div class="flex items-center">
<ui-checkbox v-model="showCustomLoginMessage" checkbox-bg="bg" />
<p class="text-lg pl-4">Custom Message on Login</p>
<p class="text-lg pl-4">{{ $strings.HeaderCustomMessageOnLogin }}</p>
</div>
<transition name="slide">
<div v-if="showCustomLoginMessage" class="w-full pt-4">

View File

@ -1,10 +1,27 @@
<template>
<div>
<app-settings-content :header-text="$strings.HeaderBackups" :description="$strings.MessageBackupsDescription">
<div v-if="backupLocation" class="flex items-center mb-4">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">folder</span>
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelBackupLocation }}:</span>
<div class="text-gray-100 pl-4">{{ backupLocation }}</div>
<div v-if="backupLocation" class="mb-4 max-w-full overflow-hidden">
<div class="flex items-center mb-0.5">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">folder</span>
<span class="text-white text-opacity-60 uppercase text-sm whitespace-nowrap">{{ $strings.LabelBackupLocation }}:</span>
</div>
<div v-if="!showEditBackupPath" class="inline-flex items-center w-full overflow-hidden">
<p class="text-gray-100 max-w-[calc(100%-40px)] text-sm sm:text-base break-words">{{ backupLocation }}</p>
<div class="w-10 min-w-10 flex items-center justify-center">
<button class="text-black-50 hover:text-yellow-500 inline-flex" type="button" @click="showEditBackupPath = !showEditBackupPath">
<span class="material-icons text-lg">edit</span>
</button>
</div>
</div>
<div v-else>
<form class="flex items-center w-full space-x-1" @submit.prevent="saveBackupPath">
<ui-text-input v-model="newBackupLocation" :disabled="savingBackupPath" class="w-full max-w-[calc(100%-50px)] text-sm h-8" />
<ui-btn small :loading="savingBackupPath" color="success" type="submit" class="h-8">{{ $strings.ButtonSave }}</ui-btn>
<ui-btn small :disabled="savingBackupPath" type="button" class="h-8" @click="cancelEditBackupPath">{{ $strings.ButtonCancel }}</ui-btn>
</form>
<p class="text-sm text-warning/80 pt-1">{{ $strings.MessageBackupsLocationEditNote }}</p>
</div>
</div>
<div class="flex items-center py-2">
@ -15,21 +32,23 @@
</div>
<div v-if="enableBackups" class="mb-6">
<div class="flex items-center pl-6 mb-2">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">schedule</span>
<div class="w-40">
<div class="flex items-center pl-0 sm:pl-6 mb-2">
<span class="material-icons-outlined text-xl sm:text-2xl text-black-50 mr-2">schedule</span>
<div class="w-32 min-w-32 sm:w-40 sm:min-w-40">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.HeaderSchedule }}:</span>
</div>
<div class="text-gray-100">{{ scheduleDescription }}</div>
<span class="material-icons text-lg text-black-50 hover:text-yellow-500 cursor-pointer ml-2" @click="showCronBuilder = !showCronBuilder">edit</span>
<div class="text-gray-100 text-sm sm:text-base">{{ scheduleDescription }}</div>
<button class="ml-2 text-black-50 hover:text-yellow-500 inline-flex" type="button" @click="showCronBuilder = !showCronBuilder">
<span class="material-icons text-lg">edit</span>
</button>
</div>
<div v-if="nextBackupDate" class="flex items-center pl-6 py-0.5 px-2">
<span class="material-icons-outlined text-2xl text-black-50 mr-2">event</span>
<div class="w-40">
<div v-if="nextBackupDate" class="flex items-center pl-0 sm:pl-6 py-0.5">
<span class="material-icons-outlined text-xl sm:text-2xl text-black-50 mr-2">event</span>
<div class="w-32 min-w-32 sm:w-40 sm:min-w-40">
<span class="text-white text-opacity-60 uppercase text-sm">{{ $strings.LabelNextBackupDate }}:</span>
</div>
<div class="text-gray-100">{{ nextBackupDate }}</div>
<div class="text-gray-100 text-sm sm:text-base">{{ nextBackupDate }}</div>
</div>
</div>
@ -49,7 +68,7 @@
</ui-tooltip>
</div>
<tables-backups-table @loaded="backupsLoaded" />
<tables-backups-table ref="backupsTable" @loaded="backupsLoaded" />
<modals-backup-schedule-modal v-model="showCronBuilder" :cron-expression.sync="cronExpression" />
</app-settings-content>
@ -72,7 +91,10 @@ export default {
cronExpression: '',
newServerSettings: {},
showCronBuilder: false,
backupLocation: ''
showEditBackupPath: false,
backupLocation: '',
newBackupLocation: '',
savingBackupPath: false
}
},
watch: {
@ -107,6 +129,39 @@ export default {
methods: {
backupsLoaded(backupLocation) {
this.backupLocation = backupLocation
this.newBackupLocation = backupLocation
},
cancelEditBackupPath() {
this.newBackupLocation = this.backupLocation
this.showEditBackupPath = false
},
saveBackupPath() {
if (!this.newBackupLocation?.trim()) {
this.$toast.error(this.$strings.MessageBackupsLocationPathEmpty)
return
}
this.newBackupLocation = this.newBackupLocation.trim()
if (this.newBackupLocation === this.backupLocation) {
this.showEditBackupPath = false
return
}
this.savingBackupPath = true
this.$axios
.patch('/api/backups/path', { path: this.newBackupLocation })
.then(() => {
this.backupLocation = this.newBackupLocation
this.showEditBackupPath = false
this.$refs.backupsTable.loadBackups()
})
.catch((error) => {
console.error('Failed to save backup path', error)
const errorMsg = error.response?.data || 'Failed to save backup path'
this.$toast.error(errorMsg)
})
.finally(() => {
this.savingBackupPath = false
})
},
updateBackupsSettings() {
if (isNaN(this.maxBackupSize) || this.maxBackupSize <= 0) {

View File

@ -368,7 +368,8 @@ export default {
},
purgeItemsCache() {
const payload = {
message: `<span class="text-warning text-base">Warning! This will delete the entire folder at /metadata/cache/items.</span><br />Are you sure you want to purge items cache?`,
// message: `This will delete the entire folder at <code>/metadata/cache/items</code>.<br />Are you sure you want to purge items cache?`,
message: this.$strings.MessageConfirmPurgeItemsCache,
callback: (confirmed) => {
if (confirmed) {
this.sendPurgeItemsCache()

View File

@ -147,6 +147,7 @@
</div>
</div>
<modals-share-modal v-model="showShareModal" :media-item-share="mediaItemShare" :library-item="libraryItem" @opened="openedShare" @removed="removedShare" />
<modals-podcast-episode-feed v-model="showPodcastEpisodeFeed" :library-item="libraryItem" :episodes="podcastFeedEpisodes" />
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :library-item-id="libraryItemId" hide-create @select="selectBookmark" />
</div>
@ -160,7 +161,7 @@ export default {
}
// Include episode downloads for podcasts
var item = await app.$axios.$get(`/api/items/${params.id}?expanded=1&include=downloads,rssfeed`).catch((error) => {
var item = await app.$axios.$get(`/api/items/${params.id}?expanded=1&include=downloads,rssfeed,share`).catch((error) => {
console.error('Failed', error)
return false
})
@ -170,7 +171,8 @@ export default {
}
return {
libraryItem: item,
rssFeed: item.rssFeed || null
rssFeed: item.rssFeed || null,
mediaItemShare: item.mediaItemShare || null
}
},
data() {
@ -184,7 +186,8 @@ export default {
episodeDownloadsQueued: [],
showBookmarksModal: false,
isDescriptionClamped: false,
showFullDescription: false
showFullDescription: false,
showShareModal: false
}
},
computed: {
@ -437,6 +440,13 @@ export default {
})
}
if (this.userIsAdminOrUp && !this.isPodcast) {
items.push({
text: 'Share',
action: 'share'
})
}
if (this.userCanDelete) {
items.push({
text: this.$strings.ButtonDelete,
@ -448,6 +458,12 @@ export default {
}
},
methods: {
openedShare(mediaItemShare) {
this.mediaItemShare = mediaItemShare
},
removedShare() {
this.mediaItemShare = null
},
selectBookmark(bookmark) {
if (!bookmark) return
if (this.isStreaming) {
@ -761,6 +777,8 @@ export default {
this.deleteLibraryItem()
} else if (action === 'sendToDevice') {
this.sendToDevice(data)
} else if (action === 'share') {
this.showShareModal = true
}
}
},

View File

@ -0,0 +1,34 @@
<template>
<div id="page-wrapper" class="w-full h-screen overflow-y-auto">
<div class="w-full h-full flex items-center justify-center">
<p class="text-xl">{{ mediaItemShare.mediaItem.title }}</p>
</div>
</div>
</template>
<script>
export default {
layout: 'blank',
async asyncData({ params, error, app }) {
const mediaItemShare = await app.$axios.$get(`/public/share/${params.slug}`).catch((error) => {
console.error('Failed', error)
return null
})
if (!mediaItemShare) {
return error({ statusCode: 404, message: 'Not found' })
}
return {
mediaItemShare: mediaItemShare
}
},
data() {
return {}
},
computed: {},
methods: {},
mounted() {
console.log('Loaded media item share', this.mediaItemShare)
}
}
</script>

View File

@ -29,4 +29,4 @@ export default class AudioTrack {
return this.contentUrl + `?token=${this.userToken}`
}
}
}

View File

@ -1,13 +1,22 @@
function getMediaInfoFromTrack(libraryItem, castImage, track) {
// https://developers.google.com/cast/docs/reference/web_sender/chrome.cast.media.AudiobookChapterMediaMetadata
var metadata = new chrome.cast.media.AudiobookChapterMediaMetadata()
metadata.bookTitle = libraryItem.media.metadata.title
metadata.chapterNumber = track.index
metadata.chapterTitle = track.title
metadata.images = [castImage]
metadata.title = track.title
metadata.subtitle = libraryItem.media.metadata.title
let metadata = null
if (libraryItem.mediaType === 'podcast') {
metadata = new chrome.cast.media.MusicTrackMediaMetadata()
metadata.albumArtist = libraryItem.media.metadata.author
metadata.artist = libraryItem.media.metadata.author
metadata.title = track.title
metadata.albumName = libraryItem.media.metadata.title
metadata.images = [castImage]
} else {
// https://developers.google.com/cast/docs/reference/web_sender/chrome.cast.media.AudiobookChapterMediaMetadata
metadata = new chrome.cast.media.AudiobookChapterMediaMetadata()
metadata.bookTitle = libraryItem.media.metadata.title
metadata.chapterNumber = track.index
metadata.chapterTitle = track.title
metadata.images = [castImage]
metadata.title = track.title
metadata.subtitle = libraryItem.media.metadata.title
}
var trackurl = track.fullContentUrl
var mimeType = track.mimeType
@ -20,17 +29,25 @@ function getMediaInfoFromTrack(libraryItem, castImage, track) {
function buildCastMediaInfo(libraryItem, coverUrl, tracks) {
const castImage = new chrome.cast.Image(coverUrl)
return tracks.map(t => getMediaInfoFromTrack(libraryItem, castImage, t))
return tracks.map((t) => getMediaInfoFromTrack(libraryItem, castImage, t))
}
function buildCastQueueRequest(libraryItem, coverUrl, tracks, startTime) {
var mediaInfoItems = buildCastMediaInfo(libraryItem, coverUrl, tracks)
var containerMetadata = new chrome.cast.media.AudiobookContainerMetadata()
containerMetadata.authors = libraryItem.media.metadata.authors.map(a => a.name)
containerMetadata.narrators = libraryItem.media.metadata.narrators || []
containerMetadata.publisher = libraryItem.media.metadata.publisher || undefined
containerMetadata.title = libraryItem.media.metadata.title
let containerMetadata = null
let queueType = chrome.cast.media.QueueType.AUDIOBOOK
if (libraryItem.mediaType === 'podcast') {
queueType = chrome.cast.media.QueueType.PODCAST_SERIES
containerMetadata = new chrome.cast.media.ContainerMetadata(chrome.cast.media.ContainerType.GENERIC_CONTAINER)
containerMetadata.title = libraryItem.media.metadata.title
} else {
containerMetadata = new chrome.cast.media.AudiobookContainerMetadata()
containerMetadata.authors = libraryItem.media.metadata.authors?.map((a) => a.name)
containerMetadata.narrators = libraryItem.media.metadata.narrators || []
containerMetadata.publisher = libraryItem.media.metadata.publisher || undefined
containerMetadata.title = libraryItem.media.metadata.title
}
var mediaQueueItems = mediaInfoItems.map((mi) => {
var queueItem = new chrome.cast.media.QueueItem(mi)
@ -38,23 +55,25 @@ function buildCastQueueRequest(libraryItem, coverUrl, tracks, startTime) {
})
// Find track to start playback and calculate track start offset
var track = tracks.find(at => at.startOffset <= startTime && at.startOffset + at.duration > startTime)
var track = tracks.find((at) => at.startOffset <= startTime && at.startOffset + at.duration > startTime)
var trackStartIndex = track ? track.index - 1 : 0
var trackStartTime = Math.floor(track ? startTime - track.startOffset : 0)
var queueData = new chrome.cast.media.QueueData(libraryItem.id, libraryItem.media.metadata.title, '', false, mediaQueueItems, trackStartIndex, trackStartTime)
queueData.containerMetadata = containerMetadata
queueData.queueType = chrome.cast.media.QueueType.AUDIOBOOK
queueData.queueType = queueType
return queueData
}
function castLoadMedia(castSession, request) {
return new Promise((resolve) => {
castSession.loadMedia(request)
.then(() => resolve(true), (reason) => {
castSession.loadMedia(request).then(
() => resolve(true),
(reason) => {
console.error('Load media failed', reason)
resolve(false)
})
}
)
})
}
@ -69,7 +88,4 @@ function buildCastLoadRequest(libraryItem, coverUrl, tracks, startTime, autoplay
return request
}
export {
buildCastLoadRequest,
castLoadMedia
}
export { buildCastLoadRequest, castLoadMedia }

View File

@ -1,36 +1,37 @@
import Vue from "vue"
import Vue from 'vue'
import enUsStrings from '../strings/en-us.json'
import { supplant } from './utils'
const defaultCode = 'en-us'
const languageCodeMap = {
'bg': { label: 'Български', dateFnsLocale: 'bg' },
'bn': { label: 'বাংলা', dateFnsLocale: 'bn' },
'cs': { label: 'Čeština', dateFnsLocale: 'cs' },
'da': { label: 'Dansk', dateFnsLocale: 'da' },
'de': { label: 'Deutsch', dateFnsLocale: 'de' },
bg: { label: 'Български', dateFnsLocale: 'bg' },
bn: { label: 'বাংলা', dateFnsLocale: 'bn' },
cs: { label: 'Čeština', dateFnsLocale: 'cs' },
da: { label: 'Dansk', dateFnsLocale: 'da' },
de: { label: 'Deutsch', dateFnsLocale: 'de' },
'en-us': { label: 'English', dateFnsLocale: 'enUS' },
'es': { label: 'Español', dateFnsLocale: 'es' },
'et': { label: 'Eesti', dateFnsLocale: 'et' },
'fr': { label: 'Français', dateFnsLocale: 'fr' },
'he': { label: 'עברית', dateFnsLocale: 'he' },
'hr': { label: 'Hrvatski', dateFnsLocale: 'hr' },
'it': { label: 'Italiano', dateFnsLocale: 'it' },
'lt': { label: 'Lietuvių', dateFnsLocale: 'lt' },
'hu': { label: 'Magyar', dateFnsLocale: 'hu' },
'nl': { label: 'Nederlands', dateFnsLocale: 'nl' },
'no': { label: 'Norsk', dateFnsLocale: 'no' },
'pl': { label: 'Polski', dateFnsLocale: 'pl' },
es: { label: 'Español', dateFnsLocale: 'es' },
et: { label: 'Eesti', dateFnsLocale: 'et' },
fi: { label: 'Suomi', dateFnsLocale: 'fi' },
fr: { label: 'Français', dateFnsLocale: 'fr' },
he: { label: 'עברית', dateFnsLocale: 'he' },
hr: { label: 'Hrvatski', dateFnsLocale: 'hr' },
it: { label: 'Italiano', dateFnsLocale: 'it' },
lt: { label: 'Lietuvių', dateFnsLocale: 'lt' },
hu: { label: 'Magyar', dateFnsLocale: 'hu' },
nl: { label: 'Nederlands', dateFnsLocale: 'nl' },
no: { label: 'Norsk', dateFnsLocale: 'no' },
pl: { label: 'Polski', dateFnsLocale: 'pl' },
'pt-br': { label: 'Português (Brasil)', dateFnsLocale: 'ptBR' },
'ru': { label: 'Русский', dateFnsLocale: 'ru' },
'sv': { label: 'Svenska', dateFnsLocale: 'sv' },
'uk': { label: 'Українська', dateFnsLocale: 'uk' },
ru: { label: 'Русский', dateFnsLocale: 'ru' },
sv: { label: 'Svenska', dateFnsLocale: 'sv' },
uk: { label: 'Українська', dateFnsLocale: 'uk' },
'vi-vn': { label: 'Tiếng Việt', dateFnsLocale: 'vi' },
'zh-cn': { label: '简体中文 (Simplified Chinese)', dateFnsLocale: 'zhCN' },
'zh-tw': { label: '正體中文 (Traditional Chinese)', dateFnsLocale: 'zhTW' }
}
Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map(code => {
Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map((code) => {
return {
text: languageCodeMap[code].label,
value: code
@ -39,34 +40,34 @@ Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map(code => {
// iTunes search API uses ISO 3166 country codes: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
const podcastSearchRegionMap = {
'br': { label: 'Brasil' },
'be': { label: 'België / Belgique / Belgien' },
'cz': { label: 'Česko' },
'dk': { label: 'Danmark' },
'de': { label: 'Deutschland' },
'ee': { label: 'Eesti' },
'es': { label: 'España / Espanya / Espainia' },
'fr': { label: 'France' },
'hr': { label: 'Hrvatska' },
'il': { label: 'ישראל / إسرائيل' },
'it': { label: 'Italia' },
'lu': { label: 'Luxembourg / Luxemburg / Lëtezebuerg' },
'hu': { label: 'Magyarország' },
'nl': { label: 'Nederland' },
'no': { label: 'Norge' },
'at': { label: 'Österreich' },
'pl': { label: 'Polska' },
'pt': { label: 'Portugal' },
'ru': { label: 'Россия' },
'ch': { label: 'Schweiz / Suisse / Svizzera' },
'se': { label: 'Sverige' },
'vn': { label: 'Việt Nam' },
'ua': { label: 'Україна' },
'gb': { label: 'United Kingdom' },
'us': { label: 'United States' },
'cn': { label: '中国' }
br: { label: 'Brasil' },
be: { label: 'België / Belgique / Belgien' },
cz: { label: 'Česko' },
dk: { label: 'Danmark' },
de: { label: 'Deutschland' },
ee: { label: 'Eesti' },
es: { label: 'España / Espanya / Espainia' },
fr: { label: 'France' },
hr: { label: 'Hrvatska' },
il: { label: 'ישראל / إسرائيل' },
it: { label: 'Italia' },
lu: { label: 'Luxembourg / Luxemburg / Lëtezebuerg' },
hu: { label: 'Magyarország' },
nl: { label: 'Nederland' },
no: { label: 'Norge' },
at: { label: 'Österreich' },
pl: { label: 'Polska' },
pt: { label: 'Portugal' },
ru: { label: 'Россия' },
ch: { label: 'Schweiz / Suisse / Svizzera' },
se: { label: 'Sverige' },
vn: { label: 'Việt Nam' },
ua: { label: 'Україна' },
gb: { label: 'United Kingdom' },
us: { label: 'United States' },
cn: { label: '中国' }
}
Vue.prototype.$podcastSearchRegionOptions = Object.keys(podcastSearchRegionMap).map(code => {
Vue.prototype.$podcastSearchRegionOptions = Object.keys(podcastSearchRegionMap).map((code) => {
return {
text: podcastSearchRegionMap[code].label,
value: code
@ -85,9 +86,9 @@ Vue.prototype.$strings = { ...enUsStrings }
/**
* Get string and substitute
*
* @param {string} key
* @param {string[]} subs
*
* @param {string} key
* @param {string[]} subs
* @returns {string}
*/
Vue.prototype.$getString = (key, subs) => {
@ -108,12 +109,14 @@ const translations = {
function loadTranslationStrings(code) {
return new Promise((resolve) => {
import(`../strings/${code}`).then((fileContents) => {
resolve(fileContents.default)
}).catch((error) => {
console.error('Failed to load i18n strings', code, error)
resolve(null)
})
import(`../strings/${code}`)
.then((fileContents) => {
resolve(fileContents.default)
})
.catch((error) => {
console.error('Failed to load i18n strings', code, error)
resolve(null)
})
})
}
@ -124,7 +127,7 @@ async function loadi18n(code) {
return false
}
const strings = translations[code] || await loadTranslationStrings(code)
const strings = translations[code] || (await loadTranslationStrings(code))
if (!strings) {
console.warn(`Invalid lang code ${code}`)
return false
@ -174,4 +177,3 @@ async function initialize() {
}
}
initialize()

View File

@ -2,7 +2,10 @@ import Vue from 'vue'
import cronParser from 'cron-parser'
import { nanoid } from 'nanoid'
Vue.prototype.$randomId = () => nanoid()
Vue.prototype.$randomId = (len = null) => {
if (len && !isNaN(len)) return nanoid(len)
return nanoid()
}
Vue.prototype.$bytesPretty = (bytes, decimals = 2) => {
if (isNaN(bytes) || bytes == 0) {
@ -119,7 +122,7 @@ Vue.prototype.$parseCronExpression = (expression) => {
value: '* * * * *'
}
]
const patternMatch = commonPatterns.find(p => p.value === expression)
const patternMatch = commonPatterns.find((p) => p.value === expression)
if (patternMatch) {
return {
description: patternMatch.text
@ -132,13 +135,17 @@ Vue.prototype.$parseCronExpression = (expression) => {
if (pieces[2] !== '*' || pieces[3] !== '*') {
return null
}
if (pieces[4] !== '*' && pieces[4].split(',').some(p => isNaN(p))) {
if (pieces[4] !== '*' && pieces[4].split(',').some((p) => isNaN(p))) {
return null
}
const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
var weekdayText = 'day'
if (pieces[4] !== '*') weekdayText = pieces[4].split(',').map(p => weekdays[p]).join(', ')
if (pieces[4] !== '*')
weekdayText = pieces[4]
.split(',')
.map((p) => weekdays[p])
.join(', ')
return {
description: `Run every ${weekdayText} at ${pieces[1]}:${pieces[0].padStart(2, '0')}`
@ -146,7 +153,7 @@ Vue.prototype.$parseCronExpression = (expression) => {
}
Vue.prototype.$getNextScheduledDate = (expression) => {
const interval = cronParser.parseExpression(expression);
const interval = cronParser.parseExpression(expression)
return interval.next().toDate()
}
@ -171,10 +178,8 @@ Vue.prototype.$downloadFile = (url, filename = null, openInNewTab = false) => {
export function supplant(str, subs) {
// source: http://crockford.com/javascript/remedial.html
return str.replace(/{([^{}]*)}/g,
function (a, b) {
var r = subs[b]
return typeof r === 'string' || typeof r === 'number' ? r : a
}
)
return str.replace(/{([^{}]*)}/g, function (a, b) {
var r = subs[b]
return typeof r === 'string' || typeof r === 'number' ? r : a
})
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Приложи",
"ButtonApplyChapters": "Приложи Глави",
"ButtonAuthors": "Автори",
"ButtonBack": "Назад",
"ButtonBrowseForFolder": "Прегледай за папка",
"ButtonCancel": "Откажи",
"ButtonCancelEncode": "Откажи закодирането",
@ -56,21 +57,20 @@
"ButtonPreviousChapter": "Предишна Глава",
"ButtonPurgeAllCache": "Изчисти Всички Кешове",
"ButtonPurgeItemsCache": "Изчисти Кеша на Елементи",
"ButtonPurgeMediaProgress": "Изчисти Прогреса на Медията",
"ButtonQueueAddItem": "Добави към опашката",
"ButtonQueueRemoveItem": "Премахни от опашката",
"ButtonQuickMatch": "Бързо Съпоставяне",
"ButtonReScan": "Пресканирай",
"ButtonRead": "Прочети",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
"ButtonRefresh": "Refresh",
"ButtonReadLess": "Покажи по-малко",
"ButtonReadMore": "Покажи повече",
"ButtonRefresh": "Обнови",
"ButtonRemove": "Премахни",
"ButtonRemoveAll": "Премахни Всички",
"ButtonRemoveAllLibraryItems": "Премахни Всички Елементи от Библиотеката",
"ButtonRemoveFromContinueListening": "Премахни от Продължаване на Слушане",
"ButtonRemoveFromContinueReading": "Премахни от Продължаване на Четене",
"ButtonRemoveSeriesFromContinueSeries": "Премахни Серия от Продължаване на Серии",
"ButtonReScan": "Пресканирай",
"ButtonReset": "Нулиране",
"ButtonResetToDefault": "Нулиране до стойност по подразбиране",
"ButtonRestore": "Възстанови",
@ -83,7 +83,7 @@
"ButtonSelectFolderPath": "Избери Път на Папка",
"ButtonSeries": "Серии",
"ButtonSetChaptersFromTracks": "Задай Глави от Песни",
"ButtonShare": "Share",
"ButtonShare": "Сподели",
"ButtonShiftTimes": "Измести Времената",
"ButtonShow": "Покажи",
"ButtonStartM4BEncode": "Започни M4B Кодиране",
@ -98,16 +98,16 @@
"ButtonUserEdit": "Редактирай Потребител {0}",
"ButtonViewAll": "Виж Всички",
"ButtonYes": "Да",
"ErrorUploadFetchMetadataAPI": "Грешка при Взимане на Метаданни ",
"ErrorUploadFetchMetadataAPI": "Грешка при Взимане на Метаданни",
"ErrorUploadFetchMetadataNoResults": "Метаданните не могат да бъдат взети - опитайте да обновите заглавието и/или автора",
"ErrorUploadLacksTitle": "Трябва да има Заглавие",
"HeaderAccount": "Профил",
"HeaderAdvanced": "Разширени",
"HeaderAppriseNotificationSettings": "Apprise Notification Опции",
"HeaderAudiobookTools": "Инструмент за Менижиране на Аудиокниги ",
"HeaderAudioTracks": "Звуков Канал",
"HeaderAudiobookTools": "Инструмент за Менижиране на Аудиокниги",
"HeaderAuthentication": "Аутентикация",
"HeaderBackups": "Backups",
"HeaderBackups": "Архив",
"HeaderChangePassword": "Промяна на Парола",
"HeaderChapters": "Глави",
"HeaderChooseAFolder": "Избети Папка",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Елементи на Колекция",
"HeaderCover": "Корица",
"HeaderCurrentDownloads": "Текущи Сваляния",
"HeaderCustomMessageOnLogin": "Потребителско съобщение при влизане",
"HeaderCustomMetadataProviders": "Потребителски Доставчици на Метаданни",
"HeaderDetails": "Детайли",
"HeaderDownloadQueue": "Опашка за Сваляне",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Елементи на Плейлист",
"HeaderPodcastsToAdd": "Подкасти за Добавяне",
"HeaderPreviewCover": "Преглед на Корица",
"HeaderRemoveEpisode": "Премахни Епизод",
"HeaderRemoveEpisodes": "Премахни {0} Епизоди",
"HeaderRSSFeedGeneral": "RSS Детайли",
"HeaderRSSFeedIsOpen": "RSS Feed е Отворен",
"HeaderRSSFeeds": "RSS Feed-ове",
"HeaderRemoveEpisode": "Премахни Епизод",
"HeaderRemoveEpisodes": "Премахни {0} Епизоди",
"HeaderSavedMediaProgress": "Запазен Прогрес на Медията",
"HeaderSchedule": "График",
"HeaderScheduleLibraryScans": "График за Автоматично Сканиране на Библиотека",
@ -186,23 +187,23 @@
"HeaderUpdateDetails": "Обнови Детайли",
"HeaderUpdateLibrary": "Обнови Библиотека",
"HeaderUsers": "Потребители",
"HeaderYearReview": "Year {0} in Review",
"HeaderYearReview": "Преглед на {0} Година",
"HeaderYourStats": "Твоята Статистика",
"LabelAbridged": "Съкратен",
"LabelAbridgedChecked": "Abridged (checked)",
"LabelAbridgedUnchecked": "Unabridged (unchecked)",
"LabelAccessibleBy": "Accessible by",
"LabelAbridgedChecked": "Съкратена (отбелязано)",
"LabelAbridgedUnchecked": "Несъкратена (не отбелязано)",
"LabelAccessibleBy": "Достъпно от",
"LabelAccountType": "Тип на Профила",
"LabelAccountTypeAdmin": "Администратор",
"LabelAccountTypeGuest": "Гост",
"LabelAccountTypeUser": "Потребител",
"LabelActivity": "Дейност",
"LabelAdded": "Добавени",
"LabelAddedAt": "Добавени На",
"LabelAddToCollection": "Добави в Колекция",
"LabelAddToCollectionBatch": "Добави {0} Книги в Колекция",
"LabelAddToPlaylist": "Добави в Плейлист",
"LabelAddToPlaylistBatch": "Добави {0} Елемент в Плейлист",
"LabelAdded": "Добавени",
"LabelAddedAt": "Добавени На",
"LabelAdminUsersOnly": "Само за Администратори",
"LabelAll": "Всички",
"LabelAllUsers": "Всички Потребители",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Промени Парола",
"LabelChannels": "Канали",
"LabelChapterTitle": "Заглавие на Глава",
"LabelChapters": "Глави",
"LabelChaptersFound": "намерени глави",
"LabelChapterTitle": "Заглавие на Глава",
"LabelClickForMoreInfo": "Кликни за повече информация",
"LabelClosePlayer": "Затвори Плейъра",
"LabelCodec": "Кодек",
@ -270,17 +271,17 @@
"LabelDownload": "Сваляне",
"LabelDownloadNEpisodes": "Свали {0} епизоди",
"LabelDuration": "Продължителност",
"LabelDurationComparisonExactMatch": "(exact match)",
"LabelDurationComparisonLonger": "({0} longer)",
"LabelDurationComparisonShorter": "({0} shorter)",
"LabelDurationComparisonExactMatch": "(точно съвпадение)",
"LabelDurationComparisonLonger": "({0} по-дълго)",
"LabelDurationComparisonShorter": "({0} по-късо)",
"LabelDurationFound": "Намерена продължителност:",
"LabelEbook": "Електронна книга",
"LabelEbooks": "Електронни книги",
"LabelEdit": "Редакция",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "От Адрес",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Отхвърли неавторизирани сертификати",
"LabelEmailSettingsRejectUnauthorizedHelp": "Спирането на валидацията на SSL сертификате може да изложи връзката ви на рискове, като man-in-the-middle атака. Спираите тази опция само ако знете имоликацийте от това и се доверявате на mail сървъра към който се свързвате.",
"LabelEmailSettingsSecure": "Сигурна",
"LabelEmailSettingsSecureHelp": "Ако е вярно възката ще изполва TLS когате се свързва със сървъра. Ако не е то TLS ще се използва ако сървъра поддържа разширението STARTTLS. В повечето случаи задайте тази стойност на истина ако се свързвате към порт 465. За порт 587 или 25 оставете я на лъжа. (от nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Тестов Адрес",
@ -306,6 +307,7 @@
"LabelFolder": "Папка",
"LabelFolders": "Папки",
"LabelFontBold": "Получерно",
"LabelFontBoldness": "Плътност на шрифта",
"LabelFontFamily": "Шрифт",
"LabelFontItalic": "Курсив",
"LabelFontScale": "Мащаб на Шрифта",
@ -321,9 +323,9 @@
"LabelHour": "Час",
"LabelIcon": "Икона",
"LabelImageURLFromTheWeb": "URL на Изображение от Интернет",
"LabelInProgress": "В Прогрес",
"LabelIncludeInTracklist": "Включи в Списъка с Канали",
"LabelIncomplete": "Незавършено",
"LabelInProgress": "В Прогрес",
"LabelInterval": "Интервал",
"LabelIntervalCustomDailyWeekly": "Потребително дневно/седмично",
"LabelIntervalEvery12Hours": "Всеки 12 часа",
@ -337,6 +339,7 @@
"LabelItem": "Елемент",
"LabelLanguage": "Език",
"LabelLanguageDefaultServer": "Език по подразбиране на сървъра",
"LabelLanguages": "Езици",
"LabelLastBookAdded": "Последно Добавена Книга",
"LabelLastBookUpdated": "Последно Обновена Книга",
"LabelLastSeen": "Последно Видян",
@ -348,6 +351,7 @@
"LabelLess": "По-малко",
"LabelLibrariesAccessibleToUser": "Библиотеки Достъпни за Потребителя",
"LabelLibrary": "Библиотека",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Елемент на Библиотека",
"LabelLibraryName": "Име на Библиотека",
"LabelLimit": "Лимит",
@ -362,14 +366,14 @@
"LabelMatchExistingUsersByDescription": "Използва се за свързване на съществуващи потребители. След свързване потребителите ще бъдат съпоставени по уникален идентификатор от вашия доставчик на SSO",
"LabelMediaPlayer": "Медия Плейър",
"LabelMediaType": "Тип на Медията",
"LabelMetadataOrderOfPrecedenceDescription": "По-високите източници на метаданни ще заменят по-ниските",
"LabelMetadataProvider": "Доставчик на Метаданни",
"LabelMetaTag": "Мета Таг",
"LabelMetaTags": "Мета Тагове",
"LabelMetadataOrderOfPrecedenceDescription": "По-високите източници на метаданни ще заменят по-ниските",
"LabelMetadataProvider": "Доставчик на Метаданни",
"LabelMinute": "Минута",
"LabelMissing": "Липсващо",
"LabelMissingEbook": "Has no ebook",
"LabelMissingSupplementaryEbook": "Has no supplementary ebook",
"LabelMissingEbook": "Няма електронна книга",
"LabelMissingSupplementaryEbook": "Няма допълнителна електронна книга",
"LabelMobileRedirectURIs": "Позволени URI за Мобилно Пренасочване",
"LabelMobileRedirectURIsDescription": "Това е whitelist на валидни URI за пренасочване за мобилни приложения. По подразбиране е <code>audiobookshelf://oauth</code>, който може да премахнете или допълните с допълнителни URI за интеграция на приложения от трети страни. Използването на звезда (<code>*</code>) като единствен запис позволява всеки URI.",
"LabelMore": "Повече",
@ -378,24 +382,25 @@
"LabelNarrator": "Разказвач",
"LabelNarrators": "Разказвачи",
"LabelNew": "Нови",
"LabelNewPassword": "Нова Парола",
"LabelNewestAuthors": "Най-нови Автори",
"LabelNewestEpisodes": "Най-нови Епизоди",
"LabelNewPassword": "Нова Парола",
"LabelNextBackupDate": "Следваща Дата на Архивиране",
"LabelNextScheduledRun": "Следващо Планирано Изпълнение",
"LabelNoCustomMetadataProviders": "Няма потребителски доставчици на метаданни",
"LabelNoEpisodesSelected": "Няма избрани епизоди",
"LabelNotes": "Бележки",
"LabelNotFinished": "Не е завършено",
"LabelNotStarted": "Не е започнато",
"LabelNotes": "Бележки",
"LabelNotificationAppriseURL": "Apprise URL-и",
"LabelNotificationAvailableVariables": "Налични променливи",
"LabelNotificationBodyTemplate": "Тяло на Шаблона",
"LabelNotificationEvent": "Събитие за Известие",
"LabelNotificationTitleTemplate": "Заглавие на Шаблона",
"LabelNotificationsMaxFailedAttempts": "Максимален брой неуспешни опити за известия",
"LabelNotificationsMaxFailedAttemptsHelp": "Известията се деактивират след като не успеят да бъдат изпратени толкова пъти",
"LabelNotificationsMaxQueueSize": "Максимален размер на опашката за известия",
"LabelNotificationsMaxQueueSizeHelp": "Събитията са ограничени до изстрелване на 1 на секунда. Събитията ще бъдат игнорирани ако опашката е на максимален размер. Това предотвратява спамирането на известия.",
"LabelNotificationTitleTemplate": "Заглавие на Шаблона",
"LabelNotStarted": "Не е започнато",
"LabelNumberOfBooks": "Брой на Книги",
"LabelNumberOfEpisodes": "# Епизоди",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -412,14 +417,15 @@
"LabelPermissionsDownload": "Може да сваля",
"LabelPermissionsUpdate": "Може да обновява",
"LabelPermissionsUpload": "Може да качва",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPersonalYearReview": "Преглед на годината Ви ({0})",
"LabelPhotoPathURL": "Път/URL на Снимка",
"LabelPlaylists": "Плейлисти",
"LabelPlayMethod": "Метод на Пускане",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Плейлисти",
"LabelPodcast": "Подкаст",
"LabelPodcasts": "Подкасти",
"LabelPodcastSearchRegion": "Регион за Търсене на Подкасти",
"LabelPodcastType": "Тип на Подкаст",
"LabelPodcasts": "Подкасти",
"LabelPort": "Порт",
"LabelPrefixesToIgnore": "Префикси за Игнориране (без значение за главни/малки букви)",
"LabelPreventIndexing": "Предотврати индексирането на вашия feed от iTunes и Google podcast директории",
@ -427,30 +433,31 @@
"LabelProgress": "Прогрес",
"LabelProvider": "Доставчик",
"LabelPubDate": "Дата на Издаване",
"LabelPublisher": "Издател",
"LabelPublishYear": "Година на Издаване",
"LabelRead": "Прочети",
"LabelReadAgain": "Прочети Отново",
"LabelReadEbookWithoutProgress": "Прочети електронната книга без записване прогрес",
"LabelRecentlyAdded": "Наскоро Добавени",
"LabelRecentSeries": "Скорошни Серии",
"LabelRecommended": "Препоръчано",
"LabelRedo": "Повтори",
"LabelRegion": "Регион",
"LabelReleaseDate": "Дата на Издаване",
"LabelRemoveCover": "Премахни Корица",
"LabelRowsPerPage": "Редове на Страница",
"LabelPublisher": "Издател",
"LabelPublishers": "Издателство",
"LabelRSSFeedCustomOwnerEmail": "Потребителски собственик Email",
"LabelRSSFeedCustomOwnerName": "Потребителски собственик Име",
"LabelRSSFeedOpen": "RSS Feed Оптворен",
"LabelRSSFeedPreventIndexing": "Предотврати индексиране",
"LabelRSSFeedSlug": "RSS Feed слъг",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Прочети",
"LabelReadAgain": "Прочети Отново",
"LabelReadEbookWithoutProgress": "Прочети електронната книга без записване прогрес",
"LabelRecentSeries": "Скорошни Серии",
"LabelRecentlyAdded": "Наскоро Добавени",
"LabelRecommended": "Препоръчано",
"LabelRedo": "Повтори",
"LabelRegion": "Регион",
"LabelReleaseDate": "Дата на Издаване",
"LabelRemoveCover": "Премахни Корица",
"LabelRowsPerPage": "Редове на Страница",
"LabelSearchTerm": "Търси Термин",
"LabelSearchTitle": "Търси Заглавие",
"LabelSearchTitleOrASIN": "Търси Заглавие или ASIN",
"LabelSeason": "Сезон",
"LabelSelectAll": "Select all",
"LabelSelectAll": "Избери всичко",
"LabelSelectAllEpisodes": "Избери всички епизоди",
"LabelSelectEpisodesShowing": "Избери {0} епизоди показани",
"LabelSelectUsers": "Избери Потребители",
@ -459,7 +466,7 @@
"LabelSeries": "Серия",
"LabelSeriesName": "Име на Серия",
"LabelSeriesProgress": "Прогрес на Серия",
"LabelServerYearReview": "Server Year in Review ({0})",
"LabelServerYearReview": "Преглед на годината на сървъра ({0})",
"LabelSetEbookAsPrimary": "Задай като основна",
"LabelSetEbookAsSupplementary": "Задай като допълнителна",
"LabelSettingsAudiobooksOnly": "Само аудиокниги",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Включи наблюдателя",
"LabelSettingsEnableWatcherForLibrary": "Включи наблюдателя за библиотека",
"LabelSettingsEnableWatcherHelp": "Включва автоматичното добавяне/обновяване на елементи, когато се открият промени във файловете. *Изисква рестарт на сървъра",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "Позволи скриптово съдържание в epub-и",
"LabelSettingsEpubsAllowScriptedContentHelp": "Позволи epub файловете да изпълняват скриптове. Препоръчително е да бъде изключено освен ако не се доверявате на източника на epub файловете.",
"LabelSettingsExperimentalFeatures": "Експериментални Функции",
"LabelSettingsExperimentalFeaturesHelp": "Функции в разработка, които могат да изискват вашето мнение и помощ за тестване. Кликнете за да отворите дискусия в github.",
"LabelSettingsFindCovers": "Намери Корици",
@ -483,7 +490,7 @@
"LabelSettingsHideSingleBookSeriesHelp": "Сериите с една книга ще бъдат скрити от страницата на серията и рафтовете на началната страница.",
"LabelSettingsHomePageBookshelfView": "Начална страница изглед на рафт",
"LabelSettingsLibraryBookshelfView": "Библиотека изглед на рафт",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Skip earlier books in Continue Series",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Пропусни предишни книги в Продължи Поредица",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "The Continue Series home page shelf shows the first book not started in series that have at least one book finished and no books in progress. Enabling this setting will continue series from the furthest completed book instead of the first book not started.",
"LabelSettingsParseSubtitles": "Извлечи подзаглавия",
"LabelSettingsParseSubtitlesHelp": "Извлича подзаглавия от имената на папките на аудиокнигите.<br>Подзаглавията трябва да бъдат разделени с \" - \"<br>например \"Заглавие на Книга - Тук е Подзаглавито\" има подзаглавие \"Тук е Подзаглавито\"",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Таймер за Сън",
"LabelSlug": "Слъг",
"LabelStart": "Старт",
"LabelStartTime": "Начално Време",
"LabelStarted": "Стартирано",
"LabelStartedAt": "Стартирано на",
"LabelStartTime": "Начално Време",
"LabelStatsAudioTracks": "Аудио Канали",
"LabelStatsAuthors": "Автори",
"LabelStatsBestDay": "Най-добър Ден",
@ -564,9 +571,9 @@
"LabelUnknown": "Неизвестно",
"LabelUpdateCover": "Обнови Корица",
"LabelUpdateCoverHelp": "Позволи презаписване на съществуващите корици за избраните книги, когато се намери съвпадение",
"LabelUpdatedAt": "Обновено на",
"LabelUpdateDetails": "Обнови Детайли",
"LabelUpdateDetailsHelp": "Позволи презаписване на съществуващите детайли за избраните книги, когато се намери съвпадение",
"LabelUpdatedAt": "Обновено на",
"LabelUploaderDragAndDrop": "Плъзни и Пусни Файлове или Папки",
"LabelUploaderDropFiles": "Пусни Файлове",
"LabelUploaderItemFetchMetadataHelp": "Автоматично вземи заглавие, автор и серия",
@ -592,8 +599,9 @@
"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.",
"MessageBatchQuickMatchDescription": "Бързото Съпоставяне ще опита да добави липсващи корици и метаданни за избраните елементи. Активирайте опциите по-долу, за да позволите на Бързото съпоставяне да презапише съществуващите корици и/или метаданни.",
"MessageBookshelfNoCollections": "Все още нямате създадени колекции",
"MessageBookshelfNoResultsForFilter": "Няма резултат за филтер \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Няма отворени RSS feed-ове",
"MessageBookshelfNoResultsForFilter": "Няма резултат за филтер \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Нямаш сеЗЙ",
"MessageChapterEndIsAfter": "Краят на главата е след края на вашата аудиокнига",
"MessageChapterErrorFirstNotZero": "Първата глава трябва да започва от 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Сигурни ли сте, че искате да маркирате всички книги в тази серия като завършени?",
"MessageConfirmMarkSeriesNotFinished": "Сигурни ли сте, че искате да маркирате всички книги в тази серия като незавършени?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Внимание! Бързото вграждане няма да архивира вашите аудио файлове. Уверете се, че имате резервно копие на вашите аудио файлове. <br><br>Искате ли да продължите?",
"MessageConfirmReScanLibraryItems": "Сигурни ли сте, че искате да сканирате отново {0} елемента?",
"MessageConfirmRemoveAllChapters": "Сигурни ли сте, че искате да премахнете всички глави?",
"MessageConfirmRemoveAuthor": "Сигурни ли сте, че искате да премахнете автор \"{0}\"?",
"MessageConfirmRemoveCollection": "Сигурни ли сте, че искате да премахнете колекция \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Сигурни ли сте, че искате да преименувате таг \"{0}\" на \"{1}\" за всички елементи?",
"MessageConfirmRenameTagMergeNote": "Забележка: Този таг вече съществува и ще бъде слято.",
"MessageConfirmRenameTagWarning": "Внимание! Вече съществува подобен таг с различно писане \"{0}\".",
"MessageConfirmReScanLibraryItems": "Сигурни ли сте, че искате да сканирате отново {0} елемента?",
"MessageConfirmSendEbookToDevice": "Сигурни ли сте, че искате да изпратите {0} електронна книга \"{1}\" до устройство \"{2}\"?",
"MessageDownloadingEpisode": "Изтегляне на епизод",
"MessageDragFilesIntoTrackOrder": "Плъзнете файлове в правилния ред на каналите",
@ -683,10 +692,10 @@
"MessageNoSeries": "Няма Серии",
"MessageNoTags": "Няма Тагове",
"MessageNoTasksRunning": "Няма вършещи се задачи",
"MessageNotYetImplemented": "Още не е изпълнено",
"MessageNoUpdateNecessary": "Не е необходимо обновяване",
"MessageNoUpdatesWereNecessary": "Не бяха необходими обновления",
"MessageNoUserPlaylists": "Няма плейлисти на потребителя",
"MessageNotYetImplemented": "Още не е изпълнено",
"MessageOr": "или",
"MessagePauseChapter": "Пауза на глава",
"MessagePlayChapter": "Пусни налчалото на глава",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Плейлистът е обновен",
"ToastPodcastCreateFailed": "Неуспешно създаване на подкаст",
"ToastPodcastCreateSuccess": "Подкастът е създаден",
"ToastRemoveItemFromCollectionFailed": "Неуспешно премахване на елемент от колекция",
"ToastRemoveItemFromCollectionSuccess": "Елементът е премахнат от колекция",
"ToastRSSFeedCloseFailed": "Неуспешно затваряне на RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed затворен",
"ToastRemoveItemFromCollectionFailed": "Неуспешно премахване на елемент от колекция",
"ToastRemoveItemFromCollectionSuccess": "Елементът е премахнат от колекция",
"ToastSendEbookToDeviceFailed": "Неуспешно изпращане на електронна книга до устройство",
"ToastSendEbookToDeviceSuccess": "Електронната книга е изпратена до устройство \"{0}\"",
"ToastSeriesUpdateFailed": "Неуспешно обновяване на серия",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Неуспешно изтриване на потребител",
"ToastUserDeleteSuccess": "Потребителят е изтрит"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "প্রয়োগ করুন",
"ButtonApplyChapters": "অধ্যায় প্রয়োগ করুন",
"ButtonAuthors": "লেখক",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "ফোল্ডারের জন্য ব্রাউজ করুন",
"ButtonCancel": "বাতিল করুন",
"ButtonCancelEncode": "এনকোড বাতিল করুন",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "আগের অধ্যায়",
"ButtonPurgeAllCache": "সমস্ত ক্যাশে পরিষ্কার করুন",
"ButtonPurgeItemsCache": "আইটেম ক্যাশে পরিষ্কার করুন",
"ButtonPurgeMediaProgress": "মিডিয়া ক্যাশে পরিষ্কার করুন",
"ButtonQueueAddItem": "সারিতে যোগ করুন",
"ButtonQueueRemoveItem": "সারি থেকে মুছে ফেলুন",
"ButtonQuickMatch": "দ্রুত ম্যাচ",
"ButtonReScan": "পুনরায় স্ক্যান",
"ButtonRead": "পড়ুন",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "শোনা চালিয়ে যাওয়া থেকে মুছে ফেলুন",
"ButtonRemoveFromContinueReading": "পঠন চালিয়ে যান থেকে মুছে ফেলুন",
"ButtonRemoveSeriesFromContinueSeries": "কন্টিনিউ সিরিজ থেকে সিরিজ মুছে ফেলুন",
"ButtonReScan": "পুনরায় স্ক্যান",
"ButtonReset": "রিসেট",
"ButtonResetToDefault": "ডিফল্টে পুনরায় সেট করুন",
"ButtonRestore": "পুনরুদ্ধার করুন",
@ -104,8 +104,8 @@
"HeaderAccount": "অ্যাকাউন্ট",
"HeaderAdvanced": "অ্যাডভান্সড",
"HeaderAppriseNotificationSettings": "বিজ্ঞপ্তি সেটিংস অবহিত করুন",
"HeaderAudiobookTools": "অডিওবই ফাইল ম্যানেজমেন্ট টুলস",
"HeaderAudioTracks": "অডিও ট্র্যাকস",
"HeaderAudiobookTools": "অডিওবই ফাইল ম্যানেজমেন্ট টুলস",
"HeaderAuthentication": "প্রমাণীকরণ",
"HeaderBackups": "ব্যাকআপ",
"HeaderChangePassword": "পাসওয়ার্ড পরিবর্তন করুন",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "সংগ্রহ আইটেম",
"HeaderCover": "কভার",
"HeaderCurrentDownloads": "বর্তমান ডাউনলোডগুলি",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "কাস্টম মেটাডেটা প্রদানকারী",
"HeaderDetails": "বিস্তারিত",
"HeaderDownloadQueue": "ডাউনলোড সারি",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "প্লেলিস্ট আইটেম",
"HeaderPodcastsToAdd": "যোগ করার জন্য পডকাস্ট",
"HeaderPreviewCover": "কভার ্দেখুন",
"HeaderRemoveEpisode": "পর্বটি সরান",
"HeaderRemoveEpisodes": "{0}টি পর্ব সরান",
"HeaderRSSFeedGeneral": "আরএসএস বিবরণ",
"HeaderRSSFeedIsOpen": "আরএসএস ফিড খোলা আছে",
"HeaderRSSFeeds": "আরএসএস ফিড",
"HeaderRemoveEpisode": "পর্বটি সরান",
"HeaderRemoveEpisodes": "{0}টি পর্ব সরান",
"HeaderSavedMediaProgress": "মিডিয়া সংরক্ষণের অগ্রগতি",
"HeaderSchedule": "সময়সূচী",
"HeaderScheduleLibraryScans": "স্বয়ংক্রিয় লাইব্রেরি স্ক্যানের সময়সূচী",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "অতিথি",
"LabelAccountTypeUser": "ব্যবহারকারী",
"LabelActivity": "ক্রিয়াকলাপ",
"LabelAdded": "যোগ করা হয়েছে",
"LabelAddedAt": "এতে যোগ করা হয়েছে",
"LabelAddToCollection": "সংগ্রহে যোগ করুন",
"LabelAddToCollectionBatch": "সংগ্রহে {0}টি বই যোগ করুন",
"LabelAddToPlaylist": "প্লেলিস্টে যোগ করুন",
"LabelAddToPlaylistBatch": "প্লেলিস্টে {0}টি আইটেম যোগ করুন",
"LabelAdded": "যোগ করা হয়েছে",
"LabelAddedAt": "এতে যোগ করা হয়েছে",
"LabelAdminUsersOnly": "শুধু অ্যাডমিন ব্যবহারকারী",
"LabelAll": "সব",
"LabelAllUsers": "সমস্ত ব্যবহারকারী",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "পাসওয়ার্ড পরিবর্তন করুন",
"LabelChannels": "চ্যানেল",
"LabelChapterTitle": "অধ্যায়ের শিরোনাম",
"LabelChapters": "অধ্যায়",
"LabelChaptersFound": "অধ্যায় পাওয়া গেছে",
"LabelChapterTitle": "অধ্যায়ের শিরোনাম",
"LabelClickForMoreInfo": "আরো তথ্যের জন্য ক্লিক করুন",
"LabelClosePlayer": "প্লেয়ার বন্ধ করুন",
"LabelCodec": "কোডেক",
@ -280,7 +281,7 @@
"LabelEmail": "ইমেইল",
"LabelEmailSettingsFromAddress": "ঠিকানা থেকে",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to",
"LabelEmailSettingsSecure": "নিরাপদ",
"LabelEmailSettingsSecureHelp": "যদি সত্য হয় সার্ভারের সাথে সংযোগ করার সময় সংযোগটি TLS ব্যবহার করবে। মিথ্যা হলে TLS ব্যবহার করা হবে যদি সার্ভার STARTTLS এক্সটেনশন সমর্থন করে। বেশিরভাগ ক্ষেত্রে এই মানটিকে সত্য হিসাবে সেট করুন যদি আপনি পোর্ট 465-এর সাথে সংযোগ করছেন। পোর্ট 587 বা পোর্টের জন্য 25 এটি মিথ্যা রাখুন। (nodemailer.com/smtp/#authentication থেকে)",
"LabelEmailSettingsTestAddress": "পরীক্ষার ঠিকানা",
@ -306,6 +307,7 @@
"LabelFolder": "ফোল্ডার",
"LabelFolders": "ফোল্ডারগুলো",
"LabelFontBold": "বোল্ড",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "ফন্ট পরিবার",
"LabelFontItalic": "ইটালিক",
"LabelFontScale": "ফন্ট স্কেল",
@ -321,9 +323,9 @@
"LabelHour": "ঘন্টা",
"LabelIcon": "আইকন",
"LabelImageURLFromTheWeb": "ওয়েব থেকে ছবির ইউআরএল",
"LabelInProgress": "প্রগতিতে আছে",
"LabelIncludeInTracklist": "ট্র্যাকলিস্টে অন্তর্ভুক্ত করুন",
"LabelIncomplete": "অসম্পূর্ণ",
"LabelInProgress": "প্রগতিতে আছে",
"LabelInterval": "বিরতি",
"LabelIntervalCustomDailyWeekly": "কাস্টম দৈনিক/সাপ্তাহিক",
"LabelIntervalEvery12Hours": "প্রতি ১২ ঘন্টায়",
@ -337,6 +339,7 @@
"LabelItem": "আইটেম",
"LabelLanguage": "ভাষা",
"LabelLanguageDefaultServer": "সার্ভারের ডিফল্ট ভাষা",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "শেষ বই যোগ করা হয়েছে",
"LabelLastBookUpdated": "শেষ বই আপডেট করা হয়েছে",
"LabelLastSeen": "শেষ দেখা",
@ -348,6 +351,7 @@
"LabelLess": "কম",
"LabelLibrariesAccessibleToUser": "ব্যবহারকারীর কাছে অ্যাক্সেসযোগ্য লাইব্রেরি",
"LabelLibrary": "লাইব্রেরি",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "লাইব্রেরি আইটেম",
"LabelLibraryName": "লাইব্রেরির নাম",
"LabelLimit": "সীমা",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "বিদ্যমান ব্যবহারকারীদের সংযোগ করার জন্য ব্যবহৃত হয়। একবার সংযুক্ত হলে, ব্যবহারকারীদের আপনার SSO প্রদানকারীর থেকে একটি অনন্য আইডি দ্বারা মিলিত হবে",
"LabelMediaPlayer": "মিডিয়া প্লেয়ার",
"LabelMediaType": "মিডিয়ার ধরন",
"LabelMetadataOrderOfPrecedenceDescription": "উচ্চ অগ্রাধিকারের মেটাডেটার উৎসগুলো নিম্ন অগ্রাধিকারের মেটাডেটা উৎসগুলোকে ওভাররাইড করবে",
"LabelMetadataProvider": "মেটাডেটা প্রদানকারী",
"LabelMetaTag": "মেটা ট্যাগ",
"LabelMetaTags": "মেটা ট্যাগগুলো",
"LabelMetadataOrderOfPrecedenceDescription": "উচ্চ অগ্রাধিকারের মেটাডেটার উৎসগুলো নিম্ন অগ্রাধিকারের মেটাডেটা উৎসগুলোকে ওভাররাইড করবে",
"LabelMetadataProvider": "মেটাডেটা প্রদানকারী",
"LabelMinute": "মিনিট",
"LabelMissing": "নিখোঁজ",
"LabelMissingEbook": "কোনও ই-বই নেই",
@ -378,24 +382,25 @@
"LabelNarrator": "কথক",
"LabelNarrators": "কথক",
"LabelNew": "নতুন",
"LabelNewPassword": "নতুন পাসওয়ার্ড",
"LabelNewestAuthors": "নতুন লেখক",
"LabelNewestEpisodes": "নতুনতম পর্ব",
"LabelNewPassword": "নতুন পাসওয়ার্ড",
"LabelNextBackupDate": "পরবর্তী ব্যাকআপ তারিখ",
"LabelNextScheduledRun": "পরবর্তী নির্ধারিত দৌড়",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "কোন পর্ব নির্বাচন করা হয়নি",
"LabelNotes": "নোটস",
"LabelNotFinished": "সমাপ্ত হয়নি",
"LabelNotStarted": "শুরু হয়নি",
"LabelNotes": "নোটস",
"LabelNotificationAppriseURL": "অবহিত URL(গুলি)",
"LabelNotificationAvailableVariables": "ব্যবহারযোগ্য ভেরিয়েবল",
"LabelNotificationBodyTemplate": "বডি টেমপ্লেট",
"LabelNotificationEvent": "ইভেন্ট বিজ্ঞপ্তি",
"LabelNotificationTitleTemplate": "শিরোনাম টেমপ্লেট",
"LabelNotificationsMaxFailedAttempts": "সর্বোচ্চ ব্যর্থ প্রচেষ্টা",
"LabelNotificationsMaxFailedAttemptsHelp": "এটি বারবার পাঠাতে ব্যর্থ হলে বিজ্ঞপ্তি অক্ষম করা হবে",
"LabelNotificationsMaxQueueSize": "বিজ্ঞপ্তি ইভেন্টের জন্য সর্বোচ্চ সারির আকার",
"LabelNotificationsMaxQueueSizeHelp": "ইভেন্টগুলি প্রতি সেকেন্ডে ১ বার ইন্ধন করার মধ্যে সীমাবদ্ধ। সারি সর্বাধিক আকারে থাকলে ইভেন্টগুলি উপেক্ষা করা হবে। এটি বিজ্ঞপ্তি স্প্যামিং প্রতিরোধ করে।",
"LabelNotificationTitleTemplate": "শিরোনাম টেমপ্লেট",
"LabelNotStarted": "শুরু হয়নি",
"LabelNumberOfBooks": "বইয়ের সংখ্যা",
"LabelNumberOfEpisodes": "# টি পর্ব",
"LabelOpenIDAdvancedPermsClaimDescription": "ওপেনআইডি দাবির নাম যাতে অ্যাপ্লিকেশনের মধ্যে ব্যবহারকারীর ক্রিয়াকলাপের জন্য উন্নত অনুমতি রয়েছে যা অ-প্রশাসক ভূমিকাগুলিতে প্রযোজ্য হবে (<b>যদি কনফিগার করা হয়</b>)। প্রতিক্রিয়া থেকে দাবিটি অনুপস্থিত থাকলে, অ্যাক্সেস করুন ABS-তে অস্বীকার করা হবে। যদি একটি একক বিকল্প অনুপস্থিত থাকে, তাহলে এটিকে <code>false</code> হিসাবে গণ্য করা হবে। নিশ্চিত করুন যে পরিচয় প্রদানকারীর দাবি প্রত্যাশিত কাঠামোর সাথে মেলে:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "আপলোড করতে পারবে",
"LabelPersonalYearReview": "আপনার বছরের পর্যালোচনা ({0})",
"LabelPhotoPathURL": "ছবি পথ/ইউআরএল",
"LabelPlaylists": "প্লেলিস্ট",
"LabelPlayMethod": "প্লে পদ্ধতি",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "প্লেলিস্ট",
"LabelPodcast": "পডকাস্ট",
"LabelPodcasts": "পডকাস্টগুলো",
"LabelPodcastSearchRegion": "পডকাস্ট অনুসন্ধান অঞ্চল",
"LabelPodcastType": "পডকাস্টের ধরন",
"LabelPodcasts": "পডকাস্টগুলো",
"LabelPort": "পোর্ট",
"LabelPrefixesToIgnore": "উপেক্ষা করার উপসর্গ (কেস সংবেদনশীল)",
"LabelPreventIndexing": "আইটিউনস এবং গুগল পডকাস্ট ডিরেক্টরি দ্বারা আপনার ফিডকে ইন্ডেক্স করা থেকে বিরত রাখুন",
@ -427,25 +433,26 @@
"LabelProgress": "প্রগতি",
"LabelProvider": "প্রদানকারী",
"LabelPubDate": "প্রকাশের তারিখ",
"LabelPublisher": "প্রকাশক",
"LabelPublishYear": "প্রকাশের বছর",
"LabelRead": "পড়ুন",
"LabelReadAgain": "আবার পড়ুন",
"LabelReadEbookWithoutProgress": "প্রগতি না রেখে ই-বই পড়ুন",
"LabelRecentlyAdded": "সম্প্রতি যোগ করা হয়েছে",
"LabelRecentSeries": "সাম্প্রতিক সিরিজ",
"LabelRecommended": "সুপারিশকৃত",
"LabelRedo": "পুনরায় করুন",
"LabelRegion": "অঞ্চল",
"LabelReleaseDate": "উন্মোচনের তারিখ",
"LabelRemoveCover": "কভার সরান",
"LabelRowsPerPage": "প্রতি পৃষ্ঠায় সারি",
"LabelPublisher": "প্রকাশক",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "কাস্টম মালিকের ইমেইল",
"LabelRSSFeedCustomOwnerName": "কাস্টম মালিকের নাম",
"LabelRSSFeedOpen": "আরএসএস ফিড খুলুন",
"LabelRSSFeedPreventIndexing": "সূচীকরণ প্রতিরোধ করুন",
"LabelRSSFeedSlug": "আরএসএস ফিড স্লাগ",
"LabelRSSFeedURL": "আরএসএস ফিড ইউআরএল",
"LabelRead": "পড়ুন",
"LabelReadAgain": "আবার পড়ুন",
"LabelReadEbookWithoutProgress": "প্রগতি না রেখে ই-বই পড়ুন",
"LabelRecentSeries": "সাম্প্রতিক সিরিজ",
"LabelRecentlyAdded": "সম্প্রতি যোগ করা হয়েছে",
"LabelRecommended": "সুপারিশকৃত",
"LabelRedo": "পুনরায় করুন",
"LabelRegion": "অঞ্চল",
"LabelReleaseDate": "উন্মোচনের তারিখ",
"LabelRemoveCover": "কভার সরান",
"LabelRowsPerPage": "প্রতি পৃষ্ঠায় সারি",
"LabelSearchTerm": "অনুসন্ধান শব্দ",
"LabelSearchTitle": "অনুসন্ধান শিরোনাম",
"LabelSearchTitleOrASIN": "অনুসন্ধান শিরোনাম বা ASIN",
@ -474,7 +481,7 @@
"LabelSettingsEnableWatcherForLibrary": "লাইব্রেরির জন্য ফোল্ডার প্রহরী সক্ষম করুন",
"LabelSettingsEnableWatcherHelp": "ফাইলের পরিবর্তন শনাক্ত হলে আইটেমগুলির স্বয়ংক্রিয় যোগ/আপডেট সক্ষম করবে। *সার্ভার পুনরায় চালু করতে হবে",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files",
"LabelSettingsExperimentalFeatures": "পরীক্ষামূলক বৈশিষ্ট্য",
"LabelSettingsExperimentalFeaturesHelp": "ফিচারের বৈশিষ্ট্য যা আপনার প্রতিক্রিয়া ব্যবহার করতে পারে এবং পরীক্ষায় সহায়তা করতে পারে। গিটহাব আলোচনা খুলতে ক্লিক করুন।",
"LabelSettingsFindCovers": "কভার খুঁজুন",
@ -484,7 +491,7 @@
"LabelSettingsHomePageBookshelfView": "নীড় পেজে বুকশেলফ ভিউ ব্যবহার করুন",
"LabelSettingsLibraryBookshelfView": "লাইব্রেরি বুকশেলফ ভিউ ব্যবহার করুন",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "কন্টিনিউ সিরিজে আগের বইগুলো এড়িয়ে যান",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "কন্টিনিউ সিরিজের হোম পেজ শেল্ফ প্রথম বইটি দেখায় যেটি সিরিজে শুরু হয়নি যেটিতে অন্তত একটি বই শেষ হয়েছে এবং কোনো বই চলছে না। এই সেটিংটি সক্ষম করা হলে তা শুরু না হওয়া প্রথম বইটির পরিবর্তে সবচেয়ে দূরের সম্পূর্ণ বই থেকে সিরিজ চালিয়ে যাবে। ",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "কন্টিনিউ সিরিজের হোম পেজ শেল্ফ প্রথম বইটি দেখায় যেটি সিরিজে শুরু হয়নি যেটিতে অন্তত একটি বই শেষ হয়েছে এবং কোনো বই চলছে না। এই সেটিংটি সক্ষম করা হলে তা শুরু না হওয়া প্রথম বইটির পরিবর্তে সবচেয়ে দূরের সম্পূর্ণ বই থেকে সিরিজ চালিয়ে যাবে।",
"LabelSettingsParseSubtitles": "সাবটাইটেল পার্স করুন",
"LabelSettingsParseSubtitlesHelp": "অডিওবুক ফোল্ডারের নাম থেকে সাবটাইটেল বের করুন৷<br>সাবটাইটেল অবশ্যই \" - \"<br>অর্থাৎ \"বুকের শিরোনাম - এখানে একটি সাবটাইটেল\" এর সাবটাইটেল আছে \"এখানে একটি সাবটাইটেল\"",
"LabelSettingsPreferMatchedMetadata": "মিলিত মেটাডেটা পছন্দ করুন",
@ -506,9 +513,9 @@
"LabelSleepTimer": "স্লিপ টাইমার",
"LabelSlug": "স্লাগ",
"LabelStart": "শুরু",
"LabelStartTime": "শুরু করার সময়",
"LabelStarted": "শুরু হয়েছে",
"LabelStartedAt": "এতে শুরু হয়েছে",
"LabelStartTime": "শুরু করার সময়",
"LabelStatsAudioTracks": "অডিও ট্র্যাক",
"LabelStatsAuthors": "লেখক",
"LabelStatsBestDay": "সেরা দিন",
@ -564,9 +571,9 @@
"LabelUnknown": "অজানা",
"LabelUpdateCover": "কভার আপডেট করুন",
"LabelUpdateCoverHelp": "একটি মিল থাকা অবস্থায় নির্বাচিত বইগুলির বিদ্যমান কভারগুলি ওভাররাইট করার অনুমতি দিন",
"LabelUpdatedAt": "আপডেট করা হয়েছে",
"LabelUpdateDetails": "বিশদ আপডেট করুন",
"LabelUpdateDetailsHelp": "একটি মিল থাকা অবস্থায় নির্বাচিত বইগুলির বিদ্যমান বিবরণ ওভাররাইট করার অনুমতি দিন",
"LabelUpdatedAt": "আপডেট করা হয়েছে",
"LabelUploaderDragAndDrop": "ফাইল বা ফোল্ডার টেনে আনুন এবং ফেলে দিন",
"LabelUploaderDropFiles": "ফাইলগুলো ফেলে দিন",
"LabelUploaderItemFetchMetadataHelp": "স্বয়ংক্রিয়ভাবে শিরোনাম, লেখক এবং সিরিজ আনুন",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "ব্যাকআপের মধ্যে রয়েছে ব্যবহারকারী, ব্যবহারকারীর অগ্রগতি, লাইব্রেরি আইটেমের বিবরণ, সার্ভার সেটিংস এবং <code>/metadata/items</code> & <code>/metadata/authors</code>-এ সংরক্ষিত ছবি। ব্যাকআপগুলি <strong> আপনার লাইব্রেরি ফোল্ডারে সঞ্চিত কোনো ফাইল >অন্তর্ভুক্ত করবেন না</strong>।",
"MessageBatchQuickMatchDescription": "কুইক ম্যাচ নির্বাচিত আইটেমগুলির জন্য অনুপস্থিত কভার এবং মেটাডেটা যোগ করার চেষ্টা করবে। বিদ্যমান কভার এবং/অথবা মেটাডেটা ওভাররাইট করার জন্য দ্রুত ম্যাচকে অনুমতি দিতে নীচের বিকল্পগুলি সক্ষম করুন।",
"MessageBookshelfNoCollections": "আপনি এখনও কোনো সংগ্রহ করেননি",
"MessageBookshelfNoResultsForFilter": "ফিল্টার \"{0}: {1}\" এর জন্য কোন ফলাফল নেই",
"MessageBookshelfNoRSSFeeds": "কোনও RSS ফিড খোলা নেই",
"MessageBookshelfNoResultsForFilter": "ফিল্টার \"{0}: {1}\" এর জন্য কোন ফলাফল নেই",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "আপনার কোনো সিরিজ নেই",
"MessageChapterEndIsAfter": "অধ্যায়ের সমাপ্তি আপনার অডিওবুকের শেষে",
"MessageChapterErrorFirstNotZero": "প্রথম অধ্যায় 0 এ শুরু হতে হবে",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "আপনি কি নিশ্চিত যে আপনি এই সিরিজের সমস্ত বইকে সমাপ্ত হিসাবে চিহ্নিত করতে চান?",
"MessageConfirmMarkSeriesNotFinished": "আপনি কি নিশ্চিত যে আপনি এই সিরিজের সমস্ত বইকে শেষ হয়নি বলে চিহ্নিত করতে চান?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "সতর্কতা! দ্রুত এম্বেড আপনার অডিও ফাইলের ব্যাকআপ করবে না। নিশ্চিত করুন যে আপনার অডিও ফাইলগুলির একটি ব্যাকআপ আছে। <br><br>আপনি কি চালিয়ে যেতে চান?",
"MessageConfirmReScanLibraryItems": "আপনি কি নিশ্চিত যে আপনি {0}টি আইটেম পুনরায় স্ক্যান করতে চান?",
"MessageConfirmRemoveAllChapters": "আপনি কি নিশ্চিত যে আপনি সমস্ত অধ্যায় সরাতে চান?",
"MessageConfirmRemoveAuthor": "আপনি কি নিশ্চিত যে আপনি লেখক \"{0}\" অপসারণ করতে চান?",
"MessageConfirmRemoveCollection": "আপনি কি নিশ্চিত যে আপনি সংগ্রহ \"{0}\" সরাতে চান?",
@ -629,13 +639,12 @@
"MessageConfirmRenameTag": "আপনি কি সব আইটেমের জন্য \"{0}\" ট্যাগের নাম পরিবর্তন করে \"{1}\" করার বিষয়ে নিশ্চিত?",
"MessageConfirmRenameTagMergeNote": "দ্রষ্টব্য: এই ট্যাগটি আগে থেকেই বিদ্যমান তাই সেগুলিকে একত্র করা হবে।",
"MessageConfirmRenameTagWarning": "সতর্কতা! একটি ভিন্ন কেসিং সহ একটি অনুরূপ ট্যাগ ইতিমধ্যেই বিদ্যমান \"{0}\"।",
"MessageConfirmReScanLibraryItems": "আপনি কি নিশ্চিত যে আপনি {0}টি আইটেম পুনরায় স্ক্যান করতে চান?",
"MessageConfirmSendEbookToDevice": "আপনি কি নিশ্চিত যে আপনি \"{2}\" ডিভাইসে {0} ইবুক \"{1}\" পাঠাতে চান?",
"MessageDownloadingEpisode": "ডাউনলোডিং পর্ব",
"MessageDragFilesIntoTrackOrder": "সঠিক ট্র্যাক অর্ডারে ফাইল টেনে আনুন",
"MessageEmbedFinished": "এম্বেড করা শেষ!",
"MessageEpisodesQueuedForDownload": "{0} পর্ব(গুলি) ডাউনলোডের জন্য সারিবদ্ধ",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below",
"MessageFeedURLWillBe": "ফিড URL হবে {0}",
"MessageFetching": "আনয় হচ্ছে...",
"MessageForceReScanDescription": "সকল ফাইল আবার নতুন স্ক্যানের মত স্ক্যান করবে। অডিও ফাইল ID3 ট্যাগ, OPF ফাইল, এবং টেক্সট ফাইলগুলি নতুন হিসাবে স্ক্যান করা হবে।",
@ -647,7 +656,7 @@
"MessageListeningSessionsInTheLastYear": "গত বছরে {0}টি শোনার সেশন",
"MessageLoading": "লোড হচ্ছে...",
"MessageLoadingFolders": "ফোল্ডার লোড হচ্ছে...",
"MessageLogsDescription": "Logs are stored in <code>/metadata/logs</code> as JSON files. Crash logs are stored in <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "Logs are stored in <code>/metadata/logs</code> as JSON files. Crash logs are stored in <code>/metadata/logs/crash_logs.txt</code>",
"MessageM4BFailed": "M4B ব্যর্থ!",
"MessageM4BFinished": "M4B সমাপ্ত!",
"MessageMapChapterTitles": "টাইমস্ট্যাম্প সামঞ্জস্য না করে আপনার বিদ্যমান অডিওবুক অধ্যায়গুলিতে অধ্যায়ের শিরোনাম ম্যাপ করুন",
@ -683,10 +692,10 @@
"MessageNoSeries": "কোন সিরিজ নেই",
"MessageNoTags": "কোন ট্যাগ নেই",
"MessageNoTasksRunning": "কোন টাস্ক চলছে না",
"MessageNotYetImplemented": "এখনও বাস্তবায়িত হয়নি",
"MessageNoUpdateNecessary": "কোন আপডেটের প্রয়োজন নেই",
"MessageNoUpdatesWereNecessary": "কোন আপডেটের প্রয়োজন ছিল না",
"MessageNoUserPlaylists": "আপনার কোনো প্লেলিস্ট নেই",
"MessageNotYetImplemented": "এখনও বাস্তবায়িত হয়নি",
"MessageOr": "বা",
"MessagePauseChapter": "পজ অধ্যায় প্লেব্যাক",
"MessagePlayChapter": "অধ্যায়ের শুরুতে শুনুন",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "প্লেলিস্ট আপডেট করা হয়েছে",
"ToastPodcastCreateFailed": "পডকাস্ট তৈরি করতে ব্যর্থ",
"ToastPodcastCreateSuccess": "পডকাস্ট সফলভাবে তৈরি করা হয়েছে",
"ToastRemoveItemFromCollectionFailed": "সংগ্রহ থেকে আইটেম সরাতে ব্যর্থ",
"ToastRemoveItemFromCollectionSuccess": "সংগ্রহ থেকে আইটেম সরানো হয়েছে",
"ToastRSSFeedCloseFailed": "RSS ফিড বন্ধ করতে ব্যর্থ",
"ToastRSSFeedCloseSuccess": "RSS ফিড বন্ধ",
"ToastRemoveItemFromCollectionFailed": "সংগ্রহ থেকে আইটেম সরাতে ব্যর্থ",
"ToastRemoveItemFromCollectionSuccess": "সংগ্রহ থেকে আইটেম সরানো হয়েছে",
"ToastSendEbookToDeviceFailed": "ডিভাইসে ইবুক পাঠাতে ব্যর্থ",
"ToastSendEbookToDeviceSuccess": "ইবুক \"{0}\" ডিভাইসে পাঠানো হয়েছে",
"ToastSeriesUpdateFailed": "সিরিজ আপডেট ব্যর্থ হয়েছে",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "ব্যবহারকারী মুছতে ব্যর্থ",
"ToastUserDeleteSuccess": "ব্যবহারকারী মুছে ফেলা হয়েছে"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Aplikovat",
"ButtonApplyChapters": "Aplikovat kapitoly",
"ButtonAuthors": "Autoři",
"ButtonBack": "Zpět",
"ButtonBrowseForFolder": "Vyhledat složku",
"ButtonCancel": "Zrušit",
"ButtonCancelEncode": "Zrušit kódování",
@ -32,8 +33,8 @@
"ButtonHide": "Skrýt",
"ButtonHome": "Domů",
"ButtonIssues": "Problémy",
"ButtonJumpBackward": "Jump Backward",
"ButtonJumpForward": "Jump Forward",
"ButtonJumpBackward": "Skok Zpět",
"ButtonJumpForward": "Skok Dopředu",
"ButtonLatest": "Nejnovější",
"ButtonLibrary": "Knihovna",
"ButtonLogout": "Odhlásit",
@ -44,7 +45,7 @@
"ButtonMatchBooks": "Spárovat Knihy",
"ButtonNevermind": "Nevadí",
"ButtonNext": "Next",
"ButtonNextChapter": "Next Chapter",
"ButtonNextChapter": "Další Kapitola",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Otevřít kanál",
"ButtonOpenManager": "Otevřít správce",
@ -52,25 +53,24 @@
"ButtonPlay": "Přehrát",
"ButtonPlaying": "Hraje",
"ButtonPlaylists": "Seznamy skladeb",
"ButtonPrevious": "Previous",
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPrevious": "Předchozí",
"ButtonPreviousChapter": "Předchozí Kapitola",
"ButtonPurgeAllCache": "Vyčistit veškerou mezipaměť",
"ButtonPurgeItemsCache": "Vyčistit mezipaměť položek",
"ButtonPurgeMediaProgress": "Vyčistit průběh médií",
"ButtonQueueAddItem": "Přidat do fronty",
"ButtonQueueRemoveItem": "Odstranit z fronty",
"ButtonQuickMatch": "Rychlé přiřazení",
"ButtonReScan": "Znovu prohledat",
"ButtonRead": "Číst",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
"ButtonRefresh": "Refresh",
"ButtonReadLess": "Číst méně",
"ButtonReadMore": "Číst více",
"ButtonRefresh": "Obnovit",
"ButtonRemove": "Odstranit",
"ButtonRemoveAll": "Odstranit vše",
"ButtonRemoveAllLibraryItems": "Odstranit všechny položky knihovny",
"ButtonRemoveFromContinueListening": "Odstranit z Pokračovat v poslechu",
"ButtonRemoveFromContinueReading": "Odstranit z Pokračovat ve čtení",
"ButtonRemoveSeriesFromContinueSeries": "Odstranit sérii z Pokračovat v sérii",
"ButtonReScan": "Znovu prohledat",
"ButtonReset": "Resetovat",
"ButtonResetToDefault": "Obnovit výchozí",
"ButtonRestore": "Obnovit",
@ -83,7 +83,7 @@
"ButtonSelectFolderPath": "Vybrat cestu ke složce",
"ButtonSeries": "Série",
"ButtonSetChaptersFromTracks": "Nastavit kapitoly ze stop",
"ButtonShare": "Share",
"ButtonShare": "Sdílet",
"ButtonShiftTimes": "Časy posunu",
"ButtonShow": "Zobrazit",
"ButtonStartM4BEncode": "Spustit kódování M4B",
@ -98,14 +98,14 @@
"ButtonUserEdit": "Upravit uživatelské {0}",
"ButtonViewAll": "Zobrazit vše",
"ButtonYes": "Ano",
"ErrorUploadFetchMetadataAPI": "Error fetching metadata",
"ErrorUploadFetchMetadataNoResults": "Could not fetch metadata - try updating title and/or author",
"ErrorUploadLacksTitle": "Must have a title",
"ErrorUploadFetchMetadataAPI": "Chyba stahování metadat",
"ErrorUploadFetchMetadataNoResults": "Nepodařilo se načíst metadata - zkuste aktualizovat název a/nebo autora",
"ErrorUploadLacksTitle": "Musí mít titul",
"HeaderAccount": "Účet",
"HeaderAdvanced": "Pokročilé",
"HeaderAppriseNotificationSettings": "Nastavení oznámení Apprise",
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
"HeaderAudioTracks": "Zvukové stopy",
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Zálohy",
"HeaderChangePassword": "Změnit heslo",
@ -115,7 +115,8 @@
"HeaderCollectionItems": "Položky kolekce",
"HeaderCover": "Obálka",
"HeaderCurrentDownloads": "Aktuální stahování",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderCustomMessageOnLogin": "Vlastní zpráva při přihlášení",
"HeaderCustomMetadataProviders": "Vlastní zprostředkovatelé metadat",
"HeaderDetails": "Podrobnosti",
"HeaderDownloadQueue": "Fronta stahování",
"HeaderEbookFiles": "Soubory elektronických knih",
@ -147,7 +148,7 @@
"HeaderNewAccount": "Nový účet",
"HeaderNewLibrary": "Nová knihovna",
"HeaderNotifications": "Oznámení",
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
"HeaderOpenIDConnectAuthentication": "Ověřování pomocí OpenID Connect",
"HeaderOpenRSSFeed": "Otevřít RSS kanál",
"HeaderOtherFiles": "Ostatní soubory",
"HeaderPasswordAuthentication": "Password Authentication",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Položky seznamu přehrávání",
"HeaderPodcastsToAdd": "Podcasty k přidání",
"HeaderPreviewCover": "Náhled obálky",
"HeaderRemoveEpisode": "Odstranit epizodu",
"HeaderRemoveEpisodes": "Odstranit {0} epizody",
"HeaderRSSFeedGeneral": "Podrobnosti o RSS",
"HeaderRSSFeedIsOpen": "Informační kanál RSS je otevřený",
"HeaderRSSFeeds": "RSS kanály",
"HeaderRemoveEpisode": "Odstranit epizodu",
"HeaderRemoveEpisodes": "Odstranit {0} epizody",
"HeaderSavedMediaProgress": "Průběh uložených médií",
"HeaderSchedule": "Plán",
"HeaderScheduleLibraryScans": "Naplánovat automatické prohledávání knihoven",
@ -175,7 +176,7 @@
"HeaderSleepTimer": "Časovač vypnutí",
"HeaderStatsLargestItems": "Největší položky",
"HeaderStatsLongestItems": "Nejdelší položky (hod.)",
"HeaderStatsMinutesListeningChart": "Počet minut poslechu (posledních 7 dní)",
"HeaderStatsMinutesListeningChart": "Poslech za posledních 7 dní (min)",
"HeaderStatsRecentSessions": "Poslední relace",
"HeaderStatsTop10Authors": "Top 10 autorů",
"HeaderStatsTop5Genres": "Top 5 žánrů",
@ -186,23 +187,23 @@
"HeaderUpdateDetails": "Aktualizovat podrobnosti",
"HeaderUpdateLibrary": "Aktualizovat knihovnu",
"HeaderUsers": "Uživatelé",
"HeaderYearReview": "Year {0} in Review",
"HeaderYearReview": "Přehled {0} roku",
"HeaderYourStats": "Vaše statistiky",
"LabelAbridged": "Zkráceno",
"LabelAbridgedChecked": "Abridged (checked)",
"LabelAbridgedUnchecked": "Unabridged (unchecked)",
"LabelAccessibleBy": "Accessible by",
"LabelAbridgedChecked": "Zkráceno (zaškrtnuto)",
"LabelAbridgedUnchecked": "Nezkrácené (nezaškrtnuté)",
"LabelAccessibleBy": "Přístupný prostřednictvím",
"LabelAccountType": "Typ účtu",
"LabelAccountTypeAdmin": "Správce",
"LabelAccountTypeGuest": "Host",
"LabelAccountTypeUser": "Uživatel",
"LabelActivity": "Aktivita",
"LabelAdded": "Přidáno",
"LabelAddedAt": "Přidáno v",
"LabelAddToCollection": "Přidat do kolekce",
"LabelAddToCollectionBatch": "Přidat {0} knihy do kolekce",
"LabelAddToPlaylist": "Přidat do seznamu přehrávání",
"LabelAddToPlaylistBatch": "Přidat {0} položky do seznamu přehrávání",
"LabelAdded": "Přidáno",
"LabelAddedAt": "Přidáno v",
"LabelAdminUsersOnly": "Pouze administrátoři",
"LabelAll": "Vše",
"LabelAllUsers": "Všichni uživatelé",
@ -215,12 +216,12 @@
"LabelAuthorLastFirst": "Autor (příjmení a jméno)",
"LabelAuthors": "Autoři",
"LabelAutoDownloadEpisodes": "Automaticky stahovat epizody",
"LabelAutoFetchMetadata": "Auto Fetch Metadata",
"LabelAutoFetchMetadataHelp": "Fetches metadata for title, author, and series to streamline uploading. Additional metadata may have to be matched after upload.",
"LabelAutoLaunch": "Auto Launch",
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
"LabelAutoRegister": "Auto Register",
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
"LabelAutoFetchMetadata": "Automatické stahování metadat",
"LabelAutoFetchMetadataHelp": "Stáhne metadata pro název, autora a sérii, aby se usnadnilo nahrávání. Další metadata může být nutné spárovat po nahrání.",
"LabelAutoLaunch": "Automatické spuštění",
"LabelAutoLaunchDescription": "Automaticky přesměrovat na zprostředkovatele ověření při vstupu na přihlašovací stránku (ruční přepsání cesty <code>/login?autoLaunch=0</code>)",
"LabelAutoRegister": "Automatická registrace",
"LabelAutoRegisterDescription": "Automaticky vytvářet nové uživatele po přihlášení",
"LabelBackToUser": "Zpět k uživateli",
"LabelBackupLocation": "Umístění zálohy",
"LabelBackupsEnableAutomaticBackups": "Povolit automatické zálohování",
@ -231,13 +232,13 @@
"LabelBackupsNumberToKeepHelp": "Najednou bude odstraněna pouze 1 záloha, takže pokud již máte více záloh, měli byste je odstranit ručně.",
"LabelBitrate": "Datový tok",
"LabelBooks": "Knihy",
"LabelButtonText": "Button Text",
"LabelButtonText": "Text tlačítka",
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Změnit heslo",
"LabelChannels": "Kanály",
"LabelChapterTitle": "Název kapitoly",
"LabelChapters": "Kapitoly",
"LabelChaptersFound": "Kapitoly nalezeny",
"LabelChapterTitle": "Název kapitoly",
"LabelClickForMoreInfo": "Klikněte pro více informací",
"LabelClosePlayer": "Zavřít přehrávač",
"LabelCodec": "Kodek",
@ -269,18 +270,18 @@
"LabelDiscover": "Objevit",
"LabelDownload": "Stáhnout",
"LabelDownloadNEpisodes": "Stáhnout {0} epizody",
"LabelDuration": "Doba trvání",
"LabelDurationComparisonExactMatch": "(exact match)",
"LabelDurationComparisonLonger": "({0} longer)",
"LabelDurationComparisonShorter": "({0} shorter)",
"LabelDuration": "Délka trvání",
"LabelDurationComparisonExactMatch": "(přesná shoda)",
"LabelDurationComparisonLonger": "({0} delší)",
"LabelDurationComparisonShorter": "({0} kratší)",
"LabelDurationFound": "Doba trvání nalezena:",
"LabelEbook": "Elektronická kniha",
"LabelEbooks": "Elektronické knihy",
"LabelEdit": "Upravit",
"LabelEmail": "E-mail",
"LabelEmailSettingsFromAddress": "Z adresy",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Odmítnout neautorizované certifikáty",
"LabelEmailSettingsRejectUnauthorizedHelp": "Vypnutím ověřování certifikátů SSL můžete své připojení vystavit bezpečnostním rizikům, například útokům typu man-in-the-middle. Tuto možnost zakažte pouze v případě, že rozumíte důsledkům a důvěřujete poštovnímu serveru, ke kterému se připojujete.",
"LabelEmailSettingsSecure": "Zabezpečené",
"LabelEmailSettingsSecureHelp": "Pokud je true, připojení bude při připojování k serveru používat TLS. Pokud je false, použije se protokol TLS, pokud server podporuje rozšíření STARTTLS. Ve většině případů nastavte tuto hodnotu na true, pokud se připojujete k portu 465. Pro port 587 nebo 25 ponechte hodnotu false. (z nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Testovací adresa",
@ -292,10 +293,10 @@
"LabelEpisodeType": "Typ epizody",
"LabelExample": "Příklad",
"LabelExplicit": "Explicitní",
"LabelExplicitChecked": "Explicit (checked)",
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
"LabelFeedURL": "URL zdroje",
"LabelFetchingMetadata": "Fetching Metadata",
"LabelFetchingMetadata": "Získávání metadat",
"LabelFile": "Soubor",
"LabelFileBirthtime": "Čas vzniku souboru",
"LabelFileModified": "Soubor změněn",
@ -305,25 +306,26 @@
"LabelFinished": "Dokončeno",
"LabelFolder": "Složka",
"LabelFolders": "Složky",
"LabelFontBold": "Bold",
"LabelFontBold": "Tučně",
"LabelFontBoldness": "Výraznost písma",
"LabelFontFamily": "Rodina písem",
"LabelFontItalic": "Italic",
"LabelFontScale": "Měřítko písma",
"LabelFontStrikethrough": "Strikethrough",
"LabelFontStrikethrough": "Přeškrtnutí",
"LabelFormat": "Formát",
"LabelGenre": "Žánr",
"LabelGenres": "Žánry",
"LabelHardDeleteFile": "Trvale smazat soubor",
"LabelHasEbook": "Obsahuje elektronickou knihu",
"LabelHasSupplementaryEbook": "Obsahuje doplňkovou elektronickou knihu",
"LabelHighestPriority": "Highest priority",
"LabelHighestPriority": "Nejvyšší priorita",
"LabelHost": "Hostitel",
"LabelHour": "Hodina",
"LabelIcon": "Ikona",
"LabelImageURLFromTheWeb": "URL obrázku z webu",
"LabelInProgress": "Probíhá",
"LabelIncludeInTracklist": "Zahrnout do seznamu stop",
"LabelIncomplete": "Neúplné",
"LabelInProgress": "Probíhá",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Vlastní denně/týdně",
"LabelIntervalEvery12Hours": "Každých 12 hodin",
@ -337,6 +339,7 @@
"LabelItem": "Položka",
"LabelLanguage": "Jazyk",
"LabelLanguageDefaultServer": "Výchozí jazyk serveru",
"LabelLanguages": "Jazyky",
"LabelLastBookAdded": "Poslední kniha přidána",
"LabelLastBookUpdated": "Poslední kniha aktualizována",
"LabelLastSeen": "Naposledy viděno",
@ -348,6 +351,7 @@
"LabelLess": "Méně",
"LabelLibrariesAccessibleToUser": "Knihovny přístupné uživateli",
"LabelLibrary": "Knihovna",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Položka knihovny",
"LabelLibraryName": "Název knihovny",
"LabelLimit": "Omezit",
@ -357,50 +361,51 @@
"LabelLogLevelInfo": "Informace",
"LabelLogLevelWarn": "Varovat",
"LabelLookForNewEpisodesAfterDate": "Hledat nové epizody po tomto datu",
"LabelLowestPriority": "Lowest Priority",
"LabelMatchExistingUsersBy": "Match existing users by",
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelLowestPriority": "Nejnižší priorita",
"LabelMatchExistingUsersBy": "Přiřadit stávající uživatele podle",
"LabelMatchExistingUsersByDescription": "Slouží k propojení stávajících uživatelů. Po propojení budou uživatelé přiřazeni k jedinečnému ID od poskytovatele SSO.",
"LabelMediaPlayer": "Přehrávač médií",
"LabelMediaType": "Typ média",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Poskytovatel metadat",
"LabelMetaTag": "Metaznačka",
"LabelMetaTags": "Metaznačky",
"LabelMetadataOrderOfPrecedenceDescription": "Zdroje metadat s vyšší prioritou budou mít přednost před zdroji metadat s nižší prioritou.",
"LabelMetadataProvider": "Poskytovatel metadat",
"LabelMinute": "Minuta",
"LabelMissing": "Chybějící",
"LabelMissingEbook": "Has no ebook",
"LabelMissingSupplementaryEbook": "Has no supplementary ebook",
"LabelMobileRedirectURIs": "Allowed Mobile Redirect URIs",
"LabelMobileRedirectURIsDescription": "This is a whitelist of valid redirect URIs for mobile apps. The default one is <code>audiobookshelf://oauth</code>, which you can remove or supplement with additional URIs for third-party app integration. Using an asterisk (<code>*</code>) as the sole entry permits any URI.",
"LabelMissingEbook": "Nemá elektronickou knihu",
"LabelMissingSupplementaryEbook": "Nemá žádnou doplňkovou elektronickou knihu",
"LabelMobileRedirectURIs": "Povolené mobilní přesměrování URI",
"LabelMobileRedirectURIsDescription": "Toto je seznam povolených přesměrování URI pro mobilní aplikace. Výchozí je <code>audiobookshelf://oauth</code>, který můžete odstranit nebo doplnit o další URI pro integraci aplikací třetích stran. Použití hvězdičky (<code>*</code>) jako jediné položky povoluje libovolný URI.",
"LabelMore": "Více",
"LabelMoreInfo": "Více informací",
"LabelName": "Jméno",
"LabelNarrator": "Interpret",
"LabelNarrators": "Interpreti",
"LabelNew": "Nový",
"LabelNewPassword": "Nové heslo",
"LabelNewestAuthors": "Nejnovější autoři",
"LabelNewestEpisodes": "Nejnovější epizody",
"LabelNewPassword": "Nové heslo",
"LabelNextBackupDate": "Datum příští zálohy",
"LabelNextScheduledRun": "Další naplánované spuštění",
"LabelNoCustomMetadataProviders": "Žádní vlastní poskytovatelé metadat",
"LabelNoEpisodesSelected": "Nebyly vybrány žádné epizody",
"LabelNotes": "Poznámky",
"LabelNotFinished": "Nedokončeno",
"LabelNotStarted": "Nezahájeno",
"LabelNotes": "Poznámky",
"LabelNotificationAppriseURL": "URL adresy Apprise",
"LabelNotificationAvailableVariables": "Dostupné proměnné",
"LabelNotificationBodyTemplate": "Šablona těla",
"LabelNotificationEvent": "Událost oznámení",
"LabelNotificationTitleTemplate": "Šablona názvu",
"LabelNotificationsMaxFailedAttempts": "Maximální počet neúspěšných pokusů",
"LabelNotificationsMaxFailedAttemptsHelp": "Oznámení jsou vypnuta, pokud se jim to nepodaří odeslat",
"LabelNotificationsMaxQueueSize": "Maximální velikost fronty pro oznamovací události",
"LabelNotificationsMaxQueueSizeHelp": "Události jsou omezeny na 1 za sekundu. Události budou ignorovány, pokud je fronta v maximální velikosti. Tím se zabrání spamování oznámení.",
"LabelNotificationTitleTemplate": "Šablona názvu",
"LabelNotStarted": "Nezahájeno",
"LabelNumberOfBooks": "Počet knih",
"LabelNumberOfEpisodes": "Počet epizod",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
"LabelOpenIDClaims": "Leave the following options empty to disable advanced group and permissions assignment, automatically assigning 'User' group then.",
"LabelOpenIDGroupClaimDescription": "Name of the OpenID claim that contains a list of the user's groups. Commonly referred to as <code>groups</code>. <b>If configured</b>, the application will automatically assign roles based on the user's group memberships, provided that these groups are named case-insensitively 'admin', 'user', or 'guest' in the claim. The claim should contain a list, and if a user belongs to multiple groups, the application will assign the role corresponding to the highest level of access. If no group matches, access will be denied.",
"LabelOpenIDAdvancedPermsClaimDescription": "Název požadavku OpenID, který obsahuje rozšířená oprávnění pro akce uživatele v rámci aplikace, která se budou vztahovat na role, které nejsou administrátory (<b>pokud jsou nakonfigurovány</b>). Pokud požadavek v odpovědi chybí, přístup do systému ABS bude zamítnut. Pokud chybí jediná možnost, bude považována za <code>false</code>. Ujistěte se, že deklarace poskytovatele identity odpovídá očekávané struktuře:",
"LabelOpenIDClaims": "Následující možnosti ponechte prázdné, abyste zakázali pokročilé přiřazování skupin a oprávnění a automatické přiřazení skupiny \"User\".",
"LabelOpenIDGroupClaimDescription": "Název požadavku OpenID, který obsahuje seznam uživatelských skupin. Běžně se označuje jako <code>groups</code>. <b>Je-li nakonfigurováno</b>, plikace automaticky přiřadí role na základě členství uživatele ve skupinách, pokud jsou tyto skupiny v požadavku pojmenovány case-insensitive 'admin', 'user' nebo 'guest'. Požadavek by měl obsahovat seznam, a pokud uživatel patří do více skupin, aplikace přiřadí roli odpovídající nejvyšší úrovni práva přístupu. Pokud žádná skupina není shodná, bude přístup odepřen.",
"LabelOpenRSSFeed": "Otevřít RSS kanál",
"LabelOverwrite": "Přepsat",
"LabelPassword": "Heslo",
@ -412,14 +417,15 @@
"LabelPermissionsDownload": "Může stahovat",
"LabelPermissionsUpdate": "Může aktualizovat",
"LabelPermissionsUpload": "Může nahrávat",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPersonalYearReview": "Váš přehled roku ({0})",
"LabelPhotoPathURL": "Cesta k fotografii/URL",
"LabelPlaylists": "Seznamy skladeb",
"LabelPlayMethod": "Metoda přehrávání",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Seznamy skladeb",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasty",
"LabelPodcastSearchRegion": "Oblast vyhledávání podcastu",
"LabelPodcastType": "Typ podcastu",
"LabelPodcasts": "Podcasty",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Předpony, které se mají ignorovat (nerozlišují se malá a velká písmena)",
"LabelPreventIndexing": "Zabránit indexování vašeho kanálu v adresářích podcastů iTunes a Google",
@ -427,30 +433,31 @@
"LabelProgress": "Průběh",
"LabelProvider": "Poskytovatel",
"LabelPubDate": "Datum vydání",
"LabelPublisher": "Vydavatel",
"LabelPublishYear": "Rok vydání",
"LabelRead": "Číst",
"LabelReadAgain": "Číst znovu",
"LabelReadEbookWithoutProgress": "Číst e-knihu bez zachování průběhu",
"LabelRecentlyAdded": "Nedávno přidané",
"LabelRecentSeries": "Nedávné série",
"LabelRecommended": "Doporučeno",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Datum vydání",
"LabelRemoveCover": "Odstranit obálku",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Vydavatel",
"LabelPublishers": "Vydavatelé",
"LabelRSSFeedCustomOwnerEmail": "Vlastní e-mail vlastníka",
"LabelRSSFeedCustomOwnerName": "Vlastní jméno vlastníka",
"LabelRSSFeedOpen": "Otevření RSS kanálu",
"LabelRSSFeedPreventIndexing": "Zabránit indexování",
"LabelRSSFeedSlug": "RSS kanál Slug",
"LabelRSSFeedURL": "URL RSS kanálu",
"LabelRead": "Číst",
"LabelReadAgain": "Číst znovu",
"LabelReadEbookWithoutProgress": "Číst e-knihu bez zachování průběhu",
"LabelRecentSeries": "Nedávné série",
"LabelRecentlyAdded": "Nedávno přidané",
"LabelRecommended": "Doporučeno",
"LabelRedo": "Přepracovat",
"LabelRegion": "Region",
"LabelReleaseDate": "Datum vydání",
"LabelRemoveCover": "Odstranit obálku",
"LabelRowsPerPage": "Řádky na stránku",
"LabelSearchTerm": "Vyhledat termín",
"LabelSearchTitle": "Vyhledat název",
"LabelSearchTitleOrASIN": "Vyhledat název nebo ASIN",
"LabelSeason": "Sezóna",
"LabelSelectAll": "Select all",
"LabelSelectAll": "Vybrat vše",
"LabelSelectAllEpisodes": "Vybrat všechny epizody",
"LabelSelectEpisodesShowing": "Vyberte {0} epizody, které se zobrazují",
"LabelSelectUsers": "Vybrat uživatele",
@ -459,7 +466,7 @@
"LabelSeries": "Série",
"LabelSeriesName": "Název série",
"LabelSeriesProgress": "Průběh série",
"LabelServerYearReview": "Server Year in Review ({0})",
"LabelServerYearReview": "Přehled roku na serveru ({0})",
"LabelSetEbookAsPrimary": "Nastavit jako primární",
"LabelSetEbookAsSupplementary": "Nastavit jako doplňkové",
"LabelSettingsAudiobooksOnly": "Pouze audioknihy",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Povolit sledování",
"LabelSettingsEnableWatcherForLibrary": "Povolit sledování složky pro knihovnu",
"LabelSettingsEnableWatcherHelp": "Povoluje automatické přidávání/aktualizaci položek, když jsou zjištěny změny souborů. *Vyžaduje restart serveru",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "Povolení skriptovaného obsahu v epubu",
"LabelSettingsEpubsAllowScriptedContentHelp": "Povolení spouštění skriptů v souborech epub. Doporučujeme toto nastavení vypnout, pokud nedůvěřujete zdroji souborů epub.",
"LabelSettingsExperimentalFeatures": "Experimentální funkce",
"LabelSettingsExperimentalFeaturesHelp": "Funkce ve vývoji, které by mohly využít vaši zpětnou vazbu a pomoc s testováním. Kliknutím otevřete diskuzi na githubu.",
"LabelSettingsFindCovers": "Najít obálky",
@ -483,10 +490,10 @@
"LabelSettingsHideSingleBookSeriesHelp": "Série, které mají jedinou knihu, budou skryty na stránce série a na domovské stránce.",
"LabelSettingsHomePageBookshelfView": "Domovská stránka používá zobrazení police s knihami",
"LabelSettingsLibraryBookshelfView": "Knihovna používá zobrazení police s knihami",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Skip earlier books in Continue Series",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "The Continue Series home page shelf shows the first book not started in series that have at least one book finished and no books in progress. Enabling this setting will continue series from the furthest completed book instead of the first book not started.",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Přeskočit předchozí knihy v pokračování série",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Polička Pokračovat v sérii na domovské stránce zobrazuje první nezačatou knihu v sériích, které mají alespoň jednu knihu dokončenou a žádnou rozečtenou. Povolením tohoto nastavení budou série pokračovat od poslední dokončené knihy namísto první nezačaté knihy.",
"LabelSettingsParseSubtitles": "Analzyovat podtitul",
"LabelSettingsParseSubtitlesHelp": "Rozparsovat podtitul z názvů složek audioknih.<br>Podtiul musí být oddělen znakem \" - \"<br>tj. \"Název knihy - Zde Podtitul\" má podtitul \"Zde podtitul\"",
"LabelSettingsParseSubtitlesHelp": "Rozparsovat podtitul z názvů složek audioknih.<br>Podtiul musí být oddělen znakem \" - \"<br>tj. \"Název knihy - Zde Podtitul\" má podtitul \"Zde podtitul\"",
"LabelSettingsPreferMatchedMetadata": "Preferovat spárovaná metadata",
"LabelSettingsPreferMatchedMetadataHelp": "Spárovaná data budou mít při použití funkce Rychlé párování přednost před údaji o položce. Ve výchozím nastavení funkce Rychlé párování pouze doplní chybějící údaje.",
"LabelSettingsSkipMatchingBooksWithASIN": "Přeskočit párování knih, které již mají ASIN",
@ -501,14 +508,14 @@
"LabelSettingsStoreMetadataWithItemHelp": "Ve výchozím nastavení jsou soubory metadat uloženy v adresáři /metadata/items, povolením tohoto nastavení budou soubory metadat uloženy ve složkách položek knihovny",
"LabelSettingsTimeFormat": "Formát času",
"LabelShowAll": "Zobrazit vše",
"LabelShowSeconds": "Show seconds",
"LabelShowSeconds": "Zobrazit sekundy",
"LabelSize": "Velikost",
"LabelSleepTimer": "Časovač vypnutí",
"LabelSlug": "Slug",
"LabelStart": "Spustit",
"LabelStartTime": "Čas Spuštění",
"LabelStarted": "Spuštěno",
"LabelStartedAt": "Spuštěno v",
"LabelStartTime": "Čas Spuštění",
"LabelStatsAudioTracks": "Zvukové stopy",
"LabelStatsAuthors": "Autoři",
"LabelStatsBestDay": "Nejlepší den",
@ -531,10 +538,10 @@
"LabelTagsAccessibleToUser": "Značky přístupné uživateli",
"LabelTagsNotAccessibleToUser": "Značky nepřístupné uživateli",
"LabelTasks": "Spuštěné Úlohy",
"LabelTextEditorBulletedList": "Bulleted list",
"LabelTextEditorBulletedList": "Seznam s odrážkami",
"LabelTextEditorLink": "Link",
"LabelTextEditorNumberedList": "Numbered list",
"LabelTextEditorUnlink": "Unlink",
"LabelTextEditorNumberedList": "Seznam s čísly",
"LabelTextEditorUnlink": "Zrušit odkaz",
"LabelTheme": "Téma",
"LabelThemeDark": "Tmavé",
"LabelThemeLight": "Světlé",
@ -560,16 +567,16 @@
"LabelTracksSingleTrack": "Jedna stopa",
"LabelType": "Typ",
"LabelUnabridged": "Nezkráceno",
"LabelUndo": "Undo",
"LabelUndo": "Zpět",
"LabelUnknown": "Neznámý",
"LabelUpdateCover": "Aktualizovat obálku",
"LabelUpdateCoverHelp": "Povolit přepsání existujících obálek pro vybrané knihy, pokud je nalezena shoda",
"LabelUpdatedAt": "Aktualizováno v",
"LabelUpdateDetails": "Aktualizovat podrobnosti",
"LabelUpdateDetailsHelp": "Povolit přepsání existujících údajů o vybraných knihách, když je nalezena shoda",
"LabelUpdatedAt": "Aktualizováno v",
"LabelUploaderDragAndDrop": "Přetáhnout soubory nebo složky",
"LabelUploaderDropFiles": "Odstranit soubory",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
"LabelUploaderItemFetchMetadataHelp": "Automaticky načíst název, autora a sérii",
"LabelUseChapterTrack": "Použít stopu kapitoly",
"LabelUseFullTrack": "Použít celou stopu",
"LabelUser": "Uživatel",
@ -581,8 +588,8 @@
"LabelViewQueue": "Zobrazit frontu přehrávače",
"LabelVolume": "Hlasitost",
"LabelWeekdaysToRun": "Dny v týdnu ke spuštění",
"LabelYearReviewHide": "Hide Year in Review",
"LabelYearReviewShow": "See Year in Review",
"LabelYearReviewHide": "Skrýt rok v přehledu",
"LabelYearReviewShow": "Zobrazit rok v přehledu",
"LabelYourAudiobookDuration": "Doba trvání vaší audioknihy",
"LabelYourBookmarks": "Vaše záložky",
"LabelYourPlaylists": "Vaše seznamy přehrávání",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Zálohy zahrnují uživatele, průběh uživatele, podrobnosti o položkách knihovny, nastavení serveru a obrázky uložené v <code>/metadata/items</code> a <code>/metadata/authors</code>. Zálohy <strong>ne</strong> zahrnují všechny soubory uložené ve složkách knihovny.",
"MessageBatchQuickMatchDescription": "Rychlá párování se pokusí přidat chybějící obálky a metadata pro vybrané položky. Povolením níže uvedených možností umožníte funkci Rychlé párování přepsat stávající obálky a/nebo metadata.",
"MessageBookshelfNoCollections": "Ještě jste nevytvořili žádnou sbírku",
"MessageBookshelfNoResultsForFilter": "Filtr \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Nejsou otevřeny žádné RSS kanály",
"MessageBookshelfNoResultsForFilter": "Filtr \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Žádné výsledky pro dotaz",
"MessageBookshelfNoSeries": "Nemáte žádnou sérii",
"MessageChapterEndIsAfter": "Konec kapitoly přesahuje konec audioknihy",
"MessageChapterErrorFirstNotZero": "První kapitola musí začínat na 0",
@ -613,14 +621,16 @@
"MessageConfirmMarkAllEpisodesNotFinished": "Opravdu chcete označit všechny epizody jako nedokončené?",
"MessageConfirmMarkSeriesFinished": "Opravdu chcete označit všechny knihy z této série jako dokončené?",
"MessageConfirmMarkSeriesNotFinished": "Opravdu chcete označit všechny knihy z této série jako nedokončené?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeCache": "Vyčistit mezipaměť odstraní celý adresář na adrese <code>/metadata/cache</code>. <br /><br />Určitě chcete odstranit adresář mezipaměti?",
"MessageConfirmPurgeItemsCache": "Vyčištění mezipaměti položek odstraní celý adresář <code>/metadata/cache/items</code>.<br />Jste si jistí?",
"MessageConfirmQuickEmbed": "Varování! Rychlé vložení nezálohuje vaše zvukové soubory. Ujistěte se, že máte zálohu zvukových souborů. <br><br>Chcete pokračovat?",
"MessageConfirmReScanLibraryItems": "Opravdu chcete znovu prohledat {0} položky?",
"MessageConfirmRemoveAllChapters": "Opravdu chcete odstranit všechny kapitoly?",
"MessageConfirmRemoveAuthor": "Opravdu chcete odstranit autora \"{0}\"?",
"MessageConfirmRemoveCollection": "Opravdu chcete odstranit kolekci \"{0}\"?",
"MessageConfirmRemoveEpisode": "Opravdu chcete odstranit epizodu \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Opravdu chcete odstranit {0} epizody?",
"MessageConfirmRemoveListeningSessions": "Are you sure you want to remove {0} listening sessions?",
"MessageConfirmRemoveListeningSessions": "Opravdu chcete odebrat {0} poslechových relací?",
"MessageConfirmRemoveNarrator": "Opravdu chcete odebrat předčítání \"{0}\"?",
"MessageConfirmRemovePlaylist": "Opravdu chcete odstranit svůj playlist \"{0}\"?",
"MessageConfirmRenameGenre": "Opravdu chcete přejmenovat žánr \"{0}\" na \"{1}\" pro všechny položky?",
@ -629,13 +639,12 @@
"MessageConfirmRenameTag": "Opravdu chcete přejmenovat tag \"{0}\" na \"{1}\" pro všechny položky?",
"MessageConfirmRenameTagMergeNote": "Poznámka: Tato značka již existuje, takže budou sloučeny.",
"MessageConfirmRenameTagWarning": "Varování! Podobná značka s jinými velkými a malými písmeny již existuje \"{0}\".",
"MessageConfirmReScanLibraryItems": "Opravdu chcete znovu prohledat {0} položky?",
"MessageConfirmSendEbookToDevice": "Opravdu chcete odeslat e-knihu {0} {1}\" do zařízení \"{2}\"?",
"MessageDownloadingEpisode": "Stahuji epizodu",
"MessageDragFilesIntoTrackOrder": "Přetáhněte soubory do správného pořadí stop",
"MessageEmbedFinished": "Vložení dokončeno!",
"MessageEpisodesQueuedForDownload": "{0} epizody zařazené do fronty ke stažení",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "Aby bylo zajištěno doručení elektronických knih, může být nutné přidat výše uvedenou e-mailovou adresu jako platného odesílatele pro každé zařízení uvedené níže.",
"MessageFeedURLWillBe": "URL zdroje bude {0}",
"MessageFetching": "Stahování...",
"MessageForceReScanDescription": "znovu prohledá všechny soubory jako při novém skenování. ID3 tagy zvukových souborů OPF soubory a textové soubory budou skenovány jako nové.",
@ -647,7 +656,7 @@
"MessageListeningSessionsInTheLastYear": "{0} poslechových relací za poslední rok",
"MessageLoading": "Načítá se...",
"MessageLoadingFolders": "Načítám složky...",
"MessageLogsDescription": "Logs are stored in <code>/metadata/logs</code> as JSON files. Crash logs are stored in <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "Protokoly se ukládají do souborů JSON v <code>/metadata/logs</code>. Protokoly o pádech jsou uloženy v <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "M4B se nezdařil!",
"MessageM4BFinished": "M4B dokončen!",
"MessageMapChapterTitles": "Mapování názvů kapitol ke stávajícím kapitolám audioknihy bez úpravy časových razítek",
@ -683,10 +692,10 @@
"MessageNoSeries": "Žádné série",
"MessageNoTags": "Žádné značky",
"MessageNoTasksRunning": "Nejsou spuštěny žádné úlohy",
"MessageNotYetImplemented": "Ještě není implementováno",
"MessageNoUpdateNecessary": "Není nutná žádná aktualizace",
"MessageNoUpdatesWereNecessary": "Nebyly nutné žádné aktualizace",
"MessageNoUserPlaylists": "Nemáte žádné seznamy skladeb",
"MessageNotYetImplemented": "Ještě není implementováno",
"MessageOr": "nebo",
"MessagePauseChapter": "Pozastavit přehrávání kapitoly",
"MessagePlayChapter": "Poslechnout si začátek kapitoly",
@ -699,10 +708,10 @@
"MessageRemoveUserWarning": "Opravdu chcete trvale smazat uživatele \"{0}\"?",
"MessageReportBugsAndContribute": "Hlásit chyby, žádat o funkce a přispívat",
"MessageResetChaptersConfirm": "Opravdu chcete resetovat kapitoly a vrátit zpět provedené změny?",
"MessageRestoreBackupConfirm": "Opravdu chcete obnovit zálohu vytvořenou dne?",
"MessageRestoreBackupConfirm": "Opravdu chcete obnovit zálohu vytvořenou dne",
"MessageRestoreBackupWarning": "Obnovení zálohy přepíše celou databázi umístěnou v /config a obálku obrázků v /metadata/items & /metadata/authors.<br /><br />Backups nezmění žádné soubory ve složkách knihovny. Pokud jste povolili nastavení serveru pro ukládání obrázků obalu a metadat do složek knihovny, nebudou zálohovány ani přepsány.<br /><br />Všichni klienti používající váš server budou automaticky obnoveni.",
"MessageSearchResultsFor": "Výsledky hledání pro",
"MessageSelected": "{0} selected",
"MessageSelected": "{0} vybráno",
"MessageServerCouldNotBeReached": "Server je nedostupný",
"MessageSetChaptersFromTracksDescription": "Nastavit kapitoly jako kapitolu a název kapitoly jako název zvukového souboru",
"MessageStartPlaybackAtTime": "Spustit přehrávání pro \"{0}\" v {1}?",
@ -714,7 +723,7 @@
"MessageWatcherIsDisabledGlobally": "Hlídač je globálně zakázán v nastavení serveru",
"MessageXLibraryIsEmpty": "{0} knihovna je prázdná!",
"MessageYourAudiobookDurationIsLonger": "Doba trvání audioknihy je delší než nalezená délka",
"MessageYourAudiobookDurationIsShorter": "Délka audioknihy je kratší, než byla nalezena.",
"MessageYourAudiobookDurationIsShorter": "Délka audioknihy je kratší, než byla nalezena",
"NoteChangeRootPassword": "Uživatel root je jediný uživatel, který může mít prázdné heslo",
"NoteChapterEditorTimes": "Poznámka: Čas začátku první kapitoly musí zůstat v 0:00 a čas začátku poslední kapitoly nesmí překročit tuto dobu trvání audioknihy.",
"NoteFolderPicker": "Poznámka: složky, které jsou již namapovány, nebudou zobrazeny",
@ -751,8 +760,8 @@
"ToastBookmarkRemoveSuccess": "Záložka odstraněna",
"ToastBookmarkUpdateFailed": "Aktualizace záložky se nezdařila",
"ToastBookmarkUpdateSuccess": "Záložka aktualizována",
"ToastCachePurgeFailed": "Failed to purge cache",
"ToastCachePurgeSuccess": "Cache purged successfully",
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
"ToastChaptersHaveErrors": "Kapitoly obsahují chyby",
"ToastChaptersMustHaveTitles": "Kapitoly musí mít názvy",
"ToastCollectionItemsRemoveFailed": "Nepodařilo se odstranit položky z kolekce",
@ -761,9 +770,9 @@
"ToastCollectionRemoveSuccess": "Kolekce odstraněna",
"ToastCollectionUpdateFailed": "Aktualizace kolekce se nezdařila",
"ToastCollectionUpdateSuccess": "Kolekce aktualizována",
"ToastDeleteFileFailed": "Failed to delete file",
"ToastDeleteFileSuccess": "File deleted",
"ToastFailedToLoadData": "Failed to load data",
"ToastDeleteFileFailed": "Nepodařilo se smazat soubor",
"ToastDeleteFileSuccess": "Soubor smazán",
"ToastFailedToLoadData": "Nepodařilo se načíst data",
"ToastItemCoverUpdateFailed": "Aktualizace obálky se nezdařila",
"ToastItemCoverUpdateSuccess": "Obálka předmětu byl aktualizována",
"ToastItemDetailsUpdateFailed": "Nepodařilo se aktualizovat podrobnosti o položce",
@ -789,24 +798,24 @@
"ToastPlaylistUpdateSuccess": "Seznam přehrávání aktualizován",
"ToastPodcastCreateFailed": "Vytvoření podcastu se nezdařilo",
"ToastPodcastCreateSuccess": "Podcast byl úspěšně vytvořen",
"ToastRemoveItemFromCollectionFailed": "Nepodařilo se odebrat položku z kolekce",
"ToastRemoveItemFromCollectionSuccess": "Položka odstraněna z kolekce",
"ToastRSSFeedCloseFailed": "Nepodařilo se zavřít RSS kanál",
"ToastRSSFeedCloseSuccess": "RSS kanál uzavřen",
"ToastRemoveItemFromCollectionFailed": "Nepodařilo se odebrat položku z kolekce",
"ToastRemoveItemFromCollectionSuccess": "Položka odstraněna z kolekce",
"ToastSendEbookToDeviceFailed": "Odeslání e-knihy do zařízení se nezdařilo",
"ToastSendEbookToDeviceSuccess": "E-kniha odeslána do zařízení \"{0}\"",
"ToastSeriesUpdateFailed": "Aktualizace série se nezdařila",
"ToastSeriesUpdateSuccess": "Aktualizace série byla úspěšná",
"ToastServerSettingsUpdateFailed": "Failed to update server settings",
"ToastServerSettingsUpdateSuccess": "Server settings updated",
"ToastServerSettingsUpdateFailed": "Nepodařilo se aktualizovat nastavení serveru",
"ToastServerSettingsUpdateSuccess": "Nastavení serveru aktualizováno",
"ToastSessionDeleteFailed": "Nepodařilo se smazat relaci",
"ToastSessionDeleteSuccess": "Relace smazána",
"ToastSocketConnected": "Socket připojen",
"ToastSocketDisconnected": "Socket odpojen",
"ToastSocketFailedToConnect": "Socket se nepodařilo připojit",
"ToastSortingPrefixesEmptyError": "Must have at least 1 sorting prefix",
"ToastSortingPrefixesUpdateFailed": "Failed to update sorting prefixes",
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastSortingPrefixesEmptyError": "Musí mít alespoň 1 třídicí předponu",
"ToastSortingPrefixesUpdateFailed": "Nepodařilo se aktualizovat třídicí předpony",
"ToastSortingPrefixesUpdateSuccess": "Aktualizovány předpony třídění ({0} položek)",
"ToastUserDeleteFailed": "Nepodařilo se smazat uživatele",
"ToastUserDeleteSuccess": "Uživatel smazán"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Anvend",
"ButtonApplyChapters": "Anvend kapitler",
"ButtonAuthors": "Forfattere",
"ButtonBack": "Tilbage",
"ButtonBrowseForFolder": "Gennemse mappe",
"ButtonCancel": "Annuller",
"ButtonCancelEncode": "Annuller kodning",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Ryd al cache",
"ButtonPurgeItemsCache": "Ryd elementcache",
"ButtonPurgeMediaProgress": "Ryd Medieforløb",
"ButtonQueueAddItem": "Tilføj til kø",
"ButtonQueueRemoveItem": "Fjern fra kø",
"ButtonQuickMatch": "Hurtig Match",
"ButtonReScan": "Gen-scan",
"ButtonRead": "Læs",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Fjern fra Fortsæt Lytning",
"ButtonRemoveFromContinueReading": "Fjern fra Fortsæt Læsning",
"ButtonRemoveSeriesFromContinueSeries": "Fjern Serie fra Fortsæt Serie",
"ButtonReScan": "Gen-scan",
"ButtonReset": "Nulstil",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "Gendan",
@ -104,8 +104,8 @@
"HeaderAccount": "Konto",
"HeaderAdvanced": "Avanceret",
"HeaderAppriseNotificationSettings": "Apprise Notifikationsindstillinger",
"HeaderAudiobookTools": "Audiobog Filhåndteringsværktøjer",
"HeaderAudioTracks": "Lydspor",
"HeaderAudiobookTools": "Audiobog Filhåndteringsværktøjer",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Sikkerhedskopier",
"HeaderChangePassword": "Skift Adgangskode",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Samlingselementer",
"HeaderCover": "Omslag",
"HeaderCurrentDownloads": "Nuværende Downloads",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Detaljer",
"HeaderDownloadQueue": "Download Kø",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Afspilningsliste Elementer",
"HeaderPodcastsToAdd": "Podcasts til Tilføjelse",
"HeaderPreviewCover": "Forhåndsvis Omslag",
"HeaderRemoveEpisode": "Fjern Episode",
"HeaderRemoveEpisodes": "Fjern {0} Episoder",
"HeaderRSSFeedGeneral": "RSS Detaljer",
"HeaderRSSFeedIsOpen": "RSS Feed er Åben",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Fjern Episode",
"HeaderRemoveEpisodes": "Fjern {0} Episoder",
"HeaderSavedMediaProgress": "Gemt Medieforløb",
"HeaderSchedule": "Planlæg",
"HeaderScheduleLibraryScans": "Planlæg Automatiske Biblioteksscanninger",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gæst",
"LabelAccountTypeUser": "Bruger",
"LabelActivity": "Aktivitet",
"LabelAdded": "Tilføjet",
"LabelAddedAt": "Tilføjet Kl.",
"LabelAddToCollection": "Tilføj til Samling",
"LabelAddToCollectionBatch": "Tilføj {0} Bøger til Samling",
"LabelAddToPlaylist": "Tilføj til Afspilningsliste",
"LabelAddToPlaylistBatch": "Tilføj {0} Elementer til Afspilningsliste",
"LabelAdded": "Tilføjet",
"LabelAddedAt": "Tilføjet Kl.",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "Alle",
"LabelAllUsers": "Alle Brugere",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Ændre Adgangskode",
"LabelChannels": "Kanaler",
"LabelChapterTitle": "Kapitel Titel",
"LabelChapters": "Kapitler",
"LabelChaptersFound": "fundne kapitler",
"LabelChapterTitle": "Kapitel Titel",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Luk afspiller",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Mappe",
"LabelFolders": "Mapper",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Fontfamilie",
"LabelFontItalic": "Italic",
"LabelFontScale": "Skriftstørrelse",
@ -321,9 +323,9 @@
"LabelHour": "Time",
"LabelIcon": "Ikon",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "I gang",
"LabelIncludeInTracklist": "Inkluder i afspilningsliste",
"LabelIncomplete": "Ufuldstændig",
"LabelInProgress": "I gang",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Tilpasset dagligt/ugentligt",
"LabelIntervalEvery12Hours": "Hver 12. time",
@ -337,6 +339,7 @@
"LabelItem": "Element",
"LabelLanguage": "Sprog",
"LabelLanguageDefaultServer": "Standard server sprog",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Senest tilføjede bog",
"LabelLastBookUpdated": "Senest opdaterede bog",
"LabelLastSeen": "Sidst set",
@ -348,6 +351,7 @@
"LabelLess": "Mindre",
"LabelLibrariesAccessibleToUser": "Biblioteker tilgængelige for bruger",
"LabelLibrary": "Bibliotek",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Bibliotekselement",
"LabelLibraryName": "Biblioteksnavn",
"LabelLimit": "Grænse",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Medieafspiller",
"LabelMediaType": "Medietype",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadataudbyder",
"LabelMetaTag": "Meta-tag",
"LabelMetaTags": "Meta-tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadataudbyder",
"LabelMinute": "Minut",
"LabelMissing": "Mangler",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Fortæller",
"LabelNarrators": "Fortællere",
"LabelNew": "Ny",
"LabelNewPassword": "Nyt kodeord",
"LabelNewestAuthors": "Nyeste forfattere",
"LabelNewestEpisodes": "Nyeste episoder",
"LabelNewPassword": "Nyt kodeord",
"LabelNextBackupDate": "Næste sikkerhedskopi dato",
"LabelNextScheduledRun": "Næste planlagte kørsel",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Ingen episoder valgt",
"LabelNotes": "Noter",
"LabelNotFinished": "Ikke færdig",
"LabelNotStarted": "Ikke påbegyndt",
"LabelNotes": "Noter",
"LabelNotificationAppriseURL": "Apprise URL'er",
"LabelNotificationAvailableVariables": "Tilgængelige variabler",
"LabelNotificationBodyTemplate": "Kropsskabelon",
"LabelNotificationEvent": "Meddelelseshændelse",
"LabelNotificationTitleTemplate": "Titelskabelon",
"LabelNotificationsMaxFailedAttempts": "Maksimalt antal mislykkede forsøg",
"LabelNotificationsMaxFailedAttemptsHelp": "Meddelelser deaktiveres, når de mislykkes med at sende så mange gange",
"LabelNotificationsMaxQueueSize": "Maksimal køstørrelse for meddelelseshændelser",
"LabelNotificationsMaxQueueSizeHelp": "Hændelser begrænses til at udløse en gang pr. sekund. Hændelser ignoreres, hvis køen er fyldt. Dette forhindrer meddelelsesspam.",
"LabelNotificationTitleTemplate": "Titelskabelon",
"LabelNotStarted": "Ikke påbegyndt",
"LabelNumberOfBooks": "Antal bøger",
"LabelNumberOfEpisodes": "Antal episoder",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Kan uploade",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Foto sti/URL",
"LabelPlaylists": "Afspilningslister",
"LabelPlayMethod": "Afspilningsmetode",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Afspilningslister",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Podcast søgeområde",
"LabelPodcastType": "Podcast type",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Præfikser der skal ignoreres (skal ikke skelne mellem store og små bogstaver)",
"LabelPreventIndexing": "Forhindrer, at dit feed bliver indekseret af iTunes og Google podcastkataloger",
@ -427,25 +433,26 @@
"LabelProgress": "Fremskridt",
"LabelProvider": "Udbyder",
"LabelPubDate": "Udgivelsesdato",
"LabelPublisher": "Forlag",
"LabelPublishYear": "Udgivelsesår",
"LabelRead": "Læst",
"LabelReadAgain": "Læs igen",
"LabelReadEbookWithoutProgress": "Læs e-bog uden at følge fremskridt",
"LabelRecentlyAdded": "Senest tilføjet",
"LabelRecentSeries": "Seneste serie",
"LabelRecommended": "Anbefalet",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Udgivelsesdato",
"LabelRemoveCover": "Fjern omslag",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Forlag",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Brugerdefineret ejerens e-mail",
"LabelRSSFeedCustomOwnerName": "Brugerdefineret ejerens navn",
"LabelRSSFeedOpen": "Åben RSS-feed",
"LabelRSSFeedPreventIndexing": "Forhindrer indeksering",
"LabelRSSFeedSlug": "RSS-feed-slug",
"LabelRSSFeedURL": "RSS-feed-URL",
"LabelRead": "Læst",
"LabelReadAgain": "Læs igen",
"LabelReadEbookWithoutProgress": "Læs e-bog uden at følge fremskridt",
"LabelRecentSeries": "Seneste serie",
"LabelRecentlyAdded": "Senest tilføjet",
"LabelRecommended": "Anbefalet",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Udgivelsesdato",
"LabelRemoveCover": "Fjern omslag",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Søgeterm",
"LabelSearchTitle": "Søg efter titel",
"LabelSearchTitleOrASIN": "Søg efter titel eller ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Søvntimer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Starttid",
"LabelStarted": "Startet",
"LabelStartedAt": "Startet klokken",
"LabelStartTime": "Starttid",
"LabelStatsAudioTracks": "Lydspor",
"LabelStatsAuthors": "Forfattere",
"LabelStatsBestDay": "Bedste dag",
@ -564,9 +571,9 @@
"LabelUnknown": "Ukendt",
"LabelUpdateCover": "Opdater omslag",
"LabelUpdateCoverHelp": "Tillad overskrivning af eksisterende omslag for de valgte bøger, når der findes en match",
"LabelUpdatedAt": "Opdateret ved",
"LabelUpdateDetails": "Opdater detaljer",
"LabelUpdateDetailsHelp": "Tillad overskrivning af eksisterende detaljer for de valgte bøger, når der findes en match",
"LabelUpdatedAt": "Opdateret ved",
"LabelUploaderDragAndDrop": "Træk og slip filer eller mapper",
"LabelUploaderDropFiles": "Smid filer",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Backups inkluderer brugere, brugerfremskridt, biblioteksvareoplysninger, serverindstillinger og billeder gemt i <code>/metadata/items</code> og <code>/metadata/authors</code>. Backups inkluderer <strong>ikke</strong> nogen filer gemt i dine biblioteksmapper.",
"MessageBatchQuickMatchDescription": "Quick Match vil forsøge at tilføje manglende omslag og metadata til de valgte elementer. Aktivér indstillingerne nedenfor for at tillade Quick Match at overskrive eksisterende omslag og/eller metadata.",
"MessageBookshelfNoCollections": "Du har ikke oprettet nogen samlinger endnu",
"MessageBookshelfNoResultsForFilter": "Ingen resultater for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Ingen RSS-feeds er åbne",
"MessageBookshelfNoResultsForFilter": "Ingen resultater for filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Du har ingen serier",
"MessageChapterEndIsAfter": "Kapitelslutningen er efter slutningen af din lydbog",
"MessageChapterErrorFirstNotZero": "Første kapitel skal starte ved 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Er du sikker på, at du vil markere alle bøger i denne serie som afsluttet?",
"MessageConfirmMarkSeriesNotFinished": "Er du sikker på, at du vil markere alle bøger i denne serie som ikke afsluttet?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Er du sikker på, at du vil fjerne alle kapitler?",
"MessageConfirmRemoveAuthor": "Er du sikker på, at du vil fjerne forfatteren \"{0}\"?",
"MessageConfirmRemoveCollection": "Er du sikker på, at du vil fjerne samlingen \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Er du sikker på, at du vil omdøbe tag \"{0}\" til \"{1}\" for alle elementer?",
"MessageConfirmRenameTagMergeNote": "Bemærk: Dette tag findes allerede, så de vil blive fusioneret.",
"MessageConfirmRenameTagWarning": "Advarsel! Et lignende tag med en anden skrivemåde eksisterer allerede \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Er du sikker på, at du vil sende {0} e-bog \"{1}\" til enhed \"{2}\"?",
"MessageDownloadingEpisode": "Downloader episode",
"MessageDragFilesIntoTrackOrder": "Træk filer ind i korrekt spororden",
@ -683,10 +692,10 @@
"MessageNoSeries": "Ingen serier",
"MessageNoTags": "Ingen tags",
"MessageNoTasksRunning": "Ingen opgaver kører",
"MessageNotYetImplemented": "Endnu ikke implementeret",
"MessageNoUpdateNecessary": "Ingen opdatering nødvendig",
"MessageNoUpdatesWereNecessary": "Ingen opdateringer var nødvendige",
"MessageNoUserPlaylists": "Du har ingen afspilningslister",
"MessageNotYetImplemented": "Endnu ikke implementeret",
"MessageOr": "eller",
"MessagePauseChapter": "Pause kapitelafspilning",
"MessagePlayChapter": "Lyt til begyndelsen af kapitlet",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Afspilningsliste opdateret",
"ToastPodcastCreateFailed": "Mislykkedes oprettelse af podcast",
"ToastPodcastCreateSuccess": "Podcast oprettet med succes",
"ToastRemoveItemFromCollectionFailed": "Mislykkedes fjernelse af element fra samling",
"ToastRemoveItemFromCollectionSuccess": "Element fjernet fra samling",
"ToastRSSFeedCloseFailed": "Mislykkedes lukning af RSS-feed",
"ToastRSSFeedCloseSuccess": "RSS-feed lukket",
"ToastRemoveItemFromCollectionFailed": "Mislykkedes fjernelse af element fra samling",
"ToastRemoveItemFromCollectionSuccess": "Element fjernet fra samling",
"ToastSendEbookToDeviceFailed": "Mislykkedes afsendelse af e-bog til enhed",
"ToastSendEbookToDeviceSuccess": "E-bog afsendt til enhed \"{0}\"",
"ToastSeriesUpdateFailed": "Mislykkedes opdatering af serie",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Mislykkedes sletning af bruger",
"ToastUserDeleteSuccess": "Bruger slettet"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Übernehmen",
"ButtonApplyChapters": "Kapitel anwenden",
"ButtonAuthors": "Autoren",
"ButtonBack": "Zurück",
"ButtonBrowseForFolder": "Ordnersuche",
"ButtonCancel": "Abbrechen",
"ButtonCancelEncode": "Codierung abbrechen",
@ -34,7 +35,7 @@
"ButtonIssues": "Probleme",
"ButtonJumpBackward": "Zurück springen",
"ButtonJumpForward": "Vorwärts springen",
"ButtonLatest": "Neuste",
"ButtonLatest": "Neueste",
"ButtonLibrary": "Bibliothek",
"ButtonLogout": "Abmelden",
"ButtonLookup": "Online-Suche",
@ -56,21 +57,20 @@
"ButtonPreviousChapter": "Vorheriges Kapitel",
"ButtonPurgeAllCache": "Cache leeren",
"ButtonPurgeItemsCache": "Lösche Medien-Cache",
"ButtonPurgeMediaProgress": "Lösche Hörfortschritte",
"ButtonQueueAddItem": "Zur Warteschlange hinzufügen",
"ButtonQueueRemoveItem": "Aus der Warteschlange entfernen",
"ButtonQuickMatch": "Schnellabgleich",
"ButtonReScan": "Neu scannen",
"ButtonRead": "Lesen",
"ButtonReadLess": "Weniger anzeigen",
"ButtonReadMore": "Mehr anzeigen",
"ButtonRefresh": "Neu Laden",
"ButtonRemove": "Löschen",
"ButtonRemove": "Entfernen",
"ButtonRemoveAll": "Alles löschen",
"ButtonRemoveAllLibraryItems": "Lösche alle Bibliothekseinträge",
"ButtonRemoveFromContinueListening": "Lösche den Eintrag aus der Fortsetzungsliste",
"ButtonRemoveFromContinueReading": "Lösche die Serie aus der Lesefortsetzungsliste",
"ButtonRemoveSeriesFromContinueSeries": "Lösche die Serie aus der Serienfortsetzungsliste",
"ButtonReScan": "Neu scannen",
"ButtonReset": "Zurücksetzen",
"ButtonResetToDefault": "Zurücksetzen auf Standard",
"ButtonRestore": "Wiederherstellen",
@ -104,17 +104,18 @@
"HeaderAccount": "Konto",
"HeaderAdvanced": "Erweitert",
"HeaderAppriseNotificationSettings": "Apprise Benachrichtigungseinstellungen",
"HeaderAudiobookTools": "Hörbuch-Dateiverwaltungstools",
"HeaderAudioTracks": "Audiodateien",
"HeaderAudiobookTools": "Hörbuch-Dateiverwaltungstools",
"HeaderAuthentication": "Authentifizierung",
"HeaderBackups": "Sicherungen",
"HeaderChangePassword": "Passwort ändern",
"HeaderChapters": "Kapitel",
"HeaderChooseAFolder": "Wähle einen Ordner",
"HeaderCollection": "Sammlungen",
"HeaderCollection": "Sammlung",
"HeaderCollectionItems": "Sammlungseinträge",
"HeaderCover": "Titelbild",
"HeaderCurrentDownloads": "Aktuelle Downloads",
"HeaderCustomMessageOnLogin": "Benutzerdefinierte Nachricht für den Login",
"HeaderCustomMetadataProviders": "Benutzerdefinierte Metadata Anbieter",
"HeaderDetails": "Details",
"HeaderDownloadQueue": "Download Warteschlange",
@ -141,7 +142,7 @@
"HeaderManageGenres": "Kategorien verwalten",
"HeaderManageTags": "Tags verwalten",
"HeaderMapDetails": "Stapelverarbeitung",
"HeaderMatch": "Metadaten",
"HeaderMatch": "Treffer",
"HeaderMetadataOrderOfPrecedence": "Metadaten Rangfolge",
"HeaderMetadataToEmbed": "Einzubettende Metadaten",
"HeaderNewAccount": "Neues Konto",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Einträge in der Wiedergabeliste",
"HeaderPodcastsToAdd": "Podcasts zum Hinzufügen",
"HeaderPreviewCover": "Vorschau Titelbild",
"HeaderRemoveEpisode": "Episode löschen",
"HeaderRemoveEpisodes": "Lösche {0} Episoden",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS-Feed ist geöffnet",
"HeaderRSSFeeds": "RSS-Feeds",
"HeaderRemoveEpisode": "Episode löschen",
"HeaderRemoveEpisodes": "Lösche {0} Episoden",
"HeaderSavedMediaProgress": "Gespeicherte Hörfortschritte",
"HeaderSchedule": "Zeitplan",
"HeaderScheduleLibraryScans": "Automatische Bibliotheksscans",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gast",
"LabelAccountTypeUser": "Benutzer",
"LabelActivity": "Aktivitäten",
"LabelAdded": "Hinzugefügt",
"LabelAddedAt": "Hinzugefügt am",
"LabelAddToCollection": "Zur Sammlung hinzufügen",
"LabelAddToCollectionBatch": "Füge {0} Hörbüch(er)/Podcast(s) der Sammlung hinzu",
"LabelAddToPlaylist": "Zur Wiedergabeliste hinzufügen",
"LabelAddToPlaylistBatch": "Füge {0} Hörbüch(er)/Podcast(s) der Wiedergabeliste hinzu",
"LabelAdded": "Hinzugefügt",
"LabelAddedAt": "Hinzugefügt am",
"LabelAdminUsersOnly": "Nur Admin Benutzer",
"LabelAll": "Alle",
"LabelAllUsers": "Alle Benutzer",
@ -235,9 +236,9 @@
"LabelByAuthor": "von {0}",
"LabelChangePassword": "Passwort ändern",
"LabelChannels": "Kanäle",
"LabelChapterTitle": "Kapitelüberschrift",
"LabelChapters": "Kapitel",
"LabelChaptersFound": "Gefundene Kapitel",
"LabelChapterTitle": "Kapitelüberschrift",
"LabelClickForMoreInfo": "Klicken für mehr Informationen",
"LabelClosePlayer": "Player schließen",
"LabelCodec": "Codec",
@ -255,7 +256,7 @@
"LabelCronExpression": "Cron-Ausdruck",
"LabelCurrent": "Aktuell",
"LabelCurrently": "Aktuell:",
"LabelCustomCronExpression": "Benutzerdefinierter Cron-Ausdruck",
"LabelCustomCronExpression": "Benutzerdefinierter Cron-Ausdruck:",
"LabelDatetime": "Datum & Uhrzeit",
"LabelDeleteFromFileSystemCheckbox": "Löschen von der Festplatte + Datenbank (deaktivieren um nur aus der Datenbank zu löschen)",
"LabelDescription": "Beschreibung",
@ -279,8 +280,8 @@
"LabelEdit": "Bearbeiten",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "Von Adresse",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Nicht autorisierte Zertifikate ablehnen",
"LabelEmailSettingsRejectUnauthorizedHelp": "Durch das Deaktivieren der SSL-Zertifikatsüberprüfung kann deine Verbindung Sicherheitsrisiken wie Man-in-the-Middle-Angriffen ausgesetzt sein. Deaktiviere diese Option nur, wenn due die Auswirkungen verstehst und dem Mailserver vertraust, mit dem eine Verbindung hergestellt wird.",
"LabelEmailSettingsSecure": "Sicher",
"LabelEmailSettingsSecureHelp": "Wenn \"an\", verwendet die Verbindung TLS, wenn du eine Verbindung zum Server herstellst. Bei \"aus\" wird TLS verwendet, wenn der Server die STARTTLS-Erweiterung unterstützt. In den meisten Fällen solltest du diesen Wert auf \"an\" schalten, wenn du eine Verbindung zu Port 465 herstellst. Für Port 587 oder 25 behalte den Wert \"aus\" bei. (von nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Adresse",
@ -306,6 +307,7 @@
"LabelFolder": "Ordner",
"LabelFolders": "Verzeichnisse",
"LabelFontBold": "Fett",
"LabelFontBoldness": "Schriftstärke",
"LabelFontFamily": "Schriftfamilie",
"LabelFontItalic": "Kursiv",
"LabelFontScale": "Schriftgröße",
@ -321,9 +323,9 @@
"LabelHour": "Stunde",
"LabelIcon": "Symbol",
"LabelImageURLFromTheWeb": "Bild-URL vom Internet",
"LabelInProgress": "In Bearbeitung",
"LabelIncludeInTracklist": "In die Titelliste aufnehmen",
"LabelIncomplete": "Unvollständig",
"LabelInProgress": "In Bearbeitung",
"LabelInterval": "Intervall",
"LabelIntervalCustomDailyWeekly": "Benutzerdefiniert Täglich/Wöchentlich",
"LabelIntervalEvery12Hours": "Alle 12 Stunden",
@ -337,6 +339,7 @@
"LabelItem": "Medium",
"LabelLanguage": "Sprache",
"LabelLanguageDefaultServer": "Standard-Server-Sprache",
"LabelLanguages": "Sprachen",
"LabelLastBookAdded": "Zuletzt hinzugefügtes Buch",
"LabelLastBookUpdated": "Zuletzt aktualisiertes Buch",
"LabelLastSeen": "Zuletzt gesehen",
@ -348,6 +351,7 @@
"LabelLess": "Weniger",
"LabelLibrariesAccessibleToUser": "Für Benutzer zugängliche Bibliotheken",
"LabelLibrary": "Bibliothek",
"LabelLibraryFilterSublistEmpty": "Nr. {0}",
"LabelLibraryItem": "Bibliothekseintrag",
"LabelLibraryName": "Bibliotheksname",
"LabelLimit": "Begrenzung",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Wird zum Verbinden vorhandener Benutzer verwendet. Sobald die Verbindung hergestellt ist, wird den Benutzern eine eindeutige ID vom SSO-Anbieter zugeordnet",
"LabelMediaPlayer": "Mediaplayer",
"LabelMediaType": "Medientyp",
"LabelMetadataOrderOfPrecedenceDescription": "Höher priorisierte Quellen für Metadaten überschreiben Metadaten aus Quellen die niedriger priorisiert sind.",
"LabelMetadataProvider": "Metadatenanbieter",
"LabelMetaTag": "Meta Schlagwort",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Höher priorisierte Quellen für Metadaten überschreiben Metadaten aus Quellen mit niedrigerer Priorität",
"LabelMetadataProvider": "Metadatenanbieter",
"LabelMinute": "Minute",
"LabelMissing": "Fehlend",
"LabelMissingEbook": "E-Book fehlt",
@ -378,24 +382,25 @@
"LabelNarrator": "Erzähler",
"LabelNarrators": "Erzähler",
"LabelNew": "Neu",
"LabelNewPassword": "Neues Passwort",
"LabelNewestAuthors": "Neueste Autoren",
"LabelNewestEpisodes": "Neueste Episoden",
"LabelNewPassword": "Neues Passwort",
"LabelNextBackupDate": "Nächstes Sicherungsdatum",
"LabelNextScheduledRun": "Nächster planmäßiger Durchlauf",
"LabelNoCustomMetadataProviders": "Keine benutzerdefinierten Metadata Anbieter",
"LabelNoEpisodesSelected": "Keine Episoden ausgewählt",
"LabelNotes": "Notizen",
"LabelNotFinished": "Nicht beendet",
"LabelNotStarted": "Nicht begonnen",
"LabelNotes": "Notizen",
"LabelNotificationAppriseURL": "Apprise URL(s)",
"LabelNotificationAvailableVariables": "Verfügbare Variablen",
"LabelNotificationBodyTemplate": "Textvorlage",
"LabelNotificationEvent": "Benachrichtigungs Event",
"LabelNotificationTitleTemplate": "Titelvorlage",
"LabelNotificationsMaxFailedAttempts": "Maximale Fehlversuche",
"LabelNotificationsMaxFailedAttemptsHelp": "Benachrichtigungen werden deaktiviert, wenn sie mehrmals nicht gesendet werden können.",
"LabelNotificationsMaxFailedAttemptsHelp": "Benachrichtigungen werden deaktiviert, wenn sie mehrmals nicht gesendet werden können",
"LabelNotificationsMaxQueueSize": "Maximale Größe der Warteschlange für die Benachrichtigungsereignisse",
"LabelNotificationsMaxQueueSizeHelp": "Es wird nur 1 Ereignis pro Sekunde ausgelöst. Ereignisse werden ignoriert, wenn die Warteschlange die maximale Größe erreicht hat. Dies verhindert Benachrichtigungsspamming.",
"LabelNotificationTitleTemplate": "Titelvorlage",
"LabelNotStarted": "Nicht begonnen",
"LabelNumberOfBooks": "Anzahl der Hörbücher",
"LabelNumberOfEpisodes": "Anzahl der Episoden",
"LabelOpenIDAdvancedPermsClaimDescription": "Name des OpenID-Claims, der erweiterte Berechtigungen für Benutzeraktionen innerhalb der Anwendung enthält, die auf Nicht-Admin-Rollen angewendet werden (<b>wenn konfiguriert</b>). Wenn der Claim in der Antwort fehlt, wird der Zugang zu ABS verweigert. Fehlt eine einzelne Option, wird sie als <code>false</code> behandelt. Stelle sicher, dass der Claim des Identitätsanbieters der erwarteten Struktur entspricht:",
@ -408,18 +413,19 @@
"LabelPermissionsAccessAllLibraries": "Zugriff auf alle Bibliotheken",
"LabelPermissionsAccessAllTags": "Zugriff auf alle Schlagwörter",
"LabelPermissionsAccessExplicitContent": "Zugriff auf explizite (alterbeschränkte) Inhalte",
"LabelPermissionsDelete": "Löschen",
"LabelPermissionsDelete": "Darf Löschen",
"LabelPermissionsDownload": "Herunterladen",
"LabelPermissionsUpdate": "Aktualisieren",
"LabelPermissionsUpload": "Hochladen",
"LabelPersonalYearReview": "Dein Jahr in Übersicht ({0})",
"LabelPhotoPathURL": "Foto Pfad/URL",
"LabelPlaylists": "Wiedergabelisten",
"LabelPlayMethod": "Abspielmethode",
"LabelPlayerChapterNumberMarker": "{0} von {1}",
"LabelPlaylists": "Wiedergabelisten",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Podcast-Suchregion",
"LabelPodcastType": "Podcast Typ",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Zu ignorierende(s) Vorwort(e) (Groß- und Kleinschreibung wird nicht berücksichtigt)",
"LabelPreventIndexing": "Verhindere, dass dein Feed von iTunes- und Google-Podcast-Verzeichnissen indiziert wird",
@ -427,25 +433,26 @@
"LabelProgress": "Fortschritt",
"LabelProvider": "Anbieter",
"LabelPubDate": "Veröffentlichungsdatum",
"LabelPublisher": "Herausgeber",
"LabelPublishYear": "Jahr",
"LabelRead": "Lesen",
"LabelReadAgain": "Noch einmal Lesen",
"LabelReadEbookWithoutProgress": "E-Book lesen und Fortschritt verwerfen",
"LabelRecentlyAdded": "Kürzlich hinzugefügt",
"LabelRecentSeries": "Aktuelle Serien",
"LabelRecommended": "Empfohlen",
"LabelRedo": "Wiederholen",
"LabelRegion": "Region",
"LabelReleaseDate": "Veröffentlichungsdatum",
"LabelRemoveCover": "Lösche Titelbild",
"LabelRowsPerPage": "Zeilen pro Seite",
"LabelPublisher": "Herausgeber",
"LabelPublishers": "Herausgeber",
"LabelRSSFeedCustomOwnerEmail": "Benutzerdefinierte Eigentümer-E-Mail",
"LabelRSSFeedCustomOwnerName": "Benutzerdefinierter Name des Eigentümers",
"LabelRSSFeedOpen": "RSS Feed Offen",
"LabelRSSFeedPreventIndexing": "Indizierung verhindern",
"LabelRSSFeedSlug": "RSS Feed Schlagwort",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Lesen",
"LabelReadAgain": "Noch einmal Lesen",
"LabelReadEbookWithoutProgress": "E-Book lesen und Fortschritt verwerfen",
"LabelRecentSeries": "Aktuelle Serien",
"LabelRecentlyAdded": "Kürzlich hinzugefügt",
"LabelRecommended": "Empfohlen",
"LabelRedo": "Wiederholen",
"LabelRegion": "Region",
"LabelReleaseDate": "Veröffentlichungsdatum",
"LabelRemoveCover": "Lösche Titelbild",
"LabelRowsPerPage": "Zeilen pro Seite",
"LabelSearchTerm": "Begriff suchen",
"LabelSearchTitle": "Titel suchen",
"LabelSearchTitleOrASIN": "Titel oder ASIN suchen",
@ -483,8 +490,8 @@
"LabelSettingsHideSingleBookSeriesHelp": "Serien, die nur ein einzelnes Buch enthalten, werden auf der Startseite und in der Serienansicht ausgeblendet.",
"LabelSettingsHomePageBookshelfView": "Startseite verwendet die Bücherregalansicht",
"LabelSettingsLibraryBookshelfView": "Bibliothek verwendet die Bücherregalansicht",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Skip earlier books in Continue Series",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "The Continue Series home page shelf shows the first book not started in series that have at least one book finished and no books in progress. Enabling this setting will continue series from the furthest completed book instead of the first book not started.",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Überspringe vorherige Bücher in fortführender Serie",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Die Startseite von \"Fortführende Serien\" zeigt das erste noch nicht begonnene Buch in Serien an, die mindestens ein Buch abgeschlossen und keine Bücher begonnen haben. Wenn diese Einstellung aktiviert wird, werden Serien ab dem letzten abgeschlossenen Buch fortgesetzt und nicht ab dem ersten nicht begonnenen Buch.",
"LabelSettingsParseSubtitles": "Analysiere Untertitel",
"LabelSettingsParseSubtitlesHelp": "Extrahiere den Untertitel von Medium-Ordnernamen.<br>Untertitel müssen vom eigentlichem Titel durch ein \" - \" getrennt sein. <br>Beispiel: \"Titel - Untertitel\"",
"LabelSettingsPreferMatchedMetadata": "Bevorzuge online abgestimmte Metadaten",
@ -492,11 +499,11 @@
"LabelSettingsSkipMatchingBooksWithASIN": "Überspringe beim Online-Abgleich alle Bücher die bereits eine ASIN haben",
"LabelSettingsSkipMatchingBooksWithISBN": "Überspringe beim Online-Abgleich alle Bücher die bereits eine ISBN haben",
"LabelSettingsSortingIgnorePrefixes": "Vorwort/Artikel beim Sortieren ignorieren",
"LabelSettingsSortingIgnorePrefixesHelp": "Beispiel: für den Artikel \"der\" würde der Mediumtitel \"Der Buchtitel\" als \"Buchtitel, Der\" sortiert werden.",
"LabelSettingsSortingIgnorePrefixesHelp": "Beispiel: für den Artikel \"der\" würde der Mediumtitel \"Der Buchtitel\" als \"Buchtitel, Der\" sortiert werden",
"LabelSettingsSquareBookCovers": "Benutze quadratische Titelbilder",
"LabelSettingsSquareBookCoversHelp": "Bevorzuge quadratische Titelbilder gegenüber den Standardtielbildern im Verhältnis 1,6:1",
"LabelSettingsStoreCoversWithItem": "Titelbilder im Medienordner speichern",
"LabelSettingsStoreCoversWithItemHelp": "Standardmäßig werden die Titelbilder in /metadata/items gespeichert. Wenn diese Option aktiviert ist, werden die Titelbilder als jpg Datei in dem gleichen Ordner gespeichert in welchem sich auch das Medium befindet. Es wird immer nur eine Datei mit dem Namen \"cover.jpg\" gespeichert.",
"LabelSettingsStoreCoversWithItemHelp": "Standardmäßig werden die Titelbilder in /metadata/items gespeichert. Wenn diese Option aktiviert ist, werden die Titelbilder als jpg Datei in dem gleichen Ordner gespeichert in welchem sich auch das Medium befindet. Es wird immer nur eine Datei mit dem Namen \"cover.jpg\" gespeichert",
"LabelSettingsStoreMetadataWithItem": "Metadaten als OPF-Datei im Medienordner speichern",
"LabelSettingsStoreMetadataWithItemHelp": "Standardmäßig werden die Metadaten in /metadata/items gespeichert. Wenn diese Option aktiviert ist, werden die Metadaten als OPF-Datei (Textdatei) in dem gleichen Ordner gespeichert in welchem sich auch das Medium befindet",
"LabelSettingsTimeFormat": "Zeitformat",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Schlummerfunktion",
"LabelSlug": "URL Teil",
"LabelStart": "Start",
"LabelStartTime": "Startzeit",
"LabelStarted": "Gestartet",
"LabelStartedAt": "Gestartet am",
"LabelStartTime": "Startzeit",
"LabelStatsAudioTracks": "Audiodateien",
"LabelStatsAuthors": "Autoren",
"LabelStatsBestDay": "Bester Tag",
@ -554,7 +561,7 @@
"LabelTotalTimeListened": "Gehörte Gesamtzeit",
"LabelTrackFromFilename": "Titel aus Dateiname",
"LabelTrackFromMetadata": "Titel aus Metadaten",
"LabelTracks": "Dateien",
"LabelTracks": "Titel",
"LabelTracksMultiTrack": "Mehrfachdatei",
"LabelTracksNone": "Keine Dateien",
"LabelTracksSingleTrack": "Einzeldatei",
@ -564,9 +571,9 @@
"LabelUnknown": "Unbekannt",
"LabelUpdateCover": "Titelbild aktualisieren",
"LabelUpdateCoverHelp": "Erlaube das Überschreiben bestehender Titelbilder für die ausgewählten Hörbücher, wenn eine Übereinstimmung gefunden wird",
"LabelUpdatedAt": "Aktualisiert am",
"LabelUpdateDetails": "Details aktualisieren",
"LabelUpdateDetailsHelp": "Erlaube das Überschreiben bestehender Details für die ausgewählten Hörbücher, wenn eine Übereinstimmung gefunden wird",
"LabelUpdatedAt": "Aktualisiert am",
"LabelUploaderDragAndDrop": "Ziehen und Ablegen von Dateien oder Ordnern",
"LabelUploaderDropFiles": "Dateien löschen",
"LabelUploaderItemFetchMetadataHelp": "Automatisches Aktualisieren von Titel, Autor und Serie",
@ -592,8 +599,9 @@
"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.",
"MessageBatchQuickMatchDescription": "Der Schnellabgleich versucht, fehlende Titelbilder und Metadaten für die ausgewählten Artikel hinzuzufügen. Aktiviere die nachstehenden Optionen, damit der Schnellabgleich vorhandene Titelbilder und/oder Metadaten überschreiben kann.",
"MessageBookshelfNoCollections": "Es wurden noch keine Sammlungen erstellt",
"MessageBookshelfNoResultsForFilter": "Keine Ergebnisse für Filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Keine RSS-Feeds geöffnet",
"MessageBookshelfNoResultsForFilter": "Keine Ergebnisse für Filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Keine Ergebnisse für die Abfrage",
"MessageBookshelfNoSeries": "Keine Serien vorhanden",
"MessageChapterEndIsAfter": "Ungültige Kapitelendzeit: Kapitelende > Mediumende (Kapitelende liegt nach dem Ende des Mediums)",
"MessageChapterErrorFirstNotZero": "Ungültige Kapitelstartzeit: Das erste Kapitel muss bei 0 beginnen",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Alle Medien dieser Reihe werden als abgeschlossen markiert! Bist du dir sicher?",
"MessageConfirmMarkSeriesNotFinished": "Alle Medien dieser Reihe werden als nicht abgeschlossen markiert! Bist du dir sicher?",
"MessageConfirmPurgeCache": "Cache leeren wird das ganze Verzeichnis <code>/metadata/cache</code> löschen. <br /><br />Bist du dir sicher, dass das Cache Verzeichnis gelöscht werden soll?",
"MessageConfirmPurgeItemsCache": "Durch Elementcache leeren wird das gesamte Verzeichnis unter <code>/metadata/cache/items</code> gelöscht.<br />Bist du dir sicher?",
"MessageConfirmQuickEmbed": "Warnung! Audiodateien werden bei der Schnelleinbettung nicht gesichert! Achte darauf, dass du eine Sicherungskopie der Audiodateien besitzt. <br><br>Möchtest du fortfahren?",
"MessageConfirmReScanLibraryItems": "{0} Elemente werden erneut gescannt! Bist du dir sicher?",
"MessageConfirmRemoveAllChapters": "Alle Kapitel werden entfernt! Bist du dir sicher?",
"MessageConfirmRemoveAuthor": "Autor \"{0}\" wird enfernt! Bist du dir sicher?",
"MessageConfirmRemoveCollection": "Sammlung \"{0}\" wird gelöscht! Bist du dir sicher?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Tag \"{0}\" in \"{1}\" für alle Hörbücher/Podcasts werden umbenannt! Bist du dir sicher?",
"MessageConfirmRenameTagMergeNote": "Hinweis: Tag existiert bereits -> Tags werden zusammengelegt.",
"MessageConfirmRenameTagWarning": "Warnung! Ein ähnlicher Tag mit einem anderen Wortlaut existiert bereits: \"{0}\".",
"MessageConfirmReScanLibraryItems": "{0} Elemente werden erneut gescannt! Bist du dir sicher?",
"MessageConfirmSendEbookToDevice": "{0} E-Book \"{1}\" wird auf das Gerät \"{2}\" gesendet! Bist du dir sicher?",
"MessageDownloadingEpisode": "Episode wird heruntergeladen",
"MessageDragFilesIntoTrackOrder": "Verschiebe die Dateien in die richtige Reihenfolge",
@ -683,10 +692,10 @@
"MessageNoSeries": "Keine Serien",
"MessageNoTags": "Keine Tags",
"MessageNoTasksRunning": "Keine laufenden Aufgaben",
"MessageNotYetImplemented": "Noch nicht implementiert",
"MessageNoUpdateNecessary": "Keine Aktualisierung erforderlich",
"MessageNoUpdatesWereNecessary": "Keine Aktualisierungen waren notwendig",
"MessageNoUserPlaylists": "Keine Wiedergabelisten vorhanden",
"MessageNotYetImplemented": "Noch nicht implementiert",
"MessageOr": "Oder",
"MessagePauseChapter": "Kapitelwiedergabe pausieren",
"MessagePlayChapter": "Kapitelanfang anhören",
@ -717,8 +726,8 @@
"MessageYourAudiobookDurationIsShorter": "Die Dauer deines Mediums ist kürzer als die gefundene Dauer",
"NoteChangeRootPassword": "Der Root-Benutzer (Hauptbenutzer) ist der einzige Benutzer, der ein leeres Passwort haben kann",
"NoteChapterEditorTimes": "Hinweis: Die Anfangszeit des ersten Kapitels muss bei 0:00 beginnen und die Anfangszeit des letzten Kapitels darf die Dauer des Mediums nicht überschreiten.",
"NoteFolderPicker": "Hinweis: Bereits zugeordnete Ordner werden nicht angezeigt.",
"NoteRSSFeedPodcastAppsHttps": "Warnung: Die meisten Podcast-Apps verlangen, dass die URL des RSS-Feeds HTTPS verwendet.",
"NoteFolderPicker": "Hinweis: Bereits zugeordnete Ordner werden nicht angezeigt",
"NoteRSSFeedPodcastAppsHttps": "Warnung: Die meisten Podcast-Apps verlangen, dass die URL des RSS-Feeds HTTPS verwendet",
"NoteRSSFeedPodcastAppsPubDate": "Warnung: 1 oder mehrere deiner Episoden haben kein Veröffentlichungsdatum. Einige Podcast-Apps verlangen dies.",
"NoteUploaderFoldersWithMediaFiles": "Ordner mit Mediendateien werden als separate Bibliothekselemente behandelt.",
"NoteUploaderOnlyAudioFiles": "Wenn du nur Audiodateien hochlädst, wird jede Audiodatei als ein separates Medium behandelt.",
@ -789,15 +798,15 @@
"ToastPlaylistUpdateSuccess": "Wiedergabeliste aktualisiert",
"ToastPodcastCreateFailed": "Podcast konnte nicht erstellt werden",
"ToastPodcastCreateSuccess": "Podcast erstellt",
"ToastRemoveItemFromCollectionFailed": "Löschen des Mediums aus der Sammlung fehlgeschlagen",
"ToastRemoveItemFromCollectionSuccess": "Medium aus der Sammlung gelöscht",
"ToastRSSFeedCloseFailed": "RSS-Feed konnte nicht geschlossen werden",
"ToastRSSFeedCloseSuccess": "RSS-Feed geschlossen",
"ToastRemoveItemFromCollectionFailed": "Löschen des Mediums aus der Sammlung fehlgeschlagen",
"ToastRemoveItemFromCollectionSuccess": "Medium aus der Sammlung gelöscht",
"ToastSendEbookToDeviceFailed": "E-Book konnte nicht auf Gerät übertragen werden",
"ToastSendEbookToDeviceSuccess": "E-Book an Gerät \"{0}\" gesendet",
"ToastSeriesUpdateFailed": "Aktualisierung der Serien fehlgeschlagen",
"ToastSeriesUpdateSuccess": "Serien aktualisiert",
"ToastServerSettingsUpdateFailed": "Die Server-Einstellungen wurden nicht gespeichert.",
"ToastServerSettingsUpdateFailed": "Die Server-Einstellungen wurden nicht gespeichert",
"ToastServerSettingsUpdateSuccess": "Die Server-Einstellungen wurden geupdated",
"ToastSessionDeleteFailed": "Sitzung konnte nicht gelöscht werden",
"ToastSessionDeleteSuccess": "Sitzung gelöscht",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Die Sortier-Prefixe wirden geupdated ({0} Einträge)",
"ToastUserDeleteFailed": "Benutzer konnte nicht gelöscht werden",
"ToastUserDeleteSuccess": "Benutzer gelöscht"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Apply",
"ButtonApplyChapters": "Apply Chapters",
"ButtonAuthors": "Authors",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Browse for Folder",
"ButtonCancel": "Cancel",
"ButtonCancelEncode": "Cancel Encode",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Purge All Cache",
"ButtonPurgeItemsCache": "Purge Items Cache",
"ButtonPurgeMediaProgress": "Purge Media Progress",
"ButtonQueueAddItem": "Add to queue",
"ButtonQueueRemoveItem": "Remove from queue",
"ButtonQuickMatch": "Quick Match",
"ButtonReScan": "Re-Scan",
"ButtonRead": "Read",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Remove from Continue Listening",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveSeriesFromContinueSeries": "Remove Series from Continue Series",
"ButtonReScan": "Re-Scan",
"ButtonReset": "Reset",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "Restore",
@ -104,8 +104,8 @@
"HeaderAccount": "Account",
"HeaderAdvanced": "Advanced",
"HeaderAppriseNotificationSettings": "Apprise Notification Settings",
"HeaderAudiobookTools": "Audiobook File Management Tools",
"HeaderAudioTracks": "Audio Tracks",
"HeaderAudiobookTools": "Audiobook File Management Tools",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Backups",
"HeaderChangePassword": "Change Password",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Collection Items",
"HeaderCover": "Cover",
"HeaderCurrentDownloads": "Current Downloads",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Details",
"HeaderDownloadQueue": "Download Queue",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Playlist Items",
"HeaderPodcastsToAdd": "Podcasts to Add",
"HeaderPreviewCover": "Preview Cover",
"HeaderRemoveEpisode": "Remove Episode",
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Remove Episode",
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderSavedMediaProgress": "Saved Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Schedule Automatic Library Scans",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Guest",
"LabelAccountTypeUser": "User",
"LabelActivity": "Activity",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAddToCollection": "Add to Collection",
"LabelAddToCollectionBatch": "Add {0} Books to Collection",
"LabelAddToPlaylist": "Add to Playlist",
"LabelAddToPlaylistBatch": "Add {0} Items to Playlist",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "All",
"LabelAllUsers": "All Users",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Change Password",
"LabelChannels": "Channels",
"LabelChapterTitle": "Chapter Title",
"LabelChapters": "Chapters",
"LabelChaptersFound": "chapters found",
"LabelChapterTitle": "Chapter Title",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Folder",
"LabelFolders": "Folders",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Font family",
"LabelFontItalic": "Italic",
"LabelFontScale": "Font scale",
@ -321,9 +323,9 @@
"LabelHour": "Hour",
"LabelIcon": "Icon",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "In Progress",
"LabelIncludeInTracklist": "Include in Tracklist",
"LabelIncomplete": "Incomplete",
"LabelInProgress": "In Progress",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Custom daily/weekly",
"LabelIntervalEvery12Hours": "Every 12 hours",
@ -337,6 +339,7 @@
"LabelItem": "Item",
"LabelLanguage": "Language",
"LabelLanguageDefaultServer": "Default Server Language",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastSeen": "Last Seen",
@ -348,6 +351,7 @@
"LabelLess": "Less",
"LabelLibrariesAccessibleToUser": "Libraries Accessible to User",
"LabelLibrary": "Library",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLimit": "Limit",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Media Player",
"LabelMediaType": "Media Type",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Provider",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Provider",
"LabelMinute": "Minute",
"LabelMissing": "Missing",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrator",
"LabelNarrators": "Narrators",
"LabelNew": "New",
"LabelNewPassword": "New Password",
"LabelNewestAuthors": "Newest Authors",
"LabelNewestEpisodes": "Newest Episodes",
"LabelNewPassword": "New Password",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notes",
"LabelNotFinished": "Not Finished",
"LabelNotStarted": "Not Started",
"LabelNotes": "Notes",
"LabelNotificationAppriseURL": "Apprise URL(s)",
"LabelNotificationAvailableVariables": "Available variables",
"LabelNotificationBodyTemplate": "Body Template",
"LabelNotificationEvent": "Notification Event",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotificationsMaxFailedAttempts": "Max failed attempts",
"LabelNotificationsMaxFailedAttemptsHelp": "Notifications are disabled once they fail to send this many times",
"LabelNotificationsMaxQueueSize": "Max queue size for notification events",
"LabelNotificationsMaxQueueSizeHelp": "Events are limited to firing 1 per second. Events will be ignored if the queue is at max size. This prevents notification spamming.",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotStarted": "Not Started",
"LabelNumberOfBooks": "Number of Books",
"LabelNumberOfEpisodes": "# of Episodes",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Can Upload",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Photo Path/URL",
"LabelPlaylists": "Playlists",
"LabelPlayMethod": "Play Method",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Playlists",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Podcast search region",
"LabelPodcastType": "Podcast Type",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
"LabelPreventIndexing": "Prevent your feed from being indexed by iTunes and Google podcast directories",
@ -427,25 +433,26 @@
"LabelProgress": "Progress",
"LabelProvider": "Provider",
"LabelPubDate": "Pub Date",
"LabelPublisher": "Publisher",
"LabelPublishYear": "Publish Year",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentlyAdded": "Recently Added",
"LabelRecentSeries": "Recent Series",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Release Date",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Publisher",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Custom owner Email",
"LabelRSSFeedCustomOwnerName": "Custom owner Name",
"LabelRSSFeedOpen": "RSS Feed Open",
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentSeries": "Recent Series",
"LabelRecentlyAdded": "Recently Added",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Release Date",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Search Term",
"LabelSearchTitle": "Search Title",
"LabelSearchTitleOrASIN": "Search Title or ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Start Time",
"LabelStarted": "Started",
"LabelStartedAt": "Started At",
"LabelStartTime": "Start Time",
"LabelStatsAudioTracks": "Audio Tracks",
"LabelStatsAuthors": "Authors",
"LabelStatsBestDay": "Best Day",
@ -564,9 +571,9 @@
"LabelUnknown": "Unknown",
"LabelUpdateCover": "Update Cover",
"LabelUpdateCoverHelp": "Allow overwriting of existing covers for the selected books when a match is located",
"LabelUpdatedAt": "Updated At",
"LabelUpdateDetails": "Update Details",
"LabelUpdateDetailsHelp": "Allow overwriting of existing details for the selected books when a match is located",
"LabelUpdatedAt": "Updated At",
"LabelUploaderDragAndDrop": "Drag & drop files or folders",
"LabelUploaderDropFiles": "Drop files",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -590,10 +597,13 @@
"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>.",
"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",
"MessageBackupsLocationPathEmpty": "Backup location path cannot be empty",
"MessageBatchQuickMatchDescription": "Quick Match will attempt to add missing covers and metadata for the selected items. Enable the options below to allow Quick Match to overwrite existing covers and/or metadata.",
"MessageBookshelfNoCollections": "You haven't made any collections yet",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "No RSS feeds are open",
"MessageBookshelfNoResultsForFilter": "No results for filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "You have no series",
"MessageChapterEndIsAfter": "Chapter end is after the end of your audiobook",
"MessageChapterErrorFirstNotZero": "First chapter must start at 0",
@ -614,7 +624,9 @@
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{0}\"?",
@ -629,7 +641,6 @@
"MessageConfirmRenameTag": "Are you sure you want to rename tag \"{0}\" to \"{1}\" for all items?",
"MessageConfirmRenameTagMergeNote": "Note: This tag already exists so they will be merged.",
"MessageConfirmRenameTagWarning": "Warning! A similar tag with a different casing already exists \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageDownloadingEpisode": "Downloading episode",
"MessageDragFilesIntoTrackOrder": "Drag files into correct track order",
@ -683,10 +694,10 @@
"MessageNoSeries": "No Series",
"MessageNoTags": "No Tags",
"MessageNoTasksRunning": "No Tasks Running",
"MessageNotYetImplemented": "Not yet implemented",
"MessageNoUpdateNecessary": "No update necessary",
"MessageNoUpdatesWereNecessary": "No updates were necessary",
"MessageNoUserPlaylists": "You have no playlists",
"MessageNotYetImplemented": "Not yet implemented",
"MessageOr": "or",
"MessagePauseChapter": "Pause chapter playback",
"MessagePlayChapter": "Listen to beginning of chapter",
@ -789,10 +800,10 @@
"ToastPlaylistUpdateSuccess": "Playlist updated",
"ToastPodcastCreateFailed": "Failed to create podcast",
"ToastPodcastCreateSuccess": "Podcast created successfully",
"ToastRemoveItemFromCollectionFailed": "Failed to remove item from collection",
"ToastRemoveItemFromCollectionSuccess": "Item removed from collection",
"ToastRSSFeedCloseFailed": "Failed to close RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed closed",
"ToastRemoveItemFromCollectionFailed": "Failed to remove item from collection",
"ToastRemoveItemFromCollectionSuccess": "Item removed from collection",
"ToastSendEbookToDeviceFailed": "Failed to send ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSeriesUpdateFailed": "Series update failed",

View File

@ -9,6 +9,7 @@
"ButtonApply": "Aplicar",
"ButtonApplyChapters": "Aplicar Capítulos",
"ButtonAuthors": "Autores",
"ButtonBack": "Atrás",
"ButtonBrowseForFolder": "Buscar por Carpeta",
"ButtonCancel": "Cancelar",
"ButtonCancelEncode": "Cancelar Codificador",
@ -52,14 +53,14 @@
"ButtonPlay": "Reproducir",
"ButtonPlaying": "Reproduciendo",
"ButtonPlaylists": "Listas de Reproducción",
"ButtonPrevious": "Previous",
"ButtonPrevious": "Anterior",
"ButtonPreviousChapter": "Capítulo Anterior",
"ButtonPurgeAllCache": "Purgar Todo el Cache",
"ButtonPurgeItemsCache": "Purgar Elementos de Cache",
"ButtonPurgeMediaProgress": "Purgar Progreso de Multimedia",
"ButtonQueueAddItem": "Agregar a la Fila",
"ButtonQueueRemoveItem": "Remover de la Fila",
"ButtonQuickMatch": "Encontrar Rápido",
"ButtonReScan": "Re-Escanear",
"ButtonRead": "Leer",
"ButtonReadLess": "Lea menos",
"ButtonReadMore": "Lea mas",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Remover de Continuar Escuchando",
"ButtonRemoveFromContinueReading": "Remover de Continuar Leyendo",
"ButtonRemoveSeriesFromContinueSeries": "Remover Serie de Continuar Series",
"ButtonReScan": "Re-Escanear",
"ButtonReset": "Reiniciar",
"ButtonResetToDefault": "Restaurar valores por defecto",
"ButtonRestore": "Restaurar",
@ -93,7 +93,7 @@
"ButtonUpload": "Subir",
"ButtonUploadBackup": "Subir Respaldo",
"ButtonUploadCover": "Subir Portada",
"ButtonUploadOPMLFile": "Subir Archivo OPML ",
"ButtonUploadOPMLFile": "Cargar archivo OPML",
"ButtonUserDelete": "Eliminar Usuario {0}",
"ButtonUserEdit": "Editar Usuario {0}",
"ButtonViewAll": "Ver Todos",
@ -104,8 +104,8 @@
"HeaderAccount": "Cuenta",
"HeaderAdvanced": "Avanzado",
"HeaderAppriseNotificationSettings": "Ajustes de Notificaciones de Apprise",
"HeaderAudiobookTools": "Herramientas de Gestión de Archivos de Audiolibro",
"HeaderAudioTracks": "Pistas de Audio",
"HeaderAudiobookTools": "Herramientas de Gestión de Archivos de Audiolibro",
"HeaderAuthentication": "Autenticación",
"HeaderBackups": "Respaldos",
"HeaderChangePassword": "Cambiar Contraseña",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Elementos en la Colección",
"HeaderCover": "Portada",
"HeaderCurrentDownloads": "Descargando Actualmente",
"HeaderCustomMessageOnLogin": "Mensaje personalizado al iniciar sesión",
"HeaderCustomMetadataProviders": "Proveedores de metadatos personalizados",
"HeaderDetails": "Detalles",
"HeaderDownloadQueue": "Lista de Descarga",
@ -137,7 +138,7 @@
"HeaderListeningSessions": "Sesión",
"HeaderListeningStats": "Estadísticas de Tiempo Escuchado",
"HeaderLogin": "Iniciar Session",
"HeaderLogs": "Logs",
"HeaderLogs": "Registros",
"HeaderManageGenres": "Administrar Géneros",
"HeaderManageTags": "Administrar Etiquetas",
"HeaderMapDetails": "Asignar Detalles",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Elementos de Lista de Reproducción",
"HeaderPodcastsToAdd": "Podcasts para agregar",
"HeaderPreviewCover": "Vista Previa de Portada",
"HeaderRemoveEpisode": "Remover Episodio",
"HeaderRemoveEpisodes": "Remover {0} Episodios",
"HeaderRSSFeedGeneral": "Detalles RSS",
"HeaderRSSFeedIsOpen": "Fuente RSS esta abierta",
"HeaderRSSFeeds": "Fuentes RSS",
"HeaderRemoveEpisode": "Remover Episodio",
"HeaderRemoveEpisodes": "Remover {0} Episodios",
"HeaderSavedMediaProgress": "Guardar Progreso de Multimedia",
"HeaderSchedule": "Horario",
"HeaderScheduleLibraryScans": "Programar Escaneo Automático de Biblioteca",
@ -172,7 +173,7 @@
"HeaderSettingsExperimental": "Funciones Experimentales",
"HeaderSettingsGeneral": "General",
"HeaderSettingsScanner": "Escáner",
"HeaderSleepTimer": "Temporizador para Dormir",
"HeaderSleepTimer": "temporizador de apagado",
"HeaderStatsLargestItems": "Artículos mas Grandes",
"HeaderStatsLongestItems": "Artículos mas Largos (h)",
"HeaderStatsMinutesListeningChart": "Minutos Escuchando (Últimos 7 días)",
@ -186,23 +187,23 @@
"HeaderUpdateDetails": "Actualizar Detalles",
"HeaderUpdateLibrary": "Actualizar Biblioteca",
"HeaderUsers": "Usuarios",
"HeaderYearReview": "Year {0} in Review",
"HeaderYearReview": "Revisión del año {0}",
"HeaderYourStats": "Tus Estadísticas",
"LabelAbridged": "Abreviado",
"LabelAbridgedChecked": "Abridged (checked)",
"LabelAbridgedUnchecked": "Unabridged (unchecked)",
"LabelAccessibleBy": "Accessible by",
"LabelAbridgedChecked": "Abreviado (comprobado)",
"LabelAbridgedUnchecked": "Sin abreviar (sin comprobar)",
"LabelAccessibleBy": "Accesible por",
"LabelAccountType": "Tipo de Cuenta",
"LabelAccountTypeAdmin": "Administrador",
"LabelAccountTypeGuest": "Invitado",
"LabelAccountTypeUser": "Usuario",
"LabelActivity": "Actividad",
"LabelAdded": "Añadido",
"LabelAddedAt": "Añadido",
"LabelAddToCollection": "Añadido a la Colección",
"LabelAddToCollectionBatch": "Se Añadieron {0} Libros a la Colección",
"LabelAddToPlaylist": "Añadido a la Lista de Reproducción",
"LabelAddToPlaylistBatch": "Se Añadieron {0} Artículos a la Lista de Reproducción",
"LabelAdded": "Añadido",
"LabelAddedAt": "Añadido",
"LabelAdminUsersOnly": "Solamente usuarios administradores",
"LabelAll": "Todos",
"LabelAllUsers": "Todos los Usuarios",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Cambiar Contraseña",
"LabelChannels": "Canales",
"LabelChapterTitle": "Titulo del Capítulo",
"LabelChapters": "Capítulos",
"LabelChaptersFound": "Capítulo Encontrado",
"LabelChapterTitle": "Titulo del Capítulo",
"LabelClickForMoreInfo": "Click para más información",
"LabelClosePlayer": "Cerrar Reproductor",
"LabelCodec": "Codec",
@ -279,8 +280,8 @@
"LabelEdit": "Editar",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "Remitente",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Rechazar certificados no autorizados",
"LabelEmailSettingsRejectUnauthorizedHelp": "Deshabilitar la validación de certificados SSL puede exponer tu conexión a riesgos de seguridad, como ataques man-in-the-middle. Desactiva esta opción sólo si conoces las implicaciones y confias en el servidor de correo al que te conectas.",
"LabelEmailSettingsSecure": "Seguridad",
"LabelEmailSettingsSecureHelp": "Si está activado, se usará TLS para conectarse al servidor. Si está apagado, se usará TLS si su servidor tiene soporte para la extensión STARTTLS. En la mayoría de los casos, puede dejar esta opción activada si se está conectando al puerto 465. Apáguela en el caso de usar los puertos 587 o 25. (de nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Probar Dirección",
@ -306,6 +307,7 @@
"LabelFolder": "Carpeta",
"LabelFolders": "Carpetas",
"LabelFontBold": "Negrilla",
"LabelFontBoldness": "Nivel de negrilla en fuente",
"LabelFontFamily": "Familia tipográfica",
"LabelFontItalic": "Itálica",
"LabelFontScale": "Tamaño de Fuente",
@ -321,9 +323,9 @@
"LabelHour": "Hora",
"LabelIcon": "Icono",
"LabelImageURLFromTheWeb": "URL de la imagen",
"LabelInProgress": "En Proceso",
"LabelIncludeInTracklist": "Incluir en la Tracklist",
"LabelIncomplete": "Incompleto",
"LabelInProgress": "En Proceso",
"LabelInterval": "Intervalo",
"LabelIntervalCustomDailyWeekly": "Personalizar diario/semanal",
"LabelIntervalEvery12Hours": "Cada 12 Horas",
@ -337,6 +339,7 @@
"LabelItem": "Elemento",
"LabelLanguage": "Lenguaje",
"LabelLanguageDefaultServer": "Lenguaje Predeterminado del Servidor",
"LabelLanguages": "Idiomas",
"LabelLastBookAdded": "Último Libro Agregado",
"LabelLastBookUpdated": "Último Libro Actualizado",
"LabelLastSeen": "Última Vez Visto",
@ -348,11 +351,12 @@
"LabelLess": "Menos",
"LabelLibrariesAccessibleToUser": "Bibliotecas Disponibles para el Usuario",
"LabelLibrary": "Biblioteca",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Elemento de Biblioteca",
"LabelLibraryName": "Nombre de Biblioteca",
"LabelLimit": "Limites",
"LabelLineSpacing": "Interlineado",
"LabelListenAgain": "Escuchar Otra Vez",
"LabelListenAgain": "Volver a escuchar",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Información",
"LabelLogLevelWarn": "Advertencia",
@ -362,45 +366,46 @@
"LabelMatchExistingUsersByDescription": "Se utiliza para conectar usuarios existentes. Una vez conectados, los usuarios serán emparejados por un identificador único de su proveedor de SSO",
"LabelMediaPlayer": "Reproductor de Medios",
"LabelMediaType": "Tipo de Multimedia",
"LabelMetadataOrderOfPrecedenceDescription": "Las fuentes de metadatos de mayor prioridad prevalecerán sobre las de menor prioridad",
"LabelMetadataProvider": "Proveedor de Metadatos",
"LabelMetaTag": "Metaetiqueta",
"LabelMetaTags": "Metaetiquetas",
"LabelMetadataOrderOfPrecedenceDescription": "Las fuentes de metadatos de mayor prioridad prevalecerán sobre las de menor prioridad",
"LabelMetadataProvider": "Proveedor de Metadatos",
"LabelMinute": "Minuto",
"LabelMissing": "Ausente",
"LabelMissingEbook": "No tiene ebook",
"LabelMissingSupplementaryEbook": "No tiene ebook suplementario",
"LabelMobileRedirectURIs": "URIs de redirección a móviles permitidos",
"LabelMobileRedirectURIsDescription": "Esta es una lista de URIs válidos para redireccionamiento de apps móviles. La URI por defecto es <code>audiobookshelf://oauth</code>, la cual puedes remover or corroborar con URIs adicionales para la integración con apps de terceros. Utilizando un asterisco (<code>*</code>) como el único punto de entrada permite cualquier URI.",
"LabelMobileRedirectURIsDescription": "Esta es una lista blanca de URI de redireccionamiento válidos para aplicaciones móviles. El predeterminado es <code> audiobookshelf</code> , que puede eliminar o complementar con URI adicionales para la integración de aplicaciones de terceros. Usando un asterisco (<code> *</code> ) como única entrada que permite cualquier URI.",
"LabelMore": "Más",
"LabelMoreInfo": "Más Información",
"LabelName": "Nombre",
"LabelNarrator": "Narrador",
"LabelNarrators": "Narradores",
"LabelNew": "Nuevo",
"LabelNewPassword": "Nueva Contraseña",
"LabelNewestAuthors": "Nuevos Autores",
"LabelNewestEpisodes": "Nuevos Episodios",
"LabelNewPassword": "Nueva Contraseña",
"LabelNextBackupDate": "Fecha del Siguiente Respaldo",
"LabelNextScheduledRun": "Próxima Ejecución Programada",
"LabelNoCustomMetadataProviders": "Sin proveedores de metadatos personalizados",
"LabelNoEpisodesSelected": "Ningún Episodio Seleccionado",
"LabelNotes": "Notas",
"LabelNotFinished": "No Terminado",
"LabelNotStarted": "Sin Iniciar",
"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",
"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.",
"LabelNotificationTitleTemplate": "Plantilla de Titulo",
"LabelNotStarted": "Sin Iniciar",
"LabelNumberOfBooks": "Numero de Libros",
"LabelNumberOfEpisodes": "# de Episodios",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
"LabelOpenIDClaims": "Leave the following options empty to disable advanced group and permissions assignment, automatically assigning 'User' group then.",
"LabelOpenIDGroupClaimDescription": "Name of the OpenID claim that contains a list of the user's groups. Commonly referred to as <code>groups</code>. <b>If configured</b>, the application will automatically assign roles based on the user's group memberships, provided that these groups are named case-insensitively 'admin', 'user', or 'guest' in the claim. The claim should contain a list, and if a user belongs to multiple groups, the application will assign the role corresponding to the highest level of access. If no group matches, access will be denied.",
"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'",
"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 Fuente RSS",
"LabelOverwrite": "Sobrescribir",
"LabelPassword": "Contraseña",
@ -412,14 +417,15 @@
"LabelPermissionsDownload": "Puede Descargar",
"LabelPermissionsUpdate": "Puede Actualizar",
"LabelPermissionsUpload": "Puede Subir",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPersonalYearReview": "Revisión de tu año ({0})",
"LabelPhotoPathURL": "Ruta de Acceso/URL de Foto",
"LabelPlaylists": "Lista de Reproducción",
"LabelPlayMethod": "Método de Reproducción",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Lista de Reproducción",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Región de búsqueda de podcasts",
"LabelPodcastType": "Tipo Podcast",
"LabelPodcasts": "Podcasts",
"LabelPort": "Puerto",
"LabelPrefixesToIgnore": "Prefijos para Ignorar (no distingue entre mayúsculas y minúsculas.)",
"LabelPreventIndexing": "Evite que su fuente sea indexada por los directorios de podcasts de iTunes y Google",
@ -427,30 +433,31 @@
"LabelProgress": "Progreso",
"LabelProvider": "Proveedor",
"LabelPubDate": "Fecha de Publicación",
"LabelPublisher": "Editor",
"LabelPublishYear": "Año de Publicación",
"LabelRead": "Leído",
"LabelReadAgain": "Volver a leer",
"LabelReadEbookWithoutProgress": "Leer Ebook sin guardar progreso",
"LabelRecentlyAdded": "Agregado Recientemente",
"LabelRecentSeries": "Series Recientes",
"LabelRecommended": "Recomendados",
"LabelRedo": "Rehacer",
"LabelRegion": "Región",
"LabelReleaseDate": "Fecha de Estreno",
"LabelRemoveCover": "Remover Portada",
"LabelRowsPerPage": "Filas por página",
"LabelPublisher": "Editor",
"LabelPublishers": "Editores",
"LabelRSSFeedCustomOwnerEmail": "Email de dueño personalizado",
"LabelRSSFeedCustomOwnerName": "Nombre de dueño personalizado",
"LabelRSSFeedOpen": "Fuente RSS Abierta",
"LabelRSSFeedPreventIndexing": "Prevenir Indexado",
"LabelRSSFeedSlug": "Fuente RSS Slug",
"LabelRSSFeedURL": "URL de Fuente RSS",
"LabelRead": "Leído",
"LabelReadAgain": "Volver a leer",
"LabelReadEbookWithoutProgress": "Leer Ebook sin guardar progreso",
"LabelRecentSeries": "Series Recientes",
"LabelRecentlyAdded": "Agregado Recientemente",
"LabelRecommended": "Recomendados",
"LabelRedo": "Rehacer",
"LabelRegion": "Región",
"LabelReleaseDate": "Fecha de Estreno",
"LabelRemoveCover": "Remover Portada",
"LabelRowsPerPage": "Filas por página",
"LabelSearchTerm": "Buscar Termino",
"LabelSearchTitle": "Buscar Titulo",
"LabelSearchTitleOrASIN": "Buscar Título o ASIN",
"LabelSeason": "Temporada",
"LabelSelectAll": "Select all",
"LabelSelectAll": "Seleccionar todo",
"LabelSelectAllEpisodes": "Seleccionar todos los episodios",
"LabelSelectEpisodesShowing": "Seleccionar los {0} episodios visibles",
"LabelSelectUsers": "Seleccionar usuarios",
@ -459,7 +466,7 @@
"LabelSeries": "Series",
"LabelSeriesName": "Nombre de la Serie",
"LabelSeriesProgress": "Progreso de la Serie",
"LabelServerYearReview": "Server Year in Review ({0})",
"LabelServerYearReview": "Resumen del año del servidor ({0})",
"LabelSetEbookAsPrimary": "Establecer como primario",
"LabelSetEbookAsSupplementary": "Establecer como suplementario",
"LabelSettingsAudiobooksOnly": "Sólo Audiolibros",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Habilitar Watcher",
"LabelSettingsEnableWatcherForLibrary": "Habilitar Watcher para la carpeta de esta biblioteca",
"LabelSettingsEnableWatcherHelp": "Permite agregar/actualizar elementos automáticamente cuando se detectan cambios en los archivos. *Requiere reiniciar el servidor",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "Permitir scripts en epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Permitir que los archivos epub ejecuten scripts. Se recomienda mantener esta opción desactivada a menos que confíe en el origen de los archivos epub.",
"LabelSettingsExperimentalFeatures": "Funciones Experimentales",
"LabelSettingsExperimentalFeaturesHelp": "Funciones en desarrollo que se beneficiarían de sus comentarios y experiencias de prueba. Haga click aquí para abrir una conversación en Github.",
"LabelSettingsFindCovers": "Buscar Portadas",
@ -483,7 +490,7 @@
"LabelSettingsHideSingleBookSeriesHelp": "Las series con un solo libro no aparecerán en la página de series ni la repisa para series de la página principal.",
"LabelSettingsHomePageBookshelfView": "Usar la vista de librero en la página principal",
"LabelSettingsLibraryBookshelfView": "Usar la vista de librero en la biblioteca",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Skip earlier books in Continue Series",
"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í\"",
@ -492,23 +499,23 @@
"LabelSettingsSkipMatchingBooksWithASIN": "Omitir libros coincidentes que ya tengan un ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Omitir libros coincidentes que ya tengan un ISBN",
"LabelSettingsSortingIgnorePrefixes": "Ignorar prefijos al ordenar",
"LabelSettingsSortingIgnorePrefixesHelp": "Por ejemplo: El prefijo \"el\" del titulo \"El titulo del libro\" se ordenará como \"Titulo del Libro, el\".",
"LabelSettingsSortingIgnorePrefixesHelp": "Es decir, para el prefijo \"el\" título del libro, \"El título del libro\" se ordenaría como \"Título del libro, El\"",
"LabelSettingsSquareBookCovers": "Usar portadas cuadradas",
"LabelSettingsSquareBookCoversHelp": "Prefierir usar portadas cuadradas sobre las portadas estándar 1.6:1",
"LabelSettingsStoreCoversWithItem": "Guardar portadas con elementos",
"LabelSettingsStoreCoversWithItemHelp": "Por defecto, las portadas se almacenan en /metadata/items. Si habilita esta opción, las portadas se almacenarán en la carpeta de elementos de su biblioteca. Se guardará un solo archivo llamado \"cover\".",
"LabelSettingsStoreCoversWithItemHelp": "De forma predeterminada, las portadas se almacenan en /metadata/items, activando esta opción almacenará las portadas en la carpeta de elementos de la biblioteca. Sólo se conservará un archivo llamado \"cover\"",
"LabelSettingsStoreMetadataWithItem": "Guardar metadatos con elementos",
"LabelSettingsStoreMetadataWithItemHelp": "Por defecto, los archivos de metadatos se almacenan en /metadata/items. Si habilita esta opción, los archivos de metadatos se guardarán en la carpeta de elementos de su biblioteca",
"LabelSettingsTimeFormat": "Formato de Tiempo",
"LabelShowAll": "Mostrar Todos",
"LabelShowSeconds": "Mostrar segundos",
"LabelSize": "Tamaño",
"LabelSleepTimer": "Temporizador para Dormir",
"LabelSleepTimer": "Temporizador de apagado",
"LabelSlug": "Slug",
"LabelStart": "Iniciar",
"LabelStartTime": "Tiempo de Inicio",
"LabelStarted": "Iniciado",
"LabelStartedAt": "Iniciado En",
"LabelStartTime": "Tiempo de Inicio",
"LabelStatsAudioTracks": "Pistas de Audio",
"LabelStatsAuthors": "Autores",
"LabelStatsBestDay": "Mejor Día",
@ -563,10 +570,10 @@
"LabelUndo": "Deshacer",
"LabelUnknown": "Desconocido",
"LabelUpdateCover": "Actualizar Portada",
"LabelUpdateCoverHelp": "Permitir sobrescribir las portadas existentes de los libros seleccionados cuando sean encontradas.",
"LabelUpdatedAt": "Actualizado En",
"LabelUpdateCoverHelp": "Permitir sobrescribir las portadas existentes para los libros seleccionados cuando se encuentra una coincidencia",
"LabelUpdateDetails": "Actualizar Detalles",
"LabelUpdateDetailsHelp": "Permitir sobrescribir detalles existentes de los libros seleccionados cuando sean encontrados",
"LabelUpdatedAt": "Actualizado En",
"LabelUploaderDragAndDrop": "Arrastre y suelte archivos o carpetas",
"LabelUploaderDropFiles": "Suelte los Archivos",
"LabelUploaderItemFetchMetadataHelp": "Buscar título, autor y series automáticamente",
@ -592,10 +599,11 @@
"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.",
"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": "No tienes ninguna colección.",
"MessageBookshelfNoResultsForFilter": "Ningún Resultado para el filtro \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Ninguna Fuente RSS esta abierta",
"MessageBookshelfNoResultsForFilter": "Ningún Resultado para el filtro \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No hay resultados para la consulta",
"MessageBookshelfNoSeries": "No tienes ninguna serie",
"MessageChapterEndIsAfter": "El final del capítulo es después del final de su audiolibro.",
"MessageChapterEndIsAfter": "El final del capítulo es después del final de tu audiolibro.",
"MessageChapterErrorFirstNotZero": "El primer capitulo debe iniciar en 0",
"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",
@ -614,7 +622,9 @@
"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?",
"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é?",
"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?",
"MessageConfirmPurgeItemsCache": "Purgar la caché de los elementos eliminará todo el directorio <code>/metadata/cache/items</code>.<br />¿Estás seguro?",
"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?",
"MessageConfirmReScanLibraryItems": "¿Estás seguro de querer re escanear {0} elemento(s)?",
"MessageConfirmRemoveAllChapters": "¿Está seguro de que desea remover todos los capitulos?",
"MessageConfirmRemoveAuthor": "¿Está seguro de que desea remover el autor \"{0}\"?",
"MessageConfirmRemoveCollection": "¿Está seguro de que desea remover la colección \"{0}\"?",
@ -629,13 +639,12 @@
"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}\".",
"MessageConfirmReScanLibraryItems": "¿Estás seguro de querer re escanear {0} elemento(s)?",
"MessageConfirmSendEbookToDevice": "¿Está seguro de que enviar {0} ebook(s) \"{1}\" al dispositivo \"{2}\"?",
"MessageDownloadingEpisode": "Descargando Capitulo",
"MessageDragFilesIntoTrackOrder": "Arrastra los archivos al orden correcto de las pistas.",
"MessageEmbedFinished": "Incrustación Terminada!",
"MessageEpisodesQueuedForDownload": "{0} Episodio(s) en cola para descargar",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"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": "URL de la fuente será {0}",
"MessageFetching": "Buscando...",
"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.",
@ -683,10 +692,10 @@
"MessageNoSeries": "Sin Series",
"MessageNoTags": "Sin Etiquetas",
"MessageNoTasksRunning": "Ninguna Tarea Corriendo",
"MessageNotYetImplemented": "Aun no implementado",
"MessageNoUpdateNecessary": "No es necesario actualizar",
"MessageNoUpdatesWereNecessary": "No fue necesario actualizar",
"MessageNoUserPlaylists": "No tienes lista de reproducciones",
"MessageNotYetImplemented": "Aun no implementado",
"MessageOr": "o",
"MessagePauseChapter": "Pausar la reproducción del capítulo",
"MessagePlayChapter": "Escuchar el comienzo del capítulo",
@ -769,9 +778,9 @@
"ToastItemDetailsUpdateFailed": "Error al actualizar los detalles del elemento",
"ToastItemDetailsUpdateSuccess": "Detalles del Elemento Actualizados",
"ToastItemDetailsUpdateUnneeded": "No se necesitan actualizaciones para los detalles del Elemento",
"ToastItemMarkedAsFinishedFailed": "Error al marcar como Terminado",
"ToastItemMarkedAsFinishedFailed": "Error al marcar como terminado",
"ToastItemMarkedAsFinishedSuccess": "Elemento marcado como terminado",
"ToastItemMarkedAsNotFinishedFailed": "Error al marcar como No Terminado",
"ToastItemMarkedAsNotFinishedFailed": "No se ha podido marcar como no finalizado",
"ToastItemMarkedAsNotFinishedSuccess": "Elemento marcado como No Terminado",
"ToastLibraryCreateFailed": "Error al crear biblioteca",
"ToastLibraryCreateSuccess": "Biblioteca \"{0}\" creada",
@ -781,7 +790,7 @@
"ToastLibraryScanStarted": "Se inició el escaneo de la biblioteca",
"ToastLibraryUpdateFailed": "Error al actualizar la biblioteca",
"ToastLibraryUpdateSuccess": "Biblioteca \"{0}\" actualizada",
"ToastPlaylistCreateFailed": "Error al crear la lista de reproducción.",
"ToastPlaylistCreateFailed": "Error al crear la lista de reproducción",
"ToastPlaylistCreateSuccess": "Lista de reproducción creada",
"ToastPlaylistRemoveFailed": "Error al eliminar la lista de reproducción",
"ToastPlaylistRemoveSuccess": "Lista de reproducción eliminada",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Lista de reproducción actualizada",
"ToastPodcastCreateFailed": "Error al crear podcast",
"ToastPodcastCreateSuccess": "Podcast creado",
"ToastRemoveItemFromCollectionFailed": "Error al eliminar el elemento de la colección",
"ToastRemoveItemFromCollectionSuccess": "Elemento eliminado de la colección.",
"ToastRSSFeedCloseFailed": "Error al cerrar fuente RSS",
"ToastRSSFeedCloseSuccess": "Fuente RSS cerrada",
"ToastRemoveItemFromCollectionFailed": "Error al eliminar el elemento de la colección",
"ToastRemoveItemFromCollectionSuccess": "Elemento eliminado de la colección.",
"ToastSendEbookToDeviceFailed": "Error al enviar el ebook al dispositivo",
"ToastSendEbookToDeviceSuccess": "Ebook enviado al dispositivo \"{0}\"",
"ToastSeriesUpdateFailed": "Error al actualizar la serie",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Prefijos de ordenar actualizaron ({0} items)",
"ToastUserDeleteFailed": "Error al eliminar el usuario",
"ToastUserDeleteSuccess": "Usuario eliminado"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Rakenda",
"ButtonApplyChapters": "Rakenda peatükid",
"ButtonAuthors": "Autorid",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Sirvi kausta",
"ButtonCancel": "Tühista",
"ButtonCancelEncode": "Tühista kodeerimine",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Eelmine peatükk",
"ButtonPurgeAllCache": "Tühjenda kogu vahemälu",
"ButtonPurgeItemsCache": "Tühjenda esemete vahemälu",
"ButtonPurgeMediaProgress": "Tühjenda meedia edenemine",
"ButtonQueueAddItem": "Lisa järjekorda",
"ButtonQueueRemoveItem": "Eemalda järjekorrast",
"ButtonQuickMatch": "Kiire sobitamine",
"ButtonReScan": "Uuestiskaneeri",
"ButtonRead": "Loe",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Eemalda jätkake kuulamisest",
"ButtonRemoveFromContinueReading": "Eemalda jätkake lugemisest",
"ButtonRemoveSeriesFromContinueSeries": "Eemalda seeria jätkamisest",
"ButtonReScan": "Uuestiskaneeri",
"ButtonReset": "Lähtesta",
"ButtonResetToDefault": "Lähtesta vaikeseade",
"ButtonRestore": "Taasta",
@ -104,8 +104,8 @@
"HeaderAccount": "Konto",
"HeaderAdvanced": "Täpsem",
"HeaderAppriseNotificationSettings": "Apprise teavitamise seaded",
"HeaderAudiobookTools": "Heliraamatu failihaldustööriistad",
"HeaderAudioTracks": "Helirajad",
"HeaderAudiobookTools": "Heliraamatu failihaldustööriistad",
"HeaderAuthentication": "Autentimine",
"HeaderBackups": "Varukoopiad",
"HeaderChangePassword": "Muuda parooli",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Kogu esemed",
"HeaderCover": "Ümbris",
"HeaderCurrentDownloads": "Praegused allalaadimised",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Kohandatud metaandmete pakkujad",
"HeaderDetails": "Detailid",
"HeaderDownloadQueue": "Allalaadimise järjekord",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Mänguloendi esemed",
"HeaderPodcastsToAdd": "Lisatavad podcastid",
"HeaderPreviewCover": "Eelvaate kaas",
"HeaderRemoveEpisode": "Eemalda episood",
"HeaderRemoveEpisodes": "Eemalda {0} episoodi",
"HeaderRSSFeedGeneral": "RSS-i üksikasjad",
"HeaderRSSFeedIsOpen": "RSS-voog on avatud",
"HeaderRSSFeeds": "RSS-vooged",
"HeaderRemoveEpisode": "Eemalda episood",
"HeaderRemoveEpisodes": "Eemalda {0} episoodi",
"HeaderSavedMediaProgress": "Salvestatud meedia edenemine",
"HeaderSchedule": "Ajakava",
"HeaderScheduleLibraryScans": "Ajasta automaatsed raamatukogu skaneerimised",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Külaline",
"LabelAccountTypeUser": "Kasutaja",
"LabelActivity": "Tegevus",
"LabelAdded": "Lisatud",
"LabelAddedAt": "Lisatud",
"LabelAddToCollection": "Lisa kogusse",
"LabelAddToCollectionBatch": "Lisa {0} raamatut kogusse",
"LabelAddToPlaylist": "Lisa mänguloendisse",
"LabelAddToPlaylistBatch": "Lisa {0} eset mänguloendisse",
"LabelAdded": "Lisatud",
"LabelAddedAt": "Lisatud",
"LabelAdminUsersOnly": "Ainult administraatorid",
"LabelAll": "Kõik",
"LabelAllUsers": "Kõik kasutajad",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Muuda parooli",
"LabelChannels": "Kanalid",
"LabelChapterTitle": "Peatüki pealkiri",
"LabelChapters": "Peatükid",
"LabelChaptersFound": "peatükid leitud",
"LabelChapterTitle": "Peatüki pealkiri",
"LabelClickForMoreInfo": "Klõpsa lisateabe saamiseks",
"LabelClosePlayer": "Sulge mängija",
"LabelCodec": "Kodek",
@ -306,6 +307,7 @@
"LabelFolder": "Kaust",
"LabelFolders": "Kataloogid",
"LabelFontBold": "Paks",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Fondi pere",
"LabelFontItalic": "Kaldkiri",
"LabelFontScale": "Fondi suurus",
@ -321,9 +323,9 @@
"LabelHour": "Tund",
"LabelIcon": "Ikoon",
"LabelImageURLFromTheWeb": "Pildi URL veebist",
"LabelInProgress": "Pooleli",
"LabelIncludeInTracklist": "Kaasa jälgimisloendis",
"LabelIncomplete": "Puudulik",
"LabelInProgress": "Pooleli",
"LabelInterval": "Intervall",
"LabelIntervalCustomDailyWeekly": "Kohandatud päevane/nädalane",
"LabelIntervalEvery12Hours": "Iga 12 tunni tagant",
@ -337,6 +339,7 @@
"LabelItem": "Kirje",
"LabelLanguage": "Keel",
"LabelLanguageDefaultServer": "Vaikeserveri keel",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Viimati lisatud raamat",
"LabelLastBookUpdated": "Viimati uuendatud raamat",
"LabelLastSeen": "Viimati nähtud",
@ -348,6 +351,7 @@
"LabelLess": "Vähem",
"LabelLibrariesAccessibleToUser": "Kasutajale ligipääsetavad raamatukogud",
"LabelLibrary": "Raamatukogu",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Raamatukogu kirje",
"LabelLibraryName": "Raamatukogu nimi",
"LabelLimit": "Piirang",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Kasutatakse olemasolevate kasutajate ühendamiseks. Ühendatud kasutajaid sobitatakse teie SSO pakkuja unikaalse ID järgi.",
"LabelMediaPlayer": "Meediapleier",
"LabelMediaType": "Meedia tüüp",
"LabelMetadataOrderOfPrecedenceDescription": "Kõrgema prioriteediga metaandmete allikad võtavad üle madalama prioriteediga metaandmete allikad",
"LabelMetadataProvider": "Metaandmete pakkuja",
"LabelMetaTag": "Meta märge",
"LabelMetaTags": "Meta märgendid",
"LabelMetadataOrderOfPrecedenceDescription": "Kõrgema prioriteediga metaandmete allikad võtavad üle madalama prioriteediga metaandmete allikad",
"LabelMetadataProvider": "Metaandmete pakkuja",
"LabelMinute": "Minut",
"LabelMissing": "Puudub",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Jutustaja",
"LabelNarrators": "Jutustajad",
"LabelNew": "Uus",
"LabelNewPassword": "Uus parool",
"LabelNewestAuthors": "Uusimad autorid",
"LabelNewestEpisodes": "Uusimad episoodid",
"LabelNewPassword": "Uus parool",
"LabelNextBackupDate": "Järgmine varukoopia kuupäev",
"LabelNextScheduledRun": "Järgmine ajakava järgmine",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Episoodid pole valitud",
"LabelNotes": "Märkused",
"LabelNotFinished": "Ei ole lõpetatud",
"LabelNotStarted": "Pole alustatud",
"LabelNotes": "Märkused",
"LabelNotificationAppriseURL": "Apprise URL-id",
"LabelNotificationAvailableVariables": "Saadaolevad muutujad",
"LabelNotificationBodyTemplate": "Keha mall",
"LabelNotificationEvent": "Teavituse sündmus",
"LabelNotificationTitleTemplate": "Pealkirja mall",
"LabelNotificationsMaxFailedAttempts": "Maksimaalsed ebaõnnestunud katsed",
"LabelNotificationsMaxFailedAttemptsHelp": "Teatised keelatakse, kui need ebaõnnestuvad nii palju kordi",
"LabelNotificationsMaxQueueSize": "Teavituste sündmuste maksimaalne järjekorra suurus",
"LabelNotificationsMaxQueueSizeHelp": "Sündmused on piiratud 1 sekundiga. Sündmusi ignoreeritakse, kui järjekord on maksimumsuuruses. See takistab teavituste rämpsposti.",
"LabelNotificationTitleTemplate": "Pealkirja mall",
"LabelNotStarted": "Pole alustatud",
"LabelNumberOfBooks": "Raamatute arv",
"LabelNumberOfEpisodes": "Episoodide arv",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Saab üles laadida",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Foto tee/URL",
"LabelPlaylists": "Mänguloendid",
"LabelPlayMethod": "Esitusmeetod",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Mänguloendid",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcastid",
"LabelPodcastSearchRegion": "Podcasti otsingu piirkond",
"LabelPodcastType": "Podcasti tüüp",
"LabelPodcasts": "Podcastid",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Eiramiseks eesliited (tõstutundetu)",
"LabelPreventIndexing": "Vältige oma voogu indekseerimist iTunes'i ja Google podcasti kataloogides",
@ -427,25 +433,26 @@
"LabelProgress": "Edenemine",
"LabelProvider": "Pakkuja",
"LabelPubDate": "Avaldamise kuupäev",
"LabelPublisher": "Kirjastaja",
"LabelPublishYear": "Aasta avaldamine",
"LabelRead": "Lugenud",
"LabelReadAgain": "Loe uuesti",
"LabelReadEbookWithoutProgress": "Lugege e-raamatut ilma edenemist säilitamata",
"LabelRecentlyAdded": "Hiljuti lisatud",
"LabelRecentSeries": "Hiljutised seeriad",
"LabelRecommended": "Soovitatud",
"LabelRedo": "Tee uuesti",
"LabelRegion": "Piirkond",
"LabelReleaseDate": "Väljalaske kuupäev",
"LabelRemoveCover": "Eemalda ümbris",
"LabelRowsPerPage": "Rida lehe kohta",
"LabelPublisher": "Kirjastaja",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Kohandatud omaniku e-post",
"LabelRSSFeedCustomOwnerName": "Kohandatud omaniku nimi",
"LabelRSSFeedOpen": "Ava RSS voog",
"LabelRSSFeedPreventIndexing": "Vältige indekseerimist",
"LabelRSSFeedSlug": "RSS voog Slug",
"LabelRSSFeedURL": "RSS voog URL",
"LabelRead": "Lugenud",
"LabelReadAgain": "Loe uuesti",
"LabelReadEbookWithoutProgress": "Lugege e-raamatut ilma edenemist säilitamata",
"LabelRecentSeries": "Hiljutised seeriad",
"LabelRecentlyAdded": "Hiljuti lisatud",
"LabelRecommended": "Soovitatud",
"LabelRedo": "Tee uuesti",
"LabelRegion": "Piirkond",
"LabelReleaseDate": "Väljalaske kuupäev",
"LabelRemoveCover": "Eemalda ümbris",
"LabelRowsPerPage": "Rida lehe kohta",
"LabelSearchTerm": "Otsingutermin",
"LabelSearchTitle": "Otsi pealkirja",
"LabelSearchTitleOrASIN": "Otsi pealkirja või ASIN-i",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Uinaku taimer",
"LabelSlug": "Slug",
"LabelStart": "Alusta",
"LabelStartTime": "Alustamise aeg",
"LabelStarted": "Alustatud",
"LabelStartedAt": "Alustatud",
"LabelStartTime": "Alustamise aeg",
"LabelStatsAudioTracks": "Audiojäljed",
"LabelStatsAuthors": "Autorid",
"LabelStatsBestDay": "Parim päev",
@ -564,9 +571,9 @@
"LabelUnknown": "Tundmatu",
"LabelUpdateCover": "Uuenda kaant",
"LabelUpdateCoverHelp": "Luba üle kirjutamine olemasolevate kaante jaoks valitud raamatutele, kui leitakse sobivus",
"LabelUpdatedAt": "Uuendatud",
"LabelUpdateDetails": "Uuenda üksikasju",
"LabelUpdateDetailsHelp": "Luba üle kirjutamine olemasolevate üksikasjade jaoks valitud raamatutele, kui leitakse sobivus",
"LabelUpdatedAt": "Uuendatud",
"LabelUploaderDragAndDrop": "Lohista ja aseta faile või kaustu",
"LabelUploaderDropFiles": "Aseta failid",
"LabelUploaderItemFetchMetadataHelp": "Hangi automaatselt pealkiri, autor ja seeria",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Varukoopiad hõlmavad kasutajaid, kasutajate edenemist, raamatukogu üksikasju, serveri seadeid ja kaustades <code>/metadata/items</code> ja <code>/metadata/authors</code> salvestatud pilte. Varukoopiad ei hõlma ühtegi teie raamatukogu kaustades olevat faili.",
"MessageBatchQuickMatchDescription": "Kiire sobitamine üritab lisada valitud üksustele puuduvad kaaned ja metaandmed. Luba allpool olevad valikud, et lubada Kiire sobitamine'il üle kirjutada olemasolevaid kaasi ja/või metaandmeid.",
"MessageBookshelfNoCollections": "Te pole veel ühtegi kogumit teinud",
"MessageBookshelfNoResultsForFilter": "Filtrile \"{0}: {1}\" pole tulemusi",
"MessageBookshelfNoRSSFeeds": "Ühtegi RSS-i voogu pole avatud",
"MessageBookshelfNoResultsForFilter": "Filtrile \"{0}: {1}\" pole tulemusi",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Teil pole ühtegi seeriat",
"MessageChapterEndIsAfter": "Peatüki lõpp on pärast teie heliraamatu lõppu",
"MessageChapterErrorFirstNotZero": "Esimene peatükk peab algama 0-st",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Olete kindel, et soovite selle seeria kõik raamatud lõpetatuks märkida?",
"MessageConfirmMarkSeriesNotFinished": "Olete kindel, et soovite selle seeria kõik raamatud mitte lõpetatuks märkida?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Hoiatus! Quick Embed ei tee varukoopiaid teie helifailidest. Veenduge, et teil oleks varukoopia oma helifailidest. <br><br>Kas soovite jätkata?",
"MessageConfirmReScanLibraryItems": "Olete kindel, et soovite uuesti skannida {0} üksust?",
"MessageConfirmRemoveAllChapters": "Olete kindel, et soovite eemaldada kõik peatükid?",
"MessageConfirmRemoveAuthor": "Olete kindel, et soovite autori \"{0}\" eemaldada?",
"MessageConfirmRemoveCollection": "Olete kindel, et soovite kogumi \"{0}\" eemaldada?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Olete kindel, et soovite silti \"{0}\" ümber nimetada kujule \"{1}\" kõikidele üksustele?",
"MessageConfirmRenameTagMergeNote": "Märkus: See silt on juba olemas, nii et need ühendatakse.",
"MessageConfirmRenameTagWarning": "Hoiatus! Sarnane silt erineva puhvriga on juba olemas \"{0}\".",
"MessageConfirmReScanLibraryItems": "Olete kindel, et soovite uuesti skannida {0} üksust?",
"MessageConfirmSendEbookToDevice": "Olete kindel, et soovite saata {0} e-raamatu \"{1}\" seadmesse \"{2}\"?",
"MessageDownloadingEpisode": "Episoodi allalaadimine",
"MessageDragFilesIntoTrackOrder": "Lohistage failid õigesse järjekorda",
@ -683,10 +692,10 @@
"MessageNoSeries": "Ühtegi seeriat pole",
"MessageNoTags": "Ühtegi silti pole",
"MessageNoTasksRunning": "Ühtegi käimasolevat ülesannet pole",
"MessageNotYetImplemented": "Pole veel ellu viidud",
"MessageNoUpdateNecessary": "Ühtegi värskendust pole vaja",
"MessageNoUpdatesWereNecessary": "Ühtegi värskendust polnud vaja",
"MessageNoUserPlaylists": "Teil pole ühtegi esitusloendit",
"MessageNotYetImplemented": "Pole veel ellu viidud",
"MessageOr": "või",
"MessagePauseChapter": "Peata peatüki esitamine",
"MessagePlayChapter": "Kuula peatüki algust",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Esitusloend värskendatud",
"ToastPodcastCreateFailed": "Podcasti loomine ebaõnnestus",
"ToastPodcastCreateSuccess": "Podcast loodud edukalt",
"ToastRemoveItemFromCollectionFailed": "Üksuse eemaldamine kogumist ebaõnnestus",
"ToastRemoveItemFromCollectionSuccess": "Üksus eemaldatud kogumist",
"ToastRSSFeedCloseFailed": "RSS-voogu sulgemine ebaõnnestus",
"ToastRSSFeedCloseSuccess": "RSS-voog suletud",
"ToastRemoveItemFromCollectionFailed": "Üksuse eemaldamine kogumist ebaõnnestus",
"ToastRemoveItemFromCollectionSuccess": "Üksus eemaldatud kogumist",
"ToastSendEbookToDeviceFailed": "E-raamatu saatmine seadmesse ebaõnnestus",
"ToastSendEbookToDeviceSuccess": "E-raamat saadetud seadmesse \"{0}\"",
"ToastSeriesUpdateFailed": "Sarja värskendamine ebaõnnestus",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Kasutaja kustutamine ebaõnnestus",
"ToastUserDeleteSuccess": "Kasutaja kustutatud"
}
}

53
client/strings/fi.json Normal file
View File

@ -0,0 +1,53 @@
{
"ButtonAdd": "Lisää",
"ButtonAuthors": "Tekijät",
"ButtonBack": "Takaisin",
"ButtonCancel": "Peruuta",
"ButtonClearFilter": "Poista suodatus",
"ButtonCloseFeed": "Sulje syöte",
"ButtonCollections": "Kokoelmat",
"ButtonCreate": "Luo",
"ButtonDelete": "Poista",
"ButtonHome": "Koti",
"ButtonIssues": "Ongelmat",
"ButtonLatest": "Viimeisimmät",
"ButtonLibrary": "Kirjasto",
"ButtonOpenFeed": "Avaa syöte",
"ButtonPause": "Pysäytä",
"ButtonPlay": "Toista",
"ButtonPlaying": "Toistetaan",
"ButtonPlaylists": "Soittolistat",
"ButtonRead": "Lue",
"ButtonRemove": "Poista",
"ButtonSave": "Tallenna",
"ButtonSearch": "Etsi",
"ButtonSeries": "Sarjat",
"ButtonSubmit": "Lähetä",
"ButtonYes": "Kyllä",
"HeaderAccount": "Tili",
"HeaderAdvanced": "Edistynyt",
"HeaderAudioTracks": "Ääniraidat",
"HeaderChapters": "Luvut",
"HeaderCollection": "Kokoelma",
"HeaderCollectionItems": "Kokoelman osat",
"HeaderDetails": "Yksityiskohdat",
"HeaderEbookFiles": "E-kirjatiedostot",
"HeaderEpisodes": "Jaksot",
"HeaderEreaderSettings": "E-lukijan asetukset",
"HeaderLatestEpisodes": "Viimeisimmät jaksot",
"HeaderLibraries": "Kirjastot",
"HeaderOpenRSSFeed": "Avaa RSS-syöte",
"HeaderPlaylist": "Soittolista",
"HeaderRSSFeedGeneral": "RSS yksityiskohdat",
"HeaderRSSFeedIsOpen": "RSS syöte on avoinna",
"HeaderSettings": "Asetukset",
"HeaderSleepTimer": "Uniajastin",
"HeaderStatsMinutesListeningChart": "Kuunteluminuutit (viim. 7 pv)",
"HeaderStatsRecentSessions": "Viimeaikaiset istunnot",
"HeaderTableOfContents": "Sisällysluettelo",
"HeaderYourStats": "Tilastosi",
"LabelAddToPlaylist": "Lisää soittolistaan",
"LabelAdded": "Lisätty",
"LabelAddedAt": "Lisätty",
"LabelAll": "Kaikki"
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Appliquer",
"ButtonApplyChapters": "Appliquer aux chapitres",
"ButtonAuthors": "Auteurs",
"ButtonBack": "Retour",
"ButtonBrowseForFolder": "Naviguer vers le répertoire",
"ButtonCancel": "Annuler",
"ButtonCancelEncode": "Annuler lencodage",
@ -22,7 +23,7 @@
"ButtonConfigureScanner": "Configurer lanalyse",
"ButtonCreate": "Créer",
"ButtonCreateBackup": "Créer une sauvegarde",
"ButtonDelete": "Effacer",
"ButtonDelete": "Supprimer",
"ButtonDownloadQueue": "File dattente de téléchargement",
"ButtonEdit": "Modifier",
"ButtonEditChapters": "Modifier les chapitres",
@ -31,7 +32,7 @@
"ButtonFullPath": "Chemin complet",
"ButtonHide": "Cacher",
"ButtonHome": "Accueil",
"ButtonIssues": "Parutions",
"ButtonIssues": "Problèmes",
"ButtonJumpBackward": "Retour",
"ButtonJumpForward": "Avancer",
"ButtonLatest": "Dernière version",
@ -49,33 +50,32 @@
"ButtonOpenFeed": "Ouvrir le flux",
"ButtonOpenManager": "Ouvrir le gestionnaire",
"ButtonPause": "Pause",
"ButtonPlay": "Écouter",
"ButtonPlay": "Lire",
"ButtonPlaying": "En lecture",
"ButtonPlaylists": "Listes de lecture",
"ButtonPrevious": "Précédent",
"ButtonPreviousChapter": "Chapitre précédent",
"ButtonPurgeAllCache": "Purger le cache",
"ButtonPurgeItemsCache": "Purger le cache des articles",
"ButtonPurgeMediaProgress": "Purger la progression des médias",
"ButtonPurgeAllCache": "Purger tout le cache",
"ButtonPurgeItemsCache": "Purger le cache des éléments",
"ButtonQueueAddItem": "Ajouter à la liste de lecture",
"ButtonQueueRemoveItem": "Supprimer de la liste de lecture",
"ButtonQuickMatch": "Recherche rapide",
"ButtonReScan": "Nouvelle analyse",
"ButtonRead": "Lire",
"ButtonReadLess": "Lire moins",
"ButtonReadMore": "Lire la suite",
"ButtonRefresh": "Rafraîchir",
"ButtonRemove": "Supprimer",
"ButtonRemoveAll": "Supprimer tout",
"ButtonRemoveAllLibraryItems": "Supprimer tous les articles de la bibliothèque",
"ButtonRemoveAllLibraryItems": "Supprimer tous les éléments de la bibliothèque",
"ButtonRemoveFromContinueListening": "Ne plus continuer à écouter",
"ButtonRemoveFromContinueReading": "Ne plus continuer à lire",
"ButtonRemoveSeriesFromContinueSeries": "Ne plus continuer à écouter la série",
"ButtonReScan": "Nouvelle analyse",
"ButtonReset": "Réinitialiser",
"ButtonResetToDefault": "Réinitialiser aux valeurs par défaut",
"ButtonRestore": "Rétablir",
"ButtonSave": "Sauvegarder",
"ButtonSaveAndClose": "Sauvegarder et Fermer",
"ButtonSaveAndClose": "Sauvegarder et fermer",
"ButtonSaveTracklist": "Sauvegarder la liste de lecture",
"ButtonScan": "Analyser",
"ButtonScanLibrary": "Analyser la bibliothèque",
@ -99,13 +99,13 @@
"ButtonViewAll": "Afficher tout",
"ButtonYes": "Oui",
"ErrorUploadFetchMetadataAPI": "Erreur lors de la récupération des métadonnées",
"ErrorUploadFetchMetadataNoResults": "Impossible de récupérer les métadonnées - essayez de mettre à jour le titre et/ou lauteur.",
"ErrorUploadFetchMetadataNoResults": "Impossible de récupérer les métadonnées - essayez de mettre à jour le titre et/ou lauteur",
"ErrorUploadLacksTitle": "Doit avoir un titre",
"HeaderAccount": "Compte",
"HeaderAdvanced": "Avancé",
"HeaderAppriseNotificationSettings": "Configuration des notifications Apprise",
"HeaderAudiobookTools": "Outils de gestion de fichiers de livres audio",
"HeaderAudioTracks": "Pistes audio",
"HeaderAudiobookTools": "Outils de gestion de fichiers de livres audio",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Sauvegardes",
"HeaderChangePassword": "Modifier le mot de passe",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Entrées de la collection",
"HeaderCover": "Couverture",
"HeaderCurrentDownloads": "Téléchargements en cours",
"HeaderCustomMessageOnLogin": "Message personnalisé lors de la connexion",
"HeaderCustomMetadataProviders": "Fournisseurs de métadonnées personnalisés",
"HeaderDetails": "Détails",
"HeaderDownloadQueue": "File dattente de téléchargements",
@ -127,7 +128,7 @@
"HeaderFiles": "Fichiers",
"HeaderFindChapters": "Trouver les chapitres",
"HeaderIgnoredFiles": "Fichiers ignorés",
"HeaderItemFiles": "Fichiers des articles",
"HeaderItemFiles": "Fichiers des éléments",
"HeaderItemMetadataUtils": "Outils de gestion des métadonnées",
"HeaderLastListeningSession": "Dernière session découte",
"HeaderLatestEpisodes": "Dernier épisodes",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Éléments de la liste de lecture",
"HeaderPodcastsToAdd": "Podcasts à ajouter",
"HeaderPreviewCover": "Prévisualiser la couverture",
"HeaderRemoveEpisode": "Supprimer lépisode",
"HeaderRemoveEpisodes": "Suppression de {0} épisodes",
"HeaderRSSFeedGeneral": "Détails de flux RSS",
"HeaderRSSFeedIsOpen": "Le Flux RSS est actif",
"HeaderRSSFeeds": "Flux RSS",
"HeaderRemoveEpisode": "Supprimer lépisode",
"HeaderRemoveEpisodes": "Suppression de {0} épisodes",
"HeaderSavedMediaProgress": "Progression de la sauvegarde des médias",
"HeaderSchedule": "Programmation",
"HeaderScheduleLibraryScans": "Analyse automatique de la bibliothèque",
@ -173,8 +174,8 @@
"HeaderSettingsGeneral": "Général",
"HeaderSettingsScanner": "Analyseur",
"HeaderSleepTimer": "Minuterie",
"HeaderStatsLargestItems": "Articles les plus lourd",
"HeaderStatsLongestItems": "Articles les plus long (heures)",
"HeaderStatsLargestItems": "Éléments les plus grands",
"HeaderStatsLongestItems": "Éléments les plus long (hrs)",
"HeaderStatsMinutesListeningChart": "Minutes découte (7 derniers jours)",
"HeaderStatsRecentSessions": "Sessions récentes",
"HeaderStatsTop10Authors": "Top 10 Auteurs",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Invité",
"LabelAccountTypeUser": "Utilisateur",
"LabelActivity": "Activité",
"LabelAdded": "Ajouté",
"LabelAddedAt": "Date dajout",
"LabelAddToCollection": "Ajouter à la collection",
"LabelAddToCollectionBatch": "Ajout de {0} livres à la lollection",
"LabelAddToPlaylist": "Ajouter à la liste de lecture",
"LabelAddToPlaylistBatch": "{0} éléments ajoutés à la liste de lecture",
"LabelAdded": "Ajouté",
"LabelAddedAt": "Date dajout",
"LabelAdminUsersOnly": "Administrateurs uniquement",
"LabelAll": "Tout",
"LabelAllUsers": "Tous les utilisateurs",
@ -214,7 +215,7 @@
"LabelAuthorFirstLast": "Auteur (Prénom Nom)",
"LabelAuthorLastFirst": "Auteur (Nom, Prénom)",
"LabelAuthors": "Auteurs",
"LabelAutoDownloadEpisodes": "Téléchargement automatique dépisode",
"LabelAutoDownloadEpisodes": "Téléchargement automatique des épisodes",
"LabelAutoFetchMetadata": "Recherche automatique de métadonnées",
"LabelAutoFetchMetadataHelp": "Récupère les métadonnées du titre, de lauteur et de la série pour simplifier le téléchargement. Il se peut que des métadonnées supplémentaires doivent être ajoutées après le téléchargement.",
"LabelAutoLaunch": "Lancement automatique",
@ -235,9 +236,9 @@
"LabelByAuthor": "par {0}",
"LabelChangePassword": "Modifier le mot de passe",
"LabelChannels": "Canaux",
"LabelChapterTitle": "Titre du chapitre",
"LabelChapters": "Chapitres",
"LabelChaptersFound": "chapitres trouvés",
"LabelChapterTitle": "Titre du chapitre",
"LabelClickForMoreInfo": "Cliquez ici pour plus dinformations",
"LabelClosePlayer": "Fermer le lecteur",
"LabelCodec": "Codec",
@ -279,10 +280,10 @@
"LabelEdit": "Modifier",
"LabelEmail": "Courriel",
"LabelEmailSettingsFromAddress": "Expéditeur",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Rejeter les certificats non autorisés",
"LabelEmailSettingsRejectUnauthorizedHelp": "Désactiver la validation du certificat SSL peut exposer votre connexion à des risques de sécurité, tels que des attaques de type « man-in-the-middle ». Ne désactivez cette option que si vous en comprenez les implications et si vous faites confiance au serveur de messagerie auquel vous vous connectez.",
"LabelEmailSettingsSecure": "Sécurisé",
"LabelEmailSettingsSecureHelp": "Utiliser TLS lors de la connexion au serveur, autrement TLS sera utilisé si le serveur prend en charge lextension STARTTLS. Dans la plupart des cas, actviez loption si vous vous connectez au port 465. Désactivez loption pour utiliser port 587 ou 25. (source: nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsSecureHelp": "Si vous activez cette option, TLS sera utiliser lors de la connexion au serveur. Sinon, TLS est utilisé uniquement si le serveur supporte lextension STARTTLS. Dans la plupart des cas, activez loption, vous vous connecterai sur le port 465. Pour le port 587 ou 25, désactiver loption. (source: nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Adresse de test",
"LabelEmbeddedCover": "Couverture du livre intégrée",
"LabelEnable": "Activer",
@ -306,6 +307,7 @@
"LabelFolder": "Dossier",
"LabelFolders": "Dossiers",
"LabelFontBold": "Gras",
"LabelFontBoldness": "Graisse de la police",
"LabelFontFamily": "Polices de caractères",
"LabelFontItalic": "Italique",
"LabelFontScale": "Taille de la police de caractère",
@ -315,15 +317,15 @@
"LabelGenres": "Genres",
"LabelHardDeleteFile": "Suppression du fichier",
"LabelHasEbook": "Dispose dun livre numérique",
"LabelHasSupplementaryEbook": "Dispose dun livre numérique supplémentaire",
"LabelHasSupplementaryEbook": "À un livre numérique supplémentaire",
"LabelHighestPriority": "Priorité la plus élevée",
"LabelHost": "Hôte",
"LabelHour": "Heure",
"LabelIcon": "Icône",
"LabelImageURLFromTheWeb": "URL de limage à partir du web",
"LabelInProgress": "En cours",
"LabelIncludeInTracklist": "Inclure dans la liste de lecture",
"LabelIncomplete": "Incomplet",
"LabelInProgress": "En cours",
"LabelInterval": "Intervalle",
"LabelIntervalCustomDailyWeekly": "Personnaliser quotidiennement / hebdomadairement",
"LabelIntervalEvery12Hours": "Toutes les 12 heures",
@ -334,9 +336,10 @@
"LabelIntervalEveryDay": "Tous les jours",
"LabelIntervalEveryHour": "Toutes les heures",
"LabelInvert": "Inverser",
"LabelItem": "Article",
"LabelItem": "Élément",
"LabelLanguage": "Langue",
"LabelLanguageDefaultServer": "Langue par défaut",
"LabelLanguages": "Langues",
"LabelLastBookAdded": "Dernier livre ajouté",
"LabelLastBookUpdated": "Dernier livre mis à jour",
"LabelLastSeen": "Vu dernièrement",
@ -348,28 +351,29 @@
"LabelLess": "Moins",
"LabelLibrariesAccessibleToUser": "Bibliothèque accessible à lutilisateur",
"LabelLibrary": "Bibliothèque",
"LabelLibraryItem": "Article de bibliothèque",
"LabelLibraryFilterSublistEmpty": "Aucun {0}",
"LabelLibraryItem": "Élément de bibliothèque",
"LabelLibraryName": "Nom de la bibliothèque",
"LabelLimit": "Limite",
"LabelLineSpacing": "Interligne",
"LabelLineSpacing": "Espacement des lignes",
"LabelListenAgain": "Écouter à nouveau",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
"LabelLogLevelWarn": "Warn",
"LabelLookForNewEpisodesAfterDate": "Chercher de nouveaux épisode après cette date",
"LabelLookForNewEpisodesAfterDate": "Rechercher les nouveaux épisodes après cette date",
"LabelLowestPriority": "Priorité la plus basse",
"LabelMatchExistingUsersBy": "Faire correspondre les utilisateurs existants par",
"LabelMatchExistingUsersByDescription": "Utilisé pour connecter les utilisateurs existants. Une fois connectés, les utilisateurs seront associés à un identifiant unique provenant de votre fournisseur SSO.",
"LabelMatchExistingUsersBy": "Correspondance avec les utilisateurs existants",
"LabelMatchExistingUsersByDescription": "Utilisé pour connecter les utilisateurs existants. Une fois connectés, les utilisateurs seront associés à un identifiant unique provenant de votre fournisseur SSO",
"LabelMediaPlayer": "Lecteur multimédia",
"LabelMediaType": "Type de média",
"LabelMetadataOrderOfPrecedenceDescription": "Les sources de métadonnées ayant une priorité plus élevée auront la priorité sur celles ayant une priorité moins élevée.",
"LabelMetadataProvider": "Fournisseur de métadonnées",
"LabelMetaTag": "Balise de métadonnée",
"LabelMetaTags": "Balises de métadonnée",
"LabelMetadataOrderOfPrecedenceDescription": "Les sources de métadonnées ayant une priorité plus élevée auront la priorité sur celles ayant une priorité moins élevée",
"LabelMetadataProvider": "Fournisseur de métadonnées",
"LabelMinute": "Minute",
"LabelMissing": "Manquant",
"LabelMissingEbook": "Ne possède pas de livre numérique",
"LabelMissingSupplementaryEbook": "Ne possède pas de livre numérique supplémentaire",
"LabelMissingEbook": "Ne possède aucun livre numérique",
"LabelMissingSupplementaryEbook": "Ne possède aucun livre numérique supplémentaire",
"LabelMobileRedirectURIs": "URI de redirection mobile autorisés",
"LabelMobileRedirectURIsDescription": "Il sagit dune liste blanche dURI de redirection valides pour les applications mobiles. Celui par défaut est <code>audiobookshelf://oauth</code>, que vous pouvez supprimer ou compléter avec des URIs supplémentaires pour lintégration dapplications tierces. Lutilisation dun astérisque (<code>*</code>) comme seule entrée autorise nimporte quel URI.",
"LabelMore": "Plus",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrateur",
"LabelNarrators": "Narrateurs",
"LabelNew": "Nouveau",
"LabelNewPassword": "Nouveau mot de passe",
"LabelNewestAuthors": "Nouveaux auteurs",
"LabelNewestEpisodes": "Derniers épisodes",
"LabelNewPassword": "Nouveau mot de passe",
"LabelNextBackupDate": "Date de la prochaine sauvegarde",
"LabelNextScheduledRun": "Prochain lancement prévu",
"LabelNoCustomMetadataProviders": "Aucun fournisseurs de métadonnées personnalisés",
"LabelNoEpisodesSelected": "Aucun épisode sélectionné",
"LabelNotes": "Notes",
"LabelNotFinished": "Non terminé",
"LabelNotStarted": "Pas commencé",
"LabelNotes": "Notes",
"LabelNotificationAppriseURL": "URL(s) dApprise",
"LabelNotificationAvailableVariables": "Variables disponibles",
"LabelNotificationBodyTemplate": "Modèle de Message",
"LabelNotificationBodyTemplate": "Modèle de message",
"LabelNotificationEvent": "Evènement de Notification",
"LabelNotificationTitleTemplate": "Modèle de titre",
"LabelNotificationsMaxFailedAttempts": "Nombres de tentatives denvoi",
"LabelNotificationsMaxFailedAttemptsHelp": "La notification est abandonnée une fois ce seuil atteint",
"LabelNotificationsMaxQueueSize": "Nombres de notifications maximum à mettre en attente",
"LabelNotificationsMaxQueueSizeHelp": "La limite de notification est de un évènement par seconde. Les notifications seront ignorées si la file dattente est à son maximum. Cela empêche un flot trop important.",
"LabelNotificationTitleTemplate": "Modèle de titre",
"LabelNotStarted": "Pas commencé",
"LabelNumberOfBooks": "Nombre de livres",
"LabelNumberOfEpisodes": "Nombre dépisodes",
"LabelOpenIDAdvancedPermsClaimDescription": "Nom de la demande OpenID qui contient des autorisations avancées pour les actions de lutilisateur dans lapplication, qui sappliqueront à des rôles autres que celui dadministrateur (<b>sil est configuré</b>). Si la demande est absente de la réponse, laccès à ABS sera refusé. Si une seule option est manquante, elle sera considérée comme <code>false</code>. Assurez-vous que la demande du fournisseur didentité correspond à la structure attendue :",
@ -412,14 +417,15 @@
"LabelPermissionsDownload": "Peut télécharger",
"LabelPermissionsUpdate": "Peut mettre à jour",
"LabelPermissionsUpload": "Peut téléverser",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPersonalYearReview": "Bilan de lannée ({0})",
"LabelPhotoPathURL": "Chemin / URL des photos",
"LabelPlaylists": "Listes de lecture",
"LabelPlayMethod": "Méthode découte",
"LabelPlayerChapterNumberMarker": "{0} sur {1}",
"LabelPlaylists": "Listes de lecture",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Région de recherche de podcasts",
"LabelPodcastType": "Type de Podcast",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Préfixes à Ignorer (Insensible à la Casse)",
"LabelPreventIndexing": "Empêcher lindexation de votre flux par les bases de données iTunes et Google podcast",
@ -427,25 +433,26 @@
"LabelProgress": "Progression",
"LabelProvider": "Fournisseur",
"LabelPubDate": "Date de publication",
"LabelPublishYear": "Année de publication",
"LabelPublisher": "Éditeur",
"LabelPublishYear": "Année dédition",
"LabelRead": "Lire",
"LabelReadAgain": "Lire à nouveau",
"LabelReadEbookWithoutProgress": "Lire le livre numérique sans sauvegarder la progression",
"LabelRecentlyAdded": "Derniers ajouts",
"LabelRecentSeries": "Séries récentes",
"LabelRecommended": "Recommandé",
"LabelRedo": "Refaire",
"LabelRegion": "Région",
"LabelReleaseDate": "Date de parution",
"LabelRemoveCover": "Supprimer la couverture",
"LabelRowsPerPage": "Lignes par page",
"LabelPublishers": "Éditeurs",
"LabelRSSFeedCustomOwnerEmail": "Courriel du propriétaire personnalisé",
"LabelRSSFeedCustomOwnerName": "Nom propriétaire personnalisé",
"LabelRSSFeedOpen": "Flux RSS ouvert",
"LabelRSSFeedPreventIndexing": "Empêcher lindexation",
"LabelRSSFeedSlug": "Balise URL du flux RSS",
"LabelRSSFeedURL": "Adresse du flux RSS",
"LabelRead": "Lire",
"LabelReadAgain": "Lire à nouveau",
"LabelReadEbookWithoutProgress": "Lire le livre numérique sans sauvegarder la progression",
"LabelRecentSeries": "Séries récentes",
"LabelRecentlyAdded": "Derniers ajouts",
"LabelRecommended": "Recommandé",
"LabelRedo": "Refaire",
"LabelRegion": "Région",
"LabelReleaseDate": "Date de parution",
"LabelRemoveCover": "Supprimer la couverture",
"LabelRowsPerPage": "Lignes par page",
"LabelSearchTerm": "Terme de recherche",
"LabelSearchTitle": "Titre de recherche",
"LabelSearchTitleOrASIN": "Recherche du titre ou ASIN",
@ -459,26 +466,26 @@
"LabelSeries": "Séries",
"LabelSeriesName": "Nom de la série",
"LabelSeriesProgress": "Progression de séries",
"LabelServerYearReview": "Server Year in Review ({0})",
"LabelServerYearReview": "Bilan de lannée du serveur ({0})",
"LabelSetEbookAsPrimary": "Définir comme principale",
"LabelSetEbookAsSupplementary": "Définir comme supplémentaire",
"LabelSettingsAudiobooksOnly": "Livres audios seulement",
"LabelSettingsAudiobooksOnlyHelp": "Lactivation de ce paramètre ignorera les fichiers de type « livre numériques », sauf sils se trouvent dans un dossier spécifique , auquel cas ils seront définis comme des livres numériques supplémentaires.",
"LabelSettingsAudiobooksOnlyHelp": "Lactivation de ce paramètre ignorera les fichiers de type « livre numériques », sauf sils se trouvent dans un dossier spécifique , auquel cas ils seront définis comme des livres numériques supplémentaires",
"LabelSettingsBookshelfViewHelp": "Interface skeumorphique avec étagères en bois",
"LabelSettingsChromecastSupport": "Support du Chromecast",
"LabelSettingsDateFormat": "Format de date",
"LabelSettingsDisableWatcher": "Désactiver la surveillance",
"LabelSettingsDisableWatcherForLibrary": "Désactiver la surveillance des dossiers pour la bibliothèque",
"LabelSettingsDisableWatcherHelp": "Désactive la mise à jour automatique lorsque des modifications de fichiers sont détectées. * nécessite le redémarrage du serveur",
"LabelSettingsDisableWatcherHelp": "Désactive la mise à jour automatique lorsque des modifications de fichiers sont détectées. * Nécessite le redémarrage du serveur",
"LabelSettingsEnableWatcher": "Activer la veille",
"LabelSettingsEnableWatcherForLibrary": "Activer la surveillance des dossiers pour la bibliothèque",
"LabelSettingsEnableWatcherHelp": "Active la mise à jour automatique automatique lorsque des modifications de fichiers sont détectées. * nécessite le redémarrage du serveur",
"LabelSettingsEnableWatcherHelp": "Active la mise à jour automatique d'éléments lorsque des modifications de fichiers sont détectées. * Nécessite le redémarrage du serveur",
"LabelSettingsEpubsAllowScriptedContent": "Autoriser le contenu scénarisé pour les fichiers EPUB",
"LabelSettingsEpubsAllowScriptedContentHelp": "Autoriser les fichiers EPUB à exécuter des scripts. Il est recommandé de laisser ce paramètre désactivé, sauf si vous faites confiance à la source des fichiers EPUB.",
"LabelSettingsExperimentalFeatures": "Fonctionnalités expérimentales",
"LabelSettingsExperimentalFeaturesHelp": "Fonctionnalités en cours de développement sur lesquelles nous attendons votre retour et expérience. Cliquez pour ouvrir la discussion GitHub.",
"LabelSettingsFindCovers": "Chercher des couvertures de livre",
"LabelSettingsFindCoversHelp": "Si votre livre audio ne possède pas de couverture intégrée ou une image de couverture dans le dossier, lanalyseur tentera de récupérer une couverture.<br>Attention, cela peut augmenter le temps danalyse.",
"LabelSettingsFindCoversHelp": "Si votre livre audio ne possède aucune couverture intégrée ou une image de couverture dans le dossier, lanalyseur tentera de récupérer une couverture.<br>Attention: cela peut augmenter le temps danalyse",
"LabelSettingsHideSingleBookSeries": "Masquer les séries de livres uniques",
"LabelSettingsHideSingleBookSeriesHelp": "Les séries qui ne comportent quun seul livre seront masquées sur la page de la série et sur les étagères de la page daccueil.",
"LabelSettingsHomePageBookshelfView": "Utiliser la vue étagère sur la page daccueil",
@ -488,28 +495,28 @@
"LabelSettingsParseSubtitles": "Analyser les sous-titres",
"LabelSettingsParseSubtitlesHelp": "Extrait les sous-titres depuis le dossier du livre audio.<br>Les sous-titres doivent être séparés par des « - »<br>cest-à-dire : « Titre du livre - Ceci est un sous-titre » aura le sous-titre « Ceci est un sous-titre »",
"LabelSettingsPreferMatchedMetadata": "Préférer les métadonnées par correspondance",
"LabelSettingsPreferMatchedMetadataHelp": "Les métadonnées par correspondance écrase les détails de larticle lors dune recherche par correspondance rapide. Par défaut, la recherche par correspondance rapide ne comblera que les éléments manquant.",
"LabelSettingsPreferMatchedMetadataHelp": "Les métadonnées mises en correspondance remplaceront les détails de lélément lors de lutilisation de la correspondance rapide. Par défaut, la correspondance rapide ne remplira que les détails manquants.",
"LabelSettingsSkipMatchingBooksWithASIN": "Ignorer la recherche par correspondance pour les livres ayant déjà un ASIN",
"LabelSettingsSkipMatchingBooksWithISBN": "Ignorer la recherche par correspondance pour les livres ayant déjà un ISBN",
"LabelSettingsSortingIgnorePrefixes": "Ignorer les préfixes lors du tri",
"LabelSettingsSortingIgnorePrefixesHelp": "cest-à-dire : pour le préfixe « le », le livre avec pour titre « Le Titre du Livre » sera trié en tant que « Titre du Livre, Le »",
"LabelSettingsSquareBookCovers": "Utiliser des couvertures carrées",
"LabelSettingsSquareBookCoversHelp": "Préférer les couvertures carrées par rapport aux couvertures standards de ratio 1.6:1.",
"LabelSettingsStoreCoversWithItem": "Enregistrer la couverture avec les articles",
"LabelSettingsStoreCoversWithItemHelp": "Par défaut, les couvertures sont enregistrées dans /metadata/items. Activer ce paramètre enregistrera les couvertures dans le dossier avec les fichiers de larticle. Seul un fichier nommé « cover » sera conservé.",
"LabelSettingsStoreMetadataWithItem": "Enregistrer les Métadonnées avec les articles",
"LabelSettingsStoreMetadataWithItemHelp": "Par défaut, les métadonnées sont enregistrées dans /metadata/items",
"LabelSettingsSquareBookCoversHelp": "Préférer les couvertures carrées par rapport aux couvertures standards de ratio 1.6:1",
"LabelSettingsStoreCoversWithItem": "Enregistrer la couverture avec les éléments",
"LabelSettingsStoreCoversWithItemHelp": "Par défaut, les couvertures sont enregistrées dans /metadata/items. Activer ce paramètre enregistrera les couvertures dans le dossier avec les fichiers de élément. Seul un fichier nommé « cover » sera conservé",
"LabelSettingsStoreMetadataWithItem": "Enregistrer les métadonnées avec lélément",
"LabelSettingsStoreMetadataWithItemHelp": "Par défaut, les fichiers de métadonnées sont stockés dans /metadata/items. En activant ce paramètre, les fichiers de métadonnées seront stockés dans les dossiers des éléments de votre bibliothèque",
"LabelSettingsTimeFormat": "Format dheure",
"LabelShowAll": "Tout afficher",
"LabelShowSeconds": "Afficher le seondes",
"LabelShowSeconds": "Afficher les seondes",
"LabelSize": "Taille",
"LabelSleepTimer": "Minuterie",
"LabelSleepTimer": "Minuterie de mise en veille",
"LabelSlug": "Balise",
"LabelStart": "Démarrer",
"LabelStartTime": "Heure de démarrage",
"LabelStarted": "Démarré",
"LabelStartedAt": "Démarré à",
"LabelStartTime": "Heure de démarrage",
"LabelStatsAudioTracks": "Pistes Audios",
"LabelStatsAudioTracks": "Pistes audio",
"LabelStatsAuthors": "Auteurs",
"LabelStatsBestDay": "Meilleur jour",
"LabelStatsDailyAverage": "Moyenne journalière",
@ -517,8 +524,8 @@
"LabelStatsDaysListened": "Jours découte",
"LabelStatsHours": "Heures",
"LabelStatsInARow": "daffilée(s)",
"LabelStatsItemsFinished": "Articles terminés",
"LabelStatsItemsInLibrary": "Articles dans la bibliothèque",
"LabelStatsItemsFinished": "Élément(s) terminé(s)",
"LabelStatsItemsInLibrary": "Éléments dans la bibliothèque",
"LabelStatsMinutes": "minutes",
"LabelStatsMinutesListening": "Minutes découte",
"LabelStatsOverallDays": "Nombre total de jours",
@ -564,9 +571,9 @@
"LabelUnknown": "Inconnu",
"LabelUpdateCover": "Mettre à jour la couverture",
"LabelUpdateCoverHelp": "Autoriser la mise à jour de la couverture existante lorsquune correspondance est trouvée",
"LabelUpdatedAt": "Mis à jour à",
"LabelUpdateDetails": "Mettre à jours les détails",
"LabelUpdateDetailsHelp": "Autoriser la mise à jour des détails existants lorsquune correspondance est trouvée",
"LabelUpdatedAt": "Mis à jour à",
"LabelUploaderDragAndDrop": "Glisser et déposer des fichiers ou dossiers",
"LabelUploaderDropFiles": "Déposer des fichiers",
"LabelUploaderItemFetchMetadataHelp": "Récupérer automatiquement le titre, lauteur et la série",
@ -576,7 +583,7 @@
"LabelUsername": "Nom dutilisateur",
"LabelValue": "Valeur",
"LabelVersion": "Version",
"LabelViewBookmarks": "Afficher les signets",
"LabelViewBookmarks": "Afficher les favoris",
"LabelViewChapters": "Afficher les chapitres",
"LabelViewQueue": "Afficher la liste de lecture",
"LabelVolume": "Volume",
@ -584,18 +591,19 @@
"LabelYearReviewHide": "Masquer le bilan de lannée",
"LabelYearReviewShow": "Afficher le bilan de lannée",
"LabelYourAudiobookDuration": "Durée de vos livres audios",
"LabelYourBookmarks": "Vos signets",
"LabelYourBookmarks": "Vos favoris",
"LabelYourPlaylists": "Vos listes de lecture",
"LabelYourProgress": "Votre progression",
"MessageAddToPlayerQueue": "Ajouter en file dattente",
"MessageAppriseDescription": "Nécessite une instance d<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API Apprise</a> pour utiliser cette fonctionnalité ou une api qui prend en charge les mêmes requêtes.<br>LURL de lAPI Apprise doit comprendre le chemin complet pour envoyer la notification. Par exemple, si votre instance écoute sur <code>http://192.168.1.1:8337</code> alors vous devez mettre <code>http://192.168.1.1:8337/notify</code>.",
"MessageBackupsDescription": "Les sauvegardes incluent les utilisateurs, la progression de lecture par utilisateur, les détails des articles des bibliothèques, les paramètres du serveur et les images sauvegardées. Les sauvegardes nincluent pas les fichiers de votre bibliothèque.",
"MessageBatchQuickMatchDescription": "La recherche par correspondance rapide tentera dajouter les couvertures et les métadonnées manquantes pour les articles sélectionnés. Activer loption suivante pour autoriser la recherche par correspondance à écraser les données existantes.",
"MessageAppriseDescription": "Nécessite une instance d<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API Apprise</a> pour utiliser cette fonctionnalité ou une api qui prend en charge les mêmes requêtes.<br />LURL de lAPI Apprise doit comprendre le chemin complet pour envoyer la notification. Par exemple, si votre instance écoute sur <code>http://192.168.1.1:8337</code> alors vous devez mettre <code>http://192.168.1.1:8337/notify</code>.",
"MessageBackupsDescription": "Les sauvegardes incluent les utilisateurs, la progression des utilisateurs, les détails des éléments de la bibliothèque, les paramètres du serveur et les images stockées dans <code>/metadata/items</code> & <code>/metadata/authors</code>. Les sauvegardes <strong>nincluent pas</strong> les fichiers stockés dans les dossiers de votre bibliothèque.",
"MessageBatchQuickMatchDescription": "La recherche par correspondance rapide tentera dajouter les couvertures et métadonnées manquantes pour les éléments sélectionnés. Activez les options ci-dessous pour permettre la Recherche par correspondance décraser les couvertures et/ou métadonnées existantes.",
"MessageBookshelfNoCollections": "Vous navez pas encore de collections",
"MessageBookshelfNoResultsForFilter": "Aucun résultat pour le filtre « {0} : {1} »",
"MessageBookshelfNoRSSFeeds": "Aucun flux RSS nest ouvert",
"MessageBookshelfNoResultsForFilter": "Aucun résultat pour le filtre « {0} : {1} »",
"MessageBookshelfNoResultsForQuery": "Aucun résultat pour la requête",
"MessageBookshelfNoSeries": "Vous navez aucune série",
"MessageChapterEndIsAfter": "La fin du chapitre se situe après la fin de votre livre audio.",
"MessageChapterEndIsAfter": "La fin du chapitre se situe après la fin de votre livre audio",
"MessageChapterErrorFirstNotZero": "Le premier capitre doit débuter à 0",
"MessageChapterErrorStartGteDuration": "Horodatage invalide car il doit débuter avant la fin du livre",
"MessageChapterErrorStartLtPrev": "Horodatage invalide car il doit débuter au moins après le précédent chapitre",
@ -612,25 +620,26 @@
"MessageConfirmMarkAllEpisodesFinished": "Êtes-vous sûr de marquer tous les épisodes comme terminés ?",
"MessageConfirmMarkAllEpisodesNotFinished": "Êtes-vous sûr de vouloir marquer tous les épisodes comme non terminés ?",
"MessageConfirmMarkSeriesFinished": "Êtes-vous sûr de vouloir marquer tous les livres de cette série comme terminées ?",
"MessageConfirmMarkSeriesNotFinished": "Êtes-vous sûr de vouloir marquer tous les livres de cette série comme comme non terminés ?",
"MessageConfirmPurgeCache": "La purge du cache supprimera lintégralité du répertoire à <code>/metadata/cache</code>.<br><br>Êtes-vous sûr de vouloir supprimer le répertoire de cache ?",
"MessageConfirmQuickEmbed": "Attention ! Lintégration rapide ne sauvegardera pas vos fichiers audio. Assurez-vous davoir effectuer une sauvegarde de vos fichiers audio.<br><br>Souhaitez-vous continuer ?",
"MessageConfirmMarkSeriesNotFinished": "Êtes-vous sûr de vouloir marquer tous les livres de cette série comme non terminés?",
"MessageConfirmPurgeCache": "La purge du cache supprimera lintégralité du répertoire à <code>/metadata/cache</code>.<br /><br />Êtes-vous sûr de vouloir supprimer le répertoire de cache?",
"MessageConfirmPurgeItemsCache": "Purger le cache des éléments supprimera l'ensemble du répertoire <code>/metadata/cache/items</code>.<br />Êtes-vous sûr?",
"MessageConfirmQuickEmbed": "Attention ! L'intégration rapide ne permet pas de sauvegarder vos fichiers audio. Assurez-vous davoir effectuer une sauvegarde de vos fichiers audio.<br><br>Souhaitez-vous continuer ?",
"MessageConfirmReScanLibraryItems": "Êtes-vous sûr de vouloir re-analyser {0} éléments ?",
"MessageConfirmRemoveAllChapters": "Êtes-vous sûr de vouloir supprimer tous les chapitres ?",
"MessageConfirmRemoveAuthor": "Êtes-vous sûr de vouloir supprimer lauteur « {0} » ?",
"MessageConfirmRemoveCollection": "Êtes-vous sûr de vouloir supprimer la collection « {0} » ?",
"MessageConfirmRemoveEpisode": "Êtes-vous sûr de vouloir supprimer lépisode « {0} » ?",
"MessageConfirmRemoveEpisodes": "Êtes-vous sûr de vouloir supprimer {0} épisodes ?",
"MessageConfirmRemoveListeningSessions": "Are you sure you want to remove {0} listening sessions?",
"MessageConfirmRemoveListeningSessions": "Êtes-vous sûr de vouloir supprimer {0} sessions découte?",
"MessageConfirmRemoveNarrator": "Êtes-vous sûr de vouloir supprimer le narrateur « {0} » ?",
"MessageConfirmRemovePlaylist": "Êtes-vous sûr de vouloir supprimer la liste de lecture « {0} » ?",
"MessageConfirmRenameGenre": "Êtes-vous sûr de vouloir renommer le genre « {0} » en « {1} » pour tous les articles ?",
"MessageConfirmRenameGenreMergeNote": "Information: Ce genre existe déjà et sera fusionné.",
"MessageConfirmRenameGenre": "Êtes-vous sûr de vouloir renommer le genre « {0} » en « {1} » pour tous les éléments ?",
"MessageConfirmRenameGenreMergeNote": "Information : ce genre existe déjà et sera fusionné.",
"MessageConfirmRenameGenreWarning": "Attention ! Un genre similaire avec une casse différente existe déjà « {0} ».",
"MessageConfirmRenameTag": "Êtes-vous sûr de vouloir renommer létiquette « {0} » en « {1} » pour tous les articles ?",
"MessageConfirmRenameTagMergeNote": "Information: Cette étiquette existe déjà et sera fusionnée.",
"MessageConfirmRenameTag": "Êtes-vous sûr de vouloir renommer létiquette « {0} » en « {1} » pour tous les éléments ?",
"MessageConfirmRenameTagMergeNote": "Information : Cette étiquette existe déjà et sera fusionnée.",
"MessageConfirmRenameTagWarning": "Attention ! Une étiquette similaire avec une casse différente existe déjà « {0} ».",
"MessageConfirmReScanLibraryItems": "Êtes-vous sûr de vouloir re-analyser {0} éléments ?",
"MessageConfirmSendEbookToDevice": "Êtes-vous sûr de vouloir envoyer le livre numérique {0} « {1} » à lappareil « {2} »?",
"MessageConfirmSendEbookToDevice": "Êtes-vous sûr de vouloir envoyer {0} livre numérique « {1} » à l'appareil « {2} » ?",
"MessageDownloadingEpisode": "Téléchargement de lépisode",
"MessageDragFilesIntoTrackOrder": "Faites glisser les fichiers dans lordre correct des pistes",
"MessageEmbedFinished": "Intégration terminée !",
@ -641,16 +650,16 @@
"MessageForceReScanDescription": "analysera de nouveau tous les fichiers. Les étiquettes ID3 des fichiers audio, les fichiers OPF et les fichiers texte seront analysés comme sils étaient nouveaux.",
"MessageImportantNotice": "Information importante !",
"MessageInsertChapterBelow": "Insérer le chapitre ci-dessous",
"MessageItemsSelected": "{0} articles sélectionnés",
"MessageItemsUpdated": "{0} articles mis à jour",
"MessageItemsSelected": "{0} éléments sélectionnés",
"MessageItemsUpdated": "{0} éléments mis à jour",
"MessageJoinUsOn": "Rejoignez-nous sur",
"MessageListeningSessionsInTheLastYear": "{0} sessions découte lan dernier",
"MessageLoading": "Chargement…",
"MessageLoadingFolders": "Chargement des dossiers…",
"MessageLogsDescription": "Les journaux sont stockés dans <code>/metadata/logs</code> sous forme de fichiers JSON. Les journaux dincidents sont stockés dans <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "M4B échec",
"MessageM4BFinished": "M4B terminé",
"MessageMapChapterTitles": "Faire correspondre les titres des chapitres aux chapitres existants de votre livre audio sans ajuster lhorodatage.",
"MessageM4BFailed": "M4B a échoué !",
"MessageM4BFinished": "M4B terminé !",
"MessageMapChapterTitles": "Faire correspondre les titres de chapitres avec ceux de vos livres audio existants sans ajuster les horodatages",
"MessageMarkAllEpisodesFinished": "Marquer tous les épisodes terminés",
"MessageMarkAllEpisodesNotFinished": "Marquer tous les épisodes non terminés",
"MessageMarkAsFinished": "Marquer comme terminé",
@ -659,20 +668,20 @@
"MessageNoAudioTracks": "Aucune piste audio",
"MessageNoAuthors": "Aucun auteur",
"MessageNoBackups": "Aucune sauvegarde",
"MessageNoBookmarks": "Aucun signet",
"MessageNoBookmarks": "Aucun favoris",
"MessageNoChapters": "Aucun chapitre",
"MessageNoCollections": "Aucune collection",
"MessageNoCoversFound": "Aucune couverture trouvée",
"MessageNoDescription": "Aucune description",
"MessageNoDownloadsInProgress": "Aucun téléchargement en cours",
"MessageNoDownloadsQueued": "Aucun téléchargement en file dattente",
"MessageNoDownloadsQueued": "Aucun téléchargement en attente",
"MessageNoEpisodeMatchesFound": "Aucune correspondance dépisode trouvée",
"MessageNoEpisodes": "Aucun épisode",
"MessageNoFoldersAvailable": "Aucun dossier disponible",
"MessageNoFoldersAvailable": "Aucun dossiers disponible",
"MessageNoGenres": "Aucun genre",
"MessageNoIssues": "Aucune parution",
"MessageNoItems": "Aucun article",
"MessageNoItemsFound": "Aucun article trouvé",
"MessageNoItems": "Aucun élément",
"MessageNoItemsFound": "Aucun élément trouvé",
"MessageNoListeningSessions": "Aucune session découte en cours",
"MessageNoLogs": "Aucun journaux",
"MessageNoMediaProgress": "Aucun média en cours",
@ -681,12 +690,12 @@
"MessageNoResults": "Aucun résultat",
"MessageNoSearchResultsFor": "Aucun résultat pour la recherche « {0} »",
"MessageNoSeries": "Aucune série",
"MessageNoTags": "Aucune détiquettes",
"MessageNoTags": "Aucune étiquette",
"MessageNoTasksRunning": "Aucune tâche en cours",
"MessageNotYetImplemented": "Non implémenté",
"MessageNoUpdateNecessary": "Aucune mise à jour nécessaire",
"MessageNoUpdatesWereNecessary": "Aucune mise à jour nétait nécessaire",
"MessageNoUserPlaylists": "Vous navez aucune liste de lecture",
"MessageNotYetImplemented": "Non implémenté",
"MessageOr": "ou",
"MessagePauseChapter": "Suspendre la lecture du chapitre",
"MessagePlayChapter": "Écouter depuis le début du chapitre",
@ -718,7 +727,7 @@
"NoteChangeRootPassword": "seul lutilisateur « root » peut utiliser un mot de passe vide",
"NoteChapterEditorTimes": "Information : lhorodatage du premier chapitre doit être à 0:00 et celui du dernier chapitre ne peut se situer au-delà de la durée du livre audio.",
"NoteFolderPicker": "Information : les dossiers déjà surveillés ne sont pas affichés",
"NoteRSSFeedPodcastAppsHttps": "Attention : la majorité des application de podcast nécessite une adresse de flux en HTTPS.",
"NoteRSSFeedPodcastAppsHttps": "Attention: la majorité des application de podcast nécessite une adresse de flux HTTPS",
"NoteRSSFeedPodcastAppsPubDate": "Attention : un ou plusieurs de vos épisodes ne possèdent pas de date de publication. Certaines applications de podcast le requièrent.",
"NoteUploaderFoldersWithMediaFiles": "Les dossiers contenant des fichiers multimédias seront traités comme des éléments distincts de la bibliothèque.",
"NoteUploaderOnlyAudioFiles": "Si vous téléversez uniquement des fichiers audio, chaque fichier audio sera traité comme un livre audio distinct.",
@ -755,8 +764,8 @@
"ToastCachePurgeSuccess": "Cache purgé avec succès",
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
"ToastChaptersMustHaveTitles": "Les chapitre doivent avoir un titre",
"ToastCollectionItemsRemoveFailed": "Échec de la suppression de(s) article(s) de la collection",
"ToastCollectionItemsRemoveSuccess": "Article(s) supprimé(s) de la collection",
"ToastCollectionItemsRemoveFailed": "Échec de la suppression dun ou plusieurs éléments de la collection",
"ToastCollectionItemsRemoveSuccess": "Élément(s) supprimé(s) de la collection",
"ToastCollectionRemoveFailed": "Échec de la suppression de la collection",
"ToastCollectionRemoveSuccess": "Collection supprimée",
"ToastCollectionUpdateFailed": "Échec de la mise à jour de la collection",
@ -764,11 +773,11 @@
"ToastDeleteFileFailed": "Échec de la suppression du fichier",
"ToastDeleteFileSuccess": "Fichier supprimé",
"ToastFailedToLoadData": "Échec du chargement des données",
"ToastItemCoverUpdateFailed": "Échec de la mise à jour de la couverture de larticle",
"ToastItemCoverUpdateSuccess": "Couverture de larticle mise à jour",
"ToastItemDetailsUpdateFailed": "Échec de la mise à jour des détails de larticle",
"ToastItemDetailsUpdateSuccess": "Détails de larticle mis à jour",
"ToastItemDetailsUpdateUnneeded": "Pas de mise à jour nécessaire sur les détails de larticle",
"ToastItemCoverUpdateFailed": "Échec de la mise à jour de la couverture de lélément",
"ToastItemCoverUpdateSuccess": "Couverture mise à jour",
"ToastItemDetailsUpdateFailed": "Échec de la mise à jour des détails de lélément",
"ToastItemDetailsUpdateSuccess": "Détails de lélément mis à jour",
"ToastItemDetailsUpdateUnneeded": "Aucune mise à jour nest nécessaire pour les détails de lélément",
"ToastItemMarkedAsFinishedFailed": "Échec de lannotation terminée",
"ToastItemMarkedAsFinishedSuccess": "Article marqué comme terminé",
"ToastItemMarkedAsNotFinishedFailed": "Échec de lannotation non-terminée",
@ -787,12 +796,12 @@
"ToastPlaylistRemoveSuccess": "Liste de lecture supprimée",
"ToastPlaylistUpdateFailed": "Échec de la mise à jour de la liste de lecture",
"ToastPlaylistUpdateSuccess": "Liste de lecture mise à jour",
"ToastPodcastCreateFailed": "Échec de la création du Podcast",
"ToastPodcastCreateSuccess": "Podcast créé",
"ToastRemoveItemFromCollectionFailed": "Échec de la suppression de larticle de la collection",
"ToastRemoveItemFromCollectionSuccess": "Article supprimé de la collection",
"ToastPodcastCreateFailed": "Échec de la création du podcast",
"ToastPodcastCreateSuccess": "Podcast créé avec succès",
"ToastRSSFeedCloseFailed": "Échec de la fermeture du flux RSS",
"ToastRSSFeedCloseSuccess": "Flux RSS fermé",
"ToastRemoveItemFromCollectionFailed": "Échec de la suppression dun élément de la collection",
"ToastRemoveItemFromCollectionSuccess": "Élément supprimé de la collection",
"ToastSendEbookToDeviceFailed": "Échec de lenvoi du livre numérique à lappareil",
"ToastSendEbookToDeviceSuccess": "Livre numérique envoyé à lappareil : {0}",
"ToastSeriesUpdateFailed": "Échec de la mise à jour de la série",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Mise à jour des préfixes de tri ({0} élément)",
"ToastUserDeleteFailed": "Échec de la suppression de lutilisateur",
"ToastUserDeleteSuccess": "Utilisateur supprimé"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "લાગુ કરો",
"ButtonApplyChapters": "પ્રકરણો લાગુ કરો",
"ButtonAuthors": "લેખકો",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "ફોલ્ડર માટે જુઓ",
"ButtonCancel": "રદ કરો",
"ButtonCancelEncode": "એન્કોડ રદ કરો",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "બધો Cache કાઢી નાખો",
"ButtonPurgeItemsCache": "વસ્તુઓનો Cache કાઢી નાખો",
"ButtonPurgeMediaProgress": "બધું સાંભળ્યું કાઢી નાખો",
"ButtonQueueAddItem": "કતારમાં ઉમેરો",
"ButtonQueueRemoveItem": "કતારથી કાઢી નાખો",
"ButtonQuickMatch": "ઝડપી મેળ ખવડાવો",
"ButtonReScan": "ફરીથી સ્કેન કરો",
"ButtonRead": "વાંચો",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "સાંભળતી પુસ્તકો માંથી કાઢી નાખો",
"ButtonRemoveFromContinueReading": "સાંભળતી પુસ્તકો માંથી કાઢી નાખો",
"ButtonRemoveSeriesFromContinueSeries": "સાંભળતી સિરીઝ માંથી કાઢી નાખો",
"ButtonReScan": "ફરીથી સ્કેન કરો",
"ButtonReset": "રીસેટ કરો",
"ButtonResetToDefault": "ડિફોલ્ટ પર રીસેટ કરો",
"ButtonRestore": "પુનઃસ્થાપિત કરો",
@ -104,8 +104,8 @@
"HeaderAccount": "એકાઉન્ટ",
"HeaderAdvanced": "અડ્વાન્સડ",
"HeaderAppriseNotificationSettings": "Apprise સૂચના સેટિંગ્સ",
"HeaderAudiobookTools": "ઓડિયોબુક ફાઇલ વ્યવસ્થાપન ટૂલ્સ",
"HeaderAudioTracks": "ઓડિયો ટ્રેક્સ",
"HeaderAudiobookTools": "ઓડિયોબુક ફાઇલ વ્યવસ્થાપન ટૂલ્સ",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "બેકઅપ્સ",
"HeaderChangePassword": "પાસવર્ડ બદલો",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "સંગ્રહ વસ્તુઓ",
"HeaderCover": "આવરણ",
"HeaderCurrentDownloads": "વર્તમાન ડાઉનલોડ્સ",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "વિગતો",
"HeaderDownloadQueue": "ડાઉનલોડ કતાર",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "પ્લેલિસ્ટ ની વસ્તુઓ",
"HeaderPodcastsToAdd": "ઉમેરવા માટે પોડકાસ્ટ્સ",
"HeaderPreviewCover": "પૂર્વાવલોકન કવર",
"HeaderRemoveEpisode": "એપિસોડ કાઢી નાખો",
"HeaderRemoveEpisodes": "{0} એપિસોડ્સ કાઢી નાખો",
"HeaderRSSFeedGeneral": "સામાન્ય RSS ફીડ",
"HeaderRSSFeedIsOpen": "RSS ફીડ ખોલેલી છે",
"HeaderRSSFeeds": "RSS ફીડ્સ",
"HeaderRemoveEpisode": "એપિસોડ કાઢી નાખો",
"HeaderRemoveEpisodes": "{0} એપિસોડ્સ કાઢી નાખો",
"HeaderSavedMediaProgress": "સાચવેલ મીડિયા પ્રગતિ",
"HeaderSchedule": "સમયપત્રક",
"HeaderScheduleLibraryScans": "પુસ્તકાલય સ્કેન સમયપત્રક",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Guest",
"LabelAccountTypeUser": "User",
"LabelActivity": "Activity",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAddToCollection": "Add to Collection",
"LabelAddToCollectionBatch": "Add {0} Books to Collection",
"LabelAddToPlaylist": "Add to Playlist",
"LabelAddToPlaylistBatch": "Add {0} Items to Playlist",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "All",
"LabelAllUsers": "All Users",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Change Password",
"LabelChannels": "Channels",
"LabelChapterTitle": "Chapter Title",
"LabelChapters": "Chapters",
"LabelChaptersFound": "chapters found",
"LabelChapterTitle": "Chapter Title",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Folder",
"LabelFolders": "Folders",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "ફોન્ટ કુટુંબ",
"LabelFontItalic": "Italic",
"LabelFontScale": "Font scale",
@ -321,9 +323,9 @@
"LabelHour": "Hour",
"LabelIcon": "Icon",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "In Progress",
"LabelIncludeInTracklist": "Include in Tracklist",
"LabelIncomplete": "Incomplete",
"LabelInProgress": "In Progress",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Custom daily/weekly",
"LabelIntervalEvery12Hours": "Every 12 hours",
@ -337,6 +339,7 @@
"LabelItem": "Item",
"LabelLanguage": "Language",
"LabelLanguageDefaultServer": "Default Server Language",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastSeen": "Last Seen",
@ -348,6 +351,7 @@
"LabelLess": "Less",
"LabelLibrariesAccessibleToUser": "Libraries Accessible to User",
"LabelLibrary": "Library",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLimit": "Limit",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Media Player",
"LabelMediaType": "Media Type",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Provider",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Provider",
"LabelMinute": "Minute",
"LabelMissing": "Missing",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrator",
"LabelNarrators": "Narrators",
"LabelNew": "New",
"LabelNewPassword": "New Password",
"LabelNewestAuthors": "Newest Authors",
"LabelNewestEpisodes": "Newest Episodes",
"LabelNewPassword": "New Password",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notes",
"LabelNotFinished": "Not Finished",
"LabelNotStarted": "Not Started",
"LabelNotes": "Notes",
"LabelNotificationAppriseURL": "Apprise URL(s)",
"LabelNotificationAvailableVariables": "Available variables",
"LabelNotificationBodyTemplate": "Body Template",
"LabelNotificationEvent": "Notification Event",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotificationsMaxFailedAttempts": "Max failed attempts",
"LabelNotificationsMaxFailedAttemptsHelp": "Notifications are disabled once they fail to send this many times",
"LabelNotificationsMaxQueueSize": "Max queue size for notification events",
"LabelNotificationsMaxQueueSizeHelp": "Events are limited to firing 1 per second. Events will be ignored if the queue is at max size. This prevents notification spamming.",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotStarted": "Not Started",
"LabelNumberOfBooks": "Number of Books",
"LabelNumberOfEpisodes": "# of Episodes",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Can Upload",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Photo Path/URL",
"LabelPlaylists": "Playlists",
"LabelPlayMethod": "Play Method",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Playlists",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "પોડકાસ્ટ શોધ પ્રદેશ",
"LabelPodcastType": "Podcast Type",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
"LabelPreventIndexing": "Prevent your feed from being indexed by iTunes and Google podcast directories",
@ -427,25 +433,26 @@
"LabelProgress": "Progress",
"LabelProvider": "Provider",
"LabelPubDate": "Pub Date",
"LabelPublisher": "Publisher",
"LabelPublishYear": "Publish Year",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentlyAdded": "Recently Added",
"LabelRecentSeries": "Recent Series",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Release Date",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Publisher",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Custom owner Email",
"LabelRSSFeedCustomOwnerName": "Custom owner Name",
"LabelRSSFeedOpen": "RSS Feed Open",
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentSeries": "Recent Series",
"LabelRecentlyAdded": "Recently Added",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Release Date",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Search Term",
"LabelSearchTitle": "Search Title",
"LabelSearchTitleOrASIN": "Search Title or ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Start Time",
"LabelStarted": "Started",
"LabelStartedAt": "Started At",
"LabelStartTime": "Start Time",
"LabelStatsAudioTracks": "Audio Tracks",
"LabelStatsAuthors": "Authors",
"LabelStatsBestDay": "Best Day",
@ -564,9 +571,9 @@
"LabelUnknown": "Unknown",
"LabelUpdateCover": "Update Cover",
"LabelUpdateCoverHelp": "Allow overwriting of existing covers for the selected books when a match is located",
"LabelUpdatedAt": "Updated At",
"LabelUpdateDetails": "Update Details",
"LabelUpdateDetailsHelp": "Allow overwriting of existing details for the selected books when a match is located",
"LabelUpdatedAt": "Updated At",
"LabelUploaderDragAndDrop": "Drag & drop files or folders",
"LabelUploaderDropFiles": "Drop files",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"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.",
"MessageBatchQuickMatchDescription": "Quick Match will attempt to add missing covers and metadata for the selected items. Enable the options below to allow Quick Match to overwrite existing covers and/or metadata.",
"MessageBookshelfNoCollections": "You haven't made any collections yet",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "No RSS feeds are open",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "You have no series",
"MessageChapterEndIsAfter": "Chapter end is after the end of your audiobook",
"MessageChapterErrorFirstNotZero": "First chapter must start at 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Are you sure you want to rename tag \"{0}\" to \"{1}\" for all items?",
"MessageConfirmRenameTagMergeNote": "Note: This tag already exists so they will be merged.",
"MessageConfirmRenameTagWarning": "Warning! A similar tag with a different casing already exists \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageDownloadingEpisode": "Downloading episode",
"MessageDragFilesIntoTrackOrder": "Drag files into correct track order",
@ -683,10 +692,10 @@
"MessageNoSeries": "No Series",
"MessageNoTags": "No Tags",
"MessageNoTasksRunning": "No Tasks Running",
"MessageNotYetImplemented": "Not yet implemented",
"MessageNoUpdateNecessary": "No update necessary",
"MessageNoUpdatesWereNecessary": "No updates were necessary",
"MessageNoUserPlaylists": "You have no playlists",
"MessageNotYetImplemented": "Not yet implemented",
"MessageOr": "or",
"MessagePauseChapter": "Pause chapter playback",
"MessagePlayChapter": "Listen to beginning of chapter",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Playlist updated",
"ToastPodcastCreateFailed": "Failed to create podcast",
"ToastPodcastCreateSuccess": "Podcast created successfully",
"ToastRemoveItemFromCollectionFailed": "Failed to remove item from collection",
"ToastRemoveItemFromCollectionSuccess": "Item removed from collection",
"ToastRSSFeedCloseFailed": "Failed to close RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed closed",
"ToastRemoveItemFromCollectionFailed": "Failed to remove item from collection",
"ToastRemoveItemFromCollectionSuccess": "Item removed from collection",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSeriesUpdateFailed": "Series update failed",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Failed to delete user",
"ToastUserDeleteSuccess": "User deleted"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "החל",
"ButtonApplyChapters": "החל פרקים",
"ButtonAuthors": "יוצרים",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "עיין בתיקייה",
"ButtonCancel": "בטל",
"ButtonCancelEncode": "בטל קידוד",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "פרק קודם",
"ButtonPurgeAllCache": "נקה את כל המטמון",
"ButtonPurgeItemsCache": "נקה את מטמון הפריטים",
"ButtonPurgeMediaProgress": "נקה את ההתקדמות במדיה",
"ButtonQueueAddItem": "הוסף לתור",
"ButtonQueueRemoveItem": "הסר מהתור",
"ButtonQuickMatch": "התאמה מהירה",
"ButtonReScan": "סרוק מחדש",
"ButtonRead": "קרא",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "הסר מ- המשך האזנה",
"ButtonRemoveFromContinueReading": "הסר מ- המשך קריאה",
"ButtonRemoveSeriesFromContinueSeries": "הסר סדרה מ- המשך סדרה",
"ButtonReScan": "סרוק מחדש",
"ButtonReset": "איפוס",
"ButtonResetToDefault": "איפוס לברירת המחדל",
"ButtonRestore": "שחזר",
@ -104,8 +104,8 @@
"HeaderAccount": "חשבון",
"HeaderAdvanced": "מתקדם",
"HeaderAppriseNotificationSettings": "הגדרות התראות של Apprise",
"HeaderAudiobookTools": "כלים לניהול קבצי ספרים קוליים",
"HeaderAudioTracks": "רצועות קול",
"HeaderAudiobookTools": "כלים לניהול קבצי ספרים קוליים",
"HeaderAuthentication": "אימות",
"HeaderBackups": "גיבויים",
"HeaderChangePassword": "שנה סיסמה",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "פריטי אוסף",
"HeaderCover": "כריכה",
"HeaderCurrentDownloads": "הורדות נוכחיות",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "ספקי מטא-נתונים מותאמים אישית",
"HeaderDetails": "פרטים",
"HeaderDownloadQueue": "תור הורדה",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "פריטי רשימת השמעה",
"HeaderPodcastsToAdd": "פודקאסטים להוספה",
"HeaderPreviewCover": "תצוגה מקדימה של כריכה",
"HeaderRemoveEpisode": "הסר פרק",
"HeaderRemoveEpisodes": "הסר {0} פרקים",
"HeaderRSSFeedGeneral": "פרטי ערוץ RSS",
"HeaderRSSFeedIsOpen": "ערוץ RSS פתוח",
"HeaderRSSFeeds": "ערוצי RSS",
"HeaderRemoveEpisode": "הסר פרק",
"HeaderRemoveEpisodes": "הסר {0} פרקים",
"HeaderSavedMediaProgress": "התקדמות מדיה שמורה",
"HeaderSchedule": "תיזמון",
"HeaderScheduleLibraryScans": "קבע סריקות ספרייה אוטומטיות",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "אורח",
"LabelAccountTypeUser": "משתמש",
"LabelActivity": "פעילות",
"LabelAdded": "נוסף",
"LabelAddedAt": "נוסף בתאריך",
"LabelAddToCollection": "הוסף לאוסף",
"LabelAddToCollectionBatch": "הוסף {0} ספרים לאוסף",
"LabelAddToPlaylist": "הוסף לרשימת השמעה",
"LabelAddToPlaylistBatch": "הוסף {0} פריטים לרשימת השמעה",
"LabelAdded": "נוסף",
"LabelAddedAt": "נוסף בתאריך",
"LabelAdminUsersOnly": "רק מנהלים",
"LabelAll": "הכל",
"LabelAllUsers": "כל המשתמשים",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "שינוי סיסמה",
"LabelChannels": "ערוצים",
"LabelChapterTitle": "כותרת הפרק",
"LabelChapters": "פרקים",
"LabelChaptersFound": "פרקים שנמצאו",
"LabelChapterTitle": "כותרת הפרק",
"LabelClickForMoreInfo": "לחץ למידע נוסף",
"LabelClosePlayer": "סגור נגן",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "תיקייה",
"LabelFolders": "תיקיות",
"LabelFontBold": "מודגש",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "משפחת הפונטים",
"LabelFontItalic": "נטוי",
"LabelFontScale": "קנה מידה של הפונט",
@ -321,9 +323,9 @@
"LabelHour": "שעה",
"LabelIcon": "סמל",
"LabelImageURLFromTheWeb": "כתובת התמונה מהרשת",
"LabelInProgress": "בתהליך",
"LabelIncludeInTracklist": "כלול ברשימת השמעה",
"LabelIncomplete": "לא הושלם",
"LabelInProgress": "בתהליך",
"LabelInterval": "מרווח",
"LabelIntervalCustomDailyWeekly": "מותאם אישית יומי/שבועי",
"LabelIntervalEvery12Hours": "כל 12 שעות",
@ -337,6 +339,7 @@
"LabelItem": "פריט",
"LabelLanguage": "שפה",
"LabelLanguageDefaultServer": "שפת ברירת המחדל של השרת",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "הספר האחרון שנוסף",
"LabelLastBookUpdated": "הספר האחרון שעודכן",
"LabelLastSeen": "נראה לאחרונה",
@ -348,6 +351,7 @@
"LabelLess": "פחות",
"LabelLibrariesAccessibleToUser": "ספריות נגישות למשתמש",
"LabelLibrary": "ספרייה",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "פריט ספרייה",
"LabelLibraryName": "שם הספרייה",
"LabelLimit": "מגבלה",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "משמש לחיבור משתמשים קיימים. לאחר החיבור, המשתמשים יותאמו לפי זיהוי ייחודי מספק ה-SSO שלך",
"LabelMediaPlayer": "נגן מדיה",
"LabelMediaType": "סוג מדיה",
"LabelMetadataOrderOfPrecedenceDescription": "מקורות המטא-נתונים עם עדיפות גבוהה יחליפו מקורות עם עדיפות נמוכה יותר",
"LabelMetadataProvider": "ספק מטא-נתונים",
"LabelMetaTag": "תג מטא",
"LabelMetaTags": "תגי מטא",
"LabelMetadataOrderOfPrecedenceDescription": "מקורות המטא-נתונים עם עדיפות גבוהה יחליפו מקורות עם עדיפות נמוכה יותר",
"LabelMetadataProvider": "ספק מטא-נתונים",
"LabelMinute": "דקה",
"LabelMissing": "חסר",
"LabelMissingEbook": "אין ספר אלקטרוני",
@ -378,24 +382,25 @@
"LabelNarrator": "מספר",
"LabelNarrators": "מספרים",
"LabelNew": "חדש",
"LabelNewPassword": "סיסמה חדשה",
"LabelNewestAuthors": "הסופרים החדשים ביותר",
"LabelNewestEpisodes": "הפרקים החדשים ביותר",
"LabelNewPassword": "סיסמה חדשה",
"LabelNextBackupDate": "תאריך הגיבוי הבא",
"LabelNextScheduledRun": "הרצה מתוזמנת הבאה",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "לא נבחרו פרקים",
"LabelNotes": "הערות",
"LabelNotFinished": "לא הושלם",
"LabelNotStarted": "לא התחיל",
"LabelNotes": "הערות",
"LabelNotificationAppriseURL": "כתובות Apprise",
"LabelNotificationAvailableVariables": "משתנים זמינים",
"LabelNotificationBodyTemplate": "תבנית גוף",
"LabelNotificationEvent": "אירוע התראה",
"LabelNotificationTitleTemplate": "תבנית כותרת",
"LabelNotificationsMaxFailedAttempts": "מספר הניסיונות הנכשלים המרבי",
"LabelNotificationsMaxFailedAttemptsHelp": "ההתראות מושבתות לאחר שהן נכשלות לשלוח מספר פעמים זה",
"LabelNotificationsMaxQueueSize": "גודל התור המרבי לאירועי התראה",
"LabelNotificationsMaxQueueSizeHelp": "האירועים מוגבלים לשליחה אחת לשנייה. האירועים יתעלמו אם התור מלא. הגדרה זו נועדה למנוע ספאם התראות.",
"LabelNotificationTitleTemplate": "תבנית כותרת",
"LabelNotStarted": "לא התחיל",
"LabelNumberOfBooks": "מספר הספרים",
"LabelNumberOfEpisodes": "מספר הפרקים",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "מותר להעלות",
"LabelPersonalYearReview": "השנה שלך בסקירה ({0})",
"LabelPhotoPathURL": "נתיב/URL לתמונה",
"LabelPlaylists": "רשימות השמעה",
"LabelPlayMethod": "שיטת הפעלה",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "רשימות השמעה",
"LabelPodcast": "פודקאסט",
"LabelPodcasts": "פודקאסטים",
"LabelPodcastSearchRegion": "אזור חיפוש פודקאסט",
"LabelPodcastType": "סוג פודקאסט",
"LabelPodcasts": "פודקאסטים",
"LabelPort": "פורט",
"LabelPrefixesToIgnore": "קידומות להתעלמות (מתעלם מאותיות גדולות/קטנות)",
"LabelPreventIndexing": "מנע רישום של הערוץ שלך על ידי ספריות אייטונס וגוגל פודקאסט",
@ -427,25 +433,26 @@
"LabelProgress": "התקדמות",
"LabelProvider": "ספק",
"LabelPubDate": "תאריך פרסום",
"LabelPublisher": "מוציא לאור",
"LabelPublishYear": "שנת הפרסום",
"LabelRead": "קריאה",
"LabelReadAgain": "קרא שוב",
"LabelReadEbookWithoutProgress": "קרא/י ספר אלקטרוני ללא שמירת התקדמות",
"LabelRecentlyAdded": "נוסף לאחרונה",
"LabelRecentSeries": "סדרות אחרונות",
"LabelRecommended": "מומלץ",
"LabelRedo": "עשה שוב",
"LabelRegion": "אזור",
"LabelReleaseDate": "תאריך הוצאה לאור",
"LabelRemoveCover": "הסר כריכה",
"LabelRowsPerPage": "שורות לעמוד",
"LabelPublisher": "מוציא לאור",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "אימייל בעלים מותאם אישית",
"LabelRSSFeedCustomOwnerName": "שם בעלים מותאם אישית",
"LabelRSSFeedOpen": "פתח ערוץ RSS",
"LabelRSSFeedPreventIndexing": "מנע רישום",
"LabelRSSFeedSlug": "Slug של ערוץ ה-RSS",
"LabelRSSFeedURL": "כתובת ערוץ ה-RSS",
"LabelRead": "קריאה",
"LabelReadAgain": "קרא שוב",
"LabelReadEbookWithoutProgress": "קרא/י ספר אלקטרוני ללא שמירת התקדמות",
"LabelRecentSeries": "סדרות אחרונות",
"LabelRecentlyAdded": "נוסף לאחרונה",
"LabelRecommended": "מומלץ",
"LabelRedo": "עשה שוב",
"LabelRegion": "אזור",
"LabelReleaseDate": "תאריך הוצאה לאור",
"LabelRemoveCover": "הסר כריכה",
"LabelRowsPerPage": "שורות לעמוד",
"LabelSearchTerm": "מונח חיפוש",
"LabelSearchTitle": "כותרת חיפוש",
"LabelSearchTitleOrASIN": "כותרת חיפוש או ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "טיימר שינה",
"LabelSlug": "Slug",
"LabelStart": "התחלה",
"LabelStartTime": "זמן התחלה",
"LabelStarted": "התחיל",
"LabelStartedAt": "התחיל ב",
"LabelStartTime": "זמן התחלה",
"LabelStatsAudioTracks": "רצועות שמע",
"LabelStatsAuthors": "מחברים",
"LabelStatsBestDay": "היום הטוב ביותר",
@ -564,9 +571,9 @@
"LabelUnknown": "לא ידוע",
"LabelUpdateCover": "עדכן כריכה",
"LabelUpdateCoverHelp": "אפשר החלפה של כריכות קיימות עבור הספרים הנבחרים כאשר נמצאה התאמה",
"LabelUpdatedAt": "עודכן ב-",
"LabelUpdateDetails": "עדכון פרטים",
"LabelUpdateDetailsHelp": "אפשר החלפה של פרטים קיימים עבור הספרים הנבחרים כאשר נמצאה התאמה",
"LabelUpdatedAt": "עודכן ב-",
"LabelUploaderDragAndDrop": "גרור ושחרר קבצים או תיקיות",
"LabelUploaderDropFiles": "שחרר קבצים",
"LabelUploaderItemFetchMetadataHelp": "משיכת כותרת, סופר וסדרה באופן אוטומטי",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "גיבויים כוללים משתמשים, התקדמות משתמש, פרטי פריטי ספרייה, הגדרות שרת ותמונות השמורות ב-<code>/metadata/items</code> & <code>/metadata/authors</code>. גיבויים <strong>לא</strong> כוללים קבצים שמורים בתיקיות הספרייה שלך.",
"MessageBatchQuickMatchDescription": "התאמה מהירה תנסה להוסיף כריכות ומטה-נתונים חסרים עבור הפריטים הנבחרים. הפעל את האפשרויות למטה כדי לאפשר להתאמה מהירה להחליף כריכות קיימות ו/או מטה-נתונים.",
"MessageBookshelfNoCollections": "עדיין לא יצרת אוספים",
"MessageBookshelfNoResultsForFilter": "אין תוצאות עבור סינון \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "אין ערוצי RSS פתוחים",
"MessageBookshelfNoResultsForFilter": "אין תוצאות עבור סינון \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "אין לך סדרות",
"MessageChapterEndIsAfter": "זמן סיום הפרק אחרי סיום הספר הקולי שלך",
"MessageChapterErrorFirstNotZero": "הפרק הראשון חייב להתחיל ב-0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "האם אתה בטוח שברצונך לסמן את כל הספרים בסדרה זו כהסתיימו?",
"MessageConfirmMarkSeriesNotFinished": "האם אתה בטוח שברצונך לסמן את כל הספרים בסדרה זו כלא הסתיימו?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "אזהרה! הטמעה מהירה לא תגבה גיבוי של קבצי האודיו שלך. וודא שיש לך גיבוי של קבצי האודיו שלך. <br><br>האם ברצונך להמשיך?",
"MessageConfirmReScanLibraryItems": "האם אתה בטוח שברצונך לסרוק מחדש {0} פריטים?",
"MessageConfirmRemoveAllChapters": "האם אתה בטוח שברצונך להסיר את כל הפרקים?",
"MessageConfirmRemoveAuthor": "האם אתה בטוח שברצונך להסיר את המחבר \"{0}\"?",
"MessageConfirmRemoveCollection": "האם אתה בטוח שברצונך להסיר אוסף \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "האם אתה בטוח שברצונך לשנות את שם התג \"{0}\" ל \"{1}\" עבור כל הפריטים?",
"MessageConfirmRenameTagMergeNote": "הערה: התג זה כבר קיים ולכן הם יתמזגו.",
"MessageConfirmRenameTagWarning": "אזהרה! יש תג דומה עם רישום שונה שכבר קיים \"{0}\".",
"MessageConfirmReScanLibraryItems": "האם אתה בטוח שברצונך לסרוק מחדש {0} פריטים?",
"MessageConfirmSendEbookToDevice": "האם אתה בטוח שברצונך לשלוח {0} את הספר האלקטרוני \"{1}\" למכשיר \"{2}\"?",
"MessageDownloadingEpisode": "מוריד פרק",
"MessageDragFilesIntoTrackOrder": "גרור קבצים לסדר ההשמעה נכון",
@ -683,10 +692,10 @@
"MessageNoSeries": "אין סדרות",
"MessageNoTags": "אין תגיות",
"MessageNoTasksRunning": "אין משימות פעילות",
"MessageNotYetImplemented": "עדיין לא מיושם",
"MessageNoUpdateNecessary": "לא נדרש עדכון",
"MessageNoUpdatesWereNecessary": "לא היה צורך בעדכונים",
"MessageNoUserPlaylists": "אין לך רשימות השמעה",
"MessageNotYetImplemented": "עדיין לא מיושם",
"MessageOr": "או",
"MessagePauseChapter": "השהה השמעת הפרק",
"MessagePlayChapter": "הקשב לתחילת הפרק",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "רשימת השמעה עודכנה בהצלחה",
"ToastPodcastCreateFailed": "יצירת הפודקאסט נכשלה",
"ToastPodcastCreateSuccess": "הפודקאסט נוצר בהצלחה",
"ToastRemoveItemFromCollectionFailed": "הסרת הפריט מהאוסף נכשלה",
"ToastRemoveItemFromCollectionSuccess": "הפריט הוסר מהאוסף בהצלחה",
"ToastRSSFeedCloseFailed": "סגירת ערוץ ה-RSS נכשלה",
"ToastRSSFeedCloseSuccess": "ערוץ ה-RSS נסגר בהצלחה",
"ToastRemoveItemFromCollectionFailed": "הסרת הפריט מהאוסף נכשלה",
"ToastRemoveItemFromCollectionSuccess": "הפריט הוסר מהאוסף בהצלחה",
"ToastSendEbookToDeviceFailed": "שליחת הספר אל המכשיר נכשלה",
"ToastSendEbookToDeviceSuccess": "הספר נשלח אל המכשיר \"{0}\"",
"ToastSeriesUpdateFailed": "עדכון הסדרה נכשל",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "מחיקת המשתמש נכשלה",
"ToastUserDeleteSuccess": "המשתמש נמחק בהצלחה"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "लागू करें",
"ButtonApplyChapters": "अध्यायों में परिवर्तन लागू करें",
"ButtonAuthors": "लेखक",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "फ़ोल्डर खोजें",
"ButtonCancel": "रद्द करें",
"ButtonCancelEncode": "एनकोड रद्द करें",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "सभी Cache मिटाएं",
"ButtonPurgeItemsCache": "आइटम Cache मिटाएं",
"ButtonPurgeMediaProgress": "अभी तक सुना हुआ सब हटा दे",
"ButtonQueueAddItem": "क़तार में जोड़ें",
"ButtonQueueRemoveItem": "कतार से हटाएं",
"ButtonQuickMatch": "जल्दी से समानता की तलाश करें",
"ButtonReScan": "पुन: स्कैन करें",
"ButtonRead": "पढ़ लिया",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "सुनना जारी रखें से हटाएं",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveSeriesFromContinueSeries": "इस सीरीज को कंटिन्यू सीरीज से हटा दें",
"ButtonReScan": "पुन: स्कैन करें",
"ButtonReset": "रीसेट करें",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "पुनर्स्थापित करें",
@ -104,8 +104,8 @@
"HeaderAccount": "खाता",
"HeaderAdvanced": "विकसित",
"HeaderAppriseNotificationSettings": "Apprise अधिसूचना सेटिंग्स",
"HeaderAudiobookTools": "Audiobook File Management Tools",
"HeaderAudioTracks": "Audio Tracks",
"HeaderAudiobookTools": "Audiobook File Management Tools",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Backups",
"HeaderChangePassword": "Change Password",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Collection Items",
"HeaderCover": "Cover",
"HeaderCurrentDownloads": "Current Downloads",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Details",
"HeaderDownloadQueue": "Download Queue",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Playlist Items",
"HeaderPodcastsToAdd": "Podcasts to Add",
"HeaderPreviewCover": "Preview Cover",
"HeaderRemoveEpisode": "Remove Episode",
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Remove Episode",
"HeaderRemoveEpisodes": "Remove {0} Episodes",
"HeaderSavedMediaProgress": "Saved Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Schedule Automatic Library Scans",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Guest",
"LabelAccountTypeUser": "User",
"LabelActivity": "Activity",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAddToCollection": "Add to Collection",
"LabelAddToCollectionBatch": "Add {0} Books to Collection",
"LabelAddToPlaylist": "Add to Playlist",
"LabelAddToPlaylistBatch": "Add {0} Items to Playlist",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "All",
"LabelAllUsers": "All Users",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Change Password",
"LabelChannels": "Channels",
"LabelChapterTitle": "Chapter Title",
"LabelChapters": "Chapters",
"LabelChaptersFound": "chapters found",
"LabelChapterTitle": "Chapter Title",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Folder",
"LabelFolders": "Folders",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "फुहारा परिवार",
"LabelFontItalic": "Italic",
"LabelFontScale": "Font scale",
@ -321,9 +323,9 @@
"LabelHour": "Hour",
"LabelIcon": "Icon",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "In Progress",
"LabelIncludeInTracklist": "Include in Tracklist",
"LabelIncomplete": "Incomplete",
"LabelInProgress": "In Progress",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Custom daily/weekly",
"LabelIntervalEvery12Hours": "Every 12 hours",
@ -337,6 +339,7 @@
"LabelItem": "Item",
"LabelLanguage": "Language",
"LabelLanguageDefaultServer": "Default Server Language",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastSeen": "Last Seen",
@ -348,6 +351,7 @@
"LabelLess": "Less",
"LabelLibrariesAccessibleToUser": "Libraries Accessible to User",
"LabelLibrary": "Library",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Library Item",
"LabelLibraryName": "Library Name",
"LabelLimit": "Limit",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Media Player",
"LabelMediaType": "Media Type",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Provider",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Provider",
"LabelMinute": "Minute",
"LabelMissing": "Missing",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrator",
"LabelNarrators": "Narrators",
"LabelNew": "New",
"LabelNewPassword": "New Password",
"LabelNewestAuthors": "Newest Authors",
"LabelNewestEpisodes": "Newest Episodes",
"LabelNewPassword": "New Password",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Notes",
"LabelNotFinished": "Not Finished",
"LabelNotStarted": "Not Started",
"LabelNotes": "Notes",
"LabelNotificationAppriseURL": "Apprise URL(s)",
"LabelNotificationAvailableVariables": "Available variables",
"LabelNotificationBodyTemplate": "Body Template",
"LabelNotificationEvent": "Notification Event",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotificationsMaxFailedAttempts": "Max failed attempts",
"LabelNotificationsMaxFailedAttemptsHelp": "Notifications are disabled once they fail to send this many times",
"LabelNotificationsMaxQueueSize": "Max queue size for notification events",
"LabelNotificationsMaxQueueSizeHelp": "Events are limited to firing 1 per second. Events will be ignored if the queue is at max size. This prevents notification spamming.",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotStarted": "Not Started",
"LabelNumberOfBooks": "Number of Books",
"LabelNumberOfEpisodes": "# of Episodes",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Can Upload",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Photo Path/URL",
"LabelPlaylists": "Playlists",
"LabelPlayMethod": "Play Method",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Playlists",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "पॉडकास्ट खोज क्षेत्र",
"LabelPodcastType": "Podcast Type",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefixes to Ignore (case insensitive)",
"LabelPreventIndexing": "Prevent your feed from being indexed by iTunes and Google podcast directories",
@ -427,25 +433,26 @@
"LabelProgress": "Progress",
"LabelProvider": "Provider",
"LabelPubDate": "Pub Date",
"LabelPublisher": "Publisher",
"LabelPublishYear": "Publish Year",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentlyAdded": "Recently Added",
"LabelRecentSeries": "Recent Series",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Release Date",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Publisher",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Custom owner Email",
"LabelRSSFeedCustomOwnerName": "Custom owner Name",
"LabelRSSFeedOpen": "RSS Feed Open",
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentSeries": "Recent Series",
"LabelRecentlyAdded": "Recently Added",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Release Date",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Search Term",
"LabelSearchTitle": "Search Title",
"LabelSearchTitleOrASIN": "Search Title or ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Start Time",
"LabelStarted": "Started",
"LabelStartedAt": "Started At",
"LabelStartTime": "Start Time",
"LabelStatsAudioTracks": "Audio Tracks",
"LabelStatsAuthors": "Authors",
"LabelStatsBestDay": "Best Day",
@ -564,9 +571,9 @@
"LabelUnknown": "Unknown",
"LabelUpdateCover": "Update Cover",
"LabelUpdateCoverHelp": "Allow overwriting of existing covers for the selected books when a match is located",
"LabelUpdatedAt": "Updated At",
"LabelUpdateDetails": "Update Details",
"LabelUpdateDetailsHelp": "Allow overwriting of existing details for the selected books when a match is located",
"LabelUpdatedAt": "Updated At",
"LabelUploaderDragAndDrop": "Drag & drop files or folders",
"LabelUploaderDropFiles": "Drop files",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"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.",
"MessageBatchQuickMatchDescription": "Quick Match will attempt to add missing covers and metadata for the selected items. Enable the options below to allow Quick Match to overwrite existing covers and/or metadata.",
"MessageBookshelfNoCollections": "You haven't made any collections yet",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "No RSS feeds are open",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "You have no series",
"MessageChapterEndIsAfter": "Chapter end is after the end of your audiobook",
"MessageChapterErrorFirstNotZero": "First chapter must start at 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Are you sure you want to rename tag \"{0}\" to \"{1}\" for all items?",
"MessageConfirmRenameTagMergeNote": "Note: This tag already exists so they will be merged.",
"MessageConfirmRenameTagWarning": "Warning! A similar tag with a different casing already exists \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageDownloadingEpisode": "Downloading episode",
"MessageDragFilesIntoTrackOrder": "Drag files into correct track order",
@ -683,10 +692,10 @@
"MessageNoSeries": "No Series",
"MessageNoTags": "No Tags",
"MessageNoTasksRunning": "No Tasks Running",
"MessageNotYetImplemented": "Not yet implemented",
"MessageNoUpdateNecessary": "No update necessary",
"MessageNoUpdatesWereNecessary": "No updates were necessary",
"MessageNoUserPlaylists": "You have no playlists",
"MessageNotYetImplemented": "Not yet implemented",
"MessageOr": "or",
"MessagePauseChapter": "Pause chapter playback",
"MessagePlayChapter": "Listen to beginning of chapter",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Playlist updated",
"ToastPodcastCreateFailed": "Failed to create podcast",
"ToastPodcastCreateSuccess": "Podcast created successfully",
"ToastRemoveItemFromCollectionFailed": "Failed to remove item from collection",
"ToastRemoveItemFromCollectionSuccess": "Item removed from collection",
"ToastRSSFeedCloseFailed": "Failed to close RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed closed",
"ToastRemoveItemFromCollectionFailed": "Failed to remove item from collection",
"ToastRemoveItemFromCollectionSuccess": "Item removed from collection",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSeriesUpdateFailed": "Series update failed",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Failed to delete user",
"ToastUserDeleteSuccess": "User deleted"
}
}

View File

@ -1,14 +1,15 @@
{
"ButtonAdd": "Dodaj",
"ButtonAddChapters": "Dodaj poglavlja",
"ButtonAddDevice": "Add Device",
"ButtonAddLibrary": "Add Library",
"ButtonAddPodcasts": "Dodaj podcaste",
"ButtonAddUser": "Add User",
"ButtonAddDevice": "Dodaj uređaj",
"ButtonAddLibrary": "Dodaj biblioteku",
"ButtonAddPodcasts": "Dodaj podkaste",
"ButtonAddUser": "Dodaj korisnika",
"ButtonAddYourFirstLibrary": "Dodaj svoju prvu biblioteku",
"ButtonApply": "Primijeni",
"ButtonApplyChapters": "Primijeni poglavlja",
"ButtonAuthors": "Autori",
"ButtonBack": "Natrag",
"ButtonBrowseForFolder": "Browse for Folder",
"ButtonCancel": "Odustani",
"ButtonCancelEncode": "Otkaži kodiranje",
@ -16,7 +17,7 @@
"ButtonCheckAndDownloadNewEpisodes": "Provjeri i preuzmi nove epizode",
"ButtonChooseAFolder": "Odaberi folder",
"ButtonChooseFiles": "Odaberi datoteke",
"ButtonClearFilter": "Clear Filter",
"ButtonClearFilter": "Poništi filter",
"ButtonCloseFeed": "Zatvori feed",
"ButtonCollections": "Kolekcije",
"ButtonConfigureScanner": "Configure Scanner",
@ -24,7 +25,7 @@
"ButtonCreateBackup": "Napravi backup",
"ButtonDelete": "Obriši",
"ButtonDownloadQueue": "Queue",
"ButtonEdit": "Edit",
"ButtonEdit": "Uredi",
"ButtonEditChapters": "Uredi poglavlja",
"ButtonEditPodcast": "Uredi podcast",
"ButtonForceReScan": "Prisilno ponovno skeniranje",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Isprazni sav cache",
"ButtonPurgeItemsCache": "Isprazni Items Cache",
"ButtonPurgeMediaProgress": "Purge Media Progress",
"ButtonQueueAddItem": "Add to queue",
"ButtonQueueRemoveItem": "Remove from queue",
"ButtonQuickMatch": "Brzi match",
"ButtonReScan": "Skeniraj ponovno",
"ButtonRead": "Pročitaj",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Ukloni iz Nastavi slušati",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveSeriesFromContinueSeries": "Ukloni seriju iz Nastavi seriju",
"ButtonReScan": "Skeniraj ponovno",
"ButtonReset": "Poništi",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "Povrati",
@ -104,8 +104,8 @@
"HeaderAccount": "Korisnički račun",
"HeaderAdvanced": "Napredno",
"HeaderAppriseNotificationSettings": "Apprise Notification Settings",
"HeaderAudiobookTools": "Audiobook File Management alati",
"HeaderAudioTracks": "Audio Tracks",
"HeaderAudiobookTools": "Audiobook File Management alati",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Backups",
"HeaderChangePassword": "Promijeni lozinku",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Stvari u kolekciji",
"HeaderCover": "Cover",
"HeaderCurrentDownloads": "Current Downloads",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Detalji",
"HeaderDownloadQueue": "Download Queue",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Playlist Items",
"HeaderPodcastsToAdd": "Podcasti za dodati",
"HeaderPreviewCover": "Pregledaj Cover",
"HeaderRemoveEpisode": "Ukloni epizodu",
"HeaderRemoveEpisodes": "Ukloni {0} epizoda/-e",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed je otvoren",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Ukloni epizodu",
"HeaderRemoveEpisodes": "Ukloni {0} epizoda/-e",
"HeaderSavedMediaProgress": "Spremljen Media Progress",
"HeaderSchedule": "Schedule",
"HeaderScheduleLibraryScans": "Zakaži automatsko skeniranje biblioteke",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gost",
"LabelAccountTypeUser": "Korisnik",
"LabelActivity": "Aktivnost",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAddToCollection": "Dodaj u kolekciju",
"LabelAddToCollectionBatch": "Add {0} Books to Collection",
"LabelAddToPlaylist": "Add to Playlist",
"LabelAddToPlaylistBatch": "Add {0} Items to Playlist",
"LabelAdded": "Added",
"LabelAddedAt": "Added At",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "All",
"LabelAllUsers": "Svi korisnici",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Promijeni lozinku",
"LabelChannels": "Channels",
"LabelChapterTitle": "Ime poglavlja",
"LabelChapters": "Chapters",
"LabelChaptersFound": "poglavlja pronađena",
"LabelChapterTitle": "Ime poglavlja",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Close player",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Folder",
"LabelFolders": "Folderi",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Font family",
"LabelFontItalic": "Italic",
"LabelFontScale": "Font scale",
@ -321,9 +323,9 @@
"LabelHour": "Sat",
"LabelIcon": "Ikona",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "U tijeku",
"LabelIncludeInTracklist": "Dodaj u Tracklist",
"LabelIncomplete": "Nepotpuno",
"LabelInProgress": "U tijeku",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Custom daily/weekly",
"LabelIntervalEvery12Hours": "Every 12 hours",
@ -337,6 +339,7 @@
"LabelItem": "Stavka",
"LabelLanguage": "Jezik",
"LabelLanguageDefaultServer": "Default jezik servera",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastSeen": "Zadnje pogledano",
@ -348,6 +351,7 @@
"LabelLess": "Manje",
"LabelLibrariesAccessibleToUser": "Biblioteke pristupačne korisniku",
"LabelLibrary": "Biblioteka",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Stavka biblioteke",
"LabelLibraryName": "Ime biblioteke",
"LabelLimit": "Limit",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Media Player",
"LabelMediaType": "Media Type",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Poslužitelj metapodataka ",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Poslužitelj metapodataka ",
"LabelMinute": "Minuta",
"LabelMissing": "Nedostaje",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrator",
"LabelNarrators": "Naratori",
"LabelNew": "Novo",
"LabelNewPassword": "Nova lozinka",
"LabelNewestAuthors": "Najnoviji autori",
"LabelNewestEpisodes": "Najnovije epizode",
"LabelNewPassword": "Nova lozinka",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Bilješke",
"LabelNotFinished": "Nedovršeno",
"LabelNotStarted": "Not Started",
"LabelNotes": "Bilješke",
"LabelNotificationAppriseURL": "Apprise URL(s)",
"LabelNotificationAvailableVariables": "Dostupne varijable",
"LabelNotificationBodyTemplate": "Body Template",
"LabelNotificationEvent": "Notification Event",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotificationsMaxFailedAttempts": "Maksimalan broj neuspjelih pokušaja",
"LabelNotificationsMaxFailedAttemptsHelp": "Obavijesti će biti isključene ako par puta budu neuspješno poslane.",
"LabelNotificationsMaxQueueSize": "Maksimalna veličina queuea za notification events",
"LabelNotificationsMaxQueueSizeHelp": "Samo 1 event po sekundi može biti pokrenut. Eventi će biti ignorirani ako je queue na maksimalnoj veličini. To spriječava spammanje s obavijestima.",
"LabelNotificationTitleTemplate": "Title Template",
"LabelNotStarted": "Not Started",
"LabelNumberOfBooks": "Number of Books",
"LabelNumberOfEpisodes": "# of Episodes",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Smije uploadati",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Slika putanja/URL",
"LabelPlaylists": "Playlists",
"LabelPlayMethod": "Vrsta reprodukcije",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Playlists",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Područje pretrage podcasta",
"LabelPodcastType": "Podcast Type",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefiksi za ignorirati (mala i velika slova nisu bitna)",
"LabelPreventIndexing": "Prevent your feed from being indexed by iTunes and Google podcast directories",
@ -427,25 +433,26 @@
"LabelProgress": "Napredak",
"LabelProvider": "Dobavljač",
"LabelPubDate": "Datam izdavanja",
"LabelPublisher": "Izdavač",
"LabelPublishYear": "Godina izdavanja",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentlyAdded": "Nedavno dodano",
"LabelRecentSeries": "Nedavne serije",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Regija",
"LabelReleaseDate": "Datum izlaska",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Izdavač",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Custom owner Email",
"LabelRSSFeedCustomOwnerName": "Custom owner Name",
"LabelRSSFeedOpen": "RSS Feed Open",
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentSeries": "Nedavne serije",
"LabelRecentlyAdded": "Nedavno dodano",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Regija",
"LabelReleaseDate": "Datum izlaska",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Traži pojam",
"LabelSearchTitle": "Traži naslov",
"LabelSearchTitleOrASIN": "Traži naslov ili ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Slug",
"LabelStart": "Pokreni",
"LabelStartTime": "Vrijeme pokretanja",
"LabelStarted": "Pokrenuto",
"LabelStartedAt": "Pokrenuto",
"LabelStartTime": "Vrijeme pokretanja",
"LabelStatsAudioTracks": "Audio Tracks",
"LabelStatsAuthors": "Autori",
"LabelStatsBestDay": "Najbolji dan",
@ -564,9 +571,9 @@
"LabelUnknown": "Nepoznato",
"LabelUpdateCover": "Aktualiziraj Cover",
"LabelUpdateCoverHelp": "Dozvoli postavljanje novog covera za odabrane knjige nakon što je match pronađen.",
"LabelUpdatedAt": "Aktualizirano",
"LabelUpdateDetails": "Aktualiziraj detalje",
"LabelUpdateDetailsHelp": "Dozvoli postavljanje novih detalja za odabrane knjige nakon što je match pronađen",
"LabelUpdatedAt": "Aktualizirano",
"LabelUploaderDragAndDrop": "Drag & Drop datoteke ili foldere",
"LabelUploaderDropFiles": "Ubaci datoteke",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Backups uključuju korisnike, korisnikov napredak, detalje stavki iz biblioteke, postavke server i slike iz <code>/metadata/items</code> & <code>/metadata/authors</code>. Backups ne uključuju nijedne datoteke koje su u folderima biblioteke.",
"MessageBatchQuickMatchDescription": "Quick Match će probati dodati nedostale covere i metapodatke za odabrane stavke. Uključi postavke ispod da omočutie Quick Mathchu da zamijeni postojeće covere i/ili metapodatke.",
"MessageBookshelfNoCollections": "You haven't made any collections yet",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "No RSS feeds are open",
"MessageBookshelfNoResultsForFilter": "No Results for filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "You have no series",
"MessageChapterEndIsAfter": "Kraj poglavlja je nakon kraja audioknjige.",
"MessageChapterErrorFirstNotZero": "First chapter must start at 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "AJeste li sigurni da želite obrisati kolekciju \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Are you sure you want to rename tag \"{0}\" to \"{1}\" for all items?",
"MessageConfirmRenameTagMergeNote": "Note: This tag already exists so they will be merged.",
"MessageConfirmRenameTagWarning": "Warning! A similar tag with a different casing already exists \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageDownloadingEpisode": "Preuzimam epizodu",
"MessageDragFilesIntoTrackOrder": "Povuci datoteke u pravilan redoslijed tracka.",
@ -683,10 +692,10 @@
"MessageNoSeries": "No Series",
"MessageNoTags": "No Tags",
"MessageNoTasksRunning": "No Tasks Running",
"MessageNotYetImplemented": "Not yet implemented",
"MessageNoUpdateNecessary": "Aktualiziranje nije potrebno",
"MessageNoUpdatesWereNecessary": "Aktualiziranje nije bilo potrebno",
"MessageNoUserPlaylists": "You have no playlists",
"MessageNotYetImplemented": "Not yet implemented",
"MessageOr": "or",
"MessagePauseChapter": "Pause chapter playback",
"MessagePlayChapter": "Listen to beginning of chapter",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Playlist updated",
"ToastPodcastCreateFailed": "Neuspješno kreiranje podcasta",
"ToastPodcastCreateSuccess": "Podcast uspješno kreiran",
"ToastRemoveItemFromCollectionFailed": "Neuspješno uklanjanje stavke iz kolekcije",
"ToastRemoveItemFromCollectionSuccess": "Stavka uklonjena iz kolekcije",
"ToastRSSFeedCloseFailed": "Neuspješno zatvaranje RSS Feeda",
"ToastRSSFeedCloseSuccess": "RSS Feed zatvoren",
"ToastRemoveItemFromCollectionFailed": "Neuspješno uklanjanje stavke iz kolekcije",
"ToastRemoveItemFromCollectionSuccess": "Stavka uklonjena iz kolekcije",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSeriesUpdateFailed": "Series update failed",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Neuspješno brisanje korisnika",
"ToastUserDeleteSuccess": "Korisnik obrisan"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Alkalmaz",
"ButtonApplyChapters": "Fejezetek alkalmazása",
"ButtonAuthors": "Szerzők",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Mappa keresése",
"ButtonCancel": "Mégse",
"ButtonCancelEncode": "Kódolás megszakítása",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Előző fejezet",
"ButtonPurgeAllCache": "Összes gyorsítótár törlése",
"ButtonPurgeItemsCache": "Elemek gyorsítótárának törlése",
"ButtonPurgeMediaProgress": "Médialejátszás állapotának törlése",
"ButtonQueueAddItem": "Hozzáadás a sorhoz",
"ButtonQueueRemoveItem": "Eltávolítás a sorból",
"ButtonQuickMatch": "Gyors egyeztetés",
"ButtonReScan": "Újraszkennelés",
"ButtonRead": "Olvasás",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Eltávolítás a Folytatás hallgatásából",
"ButtonRemoveFromContinueReading": "Eltávolítás a Folytatás olvasásából",
"ButtonRemoveSeriesFromContinueSeries": "Sorozat eltávolítása a Folytatás sorozatokból",
"ButtonReScan": "Újraszkennelés",
"ButtonReset": "Visszaállítás",
"ButtonResetToDefault": "Alapértelmezésre állítás",
"ButtonRestore": "Visszaállítás",
@ -104,8 +104,8 @@
"HeaderAccount": "Fiók",
"HeaderAdvanced": "Haladó",
"HeaderAppriseNotificationSettings": "Apprise értesítési beállítások",
"HeaderAudiobookTools": "Hangoskönyv fájlkezelő eszközök",
"HeaderAudioTracks": "Audiósávok",
"HeaderAudiobookTools": "Hangoskönyv fájlkezelő eszközök",
"HeaderAuthentication": "Hitelesítés",
"HeaderBackups": "Biztonsági másolatok",
"HeaderChangePassword": "Jelszó megváltoztatása",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Gyűjtemény elemek",
"HeaderCover": "Borító",
"HeaderCurrentDownloads": "Jelenlegi letöltések",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Egyéni metaadat-szolgáltatók",
"HeaderDetails": "Részletek",
"HeaderDownloadQueue": "Letöltési sor",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Lejátszási lista elemek",
"HeaderPodcastsToAdd": "Hozzáadandó podcastok",
"HeaderPreviewCover": "Borító előnézete",
"HeaderRemoveEpisode": "Epizód eltávolítása",
"HeaderRemoveEpisodes": "{0} epizód eltávolítása",
"HeaderRSSFeedGeneral": "RSS részletek",
"HeaderRSSFeedIsOpen": "RSS hírcsatorna nyitva",
"HeaderRSSFeeds": "RSS hírcsatornák",
"HeaderRemoveEpisode": "Epizód eltávolítása",
"HeaderRemoveEpisodes": "{0} epizód eltávolítása",
"HeaderSavedMediaProgress": "Mentett médialejátszási állapot",
"HeaderSchedule": "Ütemezés",
"HeaderScheduleLibraryScans": "Könyvtárak automatikus szkennelésének ütemezése",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Vendég",
"LabelAccountTypeUser": "Felhasználó",
"LabelActivity": "Tevékenység",
"LabelAdded": "Hozzáadva",
"LabelAddedAt": "Hozzáadás ideje",
"LabelAddToCollection": "Hozzáadás a gyűjteményhez",
"LabelAddToCollectionBatch": "{0} könyv hozzáadása a gyűjteményhez",
"LabelAddToPlaylist": "Hozzáadás a lejátszási listához",
"LabelAddToPlaylistBatch": "{0} elem hozzáadása a lejátszási listához",
"LabelAdded": "Hozzáadva",
"LabelAddedAt": "Hozzáadás ideje",
"LabelAdminUsersOnly": "Csak admin felhasználók",
"LabelAll": "Minden",
"LabelAllUsers": "Minden felhasználó",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Jelszó megváltoztatása",
"LabelChannels": "Csatornák",
"LabelChapterTitle": "Fejezet címe",
"LabelChapters": "Fejezetek",
"LabelChaptersFound": "fejezet található",
"LabelChapterTitle": "Fejezet címe",
"LabelClickForMoreInfo": "További információkért kattintson",
"LabelClosePlayer": "Lejátszó bezárása",
"LabelCodec": "Kodek",
@ -306,6 +307,7 @@
"LabelFolder": "Mappa",
"LabelFolders": "Mappák",
"LabelFontBold": "Félkövér",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Betűtípus család",
"LabelFontItalic": "Dőlt",
"LabelFontScale": "Betűméret skála",
@ -321,9 +323,9 @@
"LabelHour": "Óra",
"LabelIcon": "Ikon",
"LabelImageURLFromTheWeb": "Kép URL a weben",
"LabelInProgress": "Folyamatban",
"LabelIncludeInTracklist": "Beleértve a sávlistába",
"LabelIncomplete": "Befejezetlen",
"LabelInProgress": "Folyamatban",
"LabelInterval": "Intervallum",
"LabelIntervalCustomDailyWeekly": "Egyéni napi/heti",
"LabelIntervalEvery12Hours": "Minden 12 órában",
@ -337,6 +339,7 @@
"LabelItem": "Elem",
"LabelLanguage": "Nyelv",
"LabelLanguageDefaultServer": "Szerver alapértelmezett nyelve",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Utolsó hozzáadott könyv",
"LabelLastBookUpdated": "Utolsó frissített könyv",
"LabelLastSeen": "Utolsó látogatás",
@ -348,6 +351,7 @@
"LabelLess": "Kevesebb",
"LabelLibrariesAccessibleToUser": "A felhasználó számára elérhető könyvtárak",
"LabelLibrary": "Könyvtár",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Könyvtári elem",
"LabelLibraryName": "Könyvtár neve",
"LabelLimit": "Korlát",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Meglévő felhasználók összekapcsolására használt. Egyszer összekapcsolva, a felhasználók egyedülálló azonosítóval lesznek egyeztetve az Ön SSO szolgáltatójától",
"LabelMediaPlayer": "Médialejátszó",
"LabelMediaType": "Média típus",
"LabelMetadataOrderOfPrecedenceDescription": "A magasabb prioritású metaadat-források felülírják az alacsonyabb prioritásúakat",
"LabelMetadataProvider": "Metaadat-szolgáltató",
"LabelMetaTag": "Meta címke",
"LabelMetaTags": "Meta címkék",
"LabelMetadataOrderOfPrecedenceDescription": "A magasabb prioritású metaadat-források felülírják az alacsonyabb prioritásúakat",
"LabelMetadataProvider": "Metaadat-szolgáltató",
"LabelMinute": "Perc",
"LabelMissing": "Hiányzó",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Előadó",
"LabelNarrators": "Előadók",
"LabelNew": "Új",
"LabelNewPassword": "Új jelszó",
"LabelNewestAuthors": "Legújabb szerzők",
"LabelNewestEpisodes": "Legújabb epizódok",
"LabelNewPassword": "Új jelszó",
"LabelNextBackupDate": "Következő biztonsági másolat dátuma",
"LabelNextScheduledRun": "Következő ütemezett futtatás",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Nincsenek kiválasztott epizódok",
"LabelNotes": "Megjegyzések",
"LabelNotFinished": "Nem befejezett",
"LabelNotStarted": "Nem indult el",
"LabelNotes": "Megjegyzések",
"LabelNotificationAppriseURL": "Apprise URL(ek)",
"LabelNotificationAvailableVariables": "Elérhető változók",
"LabelNotificationBodyTemplate": "Törzs sablon",
"LabelNotificationEvent": "Értesítési esemény",
"LabelNotificationTitleTemplate": "Cím sablon",
"LabelNotificationsMaxFailedAttempts": "Maximális sikertelen próbálkozások",
"LabelNotificationsMaxFailedAttemptsHelp": "Az értesítések akkor kerülnek letiltásra, ha ennyiszer nem sikerül elküldeni őket",
"LabelNotificationsMaxQueueSize": "Maximális értesítési események sorának mérete",
"LabelNotificationsMaxQueueSizeHelp": "Az események korlátozva vannak, hogy másodpercenként 1-szer történjenek. Ha a sor maximális méretű, akkor az események figyelmen kívül lesznek hagyva. Ez megakadályozza az értesítések spamelését.",
"LabelNotificationTitleTemplate": "Cím sablon",
"LabelNotStarted": "Nem indult el",
"LabelNumberOfBooks": "Könyvek száma",
"LabelNumberOfEpisodes": "Epizódok száma",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Feltölthet",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Fénykép útvonal/URL",
"LabelPlaylists": "Lejátszási listák",
"LabelPlayMethod": "Lejátszási módszer",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Lejátszási listák",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcastok",
"LabelPodcastSearchRegion": "Podcast keresési régió",
"LabelPodcastType": "Podcast típus",
"LabelPodcasts": "Podcastok",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Figyelmen kívül hagyandó előtagok (nem érzékeny a kis- és nagybetűkre)",
"LabelPreventIndexing": "A hírcsatorna indexelésének megakadályozása az iTunes és a Google podcast könyvtáraiban",
@ -427,25 +433,26 @@
"LabelProgress": "Haladás",
"LabelProvider": "Szolgáltató",
"LabelPubDate": "Kiadás dátuma",
"LabelPublisher": "Kiadó",
"LabelPublishYear": "Kiadás éve",
"LabelRead": "Olvasás",
"LabelReadAgain": "Újraolvasás",
"LabelReadEbookWithoutProgress": "E-könyv olvasása haladás nélkül",
"LabelRecentlyAdded": "Nemrég hozzáadva",
"LabelRecentSeries": "Legutóbbi sorozatok",
"LabelRecommended": "Ajánlott",
"LabelRedo": "Újra",
"LabelRegion": "Régió",
"LabelReleaseDate": "Megjelenés dátuma",
"LabelRemoveCover": "Borító eltávolítása",
"LabelRowsPerPage": "Sorok száma oldalanként",
"LabelPublisher": "Kiadó",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Egyéni tulajdonos e-mail",
"LabelRSSFeedCustomOwnerName": "Egyéni tulajdonos neve",
"LabelRSSFeedOpen": "RSS hírcsatorna nyitva",
"LabelRSSFeedPreventIndexing": "Indexelés megakadályozása",
"LabelRSSFeedSlug": "RSS hírcsatorna slug",
"LabelRSSFeedURL": "RSS hírcsatorna URL",
"LabelRead": "Olvasás",
"LabelReadAgain": "Újraolvasás",
"LabelReadEbookWithoutProgress": "E-könyv olvasása haladás nélkül",
"LabelRecentSeries": "Legutóbbi sorozatok",
"LabelRecentlyAdded": "Nemrég hozzáadva",
"LabelRecommended": "Ajánlott",
"LabelRedo": "Újra",
"LabelRegion": "Régió",
"LabelReleaseDate": "Megjelenés dátuma",
"LabelRemoveCover": "Borító eltávolítása",
"LabelRowsPerPage": "Sorok száma oldalanként",
"LabelSearchTerm": "Keresési kifejezés",
"LabelSearchTitle": "Cím keresése",
"LabelSearchTitleOrASIN": "Cím vagy ASIN keresése",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Alvásidőzítő",
"LabelSlug": "Rövid cím",
"LabelStart": "Kezdés",
"LabelStartTime": "Kezdési idő",
"LabelStarted": "Elkezdődött",
"LabelStartedAt": "Kezdés ideje",
"LabelStartTime": "Kezdési idő",
"LabelStatsAudioTracks": "Audiósávok",
"LabelStatsAuthors": "Szerzők",
"LabelStatsBestDay": "Legjobb nap",
@ -564,9 +571,9 @@
"LabelUnknown": "Ismeretlen",
"LabelUpdateCover": "Borító frissítése",
"LabelUpdateCoverHelp": "Lehetővé teszi a meglévő borítók felülírását a kiválasztott könyveknél, amikor találatot talál",
"LabelUpdatedAt": "Frissítve",
"LabelUpdateDetails": "Részletek frissítése",
"LabelUpdateDetailsHelp": "Lehetővé teszi a meglévő részletek felülírását a kiválasztott könyveknél, amikor találatot talál",
"LabelUpdatedAt": "Frissítve",
"LabelUploaderDragAndDrop": "Fájlok vagy mappák húzása és elengedése",
"LabelUploaderDropFiles": "Fájlok elengedése",
"LabelUploaderItemFetchMetadataHelp": "Cím, szerző és sorozat automatikus lekérése",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "A biztonsági másolatok tartalmazzák a felhasználókat, a felhasználói haladást, a könyvtári elem részleteit, a szerver beállításait és a képeket, amelyek a <code>/metadata/items</code> és <code>/metadata/authors</code> mappákban vannak tárolva. A biztonsági másolatok <strong>nem</strong> tartalmazzák a könyvtári mappákban tárolt fájlokat.",
"MessageBatchQuickMatchDescription": "A Gyors egyeztetés megpróbálja hozzáadni a hiányzó borítókat és metaadatokat a kiválasztott elemekhez. Engedélyezze az alábbi opciókat, hogy a Gyors egyeztetés felülírhassa a meglévő borítókat és/vagy metaadatokat.",
"MessageBookshelfNoCollections": "Még nem készített gyűjteményeket",
"MessageBookshelfNoResultsForFilter": "Nincs eredmény a \"{0}: {1}\" szűrőre",
"MessageBookshelfNoRSSFeeds": "Nincsenek nyitott RSS hírcsatornák",
"MessageBookshelfNoResultsForFilter": "Nincs eredmény a \"{0}: {1}\" szűrőre",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Nincsenek sorozatai",
"MessageChapterEndIsAfter": "A fejezet vége a hangoskönyv végét követi",
"MessageChapterErrorFirstNotZero": "Az első fejezetnek 0:00-kor kell kezdődnie",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Biztosan meg szeretné jelölni a sorozat összes könyvét befejezettnek?",
"MessageConfirmMarkSeriesNotFinished": "Biztosan meg szeretné jelölni a sorozat összes könyvét nem befejezettnek?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Figyelem! A Gyors beágyazás nem készít biztonsági másolatot az audiofájlokról. Győződjön meg arról, hogy van biztonsági másolata az audiofájlokról. <br><br>Szeretné folytatni?",
"MessageConfirmReScanLibraryItems": "Biztosan újra szeretné szkennelni a(z) {0} elemet?",
"MessageConfirmRemoveAllChapters": "Biztosan eltávolítja az összes fejezetet?",
"MessageConfirmRemoveAuthor": "Biztosan eltávolítja a(z) \"{0}\" szerzőt?",
"MessageConfirmRemoveCollection": "Biztosan eltávolítja a(z) \"{0}\" gyűjteményt?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Biztosan át szeretné nevezni a(z) \"{0}\" címkét \"{1}\"-re az összes elemnél?",
"MessageConfirmRenameTagMergeNote": "Megjegyzés: Ez a címke már létezik, így össze lesznek vonva.",
"MessageConfirmRenameTagWarning": "Figyelem! Egy hasonló, de eltérő nagybetűkkel rendelkező címke már létezik \"{0}\".",
"MessageConfirmReScanLibraryItems": "Biztosan újra szeretné szkennelni a(z) {0} elemet?",
"MessageConfirmSendEbookToDevice": "Biztosan el szeretné küldeni a(z) {0} e-könyvet a(z) \"{1}\" eszközre?",
"MessageDownloadingEpisode": "Epizód letöltése",
"MessageDragFilesIntoTrackOrder": "Húzza a fájlokat a helyes sávrendbe",
@ -683,10 +692,10 @@
"MessageNoSeries": "Nincsenek sorozatok",
"MessageNoTags": "Nincsenek címkék",
"MessageNoTasksRunning": "Nincsenek futó feladatok",
"MessageNotYetImplemented": "Még nem implementált",
"MessageNoUpdateNecessary": "Nincs szükség frissítésre",
"MessageNoUpdatesWereNecessary": "Nem volt szükség frissítésekre",
"MessageNoUserPlaylists": "Nincsenek felhasználói lejátszási listák",
"MessageNotYetImplemented": "Még nem implementált",
"MessageOr": "vagy",
"MessagePauseChapter": "Fejezet lejátszásának szüneteltetése",
"MessagePlayChapter": "Fejezet elejének meghallgatása",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Lejátszási lista frissítve",
"ToastPodcastCreateFailed": "Podcast létrehozása sikertelen",
"ToastPodcastCreateSuccess": "Podcast sikeresen létrehozva",
"ToastRemoveItemFromCollectionFailed": "Tétel eltávolítása a gyűjteményből sikertelen",
"ToastRemoveItemFromCollectionSuccess": "Tétel eltávolítva a gyűjteményből",
"ToastRSSFeedCloseFailed": "RSS feed bezárása sikertelen",
"ToastRSSFeedCloseSuccess": "RSS feed bezárva",
"ToastRemoveItemFromCollectionFailed": "Tétel eltávolítása a gyűjteményből sikertelen",
"ToastRemoveItemFromCollectionSuccess": "Tétel eltávolítva a gyűjteményből",
"ToastSendEbookToDeviceFailed": "E-könyv küldése az eszközre sikertelen",
"ToastSendEbookToDeviceSuccess": "E-könyv elküldve az eszközre \"{0}\"",
"ToastSeriesUpdateFailed": "Sorozat frissítése sikertelen",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Felhasználó törlése sikertelen",
"ToastUserDeleteSuccess": "Felhasználó törölve"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Applica",
"ButtonApplyChapters": "Applica",
"ButtonAuthors": "Autori",
"ButtonBack": "Indietro",
"ButtonBrowseForFolder": "Per Cartella",
"ButtonCancel": "Cancella",
"ButtonCancelEncode": "Ferma la codifica",
@ -56,21 +57,20 @@
"ButtonPreviousChapter": "Capitolo Precendente",
"ButtonPurgeAllCache": "Elimina tutta la Cache",
"ButtonPurgeItemsCache": "Elimina la Cache selezionata",
"ButtonPurgeMediaProgress": "Elimina info dei media ascoltati",
"ButtonQueueAddItem": "Aggiungi alla Coda",
"ButtonQueueRemoveItem": "Rimuovi dalla Coda",
"ButtonQuickMatch": "Controlla Metadata Auto",
"ButtonReScan": "Ri-scansiona",
"ButtonRead": "Leggi",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
"ButtonRefresh": "Refresh",
"ButtonReadLess": "Leggi di Meno",
"ButtonReadMore": "Leggi di Più",
"ButtonRefresh": "Aggiorna",
"ButtonRemove": "Rimuovi",
"ButtonRemoveAll": "Rimuovi Tutto",
"ButtonRemoveAllLibraryItems": "Rimuovi tutto il contenuto della libreria",
"ButtonRemoveFromContinueListening": "Rimuovi per proseguire l'ascolto",
"ButtonRemoveFromContinueReading": "Rimuovi per proseguire la lettura",
"ButtonRemoveSeriesFromContinueSeries": "Rimuovi la Serie per Continuarla",
"ButtonReScan": "Ri-scansiona",
"ButtonReset": "Reset",
"ButtonResetToDefault": "Ripristino di default",
"ButtonRestore": "Ripristina",
@ -83,7 +83,7 @@
"ButtonSelectFolderPath": "Seleziona percorso cartella",
"ButtonSeries": "Serie",
"ButtonSetChaptersFromTracks": "Impostare i capitoli dalle tracce",
"ButtonShare": "Share",
"ButtonShare": "Condividi",
"ButtonShiftTimes": "Ricerca veloce",
"ButtonShow": "Mostra",
"ButtonStartM4BEncode": "Inizia L'Encode del M4B",
@ -104,8 +104,8 @@
"HeaderAccount": "Account",
"HeaderAdvanced": "Avanzate",
"HeaderAppriseNotificationSettings": "Apprendi le impostazioni di Notifica",
"HeaderAudiobookTools": "Utilità Audiobook File Management",
"HeaderAudioTracks": "Tracce Audio",
"HeaderAudiobookTools": "Utilità Audiobook File Management",
"HeaderAuthentication": "Authenticazione",
"HeaderBackups": "Backup",
"HeaderChangePassword": "Cambia Password",
@ -115,12 +115,13 @@
"HeaderCollectionItems": "Elementi della Raccolta",
"HeaderCover": "Cover",
"HeaderCurrentDownloads": "Download Correnti",
"HeaderCustomMetadataProviders": " Metadata Providers Personalizzato",
"HeaderCustomMessageOnLogin": "Messaggio personalizzato all'accesso",
"HeaderCustomMetadataProviders": "Metadata Providers Personalizzato",
"HeaderDetails": "Dettagli",
"HeaderDownloadQueue": "Download coda",
"HeaderEbookFiles": "Ebook File",
"HeaderEmail": "Email",
"HeaderEmailSettings": "Email Settings",
"HeaderEmailSettings": "Impostazioni Email",
"HeaderEpisodes": "Episodi",
"HeaderEreaderDevices": "Dispositivo Ereader",
"HeaderEreaderSettings": "Impostazioni Ereader",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Elementi della playlist",
"HeaderPodcastsToAdd": "Podcasts da Aggiungere",
"HeaderPreviewCover": "Anteprima Cover",
"HeaderRemoveEpisode": "Rimuovi Episodi",
"HeaderRemoveEpisodes": "Rimuovi {0} Episodi",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed è aperto",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Rimuovi Episodi",
"HeaderRemoveEpisodes": "Rimuovi {0} Episodi",
"HeaderSavedMediaProgress": "Progressi salvati",
"HeaderSchedule": "Schedula",
"HeaderScheduleLibraryScans": "Schedula la scansione della libreria",
@ -189,20 +190,20 @@
"HeaderYearReview": "Anno {0} in Sintesi",
"HeaderYourStats": "Statistiche Personali",
"LabelAbridged": "Abbreviato",
"LabelAbridgedChecked": "Abridged (checked)",
"LabelAbridgedUnchecked": "Unabridged (unchecked)",
"LabelAccessibleBy": "Accessible by",
"LabelAbridgedChecked": "Ridotto (selezionato)",
"LabelAbridgedUnchecked": "Integrale (non selezionato)",
"LabelAccessibleBy": "Accessibile da",
"LabelAccountType": "Tipo di Account",
"LabelAccountTypeAdmin": "Admin",
"LabelAccountTypeGuest": "Ospite",
"LabelAccountTypeUser": "Utente",
"LabelActivity": "Attività",
"LabelAdded": "Aggiunto",
"LabelAddedAt": "Aggiunto il",
"LabelAddToCollection": "Aggiungi alla Raccolta",
"LabelAddToCollectionBatch": "Aggiungi {0} Libri alla Raccolta",
"LabelAddToPlaylist": "aggiungi alla Playlist",
"LabelAddToPlaylistBatch": "Aggiungi {0} file alla Playlist",
"LabelAdded": "Aggiunto",
"LabelAddedAt": "Aggiunto il",
"LabelAdminUsersOnly": "Solo utenti Amministratori",
"LabelAll": "Tutti",
"LabelAllUsers": "Tutti gli Utenti",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Cambia Password",
"LabelChannels": "Canali",
"LabelChapterTitle": "Titoli dei Capitoli",
"LabelChapters": "Capitoli",
"LabelChaptersFound": "Capitoli Trovati",
"LabelChapterTitle": "Titoli dei Capitoli",
"LabelClickForMoreInfo": "Click per altre Info",
"LabelClosePlayer": "Chiudi player",
"LabelCodec": "Codec",
@ -268,20 +269,20 @@
"LabelDiscFromMetadata": "Disco dal Metadata",
"LabelDiscover": "Scopri",
"LabelDownload": "Download",
"LabelDownloadNEpisodes": "Download {0} episodes",
"LabelDownloadNEpisodes": "Download {0} episodi",
"LabelDuration": "Durata",
"LabelDurationComparisonExactMatch": "(exact match)",
"LabelDurationComparisonLonger": "({0} longer)",
"LabelDurationComparisonShorter": "({0} shorter)",
"LabelDurationComparisonExactMatch": "(corrispondenza esatta)",
"LabelDurationComparisonLonger": "({0} lungo)",
"LabelDurationComparisonShorter": "({0} corto)",
"LabelDurationFound": "Durata Trovata:",
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEdit": "Modifica",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "Da Indirizzo",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsSecure": "Secure",
"LabelEmailSettingsRejectUnauthorized": "Rifiuta i certificati non autorizzati",
"LabelEmailSettingsRejectUnauthorizedHelp": "La disattivazione della convalida del certificato SSL può esporre la tua connessione a rischi per la sicurezza, come attacchi man-in-the-middle. Disattiva questa opzione solo se ne comprendi le implicazioni e ti fidi del server di posta a cui ti stai connettendo.",
"LabelEmailSettingsSecure": "Sicuro",
"LabelEmailSettingsSecureHelp": "Se vero, la connessione utilizzerà TLS durante la connessione al server. Se false, viene utilizzato TLS se il server supporta l'estensione STARTTLS. Nella maggior parte dei casi impostare questo valore su true se ci si connette alla porta 465. Per la porta 587 o 25 mantenerlo false. (da nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Test Indirizzo",
"LabelEmbeddedCover": "Cover Integrata",
@ -292,8 +293,8 @@
"LabelEpisodeType": "Tipo Episodio",
"LabelExample": "Esempio",
"LabelExplicit": "Esplicito",
"LabelExplicitChecked": "Explicit (checked)",
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
"LabelExplicitChecked": "Esplicito (selezionato)",
"LabelExplicitUnchecked": "Non Esplicito (selezionato)",
"LabelFeedURL": "Feed URL",
"LabelFetchingMetadata": "Recupero dei metadati",
"LabelFile": "File",
@ -305,11 +306,12 @@
"LabelFinished": "Finita",
"LabelFolder": "Cartella",
"LabelFolders": "Cartelle",
"LabelFontBold": "Bold",
"LabelFontBold": "Grassetto",
"LabelFontBoldness": "Grassetto",
"LabelFontFamily": "Font family",
"LabelFontItalic": "Italic",
"LabelFontScale": "Dimensione Font",
"LabelFontStrikethrough": "Strikethrough",
"LabelFontStrikethrough": "Barrato",
"LabelFormat": "Formato",
"LabelGenre": "Genere",
"LabelGenres": "Generi",
@ -321,9 +323,9 @@
"LabelHour": "Ora",
"LabelIcon": "Icona",
"LabelImageURLFromTheWeb": "Immagine URL da internet",
"LabelInProgress": "In Corso",
"LabelIncludeInTracklist": "Includi nella Tracklist",
"LabelIncomplete": "Incompleta",
"LabelInProgress": "In Corso",
"LabelInterval": "Intervallo",
"LabelIntervalCustomDailyWeekly": "Personalizza giorni/settimane",
"LabelIntervalEvery12Hours": "Ogni 12 Ore",
@ -337,6 +339,7 @@
"LabelItem": "Oggetti",
"LabelLanguage": "Lingua",
"LabelLanguageDefaultServer": "Lingua di Default",
"LabelLanguages": "Lingua",
"LabelLastBookAdded": "Ultimo Libro Aggiunto",
"LabelLastBookUpdated": "Ultimo Libro Aggiornato",
"LabelLastSeen": "Ultimi Visti",
@ -348,11 +351,12 @@
"LabelLess": "Poco",
"LabelLibrariesAccessibleToUser": "Librerie Accessibili agli Utenti",
"LabelLibrary": "Libreria",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Elementi della Library",
"LabelLibraryName": "Nome Libreria",
"LabelLimit": "Limiti",
"LabelLineSpacing": "Interlinea",
"LabelListenAgain": "Ri-ascolta",
"LabelListenAgain": "Ascolta ancora",
"LabelLogLevelDebug": "Debug",
"LabelLogLevelInfo": "Info",
"LabelLogLevelWarn": "Allarme",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Utilizzato per connettere gli utenti esistenti. Una volta connessi, gli utenti verranno abbinati a un ID univoco dal tuo provider SSO",
"LabelMediaPlayer": "Media Player",
"LabelMediaType": "Tipo Media",
"LabelMetadataOrderOfPrecedenceDescription": "Le origini di metadati con priorità più alta sovrascriveranno le origini di metadati con priorità inferiore",
"LabelMetadataProvider": "Metadata Provider",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Le origini di metadati con priorità più alta sovrascriveranno le origini di metadati con priorità inferiore",
"LabelMetadataProvider": "Metadata Provider",
"LabelMinute": "Minuto",
"LabelMissing": "Altro",
"LabelMissingEbook": "Non ha ebook",
@ -378,29 +382,30 @@
"LabelNarrator": "Narratore",
"LabelNarrators": "Narratori",
"LabelNew": "Nuovo",
"LabelNewPassword": "Nuova Password",
"LabelNewestAuthors": "Autori Recenti",
"LabelNewestEpisodes": "Episodi Recenti",
"LabelNewPassword": "Nuova Password",
"LabelNextBackupDate": "Data Prossimo Backup",
"LabelNextScheduledRun": "Data prossima esecuzione schedulata",
"LabelNoCustomMetadataProviders": "Nessun provider di metadati personalizzato",
"LabelNoEpisodesSelected": "Nessun Episodio Selezionato",
"LabelNotes": "Note",
"LabelNotFinished": "Da Completare",
"LabelNotStarted": "Non iniziato",
"LabelNotes": "Note",
"LabelNotificationAppriseURL": "Apprendi URL(s)",
"LabelNotificationAvailableVariables": "Variabili Selezionabili",
"LabelNotificationBodyTemplate": "Template del corpo messaggio",
"LabelNotificationEvent": "Notifiche Eventi",
"LabelNotificationTitleTemplate": "Template del titolo",
"LabelNotificationsMaxFailedAttempts": "Numero massimo di tentativi falliti",
"LabelNotificationsMaxFailedAttemptsHelp": "Le notifiche vengono disabilitate se falliscono molte volte",
"LabelNotificationsMaxQueueSize": "Coda Massima di notifiche eventi",
"LabelNotificationsMaxQueueSizeHelp": "Le notifiche sono limitate per 1 al secondo, per evitare lo spamming le notifiche verrano ignorare se superano la coda",
"LabelNotificationTitleTemplate": "Template del titolo",
"LabelNotStarted": "Non iniziato",
"LabelNumberOfBooks": "Numero di libri",
"LabelNumberOfEpisodes": "# degli episodi",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
"LabelOpenIDClaims": "Leave the following options empty to disable advanced group and permissions assignment, automatically assigning 'User' group then.",
"LabelOpenIDGroupClaimDescription": "Name of the OpenID claim that contains a list of the user's groups. Commonly referred to as <code>groups</code>. <b>If configured</b>, the application will automatically assign roles based on the user's group memberships, provided that these groups are named case-insensitively 'admin', 'user', or 'guest' in the claim. The claim should contain a list, and if a user belongs to multiple groups, the application will assign the role corresponding to the highest level of access. If no group matches, access will be denied.",
"LabelOpenIDAdvancedPermsClaimDescription": "Nome dell'attestazione OpenID che contiene autorizzazioni avanzate per le azioni dell'utente all'interno dell'applicazione che verranno applicate ai ruoli non amministratori (<b>se configurato</b>). Se il reclamo manca nella risposta, l'accesso ad ABS verrà negato. Se manca una singola opzione, verrà trattata come<code>falsa</code>. Assicurati che l'attestazione del provider di identità corrisponda alla struttura prevista:",
"LabelOpenIDClaims": "Lasciare vuote le seguenti opzioni per disabilitare l'assegnazione avanzata di gruppi e autorizzazioni, assegnando quindi automaticamente il gruppo \"Utente\".",
"LabelOpenIDGroupClaimDescription": "Nome dell'attestazione OpenID che contiene un elenco dei gruppi dell'utente. Comunemente indicato come <code>gruppo</code>. <b>se configurato</b>, l'applicazione assegnerà automaticamente i ruoli in base alle appartenenze ai gruppi dell'utente, a condizione che tali gruppi siano denominati \"admin\", \"utente\" o \"ospite\" senza distinzione tra maiuscole e minuscole nell'attestazione. L'attestazione deve contenere un elenco e, se un utente appartiene a più gruppi, l'applicazione assegnerà il ruolo corrispondente al livello di accesso più alto. Se nessun gruppo corrisponde, l'accesso verrà negato.",
"LabelOpenRSSFeed": "Apri RSS Feed",
"LabelOverwrite": "Sovrascrivi",
"LabelPassword": "Password",
@ -412,14 +417,15 @@
"LabelPermissionsDownload": "Può Scaricare",
"LabelPermissionsUpdate": "Può Aggiornare",
"LabelPermissionsUpload": "Può caricare",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPersonalYearReview": "Il tuo anno in rassegna ({0})",
"LabelPhotoPathURL": "foto Path/URL",
"LabelPlaylists": "Playlists",
"LabelPlayMethod": "Metodo di riproduzione",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Playlists",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Area di ricerca podcast",
"LabelPodcastType": "Tipo di Podcast",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Suffissi da ignorare (specificando maiuscole e minuscole)",
"LabelPreventIndexing": "Impedisci che il tuo feed venga indicizzato da iTunes e dalle directory dei podcast di Google",
@ -427,32 +433,33 @@
"LabelProgress": "Cominciati",
"LabelProvider": "Provider",
"LabelPubDate": "Data Pubblicazione",
"LabelPublisher": "Editore",
"LabelPublishYear": "Anno Pubblicazione",
"LabelRead": "Leggi",
"LabelReadAgain": "Leggi Ancora",
"LabelReadEbookWithoutProgress": "Leggi l'ebook senza mantenere i progressi",
"LabelRecentlyAdded": "Aggiunti Recentemente",
"LabelRecentSeries": "Serie Recenti",
"LabelRecommended": "Raccomandati",
"LabelRedo": "Rifai",
"LabelRegion": "Regione",
"LabelReleaseDate": "Data Release",
"LabelRemoveCover": "Rimuovi cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Editore",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Email del proprietario personalizzato",
"LabelRSSFeedCustomOwnerName": "Nome del proprietario personalizzato",
"LabelRSSFeedOpen": "RSS Feed Aperto",
"LabelRSSFeedPreventIndexing": "Impedisci l'indicizzazione",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Leggi",
"LabelReadAgain": "Leggi Ancora",
"LabelReadEbookWithoutProgress": "Leggi l'ebook senza mantenere i progressi",
"LabelRecentSeries": "Serie Recenti",
"LabelRecentlyAdded": "Aggiunti Recentemente",
"LabelRecommended": "Raccomandati",
"LabelRedo": "Rifai",
"LabelRegion": "Regione",
"LabelReleaseDate": "Data Release",
"LabelRemoveCover": "Rimuovi cover",
"LabelRowsPerPage": "Righe per pagina",
"LabelSearchTerm": "Ricerca",
"LabelSearchTitle": "Cerca Titolo",
"LabelSearchTitleOrASIN": "Cerca titolo o ASIN",
"LabelSeason": "Stagione",
"LabelSelectAll": "Select all",
"LabelSelectAll": "Seleziona tutto",
"LabelSelectAllEpisodes": "Seleziona tutti gli Episodi",
"LabelSelectEpisodesShowing": "Episodi {0} selezionati ",
"LabelSelectEpisodesShowing": "Episodi {0} selezionati",
"LabelSelectUsers": "Selezione Utenti",
"LabelSendEbookToDevice": "Invia ebook a...",
"LabelSequence": "Sequenza",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Abilita Watcher",
"LabelSettingsEnableWatcherForLibrary": "Abilita il controllo cartelle per la libreria",
"LabelSettingsEnableWatcherHelp": "Abilita l'aggiunta/aggiornamento automatico degli elementi quando vengono rilevate modifiche ai file. *Richiede il riavvio del Server",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"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.",
"LabelSettingsExperimentalFeatures": "Opzioni Sperimentali",
"LabelSettingsExperimentalFeaturesHelp": "Funzionalità in fase di sviluppo che potrebbero utilizzare i tuoi feedback e aiutare i test. Fare clic per aprire la discussione github.",
"LabelSettingsFindCovers": "Trova covers",
@ -483,8 +490,8 @@
"LabelSettingsHideSingleBookSeriesHelp": "Le serie che hanno un solo libro saranno nascoste dalla pagina della serie e dagli scaffali della home page.",
"LabelSettingsHomePageBookshelfView": "Home page con sfondo legno",
"LabelSettingsLibraryBookshelfView": "Libreria con sfondo legno",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Skip earlier books in Continue Series",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "The Continue Series home page shelf shows the first book not started in series that have at least one book finished and no books in progress. Enabling this setting will continue series from the furthest completed book instead of the first book not started.",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Salta i libri precedenti nella serie Continua",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Lo scaffale della home page Continua serie mostra il primo libro non iniziato della serie che ha almeno un libro finito e nessun libro in corso. Abilitando questa impostazione le serie continueranno dal libro completato più lontano invece che dal primo libro non iniziato.",
"LabelSettingsParseSubtitles": "Analizza sottotitoli",
"LabelSettingsParseSubtitlesHelp": "Estrai i sottotitoli dai nomi delle cartelle degli audiolibri. <br> I sottotitoli devono essere separati da \" - \"<br> Per esempio \"Il signore degli anelli - Le due Torri \" avrà il sottotitolo \"Le due Torri\"",
"LabelSettingsPreferMatchedMetadata": "Preferisci i metadata trovati",
@ -501,14 +508,14 @@
"LabelSettingsStoreMetadataWithItemHelp": "Di default, i metadati sono salvati dentro /metadata/items, abilitando questa opzione si memorizzeranno i metadata nella cartella della libreria",
"LabelSettingsTimeFormat": "Formato Ora",
"LabelShowAll": "Mostra Tutto",
"LabelShowSeconds": "Show seconds",
"LabelShowSeconds": "Mostra i secondi",
"LabelSize": "Dimensione",
"LabelSleepTimer": "Sleep timer",
"LabelSlug": "Lento",
"LabelStart": "Inizo",
"LabelStartTime": "Tempo di inizio",
"LabelStarted": "Iniziato",
"LabelStartedAt": "Iniziato al",
"LabelStartTime": "Tempo di inizio",
"LabelStatsAudioTracks": "Tracce Audio",
"LabelStatsAuthors": "Autori",
"LabelStatsBestDay": "Giorno Migliore",
@ -534,11 +541,11 @@
"LabelTextEditorBulletedList": "Elenco puntato",
"LabelTextEditorLink": "Link",
"LabelTextEditorNumberedList": "Elenco Numerato",
"LabelTextEditorUnlink": "Unlink",
"LabelTextEditorUnlink": "Scollega",
"LabelTheme": "Tema",
"LabelThemeDark": "Scuro",
"LabelThemeLight": "Chiaro",
"LabelTimeBase": "Time Base",
"LabelTimeBase": "Tempo base",
"LabelTimeListened": "Tempo di Ascolto",
"LabelTimeListenedToday": "Tempo di Ascolto Oggi",
"LabelTimeRemaining": "{0} rimanente",
@ -560,13 +567,13 @@
"LabelTracksSingleTrack": "Traccia-singola",
"LabelType": "Tipo",
"LabelUnabridged": "Integrale",
"LabelUndo": "Undo",
"LabelUndo": "Annulla",
"LabelUnknown": "Sconosciuto",
"LabelUpdateCover": "Aggiornamento Cover",
"LabelUpdateCoverHelp": "Consenti la sovrascrittura delle copertine esistenti per i libri selezionati quando viene trovata una corrispondenza",
"LabelUpdatedAt": "Aggiornato alle",
"LabelUpdateDetails": "Dettagli Aggiornamento",
"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",
"LabelUploaderDropFiles": "Elimina file",
"LabelUploaderItemFetchMetadataHelp": "Recupera automaticamente titolo, autore e serie",
@ -581,8 +588,8 @@
"LabelViewQueue": "Visualizza coda",
"LabelVolume": "Volume",
"LabelWeekdaysToRun": "Giorni feriali da eseguire",
"LabelYearReviewHide": "Hide Year in Review",
"LabelYearReviewShow": "See Year in Review",
"LabelYearReviewHide": "Nascondi Anno in rassegna",
"LabelYearReviewShow": "Vedi Anno in rassegna",
"LabelYourAudiobookDuration": "La durata dell'audiolibro",
"LabelYourBookmarks": "I tuoi Preferiti",
"LabelYourPlaylists": "le tue Playlist",
@ -591,9 +598,10 @@
"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>.",
"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.",
"MessageBatchQuickMatchDescription": "Quick Match tenterà di aggiungere copertine e metadati mancanti per gli elementi selezionati. Attiva l'opzione per consentire a Quick Match di sovrascrivere copertine e/o metadati esistenti.",
"MessageBookshelfNoCollections": "Non hai ancora creato nessuna raccolta ",
"MessageBookshelfNoResultsForFilter": "Nessun risultato per il filtro \"{0}: {1}\"",
"MessageBookshelfNoCollections": "Non hai ancora creato nessuna raccolta",
"MessageBookshelfNoRSSFeeds": "Nessun RSS feeds aperto",
"MessageBookshelfNoResultsForFilter": "Nessun risultato per il filtro \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Nessun risultato per la query",
"MessageBookshelfNoSeries": "Non c'è nessuna Serie",
"MessageChapterEndIsAfter": "La fine del capitolo è dopo la fine del tuo audiolibro",
"MessageChapterErrorFirstNotZero": "Il primo capitolo deve iniziare da 0",
@ -605,7 +613,7 @@
"MessageConfirmDeleteBackup": "Sei sicuro di voler eliminare il backup {0}?",
"MessageConfirmDeleteFile": "Questo eliminerà il file dal tuo file system. Sei sicuro?",
"MessageConfirmDeleteLibrary": "Sei sicuro di voler eliminare definitivamente la libreria \"{0}\"?",
"MessageConfirmDeleteLibraryItem": " l'elemento della libreria dal database e dal file system. Sei sicuro?",
"MessageConfirmDeleteLibraryItem": "l'elemento della libreria dal database e dal file system. Sei sicuro?",
"MessageConfirmDeleteLibraryItems": "Ciò eliminerà {0} elementi della libreria dal database e dal file system. Sei sicuro?",
"MessageConfirmDeleteSession": "Sei sicuro di voler eliminare questa sessione?",
"MessageConfirmForceReScan": "Sei sicuro di voler forzare una nuova scansione?",
@ -613,13 +621,15 @@
"MessageConfirmMarkAllEpisodesNotFinished": "Sei sicuro di voler contrassegnare tutti gli episodi come non completati?",
"MessageConfirmMarkSeriesFinished": "Sei sicuro di voler contrassegnare tutti i libri di questa serie come completati?",
"MessageConfirmMarkSeriesNotFinished": "Sei sicuro di voler contrassegnare tutti i libri di questa serie come non completati?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeCache": "L'eliminazione della cache eliminerà l'intera directory dei <code>/metadata/cache</code>. <br /><br />Sei sicuro di voler rimuovere la directory della cache?",
"MessageConfirmPurgeItemsCache": "L'eliminazione della cache degli elementi eliminerà l'intera directory <code>/metadata/cache/oggetti</code>.<br />Sei sicuro?",
"MessageConfirmQuickEmbed": "Attenzione! L'incorporamento rapido non eseguirà il backup dei file audio. Assicurati di avere un backup dei tuoi file audio. <br><br>Vuoi Continuare?",
"MessageConfirmReScanLibraryItems": "Sei sicuro di voler ripetere la scansione? {0} oggetti?",
"MessageConfirmRemoveAllChapters": "Sei sicuro di voler rimuovere tutti i capitoli?",
"MessageConfirmRemoveAuthor": "Sei sicuro di voler rimuovere l'autore? \"{0}\"?",
"MessageConfirmRemoveCollection": "Sei sicuro di voler rimuovere la Raccolta \"{0}\"?",
"MessageConfirmRemoveEpisode": "Sei sicuro di voler rimuovere l'episodio \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Sei sicuro di voler rimuovere {0} episodi?",
"MessageConfirmRemoveEpisodes": "Sei sicuro di voler rimuovere {0} episodi?",
"MessageConfirmRemoveListeningSessions": "Sei sicuro di voler rimuovere {0} sessioni di Ascolto?",
"MessageConfirmRemoveNarrator": "Sei sicuro di voler rimuovere il narratore \"{0}\"?",
"MessageConfirmRemovePlaylist": "Sei sicuro di voler rimuovere la tua playlist \"{0}\"?",
@ -629,13 +639,12 @@
"MessageConfirmRenameTag": "Sei sicuro di voler rinominare il tag \"{0}\" in \"{1}\" per tutti gli oggetti?",
"MessageConfirmRenameTagMergeNote": "Nota: Questo tag esiste già e verrà unito nel vecchio.",
"MessageConfirmRenameTagWarning": "Avvertimento! Esiste già un tag simile con un nome simile \"{0}\".",
"MessageConfirmReScanLibraryItems": "Sei sicuro di voler ripetere la scansione? {0} oggetti?",
"MessageConfirmSendEbookToDevice": "Sei sicuro di voler inviare {0} ebook \"{1}\" al Device \"{2}\"?",
"MessageDownloadingEpisode": "Download episodio in corso",
"MessageDragFilesIntoTrackOrder": "Trascina i file nell'ordine di traccia corretto",
"MessageEmbedFinished": "Incorporamento finito!",
"MessageEpisodesQueuedForDownload": "{0} Episodio(i) in coda per il Download",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "Per garantire la consegna degli ebook, potrebbe essere necessario aggiungere l'indirizzo e-mail sopra indicato come mittente valido per ciascun dispositivo elencato di seguito.",
"MessageFeedURLWillBe": "Feed URL Saranno {0}",
"MessageFetching": "Recupero Info...",
"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.",
@ -647,7 +656,7 @@
"MessageListeningSessionsInTheLastYear": "{0} sessioni di ascolto nell'ultimo anno",
"MessageLoading": "Caricamento...",
"MessageLoadingFolders": "Caricamento Cartelle...",
"MessageLogsDescription": "Logs are stored in <code>/metadata/logs</code> as JSON files. Crash logs are stored in <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "I log vengono archiviati nel percorso <code>/metadata/logs</code> as JSON files. I registri degli arresti anomali vengono archiviati nel percorso <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "M4B Fallito!",
"MessageM4BFinished": "M4B Finito!",
"MessageMapChapterTitles": "Associa i titoli dei capitoli ai capitoli dell'audiolibro esistente senza modificare i timestamp",
@ -683,10 +692,10 @@
"MessageNoSeries": "Nessuna Serie",
"MessageNoTags": "Nessun Tags",
"MessageNoTasksRunning": "Nessun processo in esecuzione",
"MessageNotYetImplemented": "Non Ancora Implementato",
"MessageNoUpdateNecessary": "Nessun aggiornamento necessario",
"MessageNoUpdatesWereNecessary": "Nessun aggiornamento necessario",
"MessageNoUserPlaylists": "non hai nessuna Playlist",
"MessageNotYetImplemented": "Non Ancora Implementato",
"MessageOr": "o",
"MessagePauseChapter": "Metti in Pausa Capitolo",
"MessagePlayChapter": "Ascolta dall'inizio del capitolo",
@ -751,8 +760,8 @@
"ToastBookmarkRemoveSuccess": "Segnalibro Rimosso",
"ToastBookmarkUpdateFailed": "Aggiornamento Segnalibro fallito",
"ToastBookmarkUpdateSuccess": "Segnalibro aggiornato",
"ToastCachePurgeFailed": "Failed to purge cache",
"ToastCachePurgeSuccess": "Cache purged successfully",
"ToastCachePurgeFailed": "Impossibile eliminare la cache",
"ToastCachePurgeSuccess": "Cache eliminata correttamente",
"ToastChaptersHaveErrors": "I capitoli contengono errori",
"ToastChaptersMustHaveTitles": "I capitoli devono avere titoli",
"ToastCollectionItemsRemoveFailed": "Rimozione oggetti dalla Raccolta fallita",
@ -761,9 +770,9 @@
"ToastCollectionRemoveSuccess": "Collezione rimossa",
"ToastCollectionUpdateFailed": "Errore aggiornamento Raccolta",
"ToastCollectionUpdateSuccess": "Raccolta aggiornata",
"ToastDeleteFileFailed": "Failed to delete file",
"ToastDeleteFileSuccess": "File deleted",
"ToastFailedToLoadData": "Failed to load data",
"ToastDeleteFileFailed": "Impossibile eliminare il file",
"ToastDeleteFileSuccess": "File eliminato",
"ToastFailedToLoadData": "Impossibile caricare i dati",
"ToastItemCoverUpdateFailed": "Errore Aggiornamento cover",
"ToastItemCoverUpdateSuccess": "Cover aggiornata",
"ToastItemDetailsUpdateFailed": "Errore Aggiornamento dettagli file",
@ -789,24 +798,24 @@
"ToastPlaylistUpdateSuccess": "Playlist Aggiornata",
"ToastPodcastCreateFailed": "Errore Creazione podcast",
"ToastPodcastCreateSuccess": "Podcast creato Correttamente",
"ToastRemoveItemFromCollectionFailed": "Errore rimozione file dalla Raccolta",
"ToastRemoveItemFromCollectionSuccess": "Oggetto rimosso dalla Raccolta",
"ToastRSSFeedCloseFailed": "Errore chiusura RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed chiuso",
"ToastRemoveItemFromCollectionFailed": "Errore rimozione file dalla Raccolta",
"ToastRemoveItemFromCollectionSuccess": "Oggetto rimosso dalla Raccolta",
"ToastSendEbookToDeviceFailed": "Impossibile inviare l'ebook al dispositivo",
"ToastSendEbookToDeviceSuccess": "Ebook inviato al dispositivo \"{0}\"",
"ToastSeriesUpdateFailed": "Aggiornamento Serie Fallito",
"ToastSeriesUpdateSuccess": "Serie Aggiornate",
"ToastServerSettingsUpdateFailed": "Failed to update server settings",
"ToastServerSettingsUpdateSuccess": "Server settings updated",
"ToastServerSettingsUpdateFailed": "Impossibile aggiornare le impostazioni del server",
"ToastServerSettingsUpdateSuccess": "Impostazioni del server aggiornate",
"ToastSessionDeleteFailed": "Errore eliminazione sessione",
"ToastSessionDeleteSuccess": "Sessione cancellata",
"ToastSocketConnected": "Socket connesso",
"ToastSocketDisconnected": "Socket disconnesso",
"ToastSocketFailedToConnect": "Socket non riesce a connettersi",
"ToastSortingPrefixesEmptyError": "Must have at least 1 sorting prefix",
"ToastSortingPrefixesUpdateFailed": "Failed to update sorting prefixes",
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastSortingPrefixesEmptyError": "Deve avere almeno 1 prefisso di ordinamento",
"ToastSortingPrefixesUpdateFailed": "Impossibile aggiornare i prefissi di ordinamento",
"ToastSortingPrefixesUpdateSuccess": "Prefissi di ordinamento aggiornati ({0} items)",
"ToastUserDeleteFailed": "Errore eliminazione utente",
"ToastUserDeleteSuccess": "Utente eliminato"
}
}

View File

@ -1,14 +1,15 @@
{
"ButtonAdd": "Pridėti",
"ButtonAddChapters": "Pridėti skyrius",
"ButtonAddDevice": "Add Device",
"ButtonAddLibrary": "Add Library",
"ButtonAddDevice": "Pridėti įrenginį",
"ButtonAddLibrary": "Pridėti Biblioteką",
"ButtonAddPodcasts": "Pridėti tinklalaides",
"ButtonAddUser": "Add User",
"ButtonAddUser": "Pridėti Vartotoją",
"ButtonAddYourFirstLibrary": "Pridėkite savo pirmąją biblioteką",
"ButtonApply": "Taikyti",
"ButtonApplyChapters": "Taikyti skyrius",
"ButtonAuthors": "Autoriai",
"ButtonBack": "Atgal",
"ButtonBrowseForFolder": "Naršyti aplanko",
"ButtonCancel": "Atšaukti",
"ButtonCancelEncode": "Atšaukti kodavimą",
@ -44,7 +45,7 @@
"ButtonMatchBooks": "Pritaikyti knygas",
"ButtonNevermind": "Nesvarbu",
"ButtonNext": "Next",
"ButtonNextChapter": "Next Chapter",
"ButtonNextChapter": "Kitas Skyrius",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Atidaryti srautą",
"ButtonOpenManager": "Atidaryti tvarkyklę",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Valyti visą saugyklą",
"ButtonPurgeItemsCache": "Valyti elementų saugyklą",
"ButtonPurgeMediaProgress": "Valyti medijos progresą",
"ButtonQueueAddItem": "Pridėti į eilę",
"ButtonQueueRemoveItem": "Pašalinti iš eilės",
"ButtonQuickMatch": "Greitas pritaikymas",
"ButtonReScan": "Iš naujo nuskaityti",
"ButtonRead": "Skaityti",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Pašalinti iš Tęsti Klausimą",
"ButtonRemoveFromContinueReading": "Pašalinti iš Tęsti Skaitymą",
"ButtonRemoveSeriesFromContinueSeries": "Pašalinti seriją iš Tęsti Seriją",
"ButtonReScan": "Iš naujo nuskaityti",
"ButtonReset": "Atstatyti",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "Atkurti",
@ -104,8 +104,8 @@
"HeaderAccount": "Paskyra",
"HeaderAdvanced": "Papildomi",
"HeaderAppriseNotificationSettings": "Apprise pranešimo nustatymai",
"HeaderAudiobookTools": "Audioknygų failų valdymo įrankiai",
"HeaderAudioTracks": "Garso takeliai",
"HeaderAudiobookTools": "Audioknygų failų valdymo įrankiai",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Atsarginės kopijos",
"HeaderChangePassword": "Pakeisti slaptažodį",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Kolekcijos elementai",
"HeaderCover": "Viršelis",
"HeaderCurrentDownloads": "Dabartiniai parsisiuntimai",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Detalės",
"HeaderDownloadQueue": "Parsisiuntimo eilė",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Grojaraščio elementai",
"HeaderPodcastsToAdd": "Pridėti tinklalaides",
"HeaderPreviewCover": "Peržiūrėti viršelį",
"HeaderRemoveEpisode": "Pašalinti epizodą",
"HeaderRemoveEpisodes": "Pašalinti {0} epizodus",
"HeaderRSSFeedGeneral": "RSS informacija",
"HeaderRSSFeedIsOpen": "RSS srautas yra atidarytas",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Pašalinti epizodą",
"HeaderRemoveEpisodes": "Pašalinti {0} epizodus",
"HeaderSavedMediaProgress": "Išsaugota medijos pažanga",
"HeaderSchedule": "Tvarkaraštis",
"HeaderScheduleLibraryScans": "Nustatyti bibliotekų nuskaitymo tvarkaraštį",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Svečias",
"LabelAccountTypeUser": "Naudotojas",
"LabelActivity": "Veikla",
"LabelAdded": "Pridėta",
"LabelAddedAt": "Pridėta {0}",
"LabelAddToCollection": "Pridėti į kolekciją",
"LabelAddToCollectionBatch": "Pridėti {0} knygas į kolekciją",
"LabelAddToPlaylist": "Pridėti į grojaraštį",
"LabelAddToPlaylistBatch": "Pridėti {0} elementus į grojaraštį",
"LabelAdded": "Pridėta",
"LabelAddedAt": "Pridėta {0}",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "Visi",
"LabelAllUsers": "Visi naudotojai",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Pakeisti slaptažodį",
"LabelChannels": "Kanalai",
"LabelChapterTitle": "Skyriaus pavadinimas",
"LabelChapters": "Skyriai",
"LabelChaptersFound": "rasti skyriai",
"LabelChapterTitle": "Skyriaus pavadinimas",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Uždaryti grotuvą",
"LabelCodec": "Kodekas",
@ -306,6 +307,7 @@
"LabelFolder": "Aplankas",
"LabelFolders": "Aplankai",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Famiglia di font",
"LabelFontItalic": "Italic",
"LabelFontScale": "Šrifto mastelis",
@ -321,9 +323,9 @@
"LabelHour": "Valanda",
"LabelIcon": "Piktograma",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "Vyksta",
"LabelIncludeInTracklist": "Įtraukti į takelių sąrašą",
"LabelIncomplete": "Nebaigta",
"LabelInProgress": "Vyksta",
"LabelInterval": "Intervalas",
"LabelIntervalCustomDailyWeekly": "Pasirinktinis kasdieninės/savaitinės periodiškumas",
"LabelIntervalEvery12Hours": "Kas 12 valandų",
@ -337,6 +339,7 @@
"LabelItem": "Elementas",
"LabelLanguage": "Kalba",
"LabelLanguageDefaultServer": "Numatytoji serverio kalba",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Paskutinė pridėta knyga",
"LabelLastBookUpdated": "Paskutinė atnaujinta knyga",
"LabelLastSeen": "Paskutinį kartą matyta",
@ -348,6 +351,7 @@
"LabelLess": "Mažiau",
"LabelLibrariesAccessibleToUser": "Naudotojui pasiekiamos bibliotekos",
"LabelLibrary": "Biblioteka",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Bibliotekos elementas",
"LabelLibraryName": "Bibliotekos pavadinimas",
"LabelLimit": "Limitas",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Grotuvas",
"LabelMediaType": "Medijos tipas",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metaduomenų tiekėjas",
"LabelMetaTag": "Meta žymė",
"LabelMetaTags": "Meta žymos",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metaduomenų tiekėjas",
"LabelMinute": "Minutė",
"LabelMissing": "Trūksta",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Skaitytojas",
"LabelNarrators": "Skaitytojai",
"LabelNew": "Nauja",
"LabelNewPassword": "Naujas slaptažodis",
"LabelNewestAuthors": "Naujausi autoriai",
"LabelNewestEpisodes": "Naujausi epizodai",
"LabelNewPassword": "Naujas slaptažodis",
"LabelNextBackupDate": "Kitos atsarginės kopijos data",
"LabelNextScheduledRun": "Kito planuoto vykdymo data",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Nepasirinkti jokie epizodai",
"LabelNotes": "Užrašai",
"LabelNotFinished": "Nebaigta",
"LabelNotStarted": "Nepasileista",
"LabelNotes": "Užrašai",
"LabelNotificationAppriseURL": "Pranešimo (Apprise) URL",
"LabelNotificationAvailableVariables": "Galimi kintamieji",
"LabelNotificationBodyTemplate": "Turinio šablonas",
"LabelNotificationEvent": "Pranešimo įvykis",
"LabelNotificationTitleTemplate": "Pavadinimo šablonas",
"LabelNotificationsMaxFailedAttempts": "Maksimalus nesėkmingų bandymų skaičius",
"LabelNotificationsMaxFailedAttemptsHelp": "Pranešimai bus išjungti, jei nepavyks jų išsiųsti nurodytą kartų",
"LabelNotificationsMaxQueueSize": "Maksimalus pranešimų eilių dydis",
"LabelNotificationsMaxQueueSizeHelp": "Įvykiai yra apriboti vienu įvykiu per sekundę. Įvykiai bus ignoruojami, jei eilė yra maksimalaus dydžio. Tai apsaugo nuo pranešimų šlamšto.",
"LabelNotificationTitleTemplate": "Pavadinimo šablonas",
"LabelNotStarted": "Nepasileista",
"LabelNumberOfBooks": "Knygų skaičius",
"LabelNumberOfEpisodes": "Epizodų skaičius",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Gali įkelti",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Nuotraukos kelias/URL",
"LabelPlaylists": "Grojaraščiai",
"LabelPlayMethod": "Grojimo metodas",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Grojaraščiai",
"LabelPodcast": "Tinklalaidė",
"LabelPodcasts": "Tinklalaidės",
"LabelPodcastSearchRegion": "Podcast paieškos regionas",
"LabelPodcastType": "Tinklalaidės tipas",
"LabelPodcasts": "Tinklalaidės",
"LabelPort": "Prievadas",
"LabelPrefixesToIgnore": "Ignoruojami priešdėliai (didžiosios/mažosios nesvarbu)",
"LabelPreventIndexing": "Neleisti indeksuoti jūsų srauto „iTunes“ ir Google podcast kataloguose",
@ -427,25 +433,26 @@
"LabelProgress": "Progresas",
"LabelProvider": "Tiekėjas",
"LabelPubDate": "Publikavimo data",
"LabelPublisher": "Leidėjas",
"LabelPublishYear": "Leidimo metai",
"LabelRead": "Skaityta",
"LabelReadAgain": "Skaityti dar kartą",
"LabelReadEbookWithoutProgress": "Skaityti e-knygą be pažangos saugojimo",
"LabelRecentlyAdded": "Neseniai pridėta",
"LabelRecentSeries": "Naujausios serijos",
"LabelRecommended": "Rekomenduojama",
"LabelRedo": "Redo",
"LabelRegion": "Regionas",
"LabelReleaseDate": "Išleidimo data",
"LabelRemoveCover": "Pašalinti viršelį",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Leidėjas",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Pasirinktinis savininko el. paštas",
"LabelRSSFeedCustomOwnerName": "Pasirinktinis savininko vardas",
"LabelRSSFeedOpen": "Atidarytas RSS srautas",
"LabelRSSFeedPreventIndexing": "Neleisti indeksuoti",
"LabelRSSFeedSlug": "RSS srauto identifikatorius",
"LabelRSSFeedURL": "RSS srauto URL",
"LabelRead": "Skaityta",
"LabelReadAgain": "Skaityti dar kartą",
"LabelReadEbookWithoutProgress": "Skaityti e-knygą be pažangos saugojimo",
"LabelRecentSeries": "Naujausios serijos",
"LabelRecentlyAdded": "Neseniai pridėta",
"LabelRecommended": "Rekomenduojama",
"LabelRedo": "Redo",
"LabelRegion": "Regionas",
"LabelReleaseDate": "Išleidimo data",
"LabelRemoveCover": "Pašalinti viršelį",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Paieškos žodis",
"LabelSearchTitle": "Ieškoti pavadinimo",
"LabelSearchTitleOrASIN": "Ieškoti pavadinimo arba ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Miego laikmatis",
"LabelSlug": "Slug",
"LabelStart": "Pradėti",
"LabelStartTime": "Pradžios laikas",
"LabelStarted": "Pradėta",
"LabelStartedAt": "Pradėta",
"LabelStartTime": "Pradžios laikas",
"LabelStatsAudioTracks": "Garsiniai takeliai",
"LabelStatsAuthors": "Autoriai",
"LabelStatsBestDay": "Geriausia diena",
@ -564,9 +571,9 @@
"LabelUnknown": "Nežinoma",
"LabelUpdateCover": "Atnaujinti viršelį",
"LabelUpdateCoverHelp": "Leisti perrašyti esamus viršelius pasirinktoms knygoms, kai yra rasta atitikmenų",
"LabelUpdatedAt": "Atnaujinta",
"LabelUpdateDetails": "Atnaujinti duomenis",
"LabelUpdateDetailsHelp": "Leisti perrašyti esamus duomenis pasirinktoms knygoms, kai yra rasta atitikmenų",
"LabelUpdatedAt": "Atnaujinta",
"LabelUploaderDragAndDrop": "Tempkite ir paleiskite failus ar aplankus",
"LabelUploaderDropFiles": "Nutempti failus",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Atsarginės kopijos apima vartotojus, vartotojų pažangą, bibliotekos elemento informaciją, serverio nustatymus ir vaizdus, saugomus <code>/metadata/items</code> ir <code>/metadata/authors</code>. Atsarginės kopijos <strong>neįtraukia</strong> jokių failų, saugomų jūsų bibliotekos aplankuose.",
"MessageBatchQuickMatchDescription": "Greitas atitikmens rasti bandys pridėti trūkstamus viršelius ir metaduomenis pasirinktiems elementams. Įjunkite žemiau esančias parinktis, kad leistumėte Greitajam atitikmeniui perrašyti esamus viršelius ir/ar metaduomenis.",
"MessageBookshelfNoCollections": "Dar nepridėjote jokių kolekcijų",
"MessageBookshelfNoResultsForFilter": "Rezultatų pagal filtrą \"{0}: {1}\" nėra",
"MessageBookshelfNoRSSFeeds": "Nėra atvertų RSS srautų",
"MessageBookshelfNoResultsForFilter": "Rezultatų pagal filtrą \"{0}: {1}\" nėra",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Neturite jokių serijų",
"MessageChapterEndIsAfter": "Skyriaus pabaiga yra po jūsų garso knygos pabaigos",
"MessageChapterErrorFirstNotZero": "Pirmasis skyrius turi prasidėti nuo 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Ar tikrai norite pažymėti visas knygas šioje serijoje kaip užbaigtas?",
"MessageConfirmMarkSeriesNotFinished": "Ar tikrai norite pažymėti visas knygas šioje serijoje kaip nebaigtas?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Ar tikrai norite pašalinti visus skyrius?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Ar tikrai norite pašalinti kolekciją \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Ar tikrai norite pervadinti žymą \"{0}\" į \"{1}\" visiems elementams?",
"MessageConfirmRenameTagMergeNote": "Pastaba: ši žyma jau egzistuoja, todėl jos bus sujungtos.",
"MessageConfirmRenameTagWarning": "Įspėjimas! Panaši žyma jau egzistuoja \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Ar tikrai norite nusiųsti {0} el. knygą \"{1}\" į įrenginį \"{2}\"?",
"MessageDownloadingEpisode": "Epizodas atsisiunčiamas",
"MessageDragFilesIntoTrackOrder": "Surikiuokite takelius vilkdami failus",
@ -683,10 +692,10 @@
"MessageNoSeries": "Serijų nėra",
"MessageNoTags": "Žymų nėra",
"MessageNoTasksRunning": "Nėra vykstančių užduočių",
"MessageNotYetImplemented": "Dar neįgyvendinta",
"MessageNoUpdateNecessary": "Atnaujinimai nereikalingi",
"MessageNoUpdatesWereNecessary": "Nereikalingi jokie atnaujinimai",
"MessageNoUserPlaylists": "Neturite grojaraščių",
"MessageNotYetImplemented": "Dar neįgyvendinta",
"MessageOr": "arba",
"MessagePauseChapter": "Pristabdyti skyriaus grojimą",
"MessagePlayChapter": "Paklausyti skyriaus pradžios",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Grojaraštis atnaujintas",
"ToastPodcastCreateFailed": "Tinklalaidės sukurti nepavyko",
"ToastPodcastCreateSuccess": "Tinklalaidė sėkmingai sukurta",
"ToastRemoveItemFromCollectionFailed": "Elemento pašalinti iš kolekcijos nepavyko",
"ToastRemoveItemFromCollectionSuccess": "Elementas pašalintas iš kolekcijos",
"ToastRSSFeedCloseFailed": "RSS srauto uždaryti nepavyko",
"ToastRSSFeedCloseSuccess": "RSS srautas uždarytas",
"ToastRemoveItemFromCollectionFailed": "Elemento pašalinti iš kolekcijos nepavyko",
"ToastRemoveItemFromCollectionSuccess": "Elementas pašalintas iš kolekcijos",
"ToastSendEbookToDeviceFailed": "Nepavyko nusiųsti e-knygos į įrenginį",
"ToastSendEbookToDeviceSuccess": "E-knyga išsiųsta į įrenginį \"{0}\"",
"ToastSeriesUpdateFailed": "Serijos atnaujinti nepavyko",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Nepavyko ištrinti naudotojo",
"ToastUserDeleteSuccess": "Naudotojas ištrintas"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Pas toe",
"ButtonApplyChapters": "Hoofdstukken toepassen",
"ButtonAuthors": "Auteurs",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Bladeren naar map",
"ButtonCancel": "Annuleren",
"ButtonCancelEncode": "Encoding annuleren",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Volledige cache legen",
"ButtonPurgeItemsCache": "Onderdelen-cache legen",
"ButtonPurgeMediaProgress": "Mediavoortgang legen",
"ButtonQueueAddItem": "In wachtrij zetten",
"ButtonQueueRemoveItem": "Uit wachtrij verwijderen",
"ButtonQuickMatch": "Snelle match",
"ButtonReScan": "Nieuwe scan",
"ButtonRead": "Lees",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Vewijder uit Verder luisteren",
"ButtonRemoveFromContinueReading": "Remove from Continue Reading",
"ButtonRemoveSeriesFromContinueSeries": "Verwijder serie uit Serie vervolgen",
"ButtonReScan": "Nieuwe scan",
"ButtonReset": "Reset",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "Herstel",
@ -104,8 +104,8 @@
"HeaderAccount": "Account",
"HeaderAdvanced": "Geavanceerd",
"HeaderAppriseNotificationSettings": "Apprise-notificatie instellingen",
"HeaderAudiobookTools": "Audioboekbestandbeheer tools",
"HeaderAudioTracks": "Audiotracks",
"HeaderAudiobookTools": "Audioboekbestandbeheer tools",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Back-ups",
"HeaderChangePassword": "Wachtwoord wijzigen",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Collectie-objecten",
"HeaderCover": "Cover",
"HeaderCurrentDownloads": "Huidige downloads",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Details",
"HeaderDownloadQueue": "Download-wachtrij",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Onderdelen in afspeellijst",
"HeaderPodcastsToAdd": "Toe te voegen podcasts",
"HeaderPreviewCover": "Preview cover",
"HeaderRemoveEpisode": "Aflevering verwijderen",
"HeaderRemoveEpisodes": "Verwijder {0} afleveringen",
"HeaderRSSFeedGeneral": "RSS-details",
"HeaderRSSFeedIsOpen": "RSS-feed is open",
"HeaderRSSFeeds": "RSS-feeds",
"HeaderRemoveEpisode": "Aflevering verwijderen",
"HeaderRemoveEpisodes": "Verwijder {0} afleveringen",
"HeaderSavedMediaProgress": "Opgeslagen mediavoortgang",
"HeaderSchedule": "Schema",
"HeaderScheduleLibraryScans": "Schema automatische bibliotheekscans",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gast",
"LabelAccountTypeUser": "Gebruiker",
"LabelActivity": "Activiteit",
"LabelAdded": "Toegevoegd",
"LabelAddedAt": "Toegevoegd op",
"LabelAddToCollection": "Toevoegen aan collectie",
"LabelAddToCollectionBatch": "{0} boeken toevoegen aan collectie",
"LabelAddToPlaylist": "Toevoegen aan afspeellijst",
"LabelAddToPlaylistBatch": "{0} onderdelen toevoegen aan afspeellijst",
"LabelAdded": "Toegevoegd",
"LabelAddedAt": "Toegevoegd op",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "Alle",
"LabelAllUsers": "Alle gebruikers",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Wachtwoord wijzigen",
"LabelChannels": "Kanalen",
"LabelChapterTitle": "Hoofdstuktitel",
"LabelChapters": "Hoofdstukken",
"LabelChaptersFound": "Hoofdstukken gevonden",
"LabelChapterTitle": "Hoofdstuktitel",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Sluit speler",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Map",
"LabelFolders": "Mappen",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Lettertypefamilie",
"LabelFontItalic": "Italic",
"LabelFontScale": "Lettertype schaal",
@ -321,9 +323,9 @@
"LabelHour": "Uur",
"LabelIcon": "Icoon",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "Bezig",
"LabelIncludeInTracklist": "Includeer in tracklijst",
"LabelIncomplete": "Incompleet",
"LabelInProgress": "Bezig",
"LabelInterval": "Interval",
"LabelIntervalCustomDailyWeekly": "Aangepast dagelijks/wekelijks",
"LabelIntervalEvery12Hours": "Iedere 12 uur",
@ -337,6 +339,7 @@
"LabelItem": "Onderdeel",
"LabelLanguage": "Taal",
"LabelLanguageDefaultServer": "Standaard servertaal",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Laatst toegevoegde boek",
"LabelLastBookUpdated": "Laatst bijgewerkte boek",
"LabelLastSeen": "Laatst gezien",
@ -348,6 +351,7 @@
"LabelLess": "Minder",
"LabelLibrariesAccessibleToUser": "Voor gebruiker toegankelijke bibliotheken",
"LabelLibrary": "Bibliotheek",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Bibliotheekonderdeel",
"LabelLibraryName": "Bibliotheeknaam",
"LabelLimit": "Limiet",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Mediaspeler",
"LabelMediaType": "Mediatype",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadatabron",
"LabelMetaTag": "Meta-tag",
"LabelMetaTags": "Meta-tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadatabron",
"LabelMinute": "Minuut",
"LabelMissing": "Ontbrekend",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Verteller",
"LabelNarrators": "Vertellers",
"LabelNew": "Nieuw",
"LabelNewPassword": "Nieuw wachtwoord",
"LabelNewestAuthors": "Nieuwste auteurs",
"LabelNewestEpisodes": "Nieuwste afleveringen",
"LabelNewPassword": "Nieuw wachtwoord",
"LabelNextBackupDate": "Volgende back-up datum",
"LabelNextScheduledRun": "Volgende geplande run",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Geen afleveringen geselecteerd",
"LabelNotes": "Notities",
"LabelNotFinished": "Niet Voltooid",
"LabelNotStarted": "Niet Gestart",
"LabelNotes": "Notities",
"LabelNotificationAppriseURL": "Apprise URL(s)",
"LabelNotificationAvailableVariables": "Beschikbare variabelen",
"LabelNotificationBodyTemplate": "Body-template",
"LabelNotificationEvent": "Notificatie gebeurtenis",
"LabelNotificationTitleTemplate": "Titel-template",
"LabelNotificationsMaxFailedAttempts": "Max mislukte pogingen",
"LabelNotificationsMaxFailedAttemptsHelp": "Notificaties worden uitgeschakeld als verzenden zo vaak mislukt",
"LabelNotificationsMaxQueueSize": "Max rijgrootte voor notificatie gebeurtenissen",
"LabelNotificationsMaxQueueSizeHelp": "Gebeurtenissen zijn beperkt tot 1 aftrap per seconde. Gebeurtenissen zullen genegeerd worden als de rij aan de maximale grootte zit. Dit voorkomt notificatie-spamming.",
"LabelNotificationTitleTemplate": "Titel-template",
"LabelNotStarted": "Niet Gestart",
"LabelNumberOfBooks": "Aantal Boeken",
"LabelNumberOfEpisodes": "# afleveringen",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Kan uploaden",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Foto pad/URL",
"LabelPlaylists": "Afspeellijsten",
"LabelPlayMethod": "Afspeelwijze",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Afspeellijsten",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Podcast zoekregio",
"LabelPodcastType": "Podcasttype",
"LabelPodcasts": "Podcasts",
"LabelPort": "Poort",
"LabelPrefixesToIgnore": "Te negeren voorzetsels (ongeacht hoofdlettergebruik)",
"LabelPreventIndexing": "Voorkom indexering van je feed door iTunes- en Google podcastmappen",
@ -427,25 +433,26 @@
"LabelProgress": "Voortgang",
"LabelProvider": "Bron",
"LabelPubDate": "Publicatiedatum",
"LabelPublisher": "Uitgever",
"LabelPublishYear": "Jaar van uitgave",
"LabelRead": "Lees",
"LabelReadAgain": "Lees opnieuw",
"LabelReadEbookWithoutProgress": "Lees ebook zonder voortgang bij te houden",
"LabelRecentlyAdded": "Recent toegevoegd",
"LabelRecentSeries": "Recente series",
"LabelRecommended": "Aangeraden",
"LabelRedo": "Redo",
"LabelRegion": "Regio",
"LabelReleaseDate": "Verschijningsdatum",
"LabelRemoveCover": "Verwijder cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Uitgever",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Aangepast e-mailadres eigenaar",
"LabelRSSFeedCustomOwnerName": "Aangepaste naam eigenaar",
"LabelRSSFeedOpen": "RSS-feed open",
"LabelRSSFeedPreventIndexing": "Voorkom indexering",
"LabelRSSFeedSlug": "RSS-feed slug",
"LabelRSSFeedURL": "RSS-feed URL",
"LabelRead": "Lees",
"LabelReadAgain": "Lees opnieuw",
"LabelReadEbookWithoutProgress": "Lees ebook zonder voortgang bij te houden",
"LabelRecentSeries": "Recente series",
"LabelRecentlyAdded": "Recent toegevoegd",
"LabelRecommended": "Aangeraden",
"LabelRedo": "Redo",
"LabelRegion": "Regio",
"LabelReleaseDate": "Verschijningsdatum",
"LabelRemoveCover": "Verwijder cover",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Zoekterm",
"LabelSearchTitle": "Zoek titel",
"LabelSearchTitleOrASIN": "Zoek titel of ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Slaaptimer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Starttijd",
"LabelStarted": "Gestart",
"LabelStartedAt": "Gestart op",
"LabelStartTime": "Starttijd",
"LabelStatsAudioTracks": "Audiotracks",
"LabelStatsAuthors": "Auteurs",
"LabelStatsBestDay": "Beste dag",
@ -564,9 +571,9 @@
"LabelUnknown": "Onbekend",
"LabelUpdateCover": "Cover bijwerken",
"LabelUpdateCoverHelp": "Sta overschrijven van bestaande covers toe voor de geselecteerde boeken wanneer een match is gevonden",
"LabelUpdatedAt": "Bijgewerkt op",
"LabelUpdateDetails": "Details bijwerken",
"LabelUpdateDetailsHelp": "Sta overschrijven van bestaande details toe voor de geselecteerde boeken wanneer een match is gevonden",
"LabelUpdatedAt": "Bijgewerkt op",
"LabelUploaderDragAndDrop": "Slepen & neerzeten van bestanden of mappen",
"LabelUploaderDropFiles": "Bestanden neerzetten",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Back-ups omvatten gebruikers, gebruikers' voortgang, bibliotheekonderdeeldetails, serverinstellingen en afbeeldingen bewaard in <code>/metadata/items</code> & <code>/metadata/authors</code>. Back-ups <strong>bevatten niet</strong> de bestanden bewaard in je bibliotheekmappen.",
"MessageBatchQuickMatchDescription": "Quick Match zal proberen ontbrekende covers en metadata voor de geselecteerde onderdelen te matchten. Schakel de opties hieronder in om Quick Match toe te staan bestaande covers en/of metadata te overschrijven.",
"MessageBookshelfNoCollections": "Je hebt nog geen collecties gemaakt",
"MessageBookshelfNoResultsForFilter": "Geen resultaten voor filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Geen RSS-feeds geopend",
"MessageBookshelfNoResultsForFilter": "Geen resultaten voor filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Je hebt geen series",
"MessageChapterEndIsAfter": "Hoofdstukeinde is na het einde van je audioboek",
"MessageChapterErrorFirstNotZero": "Eerste hoofdstuk moet starten op 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Weet je zeker dat je alle boeken in deze serie wil markeren als voltooid?",
"MessageConfirmMarkSeriesNotFinished": "Weet je zeker dat je alle boeken in deze serie wil markeren als niet voltooid?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Weet je zeker dat je alle hoofdstukken wil verwijderen?",
"MessageConfirmRemoveAuthor": "Weet je zeker dat je auteur \"{0}\" wil verwijderen?",
"MessageConfirmRemoveCollection": "Weet je zeker dat je de collectie \"{0}\" wil verwijderen?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Weet je zeker dat je tag \"{0}\" wil hernoemen naar\"{1}\" voor alle onderdelen?",
"MessageConfirmRenameTagMergeNote": "Opmerking: Deze tag bestaat al, dus zullen ze worden samengevoegd.",
"MessageConfirmRenameTagWarning": "Waarschuwing! Een gelijknamige tag met ander hoofdlettergebruik bestaat al: \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Weet je zeker dat je {0} ebook \"{1}\" naar apparaat \"{2}\" wil sturen?",
"MessageDownloadingEpisode": "Aflevering aan het dowloaden",
"MessageDragFilesIntoTrackOrder": "Sleep bestanden in de juiste trackvolgorde",
@ -683,10 +692,10 @@
"MessageNoSeries": "Geen series",
"MessageNoTags": "Geen tags",
"MessageNoTasksRunning": "Geen lopende taken",
"MessageNotYetImplemented": "Nog niet geimplementeerd",
"MessageNoUpdateNecessary": "Geen bijwerking noodzakelijk",
"MessageNoUpdatesWereNecessary": "Geen bijwerkingen waren noodzakelijk",
"MessageNoUserPlaylists": "Je hebt geen afspeellijsten",
"MessageNotYetImplemented": "Nog niet geimplementeerd",
"MessageOr": "of",
"MessagePauseChapter": "Pauzeer afspelen hoofdstuk",
"MessagePlayChapter": "Luister naar begin van hoofdstuk",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Afspeellijst bijgewerkt",
"ToastPodcastCreateFailed": "Podcast aanmaken mislukt",
"ToastPodcastCreateSuccess": "Podcast aangemaakt",
"ToastRemoveItemFromCollectionFailed": "Onderdeel verwijderen uit collectie mislukt",
"ToastRemoveItemFromCollectionSuccess": "Onderdeel verwijderd uit collectie",
"ToastRSSFeedCloseFailed": "Sluiten RSS-feed mislukt",
"ToastRSSFeedCloseSuccess": "RSS-feed gesloten",
"ToastRemoveItemFromCollectionFailed": "Onderdeel verwijderen uit collectie mislukt",
"ToastRemoveItemFromCollectionSuccess": "Onderdeel verwijderd uit collectie",
"ToastSendEbookToDeviceFailed": "Ebook naar apparaat sturen mislukt",
"ToastSendEbookToDeviceSuccess": "Ebook verstuurd naar apparaat \"{0}\"",
"ToastSeriesUpdateFailed": "Bijwerken serie mislukt",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Verwijderen gebruiker mislukt",
"ToastUserDeleteSuccess": "Gebruiker verwijderd"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Bruk",
"ButtonApplyChapters": "Bruk kapittel",
"ButtonAuthors": "Forfatter",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Bla gjennom mappe",
"ButtonCancel": "Avbryt",
"ButtonCancelEncode": "Avbryt Encode",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Tøm alle mellomlager",
"ButtonPurgeItemsCache": "Tøm mellomlager",
"ButtonPurgeMediaProgress": "Slett medie fremgang",
"ButtonQueueAddItem": "Legg til kø",
"ButtonQueueRemoveItem": "Fjern fra kø",
"ButtonQuickMatch": "Kjapt søk",
"ButtonReScan": "Skann på nytt",
"ButtonRead": "Les",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Fjern fra Fortsett å lytte",
"ButtonRemoveFromContinueReading": "Fjern fra Fortsett å lese",
"ButtonRemoveSeriesFromContinueSeries": "Fjern serie fra Fortsett serie",
"ButtonReScan": "Skann på nytt",
"ButtonReset": "Nullstill",
"ButtonResetToDefault": "Reset to default",
"ButtonRestore": "Gjenopprett",
@ -104,8 +104,8 @@
"HeaderAccount": "Konto",
"HeaderAdvanced": "Avansert",
"HeaderAppriseNotificationSettings": "Apprise notifikasjonsinstillinger",
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
"HeaderAudioTracks": "Lydspor",
"HeaderAudiobookTools": "Lydbok Filbehandlingsverktøy",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Sikkerhetskopier",
"HeaderChangePassword": "Bytt passord",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Samlingsgjenstander",
"HeaderCover": "Omslag",
"HeaderCurrentDownloads": "Aktive nedlastinger",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Detaljer",
"HeaderDownloadQueue": "Last ned kø",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Spillelisteelement",
"HeaderPodcastsToAdd": "Podcaster å legge til",
"HeaderPreviewCover": "Forhåndsvis omslag",
"HeaderRemoveEpisode": "Fjern episode",
"HeaderRemoveEpisodes": "Fjern {0} episoder",
"HeaderRSSFeedGeneral": "RSS Detailer",
"HeaderRSSFeedIsOpen": "RSS Feed er åpen",
"HeaderRSSFeeds": "RSS Feeder",
"HeaderRemoveEpisode": "Fjern episode",
"HeaderRemoveEpisodes": "Fjern {0} episoder",
"HeaderSavedMediaProgress": "Lagret mediefremgang",
"HeaderSchedule": "Timeplan",
"HeaderScheduleLibraryScans": "Planlegg automatisk bibliotek skann",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gjest",
"LabelAccountTypeUser": "Bruker",
"LabelActivity": "Aktivitet",
"LabelAdded": "Lagt til",
"LabelAddedAt": "Dato lagt til ",
"LabelAddToCollection": "Legg til i samling",
"LabelAddToCollectionBatch": "Legg {0} bøker til samling",
"LabelAddToPlaylist": "Legg til i spilleliste",
"LabelAddToPlaylistBatch": "Legg {0} enheter til i spilleliste",
"LabelAdded": "Lagt til",
"LabelAddedAt": "Dato lagt til ",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "Alle",
"LabelAllUsers": "Alle brukere",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Endre passord",
"LabelChannels": "Kanaler",
"LabelChapterTitle": "Kapittel tittel",
"LabelChapters": "Kapitler",
"LabelChaptersFound": "kapitler funnet",
"LabelChapterTitle": "Kapittel tittel",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Lukk spiller",
"LabelCodec": "Kodek",
@ -306,6 +307,7 @@
"LabelFolder": "Mappe",
"LabelFolders": "Mapper",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Fontfamilie",
"LabelFontItalic": "Italic",
"LabelFontScale": "Font størrelse",
@ -321,9 +323,9 @@
"LabelHour": "Time",
"LabelIcon": "Ikon",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "I gang",
"LabelIncludeInTracklist": "Inkluder i sporliste",
"LabelIncomplete": "Ufullstendig",
"LabelInProgress": "I gang",
"LabelInterval": "Intervall",
"LabelIntervalCustomDailyWeekly": "Egendefinert daglig/ukentlig",
"LabelIntervalEvery12Hours": "Hver 12. timer",
@ -337,6 +339,7 @@
"LabelItem": "Enhet",
"LabelLanguage": "Språk",
"LabelLanguageDefaultServer": "Standard tjener språk",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Siste bok lagt til",
"LabelLastBookUpdated": "Siste bok oppdatert",
"LabelLastSeen": "Sist sett",
@ -348,6 +351,7 @@
"LabelLess": "Mindre",
"LabelLibrariesAccessibleToUser": "Biblioteker tilgjengelig for bruker",
"LabelLibrary": "Bibliotek",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Bibliotek enhet",
"LabelLibraryName": "Bibliotek navn",
"LabelLimit": "Begrensning",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Mediespiller",
"LabelMediaType": "Medie type",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Leverandør",
"LabelMetaTag": "Meta Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadata Leverandør",
"LabelMinute": "Minutt",
"LabelMissing": "Mangler",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Forteller",
"LabelNarrators": "Fortellere",
"LabelNew": "Ny",
"LabelNewPassword": "Nytt passord",
"LabelNewestAuthors": "Nyeste forfattere",
"LabelNewestEpisodes": "Nyeste episoder",
"LabelNewPassword": "Nytt passord",
"LabelNextBackupDate": "Neste sikkerhetskopi dato",
"LabelNextScheduledRun": "Neste planlagte kjøring",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Ingen episoder valgt",
"LabelNotes": "Notat",
"LabelNotFinished": "Ikke fullført",
"LabelNotStarted": "Ikke startet",
"LabelNotes": "Notat",
"LabelNotificationAppriseURL": "Apprise URL(er)",
"LabelNotificationAvailableVariables": "Tilgjengelige variabler",
"LabelNotificationBodyTemplate": "Kroppsmal",
"LabelNotificationEvent": "Notifikasjons hendelse",
"LabelNotificationTitleTemplate": "Tittel mal",
"LabelNotificationsMaxFailedAttempts": "Maks mislykkede forsøk",
"LabelNotificationsMaxFailedAttemptsHelp": "Notifikasjoner er deaktivert når de mislykkes på sende dette flere ganger",
"LabelNotificationsMaxQueueSize": "Maks kø lengde for Notifikasjonshendelser",
"LabelNotificationsMaxQueueSizeHelp": "Hendelser er begrenset til avfyre 1 gang per sekund. Hendelser vil bli ignorert om køen er full. Dette forhindrer Notifikasjon spam.",
"LabelNotificationTitleTemplate": "Tittel mal",
"LabelNotStarted": "Ikke startet",
"LabelNumberOfBooks": "Antall bøker",
"LabelNumberOfEpisodes": "Antall episoder",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Kan laste opp",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Bilde sti/URL",
"LabelPlaylists": "Spilleliste",
"LabelPlayMethod": "Avspillingsmetode",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Spilleliste",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcaster",
"LabelPodcastSearchRegion": "Podcast-søkeområde",
"LabelPodcastType": "Podcast type",
"LabelPodcasts": "Podcaster",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefiks som skal ignoreres (skiller ikke mellom store og små bokstaver)",
"LabelPreventIndexing": "Forhindre at din feed fra å bli indeksert av iTunes og Google podcast kataloger",
@ -427,25 +433,26 @@
"LabelProgress": "Framgang",
"LabelProvider": "Tilbyder",
"LabelPubDate": "Publiseringsdato",
"LabelPublisher": "Forlegger",
"LabelPublishYear": "Publikasjonsår",
"LabelRead": "Les",
"LabelReadAgain": "Les igjen",
"LabelReadEbookWithoutProgress": "Les ebok uten å beholde fremgang",
"LabelRecentlyAdded": "Nylig lagt til",
"LabelRecentSeries": "Nylige serier",
"LabelRecommended": "Anbefalte",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Utgivelsesdato",
"LabelRemoveCover": "Fjern omslag",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Forlegger",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Tilpasset eier Epost",
"LabelRSSFeedCustomOwnerName": "Tilpasset eier Navn",
"LabelRSSFeedOpen": "RSS Feed åpne",
"LabelRSSFeedPreventIndexing": "Forhindre indeksering",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRead": "Les",
"LabelReadAgain": "Les igjen",
"LabelReadEbookWithoutProgress": "Les ebok uten å beholde fremgang",
"LabelRecentSeries": "Nylige serier",
"LabelRecentlyAdded": "Nylig lagt til",
"LabelRecommended": "Anbefalte",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Utgivelsesdato",
"LabelRemoveCover": "Fjern omslag",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Søkeord",
"LabelSearchTitle": "Søk tittel",
"LabelSearchTitleOrASIN": "Søk tittel eller ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Sove-timer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Start Tid",
"LabelStarted": "Startet",
"LabelStartedAt": "Startet",
"LabelStartTime": "Start Tid",
"LabelStatsAudioTracks": "Lydspor",
"LabelStatsAuthors": "Forfattere",
"LabelStatsBestDay": "Beste dag",
@ -564,9 +571,9 @@
"LabelUnknown": "Ukjent",
"LabelUpdateCover": "Oppdater omslag",
"LabelUpdateCoverHelp": "Tillat overskriving av eksisterende omslag for de valgte bøkene når en lik bok er funnet",
"LabelUpdatedAt": "Oppdatert",
"LabelUpdateDetails": "Oppdater detaljer",
"LabelUpdateDetailsHelp": "Tillat overskriving av eksisterende detaljer for de valgte bøkene når en lik bok er funnet",
"LabelUpdatedAt": "Oppdatert",
"LabelUploaderDragAndDrop": "Dra og slipp filer eller mapper",
"LabelUploaderDropFiles": "Slipp filer",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Sikkerhetskopier inkluderer, brukerfremgang, detaljer om bibliotekgjenstander, tjener instillinger og bilder lagret under <code>/metadata/items</code> og <code>/metadata/authors</code>. Sikkerhetskopier <strong>vil ikke</strong> inkludere filer som er lagret i bibliotek mappene.",
"MessageBatchQuickMatchDescription": "Kjapt søk vil forsøke å legge til manglende omslag og metadata for de valgte gjenstandene. Aktiver dette valget for å tillate Kjapt søk til å overskrive eksisterende omslag og/eller metadata.",
"MessageBookshelfNoCollections": "Du har ikke laget noen samlinger ennå",
"MessageBookshelfNoResultsForFilter": "Ingen resultat for filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Ingen RSS feed er åpen",
"MessageBookshelfNoResultsForFilter": "Ingen resultat for filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Du har ingen serier",
"MessageChapterEndIsAfter": "Kapittel slutt er etter slutt av lydboken",
"MessageChapterErrorFirstNotZero": "Første kapittel starter på 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Er du sikker på at du vil markere alle bøkene i serien som fullført?",
"MessageConfirmMarkSeriesNotFinished": "Er du sikker på at du vil markere alle bøkene i serien som ikke fullført?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Er du sikker på at du vil fjerne alle kapitler?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Er du sikker på at du vil fjerne samling\"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Er du sikker på at du vil endre tag \"{0}\" til \"{1}\" for alle gjenstandene?",
"MessageConfirmRenameTagMergeNote": "Notis: Denne taggen finnes allerede så de vil bli slått sammen.",
"MessageConfirmRenameTagWarning": "Advarsel! En lignende tag eksisterer allerede (med forsjellige store / små bokstaver) \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Er du sikker på at du vil sende {0} ebok \"{1}\" til enhet \"{2}\"?",
"MessageDownloadingEpisode": "Laster ned episode",
"MessageDragFilesIntoTrackOrder": "Dra filene i rett spor rekkefølge",
@ -683,10 +692,10 @@
"MessageNoSeries": "Ingen serier",
"MessageNoTags": "Ingen tags",
"MessageNoTasksRunning": "Ingen oppgaver kjører",
"MessageNotYetImplemented": "Ikke implementert ennå",
"MessageNoUpdateNecessary": "Ingen oppdatering nødvendig",
"MessageNoUpdatesWereNecessary": "Ingen oppdatering var nødvendig",
"MessageNoUserPlaylists": "Du har ingen spillelister",
"MessageNotYetImplemented": "Ikke implementert ennå",
"MessageOr": "eller",
"MessagePauseChapter": "Pause avspilling av kapittel",
"MessagePlayChapter": "Lytter på begynnelsen av kapittel",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Spilleliste oppdatert",
"ToastPodcastCreateFailed": "Misslykkes å opprette podcast",
"ToastPodcastCreateSuccess": "Podcast opprettet",
"ToastRemoveItemFromCollectionFailed": "Misslykkes å fjerne gjenstsand fra samling",
"ToastRemoveItemFromCollectionSuccess": "Gjenstand fjernet fra samling",
"ToastRSSFeedCloseFailed": "Misslykkes å lukke RSS feed",
"ToastRSSFeedCloseSuccess": "RSS feed lukket",
"ToastRemoveItemFromCollectionFailed": "Misslykkes å fjerne gjenstsand fra samling",
"ToastRemoveItemFromCollectionSuccess": "Gjenstand fjernet fra samling",
"ToastSendEbookToDeviceFailed": "Misslykkes å sende ebok",
"ToastSendEbookToDeviceSuccess": "Ebok sendt til \"{0}\"",
"ToastSeriesUpdateFailed": "Misslykkes å oppdatere serie",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Misslykkes å slette bruker",
"ToastUserDeleteSuccess": "Bruker slettet"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Zatwierdź",
"ButtonApplyChapters": "Zatwierdź rozdziały",
"ButtonAuthors": "Autorzy",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Wyszukaj folder",
"ButtonCancel": "Anuluj",
"ButtonCancelEncode": "Anuluj enkodowanie",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Poprzedni rozdział",
"ButtonPurgeAllCache": "Wyczyść dane tymczasowe",
"ButtonPurgeItemsCache": "Wyczyść dane tymczasowe pozycji",
"ButtonPurgeMediaProgress": "Wyczyść postęp",
"ButtonQueueAddItem": "Dodaj do kolejki",
"ButtonQueueRemoveItem": "Usuń z kolejki",
"ButtonQuickMatch": "Szybkie dopasowanie",
"ButtonReScan": "Ponowne skanowanie",
"ButtonRead": "Czytaj",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Usuń z listy odtwarzania",
"ButtonRemoveFromContinueReading": "Usuń z Kontynuuj czytanie",
"ButtonRemoveSeriesFromContinueSeries": "Usuń serię z listy odtwarzania",
"ButtonReScan": "Ponowne skanowanie",
"ButtonReset": "Resetowanie",
"ButtonResetToDefault": "Przywróć ustawienia domyślne",
"ButtonRestore": "Przywróć",
@ -104,8 +104,8 @@
"HeaderAccount": "Konto",
"HeaderAdvanced": "Zaawansowane",
"HeaderAppriseNotificationSettings": "Ustawienia powiadomień Apprise",
"HeaderAudiobookTools": "Narzędzia do zarządzania audiobookami",
"HeaderAudioTracks": "Ścieżki audio",
"HeaderAudiobookTools": "Narzędzia do zarządzania audiobookami",
"HeaderAuthentication": "Uwierzytelnianie",
"HeaderBackups": "Kopie zapasowe",
"HeaderChangePassword": "Zmień hasło",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Elementy kolekcji",
"HeaderCover": "Okładka",
"HeaderCurrentDownloads": "Current Downloads",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Szczegóły",
"HeaderDownloadQueue": "Download Queue",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Playlist Items",
"HeaderPodcastsToAdd": "Podcasty do dodania",
"HeaderPreviewCover": "Podgląd okładki",
"HeaderRemoveEpisode": "Usuń odcinek",
"HeaderRemoveEpisodes": "Usuń {0} odcinków",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "Kanał RSS jest otwarty",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Usuń odcinek",
"HeaderRemoveEpisodes": "Usuń {0} odcinków",
"HeaderSavedMediaProgress": "Zapisany postęp",
"HeaderSchedule": "Harmonogram",
"HeaderScheduleLibraryScans": "Zaplanuj automatyczne skanowanie biblioteki",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gość",
"LabelAccountTypeUser": "Użytkownik",
"LabelActivity": "Aktywność",
"LabelAdded": "Added",
"LabelAddedAt": "Dodano",
"LabelAddToCollection": "Dodaj do kolekcji",
"LabelAddToCollectionBatch": "Dodaj {0} książki do kolekcji",
"LabelAddToPlaylist": "Add to Playlist",
"LabelAddToPlaylistBatch": "Add {0} Items to Playlist",
"LabelAdded": "Added",
"LabelAddedAt": "Dodano",
"LabelAdminUsersOnly": "Tylko użytkownicy administracyjni",
"LabelAll": "All",
"LabelAllUsers": "Wszyscy użytkownicy",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Zmień hasło",
"LabelChannels": "Channels",
"LabelChapterTitle": "Tytuł rozdziału",
"LabelChapters": "Chapters",
"LabelChaptersFound": "Znalezione rozdziały",
"LabelChapterTitle": "Tytuł rozdziału",
"LabelClickForMoreInfo": "Click for more info",
"LabelClosePlayer": "Zamknij odtwarzacz",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Folder",
"LabelFolders": "Foldery",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Rodzina czcionek",
"LabelFontItalic": "Italic",
"LabelFontScale": "Font scale",
@ -321,9 +323,9 @@
"LabelHour": "Godzina",
"LabelIcon": "Ikona",
"LabelImageURLFromTheWeb": "Image URL from the web",
"LabelInProgress": "W trakcie",
"LabelIncludeInTracklist": "Dołącz do listy odtwarzania",
"LabelIncomplete": "Nieukończone",
"LabelInProgress": "W trakcie",
"LabelInterval": "Interwał",
"LabelIntervalCustomDailyWeekly": "Niestandardowy dzienny/tygodniowy",
"LabelIntervalEvery12Hours": "Co 12 godzin",
@ -337,6 +339,7 @@
"LabelItem": "Pozycja",
"LabelLanguage": "Język",
"LabelLanguageDefaultServer": "Domyślny język serwera",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Last Book Added",
"LabelLastBookUpdated": "Last Book Updated",
"LabelLastSeen": "Ostatnio widziany",
@ -348,6 +351,7 @@
"LabelLess": "Mniej",
"LabelLibrariesAccessibleToUser": "Biblioteki dostępne dla użytkownika",
"LabelLibrary": "Biblioteka",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Element biblioteki",
"LabelLibraryName": "Nazwa biblioteki",
"LabelLimit": "Limit",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Odtwarzacz",
"LabelMediaType": "Typ mediów",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Dostawca metadanych",
"LabelMetaTag": "Tag",
"LabelMetaTags": "Meta Tags",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Dostawca metadanych",
"LabelMinute": "Minuta",
"LabelMissing": "Brakujący",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrator",
"LabelNarrators": "Lektorzy",
"LabelNew": "Nowy",
"LabelNewPassword": "Nowe hasło",
"LabelNewestAuthors": "Najnowsi autorzy",
"LabelNewestEpisodes": "Najnowsze odcinki",
"LabelNewPassword": "Nowe hasło",
"LabelNextBackupDate": "Next backup date",
"LabelNextScheduledRun": "Next scheduled run",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "No episodes selected",
"LabelNotes": "Uwagi",
"LabelNotFinished": "Nieukończone",
"LabelNotStarted": "Nie rozpoęczto",
"LabelNotes": "Uwagi",
"LabelNotificationAppriseURL": "URLe Apprise",
"LabelNotificationAvailableVariables": "Dostępne zmienne",
"LabelNotificationBodyTemplate": "Szablon treści powiadomienia",
"LabelNotificationEvent": "Zdarzenie",
"LabelNotificationTitleTemplate": "Szablon tytułu powiadmienia",
"LabelNotificationsMaxFailedAttempts": "Maksymalna liczba nieudanych prób",
"LabelNotificationsMaxFailedAttemptsHelp": "Powiadomienia są wyłączane, gdy próba ich wysyłki nie powiedzie się kilkukrotnie",
"LabelNotificationsMaxQueueSize": "Maksymalny rozmiar kolejki dla powiadomień",
"LabelNotificationsMaxQueueSizeHelp": "Zdarzenia są ograniczone do 1 na sekundę. Zdarzenia będą ignorowane jeśli kolejka ma maksymalny rozmiar. Zapobiega to spamowaniu powiadomieniami.",
"LabelNotificationTitleTemplate": "Szablon tytułu powiadmienia",
"LabelNotStarted": "Nie rozpoęczto",
"LabelNumberOfBooks": "Liczba książek",
"LabelNumberOfEpisodes": "# odcinków",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Ma możliwość dodawania",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Scieżka/URL do zdjęcia",
"LabelPlaylists": "Playlists",
"LabelPlayMethod": "Metoda odtwarzania",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Playlists",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasty",
"LabelPodcastSearchRegion": "Obszar wyszukiwania podcastów",
"LabelPodcastType": "Podcast Type",
"LabelPodcasts": "Podcasty",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Ignorowane prefiksy (wielkość liter nie ma znaczenia)",
"LabelPreventIndexing": "Prevent your feed from being indexed by iTunes and Google podcast directories",
@ -427,25 +433,26 @@
"LabelProgress": "Postęp",
"LabelProvider": "Dostawca",
"LabelPubDate": "Data publikacji",
"LabelPublisher": "Wydawca",
"LabelPublishYear": "Rok publikacji",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentlyAdded": "Niedawno dodany",
"LabelRecentSeries": "Ostatnie serie",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Data wydania",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Wydawca",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Custom owner Email",
"LabelRSSFeedCustomOwnerName": "Custom owner Name",
"LabelRSSFeedOpen": "RSS Feed otwarty",
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "URL kanały RSS",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
"LabelRecentSeries": "Ostatnie serie",
"LabelRecentlyAdded": "Niedawno dodany",
"LabelRecommended": "Recommended",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Data wydania",
"LabelRemoveCover": "Remove cover",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Wyszukiwanie frazy",
"LabelSearchTitle": "Wyszukaj tytuł",
"LabelSearchTitleOrASIN": "Szukaj tytuł lub ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Wyłącznik czasowy",
"LabelSlug": "Slug",
"LabelStart": "Rozpocznij",
"LabelStartTime": "Czas rozpoczęcia",
"LabelStarted": "Rozpoczęty",
"LabelStartedAt": "Rozpoczęto",
"LabelStartTime": "Czas rozpoczęcia",
"LabelStatsAudioTracks": "Ścieżki audio",
"LabelStatsAuthors": "Autorzy",
"LabelStatsBestDay": "Najlepszy dzień",
@ -564,9 +571,9 @@
"LabelUnknown": "Nieznany",
"LabelUpdateCover": "Zaktalizuj odkładkę",
"LabelUpdateCoverHelp": "Umożliwienie nadpisania istniejących okładek dla wybranych książek w przypadku znalezienia dopasowania",
"LabelUpdatedAt": "Zaktualizowano",
"LabelUpdateDetails": "Zaktualizuj szczegóły",
"LabelUpdateDetailsHelp": "Umożliwienie nadpisania istniejących szczegółów dla wybranych książek w przypadku znalezienia dopasowania",
"LabelUpdatedAt": "Zaktualizowano",
"LabelUploaderDragAndDrop": "Przeciągnij i puść foldery lub pliki",
"LabelUploaderDropFiles": "Puść pliki",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Kopie zapasowe obejmują użytkowników, postępy użytkowników, szczegóły pozycji biblioteki, ustawienia serwera i obrazy przechowywane w <code>/metadata/items</code> & <code>/metadata/authors</code>. Kopie zapasowe nie obejmują żadnych plików przechowywanych w folderach biblioteki.",
"MessageBatchQuickMatchDescription": "Quick Match będzie próbował dodać brakujące okładki i metadane dla wybranych elementów. Włącz poniższe opcje, aby umożliwić Quick Match nadpisanie istniejących okładek i/lub metadanych.",
"MessageBookshelfNoCollections": "Nie posiadasz jeszcze żadnych kolekcji",
"MessageBookshelfNoResultsForFilter": "Nie znaleziono żadnych pozycji przy aktualnym filtrowaniu \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Nie posiadasz żadnych otwartych feedów RSS",
"MessageBookshelfNoResultsForFilter": "Nie znaleziono żadnych pozycji przy aktualnym filtrowaniu \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Nie masz jeszcze żadnych serii",
"MessageChapterEndIsAfter": "Koniec rozdziału następuje po zakończeniu audiobooka",
"MessageChapterErrorFirstNotZero": "First chapter must start at 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Are you sure you want to mark all books in this series as finished?",
"MessageConfirmMarkSeriesNotFinished": "Are you sure you want to mark all books in this series as not finished?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Warning! Quick embed will not backup your audio files. Make sure that you have a backup of your audio files. <br><br>Would you like to continue?",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmRemoveAllChapters": "Are you sure you want to remove all chapters?",
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
"MessageConfirmRemoveCollection": "Czy na pewno chcesz usunąć kolekcję \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Are you sure you want to rename tag \"{0}\" to \"{1}\" for all items?",
"MessageConfirmRenameTagMergeNote": "Note: This tag already exists so they will be merged.",
"MessageConfirmRenameTagWarning": "Warning! A similar tag with a different casing already exists \"{0}\".",
"MessageConfirmReScanLibraryItems": "Are you sure you want to re-scan {0} items?",
"MessageConfirmSendEbookToDevice": "Are you sure you want to send {0} ebook \"{1}\" to device \"{2}\"?",
"MessageDownloadingEpisode": "Pobieranie odcinka",
"MessageDragFilesIntoTrackOrder": "przeciągnij pliki aby ustawić właściwą kolejność utworów",
@ -683,10 +692,10 @@
"MessageNoSeries": "No Series",
"MessageNoTags": "No Tags",
"MessageNoTasksRunning": "No Tasks Running",
"MessageNotYetImplemented": "Jeszcze nie zaimplementowane",
"MessageNoUpdateNecessary": "Brak konieczności aktualizacji",
"MessageNoUpdatesWereNecessary": "Brak aktualizacji",
"MessageNoUserPlaylists": "You have no playlists",
"MessageNotYetImplemented": "Jeszcze nie zaimplementowane",
"MessageOr": "lub",
"MessagePauseChapter": "Zatrzymaj odtwarzanie rozdziały",
"MessagePlayChapter": "Rozpocznij odtwarzanie od początku rozdziału",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Playlist updated",
"ToastPodcastCreateFailed": "Nie udało się utworzyć podcastu",
"ToastPodcastCreateSuccess": "Podcast został pomyślnie utworzony",
"ToastRemoveItemFromCollectionFailed": "Nie udało się usunąć elementu z kolekcji",
"ToastRemoveItemFromCollectionSuccess": "Pozycja usunięta z kolekcji",
"ToastRSSFeedCloseFailed": "Zamknięcie kanału RSS nie powiodło się",
"ToastRSSFeedCloseSuccess": "Zamknięcie kanału RSS powiodło się",
"ToastRemoveItemFromCollectionFailed": "Nie udało się usunąć elementu z kolekcji",
"ToastRemoveItemFromCollectionSuccess": "Pozycja usunięta z kolekcji",
"ToastSendEbookToDeviceFailed": "Failed to Send Ebook to device",
"ToastSendEbookToDeviceSuccess": "Ebook sent to device \"{0}\"",
"ToastSeriesUpdateFailed": "Series update failed",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Nie udało się usunąć użytkownika",
"ToastUserDeleteSuccess": "Użytkownik usunięty"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Aplicar",
"ButtonApplyChapters": "Aplicar Capítulos",
"ButtonAuthors": "Autores",
"ButtonBack": "Voltar",
"ButtonBrowseForFolder": "Procurar por Pasta",
"ButtonCancel": "Cancelar",
"ButtonCancelEncode": "Cancelar Codificação",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Capítulo Anterior",
"ButtonPurgeAllCache": "Apagar Todo o Cache",
"ButtonPurgeItemsCache": "Apagar o Cache de Itens",
"ButtonPurgeMediaProgress": "Apagar o Progresso nas Mídias",
"ButtonQueueAddItem": "Adicionar à Lista",
"ButtonQueueRemoveItem": "Remover da Lista",
"ButtonQuickMatch": "Consulta rápida",
"ButtonReScan": "Nova Verificação",
"ButtonRead": "Ler",
"ButtonReadLess": "Ler menos",
"ButtonReadMore": "Ler mais",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Remover de Continuar Escutando",
"ButtonRemoveFromContinueReading": "Remover de Continuar Lendo",
"ButtonRemoveSeriesFromContinueSeries": "Remover Série de Continuar Série",
"ButtonReScan": "Nova Verificação",
"ButtonReset": "Resetar",
"ButtonResetToDefault": "Resetar para valores padrão",
"ButtonRestore": "Restaurar",
@ -104,8 +104,8 @@
"HeaderAccount": "Conta",
"HeaderAdvanced": "Avançado",
"HeaderAppriseNotificationSettings": "Configuração de notificações Apprise",
"HeaderAudiobookTools": "Ferramentas de Gerenciamento de Arquivos de Audiobooks",
"HeaderAudioTracks": "Trilhas de áudio",
"HeaderAudiobookTools": "Ferramentas de Gerenciamento de Arquivos de Audiobooks",
"HeaderAuthentication": "Autenticação",
"HeaderBackups": "Backups",
"HeaderChangePassword": "Trocar Senha",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Itens da Coleção",
"HeaderCover": "Capas",
"HeaderCurrentDownloads": "Downloads em andamento",
"HeaderCustomMessageOnLogin": "Mensagem personalizada no login",
"HeaderCustomMetadataProviders": "Fontes de Metadados Customizados",
"HeaderDetails": "Detalhes",
"HeaderDownloadQueue": "Fila de Download",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Itens da lista de reprodução",
"HeaderPodcastsToAdd": "Podcasts para Adicionar",
"HeaderPreviewCover": "Visualização da Capa",
"HeaderRSSFeedGeneral": "Detalhes RSS",
"HeaderRSSFeedIsOpen": "Feed RSS está Aberto",
"HeaderRSSFeeds": "Feeds RSS",
"HeaderRemoveEpisode": "Remover Episódio",
"HeaderRemoveEpisodes": "Remover {0} Episódios",
"HeaderRSSFeedGeneral": "Detalhes RSS",
"HeaderRSSFeedIsOpen": "Feed RSS está aberto",
"HeaderRSSFeeds": "Feeds RSS",
"HeaderSavedMediaProgress": "Progresso da gravação das mídias",
"HeaderSchedule": "Programação",
"HeaderScheduleLibraryScans": "Programar Verificação Automática da Biblioteca",
@ -186,23 +187,23 @@
"HeaderUpdateDetails": "Atualizar Detalhes",
"HeaderUpdateLibrary": "Atualizar Biblioteca",
"HeaderUsers": "Usuários",
"HeaderYearReview": "Retrospectiva de {0} ",
"HeaderYearReview": "Retrospectiva de {0}",
"HeaderYourStats": "Suas Estatísticas",
"LabelAbridged": "Versão Abreviada",
"LabelAbridgedChecked": "Abreviada (verificada)",
"LabelAbridgedUnchecked": "Não Abreviada (não verificada)",
"LabelAccessibleBy": "Accessible by",
"LabelAccessibleBy": "Acessível por",
"LabelAccountType": "Tipo de Conta",
"LabelAccountTypeAdmin": "Administrador",
"LabelAccountTypeGuest": "Convidado",
"LabelAccountTypeUser": "Usuário",
"LabelActivity": "Atividade",
"LabelAdded": "Acrescentado",
"LabelAddedAt": "Acrescentado em",
"LabelAddToCollection": "Adicionar à Coleção",
"LabelAddToCollectionBatch": "Adicionar {0} Livros à Coleção",
"LabelAddToPlaylist": "Adicionar à Lista de Reprodução",
"LabelAddToPlaylistBatch": "Adicionar {0} itens à Lista de Reprodução",
"LabelAdded": "Acrescentado",
"LabelAddedAt": "Acrescentado em",
"LabelAdminUsersOnly": "Apenas usuários administradores",
"LabelAll": "Todos",
"LabelAllUsers": "Todos Usuários",
@ -235,9 +236,9 @@
"LabelByAuthor": "por {0}",
"LabelChangePassword": "Trocar Senha",
"LabelChannels": "Canais",
"LabelChapterTitle": "Título do Capítulo",
"LabelChapters": "Capítulos",
"LabelChaptersFound": "capítulos encontrados",
"LabelChapterTitle": "Título do Capítulo",
"LabelClickForMoreInfo": "Clique para mais informações",
"LabelClosePlayer": "Fechar Reprodutor",
"LabelCodec": "Codec",
@ -279,8 +280,8 @@
"LabelEdit": "Editar",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "Remetente",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Rejeitar certificados não autorizados",
"LabelEmailSettingsRejectUnauthorizedHelp": "Desativar a validação de certificados SSL pode expor sua conexão a riscos de segurança, como ataques \"man-in-the-middle\". Desative essa opção apenas se entender suas consequências e se puder confiar no servidor de email ao qual você está se conectando.",
"LabelEmailSettingsSecure": "Seguro",
"LabelEmailSettingsSecureHelp": "Se ativado, a conexão utilizará TLS para a conexão ao servidor. Se desativado TLS será usado se o servidor suportar a extensão STARTTLS. Na maioria dos casos ative esse valor se estiver conectando pela porta 465. Para portas 587 ou 25, mantenha inativo. (de nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Endereço de teste",
@ -306,6 +307,7 @@
"LabelFolder": "Pasta",
"LabelFolders": "Pastas",
"LabelFontBold": "Negrito",
"LabelFontBoldness": "Intensidade do negrito",
"LabelFontFamily": "Família de fonte",
"LabelFontItalic": "Itálico",
"LabelFontScale": "Escala de fonte",
@ -321,9 +323,9 @@
"LabelHour": "Hora",
"LabelIcon": "Ícone",
"LabelImageURLFromTheWeb": "URL da imagem na internet",
"LabelInProgress": "Em Andamento",
"LabelIncludeInTracklist": "Incluir na Lista de Faixas",
"LabelIncomplete": "Incompleto",
"LabelInProgress": "Em Andamento",
"LabelInterval": "Intervalo",
"LabelIntervalCustomDailyWeekly": "Personalizar diário/semanal",
"LabelIntervalEvery12Hours": "A cada 12 horas",
@ -337,6 +339,7 @@
"LabelItem": "Item",
"LabelLanguage": "Idioma",
"LabelLanguageDefaultServer": "Idioma Padrão do Servidor",
"LabelLanguages": "Idiomas",
"LabelLastBookAdded": "Último Livro Acrescentado",
"LabelLastBookUpdated": "Último Livro Atualizado",
"LabelLastSeen": "Visto pela Última Vez",
@ -348,6 +351,7 @@
"LabelLess": "Menos",
"LabelLibrariesAccessibleToUser": "Bibliotecas Acessíveis ao Usuário",
"LabelLibrary": "Biblioteca",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Item da Biblioteca",
"LabelLibraryName": "Nome da Biblioteca",
"LabelLimit": "Limite",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Utilizado para conectar usuários já existentes. Uma vez conectados, usuários serão consultados utilizando uma identificação única do seu provedor de SSO",
"LabelMediaPlayer": "Reprodutor de mídia",
"LabelMediaType": "Tipo de Mídia",
"LabelMetadataOrderOfPrecedenceDescription": "Fontes de metadados de alta prioridade terão preferência sobre as fontes de metadados de prioridade baixa",
"LabelMetadataProvider": "Fonte de Metadados",
"LabelMetaTag": "Etiqueta Meta",
"LabelMetaTags": "Etiquetas Meta",
"LabelMetadataOrderOfPrecedenceDescription": "Fontes de metadados de alta prioridade terão preferência sobre as fontes de metadados de prioridade baixa",
"LabelMetadataProvider": "Fonte de Metadados",
"LabelMinute": "Minuto",
"LabelMissing": "Ausente",
"LabelMissingEbook": "Ebook não existe",
@ -378,24 +382,25 @@
"LabelNarrator": "Narrador",
"LabelNarrators": "Narradores",
"LabelNew": "Novo",
"LabelNewPassword": "Nova Senha",
"LabelNewestAuthors": "Novos Autores",
"LabelNewestEpisodes": "Episódios mais recentes",
"LabelNewPassword": "Nova Senha",
"LabelNextBackupDate": "Data do próximo backup",
"LabelNextScheduledRun": "Próxima execução programada",
"LabelNoCustomMetadataProviders": "Não existem fontes de metadados customizados",
"LabelNoEpisodesSelected": "Nenhum episódio selecionado",
"LabelNotes": "Notas",
"LabelNotFinished": "Não concluído",
"LabelNotStarted": "Não iniciado",
"LabelNotes": "Notas",
"LabelNotificationAppriseURL": "URL(s) Apprise",
"LabelNotificationAvailableVariables": "Variáveis disponíveis",
"LabelNotificationBodyTemplate": "Modelo de Corpo",
"LabelNotificationEvent": "Evento de Notificação",
"LabelNotificationTitleTemplate": "Modelo de Título",
"LabelNotificationsMaxFailedAttempts": "Máximo de tentativas com falhas",
"LabelNotificationsMaxFailedAttemptsHelp": "Notificações serão desabilitadas após falharem este número de vezes",
"LabelNotificationsMaxQueueSize": "Tamanho máximo da fila de eventos de notificação",
"LabelNotificationsMaxQueueSizeHelp": "Eventos estão limitados a um disparo por segundo. Eventos serão ignorados se a fila estiver no tamanho máximo. Isso evita o excesso de notificações.",
"LabelNotificationTitleTemplate": "Modelo de Título",
"LabelNotStarted": "Não iniciado",
"LabelNumberOfBooks": "Número de Livros",
"LabelNumberOfEpisodes": "# de Episódios",
"LabelOpenIDAdvancedPermsClaimDescription": "Nome do claim OpenID contendo as permissões avançadas para ações do usuário na aplicação para serem aplicadas aos perfis não-administradores (<b>se configurados</b>). Se o claim não estiver presente na resposta, acesso ao ABS será negado. Se apenas uma opção estiver ausente, ela será tratada como <code>false</code>. Garanta que o claim do provedor de identidade segue a estrutura esperada:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Pode Fazer Upload",
"LabelPersonalYearReview": "Sua Retrospectiva Anual ({0})",
"LabelPhotoPathURL": "Caminho/URL para Foto",
"LabelPlaylists": "Listas de Reprodução",
"LabelPlayMethod": "Método de Reprodução",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Listas de Reprodução",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Região de busca do podcast",
"LabelPodcastType": "Tipo de Podcast",
"LabelPodcasts": "Podcasts",
"LabelPort": "Porta",
"LabelPrefixesToIgnore": "Prefixos para Ignorar (sem distinção entre maiúsculas e minúsculas)",
"LabelPreventIndexing": "Evitar que o seu feed seja indexado pelos diretórios de podcast do iTunes e Google",
@ -427,25 +433,26 @@
"LabelProgress": "Progresso",
"LabelProvider": "Fonte",
"LabelPubDate": "Data de Publicação",
"LabelPublisher": "Editora",
"LabelPublishYear": "Ano de Publicação",
"LabelRead": "Lido",
"LabelReadAgain": "Ler novamente",
"LabelReadEbookWithoutProgress": "Ler ebook sem armazenar progresso",
"LabelRecentlyAdded": "Novidades",
"LabelRecentSeries": "Séries Recentes",
"LabelRecommended": "Recomendado",
"LabelRedo": "Refazer",
"LabelRegion": "Região",
"LabelReleaseDate": "Data de Lançamento",
"LabelRemoveCover": "Remover capa",
"LabelRowsPerPage": "Linhas por Página",
"LabelPublisher": "Editora",
"LabelPublishers": "Editoras",
"LabelRSSFeedCustomOwnerEmail": "Email do dono personalizado",
"LabelRSSFeedCustomOwnerName": "Nome do dono personalizado",
"LabelRSSFeedOpen": "Feed RSS Aberto",
"LabelRSSFeedPreventIndexing": "Impedir Indexação",
"LabelRSSFeedSlug": "Slug do Feed RSS",
"LabelRSSFeedURL": "URL do Feed RSS",
"LabelRead": "Lido",
"LabelReadAgain": "Ler novamente",
"LabelReadEbookWithoutProgress": "Ler ebook sem armazenar progresso",
"LabelRecentSeries": "Séries Recentes",
"LabelRecentlyAdded": "Novidades",
"LabelRecommended": "Recomendado",
"LabelRedo": "Refazer",
"LabelRegion": "Região",
"LabelReleaseDate": "Data de Lançamento",
"LabelRemoveCover": "Remover capa",
"LabelRowsPerPage": "Linhas por Página",
"LabelSearchTerm": "Busca por Termo",
"LabelSearchTitle": "Busca por Título",
"LabelSearchTitleOrASIN": "Busca por Título ou ASIN",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Ativar Monitoramento",
"LabelSettingsEnableWatcherForLibrary": "Ativa o monitoramento de pastas para a biblioteca",
"LabelSettingsEnableWatcherHelp": "Ativa o acréscimo/atualização de itens quando forem detectadas mudanças no arquivo. *Requer reiniciar o servidor",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "Permitir scripts em epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Permitir que arquivos epub executem scripts. É recomendado manter essa configuração desativada, a não ser que confie na fonte dos arquivos epub.",
"LabelSettingsExperimentalFeatures": "Funcionalidade experimentais",
"LabelSettingsExperimentalFeaturesHelp": "Funcionalidade em desenvolvimento que se beneficiairam dos seus comentários e da sua ajuda para testar. Clique para abrir a discussão no github.",
"LabelSettingsFindCovers": "Localizar capas",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Timer",
"LabelSlug": "Slug",
"LabelStart": "Iniciar",
"LabelStartTime": "Horário do Início",
"LabelStarted": "Iniciado",
"LabelStartedAt": "Iniciado Em",
"LabelStartTime": "Horário do Início",
"LabelStatsAudioTracks": "Trilhas de Áudio",
"LabelStatsAuthors": "Autores",
"LabelStatsBestDay": "Melhor Dia",
@ -560,13 +567,13 @@
"LabelTracksSingleTrack": "Trilha única",
"LabelType": "Tipo",
"LabelUnabridged": "Não Abreviada",
"LabelUndo": "Undo",
"LabelUndo": "Desfazer",
"LabelUnknown": "Desconhecido",
"LabelUpdateCover": "Atualizar Capa",
"LabelUpdateCoverHelp": "Permite sobrescrever capas existentes para os livros selecionados quando uma consulta for localizada",
"LabelUpdatedAt": "Atualizado em",
"LabelUpdateDetails": "Atualizar Detalhes",
"LabelUpdateDetailsHelp": "Permite sobrescrever detalhes existentes para os livros selecionados quando uma consulta for localizada",
"LabelUpdatedAt": "Atualizado em",
"LabelUploaderDragAndDrop": "Arraste e solte arquivos ou pastas",
"LabelUploaderDropFiles": "Solte os arquivos",
"LabelUploaderItemFetchMetadataHelp": "Busca título, autor e série automaticamente",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Backups incluem usuários, progresso dos usuários, detalhes dos itens da biblioteca, configurações do servidor e imagens armazenadas em <code>/metadata/items</code> & <code>/metadata/authors</code>. Backups <strong>não</strong> incluem quaisquer arquivos armazenados nas pastas da sua biblioteca.",
"MessageBatchQuickMatchDescription": "Consulta Rápida tentará adicionar capas e metadados ausentes para os itens selecionados. Ative as opções abaixo para permitir que a Consulta Rápida sobrescreva capas e/ou metadados existentes.",
"MessageBookshelfNoCollections": "Você ainda não criou coleções",
"MessageBookshelfNoResultsForFilter": "Sem Resultados para o filtro \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Não existem feeds RSS abertos",
"MessageBookshelfNoResultsForFilter": "Sem Resultados para o filtro \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Sem resultados para a consulta",
"MessageBookshelfNoSeries": "Você não tem séries",
"MessageChapterEndIsAfter": "O final do capítulo está além do final do seu audiobook",
"MessageChapterErrorFirstNotZero": "O primeiro capítulo precisa começar no 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Tem certeza de que deseja marcar todos os livros nesta série como concluídos?",
"MessageConfirmMarkSeriesNotFinished": "Tem certeza de que deseja marcar todos os livros nesta série como não concluídos?",
"MessageConfirmPurgeCache": "Apagar o cache irá apagar o diretório todo localizado em <code>/metadata/cache</code>. <br /><br />Tem certeza que deseja apagar o diretório de cache?",
"MessageConfirmPurgeItemsCache": "Apagar o cache de itens irá apagar todo conteúdo da pasta <code>/metadata/cache/items</code>.<br />Tem certeza?",
"MessageConfirmQuickEmbed": "Aviso! Inclusão rápida não fará backup dos seus arquivos de áudio. Verifique se tem um backup dos seus arquivos de áudio. <br><br>Quer continuar?",
"MessageConfirmReScanLibraryItems": "Tem certeza de que deseja uma nova verificação de {0} itens?",
"MessageConfirmRemoveAllChapters": "Tem certeza de que deseja remover todos os capítulos?",
"MessageConfirmRemoveAuthor": "Tem certeza de que deseja remover o autor \"{0}\"?",
"MessageConfirmRemoveCollection": "Tem certeza de que deseja remover a coleção \"{0}\"?",
@ -626,16 +636,15 @@
"MessageConfirmRenameGenre": "Tem certeza de que deseja renomear o gênero \"{0}\" para \"{1}\" em todos os itens?",
"MessageConfirmRenameGenreMergeNote": "Aviso: Este gênero já existe então eles serão combinados.",
"MessageConfirmRenameGenreWarning": "Atenção! Um gênero com um nome semelhante já existe \"{0}\".",
"MessageConfirmRenameTag": "Tem certeza de que deseja renomear a etiqueta \"{0}\" para \"{1}\" em todos os itens?",
"MessageConfirmRenameTag": "Tem certeza de que deseja renomear a etiqueta \"{0}\" para \"{1}\" em todos os itens?",
"MessageConfirmRenameTagMergeNote": "Aviso: Esta etiqueta já existe então elas serão combinadas.",
"MessageConfirmRenameTagWarning": "Atenção! Uma etiqueta com um nome semelhante já existe \"{0}\".",
"MessageConfirmReScanLibraryItems": "Tem certeza de que deseja uma nova verificação de {0} itens?",
"MessageConfirmSendEbookToDevice": "Tem certeza de que deseja enviar {0} ebook(s) \"{1}\" para o dispositivo \"{2}\"?",
"MessageDownloadingEpisode": "Realizando o download do episódio",
"MessageDragFilesIntoTrackOrder": "Arraste os arquivos para ordenar as trilhas corretamente",
"MessageEmbedFinished": "Inclusão Concluída!",
"MessageEpisodesQueuedForDownload": "{0} Episódio(s) na fila de download",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "Para garantir a entrega dos ebooks, você pode precisar adicionar o endereço de email acima como um remetente válido para cada um dos dispositivos listados abaixo.",
"MessageFeedURLWillBe": "URL do Feed será {0}",
"MessageFetching": "Buscando...",
"MessageForceReScanDescription": "verificará todos os arquivos, como uma verificação nova. Etiquetas ID3 de arquivos de áudio, arquivos OPF e arquivos de texto serão tratados como novos.",
@ -647,7 +656,7 @@
"MessageListeningSessionsInTheLastYear": "{0} sessões de escuta no ano anterior",
"MessageLoading": "Carregando...",
"MessageLoadingFolders": "Carregando pastas...",
"MessageLogsDescription": "Os logs estão armazenados em <code>/metadata/logs</code> como arquivos JSON. Logs de crash estão armazenados em <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "Os logs estão armazenados em <code>/metadata/logs</code> como arquivos JSON. Logs de crash estão armazenados em <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "Falha no M4B!",
"MessageM4BFinished": "M4B Concluído!",
"MessageMapChapterTitles": "Designar títulos de capítulos a partir dos capítulos existentes no audiobook sem ajustar seus tempos",
@ -683,10 +692,10 @@
"MessageNoSeries": "Sem Séries",
"MessageNoTags": "Sem etiquetas",
"MessageNoTasksRunning": "Sem Tarefas em Execução",
"MessageNotYetImplemented": "Ainda não implementado",
"MessageNoUpdateNecessary": "Não é necessária a atualização",
"MessageNoUpdatesWereNecessary": "Nenhuma atualização é necessária",
"MessageNoUserPlaylists": "Você não tem listas de reprodução",
"MessageNotYetImplemented": "Ainda não implementado",
"MessageOr": "ou",
"MessagePauseChapter": "Pausar reprodução do capítulo",
"MessagePlayChapter": "Escutar o início do capítulo",
@ -751,8 +760,8 @@
"ToastBookmarkRemoveSuccess": "Marcador removido",
"ToastBookmarkUpdateFailed": "Falha ao atualizar o marcador",
"ToastBookmarkUpdateSuccess": "Marcador atualizado",
"ToastCachePurgeFailed": "Failed to purge cache",
"ToastCachePurgeSuccess": "Cache purged successfully",
"ToastCachePurgeFailed": "Falha ao apagar o cache",
"ToastCachePurgeSuccess": "Cache apagado com sucesso",
"ToastChaptersHaveErrors": "Capítulos com erro",
"ToastChaptersMustHaveTitles": "Capítulos precisam ter títulos",
"ToastCollectionItemsRemoveFailed": "Falha ao remover item(ns) da coleção",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Lista de reprodução atualizada",
"ToastPodcastCreateFailed": "Falha ao criar podcast",
"ToastPodcastCreateSuccess": "Podcast criado",
"ToastRemoveItemFromCollectionFailed": "Falha ao remover item da coleção",
"ToastRemoveItemFromCollectionSuccess": "Item removido da coleção",
"ToastRSSFeedCloseFailed": "Falha ao fechar feed RSS",
"ToastRSSFeedCloseSuccess": "Feed RSS fechado",
"ToastRemoveItemFromCollectionFailed": "Falha ao remover item da coleção",
"ToastRemoveItemFromCollectionSuccess": "Item removido da coleção",
"ToastSendEbookToDeviceFailed": "Falha ao enviar ebook para dispositivo",
"ToastSendEbookToDeviceSuccess": "Ebook enviado para o dispositivo \"{0}\"",
"ToastSeriesUpdateFailed": "Falha ao atualizar série",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Prefixos de ordenação atualizados ({0} item(ns))",
"ToastUserDeleteFailed": "Falha ao apagar usuário",
"ToastUserDeleteSuccess": "Usuário apagado"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Применить",
"ButtonApplyChapters": "Применить главы",
"ButtonAuthors": "Авторы",
"ButtonBack": "Назад",
"ButtonBrowseForFolder": "Выбрать папку",
"ButtonCancel": "Отмена",
"ButtonCancelEncode": "Отменить кодирование",
@ -32,8 +33,8 @@
"ButtonHide": "Скрыть",
"ButtonHome": "Домой",
"ButtonIssues": "Проблемы",
"ButtonJumpBackward": "Jump Backward",
"ButtonJumpForward": "Jump Forward",
"ButtonJumpBackward": "Назад",
"ButtonJumpForward": "Вперед",
"ButtonLatest": "Последнее",
"ButtonLibrary": "Библиотека",
"ButtonLogout": "Выход",
@ -44,7 +45,7 @@
"ButtonMatchBooks": "Найти книги",
"ButtonNevermind": "Не важно",
"ButtonNext": "Next",
"ButtonNextChapter": "Next Chapter",
"ButtonNextChapter": "Следующая глава",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Открыть канал",
"ButtonOpenManager": "Открыть менеджер",
@ -52,25 +53,24 @@
"ButtonPlay": "Слушать",
"ButtonPlaying": "Проигрывается",
"ButtonPlaylists": "Плейлисты",
"ButtonPrevious": "Previous",
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPrevious": "Предыдущий",
"ButtonPreviousChapter": "Предыдущая глава",
"ButtonPurgeAllCache": "Очистить весь кэш",
"ButtonPurgeItemsCache": "Очистить кэш элементов",
"ButtonPurgeMediaProgress": "Очистить прогресс медиа",
"ButtonQueueAddItem": "Добавить в очередь",
"ButtonQueueRemoveItem": "Удалить из очереди",
"ButtonQuickMatch": "Быстрый поиск",
"ButtonReScan": "Пересканировать",
"ButtonRead": "Читать",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
"ButtonRefresh": "Refresh",
"ButtonReadLess": "Читать меньше",
"ButtonReadMore": "Читать больше",
"ButtonRefresh": "Обновить",
"ButtonRemove": "Удалить",
"ButtonRemoveAll": "Удалить всё",
"ButtonRemoveAllLibraryItems": "Удалить все элементы библиотеки",
"ButtonRemoveFromContinueListening": "Удалить из Продолжить слушать",
"ButtonRemoveFromContinueReading": "Удалить из Продолжить читать",
"ButtonRemoveSeriesFromContinueSeries": "Удалить серию из Продолжить серию",
"ButtonReScan": "Пересканировать",
"ButtonReset": "Сбросить",
"ButtonResetToDefault": "Сборосить по умолчанию",
"ButtonRestore": "Восстановить",
@ -83,7 +83,7 @@
"ButtonSelectFolderPath": "Выберите путь папки",
"ButtonSeries": "Серии",
"ButtonSetChaptersFromTracks": "Установить главы из треков",
"ButtonShare": "Share",
"ButtonShare": "Поделиться",
"ButtonShiftTimes": "Смещение",
"ButtonShow": "Показать",
"ButtonStartM4BEncode": "Начать кодирование M4B",
@ -104,8 +104,8 @@
"HeaderAccount": "Учетная запись",
"HeaderAdvanced": "Дополнительно",
"HeaderAppriseNotificationSettings": "Настройки оповещений",
"HeaderAudiobookTools": "Инструменты файлов аудиокниг",
"HeaderAudioTracks": "Аудио треки",
"HeaderAudiobookTools": "Инструменты файлов аудиокниг",
"HeaderAuthentication": "Аутентификация",
"HeaderBackups": "Бэкапы",
"HeaderChangePassword": "Изменить пароль",
@ -115,7 +115,8 @@
"HeaderCollectionItems": "Элементы коллекции",
"HeaderCover": "Обложка",
"HeaderCurrentDownloads": "Текущие закачки",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderCustomMessageOnLogin": "Пользовательское сообщение при входе",
"HeaderCustomMetadataProviders": "Пользовательские поставщики метаданных",
"HeaderDetails": "Подробности",
"HeaderDownloadQueue": "Очередь скачивания",
"HeaderEbookFiles": "Файлы e-книг",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Элементы списка воспроизведения",
"HeaderPodcastsToAdd": "Подкасты для добавления",
"HeaderPreviewCover": "Предпросмотр обложки",
"HeaderRemoveEpisode": "Удалить эпизод",
"HeaderRemoveEpisodes": "Удалить {0} эпизодов",
"HeaderRSSFeedGeneral": "Сведения о RSS",
"HeaderRSSFeedIsOpen": "RSS-канал открыт",
"HeaderRSSFeeds": "RSS-каналы",
"HeaderRemoveEpisode": "Удалить эпизод",
"HeaderRemoveEpisodes": "Удалить {0} эпизодов",
"HeaderSavedMediaProgress": "Прогресс медиа сохранен",
"HeaderSchedule": "Планировщик",
"HeaderScheduleLibraryScans": "Планировщик автоматического сканирования библиотеки",
@ -186,23 +187,23 @@
"HeaderUpdateDetails": "Обновить детали",
"HeaderUpdateLibrary": "Обновить библиотеку",
"HeaderUsers": "Пользователи",
"HeaderYearReview": "Year {0} in Review",
"HeaderYearReview": "Итоги {0} года",
"HeaderYourStats": "Ваша статистика",
"LabelAbridged": "Сокращенное издание",
"LabelAbridgedChecked": "Abridged (checked)",
"LabelAbridgedUnchecked": "Unabridged (unchecked)",
"LabelAccessibleBy": "Accessible by",
"LabelAbridgedChecked": "Сокращено (отмечено)",
"LabelAbridgedUnchecked": "Без сокращений (не отмечено)",
"LabelAccessibleBy": "Доступ",
"LabelAccountType": "Тип учетной записи",
"LabelAccountTypeAdmin": "Администратор",
"LabelAccountTypeGuest": "Гость",
"LabelAccountTypeUser": "Пользователь",
"LabelActivity": "Активность",
"LabelAdded": "Добавили",
"LabelAddedAt": "Дата добавления",
"LabelAddToCollection": "Добавить в коллекцию",
"LabelAddToCollectionBatch": "Добавить {0} книг в коллекцию",
"LabelAddToPlaylist": "Добавить в плейлист",
"LabelAddToPlaylistBatch": "Добавить {0} элементов в плейлист",
"LabelAdded": "Добавили",
"LabelAddedAt": "Дата добавления",
"LabelAdminUsersOnly": "Только для пользователей с правами администратора",
"LabelAll": "Все",
"LabelAllUsers": "Все пользователи",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Изменить пароль",
"LabelChannels": "Каналы",
"LabelChapterTitle": "Название главы",
"LabelChapters": "Главы",
"LabelChaptersFound": "глав найдено",
"LabelChapterTitle": "Название главы",
"LabelClickForMoreInfo": "Нажмите, чтобы узнать больше",
"LabelClosePlayer": "Закрыть проигрыватель",
"LabelCodec": "Кодек",
@ -247,7 +248,7 @@
"LabelComplete": "Завершить",
"LabelConfirmPassword": "Подтвердить пароль",
"LabelContinueListening": "Продолжить слушать",
"LabelContinueReading": "Продолжить читать",
"LabelContinueReading": "Продолжить чтение",
"LabelContinueSeries": "Продолжить серию",
"LabelCover": "Обложка",
"LabelCoverImageURL": "URL изображения обложки",
@ -270,17 +271,17 @@
"LabelDownload": "Скачать",
"LabelDownloadNEpisodes": "Скачать {0} эпизодов",
"LabelDuration": "Длина",
"LabelDurationComparisonExactMatch": "(exact match)",
"LabelDurationComparisonLonger": "({0} longer)",
"LabelDurationComparisonShorter": "({0} shorter)",
"LabelDurationComparisonExactMatch": "(точное совпадение)",
"LabelDurationComparisonLonger": "({0} дольше)",
"LabelDurationComparisonShorter": "({0} короче)",
"LabelDurationFound": "Найденная длина:",
"LabelEbook": "E-книга",
"LabelEbooks": "E-книги",
"LabelEdit": "Редактировать",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "Адрес От",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Отклонение неавторизованных сертификатов",
"LabelEmailSettingsRejectUnauthorizedHelp": "Отключение проверки SSL-сертификата может подвергнуть ваше подключение рискам безопасности, таким как атаки типа \"man-in-the-middle\". Отключайте эту опцию только в том случае, если вы понимаете последствия и доверяете почтовому серверу, к которому подключаетесь.",
"LabelEmailSettingsSecure": "Безопасность",
"LabelEmailSettingsSecureHelp": "Если значение истинно, то соединение будет использовать TLS при подключении к серверу. Если значение ложно, то TLS будет использован, если сервер поддерживает расширение STARTTLS. В большинстве случаев установите это значение в истину, если вы подключаетесь к порту 465. Для порта 587 или 25 оставьте значение ложным. (из nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Тестовый адрес",
@ -292,8 +293,8 @@
"LabelEpisodeType": "Тип эпизода",
"LabelExample": "Пример",
"LabelExplicit": "Явный",
"LabelExplicitChecked": "Explicit (checked)",
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
"LabelExplicitChecked": "Явный (отмечено)",
"LabelExplicitUnchecked": "Не явно (не отмечено)",
"LabelFeedURL": "URL канала",
"LabelFetchingMetadata": "Извлечение метаданных",
"LabelFile": "Файл",
@ -305,11 +306,12 @@
"LabelFinished": "Закончен",
"LabelFolder": "Папка",
"LabelFolders": "Папки",
"LabelFontBold": "Bold",
"LabelFontBold": "Жирный",
"LabelFontBoldness": "Жирность шрифта",
"LabelFontFamily": "Семейство шрифтов",
"LabelFontItalic": "Italic",
"LabelFontScale": "Масштаб шрифта",
"LabelFontStrikethrough": "Strikethrough",
"LabelFontStrikethrough": "Зачеркнутый",
"LabelFormat": "Формат",
"LabelGenre": "Жанр",
"LabelGenres": "Жанры",
@ -321,9 +323,9 @@
"LabelHour": "Часы",
"LabelIcon": "Иконка",
"LabelImageURLFromTheWeb": "URL-адрес изображения из Интернета",
"LabelInProgress": "В процессе",
"LabelIncludeInTracklist": "Включать в список воспроизведения",
"LabelIncomplete": "Не завершен",
"LabelInProgress": "В процессе",
"LabelInterval": "Интервал",
"LabelIntervalCustomDailyWeekly": "Пользовательские ежедневно/еженедельно",
"LabelIntervalEvery12Hours": "Каждые 12 часов",
@ -337,6 +339,7 @@
"LabelItem": "Элемент",
"LabelLanguage": "Язык",
"LabelLanguageDefaultServer": "Язык сервера по умолчанию",
"LabelLanguages": "Языки",
"LabelLastBookAdded": "Последняя книга добавлена",
"LabelLastBookUpdated": "Последняя книга обновлена",
"LabelLastSeen": "Последнее сканирование",
@ -348,6 +351,7 @@
"LabelLess": "Менее",
"LabelLibrariesAccessibleToUser": "Библиотеки доступные для пользователя",
"LabelLibrary": "Библиотека",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Элемент библиотеки",
"LabelLibraryName": "Имя библиотеки",
"LabelLimit": "Лимит",
@ -362,14 +366,14 @@
"LabelMatchExistingUsersByDescription": "Используется для подключения существующих пользователей. После подключения пользователям будет присвоен уникальный идентификатор от поставщика единого входа",
"LabelMediaPlayer": "Медиа проигрыватель",
"LabelMediaType": "Тип медиа",
"LabelMetadataOrderOfPrecedenceDescription": "Источники метаданных с более высоким приоритетом будут переопределять источники метаданных с более низким приоритетом",
"LabelMetadataProvider": "Провайдер",
"LabelMetaTag": "Мета тег",
"LabelMetaTags": "Мета теги",
"LabelMetadataOrderOfPrecedenceDescription": "Источники метаданных с более высоким приоритетом будут переопределять источники метаданных с более низким приоритетом",
"LabelMetadataProvider": "Провайдер",
"LabelMinute": "Минуты",
"LabelMissing": "Потеряно",
"LabelMissingEbook": "Has no ebook",
"LabelMissingSupplementaryEbook": "Has no supplementary ebook",
"LabelMissingEbook": "Нет e-книги",
"LabelMissingSupplementaryEbook": "Нет дополнительной e-книги",
"LabelMobileRedirectURIs": "Разрешенные URI перенаправления с мобильных устройств",
"LabelMobileRedirectURIsDescription": "Это белый список допустимых URI перенаправления для мобильных приложений. По умолчанию используется <code>audiobookshelf://oauth</code>, который можно удалить или дополнить дополнительными URI для интеграции со сторонними приложениями. Использование звездочки (<code>*</code>) в качестве единственной записи разрешает любой URI.",
"LabelMore": "Еще",
@ -378,29 +382,30 @@
"LabelNarrator": "Читает",
"LabelNarrators": "Чтецы",
"LabelNew": "Новый",
"LabelNewPassword": "Новый пароль",
"LabelNewestAuthors": "Новые авторы",
"LabelNewestEpisodes": "Новые эпизоды",
"LabelNewPassword": "Новый пароль",
"LabelNextBackupDate": "Следующая дата бэкапирования",
"LabelNextScheduledRun": "Следущий запланированный запуск",
"LabelNoCustomMetadataProviders": "Нет пользовательских поставщиков метаданных",
"LabelNoEpisodesSelected": "Эпизоды не выбраны",
"LabelNotes": "Заметки",
"LabelNotFinished": "Не завершено",
"LabelNotStarted": "Не запущено",
"LabelNotes": "Заметки",
"LabelNotificationAppriseURL": "URL(ы) для извещений",
"LabelNotificationAvailableVariables": "Доступные переменные",
"LabelNotificationBodyTemplate": "Шаблон тела",
"LabelNotificationEvent": "Событие оповещения",
"LabelNotificationTitleTemplate": "Шаблон заголовка",
"LabelNotificationsMaxFailedAttempts": "Макс. попыток",
"LabelNotificationsMaxFailedAttemptsHelp": "Уведомления будут выключены если произойдет ошибка отправки данное количество раз",
"LabelNotificationsMaxQueueSize": "Макс. размер очереди для событий уведомлений",
"LabelNotificationsMaxQueueSizeHelp": "События ограничены 1 в секунду. События будут игнорированы если в очереди максимальное количество. Это предотвращает спам сообщениями.",
"LabelNotificationTitleTemplate": "Шаблон заголовка",
"LabelNotStarted": "Не запущено",
"LabelNumberOfBooks": "Количество книг",
"LabelNumberOfEpisodes": "# Эпизодов",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
"LabelOpenIDClaims": "Leave the following options empty to disable advanced group and permissions assignment, automatically assigning 'User' group then.",
"LabelOpenIDGroupClaimDescription": "Name of the OpenID claim that contains a list of the user's groups. Commonly referred to as <code>groups</code>. <b>If configured</b>, the application will automatically assign roles based on the user's group memberships, provided that these groups are named case-insensitively 'admin', 'user', or 'guest' in the claim. The claim should contain a list, and if a user belongs to multiple groups, the application will assign the role corresponding to the highest level of access. If no group matches, access will be denied.",
"LabelOpenIDAdvancedPermsClaimDescription": "Имя утверждения OpenID, содержащего расширенные разрешения на действия пользователя в приложении, которые будут применяться к ролям, не являющимся администраторами (<b>если они настроены</b>). Если утверждение отсутствует в ответе, в доступе к ABS будет отказано. Если одна опция отсутствует, она будет рассматриваться как <code>false</code>. Убедитесь, что утверждение поставщика удостоверений соответствует ожидаемой структуре:",
"LabelOpenIDClaims": "Оставьте следующие параметры пустыми, чтобы отключить расширенное назначение групп и разрешений, будет автоматически присвоена группа «Пользователь».",
"LabelOpenIDGroupClaimDescription": "Имя утверждения OpenID, содержащего список групп пользователя. Обычно их называют <code>groups</code>. <b>Если эта настройка</b> настроена, приложение будет автоматически назначать роли на основе членства пользователя в группах при условии, что эти группы названы в утверждении без учета регистра \"admin\", \"user\" или \"guest\". Утверждение должно содержать список, и если пользователь принадлежит к нескольким группам, то приложение назначит роль, соответствующую самому высокому уровню доступа. Если ни одна из групп не совпадает, доступ будет запрещен.",
"LabelOpenRSSFeed": "Открыть RSS-канал",
"LabelOverwrite": "Перезаписать",
"LabelPassword": "Пароль",
@ -412,14 +417,15 @@
"LabelPermissionsDownload": "Может скачивать",
"LabelPermissionsUpdate": "Может обновлять",
"LabelPermissionsUpload": "Может закачивать",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPersonalYearReview": "Итоги прошедшего года ({0})",
"LabelPhotoPathURL": "Путь к фото/URL",
"LabelPlaylists": "Плейлисты",
"LabelPlayMethod": "Метод воспроизведения",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Плейлисты",
"LabelPodcast": "Подкаст",
"LabelPodcasts": "Подкасты",
"LabelPodcastSearchRegion": "Регион поиска подкастов",
"LabelPodcastType": "Тип подкаста",
"LabelPodcasts": "Подкасты",
"LabelPort": "Порт",
"LabelPrefixesToIgnore": "Игнорируемые префиксы (без учета регистра)",
"LabelPreventIndexing": "Запретить индексацию фида каталогами подкастов iTunes и Google",
@ -427,39 +433,40 @@
"LabelProgress": "Прогресс",
"LabelProvider": "Провайдер",
"LabelPubDate": "Дата публикации",
"LabelPublisher": "Издатель",
"LabelPublishYear": "Год публикации",
"LabelRead": "Читать",
"LabelReadAgain": "Читать снова",
"LabelReadEbookWithoutProgress": "Читать e-книгу без сохранения прогресса",
"LabelRecentlyAdded": "Недавно добавленные",
"LabelRecentSeries": "Последние серии",
"LabelRecommended": "Рекомендованное",
"LabelRedo": "Redo",
"LabelRegion": "Регион",
"LabelReleaseDate": "Дата выхода",
"LabelRemoveCover": "Удалить обложку",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Издатель",
"LabelPublishers": "Издатели",
"LabelRSSFeedCustomOwnerEmail": "Пользовательский Email владельца",
"LabelRSSFeedCustomOwnerName": "Пользовательское Имя владельца",
"LabelRSSFeedOpen": "Открыть RSS-канал",
"LabelRSSFeedPreventIndexing": "Запретить индексирование",
"LabelRSSFeedSlug": "Встроить RSS-канал",
"LabelRSSFeedURL": "URL RSS-канала",
"LabelRead": "Читать",
"LabelReadAgain": "Читать снова",
"LabelReadEbookWithoutProgress": "Читать e-книгу без сохранения прогресса",
"LabelRecentSeries": "Последние серии",
"LabelRecentlyAdded": "Недавно добавленные",
"LabelRecommended": "Рекомендованное",
"LabelRedo": "Повторить",
"LabelRegion": "Регион",
"LabelReleaseDate": "Дата выхода",
"LabelRemoveCover": "Удалить обложку",
"LabelRowsPerPage": "Строк на странице",
"LabelSearchTerm": "Поисковый запрос",
"LabelSearchTitle": "Поиск по названию",
"LabelSearchTitleOrASIN": "Поиск по названию или ASIN",
"LabelSeason": "Сезон",
"LabelSelectAll": "Select all",
"LabelSelectAll": "Выбрать все",
"LabelSelectAllEpisodes": "Выбрать все эпизоды",
"LabelSelectEpisodesShowing": "Выберите {0} эпизодов для показа",
"LabelSelectUsers": "Select users",
"LabelSelectUsers": "Выбор пользователей",
"LabelSendEbookToDevice": "Отправить e-книгу в...",
"LabelSequence": "Последовательность",
"LabelSeries": "Серия",
"LabelSeriesName": "Имя серии",
"LabelSeriesProgress": "Прогресс серии",
"LabelServerYearReview": "Server Year in Review ({0})",
"LabelServerYearReview": "Итоги года всего сервера ({0})",
"LabelSetEbookAsPrimary": "Установить как основную",
"LabelSetEbookAsSupplementary": "Установить как дополнительную",
"LabelSettingsAudiobooksOnly": "Только аудиокниги",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Включить отслеживание",
"LabelSettingsEnableWatcherForLibrary": "Включить отслеживание за папками библиотеки",
"LabelSettingsEnableWatcherHelp": "Включает автоматическое добавление/обновление элементов при обнаружении изменений файлов. *Требуется перезапуск сервера",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "Разрешение содержимого epub с скриптами",
"LabelSettingsEpubsAllowScriptedContentHelp": "Разрешить файлам epub выполнять скрипты. Рекомендуется отключать этот параметр, если вы не доверяете источнику файлов epub.",
"LabelSettingsExperimentalFeatures": "Экспериментальные функции",
"LabelSettingsExperimentalFeaturesHelp": "Функционал в разработке на который Вы могли бы дать отзыв или помочь в тестировании. Нажмите для открытия обсуждения на github.",
"LabelSettingsFindCovers": "Найти обложки",
@ -483,8 +490,8 @@
"LabelSettingsHideSingleBookSeriesHelp": "Серии, в которых всего одна книга, будут скрыты со страницы серий и полок домашней страницы.",
"LabelSettingsHomePageBookshelfView": "Вид книжной полки на Домашней странице",
"LabelSettingsLibraryBookshelfView": "Вид книжной полки в Библиотеке",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Skip earlier books in Continue Series",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "The Continue Series home page shelf shows the first book not started in series that have at least one book finished and no books in progress. Enabling this setting will continue series from the furthest completed book instead of the first book not started.",
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Пропустить предыдущие книги в \"Продолжить серию\"",
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "На домашней странице \"Продолжить серию\" отображается первая книга, не начатая в серии, в которой закончена хотя бы одна книга и нет начатых книг. При включении этого параметра серия будет продолжена с самой последней завершенной книги, а не с первой, которая не начата.",
"LabelSettingsParseSubtitles": "Разбор подзаголовков",
"LabelSettingsParseSubtitlesHelp": "Извлечение подзаголовков из имен папок аудиокниг.<br>Подзаголовок должны быть отделен \" - \"<br>например \"Название Книги - Тут Подзаголовок\" подзаголовок будет \"Тут Подзаголовок\"",
"LabelSettingsPreferMatchedMetadata": "Предпочитать метаданные поиска",
@ -501,14 +508,14 @@
"LabelSettingsStoreMetadataWithItemHelp": "По умолчанию метаинформация сохраняется в папке /metadata/items, при включении этой настройки метаинформация будет храниться в папке элемента",
"LabelSettingsTimeFormat": "Формат времени",
"LabelShowAll": "Показать все",
"LabelShowSeconds": "Show seconds",
"LabelShowSeconds": "Отображать секунды",
"LabelSize": "Размер",
"LabelSleepTimer": "Таймер сна",
"LabelSlug": "Слизень",
"LabelStart": "Начало",
"LabelStartTime": "Время начала",
"LabelStarted": "Начат",
"LabelStartedAt": "Начато В",
"LabelStartTime": "Время начала",
"LabelStatsAudioTracks": "Аудио треки",
"LabelStatsAuthors": "Авторы",
"LabelStatsBestDay": "Лучший День",
@ -531,10 +538,10 @@
"LabelTagsAccessibleToUser": "Теги доступные для пользователя",
"LabelTagsNotAccessibleToUser": "Теги не доступные для пользователя",
"LabelTasks": "Запущенные задачи",
"LabelTextEditorBulletedList": "Bulleted list",
"LabelTextEditorBulletedList": "Маркированный список",
"LabelTextEditorLink": "Link",
"LabelTextEditorNumberedList": "Numbered list",
"LabelTextEditorUnlink": "Unlink",
"LabelTextEditorNumberedList": "Нумерованный список",
"LabelTextEditorUnlink": "Отсоединить",
"LabelTheme": "Тема",
"LabelThemeDark": "Темная",
"LabelThemeLight": "Светлая",
@ -560,13 +567,13 @@
"LabelTracksSingleTrack": "Один трек",
"LabelType": "Тип",
"LabelUnabridged": "Полное издание",
"LabelUndo": "Undo",
"LabelUndo": "Отменить",
"LabelUnknown": "Неизвестно",
"LabelUpdateCover": "Обновить обложку",
"LabelUpdateCoverHelp": "Позволяет перезаписывать существующие обложки для выбранных книг если будут найдены",
"LabelUpdatedAt": "Обновлено в",
"LabelUpdateDetails": "Обновить подробности",
"LabelUpdateDetailsHelp": "Позволяет перезаписывать текущие подробности для выбранных книг если будут найдены",
"LabelUpdatedAt": "Обновлено в",
"LabelUploaderDragAndDrop": "Перетащите файлы или каталоги",
"LabelUploaderDropFiles": "Перетащите файлы",
"LabelUploaderItemFetchMetadataHelp": "Автоматическое извлечение названия, автора и серии",
@ -581,8 +588,8 @@
"LabelViewQueue": "Очередь воспроизведения",
"LabelVolume": "Громкость",
"LabelWeekdaysToRun": "Дни недели для запуска",
"LabelYearReviewHide": "Hide Year in Review",
"LabelYearReviewShow": "See Year in Review",
"LabelYearReviewHide": "Скрыть итоги года",
"LabelYearReviewShow": "Итоги года",
"LabelYourAudiobookDuration": "Продолжительность Вашей книги",
"LabelYourBookmarks": "Ваши закладки",
"LabelYourPlaylists": "Ваши плейлисты",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Бэкап включает пользователей, прогресс пользователей, данные элементов библиотеки, настройки сервера и изображения хранящиеся в <code>/metadata/items</code> и <code>/metadata/authors</code>. Бэкапы <strong>НЕ</strong> сохраняют файлы из папок библиотек.",
"MessageBatchQuickMatchDescription": "Быстрый Поиск попытается добавить отсутствующие обложки и метаданные для выбранных элементов. Включите параметры ниже, чтобы разрешить Быстрому Поиску перезаписывать существующие обложки и/или метаданные.",
"MessageBookshelfNoCollections": "Вы еще не создали ни одной коллекции",
"MessageBookshelfNoResultsForFilter": "Нет Результатов для фильтра \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Нет открытых RSS-каналов",
"MessageBookshelfNoResultsForFilter": "Нет Результатов для фильтра \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Нет результатов для запроса",
"MessageBookshelfNoSeries": "У вас нет серий",
"MessageChapterEndIsAfter": "Конец главы после окончания вашей аудиокниги",
"MessageChapterErrorFirstNotZero": "Первая глава должна начинаться с 0",
@ -613,14 +621,16 @@
"MessageConfirmMarkAllEpisodesNotFinished": "Вы уверены, что хотите отметить все эпизоды как не завершенные?",
"MessageConfirmMarkSeriesFinished": "Вы уверены, что хотите отметить все книги этой серии как завершенные?",
"MessageConfirmMarkSeriesNotFinished": "Вы уверены, что хотите отметить все книги этой серии как не завершенные?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeCache": "Очистка кэша удалит весь каталог в <code>/metadata/cache</code>. <br /><br />Вы уверены, что хотите удалить каталог кэша?",
"MessageConfirmPurgeItemsCache": "Очистка кэша элементов удалит весь каталог в <code>/metadata/cache/items</code>.<br />Вы уверены?",
"MessageConfirmQuickEmbed": "Предупреждение! Быстрое встраивание не позволяет создавать резервные копии аудиофайлов. Убедитесь, что у вас есть резервная копия аудиофайлов. <br><br>Хотите продолжить?",
"MessageConfirmReScanLibraryItems": "Вы уверены, что хотите пересканировать {0} элементов?",
"MessageConfirmRemoveAllChapters": "Вы уверены, что хотите удалить все главы?",
"MessageConfirmRemoveAuthor": "Вы уверены, что хотите удалить автора \"{0}\"?",
"MessageConfirmRemoveCollection": "Вы уверены, что хотите удалить коллекцию \"{0}\"?",
"MessageConfirmRemoveEpisode": "Вы уверены, что хотите удалить эпизод \"{0}\"?",
"MessageConfirmRemoveEpisodes": "Вы уверены, что хотите удалить {0} эпизодов?",
"MessageConfirmRemoveListeningSessions": "Are you sure you want to remove {0} listening sessions?",
"MessageConfirmRemoveListeningSessions": "Вы уверены, что хотите удалить {0} сеансов прослушивания?",
"MessageConfirmRemoveNarrator": "Вы уверены, что хотите удалить чтеца \"{0}\"?",
"MessageConfirmRemovePlaylist": "Вы уверены, что хотите удалить плейлист \"{0}\"?",
"MessageConfirmRenameGenre": "Вы уверены, что хотите переименовать жанр \"{0}\" в \"{1}\" для всех элементов?",
@ -629,13 +639,12 @@
"MessageConfirmRenameTag": "Вы уверены, что хотите переименовать тег \"{0}\" в \"{1}\" для всех элементов?",
"MessageConfirmRenameTagMergeNote": "Примечание: Этот тег уже существует, поэтому они будут объединены.",
"MessageConfirmRenameTagWarning": "Предупреждение! Похожий тег с другими начальными буквами уже существует \"{0}\".",
"MessageConfirmReScanLibraryItems": "Вы уверены, что хотите пересканировать {0} элементов?",
"MessageConfirmSendEbookToDevice": "Вы уверены, что хотите отправить {0} e-книгу \"{1}\" на устройство \"{2}\"?",
"MessageDownloadingEpisode": "Эпизод скачивается",
"MessageDragFilesIntoTrackOrder": "Перетащите файлы для исправления порядка треков",
"MessageEmbedFinished": "Встраивание завершено!",
"MessageEpisodesQueuedForDownload": "{0} Эпизод(ов) запланировано для закачки",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "Чтобы обеспечить доставку электронных книг, вам может потребоваться добавить указанный выше адрес электронной почты в качестве действительного отправителя для каждого устройства, перечисленного ниже.",
"MessageFeedURLWillBe": "URL канала будет {0}",
"MessageFetching": "Завершается...",
"MessageForceReScanDescription": "будет сканировать все файлы снова, как свежее сканирование. Теги ID3 аудиофайлов, OPF-файлы и текстовые файлы будут сканироваться как новые.",
@ -647,7 +656,7 @@
"MessageListeningSessionsInTheLastYear": "{0} сеансов прослушивания в прошлом году",
"MessageLoading": "Загрузка...",
"MessageLoadingFolders": "Загрузка каталогов...",
"MessageLogsDescription": "Logs are stored in <code>/metadata/logs</code> as JSON files. Crash logs are stored in <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "Журналы хранятся в <code>/metadata/logs</code> в виде JSON-файлов. Журналы сбоев хранятся в <code>/metadata/logs/crash_logs.txt</code>.",
"MessageM4BFailed": "M4B Ошибка!",
"MessageM4BFinished": "M4B Завершено!",
"MessageMapChapterTitles": "Сопоставление названий глав с существующими главами аудиокниги без корректировки временных меток",
@ -683,10 +692,10 @@
"MessageNoSeries": "Нет серий",
"MessageNoTags": "Нет тегов",
"MessageNoTasksRunning": "Нет выполняемых задач",
"MessageNotYetImplemented": "Пока не реализовано",
"MessageNoUpdateNecessary": "Обновление не требуется",
"MessageNoUpdatesWereNecessary": "Обновления не требовались",
"MessageNoUserPlaylists": "У вас нет плейлистов",
"MessageNotYetImplemented": "Пока не реализовано",
"MessageOr": "или",
"MessagePauseChapter": "Пауза воспроизведения главы",
"MessagePlayChapter": "Прослушать начало главы",
@ -702,7 +711,7 @@
"MessageRestoreBackupConfirm": "Вы уверены, что хотите восстановить резервную копию, созданную",
"MessageRestoreBackupWarning": "Восстановление резервной копии перезапишет всю базу данных, расположенную в /config, и обложки изображений в /metadata/items и /metadata/authors.<br/><br/>Бэкапы не изменяют файлы в папках библиотеки. Если вы включили параметры сервера для хранения обложек и метаданных в папках библиотеки, то они не резервируются и не перезаписываются.<br/><br/>Все клиенты, использующие ваш сервер, будут автоматически обновлены.",
"MessageSearchResultsFor": "Результаты поиска для",
"MessageSelected": "{0} selected",
"MessageSelected": "{0} выбрано",
"MessageServerCouldNotBeReached": "Не удалось связаться с сервером",
"MessageSetChaptersFromTracksDescription": "Установка глав с использованием каждого аудиофайла в качестве главы и заголовка главы в качестве имени аудиофайла",
"MessageStartPlaybackAtTime": "Начать воспроизведение для \"{0}\" с {1}?",
@ -751,8 +760,8 @@
"ToastBookmarkRemoveSuccess": "Закладка удалена",
"ToastBookmarkUpdateFailed": "Не удалось обновить закладку",
"ToastBookmarkUpdateSuccess": "Закладка обновлена",
"ToastCachePurgeFailed": "Failed to purge cache",
"ToastCachePurgeSuccess": "Cache purged successfully",
"ToastCachePurgeFailed": "Не удалось очистить кэш",
"ToastCachePurgeSuccess": "Кэш успешно очищен",
"ToastChaptersHaveErrors": "Главы имеют ошибки",
"ToastChaptersMustHaveTitles": "Главы должны содержать названия",
"ToastCollectionItemsRemoveFailed": "Не удалось удалить элемент(ы) из коллекции",
@ -761,9 +770,9 @@
"ToastCollectionRemoveSuccess": "Коллекция удалена",
"ToastCollectionUpdateFailed": "Не удалось обновить коллекцию",
"ToastCollectionUpdateSuccess": "Коллекция обновлена",
"ToastDeleteFileFailed": "Failed to delete file",
"ToastDeleteFileSuccess": "File deleted",
"ToastFailedToLoadData": "Failed to load data",
"ToastDeleteFileFailed": "Не удалось удалить файл",
"ToastDeleteFileSuccess": "Файл удален",
"ToastFailedToLoadData": "Не удалось загрузить данные",
"ToastItemCoverUpdateFailed": "Не удалось обновить обложку элемента",
"ToastItemCoverUpdateSuccess": "Обложка элемента обновлена",
"ToastItemDetailsUpdateFailed": "Не удалось обновить сведения об элементе",
@ -789,24 +798,24 @@
"ToastPlaylistUpdateSuccess": "Плейлист обновлен",
"ToastPodcastCreateFailed": "Не удалось создать подкаст",
"ToastPodcastCreateSuccess": "Подкаст успешно создан",
"ToastRemoveItemFromCollectionFailed": "Не удалось удалить элемент из коллекции",
"ToastRemoveItemFromCollectionSuccess": "Элемент удален из коллекции",
"ToastRSSFeedCloseFailed": "Не удалось закрыть RSS-канал",
"ToastRSSFeedCloseSuccess": "RSS-канал закрыт",
"ToastRemoveItemFromCollectionFailed": "Не удалось удалить элемент из коллекции",
"ToastRemoveItemFromCollectionSuccess": "Элемент удален из коллекции",
"ToastSendEbookToDeviceFailed": "Не удалось отправить e-книгу на устройство",
"ToastSendEbookToDeviceSuccess": "E-книга отправлена на устройство \"{0}\"",
"ToastSeriesUpdateFailed": "Не удалось обновить серию",
"ToastSeriesUpdateSuccess": "Успешное обновление серии",
"ToastServerSettingsUpdateFailed": "Failed to update server settings",
"ToastServerSettingsUpdateSuccess": "Server settings updated",
"ToastServerSettingsUpdateFailed": "Не удалось обновить настройки сервера",
"ToastServerSettingsUpdateSuccess": "Обновлены настройки сервера",
"ToastSessionDeleteFailed": "Не удалось удалить сеанс",
"ToastSessionDeleteSuccess": "Сеанс удален",
"ToastSocketConnected": "Сокет подключен",
"ToastSocketDisconnected": "Сокет отключен",
"ToastSocketFailedToConnect": "Не удалось подключить сокет",
"ToastSortingPrefixesEmptyError": "Must have at least 1 sorting prefix",
"ToastSortingPrefixesUpdateFailed": "Failed to update sorting prefixes",
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastSortingPrefixesEmptyError": "Должен быть хотя бы 1 префикс сортировки",
"ToastSortingPrefixesUpdateFailed": "Не удалось обновить префиксы сортировки",
"ToastSortingPrefixesUpdateSuccess": "Обновлены префиксы сортировки ({0} элементов)",
"ToastUserDeleteFailed": "Не удалось удалить пользователя",
"ToastUserDeleteSuccess": "Пользователь удален"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Tillämpa",
"ButtonApplyChapters": "Tillämpa kapitel",
"ButtonAuthors": "Författare",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Bläddra efter mapp",
"ButtonCancel": "Avbryt",
"ButtonCancelEncode": "Avbryt kodning",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Previous Chapter",
"ButtonPurgeAllCache": "Rensa all cache",
"ButtonPurgeItemsCache": "Rensa föremåls-cache",
"ButtonPurgeMediaProgress": "Rensa medieförlopp",
"ButtonQueueAddItem": "Lägg till i kön",
"ButtonQueueRemoveItem": "Ta bort från kön",
"ButtonQuickMatch": "Snabb matchning",
"ButtonReScan": "Omstart",
"ButtonRead": "Läs",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Ta bort från Fortsätt lyssna",
"ButtonRemoveFromContinueReading": "Ta bort från Fortsätt läsa",
"ButtonRemoveSeriesFromContinueSeries": "Ta bort serie från Fortsätt serie",
"ButtonReScan": "Omstart",
"ButtonReset": "Återställ",
"ButtonResetToDefault": "Återställ till standard",
"ButtonRestore": "Återställ",
@ -104,8 +104,8 @@
"HeaderAccount": "Konto",
"HeaderAdvanced": "Avancerad",
"HeaderAppriseNotificationSettings": "Apprise Meddelandeinställningar",
"HeaderAudiobookTools": "Ljudbokshantering",
"HeaderAudioTracks": "Ljudspår",
"HeaderAudiobookTools": "Ljudbokshantering",
"HeaderAuthentication": "Authentication",
"HeaderBackups": "Säkerhetskopior",
"HeaderChangePassword": "Ändra lösenord",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Samlingselement",
"HeaderCover": "Omslag",
"HeaderCurrentDownloads": "Aktuella nedladdningar",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Custom Metadata Providers",
"HeaderDetails": "Detaljer",
"HeaderDownloadQueue": "Nedladdningskö",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Spellistobjekt",
"HeaderPodcastsToAdd": "Podcaster att lägga till",
"HeaderPreviewCover": "Förhandsgranska omslag",
"HeaderRemoveEpisode": "Ta bort avsnitt",
"HeaderRemoveEpisodes": "Ta bort {0} avsnitt",
"HeaderRSSFeedGeneral": "RSS-information",
"HeaderRSSFeedIsOpen": "RSS-flödet är öppet",
"HeaderRSSFeeds": "RSS-flöden",
"HeaderRemoveEpisode": "Ta bort avsnitt",
"HeaderRemoveEpisodes": "Ta bort {0} avsnitt",
"HeaderSavedMediaProgress": "Sparad medieförlopp",
"HeaderSchedule": "Schema",
"HeaderScheduleLibraryScans": "Schemalagda biblioteksskanningar",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Gäst",
"LabelAccountTypeUser": "Användare",
"LabelActivity": "Aktivitet",
"LabelAdded": "Tillagd",
"LabelAddedAt": "Tillagd vid",
"LabelAddToCollection": "Lägg till i Samling",
"LabelAddToCollectionBatch": "Lägg till {0} böcker i Samlingen",
"LabelAddToPlaylist": "Lägg till i Spellista",
"LabelAddToPlaylistBatch": "Lägg till {0} objekt i Spellistan",
"LabelAdded": "Tillagd",
"LabelAddedAt": "Tillagd vid",
"LabelAdminUsersOnly": "Endast administratörer",
"LabelAll": "Alla",
"LabelAllUsers": "Alla användare",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Ändra lösenord",
"LabelChannels": "Kanaler",
"LabelChapterTitle": "Kapitelrubrik",
"LabelChapters": "Kapitel",
"LabelChaptersFound": "hittade kapitel",
"LabelChapterTitle": "Kapitelrubrik",
"LabelClickForMoreInfo": "Klicka för mer information",
"LabelClosePlayer": "Stäng spelaren",
"LabelCodec": "Codec",
@ -306,6 +307,7 @@
"LabelFolder": "Mapp",
"LabelFolders": "Mappar",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Teckensnittsfamilj",
"LabelFontItalic": "Italic",
"LabelFontScale": "Teckensnittsskala",
@ -321,9 +323,9 @@
"LabelHour": "Timme",
"LabelIcon": "Ikon",
"LabelImageURLFromTheWeb": "Bild-URL från webben",
"LabelInProgress": "Pågående",
"LabelIncludeInTracklist": "Inkludera i spårlista",
"LabelIncomplete": "Ofullständig",
"LabelInProgress": "Pågående",
"LabelInterval": "Intervall",
"LabelIntervalCustomDailyWeekly": "Anpassat dagligt/veckovis",
"LabelIntervalEvery12Hours": "Var 12:e timme",
@ -337,6 +339,7 @@
"LabelItem": "Objekt",
"LabelLanguage": "Språk",
"LabelLanguageDefaultServer": "Standardspråk för server",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Senaste bok tillagd",
"LabelLastBookUpdated": "Senaste bok uppdaterad",
"LabelLastSeen": "Senast sedd",
@ -348,6 +351,7 @@
"LabelLess": "Mindre",
"LabelLibrariesAccessibleToUser": "Åtkomliga bibliotek för användare",
"LabelLibrary": "Bibliotek",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Biblioteksobjekt",
"LabelLibraryName": "Biblioteksnamn",
"LabelLimit": "Begränsning",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
"LabelMediaPlayer": "Mediaspelare",
"LabelMediaType": "Mediatyp",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadataleverantör",
"LabelMetaTag": "Metamärke",
"LabelMetaTags": "Metamärken",
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
"LabelMetadataProvider": "Metadataleverantör",
"LabelMinute": "Minut",
"LabelMissing": "Saknad",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Berättare",
"LabelNarrators": "Berättare",
"LabelNew": "Ny",
"LabelNewPassword": "Nytt lösenord",
"LabelNewestAuthors": "Nyaste författare",
"LabelNewestEpisodes": "Nyaste avsnitt",
"LabelNewPassword": "Nytt lösenord",
"LabelNextBackupDate": "Nästa säkerhetskopia datum",
"LabelNextScheduledRun": "Nästa schemalagda körning",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Inga avsnitt valda",
"LabelNotes": "Anteckningar",
"LabelNotFinished": "Ej avslutad",
"LabelNotStarted": "Inte påbörjad",
"LabelNotes": "Anteckningar",
"LabelNotificationAppriseURL": "Apprise URL(er)",
"LabelNotificationAvailableVariables": "Tillgängliga variabler",
"LabelNotificationBodyTemplate": "Kroppsmall",
"LabelNotificationEvent": "Aviseringshändelse",
"LabelNotificationTitleTemplate": "Titelsmall",
"LabelNotificationsMaxFailedAttempts": "Max antal misslyckade försök",
"LabelNotificationsMaxFailedAttemptsHelp": "Aviseringar inaktiveras när de misslyckas med att skickas så många gånger",
"LabelNotificationsMaxQueueSize": "Max köstorlek för aviseringsevenemang",
"LabelNotificationsMaxQueueSizeHelp": "Evenemang är begränsade till att utlösa ett per sekund. Evenemang kommer att ignoreras om kön är full. Detta förhindrar aviseringsspam.",
"LabelNotificationTitleTemplate": "Titelsmall",
"LabelNotStarted": "Inte påbörjad",
"LabelNumberOfBooks": "Antal böcker",
"LabelNumberOfEpisodes": "Antal avsnitt",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Kan ladda upp",
"LabelPersonalYearReview": "Your Year in Review ({0})",
"LabelPhotoPathURL": "Bildsökväg/URL",
"LabelPlaylists": "Spellistor",
"LabelPlayMethod": "Spelläge",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Spellistor",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcasts",
"LabelPodcastSearchRegion": "Podcast-sökområde",
"LabelPodcastType": "Podcasttyp",
"LabelPodcasts": "Podcasts",
"LabelPort": "Port",
"LabelPrefixesToIgnore": "Prefix att ignorera (skiftlägesokänsligt)",
"LabelPreventIndexing": "Förhindra att ditt flöde indexeras av iTunes och Google-podcastsökmotorer",
@ -427,25 +433,26 @@
"LabelProgress": "Framsteg",
"LabelProvider": "Leverantör",
"LabelPubDate": "Publiceringsdatum",
"LabelPublisher": "Utgivare",
"LabelPublishYear": "Publiceringsår",
"LabelRead": "Läst",
"LabelReadAgain": "Läs igen",
"LabelReadEbookWithoutProgress": "Läs e-bok utan att behålla framsteg",
"LabelRecentlyAdded": "Nyligen tillagd",
"LabelRecentSeries": "Senaste serier",
"LabelRecommended": "Rekommenderad",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Utgivningsdatum",
"LabelRemoveCover": "Ta bort omslag",
"LabelRowsPerPage": "Rows per page",
"LabelPublisher": "Utgivare",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Anpassad ägarens e-post",
"LabelRSSFeedCustomOwnerName": "Anpassat ägarnamn",
"LabelRSSFeedOpen": "Öppna RSS-flöde",
"LabelRSSFeedPreventIndexing": "Förhindra indexering",
"LabelRSSFeedSlug": "RSS-flödesslag",
"LabelRSSFeedURL": "RSS-flöde URL",
"LabelRead": "Läst",
"LabelReadAgain": "Läs igen",
"LabelReadEbookWithoutProgress": "Läs e-bok utan att behålla framsteg",
"LabelRecentSeries": "Senaste serier",
"LabelRecentlyAdded": "Nyligen tillagd",
"LabelRecommended": "Rekommenderad",
"LabelRedo": "Redo",
"LabelRegion": "Region",
"LabelReleaseDate": "Utgivningsdatum",
"LabelRemoveCover": "Ta bort omslag",
"LabelRowsPerPage": "Rows per page",
"LabelSearchTerm": "Sökterm",
"LabelSearchTitle": "Sök titel",
"LabelSearchTitleOrASIN": "Sök titel eller ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Sleeptimer",
"LabelSlug": "Slug",
"LabelStart": "Start",
"LabelStartTime": "Starttid",
"LabelStarted": "Startad",
"LabelStartedAt": "Startad vid",
"LabelStartTime": "Starttid",
"LabelStatsAudioTracks": "Ljudspår",
"LabelStatsAuthors": "Författare",
"LabelStatsBestDay": "Bästa dag",
@ -564,9 +571,9 @@
"LabelUnknown": "Okänd",
"LabelUpdateCover": "Uppdatera omslag",
"LabelUpdateCoverHelp": "Tillåt överskrivning av befintliga omslag för de valda böckerna när en matchning hittas",
"LabelUpdatedAt": "Uppdaterad vid",
"LabelUpdateDetails": "Uppdatera detaljer",
"LabelUpdateDetailsHelp": "Tillåt överskrivning av befintliga detaljer för de valda böckerna när en matchning hittas",
"LabelUpdatedAt": "Uppdaterad vid",
"LabelUploaderDragAndDrop": "Dra och släpp filer eller mappar",
"LabelUploaderDropFiles": "Släpp filer",
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Säkerhetskopieringar inkluderar användare, användares framsteg, biblioteksföremål, serverinställningar och bilder lagrade i <code>/metadata/items</code> & <code>/metadata/authors</code>. Säkerhetskopieringar inkluderar <strong>inte</strong> några filer lagrade i dina biblioteksmappar.",
"MessageBatchQuickMatchDescription": "Quick Match kommer försöka lägga till saknade omslag och metadata för de valda föremålen. Aktivera alternativen nedan för att tillåta Quick Match att överskriva befintliga omslag och/eller metadata.",
"MessageBookshelfNoCollections": "Du har ännu inte skapat några samlingar",
"MessageBookshelfNoResultsForFilter": "Inga resultat för filter \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Inga RSS-flöden är öppna",
"MessageBookshelfNoResultsForFilter": "Inga resultat för filter \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Du har inga serier",
"MessageChapterEndIsAfter": "Kapitelns slut är efter din ljudboks slut",
"MessageChapterErrorFirstNotZero": "Första kapitlet måste börja vid 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Är du säker på att du vill markera alla böcker i denna serie som avslutade?",
"MessageConfirmMarkSeriesNotFinished": "Är du säker på att du vill markera alla böcker i denna serie som inte avslutade?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Varning! Quick embed kommer inte att säkerhetskopiera dina ljudfiler. Se till att du har en säkerhetskopia av dina ljudfiler. <br><br>Vill du fortsätta?",
"MessageConfirmReScanLibraryItems": "Är du säker på att du vill göra omgenomsökning för {0} objekt?",
"MessageConfirmRemoveAllChapters": "Är du säker på att du vill ta bort alla kapitel?",
"MessageConfirmRemoveAuthor": "Är du säker på att du vill ta bort författaren \"{0}\"?",
"MessageConfirmRemoveCollection": "Är du säker på att du vill ta bort samlingen \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Är du säker på att du vill byta namn på taggen \"{0}\" till \"{1}\" för alla objekt?",
"MessageConfirmRenameTagMergeNote": "Observera: Den här taggen finns redan, så de kommer att slås samman.",
"MessageConfirmRenameTagWarning": "Varning! En liknande tagg med annat skrivsätt finns redan \"{0}\".",
"MessageConfirmReScanLibraryItems": "Är du säker på att du vill göra omgenomsökning för {0} objekt?",
"MessageConfirmSendEbookToDevice": "Är du säker på att du vill skicka {0} e-bok \"{1}\" till enheten \"{2}\"?",
"MessageDownloadingEpisode": "Laddar ner avsnitt",
"MessageDragFilesIntoTrackOrder": "Dra filer till rätt spårordning",
@ -683,10 +692,10 @@
"MessageNoSeries": "Inga serier",
"MessageNoTags": "Inga taggar",
"MessageNoTasksRunning": "Inga pågående uppgifter",
"MessageNotYetImplemented": "Ännu inte implementerad",
"MessageNoUpdateNecessary": "Ingen uppdatering krävs",
"MessageNoUpdatesWereNecessary": "Inga uppdateringar var nödvändiga",
"MessageNoUserPlaylists": "Du har inga spellistor",
"MessageNotYetImplemented": "Ännu inte implementerad",
"MessageOr": "eller",
"MessagePauseChapter": "Pausa kapiteluppspelning",
"MessagePlayChapter": "Lyssna på kapitlets början",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Spellistan uppdaterad",
"ToastPodcastCreateFailed": "Misslyckades med att skapa podcasten",
"ToastPodcastCreateSuccess": "Podcasten skapad framgångsrikt",
"ToastRemoveItemFromCollectionFailed": "Misslyckades med att ta bort objektet från samlingen",
"ToastRemoveItemFromCollectionSuccess": "Objektet borttaget från samlingen",
"ToastRSSFeedCloseFailed": "Misslyckades med att stänga RSS-flödet",
"ToastRSSFeedCloseSuccess": "RSS-flödet stängt",
"ToastRemoveItemFromCollectionFailed": "Misslyckades med att ta bort objektet från samlingen",
"ToastRemoveItemFromCollectionSuccess": "Objektet borttaget från samlingen",
"ToastSendEbookToDeviceFailed": "Misslyckades med att skicka e-boken till enheten",
"ToastSendEbookToDeviceSuccess": "E-boken skickad till enheten \"{0}\"",
"ToastSeriesUpdateFailed": "Serieuppdateringen misslyckades",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Misslyckades med att ta bort användaren",
"ToastUserDeleteSuccess": "Användaren borttagen"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Застосувати",
"ButtonApplyChapters": "Зберегти глави",
"ButtonAuthors": "Автори",
"ButtonBack": "Назад",
"ButtonBrowseForFolder": "Огляд тек",
"ButtonCancel": "Скасувати",
"ButtonCancelEncode": "Скасувати кодування",
@ -34,7 +35,7 @@
"ButtonIssues": "Проблеми",
"ButtonJumpBackward": "Перейти назад",
"ButtonJumpForward": "Перейти вперед",
"ButtonLatest": "Останній",
"ButtonLatest": "Останні",
"ButtonLibrary": "Бібліотека",
"ButtonLogout": "Вийти",
"ButtonLookup": "Пошук",
@ -49,17 +50,17 @@
"ButtonOpenFeed": "Відкрити стрічку",
"ButtonOpenManager": "Відкрити менеджер",
"ButtonPause": "Пауза",
"ButtonPlay": "Грати",
"ButtonPlay": "Слухати",
"ButtonPlaying": "Відтворюється",
"ButtonPlaylists": "Списки відтворення",
"ButtonPrevious": "Попередній",
"ButtonPreviousChapter": "Попередня глава",
"ButtonPurgeAllCache": "Очистити весь кеш",
"ButtonPurgeItemsCache": "Очистити кеш елементів",
"ButtonPurgeMediaProgress": "Очистити прогрес",
"ButtonQueueAddItem": "Додати до черги",
"ButtonQueueRemoveItem": "Вилучити з черги",
"ButtonQuickMatch": "Швидкий пошук",
"ButtonReScan": "Пересканувати",
"ButtonRead": "Читати",
"ButtonReadLess": "Згорнути",
"ButtonReadMore": "Читати далі",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Видалити з Продовжити слухати",
"ButtonRemoveFromContinueReading": "Видалити з Продовжити читання",
"ButtonRemoveSeriesFromContinueSeries": "Видалити серію з Продовжити серії",
"ButtonReScan": "Пересканувати",
"ButtonReset": "Скинути",
"ButtonResetToDefault": "Скинути до стандартних",
"ButtonRestore": "Відновити",
@ -104,8 +104,8 @@
"HeaderAccount": "Профіль",
"HeaderAdvanced": "Розширені",
"HeaderAppriseNotificationSettings": "Налаштування сповіщень Apprise",
"HeaderAudiobookTools": "Інструменти керування файлами книг",
"HeaderAudioTracks": "Аудіодоріжки",
"HeaderAudiobookTools": "Інструменти керування файлами книг",
"HeaderAuthentication": "Автентифікація",
"HeaderBackups": "Резервні копії",
"HeaderChangePassword": "Змінити пароль",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Елементи добірки",
"HeaderCover": "Обкладинка",
"HeaderCurrentDownloads": "Поточні завантаження",
"HeaderCustomMessageOnLogin": "Повідомлення при вході",
"HeaderCustomMetadataProviders": "Постачальники метаданих",
"HeaderDetails": "Подробиці",
"HeaderDownloadQueue": "Черга завантажень",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Елементи списку відтворення",
"HeaderPodcastsToAdd": "Додати подкасти",
"HeaderPreviewCover": "Попередній перегляд",
"HeaderRemoveEpisode": "Видалити епізод",
"HeaderRemoveEpisodes": "Видалити епізодів: {0}",
"HeaderRSSFeedGeneral": "Подробиці RSS",
"HeaderRSSFeedIsOpen": "RSS-канал відкрито",
"HeaderRSSFeeds": "RSS-канали",
"HeaderRemoveEpisode": "Видалити епізод",
"HeaderRemoveEpisodes": "Видалити епізодів: {0}",
"HeaderSavedMediaProgress": "Збережений прогрес медіа",
"HeaderSchedule": "Розклад",
"HeaderScheduleLibraryScans": "Розклад автосканування бібліотеки",
@ -191,18 +192,18 @@
"LabelAbridged": "Скорочена",
"LabelAbridgedChecked": "Скорочена (з прапорцем)",
"LabelAbridgedUnchecked": "Нескорочена (без прапорця)",
"LabelAccessibleBy": "Accessible by",
"LabelAccessibleBy": "Доступно",
"LabelAccountType": "Тип профілю",
"LabelAccountTypeAdmin": "Адміністратор",
"LabelAccountTypeGuest": "Гість",
"LabelAccountTypeUser": "Користувач",
"LabelActivity": "Активність",
"LabelAdded": "Додано",
"LabelAddedAt": "Дата додавання",
"LabelAddToCollection": "Додати у добірку",
"LabelAddToCollectionBatch": "Додати книги до добірки: {0}",
"LabelAddToPlaylist": "Додати до списку відтворення",
"LabelAddToPlaylistBatch": "Додано елементів у список відтворення: {0}",
"LabelAdded": "Додано",
"LabelAddedAt": "Дата додавання",
"LabelAdminUsersOnly": "Тільки для адміністраторів",
"LabelAll": "Усе",
"LabelAllUsers": "Усі користувачі",
@ -235,9 +236,9 @@
"LabelByAuthor": "від {0}",
"LabelChangePassword": "Змінити пароль",
"LabelChannels": "Канали",
"LabelChapterTitle": "Назва глави",
"LabelChapters": "Глави",
"LabelChaptersFound": "глав знайдено",
"LabelChapterTitle": "Назва глави",
"LabelClickForMoreInfo": "Натисніть, щоб дізнатися більше",
"LabelClosePlayer": "Закрити програвач",
"LabelCodec": "Кодек",
@ -279,8 +280,8 @@
"LabelEdit": "Редагувати",
"LabelEmail": "Електронна пошта",
"LabelEmailSettingsFromAddress": "Адреса відправника",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "Відхиляти неавторизовані сертифікати",
"LabelEmailSettingsRejectUnauthorizedHelp": "Вимкнення перевірки SSL-сертифікату може наражати ваше з’єднання на ризики безпеки, наприклад атаки типу «людина посередині». Вимкніть цей параметр, лише якщо ви розумієте наслідки та довіряєте поштовому серверу, до якого підключаєтеся.",
"LabelEmailSettingsSecure": "Безпечне",
"LabelEmailSettingsSecureHelp": "Увімкніть, аби використовувати TLS при підключенні до сервера. Якщо вимкнути, то TLS буде використано, якщо сервер підтримує STARTTLS. Увімкніть, якщо ви підключаєтеся до порту 465. Вимкніть для портів 587 або 25. (з nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "Тестова адреса",
@ -306,6 +307,7 @@
"LabelFolder": "Тека",
"LabelFolders": "Теки",
"LabelFontBold": "Жирний",
"LabelFontBoldness": "Товщина шрифту",
"LabelFontFamily": "Гарнітура",
"LabelFontItalic": "Курсив",
"LabelFontScale": "Розмір шрифту",
@ -321,9 +323,9 @@
"LabelHour": "Година",
"LabelIcon": "Іконка",
"LabelImageURLFromTheWeb": "URL зображення з мережі",
"LabelInProgress": "У процесі",
"LabelIncludeInTracklist": "Включити у список",
"LabelIncomplete": "Не завершено",
"LabelInProgress": "У процесі",
"LabelInterval": "Частота",
"LabelIntervalCustomDailyWeekly": "Налаштувати щодня/щотижня",
"LabelIntervalEvery12Hours": "Кожні 12 годин",
@ -337,6 +339,7 @@
"LabelItem": "Елемент",
"LabelLanguage": "Мова",
"LabelLanguageDefaultServer": "Типова мова сервера",
"LabelLanguages": "Мови",
"LabelLastBookAdded": "Останню книгу додано",
"LabelLastBookUpdated": "Останню книгу оновлено",
"LabelLastSeen": "Активність",
@ -348,6 +351,7 @@
"LabelLess": "Менше",
"LabelLibrariesAccessibleToUser": "Бібліотеки, доступні користувачу",
"LabelLibrary": "Бібліотека",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Елемент бібліотеки",
"LabelLibraryName": "Назва бібліотеки",
"LabelLimit": "Обмеження",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Використовується для підключення наявних користувачів. Після підключення користувач отримає унікальний id від вашого сервісу SSO",
"LabelMediaPlayer": "Програвач медіа",
"LabelMediaType": "Тип медіа",
"LabelMetadataOrderOfPrecedenceDescription": "Пріоритетніші джерела метаданих перезапишуть менш пріоритетні метадані",
"LabelMetadataProvider": "Джерело метаданих",
"LabelMetaTag": "Метатег",
"LabelMetaTags": "Метатеги",
"LabelMetadataOrderOfPrecedenceDescription": "Пріоритетніші джерела метаданих перезапишуть менш пріоритетні метадані",
"LabelMetadataProvider": "Джерело метаданих",
"LabelMinute": "Хвилина",
"LabelMissing": "Бракує",
"LabelMissingEbook": "Без електронної книги",
@ -378,24 +382,25 @@
"LabelNarrator": "Читець",
"LabelNarrators": "Читці",
"LabelNew": "Нове",
"LabelNewPassword": "Новий пароль",
"LabelNewestAuthors": "Нові автори",
"LabelNewestEpisodes": "Нові епізоди",
"LabelNewPassword": "Новий пароль",
"LabelNextBackupDate": "Дата наступного резервного копіювання",
"LabelNextScheduledRun": "Наступний запланований запуск",
"LabelNoCustomMetadataProviders": "Без постачальників метаданих",
"LabelNoEpisodesSelected": "Не вибрано жодного епізоду",
"LabelNotes": "Примітки",
"LabelNotFinished": "Незавершені",
"LabelNotStarted": "Не розпочато",
"LabelNotes": "Примітки",
"LabelNotificationAppriseURL": "URL Apprise",
"LabelNotificationAvailableVariables": "Доступні змінні",
"LabelNotificationBodyTemplate": "Шаблон сповіщення",
"LabelNotificationEvent": "Сповіщення про події",
"LabelNotificationTitleTemplate": "Шаблон заголовку",
"LabelNotificationsMaxFailedAttempts": "Ліміт невдалих спроб",
"LabelNotificationsMaxFailedAttemptsHelp": "Сповіщення буде вимкнено після багатьох невдалих надсилань",
"LabelNotificationsMaxQueueSize": "Ліміт розміру черги сповіщень",
"LabelNotificationsMaxQueueSizeHelp": "Події обмежені до 1 на секунду. Події буде проігноровано, якщо ліміт черги досягнуто. Це запобігає спаму сповіщеннями.",
"LabelNotificationTitleTemplate": "Шаблон заголовку",
"LabelNotStarted": "Не розпочато",
"LabelNumberOfBooks": "Кількість книг",
"LabelNumberOfEpisodes": "Кількість епізодів",
"LabelOpenIDAdvancedPermsClaimDescription": "Назва OpenID claim, що містить розширені дозволи на дії користувачів у додатку, які будуть застосовуватися до ролей, що не є адміністраторами (<b>якщо налаштовано</b>). Якщо у відповіді нема claim, у доступі до Audiobookshelf буде відмовлено. Якщо відсутня хоча б одна опція, відповідь буде вважатися <code>хибною</code>. Переконайтеся, що запит постачальника ідентифікаційних даних відповідає очікуваній структурі:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Може завантажувати",
"LabelPersonalYearReview": "Ваші підсумки року ({0})",
"LabelPhotoPathURL": "Шлях/URL фото",
"LabelPlaylists": "Списки відтворення",
"LabelPlayMethod": "Метод відтворення",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Списки відтворення",
"LabelPodcast": "Подкаст",
"LabelPodcasts": "Подкасти",
"LabelPodcastSearchRegion": "Регіон пошуку подкасту",
"LabelPodcastType": "Тип подкасту",
"LabelPodcasts": "Подкасти",
"LabelPort": "Порт",
"LabelPrefixesToIgnore": "Ігнорувати префікси (з урахуванням регістру)",
"LabelPreventIndexing": "Заборонити індексування вашого каналу каталогами подкастів iTunes та Google",
@ -427,25 +433,26 @@
"LabelProgress": "Прогрес",
"LabelProvider": "Джерело",
"LabelPubDate": "Дата публікації",
"LabelPublisher": "Видавець",
"LabelPublishYear": "Рік публікації",
"LabelRead": "Читати",
"LabelReadAgain": "Читати знову",
"LabelReadEbookWithoutProgress": "Читати книгу без збереження прогресу",
"LabelRecentlyAdded": "Нещодавно додані",
"LabelRecentSeries": "Останні серії",
"LabelRecommended": "Рекомендовані",
"LabelRedo": "Повторити",
"LabelRegion": "Регіон",
"LabelReleaseDate": "Дата публікації",
"LabelRemoveCover": "Видалити обкладинку",
"LabelRowsPerPage": "Рядків на сторінку",
"LabelPublisher": "Видавець",
"LabelPublishers": "Видавці",
"LabelRSSFeedCustomOwnerEmail": "Користувацька електронна адреса власника",
"LabelRSSFeedCustomOwnerName": "Користувацьке ім'я власника",
"LabelRSSFeedOpen": "RSS-канал відкрито",
"LabelRSSFeedPreventIndexing": "Запобігати індексації",
"LabelRSSFeedSlug": "Назва RSS-каналу",
"LabelRSSFeedURL": "Адреса RSS-каналу",
"LabelRead": "Читати",
"LabelReadAgain": "Читати знову",
"LabelReadEbookWithoutProgress": "Читати книгу без збереження прогресу",
"LabelRecentSeries": "Останні серії",
"LabelRecentlyAdded": "Нещодавно додані",
"LabelRecommended": "Рекомендовані",
"LabelRedo": "Повторити",
"LabelRegion": "Регіон",
"LabelReleaseDate": "Дата публікації",
"LabelRemoveCover": "Видалити обкладинку",
"LabelRowsPerPage": "Рядків на сторінку",
"LabelSearchTerm": "Пошуковий запит",
"LabelSearchTitle": "Пошук за назвою",
"LabelSearchTitleOrASIN": "Пошук назви або ASIN",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "Увімкнути спостерігача",
"LabelSettingsEnableWatcherForLibrary": "Увімкнути спостерігання тек бібліотеки",
"LabelSettingsEnableWatcherHelp": "Вмикає автоматичне додавання/оновлення елементів, коли спостерігаються зміни файлів. *Потребує перезавантаження сервера",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "Дозволити JavaScript-вміст у epub",
"LabelSettingsEpubsAllowScriptedContentHelp": "Дозволяти epub-файлам виконувати код. Вмикайте цей параметр лише якщо ви довіряєте джерелу epub-файлів.",
"LabelSettingsExperimentalFeatures": "Експериментальні функції",
"LabelSettingsExperimentalFeaturesHelp": "Функції в розробці, які потребують вашого відгуку та допомоги в тестуванні. Натисніть, щоб відкрити обговорення на Github.",
"LabelSettingsFindCovers": "Пошук обкладинок",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Таймер вимкнення",
"LabelSlug": "Назва",
"LabelStart": "Початок",
"LabelStartTime": "Час початку",
"LabelStarted": "Почато",
"LabelStartedAt": "Почато",
"LabelStartTime": "Час початку",
"LabelStatsAudioTracks": "Аудіодоріжки",
"LabelStatsAuthors": "Автори",
"LabelStatsBestDay": "Найкращий день",
@ -545,7 +552,7 @@
"LabelTimeToShift": "На скільки секунд зсунути",
"LabelTitle": "Назва",
"LabelToolsEmbedMetadata": "Вбудувати метадані",
"LabelToolsEmbedMetadataDescription": "Вбудувати метадані в аудіофайли, включно з обкладинками та главами",
"LabelToolsEmbedMetadataDescription": "Вбудувати метадані в аудіофайли, включно з обкладинками та главами.",
"LabelToolsMakeM4b": "Створити M4B-файл аудіокниги",
"LabelToolsMakeM4bDescription": "Створити .M4B-аудіокнигу з вбудованими метаданими, обкладинкою та главами.",
"LabelToolsSplitM4b": "Розділити M4B на MP3",
@ -564,9 +571,9 @@
"LabelUnknown": "Невідомо",
"LabelUpdateCover": "Оновити обкладинку",
"LabelUpdateCoverHelp": "Дозволити перезапис наявних обкладинок обраних книг після віднайдення",
"LabelUpdatedAt": "Оновлення",
"LabelUpdateDetails": "Оновити подробиці",
"LabelUpdateDetailsHelp": "Дозволити перезапис наявних подробиць обраних книг після віднайдення",
"LabelUpdatedAt": "Оновлення",
"LabelUploaderDragAndDrop": "Перетягніть файли або теки",
"LabelUploaderDropFiles": "Перетягніть файли",
"LabelUploaderItemFetchMetadataHelp": "Автоматично шукати назву, автора та серію",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Резервні копії містять користувачів, прогрес, подробиці елементів бібліотеки, налаштування сервера та зображення з <code>/metadata/items</code> та <code>/metadata/authors</code>. Резервні копії <strong>не</strong> містять жодних файлів з тек бібліотеки.",
"MessageBatchQuickMatchDescription": "Швидкий пошук спробує знайти відсутні обкладинки та метадані обраних елементів. Увімкніть налаштування нижче, аби дозволити заміну наявних обкладинок та/або метаданих під час швидкого пошуку.",
"MessageBookshelfNoCollections": "Ви не створили жодної добірки",
"MessageBookshelfNoResultsForFilter": "Немає результатів з фільтром \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Немає відкритих RSS-каналів",
"MessageBookshelfNoResultsForFilter": "Немає результатів з фільтром \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "Немає результатів за запитом",
"MessageBookshelfNoSeries": "Серії відсутні",
"MessageChapterEndIsAfter": "Кінець глави знаходиться після закінчення книги",
"MessageChapterErrorFirstNotZero": "Перша глава мусить починатися з 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Ви дійсно бажаєте позначити усі книги серії завершеними?",
"MessageConfirmMarkSeriesNotFinished": "Ви дійсно бажаєте позначити всі книги серії незавершеними?",
"MessageConfirmPurgeCache": "Очищення кешу видалить усю теку <code>/metadata/cache</code>. <br /><br />Ви дійсно бажаєте видалити теку кешу?",
"MessageConfirmPurgeItemsCache": "Очищення кешу елементів видалить усю теку <code>/metadata/cache/items</code>. <br />Ви певні?",
"MessageConfirmQuickEmbed": "Увага! Швидке вбудування не створює резервних копій ваших аудіо. Переконайтеся, що маєте копію ваших файлів.<br><br>Продовжити?",
"MessageConfirmReScanLibraryItems": "Ви дійсно бажаєте пересканувати елементи: {0}?",
"MessageConfirmRemoveAllChapters": "Ви дійсно бажаєте видалити усі глави?",
"MessageConfirmRemoveAuthor": "Ви дійсно бажаєте видалити автора \"{0}\"?",
"MessageConfirmRemoveCollection": "Ви дійсно бажаєте видалити добірку \"{0}\"?",
@ -629,13 +639,12 @@
"MessageConfirmRenameTag": "Ви дійсно бажаєте замінити мітку \"{0}\" на \"{1}\" для усіх елементів?",
"MessageConfirmRenameTagMergeNote": "Примітка: така мітка вже існує, тож їх буде об'єднано.",
"MessageConfirmRenameTagWarning": "Увага! Вже існує схожа мітка у іншому регістрі \"{0}\".",
"MessageConfirmReScanLibraryItems": "Ви дійсно бажаєте пересканувати елементи: {0}?",
"MessageConfirmSendEbookToDevice": "Ви дійсно хочете відправити на пристрій \"{2}\" електроні книги: {0}, \"{1}\"?",
"MessageDownloadingEpisode": "Завантаження епізоду",
"MessageDragFilesIntoTrackOrder": "Перетягніть файли до правильного порядку",
"MessageEmbedFinished": "Вбудовано!",
"MessageEpisodesQueuedForDownload": "Епізодів у черзі завантаження: {0}",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "Аби гарантувати отримання електронних книг, вам може знадобитися додати вказану вище адресу електронної пошти як правильного відправника на кожному з пристроїв зі списку нижче.",
"MessageFeedURLWillBe": "URL-адреса каналу буде {0}",
"MessageFetching": "Отримання...",
"MessageForceReScanDescription": "Просканує усі файли заново, неначе вперше. ID3-мітки, файли OPF та текстові файли будуть проскановані як нові.",
@ -683,10 +692,10 @@
"MessageNoSeries": "Без серії",
"MessageNoTags": "Без міток",
"MessageNoTasksRunning": "Немає активних завдань",
"MessageNotYetImplemented": "Ще не реалізовано",
"MessageNoUpdateNecessary": "Оновлення не потрібно",
"MessageNoUpdatesWereNecessary": "Оновлень не потрібно",
"MessageNoUserPlaylists": "У вас немає списків відтворення",
"MessageNotYetImplemented": "Ще не реалізовано",
"MessageOr": "або",
"MessagePauseChapter": "Призупинити відтворення глави",
"MessagePlayChapter": "Слухати початок глави",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Список відтворення оновлено",
"ToastPodcastCreateFailed": "Не вдалося створити подкаст",
"ToastPodcastCreateSuccess": "Подкаст успішно створено",
"ToastRemoveItemFromCollectionFailed": "Не вдалося видалити елемент із добірки",
"ToastRemoveItemFromCollectionSuccess": "Елемент видалено з добірки",
"ToastRSSFeedCloseFailed": "Не вдалося закрити RSS-канал",
"ToastRSSFeedCloseSuccess": "RSS-канал закрито",
"ToastRemoveItemFromCollectionFailed": "Не вдалося видалити елемент із добірки",
"ToastRemoveItemFromCollectionSuccess": "Елемент видалено з добірки",
"ToastSendEbookToDeviceFailed": "Не вдалося надіслати електронну книгу на пристрій",
"ToastSendEbookToDeviceSuccess": "Електронну книгу надіслано на пристрій \"{0}\"",
"ToastSeriesUpdateFailed": "Не вдалося оновити серію",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Префікси сортування оновлено ({0})",
"ToastUserDeleteFailed": "Не вдалося видалити користувача",
"ToastUserDeleteSuccess": "Користувача видалено"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "Áp Dụng",
"ButtonApplyChapters": "Áp Dụng Chương",
"ButtonAuthors": "Tác Giả",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "Duyệt Thư Mục",
"ButtonCancel": "Hủy",
"ButtonCancelEncode": "Hủy Mã Hóa",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "Chương Trước",
"ButtonPurgeAllCache": "Xóa Sạch Tất Cả Bộ Nhớ Cache",
"ButtonPurgeItemsCache": "Xóa Sạch Bộ Nhớ Cache Các Mục",
"ButtonPurgeMediaProgress": "Xóa Sạch Tiến Trình Phương Tiện",
"ButtonQueueAddItem": "Thêm vào hàng đợi",
"ButtonQueueRemoveItem": "Xóa khỏi hàng đợi",
"ButtonQuickMatch": "Khớp Nhanh",
"ButtonReScan": "Quét Lại",
"ButtonRead": "Đọc",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "Xóa khỏi Tiếp Tục Nghe",
"ButtonRemoveFromContinueReading": "Xóa khỏi Tiếp Tục Đọc",
"ButtonRemoveSeriesFromContinueSeries": "Xóa Series khỏi Tiếp Tục Series",
"ButtonReScan": "Quét Lại",
"ButtonReset": "Đặt Lại",
"ButtonResetToDefault": "Đặt Lại về Mặc Định",
"ButtonRestore": "Khôi Phục",
@ -104,8 +104,8 @@
"HeaderAccount": "Tài Khoản",
"HeaderAdvanced": "Nâng Cao",
"HeaderAppriseNotificationSettings": "Cài Đặt Thông Báo Apprise",
"HeaderAudiobookTools": "Công Cụ Quản Lý Tệp Truyện Nói",
"HeaderAudioTracks": "Các Track Âm Thanh",
"HeaderAudiobookTools": "Công Cụ Quản Lý Tệp Truyện Nói",
"HeaderAuthentication": "Xác Thực",
"HeaderBackups": "Bản Sao Lưu",
"HeaderChangePassword": "Thay Đổi Mật Khẩu",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "Các Mục Bộ Sưu Tập",
"HeaderCover": "Bìa",
"HeaderCurrentDownloads": "Tải Xuống Hiện Tại",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "Các Nhà Cung Cấp Metadata Tùy Chỉnh",
"HeaderDetails": "Chi Tiết",
"HeaderDownloadQueue": "Hàng Đợi Tải Xuống",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "Các Mục Danh Sách Phát",
"HeaderPodcastsToAdd": "Podcasts để Thêm",
"HeaderPreviewCover": "Xem Trước Bìa",
"HeaderRemoveEpisode": "Xóa Tập",
"HeaderRemoveEpisodes": "Xóa {0} Tập",
"HeaderRSSFeedGeneral": "Chi Tiết RSS",
"HeaderRSSFeedIsOpen": "RSS Feed Đã Mở",
"HeaderRSSFeeds": "RSS Feeds",
"HeaderRemoveEpisode": "Xóa Tập",
"HeaderRemoveEpisodes": "Xóa {0} Tập",
"HeaderSavedMediaProgress": "Tiến Trình Phương Tiện Đã Lưu",
"HeaderSchedule": "Lịch Trình",
"HeaderScheduleLibraryScans": "Lên Lịch Quét Tự Động Thư Viện",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "Khách",
"LabelAccountTypeUser": "Người Dùng",
"LabelActivity": "Hoạt Động",
"LabelAdded": "Đã Thêm",
"LabelAddedAt": "Đã Thêm Lúc",
"LabelAddToCollection": "Thêm vào Bộ Sưu Tập",
"LabelAddToCollectionBatch": "Thêm {0} Sách vào Bộ Sưu Tập",
"LabelAddToPlaylist": "Thêm vào Danh Sách Phát",
"LabelAddToPlaylistBatch": "Add {0} Items to Playlist",
"LabelAdded": "Đã Thêm",
"LabelAddedAt": "Đã Thêm Lúc",
"LabelAdminUsersOnly": "Admin users only",
"LabelAll": "All",
"LabelAllUsers": "All Users",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "Đổi Mật Khẩu",
"LabelChannels": "Kênh",
"LabelChapterTitle": "Tiêu đề Chương",
"LabelChapters": "Chương",
"LabelChaptersFound": "chương được tìm thấy",
"LabelChapterTitle": "Tiêu đề Chương",
"LabelClickForMoreInfo": "Nhấn để biết thêm thông tin",
"LabelClosePlayer": "Đóng trình phát",
"LabelCodec": "Mã hóa",
@ -306,6 +307,7 @@
"LabelFolder": "Thư Mục",
"LabelFolders": "Các Thư Mục",
"LabelFontBold": "Đậm",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "Gia đình font",
"LabelFontItalic": "Nghiêng",
"LabelFontScale": "Tỷ lệ font",
@ -321,9 +323,9 @@
"LabelHour": "Giờ",
"LabelIcon": "Biểu tượng",
"LabelImageURLFromTheWeb": "URL hình ảnh từ web",
"LabelInProgress": "Đang tiến hành",
"LabelIncludeInTracklist": "Bao gồm trong danh sách phát",
"LabelIncomplete": "Chưa hoàn thành",
"LabelInProgress": "Đang tiến hành",
"LabelInterval": "Khoảng cách",
"LabelIntervalCustomDailyWeekly": "Tuỳ chỉnh hàng ngày/hàng tuần",
"LabelIntervalEvery12Hours": "Mỗi 12 giờ",
@ -337,6 +339,7 @@
"LabelItem": "Mục",
"LabelLanguage": "Ngôn ngữ",
"LabelLanguageDefaultServer": "Ngôn ngữ Máy chủ mặc định",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "Sách mới nhất được thêm",
"LabelLastBookUpdated": "Sách mới nhất được cập nhật",
"LabelLastSeen": "Lần cuối nhìn thấy",
@ -348,6 +351,7 @@
"LabelLess": "Ít hơn",
"LabelLibrariesAccessibleToUser": "Thư viện có thể truy cập cho người dùng",
"LabelLibrary": "Thư viện",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "Mục thư viện",
"LabelLibraryName": "Tên thư viện",
"LabelLimit": "Giới hạn",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "Sử dụng để kết nối người dùng hiện có. Khi kết nối, người dùng sẽ được kết hợp bằng một ID duy nhất từ nhà cung cấp SSO của bạn",
"LabelMediaPlayer": "Trình phát đa phương tiện",
"LabelMediaType": "Loại phương tiện",
"LabelMetadataOrderOfPrecedenceDescription": "Nguồn siêu dữ liệu ưu tiên cao hơn sẽ ghi đè lên các nguồn siêu dữ liệu ưu tiên thấp hơn",
"LabelMetadataProvider": "Nhà cung cấp siêu dữ liệu",
"LabelMetaTag": "Thẻ Meta",
"LabelMetaTags": "Các thẻ Meta",
"LabelMetadataOrderOfPrecedenceDescription": "Nguồn siêu dữ liệu ưu tiên cao hơn sẽ ghi đè lên các nguồn siêu dữ liệu ưu tiên thấp hơn",
"LabelMetadataProvider": "Nhà cung cấp siêu dữ liệu",
"LabelMinute": "Phút",
"LabelMissing": "Thiếu",
"LabelMissingEbook": "Không có ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "Người kể",
"LabelNarrators": "Các người kể",
"LabelNew": "Mới",
"LabelNewPassword": "Mật khẩu mới",
"LabelNewestAuthors": "Nhà văn mới nhất",
"LabelNewestEpisodes": "Tập mới nhất",
"LabelNewPassword": "Mật khẩu mới",
"LabelNextBackupDate": "Ngày sao lưu tiếp theo",
"LabelNextScheduledRun": "Chạy tiếp theo theo lịch trình",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "Không có tập nào được chọn",
"LabelNotes": "Ghi chú",
"LabelNotFinished": "Chưa hoàn thành",
"LabelNotStarted": "Chưa bắt đầu",
"LabelNotes": "Ghi chú",
"LabelNotificationAppriseURL": "URL(s) thông báo",
"LabelNotificationAvailableVariables": "Biến có sẵn",
"LabelNotificationBodyTemplate": "Mẫu Nội dung",
"LabelNotificationEvent": "Sự kiện Thông báo",
"LabelNotificationTitleTemplate": "Mẫu Tiêu đề",
"LabelNotificationsMaxFailedAttempts": "Số lần thất bại tối đa",
"LabelNotificationsMaxFailedAttemptsHelp": "Thông báo sẽ bị vô hiệu hóa sau khi thất bại gửi số lần này",
"LabelNotificationsMaxQueueSize": "Kích thước hàng đợi tối đa cho sự kiện thông báo",
"LabelNotificationsMaxQueueSizeHelp": "Các sự kiện bị giới hạn mỗi giây chỉ gửi 1 lần. Các sự kiện sẽ bị bỏ qua nếu hàng đợi đạt kích thước tối đa. Điều này ngăn chặn spam thông báo.",
"LabelNotificationTitleTemplate": "Mẫu Tiêu đề",
"LabelNotStarted": "Chưa bắt đầu",
"LabelNumberOfBooks": "Số lượng Sách",
"LabelNumberOfEpisodes": "# của Tập",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "Có Thể Tải Lên",
"LabelPersonalYearReview": "Năm của Bạn trong Bài Đánh Giá ({0})",
"LabelPhotoPathURL": "Đường dẫn/URL ảnh",
"LabelPlaylists": "Danh sách phát",
"LabelPlayMethod": "Phương pháp phát",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "Danh sách phát",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Các podcast",
"LabelPodcastSearchRegion": "Vùng tìm kiếm podcast",
"LabelPodcastType": "Loại Podcast",
"LabelPodcasts": "Các podcast",
"LabelPort": "Cổng",
"LabelPrefixesToIgnore": "Tiền tố để bỏ qua (không phân biệt chữ hoa/chữ thường)",
"LabelPreventIndexing": "Ngăn chặn feed của bạn được chỉ mục bởi thư mục podcast của iTunes và Google",
@ -427,25 +433,26 @@
"LabelProgress": "Tiến độ",
"LabelProvider": "Nhà cung cấp",
"LabelPubDate": "Ngày Xuất bản",
"LabelPublisher": "Nhà xuất bản",
"LabelPublishYear": "Năm Xuất bản",
"LabelRead": "Đọc",
"LabelReadAgain": "Đọc lại",
"LabelReadEbookWithoutProgress": "Đọc ebook mà không giữ tiến độ",
"LabelRecentlyAdded": "Gần đây thêm vào",
"LabelRecentSeries": "Loạt phim gần đây",
"LabelRecommended": "Được khuyến nghị",
"LabelRedo": "Làm lại",
"LabelRegion": "Khu vực",
"LabelReleaseDate": "Ngày Phát hành",
"LabelRemoveCover": "Xóa ảnh bìa",
"LabelRowsPerPage": "Số dòng mỗi trang",
"LabelPublisher": "Nhà xuất bản",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "Email chủ sở hữu tùy chỉnh",
"LabelRSSFeedCustomOwnerName": "Tên chủ sở hữu tùy chỉnh",
"LabelRSSFeedOpen": "Mở RSS Feed",
"LabelRSSFeedPreventIndexing": "Ngăn chặn Chỉ mục RSS Feed",
"LabelRSSFeedSlug": "Slug RSS Feed",
"LabelRSSFeedURL": "URL RSS Feed",
"LabelRead": "Đọc",
"LabelReadAgain": "Đọc lại",
"LabelReadEbookWithoutProgress": "Đọc ebook mà không giữ tiến độ",
"LabelRecentSeries": "Loạt phim gần đây",
"LabelRecentlyAdded": "Gần đây thêm vào",
"LabelRecommended": "Được khuyến nghị",
"LabelRedo": "Làm lại",
"LabelRegion": "Khu vực",
"LabelReleaseDate": "Ngày Phát hành",
"LabelRemoveCover": "Xóa ảnh bìa",
"LabelRowsPerPage": "Số dòng mỗi trang",
"LabelSearchTerm": "Thuật ngữ tìm kiếm",
"LabelSearchTitle": "Tìm kiếm Tiêu đề",
"LabelSearchTitleOrASIN": "Tìm kiếm Tiêu đề hoặc ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "Hẹn giờ tắt",
"LabelSlug": "Slug",
"LabelStart": "Bắt đầu",
"LabelStartTime": "Thời gian bắt đầu",
"LabelStarted": "Đã bắt đầu",
"LabelStartedAt": "Bắt đầu vào",
"LabelStartTime": "Thời gian bắt đầu",
"LabelStatsAudioTracks": "Audio Tracks",
"LabelStatsAuthors": "Tác giả",
"LabelStatsBestDay": "Ngày tốt nhất",
@ -564,9 +571,9 @@
"LabelUnknown": "Không xác định",
"LabelUpdateCover": "Cập nhật ảnh bìa",
"LabelUpdateCoverHelp": "Cho phép ghi đè lên các ảnh bìa hiện có cho các cuốn sách được chọn khi tìm thấy một kết hợp",
"LabelUpdatedAt": "Cập nhật lúc",
"LabelUpdateDetails": "Cập nhật chi tiết",
"LabelUpdateDetailsHelp": "Cho phép ghi đè lên các chi tiết hiện có cho các cuốn sách được chọn khi tìm thấy một kết hợp",
"LabelUpdatedAt": "Cập nhật lúc",
"LabelUploaderDragAndDrop": "Kéo và thả tệp hoặc thư mục",
"LabelUploaderDropFiles": "Thả tệp",
"LabelUploaderItemFetchMetadataHelp": "Tự động lấy tiêu đề, tác giả và loạt",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "Bản sao bao gồm người dùng, tiến độ của người dùng, chi tiết mục thư viện, cài đặt máy chủ và hình ảnh được lưu trữ trong <code>/metadata/items</code> & <code>/metadata/authors</code>. Bản sao <strong>không</strong> bao gồm bất kỳ tệp nào được lưu trữ trong các thư mục thư viện của bạn.",
"MessageBatchQuickMatchDescription": "Quick Match sẽ cố gắng thêm các ảnh bìa và siêu dữ liệu bị thiếu cho các mục đã chọn. Bật các tùy chọn dưới đây để cho phép Quick Match ghi đè lên các ảnh bìa hiện có và / hoặc siêu dữ liệu.",
"MessageBookshelfNoCollections": "Bạn chưa tạo bất kỳ bộ sưu tập nào",
"MessageBookshelfNoResultsForFilter": "Không có Kết quả cho bộ lọc \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "Không có nguồn cung cấp RSS nào đang mở",
"MessageBookshelfNoResultsForFilter": "Không có Kết quả cho bộ lọc \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "Bạn không có bộ sách",
"MessageChapterEndIsAfter": "Kết thúc chương sau khi kết thúc sách nói của bạn",
"MessageChapterErrorFirstNotZero": "Chương đầu tiên phải bắt đầu từ 0",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "Bạn có chắc chắn muốn đánh dấu tất cả các sách trong loạt sách này đã kết thúc không?",
"MessageConfirmMarkSeriesNotFinished": "Bạn có chắc chắn muốn đánh dấu tất cả các sách trong loạt sách này chưa kết thúc không?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "Cảnh báo! Quick embed sẽ không sao lưu các tệp âm thanh của bạn. Đảm bảo bạn có một bản sao lưu của các tệp âm thanh của bạn. <br><br>Bạn có muốn tiếp tục không?",
"MessageConfirmReScanLibraryItems": "Bạn có chắc chắn muốn quét lại {0} mục không?",
"MessageConfirmRemoveAllChapters": "Bạn có chắc chắn muốn xóa tất cả các chương không?",
"MessageConfirmRemoveAuthor": "Bạn có chắc chắn muốn xóa tác giả \"{0}\" không?",
"MessageConfirmRemoveCollection": "Bạn có chắc chắn muốn xóa bộ sưu tập \"{0}\" không?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "Bạn có chắc chắn muốn đổi tên tag \"{0}\" thành \"{1}\" cho tất cả các mục không?",
"MessageConfirmRenameTagMergeNote": "Lưu ý: Thẻ này đã tồn tại nên chúng sẽ được hợp nhất.",
"MessageConfirmRenameTagWarning": "Cảnh báo! Một thẻ tương tự với kiểu chữ khác đã tồn tại \"{0}\".",
"MessageConfirmReScanLibraryItems": "Bạn có chắc chắn muốn quét lại {0} mục không?",
"MessageConfirmSendEbookToDevice": "Bạn có chắc chắn muốn gửi {0} ebook \"{1}\" đến thiết bị \"{2}\" không?",
"MessageDownloadingEpisode": "Đang tải tập phim",
"MessageDragFilesIntoTrackOrder": "Kéo tệp vào thứ tự track đúng",
@ -683,10 +692,10 @@
"MessageNoSeries": "Không có Bộ",
"MessageNoTags": "Không có Thẻ",
"MessageNoTasksRunning": "Không có Công việc đang chạy",
"MessageNotYetImplemented": "Chưa được triển khai",
"MessageNoUpdateNecessary": "Không cần cập nhật",
"MessageNoUpdatesWereNecessary": "Không cần cập nhật",
"MessageNoUserPlaylists": "Bạn chưa có danh sách phát",
"MessageNotYetImplemented": "Chưa được triển khai",
"MessageOr": "hoặc",
"MessagePauseChapter": "Tạm dừng phát chương",
"MessagePlayChapter": "Nghe từ đầu chương",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "Danh sách phát đã được cập nhật",
"ToastPodcastCreateFailed": "Tạo podcast thất bại",
"ToastPodcastCreateSuccess": "Podcast đã được tạo thành công",
"ToastRemoveItemFromCollectionFailed": "Xóa mục khỏi bộ sưu tập thất bại",
"ToastRemoveItemFromCollectionSuccess": "Mục đã được xóa khỏi bộ sưu tập",
"ToastRSSFeedCloseFailed": "Đóng nguồn cấp RSS thất bại",
"ToastRSSFeedCloseSuccess": "Nguồn cấp RSS đã được đóng",
"ToastRemoveItemFromCollectionFailed": "Xóa mục khỏi bộ sưu tập thất bại",
"ToastRemoveItemFromCollectionSuccess": "Mục đã được xóa khỏi bộ sưu tập",
"ToastSendEbookToDeviceFailed": "Gửi ebook đến thiết bị thất bại",
"ToastSendEbookToDeviceSuccess": "Ebook đã được gửi đến thiết bị \"{0}\"",
"ToastSeriesUpdateFailed": "Cập nhật loạt truyện thất bại",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "Xóa người dùng thất bại",
"ToastUserDeleteSuccess": "Người dùng đã được xóa"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "应用",
"ButtonApplyChapters": "应用到章节",
"ButtonAuthors": "作者",
"ButtonBack": "返回",
"ButtonBrowseForFolder": "浏览文件夹",
"ButtonCancel": "取消",
"ButtonCancelEncode": "取消编码",
@ -56,13 +57,13 @@
"ButtonPreviousChapter": "上一章节",
"ButtonPurgeAllCache": "清理所有缓存",
"ButtonPurgeItemsCache": "清理项目缓存",
"ButtonPurgeMediaProgress": "清理媒体进度",
"ButtonQueueAddItem": "添加到队列",
"ButtonQueueRemoveItem": "从队列中移除",
"ButtonQuickMatch": "快速匹配",
"ButtonReScan": "重新扫描",
"ButtonRead": "读取",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
"ButtonReadLess": "阅读更少",
"ButtonReadMore": "阅读更多",
"ButtonRefresh": "刷新",
"ButtonRemove": "移除",
"ButtonRemoveAll": "移除所有",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "从继续收听中删除",
"ButtonRemoveFromContinueReading": "从继续阅读中删除",
"ButtonRemoveSeriesFromContinueSeries": "从继续收听系列中删除",
"ButtonReScan": "重新扫描",
"ButtonReset": "重置",
"ButtonResetToDefault": "重置为默认",
"ButtonRestore": "恢复",
@ -83,7 +83,7 @@
"ButtonSelectFolderPath": "选择文件夹路径",
"ButtonSeries": "系列",
"ButtonSetChaptersFromTracks": "将音轨设置为章节",
"ButtonShare": "Share",
"ButtonShare": "分享",
"ButtonShiftTimes": "快速调整时间",
"ButtonShow": "显示",
"ButtonStartM4BEncode": "开始 M4B 编码",
@ -104,8 +104,8 @@
"HeaderAccount": "帐户",
"HeaderAdvanced": "高级",
"HeaderAppriseNotificationSettings": "测试通知设置",
"HeaderAudiobookTools": "有声读物文件管理工具",
"HeaderAudioTracks": "音轨",
"HeaderAudiobookTools": "有声读物文件管理工具",
"HeaderAuthentication": "身份验证",
"HeaderBackups": "备份",
"HeaderChangePassword": "更改密码",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "收藏项目",
"HeaderCover": "封面",
"HeaderCurrentDownloads": "当前下载",
"HeaderCustomMessageOnLogin": "登录时的自定义消息",
"HeaderCustomMetadataProviders": "自定义元数据提供者",
"HeaderDetails": "详情",
"HeaderDownloadQueue": "下载队列",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "播放列表项目",
"HeaderPodcastsToAdd": "要添加的播客",
"HeaderPreviewCover": "预览封面",
"HeaderRemoveEpisode": "移除剧集",
"HeaderRemoveEpisodes": "移除 {0} 剧集",
"HeaderRSSFeedGeneral": "RSS 详细信息",
"HeaderRSSFeedIsOpen": "RSS 源已打开",
"HeaderRSSFeeds": "RSS 订阅",
"HeaderRemoveEpisode": "移除剧集",
"HeaderRemoveEpisodes": "移除 {0} 剧集",
"HeaderSavedMediaProgress": "保存媒体进度",
"HeaderSchedule": "计划任务",
"HeaderScheduleLibraryScans": "自动扫描媒体库",
@ -189,20 +190,20 @@
"HeaderYearReview": "{0} 年回顾",
"HeaderYourStats": "你的统计数据",
"LabelAbridged": "概要",
"LabelAbridgedChecked": "Abridged (checked)",
"LabelAbridgedUnchecked": "Unabridged (unchecked)",
"LabelAccessibleBy": "Accessible by",
"LabelAbridgedChecked": "删节版 (已勾选)",
"LabelAbridgedUnchecked": "未删节版 (未勾选)",
"LabelAccessibleBy": "可访问",
"LabelAccountType": "帐户类型",
"LabelAccountTypeAdmin": "管理员",
"LabelAccountTypeGuest": "来宾",
"LabelAccountTypeUser": "用户",
"LabelActivity": "活动",
"LabelAdded": "添加",
"LabelAddedAt": "添加于",
"LabelAddToCollection": "添加到收藏",
"LabelAddToCollectionBatch": "批量添加 {0} 个媒体到收藏",
"LabelAddToPlaylist": "添加到播放列表",
"LabelAddToPlaylistBatch": "添加 {0} 个项目到播放列表",
"LabelAdded": "添加",
"LabelAddedAt": "添加于",
"LabelAdminUsersOnly": "仅限管理员用户",
"LabelAll": "全部",
"LabelAllUsers": "所有用户",
@ -211,7 +212,7 @@
"LabelAlreadyInYourLibrary": "已存在你的库中",
"LabelAppend": "附加",
"LabelAuthor": "作者",
"LabelAuthorFirstLast": "作者 (姓 名)",
"LabelAuthorFirstLast": "作者 (姓 名)",
"LabelAuthorLastFirst": "作者 (名, 姓)",
"LabelAuthors": "作者",
"LabelAutoDownloadEpisodes": "自动下载剧集",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "修改密码",
"LabelChannels": "声道",
"LabelChapterTitle": "章节标题",
"LabelChapters": "章节",
"LabelChaptersFound": "找到的章节",
"LabelChapterTitle": "章节标题",
"LabelClickForMoreInfo": "点击了解更多信息",
"LabelClosePlayer": "关闭播放器",
"LabelCodec": "编解码",
@ -270,17 +271,17 @@
"LabelDownload": "下载",
"LabelDownloadNEpisodes": "下载 {0} 集",
"LabelDuration": "持续时间",
"LabelDurationComparisonExactMatch": "(exact match)",
"LabelDurationComparisonLonger": "({0} longer)",
"LabelDurationComparisonShorter": "({0} shorter)",
"LabelDurationComparisonExactMatch": "(完全匹配)",
"LabelDurationComparisonLonger": "({0} 更长)",
"LabelDurationComparisonShorter": "({0} 更短)",
"LabelDurationFound": "找到持续时间:",
"LabelEbook": "电子书",
"LabelEbooks": "电子书",
"LabelEdit": "编辑",
"LabelEmail": "邮箱",
"LabelEmailSettingsFromAddress": "发件人地址",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
"LabelEmailSettingsRejectUnauthorizedHelp": "Disabling SSL certificate validation may expose your connection to security risks, such as man-in-the-middle attacks. Only disable this option if you understand the implications and trust the mail server you are connecting to.",
"LabelEmailSettingsRejectUnauthorized": "拒绝未经授权的证书",
"LabelEmailSettingsRejectUnauthorizedHelp": "禁用SSL证书验证可能会使你的连接面临安全风险, 例如中间人攻击. 只有当你了解其中的含义并信任所连接的邮件服务器时, 才能禁用此选项.",
"LabelEmailSettingsSecure": "安全",
"LabelEmailSettingsSecureHelp": "如果选是, 则连接将在连接到服务器时使用TLS. 如果选否, 则若服务器支持STARTTLS扩展, 则使用TLS. 在大多数情况下, 如果连接到端口465, 请将该值设置为是. 对于端口587或25, 请保持为否. (来自nodemailer.com/smtp/#authentication)",
"LabelEmailSettingsTestAddress": "测试地址",
@ -292,8 +293,8 @@
"LabelEpisodeType": "剧集类型",
"LabelExample": "示例",
"LabelExplicit": "信息准确",
"LabelExplicitChecked": "Explicit (checked)",
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
"LabelExplicitChecked": "明确(已选中)",
"LabelExplicitUnchecked": "不明确 (未选中)",
"LabelFeedURL": "源 URL",
"LabelFetchingMetadata": "正在获取元数据",
"LabelFile": "文件",
@ -305,7 +306,8 @@
"LabelFinished": "已听完",
"LabelFolder": "文件夹",
"LabelFolders": "文件夹",
"LabelFontBold": "Bold",
"LabelFontBold": "加粗",
"LabelFontBoldness": "字体粗细",
"LabelFontFamily": "字体系列",
"LabelFontItalic": "斜体",
"LabelFontScale": "字体比例",
@ -321,9 +323,9 @@
"LabelHour": "小时",
"LabelIcon": "图标",
"LabelImageURLFromTheWeb": "来自 Web 图像的 URL",
"LabelInProgress": "正在听",
"LabelIncludeInTracklist": "包含在音轨列表中",
"LabelIncomplete": "未听完",
"LabelInProgress": "正在听",
"LabelInterval": "间隔",
"LabelIntervalCustomDailyWeekly": "自定义 每天 / 每周",
"LabelIntervalEvery12Hours": "每 12 小时",
@ -337,6 +339,7 @@
"LabelItem": "项目",
"LabelLanguage": "语言",
"LabelLanguageDefaultServer": "默认服务器语言",
"LabelLanguages": "语言",
"LabelLastBookAdded": "最后添加的书",
"LabelLastBookUpdated": "最后更新的书",
"LabelLastSeen": "上次查看时间",
@ -348,6 +351,7 @@
"LabelLess": "较少",
"LabelLibrariesAccessibleToUser": "用户可访问的媒体库",
"LabelLibrary": "媒体库",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "媒体库项目",
"LabelLibraryName": "媒体库名称",
"LabelLimit": "限制",
@ -362,40 +366,41 @@
"LabelMatchExistingUsersByDescription": "用于连接现有用户. 连接后, 用户将通过SSO提供商提供的唯一 id 进行匹配",
"LabelMediaPlayer": "媒体播放器",
"LabelMediaType": "媒体类型",
"LabelMetadataOrderOfPrecedenceDescription": "较高优先级的元数据源将覆盖较低优先级的元数据源",
"LabelMetadataProvider": "元数据提供者",
"LabelMetaTag": "元数据标签",
"LabelMetaTags": "元标签",
"LabelMetadataOrderOfPrecedenceDescription": "较高优先级的元数据源将覆盖较低优先级的元数据源",
"LabelMetadataProvider": "元数据提供者",
"LabelMinute": "分钟",
"LabelMissing": "丢失",
"LabelMissingEbook": "没有电子书",
"LabelMissingSupplementaryEbook": "没有补充电子书",
"LabelMobileRedirectURIs": "允许移动应用重定向 URI",
"LabelMobileRedirectURIsDescription": "这是移动应用程序的有效重定向 URI 白名单. 默认值为 <code>audiobookshelf://oauth</code>可以删除它或添加其他 URI 以进行第三方应用集成. 使用星号 (<code>*</code>) 作为唯一条目允许任何 URI.",
"LabelMobileRedirectURIsDescription": "这是移动应用程序的有效重定向 URI 白名单. 默认值为 <code>audiobookshelf://oauth</code>可以删除它或添加其他 URI 以进行第三方应用集成. 使用星号 (<code>*</code>) 作为唯一条目允许任何 URI.",
"LabelMore": "更多",
"LabelMoreInfo": "更多..",
"LabelMoreInfo": "更多信息",
"LabelName": "名称",
"LabelNarrator": "演播者",
"LabelNarrators": "演播者",
"LabelNew": "新建",
"LabelNewPassword": "新密码",
"LabelNewestAuthors": "最新作者",
"LabelNewestEpisodes": "最新剧集",
"LabelNewPassword": "新密码",
"LabelNextBackupDate": "下次备份日期",
"LabelNextScheduledRun": "下次任务运行",
"LabelNoCustomMetadataProviders": "没有自定义元数据提供程序",
"LabelNoEpisodesSelected": "未选择任何剧集",
"LabelNotes": "注释",
"LabelNotFinished": "未听完",
"LabelNotStarted": "未开始",
"LabelNotes": "注释",
"LabelNotificationAppriseURL": "通知 URL(s)",
"LabelNotificationAvailableVariables": "可用变量",
"LabelNotificationBodyTemplate": "正文模板",
"LabelNotificationEvent": "通知事件",
"LabelNotificationTitleTemplate": "标题模板",
"LabelNotificationsMaxFailedAttempts": "最大失败尝试次数",
"LabelNotificationsMaxFailedAttemptsHelp": "如果多次发送失败,通知将被禁用",
"LabelNotificationsMaxQueueSize": "通知事件的最大队列大小",
"LabelNotificationsMaxQueueSizeHelp": "通知事件被限制为每秒触发 1 个. 如果队列处于最大大小, 则将忽略事件. 这可以防止通知垃圾邮件.",
"LabelNotificationTitleTemplate": "标题模板",
"LabelNotStarted": "未开始",
"LabelNumberOfBooks": "图书数量",
"LabelNumberOfEpisodes": "# 集",
"LabelOpenIDAdvancedPermsClaimDescription": "OpenID 声明的名称, 该声明包含应用程序内用户操作的高级权限, 该权限将应用于非管理员角色(<b>如果已配置</b>). 如果响应中缺少声明, 获取 ABS 的权限将被拒绝. 如果缺少单个选项, 它将被视为 <code>禁用</code>. 确保身份提供者的声明与预期结构匹配:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "可以上传",
"LabelPersonalYearReview": "你的年度回顾 ({0})",
"LabelPhotoPathURL": "图片路径或 URL",
"LabelPlaylists": "播放列表",
"LabelPlayMethod": "播放方法",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "播放列表",
"LabelPodcast": "播客",
"LabelPodcasts": "播客",
"LabelPodcastSearchRegion": "播客搜索地区",
"LabelPodcastType": "播客类型",
"LabelPodcasts": "播客",
"LabelPort": "端口",
"LabelPrefixesToIgnore": "忽略的前缀 (不区分大小写)",
"LabelPreventIndexing": "防止 iTunes 和 Google 播客目录对你的源进行索引",
@ -427,30 +433,31 @@
"LabelProgress": "进度",
"LabelProvider": "供应商",
"LabelPubDate": "出版日期",
"LabelPublisher": "出版商",
"LabelPublishYear": "发布年份",
"LabelRead": "阅读",
"LabelReadAgain": "再次阅读",
"LabelReadEbookWithoutProgress": "阅读电子书而不保存进度",
"LabelRecentlyAdded": "最近添加",
"LabelRecentSeries": "最近添加系列",
"LabelRecommended": "推荐内容",
"LabelRedo": "Redo",
"LabelRegion": "区域",
"LabelReleaseDate": "发布日期",
"LabelRemoveCover": "移除封面",
"LabelRowsPerPage": "每页行数",
"LabelPublisher": "出版商",
"LabelPublishers": "出版商",
"LabelRSSFeedCustomOwnerEmail": "自定义所有者电子邮件",
"LabelRSSFeedCustomOwnerName": "自定义所有者名称",
"LabelRSSFeedOpen": "打开 RSS 源",
"LabelRSSFeedPreventIndexing": "防止索引",
"LabelRSSFeedSlug": "RSS 源段",
"LabelRSSFeedURL": "RSS 源 URL",
"LabelRead": "阅读",
"LabelReadAgain": "再次阅读",
"LabelReadEbookWithoutProgress": "阅读电子书而不保存进度",
"LabelRecentSeries": "最近添加系列",
"LabelRecentlyAdded": "最近添加",
"LabelRecommended": "推荐内容",
"LabelRedo": "重做",
"LabelRegion": "区域",
"LabelReleaseDate": "发布日期",
"LabelRemoveCover": "移除封面",
"LabelRowsPerPage": "每页行数",
"LabelSearchTerm": "搜索项",
"LabelSearchTitle": "搜索标题",
"LabelSearchTitleOrASIN": "搜索标题或 ASIN",
"LabelSeason": "季",
"LabelSelectAll": "Select all",
"LabelSelectAll": "全选",
"LabelSelectAllEpisodes": "选择所有剧集",
"LabelSelectEpisodesShowing": "选择正在播放的 {0} 剧集",
"LabelSelectUsers": "选择用户",
@ -473,8 +480,8 @@
"LabelSettingsEnableWatcher": "启用监视程序",
"LabelSettingsEnableWatcherForLibrary": "为库启用文件夹监视程序",
"LabelSettingsEnableWatcherHelp": "当检测到文件更改时, 启用项目的自动添加/更新. *需要重新启动服务器",
"LabelSettingsEpubsAllowScriptedContent": "Allow scripted content in epubs",
"LabelSettingsEpubsAllowScriptedContentHelp": "Allow epub files to execute scripts. It is recommended to keep this setting disabled unless you trust the source of the epub files.",
"LabelSettingsEpubsAllowScriptedContent": "允许 epubs 中包含脚本内容",
"LabelSettingsEpubsAllowScriptedContentHelp": "允许 epub 文件执行脚本. 建议将此设置保持禁用, 除非你信任 epub 文件的来源.",
"LabelSettingsExperimentalFeatures": "实验功能",
"LabelSettingsExperimentalFeaturesHelp": "开发中的功能需要你的反馈并帮助测试. 点击打开 github 讨论.",
"LabelSettingsFindCovers": "查找封面",
@ -501,14 +508,14 @@
"LabelSettingsStoreMetadataWithItemHelp": "默认情况下元数据文件存储在/metadata/items文件夹中, 启用此设置将存储元数据在你媒体项目文件夹中",
"LabelSettingsTimeFormat": "时间格式",
"LabelShowAll": "全部显示",
"LabelShowSeconds": "Show seconds",
"LabelShowSeconds": "显示秒数",
"LabelSize": "文件大小",
"LabelSleepTimer": "睡眠定时",
"LabelSlug": "Slug",
"LabelStart": "开始",
"LabelStartTime": "开始时间",
"LabelStarted": "开始于",
"LabelStartedAt": "从这开始",
"LabelStartTime": "开始时间",
"LabelStatsAudioTracks": "音轨",
"LabelStatsAuthors": "作者",
"LabelStatsBestDay": "最好的一天",
@ -560,13 +567,13 @@
"LabelTracksSingleTrack": "单轨",
"LabelType": "类型",
"LabelUnabridged": "未删节",
"LabelUndo": "Undo",
"LabelUndo": "撤消",
"LabelUnknown": "未知",
"LabelUpdateCover": "更新封面",
"LabelUpdateCoverHelp": "找到匹配项时允许覆盖所选书籍存在的封面",
"LabelUpdatedAt": "更新时间",
"LabelUpdateDetails": "更新详细信息",
"LabelUpdateDetailsHelp": "找到匹配项时允许覆盖所选书籍存在的详细信息",
"LabelUpdatedAt": "更新时间",
"LabelUploaderDragAndDrop": "拖放文件或文件夹",
"LabelUploaderDropFiles": "删除文件",
"LabelUploaderItemFetchMetadataHelp": "自动获取标题, 作者和系列",
@ -588,12 +595,13 @@
"LabelYourPlaylists": "你的播放列表",
"LabelYourProgress": "你的进度",
"MessageAddToPlayerQueue": "添加到播放队列",
"MessageAppriseDescription": "要使用此功能,需要运行一个 <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> 实例或一个可以处理这些相同请求的 API. <br />Apprise API Url 应该是发送通知的完整 URL 路径, 例如: 如果你的 API 实例运行在 <code>http://192.168.1.1:8337</code>, 那么你可以输入 <code>http://192.168.1.1:8337/notify</code>.",
"MessageBackupsDescription": "备份包括用户, 用户进度, 媒体库项目详细信息, 服务器设置和图像, 存储在 <code>/metadata/items</code> & <code>/metadata/authors</code>. 备份不包括存储在的媒体库文件夹中的任何文件.",
"MessageAppriseDescription": "要使用此功能,需要运行一个 <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> 实例或一个可以处理这些相同请求的 API. <br />Apprise API Url 应该是发送通知的完整 URL 路径, 例如: 如果你的 API 实例运行在 <code>http://192.168.1.1:8337</code>, 那么你可以输入 <code>http://192.168.1.1:8337/notify</code>.",
"MessageBackupsDescription": "备份包括用户, 用户进度, 媒体库项目详细信息, 服务器设置和图像, 存储在 <code>/metadata/items</code> & <code>/metadata/authors</code>. 备份不包括存储在的媒体库文件夹中的任何文件.",
"MessageBatchQuickMatchDescription": "快速匹配将尝试为所选项目添加缺少的封面和元数据. 启用以下选项以允许快速匹配覆盖现有封面和或元数据.",
"MessageBookshelfNoCollections": "你尚未进行任何收藏",
"MessageBookshelfNoResultsForFilter": "过滤器无结果 \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "没有打开的 RSS 源",
"MessageBookshelfNoResultsForFilter": "过滤器无结果 \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "没有可查询的结果",
"MessageBookshelfNoSeries": "你没有系列",
"MessageChapterEndIsAfter": "章节结束是在有声读物结束之后",
"MessageChapterErrorFirstNotZero": "第一章节必须从 0 开始",
@ -613,8 +621,10 @@
"MessageConfirmMarkAllEpisodesNotFinished": "你确定要将所有剧集都标记为未完成吗?",
"MessageConfirmMarkSeriesFinished": "你确定要将此系列中的所有书籍都标记为已听完吗?",
"MessageConfirmMarkSeriesNotFinished": "你确定要将此系列中的所有书籍都标记为未听完吗?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeCache": "清除缓存将删除 <code>/metadata/cache</code> 整个目录. <br /><br />你确定要删除缓存目录吗?",
"MessageConfirmPurgeItemsCache": "清除项目缓存将删除 <code>/metadata/cache/items</code> 整个目录.<br />你确定吗?",
"MessageConfirmQuickEmbed": "警告! 快速嵌入不会备份你的音频文件. 确保你有音频文件的备份. <br><br>你是否想继续吗?",
"MessageConfirmReScanLibraryItems": "你确定要重新扫描 {0} 个项目吗?",
"MessageConfirmRemoveAllChapters": "你确定要移除所有章节吗?",
"MessageConfirmRemoveAuthor": "你确定要删除作者 \"{0}\"?",
"MessageConfirmRemoveCollection": "你确定要移除收藏 \"{0}\"?",
@ -629,13 +639,12 @@
"MessageConfirmRenameTag": "你确定要将所有项目标签 \"{0}\" 重命名到 \"{1}\"?",
"MessageConfirmRenameTagMergeNote": "注意: 该标签已经存在, 因此它们将被合并.",
"MessageConfirmRenameTagWarning": "警告! 已经存在有大小写不同的类似标签 \"{0}\".",
"MessageConfirmReScanLibraryItems": "你确定要重新扫描 {0} 个项目吗?",
"MessageConfirmSendEbookToDevice": "你确定要发送 {0} 电子书 \"{1}\" 到设备 \"{2}\"?",
"MessageDownloadingEpisode": "正在下载剧集",
"MessageDragFilesIntoTrackOrder": "将文件拖动到正确的音轨顺序",
"MessageEmbedFinished": "嵌入完成!",
"MessageEpisodesQueuedForDownload": "{0} 个剧集排队等待下载",
"MessageEreaderDevices": "To ensure delivery of ebooks, you may need to add the above email address as a valid sender for each device listed below.",
"MessageEreaderDevices": "为了确保电子书的送达, 你可能需要将上述电子邮件地址添加为下列每台设备的有效发件人.",
"MessageFeedURLWillBe": "源 URL 将改为 {0}",
"MessageFetching": "正在获取...",
"MessageForceReScanDescription": "将像重新扫描一样再次扫描所有文件. 音频文件 ID3 标签, OPF 文件和文本文件将被扫描为新文件.",
@ -645,9 +654,9 @@
"MessageItemsUpdated": "已更新 {0} 个项目",
"MessageJoinUsOn": "加入我们",
"MessageListeningSessionsInTheLastYear": "去年收听 {0} 个会话",
"MessageLoading": "加载...",
"MessageLoading": "正在加载...",
"MessageLoadingFolders": "加载文件夹...",
"MessageLogsDescription": "Logs are stored in <code>/metadata/logs</code> as JSON files. Crash logs are stored in <code>/metadata/logs/crash_logs.txt</code>.",
"MessageLogsDescription": "日志以 JSON 文件形式存储在 <code>/metadata/logs</code> 目录中. 崩溃日志存储在 <code>/metadata/logs/crash_logs.txt</code> 目录中.",
"MessageM4BFailed": "M4B 失败!",
"MessageM4BFinished": "M4B 完成!",
"MessageMapChapterTitles": "将章节标题映射到现有的有声读物章节, 无需调整时间戳",
@ -683,10 +692,10 @@
"MessageNoSeries": "无系列",
"MessageNoTags": "无标签",
"MessageNoTasksRunning": "没有正在运行的任务",
"MessageNotYetImplemented": "尚未实施",
"MessageNoUpdateNecessary": "无需更新",
"MessageNoUpdatesWereNecessary": "无需更新",
"MessageNoUserPlaylists": "你没有播放列表",
"MessageNotYetImplemented": "尚未实施",
"MessageOr": "或",
"MessagePauseChapter": "暂停章节播放",
"MessagePlayChapter": "开始章节播放",
@ -700,9 +709,9 @@
"MessageReportBugsAndContribute": "报告错误、请求功能和贡献在",
"MessageResetChaptersConfirm": "你确定要重置章节并撤消你所做的更改吗?",
"MessageRestoreBackupConfirm": "你确定要恢复创建的这个备份",
"MessageRestoreBackupWarning": "恢复备份将覆盖位于 /config 的整个数据库并覆盖 /metadata/items & /metadata/authors 中的图像.<br /><br />备份不会修改媒体库文件夹中的任何文件. 如果已启用服务器设置将封面和元数据存储在库文件夹中,则不会备份或覆盖这些内容.<br /><br />将自动刷新使用服务器的所有客户端.",
"MessageRestoreBackupWarning": "恢复备份将覆盖位于 /config 的整个数据库并覆盖 /metadata/items & /metadata/authors 中的图像.<br /><br />备份不会修改媒体库文件夹中的任何文件. 如果已启用服务器设置将封面和元数据存储在库文件夹中,则不会备份或覆盖这些内容.<br /><br />将自动刷新使用服务器的所有客户端.",
"MessageSearchResultsFor": "搜索结果",
"MessageSelected": "{0} selected",
"MessageSelected": "{0} 已选择",
"MessageServerCouldNotBeReached": "无法访问服务器",
"MessageSetChaptersFromTracksDescription": "把每个音频文件设置为章节并将章节标题设置为音频文件名",
"MessageStartPlaybackAtTime": "开始播放 \"{0}\" 在 {1}?",
@ -713,13 +722,13 @@
"MessageValidCronExpression": "有效的计划任务表达式",
"MessageWatcherIsDisabledGlobally": "在服务器设置中禁用全局监视程序",
"MessageXLibraryIsEmpty": "{0} 库为空!",
"MessageYourAudiobookDurationIsLonger": "的有声读物持续时间比找到的持续时间长",
"MessageYourAudiobookDurationIsShorter": "的有声读物持续时间比找到的持续时间短",
"MessageYourAudiobookDurationIsLonger": "的有声读物持续时间比找到的持续时间长",
"MessageYourAudiobookDurationIsShorter": "的有声读物持续时间比找到的持续时间短",
"NoteChangeRootPassword": "Root 是唯一可以拥有空密码的用户",
"NoteChapterEditorTimes": "注意: 第一章开始时间必须保持在 0:00, 最后一章开始时间不能超过有声读物持续时间.",
"NoteFolderPicker": "注意: 将不显示已映射的文件夹",
"NoteRSSFeedPodcastAppsHttps": "警告: 大多数播客应用程序都需要 RSS 源 URL 使用 HTTPS",
"NoteRSSFeedPodcastAppsPubDate": "警告: 的一集或多集没有发布日期. 一些播客应用程序要求这样做.",
"NoteRSSFeedPodcastAppsPubDate": "警告: 的一集或多集没有发布日期. 一些播客应用程序要求这样做.",
"NoteUploaderFoldersWithMediaFiles": "包含媒体文件的文件夹将作为单独的媒体库项目处理.",
"NoteUploaderOnlyAudioFiles": "如果只上传音频文件, 则每个音频文件将作为单独的有声读物处理.",
"NoteUploaderUnsupportedFiles": "不支持的文件将被忽略. 选择或删除文件夹时, 将忽略不在项目文件夹中的其他文件.",
@ -751,8 +760,8 @@
"ToastBookmarkRemoveSuccess": "书签已删除",
"ToastBookmarkUpdateFailed": "书签更新失败",
"ToastBookmarkUpdateSuccess": "书签已更新",
"ToastCachePurgeFailed": "Failed to purge cache",
"ToastCachePurgeSuccess": "Cache purged successfully",
"ToastCachePurgeFailed": "清除缓存失败",
"ToastCachePurgeSuccess": "缓存清除成功",
"ToastChaptersHaveErrors": "章节有错误",
"ToastChaptersMustHaveTitles": "章节必须有标题",
"ToastCollectionItemsRemoveFailed": "从收藏夹移除项目失败",
@ -761,17 +770,17 @@
"ToastCollectionRemoveSuccess": "收藏夹已删除",
"ToastCollectionUpdateFailed": "更新收藏夹失败",
"ToastCollectionUpdateSuccess": "收藏夹已更新",
"ToastDeleteFileFailed": "Failed to delete file",
"ToastDeleteFileSuccess": "File deleted",
"ToastFailedToLoadData": "Failed to load data",
"ToastDeleteFileFailed": "删除文件失败",
"ToastDeleteFileSuccess": "文件已删除",
"ToastFailedToLoadData": "加载数据失败",
"ToastItemCoverUpdateFailed": "更新项目封面失败",
"ToastItemCoverUpdateSuccess": "项目封面已更新",
"ToastItemDetailsUpdateFailed": "更新项目详细信息失败",
"ToastItemDetailsUpdateSuccess": "项目详细信息已更新",
"ToastItemDetailsUpdateUnneeded": "项目详细信息无需更新",
"ToastItemMarkedAsFinishedFailed": "标记为听完失败",
"ToastItemMarkedAsFinishedSuccess": "标记为听完的项目",
"ToastItemMarkedAsNotFinishedFailed": "标记为未听完失败",
"ToastItemMarkedAsFinishedFailed": "无法标记为听完",
"ToastItemMarkedAsFinishedSuccess": "标记为听完的项目",
"ToastItemMarkedAsNotFinishedFailed": "无法标记为未听完",
"ToastItemMarkedAsNotFinishedSuccess": "标记为未听完的项目",
"ToastLibraryCreateFailed": "创建媒体库失败",
"ToastLibraryCreateSuccess": "媒体库 \"{0}\" 创建成功",
@ -789,24 +798,24 @@
"ToastPlaylistUpdateSuccess": "播放列表已更新",
"ToastPodcastCreateFailed": "创建播客失败",
"ToastPodcastCreateSuccess": "已成功创建播客",
"ToastRemoveItemFromCollectionFailed": "从收藏中删除项目失败",
"ToastRemoveItemFromCollectionSuccess": "项目已从收藏中删除",
"ToastRSSFeedCloseFailed": "关闭 RSS 源失败",
"ToastRSSFeedCloseSuccess": "RSS 源已关闭",
"ToastRemoveItemFromCollectionFailed": "从收藏中删除项目失败",
"ToastRemoveItemFromCollectionSuccess": "项目已从收藏中删除",
"ToastSendEbookToDeviceFailed": "发送电子书到设备失败",
"ToastSendEbookToDeviceSuccess": "电子书已经发送到设备 \"{0}\"",
"ToastSeriesUpdateFailed": "更新系列失败",
"ToastSeriesUpdateSuccess": "系列已更新",
"ToastServerSettingsUpdateFailed": "Failed to update server settings",
"ToastServerSettingsUpdateSuccess": "Server settings updated",
"ToastServerSettingsUpdateFailed": "无法更新服务器设置",
"ToastServerSettingsUpdateSuccess": "服务器设置已更新",
"ToastSessionDeleteFailed": "删除会话失败",
"ToastSessionDeleteSuccess": "会话已删除",
"ToastSocketConnected": "网络已连接",
"ToastSocketDisconnected": "网络已断开",
"ToastSocketFailedToConnect": "网络连接失败",
"ToastSortingPrefixesEmptyError": "Must have at least 1 sorting prefix",
"ToastSortingPrefixesUpdateFailed": "Failed to update sorting prefixes",
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastSortingPrefixesEmptyError": "必须至少有 1 个排序前缀",
"ToastSortingPrefixesUpdateFailed": "无法更新排序前缀",
"ToastSortingPrefixesUpdateSuccess": "排序前缀已更新 ({0} 项)",
"ToastUserDeleteFailed": "删除用户失败",
"ToastUserDeleteSuccess": "用户已删除"
}
}

View File

@ -9,6 +9,7 @@
"ButtonApply": "應用",
"ButtonApplyChapters": "應用到章節",
"ButtonAuthors": "作者",
"ButtonBack": "Back",
"ButtonBrowseForFolder": "瀏覽資料夾",
"ButtonCancel": "取消",
"ButtonCancelEncode": "取消編碼",
@ -56,10 +57,10 @@
"ButtonPreviousChapter": "過去的章節",
"ButtonPurgeAllCache": "清理所有快取",
"ButtonPurgeItemsCache": "清理項目快取",
"ButtonPurgeMediaProgress": "清理媒體進度",
"ButtonQueueAddItem": "新增到佇列",
"ButtonQueueRemoveItem": "從佇列中移除",
"ButtonQuickMatch": "快速匹配",
"ButtonReScan": "重新掃描",
"ButtonRead": "讀取",
"ButtonReadLess": "Read less",
"ButtonReadMore": "Read more",
@ -70,7 +71,6 @@
"ButtonRemoveFromContinueListening": "從繼續收聽中刪除",
"ButtonRemoveFromContinueReading": "從繼續閱讀中刪除",
"ButtonRemoveSeriesFromContinueSeries": "從繼續收聽系列中刪除",
"ButtonReScan": "重新掃描",
"ButtonReset": "重置",
"ButtonResetToDefault": "重置為預設",
"ButtonRestore": "恢復",
@ -104,8 +104,8 @@
"HeaderAccount": "帳號",
"HeaderAdvanced": "高級",
"HeaderAppriseNotificationSettings": "測試通知設定",
"HeaderAudiobookTools": "有聲書檔案管理工具",
"HeaderAudioTracks": "音軌",
"HeaderAudiobookTools": "有聲書檔案管理工具",
"HeaderAuthentication": "身份驗證",
"HeaderBackups": "備份",
"HeaderChangePassword": "更改密碼",
@ -115,6 +115,7 @@
"HeaderCollectionItems": "收藏項目",
"HeaderCover": "封面",
"HeaderCurrentDownloads": "當前下載",
"HeaderCustomMessageOnLogin": "Custom Message on Login",
"HeaderCustomMetadataProviders": "自訂 Metadata 提供者",
"HeaderDetails": "詳情",
"HeaderDownloadQueue": "下載佇列",
@ -157,11 +158,11 @@
"HeaderPlaylistItems": "播放列表項目",
"HeaderPodcastsToAdd": "要新增的播客",
"HeaderPreviewCover": "預覽封面",
"HeaderRemoveEpisode": "移除劇集",
"HeaderRemoveEpisodes": "移除 {0} 劇集",
"HeaderRSSFeedGeneral": "RSS 詳細信息",
"HeaderRSSFeedIsOpen": "RSS 源已打開",
"HeaderRSSFeeds": "RSS 訂閱",
"HeaderRemoveEpisode": "移除劇集",
"HeaderRemoveEpisodes": "移除 {0} 劇集",
"HeaderSavedMediaProgress": "保存媒體進度",
"HeaderSchedule": "計劃任務",
"HeaderScheduleLibraryScans": "自動掃描媒體庫",
@ -197,12 +198,12 @@
"LabelAccountTypeGuest": "來賓",
"LabelAccountTypeUser": "使用者",
"LabelActivity": "活動",
"LabelAdded": "新增",
"LabelAddedAt": "新增於",
"LabelAddToCollection": "新增到收藏",
"LabelAddToCollectionBatch": "批量新增 {0} 個媒體到收藏",
"LabelAddToPlaylist": "新增到播放列表",
"LabelAddToPlaylistBatch": "新增 {0} 個項目到播放列表",
"LabelAdded": "新增",
"LabelAddedAt": "新增於",
"LabelAdminUsersOnly": "僅限管理員使用者",
"LabelAll": "全部",
"LabelAllUsers": "所有使用者",
@ -211,7 +212,7 @@
"LabelAlreadyInYourLibrary": "已存在你的庫中",
"LabelAppend": "附加",
"LabelAuthor": "作者",
"LabelAuthorFirstLast": "作者 (姓 名)",
"LabelAuthorFirstLast": "作者 (姓 名)",
"LabelAuthorLastFirst": "作者 (名, 姓)",
"LabelAuthors": "作者",
"LabelAutoDownloadEpisodes": "自動下載劇集",
@ -235,9 +236,9 @@
"LabelByAuthor": "by {0}",
"LabelChangePassword": "修改密碼",
"LabelChannels": "聲道",
"LabelChapterTitle": "章節標題",
"LabelChapters": "章節",
"LabelChaptersFound": "找到的章節",
"LabelChapterTitle": "章節標題",
"LabelClickForMoreInfo": "點擊了解更多資訊",
"LabelClosePlayer": "關閉播放器",
"LabelCodec": "編解碼",
@ -306,6 +307,7 @@
"LabelFolder": "資料夾",
"LabelFolders": "資料夾",
"LabelFontBold": "Bold",
"LabelFontBoldness": "Font Boldness",
"LabelFontFamily": "字體系列",
"LabelFontItalic": "斜體",
"LabelFontScale": "字體比例",
@ -321,9 +323,9 @@
"LabelHour": "小時",
"LabelIcon": "圖標",
"LabelImageURLFromTheWeb": "來自 Web 圖像的 URL",
"LabelInProgress": "正在聽",
"LabelIncludeInTracklist": "包含在音軌列表中",
"LabelIncomplete": "未聽完",
"LabelInProgress": "正在聽",
"LabelInterval": "間隔",
"LabelIntervalCustomDailyWeekly": "自定義 每天 / 每周",
"LabelIntervalEvery12Hours": "每 12 小時",
@ -337,6 +339,7 @@
"LabelItem": "項目",
"LabelLanguage": "語言",
"LabelLanguageDefaultServer": "預設伺服器語言",
"LabelLanguages": "Languages",
"LabelLastBookAdded": "最後新增的書",
"LabelLastBookUpdated": "最後更新的書",
"LabelLastSeen": "上次查看時間",
@ -348,6 +351,7 @@
"LabelLess": "較少",
"LabelLibrariesAccessibleToUser": "使用者可存取的媒體庫",
"LabelLibrary": "媒體庫",
"LabelLibraryFilterSublistEmpty": "No {0}",
"LabelLibraryItem": "媒體庫項目",
"LabelLibraryName": "媒體庫名稱",
"LabelLimit": "限制",
@ -362,10 +366,10 @@
"LabelMatchExistingUsersByDescription": "用於連接現有使用者. 連接後, 使用者將通過SSO提供商提供的唯一 id 進行匹配",
"LabelMediaPlayer": "媒體播放器",
"LabelMediaType": "媒體類型",
"LabelMetadataOrderOfPrecedenceDescription": "較高優先級的元數據源將覆蓋較低優先級的元數據源",
"LabelMetadataProvider": "元數據提供者",
"LabelMetaTag": "元數據標籤",
"LabelMetaTags": "元標籤",
"LabelMetadataOrderOfPrecedenceDescription": "較高優先級的元數據源將覆蓋較低優先級的元數據源",
"LabelMetadataProvider": "元數據提供者",
"LabelMinute": "分鐘",
"LabelMissing": "丟失",
"LabelMissingEbook": "Has no ebook",
@ -378,24 +382,25 @@
"LabelNarrator": "講述者",
"LabelNarrators": "講述者",
"LabelNew": "新建",
"LabelNewPassword": "新密碼",
"LabelNewestAuthors": "最新作者",
"LabelNewestEpisodes": "最新劇集",
"LabelNewPassword": "新密碼",
"LabelNextBackupDate": "下次備份日期",
"LabelNextScheduledRun": "下次任務運行",
"LabelNoCustomMetadataProviders": "No custom metadata providers",
"LabelNoEpisodesSelected": "未選擇任何劇集",
"LabelNotes": "注釋",
"LabelNotFinished": "未聽完",
"LabelNotStarted": "未開始",
"LabelNotes": "注釋",
"LabelNotificationAppriseURL": "通知 URL(s)",
"LabelNotificationAvailableVariables": "可用變量",
"LabelNotificationBodyTemplate": "正文模板",
"LabelNotificationEvent": "通知事件",
"LabelNotificationTitleTemplate": "標題模板",
"LabelNotificationsMaxFailedAttempts": "最大失敗嘗試次數",
"LabelNotificationsMaxFailedAttemptsHelp": "如果多次發送失敗,通知將被禁用",
"LabelNotificationsMaxQueueSize": "通知事件的最大佇列大小",
"LabelNotificationsMaxQueueSizeHelp": "通知事件被限制為每秒觸發 1 個. 如果佇列處於最大大小, 則將忽略事件. 這可以防止通知垃圾郵件.",
"LabelNotificationTitleTemplate": "標題模板",
"LabelNotStarted": "未開始",
"LabelNumberOfBooks": "圖書數量",
"LabelNumberOfEpisodes": "# 集",
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
@ -414,12 +419,13 @@
"LabelPermissionsUpload": "可以上傳",
"LabelPersonalYearReview": "你的年度回顧 ({0})",
"LabelPhotoPathURL": "圖片路徑或 URL",
"LabelPlaylists": "播放列表",
"LabelPlayMethod": "播放方法",
"LabelPlayerChapterNumberMarker": "{0} of {1}",
"LabelPlaylists": "播放列表",
"LabelPodcast": "播客",
"LabelPodcasts": "播客",
"LabelPodcastSearchRegion": "播客搜尋地區",
"LabelPodcastType": "播客類型",
"LabelPodcasts": "播客",
"LabelPort": "埠",
"LabelPrefixesToIgnore": "忽略的前綴 (不區分大小寫)",
"LabelPreventIndexing": "防止 iTunes 和 Google 播客目錄對你的源進行索引",
@ -427,25 +433,26 @@
"LabelProgress": "進度",
"LabelProvider": "供應商",
"LabelPubDate": "出版日期",
"LabelPublisher": "出版商",
"LabelPublishYear": "發布年份",
"LabelRead": "閱讀",
"LabelReadAgain": "再次閱讀",
"LabelReadEbookWithoutProgress": "閱讀電子書而不保存進度",
"LabelRecentlyAdded": "最近新增",
"LabelRecentSeries": "最近新增系列",
"LabelRecommended": "推薦內容",
"LabelRedo": "重做",
"LabelRegion": "區域",
"LabelReleaseDate": "發布日期",
"LabelRemoveCover": "移除封面",
"LabelRowsPerPage": "每頁行數",
"LabelPublisher": "出版商",
"LabelPublishers": "Publishers",
"LabelRSSFeedCustomOwnerEmail": "自定義所有者電子郵件",
"LabelRSSFeedCustomOwnerName": "自定義所有者名稱",
"LabelRSSFeedOpen": "打開 RSS 源",
"LabelRSSFeedPreventIndexing": "防止索引",
"LabelRSSFeedSlug": "RSS 源段",
"LabelRSSFeedURL": "RSS 源 URL",
"LabelRead": "閱讀",
"LabelReadAgain": "再次閱讀",
"LabelReadEbookWithoutProgress": "閱讀電子書而不保存進度",
"LabelRecentSeries": "最近新增系列",
"LabelRecentlyAdded": "最近新增",
"LabelRecommended": "推薦內容",
"LabelRedo": "重做",
"LabelRegion": "區域",
"LabelReleaseDate": "發布日期",
"LabelRemoveCover": "移除封面",
"LabelRowsPerPage": "每頁行數",
"LabelSearchTerm": "搜尋項",
"LabelSearchTitle": "搜尋標題",
"LabelSearchTitleOrASIN": "搜尋標題或 ASIN",
@ -506,9 +513,9 @@
"LabelSleepTimer": "睡眠定時",
"LabelSlug": "Slug",
"LabelStart": "開始",
"LabelStartTime": "開始時間",
"LabelStarted": "開始於",
"LabelStartedAt": "從這開始",
"LabelStartTime": "開始時間",
"LabelStatsAudioTracks": "音軌",
"LabelStatsAuthors": "作者",
"LabelStatsBestDay": "最好的一天",
@ -564,9 +571,9 @@
"LabelUnknown": "未知",
"LabelUpdateCover": "更新封面",
"LabelUpdateCoverHelp": "找到匹配項時允許覆蓋所選書籍存在的封面",
"LabelUpdatedAt": "更新時間",
"LabelUpdateDetails": "更新詳細信息",
"LabelUpdateDetailsHelp": "找到匹配項時允許覆蓋所選書籍存在的詳細信息",
"LabelUpdatedAt": "更新時間",
"LabelUploaderDragAndDrop": "拖放檔案或資料夾",
"LabelUploaderDropFiles": "刪除檔案",
"LabelUploaderItemFetchMetadataHelp": "自動獲取標題, 作者和系列",
@ -592,8 +599,9 @@
"MessageBackupsDescription": "備份包括使用者, 使用者進度, 媒體庫項目詳細信息, 伺服器設定和圖像, 存儲在 <code>/metadata/items</code> & <code>/metadata/authors</code>. 備份不包括存儲在您的媒體庫資料夾中的任何檔案.",
"MessageBatchQuickMatchDescription": "快速匹配將嘗試為所選項目新增缺少的封面和元數據. 啟用以下選項以允許快速匹配覆蓋現有封面和或元數據.",
"MessageBookshelfNoCollections": "你尚未進行任何收藏",
"MessageBookshelfNoResultsForFilter": "過濾器無結果 \"{0}: {1}\"",
"MessageBookshelfNoRSSFeeds": "沒有打開的 RSS 源",
"MessageBookshelfNoResultsForFilter": "過濾器無結果 \"{0}: {1}\"",
"MessageBookshelfNoResultsForQuery": "No results for query",
"MessageBookshelfNoSeries": "你沒有系列",
"MessageChapterEndIsAfter": "章節結束是在有聲書結束之後",
"MessageChapterErrorFirstNotZero": "第一章節必須從 0 開始",
@ -614,7 +622,9 @@
"MessageConfirmMarkSeriesFinished": "你確定要將此系列中的所有書籍都標記為已聽完嗎?",
"MessageConfirmMarkSeriesNotFinished": "你確定要將此系列中的所有書籍都標記為未聽完嗎?",
"MessageConfirmPurgeCache": "Purge cache will delete the entire directory at <code>/metadata/cache</code>. <br /><br />Are you sure you want to remove the cache directory?",
"MessageConfirmPurgeItemsCache": "Purge items cache will delete the entire directory at <code>/metadata/cache/items</code>.<br />Are you sure?",
"MessageConfirmQuickEmbed": "警告! 快速嵌入不會備份你的音頻檔案. 確保你有音頻檔案的備份. <br><br>你是否想繼續嗎?",
"MessageConfirmReScanLibraryItems": "你確定要重新掃描 {0} 個項目嗎?",
"MessageConfirmRemoveAllChapters": "你確定要移除所有章節嗎?",
"MessageConfirmRemoveAuthor": "你確定要刪除作者 \"{0}\"?",
"MessageConfirmRemoveCollection": "你確定要移除收藏 \"{0}\"?",
@ -629,7 +639,6 @@
"MessageConfirmRenameTag": "你確定要將所有項目標籤 \"{0}\" 重命名到 \"{1}\"?",
"MessageConfirmRenameTagMergeNote": "注意: 該標籤已經存在, 因此它們將被合併.",
"MessageConfirmRenameTagWarning": "警告! 已經存在有大小寫不同的類似標籤 \"{0}\".",
"MessageConfirmReScanLibraryItems": "你確定要重新掃描 {0} 個項目嗎?",
"MessageConfirmSendEbookToDevice": "你確定要發送 {0} 電子書 \"{1}\" 到設備 \"{2}\"?",
"MessageDownloadingEpisode": "正在下載劇集",
"MessageDragFilesIntoTrackOrder": "將檔案拖動到正確的音軌順序",
@ -683,10 +692,10 @@
"MessageNoSeries": "無系列",
"MessageNoTags": "無標籤",
"MessageNoTasksRunning": "沒有正在運行的任務",
"MessageNotYetImplemented": "尚未實施",
"MessageNoUpdateNecessary": "無需更新",
"MessageNoUpdatesWereNecessary": "無需更新",
"MessageNoUserPlaylists": "你沒有播放列表",
"MessageNotYetImplemented": "尚未實施",
"MessageOr": "或",
"MessagePauseChapter": "暫停章節播放",
"MessagePlayChapter": "開始章節播放",
@ -789,10 +798,10 @@
"ToastPlaylistUpdateSuccess": "播放列表已更新",
"ToastPodcastCreateFailed": "創建播客失敗",
"ToastPodcastCreateSuccess": "已成功創建播客",
"ToastRemoveItemFromCollectionFailed": "從收藏中刪除項目失敗",
"ToastRemoveItemFromCollectionSuccess": "項目已從收藏中刪除",
"ToastRSSFeedCloseFailed": "關閉 RSS 源失敗",
"ToastRSSFeedCloseSuccess": "RSS 源已關閉",
"ToastRemoveItemFromCollectionFailed": "從收藏中刪除項目失敗",
"ToastRemoveItemFromCollectionSuccess": "項目已從收藏中刪除",
"ToastSendEbookToDeviceFailed": "發送電子書到設備失敗",
"ToastSendEbookToDeviceSuccess": "電子書已經發送到設備 \"{0}\"",
"ToastSeriesUpdateFailed": "更新系列失敗",
@ -809,4 +818,4 @@
"ToastSortingPrefixesUpdateSuccess": "Sorting prefixes updated ({0} items)",
"ToastUserDeleteFailed": "刪除使用者失敗",
"ToastUserDeleteSuccess": "使用者已刪除"
}
}

View File

@ -1,30 +1,33 @@
# OpenAPI specification
This directory includes the OpenAPI spec for the ABS server.
The spec is made up of a number of individual `yaml` files located here and in the subfolders, with `root.yaml` being the file that references all of the others.
The files are organized to have the same hierarchy as the server source files.
The full spec is bundled into one file in `openapi.json`.
This directory includes the OpenAPI spec for the ABS server. The spec is made up of a number of individual `yaml` files located here and in the subfolders, with `root.yaml` being the file that references all of the others. The files are organized to have the same hierarchy as the server source files. The full spec is bundled into one file in `openapi.json`.
The spec is linted and bundled by the [`vacuum` tool](https://quobix.com/vacuum/).
The spec can also be tested with a real server using the [`wiretap` tool](https://pb33f.io/wiretap/).
Both of these tools are created by [pb33f](https://pb33f.io/).
The spec is linted and bundled using [`redocly-cli`](https://redocly.com/docs/cli/). This tool also generates HTML docs for the spec.
The tools created by [`pb33f`](https://pb33f.io/), specifically `vacuum` and `wiretap`, are also useful for linting and verification. These tools check for some other things, such as validating requests to and responses from the server.
### Bundling the spec
The command to bundle the spec into a `yaml` file is `vacuum bundle root.yaml openapi.yaml`.
The current version of `vacuum` cannot convert input `yaml` files to `json` files.
To convert the spec to `json`, you can use the `yq` tool or another tool.
The command used to bundle the spec into a `yaml` file is `redocly bundle root.yaml > bundled.yaml`.
The command to convert the spec using `yq` is `yq -p yaml -o json openapi.yaml > openapi.json`.
The `yq` tool is used to convert the `yaml` to a `json` using the `yq -p yaml -o json bundled.yaml > openapi.json`.
### Viewing report
To generate an HTML report, you can use `vacuum html-report [file]` to generate `report.html` and view the report in your browser.
### Linting the spec
The command used to lint the spec is `redocly lint root.yaml`
To generate an HTML report using `vacuum`, you can use `vacuum html-report [file]` to generate `report.html` and view the report in your browser.
### Generating documentation
Redocly allows for creating a static HTML page to document the API. This is done by using `redocly build-docs [file]` and supports exploded specs.
### Putting it all together
The full command that I run to bundle the spec and generate the report is:
The full command that I run to bundle the spec and generate the documentation is:
```
vacuum bundle root.yaml openapi.yaml && \
yq -p yaml -o json openapi.yaml > openapi.json && \
vacuum html-report openapi.json
redocly bundle root.yaml > bundled.yaml && \
yq -p yaml -o json bundled.yaml > openapi.json && \
redocly build-docs openapi.json
```

View File

@ -4,136 +4,299 @@ components:
description: Whether the author was updated without errors. Will not exist if author was merged.
type: boolean
nullable: true
parameters:
authorId:
name: id
in: path
description: Author ID
required: true
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorId'
authorMerged:
description: Whether the author was merged with another author. Will not exist if author was updated.
type: boolean
nullable: true
authorInclude:
name: include
in: query
description: A comma separated list of what to include with the author. The options are `items` and `series`. `series` will only have an effect if `items` is included.
required: false
schema:
type: string
example: "items"
examples:
empty:
summary: Do not return library items
value: ""
itemOnly:
summary: Only return library items
value: "items"
itemsAndSeries:
summary: Return library items and series
value: "items,series"
description: A comma separated list of what to include with the author. The options are `items` and `series`. `series` will only have an effect if `items` is included. For example, the value `items,series` will include both library items and series.
type: string
example: 'items'
authorLibraryId:
name: library
in: query
description: The ID of the library to to include filter included items from.
required: false
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
asin:
name: asin
in: query
description: The Audible Identifier (ASIN).
required: false
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorAsin'
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
authorSearchName:
name: q
in: query
description: The name of the author to use for searching.
required: false
schema:
type: string
example: Terry Goodkind
type: string
example: Terry Goodkind
authorName:
name: name
in: query
description: The new name of the author.
required: false
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorName'
authorDescription:
name: description
in: query
description: The new description of the author.
required: false
schema:
type: string
nullable: true
example: Terry Goodkind is a #1 New York Times Bestselling Author and creator of the critically acclaimed masterwork, The Sword of Truth. He has written 30+ major, bestselling novels, has been published in more than 20 languages world-wide, and has sold more than 26 Million books. The Sword of Truth is a revered literary tour de force, comprised of 17 volumes, borne from over 25 years of dedicated writing.
authorImagePath:
name: imagePath
in: query
description: The new absolute path for the author image.
required: false
schema:
type: string
nullable: true
example: /metadata/authors/aut_z3leimgybl7uf3y4ab.jpg
$ref: '../objects/entities/Author.yaml#/components/schemas/authorName'
imageUrl:
name: url
in: query
description: The URL of the image to add to the server
required: true
schema:
type: string
format: uri
example: https://images-na.ssl-images-amazon.com/images/I/51NoQTm33OL.__01_SX120_CR0,0,120,120__.jpg
type: string
format: uri
example: https://images-na.ssl-images-amazon.com/images/I/51NoQTm33OL.__01_SX120_CR0,0,120,120__.jpg
imageWidth:
name: width
in: query
description: The requested width of image in pixels.
schema:
type: integer
default: 400
example: 400
type: integer
default: 400
example: 400
imageHeight:
name: height
in: query
description: The requested height of image in pixels. If `null`, the height is scaled to maintain aspect ratio based on the requested width.
schema:
type: integer
nullable: true
default: null
example: 600
examples:
scaleHeight:
summary: Scale height with width
value: null
fixedHeight:
summary: Force height of image
value: 600
type: integer
nullable: true
default: null
example: 600
imageFormat:
name: format
in: query
description: The requested output format.
schema:
type: string
default: jpeg
example: webp
type: string
default: jpeg
example: webp
imageRaw:
name: raw
in: query
description: Return the raw image without scaling if true.
schema:
type: boolean
default: false
responses:
type: boolean
default: false
responses:
author200:
description: Author found.
content:
application/json:
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/author'
author404:
description: Author not found.
content:
text/html:
schema:
type: string
example: Not found
tags:
- name: Authors
description: Author endpoints
example: Author not found.
paths:
/api/authors/{id}:
parameters:
- name: id
in: path
description: Author ID
required: true
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorId'
get:
operationId: getAuthorById
summary: Get an author by ID
description: Get an author by ID. The author's books and series can be included in the response.
tags:
- Authors
parameters:
- in: query
name: include
description: A comma separated list of what to include with the author. The options are `items` and `series`. `series` will only have an effect if `items` is included. For example, the value `items,series` will include both library items and series.
allowReserved: true
schema:
type: string
example: 'items,series'
responses:
'200':
description: getAuthorById OK
content:
application/json:
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/author'
'404':
$ref: '#/components/responses/author404'
patch:
operationId: updateAuthorById
summary: Update an author by ID
description: Update an author by ID. The author's name and description can be updated. This endpoint will merge two authors if the new author name matches another author name in the database.
tags:
- Authors
requestBody:
description: The author object to update.
content:
application/json:
schema:
properties:
name:
$ref: '#/components/schemas/authorName'
description:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorDescription'
imagePath:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorImagePath'
asin:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorAsin'
responses:
'200':
description: updateAuthorById OK
content:
application/json:
schema:
oneOf:
- $ref: '../objects/entities/Author.yaml#/components/schemas/author'
- $ref: '#/components/schemas/authorUpdated'
- $ref: '#/components/schemas/authorMerged'
'404':
$ref: '#/components/responses/author404'
delete:
operationId: deleteAuthorById
summary: Delete an author by ID
description: Delete an author by ID. This will remove the author from all books.
tags:
- Authors
responses:
'200':
description: deleteAuthorById OK
content:
text/plain:
schema:
type: string
example: Author deleted.
'404':
$ref: '#/components/responses/author404'
/api/authors/{id}/image:
parameters:
- name: id
in: path
description: Author ID
required: true
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorId'
- name: token
in: query
description: API token
schema:
type: string
- name: ts
in: query
description: Updated at value
schema:
type: integer
get:
operationId: getAuthorImageById
summary: Get an author image by author ID
description: Get an author image by author ID. The image will be returned in the requested format and size.
security: [] # No security for getting author image
tags:
- Authors
requestBody:
required: false
description: The author image to get.
content:
application/json:
schema:
properties:
width:
$ref: '#/components/schemas/imageWidth'
height:
$ref: '#/components/schemas/imageHeight'
format:
$ref: '#/components/schemas/imageFormat'
raw:
$ref: '#/components/schemas/imageRaw'
responses:
'200':
description: getAuthorImageById OK
content:
image/webp:
schema:
type: string
format: binary
image/jpeg:
schema:
type: string
format: binary
image/*:
schema:
type: string
format: binary
'404':
$ref: '#/components/responses/author404'
post:
operationId: addAuthorImageById
summary: Add an author image to the server
description: Add an author image to the server. The image will be downloaded from the provided URL and stored on the server.
tags:
- Authors
requestBody:
required: true
description: The author image to add by URL.
content:
application/json:
schema:
$ref: '#/components/schemas/imageUrl'
responses:
'200':
description: addAuthorImageById OK
content:
image/*:
schema:
type: string
format: binary
'404':
$ref: '#/components/responses/author404'
patch:
operationId: updateAuthorImageById
summary: Update an author image by author ID
description: Update an author image by author ID. The image will be resized if the width, height, or format is provided.
tags:
- Authors
requestBody:
description: The author image to update.
content:
application/json:
schema:
properties:
width:
$ref: '#/components/schemas/imageWidth'
height:
$ref: '#/components/schemas/imageHeight'
format:
$ref: '#/components/schemas/imageFormat'
raw:
$ref: '#/components/schemas/imageRaw'
responses:
'200':
description: updateAuthorImageById OK
content:
image/*:
schema:
type: string
format: binary
'404':
$ref: '#/components/responses/author404'
delete:
operationId: deleteAuthorImageById
summary: Delete an author image by author ID
description: Delete an author image by author ID. This will remove the image from the server and the database.
tags:
- Authors
responses:
'200':
description: deleteAuthorImageById OK
'404':
$ref: '#/components/responses/author404'
/api/authors/{id}/match:
parameters:
- name: id
in: path
description: Author ID
required: true
schema:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorId'
post:
operationId: matchAuthorById
summary: Match the author against Audible using quick match
description: Match the author against Audible using quick match. Quick match updates the author's description and image (if no image already existed) with information from audible. Either `asin` or `q` must be provided, with `asin` taking priority if both are provided.
tags:
- Authors
requestBody:
required: true
description: The author object to match against an online provider.
content:
application/json:
schema:
type: object
properties:
q:
$ref: '#/components/schemas/authorSearchName'
asin:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorAsin'
region:
$ref: '../schemas.yaml#/components/schemas/region'
responses:
'200':
description: matchAuthorById OK
content:
application/json:
schema:
oneOf:
- $ref: '../objects/entities/Author.yaml#/components/schemas/author'
- $ref: '#/components/schemas/authorUpdated'
'404':
$ref: '#/components/responses/author404'

View File

@ -0,0 +1,479 @@
components:
schemas:
sortBy:
type: string
description: The field to sort by from the request.
example: 'media.metadata.title'
sortDesc:
description: Whether to sort in descending order.
type: boolean
example: true
filterBy:
type: string
description: The field to filter by from the request. TODO
example: 'media.metadata.title'
collapseSeries:
type: boolean
description: Whether collapse series was set in the request.
example: true
libraryFolders:
description: The folders of the library. Only specify the fullPath.
type: array
items:
$ref: '../objects/Folder.yaml#/components/schemas/folder'
libraryDisplayOrder:
description: The display order of the library. Must be >= 1.
type: integer
minimum: 1
example: 1
libraryIcon:
description: The icon of the library. See Library Icons for a list of possible icons.
type: string
example: 'audiobookshelf'
libraryMediaType:
description: The type of media that the library contains. Must be `book` or `podcast`.
type: string
example: 'book'
libraryProvider:
description: Preferred metadata provider for the library. See Metadata Providers for a list of possible providers.
type: string
example: 'audible'
librarySettings:
$ref: '../objects/Library.yaml#/components/schemas/librarySettings'
librarySort:
description: The sort order of the library. For example, to sort by title use 'sort=media.metadata.title'.
type: string
example: 'media.metadata.title'
libraryFilter:
description: The filter for the library.
type: string
example: 'media.metadata.title'
libraryCollapseSeries:
description: Whether to collapse series.
type: boolean
example: true
default: false
libraryInclude:
description: The fields to include in the response. The only current option is `rssfeed`.
type: string
example: 'rssfeed'
parameters:
limit:
in: query
name: limit
description: The number of items to return. This the size of a single page for the optional `page` query.
example: 10
schema:
type: integer
default: 0
page:
in: query
name: page
description: The page number (zero indexed) to return. If no limit is specified, then page will have no effect.
example: 0
schema:
type: integer
default: 0
desc:
in: query
name: desc
description: Return items in reversed order if true.
example: 0
schema:
type: integer
default: 0
responses:
library200:
description: Library found.
content:
application/json:
schema:
$ref: '../objects/Library.yaml#/components/schemas/library'
library404:
description: Library not found.
content:
text/html:
schema:
type: string
example: Library not found.
paths:
/api/libraries:
get:
operationId: getLibraries
summary: Get all libraries on server
description: Get all libraries on server.
tags:
- Libraries
responses:
'200':
description: getLibraries OK
content:
application/json:
schema:
type: object
properties:
libraries:
type: array
items:
$ref: '../objects/Library.yaml#/components/schemas/library'
post:
operationId: createLibrary
summary: Create a new library on server
description: Create a new library on server.
tags:
- Libraries
requestBody:
description: The library object to create.
content:
application/json:
schema:
type: object
required: [name, folders]
properties:
name:
$ref: '../objects/Library.yaml#/components/schemas/libraryName'
folders:
$ref: '#/components/schemas/libraryFolders'
displayOrder:
$ref: '#/components/schemas/libraryDisplayOrder'
icon:
$ref: '#/components/schemas/libraryIcon'
mediaType:
$ref: '#/components/schemas/libraryMediaType'
provider:
$ref: '#/components/schemas/libraryProvider'
settings:
$ref: '#/components/schemas/librarySettings'
responses:
'200':
$ref: '#/components/responses/library200'
'404':
$ref: '#/components/responses/library404'
/api/libraries/{id}:
parameters:
- name: id
in: path
description: The ID of the library.
required: true
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
get:
operationId: getLibraryById
summary: Get a single library by ID on server
description: Get a single library by ID on server.
tags:
- Libraries
parameters:
- in: query
name: include
schema:
type: string
- $ref: '../schemas.yaml#/components/parameters/minified'
responses:
'200':
$ref: '#/components/responses/library200'
'404':
$ref: '#/components/responses/library404'
patch:
operationId: updateLibraryById
summary: Update a single library by ID on server
description: Update a single library by ID on server.
tags:
- Libraries
requestBody:
required: true
description: The library object to update.
content:
application/json:
schema:
type: object
properties:
name:
$ref: '../objects/Library.yaml#/components/schemas/libraryName'
folders:
$ref: '#/components/schemas/libraryFolders'
displayOrder:
$ref: '#/components/schemas/libraryDisplayOrder'
icon:
$ref: '#/components/schemas/libraryIcon'
mediaType:
$ref: '#/components/schemas/libraryMediaType'
provider:
$ref: '#/components/schemas/libraryProvider'
settings:
$ref: '#/components/schemas/librarySettings'
responses:
'200':
$ref: '#/components/responses/library200'
'404':
$ref: '#/components/responses/library404'
delete:
operationId: deleteLibraryById
summary: Delete a single library by ID on server
description: Delete a single library by ID on server and return the deleted object.
tags:
- Libraries
responses:
'200':
$ref: '#/components/responses/library200'
'404':
$ref: '#/components/responses/library404'
/api/libraries/{id}/issues:
parameters:
- name: id
in: path
description: The ID of the library.
required: true
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
delete:
operationId: deleteLibraryIssues
summary: Delete items with issues in a library.
description: Delete all items with issues in a library by library ID on the server. This only removes the items from the ABS database and does not delete media files.
tags:
- Libraries
responses:
'200':
description: deleteLibraryIssues OK
content:
application/json:
schema:
type: string
example: 'Issues deleted.'
'404':
$ref: '#/components/responses/library404'
/api/libraries/{id}/items:
parameters:
- name: id
in: path
description: The ID of the library.
required: true
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
get:
operationId: getLibraryItems
summary: Get items in a library
description: Get items in a library by ID on server.
tags:
- Libraries
parameters:
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/page'
- in: query
name: sort
description: The field to sort by from the request.
example: 'numBooks'
schema:
type: string
default: 'name'
- $ref: '#/components/parameters/desc'
- in: query
name: filter
description: The filter for the library.
example: 'media.metadata.title'
schema:
type: string
- in: query
name: include
description: The fields to include in the response. The only current option is `rssfeed`.
allowReserved: true
example: 'rssfeed'
schema:
type: string
- $ref: '../schemas.yaml#/components/parameters/minified'
- in: query
name: collapseSeries
description: Whether to collapse series into a single cover
schema:
type: integer
default: 0
responses:
'200':
description: getLibraryItems OK
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemBase'
total:
$ref: '../schemas.yaml#/components/schemas/total'
limit:
$ref: '../schemas.yaml#/components/schemas/limit'
page:
$ref: '../schemas.yaml#/components/schemas/page'
sortBy:
$ref: '#/components/schemas/sortBy'
sortDesc:
$ref: '#/components/schemas/sortDesc'
filterBy:
$ref: '#/components/schemas/filterBy'
mediaType:
$ref: '../objects/mediaTypes/media.yaml#/components/schemas/mediaType'
minified:
$ref: '../schemas.yaml#/components/schemas/minified'
collapseSeries:
$ref: '#/components/schemas/collapseSeries'
include:
$ref: '#/components/schemas/libraryInclude'
'404':
$ref: '#/components/responses/library404'
/api/libraries/{id}/authors:
parameters:
- name: id
in: path
description: The ID of the library.
required: true
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
get:
operationId: getLibraryAuthors
summary: Get all authors in a library
description: Get all authors in a library by ID on server.
tags:
- Libraries
responses:
'200':
description: getLibraryAuthors OK
content:
application/json:
schema:
type: object
properties:
authors:
type: array
items:
$ref: '../objects/entities/Author.yaml#/components/schemas/authorExpanded'
'404':
$ref: '#/components/responses/library404'
/api/libraries/{id}/series:
parameters:
- name: id
in: path
description: The ID of the library.
required: true
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
get:
operationId: getLibrarySeries
summary: Get library series
description: Get series in a library. Filtering and sorting can be applied.
tags:
- Libraries
parameters:
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/page'
- in: query
name: sort
description: The field to sort by from the request.
example: 'numBooks'
schema:
type: string
enum: ['name', 'numBooks', 'totalDuration', 'addedAt', 'lastBookAdded', 'lastBookUpdated']
default: 'name'
- $ref: '#/components/parameters/desc'
- in: query
name: filter
description: The filter for the library.
example: 'media.metadata.title'
schema:
type: string
- in: query
name: include
description: The fields to include in the response. The only current option is `rssfeed`.
allowReserved: true
example: 'rssfeed'
schema:
type: string
- $ref: '../schemas.yaml#/components/parameters/minified'
responses:
'200':
description: getLibrarySeries OK
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesBooks'
total:
$ref: '../schemas.yaml#/components/schemas/total'
limit:
$ref: '../schemas.yaml#/components/schemas/limit'
page:
$ref: '../schemas.yaml#/components/schemas/page'
sortBy:
$ref: '#/components/schemas/sortBy'
sortDesc:
$ref: '#/components/schemas/sortDesc'
filterBy:
$ref: '#/components/schemas/filterBy'
minified:
$ref: '../schemas.yaml#/components/schemas/minified'
include:
$ref: '#/components/schemas/libraryInclude'
'404':
$ref: '#/components/responses/library404'
/api/libraries/{id}/series/{seriesId}:
parameters:
- name: id
in: path
description: The ID of the library.
required: true
schema:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
- name: seriesId
in: path
description: The ID of the series.
required: true
schema:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesId'
get:
operationId: getLibrarySeriesById
summary: Get single series in library
description: Get a single series in a library by ID on server. This endpoint is deprecated and `/api/series/{id}` should be used instead.
deprecated: true
tags:
- Libraries
parameters:
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/page'
- in: query
name: sort
description: The field to sort by from the request.
example: 'numBooks'
schema:
type: string
enum: ['name', 'numBooks', 'totalDuration', 'addedAt', 'lastBookAdded', 'lastBookUpdated']
default: 'name'
- $ref: '#/components/parameters/desc'
- in: query
name: filter
description: The filter for the library.
example: 'media.metadata.title'
schema:
type: string
- $ref: '../schemas.yaml#/components/parameters/minified'
- in: query
name: include
description: The fields to include in the response. The only current option is `rssfeed`.
allowReserved: true
example: 'rssfeed'
schema:
type: string
responses:
'200':
description: getLibrarySeriesById OK
content:
application/json:
schema:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesWithProgressAndRSS'
'404':
$ref: '#/components/responses/library404'

View File

@ -0,0 +1,223 @@
components:
responses:
notification200:
description: Notification endpoint success.
content:
text/html:
schema:
type: string
example: OK
notification404:
description: An admin user is required or notification with the given ID not found.
content:
text/html:
schema:
type: string
example: Series not found.
paths:
/api/notifications:
get:
operationId: getNotifications
description: Get all Apprise notification events and notification settings for server.
tags:
- Notification
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
events:
type: array
items:
$ref: '../objects/Notification.yaml#/components/schemas/NotificationEvent'
settings:
$ref: '../objects/Notification.yaml#/components/schemas/NotificationSettings'
'404':
$ref: '#/components/responses/notification404'
patch:
operationId: updateNotificationSettings
description: Update Notification settings.
tags:
- Notification
requestBody:
content:
application/json:
schema:
type: object
properties:
appriseApiUrl:
$ref: '../objects/Notification.yaml#/components/schemas/appriseApiUrl'
maxFailedAttempts:
$ref: '../objects/Notification.yaml#/components/schemas/maxFailedAttempts'
maxNotificationQueue:
$ref: '../objects/Notification.yaml#/components/schemas/maxNotificationQueue'
responses:
'200':
$ref: '#/components/responses/notification200'
'404':
$ref: '#/components/responses/notification404'
post:
operationId: createNotification
description: Update Notification settings.
tags:
- Notification
requestBody:
content:
application/json:
schema:
type: object
properties:
libraryId:
$ref: '../objects/Library.yaml#/components/schemas/libraryIdNullable'
eventName:
$ref: '../objects/Notification.yaml#/components/schemas/notificationEventName'
urls:
$ref: '../objects/Notification.yaml#/components/schemas/urls'
titleTemplate:
$ref: '../objects/Notification.yaml#/components/schemas/titleTemplate'
bodyTemplate:
$ref: '../objects/Notification.yaml#/components/schemas/bodyTemplate'
enabled:
$ref: '../objects/Notification.yaml#/components/schemas/enabled'
type:
$ref: '../objects/Notification.yaml#/components/schemas/notificationType'
required:
- eventName
- urls
- titleTemplate
- bodyTemplate
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
settings:
$ref: '../objects/Notification.yaml#/components/schemas/NotificationSettings'
'404':
$ref: '#/components/responses/notification404'
/api/notificationdata:
get:
operationId: getNotificationEventData
description: Get all Apprise notification event data for the server.
tags:
- Notification
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
events:
type: array
items:
$ref: '../objects/Notification.yaml#/components/schemas/NotificationEvent'
'404':
$ref: '#/components/responses/notification404'
/api/notifications/test:
get:
operationId: sendDefaultTestNotification
description: Send a test notification.
tags:
- Notification
parameters:
- in: query
name: fail
description: Whether to intentionally cause the notification to fail. `0` for false, `1` for true.
schema:
type: integer
responses:
'200':
$ref: '#/components/responses/notification200'
'404':
$ref: '#/components/responses/notification404'
/api/notifications/{id}:
parameters:
- name: id
in: path
description: The ID of the notification.
required: true
schema:
$ref: '../objects/Notification.yaml#/components/schemas/notificationId'
delete:
operationId: deleteNotification
description: Delete the notification by ID and return the notification settings.
tags:
- Notification
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
settings:
$ref: '../objects/Notification.yaml#/components/schemas/NotificationSettings'
'404':
$ref: '#/components/responses/notification404'
patch:
operationId: updateNotification
description: Update individual Notification
tags:
- Notification
requestBody:
content:
application/json:
schema:
type: object
properties:
libraryId:
$ref: '../objects/Library.yaml#/components/schemas/libraryId'
eventName:
$ref: '../objects/Notification.yaml#/components/schemas/notificationEventName'
urls:
$ref: '../objects/Notification.yaml#/components/schemas/urls'
titleTemplate:
$ref: '../objects/Notification.yaml#/components/schemas/titleTemplate'
bodyTemplate:
$ref: '../objects/Notification.yaml#/components/schemas/bodyTemplate'
enabled:
$ref: '../objects/Notification.yaml#/components/schemas/enabled'
type:
$ref: '../objects/Notification.yaml#/components/schemas/notificationType'
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
settings:
$ref: '../objects/Notification.yaml#/components/schemas/NotificationSettings'
'404':
$ref: '#/components/responses/notification404'
/api/notifications/{id}/test:
parameters:
- name: id
in: path
description: The ID of the notification.
required: true
schema:
$ref: '../objects/Notification.yaml#/components/schemas/notificationId'
get:
operationId: sendTestNotification
description: Send a test to the given notification.
tags:
- Notification
responses:
'200':
$ref: '#/components/responses/notification200'
'404':
$ref: '#/components/responses/notification404'

View File

@ -0,0 +1,72 @@
components:
responses:
series404:
description: Series not found.
content:
text/html:
schema:
type: string
example: Series not found.
paths:
/api/series/{id}:
parameters:
- name: id
in: path
description: The ID of the series.
required: true
schema:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesId'
get:
operationId: getSeries
tags:
- Series
summary: Get series
description: Get a series by ID.
requestBody:
required: false
description: A comma separated list of what to include with the series.
content:
application/json:
schema:
type: object
properties:
include:
type: string
description: A comma separated list of what to include with the series.
example: 'progress,rssfeed'
enum: ['progress', 'rssfeed', 'progress,rssfeed', 'rssfeed,progress']
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesWithProgressAndRSS'
'404':
$ref: '#/components/responses/series404'
patch:
operationId: updateSeries
tags:
- Series
summary: Update series
description: Update a series by ID.
requestBody:
required: true
description: The series to update.
content:
application/json:
schema:
properties:
name:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesName'
description:
$ref: '../objects/entities/Series.yaml#/components/schemas/seriesDescription'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '../objects/entities/Series.yaml#/components/schemas/series'
'404':
$ref: '#/components/responses/series404'

View File

@ -3,10 +3,102 @@ components:
oldLibraryId:
type: string
description: The ID of the libraries created on server version 2.2.23 and before.
format: "lib_[a-z0-9]{18}"
example: lib_o78uaoeuh78h6aoeif
format: 'lib_[a-z0-9]{18}'
example: 'lib_o78uaoeuh78h6aoeif'
libraryId:
type: string
description: The ID of the library.
format: uuid
example: e4bb1afb-4a4f-4dd6-8be0-e615d233185b
example: 'e4bb1afb-4a4f-4dd6-8be0-e615d233185b'
libraryIdNullable:
type: string
description: The ID of the library. Applies to all libraries if `null`.
format: uuid
nullable: true
example: 'e4bb1afb-4a4f-4dd6-8be0-e615d233185b'
libraryName:
description: The name of the library.
type: string
example: My Audiobooks
librarySettings:
description: The settings for the library.
type: object
properties:
coverAspectRatio:
description: Whether the library should use square book covers. Must be 0 (for false) or 1 (for true).
type: integer
example: 1
disableWatcher:
description: Whether to disable the folder watcher for the library.
type: boolean
example: false
skipMatchingMediaWithAsin:
description: Whether to skip matching books that already have an ASIN.
type: boolean
example: false
skipMatchingMediaWithIsbn:
description: Whether to skip matching books that already have an ISBN.
type: boolean
example: false
autoScanCronExpression:
description: The cron expression for when to automatically scan the library folders. If null, automatic scanning will be disabled.
type: string
nullable: true
example: '0 0 0 * * *'
audiobooksOnly:
description: Whether the library should ignore ebook files and only allow ebook files to be supplementary.
type: boolean
example: false
hideSingleBookSeries:
description: Whether to hide series with only one book.
type: boolean
example: false
onlyShowLaterBooksInContinueSeries:
description: Whether to only show books in a series after the highest series sequence.
type: boolean
example: false
metadataPrecedence:
description: The precedence of metadata sources. See Metadata Providers for a list of possible providers.
type: array
items:
type: string
example: ['folderStructure', 'audioMetatags', 'nfoFile', 'txtFiles', 'opfFile', 'absMetadata']
podcastSearchRegion:
description: The region to use when searching for podcasts.
type: string
example: 'us'
library:
description: A library object which includes either books or podcasts.
type: object
properties:
id:
$ref: '#/components/schemas/libraryId'
name:
$ref: '#/components/schemas/libraryName'
folders:
description: The folders that belong to the library.
type: array
items:
$ref: './Folder.yaml#/components/schemas/folder'
displayOrder:
description: Display position of the library in the list of libraries. Must be >= 1.
type: integer
example: 1
icon:
description: The selected icon for the library. See Library Icons for a list of possible icons.
type: string
example: 'audiobookshelf'
mediaType:
description: The type of media that the library contains. Will be `book` or `podcast`. (Read Only)
type: string
example: 'book'
provider:
description: Preferred metadata provider for the library. See Metadata Providers for a list of possible providers.
type: string
example: 'audible'
settings:
$ref: '#/components/schemas/librarySettings'
createdAt:
$ref: '../schemas.yaml#/components/schemas/createdAt'
lastUpdate:
$ref: '../schemas.yaml#/components/schemas/updatedAt'

View File

@ -4,7 +4,7 @@ components:
description: The ID of library items on server version 2.2.23 and before.
type: string
nullable: true
format: "li_[a-z0-9]{18}"
format: 'li_[a-z0-9]{18}'
example: li_o78uaoeuh78h6aoeif
libraryItemId:
type: string
@ -59,8 +59,17 @@ components:
type: object
description: A single item on the server, like a book or podcast. Minified media format.
allOf:
- $ref : '#/components/schemas/libraryItemBase'
- $ref: '#/components/schemas/libraryItemBase'
- type: object
properties:
media:
$ref: './mediaTypes/media.yaml#/components/schemas/mediaMinified'
libraryItemSequence:
type: object
description: A single item on the server, like a book or podcast. Includes series sequence information.
allOf:
- $ref: '#/components/schemas/libraryItemBase'
- type: object
properties:
sequence:
$ref: './entities/Series.yaml#/components/schemas/sequence'

View File

@ -0,0 +1,142 @@
components:
schemas:
notificationId:
type: string
description: The ID of the notification.
example: notification-settings
# This is using a value of `notification-settings`, not a UUID. Need to investigate
#format: uuid
#example: e4bb1afb-4a4f-4dd6-8be0-e615d233185b
appriseApiUrl:
type: string
nullable: true
description: The full URL where the Apprise API to use is located.
maxFailedAttempts:
type: integer
minimum: 0
default: 5
description: The maximum number of times a notification fails before being disabled.
maxNotificationQueue:
type: integer
description: The maximum number of notifications in the notification queue before events are ignored.
notificationEventName:
type: string
description: The name of the event the notification will fire on.
enum: ['onPodcastEpisodeDownloaded', 'onTest']
urls:
type: array
items:
type: string
description: The Apprise URLs to use for the notification.
example: http://192.168.0.3:8000/notify/my-cool-notification
titleTemplate:
type: string
description: The template for the notification title.
example: 'New {{podcastTitle}} Episode!'
bodyTemplate:
type: string
description: The template for the notification body.
example: '{{episodeTitle}} has been added to {{libraryName}} library.'
enabled:
type: boolean
default: false
description: Whether the notification is enabled.
notificationType:
type: string
enum: ['info', 'success', 'warning', 'failure']
nullable: true
default: 'info'
description: The notification's type.
Notification:
type: object
properties:
id:
$ref: '#/components/schemas/notificationId'
libraryId:
$ref: './Library.yaml#/components/schemas/libraryIdNullable'
eventName:
$ref: '#/components/schemas/notificationEventName'
urls:
$ref: '#/components/schemas/urls'
titleTemplate:
$ref: '#/components/schemas/titleTemplate'
bodyTemplate:
$ref: '#/components/schemas/bodyTemplate'
enabled:
$ref: '#/components/schemas/enabled'
type:
$ref: '#/components/schemas/notificationType'
lastFiredAt:
type: integer
nullable: true
description: The time (in ms since POSIX epoch) when the notification was last fired. Will be null if the notification has not fired.
lastAttemptFailed:
type: boolean
description: Whether the last notification attempt failed.
numConsecutiveFailedAttempts:
type: integer
description: The number of consecutive times the notification has failed.
default: 0
numTimesFired:
type: integer
description: The number of times the notification has fired.
default: 0
createdAt:
$ref: '../schemas.yaml#/components/schemas/createdAt'
NotificationEvent:
type: object
properties:
name:
type: string
description: The name of the notification event. The names and allowable values are defined at https://github.com/advplyr/audiobookshelf/blob/master/server/utils/notifications.js
requiresLibrary:
type: boolean
description: Whether the notification event depends on a library existing.
libraryMediaType:
type: string
description: The type of media of the library the notification depends on existing. Will not exist if requiresLibrary is false.
nullable: true
description:
type: string
description: The description of the notification event.
variables:
type: array
items:
type: string
description: The variables of the notification event that can be used in the notification templates.
defaults:
type: object
properties:
title:
type: string
description: The default title template for notifications using the notification event.
body:
type: string
description: The default body template for notifications using the notification event.
testData:
type: object
description: The keys of the testData object will match the list of variables. The values will be the data used when sending a test notification.
additionalProperties:
type: string
NotificationSettings:
type: object
properties:
id:
$ref: '#/components/schemas/notificationId'
appriseType:
type: string
description: The type of Apprise that will be used. At the moment, only api is available.
appriseApiUrl:
$ref: '#/components/schemas/appriseApiUrl'
notifications:
type: array
items:
$ref: '#/components/schemas/Notification'
description: The set notifications.
maxFailedAttempts:
$ref: '#/components/schemas/maxFailedAttempts'
maxNotificationQueue:
$ref: '#/components/schemas/maxNotificationQueue'
notificationDelay:
type: integer
description: The time (in ms) between notification pushes.

View File

@ -6,14 +6,24 @@ components:
format: uuid
example: e4bb1afb-4a4f-4dd6-8be0-e615d233185b
authorAsin:
type: string
description: The Audible identifier (ASIN) of the author. Will be null if unknown. Not the Amazon identifier.
type: string
nullable: true
example: B000APZOQA
authorName:
description: The name of the author.
type: string
example: Terry Goodkind
authorDescription:
description: The new description of the author.
type: string
nullable: true
example: Terry Goodkind is a #1 New York Times Bestselling Author and creator of the critically acclaimed masterwork, The Sword of Truth. He has written 30+ major, bestselling novels, has been published in more than 20 languages world-wide, and has sold more than 26 Million books. The Sword of Truth is a revered literary tour de force, comprised of 17 volumes, borne from over 25 years of dedicated writing.
authorImagePath:
description: The absolute path for the author image. This will be in the `metadata/` directory. Will be null if there is no image.
type: string
nullable: true
example: /metadata/authors/aut_z3leimgybl7uf3y4ab.jpg
authorSeries:
type: object
description: Series and the included library items that an author has written.
@ -26,9 +36,9 @@ components:
description: The items in the series. Each library item's media's metadata will have a `series` attribute, a `Series Sequence`, which is the matching series.
type: array
items:
ref: '../LibraryItem.yaml#/components/schemas/libraryItemMinified'
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemMinified'
author:
description: An author object which includes a description and image path.
description: An author object which includes a description and image path. The library items and series associated with the author are optionally included.
type: object
properties:
id:
@ -38,51 +48,23 @@ components:
name:
$ref: '#/components/schemas/authorName'
description:
description: A description of the author. Will be null if there is none.
type: string
nullable: true
example: |
Terry Goodkind is a #1 New York Times Bestselling Author and creator of the critically acclaimed masterwork,
The Sword of Truth. He has written 30+ major, bestselling novels, has been published in more than 20
languages world-wide, and has sold more than 26 Million books. The Sword of Truth is a revered literary
tour de force, comprised of 17 volumes, borne from over 25 years of dedicated writing. Terry Goodkind's
brilliant books are character-driven stories, with a focus on the complexity of the human psyche. Goodkind
has an uncanny grasp for crafting compelling stories about people like you and me, trapped in terrifying
situations.
$ref: '#/components/schemas/authorDescription'
imagePath:
description: The absolute path for the author image located in the `metadata/` directory. Will be null if there is no image.
type: string
nullable: true
example: /metadata/authors/aut_bxxbyjiptmgb56yzoz.jpg
$ref: '#/components/schemas/authorImagePath'
addedAt:
$ref: '../../schemas.yaml#/components/schemas/addedAt'
updatedAt:
$ref: '../../schemas.yaml#/components/schemas/updatedAt'
authorWithItems:
type: object
description: The author schema with an array of items they are associated with.
allOf:
- $ref: '#/components/schemas/author'
- type: object
properties:
libraryItems:
description: The items associated with the author
type: string
type: array
items:
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemMinified'
authorWithSeries:
type: object
description: The author schema with an array of items and series they are associated with.
allOf:
- $ref: '#/components/schemas/authorWithItems'
- type: object
properties:
series:
description: The series associated with the author
type: array
items:
$ref: '#/components/schemas/authorSeries'
libraryItems:
description: The items associated with the author
type: array
items:
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemMinified'
series:
description: The series associated with the author
type: array
items:
$ref: '#/components/schemas/authorSeries'
authorMinified:
type: object
description: Minified author object which only contains the author name and ID.
@ -101,4 +83,4 @@ components:
numBooks:
description: The number of books associated with the author in the library.
type: integer
example: 1
example: 1

View File

@ -8,4 +8,110 @@ components:
seriesName:
description: The name of the series.
type: string
example: Sword of Truth
example: Sword of Truth
seriesDescription:
description: A description for the series. Will be null if there is none.
type: string
nullable: true
example: The Sword of Truth is a series of twenty one epic fantasy novels written by Terry Goodkind.
sequence:
description: The position in the series the book is.
type: string
nullable: true
seriesProgress:
type: object
description: The user's progress of a series.
properties:
libraryItemIds:
description: The IDs of the library items in the series.
type: array
items:
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemId'
libraryItemIdsFinished:
description: The IDs of the library items in the series that are finished.
type: array
items:
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemId'
isFinished:
description: Whether the series is finished.
type: boolean
series:
type: object
description: A series object which includes the name and description of the series.
properties:
id:
$ref: '#/components/schemas/seriesId'
name:
$ref: '#/components/schemas/seriesName'
description:
$ref: '#/components/schemas/seriesDescription'
addedAt:
$ref: '../../schemas.yaml#/components/schemas/addedAt'
updatedAt:
$ref: '../../schemas.yaml#/components/schemas/updatedAt'
seriesNumBooks:
type: object
description: A series object which includes the name and number of books in the series.
properties:
id:
$ref: '#/components/schemas/seriesId'
name:
$ref: '#/components/schemas/seriesName'
numBooks:
description: The number of books in the series.
type: integer
libraryItemIds:
description: The IDs of the library items in the series.
type: array
items:
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemId'
seriesBooks:
type: object
description: A series object which includes the name and books in the series.
properties:
id:
$ref: '#/components/schemas/seriesId'
name:
$ref: '#/components/schemas/seriesName'
addedAt:
$ref: '../../schemas.yaml#/components/schemas/addedAt'
nameIgnorePrefix:
description: The name of the series with any prefix moved to the end.
type: string
nameIgnorePrefixSort:
description: The name of the series with any prefix removed.
type: string
type:
description: Will always be `series`.
type: string
books:
description: The library items that contain the books in the series. A sequence attribute that denotes the position in the series the book is in, is tacked on.
type: array
items:
$ref: '../LibraryItem.yaml#/components/schemas/libraryItemSequence'
totalDuration:
description: The combined duration (in seconds) of all books in the series.
type: number
seriesSequence:
type: object
description: A series object which includes the name and sequence of the series.
properties:
id:
$ref: '#/components/schemas/seriesId'
name:
$ref: '#/components/schemas/seriesName'
sequence:
$ref: '#/components/schemas/sequence'
seriesWithProgressAndRSS:
type: object
description: A series object which includes the name and progress of the series.
oneOf:
- $ref: '#/components/schemas/series'
- type: object
properties:
progress:
$ref: '#/components/schemas/seriesProgress'
rssFeed:
description: The RSS feed for the series.
type: string
example: 'TBD'

View File

@ -52,7 +52,7 @@ components:
type: string
example: MP2/3 (MPEG audio layer 2/3)
duration:
$ref: '#/components/schemas/durationSec'
$ref: '../../schemas.yaml#/components/schemas/durationSec'
bitRate:
description: The bit rate (in bit/s) of the audio file.
type: integer

View File

@ -0,0 +1,17 @@
components:
schemas:
ebookFile:
type: object
properties:
ino:
$ref: '../../schemas.yaml#/components/schemas/inode'
metadata:
$ref: '../metadata/FileMetadata.yaml#/components/schemas/fileMetadata'
ebookFormat:
description: The ebook format of the ebook file.
type: string
example: epub
addedAt:
$ref: '../../schemas.yaml#/components/schemas/addedAt'
updatedAt:
$ref: '../../schemas.yaml#/components/schemas/updatedAt'

View File

@ -18,18 +18,18 @@ components:
audioFiles:
type: array
items:
$ref: '#/components/schemas/audioFile'
$ref: '../files/AudioFile.yaml#/components/schemas/audioFile'
chapters:
type: array
items:
$ref: '#/components/schemas/bookChapter'
$ref: '../metadata/BookMetadata.yaml#/components/schemas/bookChapter'
missingParts:
description: Any parts missing from the book by track index.
type: array
items:
type: integer
ebookFile:
$ref: '#/components/schemas/ebookFile'
$ref: '../files/EBookFile.yaml#/components/schemas/ebookFile'
bookMinified:
type: object
description: Minified book schema. Does not depend on `bookBase` because there's pretty much no overlap.

Binary file not shown.

View File

@ -7,151 +7,52 @@ servers:
- url: http://localhost:3000
description: Development server
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
responses:
ok200:
description: OK
securitySchemes:
BearerAuth:
description: Bearer authentication
type: http
scheme: bearer
security:
- BearerAuth: []
- BearerAuth: []
paths:
/api/authors/{id}:
get:
operationId: getAuthorById
summary: Get a single author by ID on server
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorInclude'
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorLibraryId'
responses:
200:
description: getAuthorById OK
content:
application/json:
schema:
oneOf:
- $ref: './objects/entities/Author.yaml#/components/schemas/author'
- $ref: './objects/entities/Author.yaml#/components/schemas/authorWithItems'
- $ref: './objects/entities/Author.yaml#/components/schemas/authorWithSeries'
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
patch:
operationId: updateAuthorById
summary: Update a single author by ID on server. This endpoint will merge two authors if the new author name matches another author in the database.
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
- $ref: './controllers/AuthorController.yaml#/components/parameters/asin'
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorName'
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorDescription'
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorImagePath'
responses:
200:
description: updateAuthorById OK
content:
application/json:
schema:
allOf:
- $ref: './objects/entities/Author.yaml#/components/schemas/author'
- $ref: './controllers/AuthorController.yaml#/components/schemas/authorUpdated'
- type: object
properties:
merged:
description: Will only exist and be `true` if the author was merged with another author
type: boolean
nullable: true
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
delete:
operationId: deleteAuthorById
summary: Delete a single author by ID on server and remove author from all books.
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
responses:
200:
$ref: '#/components/responses/ok200'
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
$ref: './controllers/AuthorController.yaml#/paths/~1api~1authors~1{id}'
/api/authors/{id}/image:
post:
operationId: setAuthorImageById
summary: Set an author image using a provided URL.
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
- $ref: './controllers/AuthorController.yaml#/components/parameters/imageUrl'
responses:
200:
description: setAuthorImageById OK
content:
application/json:
schema:
oneOf:
- $ref: './objects/entities/Author.yaml#/components/schemas/author'
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
delete:
operationId: deleteAuthorImageById
summary: Delete an author image from the server and remove the image from the database.
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
responses:
200:
$ref: '#/components/responses/ok200'
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
patch:
operationId: getAuthorImageById
summary: Return the author image by author ID.
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
- $ref: './controllers/AuthorController.yaml#/components/parameters/imageWidth'
- $ref: './controllers/AuthorController.yaml#/components/parameters/imageHeight'
- $ref: './controllers/AuthorController.yaml#/components/parameters/imageFormat'
- $ref: './controllers/AuthorController.yaml#/components/parameters/imageRaw'
responses:
200:
description: getAuthorImageById OK
content:
image/*:
schema:
type: string
format: binary
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
$ref: './controllers/AuthorController.yaml#/paths/~1api~1authors~1{id}~1image'
/api/authors/{id}/match:
post:
operationId: matchAuthorById
summary: Match the author against Audible using quick match. Quick match updates the author's description and image (if no image already existed) with information from audible. Either `asin` or `q` must be provided, with `asin` taking priority if both are provided.
tags:
- Authors
parameters:
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorId'
- $ref: './controllers/AuthorController.yaml#/components/parameters/asin'
- $ref: './controllers/AuthorController.yaml#/components/parameters/authorSearchName'
responses:
200:
description: matchAuthorById OK
content:
application/json:
schema:
allOf:
- $ref: './objects/entities/Author.yaml#/components/schemas/author'
- $ref: './controllers/AuthorController.yaml#/components/schemas/authorUpdated'
404:
$ref: './controllers/AuthorController.yaml#/components/responses/author404'
$ref: './controllers/AuthorController.yaml#/paths/~1api~1authors~1{id}~1match'
/api/libraries:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries'
/api/libraries/{id}:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries~1{id}'
/api/libraries/{id}/authors:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries~1{id}~1authors'
/api/libraries/{id}/items:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries~1{id}~1items'
/api/libraries/{id}/issues:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries~1{id}~1issues'
/api/libraries/{id}/series:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries~1{id}~1series'
/api/libraries/{id}/series/{seriesId}:
$ref: './controllers/LibraryController.yaml#/paths/~1api~1libraries~1{id}~1series~1{seriesId}'
/api/notifications:
$ref: './controllers/NotificationController.yaml#/paths/~1api~1notifications'
/api/notificationdata:
$ref: './controllers/NotificationController.yaml#/paths/~1api~1notificationdata'
/api/notifications/test:
$ref: './controllers/NotificationController.yaml#/paths/~1api~1notifications~1test'
/api/notifications/{id}:
$ref: './controllers/NotificationController.yaml#/paths/~1api~1notifications~1{id}'
/api/notifications/{id}/test:
$ref: './controllers/NotificationController.yaml#/paths/~1api~1notifications~1{id}~1test'
/api/series/{id}:
$ref: './controllers/SeriesController.yaml#/paths/~1api~1series~1{id}'
tags:
- name: Authors
description: Author endpoints
- name: Libraries
description: Library endpoints
- name: Series
description: Series endpoints
- name: Notification
description: Notifications endpoints

View File

@ -25,9 +25,47 @@ components:
type: array
items:
type: string
example: ["To Be Read", "Genre: Nonfiction"]
example: ['To Be Read', 'Genre: Nonfiction']
inode:
description: The inode of the item in the file system.
type: string
format: "[0-9]*"
example: '649644248522215260'
format: '[0-9]*'
example: '649644248522215260'
total:
description: The total number of items in the response.
type: integer
example: 100
limit:
description: The number of items to return. If 0, no items are returned.
type: integer
example: 10
default: 0
page:
description: The page number (zero indexed) to return. If no limit is specified, then page will have no effect.
type: integer
example: 1
default: 0
sortDesc:
description: Return items in reversed order if true.
type: boolean
example: true
default: false
minified:
description: Return minified items if true.
type: boolean
example: true
default: false
region:
description: The region used to search.
type: string
example: 'us'
default: 'us'
parameters:
minified:
in: query
name: minified
description: Return minified items if true
schema:
type: integer
minimum: 0
example: 1

View File

@ -10,6 +10,7 @@ if (isDev) {
if (devEnv.FFmpegPath) process.env.FFMPEG_PATH = devEnv.FFmpegPath
if (devEnv.FFProbePath) process.env.FFPROBE_PATH = devEnv.FFProbePath
if (devEnv.SkipBinariesCheck) process.env.SKIP_BINARIES_CHECK = '1'
if (devEnv.BackupPath) process.env.BACKUP_PATH = devEnv.BackupPath
process.env.SOURCE = 'local'
process.env.ROUTER_BASE_PATH = devEnv.RouterBasePath || ''
}

1673
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
"node-tone": "^1.0.1",
"nodemailer": "^6.9.13",
"openid-client": "^5.6.1",
"p-throttle": "^4.1.1",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"sequelize": "^6.35.2",

176
readme.md
View File

@ -18,38 +18,41 @@ Audiobookshelf is a self-hosted audiobook and podcast server.
### Features
* Fully **open-source**, including the [android & iOS app](https://github.com/advplyr/audiobookshelf-app) *(in beta)*
* Stream all audio formats on the fly
* Search and add podcasts to download episodes w/ auto-download
* Multi-user support w/ custom permissions
* Keeps progress per user and syncs across devices
* Auto-detects library updates, no need to re-scan
* Upload books and podcasts w/ bulk upload drag and drop folders
* Backup your metadata + automated daily backups
* Progressive Web App (PWA)
* Chromecast support on the web app and android app
* Fetch metadata and cover art from several sources
* Chapter editor and chapter lookup (using [Audnexus API](https://audnex.us/))
* Merge your audio files into a single m4b
* Embed metadata and cover image into your audio files (using [Tone](https://github.com/sandreas/tone))
* Basic ebook support and ereader
* Epub, pdf, cbr, cbz
* Send ebook to device (i.e. Kindle)
* Open RSS feeds for podcasts and audiobooks
- Fully **open-source**, including the [android & iOS app](https://github.com/advplyr/audiobookshelf-app) _(in beta)_
- Stream all audio formats on the fly
- Search and add podcasts to download episodes w/ auto-download
- Multi-user support w/ custom permissions
- Keeps progress per user and syncs across devices
- Auto-detects library updates, no need to re-scan
- Upload books and podcasts w/ bulk upload drag and drop folders
- Backup your metadata + automated daily backups
- Progressive Web App (PWA)
- Chromecast support on the web app and android app
- Fetch metadata and cover art from several sources
- Chapter editor and chapter lookup (using [Audnexus API](https://audnex.us/))
- Merge your audio files into a single m4b
- Embed metadata and cover image into your audio files (using [Tone](https://github.com/sandreas/tone))
- Basic ebook support and ereader
- Epub, pdf, cbr, cbz
- Send ebook to device (i.e. Kindle)
- Open RSS feeds for podcasts and audiobooks
Is there a feature you are looking for? [Suggest it](https://github.com/advplyr/audiobookshelf/issues/new/choose)
Join us on [Discord](https://discord.gg/HQgCbd6E75) or [Matrix](https://matrix.to/#/#audiobookshelf:matrix.org)
### Android App (beta)
Try it out on the [Google Play Store](https://play.google.com/store/apps/details?id=com.audiobookshelf.app)
### iOS App (beta)
**Beta is currently full. Apple has a hard limit of 10k beta testers. Updates will be posted in Discord/Matrix.**
Using Test Flight: https://testflight.apple.com/join/wiic7QIW ***(beta is full)***
Using Test Flight: https://testflight.apple.com/join/wiic7QIW **_(beta is full)_**
### Build your own tools & clients
Check out the [API documentation](https://api.audiobookshelf.org/)
<br />
@ -62,7 +65,7 @@ Check out the [API documentation](https://api.audiobookshelf.org/)
#### Directory structure and folder names are important to Audiobookshelf!
See [documentation](https://audiobookshelf.org/docs#book-directory-structure) for supported directory structure, folder naming conventions, and audio file metadata usage.
See [documentation](https://audiobookshelf.org/docs#book-directory-structure) for supported directory structure, folder naming conventions, and audio file metadata usage.
<br />
@ -88,7 +91,6 @@ Toggle websockets support.
Add this to the site config file on your nginx server after you have changed the relevant parts in the <> brackets, and inserted your certificate paths.
```bash
server
{
@ -121,12 +123,13 @@ server
Add this to the site config file on your Apache server after you have changed the relevant parts in the <> brackets, and inserted your certificate paths.
For this to work you must enable at least the following mods using `a2enmod`:
- `ssl`
- `proxy`
- `proxy_http`
- `proxy_balancer`
- `proxy_wstunnel`
- `rewrite`
- `ssl`
- `proxy`
- `proxy_http`
- `proxy_balancer`
- `proxy_wstunnel`
- `rewrite`
```bash
<IfModule mod_ssl.c>
@ -151,9 +154,8 @@ For this to work you must enable at least the following mods using `a2enmod`:
</IfModule>
```
Some SSL certificates like those signed by Let's Encrypt require ACME validation. To allow Let's Encrypt to write and confirm
the ACME challenge, edit your VirtualHost definition to prevent proxying traffic that queries `/.well-known` and instead
serve that directly:
Some SSL certificates like those signed by Let's Encrypt require ACME validation. To allow Let's Encrypt to write and confirm the ACME challenge, edit your VirtualHost definition to prevent proxying traffic that queries `/.well-known` and instead serve that directly:
```bash
<VirtualHost *:443>
# ...
@ -162,15 +164,14 @@ serve that directly:
# within DocumentRoot and give the HTTP user recursive write
# access to it.
DocumentRoot /path/to/local/directory
ProxyPreserveHost On
ProxyPass /.well-known !
ProxyPass / http://localhost:<audiobookshelf_port>/
# ...
</VirtualHost>
```
# ...
</VirtualHost>
```
### SWAG Reverse Proxy
@ -179,47 +180,49 @@ serve that directly:
### Synology NAS Reverse Proxy Setup (DSM 7+/Quickconnect)
1. **Open Control Panel**
- Navigate to `Login Portal > Advanced`.
2. **General Tab**
- Click `Reverse Proxy` > `Create`.
| Setting | Value |
|---------|----------------|
| Reverse Proxy Name | audiobookshelf |
| Setting | Value |
| ------------------ | -------------- |
| Reverse Proxy Name | audiobookshelf |
3. **Source Configuration**
| Setting | Value |
|-------------------------|-------------------------------------|
| Protocol | HTTPS |
| Hostname | `<sub>.<quickconnectdomain>.synology.me` |
| Port | 443 |
| Access Control Profile | Leave as is |
| Setting | Value |
| ---------------------- | ---------------------------------------- |
| Protocol | HTTPS |
| Hostname | `<sub>.<quickconnectdomain>.synology.me` |
| Port | 443 |
| Access Control Profile | Leave as is |
- Example Hostname: `audiobookshelf.mydomain.synology.me`
4. **Destination Configuration**
| Setting | Value |
|-----------|------------------|
| Protocol | HTTP |
| Hostname | Your NAS IP |
| Port | 13378 |
| Setting | Value |
| -------- | ----------- |
| Protocol | HTTP |
| Hostname | Your NAS IP |
| Port | 13378 |
5. **Custom Header Tab**
- Go to `Create > Websocket`.
- Configure Headers (leave as is):
| Header Name | Value |
|-------------|------------------|
| Upgrade | `$http_upgrade` |
| Connection | `$connection_upgrade` |
| Header Name | Value |
| ----------- | --------------------- |
| Upgrade | `$http_upgrade` |
| Connection | `$connection_upgrade` |
6. **Advanced Settings Tab**
- Leave as is.
### [Traefik Reverse Proxy](https://doc.traefik.io/traefik/)
Middleware relating to CORS will cause the app to report Unknown Error when logging in. To prevent this don't apply any of the following headers to the router for this site:
@ -230,8 +233,7 @@ Middleware relating to CORS will cause the app to report Unknown Error when logg
<li>accessControlMaxAge</li>
</ul>
From [@Dondochaka](https://discord.com/channels/942908292873723984/942914154254176257/945074590374318170) and [@BeastleeUK](https://discord.com/channels/942908292873723984/942914154254176257/970366039294611506)
<br />
From [@Dondochaka](https://discord.com/channels/942908292873723984/942914154254176257/945074590374318170) and [@BeastleeUK](https://discord.com/channels/942908292873723984/942914154254176257/970366039294611506) <br />
### Example Caddyfile - [Caddy Reverse Proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy)
@ -241,13 +243,14 @@ subdomain.domain.com {
reverse_proxy <LOCAL_IP>:<PORT>
}
```
### HAProxy
Below is a generic HAProxy config, using `audiobookshelf.YOUR_DOMAIN.COM`.
Below is a generic HAProxy config, using `audiobookshelf.YOUR_DOMAIN.COM`.
To use `http2`, `ssl` is needed.
````make
```make
global
# ... (your global settings go here)
@ -282,7 +285,7 @@ backend default_backend
# Define the server for the default backend
server default_server 127.0.0.123:8081
````
```
### pfSense and HAProxy
@ -292,43 +295,37 @@ For pfSense the inputs are graphical, and `Health checking` is enabled.
##### Access Control lists
| Name | Expression | CS | Not | Value |
|:--------------:|:-----------------:|:--:|:---:|:---------------:|
| audiobookshelf | Host starts with: | | | audiobookshelf. |
| Name | Expression | CS | Not | Value |
| :------------: | :---------------: | :-: | :-: | :-------------: |
| audiobookshelf | Host starts with: | | | audiobookshelf. |
##### Actions
The `condition acl names` needs to match the name above `audiobookshelf`.
| Action | Parameters | Condition acl names |
|:--------------:|:-----------------:|:---------------:|
| `Use Backend` |audiobookshelf | audiobookshelf |
| Action | Parameters | Condition acl names |
| :-----------: | :------------: | :-----------------: |
| `Use Backend` | audiobookshelf | audiobookshelf |
#### Backend
The `Name` needs to match the `Parameters` above `audiobookshelf`.
| Name | audiobookshelf |
|--------------|-----------------|
| Name | audiobookshelf |
| ---- | -------------- |
##### Server list:
| Name | Expression | CS | Not | Value |
|:--------------:|:-----------------:|:--:|:---:|:---------------:|
| audiobookshelf | Host starts with: | | | audiobookshelf. |
| Name | Expression | CS | Not | Value |
| :------------: | :---------------: | :-: | :-: | :-------------: |
| audiobookshelf | Host starts with: | | | audiobookshelf. |
##### Health checking:
Health checking is enabled by default. `Http check method` of `OPTIONS` is not supported on Audiobookshelf.
If Health check fails, data will not be forwared.
Need to do one of following:
* To disable: Change `Health check method` to `none`.
* To make Health checking function: Change `Http check method` to `HEAD` or `GET`.
Health checking is enabled by default. `Http check method` of `OPTIONS` is not supported on Audiobookshelf. If Health check fails, data will not be forwared. Need to do one of following:
- To disable: Change `Health check method` to `none`.
- To make Health checking function: Change `Http check method` to `HEAD` or `GET`.
# Run from source
@ -336,16 +333,20 @@ Need to do one of following:
This application is built using [NodeJs](https://nodejs.org/).
Information on helping with translations of the web client [here](https://www.audiobookshelf.org/faq#how-do-i-help-with-translations).
### Localization
Thank you to [Weblate](https://hosted.weblate.org/engage/audiobookshelf/) for hosting our localization infrastructure pro-bono. If you want to see Audiobookshelf in your language, please help us localize. Additional information on helping with the translations [here](https://www.audiobookshelf.org/faq#how-do-i-help-with-translations). <a href="https://hosted.weblate.org/engage/audiobookshelf/"> <img src="https://hosted.weblate.org/widget/audiobookshelf/horizontal-auto.svg" alt="Translation status" /> </a>
### Dev Container Setup
The easiest way to begin developing this project is to use a dev container. An introduction to dev containers in VSCode can be found [here](https://code.visualstudio.com/docs/devcontainers/containers).
Required Software:
* [Docker Desktop](https://www.docker.com/products/docker-desktop/)
* [VSCode](https://code.visualstudio.com/download)
*Note, it is possible to use other container software than Docker and IDEs other than VSCode. However, this setup is more complicated and not covered here.*
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
- [VSCode](https://code.visualstudio.com/download)
_Note, it is possible to use other container software than Docker and IDEs other than VSCode. However, this setup is more complicated and not covered here._
<div>
<details>
@ -422,10 +423,9 @@ You can also build a version of the client that supports live reloading. To do t
If you are using VSCode, this project includes a couple of pre-defined targets to speed up this process. First, if you build the project (`ctrl+shift+b` or `cmd+shift+b`) it will automatically generate the client. Next, there are debug commands for running the server and client. You can view these targets using the debug panel (bring it up with (`ctrl+shift+d` or `cmd+shift+d`):
* `Debug server`—Run the server.
* `Debug client (nuxt)`—Run the client with live reload.
* `Debug server and client (nuxt)`—Runs both the preceding two debug targets.
- `Debug server`—Run the server.
- `Debug client (nuxt)`—Run the client with live reload.
- `Debug server and client (nuxt)`—Runs both the preceding two debug targets.
# How to Support

View File

@ -142,7 +142,7 @@ class Database {
* @returns {boolean}
*/
async checkHasDb() {
if (!await fs.pathExists(this.dbPath)) {
if (!(await fs.pathExists(this.dbPath))) {
Logger.info(`[Database] absdatabase.sqlite not found at ${this.dbPath}`)
return false
}
@ -159,14 +159,13 @@ class Database {
// First check if this is a new database
this.isNew = !(await this.checkHasDb()) || force
if (!await this.connect()) {
if (!(await this.connect())) {
throw new Error('Database connection failed')
}
await this.buildModels(force)
Logger.info(`[Database] Db initialized with models:`, Object.keys(this.sequelize.models).join(', '))
await this.loadData()
}
@ -179,11 +178,11 @@ class Database {
let logging = false
let benchmark = false
if (process.env.QUERY_LOGGING === "log") {
if (process.env.QUERY_LOGGING === 'log') {
// Setting QUERY_LOGGING=log will log all Sequelize queries before they run
Logger.info(`[Database] Query logging enabled`)
logging = (query) => Logger.debug(`Running the following query:\n ${query}`)
} else if (process.env.QUERY_LOGGING === "benchmark") {
} else if (process.env.QUERY_LOGGING === 'benchmark') {
// Setting QUERY_LOGGING=benchmark will log all Sequelize queries and their execution times, after they run
Logger.info(`[Database] Query benchmarking enabled"`)
logging = (query, time) => Logger.debug(`Ran the following query in ${time}ms:\n ${query}`)
@ -199,7 +198,7 @@ class Database {
})
// Helper function
this.sequelize.uppercaseFirst = str => str ? `${str[0].toUpperCase()}${str.substr(1)}` : ''
this.sequelize.uppercaseFirst = (str) => (str ? `${str[0].toUpperCase()}${str.substr(1)}` : '')
try {
await this.sequelize.authenticate()
@ -250,30 +249,31 @@ class Database {
require('./models/FeedEpisode').init(this.sequelize)
require('./models/Setting').init(this.sequelize)
require('./models/CustomMetadataProvider').init(this.sequelize)
require('./models/MediaItemShare').init(this.sequelize)
return this.sequelize.sync({ force, alter: false })
}
/**
* Compare two server versions
* @param {string} v1
* @param {string} v2
* @param {string} v1
* @param {string} v2
* @returns {-1|0|1} 1 if v1 > v2
*/
compareVersions(v1, v2) {
if (!v1 || !v2) return 0
return v1.localeCompare(v2, undefined, { numeric: true, sensitivity: "case", caseFirst: "upper" })
return v1.localeCompare(v2, undefined, { numeric: true, sensitivity: 'case', caseFirst: 'upper' })
}
/**
* Checks if migration to sqlite db is necessary & runs migration.
*
*
* Check if version was upgraded and run any version specific migrations.
*
*
* Loads most of the data from the database. This is a temporary solution.
*/
async loadData() {
if (this.isNew && await dbMigration.checkShouldMigrate()) {
if (this.isNew && (await dbMigration.checkShouldMigrate())) {
Logger.info(`[Database] New database was created and old database was detected - migrating old to new`)
await dbMigration.migrate(this.models)
}
@ -323,9 +323,9 @@ class Database {
/**
* Create root user
* @param {string} username
* @param {string} pash
* @param {Auth} auth
* @param {string} username
* @param {string} pash
* @param {Auth} auth
* @returns {boolean} true if created
*/
async createRootUser(username, pash, auth) {
@ -359,7 +359,7 @@ class Database {
updateBulkUsers(oldUsers) {
if (!this.sequelize) return false
return Promise.all(oldUsers.map(u => this.updateUser(u)))
return Promise.all(oldUsers.map((u) => this.updateUser(u)))
}
removeUser(userId) {
@ -379,7 +379,7 @@ class Database {
updateBulkBooks(oldBooks) {
if (!this.sequelize) return false
return Promise.all(oldBooks.map(oldBook => this.models.book.saveFromOld(oldBook)))
return Promise.all(oldBooks.map((oldBook) => this.models.book.saveFromOld(oldBook)))
}
createLibrary(oldLibrary) {
@ -420,8 +420,8 @@ class Database {
/**
* Save metadata file and update library item
*
* @param {import('./objects/LibraryItem')} oldLibraryItem
*
* @param {import('./objects/LibraryItem')} oldLibraryItem
* @returns {Promise<boolean>}
*/
async updateLibraryItem(oldLibraryItem) {
@ -548,7 +548,7 @@ class Database {
replaceTagInFilterData(oldTag, newTag) {
for (const libraryId in this.libraryFilterData) {
const indexOf = this.libraryFilterData[libraryId].tags.findIndex(n => n === oldTag)
const indexOf = this.libraryFilterData[libraryId].tags.findIndex((n) => n === oldTag)
if (indexOf >= 0) {
this.libraryFilterData[libraryId].tags.splice(indexOf, 1, newTag)
}
@ -557,7 +557,7 @@ class Database {
removeTagFromFilterData(tag) {
for (const libraryId in this.libraryFilterData) {
this.libraryFilterData[libraryId].tags = this.libraryFilterData[libraryId].tags.filter(t => t !== tag)
this.libraryFilterData[libraryId].tags = this.libraryFilterData[libraryId].tags.filter((t) => t !== tag)
}
}
@ -572,7 +572,7 @@ class Database {
replaceGenreInFilterData(oldGenre, newGenre) {
for (const libraryId in this.libraryFilterData) {
const indexOf = this.libraryFilterData[libraryId].genres.findIndex(n => n === oldGenre)
const indexOf = this.libraryFilterData[libraryId].genres.findIndex((n) => n === oldGenre)
if (indexOf >= 0) {
this.libraryFilterData[libraryId].genres.splice(indexOf, 1, newGenre)
}
@ -581,7 +581,7 @@ class Database {
removeGenreFromFilterData(genre) {
for (const libraryId in this.libraryFilterData) {
this.libraryFilterData[libraryId].genres = this.libraryFilterData[libraryId].genres.filter(g => g !== genre)
this.libraryFilterData[libraryId].genres = this.libraryFilterData[libraryId].genres.filter((g) => g !== genre)
}
}
@ -596,7 +596,7 @@ class Database {
replaceNarratorInFilterData(oldNarrator, newNarrator) {
for (const libraryId in this.libraryFilterData) {
const indexOf = this.libraryFilterData[libraryId].narrators.findIndex(n => n === oldNarrator)
const indexOf = this.libraryFilterData[libraryId].narrators.findIndex((n) => n === oldNarrator)
if (indexOf >= 0) {
this.libraryFilterData[libraryId].narrators.splice(indexOf, 1, newNarrator)
}
@ -605,7 +605,7 @@ class Database {
removeNarratorFromFilterData(narrator) {
for (const libraryId in this.libraryFilterData) {
this.libraryFilterData[libraryId].narrators = this.libraryFilterData[libraryId].narrators.filter(n => n !== narrator)
this.libraryFilterData[libraryId].narrators = this.libraryFilterData[libraryId].narrators.filter((n) => n !== narrator)
}
}
@ -620,13 +620,13 @@ class Database {
removeSeriesFromFilterData(libraryId, seriesId) {
if (!this.libraryFilterData[libraryId]) return
this.libraryFilterData[libraryId].series = this.libraryFilterData[libraryId].series.filter(se => se.id !== seriesId)
this.libraryFilterData[libraryId].series = this.libraryFilterData[libraryId].series.filter((se) => se.id !== seriesId)
}
addSeriesToFilterData(libraryId, seriesName, seriesId) {
if (!this.libraryFilterData[libraryId]) return
// Check if series is already added
if (this.libraryFilterData[libraryId].series.some(se => se.id === seriesId)) return
if (this.libraryFilterData[libraryId].series.some((se) => se.id === seriesId)) return
this.libraryFilterData[libraryId].series.push({
id: seriesId,
name: seriesName
@ -635,13 +635,13 @@ class Database {
removeAuthorFromFilterData(libraryId, authorId) {
if (!this.libraryFilterData[libraryId]) return
this.libraryFilterData[libraryId].authors = this.libraryFilterData[libraryId].authors.filter(au => au.id !== authorId)
this.libraryFilterData[libraryId].authors = this.libraryFilterData[libraryId].authors.filter((au) => au.id !== authorId)
}
addAuthorToFilterData(libraryId, authorName, authorId) {
if (!this.libraryFilterData[libraryId]) return
// Check if author is already added
if (this.libraryFilterData[libraryId].authors.some(au => au.id === authorId)) return
if (this.libraryFilterData[libraryId].authors.some((au) => au.id === authorId)) return
this.libraryFilterData[libraryId].authors.push({
id: authorId,
name: authorName
@ -662,63 +662,63 @@ class Database {
* Used when updating items to make sure author id exists
* If library filter data is set then use that for check
* otherwise lookup in db
* @param {string} libraryId
* @param {string} authorId
* @param {string} libraryId
* @param {string} authorId
* @returns {Promise<boolean>}
*/
async checkAuthorExists(libraryId, authorId) {
if (!this.libraryFilterData[libraryId]) {
return this.authorModel.checkExistsById(authorId)
}
return this.libraryFilterData[libraryId].authors.some(au => au.id === authorId)
return this.libraryFilterData[libraryId].authors.some((au) => au.id === authorId)
}
/**
* Used when updating items to make sure series id exists
* If library filter data is set then use that for check
* otherwise lookup in db
* @param {string} libraryId
* @param {string} seriesId
* @param {string} libraryId
* @param {string} seriesId
* @returns {Promise<boolean>}
*/
async checkSeriesExists(libraryId, seriesId) {
if (!this.libraryFilterData[libraryId]) {
return this.seriesModel.checkExistsById(seriesId)
}
return this.libraryFilterData[libraryId].series.some(se => se.id === seriesId)
return this.libraryFilterData[libraryId].series.some((se) => se.id === seriesId)
}
/**
* Get author id for library by name. Uses library filter data if available
*
* @param {string} libraryId
* @param {string} authorName
* @returns {Promise<string>} author id or null if not found
*
* @param {string} libraryId
* @param {string} authorName
* @returns {Promise<string>} author id or null if not found
*/
async getAuthorIdByName(libraryId, authorName) {
if (!this.libraryFilterData[libraryId]) {
return (await this.authorModel.getOldByNameAndLibrary(authorName, libraryId))?.id || null
}
return this.libraryFilterData[libraryId].authors.find(au => au.name === authorName)?.id || null
return this.libraryFilterData[libraryId].authors.find((au) => au.name === authorName)?.id || null
}
/**
* Get series id for library by name. Uses library filter data if available
*
* @param {string} libraryId
* @param {string} seriesName
*
* @param {string} libraryId
* @param {string} seriesName
* @returns {Promise<string>} series id or null if not found
*/
async getSeriesIdByName(libraryId, seriesName) {
if (!this.libraryFilterData[libraryId]) {
return (await this.seriesModel.getOldByNameAndLibrary(seriesName, libraryId))?.id || null
}
return this.libraryFilterData[libraryId].series.find(se => se.name === seriesName)?.id || null
return this.libraryFilterData[libraryId].series.find((se) => se.name === seriesName)?.id || null
}
/**
* Reset numIssues for library
* @param {string} libraryId
* @param {string} libraryId
*/
async resetLibraryIssuesFilterData(libraryId) {
if (!this.libraryFilterData[libraryId]) return // Do nothing if filter data is not set
@ -798,4 +798,4 @@ class Database {
}
}
module.exports = new Database()
module.exports = new Database()

View File

@ -20,6 +20,7 @@ const SocketAuthority = require('./SocketAuthority')
const ApiRouter = require('./routers/ApiRouter')
const HlsRouter = require('./routers/HlsRouter')
const PublicRouter = require('./routers/PublicRouter')
const LogManager = require('./managers/LogManager')
const NotificationManager = require('./managers/NotificationManager')
@ -34,6 +35,7 @@ const RssFeedManager = require('./managers/RssFeedManager')
const CronManager = require('./managers/CronManager')
const ApiCacheManager = require('./managers/ApiCacheManager')
const BinaryManager = require('./managers/BinaryManager')
const ShareManager = require('./managers/ShareManager')
const LibraryScanner = require('./scanner/LibraryScanner')
//Import the main Passport and Express-Session library
@ -51,6 +53,7 @@ class Server {
global.RouterBasePath = ROUTER_BASE_PATH
global.XAccel = process.env.USE_X_ACCEL
global.AllowCors = process.env.ALLOW_CORS === '1'
global.DisableSsrfRequestFilter = process.env.DISABLE_SSRF_REQUEST_FILTER === '1'
if (!fs.pathExistsSync(global.ConfigPath)) {
fs.mkdirSync(global.ConfigPath)
@ -78,6 +81,7 @@ class Server {
// Routers
this.apiRouter = new ApiRouter(this)
this.hlsRouter = new HlsRouter(this.auth, this.playbackSessionManager)
this.publicRouter = new PublicRouter()
Logger.logManager = new LogManager()
@ -115,6 +119,7 @@ class Server {
await this.cleanUserData() // Remove invalid user item progress
await CacheManager.ensureCachePaths()
await ShareManager.init()
await this.backupManager.init()
await this.rssFeedManager.init()
@ -249,6 +254,7 @@ class Server {
router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router)
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
router.use('/public', this.publicRouter.router)
// RSS Feed temp route
router.get('/feed/:slug', (req, res) => {
@ -286,7 +292,8 @@ class Server {
'/config/users/:id/sessions',
'/config/item-metadata-utils/:id',
'/collection/:id',
'/playlist/:id'
'/playlist/:id',
'/share/:slug'
]
dyanimicRoutes.forEach((route) => router.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html'))))

View File

@ -23,7 +23,7 @@ class FolderWatcher extends EventEmitter {
this.libraryWatchers = []
/** @type {PendingFileUpdate[]} */
this.pendingFileUpdates = []
this.pendingDelay = 4000
this.pendingDelay = 10000
/** @type {NodeJS.Timeout} */
this.pendingTimeout = null
/** @type {Task} */
@ -42,11 +42,11 @@ class FolderWatcher extends EventEmitter {
}
get pendingFilePaths() {
return this.pendingFileUpdates.map(f => f.path)
return this.pendingFileUpdates.map((f) => f.path)
}
buildLibraryWatcher(library) {
if (this.libraryWatchers.find(w => w.id === library.id)) {
if (this.libraryWatchers.find((w) => w.id === library.id)) {
Logger.warn('[Watcher] Already watching library', library.name)
return
}
@ -67,17 +67,23 @@ class FolderWatcher extends EventEmitter {
watcher
.on('add', (path) => {
this.onFileAdded(library.id, filePathToPOSIX(path))
}).on('change', (path) => {
})
.on('change', (path) => {
// This is triggered from metadata changes, not what we want
}).on('unlink', path => {
})
.on('unlink', (path) => {
this.onFileRemoved(library.id, filePathToPOSIX(path))
}).on('rename', (path, pathNext) => {
})
.on('rename', (path, pathNext) => {
this.onFileRename(library.id, filePathToPOSIX(path), filePathToPOSIX(pathNext))
}).on('error', (error) => {
})
.on('error', (error) => {
Logger.error(`[Watcher] ${error}`)
}).on('ready', () => {
})
.on('ready', () => {
Logger.info(`[Watcher] "${library.name}" Ready`)
}).on('close', () => {
})
.on('close', () => {
Logger.debug(`[Watcher] "${library.name}" Closed`)
})
@ -104,32 +110,32 @@ class FolderWatcher extends EventEmitter {
}
/**
*
* @param {import('./objects/Library')} library
*
* @param {import('./objects/Library')} library
*/
updateLibrary(library) {
if (this.disabled) return
const libwatcher = this.libraryWatchers.find(lib => lib.id === library.id)
const libwatcher = this.libraryWatchers.find((lib) => lib.id === library.id)
if (libwatcher) {
// Library watcher was disabled
if (library.settings.disableWatcher) {
Logger.info(`[Watcher] updateLibrary: Library "${library.name}" watcher disabled`)
libwatcher.watcher.close()
this.libraryWatchers = this.libraryWatchers.filter(lw => lw.id !== libwatcher.id)
this.libraryWatchers = this.libraryWatchers.filter((lw) => lw.id !== libwatcher.id)
return
}
libwatcher.name = library.name
// If any folder paths were added or removed then re-init watcher
const pathsToAdd = library.folderPaths.filter(path => !libwatcher.paths.includes(path))
const pathsRemoved = libwatcher.paths.filter(path => !library.folderPaths.includes(path))
const pathsToAdd = library.folderPaths.filter((path) => !libwatcher.paths.includes(path))
const pathsRemoved = libwatcher.paths.filter((path) => !library.folderPaths.includes(path))
if (pathsToAdd.length || pathsRemoved.length) {
Logger.info(`[Watcher] Re-Initializing watcher for "${library.name}".`)
libwatcher.watcher.close()
this.libraryWatchers = this.libraryWatchers.filter(lw => lw.id !== libwatcher.id)
this.libraryWatchers = this.libraryWatchers.filter((lw) => lw.id !== libwatcher.id)
this.buildLibraryWatcher(library)
}
} else if (!library.settings.disableWatcher) {
@ -141,25 +147,25 @@ class FolderWatcher extends EventEmitter {
removeLibrary(library) {
if (this.disabled) return
var libwatcher = this.libraryWatchers.find(lib => lib.id === library.id)
var libwatcher = this.libraryWatchers.find((lib) => lib.id === library.id)
if (libwatcher) {
Logger.info(`[Watcher] Removed watcher for "${library.name}"`)
libwatcher.watcher.close()
this.libraryWatchers = this.libraryWatchers.filter(lib => lib.id !== library.id)
this.libraryWatchers = this.libraryWatchers.filter((lib) => lib.id !== library.id)
} else {
Logger.error(`[Watcher] Library watcher not found for "${library.name}"`)
}
}
close() {
return this.libraryWatchers.map(lib => lib.watcher.close())
return this.libraryWatchers.map((lib) => lib.watcher.close())
}
/**
* Watcher detected file added
*
* @param {string} libraryId
* @param {string} path
*
* @param {string} libraryId
* @param {string} path
*/
onFileAdded(libraryId, path) {
if (this.checkShouldIgnorePath(path)) {
@ -176,9 +182,9 @@ class FolderWatcher extends EventEmitter {
/**
* Watcher detected file removed
*
* @param {string} libraryId
* @param {string} path
*
* @param {string} libraryId
* @param {string} path
*/
onFileRemoved(libraryId, path) {
if (this.checkShouldIgnorePath(path)) {
@ -190,9 +196,9 @@ class FolderWatcher extends EventEmitter {
/**
* Watcher detected file renamed
*
* @param {string} libraryId
* @param {string} path
*
* @param {string} libraryId
* @param {string} path
*/
onFileRename(libraryId, pathFrom, pathTo) {
if (this.checkShouldIgnorePath(pathTo)) {
@ -203,17 +209,18 @@ class FolderWatcher extends EventEmitter {
}
/**
* Get mtimeMs from an added file every second until it is no longer changing
* Times out after 180s
*
* @param {string} path
* @param {number} [lastMTimeMs=0]
* @param {number} [loop=0]
* Get mtimeMs from an added file every 3 seconds until it is no longer changing
* Times out after 600s
*
* @param {string} path
* @param {number} [lastMTimeMs=0]
* @param {number} [loop=0]
*/
async waitForFileToAdd(path, lastMTimeMs = 0, loop = 0) {
// Safety to catch infinite loop (180s)
if (loop >= 180) {
Logger.warn(`[Watcher] Waiting to add file at "${path}" timeout (loop ${loop}) - proceeding`)
// Safety to catch infinite loop (600s)
if (loop >= 200) {
Logger.warn(`[Watcher] Waiting to add file at "${path}" timeout (loop ${loop}) - bailing`)
this.pendingFileUpdates = this.pendingFileUpdates.filter((pfu) => pfu.path !== path)
return this.filesBeingAdded.delete(path)
}
@ -222,33 +229,33 @@ class FolderWatcher extends EventEmitter {
if (lastMTimeMs) Logger.debug(`[Watcher] File finished adding at "${path}"`)
return this.filesBeingAdded.delete(path)
}
if (lastMTimeMs % 5 === 0) {
if (loop % 5 === 0) {
Logger.debug(`[Watcher] Waiting to add file at "${path}". mtimeMs=${mtimeMs} lastMTimeMs=${lastMTimeMs} (loop ${loop})`)
}
// Wait 1 second
await new Promise((resolve) => setTimeout(resolve, 1000))
// Wait 3 seconds
await new Promise((resolve) => setTimeout(resolve, 3000))
this.waitForFileToAdd(path, mtimeMs, ++loop)
}
/**
* Queue file update
*
* @param {string} libraryId
* @param {string} path
* @param {string} type
*
* @param {string} libraryId
* @param {string} path
* @param {string} type
*/
addFileUpdate(libraryId, path, type) {
if (this.pendingFilePaths.includes(path)) return
// Get file library
const libwatcher = this.libraryWatchers.find(lw => lw.id === libraryId)
const libwatcher = this.libraryWatchers.find((lw) => lw.id === libraryId)
if (!libwatcher) {
Logger.error(`[Watcher] Invalid library id from watcher ${libraryId}`)
return
}
// Get file folder
const folder = libwatcher.folders.find(fold => isSameOrSubPath(fold.fullPath, path))
const folder = libwatcher.folders.find((fold) => isSameOrSubPath(fold.fullPath, path))
if (!folder) {
Logger.error(`[Watcher] New file folder not found in library "${libwatcher.name}" with path "${path}"`)
return
@ -264,7 +271,7 @@ class FolderWatcher extends EventEmitter {
}
// Ignore files/folders starting with "."
const hasDotPath = relPath.split('/').find(p => p.startsWith('.'))
const hasDotPath = relPath.split('/').find((p) => p.startsWith('.'))
if (hasDotPath) {
Logger.debug(`[Watcher] Ignoring dot path "${relPath}" | Piece "${hasDotPath}"`)
return
@ -298,12 +305,17 @@ class FolderWatcher extends EventEmitter {
clearTimeout(this.pendingTimeout)
this.pendingTimeout = setTimeout(() => {
// Check that files are not still being added
if (this.pendingFileUpdates.some(pfu => this.filesBeingAdded.has(pfu.path))) {
if (this.pendingFileUpdates.some((pfu) => this.filesBeingAdded.has(pfu.path))) {
Logger.debug(`[Watcher] Still waiting for pending files "${[...this.filesBeingAdded].join(', ')}"`)
return this.handlePendingFileUpdatesTimeout()
}
LibraryScanner.scanFilesChanged(this.pendingFileUpdates, this.pendingTask)
if (this.pendingFileUpdates.length) {
LibraryScanner.scanFilesChanged(this.pendingFileUpdates, this.pendingTask)
} else {
this.pendingTask.setFinished('Scan abandoned. No files to scan.')
TaskManager.taskFinished(this.pendingTask)
}
this.pendingTask = null
this.pendingFileUpdates = []
this.filesBeingAdded.clear()
@ -311,14 +323,14 @@ class FolderWatcher extends EventEmitter {
}
checkShouldIgnorePath(path) {
return !!this.ignoreDirs.find(dirpath => {
return !!this.ignoreDirs.find((dirpath) => {
return isSameOrSubPath(dirpath, path)
})
}
/**
* Convert to POSIX and remove trailing slash
* @param {string} path
* @param {string} path
* @returns {string}
*/
cleanDirPath(path) {
@ -329,11 +341,11 @@ class FolderWatcher extends EventEmitter {
/**
* Ignore this directory if files are picked up by watcher
* @param {string} path
* @param {string} path
*/
addIgnoreDir(path) {
path = this.cleanDirPath(path)
this.pendingDirsToRemoveFromIgnore = this.pendingDirsToRemoveFromIgnore.filter(p => p !== path)
this.pendingDirsToRemoveFromIgnore = this.pendingDirsToRemoveFromIgnore.filter((p) => p !== path)
if (this.ignoreDirs.includes(path)) {
// Already ignoring dir
return
@ -346,8 +358,8 @@ class FolderWatcher extends EventEmitter {
* When downloading a podcast episode we dont want the scanner triggering for that podcast
* when the episode finishes the watcher may have a delayed response so a timeout is added
* to prevent the watcher from picking up the episode
*
* @param {string} path
*
* @param {string} path
*/
removeIgnoreDir(path) {
path = this.cleanDirPath(path)
@ -364,11 +376,11 @@ class FolderWatcher extends EventEmitter {
clearTimeout(this.removeFromIgnoreTimer)
this.removeFromIgnoreTimer = setTimeout(() => {
if (this.pendingDirsToRemoveFromIgnore.includes(path)) {
this.pendingDirsToRemoveFromIgnore = this.pendingDirsToRemoveFromIgnore.filter(p => p !== path)
this.pendingDirsToRemoveFromIgnore = this.pendingDirsToRemoveFromIgnore.filter((p) => p !== path)
Logger.debug(`[Watcher] removeIgnoreDir: No longer ignoring directory "${path}"`)
this.ignoreDirs = this.ignoreDirs.filter(p => p !== path)
this.ignoreDirs = this.ignoreDirs.filter((p) => p !== path)
}
}, 5000)
}
}
module.exports = FolderWatcher
module.exports = FolderWatcher

View File

@ -9,7 +9,7 @@ const CacheManager = require('../managers/CacheManager')
const CoverManager = require('../managers/CoverManager')
const AuthorFinder = require('../finders/AuthorFinder')
const { reqSupportsWebp } = require('../utils/index')
const { reqSupportsWebp, isValidASIN } = require('../utils/index')
const naturalSort = createNewSortInstance({
comparer: new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare
@ -252,7 +252,7 @@ class AuthorController {
async match(req, res) {
let authorData = null
const region = req.body.region || 'us'
if (req.body.asin) {
if (req.body.asin && isValidASIN(req.body.asin.toUpperCase?.())) {
authorData = await AuthorFinder.findAuthorByASIN(req.body.asin, region)
} else {
authorData = await AuthorFinder.findAuthorByName(req.body.q, region)

View File

@ -1,13 +1,16 @@
const Path = require('path')
const fs = require('../libs/fsExtra')
const Logger = require('../Logger')
const { encodeUriPath } = require('../utils/fileUtils')
const Database = require('../Database')
const fileUtils = require('../utils/fileUtils')
class BackupController {
constructor() { }
constructor() {}
getAll(req, res) {
res.json({
backups: this.backupManager.backups.map(b => b.toJSON()),
backupLocation: this.backupManager.backupLocation
backups: this.backupManager.backups.map((b) => b.toJSON()),
backupLocation: this.backupManager.backupPath
})
}
@ -19,7 +22,7 @@ class BackupController {
await this.backupManager.removeBackup(req.backup)
res.json({
backups: this.backupManager.backups.map(b => b.toJSON())
backups: this.backupManager.backups.map((b) => b.toJSON())
})
}
@ -31,15 +34,65 @@ class BackupController {
this.backupManager.uploadBackup(req, res)
}
/**
* PATCH: /api/backups/path
* Update the backup path
*
* @this import('../routers/ApiRouter')
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async updatePath(req, res) {
// Validate path is not empty and is a string
if (!req.body.path || !req.body.path?.trim?.()) {
Logger.error('[BackupController] Update backup path invalid')
return res.status(400).send('Invalid request body. Must include path.')
}
const newBackupPath = fileUtils.filePathToPOSIX(Path.resolve(req.body.path))
if (newBackupPath === this.backupManager.backupPath) {
Logger.debug(`[BackupController] Backup path unchanged: ${newBackupPath}`)
return res.status(200).send('Backup path unchanged')
}
Logger.info(`[BackupController] Updating backup path to "${newBackupPath}" from "${this.backupManager.backupPath}"`)
// Check if backup path is set in environment variable
if (process.env.BACKUP_PATH) {
Logger.warn(`[BackupController] Backup path is set in environment variable BACKUP_PATH. Backup path will be reverted on server restart.`)
}
// Validate backup path is writable and create folder if it does not exist
try {
const direxists = await fs.pathExists(newBackupPath)
if (!direxists) {
// If folder does not exist try to make it
await fs.mkdir(newBackupPath)
}
} catch (error) {
Logger.error(`[BackupController] updatePath: Failed to ensure backup path "${newBackupPath}"`, error)
return res.status(400).send(`Invalid backup path "${req.body.path}"`)
}
Database.serverSettings.backupPath = newBackupPath
await Database.updateServerSettings()
await this.backupManager.reload()
res.sendStatus(200)
}
/**
* api/backups/:id/download
*
* @param {*} req
* @param {*} res
*
* @param {*} req
* @param {*} res
*/
download(req, res) {
if (global.XAccel) {
const encodedURI = encodeUriPath(global.XAccel + req.backup.fullPath)
const encodedURI = fileUtils.encodeUriPath(global.XAccel + req.backup.fullPath)
Logger.debug(`Use X-Accel to serve static file ${encodedURI}`)
return res.status(204).header({ 'X-Accel-Redirect': encodedURI }).send()
}
@ -50,9 +103,9 @@ class BackupController {
}
/**
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
apply(req, res) {
this.backupManager.requestApplyBackup(this.apiCacheManager, req.backup, res)
@ -65,7 +118,7 @@ class BackupController {
}
if (req.params.id) {
req.backup = this.backupManager.backups.find(b => b.id === req.params.id)
req.backup = this.backupManager.backups.find((b) => b.id === req.params.id)
if (!req.backup) {
return res.sendStatus(404)
}

View File

@ -13,18 +13,19 @@ const AudioFileScanner = require('../scanner/AudioFileScanner')
const Scanner = require('../scanner/Scanner')
const CacheManager = require('../managers/CacheManager')
const CoverManager = require('../managers/CoverManager')
const ShareManager = require('../managers/ShareManager')
class LibraryItemController {
constructor() { }
constructor() {}
/**
* GET: /api/items/:id
* Optional query params:
* ?include=progress,rssfeed,downloads
* ?expanded=1
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async findOne(req, res) {
const includeEntities = (req.query.include || '').split(',')
@ -42,9 +43,13 @@ class LibraryItemController {
item.rssFeed = feedData?.toJSONMinified() || null
}
if (item.mediaType === 'book' && includeEntities.includes('share')) {
item.mediaItemShare = ShareManager.findByMediaItemId(item.media.id)
}
if (item.mediaType === 'podcast' && includeEntities.includes('downloads')) {
const downloadsInQueue = this.podcastManager.getEpisodeDownloadsInQueue(req.libraryItem.id)
item.episodeDownloadsQueued = downloadsInQueue.map(d => d.toJSONForClient())
item.episodeDownloadsQueued = downloadsInQueue.map((d) => d.toJSONForClient())
if (this.podcastManager.currentDownload?.libraryItemId === req.libraryItem.id) {
item.episodesDownloading = [this.podcastManager.currentDownload.toJSONForClient()]
}
@ -88,9 +93,9 @@ class LibraryItemController {
/**
* GET: /api/items/:id/download
* Download library item. Zip file if multiple files.
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
download(req, res) {
if (!req.user.canDownload) {
@ -120,9 +125,9 @@ class LibraryItemController {
/**
* PATCH: /items/:id/media
* Update media for a library item. Will create new authors & series when necessary
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async updateMedia(req, res) {
const libraryItem = req.libraryItem
@ -151,8 +156,8 @@ class LibraryItemController {
// Book specific - Get all series being removed from this item
let seriesRemoved = []
if (libraryItem.isBook && mediaPayload.metadata?.series) {
const seriesIdsInUpdate = mediaPayload.metadata.series?.map(se => se.id) || []
seriesRemoved = libraryItem.media.metadata.series.filter(se => !seriesIdsInUpdate.includes(se.id))
const seriesIdsInUpdate = mediaPayload.metadata.series?.map((se) => se.id) || []
seriesRemoved = libraryItem.media.metadata.series.filter((se) => !seriesIdsInUpdate.includes(se.id))
}
const hasUpdates = libraryItem.media.update(mediaPayload) || mediaPayload.url
@ -162,7 +167,10 @@ class LibraryItemController {
if (seriesRemoved.length) {
// Check remove empty series
Logger.debug(`[LibraryItemController] Series was removed from book. Check if series is now empty.`)
await this.checkRemoveEmptySeries(libraryItem.media.id, seriesRemoved.map(se => se.id))
await this.checkRemoveEmptySeries(
libraryItem.media.id,
seriesRemoved.map((se) => se.id)
)
}
if (isPodcastAutoDownloadUpdated) {
@ -252,12 +260,14 @@ class LibraryItemController {
/**
* GET: api/items/:id/cover
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async getCover(req, res) {
const { query: { width, height, format, raw } } = req
const {
query: { width, height, format, raw }
} = req
const libraryItem = await Database.libraryItemModel.findByPk(req.params.id, {
attributes: ['id', 'mediaType', 'mediaId', 'libraryId'],
@ -283,14 +293,14 @@ class LibraryItemController {
}
// Check if library item media has a cover path
if (!libraryItem.media.coverPath || !await fs.pathExists(libraryItem.media.coverPath)) {
if (!libraryItem.media.coverPath || !(await fs.pathExists(libraryItem.media.coverPath))) {
return res.sendStatus(404)
}
if (req.query.ts)
res.set('Cache-Control', 'private, max-age=86400')
if (req.query.ts) res.set('Cache-Control', 'private, max-age=86400')
if (raw) { // any value
if (raw) {
// any value
if (global.XAccel) {
const encodedURI = encodeUriPath(global.XAccel + libraryItem.media.coverPath)
Logger.debug(`Use X-Accel to serve static file ${encodedURI}`)
@ -325,7 +335,7 @@ class LibraryItemController {
return res.sendStatus(404)
}
var episodeId = req.params.episodeId
if (!libraryItem.media.episodes.find(ep => ep.id === episodeId)) {
if (!libraryItem.media.episodes.find((ep) => ep.id === episodeId)) {
Logger.error(`[LibraryItemController] startPlaybackSession episode ${episodeId} not found for item ${libraryItem.id}`)
return res.sendStatus(404)
}
@ -412,8 +422,8 @@ class LibraryItemController {
let seriesRemoved = []
if (libraryItem.isBook && mediaPayload.metadata?.series) {
const seriesIdsInUpdate = (mediaPayload.metadata?.series || []).map(se => se.id)
seriesRemoved = libraryItem.media.metadata.series.filter(se => !seriesIdsInUpdate.includes(se.id))
const seriesIdsInUpdate = (mediaPayload.metadata?.series || []).map((se) => se.id)
seriesRemoved = libraryItem.media.metadata.series.filter((se) => !seriesIdsInUpdate.includes(se.id))
}
if (libraryItem.media.update(mediaPayload)) {
@ -422,7 +432,10 @@ class LibraryItemController {
if (seriesRemoved.length) {
// Check remove empty series
Logger.debug(`[LibraryItemController] Series was removed from book. Check if series is now empty.`)
await this.checkRemoveEmptySeries(libraryItem.media.id, seriesRemoved.map(se => se.id))
await this.checkRemoveEmptySeries(
libraryItem.media.id,
seriesRemoved.map((se) => se.id)
)
}
await Database.updateLibraryItem(libraryItem)
@ -447,7 +460,7 @@ class LibraryItemController {
id: libraryItemIds
})
res.json({
libraryItems: libraryItems.map(li => li.toJSONExpanded())
libraryItems: libraryItems.map((li) => li.toJSONExpanded())
})
}
@ -542,7 +555,7 @@ class LibraryItemController {
const result = await LibraryItemScanner.scanLibraryItem(req.libraryItem.id)
await Database.resetLibraryIssuesFilterData(req.libraryItem.libraryId)
res.json({
result: Object.keys(ScanResult).find(key => ScanResult[key] == result)
result: Object.keys(ScanResult).find((key) => ScanResult[key] == result)
})
}
@ -593,9 +606,9 @@ class LibraryItemController {
/**
* GET api/items/:id/ffprobe/:fileid
* FFProbe JSON result from audio file
*
*
* @param {express.Request} req
* @param {express.Response} res
* @param {express.Response} res
*/
async getFFprobeData(req, res) {
if (!req.user.isAdminOrUp) {
@ -619,9 +632,9 @@ class LibraryItemController {
/**
* GET api/items/:id/file/:fileid
*
*
* @param {express.Request} req
* @param {express.Response} res
* @param {express.Response} res
*/
async getLibraryFile(req, res) {
const libraryFile = req.libraryFile
@ -642,9 +655,9 @@ class LibraryItemController {
/**
* DELETE api/items/:id/file/:fileid
*
*
* @param {express.Request} req
* @param {express.Response} res
* @param {express.Response} res
*/
async deleteLibraryFile(req, res) {
const libraryFile = req.libraryFile
@ -672,7 +685,7 @@ class LibraryItemController {
* GET api/items/:id/file/:fileid/download
* Same as GET api/items/:id/file/:fileid but allows logging and restricting downloads
* @param {express.Request} req
* @param {express.Response} res
* @param {express.Response} res
*/
async downloadLibraryFile(req, res) {
const libraryFile = req.libraryFile
@ -704,14 +717,14 @@ class LibraryItemController {
* fileid is the inode value stored in LibraryFile.ino or EBookFile.ino
* fileid is only required when reading a supplementary ebook
* when no fileid is passed in the primary ebook will be returned
*
*
* @param {express.Request} req
* @param {express.Response} res
* @param {express.Response} res
*/
async getEBookFile(req, res) {
let ebookFile = null
if (req.params.fileid) {
ebookFile = req.libraryItem.libraryFiles.find(lf => lf.ino === req.params.fileid)
ebookFile = req.libraryItem.libraryFiles.find((lf) => lf.ino === req.params.fileid)
if (!ebookFile?.isEBookFile) {
Logger.error(`[LibraryItemController] Invalid ebook file id "${req.params.fileid}"`)
return res.status(400).send('Invalid ebook file id')
@ -740,12 +753,12 @@ class LibraryItemController {
* toggle the status of an ebook file.
* if an ebook file is the primary ebook, then it will be changed to supplementary
* if an ebook file is supplementary, then it will be changed to primary
*
*
* @param {express.Request} req
* @param {express.Response} res
* @param {express.Response} res
*/
async updateEbookFileStatus(req, res) {
const ebookLibraryFile = req.libraryItem.libraryFiles.find(lf => lf.ino === req.params.fileid)
const ebookLibraryFile = req.libraryItem.libraryFiles.find((lf) => lf.ino === req.params.fileid)
if (!ebookLibraryFile?.isEBookFile) {
Logger.error(`[LibraryItemController] Invalid ebook file id "${req.params.fileid}"`)
return res.status(400).send('Invalid ebook file id')
@ -777,7 +790,7 @@ class LibraryItemController {
// For library file routes, get the library file
if (req.params.fileid) {
req.libraryFile = req.libraryItem.libraryFiles.find(lf => lf.ino === req.params.fileid)
req.libraryFile = req.libraryItem.libraryFiles.find((lf) => lf.ino === req.params.fileid)
if (!req.libraryFile) {
Logger.error(`[LibraryItemController] Library file "${req.params.fileid}" does not exist for library item`)
return res.sendStatus(404)
@ -797,4 +810,4 @@ class LibraryItemController {
next()
}
}
module.exports = new LibraryItemController()
module.exports = new LibraryItemController()

View File

@ -14,7 +14,6 @@ const CoverManager = require('../managers/CoverManager')
const LibraryItem = require('../objects/LibraryItem')
class PodcastController {
async create(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[PodcastController] Non-admin user "${req.user.username}" attempted to create podcast`)
@ -28,7 +27,7 @@ class PodcastController {
return res.status(404).send('Library not found')
}
const folder = library.folders.find(fold => fold.id === payload.folderId)
const folder = library.folders.find((fold) => fold.id === payload.folderId)
if (!folder) {
Logger.error(`[PodcastController] Create: Folder not found "${payload.folderId}"`)
return res.status(404).send('Folder not found')
@ -37,20 +36,24 @@ class PodcastController {
const podcastPath = filePathToPOSIX(payload.path)
// Check if a library item with this podcast folder exists already
const existingLibraryItem = (await Database.libraryItemModel.count({
where: {
path: podcastPath
}
})) > 0
const existingLibraryItem =
(await Database.libraryItemModel.count({
where: {
path: podcastPath
}
})) > 0
if (existingLibraryItem) {
Logger.error(`[PodcastController] Podcast already exists at path "${podcastPath}"`)
return res.status(400).send('Podcast already exists')
}
const success = await fs.ensureDir(podcastPath).then(() => true).catch((error) => {
Logger.error(`[PodcastController] Failed to ensure podcast dir "${podcastPath}"`, error)
return false
})
const success = await fs
.ensureDir(podcastPath)
.then(() => true)
.catch((error) => {
Logger.error(`[PodcastController] Failed to ensure podcast dir "${podcastPath}"`, error)
return false
})
if (!success) return res.status(400).send('Invalid podcast path')
const libraryItemFolderStats = await getFileTimestampsWithIno(podcastPath)
@ -105,12 +108,12 @@ class PodcastController {
/**
* POST: /api/podcasts/feed
*
*
* @typedef getPodcastFeedReqBody
* @property {string} rssFeed
*
* @param {import('express').Request<{}, {}, getPodcastFeedReqBody, {}} req
* @param {import('express').Response} res
*
* @param {import('express').Request<{}, {}, getPodcastFeedReqBody, {}} req
* @param {import('express').Response} res
*/
async getPodcastFeed(req, res) {
if (!req.user.isAdminOrUp) {
@ -178,7 +181,7 @@ class PodcastController {
var downloadsInQueue = this.podcastManager.getEpisodeDownloadsInQueue(libraryItem.id)
res.json({
downloads: downloadsInQueue.map(d => d.toJSONForClient())
downloads: downloadsInQueue.map((d) => d.toJSONForClient())
})
}
@ -189,8 +192,8 @@ class PodcastController {
return res.status(500).send('Podcast does not have an RSS feed URL')
}
var searchTitle = req.query.title
if (!searchTitle) {
const searchTitle = req.query.title
if (!searchTitle || typeof searchTitle !== 'string') {
return res.sendStatus(500)
}
const episodes = await findMatchingEpisodes(rssFeedUrl, searchTitle)
@ -254,7 +257,7 @@ class PodcastController {
const episodeId = req.params.episodeId
const libraryItem = req.libraryItem
const episode = libraryItem.media.episodes.find(ep => ep.id === episodeId)
const episode = libraryItem.media.episodes.find((ep) => ep.id === episodeId)
if (!episode) {
Logger.error(`[PodcastController] getEpisode episode ${episodeId} not found for item ${libraryItem.id}`)
return res.sendStatus(404)
@ -269,7 +272,7 @@ class PodcastController {
const libraryItem = req.libraryItem
const hardDelete = req.query.hard === '1'
const episode = libraryItem.media.episodes.find(ep => ep.id === episodeId)
const episode = libraryItem.media.episodes.find((ep) => ep.id === episodeId)
if (!episode) {
Logger.error(`[PodcastController] removeEpisode episode ${episodeId} not found for item ${libraryItem.id}`)
return res.sendStatus(404)
@ -278,11 +281,14 @@ class PodcastController {
if (hardDelete) {
const audioFile = episode.audioFile
// TODO: this will trigger the watcher. should maybe handle this gracefully
await fs.remove(audioFile.metadata.path).then(() => {
Logger.info(`[PodcastController] Hard deleted episode file at "${audioFile.metadata.path}"`)
}).catch((error) => {
Logger.error(`[PodcastController] Failed to hard delete episode file at "${audioFile.metadata.path}"`, error)
})
await fs
.remove(audioFile.metadata.path)
.then(() => {
Logger.info(`[PodcastController] Hard deleted episode file at "${audioFile.metadata.path}"`)
})
.catch((error) => {
Logger.error(`[PodcastController] Failed to hard delete episode file at "${audioFile.metadata.path}"`, error)
})
}
// Remove episode from Podcast and library file

View File

@ -1,12 +1,13 @@
const Logger = require("../Logger")
const Logger = require('../Logger')
const BookFinder = require('../finders/BookFinder')
const PodcastFinder = require('../finders/PodcastFinder')
const AuthorFinder = require('../finders/AuthorFinder')
const MusicFinder = require('../finders/MusicFinder')
const Database = require("../Database")
const Database = require('../Database')
const { isValidASIN } = require('../utils')
class SearchController {
constructor() { }
constructor() {}
async findBooks(req, res) {
const id = req.query.id
@ -37,9 +38,9 @@ class SearchController {
/**
* Find podcast RSS feeds given a term
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async findPodcasts(req, res) {
const term = req.query.term
@ -63,6 +64,9 @@ class SearchController {
async findChapters(req, res) {
const asin = req.query.asin
if (!isValidASIN(asin.toUpperCase())) {
return res.json({ error: 'Invalid ASIN' })
}
const region = (req.query.region || 'us').toLowerCase()
const chapterData = await BookFinder.findChapters(asin, region)
if (!chapterData) {
@ -78,4 +82,4 @@ class SearchController {
})
}
}
module.exports = new SearchController()
module.exports = new SearchController()

View File

@ -0,0 +1,138 @@
const { Op } = require('sequelize')
const Logger = require('../Logger')
const Database = require('../Database')
const ShareManager = require('../managers/ShareManager')
class ShareController {
constructor() {}
/**
* Public route
* GET: /api/share/mediaitem/:slug
* Get media item share by slug
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async getMediaItemShareBySlug(req, res) {
const { slug } = req.params
const mediaItemShare = ShareManager.findBySlug(slug)
if (!mediaItemShare) {
return res.status(404)
}
if (mediaItemShare.expiresAt && mediaItemShare.expiresAt.valueOf() < Date.now()) {
ShareManager.removeMediaItemShare(mediaItemShare.id)
return res.status(404).send('Media item share not found')
}
try {
const mediaItemModel = mediaItemShare.mediaItemType === 'book' ? Database.bookModel : Database.podcastEpisodeModel
mediaItemShare.mediaItem = await mediaItemModel.findByPk(mediaItemShare.mediaItemId)
if (!mediaItemShare.mediaItem) {
return res.status(404).send('Media item not found')
}
res.json(mediaItemShare)
} catch (error) {
Logger.error(`[ShareController] Failed`, error)
res.status(500).send('Internal server error')
}
}
/**
* POST: /api/share/mediaitem
* Create a new media item share
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async createMediaItemShare(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[ShareController] Non-admin user "${req.user.username}" attempted to create item share`)
return res.sendStatus(403)
}
const { slug, expiresAt, mediaItemType, mediaItemId } = req.body
if (!slug?.trim?.() || typeof mediaItemType !== 'string' || typeof mediaItemId !== 'string') {
return res.status(400).send('Missing or invalid required fields')
}
if (expiresAt === null || isNaN(expiresAt) || expiresAt < 0) {
return res.status(400).send('Invalid expiration date')
}
if (!['book', 'podcastEpisode'].includes(mediaItemType)) {
return res.status(400).send('Invalid media item type')
}
try {
// Check if the media item share already exists by slug or mediaItemId
const existingMediaItemShare = await Database.models.mediaItemShare.findOne({
where: {
[Op.or]: [{ slug }, { mediaItemId }]
}
})
if (existingMediaItemShare) {
if (existingMediaItemShare.mediaItemId === mediaItemId) {
return res.status(409).send('Item is already shared')
} else {
return res.status(409).send('Slug is already in use')
}
}
// Check that media item exists
const mediaItemModel = mediaItemType === 'book' ? Database.bookModel : Database.podcastEpisodeModel
const mediaItem = await mediaItemModel.findByPk(mediaItemId)
if (!mediaItem) {
return res.status(404).send('Media item not found')
}
const mediaItemShare = await Database.models.mediaItemShare.create({
slug,
expiresAt: expiresAt || null,
mediaItemId,
mediaItemType,
userId: req.user.id
})
ShareManager.openMediaItemShare(mediaItemShare)
res.status(201).json(mediaItemShare?.toJSONForClient())
} catch (error) {
Logger.error(`[ShareController] Failed`, error)
res.status(500).send('Internal server error')
}
}
/**
* DELETE: /api/share/mediaitem/:id
* Delete media item share
*
* @param {import('express').Request} req
* @param {import('express').Response} res
*/
async deleteMediaItemShare(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[ShareController] Non-admin user "${req.user.username}" attempted to delete item share`)
return res.sendStatus(403)
}
try {
const mediaItemShare = await Database.models.mediaItemShare.findByPk(req.params.id)
if (!mediaItemShare) {
return res.status(404).send('Media item share not found')
}
ShareManager.removeMediaItemShare(mediaItemShare.id)
await mediaItemShare.destroy()
res.sendStatus(204)
} catch (error) {
Logger.error(`[ShareController] Failed`, error)
res.status(500).send('Internal server error')
}
}
}
module.exports = new ShareController()

View File

@ -15,7 +15,7 @@ var ffCodecRegexp = /^\s*([D\.])([E\.])([VAS])([I\.])([L\.])([S\.]) ([^ ]+) +(.*
var ffEncodersRegexp = /\(encoders:([^\)]+)\)/;
var ffDecodersRegexp = /\(decoders:([^\)]+)\)/;
var encodersRegexp = /^\s*([VAS\.])([F\.])([S\.])([X\.])([B\.])([D\.]) ([^ ]+) +(.*)$/;
var formatRegexp = /^\s*([D ])([E ]) ([^ ]+) +(.*)$/;
var formatRegexp = /^\s*([D ])([E ])\s+([^ ]+)\s+(.*)$/;
var lineBreakRegexp = /\r\n|\r|\n/;
var filterRegexp = /^(?: [T\.][S\.][C\.] )?([^ ]+) +(AA?|VV?|\|)->(AA?|VV?|\|) +(.*)$/;

View File

@ -17,7 +17,6 @@ const Backup = require('../objects/Backup')
class BackupManager {
constructor() {
this.BackupPath = Path.join(global.MetadataPath, 'backups')
this.ItemsMetadataPath = Path.join(global.MetadataPath, 'items')
this.AuthorsMetadataPath = Path.join(global.MetadataPath, 'authors')
@ -26,8 +25,8 @@ class BackupManager {
this.backups = []
}
get backupLocation() {
return this.BackupPath
get backupPath() {
return global.ServerSettings.backupPath
}
get backupSchedule() {
@ -43,15 +42,25 @@ class BackupManager {
}
async init() {
const backupsDirExists = await fs.pathExists(this.BackupPath)
const backupsDirExists = await fs.pathExists(this.backupPath)
if (!backupsDirExists) {
await fs.ensureDir(this.BackupPath)
await fs.ensureDir(this.backupPath)
}
await this.loadBackups()
this.scheduleCron()
}
/**
* Reload backups after updating backup path
*/
async reload() {
Logger.info(`[BackupManager] Reloading backups with backup path "${this.backupPath}"`)
this.backups = []
await this.loadBackups()
this.updateCronSchedule()
}
scheduleCron() {
if (!this.backupSchedule) {
Logger.info(`[BackupManager] Auto Backups are disabled`)
@ -87,11 +96,14 @@ class BackupManager {
return res.status(500).send('Invalid backup file')
}
const tempPath = Path.join(this.BackupPath, fileUtils.sanitizeFilename(backupFile.name))
const success = await backupFile.mv(tempPath).then(() => true).catch((error) => {
Logger.error('[BackupManager] Failed to move backup file', path, error)
return false
})
const tempPath = Path.join(this.backupPath, fileUtils.sanitizeFilename(backupFile.name))
const success = await backupFile
.mv(tempPath)
.then(() => true)
.catch((error) => {
Logger.error('[BackupManager] Failed to move backup file', path, error)
return false
})
if (!success) {
return res.status(500).send('Failed to move backup file into backups directory')
}
@ -122,7 +134,7 @@ class BackupManager {
backup.fileSize = await getFileSize(backup.fullPath)
const existingBackupIndex = this.backups.findIndex(b => b.id === backup.id)
const existingBackupIndex = this.backups.findIndex((b) => b.id === backup.id)
if (existingBackupIndex >= 0) {
Logger.warn(`[BackupManager] Backup already exists with id ${backup.id} - overwriting`)
this.backups.splice(existingBackupIndex, 1, backup)
@ -131,7 +143,7 @@ class BackupManager {
}
res.json({
backups: this.backups.map(b => b.toJSON())
backups: this.backups.map((b) => b.toJSON())
})
}
@ -139,7 +151,7 @@ class BackupManager {
var backupSuccess = await this.runBackup()
if (backupSuccess) {
res.json({
backups: this.backups.map(b => b.toJSON())
backups: this.backups.map((b) => b.toJSON())
})
} else {
res.sendStatus(500)
@ -147,10 +159,10 @@ class BackupManager {
}
/**
*
* @param {import('./ApiCacheManager')} apiCacheManager
* @param {Backup} backup
* @param {import('express').Response} res
*
* @param {import('./ApiCacheManager')} apiCacheManager
* @param {Backup} backup
* @param {import('express').Response} res
*/
async requestApplyBackup(apiCacheManager, backup, res) {
Logger.info(`[BackupManager] Applying backup at "${backup.fullPath}"`)
@ -176,7 +188,7 @@ class BackupManager {
Logger.info(`[BackupManager] Extracted backup sqlite db to temp path ${tempDbPath}`)
// Verify extract - Abandon backup if sqlite file did not extract
if (!await fs.pathExists(tempDbPath)) {
if (!(await fs.pathExists(tempDbPath))) {
Logger.error(`[BackupManager] Sqlite file not found after extract - abandon backup apply and reconnect db`)
await zip.close()
await Database.reconnect()
@ -218,12 +230,12 @@ class BackupManager {
async loadBackups() {
try {
const filesInDir = await fs.readdir(this.BackupPath)
const filesInDir = await fs.readdir(this.backupPath)
for (let i = 0; i < filesInDir.length; i++) {
const filename = filesInDir[i]
if (filename.endsWith('.audiobookshelf')) {
const fullFilePath = Path.join(this.BackupPath, filename)
const fullFilePath = Path.join(this.backupPath, filename)
let zip = null
let data = null
@ -239,14 +251,16 @@ class BackupManager {
const backup = new Backup({ details, fullPath: fullFilePath })
if (!backup.serverVersion) { // Backups before v2
if (!backup.serverVersion) {
// Backups before v2
Logger.error(`[BackupManager] Old unsupported backup was found "${backup.filename}"`)
} else if (!backup.key) { // Backups before sqlite migration
} else if (!backup.key) {
// Backups before sqlite migration
Logger.warn(`[BackupManager] Old unsupported backup was found "${backup.filename}" (pre sqlite migration)`)
}
backup.fileSize = await getFileSize(backup.fullPath)
const existingBackupWithId = this.backups.find(b => b.id === backup.id)
const existingBackupWithId = this.backups.find((b) => b.id === backup.id)
if (existingBackupWithId) {
Logger.warn(`[BackupManager] Backup already loaded with id ${backup.id} - ignoring`)
} else {
@ -267,7 +281,7 @@ class BackupManager {
// Check if Metadata Path is inside Config Path (otherwise there will be an infinite loop as the archiver tries to zip itself)
Logger.info(`[BackupManager] Running Backup`)
const newBackup = new Backup()
newBackup.setData(this.BackupPath)
newBackup.setData(this.backupPath)
await fs.ensureDir(this.AuthorsMetadataPath)
@ -296,7 +310,7 @@ class BackupManager {
newBackup.fileSize = await getFileSize(newBackup.fullPath)
const existingIndex = this.backups.findIndex(b => b.id === newBackup.id)
const existingIndex = this.backups.findIndex((b) => b.id === newBackup.id)
if (existingIndex >= 0) {
this.backups.splice(existingIndex, 1, newBackup)
} else {
@ -318,7 +332,7 @@ class BackupManager {
try {
Logger.debug(`[BackupManager] Removing Backup "${backup.fullPath}"`)
await fs.remove(backup.fullPath)
this.backups = this.backups.filter(b => b.id !== backup.id)
this.backups = this.backups.filter((b) => b.id !== backup.id)
Logger.info(`[BackupManager] Backup "${backup.id}" Removed`)
} catch (error) {
Logger.error(`[BackupManager] Failed to remove backup`, error)
@ -425,4 +439,4 @@ class BackupManager {
})
}
}
module.exports = BackupManager
module.exports = BackupManager

View File

@ -16,7 +16,7 @@ class CronManager {
/**
* Initialize library scan crons & podcast download crons
* @param {oldLibrary[]} libraries
* @param {import('../objects/Library')[]} libraries
*/
async init(libraries) {
this.initLibraryScanCrons(libraries)
@ -25,7 +25,7 @@ class CronManager {
/**
* Initialize library scan crons
* @param {oldLibrary[]} libraries
* @param {import('../objects/Library')[]} libraries
*/
initLibraryScanCrons(libraries) {
for (const library of libraries) {
@ -35,27 +35,37 @@ class CronManager {
}
}
startCronForLibrary(library) {
Logger.debug(`[CronManager] Init library scan cron for ${library.name} on schedule ${library.settings.autoScanCronExpression}`)
const libScanCron = cron.schedule(library.settings.autoScanCronExpression, () => {
Logger.debug(`[CronManager] Library scan cron executing for ${library.name}`)
LibraryScanner.scan(library)
/**
* Start cron schedule for library
*
* @param {import('../objects/Library')} _library
*/
startCronForLibrary(_library) {
Logger.debug(`[CronManager] Init library scan cron for ${_library.name} on schedule ${_library.settings.autoScanCronExpression}`)
const libScanCron = cron.schedule(_library.settings.autoScanCronExpression, async () => {
const library = await Database.libraryModel.getOldById(_library.id)
if (!library) {
Logger.error(`[CronManager] Library not found for scan cron ${_library.id}`)
} else {
Logger.debug(`[CronManager] Library scan cron executing for ${library.name}`)
LibraryScanner.scan(library)
}
})
this.libraryScanCrons.push({
libraryId: library.id,
expression: library.settings.autoScanCronExpression,
libraryId: _library.id,
expression: _library.settings.autoScanCronExpression,
task: libScanCron
})
}
removeCronForLibrary(library) {
Logger.debug(`[CronManager] Removing library scan cron for ${library.name}`)
this.libraryScanCrons = this.libraryScanCrons.filter(lsc => lsc.libraryId !== library.id)
this.libraryScanCrons = this.libraryScanCrons.filter((lsc) => lsc.libraryId !== library.id)
}
updateLibraryScanCron(library) {
const expression = library.settings.autoScanCronExpression
const existingCron = this.libraryScanCrons.find(lsc => lsc.libraryId === library.id)
const existingCron = this.libraryScanCrons.find((lsc) => lsc.libraryId === library.id)
if (!expression && existingCron) {
if (existingCron.task.stop) existingCron.task.stop()
@ -128,7 +138,7 @@ class CronManager {
}
async executePodcastCron(expression) {
const podcastCron = this.podcastCrons.find(cron => cron.expression === expression)
const podcastCron = this.podcastCrons.find((cron) => cron.expression === expression)
if (!podcastCron) {
Logger.error(`[CronManager] Podcast cron not found for expression ${expression}`)
return
@ -144,7 +154,7 @@ class CronManager {
const libraryItem = await Database.libraryItemModel.getOldById(libraryItemId)
if (!libraryItem) {
Logger.error(`[CronManager] Library item ${libraryItemId} not found for episode check cron ${expression}`)
podcastCron.libraryItemIds = podcastCron.libraryItemIds.filter(lid => lid !== libraryItemId) // Filter it out
podcastCron.libraryItemIds = podcastCron.libraryItemIds.filter((lid) => lid !== libraryItemId) // Filter it out
} else {
libraryItems.push(libraryItem)
}
@ -153,8 +163,9 @@ class CronManager {
// Run episode checks
for (const libraryItem of libraryItems) {
const keepAutoDownloading = await this.podcastManager.runEpisodeCheck(libraryItem)
if (!keepAutoDownloading) { // auto download was disabled
podcastCron.libraryItemIds = podcastCron.libraryItemIds.filter(lid => lid !== libraryItem.id) // Filter it out
if (!keepAutoDownloading) {
// auto download was disabled
podcastCron.libraryItemIds = podcastCron.libraryItemIds.filter((lid) => lid !== libraryItem.id) // Filter it out
}
}
@ -165,20 +176,20 @@ class CronManager {
}
Logger.debug(`[CronManager] Finished executing podcast cron ${expression} for ${libraryItems.length} item(s)`)
this.podcastCronExpressionsExecuting = this.podcastCronExpressionsExecuting.filter(exp => exp !== expression)
this.podcastCronExpressionsExecuting = this.podcastCronExpressionsExecuting.filter((exp) => exp !== expression)
}
removePodcastEpisodeCron(podcastCron) {
Logger.info(`[CronManager] Stopping & removing podcast episode cron for ${podcastCron.expression}`)
if (podcastCron.task) podcastCron.task.stop()
this.podcastCrons = this.podcastCrons.filter(pc => pc.expression !== podcastCron.expression)
this.podcastCrons = this.podcastCrons.filter((pc) => pc.expression !== podcastCron.expression)
}
checkUpdatePodcastCron(libraryItem) {
// Remove from old cron by library item id
const existingCron = this.podcastCrons.find(pc => pc.libraryItemIds.includes(libraryItem.id))
const existingCron = this.podcastCrons.find((pc) => pc.libraryItemIds.includes(libraryItem.id))
if (existingCron) {
existingCron.libraryItemIds = existingCron.libraryItemIds.filter(lid => lid !== libraryItem.id)
existingCron.libraryItemIds = existingCron.libraryItemIds.filter((lid) => lid !== libraryItem.id)
if (!existingCron.libraryItemIds.length) {
this.removePodcastEpisodeCron(existingCron)
}
@ -186,7 +197,7 @@ class CronManager {
// Add to cron or start new cron
if (libraryItem.media.autoDownloadEpisodes && libraryItem.media.autoDownloadSchedule) {
const cronMatchingExpression = this.podcastCrons.find(pc => pc.expression === libraryItem.media.autoDownloadSchedule)
const cronMatchingExpression = this.podcastCrons.find((pc) => pc.expression === libraryItem.media.autoDownloadSchedule)
if (cronMatchingExpression) {
cronMatchingExpression.libraryItemIds.push(libraryItem.id)
Logger.info(`[CronManager] Added podcast "${libraryItem.media.metadata.title}" to auto dl episode cron "${cronMatchingExpression.expression}"`)
@ -196,4 +207,4 @@ class CronManager {
}
}
}
module.exports = CronManager
module.exports = CronManager

View File

@ -1,4 +1,4 @@
const uuidv4 = require("uuid").v4
const uuidv4 = require('uuid').v4
const Path = require('path')
const serverVersion = require('../../package.json').version
const Logger = require('../Logger')
@ -25,10 +25,10 @@ class PlaybackSessionManager {
}
getSession(sessionId) {
return this.sessions.find(s => s.id === sessionId)
return this.sessions.find((s) => s.id === sessionId)
}
getUserSession(userId) {
return this.sessions.find(s => s.userId === userId)
return this.sessions.find((s) => s.userId === userId)
}
getStream(sessionId) {
const session = this.getSession(sessionId)
@ -59,6 +59,12 @@ class PlaybackSessionManager {
return deviceInfo
}
/**
*
* @param {import('express').Request} req
* @param {import('express').Response} res
* @param {string} [episodeId]
*/
async startSessionRequest(req, res, episodeId) {
const deviceInfo = await this.getDeviceInfo(req)
Logger.debug(`[PlaybackSessionManager] startSessionRequest for device ${deviceInfo.deviceDescription}`)
@ -94,7 +100,7 @@ class PlaybackSessionManager {
async syncLocalSession(user, sessionJson, deviceInfo) {
const libraryItem = await Database.libraryItemModel.getOldById(sessionJson.libraryItemId)
const episode = (sessionJson.episodeId && libraryItem && libraryItem.isPodcast) ? libraryItem.media.getEpisode(sessionJson.episodeId) : null
const episode = sessionJson.episodeId && libraryItem && libraryItem.isPodcast ? libraryItem.media.getEpisode(sessionJson.episodeId) : null
if (!libraryItem || (libraryItem.isPodcast && !episode)) {
Logger.error(`[PlaybackSessionManager] syncLocalSession: Media item not found for session "${sessionJson.displayTitle}" (${sessionJson.id})`)
return {
@ -178,13 +184,15 @@ class PlaybackSessionManager {
// Update user and emit socket event
if (result.progressSynced) {
const itemProgress = user.getMediaProgress(session.libraryItemId, session.episodeId)
if (itemProgress) await Database.upsertMediaProgress(itemProgress)
SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', {
id: itemProgress.id,
sessionId: session.id,
deviceDescription: session.deviceDescription,
data: itemProgress.toJSON()
})
if (itemProgress) {
await Database.upsertMediaProgress(itemProgress)
SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', {
id: itemProgress.id,
sessionId: session.id,
deviceDescription: session.deviceDescription,
data: itemProgress.toJSON()
})
}
}
return result
@ -207,9 +215,18 @@ class PlaybackSessionManager {
res.sendStatus(200)
}
/**
*
* @param {import('../objects/user/User')} user
* @param {DeviceInfo} deviceInfo
* @param {import('../objects/LibraryItem')} libraryItem
* @param {string|null} episodeId
* @param {{forceDirectPlay?:boolean, forceTranscode?:boolean, mediaPlayer:string, supportedMimeTypes?:string[]}} options
* @returns {Promise<PlaybackSession>}
*/
async startSession(user, deviceInfo, libraryItem, episodeId, options) {
// Close any sessions already open for user and device
const userSessions = this.sessions.filter(playbackSession => playbackSession.userId === user.id && playbackSession.deviceId === deviceInfo.id)
const userSessions = this.sessions.filter((playbackSession) => playbackSession.userId === user.id && playbackSession.deviceId === deviceInfo.id)
for (const session of userSessions) {
Logger.info(`[PlaybackSessionManager] startSession: Closing open session "${session.displayTitle}" for user "${user.username}" (Device: ${session.deviceDescription})`)
await this.closeSession(user, session, null)
@ -229,7 +246,7 @@ class PlaybackSessionManager {
}
}
const newPlaybackSession = new PlaybackSession()
newPlaybackSession.setData(libraryItem, user, mediaPlayer, deviceInfo, userStartTime, episodeId)
newPlaybackSession.setData(libraryItem, user.id, mediaPlayer, deviceInfo, userStartTime, episodeId)
if (libraryItem.mediaType === 'video') {
if (shouldDirectPlay) {
@ -326,12 +343,12 @@ class PlaybackSessionManager {
}
async removeSession(sessionId) {
const session = this.sessions.find(s => s.id === sessionId)
const session = this.sessions.find((s) => s.id === sessionId)
if (!session) return
if (session.stream) {
await session.stream.close()
}
this.sessions = this.sessions.filter(s => s.id !== sessionId)
this.sessions = this.sessions.filter((s) => s.id !== sessionId)
Logger.debug(`[PlaybackSessionManager] Removed session "${sessionId}"`)
}
@ -343,8 +360,9 @@ class PlaybackSessionManager {
try {
const streamsInPath = await fs.readdir(this.StreamsPath)
for (const streamId of streamsInPath) {
if (/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/.test(streamId)) { // Ensure is uuidv4
const session = this.sessions.find(se => se.id === streamId)
if (/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/.test(streamId)) {
// Ensure is uuidv4
const session = this.sessions.find((se) => se.id === streamId)
if (!session) {
const streamPath = Path.join(this.StreamsPath, streamId)
Logger.debug(`[PlaybackSessionManager] Removing orphan stream "${streamPath}"`)

View File

@ -0,0 +1,137 @@
const Database = require('../Database')
const Logger = require('../Logger')
/**
* @typedef OpenMediaItemShareObject
* @property {string} id
* @property {import('../models/MediaItemShare').MediaItemShareObject} mediaItemShare
* @property {NodeJS.Timeout} timeout
*/
class ShareManager {
constructor() {
/** @type {OpenMediaItemShareObject[]} */
this.openMediaItemShares = []
}
init() {
this.loadMediaItemShares()
}
/**
* Find an open media item share by media item ID
* @param {string} mediaItemId
* @returns {import('../models/MediaItemShare').MediaItemShareForClient}
*/
findByMediaItemId(mediaItemId) {
const mediaItemShareObject = this.openMediaItemShares.find((s) => s.mediaItemShare.mediaItemId === mediaItemId)?.mediaItemShare
if (mediaItemShareObject) {
const mediaItemShareObjectForClient = { ...mediaItemShareObject }
delete mediaItemShareObjectForClient.pash
delete mediaItemShareObjectForClient.userId
delete mediaItemShareObjectForClient.extraData
return mediaItemShareObjectForClient
}
return null
}
/**
* Find an open media item share by slug
* @param {string} slug
* @returns {import('../models/MediaItemShare').MediaItemShareForClient}
*/
findBySlug(slug) {
const mediaItemShareObject = this.openMediaItemShares.find((s) => s.mediaItemShare.slug === slug)?.mediaItemShare
if (mediaItemShareObject) {
const mediaItemShareObjectForClient = { ...mediaItemShareObject }
delete mediaItemShareObjectForClient.pash
delete mediaItemShareObjectForClient.userId
delete mediaItemShareObjectForClient.extraData
return mediaItemShareObjectForClient
}
return null
}
/**
* Load all media item shares from the database
* Remove expired & schedule active
*/
async loadMediaItemShares() {
/** @type {import('../models/MediaItemShare').MediaItemShareModel[]} */
const mediaItemShares = await Database.models.mediaItemShare.findAll()
for (const mediaItemShare of mediaItemShares) {
if (mediaItemShare.expiresAt && mediaItemShare.expiresAt.valueOf() < Date.now()) {
Logger.info(`[ShareManager] Removing expired media item share "${mediaItemShare.id}"`)
await this.destroyMediaItemShare(mediaItemShare.id)
} else if (mediaItemShare.expiresAt) {
this.scheduleMediaItemShare(mediaItemShare)
} else {
Logger.info(`[ShareManager] Loaded permanent media item share "${mediaItemShare.id}"`)
this.openMediaItemShares.push({
id: mediaItemShare.id,
mediaItemShare: mediaItemShare.toJSON()
})
}
}
}
/**
*
* @param {import('../models/MediaItemShare').MediaItemShareModel} mediaItemShare
*/
scheduleMediaItemShare(mediaItemShare) {
if (!mediaItemShare?.expiresAt) return
const expiresAtDuration = mediaItemShare.expiresAt.valueOf() - Date.now()
if (expiresAtDuration <= 0) {
Logger.warn(`[ShareManager] Attempted to schedule expired media item share "${mediaItemShare.id}"`)
this.destroyMediaItemShare(mediaItemShare.id)
return
}
const timeout = setTimeout(() => {
Logger.info(`[ShareManager] Removing expired media item share "${mediaItemShare.id}"`)
this.removeMediaItemShare(mediaItemShare.id)
}, expiresAtDuration)
this.openMediaItemShares.push({ id: mediaItemShare.id, mediaItemShare: mediaItemShare.toJSON(), timeout })
Logger.info(`[ShareManager] Scheduled media item share "${mediaItemShare.id}" to expire in ${expiresAtDuration}ms`)
}
/**
*
* @param {import('../models/MediaItemShare').MediaItemShareModel} mediaItemShare
*/
openMediaItemShare(mediaItemShare) {
if (mediaItemShare.expiresAt) {
this.scheduleMediaItemShare(mediaItemShare)
} else {
this.openMediaItemShares.push({ id: mediaItemShare.id, mediaItemShare: mediaItemShare.toJSON() })
}
}
/**
*
* @param {string} mediaItemShareId
*/
async removeMediaItemShare(mediaItemShareId) {
const mediaItemShare = this.openMediaItemShares.find((s) => s.id === mediaItemShareId)
if (!mediaItemShare) return
if (mediaItemShare.timeout) {
clearTimeout(mediaItemShare.timeout)
}
this.openMediaItemShares = this.openMediaItemShares.filter((s) => s.id !== mediaItemShareId)
await this.destroyMediaItemShare(mediaItemShareId)
}
/**
*
* @param {string} mediaItemShareId
*/
destroyMediaItemShare(mediaItemShareId) {
return Database.models.mediaItemShare.destroy({ where: { id: mediaItemShareId } })
}
}
module.exports = new ShareManager()

View File

@ -0,0 +1,130 @@
const { DataTypes, Model } = require('sequelize')
/**
* @typedef MediaItemShareObject
* @property {UUIDV4} id
* @property {UUIDV4} mediaItemId
* @property {string} mediaItemType
* @property {string} slug
* @property {string} pash
* @property {UUIDV4} userId
* @property {Date} expiresAt
* @property {Object} extraData
* @property {Date} createdAt
* @property {Date} updatedAt
*
* @typedef {MediaItemShareObject & MediaItemShare} MediaItemShareModel
*/
/**
* @typedef MediaItemShareForClient
* @property {UUIDV4} id
* @property {UUIDV4} mediaItemId
* @property {string} mediaItemType
* @property {string} slug
* @property {Date} expiresAt
* @property {Date} createdAt
* @property {Date} updatedAt
*/
class MediaItemShare extends Model {
constructor(values, options) {
super(values, options)
}
toJSONForClient() {
return {
id: this.id,
mediaItemId: this.mediaItemId,
mediaItemType: this.mediaItemType,
slug: this.slug,
expiresAt: this.expiresAt,
createdAt: this.createdAt,
updatedAt: this.updatedAt
}
}
/**
*
* @param {import('sequelize').FindOptions} options
* @returns {Promise<import('./Book')|import('./PodcastEpisode')>}
*/
getMediaItem(options) {
if (!this.mediaItemType) return Promise.resolve(null)
const mixinMethodName = `get${this.sequelize.uppercaseFirst(this.mediaItemType)}`
return this[mixinMethodName](options)
}
/**
* Initialize model
*
* @param {import('../Database').sequelize} sequelize
*/
static init(sequelize) {
super.init(
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
mediaItemId: DataTypes.UUIDV4,
mediaItemType: DataTypes.STRING,
slug: DataTypes.STRING,
pash: DataTypes.STRING,
expiresAt: DataTypes.DATE,
extraData: DataTypes.JSON
},
{
sequelize,
modelName: 'mediaItemShare'
}
)
const { user, book, podcastEpisode } = sequelize.models
user.hasMany(MediaItemShare)
MediaItemShare.belongsTo(user)
book.hasMany(MediaItemShare, {
foreignKey: 'mediaItemId',
constraints: false,
scope: {
mediaItemType: 'book'
}
})
MediaItemShare.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false })
podcastEpisode.hasOne(MediaItemShare, {
foreignKey: 'mediaItemId',
constraints: false,
scope: {
mediaItemType: 'podcastEpisode'
}
})
MediaItemShare.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false })
MediaItemShare.addHook('afterFind', (findResult) => {
if (!findResult) return
if (!Array.isArray(findResult)) findResult = [findResult]
for (const instance of findResult) {
if (instance.mediaItemType === 'book' && instance.book !== undefined) {
instance.mediaItem = instance.book
instance.dataValues.mediaItem = instance.dataValues.book
} else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) {
instance.mediaItem = instance.podcastEpisode
instance.dataValues.mediaItem = instance.dataValues.podcastEpisode
}
// To prevent mistakes:
delete instance.book
delete instance.dataValues.book
delete instance.podcastEpisode
delete instance.dataValues.podcastEpisode
}
})
}
}
module.exports = MediaItemShare

View File

@ -1,5 +1,5 @@
const date = require('../libs/dateAndTime')
const uuidv4 = require("uuid").v4
const uuidv4 = require('uuid').v4
const serverVersion = require('../../package.json').version
const BookMetadata = require('./metadata/BookMetadata')
const PodcastMetadata = require('./metadata/PodcastMetadata')
@ -59,7 +59,7 @@ class PlaybackSession {
episodeId: this.episodeId,
mediaType: this.mediaType,
mediaMetadata: this.mediaMetadata?.toJSON() || null,
chapters: (this.chapters || []).map(c => ({ ...c })),
chapters: (this.chapters || []).map((c) => ({ ...c })),
displayTitle: this.displayTitle,
displayAuthor: this.displayAuthor,
coverPath: this.coverPath,
@ -93,7 +93,7 @@ class PlaybackSession {
episodeId: this.episodeId,
mediaType: this.mediaType,
mediaMetadata: this.mediaMetadata?.toJSON() || null,
chapters: (this.chapters || []).map(c => ({ ...c })),
chapters: (this.chapters || []).map((c) => ({ ...c })),
displayTitle: this.displayTitle,
displayAuthor: this.displayAuthor,
coverPath: this.coverPath,
@ -109,7 +109,7 @@ class PlaybackSession {
currentTime: this.currentTime,
startedAt: this.startedAt,
updatedAt: this.updatedAt,
audioTracks: this.audioTracks.map(at => at.toJSON()),
audioTracks: this.audioTracks.map((at) => at.toJSON()),
videoTrack: this.videoTrack?.toJSON() || null,
libraryItem: libraryItem?.toJSONExpanded() || null
}
@ -182,7 +182,8 @@ class PlaybackSession {
return this.libraryItemId
}
get progress() { // Value between 0 and 1
get progress() {
// Value between 0 and 1
if (!this.duration) return 0
return Math.max(0, Math.min(this.currentTime / this.duration, 1))
}
@ -205,9 +206,9 @@ class PlaybackSession {
}
}
setData(libraryItem, user, mediaPlayer, deviceInfo, startTime, episodeId = null) {
setData(libraryItem, userId, mediaPlayer, deviceInfo, startTime, episodeId = null) {
this.id = uuidv4()
this.userId = user.id
this.userId = userId
this.libraryId = libraryItem.libraryId
this.libraryItemId = libraryItem.id
this.bookId = episodeId ? null : libraryItem.media.id
@ -258,4 +259,4 @@ class PlaybackSession {
return date.format(new Date(), 'YYYY-MM-DD') !== this.date
}
}
module.exports = PlaybackSession
module.exports = PlaybackSession

View File

@ -1,3 +1,4 @@
const Path = require('path')
const packageJson = require('../../../package.json')
const { BookshelfView } = require('../../utils/constants')
const Logger = require('../../Logger')
@ -25,6 +26,7 @@ class ServerSettings {
this.rateLimitLoginWindow = 10 * 60 * 1000 // 10 Minutes
// Backups
this.backupPath = Path.join(global.MetadataPath, 'backups')
this.backupSchedule = false // If false then auto-backups are disabled
this.backupsToKeep = 2
this.maxBackupSize = 1
@ -97,6 +99,7 @@ class ServerSettings {
this.rateLimitLoginRequests = !isNaN(settings.rateLimitLoginRequests) ? Number(settings.rateLimitLoginRequests) : 10
this.rateLimitLoginWindow = !isNaN(settings.rateLimitLoginWindow) ? Number(settings.rateLimitLoginWindow) : 10 * 60 * 1000 // 10 Minutes
this.backupPath = settings.backupPath || Path.join(global.MetadataPath, 'backups')
this.backupSchedule = settings.backupSchedule || false
this.backupsToKeep = settings.backupsToKeep || 2
this.maxBackupSize = settings.maxBackupSize || 1
@ -147,22 +150,26 @@ class ServerSettings {
this.authActiveAuthMethods.splice(this.authActiveAuthMethods.indexOf('openid', 0), 1)
}
// fallback to local
// fallback to local
if (!Array.isArray(this.authActiveAuthMethods) || this.authActiveAuthMethods.length == 0) {
this.authActiveAuthMethods = ['local']
}
// Migrations
if (settings.storeCoverWithBook != undefined) { // storeCoverWithBook was renamed to storeCoverWithItem in 2.0.0
if (settings.storeCoverWithBook != undefined) {
// storeCoverWithBook was renamed to storeCoverWithItem in 2.0.0
this.storeCoverWithItem = !!settings.storeCoverWithBook
}
if (settings.storeMetadataWithBook != undefined) { // storeMetadataWithBook was renamed to storeMetadataWithItem in 2.0.0
if (settings.storeMetadataWithBook != undefined) {
// storeMetadataWithBook was renamed to storeMetadataWithItem in 2.0.0
this.storeMetadataWithItem = !!settings.storeMetadataWithBook
}
if (settings.homeBookshelfView == undefined) { // homeBookshelfView was added in 2.1.3
if (settings.homeBookshelfView == undefined) {
// homeBookshelfView was added in 2.1.3
this.homeBookshelfView = settings.bookshelfView
}
if (settings.metadataFileFormat == undefined) { // metadataFileFormat was added in 2.2.21
if (settings.metadataFileFormat == undefined) {
// metadataFileFormat was added in 2.2.21
// All users using old settings will stay abs until changed
this.metadataFileFormat = 'abs'
}
@ -176,9 +183,15 @@ class ServerSettings {
if (this.logLevel !== Logger.logLevel) {
Logger.setLogLevel(this.logLevel)
}
if (process.env.BACKUP_PATH && this.backupPath !== process.env.BACKUP_PATH) {
Logger.info(`[ServerSettings] Using backup path from environment variable ${process.env.BACKUP_PATH}`)
this.backupPath = process.env.BACKUP_PATH
}
}
toJSON() { // Use toJSONForBrowser if sending to client
toJSON() {
// Use toJSONForBrowser if sending to client
return {
id: this.id,
tokenSecret: this.tokenSecret, // Do not return to client
@ -192,6 +205,7 @@ class ServerSettings {
metadataFileFormat: this.metadataFileFormat,
rateLimitLoginRequests: this.rateLimitLoginRequests,
rateLimitLoginWindow: this.rateLimitLoginWindow,
backupPath: this.backupPath,
backupSchedule: this.backupSchedule,
backupsToKeep: this.backupsToKeep,
maxBackupSize: this.maxBackupSize,
@ -249,14 +263,7 @@ class ServerSettings {
* Auth settings required for openid to be valid
*/
get isOpenIDAuthSettingsValid() {
return this.authOpenIDIssuerURL &&
this.authOpenIDAuthorizationURL &&
this.authOpenIDTokenURL &&
this.authOpenIDUserInfoURL &&
this.authOpenIDJwksURL &&
this.authOpenIDClientID &&
this.authOpenIDClientSecret &&
this.authOpenIDTokenSigningAlgorithm
return this.authOpenIDIssuerURL && this.authOpenIDAuthorizationURL && this.authOpenIDTokenURL && this.authOpenIDUserInfoURL && this.authOpenIDJwksURL && this.authOpenIDClientID && this.authOpenIDClientSecret && this.authOpenIDTokenSigningAlgorithm
}
get authenticationSettings() {
@ -297,8 +304,8 @@ class ServerSettings {
/**
* Update server settings
*
* @param {Object} payload
*
* @param {Object} payload
* @returns {boolean} true if updates were made
*/
update(payload) {

View File

@ -1,6 +1,7 @@
const axios = require('axios').default
const htmlSanitizer = require('../utils/htmlSanitizer')
const Logger = require('../Logger')
const { isValidASIN } = require('../utils/index')
class Audible {
#responseTimeout = 30000
@ -81,16 +82,6 @@ class Audible {
}
}
/**
* Test if a search title matches an ASIN. Supports lowercase letters
*
* @param {string} title
* @returns {boolean}
*/
isProbablyAsin(title) {
return /^[0-9A-Za-z]{10}$/.test(title)
}
/**
*
* @param {string} asin
@ -137,11 +128,11 @@ class Audible {
if (!timeout || isNaN(timeout)) timeout = this.#responseTimeout
let items
if (asin) {
if (asin && isValidASIN(asin.toUpperCase())) {
items = [await this.asinSearch(asin, region, timeout)]
}
if (!items && this.isProbablyAsin(title)) {
if (!items && isValidASIN(title.toUpperCase())) {
items = [await this.asinSearch(title, region, timeout)]
}

View File

@ -1,6 +1,8 @@
const axios = require('axios').default
const { levenshteinDistance } = require('../utils/index')
const Throttle = require('p-throttle')
const Logger = require('../Logger')
const { levenshteinDistance } = require('../utils/index')
const { isValidASIN } = require('../utils/index')
/**
* @typedef AuthorSearchObj
@ -11,8 +13,28 @@ const Logger = require('../Logger')
*/
class Audnexus {
static _instance = null
constructor() {
// ensures Audnexus class is singleton
if (Audnexus._instance) {
return Audnexus._instance
}
this.baseUrl = 'https://api.audnex.us'
// Rate limit is 100 requests per minute.
// @see https://github.com/laxamentumtech/audnexus#-deployment-
this.limiter = Throttle({
// Setting the limit to 1 allows for a short pause between requests that is imperceptible to the end user.
// A larger limit will grab blocks faster and then wait for the alloted time(interval) before
// fetching another batch, but with a discernable pause from the user perspective.
limit: 1,
strict: true,
interval: 150
})
Audnexus._instance = this
}
/**
@ -24,14 +46,14 @@ class Audnexus {
authorASINsRequest(name, region) {
const searchParams = new URLSearchParams()
searchParams.set('name', name)
if (region) searchParams.set('region', region)
const authorRequestUrl = `${this.baseUrl}/authors?${searchParams.toString()}`
Logger.info(`[Audnexus] Searching for author "${authorRequestUrl}"`)
return axios
.get(authorRequestUrl)
.then((res) => {
return res.data || []
})
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl)))
.then((res) => res.data || [])
.catch((error) => {
Logger.error(`[Audnexus] Author ASIN request failed for ${name}`, error)
return []
@ -45,15 +67,20 @@ class Audnexus {
* @returns {Promise<AuthorSearchObj>}
*/
authorRequest(asin, region) {
asin = encodeURIComponent(asin)
const regionQuery = region ? `?region=${region}` : ''
const authorRequestUrl = `${this.baseUrl}/authors/${asin}${regionQuery}`
if (!isValidASIN(asin?.toUpperCase?.())) {
Logger.error(`[Audnexus] Invalid ASIN ${asin}`)
return null
}
asin = encodeURIComponent(asin.toUpperCase())
const authorRequestUrl = new URL(`${this.baseUrl}/authors/${asin}`)
if (region) authorRequestUrl.searchParams.set('region', region)
Logger.info(`[Audnexus] Searching for author "${authorRequestUrl}"`)
return axios
.get(authorRequestUrl)
.then((res) => {
return res.data
})
return this._processRequest(this.limiter(() => axios.get(authorRequestUrl.toString())))
.then((res) => res.data)
.catch((error) => {
Logger.error(`[Audnexus] Author request failed for ${asin}`, error)
return null
@ -68,15 +95,15 @@ class Audnexus {
*/
async findAuthorByASIN(asin, region) {
const author = await this.authorRequest(asin, region)
if (!author) {
return null
}
return {
asin: author.asin,
description: author.description,
image: author.image || null,
name: author.name
}
return author
? {
asin: author.asin,
description: author.description,
image: author.image || null,
name: author.name
}
: null
}
/**
@ -97,13 +124,16 @@ class Audnexus {
closestMatch = authorAsinObj
}
})
if (!closestMatch || closestMatch.levenshteinDistance > maxLevenshtein) {
return null
}
const author = await this.authorRequest(closestMatch.asin)
if (!author) {
return null
}
return {
asin: author.asin,
description: author.description,
@ -112,17 +142,46 @@ class Audnexus {
}
}
/**
*
* @param {string} asin
* @param {string} region
* @returns {Promise<Object>}
*/
getChaptersByASIN(asin, region) {
Logger.debug(`[Audnexus] Get chapters for ASIN ${asin}/${region}`)
return axios
.get(`${this.baseUrl}/books/${asin}/chapters?region=${region}`)
.then((res) => {
return res.data
})
asin = encodeURIComponent(asin.toUpperCase())
const chaptersRequestUrl = new URL(`${this.baseUrl}/books/${asin}/chapters`)
if (region) chaptersRequestUrl.searchParams.set('region', region)
return this._processRequest(this.limiter(() => axios.get(chaptersRequestUrl.toString())))
.then((res) => res.data)
.catch((error) => {
Logger.error(`[Audnexus] Chapter ASIN request failed for ${asin}/${region}`, error)
return null
})
}
/**
* Internal method to process requests and retry if rate limit is exceeded.
*/
async _processRequest(request) {
try {
return await request()
} catch (error) {
if (error.response?.status === 429) {
const retryAfter = parseInt(error.response.headers?.['retry-after'], 10) || 5
Logger.warn(`[Audnexus] Rate limit exceeded. Retrying in ${retryAfter} seconds.`)
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000))
return this._processRequest(request)
}
throw error
}
}
}
module.exports = Audnexus

View File

@ -30,6 +30,7 @@ const ToolsController = require('../controllers/ToolsController')
const RSSFeedController = require('../controllers/RSSFeedController')
const CustomMetadataProviderController = require('../controllers/CustomMetadataProviderController')
const MiscController = require('../controllers/MiscController')
const ShareController = require('../controllers/ShareController')
const Author = require('../objects/entities/Author')
const Series = require('../objects/entities/Series')
@ -40,6 +41,7 @@ class ApiRouter {
this.auth = Server.auth
this.playbackSessionManager = Server.playbackSessionManager
this.abMergeManager = Server.abMergeManager
/** @type {import('../managers/BackupManager')} */
this.backupManager = Server.backupManager
/** @type {import('../Watcher')} */
this.watcher = Server.watcher
@ -193,6 +195,7 @@ class ApiRouter {
this.router.get('/backups/:id/download', BackupController.middleware.bind(this), BackupController.download.bind(this))
this.router.get('/backups/:id/apply', BackupController.middleware.bind(this), BackupController.apply.bind(this))
this.router.post('/backups/upload', BackupController.middleware.bind(this), BackupController.upload.bind(this))
this.router.patch('/backups/path', BackupController.middleware.bind(this), BackupController.updatePath.bind(this))
//
// File System Routes
@ -308,6 +311,11 @@ class ApiRouter {
this.router.post('/custom-metadata-providers', CustomMetadataProviderController.middleware.bind(this), CustomMetadataProviderController.create.bind(this))
this.router.delete('/custom-metadata-providers/:id', CustomMetadataProviderController.middleware.bind(this), CustomMetadataProviderController.delete.bind(this))
//
// Share routes
//
this.router.post('/share/mediaitem', ShareController.createMediaItemShare.bind(this))
this.router.delete('/share/mediaitem/:id', ShareController.deleteMediaItemShare.bind(this))
//
// Misc Routes
@ -567,10 +575,13 @@ class ApiRouter {
}
}
// Remove authors without an id
mediaMetadata.authors = mediaMetadata.authors.filter(au => !!au.id)
mediaMetadata.authors = mediaMetadata.authors.filter((au) => !!au.id)
if (newAuthors.length) {
await Database.createBulkAuthors(newAuthors)
SocketAuthority.emitter('authors_added', newAuthors.map(au => au.toJSON()))
SocketAuthority.emitter(
'authors_added',
newAuthors.map((au) => au.toJSON())
)
}
}
@ -611,10 +622,13 @@ class ApiRouter {
}
}
// Remove series without an id
mediaMetadata.series = mediaMetadata.series.filter(se => se.id)
mediaMetadata.series = mediaMetadata.series.filter((se) => se.id)
if (newSeries.length) {
await Database.createBulkSeries(newSeries)
SocketAuthority.emitter('multiple_series_added', newSeries.map(se => se.toJSON()))
SocketAuthority.emitter(
'multiple_series_added',
newSeries.map((se) => se.toJSON())
)
}
}
}

View File

@ -0,0 +1,15 @@
const express = require('express')
const ShareController = require('../controllers/ShareController')
class PublicRouter {
constructor() {
this.router = express()
this.router.disable('x-powered-by')
this.init()
}
init() {
this.router.get('/share/:slug', ShareController.getMediaItemShareBySlug.bind(this))
}
}
module.exports = PublicRouter

View File

@ -7,7 +7,7 @@ const { filePathToPOSIX } = require('./fileUtils')
function escapeSingleQuotes(path) {
// return path.replace(/'/g, '\'\\\'\'')
return filePathToPOSIX(path).replace(/ /g, '\\ ').replace(/'/g, '\\\'')
return filePathToPOSIX(path).replace(/ /g, '\\ ').replace(/'/g, "\\'")
}
// Returns first track start time
@ -19,7 +19,7 @@ async function writeConcatFile(tracks, outputPath, startTime = 0) {
// Find first track greater than startTime
if (startTime > 0) {
var currTrackEnd = 0
var startingTrack = tracks.find(t => {
var startingTrack = tracks.find((t) => {
currTrackEnd += t.duration
return startTime < currTrackEnd
})
@ -29,8 +29,8 @@ async function writeConcatFile(tracks, outputPath, startTime = 0) {
}
}
var tracksToInclude = tracks.filter(t => t.index >= trackToStartWithIndex)
var trackPaths = tracksToInclude.map(t => {
var tracksToInclude = tracks.filter((t) => t.index >= trackToStartWithIndex)
var trackPaths = tracksToInclude.map((t) => {
var line = 'file ' + escapeSingleQuotes(t.metadata.path) + '\n' + `duration ${t.duration}`
return line
})
@ -99,6 +99,9 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
url: podcastEpisodeDownload.url,
method: 'GET',
responseType: 'stream',
headers: {
'User-Agent': 'audiobookshelf (+https://audiobookshelf.org; like iTMS)'
},
timeout: 30000
}).catch((error) => {
Logger.error(`[ffmpegHelpers] Failed to download podcast episode with url "${podcastEpisodeDownload.url}"`, error)
@ -108,35 +111,31 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
const ffmpeg = Ffmpeg(response.data)
ffmpeg.addOption('-loglevel debug') // Debug logs printed on error
ffmpeg.outputOptions(
'-c:a', 'copy',
'-map', '0:a',
'-metadata', 'podcast=1'
)
ffmpeg.outputOptions('-c:a', 'copy', '-map', '0:a', '-metadata', 'podcast=1')
const podcastMetadata = podcastEpisodeDownload.libraryItem.media.metadata
const podcastEpisode = podcastEpisodeDownload.podcastEpisode
const finalSizeInBytes = Number(podcastEpisode.enclosure?.length || 0)
const taggings = {
'album': podcastMetadata.title,
album: podcastMetadata.title,
'album-sort': podcastMetadata.title,
'artist': podcastMetadata.author,
artist: podcastMetadata.author,
'artist-sort': podcastMetadata.author,
'comment': podcastEpisode.description,
'subtitle': podcastEpisode.subtitle,
'disc': podcastEpisode.season,
'genre': podcastMetadata.genres.length ? podcastMetadata.genres.join(';') : null,
'language': podcastMetadata.language,
'MVNM': podcastMetadata.title,
'MVIN': podcastEpisode.episode,
'track': podcastEpisode.episode,
comment: podcastEpisode.description,
subtitle: podcastEpisode.subtitle,
disc: podcastEpisode.season,
genre: podcastMetadata.genres.length ? podcastMetadata.genres.join(';') : null,
language: podcastMetadata.language,
MVNM: podcastMetadata.title,
MVIN: podcastEpisode.episode,
track: podcastEpisode.episode,
'series-part': podcastEpisode.episode,
'title': podcastEpisode.title,
title: podcastEpisode.title,
'title-sort': podcastEpisode.title,
'year': podcastEpisode.pubYear,
'date': podcastEpisode.pubDate,
'releasedate': podcastEpisode.pubDate,
year: podcastEpisode.pubYear,
date: podcastEpisode.pubDate,
releasedate: podcastEpisode.pubDate,
'itunes-id': podcastMetadata.itunesId,
'podcast-type': podcastMetadata.type,
'episode-type': podcastMetadata.episodeType

View File

@ -7,13 +7,12 @@ const rra = require('../libs/recursiveReaddirAsync')
const Logger = require('../Logger')
const { AudioMimeType } = require('./constants')
/**
* Make sure folder separator is POSIX for Windows file paths. e.g. "C:\Users\Abs" becomes "C:/Users/Abs"
*
* @param {String} path - Ugly file path
* @return {String} Pretty posix file path
*/
* Make sure folder separator is POSIX for Windows file paths. e.g. "C:\Users\Abs" becomes "C:/Users/Abs"
*
* @param {String} path - Ugly file path
* @return {String} Pretty posix file path
*/
const filePathToPOSIX = (path) => {
if (!global.isWin || !path) return path
return path.replace(/\\/g, '/')
@ -22,9 +21,9 @@ module.exports.filePathToPOSIX = filePathToPOSIX
/**
* Check path is a child of or equal to another path
*
* @param {string} parentPath
* @param {string} childPath
*
* @param {string} parentPath
* @param {string} childPath
* @returns {boolean}
*/
function isSameOrSubPath(parentPath, childPath) {
@ -33,8 +32,8 @@ function isSameOrSubPath(parentPath, childPath) {
if (parentPath === childPath) return true
const relativePath = Path.relative(parentPath, childPath)
return (
relativePath === '' // Same path (e.g. parentPath = '/a/b/', childPath = '/a/b')
|| !relativePath.startsWith('..') && !Path.isAbsolute(relativePath) // Sub path
relativePath === '' || // Same path (e.g. parentPath = '/a/b/', childPath = '/a/b')
(!relativePath.startsWith('..') && !Path.isAbsolute(relativePath)) // Sub path
)
}
module.exports.isSameOrSubPath = isSameOrSubPath
@ -67,8 +66,8 @@ module.exports.getFileTimestampsWithIno = getFileTimestampsWithIno
/**
* Get file size
*
* @param {string} path
*
* @param {string} path
* @returns {Promise<number>}
*/
module.exports.getFileSize = async (path) => {
@ -77,8 +76,8 @@ module.exports.getFileSize = async (path) => {
/**
* Get file mtimeMs
*
* @param {string} path
*
* @param {string} path
* @returns {Promise<number>} epoch timestamp
*/
module.exports.getFileMTimeMs = async (path) => {
@ -91,8 +90,8 @@ module.exports.getFileMTimeMs = async (path) => {
}
/**
*
* @param {string} filepath
*
* @param {string} filepath
* @returns {boolean}
*/
async function checkPathIsFile(filepath) {
@ -106,16 +105,19 @@ async function checkPathIsFile(filepath) {
module.exports.checkPathIsFile = checkPathIsFile
function getIno(path) {
return fs.stat(path, { bigint: true }).then((data => String(data.ino))).catch((err) => {
Logger.error('[Utils] Failed to get ino for path', path, err)
return null
})
return fs
.stat(path, { bigint: true })
.then((data) => String(data.ino))
.catch((err) => {
Logger.error('[Utils] Failed to get ino for path', path, err)
return null
})
}
module.exports.getIno = getIno
/**
* Read contents of file
* @param {string} path
* @param {string} path
* @returns {string}
*/
async function readTextFile(path) {
@ -144,8 +146,8 @@ module.exports.bytesPretty = bytesPretty
/**
* Get array of files inside dir
* @param {string} path
* @param {string} [relPathToReplace]
* @param {string} path
* @param {string} [relPathToReplace]
* @returns {{name:string, path:string, dirpath:string, reldirpath:string, fullpath:string, extension:string, deep:number}[]}
*/
async function recurseFiles(path, relPathToReplace = null) {
@ -177,55 +179,58 @@ async function recurseFiles(path, relPathToReplace = null) {
const directoriesToIgnore = []
list = list.filter((item) => {
if (item.error) {
Logger.error(`[fileUtils] Recurse files file "${item.fullname}" has error`, item.error)
return false
}
list = list
.filter((item) => {
if (item.error) {
Logger.error(`[fileUtils] Recurse files file "${item.fullname}" has error`, item.error)
return false
}
const relpath = item.fullname.replace(relPathToReplace, '')
let reldirname = Path.dirname(relpath)
if (reldirname === '.') reldirname = ''
const dirname = Path.dirname(item.fullname)
const relpath = item.fullname.replace(relPathToReplace, '')
let reldirname = Path.dirname(relpath)
if (reldirname === '.') reldirname = ''
const dirname = Path.dirname(item.fullname)
// Directory has a file named ".ignore" flag directory and ignore
if (item.name === '.ignore' && reldirname && reldirname !== '.' && !directoriesToIgnore.includes(dirname)) {
Logger.debug(`[fileUtils] .ignore found - ignoring directory "${reldirname}"`)
directoriesToIgnore.push(dirname)
return false
}
// Directory has a file named ".ignore" flag directory and ignore
if (item.name === '.ignore' && reldirname && reldirname !== '.' && !directoriesToIgnore.includes(dirname)) {
Logger.debug(`[fileUtils] .ignore found - ignoring directory "${reldirname}"`)
directoriesToIgnore.push(dirname)
return false
}
if (item.extension === '.part') {
Logger.debug(`[fileUtils] Ignoring .part file "${relpath}"`)
return false
}
if (item.extension === '.part') {
Logger.debug(`[fileUtils] Ignoring .part file "${relpath}"`)
return false
}
// Ignore any file if a directory or the filename starts with "."
if (relpath.split('/').find(p => p.startsWith('.'))) {
Logger.debug(`[fileUtils] Ignoring path has . "${relpath}"`)
return false
}
// Ignore any file if a directory or the filename starts with "."
if (relpath.split('/').find((p) => p.startsWith('.'))) {
Logger.debug(`[fileUtils] Ignoring path has . "${relpath}"`)
return false
}
return true
}).filter(item => {
// Filter out items in ignore directories
if (directoriesToIgnore.some(dir => item.fullname.startsWith(dir))) {
Logger.debug(`[fileUtils] Ignoring path in dir with .ignore "${item.fullname}"`)
return false
}
return true
}).map((item) => {
var isInRoot = (item.path + '/' === relPathToReplace)
return {
name: item.name,
path: item.fullname.replace(relPathToReplace, ''),
dirpath: item.path,
reldirpath: isInRoot ? '' : item.path.replace(relPathToReplace, ''),
fullpath: item.fullname,
extension: item.extension,
deep: item.deep
}
})
return true
})
.filter((item) => {
// Filter out items in ignore directories
if (directoriesToIgnore.some((dir) => item.fullname.startsWith(dir))) {
Logger.debug(`[fileUtils] Ignoring path in dir with .ignore "${item.fullname}"`)
return false
}
return true
})
.map((item) => {
var isInRoot = item.path + '/' === relPathToReplace
return {
name: item.name,
path: item.fullname.replace(relPathToReplace, ''),
dirpath: item.path,
reldirpath: isInRoot ? '' : item.path.replace(relPathToReplace, ''),
fullpath: item.fullname,
extension: item.extension,
deep: item.deep
}
})
// Sort from least deep to most
list.sort((a, b) => a.deep - b.deep)
@ -237,8 +242,8 @@ module.exports.recurseFiles = recurseFiles
/**
* Download file from web to local file system
* Uses SSRF filter to prevent internal URLs
*
* @param {string} url
*
* @param {string} url
* @param {string} filepath path to download the file to
* @param {Function} [contentTypeFilter] validate content type before writing
* @returns {Promise}
@ -250,34 +255,39 @@ module.exports.downloadFile = (url, filepath, contentTypeFilter = null) => {
url,
method: 'GET',
responseType: 'stream',
headers: {
'User-Agent': 'audiobookshelf (+https://audiobookshelf.org)'
},
timeout: 30000,
httpAgent: ssrfFilter(url),
httpsAgent: ssrfFilter(url)
}).then((response) => {
// Validate content type
if (contentTypeFilter && !contentTypeFilter?.(response.headers?.['content-type'])) {
return reject(new Error(`Invalid content type "${response.headers?.['content-type'] || ''}"`))
}
// Write to filepath
const writer = fs.createWriteStream(filepath)
response.data.pipe(writer)
writer.on('finish', resolve)
writer.on('error', reject)
}).catch((err) => {
Logger.error(`[fileUtils] Failed to download file "${filepath}"`, err)
reject(err)
httpAgent: global.DisableSsrfRequestFilter ? null : ssrfFilter(url),
httpsAgent: global.DisableSsrfRequestFilter ? null : ssrfFilter(url)
})
.then((response) => {
// Validate content type
if (contentTypeFilter && !contentTypeFilter?.(response.headers?.['content-type'])) {
return reject(new Error(`Invalid content type "${response.headers?.['content-type'] || ''}"`))
}
// Write to filepath
const writer = fs.createWriteStream(filepath)
response.data.pipe(writer)
writer.on('finish', resolve)
writer.on('error', reject)
})
.catch((err) => {
Logger.error(`[fileUtils] Failed to download file "${filepath}"`, err)
reject(err)
})
})
}
/**
* Download image file from web to local file system
* Response header must have content-type of image/ (excluding svg)
*
* @param {string} url
* @param {string} filepath
*
* @param {string} url
* @param {string} filepath
* @returns {Promise}
*/
module.exports.downloadImageFile = (url, filepath) => {
@ -350,14 +360,17 @@ module.exports.getAudioMimeTypeFromExtname = (extname) => {
module.exports.removeFile = (path) => {
if (!path) return false
return fs.remove(path).then(() => true).catch((error) => {
Logger.error(`[fileUtils] Failed remove file "${path}"`, error)
return false
})
return fs
.remove(path)
.then(() => true)
.catch((error) => {
Logger.error(`[fileUtils] Failed remove file "${path}"`, error)
return false
})
}
module.exports.encodeUriPath = (path) => {
const uri = new URL('/', "file://")
const uri = new URL('/', 'file://')
// we assign the path here to assure that URL control characters like # are
// actually interpreted as part of the URL path
uri.pathname = path
@ -367,8 +380,8 @@ module.exports.encodeUriPath = (path) => {
/**
* Check if directory is writable.
* This method is necessary because fs.access(directory, fs.constants.W_OK) does not work on Windows
*
* @param {string} directory
*
* @param {string} directory
* @returns {Promise<boolean>}
*/
module.exports.isWritable = async (directory) => {
@ -385,7 +398,7 @@ module.exports.isWritable = async (directory) => {
/**
* Get Windows drives as array e.g. ["C:/", "F:/"]
*
*
* @returns {Promise<string[]>}
*/
module.exports.getWindowsDrives = async () => {
@ -398,7 +411,11 @@ module.exports.getWindowsDrives = async () => {
reject(error)
return
}
let drives = stdout?.split(/\r?\n/).map(line => line.trim()).filter(line => line).slice(1)
let drives = stdout
?.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line)
.slice(1)
const validDrives = []
for (const drive of drives) {
let drivepath = drive + '/'
@ -415,33 +432,35 @@ module.exports.getWindowsDrives = async () => {
/**
* Get array of directory paths in a directory
*
* @param {string} dirPath
*
* @param {string} dirPath
* @param {number} level
* @returns {Promise<{ path:string, dirname:string, level:number }[]>}
*/
module.exports.getDirectoriesInPath = async (dirPath, level) => {
try {
const paths = await fs.readdir(dirPath)
let dirs = await Promise.all(paths.map(async dirname => {
const fullPath = Path.join(dirPath, dirname)
let dirs = await Promise.all(
paths.map(async (dirname) => {
const fullPath = Path.join(dirPath, dirname)
const lstat = await fs.lstat(fullPath).catch((error) => {
Logger.debug(`Failed to lstat "${fullPath}"`, error)
return null
const lstat = await fs.lstat(fullPath).catch((error) => {
Logger.debug(`Failed to lstat "${fullPath}"`, error)
return null
})
if (!lstat?.isDirectory()) return null
return {
path: this.filePathToPOSIX(fullPath),
dirname,
level
}
})
if (!lstat?.isDirectory()) return null
return {
path: this.filePathToPOSIX(fullPath),
dirname,
level
}
}))
dirs = dirs.filter(d => d)
)
dirs = dirs.filter((d) => d)
return dirs
} catch (error) {
Logger.error('Failed to readdir', dirPath, error)
return []
}
}
}

View File

@ -1,7 +1,7 @@
const Path = require('path')
const uuid = require('uuid')
const Logger = require('../Logger')
const { parseString } = require("xml2js")
const { parseString } = require('xml2js')
const areEquivalent = require('./areEquivalent')
const levenshteinDistance = (str1, str2, caseSensitive = false) => {
@ -11,8 +11,9 @@ const levenshteinDistance = (str1, str2, caseSensitive = false) => {
str1 = str1.toLowerCase()
str2 = str2.toLowerCase()
}
const track = Array(str2.length + 1).fill(null).map(() =>
Array(str1.length + 1).fill(null))
const track = Array(str2.length + 1)
.fill(null)
.map(() => Array(str1.length + 1).fill(null))
for (let i = 0; i <= str1.length; i += 1) {
track[0][i] = i
}
@ -25,7 +26,7 @@ const levenshteinDistance = (str1, str2, caseSensitive = false) => {
track[j][i] = Math.min(
track[j][i - 1] + 1, // deletion
track[j - 1][i] + 1, // insertion
track[j - 1][i - 1] + indicator, // substitution
track[j - 1][i - 1] + indicator // substitution
)
}
}
@ -138,7 +139,10 @@ module.exports.toNumber = (val, fallback = 0) => {
module.exports.cleanStringForSearch = (str) => {
if (!str) return ''
// Remove ' . ` " ,
return str.toLowerCase().replace(/[\'\.\`\",]/g, '').trim()
return str
.toLowerCase()
.replace(/[\'\.\`\",]/g, '')
.trim()
}
const getTitleParts = (title) => {
@ -156,7 +160,7 @@ const getTitleParts = (title) => {
/**
* Remove sortingPrefixes from title
* @example "The Good Book" => "Good Book"
* @param {string} title
* @param {string} title
* @returns {string}
*/
module.exports.getTitleIgnorePrefix = (title) => {
@ -164,9 +168,9 @@ module.exports.getTitleIgnorePrefix = (title) => {
}
/**
* Put sorting prefix at the end of title
* Put sorting prefix at the end of title
* @example "The Good Book" => "Good Book, The"
* @param {string} title
* @param {string} title
* @returns {string}
*/
module.exports.getTitlePrefixAtEnd = (title) => {
@ -178,8 +182,8 @@ module.exports.getTitlePrefixAtEnd = (title) => {
* to lower case for only ascii characters
* used to handle sqlite that doesnt support unicode lower
* @see https://github.com/advplyr/audiobookshelf/issues/2187
*
* @param {string} str
*
* @param {string} str
* @returns {string}
*/
module.exports.asciiOnlyToLowerCase = (str) => {
@ -200,8 +204,8 @@ module.exports.asciiOnlyToLowerCase = (str) => {
/**
* Escape string used in RegExp
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
*
* @param {string} str
*
* @param {string} str
* @returns {string}
*/
module.exports.escapeRegExp = (str) => {
@ -211,8 +215,8 @@ module.exports.escapeRegExp = (str) => {
/**
* Validate url string with URL class
*
* @param {string} rawUrl
*
* @param {string} rawUrl
* @returns {string} null if invalid
*/
module.exports.validateUrl = (rawUrl) => {
@ -227,11 +231,22 @@ module.exports.validateUrl = (rawUrl) => {
/**
* Check if a string is a valid UUID
*
* @param {string} str
*
* @param {string} str
* @returns {boolean}
*/
module.exports.isUUID = (str) => {
if (!str || typeof str !== 'string') return false
return uuid.validate(str)
}
}
/**
* Check if a string is a valid ASIN
*
* @param {string} str
* @returns {boolean}
*/
module.exports.isValidASIN = (str) => {
if (!str || typeof str !== 'string') return false
return /^[A-Z0-9]{10}$/.test(str)
}

View File

@ -63,7 +63,7 @@ function cleanOverdriveMediaMarkers(overdriveMediaMarkers) {
function objectValuesArrayToString(arrayOfObjects) {
Logger.debug('[parseOverdriveMediaMarkers] Converting Marker object values from arrays to strings')
arrayOfObjects.forEach((item) => {
Object.keys(item).forEach(key => {
Object.keys(item).forEach((key) => {
item[key] = item[key].toString()
})
})
@ -78,7 +78,7 @@ function removeExtraChapters(parsedOverdriveMediaMarkers) {
const weirdChapterFilterRegex = /([(]\d|[cC]ontinued)/
var cleaned = []
parsedOverdriveMediaMarkers.forEach(function (item) {
cleaned.push(item.filter(chapter => !weirdChapterFilterRegex.test(chapter.Name)))
cleaned.push(item.filter((chapter) => !weirdChapterFilterRegex.test(chapter.Name)))
})
return cleaned
@ -110,11 +110,20 @@ function generateParsedChapters(includedAudioFiles, cleanedOverdriveMediaMarkers
// cleanedOverdriveMediaMarkers is an array of array of objects, where the inner array matches to the included audio files tracks
// this allows us to leverage the individual track durations when calculating the start times of chapters in tracks after the first (using length)
// TODO: can we guarantee the inner array matches the included audio files?
// TODO: can we guarantee the inner array matches the included audio files?
includedAudioFiles.forEach((track, track_index) => {
cleanedOverdriveMediaMarkers[track_index].forEach((chapter) => {
time = chapter.Time.split(":")
time = length + parseFloat(time[0]) * 60 + parseFloat(time[1])
let timeParts = chapter.Time.split(':')
// add seconds
time = length + parseFloat(timeParts.pop())
if (timeParts.length) {
// add minutes
time += parseFloat(timeParts.pop()) * 60
}
if (timeParts.length) {
// add hours
time += parseFloat(timeParts.pop()) * 3600
}
var newChapterData = {
id: index++,
start: time,
@ -131,7 +140,7 @@ function generateParsedChapters(includedAudioFiles, cleanedOverdriveMediaMarkers
}
module.exports.parseOverdriveMediaMarkersAsChapters = (includedAudioFiles) => {
const overdriveMediaMarkers = includedAudioFiles.map((af) => af.metaTags.tagOverdriveMediaMarker).filter(af => af) || []
const overdriveMediaMarkers = includedAudioFiles.map((af) => af.metaTags.tagOverdriveMediaMarker).filter((af) => af) || []
if (!overdriveMediaMarkers.length) return null
var cleanedOverdriveMediaMarkers = cleanOverdriveMediaMarkers(overdriveMediaMarkers)
@ -139,4 +148,4 @@ module.exports.parseOverdriveMediaMarkersAsChapters = (includedAudioFiles) => {
// so if not equal then we must exit
if (cleanedOverdriveMediaMarkers.length !== includedAudioFiles.length) return null
return generateParsedChapters(includedAudioFiles, cleanedOverdriveMediaMarkers)
}
}

View File

@ -220,8 +220,8 @@ module.exports.parsePodcastRssFeedXml = async (xml, excludeEpisodeMetadata = fal
/**
* Get podcast RSS feed as JSON
* Uses SSRF filter to prevent internal URLs
*
* @param {string} feedUrl
*
* @param {string} feedUrl
* @param {boolean} [excludeEpisodeMetadata=false]
* @returns {Promise}
*/
@ -233,38 +233,42 @@ module.exports.getPodcastFeed = (feedUrl, excludeEpisodeMetadata = false) => {
method: 'GET',
timeout: 12000,
responseType: 'arraybuffer',
headers: { Accept: 'application/rss+xml, application/xhtml+xml, application/xml, */*;q=0.8' },
httpAgent: ssrfFilter(feedUrl),
httpsAgent: ssrfFilter(feedUrl)
}).then(async (data) => {
// Adding support for ios-8859-1 encoded RSS feeds.
// See: https://github.com/advplyr/audiobookshelf/issues/1489
const contentType = data.headers?.['content-type'] || '' // e.g. text/xml; charset=iso-8859-1
if (contentType.toLowerCase().includes('iso-8859-1')) {
data.data = data.data.toString('latin1')
} else {
data.data = data.data.toString()
}
if (!data?.data) {
Logger.error(`[podcastUtils] getPodcastFeed: Invalid podcast feed request response (${feedUrl})`)
return null
}
Logger.debug(`[podcastUtils] getPodcastFeed for "${feedUrl}" success - parsing xml`)
const payload = await this.parsePodcastRssFeedXml(data.data, excludeEpisodeMetadata)
if (!payload) {
return null
}
// RSS feed may be a private RSS feed
payload.podcast.metadata.feedUrl = feedUrl
return payload.podcast
}).catch((error) => {
Logger.error('[podcastUtils] getPodcastFeed Error', error)
return null
headers: {
Accept: 'application/rss+xml, application/xhtml+xml, application/xml, */*;q=0.8',
'User-Agent': 'audiobookshelf (+https://audiobookshelf.org; like iTMS)'
},
httpAgent: global.DisableSsrfRequestFilter ? null : ssrfFilter(feedUrl),
httpsAgent: global.DisableSsrfRequestFilter ? null : ssrfFilter(feedUrl)
})
.then(async (data) => {
// Adding support for ios-8859-1 encoded RSS feeds.
// See: https://github.com/advplyr/audiobookshelf/issues/1489
const contentType = data.headers?.['content-type'] || '' // e.g. text/xml; charset=iso-8859-1
if (contentType.toLowerCase().includes('iso-8859-1')) {
data.data = data.data.toString('latin1')
} else {
data.data = data.data.toString()
}
if (!data?.data) {
Logger.error(`[podcastUtils] getPodcastFeed: Invalid podcast feed request response (${feedUrl})`)
return null
}
Logger.debug(`[podcastUtils] getPodcastFeed for "${feedUrl}" success - parsing xml`)
const payload = await this.parsePodcastRssFeedXml(data.data, excludeEpisodeMetadata)
if (!payload) {
return null
}
// RSS feed may be a private RSS feed
payload.podcast.metadata.feedUrl = feedUrl
return payload.podcast
})
.catch((error) => {
Logger.error('[podcastUtils] getPodcastFeed Error', error)
return null
})
}
// Return array of episodes ordered by closest match (Levenshtein distance of 6 or less)
@ -283,7 +287,7 @@ module.exports.findMatchingEpisodesInFeed = (feed, searchTitle) => {
}
const matches = []
feed.episodes.forEach(ep => {
feed.episodes.forEach((ep) => {
if (!ep.title) return
const epTitle = ep.title.toLowerCase().trim()