mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-06-02 00:40:39 +02:00
Compare commits
397 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f7831611f | |||
| d09db19cd5 | |||
| 030e43f382 | |||
| f081a7fdc1 | |||
| f0d5f46199 | |||
| 0b8f6db45e | |||
| 806c0a2991 | |||
| 7d6d3e6687 | |||
| ad07ed7e25 | |||
| d3402e30c2 | |||
| 25fe4dee3a | |||
| 3c21c82ce1 | |||
| 3c8876a37d | |||
| fba70c9831 | |||
| 27e40d16fd | |||
| 448cbf8530 | |||
| f1153f9da5 | |||
| d09a21d922 | |||
| 62afa3c3ee | |||
| 85446be0e5 | |||
| 018ca8e7ee | |||
| f02453ac92 | |||
| 84b77f4c7f | |||
| d41276ba8c | |||
| 576d7dc024 | |||
| 6d2b1df560 | |||
| 8255e4308c | |||
| 794adf0292 | |||
| f2e0b9762c | |||
| 7d0def0edb | |||
| 0653572396 | |||
| d9a3750667 | |||
| 9c0c7b6b08 | |||
| df1391d93f | |||
| 8775e55762 | |||
| d0d152c20d | |||
| 4ff7355262 | |||
| 6cc7a44a22 | |||
| ad092ef8f8 | |||
| 4102ed8be4 | |||
| 691f291843 | |||
| ac381854e5 | |||
| 9c8900560c | |||
| d9cfcc86e7 | |||
| ce803dd6de | |||
| 97afd22f81 | |||
| e24eaab3f1 | |||
| e201247d69 | |||
| a24dae5262 | |||
| e59babdf24 | |||
| 8dbe1e4e5d | |||
| cdc37ddb0f | |||
| f127a7beb5 | |||
| df60aeb456 | |||
| 30c327d92a | |||
| 596bddf791 | |||
| 44ff90a6f2 | |||
| 293851d931 | |||
| 8b995a179d | |||
| 4d32a22de9 | |||
| af1ff12dbb | |||
| d96ed01ce4 | |||
| 7610e97f0f | |||
| 4f5123e842 | |||
| d102065d02 | |||
| 34315d4c10 | |||
| 276a179446 | |||
| 4462d32e98 | |||
| 9722674072 | |||
| 35bb77c9c2 | |||
| cf6f49ce75 | |||
| d614373c64 | |||
| b9969c78a6 | |||
| fbf482d6b6 | |||
| dd74d0a726 | |||
| b13b80e011 | |||
| e384863148 | |||
| d21fe49ce2 | |||
| a992400d6a | |||
| 108b2a60f5 | |||
| af684e6a69 | |||
| 5336d0525e | |||
| bb4eec9355 | |||
| 28404f37b8 | |||
| 7b92c15a46 | |||
| c150ed4e98 | |||
| cb7632b216 | |||
| b8849677de | |||
| 9bf8d7de11 | |||
| 6634ce8fd4 | |||
| 9d4303ef7b | |||
| 1f7be58124 | |||
| 6b8b27b04f | |||
| ba4061e5a4 | |||
| 693dc00fa3 | |||
| f3f5f3b9bd | |||
| b515c6c746 | |||
| 35e196238a | |||
| 2dc93258f1 | |||
| 5123f7d240 | |||
| 06d3bd76a8 | |||
| 52196afd99 | |||
| 3e44ee6f50 | |||
| 9841826e10 | |||
| def93d18ec | |||
| 387a3d05b4 | |||
| 398d04fc08 | |||
| c5e5e516af | |||
| 1c6f99b876 | |||
| d0af82e71a | |||
| 76e7616439 | |||
| fe99a269bc | |||
| 5315f65023 | |||
| c2809808c3 | |||
| 204ac4f204 | |||
| accd5d1096 | |||
| 5025c6a3ea | |||
| 6d0d1415e4 | |||
| 514f5c2409 | |||
| 2cc58b2c8a | |||
| 777a055fcd | |||
| b45085d2d6 | |||
| 22f6e86a12 | |||
| dc6783ea76 | |||
| a6f10ca48e | |||
| aac01d6d9a | |||
| a617994207 | |||
| 7a33a412fc | |||
| 0135b3560c | |||
| 6968a5c02a | |||
| 5e2bb0b12c | |||
| 7122756e58 | |||
| 8ecc912c2d | |||
| c8cea4e6af | |||
| 0c5d05d319 | |||
| 4a3eb7727b | |||
| 81640464ba | |||
| eda7036f70 | |||
| e669a8d378 | |||
| 8e01859075 | |||
| f0525d4f0d | |||
| 84c9c6cb50 | |||
| 346df3680c | |||
| 6aa7c8a3d8 | |||
| 704c6f7bde | |||
| f01055f6e6 | |||
| 759c58d3f7 | |||
| 357176b301 | |||
| 9bb4dc3ab0 | |||
| 709c33f27a | |||
| 4d846e225a | |||
| 5dc6d613bd | |||
| 63ccdb68f0 | |||
| 424ef1aec3 | |||
| b6995ba5d1 | |||
| 9968743a93 | |||
| c377b57601 | |||
| 262d0b46e3 | |||
| 32fc4f6555 | |||
| 81572adab6 | |||
| 1ad2e71fd5 | |||
| db66b9eaeb | |||
| 28c2e62e61 | |||
| 96401c377c | |||
| 9d45880b37 | |||
| 9052ceedd3 | |||
| 4968864498 | |||
| f44c2d9e11 | |||
| 0c8e334b1a | |||
| abaa7b5ad0 | |||
| df01e493ec | |||
| 949c8ce230 | |||
| 9eaa0c26cd | |||
| d71f091e3e | |||
| 2589121908 | |||
| ff425212e7 | |||
| 243baaf775 | |||
| 7275b1063b | |||
| 4fd97510b8 | |||
| 6e67b1d9dd | |||
| 0fc6afec26 | |||
| c950ac7d69 | |||
| 8979e19e92 | |||
| 6a51cb07e8 | |||
| 846a8c3881 | |||
| 0cd698cc8d | |||
| 13d9462868 | |||
| d8e2ff8b0e | |||
| 35c2a5c1a3 | |||
| 19dc096d22 | |||
| 535ebc10f0 | |||
| 7486a0659b | |||
| 273866fe92 | |||
| 6425d95deb | |||
| 68a39449a2 | |||
| 8e08458ea2 | |||
| 1119ddef8a | |||
| 3d0219a866 | |||
| 6ce1806359 | |||
| f05a513767 | |||
| d03c338b48 | |||
| 5e5a988f7a | |||
| 6d1f0b27df | |||
| d01a7cb756 | |||
| cae874ef05 | |||
| 733afc3e29 | |||
| 0772730336 | |||
| 8b02fe07c8 | |||
| 98f93a665c | |||
| 754566b221 | |||
| f4f9adad35 | |||
| 16f7f1166e | |||
| f527b0f4d5 | |||
| 4f41df53c9 | |||
| 8a15f775a2 | |||
| 5e83bcd283 | |||
| 2fd5dfcb66 | |||
| 872ce4fa38 | |||
| ba792d91e5 | |||
| 4997c716db | |||
| fd72d05280 | |||
| 241b56ad45 | |||
| 635c384952 | |||
| ef930fd1b4 | |||
| 49997a1336 | |||
| 8d0434143c | |||
| 8e0319994e | |||
| 0ed6045d1e | |||
| 25c7e95a64 | |||
| 1781c4bbcb | |||
| c4ce72d44e | |||
| 78813c4b28 | |||
| 990baa2dc6 | |||
| c85f4467d2 | |||
| 59f7609054 | |||
| 2ef827e3fa | |||
| 5cadc8d90f | |||
| 40e7e36ef6 | |||
| d60ad96f8a | |||
| 46ba342d49 | |||
| ace6b2b81f | |||
| fa7e2dfafe | |||
| 015310c15d | |||
| f624f04dec | |||
| 7c13cfcda2 | |||
| fc265dadae | |||
| f9905f887e | |||
| eb72bfbbc0 | |||
| c268cace09 | |||
| 9666caf7a3 | |||
| 9e01e5c24e | |||
| 25e613a867 | |||
| fe23a86eaa | |||
| cb5a7d6aef | |||
| 7deb89ce7a | |||
| 1e300c77c9 | |||
| ed7cc42959 | |||
| f681ff68a1 | |||
| ba112bf9c2 | |||
| 718434545a | |||
| 0e9a4c95a9 | |||
| 3c997c8468 | |||
| eb49646256 | |||
| c54b5eadfd | |||
| 659c671c25 | |||
| 0df5a7816d | |||
| 26c976b6b9 | |||
| bdeb22615e | |||
| 257bf2ebe0 | |||
| fc33da447a | |||
| df45347690 | |||
| b876256736 | |||
| 3ce6e45761 | |||
| 5ac6b85da1 | |||
| 69e0a0732a | |||
| 087835a9f3 | |||
| 1f7b181b7b | |||
| 1afb8840db | |||
| d9531166b6 | |||
| 336de49d8d | |||
| 3cc527484d | |||
| 45987ffd63 | |||
| 1a1ef9c378 | |||
| 342d100f3e | |||
| e0b90c6813 | |||
| 2706a9c4aa | |||
| 2cc9d1b7f8 | |||
| 2b7268c952 | |||
| e097fe1e88 | |||
| 6819c0b108 | |||
| 58cd751b43 | |||
| 9f834a5345 | |||
| 5eaf9c69ad | |||
| a1074e69ac | |||
| 65aec6a099 | |||
| 38957d4f32 | |||
| a2dc76e190 | |||
| fd84cd0d7f | |||
| db7744eb84 | |||
| af513a2fb6 | |||
| 4cb5c934d5 | |||
| 37f84a0f62 | |||
| 70595181f1 | |||
| b357bbed60 | |||
| f7a720c6ac | |||
| 6549605efd | |||
| 33952fb1fd | |||
| 7b207dc5d8 | |||
| cb24a9c1ec | |||
| 3b42af5213 | |||
| b56691f1a2 | |||
| ac3154093c | |||
| 01ef24f5e6 | |||
| 3fb73c7426 | |||
| bf3bc06322 | |||
| 2733c28784 | |||
| b3dac831e6 | |||
| 35702aa770 | |||
| b2ffb3b7b9 | |||
| c52fe4b583 | |||
| af8ace7d1f | |||
| de37e40a1e | |||
| 56f5df91dc | |||
| fc590abb09 | |||
| bc7bbc1b7d | |||
| 4345973213 | |||
| b4ff9f5944 | |||
| a9a253f769 | |||
| a9783efa34 | |||
| a380ee080f | |||
| eabefd099c | |||
| 97799919e6 | |||
| 35870a0158 | |||
| ec05bd36e4 | |||
| be041f93c2 | |||
| a156d3595b | |||
| a1d549a2b1 | |||
| 812cb5a160 | |||
| e6264540af | |||
| 79fe064c4a | |||
| 7e69713683 | |||
| 3bbeb8f27a | |||
| 04fb8fa61d | |||
| 2caa861b8a | |||
| d7f0815fb3 | |||
| e6ab05e177 | |||
| c2ecfd428b | |||
| 9f26274ca8 | |||
| 7764f1cf75 | |||
| bc1b99efd6 | |||
| 26309019e7 | |||
| b47d7b734d | |||
| 62194b8781 | |||
| 7c114a051a | |||
| 26c0c89b94 | |||
| c81071a7b3 | |||
| 31f48edcc3 | |||
| f7109a055c | |||
| 9d0e7759e0 | |||
| d15ccbd2fc | |||
| cfeb1743df | |||
| a7e0330b06 | |||
| 5f69e83d46 | |||
| fdde62896f | |||
| f1909d0fc7 | |||
| 28225618fd | |||
| 1a562a5f23 | |||
| bfbbcba160 | |||
| 21e4d17ef3 | |||
| 87faebc7d9 | |||
| 5d868d1355 | |||
| ac0fd41740 | |||
| 1202e95b66 | |||
| c05cf9718b | |||
| d8f1e43e85 | |||
| ed7e87b168 | |||
| 4ca2c9e97f | |||
| 01dd1c0615 | |||
| cd387b8fed | |||
| c85cd69152 | |||
| 9e9b52a252 | |||
| 292d5783a9 | |||
| c7faafd0f3 | |||
| ca7388b14e | |||
| ddf2ca3670 | |||
| 96825c3c2b | |||
| 6ed66fea16 | |||
| ddcda197b4 | |||
| 8bea5d83f5 | |||
| dc3c978f8d | |||
| 13fac2d5bc | |||
| fd0af6b2dd | |||
| 121805ba39 | |||
| f9bbd71174 | |||
| 2fbb31e0ea | |||
| 89167543fa | |||
| 33e0987d73 |
@@ -23,7 +23,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
if: ${{ !contains(github.event.head_commit.message, 'skip ci') && github.repository == 'advplyr/audiobookshelf' }}
|
if: ${{ !contains(github.event.head_commit.message, 'skip ci') && github.repository == 'advplyr/audiobookshelf' }}
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out
|
- name: Check out
|
||||||
|
|||||||
@@ -23,3 +23,4 @@ sw.*
|
|||||||
.DS_STORE
|
.DS_STORE
|
||||||
.idea/*
|
.idea/*
|
||||||
tailwind.compiled.css
|
tailwind.compiled.css
|
||||||
|
tailwind.config.js
|
||||||
|
|||||||
+34
-16
@@ -1,34 +1,32 @@
|
|||||||
|
ARG NUSQLITE3_DIR="/usr/local/lib/nusqlite3"
|
||||||
|
ARG NUSQLITE3_PATH="${NUSQLITE3_DIR}/libnusqlite3.so"
|
||||||
|
|
||||||
### STAGE 0: Build client ###
|
### STAGE 0: Build client ###
|
||||||
FROM node:20-alpine AS build
|
FROM node:20-alpine AS build-client
|
||||||
|
|
||||||
WORKDIR /client
|
WORKDIR /client
|
||||||
COPY /client /client
|
COPY /client /client
|
||||||
RUN npm ci && npm cache clean --force
|
RUN npm ci && npm cache clean --force
|
||||||
RUN npm run generate
|
RUN npm run generate
|
||||||
|
|
||||||
### STAGE 1: Build server ###
|
### STAGE 1: Build server ###
|
||||||
FROM node:20-alpine
|
FROM node:20-alpine AS build-server
|
||||||
|
|
||||||
|
ARG NUSQLITE3_DIR
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
RUN apk update && \
|
RUN apk add --no-cache --update \
|
||||||
apk add --no-cache --update \
|
|
||||||
curl \
|
curl \
|
||||||
tzdata \
|
|
||||||
ffmpeg \
|
|
||||||
make \
|
make \
|
||||||
python3 \
|
python3 \
|
||||||
g++ \
|
g++ \
|
||||||
tini \
|
|
||||||
unzip
|
unzip
|
||||||
|
|
||||||
COPY --from=build /client/dist /client/dist
|
WORKDIR /server
|
||||||
COPY index.js package* /
|
COPY index.js package* /server
|
||||||
COPY server server
|
COPY /server /server/server
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
|
|
||||||
ENV NUSQLITE3_DIR="/usr/local/lib/nusqlite3"
|
|
||||||
ENV NUSQLITE3_PATH="${NUSQLITE3_DIR}/libnusqlite3.so"
|
|
||||||
|
|
||||||
RUN case "$TARGETPLATFORM" in \
|
RUN case "$TARGETPLATFORM" in \
|
||||||
"linux/amd64") \
|
"linux/amd64") \
|
||||||
@@ -42,14 +40,34 @@ RUN case "$TARGETPLATFORM" in \
|
|||||||
|
|
||||||
RUN npm ci --only=production
|
RUN npm ci --only=production
|
||||||
|
|
||||||
RUN apk del make python3 g++
|
### STAGE 2: Create minimal runtime image ###
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
ARG NUSQLITE3_DIR
|
||||||
|
ARG NUSQLITE3_PATH
|
||||||
|
|
||||||
|
# Install only runtime dependencies
|
||||||
|
RUN apk add --no-cache --update \
|
||||||
|
tzdata \
|
||||||
|
ffmpeg \
|
||||||
|
tini
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy compiled frontend and server from build stages
|
||||||
|
COPY --from=build-client /client/dist /app/client/dist
|
||||||
|
COPY --from=build-server /server /app
|
||||||
|
COPY --from=build-server ${NUSQLITE3_PATH} ${NUSQLITE3_PATH}
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
ENV PORT=80
|
ENV PORT=80
|
||||||
|
ENV NODE_ENV=production
|
||||||
ENV CONFIG_PATH="/config"
|
ENV CONFIG_PATH="/config"
|
||||||
ENV METADATA_PATH="/metadata"
|
ENV METADATA_PATH="/metadata"
|
||||||
ENV SOURCE="docker"
|
ENV SOURCE="docker"
|
||||||
|
ENV NUSQLITE3_DIR=${NUSQLITE3_DIR}
|
||||||
|
ENV NUSQLITE3_PATH=${NUSQLITE3_PATH}
|
||||||
|
|
||||||
ENTRYPOINT ["tini", "--"]
|
ENTRYPOINT ["tini", "--"]
|
||||||
CMD ["node", "index.js"]
|
CMD ["node", "index.js"]
|
||||||
|
|||||||
@@ -217,6 +217,16 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.results.episodes?.length) {
|
||||||
|
shelves.push({
|
||||||
|
id: 'episodes',
|
||||||
|
label: 'Episodes',
|
||||||
|
labelStringKey: 'LabelEpisodes',
|
||||||
|
type: 'episode',
|
||||||
|
entities: this.results.episodes.map((res) => res.libraryItem)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (this.results.series?.length) {
|
if (this.results.series?.length) {
|
||||||
shelves.push({
|
shelves.push({
|
||||||
id: 'series',
|
id: 'series',
|
||||||
|
|||||||
@@ -274,15 +274,10 @@ export default {
|
|||||||
isAuthorsPage() {
|
isAuthorsPage() {
|
||||||
return this.page === 'authors'
|
return this.page === 'authors'
|
||||||
},
|
},
|
||||||
isAlbumsPage() {
|
|
||||||
return this.page === 'albums'
|
|
||||||
},
|
|
||||||
numShowing() {
|
numShowing() {
|
||||||
return this.totalEntities
|
return this.totalEntities
|
||||||
},
|
},
|
||||||
entityName() {
|
entityName() {
|
||||||
if (this.isAlbumsPage) return 'Albums'
|
|
||||||
|
|
||||||
if (this.isPodcastLibrary) return this.$strings.LabelPodcasts
|
if (this.isPodcastLibrary) return this.$strings.LabelPodcasts
|
||||||
if (!this.page) return this.$strings.LabelBooks
|
if (!this.page) return this.$strings.LabelBooks
|
||||||
if (this.isSeriesPage) return this.$strings.LabelSeries
|
if (this.isSeriesPage) return this.$strings.LabelSeries
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ export default {
|
|||||||
title: this.$strings.HeaderUsers,
|
title: this.$strings.HeaderUsers,
|
||||||
path: '/config/users'
|
path: '/config/users'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'config-api-keys',
|
||||||
|
title: this.$strings.HeaderApiKeys,
|
||||||
|
path: '/config/api-keys'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'config-sessions',
|
id: 'config-sessions',
|
||||||
title: this.$strings.HeaderListeningSessions,
|
title: this.$strings.HeaderListeningSessions,
|
||||||
|
|||||||
@@ -778,10 +778,6 @@ export default {
|
|||||||
windowResize() {
|
windowResize() {
|
||||||
this.executeRebuild()
|
this.executeRebuild()
|
||||||
},
|
},
|
||||||
socketInit() {
|
|
||||||
// Server settings are set on socket init
|
|
||||||
this.executeRebuild()
|
|
||||||
},
|
|
||||||
initListeners() {
|
initListeners() {
|
||||||
window.addEventListener('resize', this.windowResize)
|
window.addEventListener('resize', this.windowResize)
|
||||||
|
|
||||||
@@ -794,7 +790,6 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.$eventBus.$on('bookshelf_clear_selection', this.clearSelectedEntities)
|
this.$eventBus.$on('bookshelf_clear_selection', this.clearSelectedEntities)
|
||||||
this.$eventBus.$on('socket_init', this.socketInit)
|
|
||||||
this.$eventBus.$on('user-settings', this.settingsUpdated)
|
this.$eventBus.$on('user-settings', this.settingsUpdated)
|
||||||
|
|
||||||
if (this.$root.socket) {
|
if (this.$root.socket) {
|
||||||
@@ -826,7 +821,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.$eventBus.$off('bookshelf_clear_selection', this.clearSelectedEntities)
|
this.$eventBus.$off('bookshelf_clear_selection', this.clearSelectedEntities)
|
||||||
this.$eventBus.$off('socket_init', this.socketInit)
|
|
||||||
this.$eventBus.$off('user-settings', this.settingsUpdated)
|
this.$eventBus.$off('user-settings', this.settingsUpdated)
|
||||||
|
|
||||||
if (this.$root.socket) {
|
if (this.$root.socket) {
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ export default {
|
|||||||
return this.mediaMetadata.authors || []
|
return this.mediaMetadata.authors || []
|
||||||
},
|
},
|
||||||
libraryId() {
|
libraryId() {
|
||||||
return this.streamLibraryItem ? this.streamLibraryItem.libraryId : null
|
return this.streamLibraryItem?.libraryId || null
|
||||||
},
|
},
|
||||||
totalDurationPretty() {
|
totalDurationPretty() {
|
||||||
// Adjusted by playback rate
|
// Adjusted by playback rate
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ export default {
|
|||||||
coverHeight() {
|
coverHeight() {
|
||||||
return this.cardHeight
|
return this.cardHeight
|
||||||
},
|
},
|
||||||
userToken() {
|
|
||||||
return this.store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
_author() {
|
_author() {
|
||||||
return this.author || {}
|
return this.author || {}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center h-full px-1 overflow-hidden">
|
||||||
|
<covers-book-cover :library-item="libraryItem" :width="coverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||||
|
<div class="grow px-2 episodeSearchCardContent">
|
||||||
|
<p class="truncate text-sm">{{ episodeTitle }}</p>
|
||||||
|
<p class="text-xs text-gray-200 truncate">{{ podcastTitle }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
libraryItem: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
episode: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
bookCoverAspectRatio() {
|
||||||
|
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
||||||
|
},
|
||||||
|
coverWidth() {
|
||||||
|
if (this.bookCoverAspectRatio === 1) return 50 * 1.2
|
||||||
|
return 50
|
||||||
|
},
|
||||||
|
media() {
|
||||||
|
return this.libraryItem?.media || {}
|
||||||
|
},
|
||||||
|
mediaMetadata() {
|
||||||
|
return this.media.metadata || {}
|
||||||
|
},
|
||||||
|
episodeTitle() {
|
||||||
|
return this.episode.title || 'No Title'
|
||||||
|
},
|
||||||
|
podcastTitle() {
|
||||||
|
return this.mediaMetadata.title || 'No Title'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
|
mounted() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.episodeSearchCardContent {
|
||||||
|
width: calc(100% - 80px);
|
||||||
|
height: 75px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -20,10 +20,10 @@
|
|||||||
<div class="w-1/2 px-2">
|
<div class="w-1/2 px-2">
|
||||||
<div v-if="!isPodcast" class="flex items-end">
|
<div v-if="!isPodcast" class="flex items-end">
|
||||||
<ui-text-input-with-label v-model.trim="itemData.author" :disabled="processing" :label="$strings.LabelAuthor" />
|
<ui-text-input-with-label v-model.trim="itemData.author" :disabled="processing" :label="$strings.LabelAuthor" />
|
||||||
<ui-tooltip :text="$strings.LabelUploaderItemFetchMetadataHelp">
|
<ui-tooltip direction="top" :text="$strings.LabelUploaderItemFetchMetadataHelp">
|
||||||
<div class="ml-2 mb-1 w-8 h-8 bg-bg border border-white/10 flex items-center justify-center rounded-full hover:bg-primary cursor-pointer" @click="fetchMetadata">
|
<button type="button" class="ml-2 mb-1 w-8 h-8 bg-bg border border-white/10 flex items-center justify-center rounded-full hover:bg-primary cursor-pointer" @click="fetchMetadata">
|
||||||
<span class="text-base text-white/80 font-mono material-symbols">sync</span>
|
<span class="text-base text-white/80 font-mono material-symbols">sync</span>
|
||||||
</div>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="w-full">
|
<div v-else class="w-full">
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="card" :id="`album-card-${index}`" :style="{ width: cardWidth + 'px' }" class="absolute top-0 left-0 rounded-xs z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard">
|
|
||||||
<div class="relative" :style="{ height: coverHeight + 'px' }">
|
|
||||||
<div class="absolute top-0 left-0 w-full box-shadow-book shadow-height" />
|
|
||||||
<div class="w-full h-full bg-primary relative rounded-sm overflow-hidden">
|
|
||||||
<covers-preview-cover ref="cover" :src="coverSrc" :width="cardWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative w-full">
|
|
||||||
<div v-if="!isAlternativeBookshelfView" class="categoryPlacard absolute z-30 left-0 right-0 mx-auto -bottom-6e h-6e rounded-md text-center" :style="{ width: Math.min(200, cardWidth) + 'px' }">
|
|
||||||
<div class="w-full h-full shinyBlack flex items-center justify-center rounded-xs border" :style="{ padding: `0em ${0.5}em` }">
|
|
||||||
<p class="truncate" :style="{ fontSize: labelFontSize + 'em' }">{{ title }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="absolute z-30 left-0 right-0 mx-auto -bottom-8e h-8e py-1e rounded-md text-center">
|
|
||||||
<p class="truncate" :style="{ fontSize: labelFontSize + 'em' }">{{ title }}</p>
|
|
||||||
<p class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ artist || ' ' }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
index: Number,
|
|
||||||
width: Number,
|
|
||||||
height: {
|
|
||||||
type: Number,
|
|
||||||
default: 192
|
|
||||||
},
|
|
||||||
bookshelfView: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
albumMount: {
|
|
||||||
type: Object,
|
|
||||||
default: () => null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
album: null,
|
|
||||||
isSelectionMode: false,
|
|
||||||
selected: false,
|
|
||||||
isHovering: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
bookCoverAspectRatio() {
|
|
||||||
return this.store.getters['libraries/getBookCoverAspectRatio']
|
|
||||||
},
|
|
||||||
cardWidth() {
|
|
||||||
return this.width || this.coverHeight
|
|
||||||
},
|
|
||||||
coverHeight() {
|
|
||||||
return this.height * this.sizeMultiplier
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
cardHeight() {
|
|
||||||
return this.coverHeight + this.bottomTextHeight
|
|
||||||
},
|
|
||||||
bottomTextHeight() {
|
|
||||||
if (!this.isAlternativeBookshelfView) return 0
|
|
||||||
const lineHeight = 1.5
|
|
||||||
const remSize = 16
|
|
||||||
const baseHeight = this.sizeMultiplier * lineHeight * remSize
|
|
||||||
const titleHeight = this.labelFontSize * baseHeight
|
|
||||||
const paddingHeight = 4 * 2 * this.sizeMultiplier // py-1
|
|
||||||
return titleHeight + paddingHeight
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
coverSrc() {
|
|
||||||
const config = this.$config || this.$nuxt.$config
|
|
||||||
if (!this.album || !this.album.libraryItemId) return `${config.routerBasePath}/book_placeholder.jpg`
|
|
||||||
return this.store.getters['globals/getLibraryItemCoverSrcById'](this.album.libraryItemId)
|
|
||||||
},
|
|
||||||
labelFontSize() {
|
|
||||||
if (this.width < 160) return 0.75
|
|
||||||
return 0.9
|
|
||||||
},
|
|
||||||
sizeMultiplier() {
|
|
||||||
return this.store.getters['user/getSizeMultiplier']
|
|
||||||
},
|
|
||||||
title() {
|
|
||||||
return this.album ? this.album.title : ''
|
|
||||||
},
|
|
||||||
artist() {
|
|
||||||
return this.album ? this.album.artist : ''
|
|
||||||
},
|
|
||||||
store() {
|
|
||||||
return this.$store || this.$nuxt.$store
|
|
||||||
},
|
|
||||||
currentLibraryId() {
|
|
||||||
return this.store.state.libraries.currentLibraryId
|
|
||||||
},
|
|
||||||
isAlternativeBookshelfView() {
|
|
||||||
const constants = this.$constants || this.$nuxt.$constants
|
|
||||||
return this.bookshelfView == constants.BookshelfView.DETAIL
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setEntity(album) {
|
|
||||||
this.album = album
|
|
||||||
},
|
|
||||||
setSelectionMode(val) {
|
|
||||||
this.isSelectionMode = val
|
|
||||||
},
|
|
||||||
mouseover() {
|
|
||||||
this.isHovering = true
|
|
||||||
},
|
|
||||||
mouseleave() {
|
|
||||||
this.isHovering = false
|
|
||||||
},
|
|
||||||
clickCard() {
|
|
||||||
if (!this.album) return
|
|
||||||
// const router = this.$router || this.$nuxt.$router
|
|
||||||
// router.push(`/album/${this.$encode(this.title)}`)
|
|
||||||
},
|
|
||||||
clickEdit() {
|
|
||||||
this.$emit('edit', this.album)
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
// destroy the vue listeners, etc
|
|
||||||
this.$destroy()
|
|
||||||
|
|
||||||
// remove the element from the DOM
|
|
||||||
if (this.$el && this.$el.parentNode) {
|
|
||||||
this.$el.parentNode.removeChild(this.$el)
|
|
||||||
} else if (this.$el && this.$el.remove) {
|
|
||||||
this.$el.remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.albumMount) {
|
|
||||||
this.setEntity(this.albumMount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -198,7 +198,7 @@ export default {
|
|||||||
return this.store.getters['user/getSizeMultiplier']
|
return this.store.getters['user/getSizeMultiplier']
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.store.state.serverSettings.dateFormat
|
return this.store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
_libraryItem() {
|
_libraryItem() {
|
||||||
return this.libraryItem || {}
|
return this.libraryItem || {}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export default {
|
|||||||
return this.height * this.sizeMultiplier
|
return this.height * this.sizeMultiplier
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.store.state.serverSettings.dateFormat
|
return this.store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
labelFontSize() {
|
labelFontSize() {
|
||||||
if (this.width < 160) return 0.75
|
if (this.width < 160) return 0.75
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="narrators?.length" class="flex py-0.5 mt-4">
|
<div v-if="narrators?.length" class="flex py-0.5 mt-4">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelNarrators }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelNarrators }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="max-w-[calc(100vw-10rem)] overflow-hidden text-ellipsis">
|
<div class="max-w-[calc(100vw-10rem)] overflow-hidden text-ellipsis">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="publishedYear" role="paragraph" class="flex py-0.5">
|
<div v-if="publishedYear" role="paragraph" class="flex py-0.5">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelPublishYear }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelPublishYear }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="publisher" role="paragraph" class="flex py-0.5">
|
<div v-if="publisher" role="paragraph" class="flex py-0.5">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelPublisher }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelPublisher }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="podcastType" role="paragraph" class="flex py-0.5">
|
<div v-if="podcastType" role="paragraph" class="flex py-0.5">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelPodcastType }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelPodcastType }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="capitalize">
|
<div class="capitalize">
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex py-0.5" v-if="genres.length">
|
<div class="flex py-0.5" v-if="genres.length">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelGenres }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelGenres }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="max-w-[calc(100vw-10rem)] overflow-hidden text-ellipsis">
|
<div class="max-w-[calc(100vw-10rem)] overflow-hidden text-ellipsis">
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex py-0.5" v-if="tags.length">
|
<div class="flex py-0.5" v-if="tags.length">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelTags }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelTags }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="max-w-[calc(100vw-10rem)] overflow-hidden text-ellipsis">
|
<div class="max-w-[calc(100vw-10rem)] overflow-hidden text-ellipsis">
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="language" class="flex py-0.5">
|
<div v-if="language" class="flex py-0.5">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelLanguage }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelLanguage }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="tracks.length || (isPodcast && totalPodcastDuration)" role="paragraph" class="flex py-0.5">
|
<div v-if="tracks.length || (isPodcast && totalPodcastDuration)" role="paragraph" class="flex py-0.5">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelDuration }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelDuration }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div role="paragraph" class="flex py-0.5">
|
<div role="paragraph" class="flex py-0.5">
|
||||||
<div class="w-24 min-w-24 sm:w-32 sm:min-w-32">
|
<div class="w-34 min-w-34 sm:w-34 sm:min-w-34 break-words">
|
||||||
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelSize }}</span>
|
<span class="text-white/60 uppercase text-sm">{{ $strings.LabelSize }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -39,6 +39,15 @@
|
|||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<p v-if="episodeResults.length" class="uppercase text-xs text-gray-400 my-1 px-1 font-semibold">{{ $strings.LabelEpisodes }}</p>
|
||||||
|
<template v-for="item in episodeResults">
|
||||||
|
<li :key="item.libraryItem.recentEpisode.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||||
|
<nuxt-link :to="`/item/${item.libraryItem.id}`">
|
||||||
|
<cards-episode-search-card :episode="item.libraryItem.recentEpisode" :library-item="item.libraryItem" />
|
||||||
|
</nuxt-link>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
|
||||||
<p v-if="authorResults.length" class="uppercase text-xs text-gray-400 mb-1 mt-3 px-1 font-semibold">{{ $strings.LabelAuthors }}</p>
|
<p v-if="authorResults.length" class="uppercase text-xs text-gray-400 mb-1 mt-3 px-1 font-semibold">{{ $strings.LabelAuthors }}</p>
|
||||||
<template v-for="item in authorResults">
|
<template v-for="item in authorResults">
|
||||||
<li :key="item.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
<li :key="item.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||||
@@ -100,6 +109,7 @@ export default {
|
|||||||
isFetching: false,
|
isFetching: false,
|
||||||
search: null,
|
search: null,
|
||||||
podcastResults: [],
|
podcastResults: [],
|
||||||
|
episodeResults: [],
|
||||||
bookResults: [],
|
bookResults: [],
|
||||||
authorResults: [],
|
authorResults: [],
|
||||||
seriesResults: [],
|
seriesResults: [],
|
||||||
@@ -115,7 +125,7 @@ export default {
|
|||||||
return this.$store.state.libraries.currentLibraryId
|
return this.$store.state.libraries.currentLibraryId
|
||||||
},
|
},
|
||||||
totalResults() {
|
totalResults() {
|
||||||
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length
|
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length + this.episodeResults.length
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -132,6 +142,7 @@ export default {
|
|||||||
this.search = null
|
this.search = null
|
||||||
this.lastSearch = null
|
this.lastSearch = null
|
||||||
this.podcastResults = []
|
this.podcastResults = []
|
||||||
|
this.episodeResults = []
|
||||||
this.bookResults = []
|
this.bookResults = []
|
||||||
this.authorResults = []
|
this.authorResults = []
|
||||||
this.seriesResults = []
|
this.seriesResults = []
|
||||||
@@ -175,6 +186,7 @@ export default {
|
|||||||
if (!this.isFetching) return
|
if (!this.isFetching) return
|
||||||
|
|
||||||
this.podcastResults = searchResults.podcast || []
|
this.podcastResults = searchResults.podcast || []
|
||||||
|
this.episodeResults = searchResults.episodes || []
|
||||||
this.bookResults = searchResults.book || []
|
this.bookResults = searchResults.book || []
|
||||||
this.authorResults = searchResults.authors || []
|
this.authorResults = searchResults.authors || []
|
||||||
this.seriesResults = searchResults.series || []
|
this.seriesResults = searchResults.series || []
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ export default {
|
|||||||
userIsAdminOrUp() {
|
userIsAdminOrUp() {
|
||||||
return this.$store.getters['user/getIsAdminOrUp']
|
return this.$store.getters['user/getIsAdminOrUp']
|
||||||
},
|
},
|
||||||
|
userCanAccessExplicitContent() {
|
||||||
|
return this.$store.getters['user/getUserCanAccessExplicitContent']
|
||||||
|
},
|
||||||
libraryMediaType() {
|
libraryMediaType() {
|
||||||
return this.$store.getters['libraries/getCurrentLibraryMediaType']
|
return this.$store.getters['libraries/getCurrentLibraryMediaType']
|
||||||
},
|
},
|
||||||
@@ -239,6 +242,15 @@ export default {
|
|||||||
sublist: false
|
sublist: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (this.userCanAccessExplicitContent) {
|
||||||
|
items.push({
|
||||||
|
text: this.$strings.LabelExplicit,
|
||||||
|
value: 'explicit',
|
||||||
|
sublist: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (this.userIsAdminOrUp) {
|
if (this.userIsAdminOrUp) {
|
||||||
items.push({
|
items.push({
|
||||||
text: this.$strings.LabelShareOpen,
|
text: this.$strings.LabelShareOpen,
|
||||||
@@ -249,7 +261,7 @@ export default {
|
|||||||
return items
|
return items
|
||||||
},
|
},
|
||||||
podcastItems() {
|
podcastItems() {
|
||||||
return [
|
const items = [
|
||||||
{
|
{
|
||||||
text: this.$strings.LabelAll,
|
text: this.$strings.LabelAll,
|
||||||
value: 'all'
|
value: 'all'
|
||||||
@@ -276,8 +288,23 @@ export default {
|
|||||||
text: this.$strings.ButtonIssues,
|
text: this.$strings.ButtonIssues,
|
||||||
value: 'issues',
|
value: 'issues',
|
||||||
sublist: false
|
sublist: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: this.$strings.LabelRSSFeedOpen,
|
||||||
|
value: 'feed-open',
|
||||||
|
sublist: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (this.userCanAccessExplicitContent) {
|
||||||
|
items.push({
|
||||||
|
text: this.$strings.LabelExplicit,
|
||||||
|
value: 'explicit',
|
||||||
|
sublist: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return items
|
||||||
},
|
},
|
||||||
selectItems() {
|
selectItems() {
|
||||||
if (this.isSeries) return this.seriesItems
|
if (this.isSeries) return this.seriesItems
|
||||||
|
|||||||
@@ -39,9 +39,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
_author() {
|
_author() {
|
||||||
return this.author || {}
|
return this.author || {}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -309,9 +309,9 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
console.log('Account updated', data.user)
|
console.log('Account updated', data.user)
|
||||||
|
|
||||||
if (data.user.id === this.user.id && data.user.token !== this.user.token) {
|
if (data.user.id === this.user.id && data.user.accessToken !== this.user.accessToken) {
|
||||||
console.log('Current user token was updated')
|
console.log('Current user access token was updated')
|
||||||
this.$store.commit('user/setUserToken', data.user.token)
|
this.$store.commit('user/setAccessToken', data.user.accessToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$toast.success(this.$strings.ToastAccountUpdateSuccess)
|
this.$toast.success(this.$strings.ToastAccountUpdateSuccess)
|
||||||
@@ -351,9 +351,6 @@ export default {
|
|||||||
this.$toast.error(errMsg || 'Failed to create account')
|
this.$toast.error(errMsg || 'Failed to create account')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
toggleActive() {
|
|
||||||
this.newUser.isActive = !this.newUser.isActive
|
|
||||||
},
|
|
||||||
userTypeUpdated(type) {
|
userTypeUpdated(type) {
|
||||||
this.newUser.permissions = {
|
this.newUser.permissions = {
|
||||||
download: type !== 'guest',
|
download: type !== 'guest',
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<modals-modal ref="modal" v-model="show" name="api-key-created" :width="800" :height="'unset'" persistent>
|
||||||
|
<template #outer>
|
||||||
|
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
||||||
|
<p class="text-3xl text-white truncate">{{ title }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<form @submit.prevent="submitForm">
|
||||||
|
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 overflow-y-auto overflow-x-hidden" style="min-height: 200px; max-height: 80vh">
|
||||||
|
<div class="w-full p-8">
|
||||||
|
<p class="text-lg text-white mb-4">{{ $getString('LabelApiKeyCreated', [apiKeyName]) }}</p>
|
||||||
|
|
||||||
|
<p class="text-lg text-white mb-4">{{ $strings.LabelApiKeyCreatedDescription }}</p>
|
||||||
|
|
||||||
|
<ui-text-input label="API Key" :value="apiKeyKey" readonly show-copy />
|
||||||
|
|
||||||
|
<div class="flex justify-end mt-4">
|
||||||
|
<ui-btn color="bg-primary" @click="show = false">{{ $strings.ButtonClose }}</ui-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</modals-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: Boolean,
|
||||||
|
apiKey: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
show: {
|
||||||
|
get() {
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title() {
|
||||||
|
return this.$strings.HeaderNewApiKey
|
||||||
|
},
|
||||||
|
apiKeyName() {
|
||||||
|
return this.apiKey?.name || ''
|
||||||
|
},
|
||||||
|
apiKeyKey() {
|
||||||
|
return this.apiKey?.apiKey || ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
|
mounted() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
<template>
|
||||||
|
<modals-modal ref="modal" v-model="show" name="api-key" :width="800" :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">{{ title }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<form @submit.prevent="submitForm">
|
||||||
|
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 overflow-y-auto overflow-x-hidden" style="min-height: 400px; max-height: 80vh">
|
||||||
|
<div class="w-full p-8">
|
||||||
|
<div class="flex py-2">
|
||||||
|
<div class="w-1/2 px-2">
|
||||||
|
<ui-text-input-with-label v-model.trim="newApiKey.name" :readonly="!isNew" :label="$strings.LabelName" />
|
||||||
|
</div>
|
||||||
|
<div v-if="isNew" class="w-1/2 px-2">
|
||||||
|
<ui-text-input-with-label v-model.trim="newApiKey.expiresIn" :label="$strings.LabelExpiresInSeconds" type="number" :min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center pt-4 pb-2 gap-2">
|
||||||
|
<div class="flex items-center px-2">
|
||||||
|
<p class="px-3 font-semibold" id="user-enabled-toggle">{{ $strings.LabelEnable }}</p>
|
||||||
|
<ui-toggle-switch :disabled="isExpired && !apiKey.isActive" labeledBy="user-enabled-toggle" v-model="newApiKey.isActive" />
|
||||||
|
</div>
|
||||||
|
<div v-if="isExpired" class="px-2">
|
||||||
|
<p class="text-sm text-error">{{ $strings.LabelExpired }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full border-t border-b border-black-200 py-4 px-3 mt-4">
|
||||||
|
<p class="text-lg mb-2 font-semibold">{{ $strings.LabelApiKeyUser }}</p>
|
||||||
|
<p class="text-sm mb-2 text-gray-400">{{ $strings.LabelApiKeyUserDescription }}</p>
|
||||||
|
<ui-select-input v-model="newApiKey.userId" :disabled="isExpired && !apiKey.isActive" :items="userItems" :placeholder="$strings.LabelSelectUser" :label="$strings.LabelApiKeyUser" label-hidden />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex pt-4 px-2">
|
||||||
|
<div class="grow" />
|
||||||
|
<ui-btn color="bg-success" type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</modals-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: Boolean,
|
||||||
|
apiKey: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null
|
||||||
|
},
|
||||||
|
users: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
processing: false,
|
||||||
|
newApiKey: {},
|
||||||
|
isNew: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
show: {
|
||||||
|
get() {
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title() {
|
||||||
|
return this.isNew ? this.$strings.HeaderNewApiKey : this.$strings.HeaderUpdateApiKey
|
||||||
|
},
|
||||||
|
userItems() {
|
||||||
|
return this.users
|
||||||
|
.filter((u) => {
|
||||||
|
// Only show root user if the current user is root
|
||||||
|
return u.type !== 'root' || this.$store.getters['user/getIsRoot']
|
||||||
|
})
|
||||||
|
.map((u) => ({ text: u.username, value: u.id, subtext: u.type }))
|
||||||
|
},
|
||||||
|
isExpired() {
|
||||||
|
if (!this.apiKey || !this.apiKey.expiresAt) return false
|
||||||
|
|
||||||
|
return new Date(this.apiKey.expiresAt).getTime() < Date.now()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submitForm() {
|
||||||
|
if (!this.newApiKey.name) {
|
||||||
|
this.$toast.error(this.$strings.ToastNameRequired)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.newApiKey.userId) {
|
||||||
|
this.$toast.error(this.$strings.ToastNewApiKeyUserError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isNew) {
|
||||||
|
this.submitCreateApiKey()
|
||||||
|
} else {
|
||||||
|
this.submitUpdateApiKey()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
submitUpdateApiKey() {
|
||||||
|
if (this.newApiKey.isActive === this.apiKey.isActive && this.newApiKey.userId === this.apiKey.userId) {
|
||||||
|
this.$toast.info(this.$strings.ToastNoUpdatesNecessary)
|
||||||
|
this.show = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiKey = {
|
||||||
|
isActive: this.newApiKey.isActive,
|
||||||
|
userId: this.newApiKey.userId
|
||||||
|
}
|
||||||
|
|
||||||
|
this.processing = true
|
||||||
|
this.$axios
|
||||||
|
.$patch(`/api/api-keys/${this.apiKey.id}`, apiKey)
|
||||||
|
.then((data) => {
|
||||||
|
this.processing = false
|
||||||
|
if (data.error) {
|
||||||
|
this.$toast.error(`${this.$strings.ToastFailedToUpdate}: ${data.error}`)
|
||||||
|
} else {
|
||||||
|
this.show = false
|
||||||
|
this.$emit('updated', data.apiKey)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.processing = false
|
||||||
|
console.error('Failed to update apiKey', error)
|
||||||
|
var errMsg = error.response ? error.response.data || '' : ''
|
||||||
|
this.$toast.error(errMsg || this.$strings.ToastFailedToUpdate)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitCreateApiKey() {
|
||||||
|
const apiKey = { ...this.newApiKey }
|
||||||
|
|
||||||
|
if (this.newApiKey.expiresIn) {
|
||||||
|
apiKey.expiresIn = parseInt(this.newApiKey.expiresIn)
|
||||||
|
} else {
|
||||||
|
delete apiKey.expiresIn
|
||||||
|
}
|
||||||
|
|
||||||
|
this.processing = true
|
||||||
|
this.$axios
|
||||||
|
.$post('/api/api-keys', apiKey)
|
||||||
|
.then((data) => {
|
||||||
|
this.processing = false
|
||||||
|
if (data.error) {
|
||||||
|
this.$toast.error(this.$strings.ToastFailedToCreate + ': ' + data.error)
|
||||||
|
} else {
|
||||||
|
this.show = false
|
||||||
|
this.$emit('created', data.apiKey)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.processing = false
|
||||||
|
console.error('Failed to create apiKey', error)
|
||||||
|
var errMsg = error.response ? error.response.data || '' : ''
|
||||||
|
this.$toast.error(errMsg || this.$strings.ToastFailedToCreate)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
this.isNew = !this.apiKey
|
||||||
|
|
||||||
|
if (this.apiKey) {
|
||||||
|
this.newApiKey = {
|
||||||
|
name: this.apiKey.name,
|
||||||
|
isActive: this.apiKey.isActive,
|
||||||
|
userId: this.apiKey.userId
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.newApiKey = {
|
||||||
|
name: null,
|
||||||
|
expiresIn: null,
|
||||||
|
isActive: true,
|
||||||
|
userId: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -79,10 +79,10 @@ export default {
|
|||||||
return !this.bookmarks.find((bm) => Math.abs(this.currentTime - bm.time) < 1)
|
return !this.bookmarks.find((bm) => Math.abs(this.currentTime - bm.time) < 1)
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<ui-text-input-with-label ref="sequenceInput" v-model="selectedSeries.sequence" :label="$strings.LabelSequence" />
|
<ui-text-input-with-label ref="sequenceInput" v-model="selectedSeries.sequence" :label="$strings.LabelSequence" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="error" class="text-error text-sm mt-2 p-1">{{ error }}</div>
|
||||||
<div class="flex justify-end mt-2 p-1">
|
<div class="flex justify-end mt-2 p-1">
|
||||||
<ui-btn type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
|
<ui-btn type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,12 +35,17 @@ export default {
|
|||||||
existingSeriesNames: {
|
existingSeriesNames: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
|
},
|
||||||
|
originalSeriesSequence: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
el: null,
|
el: null,
|
||||||
content: null
|
content: null,
|
||||||
|
error: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -85,10 +91,17 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitSeriesForm() {
|
submitSeriesForm() {
|
||||||
|
this.error = null
|
||||||
|
|
||||||
if (this.$refs.newSeriesSelect) {
|
if (this.$refs.newSeriesSelect) {
|
||||||
this.$refs.newSeriesSelect.blur()
|
this.$refs.newSeriesSelect.blur()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.selectedSeries.sequence !== this.originalSeriesSequence && this.selectedSeries.sequence.includes(' ')) {
|
||||||
|
this.error = this.$strings.MessageSeriesSequenceCannotContainSpaces
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.$emit('submit')
|
this.$emit('submit')
|
||||||
},
|
},
|
||||||
clickClose() {
|
clickClose() {
|
||||||
@@ -100,6 +113,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setShow() {
|
setShow() {
|
||||||
|
this.error = null
|
||||||
if (!this.el || !this.content) {
|
if (!this.el || !this.content) {
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,10 +159,10 @@ export default {
|
|||||||
return 'Unknown'
|
return 'Unknown'
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
},
|
},
|
||||||
isOpenSession() {
|
isOpenSession() {
|
||||||
return !!this._session.open
|
return !!this._session.open
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default {
|
|||||||
processing: Boolean,
|
processing: Boolean,
|
||||||
persistent: {
|
persistent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: false
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: [String, Number],
|
type: [String, Number],
|
||||||
@@ -99,7 +99,7 @@ export default {
|
|||||||
this.preventClickoutside = false
|
this.preventClickoutside = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.processing && this.persistent) return
|
if (this.processing || this.persistent) return
|
||||||
if (ev.srcElement && ev.srcElement.classList.contains('modal-bg')) {
|
if (ev.srcElement && ev.srcElement.classList.contains('modal-bg')) {
|
||||||
this.show = false
|
this.show = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ export default {
|
|||||||
expirationDateString() {
|
expirationDateString() {
|
||||||
if (!this.expireDurationSeconds) return this.$strings.LabelPermanent
|
if (!this.expireDurationSeconds) return this.$strings.LabelPermanent
|
||||||
const dateMs = Date.now() + this.expireDurationSeconds * 1000
|
const dateMs = Date.now() + this.expireDurationSeconds * 1000
|
||||||
return this.$formatDatetime(dateMs, this.$store.state.serverSettings.dateFormat, this.$store.state.serverSettings.timeFormat)
|
return this.$formatDatetime(dateMs, this.$store.getters['getServerSetting']('dateFormat'), this.$store.getters['getServerSetting']('timeFormat'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
releasesToShow() {
|
releasesToShow() {
|
||||||
return this.versionData?.releasesToShow || []
|
return this.versionData?.releasesToShow || []
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ export default {
|
|||||||
media() {
|
media() {
|
||||||
return this.libraryItem.media || {}
|
return this.libraryItem.media || {}
|
||||||
},
|
},
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
userCanUpdate() {
|
userCanUpdate() {
|
||||||
return this.$store.getters['user/getUserCanUpdate']
|
return this.$store.getters['user/getUserCanUpdate']
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -74,19 +74,12 @@ export default {
|
|||||||
mediaTracks() {
|
mediaTracks() {
|
||||||
return this.media.tracks || []
|
return this.media.tracks || []
|
||||||
},
|
},
|
||||||
isSingleM4b() {
|
|
||||||
return this.mediaTracks.length === 1 && this.mediaTracks[0].metadata.ext.toLowerCase() === '.m4b'
|
|
||||||
},
|
|
||||||
chapters() {
|
chapters() {
|
||||||
return this.media.chapters || []
|
return this.media.chapters || []
|
||||||
},
|
},
|
||||||
showM4bDownload() {
|
showM4bDownload() {
|
||||||
if (!this.mediaTracks.length) return false
|
if (!this.mediaTracks.length) return false
|
||||||
return !this.isSingleM4b
|
return true
|
||||||
},
|
|
||||||
showMp3Split() {
|
|
||||||
if (!this.mediaTracks.length) return false
|
|
||||||
return this.isSingleM4b && this.chapters.length
|
|
||||||
},
|
},
|
||||||
queuedEmbedLIds() {
|
queuedEmbedLIds() {
|
||||||
return this.$store.state.tasks.queuedEmbedLIds || []
|
return this.$store.state.tasks.queuedEmbedLIds || []
|
||||||
|
|||||||
@@ -10,6 +10,12 @@
|
|||||||
<form @submit.prevent="submit" class="flex grow">
|
<form @submit.prevent="submit" class="flex grow">
|
||||||
<ui-text-input v-model="search" @input="inputUpdate" type="search" :placeholder="$strings.PlaceholderSearchEpisode" class="grow mr-2 text-sm md:text-base" />
|
<ui-text-input v-model="search" @input="inputUpdate" type="search" :placeholder="$strings.PlaceholderSearchEpisode" class="grow mr-2 text-sm md:text-base" />
|
||||||
</form>
|
</form>
|
||||||
|
<ui-btn :padding-x="4" @click="toggleSort">
|
||||||
|
<span class="pr-4">{{ $strings.LabelSortPubDate }}</span>
|
||||||
|
<span class="text-yellow-400 absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
|
<span class="material-symbols text-xl" :aria-label="sortDescending ? $strings.LabelSortDescending : $strings.LabelSortAscending">{{ sortDescending ? 'expand_more' : 'expand_less' }}</span>
|
||||||
|
</span>
|
||||||
|
</ui-btn>
|
||||||
</div>
|
</div>
|
||||||
<div ref="episodeContainer" id="episodes-scroll" class="w-full overflow-x-hidden overflow-y-auto">
|
<div ref="episodeContainer" id="episodes-scroll" class="w-full overflow-x-hidden overflow-y-auto">
|
||||||
<div v-for="(episode, index) in episodesList" :key="index" class="relative" :class="episode.isDownloaded || episode.isDownloading ? 'bg-primary/40' : selectedEpisodes[episode.cleanUrl] ? 'cursor-pointer bg-success/10' : index % 2 == 0 ? 'cursor-pointer bg-primary/25 hover:bg-primary/40' : 'cursor-pointer bg-primary/5 hover:bg-primary/25'" @click="toggleSelectEpisode(episode)">
|
<div v-for="(episode, index) in episodesList" :key="index" class="relative" :class="episode.isDownloaded || episode.isDownloading ? 'bg-primary/40' : selectedEpisodes[episode.cleanUrl] ? 'cursor-pointer bg-success/10' : index % 2 == 0 ? 'cursor-pointer bg-primary/25 hover:bg-primary/40' : 'cursor-pointer bg-primary/5 hover:bg-primary/25'" @click="toggleSelectEpisode(episode)">
|
||||||
@@ -29,7 +35,14 @@
|
|||||||
<widgets-podcast-type-indicator :type="episode.episodeType" />
|
<widgets-podcast-type-indicator :type="episode.episodeType" />
|
||||||
</div>
|
</div>
|
||||||
<p v-if="episode.subtitle" class="mb-1 text-sm text-gray-300 line-clamp-2">{{ episode.subtitle }}</p>
|
<p v-if="episode.subtitle" class="mb-1 text-sm text-gray-300 line-clamp-2">{{ episode.subtitle }}</p>
|
||||||
<p class="text-xs text-gray-300">Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}</p>
|
<div class="flex items-center space-x-2">
|
||||||
|
<!-- published -->
|
||||||
|
<p class="text-xs text-gray-300 w-40">Published {{ episode.publishedAt ? $dateDistanceFromNow(episode.publishedAt) : 'Unknown' }}</p>
|
||||||
|
<!-- duration -->
|
||||||
|
<p v-if="episode.durationSeconds && !isNaN(episode.durationSeconds)" class="text-xs text-gray-300 min-w-28">{{ $strings.LabelDuration }}: {{ $elapsedPretty(episode.durationSeconds) }}</p>
|
||||||
|
<!-- size -->
|
||||||
|
<p v-if="episode.enclosure?.length && !isNaN(episode.enclosure.length) && Number(episode.enclosure.length) > 0" class="text-xs text-gray-300">{{ $strings.LabelSize }}: {{ $bytesPretty(Number(episode.enclosure.length)) }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +86,8 @@ export default {
|
|||||||
searchTimeout: null,
|
searchTimeout: null,
|
||||||
searchText: null,
|
searchText: null,
|
||||||
downloadedEpisodeGuidMap: {},
|
downloadedEpisodeGuidMap: {},
|
||||||
downloadedEpisodeUrlMap: {}
|
downloadedEpisodeUrlMap: {},
|
||||||
|
sortDescending: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -141,6 +155,17 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
toggleSort() {
|
||||||
|
this.sortDescending = !this.sortDescending
|
||||||
|
this.episodesCleaned = this.episodesCleaned.toSorted((a, b) => {
|
||||||
|
if (this.sortDescending) {
|
||||||
|
return a.publishedAt < b.publishedAt ? 1 : -1
|
||||||
|
}
|
||||||
|
return a.publishedAt > b.publishedAt ? 1 : -1
|
||||||
|
})
|
||||||
|
this.selectedEpisodes = {}
|
||||||
|
this.selectAll = false
|
||||||
|
},
|
||||||
getIsEpisodeDownloaded(episode) {
|
getIsEpisodeDownloaded(episode) {
|
||||||
if (episode.guid && !!this.downloadedEpisodeGuidMap[episode.guid]) {
|
if (episode.guid && !!this.downloadedEpisodeGuidMap[episode.guid]) {
|
||||||
return true
|
return true
|
||||||
@@ -226,8 +251,8 @@ export default {
|
|||||||
const sizeInMb = payloadSize / 1024 / 1024
|
const sizeInMb = payloadSize / 1024 / 1024
|
||||||
const sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
|
const sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
|
||||||
console.log('Request size', sizeInMb)
|
console.log('Request size', sizeInMb)
|
||||||
if (sizeInMb > 4.99) {
|
if (sizeInMb > 9.99) {
|
||||||
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 5Mb`)
|
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 10Mb`)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processing = true
|
this.processing = true
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{{ $getString('MessageConfirmRemoveEpisode', [episodeTitle]) }}
|
{{ $getString('MessageConfirmRemoveEpisode', [episodeTitle]) }}
|
||||||
</p>
|
</p>
|
||||||
<p v-else class="text-lg text-gray-200 mb-4">{{ $getString('MessageConfirmRemoveEpisodes', [episodes.length]) }}</p>
|
<p v-else class="text-lg text-gray-200 mb-4">{{ $getString('MessageConfirmRemoveEpisodes', [episodes.length]) }}</p>
|
||||||
<p class="text-xs font-semibold text-warning/90">Note: This does not delete the audio file unless toggling "Hard delete file"</p>
|
<p class="text-xs font-semibold text-warning/90">{{ $strings.MessageConfirmRemoveEpisodeNote }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-center pt-4">
|
<div class="flex justify-between items-center pt-4">
|
||||||
<ui-checkbox v-model="hardDeleteFile" :label="$strings.LabelHardDeleteFile" check-color="error" checkbox-bg="bg" small label-class="text-base text-gray-200 pl-3" />
|
<ui-checkbox v-model="hardDeleteFile" :label="$strings.LabelHardDeleteFile" check-color="error" checkbox-bg="bg" small label-class="text-base text-gray-200 pl-3" />
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p dir="auto" class="text-lg font-semibold mb-6">{{ title }}</p>
|
<p dir="auto" class="text-lg font-semibold mb-6">{{ title }}</p>
|
||||||
<div v-if="description" dir="auto" class="default-style less-spacing" v-html="description" />
|
<div v-if="description" dir="auto" class="default-style less-spacing" @click="handleDescriptionClick" v-html="description" />
|
||||||
<p v-else class="mb-2">{{ $strings.MessageNoDescription }}</p>
|
<p v-else class="mb-2">{{ $strings.MessageNoDescription }}</p>
|
||||||
|
|
||||||
<div class="w-full h-px bg-white/5 my-4" />
|
<div class="w-full h-px bg-white/5 my-4" />
|
||||||
@@ -34,6 +34,12 @@
|
|||||||
{{ audioFileSize }}
|
{{ audioFileSize }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grow">
|
||||||
|
<p class="font-semibold text-xs mb-1">{{ $strings.LabelDuration }}</p>
|
||||||
|
<p class="mb-2 text-xs">
|
||||||
|
{{ audioFileDuration }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</modals-modal>
|
</modals-modal>
|
||||||
@@ -68,7 +74,7 @@ export default {
|
|||||||
return this.episode.title || 'No Episode Title'
|
return this.episode.title || 'No Episode Title'
|
||||||
},
|
},
|
||||||
description() {
|
description() {
|
||||||
return this.episode.description || ''
|
return this.parseDescription(this.episode.description || '')
|
||||||
},
|
},
|
||||||
media() {
|
media() {
|
||||||
return this.libraryItem?.media || {}
|
return this.libraryItem?.media || {}
|
||||||
@@ -90,11 +96,49 @@ export default {
|
|||||||
|
|
||||||
return this.$bytesPretty(size)
|
return this.$bytesPretty(size)
|
||||||
},
|
},
|
||||||
|
audioFileDuration() {
|
||||||
|
const duration = this.episode.duration || 0
|
||||||
|
return this.$elapsedPretty(duration)
|
||||||
|
},
|
||||||
bookCoverAspectRatio() {
|
bookCoverAspectRatio() {
|
||||||
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {},
|
methods: {
|
||||||
|
handleDescriptionClick(e) {
|
||||||
|
if (e.target.matches('span.time-marker')) {
|
||||||
|
const time = parseInt(e.target.dataset.time)
|
||||||
|
if (!isNaN(time)) {
|
||||||
|
this.$eventBus.$emit('play-item', {
|
||||||
|
episodeId: this.episodeId,
|
||||||
|
libraryItemId: this.libraryItem.id,
|
||||||
|
startTime: time
|
||||||
|
})
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parseDescription(description) {
|
||||||
|
const timeMarkerLinkRegex = /<a href="#([^"]*?\b\d{1,2}:\d{1,2}(?::\d{1,2})?)">(.*?)<\/a>/g
|
||||||
|
const timeMarkerRegex = /\b\d{1,2}:\d{1,2}(?::\d{1,2})?\b/g
|
||||||
|
|
||||||
|
function convertToSeconds(time) {
|
||||||
|
const timeParts = time.split(':').map(Number)
|
||||||
|
return timeParts.reduce((acc, part, index) => acc * 60 + part, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return description
|
||||||
|
.replace(timeMarkerLinkRegex, (match, href, displayTime) => {
|
||||||
|
const time = displayTime.match(timeMarkerRegex)[0]
|
||||||
|
const seekTimeInSeconds = convertToSeconds(time)
|
||||||
|
return `<span class="time-marker cursor-pointer text-blue-400 hover:text-blue-300" data-time="${seekTimeInSeconds}">${displayTime}</span>`
|
||||||
|
})
|
||||||
|
.replace(timeMarkerRegex, (match) => {
|
||||||
|
const seekTimeInSeconds = convertToSeconds(match)
|
||||||
|
return `<span class="time-marker cursor-pointer text-blue-400 hover:text-blue-300" data-time="${seekTimeInSeconds}">${match}</span>`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {}
|
mounted() {}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ export default {
|
|||||||
currentChapterStart() {
|
currentChapterStart() {
|
||||||
if (!this.currentChapter) return 0
|
if (!this.currentChapter) return 0
|
||||||
return this.currentChapter.start
|
return this.currentChapter.start
|
||||||
|
},
|
||||||
|
isMobile() {
|
||||||
|
return this.$store.state.globals.isMobile
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -145,6 +148,9 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
mousemoveTrack(e) {
|
mousemoveTrack(e) {
|
||||||
|
if (this.isMobile) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const offsetX = e.offsetX
|
const offsetX = e.offsetX
|
||||||
|
|
||||||
const baseTime = this.useChapterTrack ? this.currentChapterStart : 0
|
const baseTime = this.useChapterTrack ? this.currentChapterStart : 0
|
||||||
@@ -198,6 +204,7 @@ export default {
|
|||||||
setTrackWidth() {
|
setTrackWidth() {
|
||||||
if (this.$refs.track) {
|
if (this.$refs.track) {
|
||||||
this.trackWidth = this.$refs.track.clientWidth
|
this.trackWidth = this.$refs.track.clientWidth
|
||||||
|
this.trackOffsetLeft = this.$refs.track.getBoundingClientRect().left
|
||||||
} else {
|
} else {
|
||||||
console.error('Track not loaded', this.$refs)
|
console.error('Track not loaded', this.$refs)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ export default {
|
|||||||
return `${hoursRounded}h`
|
return `${hoursRounded}h`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
token() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
timeRemaining() {
|
timeRemaining() {
|
||||||
if (this.useChapterTrack && this.currentChapter) {
|
if (this.useChapterTrack && this.currentChapter) {
|
||||||
var currChapTime = this.currentTime - this.currentChapter.start
|
var currChapTime = this.currentTime - this.currentChapter.start
|
||||||
|
|||||||
@@ -104,9 +104,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem?.id
|
return this.libraryItem?.id
|
||||||
},
|
},
|
||||||
@@ -234,10 +231,7 @@ export default {
|
|||||||
async extract() {
|
async extract() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var buff = await this.$axios.$get(this.ebookUrl, {
|
var buff = await this.$axios.$get(this.ebookUrl, {
|
||||||
responseType: 'blob',
|
responseType: 'blob'
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${this.userToken}`
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
const archive = await Archive.open(buff)
|
const archive = await Archive.open(buff)
|
||||||
const originalFilesObject = await archive.getFilesObject()
|
const originalFilesObject = await archive.getFilesObject()
|
||||||
|
|||||||
@@ -57,9 +57,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
/** @returns {string} */
|
/** @returns {string} */
|
||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem?.id
|
return this.libraryItem?.id
|
||||||
@@ -97,9 +94,9 @@ export default {
|
|||||||
},
|
},
|
||||||
ebookUrl() {
|
ebookUrl() {
|
||||||
if (this.fileId) {
|
if (this.fileId) {
|
||||||
return `${this.$config.routerBasePath}/api/items/${this.libraryItemId}/ebook/${this.fileId}`
|
return `/api/items/${this.libraryItemId}/ebook/${this.fileId}`
|
||||||
}
|
}
|
||||||
return `${this.$config.routerBasePath}/api/items/${this.libraryItemId}/ebook`
|
return `/api/items/${this.libraryItemId}/ebook`
|
||||||
},
|
},
|
||||||
themeRules() {
|
themeRules() {
|
||||||
const isDark = this.ereaderSettings.theme === 'dark'
|
const isDark = this.ereaderSettings.theme === 'dark'
|
||||||
@@ -309,14 +306,24 @@ export default {
|
|||||||
/** @type {EpubReader} */
|
/** @type {EpubReader} */
|
||||||
const reader = this
|
const reader = this
|
||||||
|
|
||||||
|
// Use axios to make request because we have token refresh logic in interceptor
|
||||||
|
const customRequest = async (url) => {
|
||||||
|
try {
|
||||||
|
return this.$axios.$get(url, {
|
||||||
|
responseType: 'arraybuffer'
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('EpubReader.initEpub customRequest failed:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {ePub.Book} */
|
/** @type {ePub.Book} */
|
||||||
reader.book = new ePub(reader.ebookUrl, {
|
reader.book = new ePub(reader.ebookUrl, {
|
||||||
width: this.readerWidth,
|
width: this.readerWidth,
|
||||||
height: this.readerHeight - 50,
|
height: this.readerHeight - 50,
|
||||||
openAs: 'epub',
|
openAs: 'epub',
|
||||||
requestHeaders: {
|
requestMethod: customRequest
|
||||||
Authorization: `Bearer ${this.userToken}`
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/** @type {ePub.Rendition} */
|
/** @type {ePub.Rendition} */
|
||||||
@@ -337,29 +344,33 @@ export default {
|
|||||||
this.applyTheme()
|
this.applyTheme()
|
||||||
})
|
})
|
||||||
|
|
||||||
reader.book.ready.then(() => {
|
reader.book.ready
|
||||||
// set up event listeners
|
.then(() => {
|
||||||
reader.rendition.on('relocated', reader.relocated)
|
// set up event listeners
|
||||||
reader.rendition.on('keydown', reader.keyUp)
|
reader.rendition.on('relocated', reader.relocated)
|
||||||
|
reader.rendition.on('keydown', reader.keyUp)
|
||||||
|
|
||||||
reader.rendition.on('touchstart', (event) => {
|
reader.rendition.on('touchstart', (event) => {
|
||||||
this.$emit('touchstart', event)
|
this.$emit('touchstart', event)
|
||||||
})
|
|
||||||
reader.rendition.on('touchend', (event) => {
|
|
||||||
this.$emit('touchend', event)
|
|
||||||
})
|
|
||||||
|
|
||||||
// load ebook cfi locations
|
|
||||||
const savedLocations = this.loadLocations()
|
|
||||||
if (savedLocations) {
|
|
||||||
reader.book.locations.load(savedLocations)
|
|
||||||
} else {
|
|
||||||
reader.book.locations.generate().then(() => {
|
|
||||||
this.checkSaveLocations(reader.book.locations.save())
|
|
||||||
})
|
})
|
||||||
}
|
reader.rendition.on('touchend', (event) => {
|
||||||
this.getChapters()
|
this.$emit('touchend', event)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// load ebook cfi locations
|
||||||
|
const savedLocations = this.loadLocations()
|
||||||
|
if (savedLocations) {
|
||||||
|
reader.book.locations.load(savedLocations)
|
||||||
|
} else {
|
||||||
|
reader.book.locations.generate().then(() => {
|
||||||
|
this.checkSaveLocations(reader.book.locations.save())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.getChapters()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('EpubReader.initEpub failed:', error)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
getChapters() {
|
getChapters() {
|
||||||
// Load the list of chapters in the book. See https://github.com/futurepress/epub.js/issues/759
|
// Load the list of chapters in the book. See https://github.com/futurepress/epub.js/issues/759
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ export default {
|
|||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem?.id
|
return this.libraryItem?.id
|
||||||
},
|
},
|
||||||
@@ -96,11 +93,8 @@ export default {
|
|||||||
},
|
},
|
||||||
async initMobi() {
|
async initMobi() {
|
||||||
// Fetch mobi file as blob
|
// Fetch mobi file as blob
|
||||||
var buff = await this.$axios.$get(this.ebookUrl, {
|
const buff = await this.$axios.$get(this.ebookUrl, {
|
||||||
responseType: 'blob',
|
responseType: 'blob'
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${this.userToken}`
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
var reader = new FileReader()
|
var reader = new FileReader()
|
||||||
reader.onload = async (event) => {
|
reader.onload = async (event) => {
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ export default {
|
|||||||
loadedRatio: 0,
|
loadedRatio: 0,
|
||||||
page: 1,
|
page: 1,
|
||||||
numPages: 0,
|
numPages: 0,
|
||||||
pdfDocInitParams: null
|
pdfDocInitParams: null,
|
||||||
|
isRefreshing: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -152,7 +153,34 @@ export default {
|
|||||||
this.page++
|
this.page++
|
||||||
this.updateProgress()
|
this.updateProgress()
|
||||||
},
|
},
|
||||||
error(err) {
|
async refreshToken() {
|
||||||
|
if (this.isRefreshing) return
|
||||||
|
this.isRefreshing = true
|
||||||
|
const newAccessToken = await this.$store.dispatch('user/refreshToken').catch((error) => {
|
||||||
|
console.error('Failed to refresh token', error)
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
if (!newAccessToken) {
|
||||||
|
// Redirect to login on failed refresh
|
||||||
|
this.$router.push('/login')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force Vue to re-render the PDF component by creating a new object
|
||||||
|
this.pdfDocInitParams = {
|
||||||
|
url: this.ebookUrl,
|
||||||
|
httpHeaders: {
|
||||||
|
Authorization: `Bearer ${newAccessToken}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.isRefreshing = false
|
||||||
|
},
|
||||||
|
async error(err) {
|
||||||
|
if (err && err.status === 401) {
|
||||||
|
console.log('Received 401 error, refreshing token')
|
||||||
|
await this.refreshToken()
|
||||||
|
return
|
||||||
|
}
|
||||||
console.error(err)
|
console.error(err)
|
||||||
},
|
},
|
||||||
resize() {
|
resize() {
|
||||||
|
|||||||
@@ -266,9 +266,6 @@ export default {
|
|||||||
isComic() {
|
isComic() {
|
||||||
return this.ebookFormat == 'cbz' || this.ebookFormat == 'cbr'
|
return this.ebookFormat == 'cbz' || this.ebookFormat == 'cbr'
|
||||||
},
|
},
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
keepProgress() {
|
keepProgress() {
|
||||||
return this.$store.state.ereaderKeepProgress
|
return this.$store.state.ereaderKeepProgress
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -164,14 +164,15 @@ export default {
|
|||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.yearInReviewYear = new Date().getFullYear()
|
this.yearInReviewYear = new Date().getFullYear()
|
||||||
|
|
||||||
// When not December show previous year
|
this.availableYears = this.getAvailableYears()
|
||||||
if (new Date().getMonth() < 11) {
|
const availableYearValues = this.availableYears.map((y) => y.value)
|
||||||
|
|
||||||
|
// When not December show previous year if data is available
|
||||||
|
if (new Date().getMonth() < 11 && availableYearValues.includes(this.yearInReviewYear - 1)) {
|
||||||
this.yearInReviewYear--
|
this.yearInReviewYear--
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.availableYears = this.getAvailableYears()
|
|
||||||
|
|
||||||
if (typeof navigator.share !== 'undefined' && navigator.share) {
|
if (typeof navigator.share !== 'undefined' && navigator.share) {
|
||||||
this.showShareButton = true
|
this.showShareButton = true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,177 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="text-center">
|
||||||
|
<table v-if="apiKeys.length > 0" id="api-keys">
|
||||||
|
<tr>
|
||||||
|
<th>{{ $strings.LabelName }}</th>
|
||||||
|
<th class="w-44">{{ $strings.LabelApiKeyUser }}</th>
|
||||||
|
<th class="w-32">{{ $strings.LabelExpiresAt }}</th>
|
||||||
|
<th class="w-32">{{ $strings.LabelCreatedAt }}</th>
|
||||||
|
<th class="w-32"></th>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="apiKey in apiKeys" :key="apiKey.id" :class="apiKey.isActive ? '' : 'bg-error/10!'">
|
||||||
|
<td>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<p class="pl-2 truncate">{{ apiKey.name }}</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="text-xs">
|
||||||
|
<nuxt-link v-if="apiKey.user" :to="`/config/users/${apiKey.user.id}`" class="text-xs hover:underline">
|
||||||
|
{{ apiKey.user.username }}
|
||||||
|
</nuxt-link>
|
||||||
|
<p v-else class="text-xs">Error</p>
|
||||||
|
</td>
|
||||||
|
<td class="text-xs">
|
||||||
|
<p v-if="apiKey.expiresAt" class="text-xs" :title="apiKey.expiresAt">{{ getExpiresAtText(apiKey) }}</p>
|
||||||
|
<p v-else class="text-xs">{{ $strings.LabelExpiresNever }}</p>
|
||||||
|
</td>
|
||||||
|
<td class="text-xs font-mono">
|
||||||
|
<ui-tooltip direction="top" :text="$formatJsDatetime(new Date(apiKey.createdAt), dateFormat, timeFormat)">
|
||||||
|
{{ $formatJsDate(new Date(apiKey.createdAt), dateFormat) }}
|
||||||
|
</ui-tooltip>
|
||||||
|
</td>
|
||||||
|
<td class="py-0">
|
||||||
|
<div class="w-full flex justify-left">
|
||||||
|
<div class="h-8 w-8 flex items-center justify-center text-white/50 hover:text-white/100 cursor-pointer" @click.stop="editApiKey(apiKey)">
|
||||||
|
<button type="button" :aria-label="$strings.ButtonEdit" class="material-symbols text-base">edit</button>
|
||||||
|
</div>
|
||||||
|
<div class="h-8 w-8 flex items-center justify-center text-white/50 hover:text-error cursor-pointer" @click.stop="deleteApiKeyClick(apiKey)">
|
||||||
|
<button type="button" :aria-label="$strings.ButtonDelete" class="material-symbols text-base">delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p v-else class="text-base text-gray-300 py-4">{{ $strings.LabelNoApiKeys }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
apiKeys: [],
|
||||||
|
isDeletingApiKey: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dateFormat() {
|
||||||
|
return this.$store.state.serverSettings.dateFormat
|
||||||
|
},
|
||||||
|
timeFormat() {
|
||||||
|
return this.$store.state.serverSettings.timeFormat
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getExpiresAtText(apiKey) {
|
||||||
|
if (new Date(apiKey.expiresAt).getTime() < Date.now()) {
|
||||||
|
return this.$strings.LabelExpired
|
||||||
|
}
|
||||||
|
return this.$formatJsDatetime(new Date(apiKey.expiresAt), this.dateFormat, this.timeFormat)
|
||||||
|
},
|
||||||
|
deleteApiKeyClick(apiKey) {
|
||||||
|
if (this.isDeletingApiKey) return
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
message: this.$getString('MessageConfirmDeleteApiKey', [apiKey.name]),
|
||||||
|
callback: (confirmed) => {
|
||||||
|
if (confirmed) {
|
||||||
|
this.deleteApiKey(apiKey)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: 'yesNo'
|
||||||
|
}
|
||||||
|
this.$store.commit('globals/setConfirmPrompt', payload)
|
||||||
|
},
|
||||||
|
deleteApiKey(apiKey) {
|
||||||
|
this.isDeletingApiKey = true
|
||||||
|
this.$axios
|
||||||
|
.$delete(`/api/api-keys/${apiKey.id}`)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.error) {
|
||||||
|
this.$toast.error(data.error)
|
||||||
|
} else {
|
||||||
|
this.removeApiKey(apiKey.id)
|
||||||
|
this.$emit('numApiKeys', this.apiKeys.length)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Failed to delete apiKey', error)
|
||||||
|
this.$toast.error(this.$strings.ToastFailedToDelete)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.isDeletingApiKey = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
editApiKey(apiKey) {
|
||||||
|
this.$emit('edit', apiKey)
|
||||||
|
},
|
||||||
|
addApiKey(apiKey) {
|
||||||
|
this.apiKeys.push(apiKey)
|
||||||
|
},
|
||||||
|
removeApiKey(apiKeyId) {
|
||||||
|
this.apiKeys = this.apiKeys.filter((a) => a.id !== apiKeyId)
|
||||||
|
},
|
||||||
|
updateApiKey(apiKey) {
|
||||||
|
this.apiKeys = this.apiKeys.map((a) => (a.id === apiKey.id ? apiKey : a))
|
||||||
|
},
|
||||||
|
loadApiKeys() {
|
||||||
|
this.$axios
|
||||||
|
.$get('/api/api-keys')
|
||||||
|
.then((res) => {
|
||||||
|
this.apiKeys = res.apiKeys.sort((a, b) => {
|
||||||
|
return a.createdAt - b.createdAt
|
||||||
|
})
|
||||||
|
this.$emit('numApiKeys', this.apiKeys.length)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Failed to load apiKeys', error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadApiKeys()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#api-keys {
|
||||||
|
table-layout: fixed;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 1px solid #474747;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-keys td,
|
||||||
|
#api-keys th {
|
||||||
|
/* border: 1px solid #2e2e2e; */
|
||||||
|
padding: 8px 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-keys td.py-0 {
|
||||||
|
padding: 0px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-keys tr:nth-child(even) {
|
||||||
|
background-color: #373838;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-keys tr:nth-child(odd) {
|
||||||
|
background-color: #2f2f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-keys tr:hover {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-keys th {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
background-color: #272727;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
<span class="material-symbols text-2xl text-error">error_outline</span>
|
<span class="material-symbols text-2xl text-error">error_outline</span>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
|
|
||||||
<button aria-label="Download Backup" class="inline-flex material-symbols text-xl mx-1 mt-1 text-white/70 hover:text-white/100" @click.stop="downloadBackup(backup)">download</button>
|
<button aria-label="Download backup" class="inline-flex material-symbols text-xl mx-1 mt-1 text-white/70 hover:text-white/100" @click.stop="downloadBackup(backup)">download</button>
|
||||||
|
|
||||||
<button aria-label="Delete Backup" class="inline-flex material-symbols text-xl mx-1 text-white/70 hover:text-error" @click.stop="deleteBackupClick(backup)">delete</button>
|
<button aria-label="Delete backup" class="inline-flex material-symbols text-xl mx-1 text-white/70 hover:text-error" @click.stop="deleteBackupClick(backup)">delete</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -78,10 +78,10 @@ export default {
|
|||||||
return this.$store.getters['user/getToken']
|
return this.$store.getters['user/getToken']
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ export default {
|
|||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem.id
|
return this.libraryItem.id
|
||||||
},
|
},
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
userCanDownload() {
|
userCanDownload() {
|
||||||
return this.$store.getters['user/getUserCanDownload']
|
return this.$store.getters['user/getUserCanDownload']
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -53,9 +53,6 @@ export default {
|
|||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem.id
|
return this.libraryItem.id
|
||||||
},
|
},
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
userCanDownload() {
|
userCanDownload() {
|
||||||
return this.$store.getters['user/getUserCanDownload']
|
return this.$store.getters['user/getUserCanDownload']
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -76,10 +76,10 @@ export default {
|
|||||||
return usermap
|
return usermap
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export default {
|
|||||||
return this.episode?.publishedAt
|
return this.episode?.publishedAt
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.store.state.serverSettings.dateFormat
|
return this.store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
itemProgress() {
|
itemProgress() {
|
||||||
return this.store.getters['user/getUserMediaProgress'](this.libraryItemId, this.episodeId)
|
return this.store.getters['user/getUserMediaProgress'](this.libraryItemId, this.episodeId)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="lazy-episodes-table" class="w-full py-6">
|
<div id="lazy-episodes-table" class="w-full py-6">
|
||||||
<div class="flex flex-wrap flex-col md:flex-row md:items-center mb-4">
|
<div class="flex flex-wrap flex-col md:flex-row md:items-center mb-4">
|
||||||
@@ -176,6 +175,13 @@ export default {
|
|||||||
return episodeProgress && !episodeProgress.isFinished
|
return episodeProgress && !episodeProgress.isFinished
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
|
// Swap values if sort descending
|
||||||
|
if (this.sortDesc) {
|
||||||
|
const temp = a
|
||||||
|
a = b
|
||||||
|
b = temp
|
||||||
|
}
|
||||||
|
|
||||||
let aValue
|
let aValue
|
||||||
let bValue
|
let bValue
|
||||||
|
|
||||||
@@ -194,10 +200,23 @@ export default {
|
|||||||
if (!bValue) bValue = Number.MAX_VALUE
|
if (!bValue) bValue = Number.MAX_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.sortDesc) {
|
const primaryCompare = String(aValue).localeCompare(String(bValue), undefined, { numeric: true, sensitivity: 'base' })
|
||||||
return String(bValue).localeCompare(String(aValue), undefined, { numeric: true, sensitivity: 'base' })
|
if (primaryCompare !== 0 || this.sortKey === 'publishedAt') return primaryCompare
|
||||||
|
|
||||||
|
// When sorting by season, secondary sort is by episode number
|
||||||
|
if (this.sortKey === 'season') {
|
||||||
|
const aEpisode = a.episode || ''
|
||||||
|
const bEpisode = b.episode || ''
|
||||||
|
|
||||||
|
const secondaryCompare = String(aEpisode).localeCompare(String(bEpisode), undefined, { numeric: true, sensitivity: 'base' })
|
||||||
|
if (secondaryCompare !== 0) return secondaryCompare
|
||||||
}
|
}
|
||||||
return String(aValue).localeCompare(String(bValue), undefined, { numeric: true, sensitivity: 'base' })
|
|
||||||
|
// Final sort by publishedAt
|
||||||
|
let aPubDate = a.publishedAt || Number.MAX_VALUE
|
||||||
|
let bPubDate = b.publishedAt || Number.MAX_VALUE
|
||||||
|
|
||||||
|
return String(aPubDate).localeCompare(String(bPubDate), undefined, { numeric: true, sensitivity: 'base' })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
episodesList() {
|
episodesList() {
|
||||||
@@ -220,10 +239,10 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -85,9 +85,6 @@ export default {
|
|||||||
this.$emit('input', val)
|
this.$emit('input', val)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
userToken() {
|
|
||||||
return this.$store.getters['user/getToken']
|
|
||||||
},
|
|
||||||
wrapperClass() {
|
wrapperClass() {
|
||||||
var classes = []
|
var classes = []
|
||||||
if (this.disabled) classes.push('bg-black-300')
|
if (this.disabled) classes.push('bg-black-300')
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative w-full">
|
<div class="relative w-full">
|
||||||
<p v-if="label" class="text-sm font-semibold px-1" :class="disabled ? 'text-gray-300' : ''">{{ label }}</p>
|
<p v-if="label && !labelHidden" class="text-sm font-semibold px-1" :class="disabled ? 'text-gray-300' : ''">{{ label }}</p>
|
||||||
<button ref="buttonWrapper" type="button" :aria-label="longLabel" :disabled="disabled" class="relative w-full border rounded-sm shadow-xs pl-3 pr-8 py-2 text-left sm:text-sm" :class="buttonClass" aria-haspopup="listbox" aria-expanded="true" @click.stop.prevent="clickShowMenu">
|
<button ref="buttonWrapper" type="button" :aria-label="longLabel" :disabled="disabled" class="relative w-full border rounded-sm shadow-xs pl-3 pr-8 py-2 text-left sm:text-sm" :class="buttonClass" aria-haspopup="listbox" aria-expanded="true" @click.stop.prevent="clickShowMenu">
|
||||||
<span class="flex items-center">
|
<span class="flex items-center">
|
||||||
<span class="block truncate font-sans" :class="{ 'font-semibold': selectedSubtext, 'text-sm': small }">{{ selectedText }}</span>
|
<span class="block truncate font-sans" :class="{ 'font-semibold': selectedSubtext, 'text-sm': small, 'text-gray-400': !selectedText }">{{ selectedText || placeholder }}</span>
|
||||||
<span v-if="selectedSubtext">: </span>
|
<span v-if="selectedSubtext">: </span>
|
||||||
<span v-if="selectedSubtext" class="font-normal block truncate font-sans text-sm text-gray-400">{{ selectedSubtext }}</span>
|
<span v-if="selectedSubtext" class="font-normal block truncate font-sans text-sm text-gray-400">{{ selectedSubtext }}</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -36,10 +36,15 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
labelHidden: Boolean,
|
||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
small: Boolean,
|
small: Boolean,
|
||||||
menuMaxHeight: {
|
menuMaxHeight: {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<em v-if="note" class="font-normal text-xs pl-2">{{ note }}</em>
|
<em v-if="note" class="font-normal text-xs pl-2">{{ note }}</em>
|
||||||
</label>
|
</label>
|
||||||
</slot>
|
</slot>
|
||||||
<ui-text-input :placeholder="placeholder || label" :inputId="identifier" ref="input" v-model="inputValue" :disabled="disabled" :readonly="readonly" :type="type" :show-copy="showCopy" class="w-full" :class="inputClass" :trim-whitespace="trimWhitespace" @blur="inputBlurred" />
|
<ui-text-input :placeholder="placeholder || label" :inputId="identifier" ref="input" v-model="inputValue" :disabled="disabled" :readonly="readonly" :type="type" :min="min" :show-copy="showCopy" class="w-full" :class="inputClass" :trim-whitespace="trimWhitespace" @blur="inputBlurred" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: 'text'
|
default: 'text'
|
||||||
},
|
},
|
||||||
|
min: [String, Number],
|
||||||
readonly: Boolean,
|
readonly: Boolean,
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
inputClass: String,
|
inputClass: String,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="inline-flex toggle-btn-wrapper shadow-md">
|
<div class="inline-flex toggle-btn-wrapper shadow-md">
|
||||||
<button v-for="item in items" :key="item.value" type="button" class="toggle-btn outline-hidden relative border border-gray-600 px-4 py-1" :class="{ selected: item.value === value }" @click.stop="clickBtn(item.value)">
|
<button v-for="item in items" :key="item.value" type="button" :disabled="disabled" class="toggle-btn outline-hidden relative border border-gray-600 px-4 py-1" :class="{ selected: item.value === value }" @click.stop="clickBtn(item.value)">
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -9,13 +9,17 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
value: String,
|
value: [String, Number],
|
||||||
/**
|
/**
|
||||||
* [{ "text", "", "value": "" }]
|
* [{ "text", "", "value": "" }]
|
||||||
*/
|
*/
|
||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: Object
|
default: Object
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -76,10 +80,19 @@ export default {
|
|||||||
.toggle-btn.selected {
|
.toggle-btn.selected {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
.toggle-btn.selected:disabled {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.toggle-btn.selected::before {
|
.toggle-btn.selected::before {
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
button.toggle-btn.selected:disabled::before {
|
||||||
|
background-color: rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
button.toggle-btn:disabled::before {
|
button.toggle-btn:disabled::before {
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
button.toggle-btn:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</trix-toolbar>
|
</trix-toolbar>
|
||||||
<trix-editor :toolbar="toolbarId" :contenteditable="!disabledEditor" :class="['trix-content']" ref="trix" :input="computedId" :placeholder="placeholder" @trix-change="handleContentChange" @trix-initialize="handleInitialize" @trix-focus="processTrixFocus" @trix-blur="processTrixBlur" />
|
<trix-editor :toolbar="toolbarId" :contenteditable="!disabledEditor" :class="['trix-content']" ref="trix" :input="computedId" :placeholder="placeholder" @trix-change="handleContentChange" @trix-initialize="handleInitialize" @trix-focus="processTrixFocus" @trix-blur="processTrixBlur" @trix-attachment-add="handleAttachmentAdd" />
|
||||||
<input type="hidden" :name="inputName" :id="computedId" :value="editorContent" />
|
<input type="hidden" :name="inputName" :id="computedId" :value="editorContent" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -316,6 +316,10 @@ export default {
|
|||||||
if (this.$refs.trix && this.$refs.trix.blur) {
|
if (this.$refs.trix && this.$refs.trix.blur) {
|
||||||
this.$refs.trix.blur()
|
this.$refs.trix.blur()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
handleAttachmentAdd(event) {
|
||||||
|
// Prevent pasting in images/any files from the browser
|
||||||
|
event.attachment.remove()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default {
|
|||||||
nextRun() {
|
nextRun() {
|
||||||
if (!this.cronExpression) return ''
|
if (!this.cronExpression) return ''
|
||||||
const parsed = this.$getNextScheduledDate(this.cronExpression)
|
const parsed = this.$getNextScheduledDate(this.cronExpression)
|
||||||
return this.$formatJsDatetime(parsed, this.$store.state.serverSettings.dateFormat, this.$store.state.serverSettings.timeFormat) || ''
|
return this.$formatJsDatetime(parsed, this.$store.getters['getServerSetting']('dateFormat'), this.$store.getters['getServerSetting']('timeFormat')) || ''
|
||||||
},
|
},
|
||||||
description() {
|
description() {
|
||||||
if ((this.selectedInterval !== 'custom' || !this.selectedWeekdays.length) && this.selectedInterval !== 'daily') return ''
|
if ((this.selectedInterval !== 'custom' || !this.selectedWeekdays.length) && this.selectedInterval !== 'daily') return ''
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-full py-2">
|
||||||
|
<div class="flex -mb-px">
|
||||||
|
<button type="button" :disabled="disabled" class="w-1/2 h-8 rounded-tl-md relative border border-black-200 flex items-center justify-center disabled:cursor-not-allowed" :class="!showAdvancedView ? 'text-white bg-bg hover:bg-bg/60 border-b-bg' : 'text-gray-400 hover:text-gray-300 bg-primary/70 hover:bg-primary/60'" @click="showAdvancedView = false">
|
||||||
|
<p class="text-sm">{{ $strings.HeaderPresets }}</p>
|
||||||
|
</button>
|
||||||
|
<button type="button" :disabled="disabled" class="w-1/2 h-8 rounded-tr-md relative border border-black-200 flex items-center justify-center -ml-px disabled:cursor-not-allowed" :class="showAdvancedView ? 'text-white bg-bg hover:bg-bg/60 border-b-bg' : 'text-gray-400 hover:text-gray-300 bg-primary/70 hover:bg-primary/60'" @click="showAdvancedView = true">
|
||||||
|
<p class="text-sm">{{ $strings.HeaderAdvanced }}</p>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 md:p-8 border border-black-200 rounded-b-md mr-px bg-bg">
|
||||||
|
<template v-if="!showAdvancedView">
|
||||||
|
<div class="flex flex-wrap gap-4 sm:gap-8 justify-start sm:justify-center">
|
||||||
|
<div class="flex flex-col items-start gap-2">
|
||||||
|
<p class="text-sm w-40">{{ $strings.LabelCodec }}</p>
|
||||||
|
<ui-toggle-btns v-model="selectedCodec" :items="codecItems" :disabled="disabled" />
|
||||||
|
<p class="text-xs text-gray-300">
|
||||||
|
{{ $strings.LabelCurrently }} <span class="text-white">{{ currentCodec }}</span> <span v-if="isCodecsDifferent" class="text-warning">(mixed)</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-start gap-2">
|
||||||
|
<p class="text-sm w-40">{{ $strings.LabelBitrate }}</p>
|
||||||
|
<ui-toggle-btns v-model="selectedBitrate" :items="bitrateItems" :disabled="disabled" />
|
||||||
|
<p class="text-xs text-gray-300">
|
||||||
|
{{ $strings.LabelCurrently }} <span class="text-white">{{ currentBitrate }} KB/s</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-start gap-2">
|
||||||
|
<p class="text-sm w-40">{{ $strings.LabelChannels }}</p>
|
||||||
|
<ui-toggle-btns v-model="selectedChannels" :items="channelsItems" :disabled="disabled" />
|
||||||
|
<p class="text-xs text-gray-300">
|
||||||
|
{{ $strings.LabelCurrently }} <span class="text-white">{{ currentChannels }} ({{ currentChanelLayout }})</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-wrap gap-4 sm:gap-8 justify-start sm:justify-center mb-4">
|
||||||
|
<div class="w-40">
|
||||||
|
<ui-text-input-with-label v-model="customCodec" :label="$strings.LabelAudioCodec" :disabled="disabled" @input="customCodecChanged" />
|
||||||
|
</div>
|
||||||
|
<div class="w-40">
|
||||||
|
<ui-text-input-with-label v-model="customBitrate" :label="$strings.LabelAudioBitrate" :disabled="disabled" @input="customBitrateChanged" />
|
||||||
|
</div>
|
||||||
|
<div class="w-40">
|
||||||
|
<ui-text-input-with-label v-model="customChannels" :label="$strings.LabelAudioChannels" type="number" :disabled="disabled" @input="customChannelsChanged" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs sm:text-sm text-warning sm:text-center">{{ $strings.LabelEncodingWarningAdvancedSettings }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
audioTracks: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showAdvancedView: false,
|
||||||
|
selectedCodec: 'aac',
|
||||||
|
selectedBitrate: '128k',
|
||||||
|
selectedChannels: 2,
|
||||||
|
customCodec: 'aac',
|
||||||
|
customBitrate: '128k',
|
||||||
|
customChannels: 2,
|
||||||
|
currentCodec: '',
|
||||||
|
currentBitrate: '',
|
||||||
|
currentChannels: '',
|
||||||
|
currentChanelLayout: '',
|
||||||
|
isCodecsDifferent: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
codecItems() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
text: 'Copy',
|
||||||
|
value: 'copy'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'AAC',
|
||||||
|
value: 'aac'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'OPUS',
|
||||||
|
value: 'opus'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
bitrateItems() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
text: '32k',
|
||||||
|
value: '32k'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '64k',
|
||||||
|
value: '64k'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '128k',
|
||||||
|
value: '128k'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '192k',
|
||||||
|
value: '192k'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
channelsItems() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
text: '1 (mono)',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '2 (stereo)',
|
||||||
|
value: 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
customBitrateChanged(val) {
|
||||||
|
localStorage.setItem('embedMetadataBitrate', val)
|
||||||
|
},
|
||||||
|
customChannelsChanged(val) {
|
||||||
|
localStorage.setItem('embedMetadataChannels', val)
|
||||||
|
},
|
||||||
|
customCodecChanged(val) {
|
||||||
|
localStorage.setItem('embedMetadataCodec', val)
|
||||||
|
},
|
||||||
|
getEncodingOptions() {
|
||||||
|
if (this.showAdvancedView) {
|
||||||
|
return {
|
||||||
|
codec: this.customCodec || this.selectedCodec || 'aac',
|
||||||
|
bitrate: this.customBitrate || this.selectedBitrate || '128k',
|
||||||
|
channels: this.customChannels || this.selectedChannels || 2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
codec: this.selectedCodec || 'aac',
|
||||||
|
bitrate: this.selectedBitrate || '128k',
|
||||||
|
channels: this.selectedChannels || 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setPreset() {
|
||||||
|
// If already AAC and not mixed, set copy
|
||||||
|
if (this.currentCodec === 'aac' && !this.isCodecsDifferent) {
|
||||||
|
this.selectedCodec = 'copy'
|
||||||
|
} else {
|
||||||
|
this.selectedCodec = 'aac'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.currentBitrate) {
|
||||||
|
this.selectedBitrate = '128k'
|
||||||
|
} else {
|
||||||
|
// Find closest bitrate rounding up
|
||||||
|
const bitratesToMatch = [32, 64, 128, 192]
|
||||||
|
const closestBitrate = bitratesToMatch.find((bitrate) => bitrate >= this.currentBitrate) || 192
|
||||||
|
this.selectedBitrate = closestBitrate + 'k'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.currentChannels || isNaN(this.currentChannels)) {
|
||||||
|
this.selectedChannels = 2
|
||||||
|
} else {
|
||||||
|
// Either 1 or 2
|
||||||
|
this.selectedChannels = Math.max(Math.min(Number(this.currentChannels), 2), 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setCurrentValues() {
|
||||||
|
if (this.audioTracks.length === 0) return
|
||||||
|
|
||||||
|
this.currentChannels = this.audioTracks[0].channels
|
||||||
|
this.currentChanelLayout = this.audioTracks[0].channelLayout
|
||||||
|
this.currentCodec = this.audioTracks[0].codec
|
||||||
|
|
||||||
|
let totalBitrate = 0
|
||||||
|
for (const track of this.audioTracks) {
|
||||||
|
const trackBitrate = !isNaN(track.bitRate) ? track.bitRate : 0
|
||||||
|
totalBitrate += trackBitrate
|
||||||
|
|
||||||
|
if (track.channels > this.currentChannels) this.currentChannels = track.channels
|
||||||
|
if (track.codec !== this.currentCodec) {
|
||||||
|
console.warn('Audio track codec is different from the first track', track.codec)
|
||||||
|
this.isCodecsDifferent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentBitrate = Math.round(totalBitrate / this.audioTracks.length / 1000)
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
this.customBitrate = localStorage.getItem('embedMetadataBitrate') || '128k'
|
||||||
|
this.customChannels = localStorage.getItem('embedMetadataChannels') || 2
|
||||||
|
this.customCodec = localStorage.getItem('embedMetadataCodec') || 'aac'
|
||||||
|
|
||||||
|
this.setCurrentValues()
|
||||||
|
|
||||||
|
this.setPreset()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<ui-multi-select-query-input v-model="seriesItems" text-key="displayName" :label="$strings.LabelSeries" :disabled="disabled" readonly show-edit @edit="editSeriesItem" @add="addNewSeries" />
|
<ui-multi-select-query-input v-model="seriesItems" text-key="displayName" :label="$strings.LabelSeries" :disabled="disabled" readonly show-edit @edit="editSeriesItem" @add="addNewSeries" />
|
||||||
|
|
||||||
<modals-edit-series-input-inner-modal v-model="showSeriesForm" :selected-series="selectedSeries" :existing-series-names="existingSeriesNames" @submit="submitSeriesForm" />
|
<modals-edit-series-input-inner-modal v-model="showSeriesForm" :selected-series="selectedSeries" :existing-series-names="existingSeriesNames" :original-series-sequence="originalSeriesSequence" @submit="submitSeriesForm" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedSeries: null,
|
selectedSeries: null,
|
||||||
|
originalSeriesSequence: null,
|
||||||
showSeriesForm: false
|
showSeriesForm: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -59,6 +60,7 @@ export default {
|
|||||||
..._series
|
..._series
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.originalSeriesSequence = _series.sequence
|
||||||
this.showSeriesForm = true
|
this.showSeriesForm = true
|
||||||
},
|
},
|
||||||
addNewSeries() {
|
addNewSeries() {
|
||||||
@@ -68,6 +70,7 @@ export default {
|
|||||||
sequence: ''
|
sequence: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.originalSeriesSequence = null
|
||||||
this.showSeriesForm = true
|
this.showSeriesForm = true
|
||||||
},
|
},
|
||||||
submitSeriesForm() {
|
submitSeriesForm() {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ describe('LazySeriesCard', () => {
|
|||||||
},
|
},
|
||||||
$store: {
|
$store: {
|
||||||
getters: {
|
getters: {
|
||||||
|
getServerSetting: () => 'MM/dd/yyyy',
|
||||||
'user/getUserCanUpdate': true,
|
'user/getUserCanUpdate': true,
|
||||||
'user/getUserMediaProgress': (id) => null,
|
'user/getUserMediaProgress': (id) => null,
|
||||||
'user/getSizeMultiplier': 1,
|
'user/getSizeMultiplier': 1,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
socket: null,
|
socket: null,
|
||||||
isSocketConnected: false,
|
isSocketConnected: false,
|
||||||
|
isSocketAuthenticated: false,
|
||||||
isFirstSocketConnection: true,
|
isFirstSocketConnection: true,
|
||||||
socketConnectionToastId: null,
|
socketConnectionToastId: null,
|
||||||
currentLang: null,
|
currentLang: null,
|
||||||
@@ -81,9 +82,28 @@ export default {
|
|||||||
document.body.classList.add('app-bar')
|
document.body.classList.add('app-bar')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
tokenRefreshed(newAccessToken) {
|
||||||
|
if (this.isSocketConnected && !this.isSocketAuthenticated) {
|
||||||
|
console.log('[SOCKET] Re-authenticating socket after token refresh')
|
||||||
|
this.socket.emit('auth', newAccessToken)
|
||||||
|
}
|
||||||
|
},
|
||||||
updateSocketConnectionToast(content, type, timeout) {
|
updateSocketConnectionToast(content, type, timeout) {
|
||||||
if (this.socketConnectionToastId !== null && this.socketConnectionToastId !== undefined) {
|
if (this.socketConnectionToastId !== null && this.socketConnectionToastId !== undefined) {
|
||||||
this.$toast.update(this.socketConnectionToastId, { content: content, options: { timeout: timeout, type: type, closeButton: false, position: 'bottom-center', onClose: () => null, closeOnClick: timeout !== null } }, false)
|
const toastUpdateOptions = {
|
||||||
|
content: content,
|
||||||
|
options: {
|
||||||
|
timeout: timeout,
|
||||||
|
type: type,
|
||||||
|
closeButton: false,
|
||||||
|
position: 'bottom-center',
|
||||||
|
onClose: () => {
|
||||||
|
this.socketConnectionToastId = null
|
||||||
|
},
|
||||||
|
closeOnClick: timeout !== null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$toast.update(this.socketConnectionToastId, toastUpdateOptions, false)
|
||||||
} else {
|
} else {
|
||||||
this.socketConnectionToastId = this.$toast[type](content, { position: 'bottom-center', timeout: timeout, closeButton: false, closeOnClick: timeout !== null })
|
this.socketConnectionToastId = this.$toast[type](content, { position: 'bottom-center', timeout: timeout, closeButton: false, closeOnClick: timeout !== null })
|
||||||
}
|
}
|
||||||
@@ -109,7 +129,7 @@ export default {
|
|||||||
this.updateSocketConnectionToast(this.$strings.ToastSocketDisconnected, 'error', null)
|
this.updateSocketConnectionToast(this.$strings.ToastSocketDisconnected, 'error', null)
|
||||||
},
|
},
|
||||||
reconnect() {
|
reconnect() {
|
||||||
console.error('[SOCKET] reconnected')
|
console.log('[SOCKET] reconnected')
|
||||||
},
|
},
|
||||||
reconnectAttempt(val) {
|
reconnectAttempt(val) {
|
||||||
console.log(`[SOCKET] reconnect attempt ${val}`)
|
console.log(`[SOCKET] reconnect attempt ${val}`)
|
||||||
@@ -120,6 +140,10 @@ export default {
|
|||||||
reconnectFailed() {
|
reconnectFailed() {
|
||||||
console.error('[SOCKET] reconnect failed')
|
console.error('[SOCKET] reconnect failed')
|
||||||
},
|
},
|
||||||
|
authFailed(payload) {
|
||||||
|
console.error('[SOCKET] auth failed', payload.message)
|
||||||
|
this.isSocketAuthenticated = false
|
||||||
|
},
|
||||||
init(payload) {
|
init(payload) {
|
||||||
console.log('Init Payload', payload)
|
console.log('Init Payload', payload)
|
||||||
|
|
||||||
@@ -127,7 +151,7 @@ export default {
|
|||||||
this.$store.commit('users/setUsersOnline', payload.usersOnline)
|
this.$store.commit('users/setUsersOnline', payload.usersOnline)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$eventBus.$emit('socket_init')
|
this.isSocketAuthenticated = true
|
||||||
},
|
},
|
||||||
streamOpen(stream) {
|
streamOpen(stream) {
|
||||||
if (this.$refs.mediaPlayerContainer) this.$refs.mediaPlayerContainer.streamOpen(stream)
|
if (this.$refs.mediaPlayerContainer) this.$refs.mediaPlayerContainer.streamOpen(stream)
|
||||||
@@ -183,7 +207,7 @@ export default {
|
|||||||
this.$store.commit('libraries/updateFilterDataWithItem', libraryItem)
|
this.$store.commit('libraries/updateFilterDataWithItem', libraryItem)
|
||||||
},
|
},
|
||||||
libraryItemUpdated(libraryItem) {
|
libraryItemUpdated(libraryItem) {
|
||||||
if (this.$store.state.selectedLibraryItem && this.$store.state.selectedLibraryItem.id === libraryItem.id) {
|
if (this.$store.state.selectedLibraryItem?.id === libraryItem.id) {
|
||||||
this.$store.commit('setSelectedLibraryItem', libraryItem)
|
this.$store.commit('setSelectedLibraryItem', libraryItem)
|
||||||
if (this.$store.state.globals.selectedEpisode && libraryItem.mediaType === 'podcast') {
|
if (this.$store.state.globals.selectedEpisode && libraryItem.mediaType === 'podcast') {
|
||||||
const episode = libraryItem.media.episodes.find((ep) => ep.id === this.$store.state.globals.selectedEpisode.id)
|
const episode = libraryItem.media.episodes.find((ep) => ep.id === this.$store.state.globals.selectedEpisode.id)
|
||||||
@@ -192,6 +216,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.$store.state.streamLibraryItem?.id === libraryItem.id) {
|
||||||
|
this.$store.commit('updateStreamLibraryItem', libraryItem)
|
||||||
|
}
|
||||||
this.$eventBus.$emit(`${libraryItem.id}_updated`, libraryItem)
|
this.$eventBus.$emit(`${libraryItem.id}_updated`, libraryItem)
|
||||||
this.$store.commit('libraries/updateFilterDataWithItem', libraryItem)
|
this.$store.commit('libraries/updateFilterDataWithItem', libraryItem)
|
||||||
},
|
},
|
||||||
@@ -351,6 +378,15 @@ export default {
|
|||||||
this.$store.commit('scanners/removeCustomMetadataProvider', provider)
|
this.$store.commit('scanners/removeCustomMetadataProvider', provider)
|
||||||
},
|
},
|
||||||
initializeSocket() {
|
initializeSocket() {
|
||||||
|
if (this.$root.socket) {
|
||||||
|
// Can happen in dev due to hot reload
|
||||||
|
console.warn('Socket already initialized')
|
||||||
|
this.socket = this.$root.socket
|
||||||
|
this.isSocketConnected = this.$root.socket?.connected
|
||||||
|
this.isFirstSocketConnection = false
|
||||||
|
this.socketConnectionToastId = null
|
||||||
|
return
|
||||||
|
}
|
||||||
this.socket = this.$nuxtSocket({
|
this.socket = this.$nuxtSocket({
|
||||||
name: process.env.NODE_ENV === 'development' ? 'dev' : 'prod',
|
name: process.env.NODE_ENV === 'development' ? 'dev' : 'prod',
|
||||||
persist: 'main',
|
persist: 'main',
|
||||||
@@ -361,6 +397,7 @@ export default {
|
|||||||
path: `${this.$config.routerBasePath}/socket.io`
|
path: `${this.$config.routerBasePath}/socket.io`
|
||||||
})
|
})
|
||||||
this.$root.socket = this.socket
|
this.$root.socket = this.socket
|
||||||
|
this.isSocketAuthenticated = false
|
||||||
console.log('Socket initialized')
|
console.log('Socket initialized')
|
||||||
|
|
||||||
// Pre-defined socket events
|
// Pre-defined socket events
|
||||||
@@ -374,6 +411,7 @@ export default {
|
|||||||
|
|
||||||
// Event received after authorizing socket
|
// Event received after authorizing socket
|
||||||
this.socket.on('init', this.init)
|
this.socket.on('init', this.init)
|
||||||
|
this.socket.on('auth_failed', this.authFailed)
|
||||||
|
|
||||||
// Stream Listeners
|
// Stream Listeners
|
||||||
this.socket.on('stream_open', this.streamOpen)
|
this.socket.on('stream_open', this.streamOpen)
|
||||||
@@ -568,6 +606,7 @@ export default {
|
|||||||
this.updateBodyClass()
|
this.updateBodyClass()
|
||||||
this.resize()
|
this.resize()
|
||||||
this.$eventBus.$on('change-lang', this.changeLanguage)
|
this.$eventBus.$on('change-lang', this.changeLanguage)
|
||||||
|
this.$eventBus.$on('token_refreshed', this.tokenRefreshed)
|
||||||
window.addEventListener('resize', this.resize)
|
window.addEventListener('resize', this.resize)
|
||||||
window.addEventListener('keydown', this.keyDown)
|
window.addEventListener('keydown', this.keyDown)
|
||||||
|
|
||||||
@@ -591,6 +630,7 @@ export default {
|
|||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventBus.$off('change-lang', this.changeLanguage)
|
this.$eventBus.$off('change-lang', this.changeLanguage)
|
||||||
|
this.$eventBus.$off('token_refreshed', this.tokenRefreshed)
|
||||||
window.removeEventListener('resize', this.resize)
|
window.removeEventListener('resize', this.resize)
|
||||||
window.removeEventListener('keydown', this.keyDown)
|
window.removeEventListener('keydown', this.keyDown)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import LazyBookCard from '@/components/cards/LazyBookCard'
|
|||||||
import LazySeriesCard from '@/components/cards/LazySeriesCard'
|
import LazySeriesCard from '@/components/cards/LazySeriesCard'
|
||||||
import LazyCollectionCard from '@/components/cards/LazyCollectionCard'
|
import LazyCollectionCard from '@/components/cards/LazyCollectionCard'
|
||||||
import LazyPlaylistCard from '@/components/cards/LazyPlaylistCard'
|
import LazyPlaylistCard from '@/components/cards/LazyPlaylistCard'
|
||||||
import LazyAlbumCard from '@/components/cards/LazyAlbumCard'
|
|
||||||
import AuthorCard from '@/components/cards/AuthorCard'
|
import AuthorCard from '@/components/cards/AuthorCard'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -20,7 +19,6 @@ export default {
|
|||||||
if (this.entityName === 'series') return Vue.extend(LazySeriesCard)
|
if (this.entityName === 'series') return Vue.extend(LazySeriesCard)
|
||||||
if (this.entityName === 'collections') return Vue.extend(LazyCollectionCard)
|
if (this.entityName === 'collections') return Vue.extend(LazyCollectionCard)
|
||||||
if (this.entityName === 'playlists') return Vue.extend(LazyPlaylistCard)
|
if (this.entityName === 'playlists') return Vue.extend(LazyPlaylistCard)
|
||||||
if (this.entityName === 'albums') return Vue.extend(LazyAlbumCard)
|
|
||||||
if (this.entityName === 'authors') return Vue.extend(AuthorCard)
|
if (this.entityName === 'authors') return Vue.extend(AuthorCard)
|
||||||
return Vue.extend(LazyBookCard)
|
return Vue.extend(LazyBookCard)
|
||||||
},
|
},
|
||||||
@@ -28,7 +26,6 @@ export default {
|
|||||||
if (this.entityName === 'series') return 'cards-lazy-series-card'
|
if (this.entityName === 'series') return 'cards-lazy-series-card'
|
||||||
if (this.entityName === 'collections') return 'cards-lazy-collection-card'
|
if (this.entityName === 'collections') return 'cards-lazy-collection-card'
|
||||||
if (this.entityName === 'playlists') return 'cards-lazy-playlist-card'
|
if (this.entityName === 'playlists') return 'cards-lazy-playlist-card'
|
||||||
if (this.entityName === 'albums') return 'cards-lazy-album-card'
|
|
||||||
if (this.entityName === 'authors') return 'cards-author-card'
|
if (this.entityName === 'authors') return 'cards-author-card'
|
||||||
return 'cards-lazy-book-card'
|
return 'cards-lazy-book-card'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ module.exports = {
|
|||||||
|
|
||||||
// Axios module configuration: https://go.nuxtjs.dev/config-axios
|
// Axios module configuration: https://go.nuxtjs.dev/config-axios
|
||||||
axios: {
|
axios: {
|
||||||
baseURL: routerBasePath
|
baseURL: routerBasePath,
|
||||||
|
progress: false
|
||||||
},
|
},
|
||||||
|
|
||||||
// nuxt/pwa https://pwa.nuxtjs.org
|
// nuxt/pwa https://pwa.nuxtjs.org
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "2.20.0",
|
"version": "2.25.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "2.20.0",
|
"version": "2.25.1",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxtjs/axios": "^5.13.6",
|
"@nuxtjs/axios": "^5.13.6",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "2.20.0",
|
"version": "2.25.1",
|
||||||
"buildNumber": 1,
|
"buildNumber": 1,
|
||||||
"description": "Self-hosted audiobook and podcast client",
|
"description": "Self-hosted audiobook and podcast client",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|||||||
+11
-10
@@ -182,18 +182,19 @@ export default {
|
|||||||
password: this.password,
|
password: this.password,
|
||||||
newPassword: this.newPassword
|
newPassword: this.newPassword
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then(() => {
|
||||||
if (res.success) {
|
this.$toast.success(this.$strings.ToastUserPasswordChangeSuccess)
|
||||||
this.$toast.success(this.$strings.ToastUserPasswordChangeSuccess)
|
this.resetForm()
|
||||||
this.resetForm()
|
|
||||||
} else {
|
|
||||||
this.$toast.error(res.error || this.$strings.ToastUnknownError)
|
|
||||||
}
|
|
||||||
this.changingPassword = false
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error)
|
console.error('Failed to change password', error)
|
||||||
this.$toast.error(this.$strings.ToastUnknownError)
|
let errorMessage = this.$strings.ToastUnknownError
|
||||||
|
if (error.response?.data && typeof error.response.data === 'string') {
|
||||||
|
errorMessage = error.response.data
|
||||||
|
}
|
||||||
|
this.$toast.error(errorMessage)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
this.changingPassword = false
|
this.changingPassword = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="page-wrapper" class="bg-bg page overflow-y-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
<div id="page-wrapper" class="bg-bg page overflow-y-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
||||||
<div class="flex items-center py-4 px-2 md:px-0 max-w-7xl mx-auto">
|
<div class="flex items-center py-4 px-4 max-w-7xl mx-auto">
|
||||||
<nuxt-link :to="`/item/${libraryItem.id}`" class="hover:underline">
|
<nuxt-link :to="`/item/${libraryItem.id}`" class="hover:underline">
|
||||||
<h1 class="text-lg lg:text-xl">{{ title }}</h1>
|
<h1 class="text-lg lg:text-xl">{{ title }}</h1>
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap-reverse justify-center py-4 px-2">
|
<div class="flex flex-wrap-reverse lg:flex-nowrap justify-center py-4 px-4">
|
||||||
<div class="w-full max-w-3xl py-4">
|
<div class="w-full max-w-3xl py-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="w-12 hidden lg:block" />
|
<div class="w-12 hidden lg:block" />
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center mb-3 py-1 -mx-1">
|
<div class="flex items-center mb-3 py-1 -mx-1">
|
||||||
<div class="w-12 hidden lg:block" />
|
<div class="w-12 hidden lg:block" />
|
||||||
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1 whitespace-nowrap" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
||||||
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg' : 'primary'" class="mx-1" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg-bg' : 'bg-primary'" class="mx-1 whitespace-nowrap" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
||||||
<ui-btn color="bg-primary" small :class="{ 'mx-1': newChapters.length > 1 }" @click="showFindChaptersModal = true">{{ $strings.ButtonLookup }}</ui-btn>
|
<ui-btn color="bg-primary" small :class="{ 'mx-1': newChapters.length > 1 }" @click="showFindChaptersModal = true">{{ $strings.ButtonLookup }}</ui-btn>
|
||||||
<div class="grow" />
|
<div class="grow" />
|
||||||
<ui-btn v-if="hasChanges" small class="mx-1" @click.stop="resetChapters">{{ $strings.ButtonReset }}</ui-btn>
|
<ui-btn v-if="hasChanges" small class="mx-1" @click.stop="resetChapters">{{ $strings.ButtonReset }}</ui-btn>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<ui-time-picker v-else class="text-xs" v-model="chapter.start" :show-three-digit-hour="mediaDuration >= 360000" @change="checkChapters" />
|
<ui-time-picker v-else class="text-xs" v-model="chapter.start" :show-three-digit-hour="mediaDuration >= 360000" @change="checkChapters" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grow px-1">
|
<div class="grow px-1">
|
||||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs" />
|
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs min-w-52" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-32 min-w-32 px-2 py-1">
|
<div class="w-32 min-w-32 px-2 py-1">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
@@ -141,10 +141,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="w-full h-full max-h-full text-sm rounded-lg bg-bg shadow-lg border border-black-300 relative">
|
<div class="w-full h-full max-h-full text-sm rounded-lg bg-bg shadow-lg border border-black-300 relative">
|
||||||
<div v-if="!chapterData" class="flex p-20">
|
<div v-if="!chapterData" class="flex flex-col items-center justify-center p-20">
|
||||||
<ui-text-input-with-label v-model.trim="asinInput" label="ASIN" />
|
<div class="relative">
|
||||||
<ui-dropdown v-model="regionInput" :label="$strings.LabelRegion" small :items="audibleRegions" class="w-32 mx-1" />
|
<div class="flex items-end space-x-2">
|
||||||
<ui-btn small color="bg-primary" class="mt-5" @click="findChapters">{{ $strings.ButtonSearch }}</ui-btn>
|
<ui-text-input-with-label v-model.trim="asinInput" label="ASIN" class="flex-grow" />
|
||||||
|
<ui-dropdown v-model="regionInput" :label="$strings.LabelRegion" small :items="audibleRegions" class="w-20 max-w-20" />
|
||||||
|
<ui-btn color="bg-primary" @click="findChapters">{{ $strings.ButtonSearch }}</ui-btn>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<ui-checkbox v-model="removeBranding" :label="$strings.LabelRemoveAudibleBranding" small checkbox-bg="bg" label-class="pl-2 text-base text-sm" @click="toggleRemoveBranding" />
|
||||||
|
</div>
|
||||||
|
<div class="absolute left-0 mt-1.5 text-error text-s h-5">
|
||||||
|
<p v-if="asinError">{{ asinError }}</p>
|
||||||
|
<p v-if="asinError">{{ $strings.MessageAsinCheck }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="invisible mt-1 text-xs"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="w-full p-4">
|
<div v-else class="w-full p-4">
|
||||||
<div class="flex justify-between mb-4">
|
<div class="flex justify-between mb-4">
|
||||||
@@ -221,6 +233,11 @@ export default {
|
|||||||
return redirect('/')
|
return redirect('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch and set library if this items library does not match the current
|
||||||
|
if (store.state.libraries.currentLibraryId !== libraryItem.libraryId || !store.state.libraries.filterData) {
|
||||||
|
await store.dispatch('libraries/fetch', libraryItem.libraryId)
|
||||||
|
}
|
||||||
|
|
||||||
var previousRoute = from ? from.fullPath : null
|
var previousRoute = from ? from.fullPath : null
|
||||||
if (from && from.path === '/login') previousRoute = null
|
if (from && from.path === '/login') previousRoute = null
|
||||||
return {
|
return {
|
||||||
@@ -244,6 +261,8 @@ export default {
|
|||||||
findingChapters: false,
|
findingChapters: false,
|
||||||
showFindChaptersModal: false,
|
showFindChaptersModal: false,
|
||||||
chapterData: null,
|
chapterData: null,
|
||||||
|
asinError: null,
|
||||||
|
removeBranding: false,
|
||||||
showSecondInputs: false,
|
showSecondInputs: false,
|
||||||
audibleRegions: ['US', 'CA', 'UK', 'AU', 'FR', 'DE', 'JP', 'IT', 'IN', 'ES'],
|
audibleRegions: ['US', 'CA', 'UK', 'AU', 'FR', 'DE', 'JP', 'IT', 'IN', 'ES'],
|
||||||
hasChanges: false
|
hasChanges: false
|
||||||
@@ -305,6 +324,9 @@ export default {
|
|||||||
|
|
||||||
this.checkChapters()
|
this.checkChapters()
|
||||||
},
|
},
|
||||||
|
toggleRemoveBranding() {
|
||||||
|
this.removeBranding = !this.removeBranding
|
||||||
|
},
|
||||||
shiftChapterTimes() {
|
shiftChapterTimes() {
|
||||||
if (!this.shiftAmount || isNaN(this.shiftAmount) || this.newChapters.length <= 1) {
|
if (!this.shiftAmount || isNaN(this.shiftAmount) || this.newChapters.length <= 1) {
|
||||||
return
|
return
|
||||||
@@ -314,12 +336,12 @@ export default {
|
|||||||
|
|
||||||
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
||||||
if (lastChapter.start + amount > this.mediaDurationRounded) {
|
if (lastChapter.start + amount > this.mediaDurationRounded) {
|
||||||
this.$toast.error('Invalid shift amount. Last chapter start time would extend beyond the duration of this audiobook.')
|
this.$toast.error(this.$strings.ToastChaptersInvalidShiftAmountLast)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.newChapters[0].end + amount <= 0) {
|
if (this.newChapters[1].start + amount <= 0) {
|
||||||
this.$toast.error('Invalid shift amount. First chapter would have zero or negative length.')
|
this.$toast.error(this.$strings.ToastChaptersInvalidShiftAmountStart)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,17 +563,17 @@ export default {
|
|||||||
|
|
||||||
this.findingChapters = true
|
this.findingChapters = true
|
||||||
this.chapterData = null
|
this.chapterData = null
|
||||||
|
this.asinError = null // used to show warning about audible vs amazon ASIN
|
||||||
this.$axios
|
this.$axios
|
||||||
.$get(`/api/search/chapters?asin=${this.asinInput}®ion=${this.regionInput}`)
|
.$get(`/api/search/chapters?asin=${this.asinInput}®ion=${this.regionInput}`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.findingChapters = false
|
this.findingChapters = false
|
||||||
|
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
this.$toast.error(data.error)
|
this.asinError = this.$getString(data.stringKey)
|
||||||
this.showFindChaptersModal = false
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Chapter data', data)
|
console.log('Chapter data', data)
|
||||||
this.chapterData = data
|
this.chapterData = this.removeBranding ? this.removeBrandingFromData(data) : data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -561,6 +583,37 @@ export default {
|
|||||||
this.showFindChaptersModal = false
|
this.showFindChaptersModal = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
removeBrandingFromData(data) {
|
||||||
|
if (!data) return data
|
||||||
|
try {
|
||||||
|
const introDuration = data.brandIntroDurationMs
|
||||||
|
const outroDuration = data.brandOutroDurationMs
|
||||||
|
|
||||||
|
for (let i = 0; i < data.chapters.length; i++) {
|
||||||
|
const chapter = data.chapters[i]
|
||||||
|
if (chapter.startOffsetMs < introDuration) {
|
||||||
|
// This should never happen, as the intro is not longer than the first chapter
|
||||||
|
// If this happens set to the next second
|
||||||
|
// Will be 0 for the first chapter anayways
|
||||||
|
chapter.startOffsetMs = i * 1000
|
||||||
|
chapter.startOffsetSec = i
|
||||||
|
} else {
|
||||||
|
chapter.startOffsetMs -= introDuration
|
||||||
|
chapter.startOffsetSec = Math.floor(chapter.startOffsetMs / 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastChapter = data.chapters[data.chapters.length - 1]
|
||||||
|
// If there is an outro that's in the outro duration, remove it
|
||||||
|
if (lastChapter && lastChapter.lengthMs <= outroDuration) {
|
||||||
|
data.chapters.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
} catch {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
},
|
||||||
resetChapters() {
|
resetChapters() {
|
||||||
const payload = {
|
const payload = {
|
||||||
message: this.$strings.MessageResetChaptersConfirm,
|
message: this.$strings.MessageResetChaptersConfirm,
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ export default {
|
|||||||
console.error('No need to edit library item that is 1 file...')
|
console.error('No need to edit library item that is 1 file...')
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch and set library if this items library does not match the current
|
||||||
|
if (store.state.libraries.currentLibraryId !== libraryItem.libraryId || !store.state.libraries.filterData) {
|
||||||
|
await store.dispatch('libraries/fetch', libraryItem.libraryId)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
libraryItem,
|
libraryItem,
|
||||||
files: libraryItem.media.audioFiles ? libraryItem.media.audioFiles.map((af) => ({ ...af, include: !af.exclude })) : []
|
files: libraryItem.media.audioFiles ? libraryItem.media.audioFiles.map((af) => ({ ...af, include: !af.exclude })) : []
|
||||||
|
|||||||
@@ -2,7 +2,14 @@
|
|||||||
<div id="page-wrapper" class="bg-bg page p-8 overflow-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
<div id="page-wrapper" class="bg-bg page p-8 overflow-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
||||||
<div class="flex items-center justify-center mb-6">
|
<div class="flex items-center justify-center mb-6">
|
||||||
<div class="w-full max-w-2xl">
|
<div class="w-full max-w-2xl">
|
||||||
<p class="text-2xl mb-2">{{ $strings.HeaderAudiobookTools }}</p>
|
<div class="flex items-center mb-4">
|
||||||
|
<nuxt-link :to="`/item/${libraryItem.id}`" class="hover:underline">
|
||||||
|
<h1 class="text-lg lg:text-xl">{{ mediaMetadata.title }}</h1>
|
||||||
|
</nuxt-link>
|
||||||
|
<button class="w-7 h-7 flex items-center justify-center mx-4 hover:scale-110 duration-100 transform text-gray-200 hover:text-white" @click="editItem">
|
||||||
|
<span class="material-symbols text-base">edit</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-2xl">
|
<div class="w-full max-w-2xl">
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
@@ -13,43 +20,43 @@
|
|||||||
|
|
||||||
<div class="flex justify-center mb-2">
|
<div class="flex justify-center mb-2">
|
||||||
<div class="w-full max-w-2xl">
|
<div class="w-full max-w-2xl">
|
||||||
<p class="text-xl">{{ $strings.HeaderMetadataToEmbed }}</p>
|
<p class="text-lg">{{ $strings.HeaderMetadataToEmbed }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-2xl"></div>
|
<div class="w-full max-w-2xl"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-center flex-wrap">
|
<div class="flex justify-center flex-wrap lg:flex-nowrap gap-4">
|
||||||
<div class="w-full max-w-2xl border border-white/10 bg-bg mx-2">
|
<div class="w-full max-w-2xl border border-white/10 bg-bg">
|
||||||
<div class="flex py-2 px-4">
|
<div class="flex py-2 px-4">
|
||||||
<div class="w-1/3 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelMetaTag }}</div>
|
<div class="w-28 min-w-28 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelMetaTag }}</div>
|
||||||
<div class="w-2/3 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelValue }}</div>
|
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelValue }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-h-72 overflow-auto">
|
<div class="w-full max-h-72 overflow-auto">
|
||||||
<template v-for="(value, key, index) in metadataObject">
|
<template v-for="(value, key, index) in metadataObject">
|
||||||
<div :key="key" class="flex py-1 px-4 text-sm" :class="index % 2 === 0 ? 'bg-primary/25' : ''">
|
<div :key="key" class="flex py-1 px-4 text-sm" :class="index % 2 === 0 ? 'bg-primary/25' : ''">
|
||||||
<div class="w-1/3 font-semibold">{{ key }}</div>
|
<div class="w-28 min-w-28 font-semibold">{{ key }}</div>
|
||||||
<div class="w-2/3">
|
<div class="grow">
|
||||||
{{ value }}
|
{{ value }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-2xl border border-white/10 bg-bg mx-2">
|
<div class="w-full max-w-2xl border border-white/10 bg-bg">
|
||||||
<div class="flex py-2 px-4 bg-primary/25">
|
<div class="flex py-2 px-4 bg-primary/25">
|
||||||
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelChapterTitle }}</div>
|
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelChapterTitle }}</div>
|
||||||
<div class="w-24 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelStart }}</div>
|
<div class="w-16 min-w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelStart }}</div>
|
||||||
<div class="w-24 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelEnd }}</div>
|
<div class="w-16 min-w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelEnd }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-h-72 overflow-auto">
|
<div class="w-full max-h-72 overflow-auto">
|
||||||
<p v-if="!metadataChapters.length" class="py-5 text-center text-gray-200">{{ $strings.MessageNoChapters }}</p>
|
<p v-if="!metadataChapters.length" class="py-5 text-center text-gray-200">{{ $strings.MessageNoChapters }}</p>
|
||||||
<template v-for="(chapter, index) in metadataChapters">
|
<template v-for="(chapter, index) in metadataChapters">
|
||||||
<div :key="index" class="flex py-1 px-4 text-sm" :class="index % 2 === 1 ? 'bg-primary/25' : ''">
|
<div :key="index" class="flex py-1 px-4 text-sm" :class="index % 2 === 1 ? 'bg-primary/25' : ''">
|
||||||
<div class="grow font-semibold">{{ chapter.title }}</div>
|
<div class="grow font-semibold">{{ chapter.title }}</div>
|
||||||
<div class="w-24">
|
<div class="w-16 min-w-16">
|
||||||
{{ $secondsToTimestamp(chapter.start) }}
|
{{ $secondsToTimestamp(chapter.start) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="w-24">
|
<div class="w-16 min-w-16">
|
||||||
{{ $secondsToTimestamp(chapter.end) }}
|
{{ $secondsToTimestamp(chapter.end) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -77,10 +84,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- m4b embed action buttons -->
|
<!-- m4b embed action buttons -->
|
||||||
<div v-else class="w-full flex items-center mb-4">
|
<div v-else class="w-full flex items-center mb-4">
|
||||||
<button :disabled="processing" class="text-sm uppercase text-gray-200 flex items-center pt-px pl-1 pr-2 hover:bg-white/5 rounded-md" @click="showEncodeOptions = !showEncodeOptions">
|
|
||||||
<span class="material-symbols text-xl">{{ showEncodeOptions || usingCustomEncodeOptions ? 'check_box' : 'check_box_outline_blank' }}</span> <span class="pl-1">{{ $strings.LabelUseAdvancedOptions }}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="grow" />
|
<div class="grow" />
|
||||||
|
|
||||||
<ui-btn v-if="!isTaskFinished && processing" color="bg-error" :loading="isCancelingEncode" class="mr-2" @click.stop="cancelEncodeClick">{{ $strings.ButtonCancelEncode }}</ui-btn>
|
<ui-btn v-if="!isTaskFinished && processing" color="bg-error" :loading="isCancelingEncode" class="mr-2" @click.stop="cancelEncodeClick">{{ $strings.ButtonCancelEncode }}</ui-btn>
|
||||||
@@ -89,18 +92,16 @@
|
|||||||
<p v-else class="text-success text-lg font-semibold">{{ $strings.MessageM4BFinished }}</p>
|
<p v-else class="text-success text-lg font-semibold">{{ $strings.MessageM4BFinished }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- advanced encoding options -->
|
<!-- show encoding options for running task -->
|
||||||
<div v-if="isM4BTool" class="overflow-hidden">
|
<div v-if="encodeTaskHasEncodingOptions" class="mb-4 pb-4 border-b border-white/10">
|
||||||
<transition name="slide">
|
<div class="flex flex-wrap -mx-2">
|
||||||
<div v-if="showEncodeOptions || usingCustomEncodeOptions" class="mb-4 pb-4 border-b border-white/10">
|
<ui-text-input-with-label ref="bitrateInput" v-model="encodingOptions.bitrate" readonly :label="$strings.LabelAudioBitrate" class="m-2 max-w-40" @input="bitrateChanged" />
|
||||||
<div class="flex flex-wrap -mx-2">
|
<ui-text-input-with-label ref="channelsInput" v-model="encodingOptions.channels" readonly :label="$strings.LabelAudioChannels" class="m-2 max-w-40" @input="channelsChanged" />
|
||||||
<ui-text-input-with-label ref="bitrateInput" v-model="encodingOptions.bitrate" :disabled="processing || isTaskFinished" :label="$strings.LabelAudioBitrate" class="m-2 max-w-40" @input="bitrateChanged" />
|
<ui-text-input-with-label ref="codecInput" v-model="encodingOptions.codec" readonly :label="$strings.LabelAudioCodec" class="m-2 max-w-40" @input="codecChanged" />
|
||||||
<ui-text-input-with-label ref="channelsInput" v-model="encodingOptions.channels" :disabled="processing || isTaskFinished" :label="$strings.LabelAudioChannels" class="m-2 max-w-40" @input="channelsChanged" />
|
</div>
|
||||||
<ui-text-input-with-label ref="codecInput" v-model="encodingOptions.codec" :disabled="processing || isTaskFinished" :label="$strings.LabelAudioCodec" class="m-2 max-w-40" @input="codecChanged" />
|
</div>
|
||||||
</div>
|
<div v-else-if="isM4BTool" class="mb-4">
|
||||||
<p class="text-sm text-warning">{{ $strings.LabelEncodingWarningAdvancedSettings }}</p>
|
<widgets-encoder-options-card ref="encoderOptionsCard" :audio-tracks="audioFiles" :disabled="processing || isTaskFinished" />
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
@@ -146,19 +147,29 @@
|
|||||||
<div class="flex py-2 px-4 bg-primary/25">
|
<div class="flex py-2 px-4 bg-primary/25">
|
||||||
<div class="w-10 text-xs font-semibold text-gray-200">#</div>
|
<div class="w-10 text-xs font-semibold text-gray-200">#</div>
|
||||||
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelFilename }}</div>
|
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelFilename }}</div>
|
||||||
|
<div class="w-20 text-xs font-semibold uppercase text-gray-200 hidden lg:block">{{ $strings.LabelChannels }}</div>
|
||||||
|
<div class="w-16 text-xs font-semibold uppercase text-gray-200 hidden md:block">{{ $strings.LabelCodec }}</div>
|
||||||
|
<div class="w-16 text-xs font-semibold uppercase text-gray-200 hidden md:block">{{ $strings.LabelBitrate }}</div>
|
||||||
<div class="w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelSize }}</div>
|
<div class="w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelSize }}</div>
|
||||||
<div class="w-24"></div>
|
<div class="w-24"></div>
|
||||||
</div>
|
</div>
|
||||||
<template v-for="file in audioFiles">
|
<template v-for="file in audioFiles">
|
||||||
<div :key="file.index" class="flex py-2 px-4 text-sm" :class="file.index % 2 === 0 ? 'bg-primary/25' : ''">
|
<div :key="file.index" class="flex py-2 px-4 text-xs sm:text-sm" :class="file.index % 2 === 0 ? 'bg-primary/25' : ''">
|
||||||
<div class="w-10">{{ file.index }}</div>
|
<div class="w-10 min-w-10">{{ file.index }}</div>
|
||||||
<div class="grow">
|
<div class="grow">
|
||||||
{{ file.metadata.filename }}
|
{{ file.metadata.filename }}
|
||||||
</div>
|
</div>
|
||||||
<div class="w-16 font-mono text-gray-200">
|
<div class="w-20 min-w-20 text-gray-200 hidden lg:block">{{ file.channels || 'unknown' }} ({{ file.channelLayout || 'unknown' }})</div>
|
||||||
|
<div class="w-16 min-w-16 text-gray-200 hidden md:block">
|
||||||
|
{{ file.codec || 'unknown' }}
|
||||||
|
</div>
|
||||||
|
<div class="w-16 min-w-16 text-gray-200 hidden md:block">
|
||||||
|
{{ $bytesPretty(file.bitRate || 0, 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="w-16 min-w-16 text-gray-200">
|
||||||
{{ $bytesPretty(file.metadata.size) }}
|
{{ $bytesPretty(file.metadata.size) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="w-24">
|
<div class="w-24 min-w-24">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<span v-if="audioFilesFinished[file.ino]" class="material-symbols text-xl text-success leading-none">check_circle</span>
|
<span v-if="audioFilesFinished[file.ino]" class="material-symbols text-xl text-success leading-none">check_circle</span>
|
||||||
<div v-else-if="audioFilesEncoding[file.ino]">
|
<div v-else-if="audioFilesEncoding[file.ino]">
|
||||||
@@ -195,10 +206,15 @@ export default {
|
|||||||
return redirect('/?error=invalid media type')
|
return redirect('/?error=invalid media type')
|
||||||
}
|
}
|
||||||
if (!libraryItem.media.audioFiles.length) {
|
if (!libraryItem.media.audioFiles.length) {
|
||||||
cnosole.error('No audio files')
|
console.error('No audio files')
|
||||||
return redirect('/?error=no audio files')
|
return redirect('/?error=no audio files')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch and set library if this items library does not match the current
|
||||||
|
if (store.state.libraries.currentLibraryId !== libraryItem.libraryId || !store.state.libraries.filterData) {
|
||||||
|
await store.dispatch('libraries/fetch', libraryItem.libraryId)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
libraryItem
|
libraryItem
|
||||||
}
|
}
|
||||||
@@ -209,7 +225,6 @@ export default {
|
|||||||
metadataObject: null,
|
metadataObject: null,
|
||||||
selectedTool: 'embed',
|
selectedTool: 'embed',
|
||||||
isCancelingEncode: false,
|
isCancelingEncode: false,
|
||||||
showEncodeOptions: false,
|
|
||||||
shouldBackupAudioFiles: true,
|
shouldBackupAudioFiles: true,
|
||||||
encodingOptions: {
|
encodingOptions: {
|
||||||
bitrate: '128k',
|
bitrate: '128k',
|
||||||
@@ -258,9 +273,6 @@ export default {
|
|||||||
audioFiles() {
|
audioFiles() {
|
||||||
return (this.media.audioFiles || []).filter((af) => !af.exclude)
|
return (this.media.audioFiles || []).filter((af) => !af.exclude)
|
||||||
},
|
},
|
||||||
isSingleM4b() {
|
|
||||||
return this.audioFiles.length === 1 && this.audioFiles[0].metadata.ext.toLowerCase() === '.m4b'
|
|
||||||
},
|
|
||||||
streamLibraryItem() {
|
streamLibraryItem() {
|
||||||
return this.$store.state.streamLibraryItem
|
return this.$store.state.streamLibraryItem
|
||||||
},
|
},
|
||||||
@@ -268,14 +280,10 @@ export default {
|
|||||||
return this.media.chapters || []
|
return this.media.chapters || []
|
||||||
},
|
},
|
||||||
availableTools() {
|
availableTools() {
|
||||||
if (this.isSingleM4b) {
|
return [
|
||||||
return [{ value: 'embed', text: this.$strings.LabelToolsEmbedMetadata }]
|
{ value: 'embed', text: this.$strings.LabelToolsEmbedMetadata },
|
||||||
} else {
|
{ value: 'm4b', text: this.$strings.LabelToolsM4bEncoder }
|
||||||
return [
|
]
|
||||||
{ value: 'embed', text: this.$strings.LabelToolsEmbedMetadata },
|
|
||||||
{ value: 'm4b', text: this.$strings.LabelToolsM4bEncoder }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
taskFailed() {
|
taskFailed() {
|
||||||
return this.isTaskFinished && this.task.isFailed
|
return this.isTaskFinished && this.task.isFailed
|
||||||
@@ -309,8 +317,8 @@ export default {
|
|||||||
isMetadataEmbedQueued() {
|
isMetadataEmbedQueued() {
|
||||||
return this.queuedEmbedLIds.some((lid) => lid === this.libraryItemId)
|
return this.queuedEmbedLIds.some((lid) => lid === this.libraryItemId)
|
||||||
},
|
},
|
||||||
usingCustomEncodeOptions() {
|
encodeTaskHasEncodingOptions() {
|
||||||
return this.isM4BTool && this.encodeTask && this.encodeTask.data.encodeOptions && Object.keys(this.encodeTask.data.encodeOptions).length > 0
|
return this.isM4BTool && !!this.encodeTask?.data.encodeOptions && Object.keys(this.encodeTask.data.encodeOptions).length > 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -346,19 +354,15 @@ export default {
|
|||||||
if (this.$refs.channelsInput) this.$refs.channelsInput.blur()
|
if (this.$refs.channelsInput) this.$refs.channelsInput.blur()
|
||||||
if (this.$refs.codecInput) this.$refs.codecInput.blur()
|
if (this.$refs.codecInput) this.$refs.codecInput.blur()
|
||||||
|
|
||||||
let queryStr = ''
|
const encodeOptions = this.$refs.encoderOptionsCard.getEncodingOptions()
|
||||||
if (this.showEncodeOptions) {
|
|
||||||
const options = []
|
this.encodingOptions = encodeOptions
|
||||||
if (this.encodingOptions.bitrate) options.push(`bitrate=${this.encodingOptions.bitrate}`)
|
|
||||||
if (this.encodingOptions.channels) options.push(`channels=${this.encodingOptions.channels}`)
|
const queryParams = new URLSearchParams(encodeOptions)
|
||||||
if (this.encodingOptions.codec) options.push(`codec=${this.encodingOptions.codec}`)
|
|
||||||
if (options.length) {
|
|
||||||
queryStr = `?${options.join('&')}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.processing = true
|
this.processing = true
|
||||||
this.$axios
|
this.$axios
|
||||||
.$post(`/api/tools/item/${this.libraryItemId}/encode-m4b${queryStr}`)
|
.$post(`/api/tools/item/${this.libraryItemId}/encode-m4b?${queryParams.toString()}`)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('Ab m4b merge started')
|
console.log('Ab m4b merge started')
|
||||||
})
|
})
|
||||||
@@ -411,14 +415,10 @@ export default {
|
|||||||
const shouldBackupAudioFiles = localStorage.getItem('embedMetadataShouldBackup')
|
const shouldBackupAudioFiles = localStorage.getItem('embedMetadataShouldBackup')
|
||||||
this.shouldBackupAudioFiles = shouldBackupAudioFiles != 0
|
this.shouldBackupAudioFiles = shouldBackupAudioFiles != 0
|
||||||
|
|
||||||
if (this.usingCustomEncodeOptions) {
|
if (this.encodeTaskHasEncodingOptions) {
|
||||||
if (this.encodeTask.data.encodeOptions.bitrate) this.encodingOptions.bitrate = this.encodeTask.data.encodeOptions.bitrate
|
if (this.encodeTask.data.encodeOptions.bitrate) this.encodingOptions.bitrate = this.encodeTask.data.encodeOptions.bitrate
|
||||||
if (this.encodeTask.data.encodeOptions.channels) this.encodingOptions.channels = this.encodeTask.data.encodeOptions.channels
|
if (this.encodeTask.data.encodeOptions.channels) this.encodingOptions.channels = this.encodeTask.data.encodeOptions.channels
|
||||||
if (this.encodeTask.data.encodeOptions.codec) this.encodingOptions.codec = this.encodeTask.data.encodeOptions.codec
|
if (this.encodeTask.data.encodeOptions.codec) this.encodingOptions.codec = this.encodeTask.data.encodeOptions.codec
|
||||||
} else {
|
|
||||||
this.encodingOptions.bitrate = localStorage.getItem('embedMetadataBitrate') || '128k'
|
|
||||||
this.encodingOptions.channels = localStorage.getItem('embedMetadataChannels') || '2'
|
|
||||||
this.encodingOptions.codec = localStorage.getItem('embedMetadataCodec') || 'aac'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchMetadataEmbedObject() {
|
fetchMetadataEmbedObject() {
|
||||||
@@ -433,10 +433,24 @@ export default {
|
|||||||
},
|
},
|
||||||
taskUpdated(task) {
|
taskUpdated(task) {
|
||||||
this.processing = !task.isFinished
|
this.processing = !task.isFinished
|
||||||
|
},
|
||||||
|
editItem() {
|
||||||
|
this.$store.commit('showEditModal', this.libraryItem)
|
||||||
|
},
|
||||||
|
libraryItemUpdated(libraryItem) {
|
||||||
|
if (libraryItem.id === this.libraryItem.id) {
|
||||||
|
this.libraryItem = libraryItem
|
||||||
|
this.fetchMetadataEmbedObject()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.init()
|
||||||
|
|
||||||
|
this.$eventBus.$on(`${this.libraryItem.id}_updated`, this.libraryItemUpdated)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$eventBus.$off(`${this.libraryItem.id}_updated`, this.libraryItemUpdated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export default {
|
|||||||
else if (pageName === 'sessions') return this.$strings.HeaderListeningSessions
|
else if (pageName === 'sessions') return this.$strings.HeaderListeningSessions
|
||||||
else if (pageName === 'stats') return this.$strings.HeaderYourStats
|
else if (pageName === 'stats') return this.$strings.HeaderYourStats
|
||||||
else if (pageName === 'users') return this.$strings.HeaderUsers
|
else if (pageName === 'users') return this.$strings.HeaderUsers
|
||||||
|
else if (pageName === 'api-keys') return this.$strings.HeaderApiKeys
|
||||||
else if (pageName === 'item-metadata-utils') return this.$strings.HeaderItemMetadataUtils
|
else if (pageName === 'item-metadata-utils') return this.$strings.HeaderItemMetadataUtils
|
||||||
else if (pageName === 'rss-feeds') return this.$strings.HeaderRSSFeeds
|
else if (pageName === 'rss-feeds') return this.$strings.HeaderRSSFeeds
|
||||||
else if (pageName === 'email') return this.$strings.HeaderEmail
|
else if (pageName === 'email') return this.$strings.HeaderEmail
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<app-settings-content :header-text="$strings.HeaderApiKeys">
|
||||||
|
<template #header-items>
|
||||||
|
<div v-if="numApiKeys" class="mx-2 px-1.5 rounded-lg bg-primary/50 text-gray-300/90 text-sm inline-flex items-center justify-center">
|
||||||
|
<span>{{ numApiKeys }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ui-tooltip :text="$strings.LabelClickForMoreInfo" class="inline-flex ml-2">
|
||||||
|
<a href="https://www.audiobookshelf.org/guides/api-keys" target="_blank" class="inline-flex">
|
||||||
|
<span class="material-symbols text-xl w-5 text-gray-200">help_outline</span>
|
||||||
|
</a>
|
||||||
|
</ui-tooltip>
|
||||||
|
|
||||||
|
<div class="grow" />
|
||||||
|
|
||||||
|
<ui-btn color="bg-primary" :disabled="loadingUsers || users.length === 0" small @click="setShowApiKeyModal()">{{ $strings.ButtonAddApiKey }}</ui-btn>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<tables-api-keys-table ref="apiKeysTable" class="pt-2" @edit="setShowApiKeyModal" @numApiKeys="(count) => (numApiKeys = count)" />
|
||||||
|
</app-settings-content>
|
||||||
|
<modals-api-key-modal ref="apiKeyModal" v-model="showApiKeyModal" :api-key="selectedApiKey" :users="users" @created="apiKeyCreated" @updated="apiKeyUpdated" />
|
||||||
|
<modals-api-key-created-modal ref="apiKeyCreatedModal" v-model="showApiKeyCreatedModal" :api-key="selectedApiKey" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
asyncData({ store, redirect }) {
|
||||||
|
if (!store.getters['user/getIsAdminOrUp']) {
|
||||||
|
redirect('/')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loadingUsers: false,
|
||||||
|
selectedApiKey: null,
|
||||||
|
showApiKeyModal: false,
|
||||||
|
showApiKeyCreatedModal: false,
|
||||||
|
numApiKeys: 0,
|
||||||
|
users: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
apiKeyCreated(apiKey) {
|
||||||
|
this.numApiKeys++
|
||||||
|
this.selectedApiKey = apiKey
|
||||||
|
this.showApiKeyCreatedModal = true
|
||||||
|
if (this.$refs.apiKeysTable) {
|
||||||
|
this.$refs.apiKeysTable.addApiKey(apiKey)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
apiKeyUpdated(apiKey) {
|
||||||
|
if (this.$refs.apiKeysTable) {
|
||||||
|
this.$refs.apiKeysTable.updateApiKey(apiKey)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setShowApiKeyModal(selectedApiKey) {
|
||||||
|
this.selectedApiKey = selectedApiKey
|
||||||
|
this.showApiKeyModal = true
|
||||||
|
},
|
||||||
|
loadUsers() {
|
||||||
|
this.loadingUsers = true
|
||||||
|
this.$axios
|
||||||
|
.$get('/api/users')
|
||||||
|
.then((res) => {
|
||||||
|
this.users = res.users.sort((a, b) => {
|
||||||
|
return a.createdAt - b.createdAt
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Failed', error)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loadingUsers = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadUsers()
|
||||||
|
},
|
||||||
|
beforeDestroy() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -122,7 +122,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center justify-end p-4">
|
<div class="w-full flex items-center justify-between p-4">
|
||||||
|
<p v-if="enableOpenIDAuth" class="text-sm text-warning">{{ $strings.MessageAuthenticationOIDCChangesRestart }}</p>
|
||||||
<ui-btn color="bg-success" :padding-x="8" small class="text-base" :loading="savingSettings" @click="saveSettings">{{ $strings.ButtonSave }}</ui-btn>
|
<ui-btn color="bg-success" :padding-x="8" small class="text-base" :loading="savingSettings" @click="saveSettings">{{ $strings.ButtonSave }}</ui-btn>
|
||||||
</div>
|
</div>
|
||||||
</app-settings-content>
|
</app-settings-content>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<p class="truncate">{{ feed.meta.title }}</p>
|
<p class="truncate">{{ feed.meta.title }}</p>
|
||||||
</td>
|
</td>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<td class="hidden xl:table-cell">
|
<td class="hidden xl:table-cell max-w-48">
|
||||||
<p class="truncate">{{ feed.slug }}</p>
|
<p class="truncate">{{ feed.slug }}</p>
|
||||||
</td>
|
</td>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<ui-icon-btn icon="delete" class="mx-0.5" :size="7" bg-color="bg-error" outlined @click.stop="deleteFeedClick(feed)" />
|
<ui-icon-btn icon="delete" class="mx-0.5 text-white/70" borderless :size="7" iconFontSize="1.25rem" outlined @click.stop="deleteFeedClick(feed)" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -78,10 +78,10 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -250,10 +250,10 @@ export default {
|
|||||||
return user?.username || null
|
return user?.username || null
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
},
|
},
|
||||||
numSelected() {
|
numSelected() {
|
||||||
return this.listeningSessions.filter((s) => s.selected).length
|
return this.listeningSessions.filter((s) => s.selected).length
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
<widgets-online-indicator :value="!!userOnline" />
|
<widgets-online-indicator :value="!!userOnline" />
|
||||||
<h1 class="text-xl pl-2">{{ username }}</h1>
|
<h1 class="text-xl pl-2">{{ username }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="userToken" class="flex text-xs mt-4">
|
<div v-if="legacyToken" class="flex text-xs mt-4">
|
||||||
<ui-text-input-with-label :label="$strings.LabelApiToken" :value="userToken" readonly show-copy />
|
<ui-text-input-with-label label="Legacy API Token" :value="legacyToken" readonly show-copy />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full h-px bg-white/10 my-2" />
|
<div class="w-full h-px bg-white/10 my-2" />
|
||||||
<div class="py-2">
|
<div class="py-2">
|
||||||
@@ -100,9 +100,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
userToken() {
|
legacyToken() {
|
||||||
return this.user.token
|
return this.user.token
|
||||||
},
|
},
|
||||||
|
userToken() {
|
||||||
|
return this.user.accessToken
|
||||||
|
},
|
||||||
bookCoverAspectRatio() {
|
bookCoverAspectRatio() {
|
||||||
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
||||||
},
|
},
|
||||||
@@ -129,10 +132,10 @@ export default {
|
|||||||
return this.listeningSessions.sessions[0]
|
return this.listeningSessions.sessions[0]
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -98,10 +98,10 @@ export default {
|
|||||||
return this.$store.getters['users/getIsUserOnline'](this.user.id)
|
return this.$store.getters['users/getIsUserOnline'](this.user.id)
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return this.$store.state.serverSettings.timeFormat
|
return this.$store.getters['getServerSetting']('timeFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -91,15 +91,15 @@
|
|||||||
{{ isMissing ? $strings.LabelMissing : $strings.LabelIncomplete }}
|
{{ isMissing ? $strings.LabelMissing : $strings.LabelIncomplete }}
|
||||||
</ui-btn>
|
</ui-btn>
|
||||||
|
|
||||||
<ui-tooltip v-if="showQueueBtn" :text="isQueued ? $strings.ButtonQueueRemoveItem : $strings.ButtonQueueAddItem" direction="top">
|
|
||||||
<ui-icon-btn :icon="isQueued ? 'playlist_add_check' : 'playlist_play'" :bg-color="isQueued ? 'bg-primary' : 'bg-success/60'" class="mx-0.5" :class="isQueued ? 'text-success' : ''" @click="queueBtnClick" />
|
|
||||||
</ui-tooltip>
|
|
||||||
|
|
||||||
<ui-btn v-if="showReadButton" color="bg-info" :padding-x="4" small class="flex items-center h-9 mr-2" @click="openEbook">
|
<ui-btn v-if="showReadButton" color="bg-info" :padding-x="4" small class="flex items-center h-9 mr-2" @click="openEbook">
|
||||||
<span class="material-symbols text-2xl -ml-2 pr-2 text-white" aria-hidden="true">auto_stories</span>
|
<span class="material-symbols text-2xl -ml-2 pr-2 text-white" aria-hidden="true">auto_stories</span>
|
||||||
{{ $strings.ButtonRead }}
|
{{ $strings.ButtonRead }}
|
||||||
</ui-btn>
|
</ui-btn>
|
||||||
|
|
||||||
|
<ui-tooltip v-if="showQueueBtn" :text="isQueued ? $strings.ButtonQueueRemoveItem : $strings.ButtonQueueAddItem" direction="top">
|
||||||
|
<ui-icon-btn :icon="isQueued ? 'playlist_add_check' : 'playlist_play'" :bg-color="isQueued ? 'bg-primary' : 'bg-success/60'" class="mx-0.5" :class="isQueued ? 'text-success' : ''" @click="queueBtnClick" />
|
||||||
|
</ui-tooltip>
|
||||||
|
|
||||||
<ui-tooltip v-if="userCanUpdate" :text="$strings.LabelEdit" direction="top">
|
<ui-tooltip v-if="userCanUpdate" :text="$strings.LabelEdit" direction="top">
|
||||||
<ui-icon-btn icon="" outlined class="mx-0.5" :aria-label="$strings.LabelEdit" @click="editClick" />
|
<ui-icon-btn icon="" outlined class="mx-0.5" :aria-label="$strings.LabelEdit" @click="editClick" />
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
@@ -193,7 +193,7 @@ export default {
|
|||||||
return `${process.env.serverUrl}/api/items/${this.libraryItemId}/download?token=${this.userToken}`
|
return `${process.env.serverUrl}/api/items/${this.libraryItemId}/download?token=${this.userToken}`
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
},
|
},
|
||||||
userIsAdminOrUp() {
|
userIsAdminOrUp() {
|
||||||
return this.$store.getters['user/getIsAdminOrUp']
|
return this.$store.getters['user/getIsAdminOrUp']
|
||||||
@@ -819,6 +819,17 @@ export default {
|
|||||||
-webkit-line-clamp: 4;
|
-webkit-line-clamp: 4;
|
||||||
max-height: calc(6 * 1lh);
|
max-height: calc(6 * 1lh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Safari-specific fix for the description clamping */
|
||||||
|
@supports (-webkit-touch-callout: none) {
|
||||||
|
#item-description {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
max-height: calc(6 * 1lh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#item-description.show-full {
|
#item-description.show-full {
|
||||||
-webkit-line-clamp: unset;
|
-webkit-line-clamp: unset;
|
||||||
max-height: 999rem;
|
max-height: 999rem;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr v-for="narrator in narrators" :key="narrator.id">
|
<tr v-for="narrator in narrators" :key="narrator.id">
|
||||||
<td>
|
<td>
|
||||||
<p v-if="selectedNarrator?.id !== narrator.id" class="text-sm md:text-base text-gray-100">{{ narrator.name }}</p>
|
<nuxt-link v-if="selectedNarrator?.id !== narrator.id" :to="`/library/${currentLibraryId}/bookshelf?filter=narrators.${narrator.id}`" class="text-sm md:text-base text-gray-100 hover:underline">{{ narrator.name }}</nuxt-link>
|
||||||
<form v-else @submit.prevent="saveClick">
|
<form v-else @submit.prevent="saveClick">
|
||||||
<ui-text-input v-model="newNarratorName" />
|
<ui-text-input v-model="newNarratorName" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ export default {
|
|||||||
return episodeIds
|
return episodeIds
|
||||||
},
|
},
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
return this.$store.state.serverSettings.dateFormat
|
return this.$store.getters['getServerSetting']('dateFormat')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -249,7 +249,7 @@ export default {
|
|||||||
},
|
},
|
||||||
async loadRecentEpisodes(page = 0) {
|
async loadRecentEpisodes(page = 0) {
|
||||||
this.processing = true
|
this.processing = true
|
||||||
const episodePayload = await this.$axios.$get(`/api/libraries/${this.libraryId}/recent-episodes?limit=25&page=${page}`).catch((error) => {
|
const episodePayload = await this.$axios.$get(`/api/libraries/${this.libraryId}/recent-episodes?limit=50&page=${page}`).catch((error) => {
|
||||||
console.error('Failed to get recent episodes', error)
|
console.error('Failed to get recent episodes', error)
|
||||||
this.$toast.error(this.$strings.ToastFailedToLoadData)
|
this.$toast.error(this.$strings.ToastFailedToLoadData)
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export default {
|
|||||||
})
|
})
|
||||||
results = {
|
results = {
|
||||||
podcasts: results?.podcast || [],
|
podcasts: results?.podcast || [],
|
||||||
|
episodes: results?.episodes || [],
|
||||||
books: results?.book || [],
|
books: results?.book || [],
|
||||||
authors: results?.authors || [],
|
authors: results?.authors || [],
|
||||||
series: results?.series || [],
|
series: results?.series || [],
|
||||||
@@ -61,6 +62,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.results = {
|
this.results = {
|
||||||
podcasts: results?.podcast || [],
|
podcasts: results?.podcast || [],
|
||||||
|
episodes: results?.episodes || [],
|
||||||
books: results?.book || [],
|
books: results?.book || [],
|
||||||
authors: results?.authors || [],
|
authors: results?.authors || [],
|
||||||
series: results?.series || [],
|
series: results?.series || [],
|
||||||
|
|||||||
@@ -89,14 +89,16 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
asyncData({ redirect, store }) {
|
async asyncData({ redirect, store, params }) {
|
||||||
if (!store.getters['user/getIsAdminOrUp']) {
|
if (!store.getters['user/getIsAdminOrUp']) {
|
||||||
redirect('/')
|
redirect('/')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!store.state.libraries.currentLibraryId) {
|
const libraryId = params.library
|
||||||
return redirect('/config')
|
const library = await store.dispatch('libraries/fetch', libraryId)
|
||||||
|
if (!library) {
|
||||||
|
return redirect(`/oops?message=Library "${libraryId}" not found`)
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
|
|||||||
+30
-5
@@ -40,6 +40,15 @@
|
|||||||
|
|
||||||
<p v-if="error" class="text-error text-center py-2">{{ error }}</p>
|
<p v-if="error" class="text-error text-center py-2">{{ error }}</p>
|
||||||
|
|
||||||
|
<div v-if="showNewAuthSystemMessage" class="mb-4">
|
||||||
|
<widgets-alert type="warning">
|
||||||
|
<div>
|
||||||
|
<p>{{ $strings.MessageAuthenticationSecurityMessage }}</p>
|
||||||
|
<a v-if="showNewAuthSystemAdminMessage" href="https://github.com/advplyr/audiobookshelf/discussions/4460" target="_blank" class="underline">{{ $strings.LabelMoreInfo }}</a>
|
||||||
|
</div>
|
||||||
|
</widgets-alert>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form v-show="login_local" @submit.prevent="submitForm">
|
<form v-show="login_local" @submit.prevent="submitForm">
|
||||||
<label class="text-xs text-gray-300 uppercase">{{ $strings.LabelUsername }}</label>
|
<label class="text-xs text-gray-300 uppercase">{{ $strings.LabelUsername }}</label>
|
||||||
<ui-text-input v-model.trim="username" :disabled="processing" class="mb-3 w-full" inputName="username" />
|
<ui-text-input v-model.trim="username" :disabled="processing" class="mb-3 w-full" inputName="username" />
|
||||||
@@ -85,7 +94,10 @@ export default {
|
|||||||
MetadataPath: '',
|
MetadataPath: '',
|
||||||
login_local: true,
|
login_local: true,
|
||||||
login_openid: false,
|
login_openid: false,
|
||||||
authFormData: null
|
authFormData: null,
|
||||||
|
// New JWT auth system re-login flags
|
||||||
|
showNewAuthSystemMessage: false,
|
||||||
|
showNewAuthSystemAdminMessage: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -179,11 +191,14 @@ export default {
|
|||||||
|
|
||||||
this.$store.commit('libraries/setCurrentLibrary', userDefaultLibraryId)
|
this.$store.commit('libraries/setCurrentLibrary', userDefaultLibraryId)
|
||||||
this.$store.commit('user/setUser', user)
|
this.$store.commit('user/setUser', user)
|
||||||
|
this.$store.commit('user/setAccessToken', user.accessToken)
|
||||||
|
|
||||||
this.$store.dispatch('user/loadUserSettings')
|
this.$store.dispatch('user/loadUserSettings')
|
||||||
},
|
},
|
||||||
async submitForm() {
|
async submitForm() {
|
||||||
this.error = null
|
this.error = null
|
||||||
|
this.showNewAuthSystemMessage = false
|
||||||
|
this.showNewAuthSystemAdminMessage = false
|
||||||
this.processing = true
|
this.processing = true
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
@@ -217,15 +232,24 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
// Force re-login if user is using an old token with no expiration
|
||||||
|
if (res.user.isOldToken) {
|
||||||
|
this.username = res.user.username
|
||||||
|
this.showNewAuthSystemMessage = true
|
||||||
|
// Admin user sees link to github discussion
|
||||||
|
this.showNewAuthSystemAdminMessage = res.user.type === 'admin' || res.user.type === 'root'
|
||||||
|
return false
|
||||||
|
}
|
||||||
this.setUser(res)
|
this.setUser(res)
|
||||||
this.processing = false
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Authorize error', error)
|
console.error('Authorize error', error)
|
||||||
this.processing = false
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.processing = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
checkStatus() {
|
checkStatus() {
|
||||||
this.processing = true
|
this.processing = true
|
||||||
@@ -280,8 +304,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
if (this.$route.query?.setToken) {
|
// Token passed as query parameter after successful oidc login
|
||||||
localStorage.setItem('token', this.$route.query.setToken)
|
if (this.$route.query?.accessToken) {
|
||||||
|
localStorage.setItem('token', this.$route.query.accessToken)
|
||||||
}
|
}
|
||||||
if (localStorage.getItem('token')) {
|
if (localStorage.getItem('token')) {
|
||||||
if (await this.checkAuth()) return // if valid user no need to check status
|
if (await this.checkAuth()) return // if valid user no need to check status
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full h-dvh max-h-dvh overflow-hidden" :style="{ backgroundColor: coverRgb }">
|
<div class="w-full max-w-full h-dvh max-h-dvh overflow-hidden" :style="{ backgroundColor: coverRgb }">
|
||||||
<div class="w-screen h-screen absolute inset-0 pointer-events-none" style="background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(38, 38, 38, 1) 80%)"></div>
|
<div class="w-screen h-screen absolute inset-0 pointer-events-none" style="background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(38, 38, 38, 1) 80%)"></div>
|
||||||
<div class="absolute inset-0 w-screen h-dvh flex items-center justify-center z-10">
|
<div class="absolute inset-0 w-screen h-dvh flex items-center justify-center z-10">
|
||||||
<div class="w-full p-2 sm:p-4 md:p-8">
|
<div class="w-full p-2 sm:p-4 md:p-8">
|
||||||
@@ -335,8 +335,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resize() {
|
resize() {
|
||||||
this.windowWidth = window.innerWidth
|
setTimeout(() => {
|
||||||
this.windowHeight = window.innerHeight
|
this.windowWidth = window.innerWidth
|
||||||
|
this.windowHeight = window.innerHeight
|
||||||
|
this.$store.commit('globals/updateWindowSize', { width: window.innerWidth, height: window.innerHeight })
|
||||||
|
}, 100)
|
||||||
},
|
},
|
||||||
playerError(error) {
|
playerError(error) {
|
||||||
console.error('Player error', error)
|
console.error('Player error', error)
|
||||||
|
|||||||
@@ -316,9 +316,8 @@ export default {
|
|||||||
.$post('/api/upload', form)
|
.$post('/api/upload', form)
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Failed', error)
|
console.error('Failed to upload item', error)
|
||||||
var errorMessage = error.response && error.response.data ? error.response.data : 'Oops, something went wrong...'
|
this.$toast.error(error.response?.data || 'Oops, something went wrong...')
|
||||||
this.$toast.error(errorMessage)
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -360,15 +359,14 @@ export default {
|
|||||||
// Check if path already exists before starting upload
|
// Check if path already exists before starting upload
|
||||||
// uploading fails if path already exists
|
// uploading fails if path already exists
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const filepath = Path.join(this.selectedFolder.fullPath, item.directory)
|
|
||||||
const exists = await this.$axios
|
const exists = await this.$axios
|
||||||
.$post(`/api/filesystem/pathexists`, { filepath, directory: item.directory, folderPath: this.selectedFolder.fullPath })
|
.$post(`/api/filesystem/pathexists`, { directory: item.directory, folderPath: this.selectedFolder.fullPath })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.exists) {
|
if (data.exists) {
|
||||||
if (data.libraryItemTitle) {
|
if (data.libraryItemTitle) {
|
||||||
this.$toast.error(this.$getString('ToastUploaderItemExistsInSubdirectoryError', [data.libraryItemTitle]))
|
this.$toast.error(this.$getString('ToastUploaderItemExistsInSubdirectoryError', [data.libraryItemTitle]))
|
||||||
} else {
|
} else {
|
||||||
this.$toast.error(this.$getString('ToastUploaderFilepathExistsError', [filepath]))
|
this.$toast.error(this.$getString('ToastUploaderFilepathExistsError', [Path.join(this.selectedFolder.fullPath, item.directory)]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data.exists
|
return data.exists
|
||||||
@@ -382,13 +380,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let itemsUploaded = 0
|
|
||||||
let itemsFailed = 0
|
|
||||||
for (const item of itemsToUpload) {
|
for (const item of itemsToUpload) {
|
||||||
this.updateItemCardStatus(item.index, 'uploading')
|
this.updateItemCardStatus(item.index, 'uploading')
|
||||||
const result = await this.uploadItem(item)
|
const result = await this.uploadItem(item)
|
||||||
if (result) itemsUploaded++
|
|
||||||
else itemsFailed++
|
|
||||||
this.updateItemCardStatus(item.index, result ? 'success' : 'failed')
|
this.updateItemCardStatus(item.index, result ? 'success' : 'failed')
|
||||||
}
|
}
|
||||||
this.processing = false
|
this.processing = false
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export default class AudioTrack {
|
export default class AudioTrack {
|
||||||
constructor(track, userToken, routerBasePath) {
|
constructor(track, sessionId, routerBasePath) {
|
||||||
this.index = track.index || 0
|
this.index = track.index || 0
|
||||||
this.startOffset = track.startOffset || 0 // Total time of all previous tracks
|
this.startOffset = track.startOffset || 0 // Total time of all previous tracks
|
||||||
this.duration = track.duration || 0
|
this.duration = track.duration || 0
|
||||||
@@ -8,28 +8,29 @@ export default class AudioTrack {
|
|||||||
this.mimeType = track.mimeType
|
this.mimeType = track.mimeType
|
||||||
this.metadata = track.metadata || {}
|
this.metadata = track.metadata || {}
|
||||||
|
|
||||||
this.userToken = userToken
|
this.sessionId = sessionId
|
||||||
this.routerBasePath = routerBasePath || ''
|
this.routerBasePath = routerBasePath || ''
|
||||||
|
if (this.contentUrl?.startsWith('/hls')) {
|
||||||
|
this.sessionTrackUrl = this.contentUrl
|
||||||
|
} else {
|
||||||
|
this.sessionTrackUrl = `/public/session/${sessionId}/track/${this.index}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for CastPlayer
|
* Used for CastPlayer
|
||||||
*/
|
*/
|
||||||
get fullContentUrl() {
|
get fullContentUrl() {
|
||||||
if (!this.contentUrl || this.contentUrl.startsWith('http')) return this.contentUrl
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
return `${process.env.serverUrl}${this.contentUrl}?token=${this.userToken}`
|
return `${process.env.serverUrl}${this.sessionTrackUrl}`
|
||||||
}
|
}
|
||||||
return `${window.location.origin}${this.routerBasePath}${this.contentUrl}?token=${this.userToken}`
|
return `${window.location.origin}${this.routerBasePath}${this.sessionTrackUrl}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for LocalPlayer
|
* Used for LocalPlayer
|
||||||
*/
|
*/
|
||||||
get relativeContentUrl() {
|
get relativeContentUrl() {
|
||||||
if (!this.contentUrl || this.contentUrl.startsWith('http')) return this.contentUrl
|
return `${this.routerBasePath}${this.sessionTrackUrl}`
|
||||||
|
|
||||||
return `${this.routerBasePath}${this.contentUrl}?token=${this.userToken}`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ export default class PlayerHandler {
|
|||||||
get isPlayingLocalItem() {
|
get isPlayingLocalItem() {
|
||||||
return this.libraryItem && this.player instanceof LocalAudioPlayer
|
return this.libraryItem && this.player instanceof LocalAudioPlayer
|
||||||
}
|
}
|
||||||
get userToken() {
|
|
||||||
return this.ctx.$store.getters['user/getToken']
|
|
||||||
}
|
|
||||||
get playerPlaying() {
|
get playerPlaying() {
|
||||||
return this.playerState === 'PLAYING'
|
return this.playerState === 'PLAYING'
|
||||||
}
|
}
|
||||||
@@ -226,7 +223,7 @@ export default class PlayerHandler {
|
|||||||
|
|
||||||
console.log('[PlayerHandler] Preparing Session', session)
|
console.log('[PlayerHandler] Preparing Session', session)
|
||||||
|
|
||||||
var audioTracks = session.audioTracks.map((at) => new AudioTrack(at, this.userToken, this.ctx.$config.routerBasePath))
|
var audioTracks = session.audioTracks.map((at) => new AudioTrack(at, session.id, this.ctx.$config.routerBasePath))
|
||||||
|
|
||||||
this.ctx.playerLoading = true
|
this.ctx.playerLoading = true
|
||||||
this.isHlsTranscode = true
|
this.isHlsTranscode = true
|
||||||
|
|||||||
+88
-3
@@ -1,4 +1,19 @@
|
|||||||
export default function ({ $axios, store, $config }) {
|
export default function ({ $axios, store, $root, app }) {
|
||||||
|
// Track if we're currently refreshing to prevent multiple refresh attempts
|
||||||
|
let isRefreshing = false
|
||||||
|
let failedQueue = []
|
||||||
|
|
||||||
|
const processQueue = (error, token = null) => {
|
||||||
|
failedQueue.forEach(({ resolve, reject }) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error)
|
||||||
|
} else {
|
||||||
|
resolve(token)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
failedQueue = []
|
||||||
|
}
|
||||||
|
|
||||||
$axios.onRequest((config) => {
|
$axios.onRequest((config) => {
|
||||||
if (!config.url) {
|
if (!config.url) {
|
||||||
console.error('Axios request invalid config', config)
|
console.error('Axios request invalid config', config)
|
||||||
@@ -7,7 +22,7 @@ export default function ({ $axios, store, $config }) {
|
|||||||
if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
|
if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const bearerToken = store.state.user.user?.token || null
|
const bearerToken = store.getters['user/getToken']
|
||||||
if (bearerToken) {
|
if (bearerToken) {
|
||||||
config.headers.common['Authorization'] = `Bearer ${bearerToken}`
|
config.headers.common['Authorization'] = `Bearer ${bearerToken}`
|
||||||
}
|
}
|
||||||
@@ -17,9 +32,79 @@ export default function ({ $axios, store, $config }) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$axios.onError((error) => {
|
$axios.onError(async (error) => {
|
||||||
|
const originalRequest = error.config
|
||||||
const code = parseInt(error.response && error.response.status)
|
const code = parseInt(error.response && error.response.status)
|
||||||
const message = error.response ? error.response.data || 'Unknown Error' : 'Unknown Error'
|
const message = error.response ? error.response.data || 'Unknown Error' : 'Unknown Error'
|
||||||
|
|
||||||
console.error('Axios error', code, message)
|
console.error('Axios error', code, message)
|
||||||
|
|
||||||
|
// Handle 401 Unauthorized (token expired)
|
||||||
|
if (code === 401 && !originalRequest._retry) {
|
||||||
|
// Skip refresh for auth endpoints to prevent infinite loops
|
||||||
|
if (originalRequest.url === '/auth/refresh' || originalRequest.url === '/login') {
|
||||||
|
// Refresh failed or login failed, redirect to login
|
||||||
|
store.commit('user/setUser', null)
|
||||||
|
store.commit('user/setAccessToken', null)
|
||||||
|
app.router.push('/login')
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRefreshing) {
|
||||||
|
// If already refreshing, queue this request
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
failedQueue.push({ resolve, reject })
|
||||||
|
})
|
||||||
|
.then((token) => {
|
||||||
|
if (!originalRequest.headers) {
|
||||||
|
originalRequest.headers = {}
|
||||||
|
}
|
||||||
|
originalRequest.headers['Authorization'] = `Bearer ${token}`
|
||||||
|
return $axios(originalRequest)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
return Promise.reject(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
originalRequest._retry = true
|
||||||
|
isRefreshing = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Attempt to refresh the token
|
||||||
|
// Updates store if successful, otherwise clears store and throw error
|
||||||
|
const newAccessToken = await store.dispatch('user/refreshToken')
|
||||||
|
if (!newAccessToken) {
|
||||||
|
console.error('No new access token received')
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the original request with new token
|
||||||
|
if (!originalRequest.headers) {
|
||||||
|
originalRequest.headers = {}
|
||||||
|
}
|
||||||
|
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`
|
||||||
|
|
||||||
|
// Process any queued requests
|
||||||
|
processQueue(null, newAccessToken)
|
||||||
|
|
||||||
|
// Retry the original request
|
||||||
|
return $axios(originalRequest)
|
||||||
|
} catch (refreshError) {
|
||||||
|
console.error('Token refresh failed:', refreshError)
|
||||||
|
|
||||||
|
// Process queued requests with error
|
||||||
|
processQueue(refreshError, null)
|
||||||
|
|
||||||
|
// Redirect to login
|
||||||
|
app.router.push('/login')
|
||||||
|
|
||||||
|
return Promise.reject(refreshError)
|
||||||
|
} finally {
|
||||||
|
isRefreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const SupportedFileTypes = {
|
const SupportedFileTypes = {
|
||||||
image: ['png', 'jpg', 'jpeg', 'webp'],
|
image: ['png', 'jpg', 'jpeg', 'webp'],
|
||||||
audio: ['m4b', 'mp3', 'm4a', 'flac', 'opus', 'ogg', 'oga', 'mp4', 'aac', 'wma', 'aiff', 'wav', 'webm', 'webma', 'mka', 'awb', 'caf', 'mpeg', 'mpg'],
|
audio: ['m4b', 'mp3', 'm4a', 'flac', 'opus', 'ogg', 'oga', 'mp4', 'aac', 'wma', 'aiff', 'aif','wav', 'webm', 'webma', 'mka', 'awb', 'caf', 'mpeg', 'mpg'],
|
||||||
ebook: ['epub', 'pdf', 'mobi', 'azw3', 'cbr', 'cbz'],
|
ebook: ['epub', 'pdf', 'mobi', 'azw3', 'cbr', 'cbz'],
|
||||||
info: ['nfo'],
|
info: ['nfo'],
|
||||||
text: ['txt'],
|
text: ['txt'],
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { supplant } from './utils'
|
|||||||
const defaultCode = 'en-us'
|
const defaultCode = 'en-us'
|
||||||
|
|
||||||
const languageCodeMap = {
|
const languageCodeMap = {
|
||||||
|
ar: { label: 'عربي', dateFnsLocale: 'ar' },
|
||||||
bg: { label: 'Български', dateFnsLocale: 'bg' },
|
bg: { label: 'Български', dateFnsLocale: 'bg' },
|
||||||
bn: { label: 'বাংলা', dateFnsLocale: 'bn' },
|
bn: { label: 'বাংলা', dateFnsLocale: 'bn' },
|
||||||
ca: { label: 'Català', dateFnsLocale: 'ca' },
|
ca: { label: 'Català', dateFnsLocale: 'ca' },
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ export const mutations = {
|
|||||||
state.playerQueueItems = payload.queueItems || []
|
state.playerQueueItems = payload.queueItems || []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateStreamLibraryItem(state, libraryItem) {
|
||||||
|
if (!libraryItem) return
|
||||||
|
state.streamLibraryItem = libraryItem
|
||||||
|
},
|
||||||
setIsPlaying(state, isPlaying) {
|
setIsPlaying(state, isPlaying) {
|
||||||
state.streamIsPlaying = isPlaying
|
state.streamIsPlaying = isPlaying
|
||||||
},
|
},
|
||||||
|
|||||||
+36
-11
@@ -1,5 +1,6 @@
|
|||||||
export const state = () => ({
|
export const state = () => ({
|
||||||
user: null,
|
user: null,
|
||||||
|
accessToken: null,
|
||||||
settings: {
|
settings: {
|
||||||
orderBy: 'media.metadata.title',
|
orderBy: 'media.metadata.title',
|
||||||
orderDesc: false,
|
orderDesc: false,
|
||||||
@@ -25,19 +26,19 @@ export const getters = {
|
|||||||
getIsRoot: (state) => state.user && state.user.type === 'root',
|
getIsRoot: (state) => state.user && state.user.type === 'root',
|
||||||
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
|
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
|
||||||
getToken: (state) => {
|
getToken: (state) => {
|
||||||
return state.user?.token || null
|
return state.accessToken || null
|
||||||
},
|
},
|
||||||
getUserMediaProgress:
|
getUserMediaProgress:
|
||||||
(state) =>
|
(state) =>
|
||||||
(libraryItemId, episodeId = null) => {
|
(libraryItemId, episodeId = null) => {
|
||||||
if (!state.user.mediaProgress) return null
|
if (!state.user?.mediaProgress) return null
|
||||||
return state.user.mediaProgress.find((li) => {
|
return state.user.mediaProgress.find((li) => {
|
||||||
if (episodeId && li.episodeId !== episodeId) return false
|
if (episodeId && li.episodeId !== episodeId) return false
|
||||||
return li.libraryItemId == libraryItemId
|
return li.libraryItemId == libraryItemId
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getUserBookmarksForItem: (state) => (libraryItemId) => {
|
getUserBookmarksForItem: (state) => (libraryItemId) => {
|
||||||
if (!state.user.bookmarks) return []
|
if (!state.user?.bookmarks) return []
|
||||||
return state.user.bookmarks.filter((bm) => bm.libraryItemId === libraryItemId)
|
return state.user.bookmarks.filter((bm) => bm.libraryItemId === libraryItemId)
|
||||||
},
|
},
|
||||||
getUserSetting: (state) => (key) => {
|
getUserSetting: (state) => (key) => {
|
||||||
@@ -58,6 +59,9 @@ export const getters = {
|
|||||||
getUserCanAccessAllLibraries: (state) => {
|
getUserCanAccessAllLibraries: (state) => {
|
||||||
return !!state.user?.permissions?.accessAllLibraries
|
return !!state.user?.permissions?.accessAllLibraries
|
||||||
},
|
},
|
||||||
|
getUserCanAccessExplicitContent: (state) => {
|
||||||
|
return !!state.user?.permissions?.accessExplicitContent
|
||||||
|
},
|
||||||
getLibrariesAccessible: (state, getters) => {
|
getLibrariesAccessible: (state, getters) => {
|
||||||
if (!state.user) return []
|
if (!state.user) return []
|
||||||
if (getters.getUserCanAccessAllLibraries) return []
|
if (getters.getUserCanAccessAllLibraries) return []
|
||||||
@@ -142,21 +146,42 @@ export const actions = {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load userSettings from local storage', error)
|
console.error('Failed to load userSettings from local storage', error)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
refreshToken({ state, commit }) {
|
||||||
|
return this.$axios
|
||||||
|
.$post('/auth/refresh')
|
||||||
|
.then(async (response) => {
|
||||||
|
const newAccessToken = response.user.accessToken
|
||||||
|
commit('setUser', response.user)
|
||||||
|
commit('setAccessToken', newAccessToken)
|
||||||
|
// Emit event used to re-authenticate socket in default.vue since $root is not available here
|
||||||
|
if (this.$eventBus) {
|
||||||
|
this.$eventBus.$emit('token_refreshed', newAccessToken)
|
||||||
|
}
|
||||||
|
return newAccessToken
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Failed to refresh token', error)
|
||||||
|
commit('setUser', null)
|
||||||
|
commit('setAccessToken', null)
|
||||||
|
// Calling function handles redirect to login
|
||||||
|
throw error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mutations = {
|
export const mutations = {
|
||||||
setUser(state, user) {
|
setUser(state, user) {
|
||||||
state.user = user
|
state.user = user
|
||||||
if (user) {
|
|
||||||
if (user.token) localStorage.setItem('token', user.token)
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem('token')
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
setUserToken(state, token) {
|
setAccessToken(state, token) {
|
||||||
state.user.token = token
|
if (!token) {
|
||||||
localStorage.setItem('token', token)
|
localStorage.removeItem('token')
|
||||||
|
state.accessToken = null
|
||||||
|
} else {
|
||||||
|
state.accessToken = token
|
||||||
|
localStorage.setItem('token', token)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateMediaProgress(state, { id, data }) {
|
updateMediaProgress(state, { id, data }) {
|
||||||
if (!state.user) return
|
if (!state.user) return
|
||||||
|
|||||||
+965
-12
File diff suppressed because it is too large
Load Diff
+71
-2
@@ -177,6 +177,7 @@
|
|||||||
"HeaderPlaylist": "Плейлист",
|
"HeaderPlaylist": "Плейлист",
|
||||||
"HeaderPlaylistItems": "Елементи от плейлист",
|
"HeaderPlaylistItems": "Елементи от плейлист",
|
||||||
"HeaderPodcastsToAdd": "Подкасти за Добавяне",
|
"HeaderPodcastsToAdd": "Подкасти за Добавяне",
|
||||||
|
"HeaderPresets": "Настройки по подразбиране",
|
||||||
"HeaderPreviewCover": "Преглед на Корица",
|
"HeaderPreviewCover": "Преглед на Корица",
|
||||||
"HeaderRSSFeedGeneral": "RSS подробности",
|
"HeaderRSSFeedGeneral": "RSS подробности",
|
||||||
"HeaderRSSFeedIsOpen": "RSS емисията е отворена",
|
"HeaderRSSFeedIsOpen": "RSS емисията е отворена",
|
||||||
@@ -219,6 +220,7 @@
|
|||||||
"LabelAccountTypeAdmin": "Администратор",
|
"LabelAccountTypeAdmin": "Администратор",
|
||||||
"LabelAccountTypeGuest": "Гост",
|
"LabelAccountTypeGuest": "Гост",
|
||||||
"LabelAccountTypeUser": "Потребител",
|
"LabelAccountTypeUser": "Потребител",
|
||||||
|
"LabelActivities": "Дейности",
|
||||||
"LabelActivity": "Дейност",
|
"LabelActivity": "Дейност",
|
||||||
"LabelAddToCollection": "Добави в Колекция",
|
"LabelAddToCollection": "Добави в Колекция",
|
||||||
"LabelAddToCollectionBatch": "Добави {0} Книги в Колекция",
|
"LabelAddToCollectionBatch": "Добави {0} Книги в Колекция",
|
||||||
@@ -253,7 +255,7 @@
|
|||||||
"LabelBackupLocation": "Местоположение на Архив",
|
"LabelBackupLocation": "Местоположение на Архив",
|
||||||
"LabelBackupsEnableAutomaticBackups": "Включи автоматично архивиране",
|
"LabelBackupsEnableAutomaticBackups": "Включи автоматично архивиране",
|
||||||
"LabelBackupsEnableAutomaticBackupsHelp": "Архиви запазени в /metadata/backups",
|
"LabelBackupsEnableAutomaticBackupsHelp": "Архиви запазени в /metadata/backups",
|
||||||
"LabelBackupsMaxBackupSize": "Максимален размер на архива (в GB)",
|
"LabelBackupsMaxBackupSize": "Максимален размер на архива (в GB) (0 за неограничен)",
|
||||||
"LabelBackupsMaxBackupSizeHelp": "За защита срещу грешки в конфигурацията, архивите ще се провалят ако надхвърлят конфигурирания размер.",
|
"LabelBackupsMaxBackupSizeHelp": "За защита срещу грешки в конфигурацията, архивите ще се провалят ако надхвърлят конфигурирания размер.",
|
||||||
"LabelBackupsNumberToKeep": "Брой архиви за запазване",
|
"LabelBackupsNumberToKeep": "Брой архиви за запазване",
|
||||||
"LabelBackupsNumberToKeepHelp": "Само 1 архив ще бъде премахнат на веднъж, така че ако вече имате повече архиви от това трябва да ги премахнете ръчно.",
|
"LabelBackupsNumberToKeepHelp": "Само 1 архив ще бъде премахнат на веднъж, така че ако вече имате повече архиви от това трябва да ги премахнете ръчно.",
|
||||||
@@ -283,6 +285,7 @@
|
|||||||
"LabelContinueSeries": "Продължи серии",
|
"LabelContinueSeries": "Продължи серии",
|
||||||
"LabelCover": "Корица",
|
"LabelCover": "Корица",
|
||||||
"LabelCoverImageURL": "URL на Корица",
|
"LabelCoverImageURL": "URL на Корица",
|
||||||
|
"LabelCoverProvider": "Източник за обложки",
|
||||||
"LabelCreatedAt": "Създадено на",
|
"LabelCreatedAt": "Създадено на",
|
||||||
"LabelCronExpression": "Cron израз",
|
"LabelCronExpression": "Cron израз",
|
||||||
"LabelCurrent": "Текущо",
|
"LabelCurrent": "Текущо",
|
||||||
@@ -325,11 +328,20 @@
|
|||||||
"LabelEncodingClearItemCache": "Уверете се, че периодично изчиствате кеша на елементите.",
|
"LabelEncodingClearItemCache": "Уверете се, че периодично изчиствате кеша на елементите.",
|
||||||
"LabelEncodingFinishedM4B": "Завършеният M4B файл ще бъде поставен в папката на вашите аудиокниги на:",
|
"LabelEncodingFinishedM4B": "Завършеният M4B файл ще бъде поставен в папката на вашите аудиокниги на:",
|
||||||
"LabelEncodingInfoEmbedded": "Метаданните ще бъдат вградени в аудио траковете в папката на вашите аудиокниги.",
|
"LabelEncodingInfoEmbedded": "Метаданните ще бъдат вградени в аудио траковете в папката на вашите аудиокниги.",
|
||||||
|
"LabelEncodingStartedNavigation": "Когато задачата е стартирана, можете да смените тази страница.",
|
||||||
|
"LabelEncodingTimeWarning": "Кодирането може да отнеме до 30 минути.",
|
||||||
|
"LabelEncodingWarningAdvancedSettings": "Внимание: Не променяйте тези настройки, ако не сте запознати с ffmpeg настройките за кодиране.",
|
||||||
|
"LabelEncodingWatcherDisabled": "Ако сте изключили наблюдението на папки, ще е нужно да сканирате повторно аудио книгата.",
|
||||||
"LabelEnd": "Край",
|
"LabelEnd": "Край",
|
||||||
"LabelEndOfChapter": "Край на глава",
|
"LabelEndOfChapter": "Край на глава",
|
||||||
"LabelEpisode": "Епизод",
|
"LabelEpisode": "Епизод",
|
||||||
|
"LabelEpisodeNotLinkedToRssFeed": "Епизодът не е свързан с RSS канал",
|
||||||
|
"LabelEpisodeNumber": "Епизод #{0}",
|
||||||
"LabelEpisodeTitle": "Заглавие на Епизод",
|
"LabelEpisodeTitle": "Заглавие на Епизод",
|
||||||
"LabelEpisodeType": "Тип на Епизод",
|
"LabelEpisodeType": "Тип на Епизод",
|
||||||
|
"LabelEpisodeUrlFromRssFeed": "URL адрес на епизод от RSS канал",
|
||||||
|
"LabelEpisodes": "Епизоди",
|
||||||
|
"LabelEpisodic": "Епизодичен",
|
||||||
"LabelExample": "Пример",
|
"LabelExample": "Пример",
|
||||||
"LabelExpandSeries": "Покажи сериите",
|
"LabelExpandSeries": "Покажи сериите",
|
||||||
"LabelExpandSubSeries": "Покажи съб сериите",
|
"LabelExpandSubSeries": "Покажи съб сериите",
|
||||||
@@ -341,7 +353,9 @@
|
|||||||
"LabelFetchingMetadata": "Взимане на Метаданни",
|
"LabelFetchingMetadata": "Взимане на Метаданни",
|
||||||
"LabelFile": "Файл",
|
"LabelFile": "Файл",
|
||||||
"LabelFileBirthtime": "Дата на създаване на файла",
|
"LabelFileBirthtime": "Дата на създаване на файла",
|
||||||
|
"LabelFileBornDate": "Роден {0}",
|
||||||
"LabelFileModified": "Дата на модификация на файла",
|
"LabelFileModified": "Дата на модификация на файла",
|
||||||
|
"LabelFileModifiedDate": "Променен {0}",
|
||||||
"LabelFilename": "Име на файла",
|
"LabelFilename": "Име на файла",
|
||||||
"LabelFilterByUser": "Филтриране по Потребител",
|
"LabelFilterByUser": "Филтриране по Потребител",
|
||||||
"LabelFindEpisodes": "Намери Епизоди",
|
"LabelFindEpisodes": "Намери Епизоди",
|
||||||
@@ -355,14 +369,17 @@
|
|||||||
"LabelFontScale": "Мащаб на шрифта",
|
"LabelFontScale": "Мащаб на шрифта",
|
||||||
"LabelFontStrikethrough": "Зачертан",
|
"LabelFontStrikethrough": "Зачертан",
|
||||||
"LabelFormat": "Формат",
|
"LabelFormat": "Формат",
|
||||||
|
"LabelFull": "Пълен",
|
||||||
"LabelGenre": "Жанр",
|
"LabelGenre": "Жанр",
|
||||||
"LabelGenres": "Жанрове",
|
"LabelGenres": "Жанрове",
|
||||||
"LabelHardDeleteFile": "Пълно Изтриване на Файл",
|
"LabelHardDeleteFile": "Пълно Изтриване на Файл",
|
||||||
"LabelHasEbook": "Има е-книга",
|
"LabelHasEbook": "Има е-книга",
|
||||||
"LabelHasSupplementaryEbook": "Има допълнителна е-книга",
|
"LabelHasSupplementaryEbook": "Има допълнителна е-книга",
|
||||||
|
"LabelHideSubtitles": "Скрий субтитри",
|
||||||
"LabelHighestPriority": "Най-висок Приоритет",
|
"LabelHighestPriority": "Най-висок Приоритет",
|
||||||
"LabelHost": "Хост",
|
"LabelHost": "Хост",
|
||||||
"LabelHour": "Час",
|
"LabelHour": "Час",
|
||||||
|
"LabelHours": "Часа",
|
||||||
"LabelIcon": "Икона",
|
"LabelIcon": "Икона",
|
||||||
"LabelImageURLFromTheWeb": "URL на Изображение от Интернет",
|
"LabelImageURLFromTheWeb": "URL на Изображение от Интернет",
|
||||||
"LabelInProgress": "В процес на изпълнение",
|
"LabelInProgress": "В процес на изпълнение",
|
||||||
@@ -377,8 +394,11 @@
|
|||||||
"LabelIntervalEvery6Hours": "Всеки 6 часа",
|
"LabelIntervalEvery6Hours": "Всеки 6 часа",
|
||||||
"LabelIntervalEveryDay": "Всеки ден",
|
"LabelIntervalEveryDay": "Всеки ден",
|
||||||
"LabelIntervalEveryHour": "Всеки час",
|
"LabelIntervalEveryHour": "Всеки час",
|
||||||
|
"LabelIntervalEveryMinute": "Всяка минута",
|
||||||
"LabelInvert": "Обърни",
|
"LabelInvert": "Обърни",
|
||||||
"LabelItem": "Елемент",
|
"LabelItem": "Елемент",
|
||||||
|
"LabelJumpBackwardAmount": "Количество за прескачане назад",
|
||||||
|
"LabelJumpForwardAmount": "Количество за прескачане напред",
|
||||||
"LabelLanguage": "Език",
|
"LabelLanguage": "Език",
|
||||||
"LabelLanguageDefaultServer": "Език по подразбиране на сървъра",
|
"LabelLanguageDefaultServer": "Език по подразбиране на сървъра",
|
||||||
"LabelLanguages": "Езици",
|
"LabelLanguages": "Езици",
|
||||||
@@ -393,6 +413,7 @@
|
|||||||
"LabelLess": "По-малко",
|
"LabelLess": "По-малко",
|
||||||
"LabelLibrariesAccessibleToUser": "Библиотеки Достъпни за Потребителя",
|
"LabelLibrariesAccessibleToUser": "Библиотеки Достъпни за Потребителя",
|
||||||
"LabelLibrary": "Библиотека",
|
"LabelLibrary": "Библиотека",
|
||||||
|
"LabelLibraryFilterSublistEmpty": "Не {0}",
|
||||||
"LabelLibraryItem": "Елемент на Библиотека",
|
"LabelLibraryItem": "Елемент на Библиотека",
|
||||||
"LabelLibraryName": "Име на Библиотека",
|
"LabelLibraryName": "Име на Библиотека",
|
||||||
"LabelLimit": "Лимит",
|
"LabelLimit": "Лимит",
|
||||||
@@ -405,6 +426,10 @@
|
|||||||
"LabelLowestPriority": "Най-нисък Приоритет",
|
"LabelLowestPriority": "Най-нисък Приоритет",
|
||||||
"LabelMatchExistingUsersBy": "Съпостави съществуващи потребители по",
|
"LabelMatchExistingUsersBy": "Съпостави съществуващи потребители по",
|
||||||
"LabelMatchExistingUsersByDescription": "Използва се за свързване на съществуващи потребители. След свързване потребителите ще бъдат съпоставени по уникален идентификатор от вашия доставчик на SSO",
|
"LabelMatchExistingUsersByDescription": "Използва се за свързване на съществуващи потребители. След свързване потребителите ще бъдат съпоставени по уникален идентификатор от вашия доставчик на SSO",
|
||||||
|
"LabelMaxEpisodesToDownload": "Максимален брой епизоди за сваляне. Използвай 0 за неограничен.",
|
||||||
|
"LabelMaxEpisodesToDownloadPerCheck": "Максимален брой нови епизоди за сваляне за проверка",
|
||||||
|
"LabelMaxEpisodesToKeep": "Максимален брой епизоди за запазване",
|
||||||
|
"LabelMaxEpisodesToKeepHelp": "Стойност 0 указва без максимален лимит. След като нов епизод е автоматично свален, най-старият епизод ще бъде изтрит, ако имате повече от X епизода. Само по един епизод ще бъде изтриван за всеки нов свален такъв.",
|
||||||
"LabelMediaPlayer": "Медия Плейър",
|
"LabelMediaPlayer": "Медия Плейър",
|
||||||
"LabelMediaType": "Тип медия",
|
"LabelMediaType": "Тип медия",
|
||||||
"LabelMetaTag": "Мета Таг",
|
"LabelMetaTag": "Мета Таг",
|
||||||
@@ -412,6 +437,7 @@
|
|||||||
"LabelMetadataOrderOfPrecedenceDescription": "По-високите източници на метаданни ще заменят по-ниските",
|
"LabelMetadataOrderOfPrecedenceDescription": "По-високите източници на метаданни ще заменят по-ниските",
|
||||||
"LabelMetadataProvider": "Доставчик на Метаданни",
|
"LabelMetadataProvider": "Доставчик на Метаданни",
|
||||||
"LabelMinute": "Минута",
|
"LabelMinute": "Минута",
|
||||||
|
"LabelMinutes": "Минути",
|
||||||
"LabelMissing": "Липсващо",
|
"LabelMissing": "Липсващо",
|
||||||
"LabelMissingEbook": "Няма електронна книга",
|
"LabelMissingEbook": "Няма електронна книга",
|
||||||
"LabelMissingSupplementaryEbook": "Няма допълнителна електронна книга",
|
"LabelMissingSupplementaryEbook": "Няма допълнителна електронна книга",
|
||||||
@@ -449,11 +475,14 @@
|
|||||||
"LabelOpenIDGroupClaimDescription": "Име на OpenID твърдението, което съдържа списък с групите на потребителя. Обикновено се нарича <code>groups</code>. <b>Ако е конфигурирано</b>, приложението автоматично ще присвоява роли въз основа на членството на потребителя в групи, при условие че тези групи са наименувани без чувствителност към регистъра като 'admin', 'user' или 'guest' в твърдението. Твърдението трябва да съдържа списък и ако потребителят принадлежи към множество групи, приложението ще присвои ролята, съответстваща на най-високото ниво на достъп. Ако няма съвпадение с група, достъпът ще бъде отказан.",
|
"LabelOpenIDGroupClaimDescription": "Име на OpenID твърдението, което съдържа списък с групите на потребителя. Обикновено се нарича <code>groups</code>. <b>Ако е конфигурирано</b>, приложението автоматично ще присвоява роли въз основа на членството на потребителя в групи, при условие че тези групи са наименувани без чувствителност към регистъра като 'admin', 'user' или 'guest' в твърдението. Твърдението трябва да съдържа списък и ако потребителят принадлежи към множество групи, приложението ще присвои ролята, съответстваща на най-високото ниво на достъп. Ако няма съвпадение с група, достъпът ще бъде отказан.",
|
||||||
"LabelOpenRSSFeed": "Отвори RSS Feed",
|
"LabelOpenRSSFeed": "Отвори RSS Feed",
|
||||||
"LabelOverwrite": "Презапиши",
|
"LabelOverwrite": "Презапиши",
|
||||||
|
"LabelPaginationPageXOfY": "Страница {0} от {1}",
|
||||||
"LabelPassword": "Парола",
|
"LabelPassword": "Парола",
|
||||||
"LabelPath": "Път",
|
"LabelPath": "Път",
|
||||||
|
"LabelPermanent": "Постоянен",
|
||||||
"LabelPermissionsAccessAllLibraries": "Може да достъпи до всички библиотеки",
|
"LabelPermissionsAccessAllLibraries": "Може да достъпи до всички библиотеки",
|
||||||
"LabelPermissionsAccessAllTags": "Може да достъпи всички тагове",
|
"LabelPermissionsAccessAllTags": "Може да достъпи всички тагове",
|
||||||
"LabelPermissionsAccessExplicitContent": "Може да достъпи експлицитно съдържание",
|
"LabelPermissionsAccessExplicitContent": "Може да достъпи експлицитно съдържание",
|
||||||
|
"LabelPermissionsCreateEreader": "Може да създава електронен четец",
|
||||||
"LabelPermissionsDelete": "Може да трие",
|
"LabelPermissionsDelete": "Може да трие",
|
||||||
"LabelPermissionsDownload": "Може да сваля",
|
"LabelPermissionsDownload": "Може да сваля",
|
||||||
"LabelPermissionsUpdate": "Може да обновява",
|
"LabelPermissionsUpdate": "Може да обновява",
|
||||||
@@ -461,6 +490,8 @@
|
|||||||
"LabelPersonalYearReview": "Преглед на годината Ви ({0})",
|
"LabelPersonalYearReview": "Преглед на годината Ви ({0})",
|
||||||
"LabelPhotoPathURL": "Път/URL на Снимка",
|
"LabelPhotoPathURL": "Път/URL на Снимка",
|
||||||
"LabelPlayMethod": "Метод на Пускане",
|
"LabelPlayMethod": "Метод на Пускане",
|
||||||
|
"LabelPlaybackRateIncrementDecrement": "Размер на увеличаване/намаляне при скоростта на възпроизвеждане",
|
||||||
|
"LabelPlayerChapterNumberMarker": "{0} от {1}",
|
||||||
"LabelPlaylists": "Плейлисти",
|
"LabelPlaylists": "Плейлисти",
|
||||||
"LabelPodcast": "Подкаст",
|
"LabelPodcast": "Подкаст",
|
||||||
"LabelPodcastSearchRegion": "Регион за Търсене на Подкасти",
|
"LabelPodcastSearchRegion": "Регион за Търсене на Подкасти",
|
||||||
@@ -472,9 +503,12 @@
|
|||||||
"LabelPrimaryEbook": "Основна Електронна Книга",
|
"LabelPrimaryEbook": "Основна Електронна Книга",
|
||||||
"LabelProgress": "Прогрес",
|
"LabelProgress": "Прогрес",
|
||||||
"LabelProvider": "Доставчик",
|
"LabelProvider": "Доставчик",
|
||||||
|
"LabelProviderAuthorizationValue": "Стойност на Authorization Header",
|
||||||
"LabelPubDate": "Дата на публикуване",
|
"LabelPubDate": "Дата на публикуване",
|
||||||
"LabelPublishYear": "Година на публикуване",
|
"LabelPublishYear": "Година на публикуване",
|
||||||
"LabelPublishedDate": "Публикувани {0}",
|
"LabelPublishedDate": "Публикувани {0}",
|
||||||
|
"LabelPublishedDecade": "Десетилетие на публикуване",
|
||||||
|
"LabelPublishedDecades": "Десетилетия на публикуване",
|
||||||
"LabelPublisher": "Издател",
|
"LabelPublisher": "Издател",
|
||||||
"LabelPublishers": "Издателство",
|
"LabelPublishers": "Издателство",
|
||||||
"LabelRSSFeedCustomOwnerEmail": "Персонализиран имейл на собственика",
|
"LabelRSSFeedCustomOwnerEmail": "Персонализиран имейл на собственика",
|
||||||
@@ -484,6 +518,7 @@
|
|||||||
"LabelRSSFeedSlug": "идентификатор на RSS емисия",
|
"LabelRSSFeedSlug": "идентификатор на RSS емисия",
|
||||||
"LabelRSSFeedURL": "URL на RSS емисия",
|
"LabelRSSFeedURL": "URL на RSS емисия",
|
||||||
"LabelRandomly": "Случайно",
|
"LabelRandomly": "Случайно",
|
||||||
|
"LabelReAddSeriesToContinueListening": "Добави отново в \"Продължете да слушате\"",
|
||||||
"LabelRead": "Прочети",
|
"LabelRead": "Прочети",
|
||||||
"LabelReadAgain": "Прочети отново",
|
"LabelReadAgain": "Прочети отново",
|
||||||
"LabelReadEbookWithoutProgress": "Прочети електронната книга без записване прогрес",
|
"LabelReadEbookWithoutProgress": "Прочети електронната книга без записване прогрес",
|
||||||
@@ -493,29 +528,40 @@
|
|||||||
"LabelRedo": "Повтори",
|
"LabelRedo": "Повтори",
|
||||||
"LabelRegion": "Регион",
|
"LabelRegion": "Регион",
|
||||||
"LabelReleaseDate": "Дата на Издаване",
|
"LabelReleaseDate": "Дата на Издаване",
|
||||||
|
"LabelRemoveAllMetadataAbs": "Премахни всички metadata.abs файлове",
|
||||||
|
"LabelRemoveAllMetadataJson": "Премахни всички metadata.json файлове",
|
||||||
|
"LabelRemoveAudibleBranding": "Премахни въведението и заключението на Audible от главите",
|
||||||
"LabelRemoveCover": "Премахни Корица",
|
"LabelRemoveCover": "Премахни Корица",
|
||||||
|
"LabelRemoveMetadataFile": "Премахни файловете с метаданни от папката на библиотеката",
|
||||||
|
"LabelRemoveMetadataFileHelp": "Премахни всички metadata.json и metadata.abs файлове от вашата {0} папка.",
|
||||||
"LabelRowsPerPage": "Редове на Страница",
|
"LabelRowsPerPage": "Редове на Страница",
|
||||||
"LabelSearchTerm": "Търси Термин",
|
"LabelSearchTerm": "Търси Термин",
|
||||||
"LabelSearchTitle": "Търси Заглавие",
|
"LabelSearchTitle": "Търси Заглавие",
|
||||||
"LabelSearchTitleOrASIN": "Търси Заглавие или ASIN",
|
"LabelSearchTitleOrASIN": "Търси Заглавие или ASIN",
|
||||||
"LabelSeason": "Сезон",
|
"LabelSeason": "Сезон",
|
||||||
|
"LabelSeasonNumber": "Сезон #{0}",
|
||||||
"LabelSelectAll": "Избери всичко",
|
"LabelSelectAll": "Избери всичко",
|
||||||
"LabelSelectAllEpisodes": "Избери всички епизоди",
|
"LabelSelectAllEpisodes": "Избери всички епизоди",
|
||||||
"LabelSelectEpisodesShowing": "Избери {0} епизоди показани",
|
"LabelSelectEpisodesShowing": "Избери {0} епизоди показани",
|
||||||
"LabelSelectUsers": "Избери Потребители",
|
"LabelSelectUsers": "Избери Потребители",
|
||||||
"LabelSendEbookToDevice": "Изпрати електронна книга до ...",
|
"LabelSendEbookToDevice": "Изпрати електронна книга до ...",
|
||||||
"LabelSequence": "Последователност",
|
"LabelSequence": "Последователност",
|
||||||
|
"LabelSerial": "Сериал",
|
||||||
"LabelSeries": "От сериите",
|
"LabelSeries": "От сериите",
|
||||||
"LabelSeriesName": "Име на Серия",
|
"LabelSeriesName": "Име на Серия",
|
||||||
"LabelSeriesProgress": "Прогрес на Серия",
|
"LabelSeriesProgress": "Прогрес на Серия",
|
||||||
|
"LabelServerLogLevel": "Ниво на сървърен журнал",
|
||||||
"LabelServerYearReview": "Преглед на годината на сървъра ({0})",
|
"LabelServerYearReview": "Преглед на годината на сървъра ({0})",
|
||||||
"LabelSetEbookAsPrimary": "Направи главен",
|
"LabelSetEbookAsPrimary": "Направи главен",
|
||||||
"LabelSetEbookAsSupplementary": "Направи второстепенен",
|
"LabelSetEbookAsSupplementary": "Направи второстепенен",
|
||||||
|
"LabelSettingsAllowIframe": "Разреши вграждане в iframe",
|
||||||
"LabelSettingsAudiobooksOnly": "Само аудиокниги",
|
"LabelSettingsAudiobooksOnly": "Само аудиокниги",
|
||||||
"LabelSettingsAudiobooksOnlyHelp": "Активирането на тази настройка ще игнорира файловете на електронни книги, освен ако не са в папка с аудиокниги, в което случай ще бъдат зададени като допълнителни електронни книги",
|
"LabelSettingsAudiobooksOnlyHelp": "Активирането на тази настройка ще игнорира файловете на електронни книги, освен ако не са в папка с аудиокниги, в което случай ще бъдат зададени като допълнителни електронни книги",
|
||||||
"LabelSettingsBookshelfViewHelp": "Скеуморфен дизайн с дървени рафтове",
|
"LabelSettingsBookshelfViewHelp": "Скеуморфен дизайн с дървени рафтове",
|
||||||
"LabelSettingsChromecastSupport": "Chromecast поддръжка",
|
"LabelSettingsChromecastSupport": "Chromecast поддръжка",
|
||||||
"LabelSettingsDateFormat": "Формат на Дата",
|
"LabelSettingsDateFormat": "Формат на Дата",
|
||||||
|
"LabelSettingsEnableWatcher": "Автоматично сканиране на библиотеките за промени",
|
||||||
|
"LabelSettingsEnableWatcherForLibrary": "Автоматично сканиране на библиотеката за промени",
|
||||||
"LabelSettingsEnableWatcherHelp": "Включва автоматичното добавяне/обновяване на елементи, когато се открият промени във файловете. *Изисква рестарт на сървъра",
|
"LabelSettingsEnableWatcherHelp": "Включва автоматичното добавяне/обновяване на елементи, когато се открият промени във файловете. *Изисква рестарт на сървъра",
|
||||||
"LabelSettingsEpubsAllowScriptedContent": "Позволи скриптово съдържание в epub-и",
|
"LabelSettingsEpubsAllowScriptedContent": "Позволи скриптово съдържание в epub-и",
|
||||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Позволи epub файловете да изпълняват скриптове. Препоръчително е да бъде изключено освен ако не се доверявате на източника на epub файловете.",
|
"LabelSettingsEpubsAllowScriptedContentHelp": "Позволи epub файловете да изпълняват скриптове. Препоръчително е да бъде изключено освен ако не се доверявате на източника на epub файловете.",
|
||||||
@@ -527,10 +573,13 @@
|
|||||||
"LabelSettingsHideSingleBookSeriesHelp": "Сериите с една книга ще бъдат скрити от страницата на серията и рафтовете на началната страница.",
|
"LabelSettingsHideSingleBookSeriesHelp": "Сериите с една книга ще бъдат скрити от страницата на серията и рафтовете на началната страница.",
|
||||||
"LabelSettingsHomePageBookshelfView": "Начална страница изглед на рафт",
|
"LabelSettingsHomePageBookshelfView": "Начална страница изглед на рафт",
|
||||||
"LabelSettingsLibraryBookshelfView": "Библиотека изглед на рафт",
|
"LabelSettingsLibraryBookshelfView": "Библиотека изглед на рафт",
|
||||||
|
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Процент завършеност е по-голям от",
|
||||||
|
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Оставащо време е по-малко от (секунди)",
|
||||||
|
"LabelSettingsLibraryMarkAsFinishedWhen": "Отбелязване на мултимедиен елемент като завършен когато",
|
||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Пропусни предишни книги в Продължи Поредица",
|
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Пропусни предишни книги в Продължи Поредица",
|
||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Рафтът на началната страница 'Продължи поредицата' показва първата книга, която не е започната в поредици, в които има поне една завършена книга и няма книги в процес на четене. Активирането на тази настройка ще продължи поредицата от най-далечната завършена книга вместо от първата незапочната книга.",
|
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Рафтът на началната страница 'Продължи поредицата' показва първата книга, която не е започната в поредици, в които има поне една завършена книга и няма книги в процес на четене. Активирането на тази настройка ще продължи поредицата от най-далечната завършена книга вместо от първата незапочната книга.",
|
||||||
"LabelSettingsParseSubtitles": "Извлечи подзаглавия",
|
"LabelSettingsParseSubtitles": "Извлечи подзаглавия",
|
||||||
"LabelSettingsParseSubtitlesHelp": "Извлича подзаглавия от имената на папките на аудиокнигите.<br>Подзаглавията трябва да бъдат разделени с \" - \"<br>например \"Заглавие на Книга - Тук е Подзаглавито\" има подзаглавие \"Тук е Подзаглавито\"",
|
"LabelSettingsParseSubtitlesHelp": "Извлича подзаглавия от имената на папките на аудио книгите.<br>Подзаглавията трябва да бъдат разделени с \" - \"<br>например \"Заглавие на Книга - Тук е подзаглавието\" има подзаглавие \"Тук е подзаглавието\"",
|
||||||
"LabelSettingsPreferMatchedMetadata": "Предпочети съвпадащи метаданни",
|
"LabelSettingsPreferMatchedMetadata": "Предпочети съвпадащи метаданни",
|
||||||
"LabelSettingsPreferMatchedMetadataHelp": "Съвпадащите данни ще заменят детайлите на елемента при използване на Бързо Съпоставяне. По подразбиране Бързото Съпоставяне ще попълни само липсващите детайли.",
|
"LabelSettingsPreferMatchedMetadataHelp": "Съвпадащите данни ще заменят детайлите на елемента при използване на Бързо Съпоставяне. По подразбиране Бързото Съпоставяне ще попълни само липсващите детайли.",
|
||||||
"LabelSettingsSkipMatchingBooksWithASIN": "Пропусни съвпадащи книги, които вече имат ASIN",
|
"LabelSettingsSkipMatchingBooksWithASIN": "Пропусни съвпадащи книги, които вече имат ASIN",
|
||||||
@@ -544,11 +593,19 @@
|
|||||||
"LabelSettingsStoreMetadataWithItem": "Запази метаданните с елемента",
|
"LabelSettingsStoreMetadataWithItem": "Запази метаданните с елемента",
|
||||||
"LabelSettingsStoreMetadataWithItemHelp": "По подразбиране метаданните се съхраняват в /metadata/items, като активирате тази настройка метаданните ще се съхраняват в папката на елемента на вашата библиотека",
|
"LabelSettingsStoreMetadataWithItemHelp": "По подразбиране метаданните се съхраняват в /metadata/items, като активирате тази настройка метаданните ще се съхраняват в папката на елемента на вашата библиотека",
|
||||||
"LabelSettingsTimeFormat": "Формат на Време",
|
"LabelSettingsTimeFormat": "Формат на Време",
|
||||||
|
"LabelShare": "Сподели",
|
||||||
|
"LabelShareDownloadableHelp": "Разреши на потребителите през връзка за споделяне да свалят zip файл с мултимедийния елемент.",
|
||||||
|
"LabelShareOpen": "Общодостъпно",
|
||||||
|
"LabelShareURL": "URL за споделяне",
|
||||||
"LabelShowAll": "Покажи всички",
|
"LabelShowAll": "Покажи всички",
|
||||||
"LabelShowSeconds": "Покажи секунди",
|
"LabelShowSeconds": "Покажи секунди",
|
||||||
|
"LabelShowSubtitles": "Показвай подзаглавия",
|
||||||
"LabelSize": "Размер",
|
"LabelSize": "Размер",
|
||||||
"LabelSleepTimer": "Таймер за изключване",
|
"LabelSleepTimer": "Таймер за изключване",
|
||||||
"LabelSlug": "Слъг",
|
"LabelSlug": "Слъг",
|
||||||
|
"LabelSortAscending": "Възходящ",
|
||||||
|
"LabelSortDescending": "Низходящ",
|
||||||
|
"LabelSortPubDate": "Подреди по дата на публикуване",
|
||||||
"LabelStart": "Старт",
|
"LabelStart": "Старт",
|
||||||
"LabelStartTime": "Начално Време",
|
"LabelStartTime": "Начално Време",
|
||||||
"LabelStarted": "Стартирано",
|
"LabelStarted": "Стартирано",
|
||||||
@@ -583,6 +640,11 @@
|
|||||||
"LabelThemeDark": "Тъмна",
|
"LabelThemeDark": "Тъмна",
|
||||||
"LabelThemeLight": "Светла",
|
"LabelThemeLight": "Светла",
|
||||||
"LabelTimeBase": "Времева Основа",
|
"LabelTimeBase": "Времева Основа",
|
||||||
|
"LabelTimeDurationXHours": "{0} часа",
|
||||||
|
"LabelTimeDurationXMinutes": "{0} минути",
|
||||||
|
"LabelTimeDurationXSeconds": "{0} секунди",
|
||||||
|
"LabelTimeInMinutes": "Време в минути",
|
||||||
|
"LabelTimeLeft": "остава {0}",
|
||||||
"LabelTimeListened": "Време Слушано",
|
"LabelTimeListened": "Време Слушано",
|
||||||
"LabelTimeListenedToday": "Време Слушано Днес",
|
"LabelTimeListenedToday": "Време Слушано Днес",
|
||||||
"LabelTimeRemaining": "{0} оставащи",
|
"LabelTimeRemaining": "{0} оставащи",
|
||||||
@@ -590,6 +652,7 @@
|
|||||||
"LabelTitle": "Заглавие",
|
"LabelTitle": "Заглавие",
|
||||||
"LabelToolsEmbedMetadata": "Вграждане на Метаданни",
|
"LabelToolsEmbedMetadata": "Вграждане на Метаданни",
|
||||||
"LabelToolsEmbedMetadataDescription": "Вграждане на метаданни в аудио файлове, включително корица и глави.",
|
"LabelToolsEmbedMetadataDescription": "Вграждане на метаданни в аудио файлове, включително корица и глави.",
|
||||||
|
"LabelToolsM4bEncoder": "M4B кодировчик",
|
||||||
"LabelToolsMakeM4b": "Направи M4B Аудиокнига Файл",
|
"LabelToolsMakeM4b": "Направи M4B Аудиокнига Файл",
|
||||||
"LabelToolsMakeM4bDescription": "Генериране на .M4B аудиокнига файл с вградени метаданни, корица и глави.",
|
"LabelToolsMakeM4bDescription": "Генериране на .M4B аудиокнига файл с вградени метаданни, корица и глави.",
|
||||||
"LabelToolsSplitM4b": "Раздели M4B на MP3-ки",
|
"LabelToolsSplitM4b": "Раздели M4B на MP3-ки",
|
||||||
@@ -602,26 +665,32 @@
|
|||||||
"LabelTracksMultiTrack": "Многоканален",
|
"LabelTracksMultiTrack": "Многоканален",
|
||||||
"LabelTracksNone": "Няма канали",
|
"LabelTracksNone": "Няма канали",
|
||||||
"LabelTracksSingleTrack": "Единичен канал",
|
"LabelTracksSingleTrack": "Единичен канал",
|
||||||
|
"LabelTrailer": "Трейлър",
|
||||||
"LabelType": "Тип",
|
"LabelType": "Тип",
|
||||||
"LabelUnabridged": "Несъкратен",
|
"LabelUnabridged": "Несъкратен",
|
||||||
"LabelUndo": "Отмени",
|
"LabelUndo": "Отмени",
|
||||||
"LabelUnknown": "Неизвестен",
|
"LabelUnknown": "Неизвестен",
|
||||||
|
"LabelUnknownPublishDate": "Неизвестна дата на публикуване",
|
||||||
"LabelUpdateCover": "Обнови Корица",
|
"LabelUpdateCover": "Обнови Корица",
|
||||||
"LabelUpdateCoverHelp": "Позволи презаписване на съществуващите корици за избраните книги, когато се намери съвпадение",
|
"LabelUpdateCoverHelp": "Позволи презаписване на съществуващите корици за избраните книги, когато се намери съвпадение",
|
||||||
"LabelUpdateDetails": "Обнови Детайли",
|
"LabelUpdateDetails": "Обнови Детайли",
|
||||||
"LabelUpdateDetailsHelp": "Позволи презаписване на съществуващите детайли за избраните книги, когато се намери съвпадение",
|
"LabelUpdateDetailsHelp": "Позволи презаписване на съществуващите детайли за избраните книги, когато се намери съвпадение",
|
||||||
"LabelUpdatedAt": "Обновено на",
|
"LabelUpdatedAt": "Обновено на",
|
||||||
"LabelUploaderDragAndDrop": "Плъзни и Пусни Файлове или Папки",
|
"LabelUploaderDragAndDrop": "Плъзни и Пусни Файлове или Папки",
|
||||||
|
"LabelUploaderDragAndDropFilesOnly": "Извлачване на файлове",
|
||||||
"LabelUploaderDropFiles": "Пусни Файлове",
|
"LabelUploaderDropFiles": "Пусни Файлове",
|
||||||
"LabelUploaderItemFetchMetadataHelp": "Автоматично вземи заглавие, автор и серия",
|
"LabelUploaderItemFetchMetadataHelp": "Автоматично вземи заглавие, автор и серия",
|
||||||
|
"LabelUseAdvancedOptions": "Използвай разширени опции",
|
||||||
"LabelUseChapterTrack": "Използвай канал за глава",
|
"LabelUseChapterTrack": "Използвай канал за глава",
|
||||||
"LabelUseFullTrack": "Използвай пълен канал",
|
"LabelUseFullTrack": "Използвай пълен канал",
|
||||||
|
"LabelUseZeroForUnlimited": "Използвай 0 за неограничен",
|
||||||
"LabelUser": "Потребител",
|
"LabelUser": "Потребител",
|
||||||
"LabelUsername": "Потребителско име",
|
"LabelUsername": "Потребителско име",
|
||||||
"LabelValue": "Стойност",
|
"LabelValue": "Стойност",
|
||||||
"LabelVersion": "Версия",
|
"LabelVersion": "Версия",
|
||||||
"LabelViewBookmarks": "Виж Отметки",
|
"LabelViewBookmarks": "Виж Отметки",
|
||||||
"LabelViewChapters": "Виж Глави",
|
"LabelViewChapters": "Виж Глави",
|
||||||
|
"LabelViewPlayerSettings": "Виж настройки на плеъра",
|
||||||
"LabelViewQueue": "Виж Опашка",
|
"LabelViewQueue": "Виж Опашка",
|
||||||
"LabelVolume": "Сила на Звука",
|
"LabelVolume": "Сила на Звука",
|
||||||
"LabelWeekdaysToRun": "Делници за изпълнение",
|
"LabelWeekdaysToRun": "Делници за изпълнение",
|
||||||
|
|||||||
+185
-152
@@ -1,33 +1,35 @@
|
|||||||
{
|
{
|
||||||
"ButtonAdd": "Afegeix",
|
"ButtonAdd": "Afegeix",
|
||||||
"ButtonAddChapters": "Afegeix",
|
"ButtonAddChapters": "Afegeix capítols",
|
||||||
"ButtonAddDevice": "Afegeix Dispositiu",
|
"ButtonAddDevice": "Afegeix un aparell",
|
||||||
"ButtonAddLibrary": "Crea Biblioteca",
|
"ButtonAddLibrary": "Afegeix una biblioteca",
|
||||||
"ButtonAddPodcasts": "Afegeix pòdcasts",
|
"ButtonAddPodcasts": "Afegeix pòdcasts",
|
||||||
"ButtonAddUser": "Crea Usuari",
|
"ButtonAddUser": "Afegeix un usuari",
|
||||||
"ButtonAddYourFirstLibrary": "Crea la teva Primera Biblioteca",
|
"ButtonAddYourFirstLibrary": "Afegiu la vostra primera biblioteca",
|
||||||
"ButtonApply": "Aplica",
|
"ButtonApply": "Aplica",
|
||||||
"ButtonApplyChapters": "Aplica Capítols",
|
"ButtonApplyChapters": "Aplica capítols",
|
||||||
"ButtonAuthors": "Autors",
|
"ButtonAuthors": "Autors",
|
||||||
"ButtonBack": "Enrere",
|
"ButtonBack": "Enrere",
|
||||||
"ButtonBrowseForFolder": "Cerca Carpeta",
|
"ButtonBatchEditPopulateFromExisting": "Omplir des d'existent",
|
||||||
|
"ButtonBatchEditPopulateMapDetails": "Omple els detalls del mapa",
|
||||||
|
"ButtonBrowseForFolder": "Cerca una carpeta",
|
||||||
"ButtonCancel": "Cancel·la",
|
"ButtonCancel": "Cancel·la",
|
||||||
"ButtonCancelEncode": "Cancel·la Codificador",
|
"ButtonCancelEncode": "Cancel·la la codificació",
|
||||||
"ButtonChangeRootPassword": "Canvia Contrasenya Root",
|
"ButtonChangeRootPassword": "Canvia Contrasenya Root",
|
||||||
"ButtonCheckAndDownloadNewEpisodes": "Verifica i Descarrega Nous Episodis",
|
"ButtonCheckAndDownloadNewEpisodes": "Verifica i Descarrega Nous Episodis",
|
||||||
"ButtonChooseAFolder": "Tria una Carpeta",
|
"ButtonChooseAFolder": "Trieu una carpeta",
|
||||||
"ButtonChooseFiles": "Tria un Fitxer",
|
"ButtonChooseFiles": "Trieu fitxers",
|
||||||
"ButtonClearFilter": "Elimina Filtres",
|
"ButtonClearFilter": "Neteja el filtre",
|
||||||
"ButtonCloseFeed": "Tanca Font",
|
"ButtonCloseFeed": "Tanca el canal",
|
||||||
"ButtonCloseSession": "Tanca la sessió oberta",
|
"ButtonCloseSession": "Tanca la sessió oberta",
|
||||||
"ButtonCollections": "Col·leccions",
|
"ButtonCollections": "Col·leccions",
|
||||||
"ButtonConfigureScanner": "Configura Escàner",
|
"ButtonConfigureScanner": "Configura Escàner",
|
||||||
"ButtonCreate": "Crea",
|
"ButtonCreate": "Crea",
|
||||||
"ButtonCreateBackup": "Crea Còpia de Seguretat",
|
"ButtonCreateBackup": "Crea Còpia de Seguretat",
|
||||||
"ButtonDelete": "Elimina",
|
"ButtonDelete": "Suprimeix",
|
||||||
"ButtonDownloadQueue": "Cua",
|
"ButtonDownloadQueue": "Cua",
|
||||||
"ButtonEdit": "Edita",
|
"ButtonEdit": "Edita",
|
||||||
"ButtonEditChapters": "Edita Capítol",
|
"ButtonEditChapters": "Edita capítols",
|
||||||
"ButtonEditPodcast": "Edita el pòdcast",
|
"ButtonEditPodcast": "Edita el pòdcast",
|
||||||
"ButtonEnable": "Habilita",
|
"ButtonEnable": "Habilita",
|
||||||
"ButtonFireAndFail": "Executat i fallat",
|
"ButtonFireAndFail": "Executat i fallat",
|
||||||
@@ -117,7 +119,7 @@
|
|||||||
"HeaderAccount": "Compte",
|
"HeaderAccount": "Compte",
|
||||||
"HeaderAddCustomMetadataProvider": "Afegeix un proveïdor de metadades personalitzat",
|
"HeaderAddCustomMetadataProvider": "Afegeix un proveïdor de metadades personalitzat",
|
||||||
"HeaderAdvanced": "Avançat",
|
"HeaderAdvanced": "Avançat",
|
||||||
"HeaderAppriseNotificationSettings": "Configuració de Notificacions Apprise",
|
"HeaderAppriseNotificationSettings": "Paràmetres de notificacions Apprise",
|
||||||
"HeaderAudioTracks": "Pistes d'àudio",
|
"HeaderAudioTracks": "Pistes d'àudio",
|
||||||
"HeaderAudiobookTools": "Eines de gestió de fitxers de l'audiollibre",
|
"HeaderAudiobookTools": "Eines de gestió de fitxers de l'audiollibre",
|
||||||
"HeaderAuthentication": "Autenticació",
|
"HeaderAuthentication": "Autenticació",
|
||||||
@@ -133,9 +135,9 @@
|
|||||||
"HeaderCustomMetadataProviders": "Proveïdors de metadades personalitzats",
|
"HeaderCustomMetadataProviders": "Proveïdors de metadades personalitzats",
|
||||||
"HeaderDetails": "Detalls",
|
"HeaderDetails": "Detalls",
|
||||||
"HeaderDownloadQueue": "Cua de baixades",
|
"HeaderDownloadQueue": "Cua de baixades",
|
||||||
"HeaderEbookFiles": "Fitxers de Llibres Digitals",
|
"HeaderEbookFiles": "Fitxers de llibres digitals",
|
||||||
"HeaderEmail": "Correu electrònic",
|
"HeaderEmail": "Correu electrònic",
|
||||||
"HeaderEmailSettings": "Configuració de Correu Electrònic",
|
"HeaderEmailSettings": "Paràmetres de correu electrònic",
|
||||||
"HeaderEpisodes": "Episodis",
|
"HeaderEpisodes": "Episodis",
|
||||||
"HeaderEreaderDevices": "Dispositius Ereader",
|
"HeaderEreaderDevices": "Dispositius Ereader",
|
||||||
"HeaderEreaderSettings": "Paràmetres del lector",
|
"HeaderEreaderSettings": "Paràmetres del lector",
|
||||||
@@ -171,10 +173,11 @@
|
|||||||
"HeaderPasswordAuthentication": "Autenticació per Contrasenya",
|
"HeaderPasswordAuthentication": "Autenticació per Contrasenya",
|
||||||
"HeaderPermissions": "Permisos",
|
"HeaderPermissions": "Permisos",
|
||||||
"HeaderPlayerQueue": "Cua del Reproductor",
|
"HeaderPlayerQueue": "Cua del Reproductor",
|
||||||
"HeaderPlayerSettings": "Configuració del Reproductor",
|
"HeaderPlayerSettings": "Paràmetres del reproductor",
|
||||||
"HeaderPlaylist": "Llista de Reproducció",
|
"HeaderPlaylist": "Llista de Reproducció",
|
||||||
"HeaderPlaylistItems": "Elements de la Llista de Reproducció",
|
"HeaderPlaylistItems": "Elements de la Llista de Reproducció",
|
||||||
"HeaderPodcastsToAdd": "Pòdcasts a afegir",
|
"HeaderPodcastsToAdd": "Pòdcasts a afegir",
|
||||||
|
"HeaderPresets": "Valors predefinits",
|
||||||
"HeaderPreviewCover": "Previsualització de la Portada",
|
"HeaderPreviewCover": "Previsualització de la Portada",
|
||||||
"HeaderRSSFeedGeneral": "Detalls RSS",
|
"HeaderRSSFeedGeneral": "Detalls RSS",
|
||||||
"HeaderRSSFeedIsOpen": "La Font RSS està oberta",
|
"HeaderRSSFeedIsOpen": "La Font RSS està oberta",
|
||||||
@@ -190,7 +193,7 @@
|
|||||||
"HeaderSettings": "Paràmetres",
|
"HeaderSettings": "Paràmetres",
|
||||||
"HeaderSettingsDisplay": "Interfície",
|
"HeaderSettingsDisplay": "Interfície",
|
||||||
"HeaderSettingsExperimental": "Funcionalitats experimentals",
|
"HeaderSettingsExperimental": "Funcionalitats experimentals",
|
||||||
"HeaderSettingsGeneral": "General",
|
"HeaderSettingsGeneral": "Generals",
|
||||||
"HeaderSettingsScanner": "Escàner",
|
"HeaderSettingsScanner": "Escàner",
|
||||||
"HeaderSettingsWebClient": "Client web",
|
"HeaderSettingsWebClient": "Client web",
|
||||||
"HeaderSleepTimer": "Temporitzador de son",
|
"HeaderSleepTimer": "Temporitzador de son",
|
||||||
@@ -219,10 +222,10 @@
|
|||||||
"LabelAccountTypeUser": "Usuari",
|
"LabelAccountTypeUser": "Usuari",
|
||||||
"LabelActivities": "Activitats",
|
"LabelActivities": "Activitats",
|
||||||
"LabelActivity": "Activitat",
|
"LabelActivity": "Activitat",
|
||||||
"LabelAddToCollection": "Afegit a la Col·lecció",
|
"LabelAddToCollection": "Afegeix a la col·lecció",
|
||||||
"LabelAddToCollectionBatch": "S'han Afegit {0} Llibres a la Col·lecció",
|
"LabelAddToCollectionBatch": "Afegeix {0} llibres a la col·lecció",
|
||||||
"LabelAddToPlaylist": "Afegit a la llista de reproducció",
|
"LabelAddToPlaylist": "Afegeix a la llista de reproducció",
|
||||||
"LabelAddToPlaylistBatch": "S'han Afegit {0} Elements a la Llista de Reproducció",
|
"LabelAddToPlaylistBatch": "Afegeix {0} elements a la llista de reproducció",
|
||||||
"LabelAddedAt": "Afegit",
|
"LabelAddedAt": "Afegit",
|
||||||
"LabelAddedDate": "{0} Afegit",
|
"LabelAddedDate": "{0} Afegit",
|
||||||
"LabelAdminUsersOnly": "Només usuaris administradors",
|
"LabelAdminUsersOnly": "Només usuaris administradors",
|
||||||
@@ -231,7 +234,7 @@
|
|||||||
"LabelAllUsers": "Tots els usuaris",
|
"LabelAllUsers": "Tots els usuaris",
|
||||||
"LabelAllUsersExcludingGuests": "Tots els usuaris excepte convidats",
|
"LabelAllUsersExcludingGuests": "Tots els usuaris excepte convidats",
|
||||||
"LabelAllUsersIncludingGuests": "Tots els usuaris i convidats",
|
"LabelAllUsersIncludingGuests": "Tots els usuaris i convidats",
|
||||||
"LabelAlreadyInYourLibrary": "Ja existeix a la Biblioteca",
|
"LabelAlreadyInYourLibrary": "Ja existeix a la biblioteca",
|
||||||
"LabelApiToken": "Testimoni de l'API",
|
"LabelApiToken": "Testimoni de l'API",
|
||||||
"LabelAppend": "Adjuntar",
|
"LabelAppend": "Adjuntar",
|
||||||
"LabelAudioBitrate": "Taxa de bits d'àudio (per exemple, 128k)",
|
"LabelAudioBitrate": "Taxa de bits d'àudio (per exemple, 128k)",
|
||||||
@@ -288,14 +291,14 @@
|
|||||||
"LabelCronExpression": "Expressió de Cron",
|
"LabelCronExpression": "Expressió de Cron",
|
||||||
"LabelCurrent": "Actual",
|
"LabelCurrent": "Actual",
|
||||||
"LabelCurrently": "En aquest moment:",
|
"LabelCurrently": "En aquest moment:",
|
||||||
"LabelCustomCronExpression": "Expressió de Cron Personalitzada:",
|
"LabelCustomCronExpression": "Expressió del Cron personalitzada:",
|
||||||
"LabelDatetime": "Hora i Data",
|
"LabelDatetime": "Data i hora",
|
||||||
"LabelDays": "Dies",
|
"LabelDays": "Dies",
|
||||||
"LabelDeleteFromFileSystemCheckbox": "Suprimeix del sistema de fitxers (desmarqueu per a eliminar de la base de dades només)",
|
"LabelDeleteFromFileSystemCheckbox": "Suprimeix del sistema de fitxers (desmarqueu per a eliminar de la base de dades només)",
|
||||||
"LabelDescription": "Descripció",
|
"LabelDescription": "Descripció",
|
||||||
"LabelDeselectAll": "Desseleccionar Tots",
|
"LabelDeselectAll": "Desseleccionar Tots",
|
||||||
"LabelDevice": "Dispositiu",
|
"LabelDevice": "Dispositiu",
|
||||||
"LabelDeviceInfo": "Informació del Dispositiu",
|
"LabelDeviceInfo": "Informació de l'aparell",
|
||||||
"LabelDeviceIsAvailableTo": "El dispositiu està disponible per a...",
|
"LabelDeviceIsAvailableTo": "El dispositiu està disponible per a...",
|
||||||
"LabelDirectory": "Directori",
|
"LabelDirectory": "Directori",
|
||||||
"LabelDiscFromFilename": "Disc a partir del nom de fitxer",
|
"LabelDiscFromFilename": "Disc a partir del nom de fitxer",
|
||||||
@@ -333,11 +336,11 @@
|
|||||||
"LabelEnd": "Fi",
|
"LabelEnd": "Fi",
|
||||||
"LabelEndOfChapter": "Fi del capítol",
|
"LabelEndOfChapter": "Fi del capítol",
|
||||||
"LabelEpisode": "Episodi",
|
"LabelEpisode": "Episodi",
|
||||||
"LabelEpisodeNotLinkedToRssFeed": "Episodi no enllaçat al feed RSS",
|
"LabelEpisodeNotLinkedToRssFeed": "Episodi no enllaçat al canal RSS",
|
||||||
"LabelEpisodeNumber": "Episodi #{0}",
|
"LabelEpisodeNumber": "Episodi #{0}",
|
||||||
"LabelEpisodeTitle": "Títol de l'Episodi",
|
"LabelEpisodeTitle": "Títol de l'Episodi",
|
||||||
"LabelEpisodeType": "Tipus d'Episodi",
|
"LabelEpisodeType": "Tipus d'Episodi",
|
||||||
"LabelEpisodeUrlFromRssFeed": "URL de l'episodi del feed RSS",
|
"LabelEpisodeUrlFromRssFeed": "URL de l'episodi del canal RSS",
|
||||||
"LabelEpisodes": "Episodis",
|
"LabelEpisodes": "Episodis",
|
||||||
"LabelEpisodic": "Episodis",
|
"LabelEpisodic": "Episodis",
|
||||||
"LabelExample": "Exemple",
|
"LabelExample": "Exemple",
|
||||||
@@ -350,7 +353,7 @@
|
|||||||
"LabelFeedURL": "Font de URL",
|
"LabelFeedURL": "Font de URL",
|
||||||
"LabelFetchingMetadata": "Obtenció de metadades",
|
"LabelFetchingMetadata": "Obtenció de metadades",
|
||||||
"LabelFile": "Fitxer",
|
"LabelFile": "Fitxer",
|
||||||
"LabelFileBirthtime": "Arxiu creat a",
|
"LabelFileBirthtime": "Fitxer creat a",
|
||||||
"LabelFileBornDate": "Creat {0}",
|
"LabelFileBornDate": "Creat {0}",
|
||||||
"LabelFileModified": "Fitxer modificat",
|
"LabelFileModified": "Fitxer modificat",
|
||||||
"LabelFileModifiedDate": "Modificat {0}",
|
"LabelFileModifiedDate": "Modificat {0}",
|
||||||
@@ -437,7 +440,7 @@
|
|||||||
"LabelMinute": "Minut",
|
"LabelMinute": "Minut",
|
||||||
"LabelMinutes": "Minuts",
|
"LabelMinutes": "Minuts",
|
||||||
"LabelMissing": "Absent",
|
"LabelMissing": "Absent",
|
||||||
"LabelMissingEbook": "No té ebook",
|
"LabelMissingEbook": "No té llibre electrònic",
|
||||||
"LabelMissingSupplementaryEbook": "No té ebook complementari",
|
"LabelMissingSupplementaryEbook": "No té ebook complementari",
|
||||||
"LabelMobileRedirectURIs": "URI de redirecció mòbil permeses",
|
"LabelMobileRedirectURIs": "URI de redirecció mòbil permeses",
|
||||||
"LabelMobileRedirectURIsDescription": "Aquesta és una llista blanca d'URI de redirecció vàlides per a aplicacions mòbils. El predeterminat és <code> audiobookshelf</code>, que pots eliminar o complementar amb URI addicionals per a la integració d'aplicacions de tercers. Usant un asterisc (<code> *</code>) com a única entrada que permet qualsevol URI.",
|
"LabelMobileRedirectURIsDescription": "Aquesta és una llista blanca d'URI de redirecció vàlides per a aplicacions mòbils. El predeterminat és <code> audiobookshelf</code>, que pots eliminar o complementar amb URI addicionals per a la integració d'aplicacions de tercers. Usant un asterisc (<code> *</code>) com a única entrada que permet qualsevol URI.",
|
||||||
@@ -471,6 +474,7 @@
|
|||||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nom de la notificació de OpenID que conté permisos avançats per accions d'usuari dins l'aplicació que s'aplicaran a rols que no siguin d'administrador (<b>si estan configurats</b>). Si el reclam no apareix en la resposta, es denegarà l'accés a ABS. Si manca una sola opció, es tractarà com a <code>falsa</code>. Assegura't que la notificació del proveïdor d'identitats coincideixi amb l'estructura esperada:",
|
"LabelOpenIDAdvancedPermsClaimDescription": "Nom de la notificació de OpenID que conté permisos avançats per accions d'usuari dins l'aplicació que s'aplicaran a rols que no siguin d'administrador (<b>si estan configurats</b>). Si el reclam no apareix en la resposta, es denegarà l'accés a ABS. Si manca una sola opció, es tractarà com a <code>falsa</code>. Assegura't que la notificació del proveïdor d'identitats coincideixi amb l'estructura esperada:",
|
||||||
"LabelOpenIDClaims": "Deixa les següents opcions buides per desactivar l'assignació avançada de grups i permisos, el que assignaria automàticament al grup 'Usuari'.",
|
"LabelOpenIDClaims": "Deixa les següents opcions buides per desactivar l'assignació avançada de grups i permisos, el que assignaria automàticament al grup 'Usuari'.",
|
||||||
"LabelOpenIDGroupClaimDescription": "Nom de la declaració OpenID que conté una llista de grups de l'usuari. Comunament coneguts com <code>grups</code>. <b>Si es configura</b>, l'aplicació assignarà automàticament rols basats en la pertinença a grups de l'usuari, sempre que aquests grups es denominen 'admin', 'user' o 'guest' en la notificació. La sol·licitud ha de contenir una llista, i si un usuari pertany a diversos grups, l'aplicació assignarà el rol corresponent al major nivell d'accés. Si cap grup coincideix, es denegarà l'accés.",
|
"LabelOpenIDGroupClaimDescription": "Nom de la declaració OpenID que conté una llista de grups de l'usuari. Comunament coneguts com <code>grups</code>. <b>Si es configura</b>, l'aplicació assignarà automàticament rols basats en la pertinença a grups de l'usuari, sempre que aquests grups es denominen 'admin', 'user' o 'guest' en la notificació. La sol·licitud ha de contenir una llista, i si un usuari pertany a diversos grups, l'aplicació assignarà el rol corresponent al major nivell d'accés. Si cap grup coincideix, es denegarà l'accés.",
|
||||||
|
"LabelOpenRSSFeed": "Obre el canal RSS",
|
||||||
"LabelOverwrite": "Sobreescriure",
|
"LabelOverwrite": "Sobreescriure",
|
||||||
"LabelPaginationPageXOfY": "Pàgina {0} de {1}",
|
"LabelPaginationPageXOfY": "Pàgina {0} de {1}",
|
||||||
"LabelPassword": "Contrasenya",
|
"LabelPassword": "Contrasenya",
|
||||||
@@ -494,25 +498,25 @@
|
|||||||
"LabelPodcastType": "Tipus de pòdcast",
|
"LabelPodcastType": "Tipus de pòdcast",
|
||||||
"LabelPodcasts": "Pòdcasts",
|
"LabelPodcasts": "Pòdcasts",
|
||||||
"LabelPort": "Port",
|
"LabelPort": "Port",
|
||||||
"LabelPrefixesToIgnore": "Prefixos per Ignorar (no distingeix entre majúscules i minúscules.)",
|
"LabelPrefixesToIgnore": "Prefixos a ignorar (no distingeix entre majúscules i minúscules)",
|
||||||
"LabelPreventIndexing": "Evita que la teva font sigui indexada pels directoris de podcasts d'iTunes i Google",
|
"LabelPreventIndexing": "Evita que el vostre canal l'indexin els directoris de pòdcasts de l'iTunes i Google",
|
||||||
"LabelPrimaryEbook": "Ebook Principal",
|
"LabelPrimaryEbook": "Llibre electrònic principal",
|
||||||
"LabelProgress": "Progrés",
|
"LabelProgress": "Progrés",
|
||||||
"LabelProvider": "Proveïdor",
|
"LabelProvider": "Proveïdor",
|
||||||
"LabelProviderAuthorizationValue": "Valor de l'encapçalament d'autorització",
|
"LabelProviderAuthorizationValue": "Valor de l'encapçalament d'autorització",
|
||||||
"LabelPubDate": "Data de Publicació",
|
"LabelPubDate": "Data de publicació",
|
||||||
"LabelPublishYear": "Any de Publicació",
|
"LabelPublishYear": "Any de publicació",
|
||||||
"LabelPublishedDate": "Publicat {0}",
|
"LabelPublishedDate": "Publicat {0}",
|
||||||
"LabelPublishedDecade": "Dècada de Publicació",
|
"LabelPublishedDecade": "Dècada de publicació",
|
||||||
"LabelPublishedDecades": "Dècades Publicades",
|
"LabelPublishedDecades": "Dècades Publicades",
|
||||||
"LabelPublisher": "Editor",
|
"LabelPublisher": "Editor",
|
||||||
"LabelPublishers": "Editors",
|
"LabelPublishers": "Editors",
|
||||||
"LabelRSSFeedCustomOwnerEmail": "Correu Electrònic Personalitzat del Propietari",
|
"LabelRSSFeedCustomOwnerEmail": "Correu Electrònic Personalitzat del Propietari",
|
||||||
"LabelRSSFeedCustomOwnerName": "Nom Personalitzat del Propietari",
|
"LabelRSSFeedCustomOwnerName": "Nom Personalitzat del Propietari",
|
||||||
"LabelRSSFeedOpen": "Font RSS Oberta",
|
"LabelRSSFeedOpen": "Font RSS Oberta",
|
||||||
"LabelRSSFeedPreventIndexing": "Evitar l'indexació",
|
"LabelRSSFeedPreventIndexing": "Evita la indexació",
|
||||||
"LabelRSSFeedSlug": "Font RSS Slug",
|
"LabelRSSFeedSlug": "URL semàntic del canal RSS",
|
||||||
"LabelRSSFeedURL": "URL de la Font RSS",
|
"LabelRSSFeedURL": "URL del canal RSS",
|
||||||
"LabelRandomly": "A l'atzar",
|
"LabelRandomly": "A l'atzar",
|
||||||
"LabelReAddSeriesToContinueListening": "Reafegir la sèrie per continuar escoltant-la",
|
"LabelReAddSeriesToContinueListening": "Reafegir la sèrie per continuar escoltant-la",
|
||||||
"LabelRead": "Llegit",
|
"LabelRead": "Llegit",
|
||||||
@@ -521,52 +525,61 @@
|
|||||||
"LabelRecentSeries": "Sèries recents",
|
"LabelRecentSeries": "Sèries recents",
|
||||||
"LabelRecentlyAdded": "Addicions recents",
|
"LabelRecentlyAdded": "Addicions recents",
|
||||||
"LabelRecommended": "Recomanats",
|
"LabelRecommended": "Recomanats",
|
||||||
"LabelRedo": "Refer",
|
"LabelRedo": "Refés",
|
||||||
"LabelRegion": "Regió",
|
"LabelRegion": "Regió",
|
||||||
"LabelReleaseDate": "Data d'Estrena",
|
"LabelReleaseDate": "Data d'estrena",
|
||||||
"LabelRemoveAllMetadataAbs": "Eliminar tots els fitxers metadata.abs",
|
"LabelRemoveAllMetadataAbs": "Elimina tots els fitxers metadata.abs",
|
||||||
"LabelRemoveAllMetadataJson": "Eliminar tots els fitxers metadata.json",
|
"LabelRemoveAllMetadataJson": "Elimina tots els fitxers metadata.json",
|
||||||
"LabelRemoveCover": "Eliminar Coberta",
|
"LabelRemoveAudibleBranding": "Elimina la introducció i el tancament de l'Audible dels capítols",
|
||||||
|
"LabelRemoveCover": "Elimina la coberta",
|
||||||
"LabelRemoveMetadataFile": "Eliminar fitxers de metadades en carpetes d'elements de biblioteca",
|
"LabelRemoveMetadataFile": "Eliminar fitxers de metadades en carpetes d'elements de biblioteca",
|
||||||
"LabelRemoveMetadataFileHelp": "Elimina tots els fitxers metadata.json i metadata.abs de les teves carpetes {0}.",
|
"LabelRemoveMetadataFileHelp": "Elimina tots els fitxers metadata.json i metadata.abs de les vostres carpetes {0}.",
|
||||||
"LabelRowsPerPage": "Files per Pàgina",
|
"LabelRowsPerPage": "Files per pàgina",
|
||||||
"LabelSearchTerm": "Cercar Terme",
|
"LabelSearchTerm": "Cerca terme",
|
||||||
"LabelSearchTitle": "Cercar Títol",
|
"LabelSearchTitle": "Cerca títol",
|
||||||
"LabelSearchTitleOrASIN": "Cercar Títol o ASIN",
|
"LabelSearchTitleOrASIN": "Cerca títol o ASIN",
|
||||||
"LabelSeason": "Temporada",
|
"LabelSeason": "Temporada",
|
||||||
"LabelSeasonNumber": "Temporada #{0}",
|
"LabelSeasonNumber": "{0}a temporada",
|
||||||
"LabelSelectAll": "Seleccionar tot",
|
"LabelSelectAll": "Selecciona-ho tot",
|
||||||
"LabelSelectAllEpisodes": "Seleccionar tots els episodis",
|
"LabelSelectAllEpisodes": "Selecciona tots els episodis",
|
||||||
"LabelSelectEpisodesShowing": "Seleccionar els {0} episodis visibles",
|
"LabelSelectEpisodesShowing": "Seleccionar els {0} episodis visibles",
|
||||||
"LabelSelectUsers": "Seleccionar usuaris",
|
"LabelSelectUsers": "Seleccionar usuaris",
|
||||||
"LabelSendEbookToDevice": "Enviar Ebook a...",
|
"LabelSendEbookToDevice": "Enviar Ebook a...",
|
||||||
"LabelSequence": "Seqüència",
|
"LabelSequence": "Seqüència",
|
||||||
"LabelSerial": "En sèrie",
|
"LabelSerial": "En sèrie",
|
||||||
"LabelSeries": "Sèries",
|
"LabelSeries": "Sèrie",
|
||||||
"LabelSeriesName": "Nom de la Sèrie",
|
"LabelSeriesName": "Nom de la sèrie",
|
||||||
"LabelSeriesProgress": "Progrés de la Sèrie",
|
"LabelSeriesProgress": "Progrés de la sèrie",
|
||||||
"LabelServerLogLevel": "Nivell de registre del servidor",
|
"LabelServerLogLevel": "Nivell de registre del servidor",
|
||||||
"LabelServerYearReview": "Resum de l'any del servidor ({0})",
|
"LabelServerYearReview": "Resum de l'any del servidor ({0})",
|
||||||
"LabelSetEbookAsPrimary": "Establir com a principal",
|
"LabelSetEbookAsPrimary": "Establir com a principal",
|
||||||
"LabelSetEbookAsSupplementary": "Establir com a suplementari",
|
"LabelSetEbookAsSupplementary": "Establir com a suplementari",
|
||||||
"LabelSettingsAudiobooksOnly": "Només Audiollibres",
|
"LabelSettingsAudiobooksOnly": "Només audiollibres",
|
||||||
"LabelSettingsAudiobooksOnlyHelp": "Activant aquesta opció s'ignoraran els fitxers d'ebook, excepte si estan dins d'una carpeta d'audiollibre, en aquest cas es marcaran com ebooks suplementaris",
|
"LabelSettingsAudiobooksOnlyHelp": "En activar aquesta opció s'ignoraran els fitxers de llibre electrònic, excepte si estan dins d'una carpeta d'audiollibre; en aquest cas es marcaran com a llibres suplementaris",
|
||||||
"LabelSettingsBookshelfViewHelp": "Disseny esqueomorf amb prestatgeries de fusta",
|
"LabelSettingsBookshelfViewHelp": "Disseny esqueomorf amb prestatgeries de fusta",
|
||||||
"LabelSettingsChromecastSupport": "Compatibilitat amb Chromecast",
|
"LabelSettingsChromecastSupport": "Compatibilitat amb Chromecast",
|
||||||
"LabelSettingsDateFormat": "Format de Data",
|
"LabelSettingsDateFormat": "Format de data",
|
||||||
"LabelSettingsEnableWatcherHelp": "Permet afegir/actualitzar elements automàticament quan es detectin canvis en els fitxers. *Requereix reiniciar el servidor",
|
"LabelSettingsEnableWatcherHelp": "Permet afegir/actualitzar elements automàticament quan es detectin canvis en els fitxers. *Requereix reiniciar el servidor",
|
||||||
"LabelSettingsEpubsAllowScriptedContent": "Permetre scripts en epubs",
|
"LabelSettingsEpubsAllowScriptedContent": "Permetre scripts en epubs",
|
||||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Permetre que els fitxers epub executin scripts. Es recomana mantenir aquesta opció desactivada tret que confiïs en l'origen dels fitxers epub.",
|
"LabelSettingsEpubsAllowScriptedContentHelp": "Permetre que els fitxers epub executin scripts. Es recomana mantenir aquesta opció desactivada tret que confiïs en l'origen dels fitxers epub.",
|
||||||
"LabelSettingsExperimentalFeatures": "Funcions Experimentals",
|
"LabelSettingsExperimentalFeatures": "Funcions Experimentals",
|
||||||
"LabelSettingsExperimentalFeaturesHelp": "Funcions en desenvolupament que es beneficiarien dels teus comentaris i experiències de prova. Feu clic aquí per obrir una conversa a Github.",
|
"LabelSettingsExperimentalFeaturesHelp": "Funcions en desenvolupament que es beneficiarien dels teus comentaris i experiències de prova. Feu clic aquí per obrir una conversa a Github.",
|
||||||
"LabelSettingsFindCovers": "Troba cobertes",
|
"LabelSettingsFindCovers": "Troba cobertes",
|
||||||
|
"LabelSettingsHideSingleBookSeries": "Amaga les sèries amb un sol llibre",
|
||||||
|
"LabelSettingsParseSubtitles": "Analitza els subtítols",
|
||||||
"LabelSettingsSortingIgnorePrefixes": "Ignora els prefixos en ordenar",
|
"LabelSettingsSortingIgnorePrefixes": "Ignora els prefixos en ordenar",
|
||||||
|
"LabelSettingsTimeFormat": "Format d'hora",
|
||||||
|
"LabelShare": "Comparteix",
|
||||||
|
"LabelShareDownloadableHelp": "Permet els usuaris amb l'enllaç de compartició de baixar un fitxer ZIP amb l'element de la biblioteca.",
|
||||||
|
"LabelShareURL": "URL de compartició",
|
||||||
"LabelShowAll": "Mostra-ho tot",
|
"LabelShowAll": "Mostra-ho tot",
|
||||||
"LabelShowSeconds": "Mostra segons",
|
"LabelShowSeconds": "Mostra segons",
|
||||||
"LabelShowSubtitles": "Mostra subtítols",
|
"LabelShowSubtitles": "Mostra subtítols",
|
||||||
"LabelSize": "Mida",
|
"LabelSize": "Mida",
|
||||||
"LabelSleepTimer": "Temporitzador de repòs",
|
"LabelSleepTimer": "Temporitzador de repòs",
|
||||||
"LabelSlug": "Slug",
|
"LabelSlug": "Slug",
|
||||||
|
"LabelSortAscending": "Ascendent",
|
||||||
|
"LabelSortDescending": "Descendent",
|
||||||
"LabelStart": "Inicia",
|
"LabelStart": "Inicia",
|
||||||
"LabelStartTime": "Hora d'inici",
|
"LabelStartTime": "Hora d'inici",
|
||||||
"LabelStarted": "Iniciat",
|
"LabelStarted": "Iniciat",
|
||||||
@@ -654,88 +667,98 @@
|
|||||||
"LabelViewPlayerSettings": "Mostra els ajustaments del reproductor",
|
"LabelViewPlayerSettings": "Mostra els ajustaments del reproductor",
|
||||||
"LabelViewQueue": "Mostra cua del reproductor",
|
"LabelViewQueue": "Mostra cua del reproductor",
|
||||||
"LabelVolume": "Volum",
|
"LabelVolume": "Volum",
|
||||||
"LabelWebRedirectURLsDescription": "Autoritza aquestes URL al teu proveïdor OAuth per permetre redirecció a l'aplicació web després d'iniciar sessió:",
|
"LabelWebRedirectURLsDescription": "Autoritzeu aquests URL al vostre proveïdor OAuth per a permetre redirigir a l’aplicació web després d'iniciar sessió:",
|
||||||
"LabelWebRedirectURLsSubfolder": "Subcarpeta per a URL de redirecció",
|
"LabelWebRedirectURLsSubfolder": "Subcarpeta per a URL de redirecció",
|
||||||
"LabelWeekdaysToRun": "Executar en dies de la setmana",
|
"LabelWeekdaysToRun": "Executar en dies de la setmana",
|
||||||
"LabelXBooks": "{0} llibres",
|
"LabelXBooks": "{0} llibres",
|
||||||
"LabelXItems": "{0} elements",
|
"LabelXItems": "{0} elements",
|
||||||
"LabelYearReviewHide": "Oculta resum de l'any",
|
"LabelYearReviewHide": "Oculta resum de l'any",
|
||||||
"LabelYearReviewShow": "Mostra resum de l'any",
|
"LabelYearReviewShow": "Mostra resum de l'any",
|
||||||
"LabelYourAudiobookDuration": "Duració del teu audiollibre",
|
"LabelYourAudiobookDuration": "Duració del vostre audiollibre",
|
||||||
"LabelYourBookmarks": "Els vostres marcadors",
|
"LabelYourBookmarks": "Els vostres marcadors",
|
||||||
"LabelYourPlaylists": "Les teves llistes",
|
"LabelYourPlaylists": "Les vostres llistes",
|
||||||
"LabelYourProgress": "El vostre progrés",
|
"LabelYourProgress": "El vostre progrés",
|
||||||
"MessageAddToPlayerQueue": "Afegeix a la cua del reproductor",
|
"MessageAddToPlayerQueue": "Afegeix a la cua del reproductor",
|
||||||
"MessageAppriseDescription": "Per utilitzar aquesta funció, hauràs de tenir l'<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API d'Apprise</a> en funcionament o una API que gestioni resultats similars. <br/>La URL de l'API d'Apprise ha de tenir la mateixa ruta d'arxius que on s'envien les notificacions. Per exemple: si la teva API és a <code>http://192.168.1.1:8337</code>, llavors posaries <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "Per utilitzar aquesta funció, hauràs de tenir l'<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API d'Apprise</a> en funcionament o una API que gestioni resultats similars. <br/>La URL de l'API d'Apprise ha de tenir la mateixa ruta d'arxius que on s'envien les notificacions. Per exemple: si la teva API és a <code>http://192.168.1.1:8337</code>, llavors posaries <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Reengegueu el servidor després de desar perquè s'hi apliquin els canvis d'OIDC.",
|
||||||
"MessageBackupsDescription": "Les còpies de seguretat inclouen: usuaris, progrés dels usuaris, detalls dels elements de la biblioteca, configuració del servidor i imatges a <code>/metadata/items</code> i <code>/metadata/authors</code>. Les còpies de seguretat <strong>NO</strong> inclouen cap fitxer guardat a la carpeta de la teva biblioteca.",
|
"MessageBackupsDescription": "Les còpies de seguretat inclouen: usuaris, progrés dels usuaris, detalls dels elements de la biblioteca, configuració del servidor i imatges a <code>/metadata/items</code> i <code>/metadata/authors</code>. Les còpies de seguretat <strong>NO</strong> inclouen cap fitxer guardat a la carpeta de la teva biblioteca.",
|
||||||
"MessageBackupsLocationEditNote": "Nota: Actualitzar la ubicació de la còpia de seguretat no mourà ni modificarà les còpies existents",
|
"MessageBackupsLocationEditNote": "Nota: Actualitzar la ubicació de la còpia de seguretat no mourà ni modificarà les còpies existents",
|
||||||
"MessageBackupsLocationNoEditNote": "Nota: La ubicació de la còpia de seguretat es defineix mitjançant una variable d'entorn i no es pot modificar aquí.",
|
"MessageBackupsLocationNoEditNote": "Nota: La ubicació de la còpia de seguretat es defineix mitjançant una variable d'entorn i no es pot modificar aquí.",
|
||||||
"MessageBackupsLocationPathEmpty": "La ruta de la còpia de seguretat no pot estar buida",
|
"MessageBackupsLocationPathEmpty": "La ruta de la còpia de seguretat no pot estar buida",
|
||||||
"MessageBatchQuickMatchDescription": "La funció \"Troba Ràpid\" intentarà afegir portades i metadades que falten als elements seleccionats. Activa l'opció següent perquè \"Troba Ràpid\" pugui sobreescriure portades i/o metadades existents.",
|
"MessageBatchQuickMatchDescription": "La funció \"Troba Ràpid\" intentarà afegir portades i metadades que falten als elements seleccionats. Activa l'opció següent perquè \"Troba Ràpid\" pugui sobreescriure portades i/o metadades existents.",
|
||||||
"MessageBookshelfNoCollections": "No tens cap col·lecció",
|
"MessageBookshelfNoCollections": "Encara no heu fet cap col·lecció",
|
||||||
|
"MessageBookshelfNoCollectionsHelp": "Les col·leccions són públiques. Tots els usuaris amb accés a la biblioteca les podran veure.",
|
||||||
"MessageBookshelfNoRSSFeeds": "Cap font RSS està oberta",
|
"MessageBookshelfNoRSSFeeds": "Cap font RSS està oberta",
|
||||||
"MessageBookshelfNoResultsForFilter": "Cap resultat per al filtre \"{0}: {1}\"",
|
"MessageBookshelfNoResultsForFilter": "Cap resultat per al filtre «{0}: {1}»",
|
||||||
"MessageBookshelfNoResultsForQuery": "Cap resultat per a la consulta",
|
"MessageBookshelfNoResultsForQuery": "Cap resultat per a la consulta",
|
||||||
"MessageBookshelfNoSeries": "No tens cap sèrie",
|
"MessageBookshelfNoSeries": "No teniu cap sèrie",
|
||||||
"MessageChapterEndIsAfter": "El final del capítol és després del final del teu audiollibre",
|
"MessageChapterEndIsAfter": "El final del capítol és després del final del teu audiollibre",
|
||||||
"MessageChapterErrorFirstNotZero": "El primer capítol ha de començar a 0",
|
"MessageChapterErrorFirstNotZero": "El primer capítol ha de començar a 0",
|
||||||
"MessageChapterErrorStartGteDuration": "El temps d'inici no és vàlid: ha de ser inferior a la durada de l'audiollibre",
|
"MessageChapterErrorStartGteDuration": "El temps d'inici no és vàlid: ha de ser inferior a la durada de l'audiollibre",
|
||||||
"MessageChapterErrorStartLtPrev": "El temps d'inici no és vàlid: ha de ser igual o més gran que el temps d'inici del capítol anterior",
|
"MessageChapterErrorStartLtPrev": "El temps d'inici no és vàlid: ha de ser igual o més gran que el temps d'inici del capítol anterior",
|
||||||
"MessageChapterStartIsAfter": "L'inici del capítol és després del final del teu audiollibre",
|
"MessageChapterStartIsAfter": "L'inici del capítol és després del final del teu audiollibre",
|
||||||
|
"MessageChaptersNotFound": "No s'han trobat els capítols",
|
||||||
"MessageCheckingCron": "Comprovant cron...",
|
"MessageCheckingCron": "Comprovant cron...",
|
||||||
"MessageConfirmCloseFeed": "Estàs segur que vols tancar aquesta font?",
|
"MessageConfirmCloseFeed": "Segur que voleu tancar aquest canal?",
|
||||||
"MessageConfirmDeleteBackup": "Estàs segur que vols eliminar la còpia de seguretat {0}?",
|
"MessageConfirmDeleteBackup": "Segur que voleu suprimir la còpia de seguretat de {0}?",
|
||||||
"MessageConfirmDeleteDevice": "Estàs segur que vols eliminar el lector electrònic \"{0}\"?",
|
"MessageConfirmDeleteDevice": "Segur que voleu suprimir el lector electrònic «{0}»?",
|
||||||
"MessageConfirmDeleteFile": "Això eliminarà el fitxer del teu sistema. Estàs segur?",
|
"MessageConfirmDeleteFile": "Això suprimirà el fitxer del vostre sistema de fitxers. N'esteu segur?",
|
||||||
"MessageConfirmDeleteLibrary": "Estàs segur que vols eliminar permanentment la biblioteca \"{0}\"?",
|
"MessageConfirmDeleteLibrary": "Segur que voleu suprimir permanentment la biblioteca «{0}»?",
|
||||||
"MessageConfirmDeleteLibraryItem": "Això eliminarà l'element de la base de dades i del sistema. Estàs segur?",
|
"MessageConfirmDeleteLibraryItem": "Això suprimirà l’element de la base de dades i del sistema de fitxers. N’esteu segur?",
|
||||||
"MessageConfirmDeleteLibraryItems": "Això eliminarà {0} element(s) de la base de dades i del sistema. Estàs segur?",
|
"MessageConfirmDeleteLibraryItems": "Això suprimirà {0} element(s) de la base de dades i del sistema de fitxers. N'esteu segur?",
|
||||||
"MessageConfirmDeleteMetadataProvider": "Estàs segur que vols eliminar el proveïdor de metadades personalitzat \"{0}\"?",
|
"MessageConfirmDeleteMetadataProvider": "Segur que voleu suprimir el proveïdor de metadades personalitzat «{0}»?",
|
||||||
"MessageConfirmDeleteNotification": "Estàs segur que vols eliminar aquesta notificació?",
|
"MessageConfirmDeleteNotification": "Segur que voleu suprimir aquesta notificació?",
|
||||||
"MessageConfirmDeleteSession": "Estàs segur que vols eliminar aquesta sessió?",
|
"MessageConfirmDeleteSession": "Segur que voleu suprimir aquesta sessió?",
|
||||||
"MessageConfirmEmbedMetadataInAudioFiles": "Estàs segur que vols incrustar metadades a {0} fitxer(s) d'àudio?",
|
"MessageConfirmEmbedMetadataInAudioFiles": "Segur que voleu incrustar metadades a {0} fitxer(s) d'àudio?",
|
||||||
"MessageConfirmForceReScan": "Estàs segur que vols forçar un reescaneig?",
|
"MessageConfirmForceReScan": "Segur que voleu forçar un reescaneig?",
|
||||||
"MessageConfirmMarkAllEpisodesFinished": "Estàs segur que vols marcar tots els episodis com a acabats?",
|
"MessageConfirmMarkAllEpisodesFinished": "Segur que voleu marcar tots els episodis com a acabats?",
|
||||||
"MessageConfirmMarkAllEpisodesNotFinished": "Estàs segur que vols marcar tots els episodis com a no acabats?",
|
"MessageConfirmMarkAllEpisodesNotFinished": "Segur que voleu marcar tots els episodis com a no acabats?",
|
||||||
"MessageConfirmMarkItemFinished": "Estàs segur que vols marcar \"{0}\" com a acabat?",
|
"MessageConfirmMarkItemFinished": "Segur que voleu marcar «{0}» com a acabat?",
|
||||||
"MessageConfirmMarkItemNotFinished": "Estàs segur que vols marcar \"{0}\" com a no acabat?",
|
"MessageConfirmMarkItemNotFinished": "Segur que voleu marcar «{0}» com a no acabat?",
|
||||||
"MessageConfirmMarkSeriesFinished": "Estàs segur que vols marcar tots els llibres d'aquesta sèrie com a acabats?",
|
"MessageConfirmMarkSeriesFinished": "Segur que voleu marcar tots els llibres d'aquesta sèrie com a acabats?",
|
||||||
"MessageConfirmMarkSeriesNotFinished": "Estàs segur que vols marcar tots els llibres d'aquesta sèrie com a no acabats?",
|
"MessageConfirmMarkSeriesNotFinished": "Segur que voleu marcar tots els llibres d'aquesta sèrie com a no acabats?",
|
||||||
"MessageConfirmNotificationTestTrigger": "Vols activar aquesta notificació amb dades de prova?",
|
"MessageConfirmNotificationTestTrigger": "Voleu activar aquesta notificació amb dades de prova?",
|
||||||
"MessageConfirmPurgeCache": "Esborrar la memòria cau eliminarà tot el directori localitzat a <code>/metadata/cache</code>. <br /><br />Estàs segur que vols eliminar-lo?",
|
"MessageConfirmPurgeCache": "Purgar la memòria cau suprimirà tot el directori localitzat a <code>/metadata/cache</code>. <br /><br />Segur que voleu eliminar-lo?",
|
||||||
"MessageConfirmPurgeItemsCache": "Esborrar la memòria cau dels elements eliminarà el directori <code>/metadata/cache/items</code>.<br />Estàs segur?",
|
"MessageConfirmPurgeItemsCache": "Esborrar la memòria cau dels elements eliminarà el directori <code>/metadata/cache/items</code>.<br />Estàs segur?",
|
||||||
"MessageConfirmQuickEmbed": "Advertència! La integració ràpida no fa còpies de seguretat dels teus fitxers d'àudio. Assegura't d'haver-ne fet una còpia abans. <br><br>Vols continuar?",
|
"MessageConfirmQuickEmbed": "Avís: la incrustació ràpida no fa còpies de seguretat dels vostres fitxers d'àudio. Assegureu-vos d'haver-ne fet una còpia abans. <br><br>Voleu continuar?",
|
||||||
"MessageConfirmQuickMatchEpisodes": "El reconeixement ràpid sobreescriurà els detalls si es troba una coincidència. Estàs segur?",
|
"MessageConfirmQuickMatchEpisodes": "El reconeixement ràpid sobreescriurà els detalls si es troba una coincidència. Estàs segur?",
|
||||||
"MessageConfirmReScanLibraryItems": "Estàs segur que vols reescanejar {0} element(s)?",
|
"MessageConfirmReScanLibraryItems": "Segur que voleu reescanejar {0} element(s)?",
|
||||||
"MessageConfirmRemoveAllChapters": "Estàs segur que vols eliminar tots els capítols?",
|
"MessageConfirmRemoveAllChapters": "Segur que voleu eliminar tots els capítols?",
|
||||||
"MessageConfirmRemoveAuthor": "Estàs segur que vols eliminar l'autor \"{0}\"?",
|
"MessageConfirmRemoveAuthor": "Segur que voleu eliminar l'autor «{0}»?",
|
||||||
"MessageConfirmRemoveCollection": "Estàs segur que vols eliminar la col·lecció \"{0}\"?",
|
"MessageConfirmRemoveCollection": "Segur que voleu eliminar la col·lecció «{0}»?",
|
||||||
"MessageConfirmRemoveEpisode": "Estàs segur que vols eliminar l'episodi \"{0}\"?",
|
"MessageConfirmRemoveEpisode": "Segur que voleu eliminar l'episodi «{0}»?",
|
||||||
"MessageConfirmRemoveEpisodes": "Estàs segur que vols eliminar {0} episodis?",
|
"MessageConfirmRemoveEpisodes": "Segur que voleu eliminar {0} episodis?",
|
||||||
"MessageConfirmRemoveListeningSessions": "Estàs segur que vols eliminar {0} sessions d'escolta?",
|
"MessageConfirmRemoveListeningSessions": "Segur que voleu eliminar {0} sessions d'escolta?",
|
||||||
"MessageConfirmRemoveMetadataFiles": "Estàs segur que vols eliminar tots els fitxers de metadades.{0} de les carpetes dels elements de la teva biblioteca?",
|
"MessageConfirmRemoveMetadataFiles": "Segur que voleu eliminar tots els fitxers metadata.{0} de les carpetes dels elements de la vostra biblioteca?",
|
||||||
"MessageConfirmRemoveNarrator": "Estàs segur que vols eliminar el narrador \"{0}\"?",
|
"MessageConfirmRemoveNarrator": "Segur que voleu eliminar el narrador «{0}»?",
|
||||||
"MessageConfirmRemovePlaylist": "Estàs segur que vols eliminar la llista de reproducció \"{0}\"?",
|
"MessageConfirmRemovePlaylist": "Segur que voleu eliminar la llista de reproducció «{0}»?",
|
||||||
"MessageConfirmRenameGenre": "Estàs segur que vols canviar el gènere \"{0}\" a \"{1}\" per a tots els elements?",
|
"MessageConfirmRenameGenre": "Segur que voleu canviar el nom del gènere «{0}» a «{1}» per a tots els elements?",
|
||||||
"MessageConfirmRenameGenreMergeNote": "Nota: Aquest gènere ja existeix, i es fusionarà.",
|
"MessageConfirmRenameGenreMergeNote": "Nota: Aquest gènere ja existeix, i es fusionarà.",
|
||||||
"MessageConfirmRenameGenreWarning": "Advertència! Ja existeix un gènere similar \"{0}\".",
|
"MessageConfirmRenameGenreWarning": "Advertència! Ja existeix un gènere similar \"{0}\".",
|
||||||
"MessageConfirmRenameTag": "Estàs segur que vols canviar l'etiqueta \"{0}\" a \"{1}\" per a tots els elements?",
|
"MessageConfirmRenameTag": "Segur que voleu canviar el nom de l'etiqueta «{0}» a «{1}» per a tots els elements?",
|
||||||
"MessageConfirmRenameTagMergeNote": "Nota: Aquesta etiqueta ja existeix, i es fusionarà.",
|
"MessageConfirmRenameTagMergeNote": "Nota: Aquesta etiqueta ja existeix, i es fusionarà.",
|
||||||
"MessageConfirmRenameTagWarning": "Advertència! Ja existeix una etiqueta similar \"{0}\".",
|
"MessageConfirmRenameTagWarning": "Advertència! Ja existeix una etiqueta similar \"{0}\".",
|
||||||
"MessageConfirmResetProgress": "Estàs segur que vols reiniciar el teu progrés?",
|
"MessageConfirmResetProgress": "Segur que voleu reinicialitzar el vostre progrés?",
|
||||||
"MessageConfirmSendEbookToDevice": "Estàs segur que vols enviar {0} ebook(s) \"{1}\" al dispositiu \"{2}\"?",
|
"MessageConfirmSendEbookToDevice": "Segur que voleu enviar {0} llibre(s) «{1}» al dispositiu «{2}»?",
|
||||||
"MessageConfirmUnlinkOpenId": "Estàs segur que vols desvincular aquest usuari d'OpenID?",
|
"MessageConfirmUnlinkOpenId": "Segur que voleu desenllaçar aquest usuari d'OpenID?",
|
||||||
"MessageDownloadingEpisode": "Descarregant capítol",
|
"MessageDaysListenedInTheLastYear": "{0} dies escoltats l'any passat",
|
||||||
|
"MessageDownloadingEpisode": "S'està baixant l'episodi",
|
||||||
"MessageDragFilesIntoTrackOrder": "Arrossega els fitxers en l'ordre correcte de les pistes",
|
"MessageDragFilesIntoTrackOrder": "Arrossega els fitxers en l'ordre correcte de les pistes",
|
||||||
"MessageEmbedFailed": "Error en incrustar!",
|
"MessageEmbedFailed": "Error en incrustar!",
|
||||||
"MessageEmbedFinished": "Incrustació acabada!",
|
"MessageEmbedFinished": "Incrustació acabada!",
|
||||||
"MessageEmbedQueue": "En cua per incrustar metadades ({0} en cua)",
|
"MessageEmbedQueue": "En cua per incrustar metadades ({0} en cua)",
|
||||||
|
"MessageFeedURLWillBe": "L'URL del canal serà {0}",
|
||||||
"MessageFetching": "S'està recuperant...",
|
"MessageFetching": "S'està recuperant...",
|
||||||
"MessageImportantNotice": "Avís important",
|
"MessageImportantNotice": "Avís important",
|
||||||
|
"MessageInsertChapterBelow": "Insereix un capítol a sota",
|
||||||
|
"MessageInvalidAsin": "L'ASIN no és vàlid",
|
||||||
"MessageItemsSelected": "{0} elements seleccionats",
|
"MessageItemsSelected": "{0} elements seleccionats",
|
||||||
"MessageItemsUpdated": "{0} elements actualitzats",
|
"MessageItemsUpdated": "{0} elements actualitzats",
|
||||||
|
"MessageJoinUsOn": "Uniu-vos a nosaltres a",
|
||||||
"MessageLoading": "S'està carregant...",
|
"MessageLoading": "S'està carregant...",
|
||||||
"MessageLoadingFolders": "S'estan carregant les carpetes...",
|
"MessageLoadingFolders": "S'estan carregant les carpetes...",
|
||||||
|
"MessageMarkAllEpisodesFinished": "Marca tots els episodis com a acabats",
|
||||||
|
"MessageMarkAllEpisodesNotFinished": "Marca tots els episodis com a inacabats",
|
||||||
"MessageMarkAsFinished": "Marcar com acabat",
|
"MessageMarkAsFinished": "Marcar com acabat",
|
||||||
"MessageMarkAsNotFinished": "Marcar com no acabat",
|
"MessageMarkAsNotFinished": "Marcar com no acabat",
|
||||||
"MessageMatchBooksDescription": "S'intentarà fer coincidir els llibres de la biblioteca amb un llibre del proveïdor de cerca seleccionat, i s'ompliran els detalls buits i la portada. No sobreescriu els detalls.",
|
"MessageMatchBooksDescription": "S'intentarà fer coincidir els llibres de la biblioteca amb un llibre del proveïdor de cerca seleccionat, i s'ompliran els detalls buits i la portada. No sobreescriu els detalls.",
|
||||||
@@ -776,38 +799,40 @@
|
|||||||
"MessagePauseChapter": "Pausar la reproducció del capítol",
|
"MessagePauseChapter": "Pausar la reproducció del capítol",
|
||||||
"MessagePlayChapter": "Escoltar l'inici del capítol",
|
"MessagePlayChapter": "Escoltar l'inici del capítol",
|
||||||
"MessagePlaylistCreateFromCollection": "Crear una llista de reproducció a partir d'una col·lecció",
|
"MessagePlaylistCreateFromCollection": "Crear una llista de reproducció a partir d'una col·lecció",
|
||||||
"MessagePleaseWait": "Espera si us plau...",
|
"MessagePleaseWait": "Espereu...",
|
||||||
"MessagePodcastHasNoRSSFeedForMatching": "El podcast no té una URL de font RSS que es pugui utilitzar",
|
"MessagePodcastHasNoRSSFeedForMatching": "El pòdcast no té un URL de canal RSS que es pugui utilitzar",
|
||||||
"MessagePodcastSearchField": "Introdueix el terme de cerca o la URL de la font RSS",
|
"MessagePodcastSearchField": "Introduïu el terme de cerca o l'URL del canal RSS",
|
||||||
"MessageQuickEmbedInProgress": "Integració ràpida en procés",
|
"MessageQuickEmbedInProgress": "Integració ràpida en procés",
|
||||||
"MessageQuickEmbedQueue": "En cua per a inserció ràpida ({0} en cua)",
|
"MessageQuickEmbedQueue": "En cua per a inserció ràpida ({0} en cua)",
|
||||||
"MessageQuickMatchAllEpisodes": "Combina ràpidament tots els episodis",
|
"MessageQuickMatchAllEpisodes": "Combina ràpidament tots els episodis",
|
||||||
"MessageQuickMatchDescription": "Omple detalls d'elements buits i portades amb els primers resultats de '{0}'. No sobreescriu els detalls tret que l'opció \"Preferir metadades trobades\" del servidor estigui habilitada.",
|
"MessageQuickMatchDescription": "Emplena els detalls i la coberta dels elements buits amb el resultat de la primera coincidència de «{0}». No sobreescriu els detalls tret que s'activi el paràmetre del servidor «Prefereix metadades coincidents».",
|
||||||
"MessageRemoveChapter": "Eliminar capítols",
|
"MessageRemoveChapter": "Elimina el capítol",
|
||||||
"MessageRemoveEpisodes": "Eliminar {0} episodi(s)",
|
"MessageRemoveEpisodes": "Elimina {0} episodi(s)",
|
||||||
"MessageRemoveFromPlayerQueue": "Eliminar de la cua del reproductor",
|
"MessageRemoveFromPlayerQueue": "Elimina de la cua del reproductor",
|
||||||
"MessageRemoveUserWarning": "Estàs segur que vols eliminar l'usuari \"{0}\"?",
|
"MessageRemoveUserWarning": "Segur que voleu suprimir permanentment l'usuari «{0}»?",
|
||||||
"MessageReportBugsAndContribute": "Informa d'errors, sol·licita funcions i contribueix a",
|
"MessageReportBugsAndContribute": "Informa d'errors, sol·licita funcions i contribueix a",
|
||||||
"MessageResetChaptersConfirm": "Estàs segur que vols desfer els canvis i revertir els capítols al seu estat original?",
|
"MessageResetChaptersConfirm": "Segur que voleu desfer els canvis i revertir els capítols al seu estat original?",
|
||||||
"MessageRestoreBackupConfirm": "Estàs segur que vols restaurar la còpia de seguretat creada a",
|
"MessageRestoreBackupConfirm": "Segur que voleu restaurar la còpia de seguretat creada a",
|
||||||
"MessageRestoreBackupWarning": "Restaurar sobreescriurà tota la base de dades situada a /config i les imatges de portades a /metadata/items i /metadata/authors.<br /><br />La còpia de seguretat no modifica cap fitxer a les carpetes de la teva biblioteca. Si has activat l'opció del servidor per guardar portades i metadades a les carpetes de la biblioteca, aquests fitxers no es guarden ni sobreescriuen.<br /><br />Tots els clients que utilitzin el teu servidor s'actualitzaran automàticament.",
|
"MessageRestoreBackupWarning": "Restaurar sobreescriurà tota la base de dades situada a /config i les imatges de portades a /metadata/items i /metadata/authors.<br /><br />La còpia de seguretat no modifica cap fitxer a les carpetes de la teva biblioteca. Si has activat l'opció del servidor per guardar portades i metadades a les carpetes de la biblioteca, aquests fitxers no es guarden ni sobreescriuen.<br /><br />Tots els clients que utilitzin el teu servidor s'actualitzaran automàticament.",
|
||||||
|
"MessageScheduleRunEveryWeekdayAtTime": "Executa cada {0} a les {1}",
|
||||||
"MessageSearchResultsFor": "Resultats de la cerca de",
|
"MessageSearchResultsFor": "Resultats de la cerca de",
|
||||||
"MessageSelected": "{0} seleccionat(s)",
|
"MessageSelected": "{0} seleccionat(s)",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "La seqüència de la sèrie no pot contenir espais",
|
||||||
"MessageServerCouldNotBeReached": "No es va poder establir la connexió amb el servidor",
|
"MessageServerCouldNotBeReached": "No es va poder establir la connexió amb el servidor",
|
||||||
"MessageSetChaptersFromTracksDescription": "Establir capítols utilitzant cada fitxer d'àudio com un capítol i el títol del capítol com el nom del fitxer d'àudio",
|
"MessageSetChaptersFromTracksDescription": "Establir capítols utilitzant cada fitxer d'àudio com un capítol i el títol del capítol com el nom del fitxer d'àudio",
|
||||||
"MessageShareExpirationWillBe": "La caducitat serà <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "La caducitat serà <strong>{0}</strong>",
|
||||||
"MessageShareExpiresIn": "Caduca en {0}",
|
"MessageShareExpiresIn": "Caduca en {0}",
|
||||||
"MessageShareURLWillBe": "La URL per compartir serà <strong>{0}</strong>",
|
"MessageShareURLWillBe": "La URL per compartir serà <strong>{0}</strong>",
|
||||||
"MessageStartPlaybackAtTime": "Començar la reproducció per a \"{0}\" a {1}?",
|
"MessageStartPlaybackAtTime": "Voleu començar la reproducció per a «{0}» a {1}?",
|
||||||
"MessageTaskAudioFileNotWritable": "El fitxer d'àudio \"{0}\" no es pot escriure",
|
"MessageTaskAudioFileNotWritable": "El fitxer d'àudio «{0}» no es pot escriure",
|
||||||
"MessageTaskCanceledByUser": "Tasca cancel·lada per l'usuari",
|
"MessageTaskCanceledByUser": "Tasca cancel·lada per l'usuari",
|
||||||
"MessageTaskDownloadingEpisodeDescription": "Descarregant l'episodi \"{0}\"",
|
"MessageTaskDownloadingEpisodeDescription": "S'està baixant l'episodi «{0}»",
|
||||||
"MessageTaskEmbeddingMetadata": "Inserint metadades",
|
"MessageTaskEmbeddingMetadata": "Inserint metadades",
|
||||||
"MessageTaskEmbeddingMetadataDescription": "Inserint metadades en l'audiollibre \"{0}\"",
|
"MessageTaskEmbeddingMetadataDescription": "Inserint metadades en l'audiollibre \"{0}\"",
|
||||||
"MessageTaskEncodingM4b": "Codificant M4B",
|
"MessageTaskEncodingM4b": "Codificant M4B",
|
||||||
"MessageTaskEncodingM4bDescription": "Codificant l'audiollibre \"{0}\" en un únic fitxer M4B",
|
"MessageTaskEncodingM4bDescription": "S'està codificant l'audiollibre «{0}» en un únic fitxer M4B",
|
||||||
"MessageTaskFailed": "Fallada",
|
"MessageTaskFailed": "Fallada",
|
||||||
"MessageTaskFailedToBackupAudioFile": "Error en fer una còpia de seguretat del fitxer d'àudio \"{0}\"",
|
"MessageTaskFailedToBackupAudioFile": "No s'ha pogut fer una còpia de seguretat del fitxer d'àudio «{0}»",
|
||||||
"MessageTaskFailedToCreateCacheDirectory": "Error en crear el directori de la memòria cau",
|
"MessageTaskFailedToCreateCacheDirectory": "Error en crear el directori de la memòria cau",
|
||||||
"MessageTaskFailedToEmbedMetadataInFile": "Error en incrustar metadades en el fitxer \"{0}\"",
|
"MessageTaskFailedToEmbedMetadataInFile": "Error en incrustar metadades en el fitxer \"{0}\"",
|
||||||
"MessageTaskFailedToMergeAudioFiles": "Error en fusionar fitxers d'àudio",
|
"MessageTaskFailedToMergeAudioFiles": "Error en fusionar fitxers d'àudio",
|
||||||
@@ -816,14 +841,14 @@
|
|||||||
"MessageTaskMatchingBooksInLibrary": "Coincidint llibres a la biblioteca \"{0}\"",
|
"MessageTaskMatchingBooksInLibrary": "Coincidint llibres a la biblioteca \"{0}\"",
|
||||||
"MessageTaskNoFilesToScan": "Sense fitxers per escanejar",
|
"MessageTaskNoFilesToScan": "Sense fitxers per escanejar",
|
||||||
"MessageTaskOpmlImport": "Importar OPML",
|
"MessageTaskOpmlImport": "Importar OPML",
|
||||||
"MessageTaskOpmlImportDescription": "Creant podcasts a partir de {0} fonts RSS",
|
"MessageTaskOpmlImportDescription": "S'estan creant pòdcasts a partir de {0} canals RSS",
|
||||||
"MessageTaskOpmlImportFeed": "Importació de feed OPML",
|
"MessageTaskOpmlImportFeed": "Importació d'un canal OPML",
|
||||||
"MessageTaskOpmlImportFeedDescription": "Importació del feed RSS \"{0}\"",
|
"MessageTaskOpmlImportFeedDescription": "S'està important el canal RSS «{0}»",
|
||||||
"MessageTaskOpmlImportFeedFailed": "No es pot obtenir el podcast",
|
"MessageTaskOpmlImportFeedFailed": "No s'ha pogut obtenir el canal del pòdcast",
|
||||||
"MessageTaskOpmlImportFeedPodcastDescription": "Creant el podcast \"{0}\"",
|
"MessageTaskOpmlImportFeedPodcastDescription": "S'està creant el pòdcast «{0}»",
|
||||||
"MessageTaskOpmlImportFeedPodcastExists": "El podcast ja existeix a la ruta",
|
"MessageTaskOpmlImportFeedPodcastExists": "El pòdcast ja existeix al camí",
|
||||||
"MessageTaskOpmlImportFeedPodcastFailed": "Error en crear el podcast",
|
"MessageTaskOpmlImportFeedPodcastFailed": "No s'ha pogut crear el pòdcast",
|
||||||
"MessageTaskOpmlImportFinished": "Afegit {0} podcasts",
|
"MessageTaskOpmlImportFinished": "S'han afegit {0} pòdcasts",
|
||||||
"MessageTaskOpmlParseFailed": "No s'ha pogut analitzar el fitxer OPML",
|
"MessageTaskOpmlParseFailed": "No s'ha pogut analitzar el fitxer OPML",
|
||||||
"MessageTaskOpmlParseFastFail": "No s'ha trobat l'etiqueta <opml> o <outline> al fitxer OPML",
|
"MessageTaskOpmlParseFastFail": "No s'ha trobat l'etiqueta <opml> o <outline> al fitxer OPML",
|
||||||
"MessageTaskOpmlParseNoneFound": "No s'han trobat fonts al fitxer OPML",
|
"MessageTaskOpmlParseNoneFound": "No s'han trobat fonts al fitxer OPML",
|
||||||
@@ -841,13 +866,13 @@
|
|||||||
"MessageValidCronExpression": "Expressió de cron vàlida",
|
"MessageValidCronExpression": "Expressió de cron vàlida",
|
||||||
"MessageWatcherIsDisabledGlobally": "El watcher està desactivat globalment a la configuració del servidor",
|
"MessageWatcherIsDisabledGlobally": "El watcher està desactivat globalment a la configuració del servidor",
|
||||||
"MessageXLibraryIsEmpty": "La biblioteca {0} està buida!",
|
"MessageXLibraryIsEmpty": "La biblioteca {0} està buida!",
|
||||||
"MessageYourAudiobookDurationIsLonger": "La durada del teu audiollibre és més llarga que la durada trobada",
|
"MessageYourAudiobookDurationIsLonger": "La durada del vostre audiollibre és major que la durada trobada",
|
||||||
"MessageYourAudiobookDurationIsShorter": "La durada del teu audiollibre és més curta que la durada trobada",
|
"MessageYourAudiobookDurationIsShorter": "La durada del vostre audiollibre és menor que la durada trobada",
|
||||||
"NoteChangeRootPassword": "L'usuari Root és l'únic usuari que pot no tenir una contrasenya",
|
"NoteChangeRootPassword": "L'usuari Root és l'únic usuari que pot no tenir una contrasenya",
|
||||||
"NoteChapterEditorTimes": "Nota: El temps d'inici del primer capítol ha de romandre a 0:00, i el temps d'inici de l'últim capítol no pot superar la durada de l'audiollibre.",
|
"NoteChapterEditorTimes": "Nota: el temps d'inici del primer capítol ha de romandre a 0:00, i el temps d'inici de l'últim capítol no pot superar la durada de l'audiollibre.",
|
||||||
"NoteFolderPicker": "Nota: Les carpetes ja assignades no es mostraran",
|
"NoteFolderPicker": "Nota: les carpetes ja assignades no es mostraran",
|
||||||
"NoteRSSFeedPodcastAppsHttps": "Advertència: La majoria d'aplicacions de podcast requereixen que la URL de la font RSS utilitzi HTTPS",
|
"NoteRSSFeedPodcastAppsHttps": "Avís: la majoria d'aplicacions de pòdcast requereixen que l'URL del canal RSS utilitzi HTTPS",
|
||||||
"NoteRSSFeedPodcastAppsPubDate": "Advertència: Un o més dels teus episodis no tenen data de publicació. Algunes aplicacions de podcast ho requereixen.",
|
"NoteRSSFeedPodcastAppsPubDate": "Avís: un o més dels vostres episodis no tenen data de publicació. Algunes aplicacions de pòdcast ho requereixen.",
|
||||||
"NoteUploaderFoldersWithMediaFiles": "Les carpetes amb fitxers multimèdia es gestionaran com a elements separats a la biblioteca.",
|
"NoteUploaderFoldersWithMediaFiles": "Les carpetes amb fitxers multimèdia es gestionaran com a elements separats a la biblioteca.",
|
||||||
"NoteUploaderOnlyAudioFiles": "Si només puges fitxers d'àudio, cada fitxer es gestionarà com un audiollibre separat.",
|
"NoteUploaderOnlyAudioFiles": "Si només puges fitxers d'àudio, cada fitxer es gestionarà com un audiollibre separat.",
|
||||||
"NoteUploaderUnsupportedFiles": "Els fitxers no compatibles seran ignorats. Si selecciona o arrossega una carpeta, els fitxers que no estiguin dins d'una subcarpeta seran ignorats.",
|
"NoteUploaderUnsupportedFiles": "Els fitxers no compatibles seran ignorats. Si selecciona o arrossega una carpeta, els fitxers que no estiguin dins d'una subcarpeta seran ignorats.",
|
||||||
@@ -856,7 +881,7 @@
|
|||||||
"NotificationOnEpisodeDownloadedDescription": "S'activa quan es descarrega automàticament un episodi d'un podcast",
|
"NotificationOnEpisodeDownloadedDescription": "S'activa quan es descarrega automàticament un episodi d'un podcast",
|
||||||
"NotificationOnTestDescription": "Esdeveniment per provar el sistema de notificacions",
|
"NotificationOnTestDescription": "Esdeveniment per provar el sistema de notificacions",
|
||||||
"PlaceholderNewCollection": "Nou nom de la col·lecció",
|
"PlaceholderNewCollection": "Nou nom de la col·lecció",
|
||||||
"PlaceholderNewFolderPath": "Nova ruta de carpeta",
|
"PlaceholderNewFolderPath": "Camí de carpeta nou",
|
||||||
"PlaceholderNewPlaylist": "Nou nom de la llista de reproducció",
|
"PlaceholderNewPlaylist": "Nou nom de la llista de reproducció",
|
||||||
"PlaceholderSearch": "Cerca...",
|
"PlaceholderSearch": "Cerca...",
|
||||||
"PlaceholderSearchEpisode": "Cerca d'episodis...",
|
"PlaceholderSearchEpisode": "Cerca d'episodis...",
|
||||||
@@ -882,7 +907,7 @@
|
|||||||
"ToastAppriseUrlRequired": "Cal introduir una URL de Apprise",
|
"ToastAppriseUrlRequired": "Cal introduir una URL de Apprise",
|
||||||
"ToastAsinRequired": "ASIN requerit",
|
"ToastAsinRequired": "ASIN requerit",
|
||||||
"ToastAuthorImageRemoveSuccess": "S'ha eliminat la imatge de l'autor",
|
"ToastAuthorImageRemoveSuccess": "S'ha eliminat la imatge de l'autor",
|
||||||
"ToastAuthorNotFound": "No s'ha trobat l'autor \"{0}\"",
|
"ToastAuthorNotFound": "No s'ha trobat l'autor «{0}»",
|
||||||
"ToastAuthorRemoveSuccess": "Autor eliminat",
|
"ToastAuthorRemoveSuccess": "Autor eliminat",
|
||||||
"ToastAuthorSearchNotFound": "No s'ha trobat l'autor",
|
"ToastAuthorSearchNotFound": "No s'ha trobat l'autor",
|
||||||
"ToastAuthorUpdateMerged": "Autor combinat",
|
"ToastAuthorUpdateMerged": "Autor combinat",
|
||||||
@@ -898,6 +923,7 @@
|
|||||||
"ToastBackupRestoreFailed": "Error en restaurar la còpia de seguretat",
|
"ToastBackupRestoreFailed": "Error en restaurar la còpia de seguretat",
|
||||||
"ToastBackupUploadFailed": "Error en carregar la còpia de seguretat",
|
"ToastBackupUploadFailed": "Error en carregar la còpia de seguretat",
|
||||||
"ToastBackupUploadSuccess": "Còpia de seguretat carregada",
|
"ToastBackupUploadSuccess": "Còpia de seguretat carregada",
|
||||||
|
"ToastBatchApplyDetailsToItemsSuccess": "S'han aplicat els detalls als elements",
|
||||||
"ToastBatchDeleteFailed": "Error en l'eliminació per lots",
|
"ToastBatchDeleteFailed": "Error en l'eliminació per lots",
|
||||||
"ToastBatchDeleteSuccess": "Eliminació per lots correcte",
|
"ToastBatchDeleteSuccess": "Eliminació per lots correcte",
|
||||||
"ToastBatchQuickMatchFailed": "Error en la sincronització ràpida per lots!",
|
"ToastBatchQuickMatchFailed": "Error en la sincronització ràpida per lots!",
|
||||||
@@ -910,6 +936,8 @@
|
|||||||
"ToastCachePurgeFailed": "Error en purgar la memòria cau",
|
"ToastCachePurgeFailed": "Error en purgar la memòria cau",
|
||||||
"ToastCachePurgeSuccess": "Memòria cau purgada amb èxit",
|
"ToastCachePurgeSuccess": "Memòria cau purgada amb èxit",
|
||||||
"ToastChaptersHaveErrors": "Els capítols tenen errors",
|
"ToastChaptersHaveErrors": "Els capítols tenen errors",
|
||||||
|
"ToastChaptersInvalidShiftAmountLast": "La quantitat de desplaçament no és vàlida. L'hora d'inici de l'últim capítol s'estendria més enllà de la durada d'aquest audiollibre.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "La quantitat de desplaçament no és vàlida. El primer capítol tindria una durada zero o negativa i el sobreescriuria el segon capítol. Augmenteu la durada inicial del segon capítol.",
|
||||||
"ToastChaptersMustHaveTitles": "Els capítols han de tenir un títol",
|
"ToastChaptersMustHaveTitles": "Els capítols han de tenir un títol",
|
||||||
"ToastChaptersRemoved": "Capítols eliminats",
|
"ToastChaptersRemoved": "Capítols eliminats",
|
||||||
"ToastChaptersUpdated": "Capítols actualitzats",
|
"ToastChaptersUpdated": "Capítols actualitzats",
|
||||||
@@ -917,6 +945,7 @@
|
|||||||
"ToastCollectionRemoveSuccess": "Col·lecció eliminada",
|
"ToastCollectionRemoveSuccess": "Col·lecció eliminada",
|
||||||
"ToastCollectionUpdateSuccess": "Col·lecció actualitzada",
|
"ToastCollectionUpdateSuccess": "Col·lecció actualitzada",
|
||||||
"ToastCoverUpdateFailed": "Error en actualitzar la portada",
|
"ToastCoverUpdateFailed": "Error en actualitzar la portada",
|
||||||
|
"ToastDateTimeInvalidOrIncomplete": "La data i hora no és vàlida o està incompleta",
|
||||||
"ToastDeleteFileFailed": "No s'ha pogut suprimir el fitxer",
|
"ToastDeleteFileFailed": "No s'ha pogut suprimir el fitxer",
|
||||||
"ToastDeleteFileSuccess": "Fitxer suprimit",
|
"ToastDeleteFileSuccess": "Fitxer suprimit",
|
||||||
"ToastDeviceAddFailed": "Error en afegir el dispositiu",
|
"ToastDeviceAddFailed": "Error en afegir el dispositiu",
|
||||||
@@ -947,34 +976,35 @@
|
|||||||
"ToastItemMarkedAsNotFinishedSuccess": "Element marcat com a no acabat",
|
"ToastItemMarkedAsNotFinishedSuccess": "Element marcat com a no acabat",
|
||||||
"ToastItemUpdateSuccess": "Element actualitzat",
|
"ToastItemUpdateSuccess": "Element actualitzat",
|
||||||
"ToastLibraryCreateFailed": "Error en crear la biblioteca",
|
"ToastLibraryCreateFailed": "Error en crear la biblioteca",
|
||||||
"ToastLibraryCreateSuccess": "Biblioteca \"{0}\" creada",
|
"ToastLibraryCreateSuccess": "S'ha creat la biblioteca «{0}»",
|
||||||
"ToastLibraryDeleteFailed": "Error en eliminar la biblioteca",
|
"ToastLibraryDeleteFailed": "Error en eliminar la biblioteca",
|
||||||
"ToastLibraryDeleteSuccess": "Biblioteca eliminada",
|
"ToastLibraryDeleteSuccess": "Biblioteca eliminada",
|
||||||
"ToastLibraryScanFailedToStart": "Error en iniciar l'escaneig",
|
"ToastLibraryScanFailedToStart": "Error en iniciar l'escaneig",
|
||||||
"ToastLibraryScanStarted": "S'ha iniciat l'escaneig de la biblioteca",
|
"ToastLibraryScanStarted": "S'ha iniciat l'escaneig de la biblioteca",
|
||||||
"ToastLibraryUpdateSuccess": "Biblioteca \"{0}\" actualitzada",
|
"ToastLibraryUpdateSuccess": "S'ha actualitzat la biblioteca «{0}»",
|
||||||
"ToastMatchAllAuthorsFailed": "No coincideix amb tots els autors",
|
"ToastMatchAllAuthorsFailed": "No coincideix amb tots els autors",
|
||||||
"ToastMetadataFilesRemovedError": "Error en eliminar metadades de {0} arxius",
|
"ToastMetadataFilesRemovedError": "S’ha produït un error en eliminar els fitxers metadata.{0}",
|
||||||
"ToastMetadataFilesRemovedNoneFound": "No s'han trobat metadades en {0} arxius",
|
"ToastMetadataFilesRemovedNoneFound": "No hi ha cap fitxer metadata.{0} a la biblioteca",
|
||||||
"ToastMetadataFilesRemovedNoneRemoved": "Cap metadada eliminada en {0} arxius",
|
"ToastMetadataFilesRemovedNoneRemoved": "No s'ha eliminat cap fitxer metadata.{0}",
|
||||||
"ToastMetadataFilesRemovedSuccess": "{0} metadades eliminades en {1} arxius",
|
"ToastMetadataFilesRemovedSuccess": "{0} metadades eliminades en {1} arxius",
|
||||||
"ToastMustHaveAtLeastOnePath": "Ha de tenir almenys una ruta",
|
"ToastMustHaveAtLeastOnePath": "Ha de tenir almenys una ruta",
|
||||||
"ToastNameEmailRequired": "El nom i el correu electrònic són obligatoris",
|
"ToastNameEmailRequired": "El nom i el correu electrònic són obligatoris",
|
||||||
"ToastNameRequired": "Nom obligatori",
|
"ToastNameRequired": "Nom obligatori",
|
||||||
"ToastNewEpisodesFound": "{0} episodi(s) nou(s) trobat(s)",
|
"ToastNewEpisodesFound": "{0} episodi(s) nou(s) trobat(s)",
|
||||||
"ToastNewUserCreatedFailed": "Error en crear el compte: \"{0}\"",
|
"ToastNewUserCreatedFailed": "No s'ha pogut crear el compte: «{0}»",
|
||||||
"ToastNewUserCreatedSuccess": "Nou compte creat",
|
"ToastNewUserCreatedSuccess": "Nou compte creat",
|
||||||
"ToastNewUserLibraryError": "Ha de seleccionar almenys una biblioteca",
|
"ToastNewUserLibraryError": "S'ha de seleccionar almenys una biblioteca",
|
||||||
"ToastNewUserPasswordError": "Necessites una contrasenya, només el root pot estar sense contrasenya",
|
"ToastNewUserPasswordError": "Cal una contrasenya; només l'usuari primari pot estar sense contrasenya",
|
||||||
"ToastNewUserTagError": "Selecciona almenys una etiqueta",
|
"ToastNewUserTagError": "S'ha de seleccionar almenys una etiqueta",
|
||||||
"ToastNewUserUsernameError": "Introdueix un nom d'usuari",
|
"ToastNewUserUsernameError": "Introduïu un nom d'usuari",
|
||||||
"ToastNoNewEpisodesFound": "No s'han trobat nous episodis",
|
"ToastNoNewEpisodesFound": "No s'han trobat nous episodis",
|
||||||
|
"ToastNoRSSFeed": "El pòdcast no té canal RSS",
|
||||||
"ToastNoUpdatesNecessary": "No cal actualitzar",
|
"ToastNoUpdatesNecessary": "No cal actualitzar",
|
||||||
"ToastNotificationCreateFailed": "Error en crear la notificació",
|
"ToastNotificationCreateFailed": "No s'ha pogut crear la notificació",
|
||||||
"ToastNotificationDeleteFailed": "Error en eliminar la notificació",
|
"ToastNotificationDeleteFailed": "No s'ha pogut suprimir la notificació",
|
||||||
"ToastNotificationFailedMaximum": "El nombre màxim d'intents fallits ha de ser ≥ 0",
|
"ToastNotificationFailedMaximum": "El nombre màxim d'intents fallits ha de ser ≥ 0",
|
||||||
"ToastNotificationQueueMaximum": "La cua de notificació màxima ha de ser ≥ 0",
|
"ToastNotificationQueueMaximum": "La cua de notificació màxima ha de ser ≥ 0",
|
||||||
"ToastNotificationSettingsUpdateSuccess": "Configuració de notificació actualitzada",
|
"ToastNotificationSettingsUpdateSuccess": "S'han actualitzat els paràmetres de notificacions",
|
||||||
"ToastNotificationTestTriggerFailed": "No s'ha pogut activar la notificació de prova",
|
"ToastNotificationTestTriggerFailed": "No s'ha pogut activar la notificació de prova",
|
||||||
"ToastNotificationTestTriggerSuccess": "Notificació de prova activada",
|
"ToastNotificationTestTriggerSuccess": "Notificació de prova activada",
|
||||||
"ToastNotificationUpdateSuccess": "Notificació actualitzada",
|
"ToastNotificationUpdateSuccess": "Notificació actualitzada",
|
||||||
@@ -984,16 +1014,16 @@
|
|||||||
"ToastPlaylistUpdateSuccess": "Llista de reproducció actualitzada",
|
"ToastPlaylistUpdateSuccess": "Llista de reproducció actualitzada",
|
||||||
"ToastPodcastCreateFailed": "No s'ha pogut crear el pòdcast",
|
"ToastPodcastCreateFailed": "No s'ha pogut crear el pòdcast",
|
||||||
"ToastPodcastCreateSuccess": "S'ha creat el pòdcast correctament",
|
"ToastPodcastCreateSuccess": "S'ha creat el pòdcast correctament",
|
||||||
"ToastPodcastGetFeedFailed": "No s'ha pogut obtenir el podcast",
|
"ToastPodcastGetFeedFailed": "No s'ha pogut obtenir el canal del pòdcast",
|
||||||
"ToastPodcastNoEpisodesInFeed": "No s'han trobat episodis en el feed RSS",
|
"ToastPodcastNoEpisodesInFeed": "No s'ha trobat cap episodi al canal RSS",
|
||||||
"ToastPodcastNoRssFeed": "El podcast no té un feed RSS",
|
"ToastPodcastNoRssFeed": "El pòdcast no té un canal RSS",
|
||||||
"ToastProgressIsNotBeingSynced": "El progrés no s'està sincronitzant, reinicia la reproducció",
|
"ToastProgressIsNotBeingSynced": "El progrés no s'està sincronitzant, reinicia la reproducció",
|
||||||
"ToastProviderCreatedFailed": "Error en afegir el proveïdor",
|
"ToastProviderCreatedFailed": "Error en afegir el proveïdor",
|
||||||
"ToastProviderCreatedSuccess": "Nou proveïdor afegit",
|
"ToastProviderCreatedSuccess": "Nou proveïdor afegit",
|
||||||
"ToastProviderNameAndUrlRequired": "Nom i URL obligatoris",
|
"ToastProviderNameAndUrlRequired": "Nom i URL obligatoris",
|
||||||
"ToastProviderRemoveSuccess": "Proveïdor eliminat",
|
"ToastProviderRemoveSuccess": "Proveïdor eliminat",
|
||||||
"ToastRSSFeedCloseFailed": "Error en tancar el feed RSS",
|
"ToastRSSFeedCloseFailed": "No s'ha pogut tancar el canal RSS",
|
||||||
"ToastRSSFeedCloseSuccess": "Feed RSS tancat",
|
"ToastRSSFeedCloseSuccess": "Canal RSS tancat",
|
||||||
"ToastRemoveFailed": "Error en eliminar",
|
"ToastRemoveFailed": "Error en eliminar",
|
||||||
"ToastRemoveItemFromCollectionFailed": "Error en eliminar l'element de la col·lecció",
|
"ToastRemoveItemFromCollectionFailed": "Error en eliminar l'element de la col·lecció",
|
||||||
"ToastRemoveItemFromCollectionSuccess": "Element eliminat de la col·lecció",
|
"ToastRemoveItemFromCollectionSuccess": "Element eliminat de la col·lecció",
|
||||||
@@ -1007,7 +1037,8 @@
|
|||||||
"ToastScanFailed": "No s'ha pogut escanejar l'element de la biblioteca",
|
"ToastScanFailed": "No s'ha pogut escanejar l'element de la biblioteca",
|
||||||
"ToastSelectAtLeastOneUser": "Selecciona almenys un usuari",
|
"ToastSelectAtLeastOneUser": "Selecciona almenys un usuari",
|
||||||
"ToastSendEbookToDeviceFailed": "Error en enviar l'ebook al dispositiu",
|
"ToastSendEbookToDeviceFailed": "Error en enviar l'ebook al dispositiu",
|
||||||
"ToastSendEbookToDeviceSuccess": "Ebook enviat al dispositiu \"{0}\"",
|
"ToastSendEbookToDeviceSuccess": "El llibre electrònic s'ha enviat al dispositiu «{0}»",
|
||||||
|
"ToastSeriesSubmitFailedSameName": "No és possible afegir dues sèries amb el mateix nom",
|
||||||
"ToastSeriesUpdateFailed": "Error en actualitzar la sèrie",
|
"ToastSeriesUpdateFailed": "Error en actualitzar la sèrie",
|
||||||
"ToastSeriesUpdateSuccess": "Sèrie actualitzada",
|
"ToastSeriesUpdateSuccess": "Sèrie actualitzada",
|
||||||
"ToastServerSettingsUpdateSuccess": "Configuració del servidor actualitzada",
|
"ToastServerSettingsUpdateSuccess": "Configuració del servidor actualitzada",
|
||||||
@@ -1026,6 +1057,8 @@
|
|||||||
"ToastUnknownError": "Error desconegut",
|
"ToastUnknownError": "Error desconegut",
|
||||||
"ToastUnlinkOpenIdFailed": "Error en desvincular l'usuari d'OpenID",
|
"ToastUnlinkOpenIdFailed": "Error en desvincular l'usuari d'OpenID",
|
||||||
"ToastUnlinkOpenIdSuccess": "Usuari desvinculat d'OpenID",
|
"ToastUnlinkOpenIdSuccess": "Usuari desvinculat d'OpenID",
|
||||||
|
"ToastUploaderFilepathExistsError": "El camí del fitxer «{0}» ja existeix al servidor",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "L'element «{0}» usa un subdirectori del camí de pujada.",
|
||||||
"ToastUserDeleteFailed": "Error en eliminar l'usuari",
|
"ToastUserDeleteFailed": "Error en eliminar l'usuari",
|
||||||
"ToastUserDeleteSuccess": "Usuari eliminat",
|
"ToastUserDeleteSuccess": "Usuari eliminat",
|
||||||
"ToastUserPasswordChangeSuccess": "Contrasenya canviada correctament",
|
"ToastUserPasswordChangeSuccess": "Contrasenya canviada correctament",
|
||||||
|
|||||||
+39
-13
@@ -10,6 +10,8 @@
|
|||||||
"ButtonApplyChapters": "Aplikovat kapitoly",
|
"ButtonApplyChapters": "Aplikovat kapitoly",
|
||||||
"ButtonAuthors": "Autoři",
|
"ButtonAuthors": "Autoři",
|
||||||
"ButtonBack": "Zpět",
|
"ButtonBack": "Zpět",
|
||||||
|
"ButtonBatchEditPopulateFromExisting": "Vytvořit z existujících",
|
||||||
|
"ButtonBatchEditPopulateMapDetails": "Předvyplnit podrobnosti mapování",
|
||||||
"ButtonBrowseForFolder": "Vyhledat složku",
|
"ButtonBrowseForFolder": "Vyhledat složku",
|
||||||
"ButtonCancel": "Zrušit",
|
"ButtonCancel": "Zrušit",
|
||||||
"ButtonCancelEncode": "Zrušit kódování",
|
"ButtonCancelEncode": "Zrušit kódování",
|
||||||
@@ -145,14 +147,14 @@
|
|||||||
"HeaderItemFiles": "Soubory položek",
|
"HeaderItemFiles": "Soubory položek",
|
||||||
"HeaderItemMetadataUtils": "Nástroje metadat položek",
|
"HeaderItemMetadataUtils": "Nástroje metadat položek",
|
||||||
"HeaderLastListeningSession": "Poslední poslechová relace",
|
"HeaderLastListeningSession": "Poslední poslechová relace",
|
||||||
"HeaderLatestEpisodes": "Nejnovější epizody",
|
"HeaderLatestEpisodes": "Nové epizody",
|
||||||
"HeaderLibraries": "Knihovny",
|
"HeaderLibraries": "Knihovny",
|
||||||
"HeaderLibraryFiles": "Soubory knihovny",
|
"HeaderLibraryFiles": "Soubory knihovny",
|
||||||
"HeaderLibraryStats": "Statistiky knihovny",
|
"HeaderLibraryStats": "Statistiky knihovny",
|
||||||
"HeaderListeningSessions": "Poslechové relace",
|
"HeaderListeningSessions": "Poslechové relace",
|
||||||
"HeaderListeningStats": "Statistiky poslechu",
|
"HeaderListeningStats": "Statistiky poslechu",
|
||||||
"HeaderLogin": "Přihlásit",
|
"HeaderLogin": "Přihlásit",
|
||||||
"HeaderLogs": "Záznamy",
|
"HeaderLogs": "Logy",
|
||||||
"HeaderManageGenres": "Spravovat žánry",
|
"HeaderManageGenres": "Spravovat žánry",
|
||||||
"HeaderManageTags": "Spravovat štítky",
|
"HeaderManageTags": "Spravovat štítky",
|
||||||
"HeaderMapDetails": "Podrobnosti mapování",
|
"HeaderMapDetails": "Podrobnosti mapování",
|
||||||
@@ -175,6 +177,7 @@
|
|||||||
"HeaderPlaylist": "Seznam skladeb",
|
"HeaderPlaylist": "Seznam skladeb",
|
||||||
"HeaderPlaylistItems": "Položky seznamu přehrávání",
|
"HeaderPlaylistItems": "Položky seznamu přehrávání",
|
||||||
"HeaderPodcastsToAdd": "Podcasty k přidání",
|
"HeaderPodcastsToAdd": "Podcasty k přidání",
|
||||||
|
"HeaderPresets": "Předvolba",
|
||||||
"HeaderPreviewCover": "Náhled obálky",
|
"HeaderPreviewCover": "Náhled obálky",
|
||||||
"HeaderRSSFeedGeneral": "Podrobnosti o RSS",
|
"HeaderRSSFeedGeneral": "Podrobnosti o RSS",
|
||||||
"HeaderRSSFeedIsOpen": "Informační kanál RSS je otevřený",
|
"HeaderRSSFeedIsOpen": "Informační kanál RSS je otevřený",
|
||||||
@@ -227,6 +230,7 @@
|
|||||||
"LabelAddedDate": "Přidáno {0}",
|
"LabelAddedDate": "Přidáno {0}",
|
||||||
"LabelAdminUsersOnly": "Pouze administrátoři",
|
"LabelAdminUsersOnly": "Pouze administrátoři",
|
||||||
"LabelAll": "Vše",
|
"LabelAll": "Vše",
|
||||||
|
"LabelAllEpisodesDownloaded": "Všechny epizody staženy",
|
||||||
"LabelAllUsers": "Všichni uživatelé",
|
"LabelAllUsers": "Všichni uživatelé",
|
||||||
"LabelAllUsersExcludingGuests": "Všichni uživatelé kromě hostů",
|
"LabelAllUsersExcludingGuests": "Všichni uživatelé kromě hostů",
|
||||||
"LabelAllUsersIncludingGuests": "Všichni uživatelé včetně hostů",
|
"LabelAllUsersIncludingGuests": "Všichni uživatelé včetně hostů",
|
||||||
@@ -250,7 +254,7 @@
|
|||||||
"LabelBackToUser": "Zpět k uživateli",
|
"LabelBackToUser": "Zpět k uživateli",
|
||||||
"LabelBackupAudioFiles": "Zálohovat zvukové soubory",
|
"LabelBackupAudioFiles": "Zálohovat zvukové soubory",
|
||||||
"LabelBackupLocation": "Umístění zálohy",
|
"LabelBackupLocation": "Umístění zálohy",
|
||||||
"LabelBackupsEnableAutomaticBackups": "Povolit automatické zálohování",
|
"LabelBackupsEnableAutomaticBackups": "Automatické zálohování",
|
||||||
"LabelBackupsEnableAutomaticBackupsHelp": "Zálohy uložené v /metadata/backups",
|
"LabelBackupsEnableAutomaticBackupsHelp": "Zálohy uložené v /metadata/backups",
|
||||||
"LabelBackupsMaxBackupSize": "Maximální velikost zálohy (v GB) (0 bez omezení)",
|
"LabelBackupsMaxBackupSize": "Maximální velikost zálohy (v GB) (0 bez omezení)",
|
||||||
"LabelBackupsMaxBackupSizeHelp": "Ochrana proti chybné konfiguraci: Zálohování se nezdaří, pokud překročí nastavenou velikost.",
|
"LabelBackupsMaxBackupSizeHelp": "Ochrana proti chybné konfiguraci: Zálohování se nezdaří, pokud překročí nastavenou velikost.",
|
||||||
@@ -282,6 +286,7 @@
|
|||||||
"LabelContinueSeries": "Pokračovat v sérii",
|
"LabelContinueSeries": "Pokračovat v sérii",
|
||||||
"LabelCover": "Obálka",
|
"LabelCover": "Obálka",
|
||||||
"LabelCoverImageURL": "URL obrázku obálky",
|
"LabelCoverImageURL": "URL obrázku obálky",
|
||||||
|
"LabelCoverProvider": "Poskytovatel obálky",
|
||||||
"LabelCreatedAt": "Vytvořeno v",
|
"LabelCreatedAt": "Vytvořeno v",
|
||||||
"LabelCronExpression": "Výraz Cronu",
|
"LabelCronExpression": "Výraz Cronu",
|
||||||
"LabelCurrent": "Aktuální",
|
"LabelCurrent": "Aktuální",
|
||||||
@@ -341,11 +346,11 @@
|
|||||||
"LabelExample": "Příklad",
|
"LabelExample": "Příklad",
|
||||||
"LabelExpandSeries": "Rozbalit série",
|
"LabelExpandSeries": "Rozbalit série",
|
||||||
"LabelExpandSubSeries": "Rozbalit podsérie",
|
"LabelExpandSubSeries": "Rozbalit podsérie",
|
||||||
"LabelExplicit": "Explicitní",
|
"LabelExplicit": "Explicitně",
|
||||||
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
|
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
|
||||||
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
|
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
|
||||||
"LabelExportOPML": "Export OPML",
|
"LabelExportOPML": "Export OPML",
|
||||||
"LabelFeedURL": "URL zdroje",
|
"LabelFeedURL": "URL kanálu",
|
||||||
"LabelFetchingMetadata": "Získávání metadat",
|
"LabelFetchingMetadata": "Získávání metadat",
|
||||||
"LabelFile": "Soubor",
|
"LabelFile": "Soubor",
|
||||||
"LabelFileBirthtime": "Čas vzniku souboru",
|
"LabelFileBirthtime": "Čas vzniku souboru",
|
||||||
@@ -421,7 +426,7 @@
|
|||||||
"LabelLookForNewEpisodesAfterDate": "Hledat nové epizody po tomto datu",
|
"LabelLookForNewEpisodesAfterDate": "Hledat nové epizody po tomto datu",
|
||||||
"LabelLowestPriority": "Nejnižší priorita",
|
"LabelLowestPriority": "Nejnižší priorita",
|
||||||
"LabelMatchExistingUsersBy": "Přiřadit stávající uživatele podle",
|
"LabelMatchExistingUsersBy": "Přiřadit stávající uživatele podle",
|
||||||
"LabelMatchExistingUsersByDescription": "Slouží k propojení stávajících uživatelů. Po propojení budou uživatelé přiřazeni k jedinečnému ID od poskytovatele SSO.",
|
"LabelMatchExistingUsersByDescription": "Slouží k propojení stávajících uživatelů. Po propojení budou uživatelé přiřazeni k jedinečnému ID od poskytovatele SSO",
|
||||||
"LabelMaxEpisodesToDownload": "Maximální # epizod pro stažení. Použijte 0 pro bez omezení.",
|
"LabelMaxEpisodesToDownload": "Maximální # epizod pro stažení. Použijte 0 pro bez omezení.",
|
||||||
"LabelMaxEpisodesToDownloadPerCheck": "Maximální počet nových epizod ke stažení při jedné kontrole",
|
"LabelMaxEpisodesToDownloadPerCheck": "Maximální počet nových epizod ke stažení při jedné kontrole",
|
||||||
"LabelMaxEpisodesToKeep": "Maximální počet epizod k zachování",
|
"LabelMaxEpisodesToKeep": "Maximální počet epizod k zachování",
|
||||||
@@ -430,7 +435,7 @@
|
|||||||
"LabelMediaType": "Typ média",
|
"LabelMediaType": "Typ média",
|
||||||
"LabelMetaTag": "Metaznačka",
|
"LabelMetaTag": "Metaznačka",
|
||||||
"LabelMetaTags": "Metaznačky",
|
"LabelMetaTags": "Metaznačky",
|
||||||
"LabelMetadataOrderOfPrecedenceDescription": "Zdroje metadat s vyšší prioritou budou mít přednost před zdroji metadat s nižší prioritou.",
|
"LabelMetadataOrderOfPrecedenceDescription": "Zdroje metadat s vyšší prioritou budou mít přednost před zdroji metadat s nižší prioritou",
|
||||||
"LabelMetadataProvider": "Poskytovatel metadat",
|
"LabelMetadataProvider": "Poskytovatel metadat",
|
||||||
"LabelMinute": "Minuta",
|
"LabelMinute": "Minuta",
|
||||||
"LabelMinutes": "Minuty",
|
"LabelMinutes": "Minuty",
|
||||||
@@ -509,9 +514,9 @@
|
|||||||
"LabelPublishers": "Vydavatelé",
|
"LabelPublishers": "Vydavatelé",
|
||||||
"LabelRSSFeedCustomOwnerEmail": "Vlastní e-mail vlastníka",
|
"LabelRSSFeedCustomOwnerEmail": "Vlastní e-mail vlastníka",
|
||||||
"LabelRSSFeedCustomOwnerName": "Vlastní jméno vlastníka",
|
"LabelRSSFeedCustomOwnerName": "Vlastní jméno vlastníka",
|
||||||
"LabelRSSFeedOpen": "Otevření RSS kanálu",
|
"LabelRSSFeedOpen": "RSS kanál otevřen",
|
||||||
"LabelRSSFeedPreventIndexing": "Zabránit indexování",
|
"LabelRSSFeedPreventIndexing": "Zabránit indexování",
|
||||||
"LabelRSSFeedSlug": "RSS kanál Slug",
|
"LabelRSSFeedSlug": "Klíčové slovo kanálu RSS",
|
||||||
"LabelRSSFeedURL": "URL RSS kanálu",
|
"LabelRSSFeedURL": "URL RSS kanálu",
|
||||||
"LabelRandomly": "Náhodně",
|
"LabelRandomly": "Náhodně",
|
||||||
"LabelReAddSeriesToContinueListening": "Znovu přidat sérii k pokračování poslechu",
|
"LabelReAddSeriesToContinueListening": "Znovu přidat sérii k pokračování poslechu",
|
||||||
@@ -526,6 +531,7 @@
|
|||||||
"LabelReleaseDate": "Datum vydání",
|
"LabelReleaseDate": "Datum vydání",
|
||||||
"LabelRemoveAllMetadataAbs": "Odebrat všechny soubory metadata.abs",
|
"LabelRemoveAllMetadataAbs": "Odebrat všechny soubory metadata.abs",
|
||||||
"LabelRemoveAllMetadataJson": "Smazat všechny soubory metadata.json",
|
"LabelRemoveAllMetadataJson": "Smazat všechny soubory metadata.json",
|
||||||
|
"LabelRemoveAudibleBranding": "Odebrat úvod a závěr Audible z kapitol",
|
||||||
"LabelRemoveCover": "Odstranit obálku",
|
"LabelRemoveCover": "Odstranit obálku",
|
||||||
"LabelRemoveMetadataFile": "Odstranit soubory metadat ve složkách položek knihovny",
|
"LabelRemoveMetadataFile": "Odstranit soubory metadat ve složkách položek knihovny",
|
||||||
"LabelRemoveMetadataFileHelp": "Odstraníte všechny soubory metadata.json a metadata.abs ve svých složkách {0}.",
|
"LabelRemoveMetadataFileHelp": "Odstraníte všechny soubory metadata.json a metadata.abs ve svých složkách {0}.",
|
||||||
@@ -545,7 +551,7 @@
|
|||||||
"LabelSeries": "Série",
|
"LabelSeries": "Série",
|
||||||
"LabelSeriesName": "Název série",
|
"LabelSeriesName": "Název série",
|
||||||
"LabelSeriesProgress": "Průběh série",
|
"LabelSeriesProgress": "Průběh série",
|
||||||
"LabelServerLogLevel": "Úroveň protokolu serveru",
|
"LabelServerLogLevel": "Úroveň Logování serveru",
|
||||||
"LabelServerYearReview": "Přehled roku na serveru ({0})",
|
"LabelServerYearReview": "Přehled roku na serveru ({0})",
|
||||||
"LabelSetEbookAsPrimary": "Nastavit jako primární",
|
"LabelSetEbookAsPrimary": "Nastavit jako primární",
|
||||||
"LabelSetEbookAsSupplementary": "Nastavit jako doplňkové",
|
"LabelSetEbookAsSupplementary": "Nastavit jako doplňkové",
|
||||||
@@ -555,6 +561,8 @@
|
|||||||
"LabelSettingsBookshelfViewHelp": "Skeumorfní design s dřevěnými policemi",
|
"LabelSettingsBookshelfViewHelp": "Skeumorfní design s dřevěnými policemi",
|
||||||
"LabelSettingsChromecastSupport": "Podpora Chromecastu",
|
"LabelSettingsChromecastSupport": "Podpora Chromecastu",
|
||||||
"LabelSettingsDateFormat": "Formát data",
|
"LabelSettingsDateFormat": "Formát data",
|
||||||
|
"LabelSettingsEnableWatcher": "Automaticky skenovat změny v knihovnách",
|
||||||
|
"LabelSettingsEnableWatcherForLibrary": "Automaticky skenovat změny v knihovně",
|
||||||
"LabelSettingsEnableWatcherHelp": "Povoluje automatické přidávání/aktualizaci položek, když jsou zjištěny změny souborů. *Vyžaduje restart serveru",
|
"LabelSettingsEnableWatcherHelp": "Povoluje automatické přidávání/aktualizaci položek, když jsou zjištěny změny souborů. *Vyžaduje restart serveru",
|
||||||
"LabelSettingsEpubsAllowScriptedContent": "Povolení skriptovaného obsahu v epubu",
|
"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.",
|
"LabelSettingsEpubsAllowScriptedContentHelp": "Povolení spouštění skriptů v souborech epub. Doporučujeme toto nastavení vypnout, pokud nedůvěřujete zdroji souborů epub.",
|
||||||
@@ -598,6 +606,7 @@
|
|||||||
"LabelSlug": "URL název",
|
"LabelSlug": "URL název",
|
||||||
"LabelSortAscending": "Vzestupně",
|
"LabelSortAscending": "Vzestupně",
|
||||||
"LabelSortDescending": "Sestupně",
|
"LabelSortDescending": "Sestupně",
|
||||||
|
"LabelSortPubDate": "Seřadit podle datumu publikování",
|
||||||
"LabelStart": "Spustit",
|
"LabelStart": "Spustit",
|
||||||
"LabelStartTime": "Čas Spuštění",
|
"LabelStartTime": "Čas Spuštění",
|
||||||
"LabelStarted": "Spuštěno",
|
"LabelStarted": "Spuštěno",
|
||||||
@@ -698,10 +707,14 @@
|
|||||||
"LabelYourProgress": "Váš pokrok",
|
"LabelYourProgress": "Váš pokrok",
|
||||||
"MessageAddToPlayerQueue": "Přidat do fronty přehrávače",
|
"MessageAddToPlayerQueue": "Přidat do fronty přehrávače",
|
||||||
"MessageAppriseDescription": "Abyste mohli používat tuto funkci, musíte mít spuštěnou instanci <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> nebo API, které bude zpracovávat stejné požadavky. <br />Adresa URL API Apprise by měla být úplná URL cesta pro odeslání oznámení, např. pokud je vaše instance API obsluhována na adrese <code>http://192.168.1.1:8337</code> pak byste měli zadat <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "Abyste mohli používat tuto funkci, musíte mít spuštěnou instanci <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> nebo API, které bude zpracovávat stejné požadavky. <br />Adresa URL API Apprise by měla být úplná URL cesta pro odeslání oznámení, např. pokud je vaše instance API obsluhována na adrese <code>http://192.168.1.1:8337</code> pak byste měli zadat <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAsinCheck": "Ujistěte se, že používáte ASIN ze správného regionu Audible a ne z Amazonu.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Po uložení restartujte server, aby se změny OIDC použily.",
|
||||||
"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.",
|
"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.",
|
||||||
"MessageBackupsLocationEditNote": "Poznámka: Změna umístění záloh nepřesune ani nezmění existující zálohy",
|
"MessageBackupsLocationEditNote": "Poznámka: Změna umístění záloh nepřesune ani nezmění existující zálohy",
|
||||||
"MessageBackupsLocationNoEditNote": "Poznámka: Umístění záloh je nastavené z proměnných prostředí a nelze zde změnit.",
|
"MessageBackupsLocationNoEditNote": "Poznámka: Umístění záloh je nastavené z proměnných prostředí a nelze zde změnit.",
|
||||||
"MessageBackupsLocationPathEmpty": "Umístění záloh nemůže být prázdné",
|
"MessageBackupsLocationPathEmpty": "Umístění záloh nemůže být prázdné",
|
||||||
|
"MessageBatchEditPopulateMapDetailsAllHelp": "Předvyplnit vybraná pole datami ze všech položek. Pole s více hodnotami budou sloučena",
|
||||||
|
"MessageBatchEditPopulateMapDetailsItemHelp": "Předvyplnit povolená pole mapování daty z této položky",
|
||||||
"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.",
|
"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",
|
"MessageBookshelfNoCollections": "Ještě jste nevytvořili žádnou sbírku",
|
||||||
"MessageBookshelfNoCollectionsHelp": "Kolekce jsou veřejné. Mohou je zobrazit všichni uživatelé s přístupem do knihovny.",
|
"MessageBookshelfNoCollectionsHelp": "Kolekce jsou veřejné. Mohou je zobrazit všichni uživatelé s přístupem do knihovny.",
|
||||||
@@ -714,6 +727,7 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Neplatný čas začátku, musí být kratší než doba trvání audioknihy",
|
"MessageChapterErrorStartGteDuration": "Neplatný čas začátku, musí být kratší než doba trvání audioknihy",
|
||||||
"MessageChapterErrorStartLtPrev": "Neplatný čas začátku, musí být větší nebo roven času začátku předchozí kapitoly",
|
"MessageChapterErrorStartLtPrev": "Neplatný čas začátku, musí být větší nebo roven času začátku předchozí kapitoly",
|
||||||
"MessageChapterStartIsAfter": "Začátek kapitoly přesahuje konec audioknihy",
|
"MessageChapterStartIsAfter": "Začátek kapitoly přesahuje konec audioknihy",
|
||||||
|
"MessageChaptersNotFound": "Kapitoly nenalezeny",
|
||||||
"MessageCheckingCron": "Kontrola cronu...",
|
"MessageCheckingCron": "Kontrola cronu...",
|
||||||
"MessageConfirmCloseFeed": "Opravdu chcete zavřít tento kanál?",
|
"MessageConfirmCloseFeed": "Opravdu chcete zavřít tento kanál?",
|
||||||
"MessageConfirmDeleteBackup": "Opravdu chcete smazat zálohu pro {0}?",
|
"MessageConfirmDeleteBackup": "Opravdu chcete smazat zálohu pro {0}?",
|
||||||
@@ -743,6 +757,7 @@
|
|||||||
"MessageConfirmRemoveAuthor": "Opravdu chcete odstranit autora \"{0}\"?",
|
"MessageConfirmRemoveAuthor": "Opravdu chcete odstranit autora \"{0}\"?",
|
||||||
"MessageConfirmRemoveCollection": "Opravdu chcete odstranit kolekci \"{0}\"?",
|
"MessageConfirmRemoveCollection": "Opravdu chcete odstranit kolekci \"{0}\"?",
|
||||||
"MessageConfirmRemoveEpisode": "Opravdu chcete odstranit epizodu \"{0}\"?",
|
"MessageConfirmRemoveEpisode": "Opravdu chcete odstranit epizodu \"{0}\"?",
|
||||||
|
"MessageConfirmRemoveEpisodeNote": "Poznámka: Tím se zvukový soubor neodstraní, pokud nepřepnete volbu “Tvrdé odstranění souboru“",
|
||||||
"MessageConfirmRemoveEpisodes": "Opravdu chcete odstranit {0} epizody?",
|
"MessageConfirmRemoveEpisodes": "Opravdu chcete odstranit {0} epizody?",
|
||||||
"MessageConfirmRemoveListeningSessions": "Opravdu chcete odebrat {0} poslechových relací?",
|
"MessageConfirmRemoveListeningSessions": "Opravdu chcete odebrat {0} poslechových relací?",
|
||||||
"MessageConfirmRemoveMetadataFiles": "Jste si jisti, že chcete odstranit všechny metadata.{0} soubory ve složkách s položkami ve vaší knihovně?",
|
"MessageConfirmRemoveMetadataFiles": "Jste si jisti, že chcete odstranit všechny metadata.{0} soubory ve složkách s položkami ve vaší knihovně?",
|
||||||
@@ -770,12 +785,13 @@
|
|||||||
"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é.",
|
"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é.",
|
||||||
"MessageImportantNotice": "Důležité upozornění!",
|
"MessageImportantNotice": "Důležité upozornění!",
|
||||||
"MessageInsertChapterBelow": "Vložit kapitolu níže",
|
"MessageInsertChapterBelow": "Vložit kapitolu níže",
|
||||||
|
"MessageInvalidAsin": "Neplatný ASIN",
|
||||||
"MessageItemsSelected": "{0} vybraných položek",
|
"MessageItemsSelected": "{0} vybraných položek",
|
||||||
"MessageItemsUpdated": "{0} položky byly aktualizovány",
|
"MessageItemsUpdated": "{0} položky byly aktualizovány",
|
||||||
"MessageJoinUsOn": "Přidejte se k nám",
|
"MessageJoinUsOn": "Přidejte se k nám",
|
||||||
"MessageLoading": "Načítá se...",
|
"MessageLoading": "Načítá se...",
|
||||||
"MessageLoadingFolders": "Načítám složky...",
|
"MessageLoadingFolders": "Načítám složky...",
|
||||||
"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>.",
|
"MessageLogsDescription": "Logy se ukládají do souborů JSON v <code>/metadata/logs</code>. Logy o pádech jsou uloženy v <code>/metadata/logs/crash_logs.txt</code>.",
|
||||||
"MessageM4BFailed": "M4B se nezdařil!",
|
"MessageM4BFailed": "M4B se nezdařil!",
|
||||||
"MessageM4BFinished": "M4B dokončen!",
|
"MessageM4BFinished": "M4B dokončen!",
|
||||||
"MessageMapChapterTitles": "Mapování názvů kapitol ke stávajícím kapitolám audioknihy bez úpravy časových razítek",
|
"MessageMapChapterTitles": "Mapování názvů kapitol ke stávajícím kapitolám audioknihy bez úpravy časových razítek",
|
||||||
@@ -799,11 +815,11 @@
|
|||||||
"MessageNoEpisodes": "Žádné epizody",
|
"MessageNoEpisodes": "Žádné epizody",
|
||||||
"MessageNoFoldersAvailable": "Nejsou k dispozici žádné složky",
|
"MessageNoFoldersAvailable": "Nejsou k dispozici žádné složky",
|
||||||
"MessageNoGenres": "Žádné žánry",
|
"MessageNoGenres": "Žádné žánry",
|
||||||
"MessageNoIssues": "Žádné výtisk",
|
"MessageNoIssues": "Žádné problémy",
|
||||||
"MessageNoItems": "Žádné položky",
|
"MessageNoItems": "Žádné položky",
|
||||||
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
|
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
|
||||||
"MessageNoListeningSessions": "Žádné poslechové relace",
|
"MessageNoListeningSessions": "Žádné poslechové relace",
|
||||||
"MessageNoLogs": "Žádné protokoly",
|
"MessageNoLogs": "Žádné logy",
|
||||||
"MessageNoMediaProgress": "Žádný průběh médií",
|
"MessageNoMediaProgress": "Žádný průběh médií",
|
||||||
"MessageNoNotifications": "Žádná oznámení",
|
"MessageNoNotifications": "Žádná oznámení",
|
||||||
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
|
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
|
||||||
@@ -838,8 +854,10 @@
|
|||||||
"MessageRestoreBackupConfirm": "Opravdu chcete obnovit zálohu vytvořenou dne",
|
"MessageRestoreBackupConfirm": "Opravdu chcete obnovit zálohu vytvořenou dne",
|
||||||
"MessageRestoreBackupWarning": "Obnovení zálohy přepíše celou databázi umístěnou v /config a obálku obrázků v /metadata/items & /metadata/authors.<br /><br />Backups nezmění žádné soubory ve složkách knihovny. Pokud jste povolili nastavení serveru pro ukládání obrázků obalu a metadat do složek knihovny, nebudou zálohovány ani přepsány.<br /><br />Všichni klienti používající váš server budou automaticky obnoveni.",
|
"MessageRestoreBackupWarning": "Obnovení zálohy přepíše celou databázi umístěnou v /config a obálku obrázků v /metadata/items & /metadata/authors.<br /><br />Backups nezmění žádné soubory ve složkách knihovny. Pokud jste povolili nastavení serveru pro ukládání obrázků obalu a metadat do složek knihovny, nebudou zálohovány ani přepsány.<br /><br />Všichni klienti používající váš server budou automaticky obnoveni.",
|
||||||
"MessageScheduleLibraryScanNote": "Většině uživatelů se doporučuje ponechat tuto funkci vypnutou a ponechat zapnuté nastavení sledování složek. Sledování složek automaticky zjistí změny ve složkách vaší knihovny. Sledování složek nefunguje pro každý souborový systém (jako je NFS), takže místo toho lze použít plánované skenování knihoven.",
|
"MessageScheduleLibraryScanNote": "Většině uživatelů se doporučuje ponechat tuto funkci vypnutou a ponechat zapnuté nastavení sledování složek. Sledování složek automaticky zjistí změny ve složkách vaší knihovny. Sledování složek nefunguje pro každý souborový systém (jako je NFS), takže místo toho lze použít plánované skenování knihoven.",
|
||||||
|
"MessageScheduleRunEveryWeekdayAtTime": "Spusť každý {0} v {1}",
|
||||||
"MessageSearchResultsFor": "Výsledky hledání pro",
|
"MessageSearchResultsFor": "Výsledky hledání pro",
|
||||||
"MessageSelected": "{0} vybráno",
|
"MessageSelected": "{0} vybráno",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "Sekvence série nesmí obsahovat mezery",
|
||||||
"MessageServerCouldNotBeReached": "Server je nedostupný",
|
"MessageServerCouldNotBeReached": "Server je nedostupný",
|
||||||
"MessageSetChaptersFromTracksDescription": "Nastavit kapitoly jako kapitolu a název kapitoly jako název zvukového souboru",
|
"MessageSetChaptersFromTracksDescription": "Nastavit kapitoly jako kapitolu a název kapitoly jako název zvukového souboru",
|
||||||
"MessageShareExpirationWillBe": "Expiruje <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "Expiruje <strong>{0}</strong>",
|
||||||
@@ -901,6 +919,8 @@
|
|||||||
"NotificationOnBackupCompletedDescription": "Spuštěno po dokončení zálohování",
|
"NotificationOnBackupCompletedDescription": "Spuštěno po dokončení zálohování",
|
||||||
"NotificationOnBackupFailedDescription": "Spuštěno pokud zálohování selže",
|
"NotificationOnBackupFailedDescription": "Spuštěno pokud zálohování selže",
|
||||||
"NotificationOnEpisodeDownloadedDescription": "Spuštěno při automatickém stažení epizody podcastu",
|
"NotificationOnEpisodeDownloadedDescription": "Spuštěno při automatickém stažení epizody podcastu",
|
||||||
|
"NotificationOnRSSFeedDisabledDescription": "Aktivováno když je automatické stahování pozastaveno z důvodu příliš mnoho neůspěšných pokusů",
|
||||||
|
"NotificationOnRSSFeedFailedDescription": "Aktivováno když selže RSS kanál pro stahování epizod",
|
||||||
"NotificationOnTestDescription": "Akce pro otestování upozorňovacího systému",
|
"NotificationOnTestDescription": "Akce pro otestování upozorňovacího systému",
|
||||||
"PlaceholderNewCollection": "Nový název kolekce",
|
"PlaceholderNewCollection": "Nový název kolekce",
|
||||||
"PlaceholderNewFolderPath": "Nová cesta ke složce",
|
"PlaceholderNewFolderPath": "Nová cesta ke složce",
|
||||||
@@ -945,6 +965,7 @@
|
|||||||
"ToastBackupRestoreFailed": "Nepodařilo se obnovit zálohu",
|
"ToastBackupRestoreFailed": "Nepodařilo se obnovit zálohu",
|
||||||
"ToastBackupUploadFailed": "Nepodařilo se nahrát zálohu",
|
"ToastBackupUploadFailed": "Nepodařilo se nahrát zálohu",
|
||||||
"ToastBackupUploadSuccess": "Záloha nahrána",
|
"ToastBackupUploadSuccess": "Záloha nahrána",
|
||||||
|
"ToastBatchApplyDetailsToItemsSuccess": "Detaily byly aplikované na položky",
|
||||||
"ToastBatchDeleteFailed": "Hromadné smazání selhalo",
|
"ToastBatchDeleteFailed": "Hromadné smazání selhalo",
|
||||||
"ToastBatchDeleteSuccess": "Hromadné smazání proběhlo úspěšně",
|
"ToastBatchDeleteSuccess": "Hromadné smazání proběhlo úspěšně",
|
||||||
"ToastBatchQuickMatchFailed": "Rychlá schoda dávky se nezdařila!",
|
"ToastBatchQuickMatchFailed": "Rychlá schoda dávky se nezdařila!",
|
||||||
@@ -957,6 +978,8 @@
|
|||||||
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
|
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
|
||||||
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
|
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
|
||||||
"ToastChaptersHaveErrors": "Kapitoly obsahují chyby",
|
"ToastChaptersHaveErrors": "Kapitoly obsahují chyby",
|
||||||
|
"ToastChaptersInvalidShiftAmountLast": "Nesprávná délka posunu. Čas začátku poslední kapitoly by přesáhl dobu trvání této audioknihy.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "Nesprávná délka posunu. První kapitola by měla nulovou nebo zápornou délku a byla by přepsána druhou kapitolou. Zvětšete čas začátku druhé kapitoly.",
|
||||||
"ToastChaptersMustHaveTitles": "Kapitoly musí mít názvy",
|
"ToastChaptersMustHaveTitles": "Kapitoly musí mít názvy",
|
||||||
"ToastChaptersRemoved": "Kapitoly odstraněny",
|
"ToastChaptersRemoved": "Kapitoly odstraněny",
|
||||||
"ToastChaptersUpdated": "Kapitola aktualizována",
|
"ToastChaptersUpdated": "Kapitola aktualizována",
|
||||||
@@ -1057,6 +1080,7 @@
|
|||||||
"ToastSelectAtLeastOneUser": "Vyberte alespoň jednoho uživatele",
|
"ToastSelectAtLeastOneUser": "Vyberte alespoň jednoho uživatele",
|
||||||
"ToastSendEbookToDeviceFailed": "Odeslání e-knihy do zařízení se nezdařilo",
|
"ToastSendEbookToDeviceFailed": "Odeslání e-knihy do zařízení se nezdařilo",
|
||||||
"ToastSendEbookToDeviceSuccess": "E-kniha odeslána do zařízení \"{0}\"",
|
"ToastSendEbookToDeviceSuccess": "E-kniha odeslána do zařízení \"{0}\"",
|
||||||
|
"ToastSeriesSubmitFailedSameName": "Nelze přidat dvě série se stejným názvem",
|
||||||
"ToastSeriesUpdateFailed": "Aktualizace série se nezdařila",
|
"ToastSeriesUpdateFailed": "Aktualizace série se nezdařila",
|
||||||
"ToastSeriesUpdateSuccess": "Aktualizace série byla úspěšná",
|
"ToastSeriesUpdateSuccess": "Aktualizace série byla úspěšná",
|
||||||
"ToastServerSettingsUpdateSuccess": "Nastavení serveru aktualizováno",
|
"ToastServerSettingsUpdateSuccess": "Nastavení serveru aktualizováno",
|
||||||
@@ -1075,6 +1099,8 @@
|
|||||||
"ToastUnknownError": "Neznámý error",
|
"ToastUnknownError": "Neznámý error",
|
||||||
"ToastUnlinkOpenIdFailed": "Chyba při odpárování uživatele z OpenID",
|
"ToastUnlinkOpenIdFailed": "Chyba při odpárování uživatele z OpenID",
|
||||||
"ToastUnlinkOpenIdSuccess": "Uživatel odpárován z uživatele z OpenID",
|
"ToastUnlinkOpenIdSuccess": "Uživatel odpárován z uživatele z OpenID",
|
||||||
|
"ToastUploaderFilepathExistsError": "Soubor \"{0}\" na serveru již existuje",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "Položka \"{0}\" používá podadresář cesty pro nahrání.",
|
||||||
"ToastUserDeleteFailed": "Nepodařilo se smazat uživatele",
|
"ToastUserDeleteFailed": "Nepodařilo se smazat uživatele",
|
||||||
"ToastUserDeleteSuccess": "Uživatel smazán",
|
"ToastUserDeleteSuccess": "Uživatel smazán",
|
||||||
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",
|
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",
|
||||||
|
|||||||
+19
-2
@@ -177,6 +177,7 @@
|
|||||||
"HeaderPlaylist": "Afspilningsliste",
|
"HeaderPlaylist": "Afspilningsliste",
|
||||||
"HeaderPlaylistItems": "Afspilningsliste Elementer",
|
"HeaderPlaylistItems": "Afspilningsliste Elementer",
|
||||||
"HeaderPodcastsToAdd": "Podcasts til Tilføjelse",
|
"HeaderPodcastsToAdd": "Podcasts til Tilføjelse",
|
||||||
|
"HeaderPresets": "Forudindstillinger",
|
||||||
"HeaderPreviewCover": "Forhåndsvis Omslag",
|
"HeaderPreviewCover": "Forhåndsvis Omslag",
|
||||||
"HeaderRSSFeedGeneral": "RSS Detaljer",
|
"HeaderRSSFeedGeneral": "RSS Detaljer",
|
||||||
"HeaderRSSFeedIsOpen": "RSS Feed er Åben",
|
"HeaderRSSFeedIsOpen": "RSS Feed er Åben",
|
||||||
@@ -229,6 +230,7 @@
|
|||||||
"LabelAddedDate": "Tilføjet {0}",
|
"LabelAddedDate": "Tilføjet {0}",
|
||||||
"LabelAdminUsersOnly": "Kun Administratorer",
|
"LabelAdminUsersOnly": "Kun Administratorer",
|
||||||
"LabelAll": "Alle",
|
"LabelAll": "Alle",
|
||||||
|
"LabelAllEpisodesDownloaded": "Alle episoder hentet",
|
||||||
"LabelAllUsers": "Alle Brugere",
|
"LabelAllUsers": "Alle Brugere",
|
||||||
"LabelAllUsersExcludingGuests": "Alle bruger eksklusiv gæster",
|
"LabelAllUsersExcludingGuests": "Alle bruger eksklusiv gæster",
|
||||||
"LabelAllUsersIncludingGuests": "Alle bruger inklusiv gæster",
|
"LabelAllUsersIncludingGuests": "Alle bruger inklusiv gæster",
|
||||||
@@ -252,7 +254,7 @@
|
|||||||
"LabelBackToUser": "Tilbage til Bruger",
|
"LabelBackToUser": "Tilbage til Bruger",
|
||||||
"LabelBackupAudioFiles": "Sikkerhedskopier lydfiler",
|
"LabelBackupAudioFiles": "Sikkerhedskopier lydfiler",
|
||||||
"LabelBackupLocation": "Backup Placering",
|
"LabelBackupLocation": "Backup Placering",
|
||||||
"LabelBackupsEnableAutomaticBackups": "Aktivér automatisk sikkerhedskopiering",
|
"LabelBackupsEnableAutomaticBackups": "Automatisk sikkerhedskopiering",
|
||||||
"LabelBackupsEnableAutomaticBackupsHelp": "Sikkerhedskopier gemt i /metadata/backups",
|
"LabelBackupsEnableAutomaticBackupsHelp": "Sikkerhedskopier gemt i /metadata/backups",
|
||||||
"LabelBackupsMaxBackupSize": "Maksimal sikkerhedskopistørrelse (i GB) (0 for ubegrænset)",
|
"LabelBackupsMaxBackupSize": "Maksimal sikkerhedskopistørrelse (i GB) (0 for ubegrænset)",
|
||||||
"LabelBackupsMaxBackupSizeHelp": "Som en beskyttelse mod fejlkonfiguration fejler sikkerhedskopier, hvis de overstiger den konfigurerede størrelse.",
|
"LabelBackupsMaxBackupSizeHelp": "Som en beskyttelse mod fejlkonfiguration fejler sikkerhedskopier, hvis de overstiger den konfigurerede størrelse.",
|
||||||
@@ -512,7 +514,7 @@
|
|||||||
"LabelPublishers": "Forlag",
|
"LabelPublishers": "Forlag",
|
||||||
"LabelRSSFeedCustomOwnerEmail": "Brugerdefineret ejerens e-mail",
|
"LabelRSSFeedCustomOwnerEmail": "Brugerdefineret ejerens e-mail",
|
||||||
"LabelRSSFeedCustomOwnerName": "Brugerdefineret ejerens navn",
|
"LabelRSSFeedCustomOwnerName": "Brugerdefineret ejerens navn",
|
||||||
"LabelRSSFeedOpen": "Åben RSS-feed",
|
"LabelRSSFeedOpen": "RSS-feed åbent",
|
||||||
"LabelRSSFeedPreventIndexing": "Forhindrer indeksering",
|
"LabelRSSFeedPreventIndexing": "Forhindrer indeksering",
|
||||||
"LabelRSSFeedSlug": "RSS-feed-slug",
|
"LabelRSSFeedSlug": "RSS-feed-slug",
|
||||||
"LabelRSSFeedURL": "RSS-feed-URL",
|
"LabelRSSFeedURL": "RSS-feed-URL",
|
||||||
@@ -529,6 +531,7 @@
|
|||||||
"LabelReleaseDate": "Udgivelsesdato",
|
"LabelReleaseDate": "Udgivelsesdato",
|
||||||
"LabelRemoveAllMetadataAbs": "Fjern alle metadata.abs filer",
|
"LabelRemoveAllMetadataAbs": "Fjern alle metadata.abs filer",
|
||||||
"LabelRemoveAllMetadataJson": "Fjern alle metadata.json filer",
|
"LabelRemoveAllMetadataJson": "Fjern alle metadata.json filer",
|
||||||
|
"LabelRemoveAudibleBranding": "Fjern Audible intro og outro fra kapitler",
|
||||||
"LabelRemoveCover": "Fjern omslag",
|
"LabelRemoveCover": "Fjern omslag",
|
||||||
"LabelRemoveMetadataFile": "Fjern alle metadata filer i biblioteksmapper",
|
"LabelRemoveMetadataFile": "Fjern alle metadata filer i biblioteksmapper",
|
||||||
"LabelRemoveMetadataFileHelp": "Fjern alle metadata.json og metadata.abs filer i dine {0} mapper.",
|
"LabelRemoveMetadataFileHelp": "Fjern alle metadata.json og metadata.abs filer i dine {0} mapper.",
|
||||||
@@ -558,6 +561,8 @@
|
|||||||
"LabelSettingsBookshelfViewHelp": "Skeumorfisk design med træhylder",
|
"LabelSettingsBookshelfViewHelp": "Skeumorfisk design med træhylder",
|
||||||
"LabelSettingsChromecastSupport": "Chromecast-understøttelse",
|
"LabelSettingsChromecastSupport": "Chromecast-understøttelse",
|
||||||
"LabelSettingsDateFormat": "Datoformat",
|
"LabelSettingsDateFormat": "Datoformat",
|
||||||
|
"LabelSettingsEnableWatcher": "Scan automatisk bibliotek for ændringer",
|
||||||
|
"LabelSettingsEnableWatcherForLibrary": "Scan automatisk bibliotek for ændringer",
|
||||||
"LabelSettingsEnableWatcherHelp": "Aktiverer automatisk tilføjelse/opdatering af elementer, når filændringer registreres. *Kræver servergenstart",
|
"LabelSettingsEnableWatcherHelp": "Aktiverer automatisk tilføjelse/opdatering af elementer, når filændringer registreres. *Kræver servergenstart",
|
||||||
"LabelSettingsEpubsAllowScriptedContent": "Tillad scriptet indhold i epub",
|
"LabelSettingsEpubsAllowScriptedContent": "Tillad scriptet indhold i epub",
|
||||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Tillad epub filer at køre scripts. Det anbefales at holde denne indstilling deaktiveret med mindre du stoler på kilderne af epub filerne.",
|
"LabelSettingsEpubsAllowScriptedContentHelp": "Tillad epub filer at køre scripts. Det anbefales at holde denne indstilling deaktiveret med mindre du stoler på kilderne af epub filerne.",
|
||||||
@@ -601,6 +606,7 @@
|
|||||||
"LabelSlug": "Snegl",
|
"LabelSlug": "Snegl",
|
||||||
"LabelSortAscending": "Stigende",
|
"LabelSortAscending": "Stigende",
|
||||||
"LabelSortDescending": "Faldende",
|
"LabelSortDescending": "Faldende",
|
||||||
|
"LabelSortPubDate": "Sortér Pub Dato",
|
||||||
"LabelStart": "Start",
|
"LabelStart": "Start",
|
||||||
"LabelStartTime": "Starttid",
|
"LabelStartTime": "Starttid",
|
||||||
"LabelStarted": "Startet",
|
"LabelStarted": "Startet",
|
||||||
@@ -701,6 +707,8 @@
|
|||||||
"LabelYourProgress": "Din fremgang",
|
"LabelYourProgress": "Din fremgang",
|
||||||
"MessageAddToPlayerQueue": "Tilføj til afspilningskø",
|
"MessageAddToPlayerQueue": "Tilføj til afspilningskø",
|
||||||
"MessageAppriseDescription": "For at bruge denne funktion skal du have en instans af <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> kørende eller en API, der håndterer de samme anmodninger. <br /> Apprise API-webadressen skal være den fulde URL-sti for at sende underretningen, f.eks. hvis din API-instans er tilgængelig på <code>http://192.168.1.1:8337</code>, så skal du bruge <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "For at bruge denne funktion skal du have en instans af <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> kørende eller en API, der håndterer de samme anmodninger. <br /> Apprise API-webadressen skal være den fulde URL-sti for at sende underretningen, f.eks. hvis din API-instans er tilgængelig på <code>http://192.168.1.1:8337</code>, så skal du bruge <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAsinCheck": "Sikr dig at du bruger ASIN fra den korrekte Audible region, ikke Amazon.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Genstart sin server efter du har gemt for at bekræfte OIDC ændringer.",
|
||||||
"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.",
|
"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.",
|
||||||
"MessageBackupsLocationEditNote": "Note: Opdatering af backup sti vil ikke fjerne eller modificere eksisterende backups",
|
"MessageBackupsLocationEditNote": "Note: Opdatering af backup sti vil ikke fjerne eller modificere eksisterende backups",
|
||||||
"MessageBackupsLocationNoEditNote": "Note: Backup sti er sat igennem miljøvariabel og kan ikke ændres her.",
|
"MessageBackupsLocationNoEditNote": "Note: Backup sti er sat igennem miljøvariabel og kan ikke ændres her.",
|
||||||
@@ -719,6 +727,7 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Ugyldig starttid skal være mindre end lydbogens varighed",
|
"MessageChapterErrorStartGteDuration": "Ugyldig starttid skal være mindre end lydbogens varighed",
|
||||||
"MessageChapterErrorStartLtPrev": "Ugyldig starttid skal være større end eller lig med den foregående kapitels starttid",
|
"MessageChapterErrorStartLtPrev": "Ugyldig starttid skal være større end eller lig med den foregående kapitels starttid",
|
||||||
"MessageChapterStartIsAfter": "Kapitelstarten er efter slutningen af din lydbog",
|
"MessageChapterStartIsAfter": "Kapitelstarten er efter slutningen af din lydbog",
|
||||||
|
"MessageChaptersNotFound": "Kapitler ikke fundet",
|
||||||
"MessageCheckingCron": "Tjekker cron...",
|
"MessageCheckingCron": "Tjekker cron...",
|
||||||
"MessageConfirmCloseFeed": "Er du sikker på, at du vil lukke dette feed?",
|
"MessageConfirmCloseFeed": "Er du sikker på, at du vil lukke dette feed?",
|
||||||
"MessageConfirmDeleteBackup": "Er du sikker på, at du vil slette backup for {0}?",
|
"MessageConfirmDeleteBackup": "Er du sikker på, at du vil slette backup for {0}?",
|
||||||
@@ -775,6 +784,7 @@
|
|||||||
"MessageForceReScanDescription": "vil scanne alle filer igen som en frisk scanning. Lydfilens ID3-tags, OPF-filer og tekstfiler scannes som nye.",
|
"MessageForceReScanDescription": "vil scanne alle filer igen som en frisk scanning. Lydfilens ID3-tags, OPF-filer og tekstfiler scannes som nye.",
|
||||||
"MessageImportantNotice": "Vigtig besked!",
|
"MessageImportantNotice": "Vigtig besked!",
|
||||||
"MessageInsertChapterBelow": "Indsæt kapitel nedenfor",
|
"MessageInsertChapterBelow": "Indsæt kapitel nedenfor",
|
||||||
|
"MessageInvalidAsin": "Ugyldig ASIN",
|
||||||
"MessageItemsSelected": "{0} elementer valgt",
|
"MessageItemsSelected": "{0} elementer valgt",
|
||||||
"MessageItemsUpdated": "{0} elementer opdateret",
|
"MessageItemsUpdated": "{0} elementer opdateret",
|
||||||
"MessageJoinUsOn": "Deltag i os på",
|
"MessageJoinUsOn": "Deltag i os på",
|
||||||
@@ -846,6 +856,7 @@
|
|||||||
"MessageScheduleRunEveryWeekdayAtTime": "Kør hvert {0} af {1}",
|
"MessageScheduleRunEveryWeekdayAtTime": "Kør hvert {0} af {1}",
|
||||||
"MessageSearchResultsFor": "Søgeresultater for",
|
"MessageSearchResultsFor": "Søgeresultater for",
|
||||||
"MessageSelected": "{0} valgt",
|
"MessageSelected": "{0} valgt",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "Serie sekvens kan ikke indeholde mellemrum",
|
||||||
"MessageServerCouldNotBeReached": "Serveren kunne ikke nås",
|
"MessageServerCouldNotBeReached": "Serveren kunne ikke nås",
|
||||||
"MessageSetChaptersFromTracksDescription": "Indstil kapitler ved at bruge hver lydfil som et kapitel og kapiteloverskrift som lydfilnavn",
|
"MessageSetChaptersFromTracksDescription": "Indstil kapitler ved at bruge hver lydfil som et kapitel og kapiteloverskrift som lydfilnavn",
|
||||||
"MessageShareExpirationWillBe": "Udløb vil være <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "Udløb vil være <strong>{0}</strong>",
|
||||||
@@ -907,6 +918,8 @@
|
|||||||
"NotificationOnBackupCompletedDescription": "Udløst når backup er færdig",
|
"NotificationOnBackupCompletedDescription": "Udløst når backup er færdig",
|
||||||
"NotificationOnBackupFailedDescription": "Udløst når backup fejler",
|
"NotificationOnBackupFailedDescription": "Udløst når backup fejler",
|
||||||
"NotificationOnEpisodeDownloadedDescription": "Udløst når et podcast afsnit er automatisk downloadet",
|
"NotificationOnEpisodeDownloadedDescription": "Udløst når et podcast afsnit er automatisk downloadet",
|
||||||
|
"NotificationOnRSSFeedDisabledDescription": "Aktiveret når automatiske episode-downloads er slået fra, på grund af for mange forsøg",
|
||||||
|
"NotificationOnRSSFeedFailedDescription": "Aktiveret når anmodning om RSS-feedet fejler for en automatisk episode-download",
|
||||||
"NotificationOnTestDescription": "Event for test af notifikationssystemet",
|
"NotificationOnTestDescription": "Event for test af notifikationssystemet",
|
||||||
"PlaceholderNewCollection": "Nyt samlingnavn",
|
"PlaceholderNewCollection": "Nyt samlingnavn",
|
||||||
"PlaceholderNewFolderPath": "Ny mappes sti",
|
"PlaceholderNewFolderPath": "Ny mappes sti",
|
||||||
@@ -951,6 +964,7 @@
|
|||||||
"ToastBackupRestoreFailed": "Mislykkedes gendannelse af sikkerhedskopi",
|
"ToastBackupRestoreFailed": "Mislykkedes gendannelse af sikkerhedskopi",
|
||||||
"ToastBackupUploadFailed": "Mislykkedes upload af sikkerhedskopi",
|
"ToastBackupUploadFailed": "Mislykkedes upload af sikkerhedskopi",
|
||||||
"ToastBackupUploadSuccess": "Sikkerhedskopi uploadet",
|
"ToastBackupUploadSuccess": "Sikkerhedskopi uploadet",
|
||||||
|
"ToastBatchApplyDetailsToItemsSuccess": "Detaljer bekræftet på element",
|
||||||
"ToastBatchDeleteFailed": "Batch slet fejlede",
|
"ToastBatchDeleteFailed": "Batch slet fejlede",
|
||||||
"ToastBatchDeleteSuccess": "Batch slet succes",
|
"ToastBatchDeleteSuccess": "Batch slet succes",
|
||||||
"ToastBatchQuickMatchFailed": "Batch Hurtig Match fejlede!",
|
"ToastBatchQuickMatchFailed": "Batch Hurtig Match fejlede!",
|
||||||
@@ -1063,6 +1077,7 @@
|
|||||||
"ToastSelectAtLeastOneUser": "Vælg mindst en bruger",
|
"ToastSelectAtLeastOneUser": "Vælg mindst en bruger",
|
||||||
"ToastSendEbookToDeviceFailed": "Mislykkedes afsendelse af e-bog til enhed",
|
"ToastSendEbookToDeviceFailed": "Mislykkedes afsendelse af e-bog til enhed",
|
||||||
"ToastSendEbookToDeviceSuccess": "E-bog afsendt til enhed \"{0}\"",
|
"ToastSendEbookToDeviceSuccess": "E-bog afsendt til enhed \"{0}\"",
|
||||||
|
"ToastSeriesSubmitFailedSameName": "Kan ikke tilføje to serier med samme navn",
|
||||||
"ToastSeriesUpdateFailed": "Mislykkedes opdatering af serie",
|
"ToastSeriesUpdateFailed": "Mislykkedes opdatering af serie",
|
||||||
"ToastSeriesUpdateSuccess": "Serieopdatering lykkedes",
|
"ToastSeriesUpdateSuccess": "Serieopdatering lykkedes",
|
||||||
"ToastServerSettingsUpdateSuccess": "Server indstillinger opdateret",
|
"ToastServerSettingsUpdateSuccess": "Server indstillinger opdateret",
|
||||||
@@ -1081,6 +1096,8 @@
|
|||||||
"ToastUnknownError": "Ukendt fejl",
|
"ToastUnknownError": "Ukendt fejl",
|
||||||
"ToastUnlinkOpenIdFailed": "Fejlede i af afkoble bruger fra OpenID",
|
"ToastUnlinkOpenIdFailed": "Fejlede i af afkoble bruger fra OpenID",
|
||||||
"ToastUnlinkOpenIdSuccess": "Bruger afkoblet fra OpenID",
|
"ToastUnlinkOpenIdSuccess": "Bruger afkoblet fra OpenID",
|
||||||
|
"ToastUploaderFilepathExistsError": "Filsti \"{0}\" findes allerede på serveren",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "Genstand \"{0}\" benytter en undermappe af upload stien",
|
||||||
"ToastUserDeleteFailed": "Mislykkedes sletning af bruger",
|
"ToastUserDeleteFailed": "Mislykkedes sletning af bruger",
|
||||||
"ToastUserDeleteSuccess": "Bruger slettet",
|
"ToastUserDeleteSuccess": "Bruger slettet",
|
||||||
"ToastUserPasswordChangeSuccess": "Password ændret",
|
"ToastUserPasswordChangeSuccess": "Password ændret",
|
||||||
|
|||||||
+24
-6
@@ -32,7 +32,7 @@
|
|||||||
"ButtonEditChapters": "Kapitel bearbeiten",
|
"ButtonEditChapters": "Kapitel bearbeiten",
|
||||||
"ButtonEditPodcast": "Podcast bearbeiten",
|
"ButtonEditPodcast": "Podcast bearbeiten",
|
||||||
"ButtonEnable": "Aktivieren",
|
"ButtonEnable": "Aktivieren",
|
||||||
"ButtonFireAndFail": "Abfeuern und versagen",
|
"ButtonFireAndFail": "Abschicken und fehlschlagen",
|
||||||
"ButtonFireOnTest": "Test-Event abfeuern",
|
"ButtonFireOnTest": "Test-Event abfeuern",
|
||||||
"ButtonForceReScan": "Komplett-Scan (alle Medien)",
|
"ButtonForceReScan": "Komplett-Scan (alle Medien)",
|
||||||
"ButtonFullPath": "Vollständiger Pfad",
|
"ButtonFullPath": "Vollständiger Pfad",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"ButtonNext": "Vor",
|
"ButtonNext": "Vor",
|
||||||
"ButtonNextChapter": "Nächstes Kapitel",
|
"ButtonNextChapter": "Nächstes Kapitel",
|
||||||
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
|
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
|
||||||
"ButtonOk": "Einverstanden",
|
"ButtonOk": "Ok",
|
||||||
"ButtonOpenFeed": "Feed öffnen",
|
"ButtonOpenFeed": "Feed öffnen",
|
||||||
"ButtonOpenManager": "Manager öffnen",
|
"ButtonOpenManager": "Manager öffnen",
|
||||||
"ButtonPause": "Pausieren",
|
"ButtonPause": "Pausieren",
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
"ButtonSave": "Speichern",
|
"ButtonSave": "Speichern",
|
||||||
"ButtonSaveAndClose": "Speichern & Schließen",
|
"ButtonSaveAndClose": "Speichern & Schließen",
|
||||||
"ButtonSaveTracklist": "Speichere die Titelliste",
|
"ButtonSaveTracklist": "Speichere die Titelliste",
|
||||||
"ButtonScan": "Partial-Scan (nur geänderte/neue Medien)",
|
"ButtonScan": "Scannen",
|
||||||
"ButtonScanLibrary": "Bibliothek scannen",
|
"ButtonScanLibrary": "Bibliothek scannen",
|
||||||
"ButtonScrollLeft": "Nach Links scrollen",
|
"ButtonScrollLeft": "Nach Links scrollen",
|
||||||
"ButtonScrollRight": "Nach Rechts scrollen",
|
"ButtonScrollRight": "Nach Rechts scrollen",
|
||||||
@@ -177,6 +177,7 @@
|
|||||||
"HeaderPlaylist": "Wiedergabeliste",
|
"HeaderPlaylist": "Wiedergabeliste",
|
||||||
"HeaderPlaylistItems": "Einträge in der Wiedergabeliste",
|
"HeaderPlaylistItems": "Einträge in der Wiedergabeliste",
|
||||||
"HeaderPodcastsToAdd": "Podcasts zum Hinzufügen",
|
"HeaderPodcastsToAdd": "Podcasts zum Hinzufügen",
|
||||||
|
"HeaderPresets": "Voreinstellungen",
|
||||||
"HeaderPreviewCover": "Vorschau Titelbild",
|
"HeaderPreviewCover": "Vorschau Titelbild",
|
||||||
"HeaderRSSFeedGeneral": "RSS Details",
|
"HeaderRSSFeedGeneral": "RSS Details",
|
||||||
"HeaderRSSFeedIsOpen": "RSS-Feed ist geöffnet",
|
"HeaderRSSFeedIsOpen": "RSS-Feed ist geöffnet",
|
||||||
@@ -229,6 +230,7 @@
|
|||||||
"LabelAddedDate": "{0} Hinzugefügt",
|
"LabelAddedDate": "{0} Hinzugefügt",
|
||||||
"LabelAdminUsersOnly": "Nur Admin Benutzer",
|
"LabelAdminUsersOnly": "Nur Admin Benutzer",
|
||||||
"LabelAll": "Alle",
|
"LabelAll": "Alle",
|
||||||
|
"LabelAllEpisodesDownloaded": "Alle Episoden heruntergeladen",
|
||||||
"LabelAllUsers": "Alle Benutzer",
|
"LabelAllUsers": "Alle Benutzer",
|
||||||
"LabelAllUsersExcludingGuests": "Alle Benutzer außer Gästen",
|
"LabelAllUsersExcludingGuests": "Alle Benutzer außer Gästen",
|
||||||
"LabelAllUsersIncludingGuests": "Alle Benutzer und Gäste",
|
"LabelAllUsersIncludingGuests": "Alle Benutzer und Gäste",
|
||||||
@@ -397,7 +399,7 @@
|
|||||||
"LabelInvert": "Umkehren",
|
"LabelInvert": "Umkehren",
|
||||||
"LabelItem": "Medium",
|
"LabelItem": "Medium",
|
||||||
"LabelJumpBackwardAmount": "Zurückspringen Zeit",
|
"LabelJumpBackwardAmount": "Zurückspringen Zeit",
|
||||||
"LabelJumpForwardAmount": "Vorwärtsspringn Zeit",
|
"LabelJumpForwardAmount": "Vorwärtsspringen Zeit",
|
||||||
"LabelLanguage": "Sprache",
|
"LabelLanguage": "Sprache",
|
||||||
"LabelLanguageDefaultServer": "Standard-Server-Sprache",
|
"LabelLanguageDefaultServer": "Standard-Server-Sprache",
|
||||||
"LabelLanguages": "Sprachen",
|
"LabelLanguages": "Sprachen",
|
||||||
@@ -529,6 +531,7 @@
|
|||||||
"LabelReleaseDate": "Veröffentlichungsdatum",
|
"LabelReleaseDate": "Veröffentlichungsdatum",
|
||||||
"LabelRemoveAllMetadataAbs": "Alle metadata.abs Dateien löschen",
|
"LabelRemoveAllMetadataAbs": "Alle metadata.abs Dateien löschen",
|
||||||
"LabelRemoveAllMetadataJson": "Alle metadata.json Dateien löschen",
|
"LabelRemoveAllMetadataJson": "Alle metadata.json Dateien löschen",
|
||||||
|
"LabelRemoveAudibleBranding": "Audible Intro sowie Outro aus Kapiteln entfernen",
|
||||||
"LabelRemoveCover": "Entferne Titelbild",
|
"LabelRemoveCover": "Entferne Titelbild",
|
||||||
"LabelRemoveMetadataFile": "Metadaten-Dateien in Bibliotheksordnern löschen",
|
"LabelRemoveMetadataFile": "Metadaten-Dateien in Bibliotheksordnern löschen",
|
||||||
"LabelRemoveMetadataFileHelp": "Alle metadata.json und metadata.abs Dateien aus den Ordnern {0} löschen.",
|
"LabelRemoveMetadataFileHelp": "Alle metadata.json und metadata.abs Dateien aus den Ordnern {0} löschen.",
|
||||||
@@ -603,6 +606,7 @@
|
|||||||
"LabelSlug": "URL Teil",
|
"LabelSlug": "URL Teil",
|
||||||
"LabelSortAscending": "Aufsteigend",
|
"LabelSortAscending": "Aufsteigend",
|
||||||
"LabelSortDescending": "Absteigend",
|
"LabelSortDescending": "Absteigend",
|
||||||
|
"LabelSortPubDate": "Erscheinungsdatum",
|
||||||
"LabelStart": "Start",
|
"LabelStart": "Start",
|
||||||
"LabelStartTime": "Startzeit",
|
"LabelStartTime": "Startzeit",
|
||||||
"LabelStarted": "Gestartet",
|
"LabelStarted": "Gestartet",
|
||||||
@@ -703,6 +707,8 @@
|
|||||||
"LabelYourProgress": "Fortschritt",
|
"LabelYourProgress": "Fortschritt",
|
||||||
"MessageAddToPlayerQueue": "Zur Abspielwarteliste hinzufügen",
|
"MessageAddToPlayerQueue": "Zur Abspielwarteliste hinzufügen",
|
||||||
"MessageAppriseDescription": "Um diese Funktion nutzen zu können, musst du eine Instanz von <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> laufen haben oder eine API verwenden welche dieselbe Anfragen bearbeiten kann. <br />Die Apprise API Url muss der vollständige URL-Pfad sein, an den die Benachrichtigung gesendet werden soll, z.B. wenn Ihre API-Instanz unter <code>http://192.168.1.1:8337</code> läuft, würdest du <code>http://192.168.1.1:8337/notify</code> eingeben.",
|
"MessageAppriseDescription": "Um diese Funktion nutzen zu können, musst du eine Instanz von <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> laufen haben oder eine API verwenden welche dieselbe Anfragen bearbeiten kann. <br />Die Apprise API Url muss der vollständige URL-Pfad sein, an den die Benachrichtigung gesendet werden soll, z.B. wenn Ihre API-Instanz unter <code>http://192.168.1.1:8337</code> läuft, würdest du <code>http://192.168.1.1:8337/notify</code> eingeben.",
|
||||||
|
"MessageAsinCheck": "Stellen Sie sicher, dass Sie die ASIN aus der richtigen Audible Region verwenden, nicht Amazon.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Nach dem Speichern muss der Server neugestartet werden um die OIDC Änderungen zu übernehmen.",
|
||||||
"MessageBackupsDescription": "In einer Sicherung werden Benutzer, Benutzerfortschritte, Details zu den Bibliotheksobjekten, Servereinstellungen und Bilder welche in <code>/metadata/items</code> & <code>/metadata/authors</code> gespeichert sind gespeichert. Sicherungen enthalten keine Dateien welche in den einzelnen Bibliotheksordnern (Medien-Ordnern) gespeichert sind.",
|
"MessageBackupsDescription": "In einer Sicherung werden Benutzer, Benutzerfortschritte, Details zu den Bibliotheksobjekten, Servereinstellungen und Bilder welche in <code>/metadata/items</code> & <code>/metadata/authors</code> gespeichert sind gespeichert. Sicherungen enthalten keine Dateien welche in den einzelnen Bibliotheksordnern (Medien-Ordnern) gespeichert sind.",
|
||||||
"MessageBackupsLocationEditNote": "Hinweis: Durch das Aktualisieren des Backup-Speicherorts werden vorhandene Sicherungen nicht verschoben oder geändert",
|
"MessageBackupsLocationEditNote": "Hinweis: Durch das Aktualisieren des Backup-Speicherorts werden vorhandene Sicherungen nicht verschoben oder geändert",
|
||||||
"MessageBackupsLocationNoEditNote": "Hinweis: Der Sicherungsspeicherort wird über eine Umgebungsvariable festgelegt und kann hier nicht geändert werden.",
|
"MessageBackupsLocationNoEditNote": "Hinweis: Der Sicherungsspeicherort wird über eine Umgebungsvariable festgelegt und kann hier nicht geändert werden.",
|
||||||
@@ -721,6 +727,7 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumlänge (Kapitelanfang liegt zeitlich nach dem Ende des Mediums -> Lösung: Kapitelanfang < Mediumlänge)",
|
"MessageChapterErrorStartGteDuration": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumlänge (Kapitelanfang liegt zeitlich nach dem Ende des Mediums -> Lösung: Kapitelanfang < Mediumlänge)",
|
||||||
"MessageChapterErrorStartLtPrev": "Ungültige Kapitelstartzeit: Kapitelanfang < Kapitelanfang vorheriges Kapitel (Kapitelanfang liegt zeitlich vor dem Beginn des vorherigen Kapitels -> Lösung: Kapitelanfang >= Startzeit des vorherigen Kapitels)",
|
"MessageChapterErrorStartLtPrev": "Ungültige Kapitelstartzeit: Kapitelanfang < Kapitelanfang vorheriges Kapitel (Kapitelanfang liegt zeitlich vor dem Beginn des vorherigen Kapitels -> Lösung: Kapitelanfang >= Startzeit des vorherigen Kapitels)",
|
||||||
"MessageChapterStartIsAfter": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumende (Kapitelanfang liegt nach dem Ende des Mediums)",
|
"MessageChapterStartIsAfter": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumende (Kapitelanfang liegt nach dem Ende des Mediums)",
|
||||||
|
"MessageChaptersNotFound": "Kapitel gefunden nicht",
|
||||||
"MessageCheckingCron": "Überprüfe Cron...",
|
"MessageCheckingCron": "Überprüfe Cron...",
|
||||||
"MessageConfirmCloseFeed": "Feed wird geschlossen! Bist du dir sicher?",
|
"MessageConfirmCloseFeed": "Feed wird geschlossen! Bist du dir sicher?",
|
||||||
"MessageConfirmDeleteBackup": "Sicherung für {0} wird gelöscht! Bist du dir sicher?",
|
"MessageConfirmDeleteBackup": "Sicherung für {0} wird gelöscht! Bist du dir sicher?",
|
||||||
@@ -750,6 +757,7 @@
|
|||||||
"MessageConfirmRemoveAuthor": "Autor \"{0}\" wird enfernt! Bist du dir sicher?",
|
"MessageConfirmRemoveAuthor": "Autor \"{0}\" wird enfernt! Bist du dir sicher?",
|
||||||
"MessageConfirmRemoveCollection": "Sammlung \"{0}\" wird entfernt! Bist du dir sicher?",
|
"MessageConfirmRemoveCollection": "Sammlung \"{0}\" wird entfernt! Bist du dir sicher?",
|
||||||
"MessageConfirmRemoveEpisode": "Episode \"{0}\" wird entfernt! Bist du dir sicher?",
|
"MessageConfirmRemoveEpisode": "Episode \"{0}\" wird entfernt! Bist du dir sicher?",
|
||||||
|
"MessageConfirmRemoveEpisodeNote": "Hinweis: Die Audiodatei wird nicht gelöscht, es sei denn \"Datei dauerhaft löschen\" ist aktiviert",
|
||||||
"MessageConfirmRemoveEpisodes": "{0} Episoden werden entfernt! Bist du dir sicher?",
|
"MessageConfirmRemoveEpisodes": "{0} Episoden werden entfernt! Bist du dir sicher?",
|
||||||
"MessageConfirmRemoveListeningSessions": "Bist du dir sicher, dass du {0} Hörsitzungen enfernen möchtest?",
|
"MessageConfirmRemoveListeningSessions": "Bist du dir sicher, dass du {0} Hörsitzungen enfernen möchtest?",
|
||||||
"MessageConfirmRemoveMetadataFiles": "Bist du sicher, dass du alle metadata.{0} Dateien in deinen Bibliotheksordnern löschen willst?",
|
"MessageConfirmRemoveMetadataFiles": "Bist du sicher, dass du alle metadata.{0} Dateien in deinen Bibliotheksordnern löschen willst?",
|
||||||
@@ -777,6 +785,7 @@
|
|||||||
"MessageForceReScanDescription": "Durchsucht alle Dateien erneut, wie bei einem frischen Scan. ID3-Tags von Audiodateien, OPF-Dateien und Textdateien werden neu durchsucht.",
|
"MessageForceReScanDescription": "Durchsucht alle Dateien erneut, wie bei einem frischen Scan. ID3-Tags von Audiodateien, OPF-Dateien und Textdateien werden neu durchsucht.",
|
||||||
"MessageImportantNotice": "Wichtiger Hinweis!",
|
"MessageImportantNotice": "Wichtiger Hinweis!",
|
||||||
"MessageInsertChapterBelow": "Kapitel unten einfügen",
|
"MessageInsertChapterBelow": "Kapitel unten einfügen",
|
||||||
|
"MessageInvalidAsin": "Ungültige ASIN",
|
||||||
"MessageItemsSelected": "{0} ausgewählte Medien",
|
"MessageItemsSelected": "{0} ausgewählte Medien",
|
||||||
"MessageItemsUpdated": "{0} Medien aktualisiert",
|
"MessageItemsUpdated": "{0} Medien aktualisiert",
|
||||||
"MessageJoinUsOn": "Besuche uns auf",
|
"MessageJoinUsOn": "Besuche uns auf",
|
||||||
@@ -844,12 +853,13 @@
|
|||||||
"MessageResetChaptersConfirm": "Kapitel und vorgenommenen Änderungen werden zurückgesetzt und rückgängig gemacht! Bist du dir sicher?",
|
"MessageResetChaptersConfirm": "Kapitel und vorgenommenen Änderungen werden zurückgesetzt und rückgängig gemacht! Bist du dir sicher?",
|
||||||
"MessageRestoreBackupConfirm": "Bist du dir sicher, dass du die Sicherung wiederherstellen willst, welche am",
|
"MessageRestoreBackupConfirm": "Bist du dir sicher, dass du die Sicherung wiederherstellen willst, welche am",
|
||||||
"MessageRestoreBackupWarning": "Bei der Wiederherstellung einer Sicherung wird die gesamte Datenbank unter /config und die Titelbilder in /metadata/items und /metadata/authors überschrieben.<br /><br />Bei der Sicherung werden keine Dateien in deinen Bibliotheksordnern verändert. Wenn du die Servereinstellungen aktiviert hast, um Cover und Metadaten in deinen Bibliotheksordnern zu speichern, werden diese nicht gesichert oder überschrieben.<br /><br />Alle Clients, die Ihren Server nutzen, werden automatisch aktualisiert.",
|
"MessageRestoreBackupWarning": "Bei der Wiederherstellung einer Sicherung wird die gesamte Datenbank unter /config und die Titelbilder in /metadata/items und /metadata/authors überschrieben.<br /><br />Bei der Sicherung werden keine Dateien in deinen Bibliotheksordnern verändert. Wenn du die Servereinstellungen aktiviert hast, um Cover und Metadaten in deinen Bibliotheksordnern zu speichern, werden diese nicht gesichert oder überschrieben.<br /><br />Alle Clients, die Ihren Server nutzen, werden automatisch aktualisiert.",
|
||||||
"MessageScheduleLibraryScanNote": "Für die meisten Nutzer wird empfohlen, diese Funktion deaktiviert zu lassen und stattdessen die Ordnerüberwachung aktiviert zu lassen. Die Ordnerüberwachung erkennt automatisch Änderungen in deinen Bibliotheksordnern. Da die Ordnerüberwachung jedoch nicht mit jedem Dateisystem (z.B. NFS) funktioniert, können alternativ hier geplante Bibliotheks-Scans aktiviert werden.",
|
"MessageScheduleLibraryScanNote": "Für die meisten Anwender wird empfohlen, diese Funktion deaktiviert und die Ordnerüberwachung aktiviert zu lassen. Die Ordnerüberwachung wird Änderungen in den Bibliotheksordnern automatisch erkennen. Die Ordnerüberwachung funktioniert nicht mit allen Dateisystemen (wie NFS), hier kann stattdessen die automatischen Bibliothekssuchen verwendet werden.",
|
||||||
"MessageScheduleRunEveryWeekdayAtTime": "Immer {0} um {1} ausführen",
|
"MessageScheduleRunEveryWeekdayAtTime": "Immer {0} um {1} ausführen",
|
||||||
"MessageSearchResultsFor": "Suchergebnisse für",
|
"MessageSearchResultsFor": "Suchergebnisse für",
|
||||||
"MessageSelected": "{0} ausgewählt",
|
"MessageSelected": "{0} ausgewählt",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "Serie Abfolge kann keine Leerzeichen enthalten",
|
||||||
"MessageServerCouldNotBeReached": "Server kann nicht erreicht werden",
|
"MessageServerCouldNotBeReached": "Server kann nicht erreicht werden",
|
||||||
"MessageSetChaptersFromTracksDescription": "Kaitelerstellung basiert auf den existierenden einzelnen Audiodateien. Pro existierende Audiodatei wird 1 Kapitel erstellt, wobei deren Kapitelname aus dem Audiodateinamen extrahiert wird",
|
"MessageSetChaptersFromTracksDescription": "Kapitelerstellung basiert auf den existierenden einzelnen Audiodateien. Pro existierende Audiodatei wird 1 Kapitel erstellt, wobei deren Kapitelname aus dem Audiodateinamen extrahiert wird",
|
||||||
"MessageShareExpirationWillBe": "Läuft am <strong>{0}</strong> ab",
|
"MessageShareExpirationWillBe": "Läuft am <strong>{0}</strong> ab",
|
||||||
"MessageShareExpiresIn": "Läuft in {0} ab",
|
"MessageShareExpiresIn": "Läuft in {0} ab",
|
||||||
"MessageShareURLWillBe": "Der Freigabe Link wird <strong>{0}</strong> sein",
|
"MessageShareURLWillBe": "Der Freigabe Link wird <strong>{0}</strong> sein",
|
||||||
@@ -909,6 +919,8 @@
|
|||||||
"NotificationOnBackupCompletedDescription": "Wird ausgeführt wenn ein Backup erstellt wurde",
|
"NotificationOnBackupCompletedDescription": "Wird ausgeführt wenn ein Backup erstellt wurde",
|
||||||
"NotificationOnBackupFailedDescription": "Wird ausgeführt wenn ein Backup fehlgeschlagen ist",
|
"NotificationOnBackupFailedDescription": "Wird ausgeführt wenn ein Backup fehlgeschlagen ist",
|
||||||
"NotificationOnEpisodeDownloadedDescription": "Wird ausgeführt wenn eine Podcast Folge automatisch heruntergeladen wird",
|
"NotificationOnEpisodeDownloadedDescription": "Wird ausgeführt wenn eine Podcast Folge automatisch heruntergeladen wird",
|
||||||
|
"NotificationOnRSSFeedDisabledDescription": "Wird ausgeführt wenn automatische Downloads von Episoden wegen zu vielen fehlgeschlagenen Versuchen deaktiviert sind",
|
||||||
|
"NotificationOnRSSFeedFailedDescription": "Wird ausgelöst, wenn die RSS-Feed-Anforderung für einen automatischen Episoden-Download fehlschlägt",
|
||||||
"NotificationOnTestDescription": "Wird ausgeführt wenn das Benachrichtigungssystem getestet wird",
|
"NotificationOnTestDescription": "Wird ausgeführt wenn das Benachrichtigungssystem getestet wird",
|
||||||
"PlaceholderNewCollection": "Neuer Sammlungsname",
|
"PlaceholderNewCollection": "Neuer Sammlungsname",
|
||||||
"PlaceholderNewFolderPath": "Neuer Ordnerpfad",
|
"PlaceholderNewFolderPath": "Neuer Ordnerpfad",
|
||||||
@@ -953,6 +965,7 @@
|
|||||||
"ToastBackupRestoreFailed": "Sicherung konnte nicht wiederhergestellt werden",
|
"ToastBackupRestoreFailed": "Sicherung konnte nicht wiederhergestellt werden",
|
||||||
"ToastBackupUploadFailed": "Sicherung konnte nicht hochgeladen werden",
|
"ToastBackupUploadFailed": "Sicherung konnte nicht hochgeladen werden",
|
||||||
"ToastBackupUploadSuccess": "Sicherung hochgeladen",
|
"ToastBackupUploadSuccess": "Sicherung hochgeladen",
|
||||||
|
"ToastBatchApplyDetailsToItemsSuccess": "Details auf Medien anwenden",
|
||||||
"ToastBatchDeleteFailed": "Batch-Löschen fehlgeschlagen",
|
"ToastBatchDeleteFailed": "Batch-Löschen fehlgeschlagen",
|
||||||
"ToastBatchDeleteSuccess": "Batch-Löschung erfolgreich",
|
"ToastBatchDeleteSuccess": "Batch-Löschung erfolgreich",
|
||||||
"ToastBatchQuickMatchFailed": "Batch-Schnellabgleich fehlgeschlagen!",
|
"ToastBatchQuickMatchFailed": "Batch-Schnellabgleich fehlgeschlagen!",
|
||||||
@@ -965,6 +978,8 @@
|
|||||||
"ToastCachePurgeFailed": "Cache leeren fehlgeschlagen",
|
"ToastCachePurgeFailed": "Cache leeren fehlgeschlagen",
|
||||||
"ToastCachePurgeSuccess": "Cache geleert",
|
"ToastCachePurgeSuccess": "Cache geleert",
|
||||||
"ToastChaptersHaveErrors": "Kapitel sind fehlerhaft",
|
"ToastChaptersHaveErrors": "Kapitel sind fehlerhaft",
|
||||||
|
"ToastChaptersInvalidShiftAmountLast": "Die Verschiebung ist nicht möglich, da die Startzeit des letzten Kapitels über die Gesamtdauer dieses Hörbuchs hinausgehen würde.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "Ungültige Höhe der Verschiebung. Das erste Kapitel hätte eine Länge von Null oder eine negative Länge und würde vom zweiten Kapitel überschrieben werden. Erhöhen Sie die Startdauer des zweiten Kapitels.",
|
||||||
"ToastChaptersMustHaveTitles": "Kapitel benötigen eindeutige Namen",
|
"ToastChaptersMustHaveTitles": "Kapitel benötigen eindeutige Namen",
|
||||||
"ToastChaptersRemoved": "Kapitel entfernt",
|
"ToastChaptersRemoved": "Kapitel entfernt",
|
||||||
"ToastChaptersUpdated": "Kapitel aktualisiert",
|
"ToastChaptersUpdated": "Kapitel aktualisiert",
|
||||||
@@ -1065,6 +1080,7 @@
|
|||||||
"ToastSelectAtLeastOneUser": "Wähle mindestens einen Benutzer aus",
|
"ToastSelectAtLeastOneUser": "Wähle mindestens einen Benutzer aus",
|
||||||
"ToastSendEbookToDeviceFailed": "E-Buch konnte nicht auf Gerät übertragen werden",
|
"ToastSendEbookToDeviceFailed": "E-Buch konnte nicht auf Gerät übertragen werden",
|
||||||
"ToastSendEbookToDeviceSuccess": "E-Buch an Gerät „{0}“ gesendet",
|
"ToastSendEbookToDeviceSuccess": "E-Buch an Gerät „{0}“ gesendet",
|
||||||
|
"ToastSeriesSubmitFailedSameName": "Serien mit dem selben Namen können nicht hinzugefügt werden",
|
||||||
"ToastSeriesUpdateFailed": "Aktualisierung der Serien fehlgeschlagen",
|
"ToastSeriesUpdateFailed": "Aktualisierung der Serien fehlgeschlagen",
|
||||||
"ToastSeriesUpdateSuccess": "Serien aktualisiert",
|
"ToastSeriesUpdateSuccess": "Serien aktualisiert",
|
||||||
"ToastServerSettingsUpdateSuccess": "Die Server-Einstellungen wurden geupdated",
|
"ToastServerSettingsUpdateSuccess": "Die Server-Einstellungen wurden geupdated",
|
||||||
@@ -1083,6 +1099,8 @@
|
|||||||
"ToastUnknownError": "Unbekannter Fehler",
|
"ToastUnknownError": "Unbekannter Fehler",
|
||||||
"ToastUnlinkOpenIdFailed": "Fehler beim entkoppeln des Benutzers von OpenID",
|
"ToastUnlinkOpenIdFailed": "Fehler beim entkoppeln des Benutzers von OpenID",
|
||||||
"ToastUnlinkOpenIdSuccess": "Benutzer entkoppelt von OpenID",
|
"ToastUnlinkOpenIdSuccess": "Benutzer entkoppelt von OpenID",
|
||||||
|
"ToastUploaderFilepathExistsError": "Dateipfad \"{0}\" ist bereits auf dem Server horhanden",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "Element \"{0}\" verwendet ein Unterverzeichnis des Upload-Pfads.",
|
||||||
"ToastUserDeleteFailed": "Benutzer konnte nicht gelöscht werden",
|
"ToastUserDeleteFailed": "Benutzer konnte nicht gelöscht werden",
|
||||||
"ToastUserDeleteSuccess": "Benutzer gelöscht",
|
"ToastUserDeleteSuccess": "Benutzer gelöscht",
|
||||||
"ToastUserPasswordChangeSuccess": "Passwort erfolgreich verändert",
|
"ToastUserPasswordChangeSuccess": "Passwort erfolgreich verändert",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ButtonAdd": "Add",
|
"ButtonAdd": "Add",
|
||||||
|
"ButtonAddApiKey": "Add API Key",
|
||||||
"ButtonAddChapters": "Add Chapters",
|
"ButtonAddChapters": "Add Chapters",
|
||||||
"ButtonAddDevice": "Add Device",
|
"ButtonAddDevice": "Add Device",
|
||||||
"ButtonAddLibrary": "Add Library",
|
"ButtonAddLibrary": "Add Library",
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
"ButtonChooseAFolder": "Choose a folder",
|
"ButtonChooseAFolder": "Choose a folder",
|
||||||
"ButtonChooseFiles": "Choose files",
|
"ButtonChooseFiles": "Choose files",
|
||||||
"ButtonClearFilter": "Clear Filter",
|
"ButtonClearFilter": "Clear Filter",
|
||||||
|
"ButtonClose": "Close",
|
||||||
"ButtonCloseFeed": "Close Feed",
|
"ButtonCloseFeed": "Close Feed",
|
||||||
"ButtonCloseSession": "Close Open Session",
|
"ButtonCloseSession": "Close Open Session",
|
||||||
"ButtonCollections": "Collections",
|
"ButtonCollections": "Collections",
|
||||||
@@ -119,6 +121,7 @@
|
|||||||
"HeaderAccount": "Account",
|
"HeaderAccount": "Account",
|
||||||
"HeaderAddCustomMetadataProvider": "Add Custom Metadata Provider",
|
"HeaderAddCustomMetadataProvider": "Add Custom Metadata Provider",
|
||||||
"HeaderAdvanced": "Advanced",
|
"HeaderAdvanced": "Advanced",
|
||||||
|
"HeaderApiKeys": "API Keys",
|
||||||
"HeaderAppriseNotificationSettings": "Apprise Notification Settings",
|
"HeaderAppriseNotificationSettings": "Apprise Notification Settings",
|
||||||
"HeaderAudioTracks": "Audio Tracks",
|
"HeaderAudioTracks": "Audio Tracks",
|
||||||
"HeaderAudiobookTools": "Audiobook File Management Tools",
|
"HeaderAudiobookTools": "Audiobook File Management Tools",
|
||||||
@@ -162,6 +165,7 @@
|
|||||||
"HeaderMetadataOrderOfPrecedence": "Metadata order of precedence",
|
"HeaderMetadataOrderOfPrecedence": "Metadata order of precedence",
|
||||||
"HeaderMetadataToEmbed": "Metadata to embed",
|
"HeaderMetadataToEmbed": "Metadata to embed",
|
||||||
"HeaderNewAccount": "New Account",
|
"HeaderNewAccount": "New Account",
|
||||||
|
"HeaderNewApiKey": "New API Key",
|
||||||
"HeaderNewLibrary": "New Library",
|
"HeaderNewLibrary": "New Library",
|
||||||
"HeaderNotificationCreate": "Create Notification",
|
"HeaderNotificationCreate": "Create Notification",
|
||||||
"HeaderNotificationUpdate": "Update Notification",
|
"HeaderNotificationUpdate": "Update Notification",
|
||||||
@@ -177,6 +181,7 @@
|
|||||||
"HeaderPlaylist": "Playlist",
|
"HeaderPlaylist": "Playlist",
|
||||||
"HeaderPlaylistItems": "Playlist Items",
|
"HeaderPlaylistItems": "Playlist Items",
|
||||||
"HeaderPodcastsToAdd": "Podcasts to Add",
|
"HeaderPodcastsToAdd": "Podcasts to Add",
|
||||||
|
"HeaderPresets": "Presets",
|
||||||
"HeaderPreviewCover": "Preview Cover",
|
"HeaderPreviewCover": "Preview Cover",
|
||||||
"HeaderRSSFeedGeneral": "RSS Details",
|
"HeaderRSSFeedGeneral": "RSS Details",
|
||||||
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
|
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
|
||||||
@@ -205,6 +210,7 @@
|
|||||||
"HeaderTableOfContents": "Table of Contents",
|
"HeaderTableOfContents": "Table of Contents",
|
||||||
"HeaderTools": "Tools",
|
"HeaderTools": "Tools",
|
||||||
"HeaderUpdateAccount": "Update Account",
|
"HeaderUpdateAccount": "Update Account",
|
||||||
|
"HeaderUpdateApiKey": "Update API Key",
|
||||||
"HeaderUpdateAuthor": "Update Author",
|
"HeaderUpdateAuthor": "Update Author",
|
||||||
"HeaderUpdateDetails": "Update Details",
|
"HeaderUpdateDetails": "Update Details",
|
||||||
"HeaderUpdateLibrary": "Update Library",
|
"HeaderUpdateLibrary": "Update Library",
|
||||||
@@ -234,6 +240,10 @@
|
|||||||
"LabelAllUsersExcludingGuests": "All users excluding guests",
|
"LabelAllUsersExcludingGuests": "All users excluding guests",
|
||||||
"LabelAllUsersIncludingGuests": "All users including guests",
|
"LabelAllUsersIncludingGuests": "All users including guests",
|
||||||
"LabelAlreadyInYourLibrary": "Already in your library",
|
"LabelAlreadyInYourLibrary": "Already in your library",
|
||||||
|
"LabelApiKeyCreated": "API Key \"{0}\" created successfully.",
|
||||||
|
"LabelApiKeyCreatedDescription": "Make sure to copy the API key now as you will not be able to see this again.",
|
||||||
|
"LabelApiKeyUser": "Act on behalf of user",
|
||||||
|
"LabelApiKeyUserDescription": "This API key will have the same permissions as the user it is acting on behalf of. This will appear the same in logs as if the user was making the request.",
|
||||||
"LabelApiToken": "API Token",
|
"LabelApiToken": "API Token",
|
||||||
"LabelAppend": "Append",
|
"LabelAppend": "Append",
|
||||||
"LabelAudioBitrate": "Audio Bitrate (e.g. 128k)",
|
"LabelAudioBitrate": "Audio Bitrate (e.g. 128k)",
|
||||||
@@ -345,6 +355,10 @@
|
|||||||
"LabelExample": "Example",
|
"LabelExample": "Example",
|
||||||
"LabelExpandSeries": "Expand Series",
|
"LabelExpandSeries": "Expand Series",
|
||||||
"LabelExpandSubSeries": "Expand Sub Series",
|
"LabelExpandSubSeries": "Expand Sub Series",
|
||||||
|
"LabelExpired": "Expired",
|
||||||
|
"LabelExpiresAt": "Expires At",
|
||||||
|
"LabelExpiresInSeconds": "Expires in (seconds)",
|
||||||
|
"LabelExpiresNever": "Never",
|
||||||
"LabelExplicit": "Explicit",
|
"LabelExplicit": "Explicit",
|
||||||
"LabelExplicitChecked": "Explicit (checked)",
|
"LabelExplicitChecked": "Explicit (checked)",
|
||||||
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
|
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
|
||||||
@@ -454,6 +468,7 @@
|
|||||||
"LabelNewestEpisodes": "Newest Episodes",
|
"LabelNewestEpisodes": "Newest Episodes",
|
||||||
"LabelNextBackupDate": "Next backup date",
|
"LabelNextBackupDate": "Next backup date",
|
||||||
"LabelNextScheduledRun": "Next scheduled run",
|
"LabelNextScheduledRun": "Next scheduled run",
|
||||||
|
"LabelNoApiKeys": "No API keys",
|
||||||
"LabelNoCustomMetadataProviders": "No custom metadata providers",
|
"LabelNoCustomMetadataProviders": "No custom metadata providers",
|
||||||
"LabelNoEpisodesSelected": "No episodes selected",
|
"LabelNoEpisodesSelected": "No episodes selected",
|
||||||
"LabelNotFinished": "Not Finished",
|
"LabelNotFinished": "Not Finished",
|
||||||
@@ -530,6 +545,7 @@
|
|||||||
"LabelReleaseDate": "Release Date",
|
"LabelReleaseDate": "Release Date",
|
||||||
"LabelRemoveAllMetadataAbs": "Remove all metadata.abs files",
|
"LabelRemoveAllMetadataAbs": "Remove all metadata.abs files",
|
||||||
"LabelRemoveAllMetadataJson": "Remove all metadata.json files",
|
"LabelRemoveAllMetadataJson": "Remove all metadata.json files",
|
||||||
|
"LabelRemoveAudibleBranding": "Remove Audible intro and outro from chapters",
|
||||||
"LabelRemoveCover": "Remove cover",
|
"LabelRemoveCover": "Remove cover",
|
||||||
"LabelRemoveMetadataFile": "Remove metadata files in library item folders",
|
"LabelRemoveMetadataFile": "Remove metadata files in library item folders",
|
||||||
"LabelRemoveMetadataFileHelp": "Remove all metadata.json and metadata.abs files in your {0} folders.",
|
"LabelRemoveMetadataFileHelp": "Remove all metadata.json and metadata.abs files in your {0} folders.",
|
||||||
@@ -542,6 +558,7 @@
|
|||||||
"LabelSelectAll": "Select all",
|
"LabelSelectAll": "Select all",
|
||||||
"LabelSelectAllEpisodes": "Select all episodes",
|
"LabelSelectAllEpisodes": "Select all episodes",
|
||||||
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
|
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
|
||||||
|
"LabelSelectUser": "Select user",
|
||||||
"LabelSelectUsers": "Select users",
|
"LabelSelectUsers": "Select users",
|
||||||
"LabelSendEbookToDevice": "Send Ebook to...",
|
"LabelSendEbookToDevice": "Send Ebook to...",
|
||||||
"LabelSequence": "Sequence",
|
"LabelSequence": "Sequence",
|
||||||
@@ -604,6 +621,7 @@
|
|||||||
"LabelSlug": "Slug",
|
"LabelSlug": "Slug",
|
||||||
"LabelSortAscending": "Ascending",
|
"LabelSortAscending": "Ascending",
|
||||||
"LabelSortDescending": "Descending",
|
"LabelSortDescending": "Descending",
|
||||||
|
"LabelSortPubDate": "Sort Pub Date",
|
||||||
"LabelStart": "Start",
|
"LabelStart": "Start",
|
||||||
"LabelStartTime": "Start Time",
|
"LabelStartTime": "Start Time",
|
||||||
"LabelStarted": "Started",
|
"LabelStarted": "Started",
|
||||||
@@ -704,6 +722,9 @@
|
|||||||
"LabelYourProgress": "Your Progress",
|
"LabelYourProgress": "Your Progress",
|
||||||
"MessageAddToPlayerQueue": "Add to player queue",
|
"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>.",
|
"MessageAppriseDescription": "To use this feature you will need to have an instance of <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> running or an api that will handle those same requests. <br />The Apprise API Url should be the full URL path to send the notification, e.g., if your API instance is served at <code>http://192.168.1.1:8337</code> then you would put <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAsinCheck": "Ensure you are using the ASIN from the correct Audible region, not Amazon.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Restart your server after saving to apply OIDC changes.",
|
||||||
|
"MessageAuthenticationSecurityMessage": "Authentication has been improved for security. All users are required to re-login.",
|
||||||
"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.",
|
"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",
|
"MessageBackupsLocationEditNote": "Note: Updating the backup location will not move or modify existing backups",
|
||||||
"MessageBackupsLocationNoEditNote": "Note: The backup location is set through an environment variable and cannot be changed here.",
|
"MessageBackupsLocationNoEditNote": "Note: The backup location is set through an environment variable and cannot be changed here.",
|
||||||
@@ -722,8 +743,10 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Invalid start time must be less than audiobook duration",
|
"MessageChapterErrorStartGteDuration": "Invalid start time must be less than audiobook duration",
|
||||||
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
|
"MessageChapterErrorStartLtPrev": "Invalid start time must be greater than or equal to previous chapter start time",
|
||||||
"MessageChapterStartIsAfter": "Chapter start is after the end of your audiobook",
|
"MessageChapterStartIsAfter": "Chapter start is after the end of your audiobook",
|
||||||
|
"MessageChaptersNotFound": "Chapters not found",
|
||||||
"MessageCheckingCron": "Checking cron...",
|
"MessageCheckingCron": "Checking cron...",
|
||||||
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
|
"MessageConfirmCloseFeed": "Are you sure you want to close this feed?",
|
||||||
|
"MessageConfirmDeleteApiKey": "Are you sure you want to delete API key \"{0}\"?",
|
||||||
"MessageConfirmDeleteBackup": "Are you sure you want to delete backup for {0}?",
|
"MessageConfirmDeleteBackup": "Are you sure you want to delete backup for {0}?",
|
||||||
"MessageConfirmDeleteDevice": "Are you sure you want to delete e-reader device \"{0}\"?",
|
"MessageConfirmDeleteDevice": "Are you sure you want to delete e-reader device \"{0}\"?",
|
||||||
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
|
"MessageConfirmDeleteFile": "This will delete the file from your file system. Are you sure?",
|
||||||
@@ -751,6 +774,7 @@
|
|||||||
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
|
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
|
||||||
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{0}\"?",
|
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{0}\"?",
|
||||||
"MessageConfirmRemoveEpisode": "Are you sure you want to remove episode \"{0}\"?",
|
"MessageConfirmRemoveEpisode": "Are you sure you want to remove episode \"{0}\"?",
|
||||||
|
"MessageConfirmRemoveEpisodeNote": "Note: This does not delete the audio file unless toggling \"Hard delete file\"",
|
||||||
"MessageConfirmRemoveEpisodes": "Are you sure you want to remove {0} episodes?",
|
"MessageConfirmRemoveEpisodes": "Are you sure you want to remove {0} episodes?",
|
||||||
"MessageConfirmRemoveListeningSessions": "Are you sure you want to remove {0} listening sessions?",
|
"MessageConfirmRemoveListeningSessions": "Are you sure you want to remove {0} listening sessions?",
|
||||||
"MessageConfirmRemoveMetadataFiles": "Are you sure you want to remove all metadata.{0} files in your library item folders?",
|
"MessageConfirmRemoveMetadataFiles": "Are you sure you want to remove all metadata.{0} files in your library item folders?",
|
||||||
@@ -778,6 +802,7 @@
|
|||||||
"MessageForceReScanDescription": "will scan all files again like a fresh scan. Audio file ID3 tags, OPF files, and text files will be scanned as new.",
|
"MessageForceReScanDescription": "will scan all files again like a fresh scan. Audio file ID3 tags, OPF files, and text files will be scanned as new.",
|
||||||
"MessageImportantNotice": "Important Notice!",
|
"MessageImportantNotice": "Important Notice!",
|
||||||
"MessageInsertChapterBelow": "Insert chapter below",
|
"MessageInsertChapterBelow": "Insert chapter below",
|
||||||
|
"MessageInvalidAsin": "Invalid ASIN",
|
||||||
"MessageItemsSelected": "{0} items selected",
|
"MessageItemsSelected": "{0} items selected",
|
||||||
"MessageItemsUpdated": "{0} items updated",
|
"MessageItemsUpdated": "{0} items updated",
|
||||||
"MessageJoinUsOn": "Join us on",
|
"MessageJoinUsOn": "Join us on",
|
||||||
@@ -849,6 +874,7 @@
|
|||||||
"MessageScheduleRunEveryWeekdayAtTime": "Run every {0} at {1}",
|
"MessageScheduleRunEveryWeekdayAtTime": "Run every {0} at {1}",
|
||||||
"MessageSearchResultsFor": "Search results for",
|
"MessageSearchResultsFor": "Search results for",
|
||||||
"MessageSelected": "{0} selected",
|
"MessageSelected": "{0} selected",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "Series sequence cannot contain spaces",
|
||||||
"MessageServerCouldNotBeReached": "Server could not be reached",
|
"MessageServerCouldNotBeReached": "Server could not be reached",
|
||||||
"MessageSetChaptersFromTracksDescription": "Set chapters using each audio file as a chapter and chapter title as the audio file name",
|
"MessageSetChaptersFromTracksDescription": "Set chapters using each audio file as a chapter and chapter title as the audio file name",
|
||||||
"MessageShareExpirationWillBe": "Expiration will be <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "Expiration will be <strong>{0}</strong>",
|
||||||
@@ -910,6 +936,8 @@
|
|||||||
"NotificationOnBackupCompletedDescription": "Triggered when a backup is completed",
|
"NotificationOnBackupCompletedDescription": "Triggered when a backup is completed",
|
||||||
"NotificationOnBackupFailedDescription": "Triggered when a backup fails",
|
"NotificationOnBackupFailedDescription": "Triggered when a backup fails",
|
||||||
"NotificationOnEpisodeDownloadedDescription": "Triggered when a podcast episode is auto-downloaded",
|
"NotificationOnEpisodeDownloadedDescription": "Triggered when a podcast episode is auto-downloaded",
|
||||||
|
"NotificationOnRSSFeedDisabledDescription": "Triggered when automatic episode downloads are disabled due to too many failed attempts",
|
||||||
|
"NotificationOnRSSFeedFailedDescription": "Triggered when the RSS feed request fails for an automatic episode download",
|
||||||
"NotificationOnTestDescription": "Event for testing the notification system",
|
"NotificationOnTestDescription": "Event for testing the notification system",
|
||||||
"PlaceholderNewCollection": "New collection name",
|
"PlaceholderNewCollection": "New collection name",
|
||||||
"PlaceholderNewFolderPath": "New folder path",
|
"PlaceholderNewFolderPath": "New folder path",
|
||||||
@@ -967,6 +995,8 @@
|
|||||||
"ToastCachePurgeFailed": "Failed to purge cache",
|
"ToastCachePurgeFailed": "Failed to purge cache",
|
||||||
"ToastCachePurgeSuccess": "Cache purged successfully",
|
"ToastCachePurgeSuccess": "Cache purged successfully",
|
||||||
"ToastChaptersHaveErrors": "Chapters have errors",
|
"ToastChaptersHaveErrors": "Chapters have errors",
|
||||||
|
"ToastChaptersInvalidShiftAmountLast": "Invalid shift amount. The last chapter start time would extend beyond the duration of this audiobook.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "Invalid shift amount. The first chapter would have zero or negative length and would be overwritten by the second chapter. Increase the start duration of second chapter.",
|
||||||
"ToastChaptersMustHaveTitles": "Chapters must have titles",
|
"ToastChaptersMustHaveTitles": "Chapters must have titles",
|
||||||
"ToastChaptersRemoved": "Chapters removed",
|
"ToastChaptersRemoved": "Chapters removed",
|
||||||
"ToastChaptersUpdated": "Chapters updated",
|
"ToastChaptersUpdated": "Chapters updated",
|
||||||
@@ -988,6 +1018,8 @@
|
|||||||
"ToastEpisodeDownloadQueueClearSuccess": "Episode download queue cleared",
|
"ToastEpisodeDownloadQueueClearSuccess": "Episode download queue cleared",
|
||||||
"ToastEpisodeUpdateSuccess": "{0} episodes updated",
|
"ToastEpisodeUpdateSuccess": "{0} episodes updated",
|
||||||
"ToastErrorCannotShare": "Cannot share natively on this device",
|
"ToastErrorCannotShare": "Cannot share natively on this device",
|
||||||
|
"ToastFailedToCreate": "Failed to create",
|
||||||
|
"ToastFailedToDelete": "Failed to delete",
|
||||||
"ToastFailedToLoadData": "Failed to load data",
|
"ToastFailedToLoadData": "Failed to load data",
|
||||||
"ToastFailedToMatch": "Failed to match",
|
"ToastFailedToMatch": "Failed to match",
|
||||||
"ToastFailedToShare": "Failed to share",
|
"ToastFailedToShare": "Failed to share",
|
||||||
@@ -1019,6 +1051,7 @@
|
|||||||
"ToastMustHaveAtLeastOnePath": "Must have at least one path",
|
"ToastMustHaveAtLeastOnePath": "Must have at least one path",
|
||||||
"ToastNameEmailRequired": "Name and email are required",
|
"ToastNameEmailRequired": "Name and email are required",
|
||||||
"ToastNameRequired": "Name is required",
|
"ToastNameRequired": "Name is required",
|
||||||
|
"ToastNewApiKeyUserError": "Must select a user",
|
||||||
"ToastNewEpisodesFound": "{0} new episodes found",
|
"ToastNewEpisodesFound": "{0} new episodes found",
|
||||||
"ToastNewUserCreatedFailed": "Failed to create account: \"{0}\"",
|
"ToastNewUserCreatedFailed": "Failed to create account: \"{0}\"",
|
||||||
"ToastNewUserCreatedSuccess": "New account created",
|
"ToastNewUserCreatedSuccess": "New account created",
|
||||||
|
|||||||
+174
-155
@@ -10,13 +10,15 @@
|
|||||||
"ButtonApplyChapters": "Aplicar capítulos",
|
"ButtonApplyChapters": "Aplicar capítulos",
|
||||||
"ButtonAuthors": "Autores",
|
"ButtonAuthors": "Autores",
|
||||||
"ButtonBack": "Atrás",
|
"ButtonBack": "Atrás",
|
||||||
|
"ButtonBatchEditPopulateFromExisting": "Rellenar desde existentes",
|
||||||
|
"ButtonBatchEditPopulateMapDetails": "Rellenar detalles de mapa",
|
||||||
"ButtonBrowseForFolder": "Buscar carpeta",
|
"ButtonBrowseForFolder": "Buscar carpeta",
|
||||||
"ButtonCancel": "Cancelar",
|
"ButtonCancel": "Cancelar",
|
||||||
"ButtonCancelEncode": "Cancelar Codificador",
|
"ButtonCancelEncode": "Cancelar codificación",
|
||||||
"ButtonChangeRootPassword": "Cambiar contraseña administrativa",
|
"ButtonChangeRootPassword": "Cambiar contraseña administrativa",
|
||||||
"ButtonCheckAndDownloadNewEpisodes": "Comprobar y descargar episodios nuevos",
|
"ButtonCheckAndDownloadNewEpisodes": "Comprobar y descargar episodios nuevos",
|
||||||
"ButtonChooseAFolder": "Escoger una Carpeta",
|
"ButtonChooseAFolder": "Elegir una carpeta",
|
||||||
"ButtonChooseFiles": "Escoger un Archivo",
|
"ButtonChooseFiles": "Elegir archivos",
|
||||||
"ButtonClearFilter": "Quitar filtros",
|
"ButtonClearFilter": "Quitar filtros",
|
||||||
"ButtonCloseFeed": "Cerrar suministro",
|
"ButtonCloseFeed": "Cerrar suministro",
|
||||||
"ButtonCloseSession": "Cerrar la sesión abierta",
|
"ButtonCloseSession": "Cerrar la sesión abierta",
|
||||||
@@ -77,9 +79,9 @@
|
|||||||
"ButtonRemove": "Quitar",
|
"ButtonRemove": "Quitar",
|
||||||
"ButtonRemoveAll": "Quitar todo",
|
"ButtonRemoveAll": "Quitar todo",
|
||||||
"ButtonRemoveAllLibraryItems": "Quitar todos los elementos de la biblioteca",
|
"ButtonRemoveAllLibraryItems": "Quitar todos los elementos de la biblioteca",
|
||||||
"ButtonRemoveFromContinueListening": "Remover de Continuar Escuchando",
|
"ButtonRemoveFromContinueListening": "Quitar de Continuar escuchando",
|
||||||
"ButtonRemoveFromContinueReading": "Remover de Continuar Leyendo",
|
"ButtonRemoveFromContinueReading": "Quitar de Continuar leyendo",
|
||||||
"ButtonRemoveSeriesFromContinueSeries": "Remover Serie de Continuar Series",
|
"ButtonRemoveSeriesFromContinueSeries": "Quitar serie de Continuar serie",
|
||||||
"ButtonReset": "Restablecer",
|
"ButtonReset": "Restablecer",
|
||||||
"ButtonResetToDefault": "Restaurar valores predeterminados",
|
"ButtonResetToDefault": "Restaurar valores predeterminados",
|
||||||
"ButtonRestore": "Restaurar",
|
"ButtonRestore": "Restaurar",
|
||||||
@@ -87,7 +89,7 @@
|
|||||||
"ButtonSaveAndClose": "Guardar y cerrar",
|
"ButtonSaveAndClose": "Guardar y cerrar",
|
||||||
"ButtonSaveTracklist": "Guardar lista de pistas",
|
"ButtonSaveTracklist": "Guardar lista de pistas",
|
||||||
"ButtonScan": "Escanear",
|
"ButtonScan": "Escanear",
|
||||||
"ButtonScanLibrary": "Escanear Biblioteca",
|
"ButtonScanLibrary": "Escanear biblioteca",
|
||||||
"ButtonScrollLeft": "Desplazarse hacia la izquierda",
|
"ButtonScrollLeft": "Desplazarse hacia la izquierda",
|
||||||
"ButtonScrollRight": "Desplazarse hacia la derecha",
|
"ButtonScrollRight": "Desplazarse hacia la derecha",
|
||||||
"ButtonSearch": "Buscar",
|
"ButtonSearch": "Buscar",
|
||||||
@@ -147,7 +149,7 @@
|
|||||||
"HeaderLastListeningSession": "Última sesión de escucha",
|
"HeaderLastListeningSession": "Última sesión de escucha",
|
||||||
"HeaderLatestEpisodes": "Episodios más recientes",
|
"HeaderLatestEpisodes": "Episodios más recientes",
|
||||||
"HeaderLibraries": "Bibliotecas",
|
"HeaderLibraries": "Bibliotecas",
|
||||||
"HeaderLibraryFiles": "Archivos de Biblioteca",
|
"HeaderLibraryFiles": "Archivos de biblioteca",
|
||||||
"HeaderLibraryStats": "Estadísticas de biblioteca",
|
"HeaderLibraryStats": "Estadísticas de biblioteca",
|
||||||
"HeaderListeningSessions": "Sesión",
|
"HeaderListeningSessions": "Sesión",
|
||||||
"HeaderListeningStats": "Estadísticas de Tiempo Escuchado",
|
"HeaderListeningStats": "Estadísticas de Tiempo Escuchado",
|
||||||
@@ -175,6 +177,7 @@
|
|||||||
"HeaderPlaylist": "Lista de reproducción",
|
"HeaderPlaylist": "Lista de reproducción",
|
||||||
"HeaderPlaylistItems": "Elementos de lista de reproducción",
|
"HeaderPlaylistItems": "Elementos de lista de reproducción",
|
||||||
"HeaderPodcastsToAdd": "Pódcast para añadir",
|
"HeaderPodcastsToAdd": "Pódcast para añadir",
|
||||||
|
"HeaderPresets": "Preconfiguraciones",
|
||||||
"HeaderPreviewCover": "Previsualizar cubierta",
|
"HeaderPreviewCover": "Previsualizar cubierta",
|
||||||
"HeaderRSSFeedGeneral": "Detalles de RSS",
|
"HeaderRSSFeedGeneral": "Detalles de RSS",
|
||||||
"HeaderRSSFeedIsOpen": "El suministro RSS está abierto",
|
"HeaderRSSFeedIsOpen": "El suministro RSS está abierto",
|
||||||
@@ -190,7 +193,7 @@
|
|||||||
"HeaderSettings": "Configuración",
|
"HeaderSettings": "Configuración",
|
||||||
"HeaderSettingsDisplay": "Interfaz",
|
"HeaderSettingsDisplay": "Interfaz",
|
||||||
"HeaderSettingsExperimental": "Funcionalidades experimentales",
|
"HeaderSettingsExperimental": "Funcionalidades experimentales",
|
||||||
"HeaderSettingsGeneral": "General",
|
"HeaderSettingsGeneral": "Generales",
|
||||||
"HeaderSettingsScanner": "Escáner",
|
"HeaderSettingsScanner": "Escáner",
|
||||||
"HeaderSettingsWebClient": "Cliente web",
|
"HeaderSettingsWebClient": "Cliente web",
|
||||||
"HeaderSleepTimer": "Temporizador de apagado",
|
"HeaderSleepTimer": "Temporizador de apagado",
|
||||||
@@ -227,6 +230,7 @@
|
|||||||
"LabelAddedDate": "{0} Añadido",
|
"LabelAddedDate": "{0} Añadido",
|
||||||
"LabelAdminUsersOnly": "Solamente usuarios administradores",
|
"LabelAdminUsersOnly": "Solamente usuarios administradores",
|
||||||
"LabelAll": "Todos",
|
"LabelAll": "Todos",
|
||||||
|
"LabelAllEpisodesDownloaded": "Todos los episodios descargados",
|
||||||
"LabelAllUsers": "Todos los usuarios",
|
"LabelAllUsers": "Todos los usuarios",
|
||||||
"LabelAllUsersExcludingGuests": "Todos los usuarios excepto invitados",
|
"LabelAllUsersExcludingGuests": "Todos los usuarios excepto invitados",
|
||||||
"LabelAllUsersIncludingGuests": "Todos los usuarios e invitados",
|
"LabelAllUsersIncludingGuests": "Todos los usuarios e invitados",
|
||||||
@@ -261,14 +265,14 @@
|
|||||||
"LabelBooks": "Libros",
|
"LabelBooks": "Libros",
|
||||||
"LabelButtonText": "Texto del botón",
|
"LabelButtonText": "Texto del botón",
|
||||||
"LabelByAuthor": "por {0}",
|
"LabelByAuthor": "por {0}",
|
||||||
"LabelChangePassword": "Cambiar Contraseña",
|
"LabelChangePassword": "Cambiar contraseña",
|
||||||
"LabelChannels": "Canales",
|
"LabelChannels": "Canales",
|
||||||
"LabelChapterCount": "{0} capítulos",
|
"LabelChapterCount": "{0} capítulos",
|
||||||
"LabelChapterTitle": "Titulo del Capítulo",
|
"LabelChapterTitle": "Título del capítulo",
|
||||||
"LabelChapters": "Capítulos",
|
"LabelChapters": "Capítulos",
|
||||||
"LabelChaptersFound": "Capítulo Encontrado",
|
"LabelChaptersFound": "capítulos encontrados",
|
||||||
"LabelClickForMoreInfo": "Click para más información",
|
"LabelClickForMoreInfo": "Pulse para más información",
|
||||||
"LabelClickToUseCurrentValue": "Haz clic para utilizar el valor actual",
|
"LabelClickToUseCurrentValue": "Pulse para utilizar el valor actual",
|
||||||
"LabelClosePlayer": "Cerrar reproductor",
|
"LabelClosePlayer": "Cerrar reproductor",
|
||||||
"LabelCodec": "Codec",
|
"LabelCodec": "Codec",
|
||||||
"LabelCollapseSeries": "Colapsar serie",
|
"LabelCollapseSeries": "Colapsar serie",
|
||||||
@@ -276,7 +280,7 @@
|
|||||||
"LabelCollection": "Colección",
|
"LabelCollection": "Colección",
|
||||||
"LabelCollections": "Colecciones",
|
"LabelCollections": "Colecciones",
|
||||||
"LabelComplete": "Completo",
|
"LabelComplete": "Completo",
|
||||||
"LabelConfirmPassword": "Confirmar Contraseña",
|
"LabelConfirmPassword": "Confirmar contraseña",
|
||||||
"LabelContinueListening": "Seguir escuchando",
|
"LabelContinueListening": "Seguir escuchando",
|
||||||
"LabelContinueReading": "Continuar leyendo",
|
"LabelContinueReading": "Continuar leyendo",
|
||||||
"LabelContinueSeries": "Continuar series",
|
"LabelContinueSeries": "Continuar series",
|
||||||
@@ -287,8 +291,8 @@
|
|||||||
"LabelCronExpression": "Expresión de Cron",
|
"LabelCronExpression": "Expresión de Cron",
|
||||||
"LabelCurrent": "Actual",
|
"LabelCurrent": "Actual",
|
||||||
"LabelCurrently": "En este momento:",
|
"LabelCurrently": "En este momento:",
|
||||||
"LabelCustomCronExpression": "Expresión de Cron Personalizada:",
|
"LabelCustomCronExpression": "Expresión de Cron personalizada:",
|
||||||
"LabelDatetime": "Hora y Fecha",
|
"LabelDatetime": "Hora y fecha",
|
||||||
"LabelDays": "Días",
|
"LabelDays": "Días",
|
||||||
"LabelDeleteFromFileSystemCheckbox": "Eliminar del sistema de archivos (desmarque para quitar de la base de datos solamente)",
|
"LabelDeleteFromFileSystemCheckbox": "Eliminar del sistema de archivos (desmarque para quitar de la base de datos solamente)",
|
||||||
"LabelDescription": "Descripción",
|
"LabelDescription": "Descripción",
|
||||||
@@ -367,7 +371,7 @@
|
|||||||
"LabelFontStrikethrough": "Tachado",
|
"LabelFontStrikethrough": "Tachado",
|
||||||
"LabelFormat": "Formato",
|
"LabelFormat": "Formato",
|
||||||
"LabelFull": "Completo",
|
"LabelFull": "Completo",
|
||||||
"LabelGenre": "Genero",
|
"LabelGenre": "Género",
|
||||||
"LabelGenres": "Géneros",
|
"LabelGenres": "Géneros",
|
||||||
"LabelHardDeleteFile": "Eliminar Definitivamente",
|
"LabelHardDeleteFile": "Eliminar Definitivamente",
|
||||||
"LabelHasEbook": "Tiene un libro",
|
"LabelHasEbook": "Tiene un libro",
|
||||||
@@ -436,8 +440,8 @@
|
|||||||
"LabelMinute": "Minuto",
|
"LabelMinute": "Minuto",
|
||||||
"LabelMinutes": "Minutos",
|
"LabelMinutes": "Minutos",
|
||||||
"LabelMissing": "Falta",
|
"LabelMissing": "Falta",
|
||||||
"LabelMissingEbook": "No tiene ebook",
|
"LabelMissingEbook": "No tiene libro electrónico",
|
||||||
"LabelMissingSupplementaryEbook": "No tiene ebook suplementario",
|
"LabelMissingSupplementaryEbook": "No tiene libro electrónico suplementario",
|
||||||
"LabelMobileRedirectURIs": "URIs de redirección a móviles permitidos",
|
"LabelMobileRedirectURIs": "URIs de redirección a móviles permitidos",
|
||||||
"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.",
|
"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",
|
"LabelMore": "Más",
|
||||||
@@ -458,17 +462,17 @@
|
|||||||
"LabelNotes": "Notas",
|
"LabelNotes": "Notas",
|
||||||
"LabelNotificationAppriseURL": "URL(s) de Apprise",
|
"LabelNotificationAppriseURL": "URL(s) de Apprise",
|
||||||
"LabelNotificationAvailableVariables": "Variables disponibles",
|
"LabelNotificationAvailableVariables": "Variables disponibles",
|
||||||
"LabelNotificationBodyTemplate": "Plantilla de Cuerpo",
|
"LabelNotificationBodyTemplate": "Plantilla de cuerpo",
|
||||||
"LabelNotificationEvent": "Evento de Notificación",
|
"LabelNotificationEvent": "Evento de notificación",
|
||||||
"LabelNotificationTitleTemplate": "Plantilla de Titulo",
|
"LabelNotificationTitleTemplate": "Plantilla de título",
|
||||||
"LabelNotificationsMaxFailedAttempts": "Máximo de Intentos Fallidos",
|
"LabelNotificationsMaxFailedAttempts": "Máximo de intentos fallidos",
|
||||||
"LabelNotificationsMaxFailedAttemptsHelp": "Las notificaciones se desactivan después de fallar este número de veces",
|
"LabelNotificationsMaxFailedAttemptsHelp": "Las notificaciones se desactivan después de fallar este número de veces",
|
||||||
"LabelNotificationsMaxQueueSize": "Tamaño máximo de la cola de notificaciones",
|
"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.",
|
"LabelNotificationsMaxQueueSizeHelp": "Las notificaciones están limitadas a 1 por segundo. Las notificaciones serán ignoradas si llegan al numero máximo de cola para prevenir spam de eventos.",
|
||||||
"LabelNumberOfBooks": "Número de libros",
|
"LabelNumberOfBooks": "Número de libros",
|
||||||
"LabelNumberOfEpisodes": "N.º de episodios",
|
"LabelNumberOfEpisodes": "N.º de episodios",
|
||||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nombre de la notificación de OpenID que contiene permisos avanzados para acciones de usuario dentro de la aplicación que se aplicarán a roles que no sean de administrador (<b>si están configurados</b>). Si el reclamo no aparece en la respuesta, se denegará el acceso a ABS. Si falta una sola opción, se tratará como <code>falsa</code>. Asegúrese de que la notificación del proveedor de identidades coincida con la estructura esperada:",
|
"LabelOpenIDAdvancedPermsClaimDescription": "Nombre de la notificación de OpenID que contiene permisos avanzados para acciones de usuario dentro de la aplicación que se aplicarán a roles que no sean de administrador (<b>si están configurados</b>). Si el reclamo no aparece en la respuesta, se denegará el acceso a ABS. Si falta una sola opción, se tratará como <code>falsa</code>. Asegúrese de que la notificación del proveedor de identidades coincida con la estructura esperada:",
|
||||||
"LabelOpenIDClaims": "Deje las siguientes opciones vacías para deshabilitar la asignación avanzada de grupos y permisos, lo que asignaría de manera automática al grupo 'Usuario'.",
|
"LabelOpenIDClaims": "Deje las siguientes opciones vacías para desactivar la asignación avanzada de grupos y permisos, lo que asignaría de manera automática al grupo «Usuario».",
|
||||||
"LabelOpenIDGroupClaimDescription": "Nombre de la declaración OpenID que contiene una lista de grupos del usuario. Comúnmente conocidos como <code>grupos</code>. <b>Si se configura</b>, la aplicación asignará automáticamente roles en función de la pertenencia a grupos del usuario, siempre que estos grupos se denominen \"admin\", \"user\" o \"guest\" en la notificación. La solicitud debe contener una lista, y si un usuario pertenece a varios grupos, la aplicación asignará el rol correspondiente al mayor nivel de acceso. Si ningún grupo coincide, se denegará el acceso.",
|
"LabelOpenIDGroupClaimDescription": "Nombre de la declaración OpenID que contiene una lista de grupos del usuario. Comúnmente conocidos como <code>grupos</code>. <b>Si se configura</b>, la aplicación asignará automáticamente roles en función de la pertenencia a grupos del usuario, siempre que estos grupos se denominen \"admin\", \"user\" o \"guest\" en la notificación. La solicitud debe contener una lista, y si un usuario pertenece a varios grupos, la aplicación asignará el rol correspondiente al mayor nivel de acceso. Si ningún grupo coincide, se denegará el acceso.",
|
||||||
"LabelOpenRSSFeed": "Abrir suministro RSS",
|
"LabelOpenRSSFeed": "Abrir suministro RSS",
|
||||||
"LabelOverwrite": "Sobrescribir",
|
"LabelOverwrite": "Sobrescribir",
|
||||||
@@ -495,9 +499,9 @@
|
|||||||
"LabelPodcastType": "Tipo de pódcast",
|
"LabelPodcastType": "Tipo de pódcast",
|
||||||
"LabelPodcasts": "Pódcast",
|
"LabelPodcasts": "Pódcast",
|
||||||
"LabelPort": "Puerto",
|
"LabelPort": "Puerto",
|
||||||
"LabelPrefixesToIgnore": "Prefijos para Ignorar (no distingue entre mayúsculas y minúsculas.)",
|
"LabelPrefixesToIgnore": "Prefijos para ignorar (no distingue entre mayúsculas y minúsculas)",
|
||||||
"LabelPreventIndexing": "Evite que los directorios de pódcast de iTunes y Google indicen su suministro",
|
"LabelPreventIndexing": "Evite que los directorios de pódcast de iTunes y Google indicen su suministro",
|
||||||
"LabelPrimaryEbook": "Ebook principal",
|
"LabelPrimaryEbook": "Libro electrónico principal",
|
||||||
"LabelProgress": "Progreso",
|
"LabelProgress": "Progreso",
|
||||||
"LabelProvider": "Proveedor",
|
"LabelProvider": "Proveedor",
|
||||||
"LabelProviderAuthorizationValue": "Valor del encabezado de autorización",
|
"LabelProviderAuthorizationValue": "Valor del encabezado de autorización",
|
||||||
@@ -511,7 +515,7 @@
|
|||||||
"LabelRSSFeedCustomOwnerEmail": "Correo electrónico de dueño personalizado",
|
"LabelRSSFeedCustomOwnerEmail": "Correo electrónico de dueño personalizado",
|
||||||
"LabelRSSFeedCustomOwnerName": "Nombre de dueño personalizado",
|
"LabelRSSFeedCustomOwnerName": "Nombre de dueño personalizado",
|
||||||
"LabelRSSFeedOpen": "Suministro RSS abierto",
|
"LabelRSSFeedOpen": "Suministro RSS abierto",
|
||||||
"LabelRSSFeedPreventIndexing": "Prevenir indexado",
|
"LabelRSSFeedPreventIndexing": "Evitar indización",
|
||||||
"LabelRSSFeedSlug": "«Slug» de suministro RSS",
|
"LabelRSSFeedSlug": "«Slug» de suministro RSS",
|
||||||
"LabelRSSFeedURL": "URL de suministro RSS",
|
"LabelRSSFeedURL": "URL de suministro RSS",
|
||||||
"LabelRandomly": "Aleatorio",
|
"LabelRandomly": "Aleatorio",
|
||||||
@@ -527,6 +531,7 @@
|
|||||||
"LabelReleaseDate": "Fecha de estreno",
|
"LabelReleaseDate": "Fecha de estreno",
|
||||||
"LabelRemoveAllMetadataAbs": "Eliminar todos los archivos metadata.abs",
|
"LabelRemoveAllMetadataAbs": "Eliminar todos los archivos metadata.abs",
|
||||||
"LabelRemoveAllMetadataJson": "Eliminar todos los archivos metadata.json",
|
"LabelRemoveAllMetadataJson": "Eliminar todos los archivos metadata.json",
|
||||||
|
"LabelRemoveAudibleBranding": "Quitar introducción y cierre de Audible de los capítulos",
|
||||||
"LabelRemoveCover": "Quitar cubierta",
|
"LabelRemoveCover": "Quitar cubierta",
|
||||||
"LabelRemoveMetadataFile": "Eliminar archivos de metadatos en carpetas de elementos de biblioteca",
|
"LabelRemoveMetadataFile": "Eliminar archivos de metadatos en carpetas de elementos de biblioteca",
|
||||||
"LabelRemoveMetadataFileHelp": "Elimine todos los archivos metadata.json y metadata.abs de sus carpetas {0}.",
|
"LabelRemoveMetadataFileHelp": "Elimine todos los archivos metadata.json y metadata.abs de sus carpetas {0}.",
|
||||||
@@ -535,7 +540,7 @@
|
|||||||
"LabelSearchTitle": "Buscar título",
|
"LabelSearchTitle": "Buscar título",
|
||||||
"LabelSearchTitleOrASIN": "Buscar título o ASIN",
|
"LabelSearchTitleOrASIN": "Buscar título o ASIN",
|
||||||
"LabelSeason": "Temporada",
|
"LabelSeason": "Temporada",
|
||||||
"LabelSeasonNumber": "Sesión #{0}",
|
"LabelSeasonNumber": "{0}.ª temporada",
|
||||||
"LabelSelectAll": "Seleccionar todo",
|
"LabelSelectAll": "Seleccionar todo",
|
||||||
"LabelSelectAllEpisodes": "Seleccionar todos los episodios",
|
"LabelSelectAllEpisodes": "Seleccionar todos los episodios",
|
||||||
"LabelSelectEpisodesShowing": "Seleccionar los {0} episodios visibles",
|
"LabelSelectEpisodesShowing": "Seleccionar los {0} episodios visibles",
|
||||||
@@ -575,7 +580,7 @@
|
|||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Saltar libros anteriores de la serie Continuada",
|
"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.",
|
"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",
|
"LabelSettingsParseSubtitles": "Extraer Subtítulos",
|
||||||
"LabelSettingsParseSubtitlesHelp": "Extraer subtítulos de los nombres de las carpetas de los audiolibros.<br>Los subtítulos deben estar separados por \" - \"<br>Por ejemplo: \"Ejemplo de Título - Subtítulo Aquí\" tiene el subtítulo \"Subtítulo Aquí\"",
|
"LabelSettingsParseSubtitlesHelp": "Extraer subtítulos de los nombres de las carpetas de los audiolibros.<br>Los subtítulos deben estar separados por « - »<br>Así, «Título de libro - Un subtítulo aquí» tiene el subtítulo «Un subtítulo aquí»",
|
||||||
"LabelSettingsPreferMatchedMetadata": "Preferir metadatos encontrados",
|
"LabelSettingsPreferMatchedMetadata": "Preferir metadatos encontrados",
|
||||||
"LabelSettingsPreferMatchedMetadataHelp": "Los datos encontrados sobreescribirán los detalles del elemento cuando se use \"Encontrar Rápido\". Por defecto, \"Encontrar Rápido\" sólo completará los detalles faltantes.",
|
"LabelSettingsPreferMatchedMetadataHelp": "Los datos encontrados sobreescribirán los detalles del elemento cuando se use \"Encontrar Rápido\". Por defecto, \"Encontrar Rápido\" sólo completará los detalles faltantes.",
|
||||||
"LabelSettingsSkipMatchingBooksWithASIN": "Omitir libros coincidentes que ya tengan un ASIN",
|
"LabelSettingsSkipMatchingBooksWithASIN": "Omitir libros coincidentes que ya tengan un ASIN",
|
||||||
@@ -593,7 +598,7 @@
|
|||||||
"LabelShareDownloadableHelp": "Permite a quienes posean el enlace de compartición descargar un archivo ZIP del elemento de la biblioteca.",
|
"LabelShareDownloadableHelp": "Permite a quienes posean el enlace de compartición descargar un archivo ZIP del elemento de la biblioteca.",
|
||||||
"LabelShareOpen": "abrir un recurso compartido",
|
"LabelShareOpen": "abrir un recurso compartido",
|
||||||
"LabelShareURL": "Compartir la URL",
|
"LabelShareURL": "Compartir la URL",
|
||||||
"LabelShowAll": "Mostrar Todos",
|
"LabelShowAll": "Mostrar todo",
|
||||||
"LabelShowSeconds": "Mostrar segundos",
|
"LabelShowSeconds": "Mostrar segundos",
|
||||||
"LabelShowSubtitles": "Mostrar subtítulos",
|
"LabelShowSubtitles": "Mostrar subtítulos",
|
||||||
"LabelSize": "Tamaño",
|
"LabelSize": "Tamaño",
|
||||||
@@ -601,33 +606,34 @@
|
|||||||
"LabelSlug": "Slug",
|
"LabelSlug": "Slug",
|
||||||
"LabelSortAscending": "Ascendente",
|
"LabelSortAscending": "Ascendente",
|
||||||
"LabelSortDescending": "Descendente",
|
"LabelSortDescending": "Descendente",
|
||||||
|
"LabelSortPubDate": "Ord. fecha pub.",
|
||||||
"LabelStart": "Iniciar",
|
"LabelStart": "Iniciar",
|
||||||
"LabelStartTime": "Tiempo de Inicio",
|
"LabelStartTime": "Tiempo de Inicio",
|
||||||
"LabelStarted": "Iniciado",
|
"LabelStarted": "Iniciado",
|
||||||
"LabelStartedAt": "Iniciado En",
|
"LabelStartedAt": "Iniciado En",
|
||||||
"LabelStatsAudioTracks": "Pistas de Audio",
|
"LabelStatsAudioTracks": "Pistas de Audio",
|
||||||
"LabelStatsAuthors": "Autores",
|
"LabelStatsAuthors": "Autores",
|
||||||
"LabelStatsBestDay": "Mejor Día",
|
"LabelStatsBestDay": "Mejor día",
|
||||||
"LabelStatsDailyAverage": "Promedio Diario",
|
"LabelStatsDailyAverage": "Promedio diario",
|
||||||
"LabelStatsDays": "Días",
|
"LabelStatsDays": "Días",
|
||||||
"LabelStatsDaysListened": "Días Escuchando",
|
"LabelStatsDaysListened": "Días escuchando",
|
||||||
"LabelStatsHours": "Horas",
|
"LabelStatsHours": "Horas",
|
||||||
"LabelStatsInARow": "seguidos",
|
"LabelStatsInARow": "seguidos",
|
||||||
"LabelStatsItemsFinished": "Elementos Terminados",
|
"LabelStatsItemsFinished": "Elementos terminados",
|
||||||
"LabelStatsItemsInLibrary": "Elementos en biblioteca",
|
"LabelStatsItemsInLibrary": "Elementos en biblioteca",
|
||||||
"LabelStatsMinutes": "minutos",
|
"LabelStatsMinutes": "minutos",
|
||||||
"LabelStatsMinutesListening": "Minutos Escuchando",
|
"LabelStatsMinutesListening": "Minutos escuchando",
|
||||||
"LabelStatsOverallDays": "Total de Dias",
|
"LabelStatsOverallDays": "Total de días",
|
||||||
"LabelStatsOverallHours": "Total de Horas",
|
"LabelStatsOverallHours": "Total de horas",
|
||||||
"LabelStatsWeekListening": "Tiempo escuchando en la Semana",
|
"LabelStatsWeekListening": "Tiempo escuchando en la semana",
|
||||||
"LabelSubtitle": "Subtítulo",
|
"LabelSubtitle": "Subtítulo",
|
||||||
"LabelSupportedFileTypes": "Tipos de archivo admitidos",
|
"LabelSupportedFileTypes": "Tipos de archivo admitidos",
|
||||||
"LabelTag": "Etiqueta",
|
"LabelTag": "Etiqueta",
|
||||||
"LabelTags": "Etiquetas",
|
"LabelTags": "Etiquetas",
|
||||||
"LabelTagsAccessibleToUser": "Etiquetas Accessibles al Usuario",
|
"LabelTagsAccessibleToUser": "Etiquetas accessibles al usuario",
|
||||||
"LabelTagsNotAccessibleToUser": "Etiquetas no Accesibles al Usuario",
|
"LabelTagsNotAccessibleToUser": "Etiquetas no accesibles al usuario",
|
||||||
"LabelTasks": "Tareas Corriendo",
|
"LabelTasks": "Tareas en ejecución",
|
||||||
"LabelTextEditorBulletedList": "Lista con viñetas",
|
"LabelTextEditorBulletedList": "Lista con bolos",
|
||||||
"LabelTextEditorLink": "Enlazar",
|
"LabelTextEditorLink": "Enlazar",
|
||||||
"LabelTextEditorNumberedList": "Lista numerada",
|
"LabelTextEditorNumberedList": "Lista numerada",
|
||||||
"LabelTextEditorUnlink": "Desenlazar",
|
"LabelTextEditorUnlink": "Desenlazar",
|
||||||
@@ -680,7 +686,7 @@
|
|||||||
"LabelUseFullTrack": "Usar pista completa",
|
"LabelUseFullTrack": "Usar pista completa",
|
||||||
"LabelUseZeroForUnlimited": "Utilice 0 para ilimitado",
|
"LabelUseZeroForUnlimited": "Utilice 0 para ilimitado",
|
||||||
"LabelUser": "Usuario",
|
"LabelUser": "Usuario",
|
||||||
"LabelUsername": "Nombre de Usuario",
|
"LabelUsername": "Nombre de usuario",
|
||||||
"LabelValue": "Valor",
|
"LabelValue": "Valor",
|
||||||
"LabelVersion": "Versión",
|
"LabelVersion": "Versión",
|
||||||
"LabelViewBookmarks": "Ver Marcadores",
|
"LabelViewBookmarks": "Ver Marcadores",
|
||||||
@@ -693,89 +699,95 @@
|
|||||||
"LabelWeekdaysToRun": "Correr en Días de la Semana",
|
"LabelWeekdaysToRun": "Correr en Días de la Semana",
|
||||||
"LabelXBooks": "{0} libros",
|
"LabelXBooks": "{0} libros",
|
||||||
"LabelXItems": "{0} elementos",
|
"LabelXItems": "{0} elementos",
|
||||||
"LabelYearReviewHide": "Ocultar Resumen del año",
|
"LabelYearReviewHide": "Ocultar resumen del año",
|
||||||
"LabelYearReviewShow": "Resumen del año",
|
"LabelYearReviewShow": "Ver resumen del año",
|
||||||
"LabelYourAudiobookDuration": "Duración de tu Audiolibro",
|
"LabelYourAudiobookDuration": "Duración de tu Audiolibro",
|
||||||
"LabelYourBookmarks": "Tus Marcadores",
|
"LabelYourBookmarks": "Sus marcadores",
|
||||||
"LabelYourPlaylists": "Tus Listas",
|
"LabelYourPlaylists": "Tus Listas",
|
||||||
"LabelYourProgress": "Su progreso",
|
"LabelYourProgress": "Su progreso",
|
||||||
"MessageAddToPlayerQueue": "Agregar a fila del Reproductor",
|
"MessageAddToPlayerQueue": "Agregar a fila del Reproductor",
|
||||||
"MessageAppriseDescription": "Para usar esta función deberás tener <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">la API de Apprise</a> corriendo o una API que maneje los mismos resultados. <br/>La URL de la API de Apprise debe tener la misma ruta de archivos que donde se envían las notificaciones. Por ejemplo: si su API esta en <code>http://192.168.1.1:8337</code> entonces pondría <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "Para usar esta función deberás tener <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">la API de Apprise</a> corriendo o una API que maneje los mismos resultados. <br/>La URL de la API de Apprise debe tener la misma ruta de archivos que donde se envían las notificaciones. Por ejemplo: si su API esta en <code>http://192.168.1.1:8337</code> entonces pondría <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAsinCheck": "Cerciórese de usar el ASIN de la región correcta de Audible, no de Amazon.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Reinicie el servidor tras el guardado para aplicar los cambios de OIDC.",
|
||||||
"MessageBackupsDescription": "Los respaldos incluyen: usuarios, el progreso del los usuarios, los detalles de los elementos de la biblioteca, la configuración del servidor y las imágenes en <code>/metadata/items</code> y <code>/metadata/authors</code>. Los Respaldos <strong>NO</strong> incluyen ningún archivo guardado en la carpeta de tu biblioteca.",
|
"MessageBackupsDescription": "Los respaldos incluyen: usuarios, el progreso del los usuarios, los detalles de los elementos de la biblioteca, la configuración del servidor y las imágenes en <code>/metadata/items</code> y <code>/metadata/authors</code>. Los Respaldos <strong>NO</strong> incluyen ningún archivo guardado en la carpeta de tu biblioteca.",
|
||||||
"MessageBackupsLocationEditNote": "Nota: actualizar la ubicación de la copia de respaldo no moverá ni modificará los respaldos existentes",
|
"MessageBackupsLocationEditNote": "Nota: actualizar la ubicación de la copia de respaldo no moverá ni modificará los respaldos existentes",
|
||||||
"MessageBackupsLocationNoEditNote": "Nota: la ubicación de la copia de respaldo se establece a través de una variable de entorno y no se puede cambiar aquí.",
|
"MessageBackupsLocationNoEditNote": "Nota: la ubicación de la copia de respaldo se establece a través de una variable de entorno y no se puede cambiar aquí.",
|
||||||
"MessageBackupsLocationPathEmpty": "La ruta de la copia de seguridad no puede estar vacía",
|
"MessageBackupsLocationPathEmpty": "La ruta de la copia de seguridad no puede estar vacía",
|
||||||
|
"MessageBatchEditPopulateMapDetailsAllHelp": "Rellenar campos activados con datos de todos los elementos. Los campos con varios valores se combinarán",
|
||||||
|
"MessageBatchEditPopulateMapDetailsItemHelp": "Rellenar campos de detalles de mapa con datos de este elemento",
|
||||||
"MessageBatchQuickMatchDescription": "\"Encontrar Rápido\" tratará de agregar portadas y metadatos faltantes de los elementos seleccionados. Habilite la opción de abajo para que \"Encontrar Rápido\" pueda sobrescribir portadas y/o metadatos existentes.",
|
"MessageBatchQuickMatchDescription": "\"Encontrar Rápido\" tratará de agregar portadas y metadatos faltantes de los elementos seleccionados. Habilite la opción de abajo para que \"Encontrar Rápido\" pueda sobrescribir portadas y/o metadatos existentes.",
|
||||||
"MessageBookshelfNoCollections": "Aún no ha hecho ninguna colección",
|
"MessageBookshelfNoCollections": "Aún no ha hecho ninguna colección",
|
||||||
"MessageBookshelfNoCollectionsHelp": "Las colecciones son públicas. Cualquiera que pueda acceder a la biblioteca las podrá ver.",
|
"MessageBookshelfNoCollectionsHelp": "Las colecciones son públicas. Cualquiera que pueda acceder a la biblioteca las podrá ver.",
|
||||||
"MessageBookshelfNoRSSFeeds": "Ningún suministro RSS está abierto",
|
"MessageBookshelfNoRSSFeeds": "Ningún suministro RSS está abierto",
|
||||||
"MessageBookshelfNoResultsForFilter": "Ningún Resultado para el filtro \"{0}: {1}\"",
|
"MessageBookshelfNoResultsForFilter": "El filtro «{0}: {1}» no produjo ningún resultado",
|
||||||
"MessageBookshelfNoResultsForQuery": "No hay resultados para la consulta",
|
"MessageBookshelfNoResultsForQuery": "No hay resultados para la consulta",
|
||||||
"MessageBookshelfNoSeries": "No tiene ninguna serie",
|
"MessageBookshelfNoSeries": "No tiene ninguna serie",
|
||||||
"MessageChapterEndIsAfter": "El final del capítulo es después del final de tu audiolibro",
|
"MessageChapterEndIsAfter": "El final del capítulo es después del final de tu audiolibro",
|
||||||
"MessageChapterErrorFirstNotZero": "El primer capitulo debe iniciar en 0",
|
"MessageChapterErrorFirstNotZero": "El primer capítulo debe iniciar en 0",
|
||||||
"MessageChapterErrorStartGteDuration": "El tiempo de inicio no es válido: debe ser inferior a la duración del audiolibro",
|
"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",
|
"MessageChapterErrorStartLtPrev": "El tiempo de inicio no es válido: debe ser mayor o igual que el tiempo de inicio del capítulo anterior",
|
||||||
"MessageChapterStartIsAfter": "El comienzo del capítulo es después del final de su audiolibro",
|
"MessageChapterStartIsAfter": "El comienzo del capítulo es después del final de su audiolibro",
|
||||||
|
"MessageChaptersNotFound": "Capítulos no encontrados",
|
||||||
"MessageCheckingCron": "Revisando cron...",
|
"MessageCheckingCron": "Revisando cron...",
|
||||||
"MessageConfirmCloseFeed": "¿Confirma que quiere cerrar este suministro?",
|
"MessageConfirmCloseFeed": "¿Confirma que quiere cerrar este suministro?",
|
||||||
"MessageConfirmDeleteBackup": "¿Está seguro de que desea eliminar el respaldo {0}?",
|
"MessageConfirmDeleteBackup": "¿Confirma que quiere eliminar el respaldo de {0}?",
|
||||||
"MessageConfirmDeleteDevice": "¿Estás seguro de que deseas eliminar el lector electrónico \"{0}\"?",
|
"MessageConfirmDeleteDevice": "¿Confirma que quiere eliminar el lector electrónico «{0}»?",
|
||||||
"MessageConfirmDeleteFile": "Esto eliminará el archivo de su sistema de archivos. ¿Está seguro?",
|
"MessageConfirmDeleteFile": "Esto eliminará el archivo del sistema de archivos. ¿Quiere continuar?",
|
||||||
"MessageConfirmDeleteLibrary": "¿Está seguro de que desea eliminar permanentemente la biblioteca \"{0}\"?",
|
"MessageConfirmDeleteLibrary": "¿Confirma que quiere eliminar permanentemente la biblioteca «{0}»?",
|
||||||
"MessageConfirmDeleteLibraryItem": "Esto eliminará el elemento de la biblioteca de la base de datos y del sistema de archivos. ¿Confirma que quiere hacerlo?",
|
"MessageConfirmDeleteLibraryItem": "Esto eliminará el elemento de la biblioteca de la base de datos y del sistema de archivos. ¿Confirma que quiere hacerlo?",
|
||||||
"MessageConfirmDeleteLibraryItems": "Esto eliminará {0} elementos de la biblioteca de la base de datos y del sistema de archivos. ¿Confirma que quiere hacerlo?",
|
"MessageConfirmDeleteLibraryItems": "Esto eliminará {0} elementos de la biblioteca de la base de datos y del sistema de archivos. ¿Confirma que quiere hacerlo?",
|
||||||
"MessageConfirmDeleteMetadataProvider": "¿Estás seguro de que deseas eliminar el proveedor de metadatos personalizado \"{0}\"?",
|
"MessageConfirmDeleteMetadataProvider": "¿Confirma que quiere eliminar el proveedor de metadatos personalizado «{0}»?",
|
||||||
"MessageConfirmDeleteNotification": "¿Estás seguro de que deseas eliminar esta notificación?",
|
"MessageConfirmDeleteNotification": "¿Confirma que quiere eliminar esta notificación?",
|
||||||
"MessageConfirmDeleteSession": "¿Está seguro de que desea eliminar esta sesión?",
|
"MessageConfirmDeleteSession": "¿Confirma que quiere eliminar esta sesión?",
|
||||||
"MessageConfirmEmbedMetadataInAudioFiles": "¿Está seguro de que desea incrustar metadatos en {0} archivos de audio?",
|
"MessageConfirmEmbedMetadataInAudioFiles": "¿Confirma que quiere incrustar metadatos en {0} archivos de audio?",
|
||||||
"MessageConfirmForceReScan": "¿Está seguro de que desea forzar un re-escaneo?",
|
"MessageConfirmForceReScan": "¿Confirma que quiere forzar un reescaneo?",
|
||||||
"MessageConfirmMarkAllEpisodesFinished": "¿Está seguro de que desea marcar todos los episodios como terminados?",
|
"MessageConfirmMarkAllEpisodesFinished": "¿Confirma que quiere marcar todos los episodios como terminados?",
|
||||||
"MessageConfirmMarkAllEpisodesNotFinished": "¿Está seguro de que desea marcar todos los episodios como no terminados?",
|
"MessageConfirmMarkAllEpisodesNotFinished": "¿Confirma que quiere marcar todos los episodios como no terminados?",
|
||||||
"MessageConfirmMarkItemFinished": "¿Estás seguro de que deseas marcar \"{0}\" como terminado?",
|
"MessageConfirmMarkItemFinished": "¿Confirma que quiere marcar «{0}» como terminado?",
|
||||||
"MessageConfirmMarkItemNotFinished": "¿Estás seguro de que deseas marcar \"{0}\" como no acabado?",
|
"MessageConfirmMarkItemNotFinished": "¿Confirma que quiere marcar «{0}» como no terminado?",
|
||||||
"MessageConfirmMarkSeriesFinished": "¿Está seguro de que desea marcar todos los libros en esta serie como terminados?",
|
"MessageConfirmMarkSeriesFinished": "¿Confirma que quiere marcar todos los libros de esta serie como terminados?",
|
||||||
"MessageConfirmMarkSeriesNotFinished": "¿Está seguro de que desea marcar todos los libros en esta serie como no terminados?",
|
"MessageConfirmMarkSeriesNotFinished": "¿Confirma que quiere marcar todos los libros de esta serie como no terminados?",
|
||||||
"MessageConfirmNotificationTestTrigger": "¿Activar esta notificación con datos de prueba?",
|
"MessageConfirmNotificationTestTrigger": "¿Activar esta notificación con datos de prueba?",
|
||||||
"MessageConfirmPurgeCache": "Purgar el caché eliminará el directorio completo ubicado en <code>/metadata/cache</code>. <br /><br />¿Está seguro que desea eliminar el directorio del caché?",
|
"MessageConfirmPurgeCache": "Purgar la antememoria eliminará el directorio completo ubicado en <code>/metadata/cache</code>. <br /><br />¿Confirma que quiere eliminar el directorio de antememoria?",
|
||||||
"MessageConfirmPurgeItemsCache": "Purgar la caché de los elementos eliminará todo el directorio <code>/metadata/cache/items</code>.<br />¿Estás seguro?",
|
"MessageConfirmPurgeItemsCache": "Purgar la antememoria de elementos eliminará el directorio completo ubicado en <code>/metadata/cache/items</code>.<br />¿Lo confirma?",
|
||||||
"MessageConfirmQuickEmbed": "¡Advertencia! La integración rápida no realiza copias de seguridad a ninguno de tus archivos de audio. Asegúrate de haber realizado una copia de los mismos previamente. <br><br>¿Deseas continuar?",
|
"MessageConfirmQuickEmbed": "Atención: la incrustación rápida no realiza copias de respaldo a ninguno de sus archivos de audio. Cerciórese de haber realizado una copia de los mismos previamente. <br><br>¿Quiere continuar?",
|
||||||
"MessageConfirmQuickMatchEpisodes": "El reconocimiento rápido de extensiones sobrescribirá los detalles si se encuentra una coincidencia. Se actualizarán las extensiones no reconocidas. ¿Está seguro?",
|
"MessageConfirmQuickMatchEpisodes": "El reconocimiento rápido de extensiones sobrescribirá los detalles si se encuentra una coincidencia. Se actualizarán las extensiones no reconocidas. ¿Quiere continuar?",
|
||||||
"MessageConfirmReScanLibraryItems": "¿Estás seguro de querer re escanear {0} elemento(s)?",
|
"MessageConfirmReScanLibraryItems": "¿Confirma que quiere volver a analizar {0} elementos?",
|
||||||
"MessageConfirmRemoveAllChapters": "¿Está seguro de que desea remover todos los capitulos?",
|
"MessageConfirmRemoveAllChapters": "¿Confirma que quiere quitar todos los capítulos?",
|
||||||
"MessageConfirmRemoveAuthor": "¿Está seguro de que desea remover el autor \"{0}\"?",
|
"MessageConfirmRemoveAuthor": "¿Confirma que quiere quitar el autor «{0}»?",
|
||||||
"MessageConfirmRemoveCollection": "¿Está seguro de que desea remover la colección \"{0}\"?",
|
"MessageConfirmRemoveCollection": "¿Confirma que quiere quitar la colección «{0}»?",
|
||||||
"MessageConfirmRemoveEpisode": "¿Está seguro de que desea remover el episodio \"{0}\"?",
|
"MessageConfirmRemoveEpisode": "¿Confirma que quiere quitar el episodio «{0}»?",
|
||||||
"MessageConfirmRemoveEpisodes": "¿Está seguro de que desea remover {0} episodios?",
|
"MessageConfirmRemoveEpisodes": "¿Confirma que quiere quitar {0} episodios?",
|
||||||
"MessageConfirmRemoveListeningSessions": "¿Está seguro que desea remover {0} sesiones de escuchar?",
|
"MessageConfirmRemoveListeningSessions": "¿Confirma que quiere quitar {0} sesiones de escucha?",
|
||||||
"MessageConfirmRemoveMetadataFiles": "¿Está seguro de que desea eliminar todos los archivos de metadatos.{0} en las carpetas de elementos de su biblioteca?",
|
"MessageConfirmRemoveMetadataFiles": "¿Confirma que quiere quitar todos los archivos metadata.{0} en las carpetas de elementos de su biblioteca?",
|
||||||
"MessageConfirmRemoveNarrator": "¿Está seguro de que desea remover el narrador \"{0}\"?",
|
"MessageConfirmRemoveNarrator": "¿Confirma que quiere quitar el narrador «{0}»?",
|
||||||
"MessageConfirmRemovePlaylist": "¿Está seguro de que desea remover la lista de reproducción \"{0}\"?",
|
"MessageConfirmRemovePlaylist": "¿Confirma que quiere quitar la lista de reproducción «{0}»?",
|
||||||
"MessageConfirmRenameGenre": "¿Está seguro de que desea renombrar el genero \"{0}\" a \"{1}\" de todos los elementos?",
|
"MessageConfirmRenameGenre": "¿Confirma que quiere cambiar el nombre del género «{0}» a «{1}» en todos los elementos?",
|
||||||
"MessageConfirmRenameGenreMergeNote": "Nota: Este género ya existe, por lo que se fusionarán.",
|
"MessageConfirmRenameGenreMergeNote": "Nota: Este género ya existe, por lo que se fusionarán.",
|
||||||
"MessageConfirmRenameGenreWarning": "Advertencia! Un genero similar ya existe \"{0}\".",
|
"MessageConfirmRenameGenreWarning": "¡Atención! Ya existe un género similar con distinta mayusculación, «{0}».",
|
||||||
"MessageConfirmRenameTag": "¿Está seguro de que desea renombrar la etiqueta \"{0}\" a \"{1}\" de todos los elementos?",
|
"MessageConfirmRenameTag": "¿Confirma que quiere cambiar el nombre de la etiqueta «{0}» a «{1}» en todos los elementos?",
|
||||||
"MessageConfirmRenameTagMergeNote": "Nota: Esta etiqueta ya existe, por lo que se fusionarán.",
|
"MessageConfirmRenameTagMergeNote": "Nota: esta etiqueta ya existe, por lo que se fusionarán.",
|
||||||
"MessageConfirmRenameTagWarning": "Advertencia! Una etiqueta similar ya existe \"{0}\".",
|
"MessageConfirmRenameTagWarning": "¡Atención! Ya existe una etiqueta similar con distinta mayusculación, «{0}».",
|
||||||
"MessageConfirmResetProgress": "¿Estás seguro de que quieres reiniciar tu progreso?",
|
"MessageConfirmResetProgress": "¿Confirma que quiere restablecer su progreso?",
|
||||||
"MessageConfirmSendEbookToDevice": "¿Está seguro de que enviar {0} ebook(s) \"{1}\" al dispositivo \"{2}\"?",
|
"MessageConfirmSendEbookToDevice": "¿Confirma que quiere enviar el libro electrónico {0} «{1}» al dispositivo «{2}»?",
|
||||||
"MessageConfirmUnlinkOpenId": "¿Estás seguro de que deseas desvincular este usuario de OpenID?",
|
"MessageConfirmUnlinkOpenId": "¿Confirma que quiere desenlazar este usuario de OpenID?",
|
||||||
"MessageDaysListenedInTheLastYear": "{0} dies escoltats en l'últim any",
|
"MessageDaysListenedInTheLastYear": "{0} días escuchados el año pasado",
|
||||||
"MessageDownloadingEpisode": "Descargando Capitulo",
|
"MessageDownloadingEpisode": "Descargando episodio",
|
||||||
"MessageDragFilesIntoTrackOrder": "Arrastra los archivos al orden correcto de las pistas",
|
"MessageDragFilesIntoTrackOrder": "Arrastre los archivos al orden correcto de las pistas",
|
||||||
"MessageEmbedFailed": "¡Error al insertar!",
|
"MessageEmbedFailed": "Falló la incrustación.",
|
||||||
"MessageEmbedFinished": "Incrustación Terminada!",
|
"MessageEmbedFinished": "Finalizó la incrustación.",
|
||||||
"MessageEmbedQueue": "En cola para incrustar metadatos ({0} en cola)",
|
"MessageEmbedQueue": "En cola para incrustar metadatos ({0} en cola)",
|
||||||
"MessageEpisodesQueuedForDownload": "{0} Episodio(s) en cola para descargar",
|
"MessageEpisodesQueuedForDownload": "{0} episodio(s) en cola para descargar",
|
||||||
"MessageEreaderDevices": "Para garantizar la entrega de libros electrónicos, es posible que tenga que agregar la dirección de correo electrónico anterior como remitente válido para cada dispositivo enumerado a continuación.",
|
"MessageEreaderDevices": "Para garantizar la entrega de libros electrónicos, es posible que tenga que agregar la dirección de correo electrónico anterior como remitente válido para cada dispositivo enumerado a continuación.",
|
||||||
"MessageFeedURLWillBe": "El URL del suministro será {0}",
|
"MessageFeedURLWillBe": "El URL del suministro será {0}",
|
||||||
"MessageFetching": "Buscando...",
|
"MessageFetching": "Recuperando...",
|
||||||
"MessageForceReScanDescription": "Escaneará todos los archivos como un nuevo escaneo. Archivos de audio con etiquetas ID3, archivos OPF y archivos de texto serán escaneados como nuevos.",
|
"MessageForceReScanDescription": "Escaneará todos los archivos como un nuevo escaneo. Archivos de audio con etiquetas ID3, archivos OPF y archivos de texto serán escaneados como nuevos.",
|
||||||
"MessageImportantNotice": "¡Notificación importante!",
|
"MessageImportantNotice": "¡Notificación importante!",
|
||||||
"MessageInsertChapterBelow": "Insertar Capítulo Abajo",
|
"MessageInsertChapterBelow": "Insertar capítulo debajo",
|
||||||
|
"MessageInvalidAsin": "ASIN no válido",
|
||||||
"MessageItemsSelected": "{0} elementos seleccionados",
|
"MessageItemsSelected": "{0} elementos seleccionados",
|
||||||
"MessageItemsUpdated": "{0} elementos actualizados",
|
"MessageItemsUpdated": "{0} elementos actualizados",
|
||||||
"MessageJoinUsOn": "Únetenos en",
|
"MessageJoinUsOn": "Únase a nosotros en",
|
||||||
"MessageLoading": "Cargando...",
|
"MessageLoading": "Cargando...",
|
||||||
"MessageLoadingFolders": "Cargando archivos...",
|
"MessageLoadingFolders": "Cargando archivos...",
|
||||||
"MessageLogsDescription": "Logs son almacenados en <code>/metadata/logs</code> en archivos bajo formato JSON. Logs de fallos son almacenados en <code>/metadata/logs/crash_logs.txt</code>.",
|
"MessageLogsDescription": "Logs son almacenados en <code>/metadata/logs</code> en archivos bajo formato JSON. Logs de fallos son almacenados en <code>/metadata/logs/crash_logs.txt</code>.",
|
||||||
@@ -799,19 +811,19 @@
|
|||||||
"MessageNoDownloadsInProgress": "No hay descargas actualmente en curso",
|
"MessageNoDownloadsInProgress": "No hay descargas actualmente en curso",
|
||||||
"MessageNoDownloadsQueued": "Sin Lista de Descarga",
|
"MessageNoDownloadsQueued": "Sin Lista de Descarga",
|
||||||
"MessageNoEpisodeMatchesFound": "No se encontraron episodios que coinciden",
|
"MessageNoEpisodeMatchesFound": "No se encontraron episodios que coinciden",
|
||||||
"MessageNoEpisodes": "Sin Episodios",
|
"MessageNoEpisodes": "Ningún episodio",
|
||||||
"MessageNoFoldersAvailable": "No Hay Carpetas Disponibles",
|
"MessageNoFoldersAvailable": "Ninguna carpeta disponible",
|
||||||
"MessageNoGenres": "Sin Géneros",
|
"MessageNoGenres": "Ningún género",
|
||||||
"MessageNoIssues": "Sin Problemas",
|
"MessageNoIssues": "Ningún número",
|
||||||
"MessageNoItems": "Sin elementos",
|
"MessageNoItems": "Ningún elemento",
|
||||||
"MessageNoItemsFound": "Ningún elemento encontrado",
|
"MessageNoItemsFound": "Ningún elemento encontrado",
|
||||||
"MessageNoListeningSessions": "Ninguna sesión escuchada",
|
"MessageNoListeningSessions": "Ninguna sesión de escucha",
|
||||||
"MessageNoLogs": "Ningún registro",
|
"MessageNoLogs": "Ningún registro",
|
||||||
"MessageNoMediaProgress": "Multimedia sin Progreso",
|
"MessageNoMediaProgress": "Multimedia sin Progreso",
|
||||||
"MessageNoNotifications": "Ninguna notificación",
|
"MessageNoNotifications": "Ninguna notificación",
|
||||||
"MessageNoPodcastFeed": "Podcast no válido: Sin feed",
|
"MessageNoPodcastFeed": "Pódcast no válido: no hay suministro",
|
||||||
"MessageNoPodcastsFound": "Ningún podcast encontrado",
|
"MessageNoPodcastsFound": "No se encontró ningún pódcast",
|
||||||
"MessageNoResults": "Sin Resultados",
|
"MessageNoResults": "Ningún resultado",
|
||||||
"MessageNoSearchResultsFor": "La búsqueda «{0}» no produjo ningún resultado",
|
"MessageNoSearchResultsFor": "La búsqueda «{0}» no produjo ningún resultado",
|
||||||
"MessageNoSeries": "Ninguna serie",
|
"MessageNoSeries": "Ninguna serie",
|
||||||
"MessageNoTags": "Ninguna etiqueta",
|
"MessageNoTags": "Ninguna etiqueta",
|
||||||
@@ -819,60 +831,62 @@
|
|||||||
"MessageNoUpdatesWereNecessary": "No fue necesario actualizar",
|
"MessageNoUpdatesWereNecessary": "No fue necesario actualizar",
|
||||||
"MessageNoUserPlaylists": "No tiene ninguna lista de reproducción",
|
"MessageNoUserPlaylists": "No tiene ninguna lista de reproducción",
|
||||||
"MessageNoUserPlaylistsHelp": "Las listas de reproducción son privadas. Solo quien las cree podrá verlas.",
|
"MessageNoUserPlaylistsHelp": "Las listas de reproducción son privadas. Solo quien las cree podrá verlas.",
|
||||||
"MessageNotYetImplemented": "Aun no implementado",
|
"MessageNotYetImplemented": "Aún no implementado",
|
||||||
"MessageOpmlPreviewNote": "Nota: Esta es una vista previa del archivo OPML analizado. El título real del podcast se obtendrá del canal RSS.",
|
"MessageOpmlPreviewNote": "Nota: Esta es una vista previa del archivo OPML analizado. El título real del podcast se obtendrá del canal RSS.",
|
||||||
"MessageOr": "o",
|
"MessageOr": "o",
|
||||||
"MessagePauseChapter": "Pausar la reproducción del capítulo",
|
"MessagePauseChapter": "Pausar la reproducción del capítulo",
|
||||||
"MessagePlayChapter": "Escuchar el comienzo del capítulo",
|
"MessagePlayChapter": "Escuchar el comienzo del capítulo",
|
||||||
"MessagePlaylistCreateFromCollection": "Crear una lista de reproducción a partir de una colección",
|
"MessagePlaylistCreateFromCollection": "Crear una lista de reproducción a partir de una colección",
|
||||||
"MessagePleaseWait": "Por favor, espera...",
|
"MessagePleaseWait": "Espere…",
|
||||||
"MessagePodcastHasNoRSSFeedForMatching": "El pódcast no tiene un URL de suministro RSS que pueda usarse para encontrar correspondencias",
|
"MessagePodcastHasNoRSSFeedForMatching": "El pódcast no tiene un URL de suministro RSS que pueda usarse para encontrar correspondencias",
|
||||||
"MessagePodcastSearchField": "Introduzca el término de búsqueda o el URL del suministro RSS",
|
"MessagePodcastSearchField": "Introduzca el término de búsqueda o el URL del suministro RSS",
|
||||||
"MessageQuickEmbedInProgress": "Integración rápida en proceso",
|
"MessageQuickEmbedInProgress": "Integración rápida en proceso",
|
||||||
"MessageQuickEmbedQueue": "En cola para inserción rápida ({0} en cola)",
|
"MessageQuickEmbedQueue": "En cola para inserción rápida ({0} en cola)",
|
||||||
"MessageQuickMatchAllEpisodes": "Combina rápidamente todos los episodios",
|
"MessageQuickMatchAllEpisodes": "Combina rápidamente todos los episodios",
|
||||||
"MessageQuickMatchDescription": "Rellenar detalles de elementos vacíos y portada con los primeros resultados de '{0}'. No sobrescribe los detalles a menos que la opción \"Preferir Metadatos Encontrados\" del servidor esté habilitada.",
|
"MessageQuickMatchDescription": "Rellena los detalles y la cubierta de los elementos vacíos con el primer resultado coincidente de «{0}». No sobrescribe los detalles a menos que se active la opción del servidor «Preferir metadatos coincidentes».",
|
||||||
"MessageRemoveChapter": "Remover capítulos",
|
"MessageRemoveChapter": "Quitar capítulo",
|
||||||
"MessageRemoveEpisodes": "Remover {0} episodio(s)",
|
"MessageRemoveEpisodes": "Quitar {0} episodio(s)",
|
||||||
"MessageRemoveFromPlayerQueue": "Remover la cola de reproducción",
|
"MessageRemoveFromPlayerQueue": "Quitar de la cola de reproducción",
|
||||||
"MessageRemoveUserWarning": "¿Está seguro de que desea eliminar el usuario \"{0}\"?",
|
"MessageRemoveUserWarning": "¿Confirma que quiere eliminar permanentemente el usuario «{0}»?",
|
||||||
"MessageReportBugsAndContribute": "Reporte erres, solicite funciones y contribuya en",
|
"MessageReportBugsAndContribute": "Informe de defectos, solicite funciones y contribuya en",
|
||||||
"MessageResetChaptersConfirm": "¿Está seguro de que desea deshacer los cambios y revertir los capítulos a su estado original?",
|
"MessageResetChaptersConfirm": "¿Confirma que quiere deshacer los cambios y restablecer los capítulos a su estado original?",
|
||||||
"MessageRestoreBackupConfirm": "¿Está seguro de que desea para restaurar del respaldo creado en",
|
"MessageRestoreBackupConfirm": "¿Confirma que quiere restaurar el respaldo creado el",
|
||||||
"MessageRestoreBackupWarning": "Restaurar sobrescribirá toda la base de datos localizada en /config y las imágenes de portadas en /metadata/items y /metadata/authors.<br /><br />El respaldo no modifica ningún archivo en las carpetas de su biblioteca. Si ha habilitado la opción del servidor para almacenar portadas y metadata en las carpetas de su biblioteca, esos archivos no se respaldan o sobrescriben.<br /><br />Todos los clientes que usen su servidor se actualizarán automáticamente.",
|
"MessageRestoreBackupWarning": "Restaurar sobrescribirá toda la base de datos localizada en /config y las imágenes de portadas en /metadata/items y /metadata/authors.<br /><br />El respaldo no modifica ningún archivo en las carpetas de su biblioteca. Si ha habilitado la opción del servidor para almacenar portadas y metadata en las carpetas de su biblioteca, esos archivos no se respaldan o sobrescriben.<br /><br />Todos los clientes que usen su servidor se actualizarán automáticamente.",
|
||||||
"MessageScheduleLibraryScanNote": "Para la mayoría de los usuarios, se recomienda dejar esta función desactivada y mantener activada la configuración del observador de carpetas. El observador de carpetas detectará automáticamente los cambios en las carpetas de la biblioteca. El observador de carpetas no funciona para todos los sistemas de archivos (como NFS), por lo que se pueden utilizar exploraciones programadas de la biblioteca en su lugar.",
|
"MessageScheduleLibraryScanNote": "Para la mayoría de los usuarios, se recomienda dejar esta función desactivada y mantener activada la configuración del observador de carpetas. El observador de carpetas detectará automáticamente los cambios en las carpetas de la biblioteca. El observador de carpetas no funciona para todos los sistemas de archivos (como NFS), por lo que se pueden utilizar exploraciones programadas de la biblioteca en su lugar.",
|
||||||
|
"MessageScheduleRunEveryWeekdayAtTime": "Ejecutar cada {0} a las {1}",
|
||||||
"MessageSearchResultsFor": "Resultados de la búsqueda de",
|
"MessageSearchResultsFor": "Resultados de la búsqueda de",
|
||||||
"MessageSelected": "{0} seleccionado(s)",
|
"MessageSelected": "{0} seleccionado(s)",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "La secuencia de la serie no puede contener espacios",
|
||||||
"MessageServerCouldNotBeReached": "No se pudo establecer la conexión con el servidor",
|
"MessageServerCouldNotBeReached": "No se pudo establecer la conexión con el servidor",
|
||||||
"MessageSetChaptersFromTracksDescription": "Establecer capítulos usando cada archivo de audio como un capítulo y el título del capítulo como el nombre del archivo de audio",
|
"MessageSetChaptersFromTracksDescription": "Establecer capítulos usando cada archivo de audio como un capítulo y el título del capítulo como el nombre del archivo de audio",
|
||||||
"MessageShareExpirationWillBe": "La caducidad será <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "La caducidad será <strong>{0}</strong>",
|
||||||
"MessageShareExpiresIn": "Caduduca en {0}",
|
"MessageShareExpiresIn": "Caduduca en {0}",
|
||||||
"MessageShareURLWillBe": "La URL para compartir será <strong> {0} </strong>",
|
"MessageShareURLWillBe": "La URL para compartir será <strong> {0} </strong>",
|
||||||
"MessageStartPlaybackAtTime": "Iniciar reproducción para \"{0}\" en {1}?",
|
"MessageStartPlaybackAtTime": "¿Iniciar reproducción para «{0}» en {1}?",
|
||||||
"MessageTaskAudioFileNotWritable": "El archivo de audio \"{0}\" no se puede grabar",
|
"MessageTaskAudioFileNotWritable": "El archivo de audio «{0}» no se puede grabar",
|
||||||
"MessageTaskCanceledByUser": "Tarea cancelada por el usuario",
|
"MessageTaskCanceledByUser": "Tarea cancelada por el usuario",
|
||||||
"MessageTaskDownloadingEpisodeDescription": "Descargando el episodio \"{0}\"",
|
"MessageTaskDownloadingEpisodeDescription": "Descargando el episodio «{0}»",
|
||||||
"MessageTaskEmbeddingMetadata": "Inserción de metadatos",
|
"MessageTaskEmbeddingMetadata": "Inserción de metadatos",
|
||||||
"MessageTaskEmbeddingMetadataDescription": "Inserción de metadatos en el audiolibro \"{0}\"",
|
"MessageTaskEmbeddingMetadataDescription": "Incrustando metadatos en el audiolibro «{0}»",
|
||||||
"MessageTaskEncodingM4b": "Codificación M4B",
|
"MessageTaskEncodingM4b": "Codificación M4B",
|
||||||
"MessageTaskEncodingM4bDescription": "Codificación del audiolibro \"{0}\" en un único archivo m4b",
|
"MessageTaskEncodingM4bDescription": "Codificando el audiolibro «{0}» en un único archivo m4b",
|
||||||
"MessageTaskFailed": "Fallida",
|
"MessageTaskFailed": "Fallida",
|
||||||
"MessageTaskFailedToBackupAudioFile": "Error en la copia de seguridad del archivo de audio \"{0}\"",
|
"MessageTaskFailedToBackupAudioFile": "No se pudo respaldar el archivo de audio «{0}»",
|
||||||
"MessageTaskFailedToCreateCacheDirectory": "Error al crear el directorio de la caché",
|
"MessageTaskFailedToCreateCacheDirectory": "Error al crear el directorio de la caché",
|
||||||
"MessageTaskFailedToEmbedMetadataInFile": "Error al incrustar metadatos en el archivo \"{0}\"",
|
"MessageTaskFailedToEmbedMetadataInFile": "No se pudieron incrustar metadatos en el archivo «{0}»",
|
||||||
"MessageTaskFailedToMergeAudioFiles": "Error al fusionar archivos de audio",
|
"MessageTaskFailedToMergeAudioFiles": "Error al fusionar archivos de audio",
|
||||||
"MessageTaskFailedToMoveM4bFile": "Error al mover el archivo m4b",
|
"MessageTaskFailedToMoveM4bFile": "Error al mover el archivo m4b",
|
||||||
"MessageTaskFailedToWriteMetadataFile": "Error al escribir el archivo de metadatos",
|
"MessageTaskFailedToWriteMetadataFile": "Error al escribir el archivo de metadatos",
|
||||||
"MessageTaskMatchingBooksInLibrary": "Libros coincidentes en la biblioteca \"{0}\"",
|
"MessageTaskMatchingBooksInLibrary": "Libros coincidentes en la biblioteca «{0}»",
|
||||||
"MessageTaskNoFilesToScan": "Sin archivos para escanear",
|
"MessageTaskNoFilesToScan": "Sin archivos para escanear",
|
||||||
"MessageTaskOpmlImport": "Importar OPML",
|
"MessageTaskOpmlImport": "Importar OPML",
|
||||||
"MessageTaskOpmlImportDescription": "Creando pódcast a partir de {0} suministros RSS",
|
"MessageTaskOpmlImportDescription": "Creando pódcast a partir de {0} suministros RSS",
|
||||||
"MessageTaskOpmlImportFeed": "Feed de importación OPML",
|
"MessageTaskOpmlImportFeed": "Feed de importación OPML",
|
||||||
"MessageTaskOpmlImportFeedDescription": "Importando el feed RSS \"{0}\"",
|
"MessageTaskOpmlImportFeedDescription": "Importando el suministro RSS «{0}»",
|
||||||
"MessageTaskOpmlImportFeedFailed": "No se puede obtener el podcast",
|
"MessageTaskOpmlImportFeedFailed": "No se pudo obtener el suministro del pódcast",
|
||||||
"MessageTaskOpmlImportFeedPodcastDescription": "Creando podcast \"{0}\"",
|
"MessageTaskOpmlImportFeedPodcastDescription": "Creando pódcast «{0}»",
|
||||||
"MessageTaskOpmlImportFeedPodcastExists": "Podcast ya existe en la ruta",
|
"MessageTaskOpmlImportFeedPodcastExists": "El pódcast ya existe en la ruta",
|
||||||
"MessageTaskOpmlImportFeedPodcastFailed": "Error al crear podcast",
|
"MessageTaskOpmlImportFeedPodcastFailed": "No se pudo crear el pódcast",
|
||||||
"MessageTaskOpmlImportFinished": "Añadido {0} podcasts",
|
"MessageTaskOpmlImportFinished": "Añadido {0} podcasts",
|
||||||
"MessageTaskOpmlParseFailed": "No se pudo analizar el archivo OPML",
|
"MessageTaskOpmlParseFailed": "No se pudo analizar el archivo OPML",
|
||||||
"MessageTaskOpmlParseFastFail": "No se encontró la etiqueta <opml> del archivo OPML no válido O no se encontró la etiqueta <outline>",
|
"MessageTaskOpmlParseFastFail": "No se encontró la etiqueta <opml> del archivo OPML no válido O no se encontró la etiqueta <outline>",
|
||||||
@@ -881,8 +895,8 @@
|
|||||||
"MessageTaskScanItemsMissing": "Falta {0}",
|
"MessageTaskScanItemsMissing": "Falta {0}",
|
||||||
"MessageTaskScanItemsUpdated": "{0} actualizado",
|
"MessageTaskScanItemsUpdated": "{0} actualizado",
|
||||||
"MessageTaskScanNoChangesNeeded": "No se necesitan cambios",
|
"MessageTaskScanNoChangesNeeded": "No se necesitan cambios",
|
||||||
"MessageTaskScanningFileChanges": "Escaneando cambios en el archivo en \"{0}\"",
|
"MessageTaskScanningFileChanges": "Escaneando cambios en archivos en «{0}»",
|
||||||
"MessageTaskScanningLibrary": "Escaneando la biblioteca \"{0}\"",
|
"MessageTaskScanningLibrary": "Escaneando la biblioteca «{0}»",
|
||||||
"MessageTaskTargetDirectoryNotWritable": "El directorio de destino no se puede escribir",
|
"MessageTaskTargetDirectoryNotWritable": "El directorio de destino no se puede escribir",
|
||||||
"MessageThinking": "Pensando...",
|
"MessageThinking": "Pensando...",
|
||||||
"MessageUploaderItemFailed": "Error al Subir",
|
"MessageUploaderItemFailed": "Error al Subir",
|
||||||
@@ -932,7 +946,7 @@
|
|||||||
"ToastAppriseUrlRequired": "Debes ingresar una URL de Apprise",
|
"ToastAppriseUrlRequired": "Debes ingresar una URL de Apprise",
|
||||||
"ToastAsinRequired": "Se requiere ASIN",
|
"ToastAsinRequired": "Se requiere ASIN",
|
||||||
"ToastAuthorImageRemoveSuccess": "Se eliminó la imagen del autor",
|
"ToastAuthorImageRemoveSuccess": "Se eliminó la imagen del autor",
|
||||||
"ToastAuthorNotFound": "No se encontró el autor \"{0}\"",
|
"ToastAuthorNotFound": "No se encontró el autor «{0}»",
|
||||||
"ToastAuthorRemoveSuccess": "Autor eliminado",
|
"ToastAuthorRemoveSuccess": "Autor eliminado",
|
||||||
"ToastAuthorSearchNotFound": "No se encontró al autor",
|
"ToastAuthorSearchNotFound": "No se encontró al autor",
|
||||||
"ToastAuthorUpdateMerged": "Autor combinado",
|
"ToastAuthorUpdateMerged": "Autor combinado",
|
||||||
@@ -943,32 +957,35 @@
|
|||||||
"ToastBackupCreateSuccess": "Respaldo creado",
|
"ToastBackupCreateSuccess": "Respaldo creado",
|
||||||
"ToastBackupDeleteFailed": "Error al eliminar respaldo",
|
"ToastBackupDeleteFailed": "Error al eliminar respaldo",
|
||||||
"ToastBackupDeleteSuccess": "Respaldo eliminado",
|
"ToastBackupDeleteSuccess": "Respaldo eliminado",
|
||||||
"ToastBackupInvalidMaxKeep": "Número no válido de copias de seguridad a conservar",
|
"ToastBackupInvalidMaxKeep": "Número no válido de copias de respaldo para conservar",
|
||||||
"ToastBackupInvalidMaxSize": "Tamaño máximo de copia de seguridad no válido",
|
"ToastBackupInvalidMaxSize": "Tamaño máximo de copia de respaldo no válido",
|
||||||
"ToastBackupRestoreFailed": "Error al restaurar el respaldo",
|
"ToastBackupRestoreFailed": "Error al restaurar el respaldo",
|
||||||
"ToastBackupUploadFailed": "Error al subir el respaldo",
|
"ToastBackupUploadFailed": "Error al cargar la copia de respaldo",
|
||||||
"ToastBackupUploadSuccess": "Respaldo cargado",
|
"ToastBackupUploadSuccess": "Respaldo cargado",
|
||||||
"ToastBatchDeleteFailed": "Error al eliminar por lotes",
|
"ToastBatchApplyDetailsToItemsSuccess": "Detalles aplicados a los elementos",
|
||||||
"ToastBatchDeleteSuccess": "Borrado por lotes correcto",
|
"ToastBatchDeleteFailed": "Falló la eliminación por lotes",
|
||||||
|
"ToastBatchDeleteSuccess": "Se eliminó por lotes correctamente",
|
||||||
"ToastBatchQuickMatchFailed": "¡Error en la sincronización rápida por lotes!",
|
"ToastBatchQuickMatchFailed": "¡Error en la sincronización rápida por lotes!",
|
||||||
"ToastBatchQuickMatchStarted": "¡Se inició el lote de búsqueda rápida de {0} libros!",
|
"ToastBatchQuickMatchStarted": "¡Se inició el lote de búsqueda rápida de {0} libros!",
|
||||||
"ToastBatchUpdateFailed": "Subida masiva fallida",
|
"ToastBatchUpdateFailed": "Falló la actualización por lotes",
|
||||||
"ToastBatchUpdateSuccess": "Subida masiva exitosa",
|
"ToastBatchUpdateSuccess": "Se actualizó por lotes correctamente",
|
||||||
"ToastBookmarkCreateFailed": "Error al crear marcador",
|
"ToastBookmarkCreateFailed": "No se pudo crear el marcador",
|
||||||
"ToastBookmarkCreateSuccess": "Marcador Agregado",
|
"ToastBookmarkCreateSuccess": "Marcador añadido",
|
||||||
"ToastBookmarkRemoveSuccess": "Marcador eliminado",
|
"ToastBookmarkRemoveSuccess": "Marcador eliminado",
|
||||||
"ToastCachePurgeFailed": "Error al purgar el caché",
|
"ToastCachePurgeFailed": "No se pudo purgar la antememoria",
|
||||||
"ToastCachePurgeSuccess": "Caché purgado de manera exitosa",
|
"ToastCachePurgeSuccess": "Se purgó la antememoria correctamente",
|
||||||
"ToastChaptersHaveErrors": "Los capítulos tienen errores",
|
"ToastChaptersHaveErrors": "Los capítulos tienen errores",
|
||||||
"ToastChaptersMustHaveTitles": "Los capítulos tienen que tener un título",
|
"ToastChaptersInvalidShiftAmountLast": "Cantidad de desplazamiento no válida. La hora de inicio del último capítulo se extendería más allá de la duración de este audiolibro.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "Cantidad de desplazamiento no válida. El primer capítulo tendría una duración cero o negativa y lo sobrescribiría el segundo capítulo. Aumente la duración inicial del segundo capítulo.",
|
||||||
|
"ToastChaptersMustHaveTitles": "Los capítulos deben tener título",
|
||||||
"ToastChaptersRemoved": "Capítulos eliminados",
|
"ToastChaptersRemoved": "Capítulos eliminados",
|
||||||
"ToastChaptersUpdated": "Capítulos actualizados",
|
"ToastChaptersUpdated": "Capítulos actualizados",
|
||||||
"ToastCollectionItemsAddFailed": "Artículo(s) añadido(s) a la colección fallido(s)",
|
"ToastCollectionItemsAddFailed": "Artículo(s) añadido(s) a la colección fallido(s)",
|
||||||
"ToastCollectionRemoveSuccess": "Colección removida",
|
"ToastCollectionRemoveSuccess": "Colección quitada",
|
||||||
"ToastCollectionUpdateSuccess": "Colección actualizada",
|
"ToastCollectionUpdateSuccess": "Colección actualizada",
|
||||||
"ToastCoverUpdateFailed": "Error al actualizar la cubierta",
|
"ToastCoverUpdateFailed": "Error al actualizar la cubierta",
|
||||||
"ToastDateTimeInvalidOrIncomplete": "Fecha y hora inválidas o incompletas",
|
"ToastDateTimeInvalidOrIncomplete": "Fecha y hora no válidas o incompletas",
|
||||||
"ToastDeleteFileFailed": "Error el eliminar archivo",
|
"ToastDeleteFileFailed": "Falló la eliminación del archivo",
|
||||||
"ToastDeleteFileSuccess": "Archivo eliminado",
|
"ToastDeleteFileSuccess": "Archivo eliminado",
|
||||||
"ToastDeviceAddFailed": "Error al añadir dispositivo",
|
"ToastDeviceAddFailed": "Error al añadir dispositivo",
|
||||||
"ToastDeviceNameAlreadyExists": "Un libro electrónico ya existe con ese nombre",
|
"ToastDeviceNameAlreadyExists": "Un libro electrónico ya existe con ese nombre",
|
||||||
@@ -998,12 +1015,12 @@
|
|||||||
"ToastItemMarkedAsNotFinishedSuccess": "Elemento marcado como No Terminado",
|
"ToastItemMarkedAsNotFinishedSuccess": "Elemento marcado como No Terminado",
|
||||||
"ToastItemUpdateSuccess": "Elemento actualizado",
|
"ToastItemUpdateSuccess": "Elemento actualizado",
|
||||||
"ToastLibraryCreateFailed": "Error al crear biblioteca",
|
"ToastLibraryCreateFailed": "Error al crear biblioteca",
|
||||||
"ToastLibraryCreateSuccess": "Biblioteca \"{0}\" creada",
|
"ToastLibraryCreateSuccess": "Se creó la biblioteca «{0}»",
|
||||||
"ToastLibraryDeleteFailed": "Error al eliminar biblioteca",
|
"ToastLibraryDeleteFailed": "Error al eliminar biblioteca",
|
||||||
"ToastLibraryDeleteSuccess": "Biblioteca eliminada",
|
"ToastLibraryDeleteSuccess": "Biblioteca eliminada",
|
||||||
"ToastLibraryScanFailedToStart": "Error al iniciar el escaneo",
|
"ToastLibraryScanFailedToStart": "Error al iniciar el escaneo",
|
||||||
"ToastLibraryScanStarted": "Se inició el escaneo de la biblioteca",
|
"ToastLibraryScanStarted": "Se inició el escaneo de la biblioteca",
|
||||||
"ToastLibraryUpdateSuccess": "Biblioteca \"{0}\" actualizada",
|
"ToastLibraryUpdateSuccess": "Se actualizó la biblioteca «{0}»",
|
||||||
"ToastMatchAllAuthorsFailed": "No se pudo encontrar a todos los autores",
|
"ToastMatchAllAuthorsFailed": "No se pudo encontrar a todos los autores",
|
||||||
"ToastMetadataFilesRemovedError": "Error al eliminar metadatos de {0} archivo(s)",
|
"ToastMetadataFilesRemovedError": "Error al eliminar metadatos de {0} archivo(s)",
|
||||||
"ToastMetadataFilesRemovedNoneFound": "No hay metadatos.{0} archivo(s) encontrado(s) en la biblioteca",
|
"ToastMetadataFilesRemovedNoneFound": "No hay metadatos.{0} archivo(s) encontrado(s) en la biblioteca",
|
||||||
@@ -1013,7 +1030,7 @@
|
|||||||
"ToastNameEmailRequired": "Son obligatorios el nombre y el correo electrónico",
|
"ToastNameEmailRequired": "Son obligatorios el nombre y el correo electrónico",
|
||||||
"ToastNameRequired": "Nombre obligatorio",
|
"ToastNameRequired": "Nombre obligatorio",
|
||||||
"ToastNewEpisodesFound": "{0} nuevo(s) episodio(s) encontrado(s)",
|
"ToastNewEpisodesFound": "{0} nuevo(s) episodio(s) encontrado(s)",
|
||||||
"ToastNewUserCreatedFailed": "Error al crear la cuenta: \"{0}\"",
|
"ToastNewUserCreatedFailed": "No se pudo crear la cuenta: «{0}»",
|
||||||
"ToastNewUserCreatedSuccess": "Nueva cuenta creada",
|
"ToastNewUserCreatedSuccess": "Nueva cuenta creada",
|
||||||
"ToastNewUserLibraryError": "Debes seleccionar al menos una biblioteca",
|
"ToastNewUserLibraryError": "Debes seleccionar al menos una biblioteca",
|
||||||
"ToastNewUserPasswordError": "Debes tener una contraseña, solo el usuario root puede estar sin contraseña",
|
"ToastNewUserPasswordError": "Debes tener una contraseña, solo el usuario root puede estar sin contraseña",
|
||||||
@@ -1034,11 +1051,11 @@
|
|||||||
"ToastPlaylistCreateSuccess": "Lista de reproducción creada",
|
"ToastPlaylistCreateSuccess": "Lista de reproducción creada",
|
||||||
"ToastPlaylistRemoveSuccess": "Lista de reproducción eliminada",
|
"ToastPlaylistRemoveSuccess": "Lista de reproducción eliminada",
|
||||||
"ToastPlaylistUpdateSuccess": "Lista de reproducción actualizada",
|
"ToastPlaylistUpdateSuccess": "Lista de reproducción actualizada",
|
||||||
"ToastPodcastCreateFailed": "Error al crear podcast",
|
"ToastPodcastCreateFailed": "No se pudo crear el pódcast",
|
||||||
"ToastPodcastCreateSuccess": "Podcast creado",
|
"ToastPodcastCreateSuccess": "Se creó el pódcast correctamente",
|
||||||
"ToastPodcastGetFeedFailed": "No se puede obtener el podcast",
|
"ToastPodcastGetFeedFailed": "No se puede obtener el podcast",
|
||||||
"ToastPodcastNoEpisodesInFeed": "No se han encontrado episodios en el feed del RSS",
|
"ToastPodcastNoEpisodesInFeed": "No se han encontrado episodios en el feed del RSS",
|
||||||
"ToastPodcastNoRssFeed": "El podcast no tiene feed RSS",
|
"ToastPodcastNoRssFeed": "El pódcast no tiene suministro RSS",
|
||||||
"ToastProgressIsNotBeingSynced": "El progreso no se sincroniza, reinicia la reproducción",
|
"ToastProgressIsNotBeingSynced": "El progreso no se sincroniza, reinicia la reproducción",
|
||||||
"ToastProviderCreatedFailed": "Error al añadir el proveedor",
|
"ToastProviderCreatedFailed": "Error al añadir el proveedor",
|
||||||
"ToastProviderCreatedSuccess": "Nuevo proveedor añadido",
|
"ToastProviderCreatedSuccess": "Nuevo proveedor añadido",
|
||||||
@@ -1057,9 +1074,9 @@
|
|||||||
"ToastRescanUpToDate": "Reescaneado del artículo completo, estaba actualizado",
|
"ToastRescanUpToDate": "Reescaneado del artículo completo, estaba actualizado",
|
||||||
"ToastRescanUpdated": "Reescaneado completado, el artículo ha sido actualizado",
|
"ToastRescanUpdated": "Reescaneado completado, el artículo ha sido actualizado",
|
||||||
"ToastScanFailed": "No se pudo escanear el elemento de la biblioteca",
|
"ToastScanFailed": "No se pudo escanear el elemento de la biblioteca",
|
||||||
"ToastSelectAtLeastOneUser": "Selecciona al menos un usuario",
|
"ToastSelectAtLeastOneUser": "Seleccione al menos un usuario",
|
||||||
"ToastSendEbookToDeviceFailed": "Error al enviar el ebook al dispositivo",
|
"ToastSendEbookToDeviceFailed": "No se pudo enviar el libro electrónico al dispositivo",
|
||||||
"ToastSendEbookToDeviceSuccess": "Ebook enviado al dispositivo \"{0}\"",
|
"ToastSendEbookToDeviceSuccess": "Libro electrónico enviado al dispositivo «{0}»",
|
||||||
"ToastSeriesSubmitFailedSameName": "No se puede añadir dos series con el mismo nombre",
|
"ToastSeriesSubmitFailedSameName": "No se puede añadir dos series con el mismo nombre",
|
||||||
"ToastSeriesUpdateFailed": "Error al actualizar la serie",
|
"ToastSeriesUpdateFailed": "Error al actualizar la serie",
|
||||||
"ToastSeriesUpdateSuccess": "Serie actualizada",
|
"ToastSeriesUpdateSuccess": "Serie actualizada",
|
||||||
@@ -1079,10 +1096,12 @@
|
|||||||
"ToastUnknownError": "Error desconocido",
|
"ToastUnknownError": "Error desconocido",
|
||||||
"ToastUnlinkOpenIdFailed": "Error al desvincular el usuario de OpenID",
|
"ToastUnlinkOpenIdFailed": "Error al desvincular el usuario de OpenID",
|
||||||
"ToastUnlinkOpenIdSuccess": "Usuario desvinculado de OpenID",
|
"ToastUnlinkOpenIdSuccess": "Usuario desvinculado de OpenID",
|
||||||
|
"ToastUploaderFilepathExistsError": "La ruta de archivo «{0}» ya existe en el servidor",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "El elemento «{0}» usa un subdirectorio de la ruta de carga.",
|
||||||
"ToastUserDeleteFailed": "Error al eliminar el usuario",
|
"ToastUserDeleteFailed": "Error al eliminar el usuario",
|
||||||
"ToastUserDeleteSuccess": "Usuario eliminado",
|
"ToastUserDeleteSuccess": "Usuario eliminado",
|
||||||
"ToastUserPasswordChangeSuccess": "Contraseña modificada correctamente",
|
"ToastUserPasswordChangeSuccess": "Contraseña modificada correctamente",
|
||||||
"ToastUserPasswordMismatch": "No coinciden las contraseñas",
|
"ToastUserPasswordMismatch": "No coinciden las contraseñas",
|
||||||
"ToastUserPasswordMustChange": "La nueva contraseña no puede ser igual que la anterior",
|
"ToastUserPasswordMustChange": "La nueva contraseña no puede ser igual que la anterior",
|
||||||
"ToastUserRootRequireName": "Debes introducir un nombre de usuario root"
|
"ToastUserRootRequireName": "Debe introducir un nombre de usuario administrativo"
|
||||||
}
|
}
|
||||||
|
|||||||
+260
-9
@@ -69,7 +69,7 @@
|
|||||||
"ButtonQueueAddItem": "Lisää jonoon",
|
"ButtonQueueAddItem": "Lisää jonoon",
|
||||||
"ButtonQueueRemoveItem": "Poista jonosta",
|
"ButtonQueueRemoveItem": "Poista jonosta",
|
||||||
"ButtonQuickEmbed": "Pikaupota",
|
"ButtonQuickEmbed": "Pikaupota",
|
||||||
"ButtonQuickEmbedMetadata": "Upota kuvailutiedot nopeasti",
|
"ButtonQuickEmbedMetadata": "Upota metatiedot pikaisesti",
|
||||||
"ButtonQuickMatch": "Pikatäsmäys",
|
"ButtonQuickMatch": "Pikatäsmäys",
|
||||||
"ButtonReScan": "Uudelleenskannaa",
|
"ButtonReScan": "Uudelleenskannaa",
|
||||||
"ButtonRead": "Lue",
|
"ButtonRead": "Lue",
|
||||||
@@ -229,6 +229,7 @@
|
|||||||
"LabelAddedDate": "Lisätty {0}",
|
"LabelAddedDate": "Lisätty {0}",
|
||||||
"LabelAdminUsersOnly": "Vain järjestelmänvalvojat",
|
"LabelAdminUsersOnly": "Vain järjestelmänvalvojat",
|
||||||
"LabelAll": "Kaikki",
|
"LabelAll": "Kaikki",
|
||||||
|
"LabelAllEpisodesDownloaded": "Kaikki jaksot ladattu",
|
||||||
"LabelAllUsers": "Kaikki käyttäjät",
|
"LabelAllUsers": "Kaikki käyttäjät",
|
||||||
"LabelAllUsersExcludingGuests": "Kaikki käyttäjät vieraita lukuun ottamatta",
|
"LabelAllUsersExcludingGuests": "Kaikki käyttäjät vieraita lukuun ottamatta",
|
||||||
"LabelAllUsersIncludingGuests": "Kaikki käyttäjät mukaan lukien vieraat",
|
"LabelAllUsersIncludingGuests": "Kaikki käyttäjät mukaan lukien vieraat",
|
||||||
@@ -252,7 +253,7 @@
|
|||||||
"LabelBackToUser": "Takaisin käyttäjään",
|
"LabelBackToUser": "Takaisin käyttäjään",
|
||||||
"LabelBackupAudioFiles": "Varmuuskopioi äänitiedostot",
|
"LabelBackupAudioFiles": "Varmuuskopioi äänitiedostot",
|
||||||
"LabelBackupLocation": "Varmuuskopiointipaikka",
|
"LabelBackupLocation": "Varmuuskopiointipaikka",
|
||||||
"LabelBackupsEnableAutomaticBackups": "Ota automaattinen varmuuskopiointi käyttöön",
|
"LabelBackupsEnableAutomaticBackups": "Automaattiset varmuuskopiot",
|
||||||
"LabelBackupsEnableAutomaticBackupsHelp": "Varmuuskopiot tallennettu kansioon /metadata/backups",
|
"LabelBackupsEnableAutomaticBackupsHelp": "Varmuuskopiot tallennettu kansioon /metadata/backups",
|
||||||
"LabelBackupsMaxBackupSize": "Varmuuskopion enimmäiskoko (Gt) (0 rajaton)",
|
"LabelBackupsMaxBackupSize": "Varmuuskopion enimmäiskoko (Gt) (0 rajaton)",
|
||||||
"LabelBackupsMaxBackupSizeHelp": "Virheellisten asetusten estämiseksi varmuuskopiot epäonnistuvat, jos ne ovat asetettua kokoa suurempia.",
|
"LabelBackupsMaxBackupSizeHelp": "Virheellisten asetusten estämiseksi varmuuskopiot epäonnistuvat, jos ne ovat asetettua kokoa suurempia.",
|
||||||
@@ -344,6 +345,9 @@
|
|||||||
"LabelExample": "Esimerkki",
|
"LabelExample": "Esimerkki",
|
||||||
"LabelExpandSeries": "Laajenna sarja",
|
"LabelExpandSeries": "Laajenna sarja",
|
||||||
"LabelExpandSubSeries": "Laajenna alisarja",
|
"LabelExpandSubSeries": "Laajenna alisarja",
|
||||||
|
"LabelExplicit": "Yksiselitteinen",
|
||||||
|
"LabelExplicitChecked": "Yksiselitteinen (valittu)",
|
||||||
|
"LabelExplicitUnchecked": "Ei yksiselitteinen (ei valittu)",
|
||||||
"LabelExportOPML": "Vie OPML",
|
"LabelExportOPML": "Vie OPML",
|
||||||
"LabelFeedURL": "Syötteen URL",
|
"LabelFeedURL": "Syötteen URL",
|
||||||
"LabelFetchingMetadata": "Noudetaan kuvailutietoja",
|
"LabelFetchingMetadata": "Noudetaan kuvailutietoja",
|
||||||
@@ -371,8 +375,8 @@
|
|||||||
"LabelHardDeleteFile": "Kova tiedostojen poisto",
|
"LabelHardDeleteFile": "Kova tiedostojen poisto",
|
||||||
"LabelHasEbook": "Sillä on s-kirja",
|
"LabelHasEbook": "Sillä on s-kirja",
|
||||||
"LabelHasSupplementaryEbook": "Sillä on täydentävän s-kirjan",
|
"LabelHasSupplementaryEbook": "Sillä on täydentävän s-kirjan",
|
||||||
"LabelHideSubtitles": "Piilota tekstitykset",
|
"LabelHideSubtitles": "Piilota alaotsikot",
|
||||||
"LabelHighestPriority": "Tärkein",
|
"LabelHighestPriority": "Korkein etusija",
|
||||||
"LabelHost": "Isäntä",
|
"LabelHost": "Isäntä",
|
||||||
"LabelHour": "Tunti",
|
"LabelHour": "Tunti",
|
||||||
"LabelHours": "Tunnit",
|
"LabelHours": "Tunnit",
|
||||||
@@ -393,6 +397,8 @@
|
|||||||
"LabelIntervalEveryMinute": "Joka minuutti",
|
"LabelIntervalEveryMinute": "Joka minuutti",
|
||||||
"LabelInvert": "Saa käänteiseksi",
|
"LabelInvert": "Saa käänteiseksi",
|
||||||
"LabelItem": "Kohde",
|
"LabelItem": "Kohde",
|
||||||
|
"LabelJumpBackwardAmount": "Taaksepäin-hyppyjen määrä",
|
||||||
|
"LabelJumpForwardAmount": "Eteenpäin-hyppyjen määrä",
|
||||||
"LabelLanguage": "Kieli",
|
"LabelLanguage": "Kieli",
|
||||||
"LabelLanguageDefaultServer": "Palvelimen oletuskieli",
|
"LabelLanguageDefaultServer": "Palvelimen oletuskieli",
|
||||||
"LabelLanguages": "Kielet",
|
"LabelLanguages": "Kielet",
|
||||||
@@ -484,6 +490,7 @@
|
|||||||
"LabelPersonalYearReview": "Vuotesi katsauksessa ({0})",
|
"LabelPersonalYearReview": "Vuotesi katsauksessa ({0})",
|
||||||
"LabelPhotoPathURL": "Valokuvan polku/URL-osoite",
|
"LabelPhotoPathURL": "Valokuvan polku/URL-osoite",
|
||||||
"LabelPlayMethod": "Toistotapa",
|
"LabelPlayMethod": "Toistotapa",
|
||||||
|
"LabelPlaybackRateIncrementDecrement": "Toistonopeuden lisäys-/vähennysmäärä",
|
||||||
"LabelPlayerChapterNumberMarker": "{0}/{1}",
|
"LabelPlayerChapterNumberMarker": "{0}/{1}",
|
||||||
"LabelPlaylists": "Soittolistat",
|
"LabelPlaylists": "Soittolistat",
|
||||||
"LabelPodcast": "Podcast",
|
"LabelPodcast": "Podcast",
|
||||||
@@ -523,9 +530,10 @@
|
|||||||
"LabelReleaseDate": "Julkaisupäivä",
|
"LabelReleaseDate": "Julkaisupäivä",
|
||||||
"LabelRemoveAllMetadataAbs": "Poista kaikki metadata.abs-tiedostot",
|
"LabelRemoveAllMetadataAbs": "Poista kaikki metadata.abs-tiedostot",
|
||||||
"LabelRemoveAllMetadataJson": "Poista kaikki metadata.json-tiedostot",
|
"LabelRemoveAllMetadataJson": "Poista kaikki metadata.json-tiedostot",
|
||||||
|
"LabelRemoveAudibleBranding": "Poista Audiblen intro ja outro kappaleista",
|
||||||
"LabelRemoveCover": "Poista kansikuva",
|
"LabelRemoveCover": "Poista kansikuva",
|
||||||
"LabelRemoveMetadataFile": "Poista metatietotiedostot kirjaston kohdekansioista",
|
"LabelRemoveMetadataFile": "Poista metatietotiedostot kirjaston kohdekansioista",
|
||||||
"LabelRemoveMetadataFileHelp": "Poista kaikki metadata.json- ja metadata.abs-tiedostot {0} kansiostasi.",
|
"LabelRemoveMetadataFileHelp": "Poista kaikki metadata.json- ja metadata.abs-tiedostot {0} kansioistasi.",
|
||||||
"LabelRowsPerPage": "Rivejä sivulla",
|
"LabelRowsPerPage": "Rivejä sivulla",
|
||||||
"LabelSearchTerm": "Hakusana",
|
"LabelSearchTerm": "Hakusana",
|
||||||
"LabelSearchTitle": "Etsi otsikko",
|
"LabelSearchTitle": "Etsi otsikko",
|
||||||
@@ -552,6 +560,8 @@
|
|||||||
"LabelSettingsBookshelfViewHelp": "Skeuomorfinen muotoilu puisilla hyllyillä",
|
"LabelSettingsBookshelfViewHelp": "Skeuomorfinen muotoilu puisilla hyllyillä",
|
||||||
"LabelSettingsChromecastSupport": "Chromecast-tuki",
|
"LabelSettingsChromecastSupport": "Chromecast-tuki",
|
||||||
"LabelSettingsDateFormat": "Päivämäärän muoto",
|
"LabelSettingsDateFormat": "Päivämäärän muoto",
|
||||||
|
"LabelSettingsEnableWatcher": "Skannaa kirjastot automaattisesti muutoksien varalta",
|
||||||
|
"LabelSettingsEnableWatcherForLibrary": "Skannaa kirjastot automaattisesti muutoksien varalta",
|
||||||
"LabelSettingsEnableWatcherHelp": "Ottaa käyttöön kohteiden automaattisen lisäämisen ja päivityksen kun tiedostomuutoksia havaitaan. *Tarvitsee palvelimen uudelleenkäynnistyksen",
|
"LabelSettingsEnableWatcherHelp": "Ottaa käyttöön kohteiden automaattisen lisäämisen ja päivityksen kun tiedostomuutoksia havaitaan. *Tarvitsee palvelimen uudelleenkäynnistyksen",
|
||||||
"LabelSettingsEpubsAllowScriptedContent": "Salli komentosarjamuotoinen sisältö epubissa",
|
"LabelSettingsEpubsAllowScriptedContent": "Salli komentosarjamuotoinen sisältö epubissa",
|
||||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Salli epub-tiedostojen suorittaa komentosarjoja. On suositeltavaa pitää tämä asetus pois käytöstä, ellet luota epub-tiedostojen lähteeseen.",
|
"LabelSettingsEpubsAllowScriptedContentHelp": "Salli epub-tiedostojen suorittaa komentosarjoja. On suositeltavaa pitää tämä asetus pois käytöstä, ellet luota epub-tiedostojen lähteeseen.",
|
||||||
@@ -568,8 +578,8 @@
|
|||||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Merkitse mediakohde valmiiksi, kun",
|
"LabelSettingsLibraryMarkAsFinishedWhen": "Merkitse mediakohde valmiiksi, kun",
|
||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Ohita aiemmat kirjat Jatka sarjassa",
|
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Ohita aiemmat kirjat Jatka sarjassa",
|
||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Jatka sarja -kotisivun hyllyssä näkyy ensimmäinen kirja, jota ei ole aloitettu sarjoissa, joissa on vähintään yksi kirja valmiina eikä yhtään kirjaa kesken. Tämän asetuksen ottaminen käyttöön jatkaa sarjaa kauimpana valmistuneesta kirjasta ensimmäisen aloittamattoman kirjan sijaan.",
|
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Jatka sarja -kotisivun hyllyssä näkyy ensimmäinen kirja, jota ei ole aloitettu sarjoissa, joissa on vähintään yksi kirja valmiina eikä yhtään kirjaa kesken. Tämän asetuksen ottaminen käyttöön jatkaa sarjaa kauimpana valmistuneesta kirjasta ensimmäisen aloittamattoman kirjan sijaan.",
|
||||||
"LabelSettingsParseSubtitles": "Jäsennä tekstitykset",
|
"LabelSettingsParseSubtitles": "Jäsennä alaotsikot",
|
||||||
"LabelSettingsParseSubtitlesHelp": "Pura tekstitykset äänikirjojen kansioiden nimistä.<br>Tekstitys on erotettava toisistaan merkillä \"-\"<br>ts. \"Kirjan otsikko - Tekstitys täällä\" on alaotsikko \"Tekstitys täällä\"",
|
"LabelSettingsParseSubtitlesHelp": "Pura alaotsikot äänikirjojen kansioiden nimistä.<br>Tekstitys on erotettava toisistaan merkillä \"-\"<br>ts. \"Kirjan otsikko - Tekstitys täällä\" on alaotsikko \"Tekstitys täällä\"",
|
||||||
"LabelSettingsPreferMatchedMetadata": "Pidä mieluummin täsmäävät metatiedot",
|
"LabelSettingsPreferMatchedMetadata": "Pidä mieluummin täsmäävät metatiedot",
|
||||||
"LabelSettingsPreferMatchedMetadataHelp": "Täsmäävät tiedot ohittavat kohteen tiedot käytettäessä Pikatäsmäystä. Oletuksena Pikatäsmäys täyttää vain puuttuvat tiedot.",
|
"LabelSettingsPreferMatchedMetadataHelp": "Täsmäävät tiedot ohittavat kohteen tiedot käytettäessä Pikatäsmäystä. Oletuksena Pikatäsmäys täyttää vain puuttuvat tiedot.",
|
||||||
"LabelSettingsSkipMatchingBooksWithASIN": "Ohita täsmäävät kirjat, joilla on jo ASIN",
|
"LabelSettingsSkipMatchingBooksWithASIN": "Ohita täsmäävät kirjat, joilla on jo ASIN",
|
||||||
@@ -589,12 +599,13 @@
|
|||||||
"LabelShareURL": "Jaa URL-osoite",
|
"LabelShareURL": "Jaa URL-osoite",
|
||||||
"LabelShowAll": "Näytä kaikki",
|
"LabelShowAll": "Näytä kaikki",
|
||||||
"LabelShowSeconds": "Näytä sekunnit",
|
"LabelShowSeconds": "Näytä sekunnit",
|
||||||
"LabelShowSubtitles": "Näytä tekstitykset",
|
"LabelShowSubtitles": "Näytä alaotsikot",
|
||||||
"LabelSize": "Koko",
|
"LabelSize": "Koko",
|
||||||
"LabelSleepTimer": "Uniajastin",
|
"LabelSleepTimer": "Uniajastin",
|
||||||
"LabelSlug": "Slug",
|
"LabelSlug": "Slug",
|
||||||
"LabelSortAscending": "Nouseva",
|
"LabelSortAscending": "Nouseva",
|
||||||
"LabelSortDescending": "Laskeva",
|
"LabelSortDescending": "Laskeva",
|
||||||
|
"LabelSortPubDate": "Järjestä julkaisupäivän mukaan",
|
||||||
"LabelStart": "Aloita",
|
"LabelStart": "Aloita",
|
||||||
"LabelStartTime": "Aloitusaika",
|
"LabelStartTime": "Aloitusaika",
|
||||||
"LabelStarted": "Aloitettu",
|
"LabelStarted": "Aloitettu",
|
||||||
@@ -614,7 +625,7 @@
|
|||||||
"LabelStatsOverallDays": "Päivät kokonaisuudessaan",
|
"LabelStatsOverallDays": "Päivät kokonaisuudessaan",
|
||||||
"LabelStatsOverallHours": "Tunnit kokonaisuudessaan",
|
"LabelStatsOverallHours": "Tunnit kokonaisuudessaan",
|
||||||
"LabelStatsWeekListening": "Viikon aikana kuunneltu",
|
"LabelStatsWeekListening": "Viikon aikana kuunneltu",
|
||||||
"LabelSubtitle": "Tekstitys",
|
"LabelSubtitle": "Alaotsikko",
|
||||||
"LabelSupportedFileTypes": "Tuetut tiedostotyypit",
|
"LabelSupportedFileTypes": "Tuetut tiedostotyypit",
|
||||||
"LabelTag": "Tägi",
|
"LabelTag": "Tägi",
|
||||||
"LabelTags": "Tägit",
|
"LabelTags": "Tägit",
|
||||||
@@ -713,6 +724,7 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Epäkelvollinen aloitusaika; on oltava lyhyempi kuin äänikirjan kesto",
|
"MessageChapterErrorStartGteDuration": "Epäkelvollinen aloitusaika; on oltava lyhyempi kuin äänikirjan kesto",
|
||||||
"MessageChapterErrorStartLtPrev": "Epäkelvollinen aloitusaika; on oltava suurempi tai yhtä suuri kuin edellisen luvun aloitusaika",
|
"MessageChapterErrorStartLtPrev": "Epäkelvollinen aloitusaika; on oltava suurempi tai yhtä suuri kuin edellisen luvun aloitusaika",
|
||||||
"MessageChapterStartIsAfter": "Luku alkaa äänikirjan lopun jälkeen",
|
"MessageChapterStartIsAfter": "Luku alkaa äänikirjan lopun jälkeen",
|
||||||
|
"MessageChaptersNotFound": "Kappaleita ei löydy",
|
||||||
"MessageCheckingCron": "Tarkistetaan cronia...",
|
"MessageCheckingCron": "Tarkistetaan cronia...",
|
||||||
"MessageConfirmCloseFeed": "Oletko varma, että haluat sulkea tämän syötteen?",
|
"MessageConfirmCloseFeed": "Oletko varma, että haluat sulkea tämän syötteen?",
|
||||||
"MessageConfirmDeleteBackup": "Oletko varma, että haluat poistaa varmuuskopion {0}:lle?",
|
"MessageConfirmDeleteBackup": "Oletko varma, että haluat poistaa varmuuskopion {0}:lle?",
|
||||||
@@ -769,6 +781,7 @@
|
|||||||
"MessageForceReScanDescription": "skannaa kaikki tiedostot uudelleen kuten uusi tarkistus. Äänitiedoston ID3-tunnisteet, OPF-tiedostot ja tekstitiedostot skannataan uusina.",
|
"MessageForceReScanDescription": "skannaa kaikki tiedostot uudelleen kuten uusi tarkistus. Äänitiedoston ID3-tunnisteet, OPF-tiedostot ja tekstitiedostot skannataan uusina.",
|
||||||
"MessageImportantNotice": "Tärkeä huomautus!",
|
"MessageImportantNotice": "Tärkeä huomautus!",
|
||||||
"MessageInsertChapterBelow": "Syötä luku alle",
|
"MessageInsertChapterBelow": "Syötä luku alle",
|
||||||
|
"MessageInvalidAsin": "Virheellinen ASIN",
|
||||||
"MessageItemsSelected": "{0} kohdetta valittu",
|
"MessageItemsSelected": "{0} kohdetta valittu",
|
||||||
"MessageItemsUpdated": "{0} kohdetta päivitetty",
|
"MessageItemsUpdated": "{0} kohdetta päivitetty",
|
||||||
"MessageJoinUsOn": "Liity meihin",
|
"MessageJoinUsOn": "Liity meihin",
|
||||||
@@ -777,70 +790,308 @@
|
|||||||
"MessageLogsDescription": "Lokitiedot tallennetaan kansioon <code>/metadata/logs</code> JSON-tiedostoina. Kaatumislokit tallennetaan kansioon <code>/metadata/logs/crash_logs.txt</code>.",
|
"MessageLogsDescription": "Lokitiedot tallennetaan kansioon <code>/metadata/logs</code> JSON-tiedostoina. Kaatumislokit tallennetaan kansioon <code>/metadata/logs/crash_logs.txt</code>.",
|
||||||
"MessageM4BFailed": "M4B epäonnistui!",
|
"MessageM4BFailed": "M4B epäonnistui!",
|
||||||
"MessageM4BFinished": "M4B valmis!",
|
"MessageM4BFinished": "M4B valmis!",
|
||||||
|
"MessageMapChapterTitles": "Kartoita lukujen otsikot olemassa oleviin äänikirjan lukuihin muuttamatta aikaleimoja",
|
||||||
|
"MessageMarkAllEpisodesFinished": "Merkitse kaikki jaksot päättyneiksi",
|
||||||
|
"MessageMarkAllEpisodesNotFinished": "Merkitse kaikki jaksot ei-päättyneiksi",
|
||||||
"MessageMarkAsFinished": "Merkitse valmiiksi",
|
"MessageMarkAsFinished": "Merkitse valmiiksi",
|
||||||
|
"MessageMarkAsNotFinished": "Merkitse Ei-päättyneiksi",
|
||||||
|
"MessageMatchBooksDescription": "yrittää yhdistää kirjaston kirjoja valitun hakupalvelun kirjaan ja täyttää tyhjät tiedot ja kansikuvan. Ei korvaa yksityiskohtia.",
|
||||||
|
"MessageNoAudioTracks": "Ei ääniraitoja",
|
||||||
|
"MessageNoAuthors": "Ei tekijöitä",
|
||||||
|
"MessageNoBackups": "Ei varmuuskopioita",
|
||||||
"MessageNoBookmarks": "Ei kirjanmerkkejä",
|
"MessageNoBookmarks": "Ei kirjanmerkkejä",
|
||||||
"MessageNoChapters": "Ei kappaleita",
|
"MessageNoChapters": "Ei kappaleita",
|
||||||
"MessageNoCollections": "Ei kokoelmia",
|
"MessageNoCollections": "Ei kokoelmia",
|
||||||
"MessageNoCoversFound": "Kansikuvia ei löydetty",
|
"MessageNoCoversFound": "Kansikuvia ei löydetty",
|
||||||
|
"MessageNoDescription": "Ei kuvausta",
|
||||||
|
"MessageNoDevices": "Ei laitteita",
|
||||||
|
"MessageNoDownloadsInProgress": "Ei latauksia tällä hetkellä meneillään",
|
||||||
|
"MessageNoDownloadsQueued": "Ei latauksia jonossa",
|
||||||
|
"MessageNoEpisodeMatchesFound": "Jaksoosumia ei löytynyt",
|
||||||
|
"MessageNoEpisodes": "Ei jaksoja",
|
||||||
|
"MessageNoFoldersAvailable": "Ei kansioita saatavilla",
|
||||||
"MessageNoGenres": "Ei lajityyppejä",
|
"MessageNoGenres": "Ei lajityyppejä",
|
||||||
|
"MessageNoIssues": "Ei vikoja",
|
||||||
"MessageNoItems": "Ei kohteita",
|
"MessageNoItems": "Ei kohteita",
|
||||||
"MessageNoItemsFound": "Kohteita ei löytynyt",
|
"MessageNoItemsFound": "Kohteita ei löytynyt",
|
||||||
"MessageNoListeningSessions": "Ei kuunteluistuntoja",
|
"MessageNoListeningSessions": "Ei kuunteluistuntoja",
|
||||||
|
"MessageNoLogs": "Ei lokeja",
|
||||||
|
"MessageNoMediaProgress": "Ei median edistymistä",
|
||||||
|
"MessageNoNotifications": "Ei ilmoituksia",
|
||||||
|
"MessageNoPodcastFeed": "Epäkelvollinen podcast: Ei syötettä",
|
||||||
"MessageNoPodcastsFound": "Podcasteja ei löytynyt",
|
"MessageNoPodcastsFound": "Podcasteja ei löytynyt",
|
||||||
|
"MessageNoResults": "Ei tuloksia",
|
||||||
|
"MessageNoSearchResultsFor": "Ei hakutuloksia \"{0}\":lle",
|
||||||
|
"MessageNoSeries": "Ei sarjaa",
|
||||||
|
"MessageNoTags": "Ei tunnisteita",
|
||||||
|
"MessageNoTasksRunning": "Ei käynnissä olevia tehtäviä",
|
||||||
"MessageNoUpdatesWereNecessary": "Päivityksiä ei tarvittu",
|
"MessageNoUpdatesWereNecessary": "Päivityksiä ei tarvittu",
|
||||||
"MessageNoUserPlaylists": "Sinulla ei ole soittolistoja",
|
"MessageNoUserPlaylists": "Sinulla ei ole soittolistoja",
|
||||||
|
"MessageNoUserPlaylistsHelp": "Soittolistat ovat yksityisiä. Vain ne luonut käyttäjä näkee ne.",
|
||||||
|
"MessageNotYetImplemented": "Ei vielä toteutettu",
|
||||||
|
"MessageOpmlPreviewNote": "Huomautus: Tämä on esikatselu jäsennetystä OPML-tiedostosta. Varsinainen podcastin nimi tullaan ottamaan RSS-syötteestä.",
|
||||||
"MessageOr": "tai",
|
"MessageOr": "tai",
|
||||||
|
"MessagePauseChapter": "Keskeytä luvun toisto",
|
||||||
|
"MessagePlayChapter": "Kuuntele luvun alku",
|
||||||
|
"MessagePlaylistCreateFromCollection": "Luo soittolista kokoelmasta",
|
||||||
|
"MessagePleaseWait": "Ole hyvä ja odota...",
|
||||||
|
"MessagePodcastHasNoRSSFeedForMatching": "Podcastilla ei ole RSS-syötteen URL-osoitetta, jota voitaisiin käyttää täsmäämiseen",
|
||||||
"MessagePodcastSearchField": "Syötä hakutermi tai RSS-syötteen URL-osoite",
|
"MessagePodcastSearchField": "Syötä hakutermi tai RSS-syötteen URL-osoite",
|
||||||
|
"MessageQuickEmbedInProgress": "Pikaupottaminen meneillään",
|
||||||
|
"MessageQuickEmbedQueue": "Jonotettu pikaupotusta varten ({0} jonossa)",
|
||||||
"MessageQuickMatchAllEpisodes": "Pikatäsmää kaikki jaksot",
|
"MessageQuickMatchAllEpisodes": "Pikatäsmää kaikki jaksot",
|
||||||
|
"MessageQuickMatchDescription": "Täytä tyhjän tuotteen tiedot ja kansi ensimmäisellä täsmäävällä tuloksella {0}:sta. Ei korvaa tietoja, ellei 'Pidä mieluummin täsmäävät metatiedot'-palvelinasetus on otettu käyttöön.",
|
||||||
|
"MessageRemoveChapter": "Poista luku",
|
||||||
|
"MessageRemoveEpisodes": "Poista {0} jakso(a)",
|
||||||
|
"MessageRemoveFromPlayerQueue": "Poista soittimen jonosta",
|
||||||
"MessageRemoveUserWarning": "Oletko varma, että haluat poistaa käyttäjän \"{0}\" pysyvästi?",
|
"MessageRemoveUserWarning": "Oletko varma, että haluat poistaa käyttäjän \"{0}\" pysyvästi?",
|
||||||
"MessageReportBugsAndContribute": "Ilmoita virheistä, toivo ominaisuuksia ja osallistu",
|
"MessageReportBugsAndContribute": "Ilmoita virheistä, toivo ominaisuuksia ja osallistu",
|
||||||
"MessageResetChaptersConfirm": "Oletko varma, että haluat nollata luvut ja kumota tekemäsi muutokset?",
|
"MessageResetChaptersConfirm": "Oletko varma, että haluat nollata luvut ja kumota tekemäsi muutokset?",
|
||||||
"MessageRestoreBackupConfirm": "Oletko varma, että haluat palauttaa varmuuskopion, joka on luotu",
|
"MessageRestoreBackupConfirm": "Oletko varma, että haluat palauttaa varmuuskopion, joka on luotu",
|
||||||
|
"MessageRestoreBackupWarning": "Varmuuskopion palauttaminen korvaa koko /config:ssa sijaitsevan tietokannan, ja kansikuvat /metadata/items & /metadata/authors:ssa.<br /><br />Varmuuskopiot eivät muuta kirjastokansioissasi olevia tiedostoja. Jos olet ottanut käyttöön palvelinasetuksissa kansikuvien ja metatietojen tallentamisen kirjaston kansioihin, niitä ei varmuuskopioida tai korvata.<br /><br />Kaikki palvelintasi käyttävät asiakkaat virkistetään automaattisesti.",
|
||||||
"MessageScheduleLibraryScanNote": "Suurimmalle osaa käyttäjistä on suositeltavaa jättää tämä ominaisuus pois päältä ja säilyttää kansiotarkkailu päällä. Kansiotarkkailu havaitsee automaattisesti tiedostomuutokset kirjaston kansioissa. Kansiotarkkailu ei toimi kaikille tiedostojärjestelmille (kuten NFS), jolloin voidaan käyttää ajastettuja kirjastoskannauksia.",
|
"MessageScheduleLibraryScanNote": "Suurimmalle osaa käyttäjistä on suositeltavaa jättää tämä ominaisuus pois päältä ja säilyttää kansiotarkkailu päällä. Kansiotarkkailu havaitsee automaattisesti tiedostomuutokset kirjaston kansioissa. Kansiotarkkailu ei toimi kaikille tiedostojärjestelmille (kuten NFS), jolloin voidaan käyttää ajastettuja kirjastoskannauksia.",
|
||||||
|
"MessageScheduleRunEveryWeekdayAtTime": "Suorita joka {0} klo {1}",
|
||||||
|
"MessageSearchResultsFor": "Hakutulokset haulle",
|
||||||
|
"MessageSelected": "{0} valittuna",
|
||||||
|
"MessageServerCouldNotBeReached": "Palvelimelle ei saatu yhteyttä",
|
||||||
|
"MessageSetChaptersFromTracksDescription": "Aseta luvut käyttämällä kutakin äänitiedostoa lukuna ja luvun otsikkoa äänitiedoston nimenä",
|
||||||
|
"MessageShareExpirationWillBe": "Umpeutuminen on <strong>{0}</strong>",
|
||||||
|
"MessageShareExpiresIn": "Umpeutuu {0}:n kuluttua",
|
||||||
|
"MessageShareURLWillBe": "Jaa URL-osoite on <strong>{0}</strong>",
|
||||||
|
"MessageStartPlaybackAtTime": "Aloitetaanko \"{0}\":n toisto klo {1}?",
|
||||||
|
"MessageTaskAudioFileNotWritable": "Äänitiedosto \"{0}\" ei ole kirjoitettava",
|
||||||
|
"MessageTaskCanceledByUser": "Tehtävä peruttu käyttäjän toimesta",
|
||||||
|
"MessageTaskDownloadingEpisodeDescription": "Ladataan jaksoa \"{0}\"",
|
||||||
|
"MessageTaskEmbeddingMetadata": "Upotetaan metatiedot",
|
||||||
|
"MessageTaskEmbeddingMetadataDescription": "Upotetaan metatiedot äänikirjaan \"{0}\"",
|
||||||
|
"MessageTaskEncodingM4b": "Koodaus M4B",
|
||||||
|
"MessageTaskEncodingM4bDescription": "Koodataan äänikirjaa \"{0}\" yhdeksi m4b-tiedostoksi",
|
||||||
"MessageTaskFailed": "Epäonnistunut",
|
"MessageTaskFailed": "Epäonnistunut",
|
||||||
|
"MessageTaskFailedToBackupAudioFile": "Äänitiedoston \"{0}\" varmuuskopiointi epäonnistui",
|
||||||
|
"MessageTaskFailedToCreateCacheDirectory": "Välimuistihakemiston luominen epäonnistui",
|
||||||
|
"MessageTaskFailedToEmbedMetadataInFile": "Metatietojen upottaminen tiedostoon \"{0}\" epäonnistui",
|
||||||
|
"MessageTaskFailedToMergeAudioFiles": "Äänitiedostojen yhdistäminen epäonnistui",
|
||||||
|
"MessageTaskFailedToMoveM4bFile": "m4b-tiedoston siirtäminen epäonnistui",
|
||||||
|
"MessageTaskFailedToWriteMetadataFile": "Metatietotiedoston kirjoittaminen epäonnistui",
|
||||||
|
"MessageTaskMatchingBooksInLibrary": "Vastaavat kirjat kirjastossa \"{0}\"",
|
||||||
|
"MessageTaskNoFilesToScan": "Ei skannattavia tiedostoja",
|
||||||
|
"MessageTaskOpmlImport": "OPML-tuonti",
|
||||||
|
"MessageTaskOpmlImportDescription": "Luodaan podcasteja {0} RSS-syötteistä",
|
||||||
|
"MessageTaskOpmlImportFeed": "OPML-tuontisyöte",
|
||||||
|
"MessageTaskOpmlImportFeedDescription": "Tuodaan RSS-syötettä \"{0}\"",
|
||||||
|
"MessageTaskOpmlImportFeedFailed": "Podcast-syötteen saaminen epäonnistui",
|
||||||
|
"MessageTaskOpmlImportFeedPodcastDescription": "Luodaan podcastia \"{0}\"",
|
||||||
|
"MessageTaskOpmlImportFeedPodcastExists": "Podcast on jo olemassa polulla",
|
||||||
|
"MessageTaskOpmlImportFeedPodcastFailed": "Podcastin luominen epäonnistui",
|
||||||
|
"MessageTaskOpmlImportFinished": "Lisätty {0} podcastia",
|
||||||
|
"MessageTaskOpmlParseFailed": "OPML-tiedoston jäsentäminen epäonnistui",
|
||||||
|
"MessageTaskOpmlParseFastFail": "Epäkelvollinen OPML-tiedoston <opml>-tunnistetta ei löytynyt tai <outline>-tunnistetta ei löytynyt",
|
||||||
|
"MessageTaskOpmlParseNoneFound": "Syötteitä ei löytynyt OPML-tiedostosta",
|
||||||
|
"MessageTaskScanItemsAdded": "{0} lisätty",
|
||||||
|
"MessageTaskScanItemsMissing": "{0} puuttuu",
|
||||||
|
"MessageTaskScanItemsUpdated": "{0} päivitetty",
|
||||||
|
"MessageTaskScanNoChangesNeeded": "Muutoksia ei tarvita",
|
||||||
|
"MessageTaskScanningFileChanges": "Tarkastetaan tiedoston muutoksia \"{0}\":sta",
|
||||||
|
"MessageTaskScanningLibrary": "Tarkastetaan kirjastoa \"{0}\"",
|
||||||
|
"MessageTaskTargetDirectoryNotWritable": "Kohdehakemisto ei ole kirjoitettava",
|
||||||
|
"MessageThinking": "Ajattellaan...",
|
||||||
|
"MessageUploaderItemFailed": "Lataaminen ulospäin epäonnistui",
|
||||||
|
"MessageUploaderItemSuccess": "Onnistuneesti ladattu! ulospäin!",
|
||||||
|
"MessageUploading": "Ladataan! ulospäin...",
|
||||||
|
"MessageValidCronExpression": "Kelvollinen cron-lauseke",
|
||||||
"MessageWatcherIsDisabledGlobally": "Kansiotarkkailu on poistettu käytöstä kaikkialla palvelimen asetuksissa",
|
"MessageWatcherIsDisabledGlobally": "Kansiotarkkailu on poistettu käytöstä kaikkialla palvelimen asetuksissa",
|
||||||
|
"MessageXLibraryIsEmpty": "{0} Kirjasto on tyhjä!",
|
||||||
|
"MessageYourAudiobookDurationIsLonger": "Äänikirjasi kesto on pidempi kuin löydetty kesto",
|
||||||
|
"MessageYourAudiobookDurationIsShorter": "Äänikirjasi kesto on lyhyempi kuin löydetty kesto",
|
||||||
|
"NoteChangeRootPassword": "Käyttäjä root on ainoa käyttäjä, jolla voi olla tyhjä salasana",
|
||||||
|
"NoteChapterEditorTimes": "Huomautus: Ensimmäisen luvun aloitusajan on oltava 0:00 ja viimeisen luvun aloitusaika ei saa ylittää tätä äänikirjan kestoa.",
|
||||||
|
"NoteFolderPicker": "Huomautus: jo kartoitettuja kansioita ei näytetä",
|
||||||
"NoteRSSFeedPodcastAppsHttps": "Varoitus: Useimmat podcast-sovellukset edellyttävät, että RSS-syötteen URL-osoite käyttää HTTPS:a",
|
"NoteRSSFeedPodcastAppsHttps": "Varoitus: Useimmat podcast-sovellukset edellyttävät, että RSS-syötteen URL-osoite käyttää HTTPS:a",
|
||||||
"NoteRSSFeedPodcastAppsPubDate": "Varoitus: yhdellä tai useammalla jaksollasi ei ole julkaisupäivämäärää. Jotkut podcast-sovellukset vaativat tämän.",
|
"NoteRSSFeedPodcastAppsPubDate": "Varoitus: yhdellä tai useammalla jaksollasi ei ole julkaisupäivämäärää. Jotkut podcast-sovellukset vaativat tämän.",
|
||||||
|
"NoteUploaderFoldersWithMediaFiles": "Mediatiedostoja sisältävät kansiot käsitellään erillisinä kirjastokohteina.",
|
||||||
|
"NoteUploaderOnlyAudioFiles": "Jos ladataan luospäin vain äänitiedostoja, silloin jokainen äänitiedosto käsitellään erillisenä äänikirjana.",
|
||||||
|
"NoteUploaderUnsupportedFiles": "Ei-tuetut tiedostot ohitetaan. Kansiota valittaessa tai pudottaessa, muut tiedostot, jotka eivät ole kohdekansiossa, ohitetaan.",
|
||||||
|
"NotificationOnBackupCompletedDescription": "Laukaistu, kun varmuuskopiointi on valmis",
|
||||||
|
"NotificationOnBackupFailedDescription": "Laukaistu, kun varmuuskopiointi epäonnistuu",
|
||||||
|
"NotificationOnEpisodeDownloadedDescription": "Laukaistu, kun podcast-jakso ladataan automaattisesti",
|
||||||
|
"NotificationOnTestDescription": "Tapahtuma ilmoitusjärjestelmän testaamista varten",
|
||||||
|
"PlaceholderNewCollection": "Uusi kokoelman nimi",
|
||||||
|
"PlaceholderNewFolderPath": "Uusi kansion polku",
|
||||||
|
"PlaceholderNewPlaylist": "Uusi soittolistan nimi",
|
||||||
|
"PlaceholderSearch": "Haku...",
|
||||||
|
"PlaceholderSearchEpisode": "Haku jaksosta..",
|
||||||
|
"StatsAuthorsAdded": "tekijät lisätty",
|
||||||
|
"StatsBooksAdded": "kirjat lisätty",
|
||||||
|
"StatsBooksAdditional": "Jotkut lisäykset sisältävät…",
|
||||||
|
"StatsBooksFinished": "kirjat päättyneet",
|
||||||
|
"StatsBooksFinishedThisYear": "Jotkut kirjat päättyneet tänä vuonna…",
|
||||||
|
"StatsBooksListenedTo": "kuunnellut kirjat",
|
||||||
|
"StatsCollectionGrewTo": "Kirjakokoelmasi kasvoi asti…",
|
||||||
"StatsSessions": "istunnot",
|
"StatsSessions": "istunnot",
|
||||||
|
"StatsSpentListening": "kuunteluun käytetty",
|
||||||
|
"StatsTopAuthor": "HUIPPUTEKIJÄ",
|
||||||
|
"StatsTopAuthors": "HUIPPUTEKIJÄT",
|
||||||
|
"StatsTopGenre": "HUIPPUTYYLILAJI",
|
||||||
|
"StatsTopGenres": "HUIPPUTYYLILAJIT",
|
||||||
|
"StatsTopMonth": "HUIPPUKUUKAUSI",
|
||||||
|
"StatsTopNarrator": "HUIPPUKERTOJA",
|
||||||
|
"StatsTopNarrators": "HUIPPUKERTOJAT",
|
||||||
|
"StatsTotalDuration": "Kokonaiskestolla…",
|
||||||
|
"StatsYearInReview": "VUOSI KATSAUKSESSA",
|
||||||
"ToastAccountUpdateSuccess": "Tili päivitetty",
|
"ToastAccountUpdateSuccess": "Tili päivitetty",
|
||||||
"ToastAppriseUrlRequired": "Arvon tulee olla Apprise URL",
|
"ToastAppriseUrlRequired": "Arvon tulee olla Apprise URL",
|
||||||
|
"ToastAsinRequired": "ASIN vaaditaan",
|
||||||
|
"ToastAuthorImageRemoveSuccess": "Tekijän kuva poistettu",
|
||||||
|
"ToastAuthorNotFound": "Tekijää \"{0}\" ei löydy",
|
||||||
|
"ToastAuthorRemoveSuccess": "Tekijä poistettu",
|
||||||
|
"ToastAuthorSearchNotFound": "Tekijää ei löydy",
|
||||||
|
"ToastAuthorUpdateMerged": "Tekijä yhdistetty",
|
||||||
|
"ToastAuthorUpdateSuccess": "Tekijä päivitetty",
|
||||||
|
"ToastAuthorUpdateSuccessNoImageFound": "Tekijä päivitetty (kuvaa ei löytynyt)",
|
||||||
|
"ToastBackupAppliedSuccess": "Varmuuskopiointi sovellettu",
|
||||||
|
"ToastBackupCreateFailed": "Varmuuskopion luominen epäonnistui",
|
||||||
|
"ToastBackupCreateSuccess": "Varmuuskopio luotu",
|
||||||
|
"ToastBackupDeleteFailed": "Varmuuskopion poistaminen epäonnistui",
|
||||||
|
"ToastBackupDeleteSuccess": "Varmuuskopio poistettu",
|
||||||
|
"ToastBackupInvalidMaxKeep": "Epäkelvollinen määrä säilytettäviä varmuuskopioita",
|
||||||
|
"ToastBackupInvalidMaxSize": "Epäkelvollinen varmuuskopion enimmäiskoko",
|
||||||
|
"ToastBackupRestoreFailed": "Varmuuskopion palauttaminen epäonnistui",
|
||||||
|
"ToastBackupUploadFailed": "Varmuuskopion lataaminen ulospäin epäonnistui",
|
||||||
|
"ToastBackupUploadSuccess": "Varmuuskopio ladattu ulospäin",
|
||||||
|
"ToastBatchApplyDetailsToItemsSuccess": "Kohteisiin sovelletut yksityiskohdat",
|
||||||
|
"ToastBatchDeleteFailed": "Eräpoisto epäonnistui",
|
||||||
|
"ToastBatchDeleteSuccess": "Eräpoisto onnistui",
|
||||||
"ToastBatchQuickMatchFailed": "Erän pikatäsmäys epäonnistui!",
|
"ToastBatchQuickMatchFailed": "Erän pikatäsmäys epäonnistui!",
|
||||||
"ToastBatchQuickMatchStarted": "{0} kirjan erän pikatäsmäys aloitettu!",
|
"ToastBatchQuickMatchStarted": "{0} kirjan erän pikatäsmäys aloitettu!",
|
||||||
|
"ToastBatchUpdateFailed": "Eräpäivitys epäonnistui",
|
||||||
|
"ToastBatchUpdateSuccess": "Eräpäivitys onnistui",
|
||||||
"ToastBookmarkCreateFailed": "Kirjanmerkin luominen epäonnistui",
|
"ToastBookmarkCreateFailed": "Kirjanmerkin luominen epäonnistui",
|
||||||
|
"ToastBookmarkCreateSuccess": "Kirjanmerkki lisätty",
|
||||||
|
"ToastBookmarkRemoveSuccess": "Kirjanmerkki poistettu",
|
||||||
|
"ToastCachePurgeFailed": "Välimuistin tyhjentäminen epäonnistui",
|
||||||
|
"ToastCachePurgeSuccess": "Välimuisti tyhjennetty onnistuneesti",
|
||||||
|
"ToastChaptersHaveErrors": "Luvuissa on virheitä",
|
||||||
|
"ToastChaptersMustHaveTitles": "Lukuilla on oltava otsikot",
|
||||||
|
"ToastChaptersRemoved": "Luvut poistettu",
|
||||||
|
"ToastChaptersUpdated": "Luvut päivitetty",
|
||||||
|
"ToastCollectionItemsAddFailed": "Kohteen/kohteiden lisääminen kokoelmaan epäonnistui",
|
||||||
|
"ToastCollectionRemoveSuccess": "Kokoelma poistettu",
|
||||||
|
"ToastCollectionUpdateSuccess": "Kokoelma päivitetty",
|
||||||
"ToastCoverUpdateFailed": "Kansikuvan päivitys epäonnistui",
|
"ToastCoverUpdateFailed": "Kansikuvan päivitys epäonnistui",
|
||||||
|
"ToastDateTimeInvalidOrIncomplete": "Päivämäärä ja aika ovat epäkelvolliset tai puutteelliset",
|
||||||
|
"ToastDeleteFileFailed": "Tiedoston poistaminen epäonnistui",
|
||||||
|
"ToastDeleteFileSuccess": "Tiedosto poistettu",
|
||||||
|
"ToastDeviceAddFailed": "Laitteen lisääminen epäonnistui",
|
||||||
|
"ToastDeviceNameAlreadyExists": "Tämän niminen sähköinen lukulaite on jo olemassa",
|
||||||
|
"ToastDeviceTestEmailFailed": "Testisähköpostin lähettäminen epäonnistui",
|
||||||
|
"ToastDeviceTestEmailSuccess": "Testisähköposti lähetetty",
|
||||||
|
"ToastEmailSettingsUpdateSuccess": "Sähköpostiasetukset päivitetty",
|
||||||
|
"ToastEncodeCancelFailed": "Koodauksen peruuttaminen epäonnistui",
|
||||||
|
"ToastEncodeCancelSucces": "Koodaaminen peruutettu",
|
||||||
|
"ToastEpisodeDownloadQueueClearFailed": "Jonon tyhjentäminen epäonnistui",
|
||||||
|
"ToastEpisodeDownloadQueueClearSuccess": "Jakson latausjono tyhjennetty",
|
||||||
|
"ToastEpisodeUpdateSuccess": "{0} jaksoa päivitetty",
|
||||||
|
"ToastErrorCannotShare": "Ei voi jakaa alkuperäisesti tällä laitteella",
|
||||||
|
"ToastFailedToLoadData": "Tietojen lataaminen epäonnistui",
|
||||||
|
"ToastFailedToMatch": "Vastaaminen epäonnistui",
|
||||||
|
"ToastFailedToShare": "Jakaminen epäonnistui",
|
||||||
|
"ToastFailedToUpdate": "Päivittäminen epäonnistui",
|
||||||
|
"ToastInvalidImageUrl": "Epäkelvollinen kuvan URL-osoite",
|
||||||
|
"ToastInvalidMaxEpisodesToDownload": "Ladattavien jaksojen enimmäismäärä on epäkelvollinen",
|
||||||
|
"ToastInvalidUrl": "Epäkelvollinen URL-osoite",
|
||||||
"ToastItemCoverUpdateSuccess": "Kohteen kansikuva päivitetty",
|
"ToastItemCoverUpdateSuccess": "Kohteen kansikuva päivitetty",
|
||||||
|
"ToastItemDeletedFailed": "Kohteen poistaminen epäonnistui",
|
||||||
|
"ToastItemDeletedSuccess": "Poistettu kohde",
|
||||||
|
"ToastItemDetailsUpdateSuccess": "Tuotteen yksityiskohdat päivitetty",
|
||||||
"ToastItemMarkedAsFinishedFailed": "Valmiiksi merkitseminen epäonnistui",
|
"ToastItemMarkedAsFinishedFailed": "Valmiiksi merkitseminen epäonnistui",
|
||||||
|
"ToastItemMarkedAsFinishedSuccess": "Kohde merkitty Päättyneeksi",
|
||||||
"ToastItemMarkedAsNotFinishedFailed": "Valmiiksi merkitsemisen poisto epäonnistui",
|
"ToastItemMarkedAsNotFinishedFailed": "Valmiiksi merkitsemisen poisto epäonnistui",
|
||||||
|
"ToastItemMarkedAsNotFinishedSuccess": "Kohde merkitty Ei-päättyneeksi",
|
||||||
"ToastItemUpdateSuccess": "Kohde päivitetty",
|
"ToastItemUpdateSuccess": "Kohde päivitetty",
|
||||||
"ToastLibraryCreateFailed": "Kirjaston luominen epäonnistui",
|
"ToastLibraryCreateFailed": "Kirjaston luominen epäonnistui",
|
||||||
"ToastLibraryCreateSuccess": "Kirjasto \"{0}\" luotu",
|
"ToastLibraryCreateSuccess": "Kirjasto \"{0}\" luotu",
|
||||||
"ToastLibraryDeleteFailed": "Kirjaston poistaminen epäonnistui",
|
"ToastLibraryDeleteFailed": "Kirjaston poistaminen epäonnistui",
|
||||||
"ToastLibraryDeleteSuccess": "Kirjasto poistettu",
|
"ToastLibraryDeleteSuccess": "Kirjasto poistettu",
|
||||||
|
"ToastLibraryScanFailedToStart": "Skannauksen käynnistäminen epäonnistui",
|
||||||
|
"ToastLibraryScanStarted": "Kirjaston skannaus käynnistetty",
|
||||||
"ToastLibraryUpdateSuccess": "Kirjasto \"{0}\" päivitetty",
|
"ToastLibraryUpdateSuccess": "Kirjasto \"{0}\" päivitetty",
|
||||||
|
"ToastMatchAllAuthorsFailed": "Kaikkia tekijöitä ei voitu vaastattaa",
|
||||||
|
"ToastMetadataFilesRemovedError": "Virhe poistettaessa metadata.{0}-tiedostot",
|
||||||
|
"ToastMetadataFilesRemovedNoneFound": "metadata.{0}-tiedostoja ei löytynyt kirjastosta",
|
||||||
|
"ToastMetadataFilesRemovedNoneRemoved": "Ei metadata.{0}-tiedostoja poistettu",
|
||||||
|
"ToastMetadataFilesRemovedSuccess": "{0} metadata.{1}-tiedostoa poistettu",
|
||||||
|
"ToastMustHaveAtLeastOnePath": "On oltava vähintään yksi polku",
|
||||||
|
"ToastNameEmailRequired": "Nimi ja sähköpostiosoite vaaditaan",
|
||||||
|
"ToastNameRequired": "Nimi vaaditaan",
|
||||||
|
"ToastNewEpisodesFound": "{0} uutta jaksoa löydetty",
|
||||||
"ToastNewUserCreatedFailed": "Tilin \"{0}\" luominen epäonnistui",
|
"ToastNewUserCreatedFailed": "Tilin \"{0}\" luominen epäonnistui",
|
||||||
"ToastNewUserCreatedSuccess": "Uusi tili luotu",
|
"ToastNewUserCreatedSuccess": "Uusi tili luotu",
|
||||||
|
"ToastNewUserLibraryError": "On valittava vähintään yksi kirjasto",
|
||||||
|
"ToastNewUserPasswordError": "On oltava salasana; vain käyttäjällä root voi olla tyhjä salasana",
|
||||||
|
"ToastNewUserTagError": "On valittava vähintään yksi tunniste",
|
||||||
|
"ToastNewUserUsernameError": "Syötä käyttäjänimi",
|
||||||
|
"ToastNoNewEpisodesFound": "Uusia jaksoja ei löytynyt",
|
||||||
|
"ToastNoRSSFeed": "Podcastilla ei ole RSS-syötettä",
|
||||||
|
"ToastNoUpdatesNecessary": "Päivityksiä ei tarvita",
|
||||||
|
"ToastNotificationCreateFailed": "Ilmoituksen luominen epäonnistui",
|
||||||
|
"ToastNotificationDeleteFailed": "Ilmoituksen poistaminen epäonnistui",
|
||||||
|
"ToastNotificationFailedMaximum": "Epäonnistuneiden yritysten enimmäismäärän on oltava >= 0",
|
||||||
|
"ToastNotificationQueueMaximum": "Ilmoitusjonon enimmäismäärä on oltava >= 0",
|
||||||
|
"ToastNotificationSettingsUpdateSuccess": "Ilmoitusasetukset päivitetty",
|
||||||
|
"ToastNotificationTestTriggerFailed": "Testiilmoituksen laukaiseminen epäonnistui",
|
||||||
|
"ToastNotificationTestTriggerSuccess": "Laukaistiin testiilmoitus",
|
||||||
|
"ToastNotificationUpdateSuccess": "Ilmoitus päivitetty",
|
||||||
"ToastPlaylistCreateFailed": "Soittolistan luominen epäonnistui",
|
"ToastPlaylistCreateFailed": "Soittolistan luominen epäonnistui",
|
||||||
"ToastPlaylistCreateSuccess": "Soittolista luotu",
|
"ToastPlaylistCreateSuccess": "Soittolista luotu",
|
||||||
"ToastPlaylistRemoveSuccess": "Soittolista poistettu",
|
"ToastPlaylistRemoveSuccess": "Soittolista poistettu",
|
||||||
"ToastPlaylistUpdateSuccess": "Soittolista päivitetty",
|
"ToastPlaylistUpdateSuccess": "Soittolista päivitetty",
|
||||||
"ToastPodcastCreateFailed": "Podcastin luominen epäonnistui",
|
"ToastPodcastCreateFailed": "Podcastin luominen epäonnistui",
|
||||||
"ToastPodcastCreateSuccess": "Podcastin luominen onnistui",
|
"ToastPodcastCreateSuccess": "Podcastin luominen onnistui",
|
||||||
|
"ToastPodcastGetFeedFailed": "Podcast-syötteen saaminen epäonnistui",
|
||||||
|
"ToastPodcastNoEpisodesInFeed": "RSS-syötteestä ei löytynyt jaksoja",
|
||||||
|
"ToastPodcastNoRssFeed": "Podcastilla ei ole RSS-syötettä",
|
||||||
|
"ToastProgressIsNotBeingSynced": "Edistystä ei synkronoida, aloita toisto uudelleen",
|
||||||
|
"ToastProviderCreatedFailed": "Palveluntarjoajan lisääminen epäonnistui",
|
||||||
|
"ToastProviderCreatedSuccess": "Uusi palveluntarjoaja lisätty",
|
||||||
|
"ToastProviderNameAndUrlRequired": "Nimi ja URL-osoite vaaditaan",
|
||||||
|
"ToastProviderRemoveSuccess": "Palveluntarjoaja poistettu",
|
||||||
"ToastRSSFeedCloseFailed": "RSS syötteen sulkeminen epäonnistui",
|
"ToastRSSFeedCloseFailed": "RSS syötteen sulkeminen epäonnistui",
|
||||||
"ToastRSSFeedCloseSuccess": "RSS syöte suljettu",
|
"ToastRSSFeedCloseSuccess": "RSS syöte suljettu",
|
||||||
"ToastRemoveFailed": "Poistaminen epäonnistui",
|
"ToastRemoveFailed": "Poistaminen epäonnistui",
|
||||||
"ToastRemoveItemFromCollectionFailed": "Kohteen poistaminen kokoelmasta epäonnistui",
|
"ToastRemoveItemFromCollectionFailed": "Kohteen poistaminen kokoelmasta epäonnistui",
|
||||||
"ToastRemoveItemFromCollectionSuccess": "Kohde poistettu kokoelmasta",
|
"ToastRemoveItemFromCollectionSuccess": "Kohde poistettu kokoelmasta",
|
||||||
|
"ToastRemoveItemsWithIssuesFailed": "Vikoja sisältävien kirjastokohteiden poistaminen epäonnistui",
|
||||||
|
"ToastRemoveItemsWithIssuesSuccess": "Vikoja sisältäviä kirjastokohteita poistettu",
|
||||||
"ToastRenameFailed": "Uudelleennimeäminen epäonnistui",
|
"ToastRenameFailed": "Uudelleennimeäminen epäonnistui",
|
||||||
|
"ToastRescanFailed": "Uudelleenskannaus {0}n kohdalla epäonnistui",
|
||||||
|
"ToastRescanRemoved": "Uudelleenskannauksen täydellinen kohde poistettiin",
|
||||||
|
"ToastRescanUpToDate": "Uudelleenskannauksen täydellinen kohde oli ajan tasalla",
|
||||||
|
"ToastRescanUpdated": "Uudelleenskannauksen täydellinen kohde päivitettiin",
|
||||||
|
"ToastScanFailed": "Kirjastokohteen skannaaminen epäonnistui",
|
||||||
"ToastSelectAtLeastOneUser": "Valitse ainakin yksi käyttäjä",
|
"ToastSelectAtLeastOneUser": "Valitse ainakin yksi käyttäjä",
|
||||||
|
"ToastSendEbookToDeviceFailed": "S-kirjan lähettäminen laitteeseen epäonnistui",
|
||||||
|
"ToastSendEbookToDeviceSuccess": "S-kirja lähetetty laitteeseen \"{0}\"",
|
||||||
|
"ToastSeriesSubmitFailedSameName": "Ei voi lisätä kahta samannimistä sarjaa",
|
||||||
|
"ToastSeriesUpdateFailed": "Sarjan päivittäminen epäonnistui",
|
||||||
|
"ToastSeriesUpdateSuccess": "Sarjan päivittäminen onnistui",
|
||||||
"ToastServerSettingsUpdateSuccess": "Palvelimen asetukset päivitetty",
|
"ToastServerSettingsUpdateSuccess": "Palvelimen asetukset päivitetty",
|
||||||
"ToastSessionCloseFailed": "Istunnon sulkeminen epäonnistui",
|
"ToastSessionCloseFailed": "Istunnon sulkeminen epäonnistui",
|
||||||
"ToastSessionDeleteFailed": "Istunnon poistaminen epäonnistui",
|
"ToastSessionDeleteFailed": "Istunnon poistaminen epäonnistui",
|
||||||
"ToastSessionDeleteSuccess": "Istunto poistettu",
|
"ToastSessionDeleteSuccess": "Istunto poistettu",
|
||||||
|
"ToastSleepTimerDone": "Uniajastin tehty... zZzzZz",
|
||||||
|
"ToastSlugMustChange": "Slug sisältää epäkelvollisia merkkejä",
|
||||||
|
"ToastSlugRequired": "Slug vaaditaan",
|
||||||
"ToastSocketConnected": "Yhteys saatu",
|
"ToastSocketConnected": "Yhteys saatu",
|
||||||
"ToastSocketDisconnected": "Yhteys katkaistu",
|
"ToastSocketDisconnected": "Yhteys katkaistu",
|
||||||
"ToastSocketFailedToConnect": "Yhteyden muodostus epäonnistui",
|
"ToastSocketFailedToConnect": "Yhteyden muodostus epäonnistui",
|
||||||
|
"ToastSortingPrefixesEmptyError": "On oltava vähintään yksi lajitteluetuliite",
|
||||||
|
"ToastSortingPrefixesUpdateSuccess": "Lajitteluetuliitteet päivitetty ({0} kohdetta)",
|
||||||
"ToastTitleRequired": "Otsikko on pakollinen",
|
"ToastTitleRequired": "Otsikko on pakollinen",
|
||||||
"ToastUnknownError": "Tuntematon virhe",
|
"ToastUnknownError": "Tuntematon virhe",
|
||||||
|
"ToastUnlinkOpenIdFailed": "Käyttäjän linkityksen poistaminen OpenID:sta epäonnistui",
|
||||||
|
"ToastUnlinkOpenIdSuccess": "Käyttäjän linkitys poistettu OpenID:sta",
|
||||||
|
"ToastUploaderFilepathExistsError": "Tiedostopolku \"{0}\" on jo olemassa palvelimella",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "Kohde {0} käyttää ulospäinlatauspolun alihakemistoa.",
|
||||||
"ToastUserDeleteFailed": "Käyttäjän poisto epäonnistui",
|
"ToastUserDeleteFailed": "Käyttäjän poisto epäonnistui",
|
||||||
"ToastUserDeleteSuccess": "Käyttäjä poistettu",
|
"ToastUserDeleteSuccess": "Käyttäjä poistettu",
|
||||||
"ToastUserPasswordChangeSuccess": "Salasana vaihdettu onnistuneesti",
|
"ToastUserPasswordChangeSuccess": "Salasana vaihdettu onnistuneesti",
|
||||||
|
|||||||
+22
-5
@@ -229,6 +229,7 @@
|
|||||||
"LabelAddedDate": "Ajouté le {0}",
|
"LabelAddedDate": "Ajouté le {0}",
|
||||||
"LabelAdminUsersOnly": "Administrateurs uniquement",
|
"LabelAdminUsersOnly": "Administrateurs uniquement",
|
||||||
"LabelAll": "Tout",
|
"LabelAll": "Tout",
|
||||||
|
"LabelAllEpisodesDownloaded": "Tous les épisodes ont été téléchargés",
|
||||||
"LabelAllUsers": "Tous les utilisateurs",
|
"LabelAllUsers": "Tous les utilisateurs",
|
||||||
"LabelAllUsersExcludingGuests": "Tous les utilisateurs à l’exception des invités",
|
"LabelAllUsersExcludingGuests": "Tous les utilisateurs à l’exception des invités",
|
||||||
"LabelAllUsersIncludingGuests": "Tous les utilisateurs, y compris les invités",
|
"LabelAllUsersIncludingGuests": "Tous les utilisateurs, y compris les invités",
|
||||||
@@ -252,7 +253,7 @@
|
|||||||
"LabelBackToUser": "Retour à l’utilisateur",
|
"LabelBackToUser": "Retour à l’utilisateur",
|
||||||
"LabelBackupAudioFiles": "Sauvegarder les fichiers audio",
|
"LabelBackupAudioFiles": "Sauvegarder les fichiers audio",
|
||||||
"LabelBackupLocation": "Emplacement de la sauvegarde",
|
"LabelBackupLocation": "Emplacement de la sauvegarde",
|
||||||
"LabelBackupsEnableAutomaticBackups": "Activer les sauvegardes automatiques",
|
"LabelBackupsEnableAutomaticBackups": "Sauvegardes automatiques",
|
||||||
"LabelBackupsEnableAutomaticBackupsHelp": "Sauvegardes enregistrées dans /metadata/backups",
|
"LabelBackupsEnableAutomaticBackupsHelp": "Sauvegardes enregistrées dans /metadata/backups",
|
||||||
"LabelBackupsMaxBackupSize": "Taille maximale de la sauvegarde (en Go) (0 pour illimité)",
|
"LabelBackupsMaxBackupSize": "Taille maximale de la sauvegarde (en Go) (0 pour illimité)",
|
||||||
"LabelBackupsMaxBackupSizeHelp": "Afin de prévenir les mauvaises configuration, la sauvegarde échouera si elle excède la taille limite.",
|
"LabelBackupsMaxBackupSizeHelp": "Afin de prévenir les mauvaises configuration, la sauvegarde échouera si elle excède la taille limite.",
|
||||||
@@ -279,7 +280,7 @@
|
|||||||
"LabelCollections": "Collections",
|
"LabelCollections": "Collections",
|
||||||
"LabelComplete": "Complet",
|
"LabelComplete": "Complet",
|
||||||
"LabelConfirmPassword": "Confirmer le mot de passe",
|
"LabelConfirmPassword": "Confirmer le mot de passe",
|
||||||
"LabelContinueListening": "Continuer la lecture",
|
"LabelContinueListening": "Continuer l'écoute",
|
||||||
"LabelContinueReading": "Continuer la lecture",
|
"LabelContinueReading": "Continuer la lecture",
|
||||||
"LabelContinueSeries": "Continuer les séries",
|
"LabelContinueSeries": "Continuer les séries",
|
||||||
"LabelCover": "Couverture",
|
"LabelCover": "Couverture",
|
||||||
@@ -302,7 +303,7 @@
|
|||||||
"LabelDiscFromFilename": "Depuis le fichier",
|
"LabelDiscFromFilename": "Depuis le fichier",
|
||||||
"LabelDiscFromMetadata": "Depuis les métadonnées",
|
"LabelDiscFromMetadata": "Depuis les métadonnées",
|
||||||
"LabelDiscover": "Découvrir",
|
"LabelDiscover": "Découvrir",
|
||||||
"LabelDownload": "Téléchargement",
|
"LabelDownload": "Télécharger",
|
||||||
"LabelDownloadNEpisodes": "Télécharger {0} épisode(s)",
|
"LabelDownloadNEpisodes": "Télécharger {0} épisode(s)",
|
||||||
"LabelDownloadable": "Téléchargeable",
|
"LabelDownloadable": "Téléchargeable",
|
||||||
"LabelDuration": "Durée",
|
"LabelDuration": "Durée",
|
||||||
@@ -529,6 +530,7 @@
|
|||||||
"LabelReleaseDate": "Date de parution",
|
"LabelReleaseDate": "Date de parution",
|
||||||
"LabelRemoveAllMetadataAbs": "Supprimer tous les fichiers metadata.abs",
|
"LabelRemoveAllMetadataAbs": "Supprimer tous les fichiers metadata.abs",
|
||||||
"LabelRemoveAllMetadataJson": "Supprimer tous les fichiers metadata.json",
|
"LabelRemoveAllMetadataJson": "Supprimer tous les fichiers metadata.json",
|
||||||
|
"LabelRemoveAudibleBranding": "Supprimer l’intro et la fin Audible des chapitres",
|
||||||
"LabelRemoveCover": "Supprimer la couverture",
|
"LabelRemoveCover": "Supprimer la couverture",
|
||||||
"LabelRemoveMetadataFile": "Supprimer les fichiers de métadonnées dans les dossiers des éléments de la bibliothèque",
|
"LabelRemoveMetadataFile": "Supprimer les fichiers de métadonnées dans les dossiers des éléments de la bibliothèque",
|
||||||
"LabelRemoveMetadataFileHelp": "Supprimer tous les fichiers metadata.json et metadata.abs de vos dossiers {0}.",
|
"LabelRemoveMetadataFileHelp": "Supprimer tous les fichiers metadata.json et metadata.abs de vos dossiers {0}.",
|
||||||
@@ -558,6 +560,8 @@
|
|||||||
"LabelSettingsBookshelfViewHelp": "Interface skeumorphique avec étagères en bois",
|
"LabelSettingsBookshelfViewHelp": "Interface skeumorphique avec étagères en bois",
|
||||||
"LabelSettingsChromecastSupport": "Support du Chromecast",
|
"LabelSettingsChromecastSupport": "Support du Chromecast",
|
||||||
"LabelSettingsDateFormat": "Format de date",
|
"LabelSettingsDateFormat": "Format de date",
|
||||||
|
"LabelSettingsEnableWatcher": "Analyser automatiquement les bibliothèques pour détecter les modifications",
|
||||||
|
"LabelSettingsEnableWatcherForLibrary": "Analyser automatiquement la bibliothèque pour détecter les modifications",
|
||||||
"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",
|
"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",
|
"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.",
|
"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.",
|
||||||
@@ -575,7 +579,7 @@
|
|||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Sauter les livres précédents dans « Continuer la série »",
|
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Sauter les livres précédents dans « Continuer la série »",
|
||||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "L’étagère de la page d’accueil « Continuer la série » affiche le premier livre non commencé dans les séries dont au moins un livre est terminé et aucun livre n’est en cours. L’activation de ce paramètre permet de poursuivre la série à partir du dernier livre terminé au lieu du premier livre non commencé.",
|
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "L’étagère de la page d’accueil « Continuer la série » affiche le premier livre non commencé dans les séries dont au moins un livre est terminé et aucun livre n’est en cours. L’activation de ce paramètre permet de poursuivre la série à partir du dernier livre terminé au lieu du premier livre non commencé.",
|
||||||
"LabelSettingsParseSubtitles": "Analyser les sous-titres",
|
"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>c’est-à-dire : « Titre du livre - Ceci est un sous-titre » aura le sous-titre « Ceci est un sous-titre »",
|
"LabelSettingsParseSubtitlesHelp": "Extraire les sous-titres des noms de dossiers de livres audio.<br>Les sous-titres doivent être séparés par « - »<br>Par exemple, « Titre du livre - Un sous-titre » a pour sous-titre « Un sous-titre »",
|
||||||
"LabelSettingsPreferMatchedMetadata": "Préférer les métadonnées par correspondance",
|
"LabelSettingsPreferMatchedMetadata": "Préférer les métadonnées par correspondance",
|
||||||
"LabelSettingsPreferMatchedMetadataHelp": "Les métadonnées mises en correspondance remplaceront les détails de l’élément lors de l’utilisation de la correspondance rapide. Par défaut, la correspondance rapide ne remplira que les détails manquants.",
|
"LabelSettingsPreferMatchedMetadataHelp": "Les métadonnées mises en correspondance remplaceront les détails de l’élément lors de l’utilisation 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",
|
"LabelSettingsSkipMatchingBooksWithASIN": "Ignorer la recherche par correspondance pour les livres ayant déjà un ASIN",
|
||||||
@@ -601,6 +605,7 @@
|
|||||||
"LabelSlug": "Identifiant d’URL",
|
"LabelSlug": "Identifiant d’URL",
|
||||||
"LabelSortAscending": "Croissant",
|
"LabelSortAscending": "Croissant",
|
||||||
"LabelSortDescending": "Décroissant",
|
"LabelSortDescending": "Décroissant",
|
||||||
|
"LabelSortPubDate": "Trier par date de publication",
|
||||||
"LabelStart": "Démarrer",
|
"LabelStart": "Démarrer",
|
||||||
"LabelStartTime": "Heure de démarrage",
|
"LabelStartTime": "Heure de démarrage",
|
||||||
"LabelStarted": "Démarré",
|
"LabelStarted": "Démarré",
|
||||||
@@ -701,11 +706,14 @@
|
|||||||
"LabelYourProgress": "Votre progression",
|
"LabelYourProgress": "Votre progression",
|
||||||
"MessageAddToPlayerQueue": "Ajouter en file d’attente",
|
"MessageAddToPlayerQueue": "Ajouter en file d’attente",
|
||||||
"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 />L’URL de l’API 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>.",
|
"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 />L’URL de l’API 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>.",
|
||||||
|
"MessageAsinCheck": "Assurez-vous d’utiliser l’ASIN de la bonne région Audible, et non d’Amazon.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Redémarrez votre serveur après avoir enregistré pour appliquer les modifications OIDC.",
|
||||||
"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>n’incluent pas</strong> les fichiers stockés dans les dossiers de votre bibliothèque.",
|
"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>n’incluent pas</strong> les fichiers stockés dans les dossiers de votre bibliothèque.",
|
||||||
"MessageBackupsLocationEditNote": "Remarque : Mettre à jour l'emplacement de sauvegarde ne déplacera pas ou ne modifiera pas les sauvegardes existantes",
|
"MessageBackupsLocationEditNote": "Remarque : Mettre à jour l'emplacement de sauvegarde ne déplacera pas ou ne modifiera pas les sauvegardes existantes",
|
||||||
"MessageBackupsLocationNoEditNote": "Remarque : l’emplacement de sauvegarde est défini via une variable d’environnement et ne peut pas être modifié ici.",
|
"MessageBackupsLocationNoEditNote": "Remarque : l’emplacement de sauvegarde est défini via une variable d’environnement et ne peut pas être modifié ici.",
|
||||||
"MessageBackupsLocationPathEmpty": "L'emplacement de secours ne peut pas être vide",
|
"MessageBackupsLocationPathEmpty": "L'emplacement de secours ne peut pas être vide",
|
||||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Remplir les champs disponibles avec les données de tous les éléments. Les champs avec des valeurs multiples seront fusionnés.",
|
"MessageBatchEditPopulateMapDetailsAllHelp": "Remplir les champs disponibles avec les données de tous les éléments. Les champs avec des valeurs multiples seront fusionnés.",
|
||||||
|
"MessageBatchEditPopulateMapDetailsItemHelp": "Renseigner les champs de la carte active avec les informations de cet élément",
|
||||||
"MessageBatchQuickMatchDescription": "La recherche par correspondance rapide tentera d’ajouter les couvertures et métadonnées manquantes pour les éléments sélectionnés. Activez les options ci-dessous pour permettre la Recherche par correspondance d’écraser les couvertures et/ou métadonnées existantes.",
|
"MessageBatchQuickMatchDescription": "La recherche par correspondance rapide tentera d’ajouter les couvertures et métadonnées manquantes pour les éléments sélectionnés. Activez les options ci-dessous pour permettre la Recherche par correspondance d’écraser les couvertures et/ou métadonnées existantes.",
|
||||||
"MessageBookshelfNoCollections": "Vous n’avez pas encore de collections",
|
"MessageBookshelfNoCollections": "Vous n’avez pas encore de collections",
|
||||||
"MessageBookshelfNoCollectionsHelp": "Les collections sont publiques. Tous les utilisateurs ayant accès à la bibliothèque pourront les voir.",
|
"MessageBookshelfNoCollectionsHelp": "Les collections sont publiques. Tous les utilisateurs ayant accès à la bibliothèque pourront les voir.",
|
||||||
@@ -718,6 +726,7 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Horodatage invalide car il doit débuter avant la fin du livre",
|
"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",
|
"MessageChapterErrorStartLtPrev": "Horodatage invalide car il doit débuter au moins après le précédent chapitre",
|
||||||
"MessageChapterStartIsAfter": "Le premier chapitre est situé au début de votre livre audio",
|
"MessageChapterStartIsAfter": "Le premier chapitre est situé au début de votre livre audio",
|
||||||
|
"MessageChaptersNotFound": "Chapitres non trouvés",
|
||||||
"MessageCheckingCron": "Vérification du cron…",
|
"MessageCheckingCron": "Vérification du cron…",
|
||||||
"MessageConfirmCloseFeed": "Êtes-vous sûr·e de vouloir fermer ce flux ?",
|
"MessageConfirmCloseFeed": "Êtes-vous sûr·e de vouloir fermer ce flux ?",
|
||||||
"MessageConfirmDeleteBackup": "Êtes-vous sûr·e de vouloir supprimer la sauvegarde de « {0} » ?",
|
"MessageConfirmDeleteBackup": "Êtes-vous sûr·e de vouloir supprimer la sauvegarde de « {0} » ?",
|
||||||
@@ -774,6 +783,7 @@
|
|||||||
"MessageForceReScanDescription": "analysera de nouveau tous les fichiers. Les étiquettes ID3 des fichiers audio, les fichiers OPF et les fichiers texte seront analysés comme s’ils étaient nouveaux.",
|
"MessageForceReScanDescription": "analysera de nouveau tous les fichiers. Les étiquettes ID3 des fichiers audio, les fichiers OPF et les fichiers texte seront analysés comme s’ils étaient nouveaux.",
|
||||||
"MessageImportantNotice": "Information importante !",
|
"MessageImportantNotice": "Information importante !",
|
||||||
"MessageInsertChapterBelow": "Insérer le chapitre ci-dessous",
|
"MessageInsertChapterBelow": "Insérer le chapitre ci-dessous",
|
||||||
|
"MessageInvalidAsin": "ASIN invalide",
|
||||||
"MessageItemsSelected": "{0} éléments sélectionnés",
|
"MessageItemsSelected": "{0} éléments sélectionnés",
|
||||||
"MessageItemsUpdated": "{0} éléments mis à jour",
|
"MessageItemsUpdated": "{0} éléments mis à jour",
|
||||||
"MessageJoinUsOn": "Rejoignez-nous sur",
|
"MessageJoinUsOn": "Rejoignez-nous sur",
|
||||||
@@ -819,7 +829,7 @@
|
|||||||
"MessageNoTasksRunning": "Aucune tâche en cours",
|
"MessageNoTasksRunning": "Aucune tâche en cours",
|
||||||
"MessageNoUpdatesWereNecessary": "Aucune mise à jour n’était nécessaire",
|
"MessageNoUpdatesWereNecessary": "Aucune mise à jour n’était nécessaire",
|
||||||
"MessageNoUserPlaylists": "Vous n’avez aucune liste de lecture",
|
"MessageNoUserPlaylists": "Vous n’avez aucune liste de lecture",
|
||||||
"MessageNoUserPlaylistsHelp": "Les playlists sont privées. Seul l'utilisateur qui les a créées peut les voir.",
|
"MessageNoUserPlaylistsHelp": "Les playlists sont privées. Seul l’utilisateur qui les crée peut les voir.",
|
||||||
"MessageNotYetImplemented": "Non implémenté",
|
"MessageNotYetImplemented": "Non implémenté",
|
||||||
"MessageOpmlPreviewNote": "Remarque : Il s’agit d’un aperçu du fichier OPML analysé. Le titre réel du podcast provient du flux RSS.",
|
"MessageOpmlPreviewNote": "Remarque : Il s’agit d’un aperçu du fichier OPML analysé. Le titre réel du podcast provient du flux RSS.",
|
||||||
"MessageOr": "ou",
|
"MessageOr": "ou",
|
||||||
@@ -845,6 +855,7 @@
|
|||||||
"MessageScheduleRunEveryWeekdayAtTime": "Exécuté tous les {0} à {1}",
|
"MessageScheduleRunEveryWeekdayAtTime": "Exécuté tous les {0} à {1}",
|
||||||
"MessageSearchResultsFor": "Résultats de recherche pour",
|
"MessageSearchResultsFor": "Résultats de recherche pour",
|
||||||
"MessageSelected": "{0} sélectionnés",
|
"MessageSelected": "{0} sélectionnés",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "La séquence de séries ne peut pas contenir d’espaces",
|
||||||
"MessageServerCouldNotBeReached": "Serveur inaccessible",
|
"MessageServerCouldNotBeReached": "Serveur inaccessible",
|
||||||
"MessageSetChaptersFromTracksDescription": "Positionne un chapitre par fichier audio, avec le titre du fichier comme titre de chapitre",
|
"MessageSetChaptersFromTracksDescription": "Positionne un chapitre par fichier audio, avec le titre du fichier comme titre de chapitre",
|
||||||
"MessageShareExpirationWillBe": "Expire le <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "Expire le <strong>{0}</strong>",
|
||||||
@@ -950,6 +961,7 @@
|
|||||||
"ToastBackupRestoreFailed": "Échec de la restauration de sauvegarde",
|
"ToastBackupRestoreFailed": "Échec de la restauration de sauvegarde",
|
||||||
"ToastBackupUploadFailed": "Échec du téléversement de sauvegarde",
|
"ToastBackupUploadFailed": "Échec du téléversement de sauvegarde",
|
||||||
"ToastBackupUploadSuccess": "Sauvegarde téléversée",
|
"ToastBackupUploadSuccess": "Sauvegarde téléversée",
|
||||||
|
"ToastBatchApplyDetailsToItemsSuccess": "Détails appliqués aux articles",
|
||||||
"ToastBatchDeleteFailed": "Échec de la suppression par lot",
|
"ToastBatchDeleteFailed": "Échec de la suppression par lot",
|
||||||
"ToastBatchDeleteSuccess": "Suppression par lot réussie",
|
"ToastBatchDeleteSuccess": "Suppression par lot réussie",
|
||||||
"ToastBatchQuickMatchFailed": "Échec de la correspondance rapide par lot !",
|
"ToastBatchQuickMatchFailed": "Échec de la correspondance rapide par lot !",
|
||||||
@@ -962,6 +974,8 @@
|
|||||||
"ToastCachePurgeFailed": "Échec de la purge du cache",
|
"ToastCachePurgeFailed": "Échec de la purge du cache",
|
||||||
"ToastCachePurgeSuccess": "Cache purgé avec succès",
|
"ToastCachePurgeSuccess": "Cache purgé avec succès",
|
||||||
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
|
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
|
||||||
|
"ToastChaptersInvalidShiftAmountLast": "Durée de décalage non valide. L’heure de début du dernier chapitre pourrait dépasser la durée de ce livre audio.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "Durée de décalage non valide. Le premier chapitre aurait une longueur nulle ou négative et serait écrasé par le second. Augmentez la durée de début du second chapitre.",
|
||||||
"ToastChaptersMustHaveTitles": "Les chapitre doivent avoir un titre",
|
"ToastChaptersMustHaveTitles": "Les chapitre doivent avoir un titre",
|
||||||
"ToastChaptersRemoved": "Chapitres supprimés",
|
"ToastChaptersRemoved": "Chapitres supprimés",
|
||||||
"ToastChaptersUpdated": "Chapitres mis à jour",
|
"ToastChaptersUpdated": "Chapitres mis à jour",
|
||||||
@@ -1062,6 +1076,7 @@
|
|||||||
"ToastSelectAtLeastOneUser": "Sélectionnez au moins un utilisateur",
|
"ToastSelectAtLeastOneUser": "Sélectionnez au moins un utilisateur",
|
||||||
"ToastSendEbookToDeviceFailed": "Échec de l’envoi du livre numérique à l’appareil",
|
"ToastSendEbookToDeviceFailed": "Échec de l’envoi du livre numérique à l’appareil",
|
||||||
"ToastSendEbookToDeviceSuccess": "Livre numérique envoyé à l’appareil : {0}",
|
"ToastSendEbookToDeviceSuccess": "Livre numérique envoyé à l’appareil : {0}",
|
||||||
|
"ToastSeriesSubmitFailedSameName": "Impossible d’ajouter deux séries ayant le même nom",
|
||||||
"ToastSeriesUpdateFailed": "Échec de la mise à jour de la série",
|
"ToastSeriesUpdateFailed": "Échec de la mise à jour de la série",
|
||||||
"ToastSeriesUpdateSuccess": "Mise à jour de la série réussie",
|
"ToastSeriesUpdateSuccess": "Mise à jour de la série réussie",
|
||||||
"ToastServerSettingsUpdateSuccess": "Mise à jour des paramètres du serveur",
|
"ToastServerSettingsUpdateSuccess": "Mise à jour des paramètres du serveur",
|
||||||
@@ -1080,6 +1095,8 @@
|
|||||||
"ToastUnknownError": "Erreur inconnue",
|
"ToastUnknownError": "Erreur inconnue",
|
||||||
"ToastUnlinkOpenIdFailed": "Échec de la dissociation de l’utilisateur l’OpenID",
|
"ToastUnlinkOpenIdFailed": "Échec de la dissociation de l’utilisateur l’OpenID",
|
||||||
"ToastUnlinkOpenIdSuccess": "Utilisateur dissocié de OpenID",
|
"ToastUnlinkOpenIdSuccess": "Utilisateur dissocié de OpenID",
|
||||||
|
"ToastUploaderFilepathExistsError": "Le chemin de fichier « {0} » existe déjà sur le serveur",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "L’élément « {0} » utilise un sous-répertoire du chemin de téléchargement.",
|
||||||
"ToastUserDeleteFailed": "Échec de la suppression de l’utilisateur",
|
"ToastUserDeleteFailed": "Échec de la suppression de l’utilisateur",
|
||||||
"ToastUserDeleteSuccess": "Utilisateur supprimé",
|
"ToastUserDeleteSuccess": "Utilisateur supprimé",
|
||||||
"ToastUserPasswordChangeSuccess": "Mot de passe modifié avec succès",
|
"ToastUserPasswordChangeSuccess": "Mot de passe modifié avec succès",
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
"ButtonApply": "લાગુ કરો",
|
"ButtonApply": "લાગુ કરો",
|
||||||
"ButtonApplyChapters": "પ્રકરણો લાગુ કરો",
|
"ButtonApplyChapters": "પ્રકરણો લાગુ કરો",
|
||||||
"ButtonAuthors": "લેખકો",
|
"ButtonAuthors": "લેખકો",
|
||||||
|
"ButtonBack": "પાછા",
|
||||||
|
"ButtonBatchEditPopulateFromExisting": "હાલની માહિતીમાંથી ભરો",
|
||||||
|
"ButtonBatchEditPopulateMapDetails": "નકશાની વિગત ભરો",
|
||||||
"ButtonBrowseForFolder": "ફોલ્ડર માટે જુઓ",
|
"ButtonBrowseForFolder": "ફોલ્ડર માટે જુઓ",
|
||||||
"ButtonCancel": "રદ કરો",
|
"ButtonCancel": "રદ કરો",
|
||||||
"ButtonCancelEncode": "એન્કોડ રદ કરો",
|
"ButtonCancelEncode": "એન્કોડ રદ કરો",
|
||||||
@@ -27,11 +30,14 @@
|
|||||||
"ButtonEdit": "સંપાદિત કરો",
|
"ButtonEdit": "સંપાદિત કરો",
|
||||||
"ButtonEditChapters": "પ્રકરણો સંપાદિત કરો",
|
"ButtonEditChapters": "પ્રકરણો સંપાદિત કરો",
|
||||||
"ButtonEditPodcast": "પોડકાસ્ટ સંપાદિત કરો",
|
"ButtonEditPodcast": "પોડકાસ્ટ સંપાદિત કરો",
|
||||||
|
"ButtonEnable": "સક્રિય કરો",
|
||||||
"ButtonForceReScan": "બળપૂર્વક ફરીથી સ્કેન કરો",
|
"ButtonForceReScan": "બળપૂર્વક ફરીથી સ્કેન કરો",
|
||||||
"ButtonFullPath": "સંપૂર્ણ પથ",
|
"ButtonFullPath": "સંપૂર્ણ પથ",
|
||||||
"ButtonHide": "છુપાવો",
|
"ButtonHide": "છુપાવો",
|
||||||
"ButtonHome": "ઘર",
|
"ButtonHome": "ઘર",
|
||||||
"ButtonIssues": "સમસ્યાઓ",
|
"ButtonIssues": "સમસ્યાઓ",
|
||||||
|
"ButtonJumpBackward": "પાછળ જાવો",
|
||||||
|
"ButtonJumpForward": "આગળ જાવો",
|
||||||
"ButtonLatest": "નવીનતમ",
|
"ButtonLatest": "નવીનતમ",
|
||||||
"ButtonLibrary": "પુસ્તકાલય",
|
"ButtonLibrary": "પુસ્તકાલય",
|
||||||
"ButtonLogout": "લૉગ આઉટ",
|
"ButtonLogout": "લૉગ આઉટ",
|
||||||
@@ -41,19 +47,32 @@
|
|||||||
"ButtonMatchAllAuthors": "બધા મેળ ખાતા લેખકો શોધો",
|
"ButtonMatchAllAuthors": "બધા મેળ ખાતા લેખકો શોધો",
|
||||||
"ButtonMatchBooks": "મેળ ખાતી પુસ્તકો શોધો",
|
"ButtonMatchBooks": "મેળ ખાતી પુસ્તકો શોધો",
|
||||||
"ButtonNevermind": "કંઈ વાંધો નહીં",
|
"ButtonNevermind": "કંઈ વાંધો નહીં",
|
||||||
|
"ButtonNext": "આગળ જાઓ",
|
||||||
|
"ButtonNextChapter": "આગળનું અધ્યાય",
|
||||||
|
"ButtonNextItemInQueue": "કતારમાં આવતું આગળનું અધ્યાય",
|
||||||
"ButtonOk": "ઓકે",
|
"ButtonOk": "ઓકે",
|
||||||
"ButtonOpenFeed": "ફીડ ખોલો",
|
"ButtonOpenFeed": "ફીડ ખોલો",
|
||||||
"ButtonOpenManager": "મેનેજર ખોલો",
|
"ButtonOpenManager": "મેનેજર ખોલો",
|
||||||
|
"ButtonPause": "વિરામ",
|
||||||
"ButtonPlay": "ચલાવો",
|
"ButtonPlay": "ચલાવો",
|
||||||
|
"ButtonPlayAll": "બધું ચલાવો",
|
||||||
"ButtonPlaying": "ચલાવી રહ્યું છે",
|
"ButtonPlaying": "ચલાવી રહ્યું છે",
|
||||||
"ButtonPlaylists": "પ્લેલિસ્ટ",
|
"ButtonPlaylists": "પ્લેલિસ્ટ",
|
||||||
|
"ButtonPrevious": "પાછળનું",
|
||||||
|
"ButtonPreviousChapter": "પાછળનું અધ્યાય",
|
||||||
|
"ButtonProbeAudioFile": "ઑડિયો ફાઇલ તપાસો",
|
||||||
"ButtonPurgeAllCache": "બધો Cache કાઢી નાખો",
|
"ButtonPurgeAllCache": "બધો Cache કાઢી નાખો",
|
||||||
"ButtonPurgeItemsCache": "વસ્તુઓનો Cache કાઢી નાખો",
|
"ButtonPurgeItemsCache": "વસ્તુઓનો Cache કાઢી નાખો",
|
||||||
"ButtonQueueAddItem": "કતારમાં ઉમેરો",
|
"ButtonQueueAddItem": "કતારમાં ઉમેરો",
|
||||||
"ButtonQueueRemoveItem": "કતારથી કાઢી નાખો",
|
"ButtonQueueRemoveItem": "કતારથી કાઢી નાખો",
|
||||||
|
"ButtonQuickEmbed": "ઝડપથી સમાવેશ કરો",
|
||||||
|
"ButtonQuickEmbedMetadata": "ઝડપથી મેટાડેટા સમાવવો",
|
||||||
"ButtonQuickMatch": "ઝડપી મેળ ખવડાવો",
|
"ButtonQuickMatch": "ઝડપી મેળ ખવડાવો",
|
||||||
"ButtonReScan": "ફરીથી સ્કેન કરો",
|
"ButtonReScan": "ફરીથી સ્કેન કરો",
|
||||||
"ButtonRead": "વાંચો",
|
"ButtonRead": "વાંચો",
|
||||||
|
"ButtonReadLess": "ઓછું વાંચો",
|
||||||
|
"ButtonReadMore": "વધારે વાંચો",
|
||||||
|
"ButtonRefresh": "તાજું કરો",
|
||||||
"ButtonRemove": "કાઢી નાખો",
|
"ButtonRemove": "કાઢી નાખો",
|
||||||
"ButtonRemoveAll": "બધું કાઢી નાખો",
|
"ButtonRemoveAll": "બધું કાઢી નાખો",
|
||||||
"ButtonRemoveAllLibraryItems": "બધું પુસ્તકાલય વસ્તુઓ કાઢી નાખો",
|
"ButtonRemoveAllLibraryItems": "બધું પુસ્તકાલય વસ્તુઓ કાઢી નાખો",
|
||||||
@@ -68,16 +87,21 @@
|
|||||||
"ButtonSaveTracklist": "ટ્રેક યાદી સાચવો",
|
"ButtonSaveTracklist": "ટ્રેક યાદી સાચવો",
|
||||||
"ButtonScan": "સ્કેન કરો",
|
"ButtonScan": "સ્કેન કરો",
|
||||||
"ButtonScanLibrary": "પુસ્તકાલય સ્કેન કરો",
|
"ButtonScanLibrary": "પુસ્તકાલય સ્કેન કરો",
|
||||||
|
"ButtonScrollLeft": "ડાબે",
|
||||||
|
"ButtonScrollRight": "જમણે",
|
||||||
"ButtonSearch": "શોધો",
|
"ButtonSearch": "શોધો",
|
||||||
"ButtonSelectFolderPath": "ફોલ્ડર પથ પસંદ કરો",
|
"ButtonSelectFolderPath": "ફોલ્ડર પથ પસંદ કરો",
|
||||||
"ButtonSeries": "સિરીઝ",
|
"ButtonSeries": "સિરીઝ",
|
||||||
"ButtonSetChaptersFromTracks": "ટ્રેક્સથી પ્રકરણો સેટ કરો",
|
"ButtonSetChaptersFromTracks": "ટ્રેક્સથી પ્રકરણો સેટ કરો",
|
||||||
|
"ButtonShare": "શેર કરો",
|
||||||
"ButtonShiftTimes": "સમય શિફ્ટ કરો",
|
"ButtonShiftTimes": "સમય શિફ્ટ કરો",
|
||||||
"ButtonShow": "બતાવો",
|
"ButtonShow": "બતાવો",
|
||||||
"ButtonStartM4BEncode": "M4B એન્કોડ શરૂ કરો",
|
"ButtonStartM4BEncode": "M4B એન્કોડ શરૂ કરો",
|
||||||
"ButtonStartMetadataEmbed": "મેટાડેટા એમ્બેડ શરૂ કરો",
|
"ButtonStartMetadataEmbed": "મેટાડેટા એમ્બેડ શરૂ કરો",
|
||||||
|
"ButtonStats": "આંકડા",
|
||||||
"ButtonSubmit": "સબમિટ કરો",
|
"ButtonSubmit": "સબમિટ કરો",
|
||||||
"ButtonTest": "પરખ કરો",
|
"ButtonTest": "પરખ કરો",
|
||||||
|
"ButtonUnlinkOpenId": "OpenID દૂર કરો",
|
||||||
"ButtonUpload": "અપલોડ કરો",
|
"ButtonUpload": "અપલોડ કરો",
|
||||||
"ButtonUploadBackup": "બેકઅપ અપલોડ કરો",
|
"ButtonUploadBackup": "બેકઅપ અપલોડ કરો",
|
||||||
"ButtonUploadCover": "કવર અપલોડ કરો",
|
"ButtonUploadCover": "કવર અપલોડ કરો",
|
||||||
@@ -86,11 +110,16 @@
|
|||||||
"ButtonUserEdit": "વપરાશકર્તા {0} સંપાદિત કરો",
|
"ButtonUserEdit": "વપરાશકર્તા {0} સંપાદિત કરો",
|
||||||
"ButtonViewAll": "બધું જુઓ",
|
"ButtonViewAll": "બધું જુઓ",
|
||||||
"ButtonYes": "હા",
|
"ButtonYes": "હા",
|
||||||
|
"ErrorUploadFetchMetadataAPI": "મેટાડેટા મેળવવામાં તકલીફ આવી",
|
||||||
|
"ErrorUploadFetchMetadataNoResults": "મેટાડેટા મેળવી શક્યા નહીં – કૃપા કરીને શીર્ષક અને/અથવા લેખકનું નામ અપડેટ કરવાનો પ્રયત્ન કરો",
|
||||||
|
"ErrorUploadLacksTitle": "શીર્ષક હોવું આવશ્યક છે",
|
||||||
"HeaderAccount": "એકાઉન્ટ",
|
"HeaderAccount": "એકાઉન્ટ",
|
||||||
|
"HeaderAddCustomMetadataProvider": "કસ્ટમ મેટાડેટા પ્રોવાઇડર ઉમેરો",
|
||||||
"HeaderAdvanced": "અડ્વાન્સડ",
|
"HeaderAdvanced": "અડ્વાન્સડ",
|
||||||
"HeaderAppriseNotificationSettings": "Apprise સૂચના સેટિંગ્સ",
|
"HeaderAppriseNotificationSettings": "Apprise સૂચના સેટિંગ્સ",
|
||||||
"HeaderAudioTracks": "ઓડિયો ટ્રેક્સ",
|
"HeaderAudioTracks": "ઓડિયો ટ્રેક્સ",
|
||||||
"HeaderAudiobookTools": "ઓડિયોબુક ફાઇલ વ્યવસ્થાપન ટૂલ્સ",
|
"HeaderAudiobookTools": "ઓડિયોબુક ફાઇલ વ્યવસ્થાપન ટૂલ્સ",
|
||||||
|
"HeaderAuthentication": "પ્રમાણીકરણ",
|
||||||
"HeaderBackups": "બેકઅપ્સ",
|
"HeaderBackups": "બેકઅપ્સ",
|
||||||
"HeaderChangePassword": "પાસવર્ડ બદલો",
|
"HeaderChangePassword": "પાસવર્ડ બદલો",
|
||||||
"HeaderChapters": "પ્રકરણો",
|
"HeaderChapters": "પ્રકરણો",
|
||||||
@@ -99,6 +128,7 @@
|
|||||||
"HeaderCollectionItems": "સંગ્રહ વસ્તુઓ",
|
"HeaderCollectionItems": "સંગ્રહ વસ્તુઓ",
|
||||||
"HeaderCover": "આવરણ",
|
"HeaderCover": "આવરણ",
|
||||||
"HeaderCurrentDownloads": "વર્તમાન ડાઉનલોડ્સ",
|
"HeaderCurrentDownloads": "વર્તમાન ડાઉનલોડ્સ",
|
||||||
|
"HeaderCustomMetadataProviders": "કસ્ટમ મેટાડેટા પ્રોવાઇડર્સ",
|
||||||
"HeaderDetails": "વિગતો",
|
"HeaderDetails": "વિગતો",
|
||||||
"HeaderDownloadQueue": "ડાઉનલોડ કતાર",
|
"HeaderDownloadQueue": "ડાઉનલોડ કતાર",
|
||||||
"HeaderEbookFiles": "ઇબુક ફાઇલો",
|
"HeaderEbookFiles": "ઇબુક ફાઇલો",
|
||||||
@@ -129,6 +159,7 @@
|
|||||||
"HeaderMetadataToEmbed": "એમ્બેડ કરવા માટે મેટાડેટા",
|
"HeaderMetadataToEmbed": "એમ્બેડ કરવા માટે મેટાડેટા",
|
||||||
"HeaderNewAccount": "નવું એકાઉન્ટ",
|
"HeaderNewAccount": "નવું એકાઉન્ટ",
|
||||||
"HeaderNewLibrary": "નવી પુસ્તકાલય",
|
"HeaderNewLibrary": "નવી પુસ્તકાલય",
|
||||||
|
"HeaderNotificationCreate": "સૂચના બનાવો",
|
||||||
"HeaderNotifications": "સૂચનાઓ",
|
"HeaderNotifications": "સૂચનાઓ",
|
||||||
"HeaderOpenRSSFeed": "RSS ફીડ ખોલો",
|
"HeaderOpenRSSFeed": "RSS ફીડ ખોલો",
|
||||||
"HeaderOtherFiles": "અન્ય ફાઇલો",
|
"HeaderOtherFiles": "અન્ય ફાઇલો",
|
||||||
|
|||||||
+118
-48
@@ -10,6 +10,8 @@
|
|||||||
"ButtonApplyChapters": "החל פרקים",
|
"ButtonApplyChapters": "החל פרקים",
|
||||||
"ButtonAuthors": "סופרים",
|
"ButtonAuthors": "סופרים",
|
||||||
"ButtonBack": "חזור",
|
"ButtonBack": "חזור",
|
||||||
|
"ButtonBatchEditPopulateFromExisting": "מלא משדות קיימים",
|
||||||
|
"ButtonBatchEditPopulateMapDetails": "מלא פרטי מפה",
|
||||||
"ButtonBrowseForFolder": "עיין בתיקייה",
|
"ButtonBrowseForFolder": "עיין בתיקייה",
|
||||||
"ButtonCancel": "ביטול",
|
"ButtonCancel": "ביטול",
|
||||||
"ButtonCancelEncode": "בטל קידוד",
|
"ButtonCancelEncode": "בטל קידוד",
|
||||||
@@ -29,7 +31,9 @@
|
|||||||
"ButtonEdit": "ערוך",
|
"ButtonEdit": "ערוך",
|
||||||
"ButtonEditChapters": "ערוך פרקים",
|
"ButtonEditChapters": "ערוך פרקים",
|
||||||
"ButtonEditPodcast": "ערוך פודקאסט",
|
"ButtonEditPodcast": "ערוך פודקאסט",
|
||||||
"ButtonEnable": "הפעל",
|
"ButtonEnable": "אפשר",
|
||||||
|
"ButtonFireAndFail": "שלח בכישלון",
|
||||||
|
"ButtonFireOnTest": "שלח באירוע בדיקה",
|
||||||
"ButtonForceReScan": "סרוק מחדש בכוח",
|
"ButtonForceReScan": "סרוק מחדש בכוח",
|
||||||
"ButtonFullPath": "נתיב מלא",
|
"ButtonFullPath": "נתיב מלא",
|
||||||
"ButtonHide": "הסתר",
|
"ButtonHide": "הסתר",
|
||||||
@@ -37,7 +41,7 @@
|
|||||||
"ButtonIssues": "תקלות",
|
"ButtonIssues": "תקלות",
|
||||||
"ButtonJumpBackward": "דלג אחורה",
|
"ButtonJumpBackward": "דלג אחורה",
|
||||||
"ButtonJumpForward": "דלג קדימה",
|
"ButtonJumpForward": "דלג קדימה",
|
||||||
"ButtonLatest": "חדש ביותר",
|
"ButtonLatest": "אחרון",
|
||||||
"ButtonLibrary": "ספרייה",
|
"ButtonLibrary": "ספרייה",
|
||||||
"ButtonLogout": "התנתק",
|
"ButtonLogout": "התנתק",
|
||||||
"ButtonLookup": "חפש",
|
"ButtonLookup": "חפש",
|
||||||
@@ -70,7 +74,7 @@
|
|||||||
"ButtonReScan": "סרוק מחדש",
|
"ButtonReScan": "סרוק מחדש",
|
||||||
"ButtonRead": "קרא",
|
"ButtonRead": "קרא",
|
||||||
"ButtonReadLess": "קרא פחות",
|
"ButtonReadLess": "קרא פחות",
|
||||||
"ButtonReadMore": "קרא יותר",
|
"ButtonReadMore": "קרא עוד",
|
||||||
"ButtonRefresh": "רענן",
|
"ButtonRefresh": "רענן",
|
||||||
"ButtonRemove": "הסר",
|
"ButtonRemove": "הסר",
|
||||||
"ButtonRemoveAll": "הסר הכל",
|
"ButtonRemoveAll": "הסר הכל",
|
||||||
@@ -86,7 +90,9 @@
|
|||||||
"ButtonSaveTracklist": "שמור רשימת רצועות",
|
"ButtonSaveTracklist": "שמור רשימת רצועות",
|
||||||
"ButtonScan": "סרוק",
|
"ButtonScan": "סרוק",
|
||||||
"ButtonScanLibrary": "סרוק ספרייה",
|
"ButtonScanLibrary": "סרוק ספרייה",
|
||||||
"ButtonSearch": "חפש",
|
"ButtonScrollLeft": "גלול שמאלה",
|
||||||
|
"ButtonScrollRight": "גלול ימינה",
|
||||||
|
"ButtonSearch": "חיפוש",
|
||||||
"ButtonSelectFolderPath": "בחר נתיב לתיקייה",
|
"ButtonSelectFolderPath": "בחר נתיב לתיקייה",
|
||||||
"ButtonSeries": "סדרה",
|
"ButtonSeries": "סדרה",
|
||||||
"ButtonSetChaptersFromTracks": "קבע פרקים לפי הרצועות",
|
"ButtonSetChaptersFromTracks": "קבע פרקים לפי הרצועות",
|
||||||
@@ -96,7 +102,7 @@
|
|||||||
"ButtonStartM4BEncode": "התחל קידוד M4B",
|
"ButtonStartM4BEncode": "התחל קידוד M4B",
|
||||||
"ButtonStartMetadataEmbed": "התחל הטמעת מטא-נתונים",
|
"ButtonStartMetadataEmbed": "התחל הטמעת מטא-נתונים",
|
||||||
"ButtonStats": "סטטיסטיקות",
|
"ButtonStats": "סטטיסטיקות",
|
||||||
"ButtonSubmit": "שלח",
|
"ButtonSubmit": "שליחה",
|
||||||
"ButtonTest": "בדיקה",
|
"ButtonTest": "בדיקה",
|
||||||
"ButtonUnlinkOpenId": "נתק OpenID",
|
"ButtonUnlinkOpenId": "נתק OpenID",
|
||||||
"ButtonUpload": "העלה",
|
"ButtonUpload": "העלה",
|
||||||
@@ -122,26 +128,26 @@
|
|||||||
"HeaderChapters": "פרקים",
|
"HeaderChapters": "פרקים",
|
||||||
"HeaderChooseAFolder": "בחר תיקייה",
|
"HeaderChooseAFolder": "בחר תיקייה",
|
||||||
"HeaderCollection": "אוסף",
|
"HeaderCollection": "אוסף",
|
||||||
"HeaderCollectionItems": "פריטי אוסף",
|
"HeaderCollectionItems": "פרטי אוסף",
|
||||||
"HeaderCover": "כריכה",
|
"HeaderCover": "כריכה",
|
||||||
"HeaderCurrentDownloads": "הורדות נוכחיות",
|
"HeaderCurrentDownloads": "הורדות נוכחיות",
|
||||||
"HeaderCustomMessageOnLogin": "הודעה מותאמת אישית בהתחברות",
|
"HeaderCustomMessageOnLogin": "הודעה מותאמת אישית בהתחברות",
|
||||||
"HeaderCustomMetadataProviders": "ספקי מטא-נתונים מותאמים אישית",
|
"HeaderCustomMetadataProviders": "ספקי מטא-נתונים מותאמים אישית",
|
||||||
"HeaderDetails": "פרטים",
|
"HeaderDetails": "פרטים",
|
||||||
"HeaderDownloadQueue": "תור הורדה",
|
"HeaderDownloadQueue": "תור הורדה",
|
||||||
"HeaderEbookFiles": "קבצי ספר אלקטרוני",
|
"HeaderEbookFiles": "קבצי Ebook",
|
||||||
"HeaderEmail": "אימייל",
|
"HeaderEmail": "אימייל",
|
||||||
"HeaderEmailSettings": "הגדרות אימייל",
|
"HeaderEmailSettings": "הגדרות אימייל",
|
||||||
"HeaderEpisodes": "פרקים",
|
"HeaderEpisodes": "פרקים",
|
||||||
"HeaderEreaderDevices": "התקני קריאה דיגיטליים",
|
"HeaderEreaderDevices": "התקני קריאה דיגיטליים",
|
||||||
"HeaderEreaderSettings": "הגדרות התקני קריאה דיגיטליים",
|
"HeaderEreaderSettings": "הגדרות קורא אלקטרוני",
|
||||||
"HeaderFiles": "קבצים",
|
"HeaderFiles": "קבצים",
|
||||||
"HeaderFindChapters": "מצא פרקים",
|
"HeaderFindChapters": "מצא פרקים",
|
||||||
"HeaderIgnoredFiles": "קבצים שנתעלמו",
|
"HeaderIgnoredFiles": "קבצים שנתעלמו",
|
||||||
"HeaderItemFiles": "קבצי פריט",
|
"HeaderItemFiles": "קבצי פריט",
|
||||||
"HeaderItemMetadataUtils": "כלי מטא-נתונים",
|
"HeaderItemMetadataUtils": "כלי מטא-נתונים",
|
||||||
"HeaderLastListeningSession": "הפעלת האזנה אחרונה",
|
"HeaderLastListeningSession": "הפעלת האזנה אחרונה",
|
||||||
"HeaderLatestEpisodes": "הפרקים העדכניים ביותר",
|
"HeaderLatestEpisodes": "פרקים אחרונים",
|
||||||
"HeaderLibraries": "ספריות",
|
"HeaderLibraries": "ספריות",
|
||||||
"HeaderLibraryFiles": "קבצי ספרייה",
|
"HeaderLibraryFiles": "קבצי ספרייה",
|
||||||
"HeaderLibraryStats": "סטטיסטיקות ספרייה",
|
"HeaderLibraryStats": "סטטיסטיקות ספרייה",
|
||||||
@@ -171,8 +177,9 @@
|
|||||||
"HeaderPlaylist": "רשימת השמעה",
|
"HeaderPlaylist": "רשימת השמעה",
|
||||||
"HeaderPlaylistItems": "פריטי רשימת השמעה",
|
"HeaderPlaylistItems": "פריטי רשימת השמעה",
|
||||||
"HeaderPodcastsToAdd": "פודקאסטים להוספה",
|
"HeaderPodcastsToAdd": "פודקאסטים להוספה",
|
||||||
|
"HeaderPresets": "קביעות מוגדרות מראש",
|
||||||
"HeaderPreviewCover": "תצוגה מקדימה של כריכה",
|
"HeaderPreviewCover": "תצוגה מקדימה של כריכה",
|
||||||
"HeaderRSSFeedGeneral": "פרטי ערוץ RSS",
|
"HeaderRSSFeedGeneral": "פרטי RSS",
|
||||||
"HeaderRSSFeedIsOpen": "ערוץ RSS פתוח",
|
"HeaderRSSFeedIsOpen": "ערוץ RSS פתוח",
|
||||||
"HeaderRSSFeeds": "ערוצי RSS",
|
"HeaderRSSFeeds": "ערוצי RSS",
|
||||||
"HeaderRemoveEpisode": "הסר פרק",
|
"HeaderRemoveEpisode": "הסר פרק",
|
||||||
@@ -188,14 +195,15 @@
|
|||||||
"HeaderSettingsExperimental": "תכונות ניסיוניות",
|
"HeaderSettingsExperimental": "תכונות ניסיוניות",
|
||||||
"HeaderSettingsGeneral": "כללי",
|
"HeaderSettingsGeneral": "כללי",
|
||||||
"HeaderSettingsScanner": "סורק",
|
"HeaderSettingsScanner": "סורק",
|
||||||
|
"HeaderSettingsWebClient": "מערך",
|
||||||
"HeaderSleepTimer": "טיימר שינה",
|
"HeaderSleepTimer": "טיימר שינה",
|
||||||
"HeaderStatsLargestItems": "הפריטים הגדולים ביותר",
|
"HeaderStatsLargestItems": "הפריטים הגדולים ביותר",
|
||||||
"HeaderStatsLongestItems": "הפריטים הארוכים ביותר (בשעות)",
|
"HeaderStatsLongestItems": "הפריטים הארוכים ביותר (בשעות)",
|
||||||
"HeaderStatsMinutesListeningChart": "דקות האזנה (בימים האחרונים)",
|
"HeaderStatsMinutesListeningChart": "דקות האזנה (7 ימים אחרונים)",
|
||||||
"HeaderStatsRecentSessions": "הפעלות אחרונות",
|
"HeaderStatsRecentSessions": "האזנות אחרונות",
|
||||||
"HeaderStatsTop10Authors": "10 היוצרים המובילים",
|
"HeaderStatsTop10Authors": "10 היוצרים המובילים",
|
||||||
"HeaderStatsTop5Genres": "הז'אנרים המובילים 5",
|
"HeaderStatsTop5Genres": "הז'אנרים המובילים 5",
|
||||||
"HeaderTableOfContents": "תוכן העניינים",
|
"HeaderTableOfContents": "תוכן עניינים",
|
||||||
"HeaderTools": "כלים",
|
"HeaderTools": "כלים",
|
||||||
"HeaderUpdateAccount": "עדכן חשבון",
|
"HeaderUpdateAccount": "עדכן חשבון",
|
||||||
"HeaderUpdateAuthor": "עדכן יוצר",
|
"HeaderUpdateAuthor": "עדכן יוצר",
|
||||||
@@ -212,15 +220,17 @@
|
|||||||
"LabelAccountTypeAdmin": "מנהל",
|
"LabelAccountTypeAdmin": "מנהל",
|
||||||
"LabelAccountTypeGuest": "אורח",
|
"LabelAccountTypeGuest": "אורח",
|
||||||
"LabelAccountTypeUser": "משתמש",
|
"LabelAccountTypeUser": "משתמש",
|
||||||
|
"LabelActivities": "פעילויות",
|
||||||
"LabelActivity": "פעילות",
|
"LabelActivity": "פעילות",
|
||||||
"LabelAddToCollection": "הוסף לאוסף",
|
"LabelAddToCollection": "הוסף לאוסף",
|
||||||
"LabelAddToCollectionBatch": "הוסף {0} ספרים לאוסף",
|
"LabelAddToCollectionBatch": "הוסף {0} ספרים לאוסף",
|
||||||
"LabelAddToPlaylist": "הוסף לרשימת השמעה",
|
"LabelAddToPlaylist": "הוסף לרשימת השמעה",
|
||||||
"LabelAddToPlaylistBatch": "הוסף {0} פריטים לרשימת השמעה",
|
"LabelAddToPlaylistBatch": "הוסף {0} פריטים לרשימת השמעה",
|
||||||
"LabelAddedAt": "נוסף בתאריך",
|
"LabelAddedAt": "נוסף ב-",
|
||||||
"LabelAddedDate": "נוסף ב-{0}",
|
"LabelAddedDate": "נוסף ב-{0}",
|
||||||
"LabelAdminUsersOnly": "רק מנהלים",
|
"LabelAdminUsersOnly": "רק מנהלים",
|
||||||
"LabelAll": "הכל",
|
"LabelAll": "הכל",
|
||||||
|
"LabelAllEpisodesDownloaded": "כל הפרקים הורדו",
|
||||||
"LabelAllUsers": "כל המשתמשים",
|
"LabelAllUsers": "כל המשתמשים",
|
||||||
"LabelAllUsersExcludingGuests": "כל המשתמשים, ללא אורחים",
|
"LabelAllUsersExcludingGuests": "כל המשתמשים, ללא אורחים",
|
||||||
"LabelAllUsersIncludingGuests": "כל המשתמשים כולל אורחים",
|
"LabelAllUsersIncludingGuests": "כל המשתמשים כולל אורחים",
|
||||||
@@ -230,10 +240,10 @@
|
|||||||
"LabelAudioBitrate": "קצב סיביות (לדוגמא 128k)",
|
"LabelAudioBitrate": "קצב סיביות (לדוגמא 128k)",
|
||||||
"LabelAudioChannels": "ערוצי קול (1 או 2)",
|
"LabelAudioChannels": "ערוצי קול (1 או 2)",
|
||||||
"LabelAudioCodec": "קידוד קול",
|
"LabelAudioCodec": "קידוד קול",
|
||||||
"LabelAuthor": "יוצר",
|
"LabelAuthor": "סופר",
|
||||||
"LabelAuthorFirstLast": "יוצר (שם פרטי שם משפחה)",
|
"LabelAuthorFirstLast": "סופר (שם, משפחה)",
|
||||||
"LabelAuthorLastFirst": "יוצר (שם משפחה, שם פרטי)",
|
"LabelAuthorLastFirst": "סופר (משפחה, שם)",
|
||||||
"LabelAuthors": "יוצרים",
|
"LabelAuthors": "סופרים",
|
||||||
"LabelAutoDownloadEpisodes": "הורד פרקים באופן אוטומטי",
|
"LabelAutoDownloadEpisodes": "הורד פרקים באופן אוטומטי",
|
||||||
"LabelAutoFetchMetadata": "חפש והורד מטא-נתונים באופן אוטומטי",
|
"LabelAutoFetchMetadata": "חפש והורד מטא-נתונים באופן אוטומטי",
|
||||||
"LabelAutoFetchMetadataHelp": "מחפש ומוריד מטא-נתונים לשדות כותרת, יוצר וסדרה כדי לשפר את תהליך ההעלאה. ייתכן שיהיה צורך להתאים מטא-נתונים נוסף לאחר ההעלאה.",
|
"LabelAutoFetchMetadataHelp": "מחפש ומוריד מטא-נתונים לשדות כותרת, יוצר וסדרה כדי לשפר את תהליך ההעלאה. ייתכן שיהיה צורך להתאים מטא-נתונים נוסף לאחר ההעלאה.",
|
||||||
@@ -242,36 +252,48 @@
|
|||||||
"LabelAutoRegister": "הרשמה אוטומטית",
|
"LabelAutoRegister": "הרשמה אוטומטית",
|
||||||
"LabelAutoRegisterDescription": "יצירת משתמשים חדשים אוטומטית לאחר התחברות",
|
"LabelAutoRegisterDescription": "יצירת משתמשים חדשים אוטומטית לאחר התחברות",
|
||||||
"LabelBackToUser": "חזרה למשתמש",
|
"LabelBackToUser": "חזרה למשתמש",
|
||||||
|
"LabelBackupAudioFiles": "גיבוי קבצי שמע",
|
||||||
"LabelBackupLocation": "מיקום גיבוי",
|
"LabelBackupLocation": "מיקום גיבוי",
|
||||||
"LabelBackupsEnableAutomaticBackups": "הפעל גיבויים אוטומטיים",
|
"LabelBackupsEnableAutomaticBackups": "גיבויים אוטומטיים",
|
||||||
"LabelBackupsEnableAutomaticBackupsHelp": "גיבויים שמורים ב /metadata/backups",
|
"LabelBackupsEnableAutomaticBackupsHelp": "גיבויים שמורים ב /metadata/backups",
|
||||||
"LabelBackupsMaxBackupSize": "גודל הגיבוי המרבי (בג'יגה-בייט)",
|
"LabelBackupsMaxBackupSize": "גודל הגיבוי המרבי (בג'יגה-בייט) (0 - ללא הגבלה)",
|
||||||
"LabelBackupsMaxBackupSizeHelp": "כהגנה על עצמך מפני תצורה שגויה, הגיבויים ייכשלו אם הם יעברו את הגודל שהוגדר.",
|
"LabelBackupsMaxBackupSizeHelp": "כהגנה על עצמך מפני תצורה שגויה, הגיבויים ייכשלו אם הם יעברו את הגודל שהוגדר.",
|
||||||
"LabelBackupsNumberToKeep": "מספר הגיבויים לשמירה",
|
"LabelBackupsNumberToKeep": "מספר הגיבויים לשמירה",
|
||||||
"LabelBackupsNumberToKeepHelp": "רק גיבוי אחד יוסר בכל פעם, לכן אם יש לך כבר יותר מגיבוי אחד יש להסיר אותם באופן ידני.",
|
"LabelBackupsNumberToKeepHelp": "רק גיבוי אחד יוסר בכל פעם, לכן אם יש לך כבר יותר מגיבוי אחד יש להסיר אותם באופן ידני.",
|
||||||
"LabelBitrate": "קצב סיביות",
|
"LabelBitrate": "קצב סיביות",
|
||||||
|
"LabelBonus": "בונוס",
|
||||||
"LabelBooks": "ספרים",
|
"LabelBooks": "ספרים",
|
||||||
"LabelButtonText": "טקסט לחצן",
|
"LabelButtonText": "טקסט לחצן",
|
||||||
|
"LabelByAuthor": "על ידי {0}",
|
||||||
"LabelChangePassword": "שינוי סיסמה",
|
"LabelChangePassword": "שינוי סיסמה",
|
||||||
"LabelChannels": "ערוצים",
|
"LabelChannels": "ערוצים",
|
||||||
|
"LabelChapterCount": "{0} פרקים",
|
||||||
"LabelChapterTitle": "כותרת הפרק",
|
"LabelChapterTitle": "כותרת הפרק",
|
||||||
"LabelChapters": "פרקים",
|
"LabelChapters": "פרקים",
|
||||||
"LabelChaptersFound": "פרקים שנמצאו",
|
"LabelChaptersFound": "פרקים שנמצאו",
|
||||||
"LabelClickForMoreInfo": "לחץ למידע נוסף",
|
"LabelClickForMoreInfo": "לחץ למידע נוסף",
|
||||||
|
"LabelClickToUseCurrentValue": "לחץ לשימוש בערך הנוכחי",
|
||||||
"LabelClosePlayer": "סגור נגן",
|
"LabelClosePlayer": "סגור נגן",
|
||||||
"LabelCollapseSeries": "צמצום סדרה",
|
"LabelCodec": "Coded",
|
||||||
|
"LabelCollapseSeries": "הסתר סדרה",
|
||||||
|
"LabelCollapseSubSeries": "הסתר תת סדרה",
|
||||||
"LabelCollection": "אוסף",
|
"LabelCollection": "אוסף",
|
||||||
"LabelCollections": "אוספים",
|
"LabelCollections": "אוספים",
|
||||||
"LabelComplete": "מלא",
|
"LabelComplete": "הושלם",
|
||||||
"LabelConfirmPassword": "אישור סיסמה",
|
"LabelConfirmPassword": "אישור סיסמה",
|
||||||
"LabelContinueListening": "המשך האזנה",
|
"LabelContinueListening": "המשך האזנה",
|
||||||
"LabelContinueReading": "המשך קריאה",
|
"LabelContinueReading": "המשך קריאה",
|
||||||
"LabelContinueSeries": "המשך סדרה",
|
"LabelContinueSeries": "המשך סדרה",
|
||||||
"LabelCover": "כריכה",
|
"LabelCover": "כריכה",
|
||||||
"LabelCoverImageURL": "כתובת התמונה ברשת",
|
"LabelCoverImageURL": "כתובת התמונה ברשת",
|
||||||
|
"LabelCoverProvider": "ספק כריכה",
|
||||||
"LabelCreatedAt": "נוצר בתאריך",
|
"LabelCreatedAt": "נוצר בתאריך",
|
||||||
|
"LabelCronExpression": "ביטוי cron",
|
||||||
"LabelCurrent": "נוכחי",
|
"LabelCurrent": "נוכחי",
|
||||||
"LabelCurrently": "כעת:",
|
"LabelCurrently": "כעת:",
|
||||||
|
"LabelCustomCronExpression": "ביטוי cron מותאם אישית:",
|
||||||
|
"LabelDatetime": "Datetime",
|
||||||
|
"LabelDays": "ימים",
|
||||||
"LabelDeleteFromFileSystemCheckbox": "מחיקה מהמערכת הקבצים (הסר סימון למחיקה רק ממסד הנתונים)",
|
"LabelDeleteFromFileSystemCheckbox": "מחיקה מהמערכת הקבצים (הסר סימון למחיקה רק ממסד הנתונים)",
|
||||||
"LabelDescription": "תיאור",
|
"LabelDescription": "תיאור",
|
||||||
"LabelDeselectAll": "הסר בחירת כל הפריטים",
|
"LabelDeselectAll": "הסר בחירת כל הפריטים",
|
||||||
@@ -282,51 +304,83 @@
|
|||||||
"LabelDiscFromFilename": "דיסק משם הקובץ",
|
"LabelDiscFromFilename": "דיסק משם הקובץ",
|
||||||
"LabelDiscFromMetadata": "דיסק מהמטא-נתונים",
|
"LabelDiscFromMetadata": "דיסק מהמטא-נתונים",
|
||||||
"LabelDiscover": "גלה",
|
"LabelDiscover": "גלה",
|
||||||
"LabelDownload": "הורד",
|
"LabelDownload": "הורדה",
|
||||||
"LabelDownloadNEpisodes": "הורד {0} פרקים",
|
"LabelDownloadNEpisodes": "הורד {0} פרקים",
|
||||||
|
"LabelDownloadable": "ניתן להורדה",
|
||||||
"LabelDuration": "משך",
|
"LabelDuration": "משך",
|
||||||
|
"LabelDurationComparisonExactMatch": "(התאמה מדוייקת)",
|
||||||
|
"LabelDurationComparisonLonger": "({0} ארוך יותר)",
|
||||||
|
"LabelDurationComparisonShorter": "({0} קצר יותר)",
|
||||||
"LabelDurationFound": "משך נמצא:",
|
"LabelDurationFound": "משך נמצא:",
|
||||||
"LabelEbook": "ספר אלקטרוני",
|
"LabelEbook": "ספר אלקטרוני",
|
||||||
"LabelEbooks": "ספרים אלקטרוניים",
|
"LabelEbooks": "ספרים אלקטרוניים",
|
||||||
"LabelEdit": "עריכה",
|
"LabelEdit": "עריכה",
|
||||||
"LabelEmail": "דואר אלקטרוני",
|
"LabelEmail": "דואר אלקטרוני",
|
||||||
"LabelEmailSettingsFromAddress": "מאת",
|
"LabelEmailSettingsFromAddress": "מאת",
|
||||||
|
"LabelEmailSettingsRejectUnauthorized": "דחה תעודות לא מאושרות",
|
||||||
|
"LabelEmailSettingsRejectUnauthorizedHelp": "השבתת אימות תעודת SSL עלולה לחשוף את החיבור שלך לסיכוני אבטחה, כגון התקפות \"אדם באמצע\". השבת אפשרות זו רק אם אתה מבין את ההשלכות ובוטח בשרת הדואר שאליו אתה מתחבר.",
|
||||||
"LabelEmailSettingsSecure": "מאובטח",
|
"LabelEmailSettingsSecure": "מאובטח",
|
||||||
"LabelEmailSettingsSecureHelp": "אם מופעל, החיבור ישתמש ב-TLS בעת ההתחברות לשרת. אם לא, אז TLS יהיה בשימוש אם השרת תומך בהרחבת STARTTLS. ברוב המקרים מומלץ להפעיל את הגדרה זו אם אתה מתחבר לפורט 465. לפורט 587 או 25, השאר כבוי. (from nodemailer.com/smtp/#authentication)",
|
"LabelEmailSettingsSecureHelp": "אם מופעל, החיבור ישתמש ב-TLS בעת ההתחברות לשרת. אם לא, אז TLS יהיה בשימוש אם השרת תומך בהרחבת STARTTLS. ברוב המקרים מומלץ להפעיל את הגדרה זו אם אתה מתחבר לפורט 465. לפורט 587 או 25, השאר כבוי. (from nodemailer.com/smtp/#authentication)",
|
||||||
"LabelEmailSettingsTestAddress": "כתובת לבדיקה",
|
"LabelEmailSettingsTestAddress": "כתובת לבדיקה",
|
||||||
"LabelEmbeddedCover": "כריכה מוטמעת",
|
"LabelEmbeddedCover": "כריכה מוטמעת",
|
||||||
"LabelEnable": "הפעל",
|
"LabelEnable": "אפשר",
|
||||||
"LabelEnd": "סיום",
|
"LabelEncodingBackupLocation": "גיבוי של קבצי אודיו מקוריים יישמר ב:",
|
||||||
|
"LabelEncodingChaptersNotEmbedded": "פרקים אינם מוטבעים בספרי אודיו מרובי רצועות.",
|
||||||
|
"LabelEncodingClearItemCache": "הקפד לנקות מטמון פריטים מעת לעת.",
|
||||||
|
"LabelEncodingFinishedM4B": "קובץ M4B סופי יישמר בתיקייה ה-audiobook ב:",
|
||||||
|
"LabelEncodingInfoEmbedded": "מטה דאטה יוטמע ברצועות השמע בתוך תיקיית ה-audiobook.",
|
||||||
|
"LabelEncodingStartedNavigation": "לאחר שהמשימה תתחיל אפשר לנווט לדף אחר.",
|
||||||
|
"LabelEncodingTimeWarning": "קידוד יכול להימשך עד 30 דקות.",
|
||||||
|
"LabelEncodingWarningAdvancedSettings": "אזהרה: אל תעדכן את ההגדרות האלה אלא אם כן אתה מכיר את אפשרויות קידוד ffmpeg.",
|
||||||
|
"LabelEncodingWatcherDisabled": "אם ה-watcher כבוי, יש לסרוק את הספר מחדש לאחר מכן.",
|
||||||
|
"LabelEnd": "סוף",
|
||||||
|
"LabelEndOfChapter": "סוף הפרק",
|
||||||
"LabelEpisode": "פרק",
|
"LabelEpisode": "פרק",
|
||||||
|
"LabelEpisodeNotLinkedToRssFeed": "פרק לא מקושר לערוץ RSS",
|
||||||
|
"LabelEpisodeNumber": "פרק #{0}",
|
||||||
"LabelEpisodeTitle": "כותרת הפרק",
|
"LabelEpisodeTitle": "כותרת הפרק",
|
||||||
"LabelEpisodeType": "סוג הפרק",
|
"LabelEpisodeType": "סוג הפרק",
|
||||||
|
"LabelEpisodeUrlFromRssFeed": "קישור פרק מערוץ RSS",
|
||||||
|
"LabelEpisodes": "פרקים",
|
||||||
|
"LabelEpisodic": "ארעי",
|
||||||
"LabelExample": "דוגמה",
|
"LabelExample": "דוגמה",
|
||||||
|
"LabelExpandSeries": "הרחב סדרה",
|
||||||
|
"LabelExpandSubSeries": "הרחב תת סדרה",
|
||||||
"LabelExplicit": "בוטה",
|
"LabelExplicit": "בוטה",
|
||||||
|
"LabelExplicitChecked": "בוטה (מסומן)",
|
||||||
|
"LabelExplicitUnchecked": "לא בוטה (לא מסומן)",
|
||||||
|
"LabelExportOPML": "ייצוא OPML",
|
||||||
"LabelFeedURL": "כתובת ערוץ",
|
"LabelFeedURL": "כתובת ערוץ",
|
||||||
"LabelFetchingMetadata": "מושך מטא-נתונים",
|
"LabelFetchingMetadata": "מושך מטא-נתונים",
|
||||||
"LabelFile": "קובץ",
|
"LabelFile": "קובץ",
|
||||||
"LabelFileBirthtime": "זמן יצירת הקובץ",
|
"LabelFileBirthtime": "זמן יצירת הקובץ",
|
||||||
"LabelFileModified": "הקובץ שונה",
|
"LabelFileBornDate": "נוצר {0}",
|
||||||
"LabelFilename": "שם הקובץ",
|
"LabelFileModified": "קובץ נערך",
|
||||||
|
"LabelFileModifiedDate": "שונה {0}",
|
||||||
|
"LabelFilename": "שם קובץ",
|
||||||
"LabelFilterByUser": "סינון לפי משתמש",
|
"LabelFilterByUser": "סינון לפי משתמש",
|
||||||
"LabelFindEpisodes": "מצא פרקים",
|
"LabelFindEpisodes": "מצא פרקים",
|
||||||
"LabelFinished": "הושלם",
|
"LabelFinished": "הושלם",
|
||||||
"LabelFolder": "תיקייה",
|
"LabelFolder": "תיקייה",
|
||||||
"LabelFolders": "תיקיות",
|
"LabelFolders": "תיקיות",
|
||||||
"LabelFontBold": "מודגש",
|
"LabelFontBold": "מודגש",
|
||||||
|
"LabelFontBoldness": "עובי פונט",
|
||||||
"LabelFontFamily": "משפחת הפונטים",
|
"LabelFontFamily": "משפחת הפונטים",
|
||||||
"LabelFontItalic": "נטוי",
|
"LabelFontItalic": "נטוי",
|
||||||
"LabelFontScale": "קנה מידה של הפונט",
|
"LabelFontScale": "גודל פונט",
|
||||||
"LabelFontStrikethrough": "קו חוצה",
|
"LabelFontStrikethrough": "קו חוצה",
|
||||||
"LabelFormat": "תבנית",
|
"LabelFormat": "תבנית",
|
||||||
"LabelGenre": "ז'אנר",
|
"LabelFull": "מלא",
|
||||||
"LabelGenres": "ז'אנרים",
|
"LabelGenre": "סגנון",
|
||||||
|
"LabelGenres": "סגנונות",
|
||||||
"LabelHardDeleteFile": "מחיקה חזקה של הקובץ",
|
"LabelHardDeleteFile": "מחיקה חזקה של הקובץ",
|
||||||
"LabelHasEbook": "ספר אלקטרוני קיים",
|
"LabelHasEbook": "קיים ספר אלקטרוני",
|
||||||
"LabelHasSupplementaryEbook": "קיים ספר אלקטרוני נלווה",
|
"LabelHasSupplementaryEbook": "קיים ספר אלקטרוני משלים",
|
||||||
|
"LabelHideSubtitles": "הסתר תת כותרות",
|
||||||
"LabelHighestPriority": "העדיפות הגבוהה ביותר",
|
"LabelHighestPriority": "העדיפות הגבוהה ביותר",
|
||||||
"LabelHost": "מארח",
|
"LabelHost": "מארח",
|
||||||
"LabelHour": "שעה",
|
"LabelHour": "שעה",
|
||||||
|
"LabelHours": "שעות",
|
||||||
"LabelIcon": "סמל",
|
"LabelIcon": "סמל",
|
||||||
"LabelImageURLFromTheWeb": "כתובת התמונה מהרשת",
|
"LabelImageURLFromTheWeb": "כתובת התמונה מהרשת",
|
||||||
"LabelInProgress": "בתהליך",
|
"LabelInProgress": "בתהליך",
|
||||||
@@ -341,25 +395,30 @@
|
|||||||
"LabelIntervalEvery6Hours": "כל 6 שעות",
|
"LabelIntervalEvery6Hours": "כל 6 שעות",
|
||||||
"LabelIntervalEveryDay": "כל יום",
|
"LabelIntervalEveryDay": "כל יום",
|
||||||
"LabelIntervalEveryHour": "כל שעה",
|
"LabelIntervalEveryHour": "כל שעה",
|
||||||
|
"LabelIntervalEveryMinute": "כל דקה",
|
||||||
"LabelInvert": "הפוך",
|
"LabelInvert": "הפוך",
|
||||||
"LabelItem": "פריט",
|
"LabelItem": "פריט",
|
||||||
|
"LabelJumpBackwardAmount": "כמות הרצה לאחור",
|
||||||
|
"LabelJumpForwardAmount": "כמות הרצה קדימה",
|
||||||
"LabelLanguage": "שפה",
|
"LabelLanguage": "שפה",
|
||||||
"LabelLanguageDefaultServer": "שפת ברירת המחדל של השרת",
|
"LabelLanguageDefaultServer": "שפת ברירת המחדל של השרת",
|
||||||
|
"LabelLanguages": "שפות",
|
||||||
"LabelLastBookAdded": "הספר האחרון שנוסף",
|
"LabelLastBookAdded": "הספר האחרון שנוסף",
|
||||||
"LabelLastBookUpdated": "הספר האחרון שעודכן",
|
"LabelLastBookUpdated": "הספר האחרון שעודכן",
|
||||||
"LabelLastSeen": "נראה לאחרונה",
|
"LabelLastSeen": "נראה לאחרונה",
|
||||||
"LabelLastTime": "הזמן האחרון",
|
"LabelLastTime": "הזמן האחרון",
|
||||||
"LabelLastUpdate": "עדכון אחרון",
|
"LabelLastUpdate": "עדכון אחרון",
|
||||||
"LabelLayout": "פריסה",
|
"LabelLayout": "Layout",
|
||||||
"LabelLayoutSinglePage": "דף בודד",
|
"LabelLayoutSinglePage": "עמוד יחיד",
|
||||||
"LabelLayoutSplitPage": "פיצול הדף",
|
"LabelLayoutSplitPage": "פיצול הדף",
|
||||||
"LabelLess": "פחות",
|
"LabelLess": "פחות",
|
||||||
"LabelLibrariesAccessibleToUser": "ספריות נגישות למשתמש",
|
"LabelLibrariesAccessibleToUser": "ספריות נגישות למשתמש",
|
||||||
"LabelLibrary": "ספרייה",
|
"LabelLibrary": "ספרייה",
|
||||||
|
"LabelLibraryFilterSublistEmpty": "לא {0}",
|
||||||
"LabelLibraryItem": "פריט ספרייה",
|
"LabelLibraryItem": "פריט ספרייה",
|
||||||
"LabelLibraryName": "שם הספרייה",
|
"LabelLibraryName": "שם הספרייה",
|
||||||
"LabelLimit": "מגבלה",
|
"LabelLimit": "מגבלה",
|
||||||
"LabelLineSpacing": "ריווח שורות",
|
"LabelLineSpacing": "מרווח שורה",
|
||||||
"LabelListenAgain": "האזן שוב",
|
"LabelListenAgain": "האזן שוב",
|
||||||
"LabelLogLevelDebug": "דיבוג",
|
"LabelLogLevelDebug": "דיבוג",
|
||||||
"LabelLogLevelInfo": "מידע",
|
"LabelLogLevelInfo": "מידע",
|
||||||
@@ -368,6 +427,10 @@
|
|||||||
"LabelLowestPriority": "העדיפות הנמוכה ביותר",
|
"LabelLowestPriority": "העדיפות הנמוכה ביותר",
|
||||||
"LabelMatchExistingUsersBy": "התאם משתמשים קיימים לפי",
|
"LabelMatchExistingUsersBy": "התאם משתמשים קיימים לפי",
|
||||||
"LabelMatchExistingUsersByDescription": "משמש לחיבור משתמשים קיימים. לאחר החיבור, המשתמשים יותאמו לפי זיהוי ייחודי מספק ה-SSO שלך",
|
"LabelMatchExistingUsersByDescription": "משמש לחיבור משתמשים קיימים. לאחר החיבור, המשתמשים יותאמו לפי זיהוי ייחודי מספק ה-SSO שלך",
|
||||||
|
"LabelMaxEpisodesToDownload": "מספר פרקים מקסימלי להורדה. 0 - ללא הגבלה.",
|
||||||
|
"LabelMaxEpisodesToDownloadPerCheck": "מספר פרקים חדשים מקסימלי להורדה בכל בדיקה",
|
||||||
|
"LabelMaxEpisodesToKeep": "מספר פרקים מקסימלי לשמור",
|
||||||
|
"LabelMaxEpisodesToKeepHelp": "ערך של 0 קובע ללא מגבלה. לאחר הורדה אוטומטית של פרק חדש יימחק את הפרק הישן ביותר אם יש לך יותר מ-X פרקים. פעולה זו תמחק רק פרק אחד לכל הורדה חדשה.",
|
||||||
"LabelMediaPlayer": "נגן מדיה",
|
"LabelMediaPlayer": "נגן מדיה",
|
||||||
"LabelMediaType": "סוג מדיה",
|
"LabelMediaType": "סוג מדיה",
|
||||||
"LabelMetaTag": "תג מטא",
|
"LabelMetaTag": "תג מטא",
|
||||||
@@ -375,6 +438,7 @@
|
|||||||
"LabelMetadataOrderOfPrecedenceDescription": "מקורות המטא-נתונים עם עדיפות גבוהה יחליפו מקורות עם עדיפות נמוכה יותר",
|
"LabelMetadataOrderOfPrecedenceDescription": "מקורות המטא-נתונים עם עדיפות גבוהה יחליפו מקורות עם עדיפות נמוכה יותר",
|
||||||
"LabelMetadataProvider": "ספק מטא-נתונים",
|
"LabelMetadataProvider": "ספק מטא-נתונים",
|
||||||
"LabelMinute": "דקה",
|
"LabelMinute": "דקה",
|
||||||
|
"LabelMinutes": "דקות",
|
||||||
"LabelMissing": "חסר",
|
"LabelMissing": "חסר",
|
||||||
"LabelMissingEbook": "אין ספר אלקטרוני",
|
"LabelMissingEbook": "אין ספר אלקטרוני",
|
||||||
"LabelMissingSupplementaryEbook": "אין ספר אלקטרוני נלווה",
|
"LabelMissingSupplementaryEbook": "אין ספר אלקטרוני נלווה",
|
||||||
@@ -387,10 +451,11 @@
|
|||||||
"LabelNarrators": "מספרים",
|
"LabelNarrators": "מספרים",
|
||||||
"LabelNew": "חדש",
|
"LabelNew": "חדש",
|
||||||
"LabelNewPassword": "סיסמה חדשה",
|
"LabelNewPassword": "סיסמה חדשה",
|
||||||
"LabelNewestAuthors": "הסופרים החדשים ביותר",
|
"LabelNewestAuthors": "הסופרים האחרונים",
|
||||||
"LabelNewestEpisodes": "הפרקים החדשים ביותר",
|
"LabelNewestEpisodes": "הפרקים החדשים ביותר",
|
||||||
"LabelNextBackupDate": "תאריך הגיבוי הבא",
|
"LabelNextBackupDate": "תאריך הגיבוי הבא",
|
||||||
"LabelNextScheduledRun": "הרצה מתוזמנת הבאה",
|
"LabelNextScheduledRun": "הרצה מתוזמנת הבאה",
|
||||||
|
"LabelNoCustomMetadataProviders": "אין ספקי מטא-נתונים מותאמים אישית",
|
||||||
"LabelNoEpisodesSelected": "לא נבחרו פרקים",
|
"LabelNoEpisodesSelected": "לא נבחרו פרקים",
|
||||||
"LabelNotFinished": "לא הושלם",
|
"LabelNotFinished": "לא הושלם",
|
||||||
"LabelNotStarted": "לא התחיל",
|
"LabelNotStarted": "לא התחיל",
|
||||||
@@ -405,7 +470,9 @@
|
|||||||
"LabelNotificationsMaxQueueSize": "גודל התור המרבי לאירועי התראה",
|
"LabelNotificationsMaxQueueSize": "גודל התור המרבי לאירועי התראה",
|
||||||
"LabelNotificationsMaxQueueSizeHelp": "האירועים מוגבלים לשליחה אחת לשנייה. האירועים יתעלמו אם התור מלא. הגדרה זו נועדה למנוע ספאם התראות.",
|
"LabelNotificationsMaxQueueSizeHelp": "האירועים מוגבלים לשליחה אחת לשנייה. האירועים יתעלמו אם התור מלא. הגדרה זו נועדה למנוע ספאם התראות.",
|
||||||
"LabelNumberOfBooks": "מספר הספרים",
|
"LabelNumberOfBooks": "מספר הספרים",
|
||||||
"LabelNumberOfEpisodes": "מספר הפרקים",
|
"LabelNumberOfEpisodes": "# פרקים",
|
||||||
|
"LabelOpenIDAdvancedPermsClaimDescription": "שם OpenID claim המכילה הרשאות מתקדמות לפעולות משתמש בתוך האפליקציה, אשר יחולו על תפקידים שאינם מנהלי מערכת (<b>אם הוגדרה</b>). אם התביעה חסרה בתגובה, הגישה ל-ABS תידחה. אם אפשרות אחת חסרה, היא תטופל כ-<code>false</code> יש לוודא שטענת ספק הזהויות תואמת את המבנה הצפוי:",
|
||||||
|
"LabelOpenIDClaims": "השאר את האפשרויות הבאות ריקות כדי להשבית הקצאת קבוצות והרשאות מתקדמת, ולאחר מכן להקצות אוטומטית את קבוצת 'משתמש'.",
|
||||||
"LabelOpenRSSFeed": "פתח ערוץ RSS",
|
"LabelOpenRSSFeed": "פתח ערוץ RSS",
|
||||||
"LabelOverwrite": "לשכפל",
|
"LabelOverwrite": "לשכפל",
|
||||||
"LabelPassword": "סיסמה",
|
"LabelPassword": "סיסמה",
|
||||||
@@ -433,13 +500,15 @@
|
|||||||
"LabelProvider": "ספק",
|
"LabelProvider": "ספק",
|
||||||
"LabelPubDate": "תאריך פרסום",
|
"LabelPubDate": "תאריך פרסום",
|
||||||
"LabelPublishYear": "שנת הפרסום",
|
"LabelPublishYear": "שנת הפרסום",
|
||||||
|
"LabelPublishedDate": "פורסם {0}",
|
||||||
"LabelPublisher": "מוציא לאור",
|
"LabelPublisher": "מוציא לאור",
|
||||||
"LabelRSSFeedCustomOwnerEmail": "אימייל בעלים מותאם אישית",
|
"LabelRSSFeedCustomOwnerEmail": "אימייל בעלים מותאם אישית",
|
||||||
"LabelRSSFeedCustomOwnerName": "שם בעלים מותאם אישית",
|
"LabelRSSFeedCustomOwnerName": "שם בעלים מותאם אישית",
|
||||||
"LabelRSSFeedOpen": "פתח ערוץ RSS",
|
"LabelRSSFeedOpen": "ערוץ RSS פתוח",
|
||||||
"LabelRSSFeedPreventIndexing": "מנע רישום",
|
"LabelRSSFeedPreventIndexing": "מנע רישום",
|
||||||
"LabelRSSFeedSlug": "Slug של ערוץ ה-RSS",
|
"LabelRSSFeedSlug": "Slug של ערוץ ה-RSS",
|
||||||
"LabelRSSFeedURL": "כתובת ערוץ ה-RSS",
|
"LabelRSSFeedURL": "כתובת ערוץ ה-RSS",
|
||||||
|
"LabelRandomly": "באופן אקראי",
|
||||||
"LabelRead": "קריאה",
|
"LabelRead": "קריאה",
|
||||||
"LabelReadAgain": "קרא שוב",
|
"LabelReadAgain": "קרא שוב",
|
||||||
"LabelReadEbookWithoutProgress": "קרא/י ספר אלקטרוני ללא שמירת התקדמות",
|
"LabelReadEbookWithoutProgress": "קרא/י ספר אלקטרוני ללא שמירת התקדמות",
|
||||||
@@ -465,7 +534,7 @@
|
|||||||
"LabelSeriesProgress": "התקדמות בסדרה",
|
"LabelSeriesProgress": "התקדמות בסדרה",
|
||||||
"LabelServerYearReview": "השנה בסקירה של השרת ({0})",
|
"LabelServerYearReview": "השנה בסקירה של השרת ({0})",
|
||||||
"LabelSetEbookAsPrimary": "קבע כראשי",
|
"LabelSetEbookAsPrimary": "קבע כראשי",
|
||||||
"LabelSetEbookAsSupplementary": "קבע כספר אלקטרוני נלווה",
|
"LabelSetEbookAsSupplementary": "קבע כמשלים",
|
||||||
"LabelSettingsAudiobooksOnly": "רק ספרי קול",
|
"LabelSettingsAudiobooksOnly": "רק ספרי קול",
|
||||||
"LabelSettingsAudiobooksOnlyHelp": "הפעלת ההגדרה הזו תתעלם מקבצי ספרים אלקטרוניים אלא אם כן הם נמצאים בתיקיית ספרי קול, שבמקרה זה יקבעו כספרים אלקטרוניים נלווים",
|
"LabelSettingsAudiobooksOnlyHelp": "הפעלת ההגדרה הזו תתעלם מקבצי ספרים אלקטרוניים אלא אם כן הם נמצאים בתיקיית ספרי קול, שבמקרה זה יקבעו כספרים אלקטרוניים נלווים",
|
||||||
"LabelSettingsBookshelfViewHelp": "עיצוב סקאומורפי עם מדפי עץ",
|
"LabelSettingsBookshelfViewHelp": "עיצוב סקאומורפי עם מדפי עץ",
|
||||||
@@ -500,7 +569,7 @@
|
|||||||
"LabelShowAll": "הצג הכל",
|
"LabelShowAll": "הצג הכל",
|
||||||
"LabelSize": "גודל",
|
"LabelSize": "גודל",
|
||||||
"LabelSleepTimer": "טיימר שינה",
|
"LabelSleepTimer": "טיימר שינה",
|
||||||
"LabelStart": "התחלה",
|
"LabelStart": "התחל",
|
||||||
"LabelStartTime": "זמן התחלה",
|
"LabelStartTime": "זמן התחלה",
|
||||||
"LabelStarted": "התחיל",
|
"LabelStarted": "התחיל",
|
||||||
"LabelStartedAt": "התחיל ב",
|
"LabelStartedAt": "התחיל ב",
|
||||||
@@ -576,8 +645,8 @@
|
|||||||
"LabelViewQueue": "הצג תור נגן",
|
"LabelViewQueue": "הצג תור נגן",
|
||||||
"LabelVolume": "עוצמת קול",
|
"LabelVolume": "עוצמת קול",
|
||||||
"LabelWeekdaysToRun": "ימי השבוע להרצה",
|
"LabelWeekdaysToRun": "ימי השבוע להרצה",
|
||||||
"LabelYearReviewHide": "הסתר שנת סקירה",
|
"LabelYearReviewHide": "הסתר סקירת שנה",
|
||||||
"LabelYearReviewShow": "הצג שנת סקירה",
|
"LabelYearReviewShow": "הצג סקירת שנה",
|
||||||
"LabelYourAudiobookDuration": "משך הספר הקולי שלך",
|
"LabelYourAudiobookDuration": "משך הספר הקולי שלך",
|
||||||
"LabelYourBookmarks": "הסימניות שלך",
|
"LabelYourBookmarks": "הסימניות שלך",
|
||||||
"LabelYourPlaylists": "הפלייליסטים שלך",
|
"LabelYourPlaylists": "הפלייליסטים שלך",
|
||||||
@@ -628,8 +697,8 @@
|
|||||||
"MessageDownloadingEpisode": "מוריד פרק",
|
"MessageDownloadingEpisode": "מוריד פרק",
|
||||||
"MessageDragFilesIntoTrackOrder": "גרור קבצים לסדר ההשמעה נכון",
|
"MessageDragFilesIntoTrackOrder": "גרור קבצים לסדר ההשמעה נכון",
|
||||||
"MessageEmbedFinished": "ההטמעה הושלמה!",
|
"MessageEmbedFinished": "ההטמעה הושלמה!",
|
||||||
"MessageEpisodesQueuedForDownload": "{0} פרקים בתור להורדה",
|
"MessageEpisodesQueuedForDownload": "{0} פרק/ים בתור להורדה",
|
||||||
"MessageFeedURLWillBe": "כתובת URL של העדכון תהיה {0}",
|
"MessageFeedURLWillBe": "כתובת ה- URL של הערוץ תהיה {0}",
|
||||||
"MessageFetching": "מושך...",
|
"MessageFetching": "מושך...",
|
||||||
"MessageForceReScanDescription": "תבוצע סריקה מחדש כמו סריקה חדש מאפס, תגי ID3 של קבצי קול, קבצי OPF, וקבצי טקסט ייסרקו כחדשים.",
|
"MessageForceReScanDescription": "תבוצע סריקה מחדש כמו סריקה חדש מאפס, תגי ID3 של קבצי קול, קבצי OPF, וקבצי טקסט ייסרקו כחדשים.",
|
||||||
"MessageImportantNotice": "הודעה חשובה!",
|
"MessageImportantNotice": "הודעה חשובה!",
|
||||||
@@ -644,7 +713,7 @@
|
|||||||
"MessageMapChapterTitles": "מפה שמות פרקים לפרקי הספר השמורים שלך ללא שינוי תגי זמן",
|
"MessageMapChapterTitles": "מפה שמות פרקים לפרקי הספר השמורים שלך ללא שינוי תגי זמן",
|
||||||
"MessageMarkAllEpisodesFinished": "סמן את כל הפרקים כהסתיימו",
|
"MessageMarkAllEpisodesFinished": "סמן את כל הפרקים כהסתיימו",
|
||||||
"MessageMarkAllEpisodesNotFinished": "סמן את כל הפרקים כלא הסתיימו",
|
"MessageMarkAllEpisodesNotFinished": "סמן את כל הפרקים כלא הסתיימו",
|
||||||
"MessageMarkAsFinished": "סמן כהסתיים",
|
"MessageMarkAsFinished": "סמן כהושלם",
|
||||||
"MessageMarkAsNotFinished": "סמן כלא הסתיים",
|
"MessageMarkAsNotFinished": "סמן כלא הסתיים",
|
||||||
"MessageMatchBooksDescription": "ינסה להתאים ספרים בספריית הספרים שלך עם ספר מספק החיפוש הנבחר וימלא פרטים ריקים ותמונות כריכה. לא יחליף פרטים קיימים.",
|
"MessageMatchBooksDescription": "ינסה להתאים ספרים בספריית הספרים שלך עם ספר מספק החיפוש הנבחר וימלא פרטים ריקים ותמונות כריכה. לא יחליף פרטים קיימים.",
|
||||||
"MessageNoAudioTracks": "אין רצועות שמע",
|
"MessageNoAudioTracks": "אין רצועות שמע",
|
||||||
@@ -674,7 +743,7 @@
|
|||||||
"MessageNoSeries": "אין סדרות",
|
"MessageNoSeries": "אין סדרות",
|
||||||
"MessageNoTags": "אין תגיות",
|
"MessageNoTags": "אין תגיות",
|
||||||
"MessageNoTasksRunning": "אין משימות פעילות",
|
"MessageNoTasksRunning": "אין משימות פעילות",
|
||||||
"MessageNoUpdatesWereNecessary": "לא היה צורך בעדכונים",
|
"MessageNoUpdatesWereNecessary": "לא נדרש עדכון",
|
||||||
"MessageNoUserPlaylists": "אין לך רשימות השמעה",
|
"MessageNoUserPlaylists": "אין לך רשימות השמעה",
|
||||||
"MessageNotYetImplemented": "עדיין לא מיושם",
|
"MessageNotYetImplemented": "עדיין לא מיושם",
|
||||||
"MessageOr": "או",
|
"MessageOr": "או",
|
||||||
@@ -682,6 +751,7 @@
|
|||||||
"MessagePlayChapter": "הקשב לתחילת הפרק",
|
"MessagePlayChapter": "הקשב לתחילת הפרק",
|
||||||
"MessagePlaylistCreateFromCollection": "צור רשימת השמעה מאוסף",
|
"MessagePlaylistCreateFromCollection": "צור רשימת השמעה מאוסף",
|
||||||
"MessagePodcastHasNoRSSFeedForMatching": "לפודקאסט אין כתובת URL של ערוץ RSS להתאמה",
|
"MessagePodcastHasNoRSSFeedForMatching": "לפודקאסט אין כתובת URL של ערוץ RSS להתאמה",
|
||||||
|
"MessagePodcastSearchField": "הזן מונח חיפוש או כתובת URL של ערוץ RSS",
|
||||||
"MessageQuickMatchDescription": "ממלא פרטים ריקים וכריכות עם התוצאה הראשונה מ '{0}'. לא ימחק פרטים אלא אם הגדרת השרת 'העדף מטה-נתונים מותאמים' מופעלת.",
|
"MessageQuickMatchDescription": "ממלא פרטים ריקים וכריכות עם התוצאה הראשונה מ '{0}'. לא ימחק פרטים אלא אם הגדרת השרת 'העדף מטה-נתונים מותאמים' מופעלת.",
|
||||||
"MessageRemoveChapter": "הסר פרק",
|
"MessageRemoveChapter": "הסר פרק",
|
||||||
"MessageRemoveEpisodes": "הסר {0} פרקים",
|
"MessageRemoveEpisodes": "הסר {0} פרקים",
|
||||||
@@ -708,7 +778,7 @@
|
|||||||
"NoteChangeRootPassword": "המשתמש root הוא המשתמש היחיד שיכולה להיות לו סיסמה ריקה",
|
"NoteChangeRootPassword": "המשתמש root הוא המשתמש היחיד שיכולה להיות לו סיסמה ריקה",
|
||||||
"NoteChapterEditorTimes": "הערה: זמן ההתחלה של הפרק הראשון חייב להישאר 0:00 וזמן ההתחלה של הפרק האחרון לא יכול לחרוג מהזמן של ספר השמע.",
|
"NoteChapterEditorTimes": "הערה: זמן ההתחלה של הפרק הראשון חייב להישאר 0:00 וזמן ההתחלה של הפרק האחרון לא יכול לחרוג מהזמן של ספר השמע.",
|
||||||
"NoteFolderPicker": "הערה: תיקיות שכבר מופו לא יוצגו",
|
"NoteFolderPicker": "הערה: תיקיות שכבר מופו לא יוצגו",
|
||||||
"NoteRSSFeedPodcastAppsHttps": "אזהרה: רוב יישומי הפודקאסט דורשים שכתובת ה-URL ערוץ ה-RSS תשתמש ב-HTTPS",
|
"NoteRSSFeedPodcastAppsHttps": "אזהרה: רוב אפליקציות הפודקאסטים ידרשו שכתובת האתר של ערוץ ה-RSS תשתמש ב-HTTPS",
|
||||||
"NoteRSSFeedPodcastAppsPubDate": "אזהרה: פרק אחד או יותר לא מכילים תאריך פרסום. חלק מיישומי הפודקאסט דורשים זאת.",
|
"NoteRSSFeedPodcastAppsPubDate": "אזהרה: פרק אחד או יותר לא מכילים תאריך פרסום. חלק מיישומי הפודקאסט דורשים זאת.",
|
||||||
"NoteUploaderFoldersWithMediaFiles": "תיקיות עם קבצי מדיה יעובדו כפריטי ספריה נפרדים.",
|
"NoteUploaderFoldersWithMediaFiles": "תיקיות עם קבצי מדיה יעובדו כפריטי ספריה נפרדים.",
|
||||||
"NoteUploaderOnlyAudioFiles": "אם מועלים רק קבצי שמע, כל קובץ שמע יעובד כספר שמע נפרד.",
|
"NoteUploaderOnlyAudioFiles": "אם מועלים רק קבצי שמע, כל קובץ שמע יעובד כספר שמע נפרד.",
|
||||||
@@ -741,7 +811,7 @@
|
|||||||
"ToastCollectionUpdateSuccess": "האוסף עודכן בהצלחה",
|
"ToastCollectionUpdateSuccess": "האוסף עודכן בהצלחה",
|
||||||
"ToastItemCoverUpdateSuccess": "כריכת הפריט עודכנה בהצלחה",
|
"ToastItemCoverUpdateSuccess": "כריכת הפריט עודכנה בהצלחה",
|
||||||
"ToastItemDetailsUpdateSuccess": "פרטי הפריט עודכנו בהצלחה",
|
"ToastItemDetailsUpdateSuccess": "פרטי הפריט עודכנו בהצלחה",
|
||||||
"ToastItemMarkedAsFinishedFailed": "סימון כפריט כהושלם נכשל",
|
"ToastItemMarkedAsFinishedFailed": "סימון כפריט שהושלם נכשל",
|
||||||
"ToastItemMarkedAsFinishedSuccess": "הפריט סומן כהושלם בהצלחה",
|
"ToastItemMarkedAsFinishedSuccess": "הפריט סומן כהושלם בהצלחה",
|
||||||
"ToastItemMarkedAsNotFinishedFailed": "סימון כפריט שלא הושלם נכשל",
|
"ToastItemMarkedAsNotFinishedFailed": "סימון כפריט שלא הושלם נכשל",
|
||||||
"ToastItemMarkedAsNotFinishedSuccess": "הפריט סומן כלא הושלם בהצלחה",
|
"ToastItemMarkedAsNotFinishedSuccess": "הפריט סומן כלא הושלם בהצלחה",
|
||||||
|
|||||||
@@ -177,6 +177,7 @@
|
|||||||
"HeaderPlaylist": "Popis za izvođenje",
|
"HeaderPlaylist": "Popis za izvođenje",
|
||||||
"HeaderPlaylistItems": "Stavke popisa za izvođenje",
|
"HeaderPlaylistItems": "Stavke popisa za izvođenje",
|
||||||
"HeaderPodcastsToAdd": "Podcasti za dodavanje",
|
"HeaderPodcastsToAdd": "Podcasti za dodavanje",
|
||||||
|
"HeaderPresets": "Predlošci postavki",
|
||||||
"HeaderPreviewCover": "Pretpregled naslovnice",
|
"HeaderPreviewCover": "Pretpregled naslovnice",
|
||||||
"HeaderRSSFeedGeneral": "RSS pojedinosti",
|
"HeaderRSSFeedGeneral": "RSS pojedinosti",
|
||||||
"HeaderRSSFeedIsOpen": "RSS izvor je otvoren",
|
"HeaderRSSFeedIsOpen": "RSS izvor je otvoren",
|
||||||
@@ -530,6 +531,7 @@
|
|||||||
"LabelReleaseDate": "Datum izlaska",
|
"LabelReleaseDate": "Datum izlaska",
|
||||||
"LabelRemoveAllMetadataAbs": "Ukloni sve datoteke metadata.abs",
|
"LabelRemoveAllMetadataAbs": "Ukloni sve datoteke metadata.abs",
|
||||||
"LabelRemoveAllMetadataJson": "Ukloni sve datoteke metadata.json",
|
"LabelRemoveAllMetadataJson": "Ukloni sve datoteke metadata.json",
|
||||||
|
"LabelRemoveAudibleBranding": "Ukloni Audibleove najave i odjave iz poglavlja",
|
||||||
"LabelRemoveCover": "Ukloni naslovnicu",
|
"LabelRemoveCover": "Ukloni naslovnicu",
|
||||||
"LabelRemoveMetadataFile": "Ukloni datoteke s meta-podatcima iz mapa knjižničkih stavki",
|
"LabelRemoveMetadataFile": "Ukloni datoteke s meta-podatcima iz mapa knjižničkih stavki",
|
||||||
"LabelRemoveMetadataFileHelp": "Uklanjanje svih datoteka metadata.json i metadata.abs u vaših {0} mapa.",
|
"LabelRemoveMetadataFileHelp": "Uklanjanje svih datoteka metadata.json i metadata.abs u vaših {0} mapa.",
|
||||||
@@ -604,6 +606,7 @@
|
|||||||
"LabelSlug": "Slug",
|
"LabelSlug": "Slug",
|
||||||
"LabelSortAscending": "Uzlazno",
|
"LabelSortAscending": "Uzlazno",
|
||||||
"LabelSortDescending": "Silazno",
|
"LabelSortDescending": "Silazno",
|
||||||
|
"LabelSortPubDate": "Sortiranje po datumu objave",
|
||||||
"LabelStart": "Početak",
|
"LabelStart": "Početak",
|
||||||
"LabelStartTime": "Vrijeme početka",
|
"LabelStartTime": "Vrijeme početka",
|
||||||
"LabelStarted": "Započeto",
|
"LabelStarted": "Započeto",
|
||||||
@@ -704,6 +707,8 @@
|
|||||||
"LabelYourProgress": "Vaš napredak",
|
"LabelYourProgress": "Vaš napredak",
|
||||||
"MessageAddToPlayerQueue": "Dodaj u redoslijed izvođenja",
|
"MessageAddToPlayerQueue": "Dodaj u redoslijed izvođenja",
|
||||||
"MessageAppriseDescription": "Da biste se koristili ovom značajkom, treba vam instanca <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API-ja</a> ili API koji može rukovati istom vrstom zahtjeva.<br />The Adresa Apprise API-ja treba biti puna URL putanja za slanje obavijesti, npr. ako vam se API instanca poslužuje na adresi <code>http://192.168.1.1:8337</code> trebate upisati <code>http://192.168.1.1:8337/notify</code>.",
|
"MessageAppriseDescription": "Da biste se koristili ovom značajkom, treba vam instanca <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API-ja</a> ili API koji može rukovati istom vrstom zahtjeva.<br />The Adresa Apprise API-ja treba biti puna URL putanja za slanje obavijesti, npr. ako vam se API instanca poslužuje na adresi <code>http://192.168.1.1:8337</code> trebate upisati <code>http://192.168.1.1:8337/notify</code>.",
|
||||||
|
"MessageAsinCheck": "Upišite ASIN iz odgovarajuće Audibleove regije, ne s Amazonov.",
|
||||||
|
"MessageAuthenticationOIDCChangesRestart": "Ponovno pokrenite poslužitelj da biste primijenili OIDC promjene.",
|
||||||
"MessageBackupsDescription": "Sigurnosne kopije sadrže korisnike, korisnikov napredak medija, pojedinosti knjižničke građe, postavke poslužitelja i slike koje se spremaju u <code>/metadata/items</code> & <code>/metadata/authors</code>. Sigurnosne kopije ne sadrže niti jednu datoteku iz mapa knjižnice.",
|
"MessageBackupsDescription": "Sigurnosne kopije sadrže korisnike, korisnikov napredak medija, pojedinosti knjižničke građe, postavke poslužitelja i slike koje se spremaju u <code>/metadata/items</code> & <code>/metadata/authors</code>. Sigurnosne kopije ne sadrže niti jednu datoteku iz mapa knjižnice.",
|
||||||
"MessageBackupsLocationEditNote": "Napomena: Uređivanje lokacije za sigurnosne kopije ne premješta ili mijenja postojeće sigurnosne kopije",
|
"MessageBackupsLocationEditNote": "Napomena: Uređivanje lokacije za sigurnosne kopije ne premješta ili mijenja postojeće sigurnosne kopije",
|
||||||
"MessageBackupsLocationNoEditNote": "Napomena: Lokacija za sigurnosne kopije zadana je kroz varijablu okoline i ovdje se ne može izmijeniti.",
|
"MessageBackupsLocationNoEditNote": "Napomena: Lokacija za sigurnosne kopije zadana je kroz varijablu okoline i ovdje se ne može izmijeniti.",
|
||||||
@@ -722,6 +727,7 @@
|
|||||||
"MessageChapterErrorStartGteDuration": "Netočno vrijeme početka, mora biti manje od trajanja zvučne knjige",
|
"MessageChapterErrorStartGteDuration": "Netočno vrijeme početka, mora biti manje od trajanja zvučne knjige",
|
||||||
"MessageChapterErrorStartLtPrev": "Netočno vrijeme početka, mora biti veće ili jednako vremenu početka prethodnog poglavlja",
|
"MessageChapterErrorStartLtPrev": "Netočno vrijeme početka, mora biti veće ili jednako vremenu početka prethodnog poglavlja",
|
||||||
"MessageChapterStartIsAfter": "Početak poglavlja je nakon kraja zvučne knjige",
|
"MessageChapterStartIsAfter": "Početak poglavlja je nakon kraja zvučne knjige",
|
||||||
|
"MessageChaptersNotFound": "Poglavlja nisu pronađena",
|
||||||
"MessageCheckingCron": "Provjeravam cron...",
|
"MessageCheckingCron": "Provjeravam cron...",
|
||||||
"MessageConfirmCloseFeed": "Sigurno želite zatvoriti ovaj izvor?",
|
"MessageConfirmCloseFeed": "Sigurno želite zatvoriti ovaj izvor?",
|
||||||
"MessageConfirmDeleteBackup": "Sigurno želite izbrisati sigurnosnu kopiju za {0}?",
|
"MessageConfirmDeleteBackup": "Sigurno želite izbrisati sigurnosnu kopiju za {0}?",
|
||||||
@@ -778,6 +784,7 @@
|
|||||||
"MessageForceReScanDescription": "će ponovno skenirati sve datoteke kao nove datoteke. ID3 tagovi zvučnih datoteka, OPF datoteke i tekstualne datoteke skenirat će se kao da su nove.",
|
"MessageForceReScanDescription": "će ponovno skenirati sve datoteke kao nove datoteke. ID3 tagovi zvučnih datoteka, OPF datoteke i tekstualne datoteke skenirat će se kao da su nove.",
|
||||||
"MessageImportantNotice": "Važna obavijest!",
|
"MessageImportantNotice": "Važna obavijest!",
|
||||||
"MessageInsertChapterBelow": "Unesi poglavlje ispod",
|
"MessageInsertChapterBelow": "Unesi poglavlje ispod",
|
||||||
|
"MessageInvalidAsin": "Nevažeći ASIN",
|
||||||
"MessageItemsSelected": "{0} odabranih stavki",
|
"MessageItemsSelected": "{0} odabranih stavki",
|
||||||
"MessageItemsUpdated": "{0} stavki ažurirano",
|
"MessageItemsUpdated": "{0} stavki ažurirano",
|
||||||
"MessageJoinUsOn": "Pridruži nam se na",
|
"MessageJoinUsOn": "Pridruži nam se na",
|
||||||
@@ -849,6 +856,7 @@
|
|||||||
"MessageScheduleRunEveryWeekdayAtTime": "Pokreni svaki {0} u {1}",
|
"MessageScheduleRunEveryWeekdayAtTime": "Pokreni svaki {0} u {1}",
|
||||||
"MessageSearchResultsFor": "Rezultati pretrage za",
|
"MessageSearchResultsFor": "Rezultati pretrage za",
|
||||||
"MessageSelected": "{0} odabrano",
|
"MessageSelected": "{0} odabrano",
|
||||||
|
"MessageSeriesSequenceCannotContainSpaces": "Slijed serijala ne može sadržavati praznine",
|
||||||
"MessageServerCouldNotBeReached": "Nije moguće pristupiti poslužitelju",
|
"MessageServerCouldNotBeReached": "Nije moguće pristupiti poslužitelju",
|
||||||
"MessageSetChaptersFromTracksDescription": "Postavi poglavlja koristeći se zvučnom datotekom kao poglavljem i nazivom datoteke kao naslovom poglavlja",
|
"MessageSetChaptersFromTracksDescription": "Postavi poglavlja koristeći se zvučnom datotekom kao poglavljem i nazivom datoteke kao naslovom poglavlja",
|
||||||
"MessageShareExpirationWillBe": "Vrijeme isteka će biti <strong>{0}</strong>",
|
"MessageShareExpirationWillBe": "Vrijeme isteka će biti <strong>{0}</strong>",
|
||||||
@@ -910,6 +918,8 @@
|
|||||||
"NotificationOnBackupCompletedDescription": "Pokreće se po završetku sigurnosnog kopiranja",
|
"NotificationOnBackupCompletedDescription": "Pokreće se po završetku sigurnosnog kopiranja",
|
||||||
"NotificationOnBackupFailedDescription": "Pokreće se kada sigurnosno kopiranje ne uspije",
|
"NotificationOnBackupFailedDescription": "Pokreće se kada sigurnosno kopiranje ne uspije",
|
||||||
"NotificationOnEpisodeDownloadedDescription": "Pokreće se kada se nastavak podcasta automatski preuzme",
|
"NotificationOnEpisodeDownloadedDescription": "Pokreće se kada se nastavak podcasta automatski preuzme",
|
||||||
|
"NotificationOnRSSFeedDisabledDescription": "Pokreće se kada su automatska preuzimanja nastavaka onemogućena zbog previše neuspjelih pokušaja",
|
||||||
|
"NotificationOnRSSFeedFailedDescription": "Pokreće se u slučaju pogreške pri pokušaju automatskog preuzimanja nastavka s RSS izvora",
|
||||||
"NotificationOnTestDescription": "Događaj za testiranje sustava obavijesti",
|
"NotificationOnTestDescription": "Događaj za testiranje sustava obavijesti",
|
||||||
"PlaceholderNewCollection": "Ime nove zbirke",
|
"PlaceholderNewCollection": "Ime nove zbirke",
|
||||||
"PlaceholderNewFolderPath": "Nova putanja mape",
|
"PlaceholderNewFolderPath": "Nova putanja mape",
|
||||||
@@ -967,6 +977,8 @@
|
|||||||
"ToastCachePurgeFailed": "Čišćenje predmemorije nije uspjelo",
|
"ToastCachePurgeFailed": "Čišćenje predmemorije nije uspjelo",
|
||||||
"ToastCachePurgeSuccess": "Predmemorija uspješno očišćena",
|
"ToastCachePurgeSuccess": "Predmemorija uspješno očišćena",
|
||||||
"ToastChaptersHaveErrors": "Poglavlja imaju pogreške",
|
"ToastChaptersHaveErrors": "Poglavlja imaju pogreške",
|
||||||
|
"ToastChaptersInvalidShiftAmountLast": "Neispravna vrijednost pomaka. Početak zadnjeg poglavlja bio bi nakon duljine trajanja ove zvučne knjige.",
|
||||||
|
"ToastChaptersInvalidShiftAmountStart": "Neispravna vrijednost pomaka. Trajanje prvog poglavlja bilo bi nula ili negativno i drugo poglavlje bi ga prepisalo. Povećajte vrijeme početka drugog poglavlja.",
|
||||||
"ToastChaptersMustHaveTitles": "Poglavlja moraju imati naslove",
|
"ToastChaptersMustHaveTitles": "Poglavlja moraju imati naslove",
|
||||||
"ToastChaptersRemoved": "Poglavlja uklonjena",
|
"ToastChaptersRemoved": "Poglavlja uklonjena",
|
||||||
"ToastChaptersUpdated": "Poglavlja su ažurirana",
|
"ToastChaptersUpdated": "Poglavlja su ažurirana",
|
||||||
@@ -1086,6 +1098,8 @@
|
|||||||
"ToastUnknownError": "Nepoznata pogreška",
|
"ToastUnknownError": "Nepoznata pogreška",
|
||||||
"ToastUnlinkOpenIdFailed": "Uklanjanje OpenID veze korisnika nije uspjelo",
|
"ToastUnlinkOpenIdFailed": "Uklanjanje OpenID veze korisnika nije uspjelo",
|
||||||
"ToastUnlinkOpenIdSuccess": "Korisnik odspojen od OpenID-ja",
|
"ToastUnlinkOpenIdSuccess": "Korisnik odspojen od OpenID-ja",
|
||||||
|
"ToastUploaderFilepathExistsError": "Putanja \"{0}\" već postoji na poslužitelju",
|
||||||
|
"ToastUploaderItemExistsInSubdirectoryError": "Stavka \"{0}\" koristi se podmapom u putanje za učitavanje.",
|
||||||
"ToastUserDeleteFailed": "Brisanje korisnika nije uspjelo",
|
"ToastUserDeleteFailed": "Brisanje korisnika nije uspjelo",
|
||||||
"ToastUserDeleteSuccess": "Korisnik izbrisan",
|
"ToastUserDeleteSuccess": "Korisnik izbrisan",
|
||||||
"ToastUserPasswordChangeSuccess": "Zaporka je uspješno promijenjena",
|
"ToastUserPasswordChangeSuccess": "Zaporka je uspješno promijenjena",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user