mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-09-01 08:15:15 +02:00
Compare commits
460 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c7c21cc137 | ||
|
7e4c7a7e3b | ||
|
40babc9650 | ||
|
7a94f014ea | ||
|
32adb1bafd | ||
|
f9a6239049 | ||
|
8dee1ec942 | ||
|
58e43cc6a7 | ||
|
b8999fbc37 | ||
|
0dda4b6b27 | ||
|
817f2f6915 | ||
|
77fc6bba1a | ||
|
c66d652a53 | ||
|
86bddba5c3 | ||
|
7779fd2972 | ||
|
05a4577792 | ||
|
56dc042282 | ||
|
95973243a6 | ||
|
18ad23d016 | ||
|
e258f122f1 | ||
|
18200a8f01 | ||
|
9c47f404c9 | ||
|
2f6de71a3a | ||
|
deb121c523 | ||
|
320e4dfb47 | ||
|
6194c48549 | ||
|
6aa9ecaaba | ||
|
b3d020b89f | ||
|
e196a6e5ca | ||
|
73cf22b499 | ||
|
ac7464ce7e | ||
|
84e742f2a5 | ||
|
a1e882cbf1 | ||
|
09121acbd5 | ||
|
5b9df84ba3 | ||
|
266db491aa | ||
|
c7a317a87b | ||
|
b027f3bda1 | ||
|
cea991b82f | ||
|
7e2b51e6d2 | ||
|
8f310b6bf0 | ||
|
b2a5fb46f1 | ||
|
6d7639853b | ||
|
3a16acbba4 | ||
|
027e1efaca | ||
|
d1fabba86b | ||
|
b290a4ada3 | ||
|
bb477c617e | ||
|
9238c38842 | ||
|
d268516fcb | ||
|
d353cff1ae | ||
|
604f17f60b | ||
|
3911a7273b | ||
|
138bb563b8 | ||
|
3801ef062a | ||
|
e4b9ac5446 | ||
|
9987d219f8 | ||
|
dc7045c562 | ||
|
2cc6e56bd1 | ||
|
a89a24e48e | ||
|
a968aca304 | ||
|
8d1f460640 | ||
|
553ffd1934 | ||
|
fd4932cdbb | ||
|
dcaca43817 | ||
|
0eed4e82f9 | ||
|
2ed2328401 | ||
|
8b260c8bc6 | ||
|
7dcb9b98a0 | ||
|
311ac7104e | ||
|
2c45b28d48 | ||
|
b53613f82c | ||
|
751371abb8 | ||
|
6365c02875 | ||
|
fb3834156b | ||
|
c03f3f722d | ||
|
a06f48ca29 | ||
|
9d79552dda | ||
|
ed98614b6f | ||
|
09dd2cc79c | ||
|
e87237048a | ||
|
d71968fd80 | ||
|
f83c605ae1 | ||
|
4325f470dd | ||
|
800ecf8e82 | ||
|
5cb143d50b | ||
|
798c73c66c | ||
|
0fa7c46274 | ||
|
c2d420ec70 | ||
|
152daf7bf3 | ||
|
8d99249e50 | ||
|
c6724ba353 | ||
|
a519d44666 | ||
|
7e8bf977cc | ||
|
4018be6330 | ||
|
99a3867ce9 | ||
|
2116f60133 | ||
|
794f0ef42a | ||
|
3e423839a1 | ||
|
2773c8c4a9 | ||
|
e510174f12 | ||
|
08c9e8d47d | ||
|
1908ec3df5 | ||
|
df3878d4ca | ||
|
1097de6f1f | ||
|
e408070b19 | ||
|
af67c2e86f | ||
|
6a52d2a968 | ||
|
3337b3af18 | ||
|
835d2c7f36 | ||
|
03f91099e0 | ||
|
c04afd0787 | ||
|
b03bd79f5d | ||
|
5ef632a7eb | ||
|
79b4042e8e | ||
|
8f718ef91c | ||
|
4053b20623 | ||
|
c4d654635f | ||
|
ef5d0ffa48 | ||
|
6a826cdb36 | ||
|
1d837f5f21 | ||
|
80873b379c | ||
|
82a8f8f126 | ||
|
4725a466da | ||
|
031edc870c | ||
|
625e2445b5 | ||
|
1640af2f1c | ||
|
c76f76cc27 | ||
|
74af212293 | ||
|
e04efb9c6a | ||
|
ee17e7a555 | ||
|
694a852c07 | ||
|
18068bb261 | ||
|
71257f6c6c | ||
|
4d70929d2e | ||
|
578e9559e4 | ||
|
894ea0b80a | ||
|
e54571f011 | ||
|
77d7a50b99 | ||
|
32da0f1224 | ||
|
2054accdc9 | ||
|
7d8b857c77 | ||
|
0107cb4782 | ||
|
f273eee807 | ||
|
4af21b079a | ||
|
c9eaf2db2d | ||
|
cae1560344 | ||
|
a5fb0d9cdb | ||
|
53c80d9798 | ||
|
832165716b | ||
|
d9f2d8bf1d | ||
|
a7a3a56509 | ||
|
4082fadf90 | ||
|
93160b83bf | ||
|
472240f994 | ||
|
c3f0fb8e5e | ||
|
b156ebeb9f | ||
|
e4c775c847 | ||
|
45e8e72759 | ||
|
0ae7340889 | ||
|
8c38987d92 | ||
|
878f0787ba | ||
|
880d85eaef | ||
|
f7aaebc1de | ||
|
d96ebbe82d | ||
|
70d67156f0 | ||
|
f293b317be | ||
|
1f23794f88 | ||
|
e6bfd118f6 | ||
|
1166400ab1 | ||
|
55f0ac871b | ||
|
3584f6e24f | ||
|
23bf2594c8 | ||
|
8fb460ce05 | ||
|
8c4bbfd6a2 | ||
|
742961e0b8 | ||
|
5b6807892f | ||
|
b911a25c57 | ||
|
53110674e4 | ||
|
f963cd4753 | ||
|
0dccc3bcae | ||
|
5b4fd5b254 | ||
|
bdb9d3caeb | ||
|
9aca824b59 | ||
|
8e891805eb | ||
|
2760517445 | ||
|
889ee33320 | ||
|
4f65801713 | ||
|
3e75acd4ef | ||
|
3e8fe2ef60 | ||
|
0bc441de20 | ||
|
a8c2f0d4c8 | ||
|
b59da8bd0c | ||
|
77cb4f75c6 | ||
|
9cf1711fae | ||
|
f472116dc3 | ||
|
c7eb9d7799 | ||
|
c66380eaeb | ||
|
1bebb22705 | ||
|
4e96649fe3 | ||
|
a21cec806e | ||
|
8a3b8d2249 | ||
|
581277914c | ||
|
e678fe6e2f | ||
|
3845940245 | ||
|
6c63e2131c | ||
|
e25e2b238f | ||
|
99110f587a | ||
|
b553e959e2 | ||
|
f7b94a4b6d | ||
|
e9a705587a | ||
|
264ae928a9 | ||
|
f5248a9f00 | ||
|
3473ff594a | ||
|
20bb6e13b5 | ||
|
a05d32b1d7 | ||
|
c6b3521cb6 | ||
|
2444504c6a | ||
|
d38532c07a | ||
|
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 | ||
|
bf6d81b333 | ||
|
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 | ||
|
9c44fc0d01 | ||
|
d21fe49ce2 | ||
|
a992400d6a | ||
|
108b2a60f5 | ||
|
af684e6a69 | ||
|
5336d0525e | ||
|
bb4eec9355 | ||
|
28404f37b8 | ||
|
7b92c15a46 | ||
|
c150ed4e98 | ||
|
cb7632b216 | ||
|
b8849677de | ||
|
9bf8d7de11 | ||
|
6634ce8fd4 | ||
|
9d4303ef7b | ||
|
1f7be58124 | ||
|
6b8b27b04f | ||
|
ba4061e5a4 | ||
|
5017e7ce9e | ||
|
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 | ||
|
9da0be6d36 | ||
|
0c5d05d319 | ||
|
c41bdb951c | ||
|
4a3eb7727b | ||
|
81640464ba | ||
|
54815ea9c7 | ||
|
679ffed0ea | ||
|
09397cf3de | ||
|
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 | ||
|
de25763a74 | ||
|
a894ceb9cf | ||
|
387e58a714 | ||
|
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 | ||
|
dc3c978f8d | ||
|
13fac2d5bc |
164 changed files with 8269 additions and 2058 deletions
19
Dockerfile
19
Dockerfile
|
@ -1,5 +1,9 @@
|
|||
ARG NUSQLITE3_DIR="/usr/local/lib/nusqlite3"
|
||||
ARG NUSQLITE3_PATH="${NUSQLITE3_DIR}/libnusqlite3.so"
|
||||
|
||||
### STAGE 0: Build client ###
|
||||
FROM node:20-alpine AS build-client
|
||||
|
||||
WORKDIR /client
|
||||
COPY /client /client
|
||||
RUN npm ci && npm cache clean --force
|
||||
|
@ -8,6 +12,9 @@ RUN npm run generate
|
|||
### STAGE 1: Build server ###
|
||||
FROM node:20-alpine AS build-server
|
||||
|
||||
ARG NUSQLITE3_DIR
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN apk add --no-cache --update \
|
||||
|
@ -21,11 +28,6 @@ WORKDIR /server
|
|||
COPY index.js package* /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 \
|
||||
"linux/amd64") \
|
||||
curl -L -o /tmp/library.zip "https://github.com/mikiher/nunicode-sqlite/releases/download/v1.2/libnusqlite3-linux-musl-x64.zip" ;; \
|
||||
|
@ -41,6 +43,9 @@ RUN npm ci --only=production
|
|||
### 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 \
|
||||
|
@ -52,13 +57,17 @@ 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
|
||||
|
||||
ENV PORT=80
|
||||
ENV NODE_ENV=production
|
||||
ENV CONFIG_PATH="/config"
|
||||
ENV METADATA_PATH="/metadata"
|
||||
ENV SOURCE="docker"
|
||||
ENV NUSQLITE3_DIR=${NUSQLITE3_DIR}
|
||||
ENV NUSQLITE3_PATH=${NUSQLITE3_PATH}
|
||||
|
||||
ENTRYPOINT ["tini", "--"]
|
||||
CMD ["node", "index.js"]
|
||||
|
|
|
@ -217,6 +217,16 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
if (this.results.episodes?.length) {
|
||||
shelves.push({
|
||||
id: 'episodes',
|
||||
label: 'Episodes',
|
||||
labelStringKey: 'LabelEpisodes',
|
||||
type: 'episode',
|
||||
entities: this.results.episodes.map((res) => res.libraryItem)
|
||||
})
|
||||
}
|
||||
|
||||
if (this.results.series?.length) {
|
||||
shelves.push({
|
||||
id: 'series',
|
||||
|
|
|
@ -3,24 +3,18 @@
|
|||
<div class="flex md:hidden h-10 items-center">
|
||||
<nuxt-link :to="`/library/${currentLibraryId}`" class="grow h-full flex justify-center items-center" :class="isHomePage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p v-if="isHomePage || isPodcastLibrary" class="text-sm">{{ $strings.ButtonHome }}</p>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
||||
</svg>
|
||||
<span v-else class="material-symbols text-lg">home</span>
|
||||
</nuxt-link>
|
||||
<nuxt-link :to="`/library/${currentLibraryId}/bookshelf`" class="grow h-full flex justify-center items-center" :class="isLibraryPage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p v-if="isLibraryPage || isPodcastLibrary" class="text-sm">{{ $strings.ButtonLibrary }}</p>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
||||
</svg>
|
||||
<span v-else class="material-symbols text-lg">import_contacts</span>
|
||||
</nuxt-link>
|
||||
<nuxt-link v-if="isPodcastLibrary" :to="`/library/${currentLibraryId}/podcast/latest`" class="grow h-full flex justify-center items-center" :class="isPodcastLatestPage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p class="text-sm">{{ $strings.ButtonLatest }}</p>
|
||||
</nuxt-link>
|
||||
<nuxt-link v-if="isBookLibrary" :to="`/library/${currentLibraryId}/bookshelf/series`" class="grow h-full flex justify-center items-center" :class="isSeriesPage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p v-if="isSeriesPage" class="text-sm">{{ $strings.ButtonSeries }}</p>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" />
|
||||
</svg>
|
||||
<span v-else class="material-symbols text-lg">view_column</span>
|
||||
</nuxt-link>
|
||||
<nuxt-link v-if="showPlaylists" :to="`/library/${currentLibraryId}/bookshelf/playlists`" class="grow h-full flex justify-center items-center" :class="isPlaylistsPage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p v-if="isPlaylistsPage || isPodcastLibrary" class="text-sm">{{ $strings.ButtonPlaylists }}</p>
|
||||
|
@ -32,12 +26,7 @@
|
|||
</nuxt-link>
|
||||
<nuxt-link v-if="isBookLibrary" :to="`/library/${currentLibraryId}/bookshelf/authors`" class="grow h-full flex justify-center items-center" :class="isAuthorsPage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p v-if="isAuthorsPage" class="text-sm">{{ $strings.ButtonAuthors }}</p>
|
||||
<svg v-else class="w-5 h-5" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z"
|
||||
/>
|
||||
</svg>
|
||||
<span v-else class="material-symbols text-lg">groups</span>
|
||||
</nuxt-link>
|
||||
<nuxt-link v-if="isPodcastLibrary && userIsAdminOrUp" :to="`/library/${currentLibraryId}/podcast/search`" class="grow h-full flex justify-center items-center" :class="isPodcastSearchPage ? 'bg-primary/80' : 'bg-primary/40'">
|
||||
<p class="text-sm">{{ $strings.ButtonAdd }}</p>
|
||||
|
|
|
@ -70,6 +70,11 @@ export default {
|
|||
title: this.$strings.HeaderUsers,
|
||||
path: '/config/users'
|
||||
},
|
||||
{
|
||||
id: 'config-api-keys',
|
||||
title: this.$strings.HeaderApiKeys,
|
||||
path: '/config/api-keys'
|
||||
},
|
||||
{
|
||||
id: 'config-sessions',
|
||||
title: this.$strings.HeaderListeningSessions,
|
||||
|
|
|
@ -778,10 +778,6 @@ export default {
|
|||
windowResize() {
|
||||
this.executeRebuild()
|
||||
},
|
||||
socketInit() {
|
||||
// Server settings are set on socket init
|
||||
this.executeRebuild()
|
||||
},
|
||||
initListeners() {
|
||||
window.addEventListener('resize', this.windowResize)
|
||||
|
||||
|
@ -794,7 +790,6 @@ export default {
|
|||
})
|
||||
|
||||
this.$eventBus.$on('bookshelf_clear_selection', this.clearSelectedEntities)
|
||||
this.$eventBus.$on('socket_init', this.socketInit)
|
||||
this.$eventBus.$on('user-settings', this.settingsUpdated)
|
||||
|
||||
if (this.$root.socket) {
|
||||
|
@ -826,7 +821,6 @@ export default {
|
|||
}
|
||||
|
||||
this.$eventBus.$off('bookshelf_clear_selection', this.clearSelectedEntities)
|
||||
this.$eventBus.$off('socket_init', this.socketInit)
|
||||
this.$eventBus.$off('user-settings', this.settingsUpdated)
|
||||
|
||||
if (this.$root.socket) {
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
<div id="siderail-buttons-container" role="navigation" aria-label="Library Navigation" :class="{ 'player-open': streamLibraryItem }" class="w-full overflow-y-auto overflow-x-hidden">
|
||||
<nuxt-link :to="`/library/${currentLibraryId}`" class="w-full h-20 flex flex-col items-center justify-center text-white border-b border-primary/70 hover:bg-primary cursor-pointer relative" :class="homePage ? 'bg-primary/80' : 'bg-bg/60'">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
||||
</svg>
|
||||
<span class="material-symbols text-2xl">home</span>
|
||||
|
||||
<p class="pt-1.5 text-center leading-4" style="font-size: 0.9rem">{{ $strings.ButtonHome }}</p>
|
||||
|
||||
|
@ -23,9 +21,7 @@
|
|||
</nuxt-link>
|
||||
|
||||
<nuxt-link :to="`/library/${currentLibraryId}/bookshelf`" class="w-full h-20 flex flex-col items-center justify-center text-white border-b border-primary/70 hover:bg-primary cursor-pointer relative" :class="showLibrary ? 'bg-primary/80' : 'bg-bg/60'">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
||||
</svg>
|
||||
<span class="material-symbols text-2xl">import_contacts</span>
|
||||
|
||||
<p class="pt-1.5 text-center leading-4" style="font-size: 0.9rem">{{ $strings.ButtonLibrary }}</p>
|
||||
|
||||
|
@ -33,9 +29,7 @@
|
|||
</nuxt-link>
|
||||
|
||||
<nuxt-link v-if="isBookLibrary" :to="`/library/${currentLibraryId}/bookshelf/series`" class="w-full h-20 flex flex-col items-center justify-center text-white/80 border-b border-primary/70 hover:bg-primary cursor-pointer relative" :class="isSeriesPage ? 'bg-primary/80' : 'bg-bg/60'">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" />
|
||||
</svg>
|
||||
<span class="material-symbols text-2xl">view_column</span>
|
||||
|
||||
<p class="pt-1.5 text-center leading-4" style="font-size: 0.9rem">{{ $strings.ButtonSeries }}</p>
|
||||
|
||||
|
@ -59,12 +53,7 @@
|
|||
</nuxt-link>
|
||||
|
||||
<nuxt-link v-if="isBookLibrary" :to="`/library/${currentLibraryId}/bookshelf/authors`" class="w-full h-20 flex flex-col items-center justify-center text-white/80 border-b border-primary/70 hover:bg-primary cursor-pointer relative" :class="isAuthorsPage ? 'bg-primary/80' : 'bg-bg/60'">
|
||||
<svg class="w-6 h-6" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="material-symbols text-2xl">groups</span>
|
||||
|
||||
<p class="pt-1 text-center leading-4" style="font-size: 0.9rem">{{ $strings.ButtonAuthors }}</p>
|
||||
|
||||
|
@ -116,7 +105,7 @@
|
|||
</div>
|
||||
|
||||
<div class="w-full h-12 px-1 py-2 border-t border-black/20 bg-bg absolute left-0" :style="{ bottom: streamLibraryItem ? '224px' : '65px' }">
|
||||
<p class="underline font-mono text-xs text-center text-gray-300 leading-3 mb-1" @click="clickChangelog">v{{ $config.version }}</p>
|
||||
<p class="underline font-mono text-xs text-center text-gray-300 leading-3 mb-1 cursor-pointer" @click="clickChangelog">v{{ $config.version }}</p>
|
||||
<a v-if="hasUpdate" :href="githubTagUrl" target="_blank" class="text-warning text-xxs text-center block leading-3">Update</a>
|
||||
<p v-else class="text-xxs text-gray-400 leading-3 text-center italic">{{ Source }}</p>
|
||||
</div>
|
||||
|
|
|
@ -71,9 +71,6 @@ export default {
|
|||
coverHeight() {
|
||||
return this.cardHeight
|
||||
},
|
||||
userToken() {
|
||||
return this.store.getters['user/getToken']
|
||||
},
|
||||
_author() {
|
||||
return this.author || {}
|
||||
},
|
||||
|
|
|
@ -13,9 +13,17 @@
|
|||
<div class="grow" />
|
||||
<p class="text-sm md:text-base">{{ book.publishedYear }}</p>
|
||||
</div>
|
||||
<p v-if="book.author" class="text-gray-300 text-xs md:text-sm">{{ $getString('LabelByAuthor', [book.author]) }}</p>
|
||||
<p v-if="book.narrator" class="text-gray-400 text-xs">{{ $strings.LabelNarrators }}: {{ book.narrator }}</p>
|
||||
<p v-if="book.duration" class="text-gray-400 text-xs">{{ $strings.LabelDuration }}: {{ $elapsedPrettyExtended(bookDuration, false) }} {{ bookDurationComparison }}</p>
|
||||
|
||||
<div class="flex items-center">
|
||||
<div>
|
||||
<p v-if="book.author" class="text-gray-300 text-xs md:text-sm">{{ $getString('LabelByAuthor', [book.author]) }}</p>
|
||||
<p v-if="book.narrator" class="text-gray-400 text-xs">{{ $strings.LabelNarrators }}: {{ book.narrator }}</p>
|
||||
<p v-if="book.duration" class="text-gray-400 text-xs">{{ $strings.LabelDuration }}: {{ $elapsedPrettyExtended(bookDuration, false) }} {{ bookDurationComparison }}</p>
|
||||
</div>
|
||||
<div class="grow" />
|
||||
<div v-if="book.matchConfidence" class="rounded-full px-2 py-1 text-xs whitespace-nowrap text-white" :class="book.matchConfidence > 0.95 ? 'bg-success/80' : 'bg-info/80'">{{ $strings.LabelMatchConfidence }}: {{ (book.matchConfidence * 100).toFixed(0) }}%</div>
|
||||
</div>
|
||||
|
||||
<div v-if="book.series?.length" class="flex py-1 -mx-1">
|
||||
<div v-for="(series, index) in book.series" :key="index" class="bg-white/10 rounded-full px-1 py-0.5 mx-1">
|
||||
<p class="leading-3 text-xs text-gray-400">
|
||||
|
|
|
@ -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>
|
|
@ -101,7 +101,8 @@
|
|||
<!-- Podcast Episode # -->
|
||||
<div cy-id="podcastEpisodeNumber" v-if="recentEpisodeNumber !== null && !isHovering && !isSelectionMode && !processing" class="absolute rounded-lg bg-black/90 box-shadow-md z-10" :style="{ top: 0.375 + 'em', right: 0.375 + 'em', padding: `${0.1}em ${0.25}em` }">
|
||||
<p :style="{ fontSize: 0.8 + 'em' }">
|
||||
Episode<span v-if="recentEpisodeNumber"> #{{ recentEpisodeNumber }}</span>
|
||||
Episode
|
||||
<span v-if="recentEpisodeNumber">#{{ recentEpisodeNumber }}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -198,7 +199,10 @@ export default {
|
|||
return this.store.getters['user/getSizeMultiplier']
|
||||
},
|
||||
dateFormat() {
|
||||
return this.store.state.serverSettings.dateFormat
|
||||
return this.store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.store.getters['getServerSetting']('timeFormat')
|
||||
},
|
||||
_libraryItem() {
|
||||
return this.libraryItem || {}
|
||||
|
@ -345,6 +349,18 @@ export default {
|
|||
if (this.mediaMetadata.publishedYear) return this.$getString('LabelPublishedDate', [this.mediaMetadata.publishedYear])
|
||||
return '\u00A0'
|
||||
}
|
||||
if (this.orderBy === 'progress') {
|
||||
if (!this.userProgressLastUpdated) return '\u00A0'
|
||||
return this.$getString('LabelLastProgressDate', [this.$formatDatetime(this.userProgressLastUpdated, this.dateFormat, this.timeFormat)])
|
||||
}
|
||||
if (this.orderBy === 'progress.createdAt') {
|
||||
if (!this.userProgressStartedDate) return '\u00A0'
|
||||
return this.$getString('LabelStartedDate', [this.$formatDatetime(this.userProgressStartedDate, this.dateFormat, this.timeFormat)])
|
||||
}
|
||||
if (this.orderBy === 'progress.finishedAt') {
|
||||
if (!this.userProgressFinishedDate) return '\u00A0'
|
||||
return this.$getString('LabelFinishedDate', [this.$formatDatetime(this.userProgressFinishedDate, this.dateFormat, this.timeFormat)])
|
||||
}
|
||||
return null
|
||||
},
|
||||
episodeProgress() {
|
||||
|
@ -377,6 +393,18 @@ export default {
|
|||
let progressPercent = this.itemIsFinished ? 1 : this.booksInSeries ? this.seriesProgressPercent : this.useEBookProgress ? this.userProgress?.ebookProgress || 0 : this.userProgress?.progress || 0
|
||||
return Math.max(Math.min(1, progressPercent), 0)
|
||||
},
|
||||
userProgressLastUpdated() {
|
||||
if (!this.userProgress) return null
|
||||
return this.userProgress.lastUpdate
|
||||
},
|
||||
userProgressStartedDate() {
|
||||
if (!this.userProgress) return null
|
||||
return this.userProgress.startedAt
|
||||
},
|
||||
userProgressFinishedDate() {
|
||||
if (!this.userProgress) return null
|
||||
return this.userProgress.finishedAt
|
||||
},
|
||||
itemIsFinished() {
|
||||
if (this.booksInSeries) return this.seriesIsFinished
|
||||
return this.userProgress ? !!this.userProgress.isFinished : false
|
||||
|
|
|
@ -71,7 +71,7 @@ export default {
|
|||
return this.height * this.sizeMultiplier
|
||||
},
|
||||
dateFormat() {
|
||||
return this.store.state.serverSettings.dateFormat
|
||||
return this.store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
labelFontSize() {
|
||||
if (this.width < 160) return 0.75
|
||||
|
|
|
@ -39,6 +39,15 @@
|
|||
</li>
|
||||
</template>
|
||||
|
||||
<p v-if="episodeResults.length" class="uppercase text-xs text-gray-400 my-1 px-1 font-semibold">{{ $strings.LabelEpisodes }}</p>
|
||||
<template v-for="item in episodeResults">
|
||||
<li :key="item.libraryItem.recentEpisode.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||
<nuxt-link :to="`/item/${item.libraryItem.id}`">
|
||||
<cards-episode-search-card :episode="item.libraryItem.recentEpisode" :library-item="item.libraryItem" />
|
||||
</nuxt-link>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<p v-if="authorResults.length" class="uppercase text-xs text-gray-400 mb-1 mt-3 px-1 font-semibold">{{ $strings.LabelAuthors }}</p>
|
||||
<template v-for="item in authorResults">
|
||||
<li :key="item.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||
|
@ -100,6 +109,7 @@ export default {
|
|||
isFetching: false,
|
||||
search: null,
|
||||
podcastResults: [],
|
||||
episodeResults: [],
|
||||
bookResults: [],
|
||||
authorResults: [],
|
||||
seriesResults: [],
|
||||
|
@ -115,7 +125,7 @@ export default {
|
|||
return this.$store.state.libraries.currentLibraryId
|
||||
},
|
||||
totalResults() {
|
||||
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length
|
||||
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length + this.episodeResults.length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -132,6 +142,7 @@ export default {
|
|||
this.search = null
|
||||
this.lastSearch = null
|
||||
this.podcastResults = []
|
||||
this.episodeResults = []
|
||||
this.bookResults = []
|
||||
this.authorResults = []
|
||||
this.seriesResults = []
|
||||
|
@ -175,6 +186,7 @@ export default {
|
|||
if (!this.isFetching) return
|
||||
|
||||
this.podcastResults = searchResults.podcast || []
|
||||
this.episodeResults = searchResults.episodes || []
|
||||
this.bookResults = searchResults.book || []
|
||||
this.authorResults = searchResults.authors || []
|
||||
this.seriesResults = searchResults.series || []
|
||||
|
|
|
@ -94,6 +94,9 @@ export default {
|
|||
userIsAdminOrUp() {
|
||||
return this.$store.getters['user/getIsAdminOrUp']
|
||||
},
|
||||
userCanAccessExplicitContent() {
|
||||
return this.$store.getters['user/getUserCanAccessExplicitContent']
|
||||
},
|
||||
libraryMediaType() {
|
||||
return this.$store.getters['libraries/getCurrentLibraryMediaType']
|
||||
},
|
||||
|
@ -239,6 +242,15 @@ export default {
|
|||
sublist: false
|
||||
}
|
||||
]
|
||||
|
||||
if (this.userCanAccessExplicitContent) {
|
||||
items.push({
|
||||
text: this.$strings.LabelExplicit,
|
||||
value: 'explicit',
|
||||
sublist: false
|
||||
})
|
||||
}
|
||||
|
||||
if (this.userIsAdminOrUp) {
|
||||
items.push({
|
||||
text: this.$strings.LabelShareOpen,
|
||||
|
@ -249,7 +261,7 @@ export default {
|
|||
return items
|
||||
},
|
||||
podcastItems() {
|
||||
return [
|
||||
const items = [
|
||||
{
|
||||
text: this.$strings.LabelAll,
|
||||
value: 'all'
|
||||
|
@ -276,8 +288,23 @@ export default {
|
|||
text: this.$strings.ButtonIssues,
|
||||
value: 'issues',
|
||||
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() {
|
||||
if (this.isSeries) return this.seriesItems
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</span>
|
||||
</button>
|
||||
|
||||
<ul v-show="showMenu" class="absolute z-10 mt-1 w-full bg-bg border border-black-200 shadow-lg max-h-96 rounded-md py-1 ring-1 ring-black/5 overflow-auto focus:outline-hidden text-sm" role="menu">
|
||||
<ul v-show="showMenu" class="librarySortMenu absolute z-10 mt-1 w-full bg-bg border border-black-200 shadow-lg max-h-96 rounded-md py-1 ring-1 ring-black/5 overflow-auto focus:outline-hidden text-sm" role="menu">
|
||||
<template v-for="item in selectItems">
|
||||
<li :key="item.value" class="select-none relative py-2 pr-9 cursor-pointer hover:bg-white/5" :class="item.value === selected ? 'bg-white/5 text-yellow-400' : 'text-gray-200 hover:text-white'" role="menuitem" @click="clickedOption(item.value)">
|
||||
<div class="flex items-center">
|
||||
|
@ -130,6 +130,18 @@ export default {
|
|||
text: this.$strings.LabelFileModified,
|
||||
value: 'mtimeMs'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelLibrarySortByProgress,
|
||||
value: 'progress'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelLibrarySortByProgressStarted,
|
||||
value: 'progress.createdAt'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelLibrarySortByProgressFinished,
|
||||
value: 'progress.finishedAt'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelRandomly,
|
||||
value: 'random'
|
||||
|
@ -191,3 +203,9 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.librarySortMenu {
|
||||
max-height: calc(100vh - 125px);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -39,9 +39,6 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
_author() {
|
||||
return this.author || {}
|
||||
},
|
||||
|
|
|
@ -309,9 +309,9 @@ export default {
|
|||
} else {
|
||||
console.log('Account updated', data.user)
|
||||
|
||||
if (data.user.id === this.user.id && data.user.token !== this.user.token) {
|
||||
console.log('Current user token was updated')
|
||||
this.$store.commit('user/setUserToken', data.user.token)
|
||||
if (data.user.id === this.user.id && data.user.accessToken !== this.user.accessToken) {
|
||||
console.log('Current user access token was updated')
|
||||
this.$store.commit('user/setAccessToken', data.user.accessToken)
|
||||
}
|
||||
|
||||
this.$toast.success(this.$strings.ToastAccountUpdateSuccess)
|
||||
|
@ -351,9 +351,6 @@ export default {
|
|||
this.$toast.error(errMsg || 'Failed to create account')
|
||||
})
|
||||
},
|
||||
toggleActive() {
|
||||
this.newUser.isActive = !this.newUser.isActive
|
||||
},
|
||||
userTypeUpdated(type) {
|
||||
this.newUser.permissions = {
|
||||
download: type !== 'guest',
|
||||
|
|
60
client/components/modals/ApiKeyCreatedModal.vue
Normal file
60
client/components/modals/ApiKeyCreatedModal.vue
Normal file
|
@ -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>
|
198
client/components/modals/ApiKeyModal.vue
Normal file
198
client/components/modals/ApiKeyModal.vue
Normal file
|
@ -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)
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<ui-text-input-with-label ref="sequenceInput" v-model="selectedSeries.sequence" :label="$strings.LabelSequence" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="error" class="text-error text-sm mt-2 p-1">{{ error }}</div>
|
||||
<div class="flex justify-end mt-2 p-1">
|
||||
<ui-btn type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
|
||||
</div>
|
||||
|
@ -34,12 +35,17 @@ export default {
|
|||
existingSeriesNames: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
originalSeriesSequence: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
el: null,
|
||||
content: null
|
||||
content: null,
|
||||
error: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -85,10 +91,17 @@ export default {
|
|||
}
|
||||
},
|
||||
submitSeriesForm() {
|
||||
this.error = null
|
||||
|
||||
if (this.$refs.newSeriesSelect) {
|
||||
this.$refs.newSeriesSelect.blur()
|
||||
}
|
||||
|
||||
if (this.selectedSeries.sequence !== this.originalSeriesSequence && this.selectedSeries.sequence.includes(' ')) {
|
||||
this.error = this.$strings.MessageSeriesSequenceCannotContainSpaces
|
||||
return
|
||||
}
|
||||
|
||||
this.$emit('submit')
|
||||
},
|
||||
clickClose() {
|
||||
|
@ -100,6 +113,7 @@ export default {
|
|||
}
|
||||
},
|
||||
setShow() {
|
||||
this.error = null
|
||||
if (!this.el || !this.content) {
|
||||
this.init()
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
</div>
|
||||
<div class="w-full md:w-1/3">
|
||||
<p v-if="!isMediaItemShareSession" class="font-semibold uppercase text-xs text-gray-400 tracking-wide mb-2 mt-6 md:mt-0">{{ $strings.LabelUser }}</p>
|
||||
<p v-if="!isMediaItemShareSession" class="mb-1 text-xs">{{ _session.userId }}</p>
|
||||
<p v-if="!isMediaItemShareSession" class="mb-1 text-xs">{{ username }}</p>
|
||||
|
||||
<p class="font-semibold uppercase text-xs text-gray-400 tracking-wide mt-6 mb-2">{{ $strings.LabelMediaPlayer }}</p>
|
||||
<p class="mb-1">{{ playMethodName }}</p>
|
||||
|
@ -132,6 +132,9 @@ export default {
|
|||
_session() {
|
||||
return this.session || {}
|
||||
},
|
||||
username() {
|
||||
return this._session.user?.username || this._session.userId || ''
|
||||
},
|
||||
deviceInfo() {
|
||||
return this._session.deviceInfo || {}
|
||||
},
|
||||
|
@ -159,10 +162,10 @@ export default {
|
|||
return 'Unknown'
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
},
|
||||
isOpenSession() {
|
||||
return !!this._session.open
|
||||
|
|
|
@ -23,7 +23,7 @@ export default {
|
|||
processing: Boolean,
|
||||
persistent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: false
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
|
@ -99,7 +99,7 @@ export default {
|
|||
this.preventClickoutside = false
|
||||
return
|
||||
}
|
||||
if (this.processing && this.persistent) return
|
||||
if (this.processing || this.persistent) return
|
||||
if (ev.srcElement && ev.srcElement.classList.contains('modal-bg')) {
|
||||
this.show = false
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ export default {
|
|||
expirationDateString() {
|
||||
if (!this.expireDurationSeconds) return this.$strings.LabelPermanent
|
||||
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: {
|
||||
|
|
|
@ -40,7 +40,7 @@ export default {
|
|||
}
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
releasesToShow() {
|
||||
return this.versionData?.releasesToShow || []
|
||||
|
|
|
@ -29,9 +29,6 @@ export default {
|
|||
media() {
|
||||
return this.libraryItem.media || {}
|
||||
},
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
userCanUpdate() {
|
||||
return this.$store.getters['user/getUserCanUpdate']
|
||||
},
|
||||
|
|
|
@ -77,8 +77,8 @@
|
|||
<ui-checkbox v-model="selectedMatchUsage.author" checkbox-bg="bg" @input="checkboxToggled" />
|
||||
<div class="grow ml-4">
|
||||
<ui-text-input-with-label v-model="selectedMatch.author" :disabled="!selectedMatchUsage.author" :label="$strings.LabelAuthor" />
|
||||
<p v-if="mediaMetadata.authorName" class="text-xs ml-1 text-white/60">
|
||||
{{ $strings.LabelCurrently }} <a title="$strings.LabelClickToUseCurrentValue" class="cursor-pointer hover:underline" @click.stop="setMatchFieldValue('author', mediaMetadata.authorName)">{{ mediaMetadata.authorName }}</a>
|
||||
<p v-if="mediaMetadata.authorName || (isPodcast && mediaMetadata.author)" class="text-xs ml-1 text-white/60">
|
||||
{{ $strings.LabelCurrently }} <a title="$strings.LabelClickToUseCurrentValue" class="cursor-pointer hover:underline" @click.stop="setMatchFieldValue('author', isPodcast ? mediaMetadata.author : mediaMetadata.authorName)">{{ isPodcast ? mediaMetadata.author : mediaMetadata.authorName }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -400,7 +400,9 @@ export default {
|
|||
this.$toast.warning(this.$strings.ToastTitleRequired)
|
||||
return
|
||||
}
|
||||
this.persistProvider()
|
||||
if (!this.isPodcast) {
|
||||
this.persistProvider()
|
||||
}
|
||||
this.runSearch()
|
||||
},
|
||||
async runSearch() {
|
||||
|
|
|
@ -35,7 +35,14 @@
|
|||
<widgets-podcast-type-indicator :type="episode.episodeType" />
|
||||
</div>
|
||||
<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>
|
||||
|
@ -244,8 +251,8 @@ export default {
|
|||
const sizeInMb = payloadSize / 1024 / 1024
|
||||
const sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
|
||||
console.log('Request size', sizeInMb)
|
||||
if (sizeInMb > 4.99) {
|
||||
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 5Mb`)
|
||||
if (sizeInMb > 9.99) {
|
||||
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 10Mb`)
|
||||
}
|
||||
|
||||
this.processing = true
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
{{ $getString('MessageConfirmRemoveEpisode', [episodeTitle]) }}
|
||||
</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 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" />
|
||||
|
@ -94,7 +94,6 @@ export default {
|
|||
}
|
||||
|
||||
this.processing = false
|
||||
this.$toast.success(`${this.episodes.length} episode${this.episodes.length > 1 ? 's' : ''} removed`)
|
||||
this.show = false
|
||||
this.$emit('clearSelected')
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<div class="w-full h-px bg-white/5 my-4" />
|
||||
|
@ -34,6 +34,12 @@
|
|||
{{ audioFileSize }}
|
||||
</p>
|
||||
</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>
|
||||
</modals-modal>
|
||||
|
@ -68,7 +74,7 @@ export default {
|
|||
return this.episode.title || 'No Episode Title'
|
||||
},
|
||||
description() {
|
||||
return this.episode.description || ''
|
||||
return this.parseDescription(this.episode.description || '')
|
||||
},
|
||||
media() {
|
||||
return this.libraryItem?.media || {}
|
||||
|
@ -90,11 +96,49 @@ export default {
|
|||
|
||||
return this.$bytesPretty(size)
|
||||
},
|
||||
audioFileDuration() {
|
||||
const duration = this.episode.duration || 0
|
||||
return this.$elapsedPretty(duration)
|
||||
},
|
||||
bookCoverAspectRatio() {
|
||||
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() {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -114,7 +114,7 @@ export default {
|
|||
.$patch(`/api/podcasts/${this.libraryItem.id}/episode/${this.episodeId}`, updatePayload)
|
||||
.then(() => {
|
||||
this.isProcessing = false
|
||||
this.$toast.success('Podcast episode updated')
|
||||
this.$toast.success(this.$strings.ToastPodcastEpisodeUpdated)
|
||||
this.$emit('selectTab', 'details')
|
||||
})
|
||||
.catch((error) => {
|
||||
|
|
|
@ -129,9 +129,6 @@ export default {
|
|||
return `${hoursRounded}h`
|
||||
}
|
||||
},
|
||||
token() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
timeRemaining() {
|
||||
if (this.useChapterTrack && this.currentChapter) {
|
||||
var currChapTime = this.currentTime - this.currentChapter.start
|
||||
|
|
|
@ -104,9 +104,6 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
libraryItemId() {
|
||||
return this.libraryItem?.id
|
||||
},
|
||||
|
@ -234,10 +231,7 @@ export default {
|
|||
async extract() {
|
||||
this.loading = true
|
||||
var buff = await this.$axios.$get(this.ebookUrl, {
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.userToken}`
|
||||
}
|
||||
responseType: 'blob'
|
||||
})
|
||||
const archive = await Archive.open(buff)
|
||||
const originalFilesObject = await archive.getFilesObject()
|
||||
|
|
|
@ -57,9 +57,6 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
/** @returns {string} */
|
||||
libraryItemId() {
|
||||
return this.libraryItem?.id
|
||||
|
@ -97,27 +94,37 @@ export default {
|
|||
},
|
||||
ebookUrl() {
|
||||
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() {
|
||||
const isDark = this.ereaderSettings.theme === 'dark'
|
||||
const fontColor = isDark ? '#fff' : '#000'
|
||||
const backgroundColor = isDark ? 'rgb(35 35 35)' : 'rgb(255, 255, 255)'
|
||||
const theme = this.ereaderSettings.theme
|
||||
const isDark = theme === 'dark'
|
||||
const isSepia = theme === 'sepia'
|
||||
|
||||
const fontColor = isDark
|
||||
? '#fff'
|
||||
: isSepia
|
||||
? '#5b4636'
|
||||
: '#000'
|
||||
|
||||
const backgroundColor = isDark
|
||||
? 'rgb(35 35 35)'
|
||||
: isSepia
|
||||
? 'rgb(244, 236, 216)'
|
||||
: 'rgb(255, 255, 255)'
|
||||
|
||||
const lineSpacing = this.ereaderSettings.lineSpacing / 100
|
||||
|
||||
const fontScale = this.ereaderSettings.fontScale / 100
|
||||
|
||||
const textStroke = this.ereaderSettings.textStroke / 100
|
||||
const fontScale = this.ereaderSettings.fontScale / 100
|
||||
const textStroke = this.ereaderSettings.textStroke / 100
|
||||
|
||||
return {
|
||||
'*': {
|
||||
color: `${fontColor}!important`,
|
||||
'background-color': `${backgroundColor}!important`,
|
||||
'line-height': lineSpacing * fontScale + 'rem!important',
|
||||
'-webkit-text-stroke': textStroke + 'px ' + fontColor + '!important'
|
||||
'line-height': `${lineSpacing * fontScale}rem!important`,
|
||||
'-webkit-text-stroke': `${textStroke}px ${fontColor}!important`
|
||||
},
|
||||
a: {
|
||||
color: `${fontColor}!important`
|
||||
|
@ -309,14 +316,24 @@ export default {
|
|||
/** @type {EpubReader} */
|
||||
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} */
|
||||
reader.book = new ePub(reader.ebookUrl, {
|
||||
width: this.readerWidth,
|
||||
height: this.readerHeight - 50,
|
||||
openAs: 'epub',
|
||||
requestHeaders: {
|
||||
Authorization: `Bearer ${this.userToken}`
|
||||
}
|
||||
requestMethod: customRequest
|
||||
})
|
||||
|
||||
/** @type {ePub.Rendition} */
|
||||
|
@ -337,29 +354,33 @@ export default {
|
|||
this.applyTheme()
|
||||
})
|
||||
|
||||
reader.book.ready.then(() => {
|
||||
// set up event listeners
|
||||
reader.rendition.on('relocated', reader.relocated)
|
||||
reader.rendition.on('keydown', reader.keyUp)
|
||||
reader.book.ready
|
||||
.then(() => {
|
||||
// set up event listeners
|
||||
reader.rendition.on('relocated', reader.relocated)
|
||||
reader.rendition.on('keydown', reader.keyUp)
|
||||
|
||||
reader.rendition.on('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('touchstart', (event) => {
|
||||
this.$emit('touchstart', event)
|
||||
})
|
||||
}
|
||||
this.getChapters()
|
||||
})
|
||||
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())
|
||||
})
|
||||
}
|
||||
this.getChapters()
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('EpubReader.initEpub failed:', error)
|
||||
})
|
||||
},
|
||||
getChapters() {
|
||||
// Load the list of chapters in the book. See https://github.com/futurepress/epub.js/issues/759
|
||||
|
|
|
@ -26,9 +26,6 @@ export default {
|
|||
return {}
|
||||
},
|
||||
computed: {
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
libraryItemId() {
|
||||
return this.libraryItem?.id
|
||||
},
|
||||
|
@ -96,11 +93,8 @@ export default {
|
|||
},
|
||||
async initMobi() {
|
||||
// Fetch mobi file as blob
|
||||
var buff = await this.$axios.$get(this.ebookUrl, {
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.userToken}`
|
||||
}
|
||||
const buff = await this.$axios.$get(this.ebookUrl, {
|
||||
responseType: 'blob'
|
||||
})
|
||||
var reader = new FileReader()
|
||||
reader.onload = async (event) => {
|
||||
|
|
|
@ -55,7 +55,8 @@ export default {
|
|||
loadedRatio: 0,
|
||||
page: 1,
|
||||
numPages: 0,
|
||||
pdfDocInitParams: null
|
||||
pdfDocInitParams: null,
|
||||
isRefreshing: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -152,7 +153,34 @@ export default {
|
|||
this.page++
|
||||
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)
|
||||
},
|
||||
resize() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="show" id="reader" :data-theme="ereaderTheme" class="group absolute top-0 left-0 w-full z-60 data-[theme=dark]:bg-primary data-[theme=dark]:text-white data-[theme=light]:bg-white data-[theme=light]:text-black" :class="{ 'reader-player-open': !!streamLibraryItem }">
|
||||
<div v-if="show" id="reader" :data-theme="ereaderTheme" class="group absolute top-0 left-0 w-full z-60 data-[theme=dark]:bg-primary data-[theme=dark]:text-white data-[theme=light]:bg-white data-[theme=light]:text-black data-[theme=sepia]:bg-[rgb(244,236,216)] data-[theme=sepia]:text-[#5b4636]" :class="{ 'reader-player-open': !!streamLibraryItem }">
|
||||
<div class="absolute top-4 left-4 z-20 flex items-center">
|
||||
<button v-if="isEpub" @click="toggleToC" type="button" aria-label="Table of contents menu" class="inline-flex opacity-80 hover:opacity-100">
|
||||
<span class="material-symbols text-2xl">menu</span>
|
||||
|
@ -27,7 +27,12 @@
|
|||
|
||||
<!-- TOC side nav -->
|
||||
<div v-if="tocOpen" class="w-full h-full overflow-y-scroll absolute inset-0 bg-black/20 z-20" @click.stop.prevent="toggleToC"></div>
|
||||
<div v-if="isEpub" class="w-96 h-full max-h-full absolute top-0 left-0 shadow-xl transition-transform z-30 group-data-[theme=dark]:bg-primary group-data-[theme=dark]:text-white group-data-[theme=light]:bg-white group-data-[theme=light]:text-black" :class="tocOpen ? 'translate-x-0' : '-translate-x-96'" @click.stop.prevent>
|
||||
<div
|
||||
v-if="isEpub"
|
||||
class="w-96 h-full max-h-full absolute top-0 left-0 shadow-xl transition-transform z-30 group-data-[theme=dark]:bg-primary group-data-[theme=dark]:text-white group-data-[theme=light]:bg-white group-data-[theme=light]:text-black group-data-[theme=sepia]:bg-[rgb(244,236,216)] group-data-[theme=sepia]:text-[#5b4636]"
|
||||
:class="tocOpen ? 'translate-x-0' : '-translate-x-96'"
|
||||
@click.stop.prevent
|
||||
>
|
||||
<div class="flex flex-col p-4 h-full">
|
||||
<div class="flex items-center mb-2">
|
||||
<button @click.stop.prevent="toggleToC" type="button" aria-label="Close table of contents" class="inline-flex opacity-80 hover:opacity-100">
|
||||
|
@ -37,7 +42,7 @@
|
|||
<p class="text-lg font-semibold ml-2">{{ $strings.HeaderTableOfContents }}</p>
|
||||
</div>
|
||||
<form @submit.prevent="searchBook" @click.stop.prevent>
|
||||
<ui-text-input clearable ref="input" @clear="searchBook" v-model="searchQuery" :placeholder="$strings.PlaceholderSearch" class="h-8 w-full text-sm flex mb-2" />
|
||||
<ui-text-input clearable ref="input" @clear="searchBook" v-model="searchQuery" :placeholder="$strings.PlaceholderSearch" custom-input-class="text-inherit !bg-inherit" class="h-8 w-full text-sm flex mb-2" />
|
||||
</form>
|
||||
|
||||
<div class="overflow-y-auto">
|
||||
|
@ -181,6 +186,10 @@ export default {
|
|||
text: this.$strings.LabelThemeDark,
|
||||
value: 'dark'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelThemeSepia,
|
||||
value: 'sepia'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelThemeLight,
|
||||
value: 'light'
|
||||
|
@ -266,9 +275,6 @@ export default {
|
|||
isComic() {
|
||||
return this.ebookFormat == 'cbz' || this.ebookFormat == 'cbr'
|
||||
},
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
keepProgress() {
|
||||
return this.$store.state.ereaderKeepProgress
|
||||
},
|
||||
|
|
|
@ -152,7 +152,7 @@ export default {
|
|||
|
||||
this.showingTooltipIndex = index
|
||||
this.tooltipEl.style.display = 'block'
|
||||
this.tooltipTextEl.innerHTML = block.value ? `<strong>${this.$elapsedPretty(block.value, true)} listening</strong> on ${block.datePretty}` : `No listening sessions on ${block.datePretty}`
|
||||
this.tooltipTextEl.innerHTML = block.value ? this.$getString('MessageHeatmapListeningTimeTooltip', [this.$elapsedPrettyLocalized(block.value, true), block.datePretty]) : this.$getString('MessageHeatmapNoListeningSessions', [block.datePretty])
|
||||
|
||||
const calculateRect = this.tooltipEl.getBoundingClientRect()
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
<template>
|
||||
<div class="flex flex-wrap justify-center mt-6">
|
||||
<div class="flex p-2">
|
||||
<svg class="h-14 w-14" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M9 3V18H12V3H9M12 5L16 18L19 17L15 4L12 5M5 5V18H8V5H5M3 19V21H21V19H3Z" />
|
||||
</svg>
|
||||
<span class="material-symbols text-5xl py-1">newsstand</span>
|
||||
<div class="px-1">
|
||||
<p class="text-4.5xl leading-none font-bold">{{ $formatNumber(totalItems) }}</p>
|
||||
<p class="text-xs md:text-sm text-white/80">{{ $strings.LabelStatsItemsInLibrary }}</p>
|
||||
|
@ -19,9 +17,7 @@
|
|||
</div>
|
||||
|
||||
<div v-if="isBookLibrary" class="flex p-2">
|
||||
<svg class="h-14 w-14" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,6A2,2 0 0,0 10,8A2,2 0 0,0 12,10A2,2 0 0,0 14,8A2,2 0 0,0 12,6M12,13C14.67,13 20,14.33 20,17V20H4V17C4,14.33 9.33,13 12,13M12,14.9C9.03,14.9 5.9,16.36 5.9,17V18.1H18.1V17C18.1,16.36 14.97,14.9 12,14.9Z" />
|
||||
</svg>
|
||||
<span class="material-symbols text-5xl py-1">person</span>
|
||||
<div class="px-1">
|
||||
<p class="text-4.5xl leading-none font-bold">{{ $formatNumber(totalAuthors) }}</p>
|
||||
<p class="text-xs md:text-sm text-white/80">{{ $strings.LabelStatsAuthors }}</p>
|
||||
|
|
177
client/components/tables/ApiKeysTable.vue
Normal file
177
client/components/tables/ApiKeysTable.vue
Normal file
|
@ -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>
|
|
@ -78,10 +78,10 @@ export default {
|
|||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -49,9 +49,6 @@ export default {
|
|||
libraryItemId() {
|
||||
return this.libraryItem.id
|
||||
},
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
userCanDownload() {
|
||||
return this.$store.getters['user/getUserCanDownload']
|
||||
},
|
||||
|
|
|
@ -53,9 +53,6 @@ export default {
|
|||
libraryItemId() {
|
||||
return this.libraryItem.id
|
||||
},
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
userCanDownload() {
|
||||
return this.$store.getters['user/getUserCanDownload']
|
||||
},
|
||||
|
|
|
@ -76,10 +76,10 @@ export default {
|
|||
return usermap
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -112,7 +112,7 @@ export default {
|
|||
return this.episode?.publishedAt
|
||||
},
|
||||
dateFormat() {
|
||||
return this.store.state.serverSettings.dateFormat
|
||||
return this.store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
itemProgress() {
|
||||
return this.store.getters['user/getUserMediaProgress'](this.libraryItemId, this.episodeId)
|
||||
|
|
|
@ -239,10 +239,10 @@ export default {
|
|||
})
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -85,9 +85,6 @@ export default {
|
|||
this.$emit('input', val)
|
||||
}
|
||||
},
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
},
|
||||
wrapperClass() {
|
||||
var classes = []
|
||||
if (this.disabled) classes.push('bg-black-300')
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
<template>
|
||||
<button :aria-label="isRead ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" class="icon-btn rounded-md flex items-center justify-center h-9 w-9 relative" :class="borderless ? '' : 'bg-primary border border-gray-600'" @click="clickBtn">
|
||||
<div class="w-5 h-5 text-white relative">
|
||||
<svg v-if="isRead" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="rgb(63, 181, 68)">
|
||||
<path d="M19 1H5c-1.1 0-1.99.9-1.99 2L3 15.93c0 .69.35 1.3.88 1.66L12 23l8.11-5.41c.53-.36.88-.97.88-1.66L21 3c0-1.1-.9-2-2-2zm-9 15l-5-5 1.41-1.41L10 13.17l7.59-7.59L19 7l-9 9z" />
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19 1H5c-1.1 0-1.99.9-1.99 2L3 15.93c0 .69.35 1.3.88 1.66L12 23l8.11-5.41c.53-.36.88-.97.88-1.66L21 3c0-1.1-.9-2-2-2zm-7 19.6l-7-4.66V3h14v12.93l-7 4.67zm-2.01-7.42l-2.58-2.59L6 12l4 4 8-8-1.42-1.42z" />
|
||||
</svg>
|
||||
<div class="w-5 h-5 relative">
|
||||
<span v-if="isRead" class="material-symbols fill text-xl text-success">beenhere</span>
|
||||
<span v-else class="material-symbols text-xl text-white">beenhere</span>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<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">
|
||||
<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" class="font-normal block truncate font-sans text-sm text-gray-400">{{ selectedSubtext }}</span>
|
||||
</span>
|
||||
|
@ -36,10 +36,15 @@ export default {
|
|||
type: String,
|
||||
default: ''
|
||||
},
|
||||
labelHidden: Boolean,
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
disabled: Boolean,
|
||||
small: Boolean,
|
||||
menuMaxHeight: {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<em v-if="note" class="font-normal text-xs pl-2">{{ note }}</em>
|
||||
</label>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
|
@ -21,6 +21,7 @@ export default {
|
|||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
min: [String, Number],
|
||||
readonly: Boolean,
|
||||
disabled: Boolean,
|
||||
inputClass: String,
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</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" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -316,6 +316,10 @@ export default {
|
|||
if (this.$refs.trix && this.$refs.trix.blur) {
|
||||
this.$refs.trix.blur()
|
||||
}
|
||||
},
|
||||
handleAttachmentAdd(event) {
|
||||
// Prevent pasting in images/any files from the browser
|
||||
event.attachment.remove()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
@ -85,7 +85,7 @@ export default {
|
|||
nextRun() {
|
||||
if (!this.cronExpression) return ''
|
||||
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() {
|
||||
if ((this.selectedInterval !== 'custom' || !this.selectedWeekdays.length) && this.selectedInterval !== 'daily') return ''
|
||||
|
|
|
@ -143,10 +143,18 @@ export default {
|
|||
localStorage.setItem('embedMetadataCodec', val)
|
||||
},
|
||||
getEncodingOptions() {
|
||||
return {
|
||||
codec: this.selectedCodec || 'aac',
|
||||
bitrate: this.selectedBitrate || '128k',
|
||||
channels: this.selectedChannels || 2
|
||||
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() {
|
||||
|
@ -162,7 +170,7 @@ export default {
|
|||
} else {
|
||||
// Find closest bitrate rounding up
|
||||
const bitratesToMatch = [32, 64, 128, 192]
|
||||
const closestBitrate = bitratesToMatch.find((bitrate) => bitrate >= this.currentBitrate)
|
||||
const closestBitrate = bitratesToMatch.find((bitrate) => bitrate >= this.currentBitrate) || 192
|
||||
this.selectedBitrate = closestBitrate + 'k'
|
||||
}
|
||||
|
||||
|
|
|
@ -1,40 +1,6 @@
|
|||
<template>
|
||||
<ui-tooltip :text="$strings.LabelExplicit" direction="top">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12px" height="12px" viewBox="0 0 512 512" class="ml-1">
|
||||
<path
|
||||
fill="white"
|
||||
d="M 89.00,40.12
|
||||
C 89.00,40.12 127.00,40.12 127.00,40.12
|
||||
127.00,40.12 198.00,40.12 198.00,40.12
|
||||
198.00,40.12 416.00,40.12 416.00,40.12
|
||||
446.58,40.05 472.95,66.42 473.00,97.00
|
||||
473.00,97.00 473.00,303.00 473.00,303.00
|
||||
473.00,303.00 473.00,418.00 473.00,418.00
|
||||
472.65,447.55 445.06,472.95 416.00,473.00
|
||||
416.00,473.00 210.00,473.00 210.00,473.00
|
||||
210.00,473.00 95.00,473.00 95.00,473.00
|
||||
65.45,472.65 40.05,445.06 40.00,416.00
|
||||
40.00,416.00 40.00,136.00 40.00,136.00
|
||||
40.00,136.00 40.00,109.00 40.00,109.00
|
||||
40.00,109.00 40.00,96.00 40.00,96.00
|
||||
40.07,81.58 46.89,67.14 57.01,57.01
|
||||
61.17,52.86 64.86,50.13 70.00,47.31
|
||||
77.25,43.33 81.02,42.18 89.00,40.12 Z
|
||||
M 337.00,121.00
|
||||
C 337.00,121.00 175.00,121.00 175.00,121.00
|
||||
175.00,121.00 175.00,392.00 175.00,392.00
|
||||
175.00,392.00 337.00,392.00 337.00,392.00
|
||||
337.00,392.00 337.00,349.00 337.00,349.00
|
||||
337.00,349.00 226.00,349.00 226.00,349.00
|
||||
226.00,349.00 226.00,274.00 226.00,274.00
|
||||
226.00,274.00 332.00,274.00 332.00,274.00
|
||||
332.00,274.00 332.00,232.00 332.00,232.00
|
||||
332.00,232.00 226.00,232.00 226.00,232.00
|
||||
226.00,232.00 226.00,164.00 226.00,164.00
|
||||
226.00,164.00 337.00,164.00 337.00,164.00
|
||||
337.00,164.00 337.00,121.00 337.00,121.00 Z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="material-symbols fill text-sm ml-1 !block">explicit</span>
|
||||
</ui-tooltip>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -248,4 +248,4 @@ export default {
|
|||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<ui-multi-select-query-input v-model="seriesItems" text-key="displayName" :label="$strings.LabelSeries" :disabled="disabled" readonly show-edit @edit="editSeriesItem" @add="addNewSeries" />
|
||||
|
||||
<modals-edit-series-input-inner-modal v-model="showSeriesForm" :selected-series="selectedSeries" :existing-series-names="existingSeriesNames" @submit="submitSeriesForm" />
|
||||
<modals-edit-series-input-inner-modal v-model="showSeriesForm" :selected-series="selectedSeries" :existing-series-names="existingSeriesNames" :original-series-sequence="originalSeriesSequence" @submit="submitSeriesForm" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -18,6 +18,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
selectedSeries: null,
|
||||
originalSeriesSequence: null,
|
||||
showSeriesForm: false
|
||||
}
|
||||
},
|
||||
|
@ -59,6 +60,7 @@ export default {
|
|||
..._series
|
||||
}
|
||||
|
||||
this.originalSeriesSequence = _series.sequence
|
||||
this.showSeriesForm = true
|
||||
},
|
||||
addNewSeries() {
|
||||
|
@ -68,6 +70,7 @@ export default {
|
|||
sequence: ''
|
||||
}
|
||||
|
||||
this.originalSeriesSequence = null
|
||||
this.showSeriesForm = true
|
||||
},
|
||||
submitSeriesForm() {
|
||||
|
@ -106,4 +109,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -40,6 +40,7 @@ describe('LazySeriesCard', () => {
|
|||
},
|
||||
$store: {
|
||||
getters: {
|
||||
getServerSetting: () => 'MM/dd/yyyy',
|
||||
'user/getUserCanUpdate': true,
|
||||
'user/getUserMediaProgress': (id) => null,
|
||||
'user/getSizeMultiplier': 1,
|
||||
|
|
|
@ -33,6 +33,7 @@ export default {
|
|||
return {
|
||||
socket: null,
|
||||
isSocketConnected: false,
|
||||
isSocketAuthenticated: false,
|
||||
isFirstSocketConnection: true,
|
||||
socketConnectionToastId: null,
|
||||
currentLang: null,
|
||||
|
@ -81,9 +82,28 @@ export default {
|
|||
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) {
|
||||
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 {
|
||||
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)
|
||||
},
|
||||
reconnect() {
|
||||
console.error('[SOCKET] reconnected')
|
||||
console.log('[SOCKET] reconnected')
|
||||
},
|
||||
reconnectAttempt(val) {
|
||||
console.log(`[SOCKET] reconnect attempt ${val}`)
|
||||
|
@ -120,6 +140,10 @@ export default {
|
|||
reconnectFailed() {
|
||||
console.error('[SOCKET] reconnect failed')
|
||||
},
|
||||
authFailed(payload) {
|
||||
console.error('[SOCKET] auth failed', payload.message)
|
||||
this.isSocketAuthenticated = false
|
||||
},
|
||||
init(payload) {
|
||||
console.log('Init Payload', payload)
|
||||
|
||||
|
@ -127,7 +151,7 @@ export default {
|
|||
this.$store.commit('users/setUsersOnline', payload.usersOnline)
|
||||
}
|
||||
|
||||
this.$eventBus.$emit('socket_init')
|
||||
this.isSocketAuthenticated = true
|
||||
},
|
||||
streamOpen(stream) {
|
||||
if (this.$refs.mediaPlayerContainer) this.$refs.mediaPlayerContainer.streamOpen(stream)
|
||||
|
@ -175,7 +199,7 @@ export default {
|
|||
}
|
||||
} else {
|
||||
console.error('User has no more accessible libraries')
|
||||
this.$store.commit('libraries/setCurrentLibrary', null)
|
||||
this.$store.commit('libraries/setCurrentLibrary', { id: null })
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -354,6 +378,15 @@ export default {
|
|||
this.$store.commit('scanners/removeCustomMetadataProvider', provider)
|
||||
},
|
||||
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({
|
||||
name: process.env.NODE_ENV === 'development' ? 'dev' : 'prod',
|
||||
persist: 'main',
|
||||
|
@ -364,6 +397,7 @@ export default {
|
|||
path: `${this.$config.routerBasePath}/socket.io`
|
||||
})
|
||||
this.$root.socket = this.socket
|
||||
this.isSocketAuthenticated = false
|
||||
console.log('Socket initialized')
|
||||
|
||||
// Pre-defined socket events
|
||||
|
@ -377,6 +411,7 @@ export default {
|
|||
|
||||
// Event received after authorizing socket
|
||||
this.socket.on('init', this.init)
|
||||
this.socket.on('auth_failed', this.authFailed)
|
||||
|
||||
// Stream Listeners
|
||||
this.socket.on('stream_open', this.streamOpen)
|
||||
|
@ -571,6 +606,7 @@ export default {
|
|||
this.updateBodyClass()
|
||||
this.resize()
|
||||
this.$eventBus.$on('change-lang', this.changeLanguage)
|
||||
this.$eventBus.$on('token_refreshed', this.tokenRefreshed)
|
||||
window.addEventListener('resize', this.resize)
|
||||
window.addEventListener('keydown', this.keyDown)
|
||||
|
||||
|
@ -594,6 +630,7 @@ export default {
|
|||
},
|
||||
beforeDestroy() {
|
||||
this.$eventBus.$off('change-lang', this.changeLanguage)
|
||||
this.$eventBus.$off('token_refreshed', this.tokenRefreshed)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
window.removeEventListener('keydown', this.keyDown)
|
||||
}
|
||||
|
|
|
@ -73,7 +73,8 @@ module.exports = {
|
|||
|
||||
// Axios module configuration: https://go.nuxtjs.dev/config-axios
|
||||
axios: {
|
||||
baseURL: routerBasePath
|
||||
baseURL: routerBasePath,
|
||||
progress: false
|
||||
},
|
||||
|
||||
// nuxt/pwa https://pwa.nuxtjs.org
|
||||
|
|
4
client/package-lock.json
generated
4
client/package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.22.0",
|
||||
"version": "2.29.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.22.0",
|
||||
"version": "2.29.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nuxtjs/axios": "^5.13.6",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "audiobookshelf-client",
|
||||
"version": "2.22.0",
|
||||
"version": "2.29.0",
|
||||
"buildNumber": 1,
|
||||
"description": "Self-hosted audiobook and podcast client",
|
||||
"main": "index.js",
|
||||
|
|
|
@ -182,18 +182,19 @@ export default {
|
|||
password: this.password,
|
||||
newPassword: this.newPassword
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.$toast.success(this.$strings.ToastUserPasswordChangeSuccess)
|
||||
this.resetForm()
|
||||
} else {
|
||||
this.$toast.error(res.error || this.$strings.ToastUnknownError)
|
||||
}
|
||||
this.changingPassword = false
|
||||
.then(() => {
|
||||
this.$toast.success(this.$strings.ToastUserPasswordChangeSuccess)
|
||||
this.resetForm()
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
this.$toast.error(this.$strings.ToastUnknownError)
|
||||
console.error('Failed to change password', error)
|
||||
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
|
||||
})
|
||||
},
|
||||
|
|
|
@ -53,51 +53,101 @@
|
|||
|
||||
<div class="flex text-xs uppercase text-gray-300 font-semibold mb-2">
|
||||
<div class="w-8 min-w-8 md:w-12 md:min-w-12"></div>
|
||||
<div class="w-24 min-w-24 md:w-32 md:min-w-32 px-2">{{ $strings.LabelStart }}</div>
|
||||
<div class="grow px-2">{{ $strings.LabelTitle }}</div>
|
||||
<div class="w-38 min-w-38 md:w-40 md:min-w-40 px-1 pl-8">{{ $strings.LabelStart }}</div>
|
||||
<div class="grow px-1 min-w-54">{{ $strings.LabelTitle }}</div>
|
||||
<div class="w-7 min-w-7 px-1 flex items-center justify-center">
|
||||
<ui-tooltip :text="allChaptersLocked ? $strings.TooltipUnlockAllChapters : $strings.TooltipLockAllChapters" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center cursor-pointer transition-colors duration-150" :class="allChaptersLocked ? 'text-orange-400 hover:text-orange-300' : 'text-gray-300 hover:text-white'" @click="toggleAllChaptersLock">
|
||||
<span class="material-symbols text-xl">{{ allChaptersLocked ? 'lock' : 'lock_open' }}</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
</div>
|
||||
<div class="w-32"></div>
|
||||
</div>
|
||||
<template v-for="chapter in newChapters">
|
||||
<div :key="chapter.id" class="flex py-1">
|
||||
<div class="w-8 min-w-8 md:w-12 md:min-w-12">#{{ chapter.id + 1 }}</div>
|
||||
<div class="w-24 min-w-24 md:w-32 md:min-w-32 px-1">
|
||||
<ui-text-input v-if="showSecondInputs" v-model="chapter.start" type="number" class="text-xs" @change="checkChapters" />
|
||||
<ui-time-picker v-else class="text-xs" v-model="chapter.start" :show-three-digit-hour="mediaDuration >= 360000" @change="checkChapters" />
|
||||
</div>
|
||||
<div class="grow px-1">
|
||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs min-w-52" />
|
||||
</div>
|
||||
<div class="w-32 min-w-32 px-2 py-1">
|
||||
<div class="flex items-center">
|
||||
<ui-tooltip :text="$strings.MessageRemoveChapter" direction="bottom">
|
||||
<button v-if="newChapters.length > 1" class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-error transform hover:scale-110 duration-150" @click="removeChapter(chapter)">
|
||||
<span class="material-symbols text-base">remove</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
<div v-for="chapter in newChapters" :key="chapter.id" class="flex py-1">
|
||||
<div class="w-8 min-w-8 md:w-12 md:min-w-12">#{{ chapter.id + 1 }}</div>
|
||||
<div class="w-38 min-w-38 md:w-40 md:min-w-40 px-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<ui-tooltip :text="$strings.TooltipSubtractOneSecond" direction="bottom">
|
||||
<button
|
||||
class="w-6 h-6 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150 flex-shrink-0"
|
||||
:class="{ 'opacity-50 cursor-not-allowed': chapter.id === 0 && chapter.start - timeIncrementAmount < 0 }"
|
||||
@click="incrementChapterTime(chapter, -timeIncrementAmount)"
|
||||
:disabled="chapter.id === 0 && chapter.start - timeIncrementAmount < 0"
|
||||
>
|
||||
<span class="material-symbols text-sm">remove</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
|
||||
<ui-tooltip :text="$strings.MessageInsertChapterBelow" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-success transform hover:scale-110 duration-150" @click="addChapter(chapter)">
|
||||
<span class="material-symbols text-lg">add</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
|
||||
<ui-tooltip :text="selectedChapterId === chapter.id && isPlayingChapter ? $strings.MessagePauseChapter : $strings.MessagePlayChapter" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150" @click="playChapter(chapter)">
|
||||
<widgets-loading-spinner v-if="selectedChapterId === chapter.id && isLoadingChapter" />
|
||||
<span v-else-if="selectedChapterId === chapter.id && isPlayingChapter" class="material-symbols text-base">pause</span>
|
||||
<span v-else class="material-symbols text-base">play_arrow</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
|
||||
<ui-tooltip v-if="chapter.error" :text="chapter.error" direction="left">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-error">
|
||||
<span class="material-symbols text-lg">error_outline</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
<div class="flex-1 min-w-0">
|
||||
<ui-text-input v-if="showSecondInputs" v-model="chapter.start" type="number" class="text-xs" @change="checkChapters" />
|
||||
<ui-time-picker v-else class="text-xs" v-model="chapter.start" :show-three-digit-hour="mediaDuration >= 360000" @change="checkChapters" />
|
||||
</div>
|
||||
|
||||
<ui-tooltip :text="$strings.TooltipAddOneSecond" direction="bottom">
|
||||
<button class="w-6 h-6 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150 flex-shrink-0" :class="{ 'opacity-50 cursor-not-allowed': chapter.start + timeIncrementAmount >= mediaDuration }" @click="incrementChapterTime(chapter, timeIncrementAmount)" :disabled="chapter.start + timeIncrementAmount >= mediaDuration">
|
||||
<span class="material-symbols text-sm">add</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="grow px-1">
|
||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs min-w-52" />
|
||||
</div>
|
||||
<div class="w-7 min-w-7 px-1 py-1">
|
||||
<div class="flex items-center justify-center">
|
||||
<ui-tooltip :text="lockedChapters.has(chapter.id) ? $strings.TooltipUnlockChapter : $strings.TooltipLockChapter" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center transform hover:scale-110 duration-150 flex-shrink-0" :class="lockedChapters.has(chapter.id) ? 'text-orange-400 hover:text-orange-300' : 'text-gray-300 hover:text-white'" @click="toggleChapterLock(chapter, $event)">
|
||||
<span class="material-symbols text-base">{{ lockedChapters.has(chapter.id) ? 'lock' : 'lock_open' }}</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-32 min-w-32 px-2 py-1">
|
||||
<div class="flex items-center">
|
||||
<ui-tooltip :text="$strings.MessageRemoveChapter" direction="bottom">
|
||||
<button v-if="newChapters.length > 1" class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-error transform hover:scale-110 duration-150" @click="removeChapter(chapter)">
|
||||
<span class="material-symbols text-base">delete</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
|
||||
<ui-tooltip :text="$strings.MessageInsertChapterBelow" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-success transform hover:scale-110 duration-150" @click="addChapter(chapter)">
|
||||
<span class="material-symbols text-lg">add_row_below</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
<ui-tooltip :text="selectedChapterId === chapter.id && isPlayingChapter ? $strings.MessagePauseChapter : $strings.MessagePlayChapter" direction="bottom">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150" @click="playChapter(chapter)">
|
||||
<widgets-loading-spinner v-if="selectedChapterId === chapter.id && isLoadingChapter" />
|
||||
<span v-else-if="selectedChapterId === chapter.id && isPlayingChapter" class="material-symbols text-base">pause</span>
|
||||
<span v-else class="material-symbols text-base">play_arrow</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
<ui-tooltip v-if="selectedChapterId === chapter.id && (isPlayingChapter || isLoadingChapter)" :text="$strings.TooltipAdjustChapterStart" direction="bottom">
|
||||
<div class="ml-2 text-xs text-gray-300 font-mono min-w-10 cursor-pointer hover:text-white transition-colors duration-150" @click="adjustChapterStartTime(chapter)">{{ elapsedTime }}s</div>
|
||||
</ui-tooltip>
|
||||
<ui-tooltip v-if="chapter.error" :text="chapter.error" direction="left">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-error">
|
||||
<span class="material-symbols text-lg">error_outline</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center mt-4 mb-2">
|
||||
<div class="w-8 min-w-8 md:w-12 md:min-w-12"></div>
|
||||
<div class="w-38 min-w-38 md:w-40 md:min-w-40 px-1"></div>
|
||||
<div class="flex items-center gap-2 grow px-1">
|
||||
<ui-text-input v-model="bulkChapterInput" :placeholder="$strings.PlaceholderBulkChapterInput" class="text-xs grow min-w-52" @keyup.enter="handleBulkChapterAdd" />
|
||||
</div>
|
||||
<div class="w-39 min-w-39 px-1 py-1">
|
||||
<ui-tooltip :text="$strings.TooltipAddChapters" direction="bottom" class="inline-block align-middle">
|
||||
<button class="w-5 h-5 rounded-full flex items-center justify-center text-gray-300 hover:text-success transform hover:scale-110 duration-150 flex-shrink-0" :aria-label="$strings.TooltipAddChapters" :class="{ 'opacity-50 cursor-not-allowed': !bulkChapterInput.trim() }" :disabled="!bulkChapterInput.trim()" @click="handleBulkChapterAdd">
|
||||
<span class="material-symbols text-lg">add</span>
|
||||
</button>
|
||||
</ui-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full max-w-xl py-4 px-2">
|
||||
|
@ -114,19 +164,15 @@
|
|||
<div class="w-20">{{ $strings.LabelDuration }}</div>
|
||||
<div class="w-20 hidden md:block text-center">{{ $strings.HeaderChapters }}</div>
|
||||
</div>
|
||||
<template v-for="track in audioTracks">
|
||||
<div :key="track.ino" class="flex items-center py-2" :class="currentTrackIndex === track.index && isPlayingChapter ? 'bg-success/10' : ''">
|
||||
<div class="grow max-w-[calc(100%-80px)] pr-2">
|
||||
<p class="text-xs truncate max-w-sm">{{ track.metadata.filename }}</p>
|
||||
</div>
|
||||
<div class="w-20" style="min-width: 80px">
|
||||
<p class="text-xs font-mono text-gray-200">{{ $secondsToTimestamp(Math.round(track.duration), false, true) }}</p>
|
||||
</div>
|
||||
<div class="w-20 hidden md:flex justify-center" style="min-width: 80px">
|
||||
<span v-if="(track.chapters || []).length" class="material-symbols text-success text-sm">check</span>
|
||||
</div>
|
||||
<div v-for="track in audioTracks" :key="track.ino" class="flex items-center py-2" :class="currentTrackIndex === track.index && isPlayingChapter ? 'bg-success/10' : ''">
|
||||
<div class="grow max-w-[calc(100%-80px)] pr-2">
|
||||
<p class="text-xs truncate max-w-sm">{{ track.metadata.filename }}</p>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-20" style="min-width: 80px">
|
||||
<p class="text-xs font-mono text-gray-200">{{ $secondsToTimestamp(Math.round(track.duration), false, true) }}</p>
|
||||
</div>
|
||||
<div class="w-20 hidden md:flex justify-center" style="min-width: 80px"><span v-if="(track.chapters || []).length" class="material-symbols text-success text-sm">check</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -134,6 +180,7 @@
|
|||
<ui-loading-indicator />
|
||||
</div>
|
||||
|
||||
<!-- audible chapter lookup modal -->
|
||||
<modals-modal v-model="showFindChaptersModal" name="edit-book" :width="500" :processing="findingChapters">
|
||||
<template #outer>
|
||||
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden pointer-events-none">
|
||||
|
@ -159,12 +206,16 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-else class="w-full p-4">
|
||||
<div class="flex justify-between mb-4">
|
||||
<div class="flex mb-4">
|
||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-white flex-shrink-0" :aria-label="$strings.ButtonBack" @click="resetChapterLookupData">
|
||||
<span class="material-symbols text-lg">arrow_back</span>
|
||||
</button>
|
||||
<p>
|
||||
{{ $strings.LabelDurationFound }} <span class="font-semibold">{{ $secondsToTimestamp(chapterData.runtimeLengthSec) }}</span
|
||||
><br />
|
||||
{{ $strings.LabelDurationFound }} <span class="font-semibold">{{ $secondsToTimestamp(chapterData.runtimeLengthSec) }}</span>
|
||||
<br />
|
||||
<span class="font-semibold" :class="{ 'text-warning': chapters.length !== chapterData.chapters.length }">{{ chapterData.chapters.length }}</span> {{ $strings.LabelChaptersFound }}
|
||||
</p>
|
||||
<div class="grow" />
|
||||
<p>
|
||||
{{ $strings.LabelYourAudiobookDuration }}: <span class="font-semibold">{{ $secondsToTimestamp(mediaDurationRounded) }}</span
|
||||
><br />
|
||||
|
@ -198,17 +249,49 @@
|
|||
<p class="pl-2">{{ $strings.MessageChapterStartIsAfter }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center pt-2">
|
||||
<ui-btn small color="bg-primary" class="mr-1" @click="applyChapterNamesOnly">{{ $strings.ButtonMapChapterTitles }}</ui-btn>
|
||||
<ui-tooltip :text="$strings.MessageMapChapterTitles" direction="top" class="flex items-center">
|
||||
<span class="material-symbols text-xl text-gray-200">info</span>
|
||||
</ui-tooltip>
|
||||
<div class="grow" />
|
||||
<div class="flex items-center pt-2 justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<ui-btn small color="bg-primary" @click="applyChapterNamesOnly">{{ $strings.ButtonMapChapterTitles }}</ui-btn>
|
||||
<ui-tooltip :text="$strings.MessageMapChapterTitles" direction="top" class="flex items-center">
|
||||
<span class="material-symbols text-xl text-gray-200">info</span>
|
||||
</ui-tooltip>
|
||||
</div>
|
||||
<ui-btn small color="bg-success" @click="applyChapterData">{{ $strings.ButtonApplyChapters }}</ui-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</modals-modal>
|
||||
|
||||
<!-- create bulk chapters modal -->
|
||||
<modals-modal v-model="showBulkChapterModal" name="bulk-chapters" :width="400">
|
||||
<template #outer>
|
||||
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden pointer-events-none">
|
||||
<p class="text-3xl text-white truncate pointer-events-none">{{ $strings.HeaderBulkChapterModal }}</p>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-full h-full max-h-full text-sm rounded-lg bg-bg shadow-lg border border-black-300 relative p-6">
|
||||
<div class="flex flex-col space-y-8">
|
||||
<p class="text-base">{{ $strings.MessageBulkChapterPattern }}</p>
|
||||
|
||||
<div v-if="detectedPattern" class="text-sm text-gray-400 bg-gray-800 p-2 rounded">
|
||||
<strong>{{ $strings.LabelDetectedPattern }}</strong> "{{ detectedPattern.before }}{{ formatNumberWithPadding(detectedPattern.startingNumber, detectedPattern) }}{{ detectedPattern.after }}"
|
||||
<br />
|
||||
<strong>{{ $strings.LabelNextChapters }}</strong>
|
||||
"{{ detectedPattern.before }}{{ formatNumberWithPadding(detectedPattern.startingNumber + 1, detectedPattern) }}{{ detectedPattern.after }}", "{{ detectedPattern.before }}{{ formatNumberWithPadding(detectedPattern.startingNumber + 2, detectedPattern) }}{{ detectedPattern.after }}", etc.
|
||||
</div>
|
||||
<div class="flex px-1 items-center">
|
||||
<label class="text-base font-medium">{{ $strings.LabelNumberOfChapters }}</label>
|
||||
<div class="grow" />
|
||||
<ui-text-input v-model="bulkChapterCount" type="number" min="1" max="50" class="w-14" :style="{ height: `2em` }" @keyup.enter="addBulkChapters" />
|
||||
</div>
|
||||
<div class="flex px-1 items-center">
|
||||
<ui-btn small @click="showBulkChapterModal = false">{{ $strings.ButtonCancel }}</ui-btn>
|
||||
<div class="grow" />
|
||||
<ui-btn small color="bg-success" @click="addBulkChapters">{{ $strings.ButtonAddChapters }}</ui-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</modals-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -265,7 +348,17 @@ export default {
|
|||
removeBranding: false,
|
||||
showSecondInputs: false,
|
||||
audibleRegions: ['US', 'CA', 'UK', 'AU', 'FR', 'DE', 'JP', 'IT', 'IN', 'ES'],
|
||||
hasChanges: false
|
||||
hasChanges: false,
|
||||
timeIncrementAmount: 1,
|
||||
elapsedTime: 0,
|
||||
playStartTime: null,
|
||||
elapsedTimeInterval: null,
|
||||
lockedChapters: new Set(),
|
||||
lastSelectedLockIndex: null,
|
||||
bulkChapterInput: '',
|
||||
showBulkChapterModal: false,
|
||||
bulkChapterCount: 1,
|
||||
detectedPattern: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -304,9 +397,18 @@ export default {
|
|||
},
|
||||
selectedChapterId() {
|
||||
return this.selectedChapter ? this.selectedChapter.id : null
|
||||
},
|
||||
allChaptersLocked() {
|
||||
return this.newChapters.length > 0 && this.newChapters.every((chapter) => this.lockedChapters.has(chapter.id))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatNumberWithPadding(number, pattern) {
|
||||
if (!pattern || !pattern.hasLeadingZeros || !pattern.originalPadding) {
|
||||
return number.toString()
|
||||
}
|
||||
return number.toString().padStart(pattern.originalPadding, '0')
|
||||
},
|
||||
setChaptersFromTracks() {
|
||||
let currentStartTime = 0
|
||||
let index = 0
|
||||
|
@ -321,7 +423,7 @@ export default {
|
|||
currentStartTime += track.duration
|
||||
}
|
||||
this.newChapters = chapters
|
||||
|
||||
this.lockedChapters = new Set()
|
||||
this.checkChapters()
|
||||
},
|
||||
toggleRemoveBranding() {
|
||||
|
@ -334,19 +436,22 @@ export default {
|
|||
|
||||
const amount = Number(this.shiftAmount)
|
||||
|
||||
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
||||
if (lastChapter.start + amount > this.mediaDurationRounded) {
|
||||
this.$toast.error(this.$strings.ToastChaptersInvalidShiftAmountLast)
|
||||
return
|
||||
}
|
||||
// Check if any unlocked chapters would be affected negatively
|
||||
const unlockedChapters = this.newChapters.filter((chap) => !this.lockedChapters.has(chap.id))
|
||||
|
||||
if (this.newChapters[1].start + amount <= 0) {
|
||||
this.$toast.error(this.$strings.ToastChaptersInvalidShiftAmountStart)
|
||||
if (unlockedChapters.length === 0) {
|
||||
this.$toast.warning(this.$strings.ToastChaptersAllLocked)
|
||||
return
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.newChapters.length; i++) {
|
||||
const chap = this.newChapters[i]
|
||||
|
||||
// Skip locked chapters
|
||||
if (this.lockedChapters.has(chap.id)) {
|
||||
continue
|
||||
}
|
||||
|
||||
chap.end = Math.min(chap.end + amount, this.mediaDuration)
|
||||
if (i > 0) {
|
||||
chap.start = Math.max(0, chap.start + amount)
|
||||
|
@ -354,6 +459,83 @@ export default {
|
|||
}
|
||||
this.checkChapters()
|
||||
},
|
||||
incrementChapterTime(chapter, amount) {
|
||||
if (chapter.id === 0 && chapter.start + amount < 0) {
|
||||
return
|
||||
}
|
||||
if (chapter.start + amount >= this.mediaDuration) {
|
||||
return
|
||||
}
|
||||
|
||||
chapter.start = Math.max(0, chapter.start + amount)
|
||||
this.checkChapters()
|
||||
},
|
||||
adjustChapterStartTime(chapter) {
|
||||
const newStartTime = chapter.start + this.elapsedTime
|
||||
chapter.start = newStartTime
|
||||
this.checkChapters()
|
||||
this.$toast.success(this.$strings.ToastChapterStartTimeAdjusted.replace('{0}', this.elapsedTime))
|
||||
|
||||
this.destroyAudioEl()
|
||||
},
|
||||
startElapsedTimeTracking() {
|
||||
this.elapsedTime = 0
|
||||
this.playStartTime = Date.now()
|
||||
this.elapsedTimeInterval = setInterval(() => {
|
||||
this.elapsedTime = Math.floor((Date.now() - this.playStartTime) / 1000)
|
||||
}, 100)
|
||||
},
|
||||
stopElapsedTimeTracking() {
|
||||
if (this.elapsedTimeInterval) {
|
||||
clearInterval(this.elapsedTimeInterval)
|
||||
this.elapsedTimeInterval = null
|
||||
}
|
||||
this.elapsedTime = 0
|
||||
this.playStartTime = null
|
||||
},
|
||||
toggleChapterLock(chapter, event) {
|
||||
const chapterId = chapter.id
|
||||
|
||||
if (event.shiftKey && this.lastSelectedLockIndex !== null) {
|
||||
const startIndex = Math.min(this.lastSelectedLockIndex, chapterId)
|
||||
const endIndex = Math.max(this.lastSelectedLockIndex, chapterId)
|
||||
const shouldLock = !this.lockedChapters.has(chapterId)
|
||||
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
if (shouldLock) {
|
||||
this.lockedChapters.add(i)
|
||||
} else {
|
||||
this.lockedChapters.delete(i)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.lockedChapters.has(chapterId)) {
|
||||
this.lockedChapters.delete(chapterId)
|
||||
} else {
|
||||
this.lockedChapters.add(chapterId)
|
||||
}
|
||||
}
|
||||
|
||||
this.lastSelectedLockIndex = chapterId
|
||||
this.lockedChapters = new Set(this.lockedChapters)
|
||||
},
|
||||
lockAllChapters() {
|
||||
this.newChapters.forEach((chapter) => {
|
||||
this.lockedChapters.add(chapter.id)
|
||||
})
|
||||
this.lockedChapters = new Set(this.lockedChapters)
|
||||
},
|
||||
unlockAllChapters() {
|
||||
this.lockedChapters.clear()
|
||||
this.lockedChapters = new Set(this.lockedChapters)
|
||||
},
|
||||
toggleAllChaptersLock() {
|
||||
if (this.allChaptersLocked) {
|
||||
this.unlockAllChapters()
|
||||
} else {
|
||||
this.lockAllChapters()
|
||||
}
|
||||
},
|
||||
editItem() {
|
||||
this.$store.commit('showEditModal', this.libraryItem)
|
||||
},
|
||||
|
@ -368,6 +550,10 @@ export default {
|
|||
this.checkChapters()
|
||||
},
|
||||
removeChapter(chapter) {
|
||||
if (this.lockedChapters.has(chapter.id)) {
|
||||
this.$toast.warning(this.$strings.ToastChapterLocked)
|
||||
return
|
||||
}
|
||||
this.newChapters = this.newChapters.filter((ch) => ch.id !== chapter.id)
|
||||
this.checkChapters()
|
||||
},
|
||||
|
@ -451,6 +637,7 @@ export default {
|
|||
console.log('Audio playing')
|
||||
this.isLoadingChapter = false
|
||||
this.isPlayingChapter = true
|
||||
this.startElapsedTimeTracking()
|
||||
})
|
||||
audioEl.addEventListener('ended', () => {
|
||||
console.log('Audio ended')
|
||||
|
@ -473,6 +660,10 @@ export default {
|
|||
this.selectedChapter = null
|
||||
this.isPlayingChapter = false
|
||||
this.isLoadingChapter = false
|
||||
this.stopElapsedTimeTracking()
|
||||
},
|
||||
resetChapterLookupData() {
|
||||
this.chapterData = null
|
||||
},
|
||||
saveChapters() {
|
||||
this.checkChapters()
|
||||
|
@ -523,7 +714,7 @@ export default {
|
|||
},
|
||||
applyChapterNamesOnly() {
|
||||
this.newChapters.forEach((chapter, index) => {
|
||||
if (this.chapterData.chapters[index]) {
|
||||
if (this.chapterData.chapters[index] && !this.lockedChapters.has(chapter.id)) {
|
||||
chapter.title = this.chapterData.chapters[index].title
|
||||
}
|
||||
})
|
||||
|
@ -535,7 +726,7 @@ export default {
|
|||
},
|
||||
applyChapterData() {
|
||||
let index = 0
|
||||
this.newChapters = this.chapterData.chapters
|
||||
const audibleChapters = this.chapterData.chapters
|
||||
.filter((chap) => chap.startOffsetSec < this.mediaDuration)
|
||||
.map((chap) => {
|
||||
return {
|
||||
|
@ -545,6 +736,21 @@ export default {
|
|||
title: chap.title
|
||||
}
|
||||
})
|
||||
|
||||
const merged = []
|
||||
let audibleIdx = 0
|
||||
for (let i = 0; i < Math.max(this.newChapters.length, audibleChapters.length); i++) {
|
||||
const isLocked = this.lockedChapters.has(i)
|
||||
if (isLocked && this.newChapters[i]) {
|
||||
merged.push({ ...this.newChapters[i], id: i })
|
||||
} else if (audibleChapters[audibleIdx]) {
|
||||
merged.push({ ...audibleChapters[audibleIdx], id: i })
|
||||
audibleIdx++
|
||||
} else if (this.newChapters[i]) {
|
||||
merged.push({ ...this.newChapters[i], id: i })
|
||||
}
|
||||
}
|
||||
this.newChapters = merged
|
||||
this.showFindChaptersModal = false
|
||||
this.chapterData = null
|
||||
|
||||
|
@ -572,7 +778,7 @@ export default {
|
|||
if (data.error) {
|
||||
this.asinError = this.$getString(data.stringKey)
|
||||
} else {
|
||||
console.log('Chapter data', data)
|
||||
console.log('Chapter data', { ...data })
|
||||
this.chapterData = this.removeBranding ? this.removeBrandingFromData(data) : data
|
||||
}
|
||||
})
|
||||
|
@ -609,6 +815,11 @@ export default {
|
|||
data.chapters.pop()
|
||||
}
|
||||
|
||||
// Remove Branding durations from Runtime totals
|
||||
data.runtimeLengthMs -= introDuration + outroDuration
|
||||
data.runtimeLengthSec = Math.floor(data.runtimeLengthMs / 1000)
|
||||
console.log('Brandless Chapter data', data)
|
||||
|
||||
return data
|
||||
} catch {
|
||||
return data
|
||||
|
@ -638,6 +849,7 @@ export default {
|
|||
}
|
||||
]
|
||||
}
|
||||
this.lockedChapters = new Set()
|
||||
this.checkChapters()
|
||||
},
|
||||
removeAllChaptersClick() {
|
||||
|
@ -679,6 +891,91 @@ export default {
|
|||
this.saving = false
|
||||
})
|
||||
},
|
||||
handleBulkChapterAdd() {
|
||||
const input = this.bulkChapterInput.trim()
|
||||
if (!input) return
|
||||
|
||||
const numberMatch = input.match(/(\d+)/)
|
||||
|
||||
if (numberMatch) {
|
||||
// Extract the base pattern and number, preserving zero-padding
|
||||
const originalNumberString = numberMatch[1]
|
||||
const foundNumber = parseInt(originalNumberString)
|
||||
const numberIndex = numberMatch.index
|
||||
const beforeNumber = input.substring(0, numberIndex)
|
||||
const afterNumber = input.substring(numberIndex + originalNumberString.length)
|
||||
|
||||
this.detectedPattern = {
|
||||
before: beforeNumber,
|
||||
after: afterNumber,
|
||||
startingNumber: foundNumber,
|
||||
originalPadding: originalNumberString.length,
|
||||
hasLeadingZeros: originalNumberString.length > 1 && originalNumberString.startsWith('0')
|
||||
}
|
||||
|
||||
this.bulkChapterCount = 1
|
||||
this.showBulkChapterModal = true
|
||||
} else {
|
||||
this.addSingleChapterFromInput(input)
|
||||
}
|
||||
},
|
||||
addSingleChapterFromInput(title) {
|
||||
// Find the last chapter to determine where to add the new one
|
||||
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
||||
const newStart = lastChapter ? lastChapter.end : 0
|
||||
const newEnd = Math.min(newStart + 300, this.mediaDuration)
|
||||
|
||||
const newChapter = {
|
||||
id: this.newChapters.length,
|
||||
start: newStart,
|
||||
end: newEnd,
|
||||
title: title
|
||||
}
|
||||
|
||||
this.newChapters.push(newChapter)
|
||||
this.bulkChapterInput = ''
|
||||
this.checkChapters()
|
||||
},
|
||||
|
||||
addBulkChapters() {
|
||||
const count = parseInt(this.bulkChapterCount)
|
||||
if (!count || count < 1 || count > 150) {
|
||||
this.$toast.error(this.$strings.ToastBulkChapterInvalidCount)
|
||||
return
|
||||
}
|
||||
|
||||
const { before, after, startingNumber, originalPadding, hasLeadingZeros } = this.detectedPattern
|
||||
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
||||
const baseStart = lastChapter ? lastChapter.start + 1 : 0
|
||||
|
||||
// Add multiple chapters with the detected pattern
|
||||
for (let i = 0; i < count; i++) {
|
||||
const chapterNumber = startingNumber + i
|
||||
let formattedNumber = chapterNumber.toString()
|
||||
|
||||
// Apply zero-padding if the original had leading zeros
|
||||
if (hasLeadingZeros && originalPadding > 1) {
|
||||
formattedNumber = chapterNumber.toString().padStart(originalPadding, '0')
|
||||
}
|
||||
|
||||
const newStart = baseStart + i
|
||||
const newEnd = Math.min(newStart + i + i, this.mediaDuration)
|
||||
|
||||
const newChapter = {
|
||||
id: this.newChapters.length,
|
||||
start: newStart,
|
||||
end: newEnd,
|
||||
title: `${before}${formattedNumber}${after}`
|
||||
}
|
||||
|
||||
this.newChapters.push(newChapter)
|
||||
}
|
||||
|
||||
this.bulkChapterInput = ''
|
||||
this.showBulkChapterModal = false
|
||||
this.detectedPattern = null
|
||||
this.checkChapters()
|
||||
},
|
||||
libraryItemUpdated(libraryItem) {
|
||||
if (libraryItem.id === this.libraryItem.id) {
|
||||
if (!!libraryItem.media.metadata.asin && this.mediaMetadata.asin !== libraryItem.media.metadata.asin) {
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
<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">
|
||||
<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-2/3 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelValue }}</div>
|
||||
<div class="w-28 min-w-28 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelMetaTag }}</div>
|
||||
<div class="grow text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelValue }}</div>
|
||||
</div>
|
||||
<div class="w-full max-h-72 overflow-auto">
|
||||
<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 class="w-1/3 font-semibold">{{ key }}</div>
|
||||
<div class="w-2/3">
|
||||
<div class="w-28 min-w-28 font-semibold">{{ key }}</div>
|
||||
<div class="grow">
|
||||
{{ value }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -45,18 +45,18 @@
|
|||
<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="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-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.LabelStart }}</div>
|
||||
<div class="w-16 min-w-16 text-xs font-semibold uppercase text-gray-200">{{ $strings.LabelEnd }}</div>
|
||||
</div>
|
||||
<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>
|
||||
<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 class="grow font-semibold">{{ chapter.title }}</div>
|
||||
<div class="w-24">
|
||||
<div class="w-16 min-w-16">
|
||||
{{ $secondsToTimestamp(chapter.start) }}
|
||||
</div>
|
||||
<div class="w-24">
|
||||
<div class="w-16 min-w-16">
|
||||
{{ $secondsToTimestamp(chapter.end) }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -356,6 +356,8 @@ export default {
|
|||
|
||||
const encodeOptions = this.$refs.encoderOptionsCard.getEncodingOptions()
|
||||
|
||||
this.encodingOptions = encodeOptions
|
||||
|
||||
const queryParams = new URLSearchParams(encodeOptions)
|
||||
|
||||
this.processing = true
|
||||
|
|
|
@ -53,6 +53,7 @@ export default {
|
|||
else if (pageName === 'sessions') return this.$strings.HeaderListeningSessions
|
||||
else if (pageName === 'stats') return this.$strings.HeaderYourStats
|
||||
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 === 'rss-feeds') return this.$strings.HeaderRSSFeeds
|
||||
else if (pageName === 'email') return this.$strings.HeaderEmail
|
||||
|
|
84
client/pages/config/api-keys/index.vue
Normal file
84
client/pages/config/api-keys/index.vue
Normal file
|
@ -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>
|
|
@ -131,35 +131,26 @@
|
|||
</div>
|
||||
|
||||
<div class="grow py-2">
|
||||
<ui-dropdown :label="$strings.LabelSettingsDateFormat" v-model="newServerSettings.dateFormat" :items="dateFormats" small class="max-w-52" @input="(val) => updateSettingsKey('dateFormat', val)" />
|
||||
<ui-dropdown :label="$strings.LabelSettingsDateFormat" v-model="newServerSettings.dateFormat" :items="dateFormats" small class="max-w-72" @input="(val) => updateSettingsKey('dateFormat', val)" />
|
||||
<p class="text-xs ml-1 text-white/60">{{ $strings.LabelExample }}: {{ dateExample }}</p>
|
||||
</div>
|
||||
|
||||
<div class="grow py-2">
|
||||
<ui-dropdown :label="$strings.LabelSettingsTimeFormat" v-model="newServerSettings.timeFormat" :items="timeFormats" small class="max-w-52" @input="(val) => updateSettingsKey('timeFormat', val)" />
|
||||
<ui-dropdown :label="$strings.LabelSettingsTimeFormat" v-model="newServerSettings.timeFormat" :items="timeFormats" small class="max-w-72" @input="(val) => updateSettingsKey('timeFormat', val)" />
|
||||
<p class="text-xs ml-1 text-white/60">{{ $strings.LabelExample }}: {{ timeExample }}</p>
|
||||
</div>
|
||||
|
||||
<div class="py-2">
|
||||
<ui-dropdown :label="$strings.LabelLanguageDefaultServer" ref="langDropdown" v-model="newServerSettings.language" :items="$languageCodeOptions" small class="max-w-52" @input="updateServerLanguage" />
|
||||
<ui-dropdown :label="$strings.LabelLanguageDefaultServer" ref="langDropdown" v-model="newServerSettings.language" :items="$languageCodeOptions" small class="max-w-72" @input="updateServerLanguage" />
|
||||
</div>
|
||||
|
||||
<!-- old experimental features -->
|
||||
<!-- <div class="pt-4">
|
||||
<h2 class="font-semibold">{{ $strings.HeaderSettingsExperimental }}</h2>
|
||||
<div class="pt-4">
|
||||
<h2 class="font-semibold">{{ $strings.HeaderSettingsSecurity }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-2">
|
||||
<ui-toggle-switch labeledBy="settings-experimental-features" v-model="showExperimentalFeatures" />
|
||||
<ui-tooltip :text="$strings.LabelSettingsExperimentalFeaturesHelp">
|
||||
<p class="pl-4">
|
||||
<span id="settings-experimental-features">{{ $strings.LabelSettingsExperimentalFeatures }}</span>
|
||||
<a :aria-label="$strings.LabelSettingsExperimentalFeaturesHelp" href="https://github.com/advplyr/audiobookshelf/discussions/75" target="_blank">
|
||||
<span class="material-symbols icon-text">info</span>
|
||||
</a>
|
||||
</p>
|
||||
</ui-tooltip>
|
||||
</div> -->
|
||||
<div class="py-2">
|
||||
<ui-multi-select v-model="newServerSettings.allowedOrigins" :items="newServerSettings.allowedOrigins" :label="$strings.LabelCorsAllowed" class="max-w-72" @input="updateCorsOrigins" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</app-settings-content>
|
||||
|
@ -323,6 +314,27 @@ export default {
|
|||
updateServerLanguage(val) {
|
||||
this.updateSettingsKey('language', val)
|
||||
},
|
||||
updateCorsOrigins(val) {
|
||||
const validOrigins = []
|
||||
const invalidOrigins = []
|
||||
|
||||
val.forEach((origin) => {
|
||||
const trimmedOrigin = origin.trim().toLowerCase()
|
||||
try {
|
||||
new URL(trimmedOrigin)
|
||||
validOrigins.push(trimmedOrigin)
|
||||
} catch {
|
||||
invalidOrigins.push(trimmedOrigin)
|
||||
}
|
||||
})
|
||||
|
||||
if (invalidOrigins.length > 0) {
|
||||
this.$toast.error(this.$strings.ToastInvalidUrls)
|
||||
}
|
||||
|
||||
this.newServerSettings.allowedOrigins = validOrigins
|
||||
this.updateSettingsKey('allowedOrigins', validOrigins)
|
||||
},
|
||||
updateSettingsKey(key, val) {
|
||||
if (key === 'scannerDisableWatcher') {
|
||||
this.newServerSettings.scannerDisableWatcher = val
|
||||
|
@ -352,6 +364,7 @@ export default {
|
|||
initServerSettings() {
|
||||
this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {}
|
||||
this.newServerSettings.sortingPrefixes = [...(this.newServerSettings.sortingPrefixes || [])]
|
||||
this.newServerSettings.allowedOrigins = [...(this.newServerSettings.allowedOrigins || [])]
|
||||
this.scannerEnableWatcher = !this.newServerSettings.scannerDisableWatcher
|
||||
|
||||
this.homepageUseBookshelfView = this.newServerSettings.homeBookshelfView != this.$constants.BookshelfView.DETAIL
|
||||
|
|
|
@ -78,10 +78,10 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -6,80 +6,82 @@
|
|||
</div>
|
||||
|
||||
<div v-if="listeningSessions.length" class="block max-w-full relative">
|
||||
<table class="userSessionsTable">
|
||||
<tr class="bg-primary/40">
|
||||
<th class="w-6 min-w-6 text-left hidden md:table-cell h-11">
|
||||
<ui-checkbox v-model="isAllSelected" :partial="numSelected > 0 && !isAllSelected" small checkbox-bg="bg" />
|
||||
</th>
|
||||
<th v-if="numSelected" class="grow text-left" :colspan="7">
|
||||
<div class="flex items-center">
|
||||
<p>{{ $getString('MessageSelected', [numSelected]) }}</p>
|
||||
<div class="grow" />
|
||||
<ui-btn small color="bg-error" :loading="deletingSessions" @click.stop="removeSessionsClick">{{ $strings.ButtonRemove }}</ui-btn>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="grow sm:grow-0 sm:w-48 sm:max-w-48 text-left group cursor-pointer" @click.stop="sortColumn('displayTitle')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelItem }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('displayTitle') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="w-20 min-w-20 text-left hidden md:table-cell">{{ $strings.LabelUser }}</th>
|
||||
<th v-if="!numSelected" class="w-26 min-w-26 text-left hidden md:table-cell group cursor-pointer" @click.stop="sortColumn('playMethod')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelPlayMethod }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('playMethod') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
|
||||
<th v-if="!numSelected" class="w-24 min-w-24 sm:w-32 sm:min-w-32 group cursor-pointer" @click.stop="sortColumn('timeListening')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelTimeListened }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('timeListening') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="w-24 min-w-24 group cursor-pointer" @click.stop="sortColumn('currentTime')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelLastTime }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('currentTime') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="grow hidden sm:table-cell cursor-pointer group" @click.stop="sortColumn('updatedAt')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelLastUpdate }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('updatedAt') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="userSessionsTable">
|
||||
<tr class="bg-primary/40">
|
||||
<th class="w-6 min-w-6 text-left hidden md:table-cell h-11">
|
||||
<ui-checkbox v-model="isAllSelected" :partial="numSelected > 0 && !isAllSelected" small checkbox-bg="bg" />
|
||||
</th>
|
||||
<th v-if="numSelected" class="grow text-left" :colspan="7">
|
||||
<div class="flex items-center">
|
||||
<p>{{ $getString('MessageSelected', [numSelected]) }}</p>
|
||||
<div class="grow" />
|
||||
<ui-btn small color="bg-error" :loading="deletingSessions" @click.stop="removeSessionsClick">{{ $strings.ButtonRemove }}</ui-btn>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="grow sm:grow-0 sm:w-48 sm:max-w-48 text-left group cursor-pointer" @click.stop="sortColumn('displayTitle')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelItem }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('displayTitle') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="w-20 min-w-20 text-left hidden md:table-cell">{{ $strings.LabelUser }}</th>
|
||||
<th v-if="!numSelected" class="w-26 min-w-26 text-left hidden md:table-cell group cursor-pointer" @click.stop="sortColumn('playMethod')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelPlayMethod }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('playMethod') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
|
||||
<th v-if="!numSelected" class="w-24 min-w-24 sm:w-32 sm:min-w-32 group cursor-pointer" @click.stop="sortColumn('timeListening')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelTimeListened }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('timeListening') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="w-24 min-w-24 group cursor-pointer" @click.stop="sortColumn('currentTime')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelLastTime }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('currentTime') }" class="material-symbols text-base pl-px hidden sm:inline-block">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
<th v-if="!numSelected" class="grow hidden sm:table-cell cursor-pointer group" @click.stop="sortColumn('updatedAt')">
|
||||
<div class="inline-flex items-center">
|
||||
{{ $strings.LabelLastUpdate }} <span :class="{ 'opacity-0 group-hover:opacity-30': !isSortSelected('updatedAt') }" class="material-symbols text-base pl-px">{{ sortDesc ? 'arrow_drop_down' : 'arrow_drop_up' }}</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr v-for="session in listeningSessions" :key="session.id" :class="{ selected: session.selected }" class="cursor-pointer" @click="clickSessionRow(session)">
|
||||
<td class="hidden md:table-cell py-1 max-w-6 relative">
|
||||
<ui-checkbox v-model="session.selected" small checkbox-bg="bg" />
|
||||
<!-- overlay of the checkbox so that the entire box is clickable -->
|
||||
<div class="absolute inset-0 w-full h-full" @click.stop="session.selected = !session.selected" />
|
||||
</td>
|
||||
<td class="py-1 grow sm:grow-0 sm:w-48 sm:max-w-48">
|
||||
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
|
||||
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
|
||||
</td>
|
||||
<td class="hidden md:table-cell w-20 min-w-20">
|
||||
<p v-if="filteredUserUsername" class="text-xs">{{ filteredUserUsername }}</p>
|
||||
<p v-else class="text-xs">{{ session.user ? session.user.username : 'N/A' }}</p>
|
||||
</td>
|
||||
<td class="hidden md:table-cell w-26 min-w-26">
|
||||
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
|
||||
</td>
|
||||
<td class="hidden sm:table-cell max-w-32 min-w-32">
|
||||
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
|
||||
</td>
|
||||
<td class="text-center w-24 min-w-24 sm:w-32 sm:min-w-32">
|
||||
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
|
||||
</td>
|
||||
<td class="text-center hover:underline w-24 min-w-24" @click.stop="clickCurrentTime(session)">
|
||||
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
|
||||
</td>
|
||||
<td class="text-center hidden sm:table-cell">
|
||||
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
|
||||
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
|
||||
</ui-tooltip>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<tr v-for="session in listeningSessions" :key="session.id" :class="{ selected: session.selected }" class="cursor-pointer" @click="clickSessionRow(session)">
|
||||
<td class="hidden md:table-cell py-1 max-w-6 relative">
|
||||
<ui-checkbox v-model="session.selected" small checkbox-bg="bg" />
|
||||
<!-- overlay of the checkbox so that the entire box is clickable -->
|
||||
<div class="absolute inset-0 w-full h-full" @click.stop="session.selected = !session.selected" />
|
||||
</td>
|
||||
<td class="py-1 grow sm:grow-0 sm:w-48 sm:max-w-48">
|
||||
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
|
||||
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
|
||||
</td>
|
||||
<td class="hidden md:table-cell w-20 min-w-20">
|
||||
<p v-if="filteredUserUsername" class="text-xs">{{ filteredUserUsername }}</p>
|
||||
<p v-else class="text-xs">{{ session.user ? session.user.username : 'N/A' }}</p>
|
||||
</td>
|
||||
<td class="hidden md:table-cell w-26 min-w-26">
|
||||
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
|
||||
</td>
|
||||
<td class="hidden sm:table-cell max-w-32 min-w-32">
|
||||
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
|
||||
</td>
|
||||
<td class="text-center w-24 min-w-24 sm:w-32 sm:min-w-32">
|
||||
<p class="text-xs font-mono">{{ $elapsedPrettyLocalized(session.timeListening) }}</p>
|
||||
</td>
|
||||
<td class="text-center hover:underline w-24 min-w-24" @click.stop="clickCurrentTime(session)">
|
||||
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
|
||||
</td>
|
||||
<td class="text-center hidden sm:table-cell">
|
||||
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
|
||||
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
|
||||
</ui-tooltip>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- table bottom options -->
|
||||
<div class="flex items-center my-2">
|
||||
<div class="grow" />
|
||||
|
@ -250,10 +252,10 @@ export default {
|
|||
return user?.username || null
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
},
|
||||
numSelected() {
|
||||
return this.listeningSessions.filter((s) => s.selected).length
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
<widgets-online-indicator :value="!!userOnline" />
|
||||
<h1 class="text-xl pl-2">{{ username }}</h1>
|
||||
</div>
|
||||
<div v-if="userToken" class="flex text-xs mt-4">
|
||||
<ui-text-input-with-label :label="$strings.LabelApiToken" :value="userToken" readonly show-copy />
|
||||
<div v-if="legacyToken" class="text-xs space-y-2 mt-4">
|
||||
<ui-text-input-with-label label="Legacy API Token" :value="legacyToken" readonly show-copy />
|
||||
|
||||
<p class="text-warning" v-html="$strings.MessageAuthenticationLegacyTokenWarning" />
|
||||
</div>
|
||||
<div class="w-full h-px bg-white/10 my-2" />
|
||||
<div class="py-2">
|
||||
|
@ -100,9 +102,12 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
userToken() {
|
||||
legacyToken() {
|
||||
return this.user.token
|
||||
},
|
||||
userToken() {
|
||||
return this.user.accessToken
|
||||
},
|
||||
bookCoverAspectRatio() {
|
||||
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
||||
},
|
||||
|
@ -129,10 +134,10 @@ export default {
|
|||
return this.listeningSessions.sessions[0]
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -19,39 +19,41 @@
|
|||
<div class="py-2">
|
||||
<h1 class="text-lg mb-2 text-white/90 px-2 sm:px-0">{{ $strings.HeaderListeningSessions }}</h1>
|
||||
<div v-if="listeningSessions.length">
|
||||
<table class="userSessionsTable">
|
||||
<tr class="bg-primary/40">
|
||||
<th class="w-48 min-w-48 text-left">{{ $strings.LabelItem }}</th>
|
||||
<th class="w-32 min-w-32 text-left hidden md:table-cell">{{ $strings.LabelPlayMethod }}</th>
|
||||
<th class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
|
||||
<th class="w-32 min-w-32">{{ $strings.LabelTimeListened }}</th>
|
||||
<th class="w-16 min-w-16">{{ $strings.LabelLastTime }}</th>
|
||||
<th class="grow hidden sm:table-cell">{{ $strings.LabelLastUpdate }}</th>
|
||||
</tr>
|
||||
<tr v-for="session in listeningSessions" :key="session.id" class="cursor-pointer" @click="showSession(session)">
|
||||
<td class="py-1 max-w-48">
|
||||
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
|
||||
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
|
||||
</td>
|
||||
<td class="hidden md:table-cell">
|
||||
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
|
||||
</td>
|
||||
<td class="hidden sm:table-cell min-w-32 max-w-32">
|
||||
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
|
||||
</td>
|
||||
<td class="text-center hover:underline" @click.stop="clickCurrentTime(session)">
|
||||
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
|
||||
</td>
|
||||
<td class="text-center hidden sm:table-cell">
|
||||
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
|
||||
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
|
||||
</ui-tooltip>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="userSessionsTable">
|
||||
<tr class="bg-primary/40">
|
||||
<th class="w-48 min-w-48 text-left">{{ $strings.LabelItem }}</th>
|
||||
<th class="w-32 min-w-32 text-left hidden md:table-cell">{{ $strings.LabelPlayMethod }}</th>
|
||||
<th class="w-32 min-w-32 text-left hidden sm:table-cell">{{ $strings.LabelDeviceInfo }}</th>
|
||||
<th class="w-32 min-w-32">{{ $strings.LabelTimeListened }}</th>
|
||||
<th class="w-16 min-w-16">{{ $strings.LabelLastTime }}</th>
|
||||
<th class="grow hidden sm:table-cell">{{ $strings.LabelLastUpdate }}</th>
|
||||
</tr>
|
||||
<tr v-for="session in listeningSessions" :key="session.id" class="cursor-pointer" @click="showSession(session)">
|
||||
<td class="py-1 max-w-48">
|
||||
<p class="text-xs text-gray-200 truncate">{{ session.displayTitle }}</p>
|
||||
<p class="text-xs text-gray-400 truncate">{{ session.displayAuthor }}</p>
|
||||
</td>
|
||||
<td class="hidden md:table-cell">
|
||||
<p class="text-xs">{{ getPlayMethodName(session.playMethod) }}</p>
|
||||
</td>
|
||||
<td class="hidden sm:table-cell min-w-32 max-w-32">
|
||||
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<p class="text-xs font-mono">{{ $elapsedPrettyLocalized(session.timeListening) }}</p>
|
||||
</td>
|
||||
<td class="text-center hover:underline" @click.stop="clickCurrentTime(session)">
|
||||
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
|
||||
</td>
|
||||
<td class="text-center hidden sm:table-cell">
|
||||
<ui-tooltip v-if="session.updatedAt" direction="top" :text="$formatDatetime(session.updatedAt, dateFormat, timeFormat)">
|
||||
<p class="text-xs text-gray-200">{{ $dateDistanceFromNow(session.updatedAt) }}</p>
|
||||
</ui-tooltip>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="flex items-center justify-end py-1">
|
||||
<ui-icon-btn icon="arrow_back_ios_new" :size="7" icon-font-size="1rem" class="mx-1" :disabled="currentPage === 0" @click="prevPage" />
|
||||
<p class="text-sm mx-1">{{ $getString('LabelPaginationPageXOfY', [currentPage + 1, numPages]) }}</p>
|
||||
|
@ -98,10 +100,10 @@ export default {
|
|||
return this.$store.getters['users/getIsUserOnline'](this.user.id)
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
timeFormat() {
|
||||
return this.$store.state.serverSettings.timeFormat
|
||||
return this.$store.getters['getServerSetting']('timeFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -193,7 +193,7 @@ export default {
|
|||
return `${process.env.serverUrl}/api/items/${this.libraryItemId}/download?token=${this.userToken}`
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
},
|
||||
userIsAdminOrUp() {
|
||||
return this.$store.getters['user/getIsAdminOrUp']
|
||||
|
@ -819,6 +819,17 @@ export default {
|
|||
-webkit-line-clamp: 4;
|
||||
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 {
|
||||
-webkit-line-clamp: unset;
|
||||
max-height: 999rem;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</tr>
|
||||
<tr v-for="narrator in narrators" :key="narrator.id">
|
||||
<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">
|
||||
<ui-text-input v-model="newNarratorName" />
|
||||
</form>
|
||||
|
|
|
@ -141,7 +141,7 @@ export default {
|
|||
return episodeIds
|
||||
},
|
||||
dateFormat() {
|
||||
return this.$store.state.serverSettings.dateFormat
|
||||
return this.$store.getters['getServerSetting']('dateFormat')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -22,6 +22,7 @@ export default {
|
|||
})
|
||||
results = {
|
||||
podcasts: results?.podcast || [],
|
||||
episodes: results?.episodes || [],
|
||||
books: results?.book || [],
|
||||
authors: results?.authors || [],
|
||||
series: results?.series || [],
|
||||
|
@ -61,6 +62,7 @@ export default {
|
|||
})
|
||||
this.results = {
|
||||
podcasts: results?.podcast || [],
|
||||
episodes: results?.episodes || [],
|
||||
books: results?.book || [],
|
||||
authors: results?.authors || [],
|
||||
series: results?.series || [],
|
||||
|
|
|
@ -40,6 +40,15 @@
|
|||
|
||||
<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">
|
||||
<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" />
|
||||
|
@ -85,7 +94,10 @@ export default {
|
|||
MetadataPath: '',
|
||||
login_local: true,
|
||||
login_openid: false,
|
||||
authFormData: null
|
||||
authFormData: null,
|
||||
// New JWT auth system re-login flags
|
||||
showNewAuthSystemMessage: false,
|
||||
showNewAuthSystemAdminMessage: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -177,13 +189,19 @@ export default {
|
|||
require('@/plugins/chromecast.js').default(this)
|
||||
}
|
||||
|
||||
this.$store.commit('libraries/setCurrentLibrary', userDefaultLibraryId)
|
||||
this.$store.commit('libraries/setCurrentLibrary', { id: userDefaultLibraryId })
|
||||
this.$store.commit('user/setUser', user)
|
||||
// Access token only returned from login, not authorize
|
||||
if (user.accessToken) {
|
||||
this.$store.commit('user/setAccessToken', user.accessToken)
|
||||
}
|
||||
|
||||
this.$store.dispatch('user/loadUserSettings')
|
||||
},
|
||||
async submitForm() {
|
||||
this.error = null
|
||||
this.showNewAuthSystemMessage = false
|
||||
this.showNewAuthSystemAdminMessage = false
|
||||
this.processing = true
|
||||
|
||||
const payload = {
|
||||
|
@ -210,6 +228,8 @@ export default {
|
|||
|
||||
this.processing = true
|
||||
|
||||
this.$store.commit('user/setAccessToken', token)
|
||||
|
||||
return this.$axios
|
||||
.$post('/api/authorize', null, {
|
||||
headers: {
|
||||
|
@ -217,15 +237,25 @@ export default {
|
|||
}
|
||||
})
|
||||
.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.processing = false
|
||||
return true
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Authorize error', error)
|
||||
this.processing = false
|
||||
return false
|
||||
})
|
||||
.finally(() => {
|
||||
this.processing = false
|
||||
})
|
||||
},
|
||||
checkStatus() {
|
||||
this.processing = true
|
||||
|
@ -280,8 +310,9 @@ export default {
|
|||
}
|
||||
},
|
||||
async mounted() {
|
||||
if (this.$route.query?.setToken) {
|
||||
localStorage.setItem('token', this.$route.query.setToken)
|
||||
// Token passed as query parameter after successful oidc login
|
||||
if (this.$route.query?.accessToken) {
|
||||
localStorage.setItem('token', this.$route.query.accessToken)
|
||||
}
|
||||
if (localStorage.getItem('token')) {
|
||||
if (await this.checkAuth()) return // if valid user no need to check status
|
||||
|
|
|
@ -359,15 +359,14 @@ export default {
|
|||
// Check if path already exists before starting upload
|
||||
// uploading fails if path already exists
|
||||
for (const item of items) {
|
||||
const filepath = Path.join(this.selectedFolder.fullPath, item.directory)
|
||||
const exists = await this.$axios
|
||||
.$post(`/api/filesystem/pathexists`, { filepath, directory: item.directory, folderPath: this.selectedFolder.fullPath })
|
||||
.$post(`/api/filesystem/pathexists`, { directory: item.directory, folderPath: this.selectedFolder.fullPath })
|
||||
.then((data) => {
|
||||
if (data.exists) {
|
||||
if (data.libraryItemTitle) {
|
||||
this.$toast.error(this.$getString('ToastUploaderItemExistsInSubdirectoryError', [data.libraryItemTitle]))
|
||||
} else {
|
||||
this.$toast.error(this.$getString('ToastUploaderFilepathExistsError', [filepath]))
|
||||
this.$toast.error(this.$getString('ToastUploaderFilepathExistsError', [Path.join(this.selectedFolder.fullPath, item.directory)]))
|
||||
}
|
||||
}
|
||||
return data.exists
|
||||
|
|
|
@ -1,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) => {
|
||||
if (!config.url) {
|
||||
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:')) {
|
||||
return
|
||||
}
|
||||
const bearerToken = store.state.user.user?.token || null
|
||||
const bearerToken = store.getters['user/getToken']
|
||||
if (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 message = error.response ? error.response.data || 'Unknown Error' : 'Unknown Error'
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { supplant } from './utils'
|
|||
const defaultCode = 'en-us'
|
||||
|
||||
const languageCodeMap = {
|
||||
ar: { label: 'عربي', dateFnsLocale: 'ar' },
|
||||
bg: { label: 'Български', dateFnsLocale: 'bg' },
|
||||
bn: { label: 'বাংলা', dateFnsLocale: 'bn' },
|
||||
ca: { label: 'Català', dateFnsLocale: 'ca' },
|
||||
|
|
|
@ -37,6 +37,48 @@ Vue.prototype.$elapsedPretty = (seconds, useFullNames = false, useMilliseconds =
|
|||
return `${hours} ${useFullNames ? `hour${hours === 1 ? '' : 's'}` : 'hr'} ${minutes} ${useFullNames ? `minute${minutes === 1 ? '' : 's'}` : 'min'}`
|
||||
}
|
||||
|
||||
Vue.prototype.$elapsedPrettyLocalized = (seconds, useFullNames = false, useMilliseconds = false) => {
|
||||
if (isNaN(seconds) || seconds === null) return ''
|
||||
|
||||
try {
|
||||
const df = new Intl.DurationFormat(Vue.prototype.$languageCodes.current, {
|
||||
style: useFullNames ? 'long' : 'short'
|
||||
})
|
||||
|
||||
const duration = {}
|
||||
|
||||
if (seconds < 60) {
|
||||
if (useMilliseconds && seconds < 1) {
|
||||
duration.milliseconds = Math.floor(seconds * 1000)
|
||||
} else {
|
||||
duration.seconds = Math.floor(seconds)
|
||||
}
|
||||
} else if (seconds < 3600) {
|
||||
// 1 hour
|
||||
duration.minutes = Math.floor(seconds / 60)
|
||||
} else if (seconds < 86400) {
|
||||
// 1 day
|
||||
duration.hours = Math.floor(seconds / 3600)
|
||||
const minutes = Math.floor((seconds % 3600) / 60)
|
||||
if (minutes > 0) {
|
||||
duration.minutes = minutes
|
||||
}
|
||||
} else {
|
||||
duration.days = Math.floor(seconds / 86400)
|
||||
const hours = Math.floor((seconds % 86400) / 3600)
|
||||
if (hours > 0) {
|
||||
duration.hours = hours
|
||||
}
|
||||
}
|
||||
|
||||
return df.format(duration)
|
||||
} catch (error) {
|
||||
// Handle not supported
|
||||
console.warn('Intl.DurationFormat not supported, not localizing duration')
|
||||
return Vue.prototype.$elapsedPretty(seconds, useFullNames, useMilliseconds)
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$secondsToTimestamp = (seconds, includeMs = false, alwaysIncludeHours = false) => {
|
||||
if (!seconds) {
|
||||
return alwaysIncludeHours ? '00:00:00' : '0:00'
|
||||
|
|
|
@ -133,7 +133,7 @@ export const actions = {
|
|||
commit('setNumUserPlaylists', numUserPlaylists)
|
||||
commit('scanners/setCustomMetadataProviders', customMetadataProviders, { root: true })
|
||||
|
||||
commit('setCurrentLibrary', libraryId)
|
||||
commit('setCurrentLibrary', { id: libraryId })
|
||||
return data
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -182,8 +182,8 @@ export const mutations = {
|
|||
setLibraryIssues(state, val) {
|
||||
state.issues = val
|
||||
},
|
||||
setCurrentLibrary(state, val) {
|
||||
state.currentLibraryId = val
|
||||
setCurrentLibrary(state, { id }) {
|
||||
state.currentLibraryId = id
|
||||
},
|
||||
set(state, libraries) {
|
||||
state.libraries = libraries
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export const state = () => ({
|
||||
user: null,
|
||||
accessToken: null,
|
||||
settings: {
|
||||
orderBy: 'media.metadata.title',
|
||||
orderDesc: false,
|
||||
|
@ -25,19 +26,19 @@ export const getters = {
|
|||
getIsRoot: (state) => state.user && state.user.type === 'root',
|
||||
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
|
||||
getToken: (state) => {
|
||||
return state.user?.token || null
|
||||
return state.accessToken || null
|
||||
},
|
||||
getUserMediaProgress:
|
||||
(state) =>
|
||||
(libraryItemId, episodeId = null) => {
|
||||
if (!state.user.mediaProgress) return null
|
||||
if (!state.user?.mediaProgress) return null
|
||||
return state.user.mediaProgress.find((li) => {
|
||||
if (episodeId && li.episodeId !== episodeId) return false
|
||||
return li.libraryItemId == libraryItemId
|
||||
})
|
||||
},
|
||||
getUserBookmarksForItem: (state) => (libraryItemId) => {
|
||||
if (!state.user.bookmarks) return []
|
||||
if (!state.user?.bookmarks) return []
|
||||
return state.user.bookmarks.filter((bm) => bm.libraryItemId === libraryItemId)
|
||||
},
|
||||
getUserSetting: (state) => (key) => {
|
||||
|
@ -58,6 +59,9 @@ export const getters = {
|
|||
getUserCanAccessAllLibraries: (state) => {
|
||||
return !!state.user?.permissions?.accessAllLibraries
|
||||
},
|
||||
getUserCanAccessExplicitContent: (state) => {
|
||||
return !!state.user?.permissions?.accessExplicitContent
|
||||
},
|
||||
getLibrariesAccessible: (state, getters) => {
|
||||
if (!state.user) return []
|
||||
if (getters.getUserCanAccessAllLibraries) return []
|
||||
|
@ -88,7 +92,7 @@ export const actions = {
|
|||
if (state.settings.orderBy == 'media.duration') {
|
||||
settingsUpdate.orderBy = 'media.numTracks'
|
||||
}
|
||||
if (state.settings.orderBy == 'media.metadata.publishedYear') {
|
||||
if (state.settings.orderBy == 'media.metadata.publishedYear' || state.settings.orderBy == 'progress') {
|
||||
settingsUpdate.orderBy = 'media.metadata.title'
|
||||
}
|
||||
const invalidFilters = ['series', 'authors', 'narrators', 'publishers', 'publishedDecades', 'languages', 'progress', 'issues', 'ebooks', 'abridged']
|
||||
|
@ -142,21 +146,41 @@ export const actions = {
|
|||
} catch (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('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 = {
|
||||
setUser(state, user) {
|
||||
state.user = user
|
||||
if (user) {
|
||||
if (user.token) localStorage.setItem('token', user.token)
|
||||
} else {
|
||||
localStorage.removeItem('token')
|
||||
}
|
||||
},
|
||||
setUserToken(state, token) {
|
||||
state.user.token = token
|
||||
localStorage.setItem('token', token)
|
||||
setAccessToken(state, token) {
|
||||
if (!token) {
|
||||
localStorage.removeItem('token')
|
||||
state.accessToken = null
|
||||
} else {
|
||||
state.accessToken = token
|
||||
localStorage.setItem('token', token)
|
||||
}
|
||||
},
|
||||
updateMediaProgress(state, { id, data }) {
|
||||
if (!state.user) return
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Дадаць",
|
||||
"ButtonAddApiKey": "Дадаць API-ключ",
|
||||
"ButtonAddChapters": "Дадаць раздзелы",
|
||||
"ButtonAddDevice": "Дадаць прыладу",
|
||||
"ButtonAddLibrary": "Дадаць бібліятэку",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Выбраць тэчку",
|
||||
"ButtonChooseFiles": "Выбраць файлы",
|
||||
"ButtonClearFilter": "Ачысціць фільтр",
|
||||
"ButtonClose": "Закрыць",
|
||||
"ButtonCloseFeed": "Закрыць стужку",
|
||||
"ButtonCloseSession": "Закрыць адкрыты сеанс",
|
||||
"ButtonCollections": "Калекцыі",
|
||||
|
@ -69,7 +71,7 @@
|
|||
"ButtonQueueAddItem": "Дадаць у чаргу",
|
||||
"ButtonQueueRemoveItem": "Выдаліць з чаргі",
|
||||
"ButtonQuickEmbed": "Хуткае ўбудаванне",
|
||||
"ButtonQuickEmbedMetadata": "Хуткае ўбудаванне метаданых",
|
||||
"ButtonQuickEmbedMetadata": "Хуткае ўбудаванне метададзеных",
|
||||
"ButtonQuickMatch": "Хуткі пошук",
|
||||
"ButtonReScan": "Паўторнае сканаванне",
|
||||
"ButtonRead": "Чытаць",
|
||||
|
@ -98,8 +100,9 @@
|
|||
"ButtonSetChaptersFromTracks": "Усталяваць раздзелы з трэкаў",
|
||||
"ButtonShare": "Падзяліцца",
|
||||
"ButtonShiftTimes": "Карэкцыя часу",
|
||||
"ButtonShow": "Паказаць",
|
||||
"ButtonStartM4BEncode": "Пачаць кадзіраванне ў M4B",
|
||||
"ButtonStartMetadataEmbed": "Пачаць убудаванне метаданых",
|
||||
"ButtonStartMetadataEmbed": "Пачаць убудаванне метададзеных",
|
||||
"ButtonStats": "Статыстыка",
|
||||
"ButtonSubmit": "Адправіць",
|
||||
"ButtonTest": "Тэст",
|
||||
|
@ -107,7 +110,7 @@
|
|||
"ButtonUpload": "Загрузіць",
|
||||
"ButtonUploadBackup": "Загрузіць рэзервовую копію",
|
||||
"ButtonUploadCover": "Загрузіць вокладку",
|
||||
"ButtonUploadOPMLFile": "Загрузіць OPML файл",
|
||||
"ButtonUploadOPMLFile": "Загрузіць файл OPML",
|
||||
"ButtonUserDelete": "Выдаліць карыстальніка {0}",
|
||||
"ButtonUserEdit": "Рэдагаваць карыстальніка {0}",
|
||||
"ButtonViewAll": "Прагледзець усе",
|
||||
|
@ -116,8 +119,9 @@
|
|||
"ErrorUploadFetchMetadataNoResults": "Не ўдалося атрымаць метададзеныя – паспрабуйце абнавіць назву і/або аўтара",
|
||||
"ErrorUploadLacksTitle": "Павінна быць назва",
|
||||
"HeaderAccount": "Уліковы запіс",
|
||||
"HeaderAddCustomMetadataProvider": "Дадаць карыстальніцкага пастаўшчыка метаданных",
|
||||
"HeaderAddCustomMetadataProvider": "Дадаць карыстальніцкага пастаўшчыка метададзенных",
|
||||
"HeaderAdvanced": "Дадаткова",
|
||||
"HeaderApiKeys": "API-ключы",
|
||||
"HeaderAppriseNotificationSettings": "Налады апавяшчэнняў Apprise",
|
||||
"HeaderAudioTracks": "Аўдыядарожкі",
|
||||
"HeaderAudiobookTools": "Сродкі кіравання файламі аўдыякніг",
|
||||
|
@ -157,9 +161,11 @@
|
|||
"HeaderManageGenres": "Кіраванне жанрамі",
|
||||
"HeaderManageTags": "Кіраванне тэгамі",
|
||||
"HeaderMapDetails": "Падрабязнасці адлюстравання",
|
||||
"HeaderMatch": "Супадзенне",
|
||||
"HeaderMetadataOrderOfPrecedence": "Парадак прыярытэтнасці метададзеных",
|
||||
"HeaderMetadataToEmbed": "Метададзеныя для ўбудавання",
|
||||
"HeaderNewAccount": "Новы ўліковы запіс",
|
||||
"HeaderNewApiKey": "Новы API-ключ",
|
||||
"HeaderNewLibrary": "Новая бібліятэка",
|
||||
"HeaderNotificationCreate": "Стварыць апавяшчэнне",
|
||||
"HeaderNotificationUpdate": "Абнавіць апавяшчэнне",
|
||||
|
@ -175,9 +181,10 @@
|
|||
"HeaderPlaylist": "Спіс прайгравання",
|
||||
"HeaderPlaylistItems": "Элементы спіса прайгравання",
|
||||
"HeaderPodcastsToAdd": "Падкасты для дадання",
|
||||
"HeaderPresets": "Прадустаноўкі",
|
||||
"HeaderPreviewCover": "Прадпрагляд вокладкі",
|
||||
"HeaderRSSFeedGeneral": "Падрабязнасці RSS",
|
||||
"HeaderRSSFeedIsOpen": "RSS-стужка адкрыта",
|
||||
"HeaderRSSFeedIsOpen": "RSS-стужка адкрытая",
|
||||
"HeaderRSSFeeds": "RSS-стужкі",
|
||||
"HeaderRemoveEpisode": "Выдаліць эпізод",
|
||||
"HeaderRemoveEpisodes": "Выдаліць {0} эпізодаў",
|
||||
|
@ -203,6 +210,7 @@
|
|||
"HeaderTableOfContents": "Змест",
|
||||
"HeaderTools": "Інструменты",
|
||||
"HeaderUpdateAccount": "Абнавіць уліковы запіс",
|
||||
"HeaderUpdateApiKey": "Абнавіць API-ключ",
|
||||
"HeaderUpdateAuthor": "Абнавіць аўтара",
|
||||
"HeaderUpdateDetails": "Абнавіць падрабязнасці",
|
||||
"HeaderUpdateLibrary": "Абнавіць бібліятэку",
|
||||
|
@ -227,10 +235,15 @@
|
|||
"LabelAddedDate": "Дададзена {0}",
|
||||
"LabelAdminUsersOnly": "Толькі для адміністратараў",
|
||||
"LabelAll": "Усе",
|
||||
"LabelAllEpisodesDownloaded": "Усе эпізоды спампаваныя",
|
||||
"LabelAllUsers": "Усе карыстальнікі",
|
||||
"LabelAllUsersExcludingGuests": "Усе карыстальнікі, акрамя гасцей",
|
||||
"LabelAllUsersIncludingGuests": "Усе карыстальнікі, уключаючы гасцей",
|
||||
"LabelAlreadyInYourLibrary": "Ужо ў вашай бібліятэцы",
|
||||
"LabelApiKeyCreated": "API-ключ \"{0}\" паспяхова створаны.",
|
||||
"LabelApiKeyCreatedDescription": "Пераканайцеся, што вы скапіявалі API-ключ зараз, бо паўторна яго ўбачыць не атрымаецца.",
|
||||
"LabelApiKeyUser": "Дзейнічаць ад імя карыстальніка",
|
||||
"LabelApiKeyUserDescription": "Гэты API-ключ будзе мець тыя ж правы, што і карыстальнік, ад імя якога ён дзейнічае. У журналах гэта будзе выглядаць так, быццам запыт робіць сам карыстальнік.",
|
||||
"LabelApiToken": "Токен API",
|
||||
"LabelAppend": "Дадаць",
|
||||
"LabelAudioBitrate": "Бітрэйт аўдыё (напрыклад, 128к)",
|
||||
|
@ -242,39 +255,108 @@
|
|||
"LabelAuthors": "Аўтары",
|
||||
"LabelAutoDownloadEpisodes": "Аўтаматычнае спампаванне эпізодаў",
|
||||
"LabelAutoFetchMetadata": "Аўтаматычнае атрыманне метададзеных",
|
||||
"LabelAutoFetchMetadataHelp": "Атрыманне звестак пра назву, аўтара і серыю для падыходнага фарматавання перад загрузкай. Далей можа быць неабходна дапоўніць метададзеныя.",
|
||||
"LabelAutoLaunch": "Аўтазапуск",
|
||||
"LabelAutoLaunchDescription": "Аўтаматычна перанакіроўваць да пастаўшчыка аўтэнтыфікацыі пры переходзе на старонку ўваходу (ручное пераключэнне праз шлях <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Аўтарэгістрацыя",
|
||||
"LabelAutoRegisterDescription": "Аўтаматычна ствараць новых карыстальнікаў пасля ўваходу ў сістэму",
|
||||
"LabelBackToUser": "Вярнуцца да карыстальніка",
|
||||
"LabelBackupAudioFiles": "Рэзервовае капіраванне аўдыёфайлаў",
|
||||
"LabelBackupLocation": "Месцазнаходжанне рэзервовых копій",
|
||||
"LabelBackupsEnableAutomaticBackups": "Аўтаматычнае рэзервовае капіраванне",
|
||||
"LabelBackupsEnableAutomaticBackupsHelp": "Рэзервовыя копіі захаваныя ў /metadata/backups",
|
||||
"LabelBackupsMaxBackupSize": "Максімальны памер рэзервовай копіі (у ГБ) (0 — неабмежавана)",
|
||||
"LabelBackupsMaxBackupSizeHelp": "Для таго, каб пазбегнуць няправільных налад, рэзервовыя копіі не будуць створаны, калі іх памер будзе больш за дапушчальны.",
|
||||
"LabelBackupsNumberToKeep": "Колькасць захаваных рэзервовых копій",
|
||||
"LabelBackupsNumberToKeepHelp": "Адначасова будзе выдаляцца толькі 1 рэзервовая копія, таму, калі ў вас іх больш, вам варта выдаліць іх уручную.",
|
||||
"LabelBitrate": "Бітрэйт",
|
||||
"LabelBonus": "Бонус",
|
||||
"LabelBooks": "Кнігі",
|
||||
"LabelButtonText": "Тэкст кнопкі",
|
||||
"LabelByAuthor": "ад {0}",
|
||||
"LabelChangePassword": "Змяніць пароль",
|
||||
"LabelChannels": "Каналы",
|
||||
"LabelChapterCount": "{0} раздзелаў",
|
||||
"LabelChapterTitle": "Назва раздзела",
|
||||
"LabelChapters": "Раздзелы",
|
||||
"LabelChaptersFound": "раздзелаў знойдзена",
|
||||
"LabelClickForMoreInfo": "Націсніце для больш падрабязнай інфармацыі",
|
||||
"LabelClickToUseCurrentValue": "Націсніце, каб выкарыстоўваць бягучае значэнне",
|
||||
"LabelClosePlayer": "Зачыніць прайгравальнік",
|
||||
"LabelCodec": "Кодэк",
|
||||
"LabelCollapseSeries": "Згарнуць серыі",
|
||||
"LabelCollapseSubSeries": "Згарнуць падсерыі",
|
||||
"LabelCollection": "Калекцыя",
|
||||
"LabelCollections": "Калекцыі",
|
||||
"LabelComplete": "Завершана",
|
||||
"LabelConfirmPassword": "Пацвердзіце пароль",
|
||||
"LabelContinueListening": "Працягваць слухаць",
|
||||
"LabelContinueReading": "Працягнуць чытанне",
|
||||
"LabelContinueSeries": "Працягнуць серыі",
|
||||
"LabelCover": "Вокладка",
|
||||
"LabelCoverImageURL": "URL выявы вокладкі",
|
||||
"LabelCoverProvider": "Крыніца вокладак",
|
||||
"LabelCreatedAt": "Дата стварэння",
|
||||
"LabelCronExpression": "Запіс Cron",
|
||||
"LabelCurrent": "Бягучы",
|
||||
"LabelCurrently": "Бягучы:",
|
||||
"LabelCustomCronExpression": "Уласны запіс Cron:",
|
||||
"LabelDatetime": "Дата і час",
|
||||
"LabelDays": "Дзён",
|
||||
"LabelDeleteFromFileSystemCheckbox": "Выдаліць з файлавай сістэмы (зніміце галачку, каб выдаліць толькі з базы даных)",
|
||||
"LabelDescription": "Апісанне",
|
||||
"LabelDeselectAll": "Скасаваць выбар усяго",
|
||||
"LabelDevice": "Прылада",
|
||||
"LabelDeviceInfo": "Інфармацыя пра прыладу",
|
||||
"LabelDeviceIsAvailableTo": "Прылада даступная для...",
|
||||
"LabelDirectory": "Каталог",
|
||||
"LabelDiscFromFilename": "Дыск з імя файла",
|
||||
"LabelDiscFromMetadata": "Дыск па метададзеных",
|
||||
"LabelDiscover": "Знайсці",
|
||||
"LabelDownload": "Спампаваць",
|
||||
"LabelDownloadNEpisodes": "Спампована {0} эпізодаў",
|
||||
"LabelDownloadable": "Спампоўваецца",
|
||||
"LabelDuration": "Працягласць",
|
||||
"LabelDurationComparisonExactMatch": "(дакладнае супадзенне)",
|
||||
"LabelDurationComparisonLonger": "(на {0} даўжэй)",
|
||||
"LabelDurationComparisonShorter": "(на {0} карацей)",
|
||||
"LabelDurationFound": "Знойдзеная працягласць:",
|
||||
"LabelEbook": "Электронная кніга",
|
||||
"LabelEbooks": "Электронныя кнігі",
|
||||
"LabelEdit": "Рэдагаваць",
|
||||
"LabelEmail": "Электронная пошта",
|
||||
"LabelEmailSettingsFromAddress": "Адрас адпраўніка",
|
||||
"LabelEmailSettingsRejectUnauthorized": "Адхіляць неаўтарызаваныя сертыфікаты",
|
||||
"LabelEmailSettingsRejectUnauthorizedHelp": "Адключэнне праверкі SSL-сертыфіката можа зрабіць ваша злучэнне ўразлівым перад пагрозамі бяспекі, такімі як атакі \"чалавек пасярэдзіне\". Адключайце гэтую опцыю толькі калі цалкам разумееце наступствы і ўпэўнены ў надзейнасці паштовага сервера.",
|
||||
"LabelEmailSettingsSecure": "Бяспечныя",
|
||||
"LabelEmailSettingsSecureHelp": "Калі ўключана, злучэнне будзе выкарыстоўваць TLS пры падключэнні да сервера. Калі выключана, TLS будзе выкарыстоўвацца толькі ў выпадку падтрымкі пашырэння STARTTLS на серверы. У большасці выпадкаў усталюйце значэнне true пры падключэнні да порта 465. Для партоў 587 або 25 не ўключайце яго. (інфармацыя з nodemailer.com/smtp/#authentication)",
|
||||
"LabelEmailSettingsTestAddress": "Тэставы адрас",
|
||||
"LabelEmbeddedCover": "Убудаваная вокладка",
|
||||
"LabelEnable": "Уключыць",
|
||||
"LabelEncodingBackupLocation": "Рэзервовая копія вашых арыгінальных аўдыёфайлаў будзе захавана ў:",
|
||||
"LabelEncodingChaptersNotEmbedded": "Раздзелы не ўбудаваны ў шматдарожкавыя аўдыякнігі.",
|
||||
"LabelEncodingClearItemCache": "Пераканайцеся, што перыядычна ачышчаеце кэш элементаў.",
|
||||
"LabelEncodingFinishedM4B": "Гатовы файл M4B будзе змешчаны ў вашу тэчку з аўдыякнігамі па адрасе:",
|
||||
"LabelEncodingInfoEmbedded": "Метаданыя будуць убудаваны ў аўдыядарожкі ўнутры вашай тэчкі з аўдыякнігамі.",
|
||||
"LabelEncodingInfoEmbedded": "Метададзеныя будуць убудаваны ў аўдыядарожкі ўнутры вашай тэчкі з аўдыякнігамі.",
|
||||
"LabelEncodingStartedNavigation": "Пасля запуску задачы вы можаце перайсці на іншую старонку.",
|
||||
"LabelEncodingTimeWarning": "Кадаванне можа заняць да 30 хвілін.",
|
||||
"LabelEnd": "Канец",
|
||||
"LabelEndOfChapter": "Канец раздзела",
|
||||
"LabelEpisode": "Эпізод",
|
||||
"LabelEpisodeNotLinkedToRssFeed": "Эпізод не звязаны з RSS-стужкай",
|
||||
"LabelEpisodeUrlFromRssFeed": "URL эпізоду з RSS-стужкі",
|
||||
"LabelEpisodic": "Эпізадычны",
|
||||
"LabelExample": "Прыклад",
|
||||
"LabelExpandSeries": "Разгарнуць серыю",
|
||||
"LabelExpandSubSeries": "Разгарнуць падсерыі",
|
||||
"LabelExpired": "Пратэрмінаваны",
|
||||
"LabelExpiresAt": "Тэрмін дзеяння заканчваецца ў",
|
||||
"LabelExpiresInSeconds": "Тэрмін дзеяння заканчваецца праз (секунд)",
|
||||
"LabelExpiresNever": "Ніколі",
|
||||
"LabelExplicit": "Відверты",
|
||||
"LabelExportOPML": "Экспарт OPML",
|
||||
"LabelFeedURL": "URL стужкі",
|
||||
"LabelFetchingMetadata": "Атрыманне метададзеных",
|
||||
"LabelFile": "Файл",
|
||||
"LabelFileBirthtime": "Час стварэння файла",
|
||||
"LabelFileModified": "Час змянення файла",
|
||||
|
@ -289,6 +371,7 @@
|
|||
"LabelHasSupplementaryEbook": "Мае дадатковую электронную кнігу",
|
||||
"LabelHideSubtitles": "Схаваць падзагалоўкі",
|
||||
"LabelHost": "Хост",
|
||||
"LabelImageURLFromTheWeb": "URL выявы з інтэрнэту",
|
||||
"LabelInProgress": "У працэсе",
|
||||
"LabelIncomplete": "Незавершана",
|
||||
"LabelIntervalCustomDailyWeekly": "Карыстальніцкі штодзённы/штотыднёвы",
|
||||
|
@ -319,6 +402,7 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Не {0}",
|
||||
"LabelLibraryItem": "Элемент бібліятэкі",
|
||||
"LabelLibraryName": "Імя бібліятэкі",
|
||||
"LabelLibrarySortByProgress": "Прагрэс абноўлены",
|
||||
"LabelLimit": "Абмежаванне",
|
||||
"LabelLineSpacing": "Міжрадковы інтэрвал",
|
||||
"LabelListenAgain": "Паслухаць зноў",
|
||||
|
@ -327,6 +411,8 @@
|
|||
"LabelMaxEpisodesToKeepHelp": "Значэнне 0 не ўстанаўлівае максімальнага абмежавання. Пасля аўтаматычнай спампоўкі новага эпізоду будзе выдалены самы стары эпізод, калі ў вас больш за X эпізодаў. Пры кожнай новай спампоўцы будзе выдаляцца толькі 1 эпізод.",
|
||||
"LabelMediaPlayer": "Медыяпрайгравальнік",
|
||||
"LabelMediaType": "Тып медыя",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Крыніцы метададзеных з вышэйшым прыярытэтам будуць замяняць крыніцы з ніжэйшым прыярытэтам",
|
||||
"LabelMetadataProvider": "Пастаўшчык метададзеных",
|
||||
"LabelMissing": "Адсутнічае",
|
||||
"LabelMore": "Больш",
|
||||
"LabelMoreInfo": "Больш інфармацыі",
|
||||
|
@ -335,6 +421,7 @@
|
|||
"LabelNarrators": "Чытальнікі",
|
||||
"LabelNewestAuthors": "Новыя аўтары",
|
||||
"LabelNewestEpisodes": "Новыя эпізоды",
|
||||
"LabelNoCustomMetadataProviders": "Няма карыстацкіх пастаўшчыкоў метададзеных",
|
||||
"LabelNotFinished": "Не скончана",
|
||||
"LabelNotStarted": "Не пачата",
|
||||
"LabelNotificationsMaxFailedAttemptsHelp": "Апавяшчэнні адключаюцца пасля таго, як не ўдаецца іх адправіць гэтулькі разоў",
|
||||
|
@ -353,7 +440,7 @@
|
|||
"LabelPublishedDate": "Апублікавана {0}",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Карыстальніцкая электронная пошта ўладальніка",
|
||||
"LabelRSSFeedCustomOwnerName": "Карыстальніцкае імя ўладальніка",
|
||||
"LabelRSSFeedOpen": "RSS-стужка адкрытая",
|
||||
"LabelRSSFeedOpen": "RSS-стужка адкрыта",
|
||||
"LabelRSSFeedPreventIndexing": "Прадухіліць індэксацыю",
|
||||
"LabelRSSFeedSlug": "Ідэнтыфікатар RSS-стужкі",
|
||||
"LabelRSSFeedURL": "URL RSS-стужкі",
|
||||
|
@ -392,6 +479,7 @@
|
|||
"LabelSettingsAudiobooksOnly": "Толькі аўдыякнігі",
|
||||
"LabelSettingsAudiobooksOnlyHelp": "Уключэнне гэтай налады будзе ігнараваць файлы электронных кніг, калі толькі яны не знаходзяцца ў тэчцы з аўдыякнігамі. У такім выпадку яны будуць пазначаны як дадатковыя электронныя кнігі.",
|
||||
"LabelSettingsBookshelfViewHelp": "Рэалістычны дызайн з драўлянымі паліцамі",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Аўтаматычна правяраць бібліятэку на змены",
|
||||
"LabelSettingsEnableWatcherHelp": "Адключае аўтаматычнае дадаванне/абнаўленне элементаў пры выяўленні змен у файлах. *Патрабуецца перазапуск сервера",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Дазволіць скрыптавы кантэнт у EPUB",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Дазволіць EPUB-файлам выконваць скрыпты. Рэкамендуецца пакінуць гэтую наладу выключанай, калі вы не давяраеце крыніцы EPUB-файлаў.",
|
||||
|
@ -409,6 +497,11 @@
|
|||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Палка \"Працягнуць серыю\" на галоўнай старонцы паказвае першую не пачатую кнігу ў серыях, дзе завершана хаця б адна кніга і няма кніг у працэсе чытання. Уключэнне гэтай налады дазволіць працягваць серыю з самай апошняй завершанай кнігі замест першай не пачатай.",
|
||||
"LabelSettingsParseSubtitles": "Разабраць падзагалоўкі",
|
||||
"LabelSettingsParseSubtitlesHelp": "Выдзяляць падзагаловак з назваў тэчак аўдыякніг.<br>Падзагаловак павінен быць аддзелены знакам \" - \".<br>Напрыклад, \"Назва кнігі - Падзагаловак тут\" мае падзагаловак \"Падзагаловак тут\"",
|
||||
"LabelSettingsPreferMatchedMetadata": "Аддаваць перавагу супадаючым метададзеным",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Супадаючыя дадзеныя будуць замяняць дэталі элемента пры выкарыстанні функцыі Хуткі пошук. Па змаўчанні Хуткі пошук запаўняе толькі адсутныя дэталі.",
|
||||
"LabelSettingsStoreCoversWithItemHelp": "Па змаўчанні вокладкі захоўваюцца ў /metadata/items, уключэнне гэтай опцыі забяспечыць захоўванне вокладак у тэчцы элемента вашай бібліятэкі. Захоўвацца будзе толькі адзін файл з назвай \"cover\"",
|
||||
"LabelSettingsStoreMetadataWithItem": "Захоўваць метададзеныя разам з элементам",
|
||||
"LabelSettingsStoreMetadataWithItemHelp": "Па змаўчанні метададзеныя захоўваюцца ў /metadata/items. Уключэнне гэтай опцыі забяспечыць захоўванне файлаў метададзеных у тэчках элементаў вашай бібліятэкі",
|
||||
"LabelSettingsTimeFormat": "Фармат часу",
|
||||
"LabelShareDownloadableHelp": "Дазваляе карыстальнікам, якія маюць спасылку на доступ, спампаваць ZIP-файл элемента бібліятэкі.",
|
||||
"LabelShowAll": "Паказаць усё",
|
||||
|
@ -438,7 +531,7 @@
|
|||
"LabelTags": "Меткі",
|
||||
"LabelTagsAccessibleToUser": "Меткі, даступныя карыстальніку",
|
||||
"LabelTagsNotAccessibleToUser": "Меткі, недаступныя карыстальніку",
|
||||
"LabelTasks": "Выконваюцца задачы",
|
||||
"LabelTasks": "Запушчаныя задачы",
|
||||
"LabelTextEditorBulletedList": "Маркіраваны спіс",
|
||||
"LabelTextEditorLink": "Спасылка",
|
||||
"LabelTextEditorNumberedList": "Нумараваны спіс",
|
||||
|
@ -457,11 +550,14 @@
|
|||
"LabelTimeRemaining": "Засталося {0}",
|
||||
"LabelTimeToShift": "Час зрушэння ў секундах",
|
||||
"LabelTitle": "Назва",
|
||||
"LabelToolsSplitM4bDescription": "Стварэнне MP3 з M4B, падзеленага па раздзелах, з убудаванымі метаданымі, вокладкай і раздзеламі.",
|
||||
"LabelToolsEmbedMetadata": "Убудаваць метададзеныя",
|
||||
"LabelToolsEmbedMetadataDescription": "Убудаваць метададзеныя ў аўдыёфайлы, уключаючы выяву вокладкі і раздзелы.",
|
||||
"LabelToolsMakeM4bDescription": "Стварыць аўдыёкнігу ў фармаце .M4B з убудаванымі метададзенымі, выявай вокладкі і раздзеламі.",
|
||||
"LabelToolsSplitM4bDescription": "Стварэнне MP3 з M4B, падзеленага па раздзелах, з убудаванымі метададзенымі, выявай вокладкі і раздзеламі.",
|
||||
"LabelTotalDuration": "Агульная працягласць",
|
||||
"LabelTotalTimeListened": "Агульны час праслухоўвання",
|
||||
"LabelTrackFromFilename": "Дарожка з імя файла",
|
||||
"LabelTrackFromMetadata": "Дарожка з метаданых",
|
||||
"LabelTrackFromMetadata": "Дарожка з метададзеных",
|
||||
"LabelTracks": "Дарожкі",
|
||||
"LabelTracksMultiTrack": "Шматдарожкавы",
|
||||
"LabelTracksNone": "Няма дарожак",
|
||||
|
@ -510,19 +606,30 @@
|
|||
"MessageBackupsLocationPathEmpty": "Шлях да месцазнаходжання рэзервовых копій не можа быць пустым",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Запоўніце ўключаныя палі дадзенымі з усіх элементаў. Палі з некалькімі значэннямі будуць аб'яднаны",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "Запоўніце ўключаныя палі падрабязнасцей карты дадзенымі з гэтага элемента",
|
||||
"MessageBatchQuickMatchDescription": "Хуткі пошук паспрабуе дадаць адсутныя вокладкі і метададзеныя для выбраных элементаў. Уключыце ніжэй выкладзеныя опцыі, каб дазволіць Хуткаму пошуку замяняць існуючыя вокладкі і/або метададзеныя.",
|
||||
"MessageBookshelfNoRSSFeeds": "Няма адкрытых RSS-стужак",
|
||||
"MessageChapterErrorStartGteDuration": "Няправільны час пачатку: ён павінен быць меншым за працягласць аўдыякнігі",
|
||||
"MessageChapterErrorStartLtPrev": "Няправільны час пачатку: ён павінен быць большым або роўным часу пачатку папярэдняга раздзела",
|
||||
"MessageConfirmCloseFeed": "Вы ўпэўнены, што жадаеце закрыць гэтую стужку?",
|
||||
"MessageConfirmDeleteMetadataProvider": "Ці ўпэўненыя вы, што жадаеце выдаліць карыстацкага пастаўшчыка метададзеных \"{0}\"?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Ці ўпэўненыя вы, што жадаеце ўбудаваць метададзеныя ў {0} аўдыёфайлаў?",
|
||||
"MessageConfirmPurgeCache": "Ачышчэнне кэша выдаліць увесь каталог па адрасе <code>/metadata/cache</code>. <br /><br /> Ці сапраўды вы жадаеце выдаліць каталог кэша?",
|
||||
"MessageConfirmPurgeItemsCache": "Ачышчэнне кэша элементаў выдаліць увесь каталог па адрасе <code>/metadata/cache/items</code>. <br /> Вы ўпэўнены?",
|
||||
"MessageConfirmQuickMatchEpisodes": "Хуткае супадзенне эпізодаў перазапіша дэталі, калі супадзенне будзе знойдзена. Будуць абноўлены толькі эпізоды, якія не супадаюць. Вы ўпэўнены?",
|
||||
"MessageConfirmRemoveListeningSessions": "Вы ўпэўнены, што жадаеце выдаліць {0} сеансаў праслухоўвання?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Ці ўпэўненыя вы, што жадаеце выдаліць усе файлы метададзеных{0} у тэчках элементаў вашай бібліятэкі?",
|
||||
"MessageConfirmRemovePlaylist": "Вы ўпэўненыя, што жадаеце выдаліць свой спіс прайгравання \"{0}\"?",
|
||||
"MessageConfirmSendEbookToDevice": "Вы ўпэўнены, што хочаце адправіць {0} электронную кнігу \"{1}\" на прыладу \"{2}\"?",
|
||||
"MessageDownloadingEpisode": "Спампоўка эпізоду",
|
||||
"MessageEmbedQueue": "У чарзе на ўбудаванне метададзеных (у чарзе {0})",
|
||||
"MessageEpisodesQueuedForDownload": "{0} эпізод(аў) у чарзе для спампоўкі",
|
||||
"MessageEreaderDevices": "Каб забяспечыць дастаўку электронных кніг, вам можа спатрэбіцца дадаць вышэйзгаданы адрас электроннай пошты як дазволенага адпраўніка для кожнай прылады, пералічанай ніжэй.",
|
||||
"MessageFeedURLWillBe": "URL стужкі будзе {0}",
|
||||
"MessageFetching": "Атрыманне...",
|
||||
"MessageInvalidAsin": "Няправільны ASIN",
|
||||
"MessageItemsUpdated": "{0} элементаў абноўлена",
|
||||
"MessageLoading": "Загрузка...",
|
||||
"MessageLogsDescription": "Журналы захоўваюцца ў каталогу <code>/metadata/logs</code> у фармаце JSON. Журналы памылак захоўваюцца ў файле <code>/metadata/logs/crashlogs.txt</code>.",
|
||||
"MessageMapChapterTitles": "Супаставіць назвы раздзелаў з вашымі існуючымі раздзеламі аўдыякнігі без змянення часовых метак",
|
||||
"MessageMarkAsFinished": "Пазначыць як скончана",
|
||||
"MessageNoBookmarks": "Няма закладак",
|
||||
|
@ -536,26 +643,54 @@
|
|||
"MessageNoMediaProgress": "Няма прагрэсу медыя",
|
||||
"MessageNoPodcastFeed": "Няправільны падкаст: Няма стужкі",
|
||||
"MessageNoPodcastsFound": "Падкасты не знойдзены",
|
||||
"MessageNoTasksRunning": "Няма запушчаных задач",
|
||||
"MessageNoUpdatesWereNecessary": "Абнаўленні не патрабаваліся",
|
||||
"MessageNoUserPlaylists": "У вас няма спісаў прайгравання",
|
||||
"MessageNoUserPlaylistsHelp": "Спісы прайгравання прыватныя. Толькі карыстальнік, які іх стварыў, можа іх бачыць.",
|
||||
"MessageOpmlPreviewNote": "Заўвага: гэта папярэдні прагляд разабранага OPML-файла. Фактычная назва падкаста будзе ўзятая з RSS-стужкі.",
|
||||
"MessageOpmlPreviewNote": "Заўвага: гэта папярэдні прагляд разабранага файла OPML. Фактычная назва падкаста будзе ўзятая з RSS-стужкі.",
|
||||
"MessagePlaylistCreateFromCollection": "Стварыць спіс прайгравання з калекцыі",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "У падкаста няма URL RSS-стужкі для супадзення",
|
||||
"MessagePodcastSearchField": "Увядзіце пошукавы запыт або URL RSS-стужкі",
|
||||
"MessageQuickMatchDescription": "Запоўніць пустыя дэталі элемента і вокладку першым вынікам супадзення з '{0}'. Не замяняе дэталі, калі опцыя «Аддаваць перавагу супадаючым метададзеным» на серверы не ўключана.",
|
||||
"MessageReportBugsAndContribute": "Паведамляйце пра памылкі, прапануйце новыя функцыі і ўдзельнічайце на",
|
||||
"MessageRestoreBackupWarning": "Аднаўленне рэзервовай копіі перазапіша ўсю базу даных, размешчаную ў /config, а таксама выявы вокладкі ў /metadata/items і /metadata/authors. <br /><br /> Рэзервовыя копіі не змяняюць файлы ў вашых тэчках бібліятэкі. Калі вы ўключылі наладкі сервера для захоўвання воклак і метададзеных у тэчках бібліятэкі, гэтыя файлы не будуць захаваныя ў рэзервовых копіях і не зменяцца. <br /><br /> Усе кліенты, якія карыстаюцца вашым серверам, будуць аўтаматычна абноўлены.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Выконваць кожныя {0} у {1}",
|
||||
"MessageStartPlaybackAtTime": "Пачаць прайграванне для \"{0}\" з {1}?",
|
||||
"MessageTaskAudioFileNotWritable": "Аўдыёфайл \"{0}\" недаступны для запісу",
|
||||
"MessageTaskCanceledByUser": "Задача скасавана карыстальнікам",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Спампоўка эпізоду \"{0}\"",
|
||||
"MessageTaskEmbeddingMetadata": "Убудаванне метададзеных",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Убудаванне метададзеных у аўдыёкнігу \"{0}\"",
|
||||
"MessageTaskEncodingM4b": "Кадаванне M4B",
|
||||
"MessageTaskEncodingM4bDescription": "Кадаванне аўдыякнігі \"{0}\" у адзін файл m4b",
|
||||
"MessageTaskFailed": "Не ўдалося",
|
||||
"MessageTaskFailedToBackupAudioFile": "Не ўдалося зрабіць рэзервовую копію аўдыёфайла \"{0}\"",
|
||||
"MessageTaskFailedToCreateCacheDirectory": "Не ўдалося стварыць каталог кэша",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "Не ўдалося ўбудаваць метададзеныя ў файл \"{0}\"",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Не ўдалося аб’яднаць аўдыёфайлы",
|
||||
"MessageTaskFailedToMoveM4bFile": "Не ўдалося перамясціць файл m4b",
|
||||
"MessageTaskFailedToWriteMetadataFile": "Не ўдалося захаваць файл метададзеных",
|
||||
"MessageTaskMatchingBooksInLibrary": "Пошук супадзенняў кніг у бібліятэцы \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Няма файлаў для сканавання",
|
||||
"MessageTaskOpmlImport": "Імпарт OPML",
|
||||
"MessageTaskOpmlImportDescription": "Стварэнне падкастаў з {0} RSS-стужак",
|
||||
"MessageTaskOpmlImportFeed": "Імпарт стужкі з OPML",
|
||||
"MessageTaskOpmlImportFeed": "Імпарт стужкі OPML",
|
||||
"MessageTaskOpmlImportFeedDescription": "Імпартаванне RSS-стужкі \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedFailed": "Не ўдалося атрымаць стужку падкаста",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Стварэнне падкаста \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "Падкаст ужо існуе па гэтым шляху",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Не ўдалося стварыць падкаст",
|
||||
"MessageTaskOpmlParseNoneFound": "У OPML-файле не знойдзена стужак",
|
||||
"MessageTaskOpmlImportFinished": "Дададзена {0} падкастаў",
|
||||
"MessageTaskOpmlParseFailed": "Не ўдалося разабраць файл OPML",
|
||||
"MessageTaskOpmlParseFastFail": "Неправільны файл OPML: тэг <opml> не знойдзены АБО тэг <outline> не знойдзены",
|
||||
"MessageTaskOpmlParseNoneFound": "У файле OPML не знойдзена стужак",
|
||||
"MessageTaskScanItemsAdded": "{0} дададзена",
|
||||
"MessageTaskScanItemsMissing": "{0} адсутнічае",
|
||||
"MessageTaskScanItemsUpdated": "{0} абноўлена",
|
||||
"MessageTaskScanNoChangesNeeded": "Змены не патрабуюцца",
|
||||
"MessageTaskScanningFileChanges": "Сканіраванне змяненняў у файле \"{0}\"",
|
||||
"MessageTaskScanningLibrary": "Сканіраванне бібліятэкі \"{0}\"",
|
||||
"MessageTaskTargetDirectoryNotWritable": "Мэтавы каталог недаступны для запісу",
|
||||
"NoteChapterEditorTimes": "Заўвага: Час пачатку першага раздзела павінен заставацца 0:00, а час пачатку апошняга раздзела не можа перавышаць працягласць гэтай аўдыякнігі.",
|
||||
"NoteRSSFeedPodcastAppsHttps": "Папярэджанне: большасць праграм для падкастаў патрабуюць, каб URL RSS-стужкі выкарыстоўваў HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Папярэджанне: адзін ці больш вашых эпізодаў не маюць даты публікацыі. Некаторыя праграмы для падкастаў патрабуюць гэтага.",
|
||||
|
@ -567,6 +702,11 @@
|
|||
"StatsBooksListenedTo": "кнігі, якія былі праслуханы",
|
||||
"StatsCollectionGrewTo": "Ваша калекцыя кніг павялічылася да…",
|
||||
"ToastAccountUpdateSuccess": "Уліковы запіс абноўлены",
|
||||
"ToastAuthorImageRemoveSuccess": "Выява аўтара выдалена",
|
||||
"ToastAuthorUpdateSuccess": "Аўтар абноўлены",
|
||||
"ToastAuthorUpdateSuccessNoImageFound": "Аўтар абноўлены (малюнак не знойдзены)",
|
||||
"ToastBackupInvalidMaxKeep": "Няправільная колькасць рэзервовых копій для захоўвання",
|
||||
"ToastBackupInvalidMaxSize": "Няправільны максімальны памер рэзервовай копіі",
|
||||
"ToastBookmarkCreateFailed": "Не ўдалося стварыць закладку",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Дата і час указаны некарэктна або не цалкам",
|
||||
"ToastDeviceTestEmailFailed": "Не ўдалося адправіць тэставае электроннае пісьмо",
|
||||
|
@ -574,6 +714,7 @@
|
|||
"ToastEncodeCancelSucces": "Кадаванне скасавана",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Не ўдалося ачысціць чаргу",
|
||||
"ToastEpisodeDownloadQueueClearSuccess": "Чарга спампоўкі эпізодаў ачышчана",
|
||||
"ToastInvalidImageUrl": "Няправільны URL выявы",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Няправільная максімальная колькасць эпізодаў для спампоўкі",
|
||||
"ToastItemMarkedAsFinishedFailed": "Не ўдалося пазначыць як Скончана",
|
||||
"ToastItemMarkedAsFinishedSuccess": "Элемент пазначаны як Завершаны",
|
||||
|
@ -602,6 +743,8 @@
|
|||
"ToastPlaylistCreateSuccess": "Спіс прайгравання створаны",
|
||||
"ToastPlaylistRemoveSuccess": "Спіс прайгравання выдалены",
|
||||
"ToastPlaylistUpdateSuccess": "Спіс прайгравання абноўлены",
|
||||
"ToastPodcastCreateFailed": "Не ўдалося стварыць падкаст",
|
||||
"ToastPodcastCreateSuccess": "Падкаст паспяхова створаны",
|
||||
"ToastPodcastGetFeedFailed": "Не ўдалося атрымаць стужку падкаста",
|
||||
"ToastPodcastNoEpisodesInFeed": "У RSS-стужцы не знойдзена эпізодаў",
|
||||
"ToastPodcastNoRssFeed": "У падкаста няма RSS-стужкі",
|
||||
|
@ -610,6 +753,7 @@
|
|||
"ToastSendEbookToDeviceFailed": "Не ўдалося адправіць электронную кнігу на прыладу",
|
||||
"ToastSendEbookToDeviceSuccess": "Электронная кніга адпраўлена на прыладу \"{0}\"",
|
||||
"ToastSleepTimerDone": "Таймер сну скончыўся... Хр-р-р",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Элемент \"{0}\" выкарыстоўвае падкаталог шляху загрузкі.",
|
||||
"ToastUserPasswordMustChange": "Новы пароль не можа супадаць са старым",
|
||||
"ToastUserRootRequireName": "Неабходна ўвесці імя карыстальніка адміністратара"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Създай",
|
||||
"ButtonAddApiKey": "Добави API ключ",
|
||||
"ButtonAddChapters": "Добави Глави",
|
||||
"ButtonAddDevice": "Добави Устройство",
|
||||
"ButtonAddLibrary": "Добави Библиотека",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Избери Папка",
|
||||
"ButtonChooseFiles": "Избери Файлове",
|
||||
"ButtonClearFilter": "Изчисти филтър",
|
||||
"ButtonClose": "Затвори",
|
||||
"ButtonCloseFeed": "Затвори стената",
|
||||
"ButtonCloseSession": "Затвори отворената сесия",
|
||||
"ButtonCollections": "Колекции",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Профил",
|
||||
"HeaderAddCustomMetadataProvider": "Добави персонализиран доставчик на метаданни",
|
||||
"HeaderAdvanced": "Разширени настройки",
|
||||
"HeaderApiKeys": "API ключове",
|
||||
"HeaderAppriseNotificationSettings": "Apprise Notification Опции",
|
||||
"HeaderAudioTracks": "Песни",
|
||||
"HeaderAudiobookTools": "Инструмент за Менижиране на Аудиокниги",
|
||||
"HeaderAuthentication": "Аутентикация",
|
||||
"HeaderBackups": "Архив",
|
||||
"HeaderBulkChapterModal": "Добави няколко глави",
|
||||
"HeaderChangePassword": "Промяна на Парола",
|
||||
"HeaderChapters": "Глави",
|
||||
"HeaderChooseAFolder": "Избети Папка",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Предимство на Метаданни",
|
||||
"HeaderMetadataToEmbed": "Метаданни за Вграждане",
|
||||
"HeaderNewAccount": "Нов Профил",
|
||||
"HeaderNewApiKey": "Нов API ключ",
|
||||
"HeaderNewLibrary": "Нова Библиотека",
|
||||
"HeaderNotificationCreate": "Създай нотификация",
|
||||
"HeaderNotificationUpdate": "Обнови нотификация",
|
||||
|
@ -177,6 +182,7 @@
|
|||
"HeaderPlaylist": "Плейлист",
|
||||
"HeaderPlaylistItems": "Елементи от плейлист",
|
||||
"HeaderPodcastsToAdd": "Подкасти за Добавяне",
|
||||
"HeaderPresets": "Настройки по подразбиране",
|
||||
"HeaderPreviewCover": "Преглед на Корица",
|
||||
"HeaderRSSFeedGeneral": "RSS подробности",
|
||||
"HeaderRSSFeedIsOpen": "RSS емисията е отворена",
|
||||
|
@ -194,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Експериментални Функции",
|
||||
"HeaderSettingsGeneral": "Общи",
|
||||
"HeaderSettingsScanner": "Скенер",
|
||||
"HeaderSettingsSecurity": "Сигурност",
|
||||
"HeaderSettingsWebClient": "Уеб клиент",
|
||||
"HeaderSleepTimer": "Таймер за заспиване",
|
||||
"HeaderStatsLargestItems": "Най-Големите Елементи",
|
||||
|
@ -205,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Съдържание",
|
||||
"HeaderTools": "Инструменти",
|
||||
"HeaderUpdateAccount": "Обнови Профил",
|
||||
"HeaderUpdateApiKey": "Обнови API ключ",
|
||||
"HeaderUpdateAuthor": "Обнови Автор",
|
||||
"HeaderUpdateDetails": "Обнови Детайли",
|
||||
"HeaderUpdateLibrary": "Обнови Библиотека",
|
||||
|
@ -219,6 +227,7 @@
|
|||
"LabelAccountTypeAdmin": "Администратор",
|
||||
"LabelAccountTypeGuest": "Гост",
|
||||
"LabelAccountTypeUser": "Потребител",
|
||||
"LabelActivities": "Дейности",
|
||||
"LabelActivity": "Дейност",
|
||||
"LabelAddToCollection": "Добави в Колекция",
|
||||
"LabelAddToCollectionBatch": "Добави {0} Книги в Колекция",
|
||||
|
@ -228,10 +237,15 @@
|
|||
"LabelAddedDate": "Добавено",
|
||||
"LabelAdminUsersOnly": "Само за Администратори",
|
||||
"LabelAll": "Всичко",
|
||||
"LabelAllEpisodesDownloaded": "Всички епизоди са изтеглени",
|
||||
"LabelAllUsers": "Всички Потребители",
|
||||
"LabelAllUsersExcludingGuests": "Всички потребители без гости",
|
||||
"LabelAllUsersIncludingGuests": "Всички потребители включително гости",
|
||||
"LabelAlreadyInYourLibrary": "Вече е в твоята библиотека",
|
||||
"LabelApiKeyCreated": "API ключ \"{0}\" успешно създатен.",
|
||||
"LabelApiKeyCreatedDescription": "Погрижете се да копирате API ключът сега, защото повече няма да можете да го виждате онново.",
|
||||
"LabelApiKeyUser": "Действай от името на потребителя",
|
||||
"LabelApiKeyUserDescription": "Този API ключ ще има същите права като на потребителя за чието име действа. В логовете ще изглежда все едно потребителя прави заявката.",
|
||||
"LabelApiToken": "АПИ Токен",
|
||||
"LabelAppend": "Добави",
|
||||
"LabelAudioBitrate": "Аудио битрейт (напр. 128k)",
|
||||
|
@ -251,9 +265,9 @@
|
|||
"LabelBackToUser": "Обратно към Потребител",
|
||||
"LabelBackupAudioFiles": "Създай резервно копие на аудио файлове",
|
||||
"LabelBackupLocation": "Местоположение на Архив",
|
||||
"LabelBackupsEnableAutomaticBackups": "Включи автоматично архивиране",
|
||||
"LabelBackupsEnableAutomaticBackups": "Автоматично архивиране",
|
||||
"LabelBackupsEnableAutomaticBackupsHelp": "Архиви запазени в /metadata/backups",
|
||||
"LabelBackupsMaxBackupSize": "Максимален размер на архива (в GB)",
|
||||
"LabelBackupsMaxBackupSize": "Максимален размер на архива (в GB) (0 за неограничен)",
|
||||
"LabelBackupsMaxBackupSizeHelp": "За защита срещу грешки в конфигурацията, архивите ще се провалят ако надхвърлят конфигурирания размер.",
|
||||
"LabelBackupsNumberToKeep": "Брой архиви за запазване",
|
||||
"LabelBackupsNumberToKeepHelp": "Само 1 архив ще бъде премахнат на веднъж, така че ако вече имате повече архиви от това трябва да ги премахнете ръчно.",
|
||||
|
@ -270,7 +284,7 @@
|
|||
"LabelChaptersFound": "намерени глави",
|
||||
"LabelClickForMoreInfo": "Кликни за повече информация",
|
||||
"LabelClickToUseCurrentValue": "Натисни да ползваш сегашната стойност",
|
||||
"LabelClosePlayer": "Затвори",
|
||||
"LabelClosePlayer": "Затвори плейъра",
|
||||
"LabelCodec": "Кодек",
|
||||
"LabelCollapseSeries": "Скрий сериите",
|
||||
"LabelCollapseSubSeries": "Свий подсерии",
|
||||
|
@ -281,8 +295,10 @@
|
|||
"LabelContinueListening": "Продължи слушане",
|
||||
"LabelContinueReading": "Продължи четене",
|
||||
"LabelContinueSeries": "Продължи серии",
|
||||
"LabelCorsAllowed": "Разрешени CORS Origins",
|
||||
"LabelCover": "Корица",
|
||||
"LabelCoverImageURL": "URL на Корица",
|
||||
"LabelCoverProvider": "Източник за обложки",
|
||||
"LabelCreatedAt": "Създадено на",
|
||||
"LabelCronExpression": "Cron израз",
|
||||
"LabelCurrent": "Текущо",
|
||||
|
@ -293,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Изтрий от файловата система (отмени за да бъдат премахни само от базата данни)",
|
||||
"LabelDescription": "Описание",
|
||||
"LabelDeselectAll": "Премахни всички",
|
||||
"LabelDetectedPattern": "Намерен образец:",
|
||||
"LabelDevice": "Устройство",
|
||||
"LabelDeviceInfo": "Информация за Устройство",
|
||||
"LabelDeviceIsAvailableTo": "Устройството е достъпно за ...",
|
||||
|
@ -325,15 +342,28 @@
|
|||
"LabelEncodingClearItemCache": "Уверете се, че периодично изчиствате кеша на елементите.",
|
||||
"LabelEncodingFinishedM4B": "Завършеният M4B файл ще бъде поставен в папката на вашите аудиокниги на:",
|
||||
"LabelEncodingInfoEmbedded": "Метаданните ще бъдат вградени в аудио траковете в папката на вашите аудиокниги.",
|
||||
"LabelEncodingStartedNavigation": "Когато задачата е стартирана, можете да смените тази страница.",
|
||||
"LabelEncodingTimeWarning": "Кодирането може да отнеме до 30 минути.",
|
||||
"LabelEncodingWarningAdvancedSettings": "Внимание: Не променяйте тези настройки, ако не сте запознати с ffmpeg настройките за кодиране.",
|
||||
"LabelEncodingWatcherDisabled": "Ако сте изключили наблюдението на папки, ще е нужно да сканирате повторно аудио книгата.",
|
||||
"LabelEnd": "Край",
|
||||
"LabelEndOfChapter": "Край на глава",
|
||||
"LabelEpisode": "Епизод",
|
||||
"LabelEpisodeNotLinkedToRssFeed": "Епизодът не е свързан с RSS канал",
|
||||
"LabelEpisodeNumber": "Епизод #{0}",
|
||||
"LabelEpisodeTitle": "Заглавие на Епизод",
|
||||
"LabelEpisodeType": "Тип на Епизод",
|
||||
"LabelEpisodeUrlFromRssFeed": "URL адрес на епизод от RSS канал",
|
||||
"LabelEpisodes": "Епизоди",
|
||||
"LabelEpisodic": "Епизодичен",
|
||||
"LabelExample": "Пример",
|
||||
"LabelExpandSeries": "Покажи сериите",
|
||||
"LabelExpandSubSeries": "Покажи съб сериите",
|
||||
"LabelExplicit": "С нецензурно съдържание",
|
||||
"LabelExpired": "Изтекъл",
|
||||
"LabelExpiresAt": "Изтича на",
|
||||
"LabelExpiresInSeconds": "Изтича след (секунди)",
|
||||
"LabelExpiresNever": "Никога",
|
||||
"LabelExplicit": "Експлицитно",
|
||||
"LabelExplicitChecked": "С нецензурно съдържание (проверено)",
|
||||
"LabelExplicitUnchecked": "Без нецензурно съдържание (непроверено)",
|
||||
"LabelExportOPML": "Експортирай OPML",
|
||||
|
@ -341,7 +371,9 @@
|
|||
"LabelFetchingMetadata": "Взимане на Метаданни",
|
||||
"LabelFile": "Файл",
|
||||
"LabelFileBirthtime": "Дата на създаване на файла",
|
||||
"LabelFileBornDate": "Роден {0}",
|
||||
"LabelFileModified": "Дата на модификация на файла",
|
||||
"LabelFileModifiedDate": "Променен {0}",
|
||||
"LabelFilename": "Име на файла",
|
||||
"LabelFilterByUser": "Филтриране по Потребител",
|
||||
"LabelFindEpisodes": "Намери Епизоди",
|
||||
|
@ -355,14 +387,17 @@
|
|||
"LabelFontScale": "Мащаб на шрифта",
|
||||
"LabelFontStrikethrough": "Зачертан",
|
||||
"LabelFormat": "Формат",
|
||||
"LabelFull": "Пълен",
|
||||
"LabelGenre": "Жанр",
|
||||
"LabelGenres": "Жанрове",
|
||||
"LabelHardDeleteFile": "Пълно Изтриване на Файл",
|
||||
"LabelHasEbook": "Има е-книга",
|
||||
"LabelHasSupplementaryEbook": "Има допълнителна е-книга",
|
||||
"LabelHideSubtitles": "Скрий субтитри",
|
||||
"LabelHighestPriority": "Най-висок Приоритет",
|
||||
"LabelHost": "Хост",
|
||||
"LabelHour": "Час",
|
||||
"LabelHours": "Часа",
|
||||
"LabelIcon": "Икона",
|
||||
"LabelImageURLFromTheWeb": "URL на Изображение от Интернет",
|
||||
"LabelInProgress": "В процес на изпълнение",
|
||||
|
@ -377,13 +412,17 @@
|
|||
"LabelIntervalEvery6Hours": "Всеки 6 часа",
|
||||
"LabelIntervalEveryDay": "Всеки ден",
|
||||
"LabelIntervalEveryHour": "Всеки час",
|
||||
"LabelIntervalEveryMinute": "Всяка минута",
|
||||
"LabelInvert": "Обърни",
|
||||
"LabelItem": "Елемент",
|
||||
"LabelJumpBackwardAmount": "Количество за прескачане назад",
|
||||
"LabelJumpForwardAmount": "Количество за прескачане напред",
|
||||
"LabelLanguage": "Език",
|
||||
"LabelLanguageDefaultServer": "Език по подразбиране на сървъра",
|
||||
"LabelLanguages": "Езици",
|
||||
"LabelLastBookAdded": "Последно Добавена Книга",
|
||||
"LabelLastBookUpdated": "Последно Обновена Книга",
|
||||
"LabelLastProgressDate": "Последен прогрес: {0}",
|
||||
"LabelLastSeen": "Последно Видян",
|
||||
"LabelLastTime": "Последно Време",
|
||||
"LabelLastUpdate": "Последно Обновяване",
|
||||
|
@ -393,8 +432,10 @@
|
|||
"LabelLess": "По-малко",
|
||||
"LabelLibrariesAccessibleToUser": "Библиотеки Достъпни за Потребителя",
|
||||
"LabelLibrary": "Библиотека",
|
||||
"LabelLibraryFilterSublistEmpty": "Не {0}",
|
||||
"LabelLibraryItem": "Елемент на Библиотека",
|
||||
"LabelLibraryName": "Име на Библиотека",
|
||||
"LabelLibrarySortByProgress": "Прогресът е обновен",
|
||||
"LabelLimit": "Лимит",
|
||||
"LabelLineSpacing": "Междуредие",
|
||||
"LabelListenAgain": "Слушай отново",
|
||||
|
@ -403,8 +444,13 @@
|
|||
"LabelLogLevelWarn": "Предупреждение",
|
||||
"LabelLookForNewEpisodesAfterDate": "Търси нови епизоди след дата",
|
||||
"LabelLowestPriority": "Най-нисък Приоритет",
|
||||
"LabelMatchConfidence": "Увереност",
|
||||
"LabelMatchExistingUsersBy": "Съпостави съществуващи потребители по",
|
||||
"LabelMatchExistingUsersByDescription": "Използва се за свързване на съществуващи потребители. След свързване потребителите ще бъдат съпоставени по уникален идентификатор от вашия доставчик на SSO",
|
||||
"LabelMaxEpisodesToDownload": "Максимален брой епизоди за сваляне. Използвай 0 за неограничен.",
|
||||
"LabelMaxEpisodesToDownloadPerCheck": "Максимален брой нови епизоди за сваляне за проверка",
|
||||
"LabelMaxEpisodesToKeep": "Максимален брой епизоди за запазване",
|
||||
"LabelMaxEpisodesToKeepHelp": "Стойност 0 указва без максимален лимит. След като нов епизод е автоматично свален, най-старият епизод ще бъде изтрит, ако имате повече от X епизода. Само по един епизод ще бъде изтриван за всеки нов свален такъв.",
|
||||
"LabelMediaPlayer": "Медия Плейър",
|
||||
"LabelMediaType": "Тип медия",
|
||||
"LabelMetaTag": "Мета Таг",
|
||||
|
@ -412,6 +458,7 @@
|
|||
"LabelMetadataOrderOfPrecedenceDescription": "По-високите източници на метаданни ще заменят по-ниските",
|
||||
"LabelMetadataProvider": "Доставчик на Метаданни",
|
||||
"LabelMinute": "Минута",
|
||||
"LabelMinutes": "Минути",
|
||||
"LabelMissing": "Липсващо",
|
||||
"LabelMissingEbook": "Няма електронна книга",
|
||||
"LabelMissingSupplementaryEbook": "Няма допълнителна електронна книга",
|
||||
|
@ -427,7 +474,9 @@
|
|||
"LabelNewestAuthors": "Най-новите автори",
|
||||
"LabelNewestEpisodes": "Най-новите епизоди",
|
||||
"LabelNextBackupDate": "Следваща Дата на Архивиране",
|
||||
"LabelNextChapters": "Следващите глави ще бъдат:",
|
||||
"LabelNextScheduledRun": "Следващо Планирано Изпълнение",
|
||||
"LabelNoApiKeys": "Няма API ключове",
|
||||
"LabelNoCustomMetadataProviders": "Няма потребителски доставчици на метаданни",
|
||||
"LabelNoEpisodesSelected": "Няма избрани епизоди",
|
||||
"LabelNotFinished": "Не е приключено",
|
||||
|
@ -443,17 +492,21 @@
|
|||
"LabelNotificationsMaxQueueSize": "Максимален размер на опашката за известия",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Събитията са ограничени до изстрелване на 1 на секунда. Събитията ще бъдат игнорирани ако опашката е на максимален размер. Това предотвратява спамирането на известия.",
|
||||
"LabelNumberOfBooks": "Брой на Книги",
|
||||
"LabelNumberOfChapters": "Брой глави:",
|
||||
"LabelNumberOfEpisodes": "Брой епизоди",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Име на OpenID твърдението, което съдържа разширени права за достъп до потребителски действия в приложението, които ще се прилагат за роли, различни от администраторските (<b>ако е конфигурирано</b>). Ако твърдението липсва в отговора, достъпът до ABS ще бъде отказан. Ако липсва една опция, тя ще се третира като <code>false</code>. Уверете се, че твърдението на доставчика на идентичност съответства на очакваната структура:",
|
||||
"LabelOpenIDClaims": "Оставете следните опции празни, за да деактивирате разширеното присвояване на групи, като автоматично ще бъде присвоена групата 'Потребител'.",
|
||||
"LabelOpenIDGroupClaimDescription": "Име на OpenID твърдението, което съдържа списък с групите на потребителя. Обикновено се нарича <code>groups</code>. <b>Ако е конфигурирано</b>, приложението автоматично ще присвоява роли въз основа на членството на потребителя в групи, при условие че тези групи са наименувани без чувствителност към регистъра като 'admin', 'user' или 'guest' в твърдението. Твърдението трябва да съдържа списък и ако потребителят принадлежи към множество групи, приложението ще присвои ролята, съответстваща на най-високото ниво на достъп. Ако няма съвпадение с група, достъпът ще бъде отказан.",
|
||||
"LabelOpenRSSFeed": "Отвори RSS Feed",
|
||||
"LabelOverwrite": "Презапиши",
|
||||
"LabelPaginationPageXOfY": "Страница {0} от {1}",
|
||||
"LabelPassword": "Парола",
|
||||
"LabelPath": "Път",
|
||||
"LabelPermanent": "Постоянен",
|
||||
"LabelPermissionsAccessAllLibraries": "Може да достъпи до всички библиотеки",
|
||||
"LabelPermissionsAccessAllTags": "Може да достъпи всички тагове",
|
||||
"LabelPermissionsAccessExplicitContent": "Може да достъпи експлицитно съдържание",
|
||||
"LabelPermissionsCreateEreader": "Може да създава електронен четец",
|
||||
"LabelPermissionsDelete": "Може да трие",
|
||||
"LabelPermissionsDownload": "Може да сваля",
|
||||
"LabelPermissionsUpdate": "Може да обновява",
|
||||
|
@ -461,6 +514,8 @@
|
|||
"LabelPersonalYearReview": "Преглед на годината Ви ({0})",
|
||||
"LabelPhotoPathURL": "Път/URL на Снимка",
|
||||
"LabelPlayMethod": "Метод на Пускане",
|
||||
"LabelPlaybackRateIncrementDecrement": "Размер на увеличаване/намаляне при скоростта на възпроизвеждане",
|
||||
"LabelPlayerChapterNumberMarker": "{0} от {1}",
|
||||
"LabelPlaylists": "Плейлисти",
|
||||
"LabelPodcast": "Подкаст",
|
||||
"LabelPodcastSearchRegion": "Регион за Търсене на Подкасти",
|
||||
|
@ -472,18 +527,22 @@
|
|||
"LabelPrimaryEbook": "Основна Електронна Книга",
|
||||
"LabelProgress": "Прогрес",
|
||||
"LabelProvider": "Доставчик",
|
||||
"LabelProviderAuthorizationValue": "Стойност на Authorization Header",
|
||||
"LabelPubDate": "Дата на публикуване",
|
||||
"LabelPublishYear": "Година на публикуване",
|
||||
"LabelPublishedDate": "Публикувани {0}",
|
||||
"LabelPublishedDecade": "Десетилетие на публикуване",
|
||||
"LabelPublishedDecades": "Десетилетия на публикуване",
|
||||
"LabelPublisher": "Издател",
|
||||
"LabelPublishers": "Издателство",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Персонализиран имейл на собственика",
|
||||
"LabelRSSFeedCustomOwnerName": "Персонализирано име на собственика",
|
||||
"LabelRSSFeedOpen": "RSS Feed Оптворен",
|
||||
"LabelRSSFeedOpen": "RSS Feed е отворен",
|
||||
"LabelRSSFeedPreventIndexing": "Предотвратете индексиране",
|
||||
"LabelRSSFeedSlug": "идентификатор на RSS емисия",
|
||||
"LabelRSSFeedURL": "URL на RSS емисия",
|
||||
"LabelRandomly": "Случайно",
|
||||
"LabelReAddSeriesToContinueListening": "Добави отново в \"Продължете да слушате\"",
|
||||
"LabelRead": "Прочети",
|
||||
"LabelReadAgain": "Прочети отново",
|
||||
"LabelReadEbookWithoutProgress": "Прочети електронната книга без записване прогрес",
|
||||
|
@ -493,29 +552,41 @@
|
|||
"LabelRedo": "Повтори",
|
||||
"LabelRegion": "Регион",
|
||||
"LabelReleaseDate": "Дата на Издаване",
|
||||
"LabelRemoveAllMetadataAbs": "Премахни всички metadata.abs файлове",
|
||||
"LabelRemoveAllMetadataJson": "Премахни всички metadata.json файлове",
|
||||
"LabelRemoveAudibleBranding": "Премахни въведението и заключението на Audible от главите",
|
||||
"LabelRemoveCover": "Премахни Корица",
|
||||
"LabelRemoveMetadataFile": "Премахни файловете с метаданни от папката на библиотеката",
|
||||
"LabelRemoveMetadataFileHelp": "Премахни всички metadata.json и metadata.abs файлове от вашата {0} папка.",
|
||||
"LabelRowsPerPage": "Редове на Страница",
|
||||
"LabelSearchTerm": "Търси Термин",
|
||||
"LabelSearchTitle": "Търси Заглавие",
|
||||
"LabelSearchTitleOrASIN": "Търси Заглавие или ASIN",
|
||||
"LabelSeason": "Сезон",
|
||||
"LabelSeasonNumber": "Сезон #{0}",
|
||||
"LabelSelectAll": "Избери всичко",
|
||||
"LabelSelectAllEpisodes": "Избери всички епизоди",
|
||||
"LabelSelectEpisodesShowing": "Избери {0} епизоди показани",
|
||||
"LabelSelectUser": "Избери потребител",
|
||||
"LabelSelectUsers": "Избери Потребители",
|
||||
"LabelSendEbookToDevice": "Изпрати електронна книга до ...",
|
||||
"LabelSequence": "Последователност",
|
||||
"LabelSerial": "Сериал",
|
||||
"LabelSeries": "От сериите",
|
||||
"LabelSeriesName": "Име на Серия",
|
||||
"LabelSeriesProgress": "Прогрес на Серия",
|
||||
"LabelServerLogLevel": "Ниво на сървърен журнал",
|
||||
"LabelServerYearReview": "Преглед на годината на сървъра ({0})",
|
||||
"LabelSetEbookAsPrimary": "Направи главен",
|
||||
"LabelSetEbookAsSupplementary": "Направи второстепенен",
|
||||
"LabelSettingsAllowIframe": "Разреши вграждане в iframe",
|
||||
"LabelSettingsAudiobooksOnly": "Само аудиокниги",
|
||||
"LabelSettingsAudiobooksOnlyHelp": "Активирането на тази настройка ще игнорира файловете на електронни книги, освен ако не са в папка с аудиокниги, в което случай ще бъдат зададени като допълнителни електронни книги",
|
||||
"LabelSettingsBookshelfViewHelp": "Скеуморфен дизайн с дървени рафтове",
|
||||
"LabelSettingsChromecastSupport": "Chromecast поддръжка",
|
||||
"LabelSettingsDateFormat": "Формат на Дата",
|
||||
"LabelSettingsEnableWatcher": "Автоматично сканиране на библиотеките за промени",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Автоматично сканиране на библиотеката за промени",
|
||||
"LabelSettingsEnableWatcherHelp": "Включва автоматичното добавяне/обновяване на елементи, когато се открият промени във файловете. *Изисква рестарт на сървъра",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Позволи скриптово съдържание в epub-и",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Позволи epub файловете да изпълняват скриптове. Препоръчително е да бъде изключено освен ако не се доверявате на източника на epub файловете.",
|
||||
|
@ -527,10 +598,13 @@
|
|||
"LabelSettingsHideSingleBookSeriesHelp": "Сериите с една книга ще бъдат скрити от страницата на серията и рафтовете на началната страница.",
|
||||
"LabelSettingsHomePageBookshelfView": "Начална страница изглед на рафт",
|
||||
"LabelSettingsLibraryBookshelfView": "Библиотека изглед на рафт",
|
||||
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Процент завършеност е по-голям от",
|
||||
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Оставащо време е по-малко от (секунди)",
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Отбелязване на мултимедиен елемент като завършен когато",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Пропусни предишни книги в Продължи Поредица",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Рафтът на началната страница 'Продължи поредицата' показва първата книга, която не е започната в поредици, в които има поне една завършена книга и няма книги в процес на четене. Активирането на тази настройка ще продължи поредицата от най-далечната завършена книга вместо от първата незапочната книга.",
|
||||
"LabelSettingsParseSubtitles": "Извлечи подзаглавия",
|
||||
"LabelSettingsParseSubtitlesHelp": "Извлича подзаглавия от имената на папките на аудиокнигите.<br>Подзаглавията трябва да бъдат разделени с \" - \"<br>например \"Заглавие на Книга - Тук е Подзаглавито\" има подзаглавие \"Тук е Подзаглавито\"",
|
||||
"LabelSettingsParseSubtitlesHelp": "Извлича подзаглавия от имената на папките на аудио книгите.<br>Подзаглавията трябва да бъдат разделени с \" - \"<br>например \"Заглавие на Книга - Тук е подзаглавието\" има подзаглавие \"Тук е подзаглавието\"",
|
||||
"LabelSettingsPreferMatchedMetadata": "Предпочети съвпадащи метаданни",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Съвпадащите данни ще заменят детайлите на елемента при използване на Бързо Съпоставяне. По подразбиране Бързото Съпоставяне ще попълни само липсващите детайли.",
|
||||
"LabelSettingsSkipMatchingBooksWithASIN": "Пропусни съвпадащи книги, които вече имат ASIN",
|
||||
|
@ -544,11 +618,19 @@
|
|||
"LabelSettingsStoreMetadataWithItem": "Запази метаданните с елемента",
|
||||
"LabelSettingsStoreMetadataWithItemHelp": "По подразбиране метаданните се съхраняват в /metadata/items, като активирате тази настройка метаданните ще се съхраняват в папката на елемента на вашата библиотека",
|
||||
"LabelSettingsTimeFormat": "Формат на Време",
|
||||
"LabelShare": "Сподели",
|
||||
"LabelShareDownloadableHelp": "Разреши на потребителите през връзка за споделяне да свалят zip файл с мултимедийния елемент.",
|
||||
"LabelShareOpen": "Общодостъпно",
|
||||
"LabelShareURL": "URL за споделяне",
|
||||
"LabelShowAll": "Покажи всички",
|
||||
"LabelShowSeconds": "Покажи секунди",
|
||||
"LabelShowSubtitles": "Показвай подзаглавия",
|
||||
"LabelSize": "Размер",
|
||||
"LabelSleepTimer": "Таймер за изключване",
|
||||
"LabelSlug": "Слъг",
|
||||
"LabelSortAscending": "Възходящ",
|
||||
"LabelSortDescending": "Низходящ",
|
||||
"LabelSortPubDate": "Подреди по дата на публикуване",
|
||||
"LabelStart": "Старт",
|
||||
"LabelStartTime": "Начално Време",
|
||||
"LabelStarted": "Стартирано",
|
||||
|
@ -582,7 +664,13 @@
|
|||
"LabelTheme": "Тема",
|
||||
"LabelThemeDark": "Тъмна",
|
||||
"LabelThemeLight": "Светла",
|
||||
"LabelThemeSepia": "Сепия",
|
||||
"LabelTimeBase": "Времева Основа",
|
||||
"LabelTimeDurationXHours": "{0} часа",
|
||||
"LabelTimeDurationXMinutes": "{0} минути",
|
||||
"LabelTimeDurationXSeconds": "{0} секунди",
|
||||
"LabelTimeInMinutes": "Време в минути",
|
||||
"LabelTimeLeft": "остава {0}",
|
||||
"LabelTimeListened": "Време Слушано",
|
||||
"LabelTimeListenedToday": "Време Слушано Днес",
|
||||
"LabelTimeRemaining": "{0} оставащи",
|
||||
|
@ -590,6 +678,7 @@
|
|||
"LabelTitle": "Заглавие",
|
||||
"LabelToolsEmbedMetadata": "Вграждане на Метаданни",
|
||||
"LabelToolsEmbedMetadataDescription": "Вграждане на метаданни в аудио файлове, включително корица и глави.",
|
||||
"LabelToolsM4bEncoder": "M4B кодировчик",
|
||||
"LabelToolsMakeM4b": "Направи M4B Аудиокнига Файл",
|
||||
"LabelToolsMakeM4bDescription": "Генериране на .M4B аудиокнига файл с вградени метаданни, корица и глави.",
|
||||
"LabelToolsSplitM4b": "Раздели M4B на MP3-ки",
|
||||
|
@ -602,29 +691,39 @@
|
|||
"LabelTracksMultiTrack": "Многоканален",
|
||||
"LabelTracksNone": "Няма канали",
|
||||
"LabelTracksSingleTrack": "Единичен канал",
|
||||
"LabelTrailer": "Трейлър",
|
||||
"LabelType": "Тип",
|
||||
"LabelUnabridged": "Несъкратен",
|
||||
"LabelUndo": "Отмени",
|
||||
"LabelUnknown": "Неизвестен",
|
||||
"LabelUnknownPublishDate": "Неизвестна дата на публикуване",
|
||||
"LabelUpdateCover": "Обнови Корица",
|
||||
"LabelUpdateCoverHelp": "Позволи презаписване на съществуващите корици за избраните книги, когато се намери съвпадение",
|
||||
"LabelUpdateDetails": "Обнови Детайли",
|
||||
"LabelUpdateDetailsHelp": "Позволи презаписване на съществуващите детайли за избраните книги, когато се намери съвпадение",
|
||||
"LabelUpdatedAt": "Обновено на",
|
||||
"LabelUploaderDragAndDrop": "Плъзни и Пусни Файлове или Папки",
|
||||
"LabelUploaderDragAndDropFilesOnly": "Извлачване на файлове",
|
||||
"LabelUploaderDropFiles": "Пусни Файлове",
|
||||
"LabelUploaderItemFetchMetadataHelp": "Автоматично вземи заглавие, автор и серия",
|
||||
"LabelUseAdvancedOptions": "Използвай разширени опции",
|
||||
"LabelUseChapterTrack": "Използвай канал за глава",
|
||||
"LabelUseFullTrack": "Използвай пълен канал",
|
||||
"LabelUseZeroForUnlimited": "Използвай 0 за неограничен",
|
||||
"LabelUser": "Потребител",
|
||||
"LabelUsername": "Потребителско име",
|
||||
"LabelValue": "Стойност",
|
||||
"LabelVersion": "Версия",
|
||||
"LabelViewBookmarks": "Виж Отметки",
|
||||
"LabelViewChapters": "Виж Глави",
|
||||
"LabelViewPlayerSettings": "Виж настройки на плеъра",
|
||||
"LabelViewQueue": "Виж Опашка",
|
||||
"LabelVolume": "Сила на Звука",
|
||||
"LabelWebRedirectURLsDescription": "Разрешете тези URL-и във вашият OAuth доставчик, за да позволите пренасочването обратно към уеб приложението след вход:",
|
||||
"LabelWebRedirectURLsSubfolder": "Подпапка за URL адреси за пренасочване",
|
||||
"LabelWeekdaysToRun": "Делници за изпълнение",
|
||||
"LabelXBooks": "{0} книги",
|
||||
"LabelXItems": "{0} елемента",
|
||||
"LabelYearReviewHide": "Скрий ревю на годината ти",
|
||||
"LabelYearReviewShow": "Виж ревю на годината ти",
|
||||
"LabelYourAudiobookDuration": "Продължителност на вашата аудиокнига",
|
||||
|
@ -633,31 +732,51 @@
|
|||
"LabelYourProgress": "Твоят прогрес",
|
||||
"MessageAddToPlayerQueue": "Добави към опашката на плейъра",
|
||||
"MessageAppriseDescription": "За да ползвате тази функция трябва да имате активна инстанция на <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> или на друго АПИ което да обработва тези заявки. <br />The Apprise API Url-а трябва дае пълния URL път за изпращане на известията, например, ако вашето АПИ ве подава от <code>http://192.168.1.1:8337</code> трябва да сложитев <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Уверете се, че използвате ASIN от правилния Audible регион, а не от Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Остарелите API токени ще бъдат премахнати в бъдеще. Вместо това използвайте <a href=\"/config/api-keys\">API ключове</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Рестартирайте сървърът след записването на настройките, за да активирате OIDC промените.",
|
||||
"MessageAuthenticationSecurityMessage": "За осигуряването на по-добра сигурност, автентикацията беше подобрена. Всеки потребител ще трябва да се автентикира наново.",
|
||||
"MessageBackupsDescription": "Резервните копия включват потребители, напредък на потребителите, подробности за елементите в библиотеката, настройки на сървъра и изображения, съхранени в <code>/metadata/items</code> и <code>/metadata/authors</code>. Резервните копия <strong>не</strong> включват никакви файлове, съхранени в папките на вашата библиотека.",
|
||||
"MessageBackupsLocationEditNote": "Забележка: Актуализирането на местоположението за архивиране няма да премести или промени съществуващите архиви",
|
||||
"MessageBackupsLocationNoEditNote": "Забележка: Местоположението за архивиране се задава с помощта на променлива на средата и не може бъде променена от тук.",
|
||||
"MessageBackupsLocationPathEmpty": "Пътят към местоположението за архивиране не може да бъде празен",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Популирайте активираните полета с данни от всички елементи. Полетата със няколко стоайности ще бъдат обединени",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "Попълнете активираните полета с информация за картата с данни от този елемент",
|
||||
"MessageBatchQuickMatchDescription": "Бързото Съпоставяне ще опита да добави липсващи корици и метаданни за избраните елементи. Активирайте опциите по-долу, за да позволите на Бързото съпоставяне да презапише съществуващите корици и/или метаданни.",
|
||||
"MessageBookshelfNoCollections": "Все още нямате създадени колекции",
|
||||
"MessageBookshelfNoCollectionsHelp": "Колекциите са публични. Всички потребители с достъп до библиотеката ще могат да ги виждат.",
|
||||
"MessageBookshelfNoRSSFeeds": "Няма отворени RSS feed-ове",
|
||||
"MessageBookshelfNoResultsForFilter": "Няма резултат за филтер \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Няма резултати от заявката",
|
||||
"MessageBookshelfNoSeries": "Нямаш сеЗЙ",
|
||||
"MessageBulkChapterPattern": "Колко глави искате да добавите, използвайки тази схема за номериране?",
|
||||
"MessageChapterEndIsAfter": "Краят на главата е след края на вашата аудиокнига",
|
||||
"MessageChapterErrorFirstNotZero": "Първата глава трябва да започва от 0",
|
||||
"MessageChapterErrorStartGteDuration": "Началото на главата трябва да бъде по-малко от продължителността на аудиокнигата",
|
||||
"MessageChapterErrorStartLtPrev": "Началото на главата трябва да бъде по-голямо или равно на края на предишната глава",
|
||||
"MessageChapterStartIsAfter": "Началото на главата е след края на вашата аудиокнига",
|
||||
"MessageChaptersNotFound": "Главите не са намерени",
|
||||
"MessageCheckingCron": "Проверяване на cron...",
|
||||
"MessageConfirmCloseFeed": "Сигурни ли сте, че искате да затворите този feed?",
|
||||
"MessageConfirmDeleteApiKey": "Сигурни ли сте, че искате да изтриете API ключ \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Сигурни ли сте, че искате да изтриете този архив {0}?",
|
||||
"MessageConfirmDeleteDevice": "Сигурни ли сте, че искате да изтриете е-четец \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Това ще изтрие файла от файловата Ви система. Сигурни ли сте?",
|
||||
"MessageConfirmDeleteLibrary": "Сигурни ли сте, че искате да изтриете за винаги библиотека \"{0}\"?",
|
||||
"MessageConfirmDeleteLibraryItem": "Това ще изтрие елемента от базата данни и файловата Ви система. Сигурни ли сте?",
|
||||
"MessageConfirmDeleteLibraryItems": "Това ще изтрие {0} елемента от базата данни и файловата Ви система. Сигурни ли сте?",
|
||||
"MessageConfirmDeleteMetadataProvider": "Сигурни ли сте, че искате да изтриете доставчика нa метаданни \"{0}\"?",
|
||||
"MessageConfirmDeleteNotification": "Сигурни ли сте, че искате да изтриете това уведомление?",
|
||||
"MessageConfirmDeleteSession": "Сигурни ли сте, че искате да изтриете тази сесия?",
|
||||
"MessageConfirmEmbedMetadataInAudioFiles": "Сигурнли ли сте, че искате да вградите метаданните в {0} аудио файла?",
|
||||
"MessageConfirmForceReScan": "Сигурни ли сте, че искате да принудите повторно сканиране?",
|
||||
"MessageConfirmMarkAllEpisodesFinished": "Сигурни ли сте, че искате да маркирате всички епизоди като завършени?",
|
||||
"MessageConfirmMarkAllEpisodesNotFinished": "Сигурни ли сте, че искате да маркирате всички епизоди като незавършени?",
|
||||
"MessageConfirmMarkItemFinished": "Сигурни ли сте, че искате да маркирате \"{0}\" като приключено?",
|
||||
"MessageConfirmMarkItemNotFinished": "Сигурни ли сте, че искате да маркирате \"{0}\" като неприключено?",
|
||||
"MessageConfirmMarkSeriesFinished": "Сигурни ли сте, че искате да маркирате всички книги в тази серия като завършени?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Сигурни ли сте, че искате да маркирате всички книги в тази серия като незавършени?",
|
||||
"MessageConfirmNotificationTestTrigger": "Пуснете това уведомление с тестови данни?",
|
||||
"MessageConfirmPurgeCache": "Изчистването на кеша ще изтрие цялата директория в <code>/metadata/cache</code>. <br /><br />Сигурни ли сте, че искате да премахнете директорията на кеша?",
|
||||
"MessageConfirmPurgeItemsCache": "Изчистването на кеша на елементите ще изтрие цялата директория в <code>/metadata/cache/items</code>. <br />Сигурни ли сте?",
|
||||
"MessageConfirmQuickEmbed": "Внимание! Бързото вграждане няма да архивира вашите аудио файлове. Уверете се, че имате резервно копие на вашите аудио файлове. <br><br>Искате ли да продължите?",
|
||||
|
@ -666,6 +785,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Сигурни ли сте, че искате да премахнете автор \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Сигурни ли сте, че искате да премахнете колекция \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Сигурни ли сте, че искате да премахнете епизод \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodeNote": "Забележка: Това няма да доведе до изтриване на аудио файла, освен ако не активирате опцията \"Твърдо изтриване на файла\"",
|
||||
"MessageConfirmRemoveEpisodes": "Сигурни ли сте, че искате да премахнете {0} епизода?",
|
||||
"MessageConfirmRemoveListeningSessions": "Сигурни ли сте, че искате да премахнете {0} слушателски сесии?",
|
||||
"MessageConfirmRemoveNarrator": "Сигурни ли сте, че искате да премахнете разказвач \"{0}\"?",
|
||||
|
@ -676,19 +796,27 @@
|
|||
"MessageConfirmRenameTag": "Сигурни ли сте, че искате да преименувате таг \"{0}\" на \"{1}\" за всички елементи?",
|
||||
"MessageConfirmRenameTagMergeNote": "Забележка: Този таг вече съществува и ще бъде слято.",
|
||||
"MessageConfirmRenameTagWarning": "Внимание! Вече съществува подобен таг с различно писане \"{0}\".",
|
||||
"MessageConfirmResetProgress": "Сигурни ли сте, че искате да нулирате прогреса си?",
|
||||
"MessageConfirmSendEbookToDevice": "Сигурни ли сте, че искате да изпратите {0} електронна книга \"{1}\" до устройство \"{2}\"?",
|
||||
"MessageConfirmUnlinkOpenId": "Сигурни ли сте, че искате да отвържете този потребител от OpenID?",
|
||||
"MessageDaysListenedInTheLastYear": "{0} дни слушане през последната година",
|
||||
"MessageDownloadingEpisode": "Сваля епизод",
|
||||
"MessageDragFilesIntoTrackOrder": "Плъзнете файлове в правилния ред на каналите",
|
||||
"MessageEmbedFailed": "Вграждането беше неуспешно!",
|
||||
"MessageEmbedFinished": "Вграждането завърши!",
|
||||
"MessageEmbedQueue": "Поставено в опашката за вграждане на метаданни ({0} в опашката)",
|
||||
"MessageEpisodesQueuedForDownload": "{0} Епизод(и) са сложени за сваляне",
|
||||
"MessageEreaderDevices": "За да осигурите доставката на е-книги, може да се наложи да добавите горепосочения имейл адрес като валиден подател за всяко устройство, изброено по-долу.",
|
||||
"MessageFeedURLWillBe": "Адресът на емисията ще бъде {0}",
|
||||
"MessageFetching": "Извличане...",
|
||||
"MessageForceReScanDescription": "ще сканира всички файлове отново като прясно сканиране. Аудио файлове ID3 тагове, OPF файлове и текстови файлове ще бъдат сканирани като нови.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} слушане</strong> на {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Няма сесии за слушане на {0}",
|
||||
"MessageImportantNotice": "Важно Съобщение!",
|
||||
"MessageInsertChapterBelow": "Вмъкни глава под",
|
||||
"MessageItemsSelected": "{0} избрани",
|
||||
"MessageItemsUpdated": "{0} елемента обновени",
|
||||
"MessageInvalidAsin": "Невалиден ASIN",
|
||||
"MessageItemsSelected": "{0} избрани елемента",
|
||||
"MessageItemsUpdated": "{0} обновени елемента",
|
||||
"MessageJoinUsOn": "Присъединете се към нас",
|
||||
"MessageLoading": "Зарежда...",
|
||||
"MessageLoadingFolders": "Зареждане на Папки...",
|
||||
|
@ -709,6 +837,7 @@
|
|||
"MessageNoCollections": "Няма колекции",
|
||||
"MessageNoCoversFound": "Не са намерени корици",
|
||||
"MessageNoDescription": "Няма описание",
|
||||
"MessageNoDevices": "Няма устройства",
|
||||
"MessageNoDownloadsInProgress": "Няма изтегляния в прогрес",
|
||||
"MessageNoDownloadsQueued": "Няма изтегляния в опашка",
|
||||
"MessageNoEpisodeMatchesFound": "Няма намерени съвпадения за епизоди",
|
||||
|
@ -722,6 +851,7 @@
|
|||
"MessageNoLogs": "Няма логове",
|
||||
"MessageNoMediaProgress": "Няма прогрес на медията",
|
||||
"MessageNoNotifications": "Няма известия",
|
||||
"MessageNoPodcastFeed": "Невалиден подкаст: Няма канал",
|
||||
"MessageNoPodcastsFound": "Няма намерени подкасти",
|
||||
"MessageNoResults": "Няма резултати",
|
||||
"MessageNoSearchResultsFor": "Няма резултати за \"{0}\"",
|
||||
|
@ -730,13 +860,17 @@
|
|||
"MessageNoTasksRunning": "Няма вършещи се задачи",
|
||||
"MessageNoUpdatesWereNecessary": "Няма нужда от обновяване",
|
||||
"MessageNoUserPlaylists": "Нямате създадени плейлисти",
|
||||
"MessageNoUserPlaylistsHelp": "Плейлистите за частни. Само създалият ги потребител ще може да ги вижда.",
|
||||
"MessageNotYetImplemented": "Още не е изпълнено",
|
||||
"MessageOr": "или",
|
||||
"MessagePauseChapter": "Пауза на глава",
|
||||
"MessagePlayChapter": "Пусни налчалото на глава",
|
||||
"MessagePlaylistCreateFromCollection": "Създай плейлист от колекция",
|
||||
"MessagePleaseWait": "Моля изчакайте...",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "Подкастът няма URL адрес на RSS feed за използване за съпоставяне",
|
||||
"MessagePodcastSearchField": "Въведи какво да търся или RSS емисия адрес",
|
||||
"MessageQuickEmbedInProgress": "Бързото вграждане е в процес на изпълнение",
|
||||
"MessageQuickEmbedQueue": "Поставено в опашката за бързо вграждане ({0} в опашката)",
|
||||
"MessageQuickMatchDescription": "Попълни празните детайли и корици с първия резултат от '{0}'. Не презаписва детайлите, освен ако не е активирана настройката 'Предпочети съвпадащи метаданни' на сървъра.",
|
||||
"MessageRemoveChapter": "Премахни глава",
|
||||
"MessageRemoveEpisodes": "Премахни {0} епизод(и)",
|
||||
|
@ -746,11 +880,43 @@
|
|||
"MessageResetChaptersConfirm": "Сигурни ли сте, че искате да нулирате главите и да отмените промените, които сте направили?",
|
||||
"MessageRestoreBackupConfirm": "Сигурни ли сте, че искате да възстановите архива създаден на",
|
||||
"MessageRestoreBackupWarning": "Възстановяването на архив ще презапише цялата база данни, намираща се в /config и кориците в /metadata/items & /metadata/authors.<br /><br />Архивите не променят файловете в папките на вашата библиотека. Ако сте активирали настройките на сървъра за съхранение на корици и метаданни в папките на вашата библиотека, те няма да бъдат архивирани или презаписани.<br /><br />Всички клиенти, използващи вашия сървър, ще бъдат автоматично обновени.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Изпълни всеки {0} в {1}",
|
||||
"MessageSearchResultsFor": "Резултати от търсенето за",
|
||||
"MessageSelected": "{0} избрани",
|
||||
"MessageServerCouldNotBeReached": "Сървърът не може да бъде достигнат",
|
||||
"MessageSetChaptersFromTracksDescription": "Задайте глави, като използвате всеки аудио файл като глава и заглавие на главата като име на аудио файла",
|
||||
"MessageShareExpiresIn": "Изтича след {0}",
|
||||
"MessageStartPlaybackAtTime": "Започни възпроизвеждане на \"{0}\" в {1}?",
|
||||
"MessageTaskDownloadingEpisodeDescription": "Изтегляне на епизод \"{0}\"",
|
||||
"MessageTaskEmbeddingMetadata": "Вграждане на метаданни",
|
||||
"MessageTaskEmbeddingMetadataDescription": "Вграждане на метаданни в аудиокнига \"{0}\"",
|
||||
"MessageTaskEncodingM4bDescription": "Кодиране на аудиокнига \"{0}\" в единичен m4b файл",
|
||||
"MessageTaskFailed": "Неуспешно",
|
||||
"MessageTaskFailedToBackupAudioFile": "Неуспешно създаване на разервно копие на аудио файл \"{0}\"",
|
||||
"MessageTaskFailedToCreateCacheDirectory": "Неуспешно създаване на директория за кеширане",
|
||||
"MessageTaskFailedToEmbedMetadataInFile": "Неуспешно вграждане на метаданни във файл \"{0}\"",
|
||||
"MessageTaskFailedToMergeAudioFiles": "Неуспешно сливане на аудио файловете",
|
||||
"MessageTaskFailedToMoveM4bFile": "Неуспешно преместване на m4b файл",
|
||||
"MessageTaskFailedToWriteMetadataFile": "Неуспешно записване на файла за метаданни",
|
||||
"MessageTaskMatchingBooksInLibrary": "Съответстващи книги в библиотека \"{0}\"",
|
||||
"MessageTaskNoFilesToScan": "Няма файлове за сканиране",
|
||||
"MessageTaskOpmlImport": "OPML импортиране",
|
||||
"MessageTaskOpmlImportDescription": "Създаване на подкасти от {0} RSS хранилки",
|
||||
"MessageTaskOpmlImportFeedDescription": "Импортиране на RSS хранилка \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "Създаване на подкаст \"{0}\"",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "На този път вече съществува подкаст",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Неуспешно създаване на подкаст",
|
||||
"MessageTaskOpmlImportFinished": "Добавени {0} подкаста",
|
||||
"MessageTaskOpmlParseFailed": "Неуспешно анализиране на OPML файла",
|
||||
"MessageTaskOpmlParseFastFail": "Невалиден OPML файл, не беше намерен нито <opml> таг нито <outline> таг",
|
||||
"MessageTaskOpmlParseNoneFound": "Няма намерени канали във OPML файла",
|
||||
"MessageTaskScanItemsAdded": "{0} добавени",
|
||||
"MessageTaskScanItemsMissing": "{0} липсващи",
|
||||
"MessageTaskScanItemsUpdated": "{0} обновени",
|
||||
"MessageTaskScanNoChangesNeeded": "Не са нужни промени",
|
||||
"MessageTaskScanningFileChanges": "Проверка за промени във файловете в \"{0}\"",
|
||||
"MessageTaskScanningLibrary": "Сканиране на \"{0}\" библиотека",
|
||||
"MessageTaskTargetDirectoryNotWritable": "Целевата директория не е достъпна за запис",
|
||||
"MessageThinking": "Мисля...",
|
||||
"MessageUploaderItemFailed": "Неуспешно качване",
|
||||
"MessageUploaderItemSuccess": "Успешно качване!",
|
||||
|
@ -768,11 +934,18 @@
|
|||
"NoteUploaderFoldersWithMediaFiles": "Папките с медийни файлове ще бъдат обработени като отделни елементи на библиотеката.",
|
||||
"NoteUploaderOnlyAudioFiles": "Ако качвате само аудио файлове, то всеки аудио файл ще бъде обработен като отделна аудиокнига.",
|
||||
"NoteUploaderUnsupportedFiles": "Неподдържаните файлове се игнорират. При избор или пускане на папка, други файлове, които не са в папка на елемент, се игнорират.",
|
||||
"NotificationOnBackupCompletedDescription": "Изпълнява се при завършване на създаване на резервно копие",
|
||||
"NotificationOnBackupFailedDescription": "Изпълнява се при неуспешено създаване на резервно копие",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Изпълнява се при автоматично изтегляне на подкаст епизод",
|
||||
"NotificationOnRSSFeedDisabledDescription": "Изпълнява се, когато автоматичното изтегляне на епизодите е деактивирано, поради твърде много неуспешни опити",
|
||||
"PlaceholderNewCollection": "Ново име на колекцията",
|
||||
"PlaceholderNewFolderPath": "Нов път на папката",
|
||||
"PlaceholderNewPlaylist": "Ново име на плейлиста",
|
||||
"PlaceholderSearch": "Търсене...",
|
||||
"PlaceholderSearchEpisode": "Търсене на Епизоди...",
|
||||
"StatsAuthorsAdded": "добаврени автори",
|
||||
"StatsBooksAdded": "добавени книги",
|
||||
"StatsBooksFinished": "завършени книги",
|
||||
"ToastAccountUpdateSuccess": "Успешно обновяване на акаунта",
|
||||
"ToastAuthorImageRemoveSuccess": "Авторската снимка е премахната",
|
||||
"ToastAuthorUpdateMerged": "Обновяване на автора сливано",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"HeaderPlaylist": "Llista de Reproducció",
|
||||
"HeaderPlaylistItems": "Elements de la Llista de Reproducció",
|
||||
"HeaderPodcastsToAdd": "Pòdcasts a afegir",
|
||||
"HeaderPresets": "Valors predefinits",
|
||||
"HeaderPreviewCover": "Previsualització de la Portada",
|
||||
"HeaderRSSFeedGeneral": "Detalls RSS",
|
||||
"HeaderRSSFeedIsOpen": "La Font RSS està oberta",
|
||||
|
@ -439,7 +440,7 @@
|
|||
"LabelMinute": "Minut",
|
||||
"LabelMinutes": "Minuts",
|
||||
"LabelMissing": "Absent",
|
||||
"LabelMissingEbook": "No té ebook",
|
||||
"LabelMissingEbook": "No té llibre electrònic",
|
||||
"LabelMissingSupplementaryEbook": "No té ebook complementari",
|
||||
"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.",
|
||||
|
@ -497,25 +498,25 @@
|
|||
"LabelPodcastType": "Tipus de pòdcast",
|
||||
"LabelPodcasts": "Pòdcasts",
|
||||
"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 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",
|
||||
"LabelProvider": "Proveïdor",
|
||||
"LabelProviderAuthorizationValue": "Valor de l'encapçalament d'autorització",
|
||||
"LabelPubDate": "Data de Publicació",
|
||||
"LabelPublishYear": "Any de Publicació",
|
||||
"LabelPubDate": "Data de publicació",
|
||||
"LabelPublishYear": "Any de publicació",
|
||||
"LabelPublishedDate": "Publicat {0}",
|
||||
"LabelPublishedDecade": "Dècada de Publicació",
|
||||
"LabelPublishedDecade": "Dècada de publicació",
|
||||
"LabelPublishedDecades": "Dècades Publicades",
|
||||
"LabelPublisher": "Editor",
|
||||
"LabelPublishers": "Editors",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Correu Electrònic Personalitzat del Propietari",
|
||||
"LabelRSSFeedCustomOwnerName": "Nom Personalitzat del Propietari",
|
||||
"LabelRSSFeedOpen": "Font RSS Oberta",
|
||||
"LabelRSSFeedPreventIndexing": "Evitar l'indexació",
|
||||
"LabelRSSFeedSlug": "Font RSS Slug",
|
||||
"LabelRSSFeedURL": "URL de la Font RSS",
|
||||
"LabelRSSFeedPreventIndexing": "Evita la indexació",
|
||||
"LabelRSSFeedSlug": "URL semàntic del canal RSS",
|
||||
"LabelRSSFeedURL": "URL del canal RSS",
|
||||
"LabelRandomly": "A l'atzar",
|
||||
"LabelReAddSeriesToContinueListening": "Reafegir la sèrie per continuar escoltant-la",
|
||||
"LabelRead": "Llegit",
|
||||
|
@ -524,45 +525,47 @@
|
|||
"LabelRecentSeries": "Sèries recents",
|
||||
"LabelRecentlyAdded": "Addicions recents",
|
||||
"LabelRecommended": "Recomanats",
|
||||
"LabelRedo": "Refer",
|
||||
"LabelRedo": "Refés",
|
||||
"LabelRegion": "Regió",
|
||||
"LabelReleaseDate": "Data d'Estrena",
|
||||
"LabelRemoveAllMetadataAbs": "Eliminar tots els fitxers metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Eliminar tots els fitxers metadata.json",
|
||||
"LabelRemoveCover": "Eliminar Coberta",
|
||||
"LabelReleaseDate": "Data d'estrena",
|
||||
"LabelRemoveAllMetadataAbs": "Elimina tots els fitxers metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Elimina tots els fitxers metadata.json",
|
||||
"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",
|
||||
"LabelRemoveMetadataFileHelp": "Elimina tots els fitxers metadata.json i metadata.abs de les teves carpetes {0}.",
|
||||
"LabelRowsPerPage": "Files per Pàgina",
|
||||
"LabelSearchTerm": "Cercar Terme",
|
||||
"LabelSearchTitle": "Cercar Títol",
|
||||
"LabelSearchTitleOrASIN": "Cercar Títol o ASIN",
|
||||
"LabelRemoveMetadataFileHelp": "Elimina tots els fitxers metadata.json i metadata.abs de les vostres carpetes {0}.",
|
||||
"LabelRowsPerPage": "Files per pàgina",
|
||||
"LabelSearchTerm": "Cerca terme",
|
||||
"LabelSearchTitle": "Cerca títol",
|
||||
"LabelSearchTitleOrASIN": "Cerca títol o ASIN",
|
||||
"LabelSeason": "Temporada",
|
||||
"LabelSeasonNumber": "Temporada #{0}",
|
||||
"LabelSelectAll": "Seleccionar tot",
|
||||
"LabelSelectAllEpisodes": "Seleccionar tots els episodis",
|
||||
"LabelSeasonNumber": "{0}a temporada",
|
||||
"LabelSelectAll": "Selecciona-ho tot",
|
||||
"LabelSelectAllEpisodes": "Selecciona tots els episodis",
|
||||
"LabelSelectEpisodesShowing": "Seleccionar els {0} episodis visibles",
|
||||
"LabelSelectUsers": "Seleccionar usuaris",
|
||||
"LabelSendEbookToDevice": "Enviar Ebook a...",
|
||||
"LabelSequence": "Seqüència",
|
||||
"LabelSerial": "En sèrie",
|
||||
"LabelSeries": "Sèries",
|
||||
"LabelSeriesName": "Nom de la Sèrie",
|
||||
"LabelSeriesProgress": "Progrés de la Sèrie",
|
||||
"LabelSeries": "Sèrie",
|
||||
"LabelSeriesName": "Nom de la sèrie",
|
||||
"LabelSeriesProgress": "Progrés de la sèrie",
|
||||
"LabelServerLogLevel": "Nivell de registre del servidor",
|
||||
"LabelServerYearReview": "Resum de l'any del servidor ({0})",
|
||||
"LabelSetEbookAsPrimary": "Establir com a principal",
|
||||
"LabelSetEbookAsSupplementary": "Establir com a suplementari",
|
||||
"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",
|
||||
"LabelSettingsAudiobooksOnly": "Només audiollibres",
|
||||
"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",
|
||||
"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",
|
||||
"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.",
|
||||
"LabelSettingsExperimentalFeatures": "Funcions Experimentals",
|
||||
"LabelSettingsExperimentalFeaturesHelp": "Funcions en desenvolupament que es beneficiarien dels teus comentaris i experiències de prova. Feu clic aquí per obrir una conversa a Github.",
|
||||
"LabelSettingsFindCovers": "Troba cobertes",
|
||||
"LabelSettingsHideSingleBookSeries": "Amaga les sèries amb un sol llibre",
|
||||
"LabelSettingsParseSubtitles": "Analitza els subtítols",
|
||||
"LabelSettingsSortingIgnorePrefixes": "Ignora els prefixos en ordenar",
|
||||
"LabelSettingsTimeFormat": "Format d'hora",
|
||||
|
@ -575,6 +578,8 @@
|
|||
"LabelSize": "Mida",
|
||||
"LabelSleepTimer": "Temporitzador de repòs",
|
||||
"LabelSlug": "Slug",
|
||||
"LabelSortAscending": "Ascendent",
|
||||
"LabelSortDescending": "Descendent",
|
||||
"LabelStart": "Inicia",
|
||||
"LabelStartTime": "Hora d'inici",
|
||||
"LabelStarted": "Iniciat",
|
||||
|
@ -662,19 +667,20 @@
|
|||
"LabelViewPlayerSettings": "Mostra els ajustaments del reproductor",
|
||||
"LabelViewQueue": "Mostra cua del reproductor",
|
||||
"LabelVolume": "Volum",
|
||||
"LabelWebRedirectURLsDescription": "Autoritza aquestes URL al teu proveïdor OAuth per permetre redirecció a l'aplicació web després d'iniciar sessió:",
|
||||
"LabelWebRedirectURLsDescription": "Autoritzeu aquests URL al vostre proveïdor OAuth per a permetre redirigir a l’aplicació web després d'iniciar sessió:",
|
||||
"LabelWebRedirectURLsSubfolder": "Subcarpeta per a URL de redirecció",
|
||||
"LabelWeekdaysToRun": "Executar en dies de la setmana",
|
||||
"LabelXBooks": "{0} llibres",
|
||||
"LabelXItems": "{0} elements",
|
||||
"LabelYearReviewHide": "Oculta resum de l'any",
|
||||
"LabelYearReviewShow": "Mostra resum de l'any",
|
||||
"LabelYourAudiobookDuration": "Duració del teu audiollibre",
|
||||
"LabelYourAudiobookDuration": "Duració del vostre audiollibre",
|
||||
"LabelYourBookmarks": "Els vostres marcadors",
|
||||
"LabelYourPlaylists": "Les teves llistes",
|
||||
"LabelYourPlaylists": "Les vostres llistes",
|
||||
"LabelYourProgress": "El vostre progrés",
|
||||
"MessageAddToPlayerQueue": "Afegeix a la cua del reproductor",
|
||||
"MessageAppriseDescription": "Per utilitzar aquesta funció, hauràs de tenir l'<a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">API d'Apprise</a> en funcionament o una API que gestioni resultats similars. <br/>La URL de l'API d'Apprise ha de tenir la mateixa ruta d'arxius que on s'envien les notificacions. Per exemple: si la teva API és a <code>http://192.168.1.1:8337</code>, llavors posaries <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Reengegueu el servidor després de desar perquè s'hi apliquin els canvis d'OIDC.",
|
||||
"MessageBackupsDescription": "Les còpies de seguretat inclouen: usuaris, progrés dels usuaris, detalls dels elements de la biblioteca, configuració del servidor i imatges a <code>/metadata/items</code> i <code>/metadata/authors</code>. Les còpies de seguretat <strong>NO</strong> inclouen cap fitxer guardat a la carpeta de la teva biblioteca.",
|
||||
"MessageBackupsLocationEditNote": "Nota: Actualitzar la ubicació de la còpia de seguretat no mourà ni modificarà les còpies existents",
|
||||
"MessageBackupsLocationNoEditNote": "Nota: La ubicació de la còpia de seguretat es defineix mitjançant una variable d'entorn i no es pot modificar aquí.",
|
||||
|
@ -685,7 +691,7 @@
|
|||
"MessageBookshelfNoRSSFeeds": "Cap font RSS està oberta",
|
||||
"MessageBookshelfNoResultsForFilter": "Cap resultat per al filtre «{0}: {1}»",
|
||||
"MessageBookshelfNoResultsForQuery": "Cap resultat per a la consulta",
|
||||
"MessageBookshelfNoSeries": "No tens cap sèrie",
|
||||
"MessageBookshelfNoSeries": "No teniu cap sèrie",
|
||||
"MessageChapterEndIsAfter": "El final del capítol és després del final del teu audiollibre",
|
||||
"MessageChapterErrorFirstNotZero": "El primer capítol ha de començar a 0",
|
||||
"MessageChapterErrorStartGteDuration": "El temps d'inici no és vàlid: ha de ser inferior a la durada de l'audiollibre",
|
||||
|
@ -712,7 +718,7 @@
|
|||
"MessageConfirmMarkSeriesFinished": "Segur que voleu marcar tots els llibres d'aquesta sèrie com a acabats?",
|
||||
"MessageConfirmMarkSeriesNotFinished": "Segur que voleu marcar tots els llibres d'aquesta sèrie com a no acabats?",
|
||||
"MessageConfirmNotificationTestTrigger": "Voleu activar aquesta notificació amb dades de prova?",
|
||||
"MessageConfirmPurgeCache": "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?",
|
||||
"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?",
|
||||
|
@ -748,6 +754,7 @@
|
|||
"MessageInvalidAsin": "L'ASIN no és vàlid",
|
||||
"MessageItemsSelected": "{0} elements seleccionats",
|
||||
"MessageItemsUpdated": "{0} elements actualitzats",
|
||||
"MessageJoinUsOn": "Uniu-vos a nosaltres a",
|
||||
"MessageLoading": "S'està carregant...",
|
||||
"MessageLoadingFolders": "S'estan carregant les carpetes...",
|
||||
"MessageMarkAllEpisodesFinished": "Marca tots els episodis com a acabats",
|
||||
|
@ -798,23 +805,25 @@
|
|||
"MessageQuickEmbedInProgress": "Integració ràpida en procés",
|
||||
"MessageQuickEmbedQueue": "En cua per a inserció ràpida ({0} en cua)",
|
||||
"MessageQuickMatchAllEpisodes": "Combina ràpidament tots els episodis",
|
||||
"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.",
|
||||
"MessageRemoveChapter": "Eliminar capítols",
|
||||
"MessageRemoveEpisodes": "Eliminar {0} episodi(s)",
|
||||
"MessageRemoveFromPlayerQueue": "Eliminar de la cua del reproductor",
|
||||
"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": "Elimina el capítol",
|
||||
"MessageRemoveEpisodes": "Elimina {0} episodi(s)",
|
||||
"MessageRemoveFromPlayerQueue": "Elimina de la cua del reproductor",
|
||||
"MessageRemoveUserWarning": "Segur que voleu suprimir permanentment l'usuari «{0}»?",
|
||||
"MessageReportBugsAndContribute": "Informa d'errors, sol·licita funcions i contribueix a",
|
||||
"MessageResetChaptersConfirm": "Segur que voleu desfer els canvis i revertir els capítols al seu estat original?",
|
||||
"MessageRestoreBackupConfirm": "Segur que voleu restaurar la còpia de seguretat creada a",
|
||||
"MessageRestoreBackupWarning": "Restaurar sobreescriurà tota la base de dades situada a /config i les imatges de portades a /metadata/items i /metadata/authors.<br /><br />La còpia de seguretat no modifica cap fitxer a les carpetes de la teva biblioteca. Si has activat l'opció del servidor per guardar portades i metadades a les carpetes de la biblioteca, aquests fitxers no es guarden ni sobreescriuen.<br /><br />Tots els clients que utilitzin el teu servidor s'actualitzaran automàticament.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Executa cada {0} a les {1}",
|
||||
"MessageSearchResultsFor": "Resultats de la cerca de",
|
||||
"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",
|
||||
"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>",
|
||||
"MessageShareExpiresIn": "Caduca en {0}",
|
||||
"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",
|
||||
"MessageTaskCanceledByUser": "Tasca cancel·lada per l'usuari",
|
||||
"MessageTaskDownloadingEpisodeDescription": "S'està baixant l'episodi «{0}»",
|
||||
|
@ -838,7 +847,7 @@
|
|||
"MessageTaskOpmlImportFeedFailed": "No s'ha pogut obtenir el canal del pòdcast",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "S'està creant el pòdcast «{0}»",
|
||||
"MessageTaskOpmlImportFeedPodcastExists": "El pòdcast ja existeix al camí",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "Error en crear el podcast",
|
||||
"MessageTaskOpmlImportFeedPodcastFailed": "No s'ha pogut crear el pòdcast",
|
||||
"MessageTaskOpmlImportFinished": "S'han afegit {0} pòdcasts",
|
||||
"MessageTaskOpmlParseFailed": "No s'ha pogut analitzar el fitxer OPML",
|
||||
"MessageTaskOpmlParseFastFail": "No s'ha trobat l'etiqueta <opml> o <outline> al fitxer OPML",
|
||||
|
@ -857,13 +866,13 @@
|
|||
"MessageValidCronExpression": "Expressió de cron vàlida",
|
||||
"MessageWatcherIsDisabledGlobally": "El watcher està desactivat globalment a la configuració del servidor",
|
||||
"MessageXLibraryIsEmpty": "La biblioteca {0} està buida!",
|
||||
"MessageYourAudiobookDurationIsLonger": "La durada del teu audiollibre és més llarga que la durada trobada",
|
||||
"MessageYourAudiobookDurationIsShorter": "La durada del teu audiollibre és més curta que la durada trobada",
|
||||
"MessageYourAudiobookDurationIsLonger": "La durada del vostre audiollibre és major que la durada trobada",
|
||||
"MessageYourAudiobookDurationIsShorter": "La durada del vostre audiollibre és menor que la durada trobada",
|
||||
"NoteChangeRootPassword": "L'usuari Root és l'únic usuari que pot no tenir una contrasenya",
|
||||
"NoteChapterEditorTimes": "Nota: El temps d'inici del primer capítol ha de romandre a 0:00, i el temps d'inici de l'últim capítol no pot superar la durada de l'audiollibre.",
|
||||
"NoteFolderPicker": "Nota: Les carpetes ja assignades no es mostraran",
|
||||
"NoteRSSFeedPodcastAppsHttps": "Advertència: La majoria d'aplicacions de podcast requereixen que la URL de la font RSS utilitzi HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Advertència: Un o més dels teus episodis no tenen data de publicació. Algunes aplicacions de podcast ho requereixen.",
|
||||
"NoteChapterEditorTimes": "Nota: el temps d'inici del primer capítol ha de romandre a 0:00, i el temps d'inici de l'últim capítol no pot superar la durada de l'audiollibre.",
|
||||
"NoteFolderPicker": "Nota: les carpetes ja assignades no es mostraran",
|
||||
"NoteRSSFeedPodcastAppsHttps": "Avís: la majoria d'aplicacions de pòdcast requereixen que l'URL del canal RSS utilitzi HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "Avís: un o més dels vostres episodis no tenen data de publicació. Algunes aplicacions de pòdcast ho requereixen.",
|
||||
"NoteUploaderFoldersWithMediaFiles": "Les carpetes amb fitxers multimèdia es gestionaran com a elements separats a la biblioteca.",
|
||||
"NoteUploaderOnlyAudioFiles": "Si només puges fitxers d'àudio, cada fitxer es gestionarà com un audiollibre separat.",
|
||||
"NoteUploaderUnsupportedFiles": "Els fitxers no compatibles seran ignorats. Si selecciona o arrossega una carpeta, els fitxers que no estiguin dins d'una subcarpeta seran ignorats.",
|
||||
|
@ -872,7 +881,7 @@
|
|||
"NotificationOnEpisodeDownloadedDescription": "S'activa quan es descarrega automàticament un episodi d'un podcast",
|
||||
"NotificationOnTestDescription": "Esdeveniment per provar el sistema de notificacions",
|
||||
"PlaceholderNewCollection": "Nou nom de la col·lecció",
|
||||
"PlaceholderNewFolderPath": "Nova ruta de carpeta",
|
||||
"PlaceholderNewFolderPath": "Camí de carpeta nou",
|
||||
"PlaceholderNewPlaylist": "Nou nom de la llista de reproducció",
|
||||
"PlaceholderSearch": "Cerca...",
|
||||
"PlaceholderSearchEpisode": "Cerca d'episodis...",
|
||||
|
@ -914,6 +923,7 @@
|
|||
"ToastBackupRestoreFailed": "Error en restaurar la còpia de seguretat",
|
||||
"ToastBackupUploadFailed": "Error en carregar la còpia de seguretat",
|
||||
"ToastBackupUploadSuccess": "Còpia de seguretat carregada",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "S'han aplicat els detalls als elements",
|
||||
"ToastBatchDeleteFailed": "Error en l'eliminació per lots",
|
||||
"ToastBatchDeleteSuccess": "Eliminació per lots correcte",
|
||||
"ToastBatchQuickMatchFailed": "Error en la sincronització ràpida per lots!",
|
||||
|
@ -926,6 +936,8 @@
|
|||
"ToastCachePurgeFailed": "Error en purgar la memòria cau",
|
||||
"ToastCachePurgeSuccess": "Memòria cau purgada amb èxit",
|
||||
"ToastChaptersHaveErrors": "Els capítols tenen errors",
|
||||
"ToastChaptersInvalidShiftAmountLast": "La quantitat de desplaçament no és vàlida. L'hora d'inici de l'últim capítol s'estendria més enllà de la durada d'aquest audiollibre.",
|
||||
"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",
|
||||
"ToastChaptersRemoved": "Capítols eliminats",
|
||||
"ToastChaptersUpdated": "Capítols actualitzats",
|
||||
|
@ -933,6 +945,7 @@
|
|||
"ToastCollectionRemoveSuccess": "Col·lecció eliminada",
|
||||
"ToastCollectionUpdateSuccess": "Col·lecció actualitzada",
|
||||
"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",
|
||||
"ToastDeleteFileSuccess": "Fitxer suprimit",
|
||||
"ToastDeviceAddFailed": "Error en afegir el dispositiu",
|
||||
|
@ -970,7 +983,7 @@
|
|||
"ToastLibraryScanStarted": "S'ha iniciat l'escaneig de la biblioteca",
|
||||
"ToastLibraryUpdateSuccess": "S'ha actualitzat la biblioteca «{0}»",
|
||||
"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 hi ha cap fitxer metadata.{0} a la biblioteca",
|
||||
"ToastMetadataFilesRemovedNoneRemoved": "No s'ha eliminat cap fitxer metadata.{0}",
|
||||
"ToastMetadataFilesRemovedSuccess": "{0} metadades eliminades en {1} arxius",
|
||||
|
@ -980,18 +993,18 @@
|
|||
"ToastNewEpisodesFound": "{0} episodi(s) nou(s) trobat(s)",
|
||||
"ToastNewUserCreatedFailed": "No s'ha pogut crear el compte: «{0}»",
|
||||
"ToastNewUserCreatedSuccess": "Nou compte creat",
|
||||
"ToastNewUserLibraryError": "Ha de seleccionar almenys una biblioteca",
|
||||
"ToastNewUserPasswordError": "Necessites una contrasenya, només el root pot estar sense contrasenya",
|
||||
"ToastNewUserTagError": "Selecciona almenys una etiqueta",
|
||||
"ToastNewUserUsernameError": "Introdueix un nom d'usuari",
|
||||
"ToastNewUserLibraryError": "S'ha de seleccionar almenys una biblioteca",
|
||||
"ToastNewUserPasswordError": "Cal una contrasenya; només l'usuari primari pot estar sense contrasenya",
|
||||
"ToastNewUserTagError": "S'ha de seleccionar almenys una etiqueta",
|
||||
"ToastNewUserUsernameError": "Introduïu un nom d'usuari",
|
||||
"ToastNoNewEpisodesFound": "No s'han trobat nous episodis",
|
||||
"ToastNoRSSFeed": "El pòdcast no té canal RSS",
|
||||
"ToastNoUpdatesNecessary": "No cal actualitzar",
|
||||
"ToastNotificationCreateFailed": "Error en crear la notificació",
|
||||
"ToastNotificationDeleteFailed": "Error en eliminar la notificació",
|
||||
"ToastNotificationCreateFailed": "No s'ha pogut crear la notificació",
|
||||
"ToastNotificationDeleteFailed": "No s'ha pogut suprimir la notificació",
|
||||
"ToastNotificationFailedMaximum": "El nombre màxim d'intents fallits ha de ser ≥ 0",
|
||||
"ToastNotificationQueueMaximum": "La cua de notificació màxima ha de ser ≥ 0",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Configuració de notificació actualitzada",
|
||||
"ToastNotificationSettingsUpdateSuccess": "S'han actualitzat els paràmetres de notificacions",
|
||||
"ToastNotificationTestTriggerFailed": "No s'ha pogut activar la notificació de prova",
|
||||
"ToastNotificationTestTriggerSuccess": "Notificació de prova activada",
|
||||
"ToastNotificationUpdateSuccess": "Notificació actualitzada",
|
||||
|
@ -1024,7 +1037,8 @@
|
|||
"ToastScanFailed": "No s'ha pogut escanejar l'element de la biblioteca",
|
||||
"ToastSelectAtLeastOneUser": "Selecciona almenys un usuari",
|
||||
"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",
|
||||
"ToastSeriesUpdateSuccess": "Sèrie actualitzada",
|
||||
"ToastServerSettingsUpdateSuccess": "Configuració del servidor actualitzada",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Přidat",
|
||||
"ButtonAddApiKey": "Přidat API klíč",
|
||||
"ButtonAddChapters": "Přidat kapitoly",
|
||||
"ButtonAddDevice": "Přidat zařízení",
|
||||
"ButtonAddLibrary": "Přidat knihovnu",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Vybrat složku",
|
||||
"ButtonChooseFiles": "Vybrat soubory",
|
||||
"ButtonClearFilter": "Vymazat filtr",
|
||||
"ButtonClose": "Zavřít",
|
||||
"ButtonCloseFeed": "Zavřít kanál",
|
||||
"ButtonCloseSession": "Zavřít otevřenou relaci",
|
||||
"ButtonCollections": "Kolekce",
|
||||
|
@ -119,6 +121,7 @@
|
|||
"HeaderAccount": "Účet",
|
||||
"HeaderAddCustomMetadataProvider": "Přidat vlastního poskytovatele metadat",
|
||||
"HeaderAdvanced": "Pokročilé",
|
||||
"HeaderApiKeys": "API klíče",
|
||||
"HeaderAppriseNotificationSettings": "Nastavení oznámení Apprise",
|
||||
"HeaderAudioTracks": "Zvukové stopy",
|
||||
"HeaderAudiobookTools": "Nástroje pro správu souborů audioknih",
|
||||
|
@ -154,7 +157,7 @@
|
|||
"HeaderListeningSessions": "Poslechové relace",
|
||||
"HeaderListeningStats": "Statistiky poslechu",
|
||||
"HeaderLogin": "Přihlásit",
|
||||
"HeaderLogs": "Záznamy",
|
||||
"HeaderLogs": "Logy",
|
||||
"HeaderManageGenres": "Spravovat žánry",
|
||||
"HeaderManageTags": "Spravovat štítky",
|
||||
"HeaderMapDetails": "Podrobnosti mapování",
|
||||
|
@ -162,6 +165,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Pořadí priorit metadat",
|
||||
"HeaderMetadataToEmbed": "Metadata k vložení",
|
||||
"HeaderNewAccount": "Nový účet",
|
||||
"HeaderNewApiKey": "Nový API klíč",
|
||||
"HeaderNewLibrary": "Nová knihovna",
|
||||
"HeaderNotificationCreate": "Vytvořit notifikaci",
|
||||
"HeaderNotificationUpdate": "Aktualizovat notifikaci",
|
||||
|
@ -177,6 +181,7 @@
|
|||
"HeaderPlaylist": "Seznam skladeb",
|
||||
"HeaderPlaylistItems": "Položky seznamu přehrávání",
|
||||
"HeaderPodcastsToAdd": "Podcasty k přidání",
|
||||
"HeaderPresets": "Předvolba",
|
||||
"HeaderPreviewCover": "Náhled obálky",
|
||||
"HeaderRSSFeedGeneral": "Podrobnosti o RSS",
|
||||
"HeaderRSSFeedIsOpen": "Informační kanál RSS je otevřený",
|
||||
|
@ -194,6 +199,7 @@
|
|||
"HeaderSettingsExperimental": "Experimentální funkce",
|
||||
"HeaderSettingsGeneral": "Obecné",
|
||||
"HeaderSettingsScanner": "Skener",
|
||||
"HeaderSettingsSecurity": "Zabezpečení",
|
||||
"HeaderSettingsWebClient": "Webový klient",
|
||||
"HeaderSleepTimer": "Časovač vypnutí",
|
||||
"HeaderStatsLargestItems": "Největší položky",
|
||||
|
@ -205,6 +211,7 @@
|
|||
"HeaderTableOfContents": "Obsah",
|
||||
"HeaderTools": "Nástroje",
|
||||
"HeaderUpdateAccount": "Aktualizovat účet",
|
||||
"HeaderUpdateApiKey": "Aktualizovat API klíč",
|
||||
"HeaderUpdateAuthor": "Aktualizovat autora",
|
||||
"HeaderUpdateDetails": "Aktualizovat podrobnosti",
|
||||
"HeaderUpdateLibrary": "Aktualizovat knihovnu",
|
||||
|
@ -234,6 +241,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Všichni uživatelé kromě hostů",
|
||||
"LabelAllUsersIncludingGuests": "Všichni uživatelé včetně hostů",
|
||||
"LabelAlreadyInYourLibrary": "Již ve vaší knihovně",
|
||||
"LabelApiKeyCreated": "API klíč \"{0}\" byl úspěšně vytvořen.",
|
||||
"LabelApiKeyCreatedDescription": "Zkopírujte si API klíč nyní, později již nebude možné jej zobrazit.",
|
||||
"LabelApiKeyUser": "Vydávat se za uživatele",
|
||||
"LabelApiKeyUserDescription": "Tento API klíč bude mít stejná oprávnění jako uživatel za něhož vystupuje. V protokolech to bude vypadat jako kdyby požadavky vytvářel přímo daný uživatel.",
|
||||
"LabelApiToken": "API Token",
|
||||
"LabelAppend": "Připojit",
|
||||
"LabelAudioBitrate": "Bitový tok zvuku (např. 128k)",
|
||||
|
@ -283,6 +294,7 @@
|
|||
"LabelContinueListening": "Pokračovat v poslechu",
|
||||
"LabelContinueReading": "Pokračovat ve čtení",
|
||||
"LabelContinueSeries": "Pokračovat v sérii",
|
||||
"LabelCorsAllowed": "Povolené CORS Origins",
|
||||
"LabelCover": "Obálka",
|
||||
"LabelCoverImageURL": "URL obrázku obálky",
|
||||
"LabelCoverProvider": "Poskytovatel obálky",
|
||||
|
@ -345,11 +357,15 @@
|
|||
"LabelExample": "Příklad",
|
||||
"LabelExpandSeries": "Rozbalit série",
|
||||
"LabelExpandSubSeries": "Rozbalit podsérie",
|
||||
"LabelExplicit": "Explicitní",
|
||||
"LabelExpired": "Expirovaný",
|
||||
"LabelExpiresAt": "Expiruje v",
|
||||
"LabelExpiresInSeconds": "Expiruje za (sekundy)",
|
||||
"LabelExpiresNever": "Nikdy",
|
||||
"LabelExplicit": "Explicitně",
|
||||
"LabelExplicitChecked": "Explicitní (zaškrtnuto)",
|
||||
"LabelExplicitUnchecked": "Není explicitní (nezaškrtnuto)",
|
||||
"LabelExportOPML": "Export OPML",
|
||||
"LabelFeedURL": "URL zdroje",
|
||||
"LabelFeedURL": "URL kanálu",
|
||||
"LabelFetchingMetadata": "Získávání metadat",
|
||||
"LabelFile": "Soubor",
|
||||
"LabelFileBirthtime": "Čas vzniku souboru",
|
||||
|
@ -404,6 +420,7 @@
|
|||
"LabelLanguages": "Jazyky",
|
||||
"LabelLastBookAdded": "Poslední kniha přidána",
|
||||
"LabelLastBookUpdated": "Poslední kniha aktualizována",
|
||||
"LabelLastProgressDate": "Poslední pokrok: {0}",
|
||||
"LabelLastSeen": "Naposledy viděno",
|
||||
"LabelLastTime": "Naposledy",
|
||||
"LabelLastUpdate": "Poslední aktualizace",
|
||||
|
@ -416,6 +433,7 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Žádné {0}",
|
||||
"LabelLibraryItem": "Položka knihovny",
|
||||
"LabelLibraryName": "Název knihovny",
|
||||
"LabelLibrarySortByProgress": "Aktualizace pokroku",
|
||||
"LabelLimit": "Omezit",
|
||||
"LabelLineSpacing": "Řádkování",
|
||||
"LabelListenAgain": "Poslouchat znovu",
|
||||
|
@ -424,6 +442,7 @@
|
|||
"LabelLogLevelWarn": "Varovat",
|
||||
"LabelLookForNewEpisodesAfterDate": "Hledat nové epizody po tomto datu",
|
||||
"LabelLowestPriority": "Nejnižší priorita",
|
||||
"LabelMatchConfidence": "Jistota",
|
||||
"LabelMatchExistingUsersBy": "Přiřadit stávající uživatele podle",
|
||||
"LabelMatchExistingUsersByDescription": "Slouží k propojení stávajících uživatelů. Po propojení budou uživatelé přiřazeni k jedinečnému ID od poskytovatele SSO",
|
||||
"LabelMaxEpisodesToDownload": "Maximální # epizod pro stažení. Použijte 0 pro bez omezení.",
|
||||
|
@ -454,6 +473,7 @@
|
|||
"LabelNewestEpisodes": "Nejnovější epizody",
|
||||
"LabelNextBackupDate": "Datum příští zálohy",
|
||||
"LabelNextScheduledRun": "Další naplánované spuštění",
|
||||
"LabelNoApiKeys": "Žádné API klíče",
|
||||
"LabelNoCustomMetadataProviders": "Žádní vlastní poskytovatelé metadat",
|
||||
"LabelNoEpisodesSelected": "Nebyly vybrány žádné epizody",
|
||||
"LabelNotFinished": "Nedokončeno",
|
||||
|
@ -513,9 +533,9 @@
|
|||
"LabelPublishers": "Vydavatelé",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Vlastní e-mail 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í",
|
||||
"LabelRSSFeedSlug": "RSS kanál Slug",
|
||||
"LabelRSSFeedSlug": "Klíčové slovo kanálu RSS",
|
||||
"LabelRSSFeedURL": "URL RSS kanálu",
|
||||
"LabelRandomly": "Náhodně",
|
||||
"LabelReAddSeriesToContinueListening": "Znovu přidat sérii k pokračování poslechu",
|
||||
|
@ -530,6 +550,7 @@
|
|||
"LabelReleaseDate": "Datum vydání",
|
||||
"LabelRemoveAllMetadataAbs": "Odebrat všechny soubory metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Smazat všechny soubory metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Odebrat úvod a závěr Audible z kapitol",
|
||||
"LabelRemoveCover": "Odstranit obálku",
|
||||
"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}.",
|
||||
|
@ -542,6 +563,7 @@
|
|||
"LabelSelectAll": "Vybrat vše",
|
||||
"LabelSelectAllEpisodes": "Vybrat všechny epizody",
|
||||
"LabelSelectEpisodesShowing": "Vyberte {0} epizody, které se zobrazují",
|
||||
"LabelSelectUser": "Vybrat uživatele",
|
||||
"LabelSelectUsers": "Vybrat uživatele",
|
||||
"LabelSendEbookToDevice": "Odeslat e-knihu do...",
|
||||
"LabelSequence": "Sekvence",
|
||||
|
@ -549,7 +571,7 @@
|
|||
"LabelSeries": "Série",
|
||||
"LabelSeriesName": "Název série",
|
||||
"LabelSeriesProgress": "Průběh série",
|
||||
"LabelServerLogLevel": "Úroveň protokolu serveru",
|
||||
"LabelServerLogLevel": "Úroveň Logování serveru",
|
||||
"LabelServerYearReview": "Přehled roku na serveru ({0})",
|
||||
"LabelSetEbookAsPrimary": "Nastavit jako primární",
|
||||
"LabelSetEbookAsSupplementary": "Nastavit jako doplňkové",
|
||||
|
@ -705,6 +727,10 @@
|
|||
"LabelYourProgress": "Váš pokrok",
|
||||
"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>.",
|
||||
"MessageAsinCheck": "Ujistěte se, že používáte ASIN ze správného regionu Audible a ne z Amazonu.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Zastaralé API tokeny budou v budoucnu odstraněny. Použijte místo nich <a href=\"/config/api-keys\">API klíče</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Po uložení restartujte server, aby se změny OIDC použily.",
|
||||
"MessageAuthenticationSecurityMessage": "Bezpečnost autentizace byla vylepšena. Všichni uživatelé se musí znovu přihlásit.",
|
||||
"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",
|
||||
"MessageBackupsLocationNoEditNote": "Poznámka: Umístění záloh je nastavené z proměnných prostředí a nelze zde změnit.",
|
||||
|
@ -723,8 +749,10 @@
|
|||
"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",
|
||||
"MessageChapterStartIsAfter": "Začátek kapitoly přesahuje konec audioknihy",
|
||||
"MessageChaptersNotFound": "Kapitoly nenalezeny",
|
||||
"MessageCheckingCron": "Kontrola cronu...",
|
||||
"MessageConfirmCloseFeed": "Opravdu chcete zavřít tento kanál?",
|
||||
"MessageConfirmDeleteApiKey": "Opravdu chcete vymazat API klíč \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Opravdu chcete smazat zálohu pro {0}?",
|
||||
"MessageConfirmDeleteDevice": "Opravdu chcete vymazat zařízení e-reader \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Tento krok smaže soubor ze souborového systému. Jsi si jisti?",
|
||||
|
@ -752,6 +780,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Opravdu chcete odstranit autora \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Opravdu chcete odstranit kolekci \"{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?",
|
||||
"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ě?",
|
||||
|
@ -777,14 +806,17 @@
|
|||
"MessageFeedURLWillBe": "URL zdroje bude {0}",
|
||||
"MessageFetching": "Načítání...",
|
||||
"MessageForceReScanDescription": "znovu prohledá všechny soubory jako při novém skenování. ID3 tagy zvukových souborů OPF soubory a textové soubory budou skenovány jako nové.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} poslechnuto</strong> na {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Žádné relace poslouchání na {0}",
|
||||
"MessageImportantNotice": "Důležité upozornění!",
|
||||
"MessageInsertChapterBelow": "Vložit kapitolu níže",
|
||||
"MessageInvalidAsin": "Neplatný ASIN",
|
||||
"MessageItemsSelected": "{0} vybraných položek",
|
||||
"MessageItemsUpdated": "{0} položky byly aktualizovány",
|
||||
"MessageJoinUsOn": "Přidejte se k nám",
|
||||
"MessageLoading": "Načítá se...",
|
||||
"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!",
|
||||
"MessageM4BFinished": "M4B dokončen!",
|
||||
"MessageMapChapterTitles": "Mapování názvů kapitol ke stávajícím kapitolám audioknihy bez úpravy časových razítek",
|
||||
|
@ -808,11 +840,11 @@
|
|||
"MessageNoEpisodes": "Žádné epizody",
|
||||
"MessageNoFoldersAvailable": "Nejsou k dispozici žádné složky",
|
||||
"MessageNoGenres": "Žádné žánry",
|
||||
"MessageNoIssues": "Žádné výtisk",
|
||||
"MessageNoIssues": "Žádné problémy",
|
||||
"MessageNoItems": "Žádné položky",
|
||||
"MessageNoItemsFound": "Nebyly nalezeny žádné položky",
|
||||
"MessageNoListeningSessions": "Žádné poslechové relace",
|
||||
"MessageNoLogs": "Žádné protokoly",
|
||||
"MessageNoLogs": "Žádné logy",
|
||||
"MessageNoMediaProgress": "Žádný průběh médií",
|
||||
"MessageNoNotifications": "Žádná oznámení",
|
||||
"MessageNoPodcastFeed": "Neplatný podcast: Žádný kanál",
|
||||
|
@ -850,6 +882,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Spusť každý {0} v {1}",
|
||||
"MessageSearchResultsFor": "Výsledky hledání pro",
|
||||
"MessageSelected": "{0} vybráno",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Sekvence série nesmí obsahovat mezery",
|
||||
"MessageServerCouldNotBeReached": "Server je nedostupný",
|
||||
"MessageSetChaptersFromTracksDescription": "Nastavit kapitoly jako kapitolu a název kapitoly jako název zvukového souboru",
|
||||
"MessageShareExpirationWillBe": "Expiruje <strong>{0}</strong>",
|
||||
|
@ -911,6 +944,8 @@
|
|||
"NotificationOnBackupCompletedDescription": "Spuštěno po dokončení zálohování",
|
||||
"NotificationOnBackupFailedDescription": "Spuštěno pokud zálohování selže",
|
||||
"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",
|
||||
"PlaceholderNewCollection": "Nový název kolekce",
|
||||
"PlaceholderNewFolderPath": "Nová cesta ke složce",
|
||||
|
@ -955,7 +990,7 @@
|
|||
"ToastBackupRestoreFailed": "Nepodařilo se obnovit zálohu",
|
||||
"ToastBackupUploadFailed": "Nepodařilo se nahrát zálohu",
|
||||
"ToastBackupUploadSuccess": "Záloha nahrána",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Detaily aplikované na položky",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Detaily byly aplikované na položky",
|
||||
"ToastBatchDeleteFailed": "Hromadné smazání selhalo",
|
||||
"ToastBatchDeleteSuccess": "Hromadné smazání proběhlo úspěšně",
|
||||
"ToastBatchQuickMatchFailed": "Rychlá schoda dávky se nezdařila!",
|
||||
|
@ -968,6 +1003,8 @@
|
|||
"ToastCachePurgeFailed": "Nepodařilo se vyčistit mezipaměť",
|
||||
"ToastCachePurgeSuccess": "Vyrovnávací paměť úspěšně vyčištěna",
|
||||
"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",
|
||||
"ToastChaptersRemoved": "Kapitoly odstraněny",
|
||||
"ToastChaptersUpdated": "Kapitola aktualizována",
|
||||
|
@ -989,6 +1026,8 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Fronta stahování epizod je prázdná",
|
||||
"ToastEpisodeUpdateSuccess": "{0} epizod aktualizováno",
|
||||
"ToastErrorCannotShare": "Na tomto zařízení nelze nativně sdílet",
|
||||
"ToastFailedToCreate": "Nepodařilo se vytvořit",
|
||||
"ToastFailedToDelete": "Nepodařilo se odstranit",
|
||||
"ToastFailedToLoadData": "Nepodařilo se načíst data",
|
||||
"ToastFailedToMatch": "Nepodařilo se spárovat",
|
||||
"ToastFailedToShare": "Sdílení selhalo",
|
||||
|
@ -996,6 +1035,7 @@
|
|||
"ToastInvalidImageUrl": "Neplatná URL obrázku",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Neplatný maximální počet epizod ke stažení",
|
||||
"ToastInvalidUrl": "Neplatná URL",
|
||||
"ToastInvalidUrls": "Alespoň jedna URL je neplatná",
|
||||
"ToastItemCoverUpdateSuccess": "Obálka předmětu byl aktualizována",
|
||||
"ToastItemDeletedFailed": "Smazání položky selhalo",
|
||||
"ToastItemDeletedSuccess": "Položka smazána",
|
||||
|
@ -1020,6 +1060,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Musí mít minimálně jednu cestu",
|
||||
"ToastNameEmailRequired": "Jméno a email jsou vyžadovány",
|
||||
"ToastNameRequired": "Jméno je vyžadováno",
|
||||
"ToastNewApiKeyUserError": "Je nutné vybrat uživatele",
|
||||
"ToastNewEpisodesFound": "{0} nových epizod bylo nalezeno",
|
||||
"ToastNewUserCreatedFailed": "Chyba při vytváření účtu: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Vytvořen nový účet",
|
||||
|
@ -1088,7 +1129,7 @@
|
|||
"ToastUnlinkOpenIdFailed": "Chyba při odpárování 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á podsložku nahrávané cesty.",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Položka \"{0}\" používá podadresář cesty pro nahrání.",
|
||||
"ToastUserDeleteFailed": "Nepodařilo se smazat uživatele",
|
||||
"ToastUserDeleteSuccess": "Uživatel smazán",
|
||||
"ToastUserPasswordChangeSuccess": "Heslo bylo změněno úspěšně",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Tilføj",
|
||||
"ButtonAddApiKey": "Tilføj API-nøgle",
|
||||
"ButtonAddChapters": "Tilføj kapitler",
|
||||
"ButtonAddDevice": "Tilføj enhed",
|
||||
"ButtonAddLibrary": "Tilføj Bibliotek",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Vælg en mappe",
|
||||
"ButtonChooseFiles": "Vælg filer",
|
||||
"ButtonClearFilter": "Ryd filter",
|
||||
"ButtonClose": "Luk",
|
||||
"ButtonCloseFeed": "Luk feed",
|
||||
"ButtonCloseSession": "Luk Åben Session",
|
||||
"ButtonCollections": "Samlinger",
|
||||
|
@ -119,6 +121,7 @@
|
|||
"HeaderAccount": "Konto",
|
||||
"HeaderAddCustomMetadataProvider": "Tilføj Brugerdefineret Metadataudbyder",
|
||||
"HeaderAdvanced": "Avanceret",
|
||||
"HeaderApiKeys": "API-nøgler",
|
||||
"HeaderAppriseNotificationSettings": "Apprise Notifikationsindstillinger",
|
||||
"HeaderAudioTracks": "Lydspor",
|
||||
"HeaderAudiobookTools": "Audiobog Filhåndteringsværktøjer",
|
||||
|
@ -162,6 +165,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Metadata-prioritet",
|
||||
"HeaderMetadataToEmbed": "Metadata til indlejring",
|
||||
"HeaderNewAccount": "Ny Konto",
|
||||
"HeaderNewApiKey": "Ny API-nøgle",
|
||||
"HeaderNewLibrary": "Nyt Bibliotek",
|
||||
"HeaderNotificationCreate": "Opret Notifikation",
|
||||
"HeaderNotificationUpdate": "Updater Notifikation",
|
||||
|
@ -177,6 +181,7 @@
|
|||
"HeaderPlaylist": "Afspilningsliste",
|
||||
"HeaderPlaylistItems": "Afspilningsliste Elementer",
|
||||
"HeaderPodcastsToAdd": "Podcasts til Tilføjelse",
|
||||
"HeaderPresets": "Forudindstillinger",
|
||||
"HeaderPreviewCover": "Forhåndsvis Omslag",
|
||||
"HeaderRSSFeedGeneral": "RSS Detaljer",
|
||||
"HeaderRSSFeedIsOpen": "RSS Feed er Åben",
|
||||
|
@ -205,6 +210,7 @@
|
|||
"HeaderTableOfContents": "Indholdsfortegnelse",
|
||||
"HeaderTools": "Værktøjer",
|
||||
"HeaderUpdateAccount": "Opdater Konto",
|
||||
"HeaderUpdateApiKey": "Opdater API-nøgle",
|
||||
"HeaderUpdateAuthor": "Opdater Forfatter",
|
||||
"HeaderUpdateDetails": "Opdater Detaljer",
|
||||
"HeaderUpdateLibrary": "Opdater Bibliotek",
|
||||
|
@ -234,6 +240,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Alle bruger eksklusiv gæster",
|
||||
"LabelAllUsersIncludingGuests": "Alle bruger inklusiv gæster",
|
||||
"LabelAlreadyInYourLibrary": "Allerede i dit bibliotek",
|
||||
"LabelApiKeyCreated": "API-nøgle\"{0}\" oprettet succesfuldt.",
|
||||
"LabelApiKeyCreatedDescription": "Sørg for at kopiere API-nøglen nu, da du ikke vil kunne se den igen.",
|
||||
"LabelApiKeyUser": "Ret på vegne af brugeren",
|
||||
"LabelApiKeyUserDescription": "Denne API-nøgle vil have de samme tilladelser som den bruger, den handler på vegne af. Dette vil fremgå på samme måde i logfiler, som hvis brugeren foretog anmodningen.",
|
||||
"LabelApiToken": "API Token",
|
||||
"LabelAppend": "Tilføj",
|
||||
"LabelAudioBitrate": "Lydbitrate (f.eks. 128k)",
|
||||
|
@ -286,7 +296,7 @@
|
|||
"LabelCover": "Omslag",
|
||||
"LabelCoverImageURL": "Omslagsbillede URL",
|
||||
"LabelCoverProvider": "Cover billede udbyder",
|
||||
"LabelCreatedAt": "Oprettet Kl.",
|
||||
"LabelCreatedAt": "Oprettet d.",
|
||||
"LabelCronExpression": "Cron Udtryk",
|
||||
"LabelCurrent": "Aktuel",
|
||||
"LabelCurrently": "Aktuelt:",
|
||||
|
@ -345,6 +355,10 @@
|
|||
"LabelExample": "Eksempel",
|
||||
"LabelExpandSeries": "Udfold serie",
|
||||
"LabelExpandSubSeries": "Udfold underserie",
|
||||
"LabelExpired": "Udløbet",
|
||||
"LabelExpiresAt": "Udløbsdato",
|
||||
"LabelExpiresInSeconds": "Udløber om (seconds)",
|
||||
"LabelExpiresNever": "Aldrig",
|
||||
"LabelExplicit": "Eksplisit",
|
||||
"LabelExplicitChecked": "Eksplicit (markeret)",
|
||||
"LabelExplicitUnchecked": "Ikke eksplicit (ikke markeret)",
|
||||
|
@ -454,6 +468,7 @@
|
|||
"LabelNewestEpisodes": "Nyeste episoder",
|
||||
"LabelNextBackupDate": "Næste sikkerhedskopi dato",
|
||||
"LabelNextScheduledRun": "Næste planlagte kørsel",
|
||||
"LabelNoApiKeys": "Ingen API-nøgler",
|
||||
"LabelNoCustomMetadataProviders": "Ingen brugerdefinerede metadata udbydere",
|
||||
"LabelNoEpisodesSelected": "Ingen episoder valgt",
|
||||
"LabelNotFinished": "Ikke færdig",
|
||||
|
@ -513,7 +528,7 @@
|
|||
"LabelPublishers": "Forlag",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Brugerdefineret ejerens e-mail",
|
||||
"LabelRSSFeedCustomOwnerName": "Brugerdefineret ejerens navn",
|
||||
"LabelRSSFeedOpen": "Åben RSS-feed",
|
||||
"LabelRSSFeedOpen": "RSS-feed åbent",
|
||||
"LabelRSSFeedPreventIndexing": "Forhindrer indeksering",
|
||||
"LabelRSSFeedSlug": "RSS-feed-slug",
|
||||
"LabelRSSFeedURL": "RSS-feed-URL",
|
||||
|
@ -530,6 +545,7 @@
|
|||
"LabelReleaseDate": "Udgivelsesdato",
|
||||
"LabelRemoveAllMetadataAbs": "Fjern alle metadata.abs filer",
|
||||
"LabelRemoveAllMetadataJson": "Fjern alle metadata.json filer",
|
||||
"LabelRemoveAudibleBranding": "Fjern Audible intro og outro fra kapitler",
|
||||
"LabelRemoveCover": "Fjern omslag",
|
||||
"LabelRemoveMetadataFile": "Fjern alle metadata filer i biblioteksmapper",
|
||||
"LabelRemoveMetadataFileHelp": "Fjern alle metadata.json og metadata.abs filer i dine {0} mapper.",
|
||||
|
@ -542,6 +558,7 @@
|
|||
"LabelSelectAll": "Vælg alle",
|
||||
"LabelSelectAllEpisodes": "Vælg alle episoder",
|
||||
"LabelSelectEpisodesShowing": "Vælg {0} episoder vist",
|
||||
"LabelSelectUser": "Vælg bruger",
|
||||
"LabelSelectUsers": "Valgte brugere",
|
||||
"LabelSendEbookToDevice": "Send e-bog til...",
|
||||
"LabelSequence": "Sekvens",
|
||||
|
@ -575,14 +592,14 @@
|
|||
"LabelSettingsLibraryMarkAsFinishedPercentComplete": "Procent gennemført er større end",
|
||||
"LabelSettingsLibraryMarkAsFinishedTimeRemaining": "Tid tilbage er mindre end (sekunder)",
|
||||
"LabelSettingsLibraryMarkAsFinishedWhen": "Marker medie indhold som færdigt når",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Spring til tidligere bøger i Fortsæt serie",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Fortsæt Serien siden hylde viser de første bøger som ikke er startet i serier med mindst en bog som ikke er startet og ingen bøger i gang. Aktivering af denne indstilling vil fortsætte serien fra den sidst gennemførte bog modsat den først ikke startede bog.",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeries": "Spring tidligere bøger i Fortsæt serie over",
|
||||
"LabelSettingsOnlyShowLaterBooksInContinueSeriesHelp": "Fortsæt Serien siden viser den første bog som ikke er startet i serier med mindst en bog som ikke er startet og hvor ingen bøger i gang. Aktivering af denne indstilling vil fortsætte serien fra den sidst gennemførte bog i stedet for fra den første ikke startede bog.",
|
||||
"LabelSettingsParseSubtitles": "Fortolk undertitler",
|
||||
"LabelSettingsParseSubtitlesHelp": "Udtræk undertekster fra lydbogsmappenavne.<br>Undertitler skal adskilles af \" - \"<br>f.eks. \"Bogtitel - En undertitel her\" har undertitlen \"En undertitel her\"",
|
||||
"LabelSettingsPreferMatchedMetadata": "Foretræk matchede metadata",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "Matchede data vil tilsidesætte elementdetaljer ved brug af Hurtig Match. Som standard udfylder Hurtig Match kun manglende detaljer.",
|
||||
"LabelSettingsSkipMatchingBooksWithASIN": "Spring over matchende bøger, der allerede har en ASIN",
|
||||
"LabelSettingsSkipMatchingBooksWithISBN": "Spring matchende bøger over, som allerede har et ISBN-nummer",
|
||||
"LabelSettingsSkipMatchingBooksWithASIN": "Ignorer matchende bøger, der allerede har en ASIN",
|
||||
"LabelSettingsSkipMatchingBooksWithISBN": "Ignorer matchende bøger, som allerede har et ISBN-nummer",
|
||||
"LabelSettingsSortingIgnorePrefixes": "Ignorer præfikser ved sortering",
|
||||
"LabelSettingsSortingIgnorePrefixesHelp": "f.eks. for præfikset \"the\" vil bogtitlen \"The Book Title\" blive sorteret som \"Book Title, The\"",
|
||||
"LabelSettingsSquareBookCovers": "Brug kvadratiske bogomslag",
|
||||
|
@ -604,6 +621,7 @@
|
|||
"LabelSlug": "Snegl",
|
||||
"LabelSortAscending": "Stigende",
|
||||
"LabelSortDescending": "Faldende",
|
||||
"LabelSortPubDate": "Sortér Pub Dato",
|
||||
"LabelStart": "Start",
|
||||
"LabelStartTime": "Starttid",
|
||||
"LabelStarted": "Startet",
|
||||
|
@ -704,6 +722,10 @@
|
|||
"LabelYourProgress": "Din fremgang",
|
||||
"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>.",
|
||||
"MessageAsinCheck": "Sikr dig at du bruger ASIN fra den korrekte Audible region, ikke Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Ældre API tokens vil blive fjernet i fremtiden. Brug <a href=\"/config/api-keys\">API-nøgler</a> i stedet.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Genstart sin server efter du har gemt for at bekræfte OIDC ændringer.",
|
||||
"MessageAuthenticationSecurityMessage": "Autentificeringen er blevet forbedret af sikkerhedsmæssige årsager. Alle brugere skal logge ind igen.",
|
||||
"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",
|
||||
"MessageBackupsLocationNoEditNote": "Note: Backup sti er sat igennem miljøvariabel og kan ikke ændres her.",
|
||||
|
@ -722,8 +744,10 @@
|
|||
"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",
|
||||
"MessageChapterStartIsAfter": "Kapitelstarten er efter slutningen af din lydbog",
|
||||
"MessageChaptersNotFound": "Kapitler ikke fundet",
|
||||
"MessageCheckingCron": "Tjekker cron...",
|
||||
"MessageConfirmCloseFeed": "Er du sikker på, at du vil lukke dette feed?",
|
||||
"MessageConfirmDeleteApiKey": "Er du sikker på at du vil slette API-nøglen \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Er du sikker på, at du vil slette backup for {0}?",
|
||||
"MessageConfirmDeleteDevice": "Er du sikker på at du vil fjerne elæser enhed \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Dette vil slette filen fra dit filsystem. Er du sikker?",
|
||||
|
@ -778,6 +802,7 @@
|
|||
"MessageForceReScanDescription": "vil scanne alle filer igen som en frisk scanning. Lydfilens ID3-tags, OPF-filer og tekstfiler scannes som nye.",
|
||||
"MessageImportantNotice": "Vigtig besked!",
|
||||
"MessageInsertChapterBelow": "Indsæt kapitel nedenfor",
|
||||
"MessageInvalidAsin": "Ugyldig ASIN",
|
||||
"MessageItemsSelected": "{0} elementer valgt",
|
||||
"MessageItemsUpdated": "{0} elementer opdateret",
|
||||
"MessageJoinUsOn": "Deltag i os på",
|
||||
|
@ -849,6 +874,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Kør hvert {0} af {1}",
|
||||
"MessageSearchResultsFor": "Søgeresultater for",
|
||||
"MessageSelected": "{0} valgt",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Serie sekvens kan ikke indeholde mellemrum",
|
||||
"MessageServerCouldNotBeReached": "Serveren kunne ikke nås",
|
||||
"MessageSetChaptersFromTracksDescription": "Indstil kapitler ved at bruge hver lydfil som et kapitel og kapiteloverskrift som lydfilnavn",
|
||||
"MessageShareExpirationWillBe": "Udløb vil være <strong>{0}</strong>",
|
||||
|
@ -910,6 +936,8 @@
|
|||
"NotificationOnBackupCompletedDescription": "Udløst når backup er færdig",
|
||||
"NotificationOnBackupFailedDescription": "Udløst når backup fejler",
|
||||
"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",
|
||||
"PlaceholderNewCollection": "Nyt samlingnavn",
|
||||
"PlaceholderNewFolderPath": "Ny mappes sti",
|
||||
|
@ -954,6 +982,7 @@
|
|||
"ToastBackupRestoreFailed": "Mislykkedes gendannelse af sikkerhedskopi",
|
||||
"ToastBackupUploadFailed": "Mislykkedes upload af sikkerhedskopi",
|
||||
"ToastBackupUploadSuccess": "Sikkerhedskopi uploadet",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Detaljer bekræftet på element",
|
||||
"ToastBatchDeleteFailed": "Batch slet fejlede",
|
||||
"ToastBatchDeleteSuccess": "Batch slet succes",
|
||||
"ToastBatchQuickMatchFailed": "Batch Hurtig Match fejlede!",
|
||||
|
@ -987,6 +1016,7 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Afsnit download kø renset",
|
||||
"ToastEpisodeUpdateSuccess": "{0} afsnit opdateret",
|
||||
"ToastErrorCannotShare": "Kan ikke dele på denne enhed",
|
||||
"ToastFailedToCreate": "Oprettelsen mislykkedes",
|
||||
"ToastFailedToLoadData": "Fejlede at indlæse data",
|
||||
"ToastFailedToMatch": "Fejlet match",
|
||||
"ToastFailedToShare": "Fejlet deling",
|
||||
|
@ -1003,11 +1033,11 @@
|
|||
"ToastItemMarkedAsNotFinishedFailed": "Mislykkedes markering som ikke afsluttet",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "Vare markeret som ikke afsluttet",
|
||||
"ToastItemUpdateSuccess": "Genstand opdateret",
|
||||
"ToastLibraryCreateFailed": "Mislykkedes oprettelse af bibliotek",
|
||||
"ToastLibraryCreateFailed": "Oprettelse af bibliotek mislykkedes",
|
||||
"ToastLibraryCreateSuccess": "Bibliotek \"{0}\" oprettet",
|
||||
"ToastLibraryDeleteFailed": "Mislykkedes sletning af bibliotek",
|
||||
"ToastLibraryDeleteFailed": "Sletning af bibliotek mislykkedes",
|
||||
"ToastLibraryDeleteSuccess": "Bibliotek slettet",
|
||||
"ToastLibraryScanFailedToStart": "Mislykkedes start af skanning",
|
||||
"ToastLibraryScanFailedToStart": "Start af skanning mislykkedes",
|
||||
"ToastLibraryScanStarted": "Biblioteksskanning startet",
|
||||
"ToastLibraryUpdateSuccess": "Bibliotek \"{0}\" opdateret",
|
||||
"ToastMatchAllAuthorsFailed": "Fejlede at matche alle forfattere",
|
||||
|
@ -1086,7 +1116,7 @@
|
|||
"ToastUnlinkOpenIdFailed": "Fejlede i af afkoble bruger fra OpenID",
|
||||
"ToastUnlinkOpenIdSuccess": "Bruger afkoblet fra OpenID",
|
||||
"ToastUploaderFilepathExistsError": "Filsti \"{0}\" findes allerede på serveren",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Genstand \"{0}\" benytter en undermappe af upload stien",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "Genstand \"{0}\" benytter en undermappe af upload stien.",
|
||||
"ToastUserDeleteFailed": "Mislykkedes sletning af bruger",
|
||||
"ToastUserDeleteSuccess": "Bruger slettet",
|
||||
"ToastUserPasswordChangeSuccess": "Password ændret",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Hinzufügen",
|
||||
"ButtonAddApiKey": "API-Schlüssel hinzufügen",
|
||||
"ButtonAddChapters": "Kapitel hinzufügen",
|
||||
"ButtonAddDevice": "Gerät hinzufügen",
|
||||
"ButtonAddLibrary": "Bibliothek hinzufügen",
|
||||
|
@ -14,12 +15,13 @@
|
|||
"ButtonBatchEditPopulateMapDetails": "Kartendetails auffüllen",
|
||||
"ButtonBrowseForFolder": "Ordnersuche",
|
||||
"ButtonCancel": "Abbrechen",
|
||||
"ButtonCancelEncode": "Codierung abbrechen",
|
||||
"ButtonCancelEncode": "Konvertierung abbrechen",
|
||||
"ButtonChangeRootPassword": "Hauptpasswort ändern",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "Überprüfe & lade neue Episoden herunter",
|
||||
"ButtonChooseAFolder": "Wähle einen Ordner",
|
||||
"ButtonChooseFiles": "Wähle eine Datei",
|
||||
"ButtonClearFilter": "Filter löschen",
|
||||
"ButtonClose": "Schließen",
|
||||
"ButtonCloseFeed": "Feed schließen",
|
||||
"ButtonCloseSession": "Offene Sitzung schließen",
|
||||
"ButtonCollections": "Sammlungen",
|
||||
|
@ -32,7 +34,7 @@
|
|||
"ButtonEditChapters": "Kapitel bearbeiten",
|
||||
"ButtonEditPodcast": "Podcast bearbeiten",
|
||||
"ButtonEnable": "Aktivieren",
|
||||
"ButtonFireAndFail": "Abfeuern und versagen",
|
||||
"ButtonFireAndFail": "Abschicken und fehlschlagen",
|
||||
"ButtonFireOnTest": "Test-Event abfeuern",
|
||||
"ButtonForceReScan": "Komplett-Scan (alle Medien)",
|
||||
"ButtonFullPath": "Vollständiger Pfad",
|
||||
|
@ -53,7 +55,7 @@
|
|||
"ButtonNext": "Vor",
|
||||
"ButtonNextChapter": "Nächstes Kapitel",
|
||||
"ButtonNextItemInQueue": "Das nächste Element in der Warteschlange",
|
||||
"ButtonOk": "Einverstanden",
|
||||
"ButtonOk": "Ok",
|
||||
"ButtonOpenFeed": "Feed öffnen",
|
||||
"ButtonOpenManager": "Manager öffnen",
|
||||
"ButtonPause": "Pausieren",
|
||||
|
@ -88,7 +90,7 @@
|
|||
"ButtonSave": "Speichern",
|
||||
"ButtonSaveAndClose": "Speichern & Schließen",
|
||||
"ButtonSaveTracklist": "Speichere die Titelliste",
|
||||
"ButtonScan": "Partial-Scan (nur geänderte/neue Medien)",
|
||||
"ButtonScan": "Scannen",
|
||||
"ButtonScanLibrary": "Bibliothek scannen",
|
||||
"ButtonScrollLeft": "Nach Links scrollen",
|
||||
"ButtonScrollRight": "Nach Rechts scrollen",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Konto",
|
||||
"HeaderAddCustomMetadataProvider": "Benutzerdefinierten Metadatenanbieter hinzufügen",
|
||||
"HeaderAdvanced": "Erweitert",
|
||||
"HeaderApiKeys": "API-Schlüssel",
|
||||
"HeaderAppriseNotificationSettings": "Apprise Benachrichtigungseinstellungen",
|
||||
"HeaderAudioTracks": "Audiodateien",
|
||||
"HeaderAudiobookTools": "Hörbuch-Dateiverwaltungswerkzeuge",
|
||||
"HeaderAuthentication": "Authentifizierung",
|
||||
"HeaderBackups": "Sicherungen",
|
||||
"HeaderBulkChapterModal": "Mehrere Kapitel hinzufügen",
|
||||
"HeaderChangePassword": "Passwort ändern",
|
||||
"HeaderChapters": "Kapitel",
|
||||
"HeaderChooseAFolder": "Wähle einen Ordner",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Metadaten Rangfolge",
|
||||
"HeaderMetadataToEmbed": "Einzubettende Metadaten",
|
||||
"HeaderNewAccount": "Neues Konto",
|
||||
"HeaderNewApiKey": "Neuen API-Schlüssel erstellen",
|
||||
"HeaderNewLibrary": "Neue Bibliothek",
|
||||
"HeaderNotificationCreate": "Benachrichtigung erstellen",
|
||||
"HeaderNotificationUpdate": "Benachrichtigung bearbeiten",
|
||||
|
@ -177,6 +182,7 @@
|
|||
"HeaderPlaylist": "Wiedergabeliste",
|
||||
"HeaderPlaylistItems": "Einträge in der Wiedergabeliste",
|
||||
"HeaderPodcastsToAdd": "Podcasts zum Hinzufügen",
|
||||
"HeaderPresets": "Voreinstellungen",
|
||||
"HeaderPreviewCover": "Vorschau Titelbild",
|
||||
"HeaderRSSFeedGeneral": "RSS Details",
|
||||
"HeaderRSSFeedIsOpen": "RSS-Feed ist geöffnet",
|
||||
|
@ -194,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Experimentelle Funktionen",
|
||||
"HeaderSettingsGeneral": "Allgemein",
|
||||
"HeaderSettingsScanner": "Scanner",
|
||||
"HeaderSettingsSecurity": "Sicherheit",
|
||||
"HeaderSettingsWebClient": "Web-Client",
|
||||
"HeaderSleepTimer": "Sleep-Timer",
|
||||
"HeaderStatsLargestItems": "Größte Medien",
|
||||
|
@ -205,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Inhaltsverzeichnis",
|
||||
"HeaderTools": "Werkzeuge",
|
||||
"HeaderUpdateAccount": "Konto aktualisieren",
|
||||
"HeaderUpdateApiKey": "API-Schlüssel aktualisieren",
|
||||
"HeaderUpdateAuthor": "Autor aktualisieren",
|
||||
"HeaderUpdateDetails": "Details aktualisieren",
|
||||
"HeaderUpdateLibrary": "Bibliothek aktualisieren",
|
||||
|
@ -234,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Alle Benutzer außer Gästen",
|
||||
"LabelAllUsersIncludingGuests": "Alle Benutzer und Gäste",
|
||||
"LabelAlreadyInYourLibrary": "Bereits in der Bibliothek",
|
||||
"LabelApiKeyCreated": "API-Schlüssel \"{0}\" erfolgreich erstellt.",
|
||||
"LabelApiKeyCreatedDescription": "Speichere den API-Schlüssel an einem sicheren Ort, du wirst ihn später nicht mehr abrufen können.",
|
||||
"LabelApiKeyUser": "Im Kontext eines Nutzers agieren",
|
||||
"LabelApiKeyUserDescription": "Dieser API-Schlüssel hat die gleichen Berechtigungen wie der Benutzer, in dessen Namen er erstellt wurde .In den Protokollen wird es aussehen, als ob der Benutzer die Anfrage durchführte.",
|
||||
"LabelApiToken": "API Schlüssel",
|
||||
"LabelAppend": "Anhängen",
|
||||
"LabelAudioBitrate": "Audiobitrate (z. B. 128 kbit/s)",
|
||||
|
@ -283,6 +295,7 @@
|
|||
"LabelContinueListening": "Weiterhören",
|
||||
"LabelContinueReading": "Weiterlesen",
|
||||
"LabelContinueSeries": "Serien fortsetzen",
|
||||
"LabelCorsAllowed": "Erlaubte CORS Quellen",
|
||||
"LabelCover": "Titelbild",
|
||||
"LabelCoverImageURL": "URL des Titelbildes",
|
||||
"LabelCoverProvider": "Titelbildanbieter",
|
||||
|
@ -296,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Löschen von der Festplatte + Datenbank (deaktivieren um nur aus der Datenbank zu entfernen)",
|
||||
"LabelDescription": "Beschreibung",
|
||||
"LabelDeselectAll": "Alles abwählen",
|
||||
"LabelDetectedPattern": "Erkanntes Muster:",
|
||||
"LabelDevice": "Gerät",
|
||||
"LabelDeviceInfo": "Geräteinformationen",
|
||||
"LabelDeviceIsAvailableTo": "Dem Gerät ist es möglich zu ...",
|
||||
|
@ -345,7 +359,11 @@
|
|||
"LabelExample": "Beispiel",
|
||||
"LabelExpandSeries": "Serie ausklappen",
|
||||
"LabelExpandSubSeries": "Unterserie ausklappen",
|
||||
"LabelExplicit": "Explizit (Altersbeschränkung)",
|
||||
"LabelExpired": "Abgelaufen",
|
||||
"LabelExpiresAt": "Läuft ab am",
|
||||
"LabelExpiresInSeconds": "Ablauf in (seconds) Sekunden",
|
||||
"LabelExpiresNever": "Niemals",
|
||||
"LabelExplicit": "Explizit",
|
||||
"LabelExplicitChecked": "Explicit (Altersbeschränkung) (angehakt)",
|
||||
"LabelExplicitUnchecked": "Not Explicit (Altersbeschränkung) (nicht angehakt)",
|
||||
"LabelExportOPML": "OPML exportieren",
|
||||
|
@ -404,6 +422,7 @@
|
|||
"LabelLanguages": "Sprachen",
|
||||
"LabelLastBookAdded": "Zuletzt hinzugefügtes Buch",
|
||||
"LabelLastBookUpdated": "Zuletzt aktualisiertes Buch",
|
||||
"LabelLastProgressDate": "Letzter Fortschritt: {0}",
|
||||
"LabelLastSeen": "Zuletzt gesehen",
|
||||
"LabelLastTime": "Letztes Mal",
|
||||
"LabelLastUpdate": "Letzte Aktualisierung",
|
||||
|
@ -416,6 +435,7 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Keine {0}",
|
||||
"LabelLibraryItem": "Bibliothekseintrag",
|
||||
"LabelLibraryName": "Bibliotheksname",
|
||||
"LabelLibrarySortByProgress": "Fortschritt aktualisiert",
|
||||
"LabelLimit": "Begrenzung",
|
||||
"LabelLineSpacing": "Zeilenabstand",
|
||||
"LabelListenAgain": "Erneut anhören",
|
||||
|
@ -424,6 +444,7 @@
|
|||
"LabelLogLevelWarn": "Warnungen",
|
||||
"LabelLookForNewEpisodesAfterDate": "Suche nach neuen Episoden nach diesem Datum",
|
||||
"LabelLowestPriority": "Niedrigste Priorität",
|
||||
"LabelMatchConfidence": "Vertrauenswert",
|
||||
"LabelMatchExistingUsersBy": "Zuordnen existierender Benutzer mit",
|
||||
"LabelMatchExistingUsersByDescription": "Wird zum Verbinden vorhandener Benutzer verwendet. Sobald die Verbindung hergestellt ist, wird den Benutzern eine eindeutige ID vom SSO-Anbieter zugeordnet",
|
||||
"LabelMaxEpisodesToDownload": "Max. Anzahl an Episoden zum Herunterladen, 0 für unbegrenzte Episoden.",
|
||||
|
@ -432,7 +453,7 @@
|
|||
"LabelMaxEpisodesToKeepHelp": "0 setzt keine Begrenzung. Wenn eine neue Episode automatisch heruntergeladen wird, wird die älteste Episode gelöscht, wenn du mehr als X Episoden gespeichert hast. Es wird nur eine Episode pro neuem Download gelöscht.",
|
||||
"LabelMediaPlayer": "Mediaplayer",
|
||||
"LabelMediaType": "Medientyp",
|
||||
"LabelMetaTag": "Meta Schlagwort",
|
||||
"LabelMetaTag": "Meta Tag",
|
||||
"LabelMetaTags": "Meta Tags",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Höher priorisierte Quellen für Metadaten überschreiben Metadaten aus Quellen mit niedrigerer Priorität",
|
||||
"LabelMetadataProvider": "Metadatenanbieter",
|
||||
|
@ -453,7 +474,9 @@
|
|||
"LabelNewestAuthors": "Neueste Autoren",
|
||||
"LabelNewestEpisodes": "Neueste Episoden",
|
||||
"LabelNextBackupDate": "Nächstes Sicherungsdatum",
|
||||
"LabelNextChapters": "Das nächste Kapitel ist:",
|
||||
"LabelNextScheduledRun": "Nächster planmäßiger Durchlauf",
|
||||
"LabelNoApiKeys": "Keine API-Schlüssel vorhanden",
|
||||
"LabelNoCustomMetadataProviders": "Keine benutzerdefinierten Metadata Anbieter",
|
||||
"LabelNoEpisodesSelected": "Keine Episoden ausgewählt",
|
||||
"LabelNotFinished": "Nicht beendet",
|
||||
|
@ -469,6 +492,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Maximale Größe der Warteschlange für die Benachrichtigungsereignisse",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Es wird nur 1 Ereignis pro Sekunde ausgelöst. Ereignisse werden ignoriert, wenn die Warteschlange die maximale Größe erreicht hat. Dies verhindert Benachrichtigungsspamming.",
|
||||
"LabelNumberOfBooks": "Anzahl der Hörbücher",
|
||||
"LabelNumberOfChapters": "Anzahl an Kapiteln:",
|
||||
"LabelNumberOfEpisodes": "Anzahl der Episoden",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Name des OpenID-Claims, der erweiterte Berechtigungen für Benutzeraktionen innerhalb der Anwendung enthält, die auf Nicht-Admin-Rollen angewendet werden (<b>wenn konfiguriert</b>). Wenn der Claim in der Antwort fehlt, wird der Zugang zu ABS verweigert. Fehlt eine einzelne Option, wird sie als <code>false</code> behandelt. Stelle sicher, dass der Claim des Identitätsanbieters der erwarteten Struktur entspricht:",
|
||||
"LabelOpenIDClaims": "Lass die folgenden Optionen leer, um die erweiterte Zuweisung von Gruppen und Berechtigungen zu deaktivieren und automatisch die 'User'-Gruppe zuzuweisen.",
|
||||
|
@ -513,7 +537,7 @@
|
|||
"LabelPublishers": "Herausgeber",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Benutzerdefinierte Eigentümer-E-Mail",
|
||||
"LabelRSSFeedCustomOwnerName": "Benutzerdefinierter Name des Eigentümers",
|
||||
"LabelRSSFeedOpen": "RSS Feed offen",
|
||||
"LabelRSSFeedOpen": "RSS-Feed offen",
|
||||
"LabelRSSFeedPreventIndexing": "Indizierung verhindern",
|
||||
"LabelRSSFeedSlug": "RSS-Feed-Schlagwort",
|
||||
"LabelRSSFeedURL": "RSS-Feed-URL",
|
||||
|
@ -530,6 +554,7 @@
|
|||
"LabelReleaseDate": "Veröffentlichungsdatum",
|
||||
"LabelRemoveAllMetadataAbs": "Alle metadata.abs Dateien löschen",
|
||||
"LabelRemoveAllMetadataJson": "Alle metadata.json Dateien löschen",
|
||||
"LabelRemoveAudibleBranding": "Audible Intro sowie Outro aus Kapiteln entfernen",
|
||||
"LabelRemoveCover": "Entferne Titelbild",
|
||||
"LabelRemoveMetadataFile": "Metadaten-Dateien in Bibliotheksordnern löschen",
|
||||
"LabelRemoveMetadataFileHelp": "Alle metadata.json und metadata.abs Dateien aus den Ordnern {0} löschen.",
|
||||
|
@ -542,6 +567,7 @@
|
|||
"LabelSelectAll": "Alles auswählen",
|
||||
"LabelSelectAllEpisodes": "Alle Episoden auswählen",
|
||||
"LabelSelectEpisodesShowing": "{0} ausgewählte Episoden werden angezeigt",
|
||||
"LabelSelectUser": "Ausgewählter Benutzer",
|
||||
"LabelSelectUsers": "Benutzer auswählen",
|
||||
"LabelSendEbookToDevice": "E-Buch senden an …",
|
||||
"LabelSequence": "Reihenfolge",
|
||||
|
@ -638,6 +664,7 @@
|
|||
"LabelTheme": "Farbschema",
|
||||
"LabelThemeDark": "Dunkel",
|
||||
"LabelThemeLight": "Hell",
|
||||
"LabelThemeSepia": "Sepia",
|
||||
"LabelTimeBase": "Basiszeit",
|
||||
"LabelTimeDurationXHours": "{0} Stunden",
|
||||
"LabelTimeDurationXMinutes": "{0} Minuten",
|
||||
|
@ -705,7 +732,10 @@
|
|||
"LabelYourProgress": "Fortschritt",
|
||||
"MessageAddToPlayerQueue": "Zur Abspielwarteliste hinzufügen",
|
||||
"MessageAppriseDescription": "Um diese Funktion nutzen zu können, musst du eine Instanz von <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> laufen haben oder eine API verwenden welche dieselbe Anfragen bearbeiten kann. <br />Die Apprise API Url muss der vollständige URL-Pfad sein, an den die Benachrichtigung gesendet werden soll, z.B. wenn Ihre API-Instanz unter <code>http://192.168.1.1:8337</code> läuft, würdest du <code>http://192.168.1.1:8337/notify</code> eingeben.",
|
||||
"MessageAsinCheck": "Stellen Sie sicher, dass Sie die ASIN aus der richtigen Audible Region verwenden, nicht Amazon.",
|
||||
"MessageAsinCheck": "Stelle sicher, dass die ASIN aus der richtigen Audible Region verwendet wird, nicht Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Alte API tokens werden in Zukunft entfernt. Benutze stattdessen <a href=\"/config/api-keys\">API Keys</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Nach dem Speichern muss der Server neugestartet werden um die OIDC Änderungen zu übernehmen.",
|
||||
"MessageAuthenticationSecurityMessage": "Die Anmeldung wurde abgesichert. Benutzersitzungen werden getrennt, alle Benutzer müssen sich erneut anmelden.",
|
||||
"MessageBackupsDescription": "In einer Sicherung werden Benutzer, Benutzerfortschritte, Details zu den Bibliotheksobjekten, Servereinstellungen und Bilder welche in <code>/metadata/items</code> & <code>/metadata/authors</code> gespeichert sind gespeichert. Sicherungen enthalten keine Dateien welche in den einzelnen Bibliotheksordnern (Medien-Ordnern) gespeichert sind.",
|
||||
"MessageBackupsLocationEditNote": "Hinweis: Durch das Aktualisieren des Backup-Speicherorts werden vorhandene Sicherungen nicht verschoben oder geändert",
|
||||
"MessageBackupsLocationNoEditNote": "Hinweis: Der Sicherungsspeicherort wird über eine Umgebungsvariable festgelegt und kann hier nicht geändert werden.",
|
||||
|
@ -719,6 +749,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Keine Ergebnisse für Filter \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Keine Ergebnisse für die Abfrage",
|
||||
"MessageBookshelfNoSeries": "Keine Serien vorhanden",
|
||||
"MessageBulkChapterPattern": "Wie viele Kapitel mit diesem Nummerierungs-Muster sollen hinzugefügt werden?",
|
||||
"MessageChapterEndIsAfter": "Ungültige Kapitelendzeit: Kapitelende > Mediumende (Kapitelende liegt nach dem Ende des Mediums)",
|
||||
"MessageChapterErrorFirstNotZero": "Ungültige Kapitelstartzeit: Das erste Kapitel muss bei 0 beginnen",
|
||||
"MessageChapterErrorStartGteDuration": "Ungültige Kapitelstartzeit: Kapitelanfang > Mediumlänge (Kapitelanfang liegt zeitlich nach dem Ende des Mediums -> Lösung: Kapitelanfang < Mediumlänge)",
|
||||
|
@ -727,6 +758,7 @@
|
|||
"MessageChaptersNotFound": "Kapitel gefunden nicht",
|
||||
"MessageCheckingCron": "Überprüfe Cron...",
|
||||
"MessageConfirmCloseFeed": "Feed wird geschlossen! Bist du dir sicher?",
|
||||
"MessageConfirmDeleteApiKey": "Möchtest du den API-Schlüssel \"{0}\" wirklich entfernen ?",
|
||||
"MessageConfirmDeleteBackup": "Sicherung für {0} wird gelöscht! Bist du dir sicher?",
|
||||
"MessageConfirmDeleteDevice": "Möchtest du das Lesegerät „{0}“ wirklich löschen?",
|
||||
"MessageConfirmDeleteFile": "Datei wird vom System gelöscht! Bist du dir sicher?",
|
||||
|
@ -754,6 +786,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Autor \"{0}\" wird enfernt! Bist du dir sicher?",
|
||||
"MessageConfirmRemoveCollection": "Sammlung \"{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?",
|
||||
"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?",
|
||||
|
@ -779,6 +812,8 @@
|
|||
"MessageFeedURLWillBe": "Feed-URL wird {0} sein",
|
||||
"MessageFetching": "Wird abgerufen …",
|
||||
"MessageForceReScanDescription": "Durchsucht alle Dateien erneut, wie bei einem frischen Scan. ID3-Tags von Audiodateien, OPF-Dateien und Textdateien werden neu durchsucht.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} </strong> auf {1} gehört",
|
||||
"MessageHeatmapNoListeningSessions": "Keine Hörsitzungen am {0}",
|
||||
"MessageImportantNotice": "Wichtiger Hinweis!",
|
||||
"MessageInsertChapterBelow": "Kapitel unten einfügen",
|
||||
"MessageInvalidAsin": "Ungültige ASIN",
|
||||
|
@ -849,12 +884,13 @@
|
|||
"MessageResetChaptersConfirm": "Kapitel und vorgenommenen Änderungen werden zurückgesetzt und rückgängig gemacht! Bist du dir sicher?",
|
||||
"MessageRestoreBackupConfirm": "Bist du dir sicher, dass du die Sicherung wiederherstellen willst, welche am",
|
||||
"MessageRestoreBackupWarning": "Bei der Wiederherstellung einer Sicherung wird die gesamte Datenbank unter /config und die Titelbilder in /metadata/items und /metadata/authors überschrieben.<br /><br />Bei der Sicherung werden keine Dateien in deinen Bibliotheksordnern verändert. Wenn du die Servereinstellungen aktiviert hast, um Cover und Metadaten in deinen Bibliotheksordnern zu speichern, werden diese nicht gesichert oder überschrieben.<br /><br />Alle Clients, die Ihren Server nutzen, werden automatisch aktualisiert.",
|
||||
"MessageScheduleLibraryScanNote": "Für die meisten 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",
|
||||
"MessageSearchResultsFor": "Suchergebnisse für",
|
||||
"MessageSelected": "{0} ausgewählt",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Serie Abfolge kann keine Leerzeichen enthalten",
|
||||
"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",
|
||||
"MessageShareExpiresIn": "Läuft in {0} ab",
|
||||
"MessageShareURLWillBe": "Der Freigabe Link wird <strong>{0}</strong> sein",
|
||||
|
@ -914,7 +950,10 @@
|
|||
"NotificationOnBackupCompletedDescription": "Wird ausgeführt wenn ein Backup erstellt wurde",
|
||||
"NotificationOnBackupFailedDescription": "Wird ausgeführt wenn ein Backup fehlgeschlagen ist",
|
||||
"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",
|
||||
"PlaceholderBulkChapterInput": "Kapitelbezeichnung eingeben oder Nummerierung verwenden (z.B. 'Episode 1', 'Kapitel 10', '1.')",
|
||||
"PlaceholderNewCollection": "Neuer Sammlungsname",
|
||||
"PlaceholderNewFolderPath": "Neuer Ordnerpfad",
|
||||
"PlaceholderNewPlaylist": "Neuer Wiedergabelistenname",
|
||||
|
@ -968,9 +1007,15 @@
|
|||
"ToastBookmarkCreateFailed": "Lesezeichen konnte nicht erstellt werden",
|
||||
"ToastBookmarkCreateSuccess": "Lesezeichen hinzugefügt",
|
||||
"ToastBookmarkRemoveSuccess": "Lesezeichen entfernt",
|
||||
"ToastBulkChapterInvalidCount": "Gebe eine Zahl zwischen 1 und 150 ein",
|
||||
"ToastCachePurgeFailed": "Cache leeren fehlgeschlagen",
|
||||
"ToastCachePurgeSuccess": "Cache geleert",
|
||||
"ToastChapterLocked": "Kapitel ist freigegeben.",
|
||||
"ToastChapterStartTimeAdjusted": "Kapitelbeginn um {0} Sekunden angepasst",
|
||||
"ToastChaptersAllLocked": "Alle Kapitel sind gesperrt. Gebe einige Kapitel frei um die Zeiten anzupassen.",
|
||||
"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öhe die Startdauer des zweiten Kapitels.",
|
||||
"ToastChaptersMustHaveTitles": "Kapitel benötigen eindeutige Namen",
|
||||
"ToastChaptersRemoved": "Kapitel entfernt",
|
||||
"ToastChaptersUpdated": "Kapitel aktualisiert",
|
||||
|
@ -992,13 +1037,16 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Warteschlange für Episoden-Downloads gelöscht",
|
||||
"ToastEpisodeUpdateSuccess": "{0} Episoden aktualisiert",
|
||||
"ToastErrorCannotShare": "Das kann nicht nativ auf diesem Gerät freigegeben werden",
|
||||
"ToastFailedToLoadData": "Daten laden fehlgeschlagen",
|
||||
"ToastFailedToCreate": "Fehler beim Erzeugen",
|
||||
"ToastFailedToDelete": "Fehler beim Löschen",
|
||||
"ToastFailedToLoadData": "Fehler beim laden der Daten",
|
||||
"ToastFailedToMatch": "Fehler beim Abgleich",
|
||||
"ToastFailedToShare": "Fehler beim Teilen",
|
||||
"ToastFailedToUpdate": "Aktualisierung ist fehlgeschlagen",
|
||||
"ToastInvalidImageUrl": "Ungültiger Bild URL",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Ungültige Max. Anzahl an Episoden zum Herunterladen",
|
||||
"ToastInvalidUrl": "Ungültiger URL",
|
||||
"ToastInvalidUrls": "Eine oder mehrere URLs sind ungültig",
|
||||
"ToastItemCoverUpdateSuccess": "Titelbild aktualisiert",
|
||||
"ToastItemDeletedFailed": "Fehler beim löschen des Artikels",
|
||||
"ToastItemDeletedSuccess": "Artikel gelöscht",
|
||||
|
@ -1023,6 +1071,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Es muss mindestens ein Pfad angegeben werden",
|
||||
"ToastNameEmailRequired": "Name und E-Mail sind erforderlich",
|
||||
"ToastNameRequired": "Name ist erforderlich",
|
||||
"ToastNewApiKeyUserError": "Bitte wähle einen Benutzer aus (Pflichtfeld)",
|
||||
"ToastNewEpisodesFound": "{0} neue Episoden gefunden",
|
||||
"ToastNewUserCreatedFailed": "Fehler beim erstellen des Accounts: \"{ 0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Neuer Account erstellt",
|
||||
|
@ -1097,5 +1146,13 @@
|
|||
"ToastUserPasswordChangeSuccess": "Passwort erfolgreich verändert",
|
||||
"ToastUserPasswordMismatch": "Passwörter stimmen nicht überein",
|
||||
"ToastUserPasswordMustChange": "Neues Passwort muss sich von altem Passwort unterscheiden",
|
||||
"ToastUserRootRequireName": "Root Benutzername muss angegeben werden"
|
||||
"ToastUserRootRequireName": "Root Benutzername muss angegeben werden",
|
||||
"TooltipAddChapters": "Kapitel hinzufügen",
|
||||
"TooltipAddOneSecond": "1 Sekunde hinzufügen",
|
||||
"TooltipAdjustChapterStart": "Klicke um die Startzeit anzupassen",
|
||||
"TooltipLockAllChapters": "Alle Kapitel sperren",
|
||||
"TooltipLockChapter": "Kapitel sperren (Shift+Klick für mehrere)",
|
||||
"TooltipSubtractOneSecond": "1 Sekunde abziehen",
|
||||
"TooltipUnlockAllChapters": "Alle Kapitel freigeben",
|
||||
"TooltipUnlockChapter": "Kapitel freigeben (Shift+Klick für mehrere)"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Add",
|
||||
"ButtonAddApiKey": "Add API Key",
|
||||
"ButtonAddChapters": "Add Chapters",
|
||||
"ButtonAddDevice": "Add Device",
|
||||
"ButtonAddLibrary": "Add Library",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Choose a folder",
|
||||
"ButtonChooseFiles": "Choose files",
|
||||
"ButtonClearFilter": "Clear Filter",
|
||||
"ButtonClose": "Close",
|
||||
"ButtonCloseFeed": "Close Feed",
|
||||
"ButtonCloseSession": "Close Open Session",
|
||||
"ButtonCollections": "Collections",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Account",
|
||||
"HeaderAddCustomMetadataProvider": "Add Custom Metadata Provider",
|
||||
"HeaderAdvanced": "Advanced",
|
||||
"HeaderApiKeys": "API Keys",
|
||||
"HeaderAppriseNotificationSettings": "Apprise Notification Settings",
|
||||
"HeaderAudioTracks": "Audio Tracks",
|
||||
"HeaderAudiobookTools": "Audiobook File Management Tools",
|
||||
"HeaderAuthentication": "Authentication",
|
||||
"HeaderBackups": "Backups",
|
||||
"HeaderBulkChapterModal": "Add Multiple Chapters",
|
||||
"HeaderChangePassword": "Change Password",
|
||||
"HeaderChapters": "Chapters",
|
||||
"HeaderChooseAFolder": "Choose a Folder",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Metadata order of precedence",
|
||||
"HeaderMetadataToEmbed": "Metadata to embed",
|
||||
"HeaderNewAccount": "New Account",
|
||||
"HeaderNewApiKey": "New API Key",
|
||||
"HeaderNewLibrary": "New Library",
|
||||
"HeaderNotificationCreate": "Create Notification",
|
||||
"HeaderNotificationUpdate": "Update Notification",
|
||||
|
@ -195,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Experimental Features",
|
||||
"HeaderSettingsGeneral": "General",
|
||||
"HeaderSettingsScanner": "Scanner",
|
||||
"HeaderSettingsSecurity": "Security",
|
||||
"HeaderSettingsWebClient": "Web Client",
|
||||
"HeaderSleepTimer": "Sleep Timer",
|
||||
"HeaderStatsLargestItems": "Largest Items",
|
||||
|
@ -206,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Table of Contents",
|
||||
"HeaderTools": "Tools",
|
||||
"HeaderUpdateAccount": "Update Account",
|
||||
"HeaderUpdateApiKey": "Update API Key",
|
||||
"HeaderUpdateAuthor": "Update Author",
|
||||
"HeaderUpdateDetails": "Update Details",
|
||||
"HeaderUpdateLibrary": "Update Library",
|
||||
|
@ -235,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "All users excluding guests",
|
||||
"LabelAllUsersIncludingGuests": "All users including guests",
|
||||
"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",
|
||||
"LabelAppend": "Append",
|
||||
"LabelAudioBitrate": "Audio Bitrate (e.g. 128k)",
|
||||
|
@ -284,6 +295,7 @@
|
|||
"LabelContinueListening": "Continue Listening",
|
||||
"LabelContinueReading": "Continue Reading",
|
||||
"LabelContinueSeries": "Continue Series",
|
||||
"LabelCorsAllowed": "Allowed CORS Origins",
|
||||
"LabelCover": "Cover",
|
||||
"LabelCoverImageURL": "Cover Image URL",
|
||||
"LabelCoverProvider": "Cover Provider",
|
||||
|
@ -297,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Delete from file system (uncheck to only remove from database)",
|
||||
"LabelDescription": "Description",
|
||||
"LabelDeselectAll": "Deselect All",
|
||||
"LabelDetectedPattern": "Detected pattern:",
|
||||
"LabelDevice": "Device",
|
||||
"LabelDeviceInfo": "Device Info",
|
||||
"LabelDeviceIsAvailableTo": "Device is available to...",
|
||||
|
@ -346,6 +359,10 @@
|
|||
"LabelExample": "Example",
|
||||
"LabelExpandSeries": "Expand Series",
|
||||
"LabelExpandSubSeries": "Expand Sub Series",
|
||||
"LabelExpired": "Expired",
|
||||
"LabelExpiresAt": "Expires At",
|
||||
"LabelExpiresInSeconds": "Expires in (seconds)",
|
||||
"LabelExpiresNever": "Never",
|
||||
"LabelExplicit": "Explicit",
|
||||
"LabelExplicitChecked": "Explicit (checked)",
|
||||
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
|
||||
|
@ -361,6 +378,7 @@
|
|||
"LabelFilterByUser": "Filter by User",
|
||||
"LabelFindEpisodes": "Find Episodes",
|
||||
"LabelFinished": "Finished",
|
||||
"LabelFinishedDate": "Finished {0}",
|
||||
"LabelFolder": "Folder",
|
||||
"LabelFolders": "Folders",
|
||||
"LabelFontBold": "Bold",
|
||||
|
@ -405,6 +423,7 @@
|
|||
"LabelLanguages": "Languages",
|
||||
"LabelLastBookAdded": "Last Book Added",
|
||||
"LabelLastBookUpdated": "Last Book Updated",
|
||||
"LabelLastProgressDate": "Last progress: {0}",
|
||||
"LabelLastSeen": "Last Seen",
|
||||
"LabelLastTime": "Last Time",
|
||||
"LabelLastUpdate": "Last Update",
|
||||
|
@ -417,6 +436,9 @@
|
|||
"LabelLibraryFilterSublistEmpty": "No {0}",
|
||||
"LabelLibraryItem": "Library Item",
|
||||
"LabelLibraryName": "Library Name",
|
||||
"LabelLibrarySortByProgress": "Progress: Last Updated",
|
||||
"LabelLibrarySortByProgressFinished": "Progress: Finished",
|
||||
"LabelLibrarySortByProgressStarted": "Progress: Started",
|
||||
"LabelLimit": "Limit",
|
||||
"LabelLineSpacing": "Line spacing",
|
||||
"LabelListenAgain": "Listen Again",
|
||||
|
@ -425,6 +447,7 @@
|
|||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Look for new episodes after this date",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchConfidence": "Confidence",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMaxEpisodesToDownload": "Max # of episodes to download. Use 0 for unlimited.",
|
||||
|
@ -454,7 +477,9 @@
|
|||
"LabelNewestAuthors": "Newest Authors",
|
||||
"LabelNewestEpisodes": "Newest Episodes",
|
||||
"LabelNextBackupDate": "Next backup date",
|
||||
"LabelNextChapters": "Next chapters will be:",
|
||||
"LabelNextScheduledRun": "Next scheduled run",
|
||||
"LabelNoApiKeys": "No API keys",
|
||||
"LabelNoCustomMetadataProviders": "No custom metadata providers",
|
||||
"LabelNoEpisodesSelected": "No episodes selected",
|
||||
"LabelNotFinished": "Not Finished",
|
||||
|
@ -470,6 +495,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Max queue size for notification events",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Events are limited to firing 1 per second. Events will be ignored if the queue is at max size. This prevents notification spamming.",
|
||||
"LabelNumberOfBooks": "Number of Books",
|
||||
"LabelNumberOfChapters": "Number of chapters:",
|
||||
"LabelNumberOfEpisodes": "# of Episodes",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Name of the OpenID claim that contains advanced permissions for user actions within the application which will apply to non-admin roles (<b>if configured</b>). If the claim is missing from the response, access to ABS will be denied. If a single option is missing, it will be treated as <code>false</code>. Ensure the identity provider's claim matches the expected structure:",
|
||||
"LabelOpenIDClaims": "Leave the following options empty to disable advanced group and permissions assignment, automatically assigning 'User' group then.",
|
||||
|
@ -544,6 +570,7 @@
|
|||
"LabelSelectAll": "Select all",
|
||||
"LabelSelectAllEpisodes": "Select all episodes",
|
||||
"LabelSelectEpisodesShowing": "Select {0} episodes showing",
|
||||
"LabelSelectUser": "Select user",
|
||||
"LabelSelectUsers": "Select users",
|
||||
"LabelSendEbookToDevice": "Send Ebook to...",
|
||||
"LabelSequence": "Sequence",
|
||||
|
@ -611,6 +638,7 @@
|
|||
"LabelStartTime": "Start Time",
|
||||
"LabelStarted": "Started",
|
||||
"LabelStartedAt": "Started At",
|
||||
"LabelStartedDate": "Started {0}",
|
||||
"LabelStatsAudioTracks": "Audio Tracks",
|
||||
"LabelStatsAuthors": "Authors",
|
||||
"LabelStatsBestDay": "Best Day",
|
||||
|
@ -640,6 +668,7 @@
|
|||
"LabelTheme": "Theme",
|
||||
"LabelThemeDark": "Dark",
|
||||
"LabelThemeLight": "Light",
|
||||
"LabelThemeSepia": "Sepia",
|
||||
"LabelTimeBase": "Time Base",
|
||||
"LabelTimeDurationXHours": "{0} hours",
|
||||
"LabelTimeDurationXMinutes": "{0} minutes",
|
||||
|
@ -708,7 +737,9 @@
|
|||
"MessageAddToPlayerQueue": "Add to player queue",
|
||||
"MessageAppriseDescription": "To use this feature you will need to have an instance of <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> running or an api that will handle those same requests. <br />The Apprise API Url should be the full URL path to send the notification, e.g., if your API instance is served at <code>http://192.168.1.1:8337</code> then you would put <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Ensure you are using the ASIN from the correct Audible region, not Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Legacy API tokens will be removed in the future. Use <a href=\"/config/api-keys\">API Keys</a> instead.",
|
||||
"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.",
|
||||
"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.",
|
||||
|
@ -722,6 +753,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "No results for filter \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "No results for query",
|
||||
"MessageBookshelfNoSeries": "You have no series",
|
||||
"MessageBulkChapterPattern": "How many chapters would you like to add with this numbering pattern?",
|
||||
"MessageChapterEndIsAfter": "Chapter end is after the end of your audiobook",
|
||||
"MessageChapterErrorFirstNotZero": "First chapter must start at 0",
|
||||
"MessageChapterErrorStartGteDuration": "Invalid start time must be less than audiobook duration",
|
||||
|
@ -730,6 +762,7 @@
|
|||
"MessageChaptersNotFound": "Chapters not found",
|
||||
"MessageCheckingCron": "Checking cron...",
|
||||
"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}?",
|
||||
"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?",
|
||||
|
@ -757,6 +790,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Are you sure you want to remove author \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Are you sure you want to remove collection \"{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?",
|
||||
"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?",
|
||||
|
@ -782,6 +816,8 @@
|
|||
"MessageFeedURLWillBe": "Feed URL will be {0}",
|
||||
"MessageFetching": "Fetching...",
|
||||
"MessageForceReScanDescription": "will scan all files again like a fresh scan. Audio file ID3 tags, OPF files, and text files will be scanned as new.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} listening</strong> on {1}",
|
||||
"MessageHeatmapNoListeningSessions": "No listening sessions on {0}",
|
||||
"MessageImportantNotice": "Important Notice!",
|
||||
"MessageInsertChapterBelow": "Insert chapter below",
|
||||
"MessageInvalidAsin": "Invalid ASIN",
|
||||
|
@ -856,6 +892,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Run every {0} at {1}",
|
||||
"MessageSearchResultsFor": "Search results for",
|
||||
"MessageSelected": "{0} selected",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Series sequence cannot contain spaces",
|
||||
"MessageServerCouldNotBeReached": "Server could not be reached",
|
||||
"MessageSetChaptersFromTracksDescription": "Set chapters using each audio file as a chapter and chapter title as the audio file name",
|
||||
"MessageShareExpirationWillBe": "Expiration will be <strong>{0}</strong>",
|
||||
|
@ -917,7 +954,10 @@
|
|||
"NotificationOnBackupCompletedDescription": "Triggered when a backup is completed",
|
||||
"NotificationOnBackupFailedDescription": "Triggered when a backup fails",
|
||||
"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",
|
||||
"PlaceholderBulkChapterInput": "Enter chapter title or use numbering (e.g., 'Episode 1', 'Chapter 10', '1.')",
|
||||
"PlaceholderNewCollection": "New collection name",
|
||||
"PlaceholderNewFolderPath": "New folder path",
|
||||
"PlaceholderNewPlaylist": "New playlist name",
|
||||
|
@ -971,8 +1011,12 @@
|
|||
"ToastBookmarkCreateFailed": "Failed to create bookmark",
|
||||
"ToastBookmarkCreateSuccess": "Bookmark added",
|
||||
"ToastBookmarkRemoveSuccess": "Bookmark removed",
|
||||
"ToastBulkChapterInvalidCount": "Enter a number between 1 and 150",
|
||||
"ToastCachePurgeFailed": "Failed to purge cache",
|
||||
"ToastCachePurgeSuccess": "Cache purged successfully",
|
||||
"ToastChapterLocked": "Chapter is locked.",
|
||||
"ToastChapterStartTimeAdjusted": "Chapter start time adjusted by {0} seconds",
|
||||
"ToastChaptersAllLocked": "All chapters are locked. Unlock some chapters to shift their times.",
|
||||
"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.",
|
||||
|
@ -997,6 +1041,8 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Episode download queue cleared",
|
||||
"ToastEpisodeUpdateSuccess": "{0} episodes updated",
|
||||
"ToastErrorCannotShare": "Cannot share natively on this device",
|
||||
"ToastFailedToCreate": "Failed to create",
|
||||
"ToastFailedToDelete": "Failed to delete",
|
||||
"ToastFailedToLoadData": "Failed to load data",
|
||||
"ToastFailedToMatch": "Failed to match",
|
||||
"ToastFailedToShare": "Failed to share",
|
||||
|
@ -1004,6 +1050,7 @@
|
|||
"ToastInvalidImageUrl": "Invalid image URL",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Invalid max episodes to download",
|
||||
"ToastInvalidUrl": "Invalid URL",
|
||||
"ToastInvalidUrls": "One or more URLs are invalid",
|
||||
"ToastItemCoverUpdateSuccess": "Item cover updated",
|
||||
"ToastItemDeletedFailed": "Failed to delete item",
|
||||
"ToastItemDeletedSuccess": "Deleted item",
|
||||
|
@ -1028,6 +1075,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Must have at least one path",
|
||||
"ToastNameEmailRequired": "Name and email are required",
|
||||
"ToastNameRequired": "Name is required",
|
||||
"ToastNewApiKeyUserError": "Must select a user",
|
||||
"ToastNewEpisodesFound": "{0} new episodes found",
|
||||
"ToastNewUserCreatedFailed": "Failed to create account: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "New account created",
|
||||
|
@ -1052,6 +1100,7 @@
|
|||
"ToastPlaylistUpdateSuccess": "Playlist updated",
|
||||
"ToastPodcastCreateFailed": "Failed to create podcast",
|
||||
"ToastPodcastCreateSuccess": "Podcast created successfully",
|
||||
"ToastPodcastEpisodeUpdated": "Episode updated",
|
||||
"ToastPodcastGetFeedFailed": "Failed to get podcast feed",
|
||||
"ToastPodcastNoEpisodesInFeed": "No episodes found in RSS feed",
|
||||
"ToastPodcastNoRssFeed": "Podcast does not have an RSS feed",
|
||||
|
@ -1102,5 +1151,13 @@
|
|||
"ToastUserPasswordChangeSuccess": "Password changed successfully",
|
||||
"ToastUserPasswordMismatch": "Passwords do not match",
|
||||
"ToastUserPasswordMustChange": "New password cannot match old password",
|
||||
"ToastUserRootRequireName": "Must enter a root username"
|
||||
"ToastUserRootRequireName": "Must enter a root username",
|
||||
"TooltipAddChapters": "Add chapter(s)",
|
||||
"TooltipAddOneSecond": "Add 1 second",
|
||||
"TooltipAdjustChapterStart": "Click to adjust start time",
|
||||
"TooltipLockAllChapters": "Lock all chapters",
|
||||
"TooltipLockChapter": "Lock chapter (Shift+click for range)",
|
||||
"TooltipSubtractOneSecond": "Subtract 1 second",
|
||||
"TooltipUnlockAllChapters": "Unlock all chapters",
|
||||
"TooltipUnlockChapter": "Unlock chapter (Shift+click for range)"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Añadir",
|
||||
"ButtonAddApiKey": "Añadir clave API",
|
||||
"ButtonAddChapters": "Añadir capítulos",
|
||||
"ButtonAddDevice": "Añadir dispositivo",
|
||||
"ButtonAddLibrary": "Añadir biblioteca",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Elegir una carpeta",
|
||||
"ButtonChooseFiles": "Elegir archivos",
|
||||
"ButtonClearFilter": "Quitar filtros",
|
||||
"ButtonClose": "Cerrar",
|
||||
"ButtonCloseFeed": "Cerrar suministro",
|
||||
"ButtonCloseSession": "Cerrar la sesión abierta",
|
||||
"ButtonCollections": "Colecciones",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Cuenta",
|
||||
"HeaderAddCustomMetadataProvider": "Añadir proveedor de metadatos personalizado",
|
||||
"HeaderAdvanced": "Avanzado",
|
||||
"HeaderApiKeys": "Claves API",
|
||||
"HeaderAppriseNotificationSettings": "Configuración de notificaciones de Apprise",
|
||||
"HeaderAudioTracks": "Pistas de audio",
|
||||
"HeaderAudiobookTools": "Herramientas de Gestión de Archivos de Audiolibro",
|
||||
"HeaderAuthentication": "Autenticación",
|
||||
"HeaderBackups": "Respaldos",
|
||||
"HeaderBulkChapterModal": "Añadir Múltiples Capítulos",
|
||||
"HeaderChangePassword": "Cambiar contraseña",
|
||||
"HeaderChapters": "Capítulos",
|
||||
"HeaderChooseAFolder": "Escoger una Carpeta",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Orden de precedencia de metadatos",
|
||||
"HeaderMetadataToEmbed": "Metadatos para Insertar",
|
||||
"HeaderNewAccount": "Cuenta nueva",
|
||||
"HeaderNewApiKey": "Nueva clave API",
|
||||
"HeaderNewLibrary": "Biblioteca nueva",
|
||||
"HeaderNotificationCreate": "Crear notificación",
|
||||
"HeaderNotificationUpdate": "Notificación de actualización",
|
||||
|
@ -195,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Funcionalidades experimentales",
|
||||
"HeaderSettingsGeneral": "Generales",
|
||||
"HeaderSettingsScanner": "Escáner",
|
||||
"HeaderSettingsSecurity": "Seguridad",
|
||||
"HeaderSettingsWebClient": "Cliente web",
|
||||
"HeaderSleepTimer": "Temporizador de apagado",
|
||||
"HeaderStatsLargestItems": "Elementos más grandes",
|
||||
|
@ -206,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Sumario",
|
||||
"HeaderTools": "Herramientas",
|
||||
"HeaderUpdateAccount": "Actualizar cuenta",
|
||||
"HeaderUpdateApiKey": "Actualizar clave API",
|
||||
"HeaderUpdateAuthor": "Actualizar autor",
|
||||
"HeaderUpdateDetails": "Actualizar detalles",
|
||||
"HeaderUpdateLibrary": "Actualizar biblioteca",
|
||||
|
@ -297,6 +304,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Eliminar del sistema de archivos (desmarque para quitar de la base de datos solamente)",
|
||||
"LabelDescription": "Descripción",
|
||||
"LabelDeselectAll": "Deseleccionar Todos",
|
||||
"LabelDetectedPattern": "Patrón detectado:",
|
||||
"LabelDevice": "Dispositivo",
|
||||
"LabelDeviceInfo": "Información del dispositivo",
|
||||
"LabelDeviceIsAvailableTo": "El dispositivo está disponible para...",
|
||||
|
@ -454,6 +462,7 @@
|
|||
"LabelNewestAuthors": "Autores más nuevos",
|
||||
"LabelNewestEpisodes": "Episodios más nuevos",
|
||||
"LabelNextBackupDate": "Fecha del siguiente respaldo",
|
||||
"LabelNextChapters": "Los próximos capítulos serán:",
|
||||
"LabelNextScheduledRun": "Próxima ejecución programada",
|
||||
"LabelNoCustomMetadataProviders": "Sin proveedores de metadatos personalizados",
|
||||
"LabelNoEpisodesSelected": "Ningún Episodio Seleccionado",
|
||||
|
@ -462,17 +471,18 @@
|
|||
"LabelNotes": "Notas",
|
||||
"LabelNotificationAppriseURL": "URL(s) de Apprise",
|
||||
"LabelNotificationAvailableVariables": "Variables disponibles",
|
||||
"LabelNotificationBodyTemplate": "Plantilla de Cuerpo",
|
||||
"LabelNotificationEvent": "Evento de Notificación",
|
||||
"LabelNotificationTitleTemplate": "Plantilla de Titulo",
|
||||
"LabelNotificationsMaxFailedAttempts": "Máximo de Intentos Fallidos",
|
||||
"LabelNotificationBodyTemplate": "Plantilla de cuerpo",
|
||||
"LabelNotificationEvent": "Evento de notificación",
|
||||
"LabelNotificationTitleTemplate": "Plantilla de título",
|
||||
"LabelNotificationsMaxFailedAttempts": "Máximo de intentos fallidos",
|
||||
"LabelNotificationsMaxFailedAttemptsHelp": "Las notificaciones se desactivan después de fallar este número de veces",
|
||||
"LabelNotificationsMaxQueueSize": "Tamaño máximo de la cola de notificaciones",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Las notificaciones están limitadas a 1 por segundo. Las notificaciones serán ignoradas si llegan al numero máximo de cola para prevenir spam de eventos.",
|
||||
"LabelNumberOfBooks": "Número de libros",
|
||||
"LabelNumberOfChapters": "Número de capítulos:",
|
||||
"LabelNumberOfEpisodes": "N.º de episodios",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nombre de la notificación de OpenID que contiene permisos avanzados para acciones de usuario dentro de la aplicación que se aplicarán a roles que no sean de administrador (<b>si están configurados</b>). Si el reclamo no aparece en la respuesta, se denegará el acceso a ABS. Si falta una sola opción, se tratará como <code>falsa</code>. Asegúrese de que la notificación del proveedor de identidades coincida con la estructura esperada:",
|
||||
"LabelOpenIDClaims": "Deje las siguientes opciones vacías para deshabilitar la asignación avanzada de grupos y permisos, lo que asignaría de manera automática al grupo 'Usuario'.",
|
||||
"LabelOpenIDClaims": "Deje las siguientes opciones vacías para desactivar la asignación avanzada de grupos y permisos, lo que asignaría de manera automática al grupo «Usuario».",
|
||||
"LabelOpenIDGroupClaimDescription": "Nombre de la declaración OpenID que contiene una lista de grupos del usuario. Comúnmente conocidos como <code>grupos</code>. <b>Si se configura</b>, la aplicación asignará automáticamente roles en función de la pertenencia a grupos del usuario, siempre que estos grupos se denominen \"admin\", \"user\" o \"guest\" en la notificación. La solicitud debe contener una lista, y si un usuario pertenece a varios grupos, la aplicación asignará el rol correspondiente al mayor nivel de acceso. Si ningún grupo coincide, se denegará el acceso.",
|
||||
"LabelOpenRSSFeed": "Abrir suministro RSS",
|
||||
"LabelOverwrite": "Sobrescribir",
|
||||
|
@ -499,7 +509,7 @@
|
|||
"LabelPodcastType": "Tipo de pódcast",
|
||||
"LabelPodcasts": "Pódcast",
|
||||
"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",
|
||||
"LabelPrimaryEbook": "Libro electrónico principal",
|
||||
"LabelProgress": "Progreso",
|
||||
|
@ -515,7 +525,7 @@
|
|||
"LabelRSSFeedCustomOwnerEmail": "Correo electrónico de dueño personalizado",
|
||||
"LabelRSSFeedCustomOwnerName": "Nombre de dueño personalizado",
|
||||
"LabelRSSFeedOpen": "Suministro RSS abierto",
|
||||
"LabelRSSFeedPreventIndexing": "Prevenir indexado",
|
||||
"LabelRSSFeedPreventIndexing": "Evitar indización",
|
||||
"LabelRSSFeedSlug": "«Slug» de suministro RSS",
|
||||
"LabelRSSFeedURL": "URL de suministro RSS",
|
||||
"LabelRandomly": "Aleatorio",
|
||||
|
@ -531,6 +541,7 @@
|
|||
"LabelReleaseDate": "Fecha de estreno",
|
||||
"LabelRemoveAllMetadataAbs": "Eliminar todos los archivos metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Eliminar todos los archivos metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Quitar introducción y cierre de Audible de los capítulos",
|
||||
"LabelRemoveCover": "Quitar cubierta",
|
||||
"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}.",
|
||||
|
@ -539,7 +550,7 @@
|
|||
"LabelSearchTitle": "Buscar título",
|
||||
"LabelSearchTitleOrASIN": "Buscar título o ASIN",
|
||||
"LabelSeason": "Temporada",
|
||||
"LabelSeasonNumber": "Sesión #{0}",
|
||||
"LabelSeasonNumber": "{0}.ª temporada",
|
||||
"LabelSelectAll": "Seleccionar todo",
|
||||
"LabelSelectAllEpisodes": "Seleccionar todos los episodios",
|
||||
"LabelSelectEpisodesShowing": "Seleccionar los {0} episodios visibles",
|
||||
|
@ -707,6 +718,7 @@
|
|||
"MessageAddToPlayerQueue": "Agregar a fila del Reproductor",
|
||||
"MessageAppriseDescription": "Para usar esta función deberás tener <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">la API de Apprise</a> corriendo o una API que maneje los mismos resultados. <br/>La URL de la API de Apprise debe tener la misma ruta de archivos que donde se envían las notificaciones. Por ejemplo: si su API esta en <code>http://192.168.1.1:8337</code> entonces pondría <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Cerciórese de usar el ASIN de la región correcta de Audible, no de Amazon.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Reinicie el servidor tras el guardado para aplicar los cambios de OIDC.",
|
||||
"MessageBackupsDescription": "Los respaldos incluyen: usuarios, el progreso del los usuarios, los detalles de los elementos de la biblioteca, la configuración del servidor y las imágenes en <code>/metadata/items</code> y <code>/metadata/authors</code>. Los Respaldos <strong>NO</strong> incluyen ningún archivo guardado en la carpeta de tu biblioteca.",
|
||||
"MessageBackupsLocationEditNote": "Nota: actualizar la ubicación de la copia de respaldo no moverá ni modificará los respaldos existentes",
|
||||
"MessageBackupsLocationNoEditNote": "Nota: la ubicación de la copia de respaldo se establece a través de una variable de entorno y no se puede cambiar aquí.",
|
||||
|
@ -720,6 +732,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "El filtro «{0}: {1}» no produjo ningún resultado",
|
||||
"MessageBookshelfNoResultsForQuery": "No hay resultados para la consulta",
|
||||
"MessageBookshelfNoSeries": "No tiene ninguna serie",
|
||||
"MessageBulkChapterPattern": "¿Cuántos capítulos desea añadir con este patrón de numeración?",
|
||||
"MessageChapterEndIsAfter": "El final del capítulo es después del final de tu audiolibro",
|
||||
"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",
|
||||
|
@ -748,7 +761,7 @@
|
|||
"MessageConfirmNotificationTestTrigger": "¿Activar esta notificación con datos de prueba?",
|
||||
"MessageConfirmPurgeCache": "Purgar la antememoria eliminará el directorio completo ubicado en <code>/metadata/cache</code>. <br /><br />¿Confirma que quiere eliminar el directorio de antememoria?",
|
||||
"MessageConfirmPurgeItemsCache": "Purgar la antememoria de elementos eliminará el directorio completo ubicado en <code>/metadata/cache/items</code>.<br />¿Lo confirma?",
|
||||
"MessageConfirmQuickEmbed": "¡Advertencia! La integración rápida no realiza copias de seguridad a ninguno de tus archivos de audio. Asegúrate de haber realizado una copia de los mismos previamente. <br><br>¿Deseas continuar?",
|
||||
"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. ¿Quiere continuar?",
|
||||
"MessageConfirmReScanLibraryItems": "¿Confirma que quiere volver a analizar {0} elementos?",
|
||||
"MessageConfirmRemoveAllChapters": "¿Confirma que quiere quitar todos los capítulos?",
|
||||
|
@ -841,7 +854,7 @@
|
|||
"MessageQuickEmbedInProgress": "Integración rápida en proceso",
|
||||
"MessageQuickEmbedQueue": "En cola para inserción rápida ({0} en cola)",
|
||||
"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": "Quitar capítulo",
|
||||
"MessageRemoveEpisodes": "Quitar {0} episodio(s)",
|
||||
"MessageRemoveFromPlayerQueue": "Quitar de la cola de reproducción",
|
||||
|
@ -854,6 +867,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Ejecutar cada {0} a las {1}",
|
||||
"MessageSearchResultsFor": "Resultados de la búsqueda de",
|
||||
"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",
|
||||
"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>",
|
||||
|
@ -916,6 +930,7 @@
|
|||
"NotificationOnBackupFailedDescription": "Se activa cuando falla una copia de seguridad",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Se activa cuando se descarga automáticamente un episodio de un podcast",
|
||||
"NotificationOnTestDescription": "Evento para probar el sistema de notificaciones",
|
||||
"PlaceholderBulkChapterInput": "Ingrese título de capítulo o use numeración (ej. 'Episodio 1', 'Capítulo 10', '1.')",
|
||||
"PlaceholderNewCollection": "Nuevo nombre de la colección",
|
||||
"PlaceholderNewFolderPath": "Nueva ruta de carpeta",
|
||||
"PlaceholderNewPlaylist": "Nuevo nombre de la lista de reproducción",
|
||||
|
@ -954,33 +969,37 @@
|
|||
"ToastBackupCreateSuccess": "Respaldo creado",
|
||||
"ToastBackupDeleteFailed": "Error al eliminar respaldo",
|
||||
"ToastBackupDeleteSuccess": "Respaldo eliminado",
|
||||
"ToastBackupInvalidMaxKeep": "Número no válido de copias de seguridad a conservar",
|
||||
"ToastBackupInvalidMaxSize": "Tamaño máximo de copia de seguridad no válido",
|
||||
"ToastBackupInvalidMaxKeep": "Número no válido de copias de respaldo para conservar",
|
||||
"ToastBackupInvalidMaxSize": "Tamaño máximo de copia de respaldo no válido",
|
||||
"ToastBackupRestoreFailed": "Error al restaurar el respaldo",
|
||||
"ToastBackupUploadFailed": "Error al subir el respaldo",
|
||||
"ToastBackupUploadFailed": "Error al cargar la copia de respaldo",
|
||||
"ToastBackupUploadSuccess": "Respaldo cargado",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Detalles aplicados a los elementos",
|
||||
"ToastBatchDeleteFailed": "Error al eliminar por lotes",
|
||||
"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!",
|
||||
"ToastBatchQuickMatchStarted": "¡Se inició el lote de búsqueda rápida de {0} libros!",
|
||||
"ToastBatchUpdateFailed": "Subida masiva fallida",
|
||||
"ToastBatchUpdateSuccess": "Subida masiva exitosa",
|
||||
"ToastBookmarkCreateFailed": "Error al crear marcador",
|
||||
"ToastBookmarkCreateSuccess": "Marcador Agregado",
|
||||
"ToastBatchUpdateFailed": "Falló la actualización por lotes",
|
||||
"ToastBatchUpdateSuccess": "Se actualizó por lotes correctamente",
|
||||
"ToastBookmarkCreateFailed": "No se pudo crear el marcador",
|
||||
"ToastBookmarkCreateSuccess": "Marcador añadido",
|
||||
"ToastBookmarkRemoveSuccess": "Marcador eliminado",
|
||||
"ToastCachePurgeFailed": "Error al purgar el caché",
|
||||
"ToastCachePurgeSuccess": "Caché purgado de manera exitosa",
|
||||
"ToastBulkChapterInvalidCount": "Por favor ingrese un número válido entre 1 y 150",
|
||||
"ToastCachePurgeFailed": "No se pudo purgar la antememoria",
|
||||
"ToastCachePurgeSuccess": "Se purgó la antememoria correctamente",
|
||||
"ToastChaptersAllLocked": "Todos los capítulos están bloqueados. Desbloquee algunos capítulos para cambiar sus tiempos.",
|
||||
"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",
|
||||
"ToastChaptersUpdated": "Capítulos actualizados",
|
||||
"ToastCollectionItemsAddFailed": "Artículo(s) añadido(s) a la colección fallido(s)",
|
||||
"ToastCollectionRemoveSuccess": "Colección quitada",
|
||||
"ToastCollectionUpdateSuccess": "Colección actualizada",
|
||||
"ToastCoverUpdateFailed": "Error al actualizar la cubierta",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Fecha y hora inválidas o incompletas",
|
||||
"ToastDeleteFileFailed": "Error el eliminar archivo",
|
||||
"ToastDateTimeInvalidOrIncomplete": "Fecha y hora no válidas o incompletas",
|
||||
"ToastDeleteFileFailed": "Falló la eliminación del archivo",
|
||||
"ToastDeleteFileSuccess": "Archivo eliminado",
|
||||
"ToastDeviceAddFailed": "Error al añadir dispositivo",
|
||||
"ToastDeviceNameAlreadyExists": "Un libro electrónico ya existe con ese nombre",
|
||||
|
@ -1098,5 +1117,12 @@
|
|||
"ToastUserPasswordChangeSuccess": "Contraseña modificada correctamente",
|
||||
"ToastUserPasswordMismatch": "No coinciden las contraseñas",
|
||||
"ToastUserPasswordMustChange": "La nueva contraseña no puede ser igual que la anterior",
|
||||
"ToastUserRootRequireName": "Debe introducir un nombre de usuario administrativo"
|
||||
"ToastUserRootRequireName": "Debe introducir un nombre de usuario administrativo",
|
||||
"TooltipAddChapters": "Añadir capítulo(s)",
|
||||
"TooltipAddOneSecond": "Añadir 1 segundo",
|
||||
"TooltipLockAllChapters": "Bloquear todos los capítulos",
|
||||
"TooltipLockChapter": "Bloquear capítulo (Mayús+clic para rango)",
|
||||
"TooltipSubtractOneSecond": "Restar 1 segundo",
|
||||
"TooltipUnlockAllChapters": "Desbloquear todos los capítulos",
|
||||
"TooltipUnlockChapter": "Desbloquear capítulo (Mayús+clic para rango)"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"ButtonAuthors": "Autorid",
|
||||
"ButtonBack": "Tagasi",
|
||||
"ButtonBrowseForFolder": "Sirvi kausta",
|
||||
"ButtonCancel": "Tühista",
|
||||
"ButtonCancel": "Katkesta",
|
||||
"ButtonCancelEncode": "Tühista kodeerimine",
|
||||
"ButtonChangeRootPassword": "Muuda põhiparooli",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "Kontrolli ja laadi alla uued episoodid",
|
||||
|
@ -20,9 +20,9 @@
|
|||
"ButtonClearFilter": "Tühista filter",
|
||||
"ButtonCloseFeed": "Sulge voog",
|
||||
"ButtonCloseSession": "Sulge avatud sessioon",
|
||||
"ButtonCollections": "Kogud",
|
||||
"ButtonCollections": "Kollektsioonid",
|
||||
"ButtonConfigureScanner": "Konfigureeri skanner",
|
||||
"ButtonCreate": "Loo",
|
||||
"ButtonCreate": "Loo uus",
|
||||
"ButtonCreateBackup": "Loo varundus",
|
||||
"ButtonDelete": "Kustuta",
|
||||
"ButtonDownloadQueue": "Järjekord",
|
||||
|
@ -37,7 +37,7 @@
|
|||
"ButtonIssues": "Probleemid",
|
||||
"ButtonJumpBackward": "Hüppa tagasi",
|
||||
"ButtonJumpForward": "Hüppa edasi",
|
||||
"ButtonLatest": "Uusim",
|
||||
"ButtonLatest": "Viimased",
|
||||
"ButtonLibrary": "Raamatukogu",
|
||||
"ButtonLogout": "Logi välja",
|
||||
"ButtonLookup": "Otsi",
|
||||
|
@ -52,11 +52,11 @@
|
|||
"ButtonOk": "Ok",
|
||||
"ButtonOpenFeed": "Ava voog",
|
||||
"ButtonOpenManager": "Ava haldur",
|
||||
"ButtonPause": "Peata",
|
||||
"ButtonPlay": "Mängi",
|
||||
"ButtonPause": "Paus",
|
||||
"ButtonPlay": "Play",
|
||||
"ButtonPlayAll": "Mängi kõik",
|
||||
"ButtonPlaying": "Mängib",
|
||||
"ButtonPlaylists": "Esitusloendid",
|
||||
"ButtonPlaylists": "Playlist",
|
||||
"ButtonPrevious": "Eelmine",
|
||||
"ButtonPreviousChapter": "Eelmine peatükk",
|
||||
"ButtonPurgeAllCache": "Tühjenda kogu vahemälu",
|
||||
|
@ -69,7 +69,7 @@
|
|||
"ButtonReadLess": "Loe vähem",
|
||||
"ButtonReadMore": "Loe rohkem",
|
||||
"ButtonRefresh": "Värskenda",
|
||||
"ButtonRemove": "Eemalda",
|
||||
"ButtonRemove": "Kustuta",
|
||||
"ButtonRemoveAll": "Eemalda kõik",
|
||||
"ButtonRemoveAllLibraryItems": "Eemalda kõik raamatukogu esemed",
|
||||
"ButtonRemoveFromContinueListening": "Eemalda jätkake kuulamisest",
|
||||
|
@ -120,12 +120,12 @@
|
|||
"HeaderCustomMetadataProviders": "Kohandatud metaandmete pakkujad",
|
||||
"HeaderDetails": "Detailid",
|
||||
"HeaderDownloadQueue": "Allalaadimise järjekord",
|
||||
"HeaderEbookFiles": "E-raamatute failid",
|
||||
"HeaderEbookFiles": "E-raamatu failid",
|
||||
"HeaderEmail": "E-post",
|
||||
"HeaderEmailSettings": "E-posti seaded",
|
||||
"HeaderEpisodes": "Episoodid",
|
||||
"HeaderEreaderDevices": "E-lugerite seadmed",
|
||||
"HeaderEreaderSettings": "E-lugerite seadistused",
|
||||
"HeaderEreaderSettings": "E-lugeja sätted",
|
||||
"HeaderFiles": "Failid",
|
||||
"HeaderFindChapters": "Leia peatükid",
|
||||
"HeaderIgnoredFiles": "Ignoreeritud failid",
|
||||
|
@ -155,8 +155,8 @@
|
|||
"HeaderPasswordAuthentication": "Parooli autentimine",
|
||||
"HeaderPermissions": "Õigused",
|
||||
"HeaderPlayerQueue": "Mängija järjekord",
|
||||
"HeaderPlaylist": "Mänguloend",
|
||||
"HeaderPlaylistItems": "Mänguloendi esemed",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
"HeaderPlaylistItems": "Playlisti esemed",
|
||||
"HeaderPodcastsToAdd": "Lisatavad podcastid",
|
||||
"HeaderPreviewCover": "Eelvaate kaas",
|
||||
"HeaderRSSFeedGeneral": "RSS-i üksikasjad",
|
||||
|
@ -174,7 +174,7 @@
|
|||
"HeaderSettingsExperimental": "Katsetusfunktsioonid",
|
||||
"HeaderSettingsGeneral": "Üldised",
|
||||
"HeaderSettingsScanner": "Skanner",
|
||||
"HeaderSleepTimer": "Uinaku taimer",
|
||||
"HeaderSleepTimer": "Unetaimer",
|
||||
"HeaderStatsLargestItems": "Suurimad esemed",
|
||||
"HeaderStatsLongestItems": "Kõige pikemad esemed (tunnid)",
|
||||
"HeaderStatsMinutesListeningChart": "Kuulamise minutid (viimased 7 päeva)",
|
||||
|
@ -197,9 +197,10 @@
|
|||
"LabelActivity": "Tegevus",
|
||||
"LabelAddToCollection": "Lisa kogusse",
|
||||
"LabelAddToCollectionBatch": "Lisa {0} raamatut kogusse",
|
||||
"LabelAddToPlaylist": "Lisa mänguloendisse",
|
||||
"LabelAddToPlaylist": "Lisa playlisti",
|
||||
"LabelAddToPlaylistBatch": "Lisa {0} eset mänguloendisse",
|
||||
"LabelAddedAt": "Lisatud",
|
||||
"LabelAddedDate": "Lisatud {0}",
|
||||
"LabelAdminUsersOnly": "Ainult administraatorid",
|
||||
"LabelAll": "Kõik",
|
||||
"LabelAllUsers": "Kõik kasutajad",
|
||||
|
@ -208,10 +209,10 @@
|
|||
"LabelAlreadyInYourLibrary": "Juba teie raamatukogus",
|
||||
"LabelAppend": "Lisa",
|
||||
"LabelAuthor": "Autor",
|
||||
"LabelAuthorFirstLast": "Autor (Eesnimi Perekonnanimi)",
|
||||
"LabelAuthorLastFirst": "Autor (Perekonnanimi, Eesnimi)",
|
||||
"LabelAuthorFirstLast": "Autor (eesnimi perekonnanimi)",
|
||||
"LabelAuthorLastFirst": "Autor (perekonnanimi, eesnimi)",
|
||||
"LabelAuthors": "Autorid",
|
||||
"LabelAutoDownloadEpisodes": "Automaatne episoodide allalaadimine",
|
||||
"LabelAutoDownloadEpisodes": "Episoodide automaatne allalaadimine",
|
||||
"LabelAutoFetchMetadata": "Automaatne metaandmete hankimine",
|
||||
"LabelAutoFetchMetadataHelp": "Toob tiitli, autori ja seeria metaandmed üleslaadimise hõlbustamiseks. Lisametaandmed võivad pärast üleslaadimist vajada vastavust.",
|
||||
"LabelAutoLaunch": "Automaatne käivitamine",
|
||||
|
@ -265,7 +266,7 @@
|
|||
"LabelDiscover": "Avasta",
|
||||
"LabelDownload": "Lae alla",
|
||||
"LabelDownloadNEpisodes": "Lae alla {0} episoodi",
|
||||
"LabelDuration": "Kestus",
|
||||
"LabelDuration": "Kestvus",
|
||||
"LabelDurationFound": "Leitud kestus:",
|
||||
"LabelEbook": "E-raamat",
|
||||
"LabelEbooks": "E-raamatud",
|
||||
|
@ -278,6 +279,7 @@
|
|||
"LabelEmbeddedCover": "Manustatud kaas",
|
||||
"LabelEnable": "Luba",
|
||||
"LabelEnd": "Lõpp",
|
||||
"LabelEndOfChapter": "Peatükki lõpp",
|
||||
"LabelEpisode": "Episood",
|
||||
"LabelEpisodeTitle": "Episoodi pealkiri",
|
||||
"LabelEpisodeType": "Episoodi tüüp",
|
||||
|
@ -288,13 +290,14 @@
|
|||
"LabelFile": "Fail",
|
||||
"LabelFileBirthtime": "Faili sünniaeg",
|
||||
"LabelFileModified": "Faili muudetud",
|
||||
"LabelFilename": "Failinimi",
|
||||
"LabelFilename": "Faili nimi",
|
||||
"LabelFilterByUser": "Filtri alusel kasutaja järgi",
|
||||
"LabelFindEpisodes": "Otsi episoodid",
|
||||
"LabelFinished": "Lõpetatud",
|
||||
"LabelFolder": "Kaust",
|
||||
"LabelFolders": "Kataloogid",
|
||||
"LabelFontBold": "Paks",
|
||||
"LabelFontBoldness": "Fondi paksus",
|
||||
"LabelFontFamily": "Fondi pere",
|
||||
"LabelFontItalic": "Kaldkiri",
|
||||
"LabelFontScale": "Fondi suurus",
|
||||
|
@ -303,7 +306,7 @@
|
|||
"LabelGenre": "Žanr",
|
||||
"LabelGenres": "Žanrid",
|
||||
"LabelHardDeleteFile": "Faili lõplik kustutamine",
|
||||
"LabelHasEbook": "On e-raamat",
|
||||
"LabelHasEbook": "E-raamat olemas",
|
||||
"LabelHasSupplementaryEbook": "On täiendav e-raamat",
|
||||
"LabelHighestPriority": "Kõrgeim prioriteet",
|
||||
"LabelHour": "Tund",
|
||||
|
@ -311,7 +314,7 @@
|
|||
"LabelImageURLFromTheWeb": "Pildi URL veebist",
|
||||
"LabelInProgress": "Pooleli",
|
||||
"LabelIncludeInTracklist": "Kaasa jälgimisloendis",
|
||||
"LabelIncomplete": "Puudulik",
|
||||
"LabelIncomplete": "Lõpetamata",
|
||||
"LabelInterval": "Intervall",
|
||||
"LabelIntervalCustomDailyWeekly": "Kohandatud päevane/nädalane",
|
||||
"LabelIntervalEvery12Hours": "Iga 12 tunni tagant",
|
||||
|
@ -365,12 +368,12 @@
|
|||
"LabelNarrators": "Jutustajad",
|
||||
"LabelNew": "Uus",
|
||||
"LabelNewPassword": "Uus parool",
|
||||
"LabelNewestAuthors": "Uusimad autorid",
|
||||
"LabelNewestEpisodes": "Uusimad episoodid",
|
||||
"LabelNewestAuthors": "Uuemad autorid",
|
||||
"LabelNewestEpisodes": "Uuemad episoodid",
|
||||
"LabelNextBackupDate": "Järgmine varukoopia kuupäev",
|
||||
"LabelNextScheduledRun": "Järgmine ajakava järgmine",
|
||||
"LabelNoEpisodesSelected": "Episoodid pole valitud",
|
||||
"LabelNotFinished": "Ei ole lõpetatud",
|
||||
"LabelNotFinished": "Lõpetamata",
|
||||
"LabelNotStarted": "Pole alustatud",
|
||||
"LabelNotes": "Märkused",
|
||||
"LabelNotificationAppriseURL": "Apprise URL-id",
|
||||
|
@ -383,7 +386,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Teavituste sündmuste maksimaalne järjekorra suurus",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Sündmused on piiratud 1 sekundiga. Sündmusi ignoreeritakse, kui järjekord on maksimumsuuruses. See takistab teavituste rämpsposti.",
|
||||
"LabelNumberOfBooks": "Raamatute arv",
|
||||
"LabelNumberOfEpisodes": "Episoodide arv",
|
||||
"LabelNumberOfEpisodes": "# episoode",
|
||||
"LabelOpenRSSFeed": "Ava RSS voog",
|
||||
"LabelOverwrite": "Kirjuta üle",
|
||||
"LabelPassword": "Parool",
|
||||
|
@ -398,16 +401,18 @@
|
|||
"LabelPhotoPathURL": "Foto tee/URL",
|
||||
"LabelPlayMethod": "Esitusmeetod",
|
||||
"LabelPlaylists": "Mänguloendid",
|
||||
"LabelPodcast": "Podcast",
|
||||
"LabelPodcastSearchRegion": "Podcasti otsingu piirkond",
|
||||
"LabelPodcastType": "Podcasti tüüp",
|
||||
"LabelPodcasts": "Podcastid",
|
||||
"LabelPrefixesToIgnore": "Eiramiseks eesliited (tõstutundetu)",
|
||||
"LabelPreventIndexing": "Vältige oma voogu indekseerimist iTunes'i ja Google podcasti kataloogides",
|
||||
"LabelPrimaryEbook": "Esmane e-raamat",
|
||||
"LabelProgress": "Edenemine",
|
||||
"LabelProgress": "Progress",
|
||||
"LabelProvider": "Pakkuja",
|
||||
"LabelPubDate": "Avaldamise kuupäev",
|
||||
"LabelPublishYear": "Aasta avaldamine",
|
||||
"LabelPubDate": "Publitseerimise kuupäev",
|
||||
"LabelPublishYear": "Publitseerimise aasta",
|
||||
"LabelPublishedDate": "Publitseeritud {0}",
|
||||
"LabelPublisher": "Kirjastaja",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Kohandatud omaniku e-post",
|
||||
"LabelRSSFeedCustomOwnerName": "Kohandatud omaniku nimi",
|
||||
|
@ -415,7 +420,8 @@
|
|||
"LabelRSSFeedPreventIndexing": "Vältige indekseerimist",
|
||||
"LabelRSSFeedSlug": "RSS voog Slug",
|
||||
"LabelRSSFeedURL": "RSS voog URL",
|
||||
"LabelRead": "Lugenud",
|
||||
"LabelRandomly": "Juhuslikus järjekorras",
|
||||
"LabelRead": "Loetud läbi",
|
||||
"LabelReadAgain": "Loe uuesti",
|
||||
"LabelReadEbookWithoutProgress": "Lugege e-raamatut ilma edenemist säilitamata",
|
||||
"LabelRecentSeries": "Hiljutised seeriad",
|
||||
|
@ -469,9 +475,9 @@
|
|||
"LabelSettingsStoreMetadataWithItem": "Salvesta metaandmed üksusega",
|
||||
"LabelSettingsStoreMetadataWithItemHelp": "Vaikimisi salvestatakse metaandmed /metadata/items kausta. Selle seadistuse lubamine salvestab metaandmed teie raamatukogu üksuse kaustadesse",
|
||||
"LabelSettingsTimeFormat": "Kellaaja vorming",
|
||||
"LabelShowAll": "Näita kõiki",
|
||||
"LabelShowAll": "Näita kõik",
|
||||
"LabelSize": "Suurus",
|
||||
"LabelSleepTimer": "Uinaku taimer",
|
||||
"LabelSleepTimer": "Unetaimer",
|
||||
"LabelStart": "Alusta",
|
||||
"LabelStartTime": "Alustamise aeg",
|
||||
"LabelStarted": "Alustatud",
|
||||
|
@ -480,13 +486,13 @@
|
|||
"LabelStatsAuthors": "Autorid",
|
||||
"LabelStatsBestDay": "Parim päev",
|
||||
"LabelStatsDailyAverage": "Päevane keskmine",
|
||||
"LabelStatsDays": "Päevad",
|
||||
"LabelStatsDays": "Päevi",
|
||||
"LabelStatsDaysListened": "Kuulatud päevad",
|
||||
"LabelStatsHours": "Tunnid",
|
||||
"LabelStatsInARow": "järjest",
|
||||
"LabelStatsItemsFinished": "Lõpetatud üksused",
|
||||
"LabelStatsItemsInLibrary": "Üksused raamatukogus",
|
||||
"LabelStatsMinutes": "minutit",
|
||||
"LabelStatsMinutes": "minuteid",
|
||||
"LabelStatsMinutesListening": "Kuulamise minutid",
|
||||
"LabelStatsOverallDays": "Kokku päevad",
|
||||
"LabelStatsOverallHours": "Kokku tunnid",
|
||||
|
@ -502,7 +508,7 @@
|
|||
"LabelTextEditorNumberedList": "Numberloend",
|
||||
"LabelTextEditorUnlink": "Eemalda link",
|
||||
"LabelTheme": "Teema",
|
||||
"LabelThemeDark": "Tume",
|
||||
"LabelThemeDark": "Pime",
|
||||
"LabelThemeLight": "Hele",
|
||||
"LabelTimeBase": "Aja alus",
|
||||
"LabelTimeListened": "Kuulatud aeg",
|
||||
|
@ -527,7 +533,7 @@
|
|||
"LabelType": "Tüüp",
|
||||
"LabelUnabridged": "Täismahus",
|
||||
"LabelUndo": "Võta tagasi",
|
||||
"LabelUnknown": "Tundmatu",
|
||||
"LabelUnknown": "Teadmata",
|
||||
"LabelUpdateCover": "Uuenda kaant",
|
||||
"LabelUpdateCoverHelp": "Luba üle kirjutamine olemasolevate kaante jaoks valitud raamatutele, kui leitakse sobivus",
|
||||
"LabelUpdateDetails": "Uuenda üksikasju",
|
||||
|
|
1
client/strings/eu.json
Normal file
1
client/strings/eu.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Ajouter",
|
||||
"ButtonAddApiKey": "Ajouter une clé API",
|
||||
"ButtonAddChapters": "Ajouter des chapitres",
|
||||
"ButtonAddDevice": "Ajouter un appareil",
|
||||
"ButtonAddLibrary": "Ajouter une bibliothèque",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Sélectionner un dossier",
|
||||
"ButtonChooseFiles": "Sélectionner des fichiers",
|
||||
"ButtonClearFilter": "Effacer le filtre",
|
||||
"ButtonClose": "Fermer",
|
||||
"ButtonCloseFeed": "Fermer le flux",
|
||||
"ButtonCloseSession": "Fermer la session",
|
||||
"ButtonCollections": "Collections",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Compte",
|
||||
"HeaderAddCustomMetadataProvider": "Ajouter un fournisseur de métadonnées personnalisé",
|
||||
"HeaderAdvanced": "Avancé",
|
||||
"HeaderApiKeys": "Clés API",
|
||||
"HeaderAppriseNotificationSettings": "Configuration des notifications Apprise",
|
||||
"HeaderAudioTracks": "Pistes audio",
|
||||
"HeaderAudiobookTools": "Outils de gestion de fichiers de livres audio",
|
||||
"HeaderAuthentication": "Authentification",
|
||||
"HeaderBackups": "Sauvegardes",
|
||||
"HeaderBulkChapterModal": "Ajouter Plusieurs Chapitres",
|
||||
"HeaderChangePassword": "Modifier le mot de passe",
|
||||
"HeaderChapters": "Chapitres",
|
||||
"HeaderChooseAFolder": "Sélectionner un dossier",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Ordre de priorité des métadonnées",
|
||||
"HeaderMetadataToEmbed": "Métadonnées à intégrer",
|
||||
"HeaderNewAccount": "Nouveau compte",
|
||||
"HeaderNewApiKey": "Nouvelle clé API",
|
||||
"HeaderNewLibrary": "Nouvelle bibliothèque",
|
||||
"HeaderNotificationCreate": "Créer une notification",
|
||||
"HeaderNotificationUpdate": "Mise à jour de la notification",
|
||||
|
@ -177,6 +182,7 @@
|
|||
"HeaderPlaylist": "Liste de lecture",
|
||||
"HeaderPlaylistItems": "Éléments de la liste de lecture",
|
||||
"HeaderPodcastsToAdd": "Podcasts à ajouter",
|
||||
"HeaderPresets": "Préréglages",
|
||||
"HeaderPreviewCover": "Prévisualiser la couverture",
|
||||
"HeaderRSSFeedGeneral": "Détails du flux RSS",
|
||||
"HeaderRSSFeedIsOpen": "Le flux RSS est actif",
|
||||
|
@ -194,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Fonctionnalités expérimentales",
|
||||
"HeaderSettingsGeneral": "Général",
|
||||
"HeaderSettingsScanner": "Analyseur",
|
||||
"HeaderSettingsSecurity": "Sécurité",
|
||||
"HeaderSettingsWebClient": "Client Web",
|
||||
"HeaderSleepTimer": "Minuterie",
|
||||
"HeaderStatsLargestItems": "Éléments les plus grands",
|
||||
|
@ -201,10 +208,11 @@
|
|||
"HeaderStatsMinutesListeningChart": "Minutes d’écoute (7 derniers jours)",
|
||||
"HeaderStatsRecentSessions": "Sessions récentes",
|
||||
"HeaderStatsTop10Authors": "Top 10 Auteurs",
|
||||
"HeaderStatsTop5Genres": "Top 5 Genres",
|
||||
"HeaderStatsTop5Genres": "Top 5 des genres",
|
||||
"HeaderTableOfContents": "Table des matières",
|
||||
"HeaderTools": "Outils",
|
||||
"HeaderUpdateAccount": "Mettre à jour le compte",
|
||||
"HeaderUpdateApiKey": "Mettre à jour la clé API",
|
||||
"HeaderUpdateAuthor": "Mettre à jour l’auteur",
|
||||
"HeaderUpdateDetails": "Mettre à jour les détails",
|
||||
"HeaderUpdateLibrary": "Mettre à jour la bibliothèque",
|
||||
|
@ -234,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Tous les utilisateurs à l’exception des invités",
|
||||
"LabelAllUsersIncludingGuests": "Tous les utilisateurs, y compris les invités",
|
||||
"LabelAlreadyInYourLibrary": "Déjà dans la bibliothèque",
|
||||
"LabelApiKeyCreated": "La clé API « {0} » a été créée avec succès.",
|
||||
"LabelApiKeyCreatedDescription": "Assurez-vous de copier la clé API maintenant car vous ne pourrez plus la voir.",
|
||||
"LabelApiKeyUser": "Agir au nom de l’utilisateur",
|
||||
"LabelApiKeyUserDescription": "Cette clé API disposera des mêmes autorisations que l’utilisateur pour lequel elle agit. Elle apparaîtra dans les journaux comme si c’était l’utilisateur qui effectuait la requête.",
|
||||
"LabelApiToken": "Token API",
|
||||
"LabelAppend": "Ajouter",
|
||||
"LabelAudioBitrate": "Débit audio (par exemple 128k)",
|
||||
|
@ -280,9 +292,10 @@
|
|||
"LabelCollections": "Collections",
|
||||
"LabelComplete": "Complet",
|
||||
"LabelConfirmPassword": "Confirmer le mot de passe",
|
||||
"LabelContinueListening": "Continuer la lecture",
|
||||
"LabelContinueListening": "Continuer l'écoute",
|
||||
"LabelContinueReading": "Continuer la lecture",
|
||||
"LabelContinueSeries": "Continuer les séries",
|
||||
"LabelCorsAllowed": "Origines autorisées pour les requêtes CORS",
|
||||
"LabelCover": "Couverture",
|
||||
"LabelCoverImageURL": "URL vers l’image de couverture",
|
||||
"LabelCoverProvider": "Source des couvertures",
|
||||
|
@ -296,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Supprimer du système de fichiers (décocher pour ne supprimer que de la base de données)",
|
||||
"LabelDescription": "Description",
|
||||
"LabelDeselectAll": "Tout déselectionner",
|
||||
"LabelDetectedPattern": "Motif détecté :",
|
||||
"LabelDevice": "Appareil",
|
||||
"LabelDeviceInfo": "Détail de l’appareil",
|
||||
"LabelDeviceIsAvailableTo": "L’appareil est disponible pour…",
|
||||
|
@ -303,7 +317,7 @@
|
|||
"LabelDiscFromFilename": "Depuis le fichier",
|
||||
"LabelDiscFromMetadata": "Depuis les métadonnées",
|
||||
"LabelDiscover": "Découvrir",
|
||||
"LabelDownload": "Téléchargement",
|
||||
"LabelDownload": "Télécharger",
|
||||
"LabelDownloadNEpisodes": "Télécharger {0} épisode(s)",
|
||||
"LabelDownloadable": "Téléchargeable",
|
||||
"LabelDuration": "Durée",
|
||||
|
@ -345,7 +359,11 @@
|
|||
"LabelExample": "Exemple",
|
||||
"LabelExpandSeries": "Développer la série",
|
||||
"LabelExpandSubSeries": "Développer les sous-séries",
|
||||
"LabelExplicit": "Restriction",
|
||||
"LabelExpired": "Expiré",
|
||||
"LabelExpiresAt": "Expire à",
|
||||
"LabelExpiresInSeconds": "Expire dans (secondes)",
|
||||
"LabelExpiresNever": "Jamais",
|
||||
"LabelExplicit": "Contenu explicite",
|
||||
"LabelExplicitChecked": "Explicite (vérifié)",
|
||||
"LabelExplicitUnchecked": "Non explicite (non vérifié)",
|
||||
"LabelExportOPML": "Exporter OPML",
|
||||
|
@ -404,6 +422,7 @@
|
|||
"LabelLanguages": "Langues",
|
||||
"LabelLastBookAdded": "Dernier livre ajouté",
|
||||
"LabelLastBookUpdated": "Dernier livre mis à jour",
|
||||
"LabelLastProgressDate": "Dernière position : {0}",
|
||||
"LabelLastSeen": "Vu dernièrement",
|
||||
"LabelLastTime": "Progression",
|
||||
"LabelLastUpdate": "Dernière mise à jour",
|
||||
|
@ -416,14 +435,16 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Aucun {0}",
|
||||
"LabelLibraryItem": "Élément de bibliothèque",
|
||||
"LabelLibraryName": "Nom de la bibliothèque",
|
||||
"LabelLibrarySortByProgress": "Progression mise à jour",
|
||||
"LabelLimit": "Limite",
|
||||
"LabelLineSpacing": "Espacement des lignes",
|
||||
"LabelListenAgain": "Écouter à nouveau",
|
||||
"LabelLogLevelDebug": "Débogage",
|
||||
"LabelLogLevelInfo": "Info",
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLogLevelWarn": "Attention",
|
||||
"LabelLookForNewEpisodesAfterDate": "Rechercher les nouveaux épisodes après cette date",
|
||||
"LabelLowestPriority": "Priorité la plus basse",
|
||||
"LabelMatchConfidence": "Confiance",
|
||||
"LabelMatchExistingUsersBy": "Correspondance avec les utilisateurs existants",
|
||||
"LabelMatchExistingUsersByDescription": "Utilisé pour connecter les utilisateurs existants. Une fois connectés, les utilisateurs seront associés à un identifiant unique provenant de votre fournisseur SSO",
|
||||
"LabelMaxEpisodesToDownload": "Nombre maximum d’épisodes à télécharger. 0 pour illimité.",
|
||||
|
@ -453,7 +474,9 @@
|
|||
"LabelNewestAuthors": "Auteurs récents",
|
||||
"LabelNewestEpisodes": "Épisodes récents",
|
||||
"LabelNextBackupDate": "Date de la prochaine sauvegarde",
|
||||
"LabelNextChapters": "Les prochains chapitres seront :",
|
||||
"LabelNextScheduledRun": "Prochain lancement prévu",
|
||||
"LabelNoApiKeys": "Aucune clé API",
|
||||
"LabelNoCustomMetadataProviders": "Aucun fournisseurs de métadonnées personnalisés",
|
||||
"LabelNoEpisodesSelected": "Aucun épisode sélectionné",
|
||||
"LabelNotFinished": "Non terminé",
|
||||
|
@ -469,6 +492,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Nombres de notifications maximum à mettre en attente",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "La limite de notification est de un évènement par seconde. Les notifications seront ignorées si la file d’attente est à son maximum. Cela empêche un flot trop important.",
|
||||
"LabelNumberOfBooks": "Nombre de livres",
|
||||
"LabelNumberOfChapters": "Nombre de chapitres :",
|
||||
"LabelNumberOfEpisodes": "Nombre d'épisodes",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nom de la demande OpenID qui contient des autorisations avancées pour les actions de l’utilisateur dans l’application, qui s’appliqueront à des rôles autres que celui d’administrateur (<b>s’il est configuré</b>). Si la demande est absente de la réponse, l’accès à ABS sera refusé. Si une seule option est manquante, elle sera considérée comme <code>false</code>. Assurez-vous que la demande du fournisseur d’identité correspond à la structure attendue :",
|
||||
"LabelOpenIDClaims": "Laissez les options suivantes vides pour désactiver l’attribution avancée de groupes et d’autorisations, en attribuant alors automatiquement le groupe « Utilisateur ».",
|
||||
|
@ -530,6 +554,7 @@
|
|||
"LabelReleaseDate": "Date de parution",
|
||||
"LabelRemoveAllMetadataAbs": "Supprimer tous les fichiers metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Supprimer tous les fichiers metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Supprimer l’intro et la fin Audible des chapitres",
|
||||
"LabelRemoveCover": "Supprimer la couverture",
|
||||
"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}.",
|
||||
|
@ -542,6 +567,7 @@
|
|||
"LabelSelectAll": "Tout sélectionner",
|
||||
"LabelSelectAllEpisodes": "Sélectionner tous les épisodes",
|
||||
"LabelSelectEpisodesShowing": "Sélectionner {0} épisode(s) en cours",
|
||||
"LabelSelectUser": "Sélectionner l’utilisateur",
|
||||
"LabelSelectUsers": "Sélectionner les utilisateurs",
|
||||
"LabelSendEbookToDevice": "Envoyer le livre numérique à…",
|
||||
"LabelSequence": "Séquence",
|
||||
|
@ -597,7 +623,7 @@
|
|||
"LabelShareOpen": "Ouvrir le partage",
|
||||
"LabelShareURL": "Partager l’URL",
|
||||
"LabelShowAll": "Tout afficher",
|
||||
"LabelShowSeconds": "Afficher les seondes",
|
||||
"LabelShowSeconds": "Afficher les secondes",
|
||||
"LabelShowSubtitles": "Afficher les sous-titres",
|
||||
"LabelSize": "Taille",
|
||||
"LabelSleepTimer": "Minuterie de mise en veille",
|
||||
|
@ -638,6 +664,7 @@
|
|||
"LabelTheme": "Thème",
|
||||
"LabelThemeDark": "Sombre",
|
||||
"LabelThemeLight": "Clair",
|
||||
"LabelThemeSepia": "Sépia",
|
||||
"LabelTimeBase": "Base de temps",
|
||||
"LabelTimeDurationXHours": "{0} heures",
|
||||
"LabelTimeDurationXMinutes": "{0} minutes",
|
||||
|
@ -705,6 +732,10 @@
|
|||
"LabelYourProgress": "Votre progression",
|
||||
"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>.",
|
||||
"MessageAsinCheck": "Assurez-vous d’utiliser l’ASIN de la bonne région Audible, et non d’Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Les jetons d’API hérités seront supprimés à l’avenir. Utilisez plutôt les <a href=\"/config/api-keys\">clés API</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Redémarrez votre serveur après avoir enregistré pour appliquer les modifications OIDC.",
|
||||
"MessageAuthenticationSecurityMessage": "L’authentification a été améliorée pour plus de sécurité. Tous les utilisateurs doivent se reconnecter.",
|
||||
"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",
|
||||
"MessageBackupsLocationNoEditNote": "Remarque : l’emplacement de sauvegarde est défini via une variable d’environnement et ne peut pas être modifié ici.",
|
||||
|
@ -718,13 +749,16 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Aucun résultat pour le filtre « {0} : {1} »",
|
||||
"MessageBookshelfNoResultsForQuery": "Aucun résultat pour la requête",
|
||||
"MessageBookshelfNoSeries": "Vous n’avez aucune série",
|
||||
"MessageBulkChapterPattern": "Combien de chapitres souhaitez-vous ajouter avec ce motif de numérotation ?",
|
||||
"MessageChapterEndIsAfter": "La fin du chapitre se situe après la fin de votre livre audio",
|
||||
"MessageChapterErrorFirstNotZero": "Le premier capitre doit débuter à 0",
|
||||
"MessageChapterErrorStartGteDuration": "Horodatage invalide car il doit débuter avant la fin du livre",
|
||||
"MessageChapterErrorStartLtPrev": "Horodatage invalide car il doit débuter au moins après le précédent chapitre",
|
||||
"MessageChapterStartIsAfter": "Le premier chapitre est situé au début de votre livre audio",
|
||||
"MessageChaptersNotFound": "Chapitres non trouvés",
|
||||
"MessageCheckingCron": "Vérification du cron…",
|
||||
"MessageConfirmCloseFeed": "Êtes-vous sûr·e de vouloir fermer ce flux ?",
|
||||
"MessageConfirmDeleteApiKey": "Êtes-vous sûr de vouloir supprimer la clé API « {0} » ?",
|
||||
"MessageConfirmDeleteBackup": "Êtes-vous sûr·e de vouloir supprimer la sauvegarde de « {0} » ?",
|
||||
"MessageConfirmDeleteDevice": "Êtes-vous sûr·e de vouloir supprimer la liseuse « {0} » ?",
|
||||
"MessageConfirmDeleteFile": "Cela supprimera le fichier de votre système de fichiers. Êtes-vous sûr ?",
|
||||
|
@ -752,6 +786,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Êtes-vous sûr·e de vouloir supprimer l’auteur « {0} » ?",
|
||||
"MessageConfirmRemoveCollection": "Êtes-vous sûr·e de vouloir supprimer la collection « {0} » ?",
|
||||
"MessageConfirmRemoveEpisode": "Êtes-vous sûr·e de vouloir supprimer l’épisode « {0} » ?",
|
||||
"MessageConfirmRemoveEpisodeNote": "Remarque : cela ne supprime pas le fichier audio, sauf si vous activez « Supprimer définitivement le fichier »",
|
||||
"MessageConfirmRemoveEpisodes": "Êtes-vous sûr·e de vouloir supprimer {0} épisodes ?",
|
||||
"MessageConfirmRemoveListeningSessions": "Êtes-vous sûr·e de vouloir supprimer {0} sessions d’écoute ?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Êtes-vous sûr·e de vouloir supprimer tous les fichiers « metatadata.{0} » des dossiers d’éléments de votre bibliothèque ?",
|
||||
|
@ -777,8 +812,11 @@
|
|||
"MessageFeedURLWillBe": "L’URL du flux sera {0}",
|
||||
"MessageFetching": "Récupération…",
|
||||
"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.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} À l’écoute</strong> sur {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Aucune session en cours sur {0}",
|
||||
"MessageImportantNotice": "Information importante !",
|
||||
"MessageInsertChapterBelow": "Insérer le chapitre ci-dessous",
|
||||
"MessageInvalidAsin": "ASIN invalide",
|
||||
"MessageItemsSelected": "{0} éléments sélectionnés",
|
||||
"MessageItemsUpdated": "{0} éléments mis à jour",
|
||||
"MessageJoinUsOn": "Rejoignez-nous sur",
|
||||
|
@ -812,7 +850,7 @@
|
|||
"MessageNoItems": "Aucun élément",
|
||||
"MessageNoItemsFound": "Aucun élément trouvé",
|
||||
"MessageNoListeningSessions": "Aucune session d’écoute en cours",
|
||||
"MessageNoLogs": "Aucun journaux",
|
||||
"MessageNoLogs": "Aucun journal",
|
||||
"MessageNoMediaProgress": "Aucun média en cours",
|
||||
"MessageNoNotifications": "Aucune notification",
|
||||
"MessageNoPodcastFeed": "Podcast invalide : pas de flux",
|
||||
|
@ -850,6 +888,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Exécuté tous les {0} à {1}",
|
||||
"MessageSearchResultsFor": "Résultats de recherche pour",
|
||||
"MessageSelected": "{0} sélectionnés",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "La séquence de séries ne peut pas contenir d’espaces",
|
||||
"MessageServerCouldNotBeReached": "Serveur inaccessible",
|
||||
"MessageSetChaptersFromTracksDescription": "Positionne un chapitre par fichier audio, avec le titre du fichier comme titre de chapitre",
|
||||
"MessageShareExpirationWillBe": "Expire le <strong>{0}</strong>",
|
||||
|
@ -911,12 +950,15 @@
|
|||
"NotificationOnBackupCompletedDescription": "Déclenché lorsqu’une sauvegarde est terminée",
|
||||
"NotificationOnBackupFailedDescription": "Déclenché lorsqu'une sauvegarde échoue",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Déclenché lorsqu’un épisode de podcast est téléchargé automatiquement",
|
||||
"NotificationOnRSSFeedDisabledDescription": "Déclenché lorsque les téléchargements automatiques d’épisodes sont désactivés en raison d’un trop grand nombre de tentatives infructueuses",
|
||||
"NotificationOnRSSFeedFailedDescription": "Déclenché lorsque la demande de flux RSS échoue pour un téléchargement automatique d’épisode",
|
||||
"NotificationOnTestDescription": "Événement pour tester le système de notification",
|
||||
"PlaceholderBulkChapterInput": "Entrez le titre du chapitre ou utilisez la numérotation (ex. 'Épisode 1', 'Chapitre 10', '1.')",
|
||||
"PlaceholderNewCollection": "Nom de la nouvelle collection",
|
||||
"PlaceholderNewFolderPath": "Nouveau chemin de dossier",
|
||||
"PlaceholderNewPlaylist": "Nouveau nom de liste de lecture",
|
||||
"PlaceholderSearch": "Recherche…",
|
||||
"PlaceholderSearchEpisode": "Recherche d’épisode…",
|
||||
"PlaceholderSearchEpisode": "Rechercher un épisode…",
|
||||
"StatsAuthorsAdded": "auteurs ajoutés",
|
||||
"StatsBooksAdded": "livres ajoutés",
|
||||
"StatsBooksAdditional": "Les ajouts comprennent…",
|
||||
|
@ -965,9 +1007,13 @@
|
|||
"ToastBookmarkCreateFailed": "Échec de la création de signet",
|
||||
"ToastBookmarkCreateSuccess": "Signet ajouté",
|
||||
"ToastBookmarkRemoveSuccess": "Signet supprimé",
|
||||
"ToastBulkChapterInvalidCount": "Veuillez entrer un nombre valide entre 1 et 150",
|
||||
"ToastCachePurgeFailed": "Échec de la purge du cache",
|
||||
"ToastCachePurgeSuccess": "Cache purgé avec succès",
|
||||
"ToastChaptersAllLocked": "Tous les chapitres sont verrouillés. Déverrouillez certains chapitres pour décaler leurs temps.",
|
||||
"ToastChaptersHaveErrors": "Les chapitres contiennent des erreurs",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Durée de décalage non valide. L’heure de début du dernier chapitre pourrait dépasser la durée de ce livre audio.",
|
||||
"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",
|
||||
"ToastChaptersRemoved": "Chapitres supprimés",
|
||||
"ToastChaptersUpdated": "Chapitres mis à jour",
|
||||
|
@ -989,6 +1035,8 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "File d’attente de téléchargement des épisodes effacée",
|
||||
"ToastEpisodeUpdateSuccess": "{0} épisodes mis à jour",
|
||||
"ToastErrorCannotShare": "Impossible de partager nativement sur cet appareil",
|
||||
"ToastFailedToCreate": "Échec de la création",
|
||||
"ToastFailedToDelete": "Échec de la suppression",
|
||||
"ToastFailedToLoadData": "Échec du chargement des données",
|
||||
"ToastFailedToMatch": "Échec de la correspondance",
|
||||
"ToastFailedToShare": "Échec du partage",
|
||||
|
@ -996,6 +1044,7 @@
|
|||
"ToastInvalidImageUrl": "URL de l'image invalide",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Nombre maximum d’épisodes à télécharger non valide",
|
||||
"ToastInvalidUrl": "URL invalide",
|
||||
"ToastInvalidUrls": "Une ou plusieurs URL sont invalides",
|
||||
"ToastItemCoverUpdateSuccess": "Couverture mise à jour",
|
||||
"ToastItemDeletedFailed": "La suppression de l'élément à échouée",
|
||||
"ToastItemDeletedSuccess": "Élément supprimé",
|
||||
|
@ -1020,6 +1069,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Doit avoir au moins un chemin",
|
||||
"ToastNameEmailRequired": "Le nom et le courriel sont requis",
|
||||
"ToastNameRequired": "Le nom est requis",
|
||||
"ToastNewApiKeyUserError": "Vous devez sélectionner un utilisateur",
|
||||
"ToastNewEpisodesFound": "{0} nouveaux épisodes trouvés",
|
||||
"ToastNewUserCreatedFailed": "La création du compte à échouée : « {0} »",
|
||||
"ToastNewUserCreatedSuccess": "Nouveau compte créé",
|
||||
|
@ -1094,5 +1144,12 @@
|
|||
"ToastUserPasswordChangeSuccess": "Mot de passe modifié avec succès",
|
||||
"ToastUserPasswordMismatch": "Les mots de passe ne correspondent pas",
|
||||
"ToastUserPasswordMustChange": "Le nouveau mot de passe ne peut pas être identique à l’ancien",
|
||||
"ToastUserRootRequireName": "Vous devez entrer un nom d’utilisateur root"
|
||||
"ToastUserRootRequireName": "Vous devez entrer un nom d’utilisateur root",
|
||||
"TooltipAddChapters": "Ajouter chapitre(s)",
|
||||
"TooltipAddOneSecond": "Ajouter 1 seconde",
|
||||
"TooltipLockAllChapters": "Verrouiller tous les chapitres",
|
||||
"TooltipLockChapter": "Verrouiller le chapitre (Maj+clic pour plage)",
|
||||
"TooltipSubtractOneSecond": "Soustraire 1 seconde",
|
||||
"TooltipUnlockAllChapters": "Déverrouiller tous les chapitres",
|
||||
"TooltipUnlockChapter": "Déverrouiller le chapitre (Maj+clic pour plage)"
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
"ButtonApply": "લાગુ કરો",
|
||||
"ButtonApplyChapters": "પ્રકરણો લાગુ કરો",
|
||||
"ButtonAuthors": "લેખકો",
|
||||
"ButtonBack": "પાછા",
|
||||
"ButtonBatchEditPopulateFromExisting": "હાલની માહિતીમાંથી ભરો",
|
||||
"ButtonBatchEditPopulateMapDetails": "નકશાની વિગત ભરો",
|
||||
"ButtonBrowseForFolder": "ફોલ્ડર માટે જુઓ",
|
||||
"ButtonCancel": "રદ કરો",
|
||||
"ButtonCancelEncode": "એન્કોડ રદ કરો",
|
||||
|
@ -27,11 +30,14 @@
|
|||
"ButtonEdit": "સંપાદિત કરો",
|
||||
"ButtonEditChapters": "પ્રકરણો સંપાદિત કરો",
|
||||
"ButtonEditPodcast": "પોડકાસ્ટ સંપાદિત કરો",
|
||||
"ButtonEnable": "સક્રિય કરો",
|
||||
"ButtonForceReScan": "બળપૂર્વક ફરીથી સ્કેન કરો",
|
||||
"ButtonFullPath": "સંપૂર્ણ પથ",
|
||||
"ButtonHide": "છુપાવો",
|
||||
"ButtonHome": "ઘર",
|
||||
"ButtonIssues": "સમસ્યાઓ",
|
||||
"ButtonJumpBackward": "પાછળ જાવો",
|
||||
"ButtonJumpForward": "આગળ જાવો",
|
||||
"ButtonLatest": "નવીનતમ",
|
||||
"ButtonLibrary": "પુસ્તકાલય",
|
||||
"ButtonLogout": "લૉગ આઉટ",
|
||||
|
@ -41,19 +47,32 @@
|
|||
"ButtonMatchAllAuthors": "બધા મેળ ખાતા લેખકો શોધો",
|
||||
"ButtonMatchBooks": "મેળ ખાતી પુસ્તકો શોધો",
|
||||
"ButtonNevermind": "કંઈ વાંધો નહીં",
|
||||
"ButtonNext": "આગળ જાઓ",
|
||||
"ButtonNextChapter": "આગળનું અધ્યાય",
|
||||
"ButtonNextItemInQueue": "કતારમાં આવતું આગળનું અધ્યાય",
|
||||
"ButtonOk": "ઓકે",
|
||||
"ButtonOpenFeed": "ફીડ ખોલો",
|
||||
"ButtonOpenManager": "મેનેજર ખોલો",
|
||||
"ButtonPause": "વિરામ",
|
||||
"ButtonPlay": "ચલાવો",
|
||||
"ButtonPlayAll": "બધું ચલાવો",
|
||||
"ButtonPlaying": "ચલાવી રહ્યું છે",
|
||||
"ButtonPlaylists": "પ્લેલિસ્ટ",
|
||||
"ButtonPrevious": "પાછળનું",
|
||||
"ButtonPreviousChapter": "પાછળનું અધ્યાય",
|
||||
"ButtonProbeAudioFile": "ઑડિયો ફાઇલ તપાસો",
|
||||
"ButtonPurgeAllCache": "બધો Cache કાઢી નાખો",
|
||||
"ButtonPurgeItemsCache": "વસ્તુઓનો Cache કાઢી નાખો",
|
||||
"ButtonQueueAddItem": "કતારમાં ઉમેરો",
|
||||
"ButtonQueueRemoveItem": "કતારથી કાઢી નાખો",
|
||||
"ButtonQuickEmbed": "ઝડપથી સમાવેશ કરો",
|
||||
"ButtonQuickEmbedMetadata": "ઝડપથી મેટાડેટા સમાવવો",
|
||||
"ButtonQuickMatch": "ઝડપી મેળ ખવડાવો",
|
||||
"ButtonReScan": "ફરીથી સ્કેન કરો",
|
||||
"ButtonRead": "વાંચો",
|
||||
"ButtonReadLess": "ઓછું વાંચો",
|
||||
"ButtonReadMore": "વધારે વાંચો",
|
||||
"ButtonRefresh": "તાજું કરો",
|
||||
"ButtonRemove": "કાઢી નાખો",
|
||||
"ButtonRemoveAll": "બધું કાઢી નાખો",
|
||||
"ButtonRemoveAllLibraryItems": "બધું પુસ્તકાલય વસ્તુઓ કાઢી નાખો",
|
||||
|
@ -68,16 +87,21 @@
|
|||
"ButtonSaveTracklist": "ટ્રેક યાદી સાચવો",
|
||||
"ButtonScan": "સ્કેન કરો",
|
||||
"ButtonScanLibrary": "પુસ્તકાલય સ્કેન કરો",
|
||||
"ButtonScrollLeft": "ડાબે",
|
||||
"ButtonScrollRight": "જમણે",
|
||||
"ButtonSearch": "શોધો",
|
||||
"ButtonSelectFolderPath": "ફોલ્ડર પથ પસંદ કરો",
|
||||
"ButtonSeries": "સિરીઝ",
|
||||
"ButtonSetChaptersFromTracks": "ટ્રેક્સથી પ્રકરણો સેટ કરો",
|
||||
"ButtonShare": "શેર કરો",
|
||||
"ButtonShiftTimes": "સમય શિફ્ટ કરો",
|
||||
"ButtonShow": "બતાવો",
|
||||
"ButtonStartM4BEncode": "M4B એન્કોડ શરૂ કરો",
|
||||
"ButtonStartMetadataEmbed": "મેટાડેટા એમ્બેડ શરૂ કરો",
|
||||
"ButtonStats": "આંકડા",
|
||||
"ButtonSubmit": "સબમિટ કરો",
|
||||
"ButtonTest": "પરખ કરો",
|
||||
"ButtonUnlinkOpenId": "OpenID દૂર કરો",
|
||||
"ButtonUpload": "અપલોડ કરો",
|
||||
"ButtonUploadBackup": "બેકઅપ અપલોડ કરો",
|
||||
"ButtonUploadCover": "કવર અપલોડ કરો",
|
||||
|
@ -86,11 +110,16 @@
|
|||
"ButtonUserEdit": "વપરાશકર્તા {0} સંપાદિત કરો",
|
||||
"ButtonViewAll": "બધું જુઓ",
|
||||
"ButtonYes": "હા",
|
||||
"ErrorUploadFetchMetadataAPI": "મેટાડેટા મેળવવામાં તકલીફ આવી",
|
||||
"ErrorUploadFetchMetadataNoResults": "મેટાડેટા મેળવી શક્યા નહીં – કૃપા કરીને શીર્ષક અને/અથવા લેખકનું નામ અપડેટ કરવાનો પ્રયત્ન કરો",
|
||||
"ErrorUploadLacksTitle": "શીર્ષક હોવું આવશ્યક છે",
|
||||
"HeaderAccount": "એકાઉન્ટ",
|
||||
"HeaderAddCustomMetadataProvider": "કસ્ટમ મેટાડેટા પ્રોવાઇડર ઉમેરો",
|
||||
"HeaderAdvanced": "અડ્વાન્સડ",
|
||||
"HeaderAppriseNotificationSettings": "Apprise સૂચના સેટિંગ્સ",
|
||||
"HeaderAudioTracks": "ઓડિયો ટ્રેક્સ",
|
||||
"HeaderAudiobookTools": "ઓડિયોબુક ફાઇલ વ્યવસ્થાપન ટૂલ્સ",
|
||||
"HeaderAuthentication": "પ્રમાણીકરણ",
|
||||
"HeaderBackups": "બેકઅપ્સ",
|
||||
"HeaderChangePassword": "પાસવર્ડ બદલો",
|
||||
"HeaderChapters": "પ્રકરણો",
|
||||
|
@ -99,6 +128,7 @@
|
|||
"HeaderCollectionItems": "સંગ્રહ વસ્તુઓ",
|
||||
"HeaderCover": "આવરણ",
|
||||
"HeaderCurrentDownloads": "વર્તમાન ડાઉનલોડ્સ",
|
||||
"HeaderCustomMetadataProviders": "કસ્ટમ મેટાડેટા પ્રોવાઇડર્સ",
|
||||
"HeaderDetails": "વિગતો",
|
||||
"HeaderDownloadQueue": "ડાઉનલોડ કતાર",
|
||||
"HeaderEbookFiles": "ઇબુક ફાઇલો",
|
||||
|
@ -129,6 +159,7 @@
|
|||
"HeaderMetadataToEmbed": "એમ્બેડ કરવા માટે મેટાડેટા",
|
||||
"HeaderNewAccount": "નવું એકાઉન્ટ",
|
||||
"HeaderNewLibrary": "નવી પુસ્તકાલય",
|
||||
"HeaderNotificationCreate": "સૂચના બનાવો",
|
||||
"HeaderNotifications": "સૂચનાઓ",
|
||||
"HeaderOpenRSSFeed": "RSS ફીડ ખોલો",
|
||||
"HeaderOtherFiles": "અન્ય ફાઇલો",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "הוסף",
|
||||
"ButtonAddApiKey": "הוסף מפתח ממשק תכנות (API)",
|
||||
"ButtonAddChapters": "הוסף פרקים",
|
||||
"ButtonAddDevice": "הוסף התקן",
|
||||
"ButtonAddLibrary": "הוסף ספרייה",
|
||||
|
@ -10,6 +11,8 @@
|
|||
"ButtonApplyChapters": "החל פרקים",
|
||||
"ButtonAuthors": "סופרים",
|
||||
"ButtonBack": "חזור",
|
||||
"ButtonBatchEditPopulateFromExisting": "מלא משדות קיימים",
|
||||
"ButtonBatchEditPopulateMapDetails": "מלא פרטי מפה",
|
||||
"ButtonBrowseForFolder": "עיין בתיקייה",
|
||||
"ButtonCancel": "ביטול",
|
||||
"ButtonCancelEncode": "בטל קידוד",
|
||||
|
@ -18,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "בחר תיקייה",
|
||||
"ButtonChooseFiles": "בחר קבצים",
|
||||
"ButtonClearFilter": "נקה סינון",
|
||||
"ButtonClose": "סגור",
|
||||
"ButtonCloseFeed": "סגור ערוץ",
|
||||
"ButtonCloseSession": "סגור סשן פתוח",
|
||||
"ButtonCollections": "אוספים",
|
||||
|
@ -29,7 +33,9 @@
|
|||
"ButtonEdit": "ערוך",
|
||||
"ButtonEditChapters": "ערוך פרקים",
|
||||
"ButtonEditPodcast": "ערוך פודקאסט",
|
||||
"ButtonEnable": "הפעל",
|
||||
"ButtonEnable": "אפשר",
|
||||
"ButtonFireAndFail": "שלח בכישלון",
|
||||
"ButtonFireOnTest": "שלח באירוע בדיקה",
|
||||
"ButtonForceReScan": "סרוק מחדש בכוח",
|
||||
"ButtonFullPath": "נתיב מלא",
|
||||
"ButtonHide": "הסתר",
|
||||
|
@ -37,7 +43,7 @@
|
|||
"ButtonIssues": "תקלות",
|
||||
"ButtonJumpBackward": "דלג אחורה",
|
||||
"ButtonJumpForward": "דלג קדימה",
|
||||
"ButtonLatest": "חדש ביותר",
|
||||
"ButtonLatest": "אחרון",
|
||||
"ButtonLibrary": "ספרייה",
|
||||
"ButtonLogout": "התנתק",
|
||||
"ButtonLookup": "חפש",
|
||||
|
@ -70,7 +76,7 @@
|
|||
"ButtonReScan": "סרוק מחדש",
|
||||
"ButtonRead": "קרא",
|
||||
"ButtonReadLess": "קרא פחות",
|
||||
"ButtonReadMore": "קרא יותר",
|
||||
"ButtonReadMore": "קרא עוד",
|
||||
"ButtonRefresh": "רענן",
|
||||
"ButtonRemove": "הסר",
|
||||
"ButtonRemoveAll": "הסר הכל",
|
||||
|
@ -86,7 +92,9 @@
|
|||
"ButtonSaveTracklist": "שמור רשימת רצועות",
|
||||
"ButtonScan": "סרוק",
|
||||
"ButtonScanLibrary": "סרוק ספרייה",
|
||||
"ButtonSearch": "חפש",
|
||||
"ButtonScrollLeft": "גלול שמאלה",
|
||||
"ButtonScrollRight": "גלול ימינה",
|
||||
"ButtonSearch": "חיפוש",
|
||||
"ButtonSelectFolderPath": "בחר נתיב לתיקייה",
|
||||
"ButtonSeries": "סדרה",
|
||||
"ButtonSetChaptersFromTracks": "קבע פרקים לפי הרצועות",
|
||||
|
@ -96,7 +104,7 @@
|
|||
"ButtonStartM4BEncode": "התחל קידוד M4B",
|
||||
"ButtonStartMetadataEmbed": "התחל הטמעת מטא-נתונים",
|
||||
"ButtonStats": "סטטיסטיקות",
|
||||
"ButtonSubmit": "שלח",
|
||||
"ButtonSubmit": "שליחה",
|
||||
"ButtonTest": "בדיקה",
|
||||
"ButtonUnlinkOpenId": "נתק OpenID",
|
||||
"ButtonUpload": "העלה",
|
||||
|
@ -122,26 +130,26 @@
|
|||
"HeaderChapters": "פרקים",
|
||||
"HeaderChooseAFolder": "בחר תיקייה",
|
||||
"HeaderCollection": "אוסף",
|
||||
"HeaderCollectionItems": "פריטי אוסף",
|
||||
"HeaderCollectionItems": "פרטי אוסף",
|
||||
"HeaderCover": "כריכה",
|
||||
"HeaderCurrentDownloads": "הורדות נוכחיות",
|
||||
"HeaderCustomMessageOnLogin": "הודעה מותאמת אישית בהתחברות",
|
||||
"HeaderCustomMetadataProviders": "ספקי מטא-נתונים מותאמים אישית",
|
||||
"HeaderDetails": "פרטים",
|
||||
"HeaderDownloadQueue": "תור הורדה",
|
||||
"HeaderEbookFiles": "קבצי ספר אלקטרוני",
|
||||
"HeaderEbookFiles": "קבצי Ebook",
|
||||
"HeaderEmail": "אימייל",
|
||||
"HeaderEmailSettings": "הגדרות אימייל",
|
||||
"HeaderEpisodes": "פרקים",
|
||||
"HeaderEreaderDevices": "התקני קריאה דיגיטליים",
|
||||
"HeaderEreaderSettings": "הגדרות התקני קריאה דיגיטליים",
|
||||
"HeaderEreaderSettings": "הגדרות קורא אלקטרוני",
|
||||
"HeaderFiles": "קבצים",
|
||||
"HeaderFindChapters": "מצא פרקים",
|
||||
"HeaderIgnoredFiles": "קבצים שנתעלמו",
|
||||
"HeaderItemFiles": "קבצי פריט",
|
||||
"HeaderItemMetadataUtils": "כלי מטא-נתונים",
|
||||
"HeaderLastListeningSession": "הפעלת האזנה אחרונה",
|
||||
"HeaderLatestEpisodes": "הפרקים העדכניים ביותר",
|
||||
"HeaderLatestEpisodes": "פרקים אחרונים",
|
||||
"HeaderLibraries": "ספריות",
|
||||
"HeaderLibraryFiles": "קבצי ספרייה",
|
||||
"HeaderLibraryStats": "סטטיסטיקות ספרייה",
|
||||
|
@ -171,8 +179,9 @@
|
|||
"HeaderPlaylist": "רשימת השמעה",
|
||||
"HeaderPlaylistItems": "פריטי רשימת השמעה",
|
||||
"HeaderPodcastsToAdd": "פודקאסטים להוספה",
|
||||
"HeaderPresets": "קביעות מוגדרות מראש",
|
||||
"HeaderPreviewCover": "תצוגה מקדימה של כריכה",
|
||||
"HeaderRSSFeedGeneral": "פרטי ערוץ RSS",
|
||||
"HeaderRSSFeedGeneral": "פרטי RSS",
|
||||
"HeaderRSSFeedIsOpen": "ערוץ RSS פתוח",
|
||||
"HeaderRSSFeeds": "ערוצי RSS",
|
||||
"HeaderRemoveEpisode": "הסר פרק",
|
||||
|
@ -188,14 +197,15 @@
|
|||
"HeaderSettingsExperimental": "תכונות ניסיוניות",
|
||||
"HeaderSettingsGeneral": "כללי",
|
||||
"HeaderSettingsScanner": "סורק",
|
||||
"HeaderSettingsWebClient": "מערך",
|
||||
"HeaderSleepTimer": "טיימר שינה",
|
||||
"HeaderStatsLargestItems": "הפריטים הגדולים ביותר",
|
||||
"HeaderStatsLongestItems": "הפריטים הארוכים ביותר (בשעות)",
|
||||
"HeaderStatsMinutesListeningChart": "דקות האזנה (בימים האחרונים)",
|
||||
"HeaderStatsRecentSessions": "הפעלות אחרונות",
|
||||
"HeaderStatsMinutesListeningChart": "דקות האזנה (7 ימים אחרונים)",
|
||||
"HeaderStatsRecentSessions": "האזנות אחרונות",
|
||||
"HeaderStatsTop10Authors": "10 היוצרים המובילים",
|
||||
"HeaderStatsTop5Genres": "הז'אנרים המובילים 5",
|
||||
"HeaderTableOfContents": "תוכן העניינים",
|
||||
"HeaderTableOfContents": "תוכן עניינים",
|
||||
"HeaderTools": "כלים",
|
||||
"HeaderUpdateAccount": "עדכן חשבון",
|
||||
"HeaderUpdateAuthor": "עדכן יוצר",
|
||||
|
@ -212,15 +222,17 @@
|
|||
"LabelAccountTypeAdmin": "מנהל",
|
||||
"LabelAccountTypeGuest": "אורח",
|
||||
"LabelAccountTypeUser": "משתמש",
|
||||
"LabelActivities": "פעילויות",
|
||||
"LabelActivity": "פעילות",
|
||||
"LabelAddToCollection": "הוסף לאוסף",
|
||||
"LabelAddToCollectionBatch": "הוסף {0} ספרים לאוסף",
|
||||
"LabelAddToPlaylist": "הוסף לרשימת השמעה",
|
||||
"LabelAddToPlaylistBatch": "הוסף {0} פריטים לרשימת השמעה",
|
||||
"LabelAddedAt": "נוסף בתאריך",
|
||||
"LabelAddedAt": "נוסף ב-",
|
||||
"LabelAddedDate": "נוסף ב-{0}",
|
||||
"LabelAdminUsersOnly": "רק מנהלים",
|
||||
"LabelAll": "הכל",
|
||||
"LabelAllEpisodesDownloaded": "כל הפרקים הורדו",
|
||||
"LabelAllUsers": "כל המשתמשים",
|
||||
"LabelAllUsersExcludingGuests": "כל המשתמשים, ללא אורחים",
|
||||
"LabelAllUsersIncludingGuests": "כל המשתמשים כולל אורחים",
|
||||
|
@ -230,10 +242,10 @@
|
|||
"LabelAudioBitrate": "קצב סיביות (לדוגמא 128k)",
|
||||
"LabelAudioChannels": "ערוצי קול (1 או 2)",
|
||||
"LabelAudioCodec": "קידוד קול",
|
||||
"LabelAuthor": "יוצר",
|
||||
"LabelAuthorFirstLast": "יוצר (שם פרטי שם משפחה)",
|
||||
"LabelAuthorLastFirst": "יוצר (שם משפחה, שם פרטי)",
|
||||
"LabelAuthors": "יוצרים",
|
||||
"LabelAuthor": "סופר",
|
||||
"LabelAuthorFirstLast": "סופר (שם, משפחה)",
|
||||
"LabelAuthorLastFirst": "סופר (משפחה, שם)",
|
||||
"LabelAuthors": "סופרים",
|
||||
"LabelAutoDownloadEpisodes": "הורד פרקים באופן אוטומטי",
|
||||
"LabelAutoFetchMetadata": "חפש והורד מטא-נתונים באופן אוטומטי",
|
||||
"LabelAutoFetchMetadataHelp": "מחפש ומוריד מטא-נתונים לשדות כותרת, יוצר וסדרה כדי לשפר את תהליך ההעלאה. ייתכן שיהיה צורך להתאים מטא-נתונים נוסף לאחר ההעלאה.",
|
||||
|
@ -242,36 +254,48 @@
|
|||
"LabelAutoRegister": "הרשמה אוטומטית",
|
||||
"LabelAutoRegisterDescription": "יצירת משתמשים חדשים אוטומטית לאחר התחברות",
|
||||
"LabelBackToUser": "חזרה למשתמש",
|
||||
"LabelBackupAudioFiles": "גיבוי קבצי שמע",
|
||||
"LabelBackupLocation": "מיקום גיבוי",
|
||||
"LabelBackupsEnableAutomaticBackups": "הפעל גיבויים אוטומטיים",
|
||||
"LabelBackupsEnableAutomaticBackups": "גיבויים אוטומטיים",
|
||||
"LabelBackupsEnableAutomaticBackupsHelp": "גיבויים שמורים ב /metadata/backups",
|
||||
"LabelBackupsMaxBackupSize": "גודל הגיבוי המרבי (בג'יגה-בייט)",
|
||||
"LabelBackupsMaxBackupSize": "גודל הגיבוי המרבי (בג'יגה-בייט) (0 - ללא הגבלה)",
|
||||
"LabelBackupsMaxBackupSizeHelp": "כהגנה על עצמך מפני תצורה שגויה, הגיבויים ייכשלו אם הם יעברו את הגודל שהוגדר.",
|
||||
"LabelBackupsNumberToKeep": "מספר הגיבויים לשמירה",
|
||||
"LabelBackupsNumberToKeepHelp": "רק גיבוי אחד יוסר בכל פעם, לכן אם יש לך כבר יותר מגיבוי אחד יש להסיר אותם באופן ידני.",
|
||||
"LabelBitrate": "קצב סיביות",
|
||||
"LabelBonus": "בונוס",
|
||||
"LabelBooks": "ספרים",
|
||||
"LabelButtonText": "טקסט לחצן",
|
||||
"LabelByAuthor": "על ידי {0}",
|
||||
"LabelChangePassword": "שינוי סיסמה",
|
||||
"LabelChannels": "ערוצים",
|
||||
"LabelChapterCount": "{0} פרקים",
|
||||
"LabelChapterTitle": "כותרת הפרק",
|
||||
"LabelChapters": "פרקים",
|
||||
"LabelChaptersFound": "פרקים שנמצאו",
|
||||
"LabelClickForMoreInfo": "לחץ למידע נוסף",
|
||||
"LabelClickToUseCurrentValue": "לחץ לשימוש בערך הנוכחי",
|
||||
"LabelClosePlayer": "סגור נגן",
|
||||
"LabelCollapseSeries": "צמצום סדרה",
|
||||
"LabelCodec": "Coded",
|
||||
"LabelCollapseSeries": "הסתר סדרה",
|
||||
"LabelCollapseSubSeries": "הסתר תת סדרה",
|
||||
"LabelCollection": "אוסף",
|
||||
"LabelCollections": "אוספים",
|
||||
"LabelComplete": "מלא",
|
||||
"LabelComplete": "הושלם",
|
||||
"LabelConfirmPassword": "אישור סיסמה",
|
||||
"LabelContinueListening": "המשך האזנה",
|
||||
"LabelContinueReading": "המשך קריאה",
|
||||
"LabelContinueSeries": "המשך סדרה",
|
||||
"LabelCover": "כריכה",
|
||||
"LabelCoverImageURL": "כתובת התמונה ברשת",
|
||||
"LabelCoverProvider": "ספק כריכה",
|
||||
"LabelCreatedAt": "נוצר בתאריך",
|
||||
"LabelCronExpression": "ביטוי cron",
|
||||
"LabelCurrent": "נוכחי",
|
||||
"LabelCurrently": "כעת:",
|
||||
"LabelCustomCronExpression": "ביטוי cron מותאם אישית:",
|
||||
"LabelDatetime": "Datetime",
|
||||
"LabelDays": "ימים",
|
||||
"LabelDeleteFromFileSystemCheckbox": "מחיקה מהמערכת הקבצים (הסר סימון למחיקה רק ממסד הנתונים)",
|
||||
"LabelDescription": "תיאור",
|
||||
"LabelDeselectAll": "הסר בחירת כל הפריטים",
|
||||
|
@ -282,51 +306,83 @@
|
|||
"LabelDiscFromFilename": "דיסק משם הקובץ",
|
||||
"LabelDiscFromMetadata": "דיסק מהמטא-נתונים",
|
||||
"LabelDiscover": "גלה",
|
||||
"LabelDownload": "הורד",
|
||||
"LabelDownload": "הורדה",
|
||||
"LabelDownloadNEpisodes": "הורד {0} פרקים",
|
||||
"LabelDownloadable": "ניתן להורדה",
|
||||
"LabelDuration": "משך",
|
||||
"LabelDurationComparisonExactMatch": "(התאמה מדוייקת)",
|
||||
"LabelDurationComparisonLonger": "({0} ארוך יותר)",
|
||||
"LabelDurationComparisonShorter": "({0} קצר יותר)",
|
||||
"LabelDurationFound": "משך נמצא:",
|
||||
"LabelEbook": "ספר אלקטרוני",
|
||||
"LabelEbooks": "ספרים אלקטרוניים",
|
||||
"LabelEdit": "עריכה",
|
||||
"LabelEmail": "דואר אלקטרוני",
|
||||
"LabelEmailSettingsFromAddress": "מאת",
|
||||
"LabelEmailSettingsRejectUnauthorized": "דחה תעודות לא מאושרות",
|
||||
"LabelEmailSettingsRejectUnauthorizedHelp": "השבתת אימות תעודת SSL עלולה לחשוף את החיבור שלך לסיכוני אבטחה, כגון התקפות \"אדם באמצע\". השבת אפשרות זו רק אם אתה מבין את ההשלכות ובוטח בשרת הדואר שאליו אתה מתחבר.",
|
||||
"LabelEmailSettingsSecure": "מאובטח",
|
||||
"LabelEmailSettingsSecureHelp": "אם מופעל, החיבור ישתמש ב-TLS בעת ההתחברות לשרת. אם לא, אז TLS יהיה בשימוש אם השרת תומך בהרחבת STARTTLS. ברוב המקרים מומלץ להפעיל את הגדרה זו אם אתה מתחבר לפורט 465. לפורט 587 או 25, השאר כבוי. (from nodemailer.com/smtp/#authentication)",
|
||||
"LabelEmailSettingsTestAddress": "כתובת לבדיקה",
|
||||
"LabelEmbeddedCover": "כריכה מוטמעת",
|
||||
"LabelEnable": "הפעל",
|
||||
"LabelEnd": "סיום",
|
||||
"LabelEnable": "אפשר",
|
||||
"LabelEncodingBackupLocation": "גיבוי של קבצי אודיו מקוריים יישמר ב:",
|
||||
"LabelEncodingChaptersNotEmbedded": "פרקים אינם מוטבעים בספרי אודיו מרובי רצועות.",
|
||||
"LabelEncodingClearItemCache": "הקפד לנקות מטמון פריטים מעת לעת.",
|
||||
"LabelEncodingFinishedM4B": "קובץ M4B סופי יישמר בתיקייה ה-audiobook ב:",
|
||||
"LabelEncodingInfoEmbedded": "מטה דאטה יוטמע ברצועות השמע בתוך תיקיית ה-audiobook.",
|
||||
"LabelEncodingStartedNavigation": "לאחר שהמשימה תתחיל אפשר לנווט לדף אחר.",
|
||||
"LabelEncodingTimeWarning": "קידוד יכול להימשך עד 30 דקות.",
|
||||
"LabelEncodingWarningAdvancedSettings": "אזהרה: אל תעדכן את ההגדרות האלה אלא אם כן אתה מכיר את אפשרויות קידוד ffmpeg.",
|
||||
"LabelEncodingWatcherDisabled": "אם ה-watcher כבוי, יש לסרוק את הספר מחדש לאחר מכן.",
|
||||
"LabelEnd": "סוף",
|
||||
"LabelEndOfChapter": "סוף הפרק",
|
||||
"LabelEpisode": "פרק",
|
||||
"LabelEpisodeNotLinkedToRssFeed": "פרק לא מקושר לערוץ RSS",
|
||||
"LabelEpisodeNumber": "פרק #{0}",
|
||||
"LabelEpisodeTitle": "כותרת הפרק",
|
||||
"LabelEpisodeType": "סוג הפרק",
|
||||
"LabelEpisodeUrlFromRssFeed": "קישור פרק מערוץ RSS",
|
||||
"LabelEpisodes": "פרקים",
|
||||
"LabelEpisodic": "ארעי",
|
||||
"LabelExample": "דוגמה",
|
||||
"LabelExpandSeries": "הרחב סדרה",
|
||||
"LabelExpandSubSeries": "הרחב תת סדרה",
|
||||
"LabelExplicit": "בוטה",
|
||||
"LabelExplicitChecked": "בוטה (מסומן)",
|
||||
"LabelExplicitUnchecked": "לא בוטה (לא מסומן)",
|
||||
"LabelExportOPML": "ייצוא OPML",
|
||||
"LabelFeedURL": "כתובת ערוץ",
|
||||
"LabelFetchingMetadata": "מושך מטא-נתונים",
|
||||
"LabelFile": "קובץ",
|
||||
"LabelFileBirthtime": "זמן יצירת הקובץ",
|
||||
"LabelFileModified": "הקובץ שונה",
|
||||
"LabelFilename": "שם הקובץ",
|
||||
"LabelFileBornDate": "נוצר {0}",
|
||||
"LabelFileModified": "קובץ נערך",
|
||||
"LabelFileModifiedDate": "שונה {0}",
|
||||
"LabelFilename": "שם קובץ",
|
||||
"LabelFilterByUser": "סינון לפי משתמש",
|
||||
"LabelFindEpisodes": "מצא פרקים",
|
||||
"LabelFinished": "הושלם",
|
||||
"LabelFolder": "תיקייה",
|
||||
"LabelFolders": "תיקיות",
|
||||
"LabelFontBold": "מודגש",
|
||||
"LabelFontBoldness": "עובי פונט",
|
||||
"LabelFontFamily": "משפחת הפונטים",
|
||||
"LabelFontItalic": "נטוי",
|
||||
"LabelFontScale": "קנה מידה של הפונט",
|
||||
"LabelFontScale": "גודל פונט",
|
||||
"LabelFontStrikethrough": "קו חוצה",
|
||||
"LabelFormat": "תבנית",
|
||||
"LabelGenre": "ז'אנר",
|
||||
"LabelGenres": "ז'אנרים",
|
||||
"LabelFull": "מלא",
|
||||
"LabelGenre": "סגנון",
|
||||
"LabelGenres": "סגנונות",
|
||||
"LabelHardDeleteFile": "מחיקה חזקה של הקובץ",
|
||||
"LabelHasEbook": "ספר אלקטרוני קיים",
|
||||
"LabelHasSupplementaryEbook": "קיים ספר אלקטרוני נלווה",
|
||||
"LabelHasEbook": "קיים ספר אלקטרוני",
|
||||
"LabelHasSupplementaryEbook": "קיים ספר אלקטרוני משלים",
|
||||
"LabelHideSubtitles": "הסתר תת כותרות",
|
||||
"LabelHighestPriority": "העדיפות הגבוהה ביותר",
|
||||
"LabelHost": "מארח",
|
||||
"LabelHour": "שעה",
|
||||
"LabelHours": "שעות",
|
||||
"LabelIcon": "סמל",
|
||||
"LabelImageURLFromTheWeb": "כתובת התמונה מהרשת",
|
||||
"LabelInProgress": "בתהליך",
|
||||
|
@ -341,25 +397,30 @@
|
|||
"LabelIntervalEvery6Hours": "כל 6 שעות",
|
||||
"LabelIntervalEveryDay": "כל יום",
|
||||
"LabelIntervalEveryHour": "כל שעה",
|
||||
"LabelIntervalEveryMinute": "כל דקה",
|
||||
"LabelInvert": "הפוך",
|
||||
"LabelItem": "פריט",
|
||||
"LabelJumpBackwardAmount": "כמות הרצה לאחור",
|
||||
"LabelJumpForwardAmount": "כמות הרצה קדימה",
|
||||
"LabelLanguage": "שפה",
|
||||
"LabelLanguageDefaultServer": "שפת ברירת המחדל של השרת",
|
||||
"LabelLanguages": "שפות",
|
||||
"LabelLastBookAdded": "הספר האחרון שנוסף",
|
||||
"LabelLastBookUpdated": "הספר האחרון שעודכן",
|
||||
"LabelLastSeen": "נראה לאחרונה",
|
||||
"LabelLastTime": "הזמן האחרון",
|
||||
"LabelLastUpdate": "עדכון אחרון",
|
||||
"LabelLayout": "פריסה",
|
||||
"LabelLayoutSinglePage": "דף בודד",
|
||||
"LabelLayout": "Layout",
|
||||
"LabelLayoutSinglePage": "עמוד יחיד",
|
||||
"LabelLayoutSplitPage": "פיצול הדף",
|
||||
"LabelLess": "פחות",
|
||||
"LabelLibrariesAccessibleToUser": "ספריות נגישות למשתמש",
|
||||
"LabelLibrary": "ספרייה",
|
||||
"LabelLibraryFilterSublistEmpty": "לא {0}",
|
||||
"LabelLibraryItem": "פריט ספרייה",
|
||||
"LabelLibraryName": "שם הספרייה",
|
||||
"LabelLimit": "מגבלה",
|
||||
"LabelLineSpacing": "ריווח שורות",
|
||||
"LabelLineSpacing": "מרווח שורה",
|
||||
"LabelListenAgain": "האזן שוב",
|
||||
"LabelLogLevelDebug": "דיבוג",
|
||||
"LabelLogLevelInfo": "מידע",
|
||||
|
@ -368,6 +429,10 @@
|
|||
"LabelLowestPriority": "העדיפות הנמוכה ביותר",
|
||||
"LabelMatchExistingUsersBy": "התאם משתמשים קיימים לפי",
|
||||
"LabelMatchExistingUsersByDescription": "משמש לחיבור משתמשים קיימים. לאחר החיבור, המשתמשים יותאמו לפי זיהוי ייחודי מספק ה-SSO שלך",
|
||||
"LabelMaxEpisodesToDownload": "מספר פרקים מקסימלי להורדה. 0 - ללא הגבלה.",
|
||||
"LabelMaxEpisodesToDownloadPerCheck": "מספר פרקים חדשים מקסימלי להורדה בכל בדיקה",
|
||||
"LabelMaxEpisodesToKeep": "מספר פרקים מקסימלי לשמור",
|
||||
"LabelMaxEpisodesToKeepHelp": "ערך של 0 קובע ללא מגבלה. לאחר הורדה אוטומטית של פרק חדש יימחק את הפרק הישן ביותר אם יש לך יותר מ-X פרקים. פעולה זו תמחק רק פרק אחד לכל הורדה חדשה.",
|
||||
"LabelMediaPlayer": "נגן מדיה",
|
||||
"LabelMediaType": "סוג מדיה",
|
||||
"LabelMetaTag": "תג מטא",
|
||||
|
@ -375,6 +440,7 @@
|
|||
"LabelMetadataOrderOfPrecedenceDescription": "מקורות המטא-נתונים עם עדיפות גבוהה יחליפו מקורות עם עדיפות נמוכה יותר",
|
||||
"LabelMetadataProvider": "ספק מטא-נתונים",
|
||||
"LabelMinute": "דקה",
|
||||
"LabelMinutes": "דקות",
|
||||
"LabelMissing": "חסר",
|
||||
"LabelMissingEbook": "אין ספר אלקטרוני",
|
||||
"LabelMissingSupplementaryEbook": "אין ספר אלקטרוני נלווה",
|
||||
|
@ -387,10 +453,11 @@
|
|||
"LabelNarrators": "מספרים",
|
||||
"LabelNew": "חדש",
|
||||
"LabelNewPassword": "סיסמה חדשה",
|
||||
"LabelNewestAuthors": "הסופרים החדשים ביותר",
|
||||
"LabelNewestAuthors": "הסופרים האחרונים",
|
||||
"LabelNewestEpisodes": "הפרקים החדשים ביותר",
|
||||
"LabelNextBackupDate": "תאריך הגיבוי הבא",
|
||||
"LabelNextScheduledRun": "הרצה מתוזמנת הבאה",
|
||||
"LabelNoCustomMetadataProviders": "אין ספקי מטא-נתונים מותאמים אישית",
|
||||
"LabelNoEpisodesSelected": "לא נבחרו פרקים",
|
||||
"LabelNotFinished": "לא הושלם",
|
||||
"LabelNotStarted": "לא התחיל",
|
||||
|
@ -405,7 +472,9 @@
|
|||
"LabelNotificationsMaxQueueSize": "גודל התור המרבי לאירועי התראה",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "האירועים מוגבלים לשליחה אחת לשנייה. האירועים יתעלמו אם התור מלא. הגדרה זו נועדה למנוע ספאם התראות.",
|
||||
"LabelNumberOfBooks": "מספר הספרים",
|
||||
"LabelNumberOfEpisodes": "מספר הפרקים",
|
||||
"LabelNumberOfEpisodes": "# פרקים",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "שם OpenID claim המכילה הרשאות מתקדמות לפעולות משתמש בתוך האפליקציה, אשר יחולו על תפקידים שאינם מנהלי מערכת (<b>אם הוגדרה</b>). אם התביעה חסרה בתגובה, הגישה ל-ABS תידחה. אם אפשרות אחת חסרה, היא תטופל כ-<code>false</code> יש לוודא שטענת ספק הזהויות תואמת את המבנה הצפוי:",
|
||||
"LabelOpenIDClaims": "השאר את האפשרויות הבאות ריקות כדי להשבית הקצאת קבוצות והרשאות מתקדמת, ולאחר מכן להקצות אוטומטית את קבוצת 'משתמש'.",
|
||||
"LabelOpenRSSFeed": "פתח ערוץ RSS",
|
||||
"LabelOverwrite": "לשכפל",
|
||||
"LabelPassword": "סיסמה",
|
||||
|
@ -433,13 +502,15 @@
|
|||
"LabelProvider": "ספק",
|
||||
"LabelPubDate": "תאריך פרסום",
|
||||
"LabelPublishYear": "שנת הפרסום",
|
||||
"LabelPublishedDate": "פורסם {0}",
|
||||
"LabelPublisher": "מוציא לאור",
|
||||
"LabelRSSFeedCustomOwnerEmail": "אימייל בעלים מותאם אישית",
|
||||
"LabelRSSFeedCustomOwnerName": "שם בעלים מותאם אישית",
|
||||
"LabelRSSFeedOpen": "פתח ערוץ RSS",
|
||||
"LabelRSSFeedOpen": "ערוץ RSS פתוח",
|
||||
"LabelRSSFeedPreventIndexing": "מנע רישום",
|
||||
"LabelRSSFeedSlug": "Slug של ערוץ ה-RSS",
|
||||
"LabelRSSFeedURL": "כתובת ערוץ ה-RSS",
|
||||
"LabelRandomly": "באופן אקראי",
|
||||
"LabelRead": "קריאה",
|
||||
"LabelReadAgain": "קרא שוב",
|
||||
"LabelReadEbookWithoutProgress": "קרא/י ספר אלקטרוני ללא שמירת התקדמות",
|
||||
|
@ -465,7 +536,7 @@
|
|||
"LabelSeriesProgress": "התקדמות בסדרה",
|
||||
"LabelServerYearReview": "השנה בסקירה של השרת ({0})",
|
||||
"LabelSetEbookAsPrimary": "קבע כראשי",
|
||||
"LabelSetEbookAsSupplementary": "קבע כספר אלקטרוני נלווה",
|
||||
"LabelSetEbookAsSupplementary": "קבע כמשלים",
|
||||
"LabelSettingsAudiobooksOnly": "רק ספרי קול",
|
||||
"LabelSettingsAudiobooksOnlyHelp": "הפעלת ההגדרה הזו תתעלם מקבצי ספרים אלקטרוניים אלא אם כן הם נמצאים בתיקיית ספרי קול, שבמקרה זה יקבעו כספרים אלקטרוניים נלווים",
|
||||
"LabelSettingsBookshelfViewHelp": "עיצוב סקאומורפי עם מדפי עץ",
|
||||
|
@ -500,7 +571,7 @@
|
|||
"LabelShowAll": "הצג הכל",
|
||||
"LabelSize": "גודל",
|
||||
"LabelSleepTimer": "טיימר שינה",
|
||||
"LabelStart": "התחלה",
|
||||
"LabelStart": "התחל",
|
||||
"LabelStartTime": "זמן התחלה",
|
||||
"LabelStarted": "התחיל",
|
||||
"LabelStartedAt": "התחיל ב",
|
||||
|
@ -576,8 +647,8 @@
|
|||
"LabelViewQueue": "הצג תור נגן",
|
||||
"LabelVolume": "עוצמת קול",
|
||||
"LabelWeekdaysToRun": "ימי השבוע להרצה",
|
||||
"LabelYearReviewHide": "הסתר שנת סקירה",
|
||||
"LabelYearReviewShow": "הצג שנת סקירה",
|
||||
"LabelYearReviewHide": "הסתר סקירת שנה",
|
||||
"LabelYearReviewShow": "הצג סקירת שנה",
|
||||
"LabelYourAudiobookDuration": "משך הספר הקולי שלך",
|
||||
"LabelYourBookmarks": "הסימניות שלך",
|
||||
"LabelYourPlaylists": "הפלייליסטים שלך",
|
||||
|
@ -628,8 +699,8 @@
|
|||
"MessageDownloadingEpisode": "מוריד פרק",
|
||||
"MessageDragFilesIntoTrackOrder": "גרור קבצים לסדר ההשמעה נכון",
|
||||
"MessageEmbedFinished": "ההטמעה הושלמה!",
|
||||
"MessageEpisodesQueuedForDownload": "{0} פרקים בתור להורדה",
|
||||
"MessageFeedURLWillBe": "כתובת URL של העדכון תהיה {0}",
|
||||
"MessageEpisodesQueuedForDownload": "{0} פרק/ים בתור להורדה",
|
||||
"MessageFeedURLWillBe": "כתובת ה- URL של הערוץ תהיה {0}",
|
||||
"MessageFetching": "מושך...",
|
||||
"MessageForceReScanDescription": "תבוצע סריקה מחדש כמו סריקה חדש מאפס, תגי ID3 של קבצי קול, קבצי OPF, וקבצי טקסט ייסרקו כחדשים.",
|
||||
"MessageImportantNotice": "הודעה חשובה!",
|
||||
|
@ -644,7 +715,7 @@
|
|||
"MessageMapChapterTitles": "מפה שמות פרקים לפרקי הספר השמורים שלך ללא שינוי תגי זמן",
|
||||
"MessageMarkAllEpisodesFinished": "סמן את כל הפרקים כהסתיימו",
|
||||
"MessageMarkAllEpisodesNotFinished": "סמן את כל הפרקים כלא הסתיימו",
|
||||
"MessageMarkAsFinished": "סמן כהסתיים",
|
||||
"MessageMarkAsFinished": "סמן כהושלם",
|
||||
"MessageMarkAsNotFinished": "סמן כלא הסתיים",
|
||||
"MessageMatchBooksDescription": "ינסה להתאים ספרים בספריית הספרים שלך עם ספר מספק החיפוש הנבחר וימלא פרטים ריקים ותמונות כריכה. לא יחליף פרטים קיימים.",
|
||||
"MessageNoAudioTracks": "אין רצועות שמע",
|
||||
|
@ -674,7 +745,7 @@
|
|||
"MessageNoSeries": "אין סדרות",
|
||||
"MessageNoTags": "אין תגיות",
|
||||
"MessageNoTasksRunning": "אין משימות פעילות",
|
||||
"MessageNoUpdatesWereNecessary": "לא היה צורך בעדכונים",
|
||||
"MessageNoUpdatesWereNecessary": "לא נדרש עדכון",
|
||||
"MessageNoUserPlaylists": "אין לך רשימות השמעה",
|
||||
"MessageNotYetImplemented": "עדיין לא מיושם",
|
||||
"MessageOr": "או",
|
||||
|
@ -682,6 +753,7 @@
|
|||
"MessagePlayChapter": "הקשב לתחילת הפרק",
|
||||
"MessagePlaylistCreateFromCollection": "צור רשימת השמעה מאוסף",
|
||||
"MessagePodcastHasNoRSSFeedForMatching": "לפודקאסט אין כתובת URL של ערוץ RSS להתאמה",
|
||||
"MessagePodcastSearchField": "הזן מונח חיפוש או כתובת URL של ערוץ RSS",
|
||||
"MessageQuickMatchDescription": "ממלא פרטים ריקים וכריכות עם התוצאה הראשונה מ '{0}'. לא ימחק פרטים אלא אם הגדרת השרת 'העדף מטה-נתונים מותאמים' מופעלת.",
|
||||
"MessageRemoveChapter": "הסר פרק",
|
||||
"MessageRemoveEpisodes": "הסר {0} פרקים",
|
||||
|
@ -708,7 +780,7 @@
|
|||
"NoteChangeRootPassword": "המשתמש root הוא המשתמש היחיד שיכולה להיות לו סיסמה ריקה",
|
||||
"NoteChapterEditorTimes": "הערה: זמן ההתחלה של הפרק הראשון חייב להישאר 0:00 וזמן ההתחלה של הפרק האחרון לא יכול לחרוג מהזמן של ספר השמע.",
|
||||
"NoteFolderPicker": "הערה: תיקיות שכבר מופו לא יוצגו",
|
||||
"NoteRSSFeedPodcastAppsHttps": "אזהרה: רוב יישומי הפודקאסט דורשים שכתובת ה-URL ערוץ ה-RSS תשתמש ב-HTTPS",
|
||||
"NoteRSSFeedPodcastAppsHttps": "אזהרה: רוב אפליקציות הפודקאסטים ידרשו שכתובת האתר של ערוץ ה-RSS תשתמש ב-HTTPS",
|
||||
"NoteRSSFeedPodcastAppsPubDate": "אזהרה: פרק אחד או יותר לא מכילים תאריך פרסום. חלק מיישומי הפודקאסט דורשים זאת.",
|
||||
"NoteUploaderFoldersWithMediaFiles": "תיקיות עם קבצי מדיה יעובדו כפריטי ספריה נפרדים.",
|
||||
"NoteUploaderOnlyAudioFiles": "אם מועלים רק קבצי שמע, כל קובץ שמע יעובד כספר שמע נפרד.",
|
||||
|
@ -741,7 +813,7 @@
|
|||
"ToastCollectionUpdateSuccess": "האוסף עודכן בהצלחה",
|
||||
"ToastItemCoverUpdateSuccess": "כריכת הפריט עודכנה בהצלחה",
|
||||
"ToastItemDetailsUpdateSuccess": "פרטי הפריט עודכנו בהצלחה",
|
||||
"ToastItemMarkedAsFinishedFailed": "סימון כפריט כהושלם נכשל",
|
||||
"ToastItemMarkedAsFinishedFailed": "סימון כפריט שהושלם נכשל",
|
||||
"ToastItemMarkedAsFinishedSuccess": "הפריט סומן כהושלם בהצלחה",
|
||||
"ToastItemMarkedAsNotFinishedFailed": "סימון כפריט שלא הושלם נכשל",
|
||||
"ToastItemMarkedAsNotFinishedSuccess": "הפריט סומן כלא הושלם בהצלחה",
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
{
|
||||
"ButtonAdd": "जोड़ें",
|
||||
"ButtonAddApiKey": "एपीआई कुंजी जोड़ें",
|
||||
"ButtonAddChapters": "अध्याय जोड़ें",
|
||||
"ButtonAddDevice": "उपकरण जोड़ें",
|
||||
"ButtonAddLibrary": "संग्रह जोड़ें",
|
||||
"ButtonAddPodcasts": "पॉडकास्ट जोड़ें",
|
||||
"ButtonAddUser": "उपयोगकर्ता जोड़ें",
|
||||
"ButtonAddYourFirstLibrary": "अपनी पहली पुस्तकालय जोड़ें",
|
||||
"ButtonApply": "लागू करें",
|
||||
"ButtonApplyChapters": "अध्यायों में परिवर्तन लागू करें",
|
||||
"ButtonAuthors": "लेखक",
|
||||
"ButtonBack": "पीछे",
|
||||
"ButtonBatchEditPopulateFromExisting": "मौजूदा से आबाद करें",
|
||||
"ButtonBatchEditPopulateMapDetails": "मानचित्र विवरण भरें",
|
||||
"ButtonBrowseForFolder": "फ़ोल्डर खोजें",
|
||||
"ButtonCancel": "रद्द करें",
|
||||
"ButtonCancelEncode": "एनकोड रद्द करें",
|
||||
|
@ -15,7 +21,9 @@
|
|||
"ButtonChooseAFolder": "एक फ़ोल्डर चुनें",
|
||||
"ButtonChooseFiles": "फ़ाइलें चुनें",
|
||||
"ButtonClearFilter": "लागू फ़िल्टर साफ़ करें",
|
||||
"ButtonClose": "बंद करें",
|
||||
"ButtonCloseFeed": "फ़ीड बंद करें",
|
||||
"ButtonCloseSession": "वर्तमान सत्र बंद करें",
|
||||
"ButtonCollections": "संग्रह",
|
||||
"ButtonConfigureScanner": "स्कैनर सेटिंग्स बदलें",
|
||||
"ButtonCreate": "बनाएं",
|
||||
|
@ -25,6 +33,7 @@
|
|||
"ButtonEdit": "संपादित करें",
|
||||
"ButtonEditChapters": "अध्याय संपादित करें",
|
||||
"ButtonEditPodcast": "पॉडकास्ट संपादित करें",
|
||||
"ButtonEnable": "सक्षम करें",
|
||||
"ButtonForceReScan": "बलपूर्वक पुन: स्कैन करें",
|
||||
"ButtonFullPath": "पूर्ण पथ",
|
||||
"ButtonHide": "छुपाएं",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Dodaj",
|
||||
"ButtonAddApiKey": "Dodaj API ključ",
|
||||
"ButtonAddChapters": "Dodaj poglavlja",
|
||||
"ButtonAddDevice": "Dodaj uređaj",
|
||||
"ButtonAddLibrary": "Dodaj knjižnicu",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Odaberi mapu",
|
||||
"ButtonChooseFiles": "Odaberi datoteke",
|
||||
"ButtonClearFilter": "Poništi filter",
|
||||
"ButtonClose": "Zatvori",
|
||||
"ButtonCloseFeed": "Zatvori izvor",
|
||||
"ButtonCloseSession": "Zatvori otvorenu sesiju",
|
||||
"ButtonCollections": "Zbirke",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Korisnički račun",
|
||||
"HeaderAddCustomMetadataProvider": "Dodaj prilagođenog pružatelja meta-podataka",
|
||||
"HeaderAdvanced": "Napredno",
|
||||
"HeaderApiKeys": "API ključevi",
|
||||
"HeaderAppriseNotificationSettings": "Postavke obavijesti Apprise",
|
||||
"HeaderAudioTracks": "Zvučni zapisi",
|
||||
"HeaderAudiobookTools": "Alati za upravljanje datotekama zvučnih knjiga",
|
||||
"HeaderAuthentication": "Provjera autentičnosti",
|
||||
"HeaderBackups": "Sigurnosne kopije",
|
||||
"HeaderBulkChapterModal": "Dodaj više poglavlja",
|
||||
"HeaderChangePassword": "Promjena zaporke",
|
||||
"HeaderChapters": "Poglavlja",
|
||||
"HeaderChooseAFolder": "Odaberi mapu",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Redoslijed prihvaćanja meta-podataka",
|
||||
"HeaderMetadataToEmbed": "Meta-podatci za ugradnju",
|
||||
"HeaderNewAccount": "Novi korisnički račun",
|
||||
"HeaderNewApiKey": "Novi API ključ",
|
||||
"HeaderNewLibrary": "Nova knjižnica",
|
||||
"HeaderNotificationCreate": "Izradi obavijest",
|
||||
"HeaderNotificationUpdate": "Ažuriraj obavijest",
|
||||
|
@ -177,6 +182,7 @@
|
|||
"HeaderPlaylist": "Popis za izvođenje",
|
||||
"HeaderPlaylistItems": "Stavke popisa za izvođenje",
|
||||
"HeaderPodcastsToAdd": "Podcasti za dodavanje",
|
||||
"HeaderPresets": "Predlošci postavki",
|
||||
"HeaderPreviewCover": "Pretpregled naslovnice",
|
||||
"HeaderRSSFeedGeneral": "RSS pojedinosti",
|
||||
"HeaderRSSFeedIsOpen": "RSS izvor je otvoren",
|
||||
|
@ -194,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Eksperimentalne značajke",
|
||||
"HeaderSettingsGeneral": "Općenito",
|
||||
"HeaderSettingsScanner": "Skener",
|
||||
"HeaderSettingsSecurity": "Sigurnost",
|
||||
"HeaderSettingsWebClient": "Web klijent",
|
||||
"HeaderSleepTimer": "Timer za spavanje",
|
||||
"HeaderStatsLargestItems": "Najveće stavke",
|
||||
|
@ -205,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Sadržaj",
|
||||
"HeaderTools": "Alati",
|
||||
"HeaderUpdateAccount": "Ažuriraj korisnički račun",
|
||||
"HeaderUpdateApiKey": "Ažuriraj API ključ",
|
||||
"HeaderUpdateAuthor": "Ažuriraj autora",
|
||||
"HeaderUpdateDetails": "Ažuriraj pojedinosti",
|
||||
"HeaderUpdateLibrary": "Ažuriraj knjižnicu",
|
||||
|
@ -234,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Svi korisnici osim gostiju",
|
||||
"LabelAllUsersIncludingGuests": "Svi korisnici uključujući i goste",
|
||||
"LabelAlreadyInYourLibrary": "Već u vašoj knjižnici",
|
||||
"LabelApiKeyCreated": "API ključ \"{0}\" uspješno izrađen.",
|
||||
"LabelApiKeyCreatedDescription": "Ne zaboravite odmah kopirati API ključ jer ga više nećete moći vidjeti.",
|
||||
"LabelApiKeyUser": "Izvršavaj u ime korisnika",
|
||||
"LabelApiKeyUserDescription": "Ovaj API ključ imat će iste dozvole kao i korisnik u čije ime djeluje. U zapisnicima će biti zabilježeno da je korisnik slao zahtjeve.",
|
||||
"LabelApiToken": "API Token",
|
||||
"LabelAppend": "Pridodaj",
|
||||
"LabelAudioBitrate": "Kvaliteta zvučnog zapisa (npr. 128k)",
|
||||
|
@ -283,6 +295,7 @@
|
|||
"LabelContinueListening": "Nastavi slušati",
|
||||
"LabelContinueReading": "Nastavi čitati",
|
||||
"LabelContinueSeries": "Nastavi serijal",
|
||||
"LabelCorsAllowed": "Dozvoljena CORS ishodišta",
|
||||
"LabelCover": "Naslovnica",
|
||||
"LabelCoverImageURL": "URL naslovnice",
|
||||
"LabelCoverProvider": "Pružatelj naslovnica",
|
||||
|
@ -296,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Izbriši datoteke (uklonite kvačicu ako stavku želite izbrisati samo iz baze podataka)",
|
||||
"LabelDescription": "Opis",
|
||||
"LabelDeselectAll": "Odznači sve",
|
||||
"LabelDetectedPattern": "Prepoznat obrazac:",
|
||||
"LabelDevice": "Uređaj",
|
||||
"LabelDeviceInfo": "O uređaju",
|
||||
"LabelDeviceIsAvailableTo": "Uređaj je dostupan...",
|
||||
|
@ -345,7 +359,11 @@
|
|||
"LabelExample": "Primjer",
|
||||
"LabelExpandSeries": "Serijal prikaži prošireno",
|
||||
"LabelExpandSubSeries": "Podserijal prikaži prošireno",
|
||||
"LabelExplicit": "Eksplicitni sadržaj",
|
||||
"LabelExpired": "Istekao",
|
||||
"LabelExpiresAt": "Istječe",
|
||||
"LabelExpiresInSeconds": "Istječe za (sekundi)",
|
||||
"LabelExpiresNever": "Nikada",
|
||||
"LabelExplicit": "Eksplicitno",
|
||||
"LabelExplicitChecked": "Eksplicitni sadržaj (označeno)",
|
||||
"LabelExplicitUnchecked": "Nije eksplicitni sadržaj (odznačeno)",
|
||||
"LabelExportOPML": "Izvoz OPML-a",
|
||||
|
@ -404,6 +422,7 @@
|
|||
"LabelLanguages": "Jezici",
|
||||
"LabelLastBookAdded": "Zadnja dodana knjiga",
|
||||
"LabelLastBookUpdated": "Zadnja ažurirana knjiga",
|
||||
"LabelLastProgressDate": "Zadnji napredak: {0}",
|
||||
"LabelLastSeen": "Zadnji puta viđen",
|
||||
"LabelLastTime": "Zadnje doslušano vrijeme",
|
||||
"LabelLastUpdate": "Zadnje ažuriranje",
|
||||
|
@ -416,6 +435,7 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Br {0}",
|
||||
"LabelLibraryItem": "Stavka knjižnice",
|
||||
"LabelLibraryName": "Ime knjižnice",
|
||||
"LabelLibrarySortByProgress": "Napredak ažuriran",
|
||||
"LabelLimit": "Ograničenje",
|
||||
"LabelLineSpacing": "Razmak između redaka",
|
||||
"LabelListenAgain": "Ponovno poslušaj",
|
||||
|
@ -424,6 +444,7 @@
|
|||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Traži nove nastavke nakon ovog datuma",
|
||||
"LabelLowestPriority": "Najniži prioritet",
|
||||
"LabelMatchConfidence": "Pouzdanost",
|
||||
"LabelMatchExistingUsersBy": "Prepoznaj postojeće korisnike pomoću",
|
||||
"LabelMatchExistingUsersByDescription": "Rabi se za povezivanje postojećih korisnika. Nakon što se spoje, korisnike se prepoznaje temeljem jedinstvene oznake vašeg pružatelja SSO usluga",
|
||||
"LabelMaxEpisodesToDownload": "Najveći broj nastavaka za preuzimanje. 0 za neograničeno.",
|
||||
|
@ -453,7 +474,9 @@
|
|||
"LabelNewestAuthors": "Najnoviji autori",
|
||||
"LabelNewestEpisodes": "Najnoviji nastavci",
|
||||
"LabelNextBackupDate": "Sljedeća izrada sigurnosne kopije",
|
||||
"LabelNextChapters": "Sljedeća poglavlja bit će:",
|
||||
"LabelNextScheduledRun": "Sljedeće zakazano izvođenje",
|
||||
"LabelNoApiKeys": "Nema API ključeva",
|
||||
"LabelNoCustomMetadataProviders": "Nema prilagođenih pružatelja meta-podataka",
|
||||
"LabelNoEpisodesSelected": "Nema odabranih nastavaka",
|
||||
"LabelNotFinished": "Nije dovršeno",
|
||||
|
@ -469,6 +492,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Najveći broj događaja za obavijest u redu čekanja",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Događaji se mogu okinuti samo jednom u sekundi. Događaji će se zanemariti ako je red čekanja pun. Ovo sprečava prekomjerno slanje obavijesti.",
|
||||
"LabelNumberOfBooks": "Broj knjiga",
|
||||
"LabelNumberOfChapters": "Broj poglavljâ:",
|
||||
"LabelNumberOfEpisodes": "broj nastavaka",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Naziv OpenID zahtjeva koji sadrži napredna dopuštenja za korisničke radnje u aplikaciji koje će se primijeniti na ne-administratorske uloge (<b>ako su konfigurirane</b>). Ako zahtjev nedostaje u odgovoru, pristup ABS-u neće se odobriti. Ako i jedna opcija nedostaje, smatrat će se da je <code>false</code>. Pripazite da zahtjev pružatelja identiteta uvijek odgovara očekivanoj strukturi:",
|
||||
"LabelOpenIDClaims": "Sljedeće opcije ostavite praznima ako želite onemogućiti napredno dodjeljivanje grupa i dozvola, odnosno ako želite automatski dodijeliti grupu 'korisnik'.",
|
||||
|
@ -530,6 +554,7 @@
|
|||
"LabelReleaseDate": "Datum izlaska",
|
||||
"LabelRemoveAllMetadataAbs": "Ukloni sve datoteke metadata.abs",
|
||||
"LabelRemoveAllMetadataJson": "Ukloni sve datoteke metadata.json",
|
||||
"LabelRemoveAudibleBranding": "Ukloni Audibleove najave i odjave iz poglavlja",
|
||||
"LabelRemoveCover": "Ukloni naslovnicu",
|
||||
"LabelRemoveMetadataFile": "Ukloni datoteke s meta-podatcima iz mapa knjižničkih stavki",
|
||||
"LabelRemoveMetadataFileHelp": "Uklanjanje svih datoteka metadata.json i metadata.abs u vaših {0} mapa.",
|
||||
|
@ -542,6 +567,7 @@
|
|||
"LabelSelectAll": "Označi sve",
|
||||
"LabelSelectAllEpisodes": "Označi sve nastavke",
|
||||
"LabelSelectEpisodesShowing": "Prikazujem {0} odabranih nastavaka",
|
||||
"LabelSelectUser": "Odaberite korisnika",
|
||||
"LabelSelectUsers": "Označi korisnike",
|
||||
"LabelSendEbookToDevice": "Pošalji e-knjigu …",
|
||||
"LabelSequence": "Slijed",
|
||||
|
@ -638,6 +664,7 @@
|
|||
"LabelTheme": "Tema",
|
||||
"LabelThemeDark": "Tamna",
|
||||
"LabelThemeLight": "Svijetla",
|
||||
"LabelThemeSepia": "Sepija",
|
||||
"LabelTimeBase": "Baza vremena",
|
||||
"LabelTimeDurationXHours": "{0} sati",
|
||||
"LabelTimeDurationXMinutes": "{0} minuta",
|
||||
|
@ -706,6 +733,9 @@
|
|||
"MessageAddToPlayerQueue": "Dodaj u redoslijed izvođenja",
|
||||
"MessageAppriseDescription": "Da biste se koristili ovom značajkom, treba vam instanca <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API-ja</a> ili API koji može rukovati istom vrstom zahtjeva.<br />The Adresa Apprise API-ja treba biti puna URL putanja za slanje obavijesti, npr. ako vam se API instanca poslužuje na adresi <code>http://192.168.1.1:8337</code> trebate upisati <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Upišite ASIN iz odgovarajuće Audibleove regije, ne s Amazonov.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "Starije API tokene ćemo ukloniti. Umjesto njih, koristite se <a href=\"/config/api-keys\">API ključevima</a> .",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Ponovno pokrenite poslužitelj da biste primijenili OIDC promjene.",
|
||||
"MessageAuthenticationSecurityMessage": "Provjera autentičnosti poboljšana je radi sigurnosti. Svi se korisnici moraju ponovno prijaviti.",
|
||||
"MessageBackupsDescription": "Sigurnosne kopije sadrže korisnike, korisnikov napredak medija, pojedinosti knjižničke građe, postavke poslužitelja i slike koje se spremaju u <code>/metadata/items</code> & <code>/metadata/authors</code>. Sigurnosne kopije ne sadrže niti jednu datoteku iz mapa knjižnice.",
|
||||
"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.",
|
||||
|
@ -719,6 +749,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Nema rezultata za filter \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Vaš upit nema rezultata",
|
||||
"MessageBookshelfNoSeries": "Nemate niti jedan serijal",
|
||||
"MessageBulkChapterPattern": "Koliko poglavlja želite dodati s ovim obrascem numeracije?",
|
||||
"MessageChapterEndIsAfter": "Kraj poglavlja je nakon kraja zvučne knjige",
|
||||
"MessageChapterErrorFirstNotZero": "Prvo poglavlje mora započeti u 0",
|
||||
"MessageChapterErrorStartGteDuration": "Netočno vrijeme početka, mora biti manje od trajanja zvučne knjige",
|
||||
|
@ -727,6 +758,7 @@
|
|||
"MessageChaptersNotFound": "Poglavlja nisu pronađena",
|
||||
"MessageCheckingCron": "Provjeravam cron...",
|
||||
"MessageConfirmCloseFeed": "Sigurno želite zatvoriti ovaj izvor?",
|
||||
"MessageConfirmDeleteApiKey": "Sigurno želite izbrisati API ključ \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Sigurno želite izbrisati sigurnosnu kopiju za {0}?",
|
||||
"MessageConfirmDeleteDevice": "Sigurno želite izbrisati e-čitač \"{0}\"?",
|
||||
"MessageConfirmDeleteFile": "Ovo će izbrisati datoteke s datotečnog sustava. Jeste li sigurni?",
|
||||
|
@ -754,6 +786,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Sigurno želite ukloniti autora \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Sigurno želite obrisati kolekciju \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Sigurno želite ukloniti nastavak \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodeNote": "Napomena: Ova funkcija neće izbrisati zvučnu datoteku ukoliko ne uključite opciju \"Izbriši datoteku zauvijek\"",
|
||||
"MessageConfirmRemoveEpisodes": "Sigurno želite ukloniti {0} nastavaka?",
|
||||
"MessageConfirmRemoveListeningSessions": "Sigurno želite ukloniti {0} sesija slušanja?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Sigurno želite ukloniti sve datoteke metadata.{0} u mapama vaših knjižničkih stavki?",
|
||||
|
@ -779,6 +812,8 @@
|
|||
"MessageFeedURLWillBe": "URL izvora bit će {0}",
|
||||
"MessageFetching": "Dohvaćam...",
|
||||
"MessageForceReScanDescription": "će ponovno skenirati sve datoteke kao nove datoteke. ID3 tagovi zvučnih datoteka, OPF datoteke i tekstualne datoteke skenirat će se kao da su nove.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} sluša</strong> na {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Nema sesija slušanja na {0}",
|
||||
"MessageImportantNotice": "Važna obavijest!",
|
||||
"MessageInsertChapterBelow": "Unesi poglavlje ispod",
|
||||
"MessageInvalidAsin": "Nevažeći ASIN",
|
||||
|
@ -853,6 +888,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Pokreni svaki {0} u {1}",
|
||||
"MessageSearchResultsFor": "Rezultati pretrage za",
|
||||
"MessageSelected": "{0} odabrano",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Slijed serijala ne može sadržavati praznine",
|
||||
"MessageServerCouldNotBeReached": "Nije moguće pristupiti poslužitelju",
|
||||
"MessageSetChaptersFromTracksDescription": "Postavi poglavlja koristeći se zvučnom datotekom kao poglavljem i nazivom datoteke kao naslovom poglavlja",
|
||||
"MessageShareExpirationWillBe": "Vrijeme isteka će biti <strong>{0}</strong>",
|
||||
|
@ -914,7 +950,10 @@
|
|||
"NotificationOnBackupCompletedDescription": "Pokreće se po završetku sigurnosnog kopiranja",
|
||||
"NotificationOnBackupFailedDescription": "Pokreće se kada sigurnosno kopiranje ne uspije",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Pokreće se kada se nastavak podcasta automatski preuzme",
|
||||
"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",
|
||||
"PlaceholderBulkChapterInput": "Upišite naslov poglavlja ili ga numerirajte (npr. '1. nastavak', 'Poglavlje 10', '1.')",
|
||||
"PlaceholderNewCollection": "Ime nove zbirke",
|
||||
"PlaceholderNewFolderPath": "Nova putanja mape",
|
||||
"PlaceholderNewPlaylist": "Naziv novog popisa za izvođenje",
|
||||
|
@ -968,9 +1007,15 @@
|
|||
"ToastBookmarkCreateFailed": "Izrada knjižne oznake nije uspjela",
|
||||
"ToastBookmarkCreateSuccess": "Knjižna oznaka dodana",
|
||||
"ToastBookmarkRemoveSuccess": "Knjižna oznaka uklonjena",
|
||||
"ToastBulkChapterInvalidCount": "Upišite broj od 1 i 150",
|
||||
"ToastCachePurgeFailed": "Čišćenje predmemorije nije uspjelo",
|
||||
"ToastCachePurgeSuccess": "Predmemorija uspješno očišćena",
|
||||
"ToastChapterLocked": "Poglavlje je zaključano.",
|
||||
"ToastChapterStartTimeAdjusted": "Vrijeme početka poglavlja prilagođeno za {0} sekundi",
|
||||
"ToastChaptersAllLocked": "Sva su poglavlja zaključana. Otključajte neka poglavlja za pomicanje njihovog vremena.",
|
||||
"ToastChaptersHaveErrors": "Poglavlja imaju pogreške",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Neispravna vrijednost pomaka. Početak zadnjeg poglavlja bio bi nakon duljine trajanja ove zvučne knjige.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Neispravna vrijednost pomaka. Trajanje prvog poglavlja bilo bi nula ili negativno i drugo poglavlje bi ga prepisalo. Povećajte vrijeme početka drugog poglavlja.",
|
||||
"ToastChaptersMustHaveTitles": "Poglavlja moraju imati naslove",
|
||||
"ToastChaptersRemoved": "Poglavlja uklonjena",
|
||||
"ToastChaptersUpdated": "Poglavlja su ažurirana",
|
||||
|
@ -992,6 +1037,8 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Redoslijed preuzimanja nastavaka očišćen",
|
||||
"ToastEpisodeUpdateSuccess": "{0} nastavak/a ažurirano",
|
||||
"ToastErrorCannotShare": "Dijeljenje na ovaj uređaj nije moguće",
|
||||
"ToastFailedToCreate": "Izrada nije uspjela",
|
||||
"ToastFailedToDelete": "Brisanje nije uspjelo",
|
||||
"ToastFailedToLoadData": "Učitavanje podataka nije uspjelo",
|
||||
"ToastFailedToMatch": "Nije prepoznato",
|
||||
"ToastFailedToShare": "Dijeljenje nije uspjelo",
|
||||
|
@ -999,6 +1046,7 @@
|
|||
"ToastInvalidImageUrl": "Neispravan URL slike",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Neispravan unos maksimalnog broja nastavaka",
|
||||
"ToastInvalidUrl": "Neispravan URL",
|
||||
"ToastInvalidUrls": "Jedan ili više URL-ova nisu ispravni",
|
||||
"ToastItemCoverUpdateSuccess": "Naslovnica stavke ažurirana",
|
||||
"ToastItemDeletedFailed": "Brisanje stavke nije uspjelo",
|
||||
"ToastItemDeletedSuccess": "Stavka je izbrisana",
|
||||
|
@ -1023,6 +1071,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Mora postojati barem jedna putanja",
|
||||
"ToastNameEmailRequired": "Ime i adresa e-pošte su obavezni",
|
||||
"ToastNameRequired": "Ime je obavezno",
|
||||
"ToastNewApiKeyUserError": "Morate odabrati korisnika",
|
||||
"ToastNewEpisodesFound": "pronađeno {0} novih nastavaka",
|
||||
"ToastNewUserCreatedFailed": "Račun \"{0}\" nije uspješno izrađen",
|
||||
"ToastNewUserCreatedSuccess": "Novi račun izrađen",
|
||||
|
@ -1097,5 +1146,13 @@
|
|||
"ToastUserPasswordChangeSuccess": "Zaporka je uspješno promijenjena",
|
||||
"ToastUserPasswordMismatch": "Zaporke se ne podudaraju",
|
||||
"ToastUserPasswordMustChange": "Nova zaporka ne smije biti jednaka staroj",
|
||||
"ToastUserRootRequireName": "Obavezan je unos korisničkog imena root korisnika"
|
||||
"ToastUserRootRequireName": "Obavezan je unos korisničkog imena root korisnika",
|
||||
"TooltipAddChapters": "Dodavanje poglavlja",
|
||||
"TooltipAddOneSecond": "Dodaj 1 sekundu",
|
||||
"TooltipAdjustChapterStart": "Kliknite za uređivanje početnog vremena",
|
||||
"TooltipLockAllChapters": "Zaključaj sva poglavlja",
|
||||
"TooltipLockChapter": "Zaključaj poglavlje (Shift + klik za raspon)",
|
||||
"TooltipSubtractOneSecond": "Oduzmi 1 sekundu",
|
||||
"TooltipUnlockAllChapters": "Otključaj sva poglavlja",
|
||||
"TooltipUnlockChapter": "Otključaj poglavlje (Shift+klik za raspon)"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"ButtonAdd": "Hozzáadás",
|
||||
"ButtonAddApiKey": "API kulcs hozzáadása",
|
||||
"ButtonAddChapters": "Fejezetek hozzáadása",
|
||||
"ButtonAddDevice": "Eszköz hozzáadása",
|
||||
"ButtonAddLibrary": "Könyvtár hozzáadása",
|
||||
|
@ -11,7 +12,7 @@
|
|||
"ButtonAuthors": "Szerzők",
|
||||
"ButtonBack": "Vissza",
|
||||
"ButtonBatchEditPopulateFromExisting": "Létezőből feltöltés",
|
||||
"ButtonBatchEditPopulateMapDetails": "",
|
||||
"ButtonBatchEditPopulateMapDetails": "A térkép részleteinek feltöltése",
|
||||
"ButtonBrowseForFolder": "Mappa keresése",
|
||||
"ButtonCancel": "Mégse",
|
||||
"ButtonCancelEncode": "Kódolás megszakítása",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"ButtonChooseAFolder": "Válassz egy mappát",
|
||||
"ButtonChooseFiles": "Fájlok kiválasztása",
|
||||
"ButtonClearFilter": "Szűrő törlése",
|
||||
"ButtonClose": "Bezár",
|
||||
"ButtonCloseFeed": "Hírcsatorna bezárása",
|
||||
"ButtonCloseSession": "Nyitott munkamenet bezárása",
|
||||
"ButtonCollections": "Gyűjtemények",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Fiók",
|
||||
"HeaderAddCustomMetadataProvider": "Egyedi metaadat szolgáltató hozzáadása",
|
||||
"HeaderAdvanced": "Haladó",
|
||||
"HeaderApiKeys": "API kulcsok",
|
||||
"HeaderAppriseNotificationSettings": "Apprise értesítési beállítások",
|
||||
"HeaderAudioTracks": "Audiósávok",
|
||||
"HeaderAudiobookTools": "Hangoskönyv fájlkezelő eszközök",
|
||||
"HeaderAuthentication": "Hitelesítés",
|
||||
"HeaderBackups": "Biztonsági másolatok",
|
||||
"HeaderBulkChapterModal": "Több fejezet hozzáadása",
|
||||
"HeaderChangePassword": "Jelszó megváltoztatása",
|
||||
"HeaderChapters": "Fejezetek",
|
||||
"HeaderChooseAFolder": "Válasszon egy mappát",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Metaadatok előnyben részesítési sorrendje",
|
||||
"HeaderMetadataToEmbed": "Beágyazandó metaadatok",
|
||||
"HeaderNewAccount": "Új fiók",
|
||||
"HeaderNewApiKey": "Új API kulcs",
|
||||
"HeaderNewLibrary": "Új könyvtár",
|
||||
"HeaderNotificationCreate": "Értesítés készítése",
|
||||
"HeaderNotificationUpdate": "Értesítés frissítése",
|
||||
|
@ -177,6 +182,7 @@
|
|||
"HeaderPlaylist": "Lejátszási lista",
|
||||
"HeaderPlaylistItems": "Lejátszási lista elemek",
|
||||
"HeaderPodcastsToAdd": "Hozzáadandó podcastok",
|
||||
"HeaderPresets": "Alapbeállítások",
|
||||
"HeaderPreviewCover": "Borító előnézete",
|
||||
"HeaderRSSFeedGeneral": "RSS részletek",
|
||||
"HeaderRSSFeedIsOpen": "RSS hírcsatorna nyitva van",
|
||||
|
@ -194,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Kísérleti funkciók",
|
||||
"HeaderSettingsGeneral": "Általános",
|
||||
"HeaderSettingsScanner": "Szkenner",
|
||||
"HeaderSettingsSecurity": "Biztonság",
|
||||
"HeaderSettingsWebClient": "Webkliens",
|
||||
"HeaderSleepTimer": "Alvásidőzítő",
|
||||
"HeaderStatsLargestItems": "Legnagyobb elemek",
|
||||
|
@ -205,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Tartalomjegyzék",
|
||||
"HeaderTools": "Eszközök",
|
||||
"HeaderUpdateAccount": "Fiók frissítése",
|
||||
"HeaderUpdateApiKey": "API kulcs frissítése",
|
||||
"HeaderUpdateAuthor": "Szerző frissítése",
|
||||
"HeaderUpdateDetails": "Részletek frissítése",
|
||||
"HeaderUpdateLibrary": "Könyvtár frissítése",
|
||||
|
@ -219,6 +227,7 @@
|
|||
"LabelAccountTypeAdmin": "Adminisztrátor",
|
||||
"LabelAccountTypeGuest": "Vendég",
|
||||
"LabelAccountTypeUser": "Felhasználó",
|
||||
"LabelActivities": "Tevékenységek",
|
||||
"LabelActivity": "Tevékenység",
|
||||
"LabelAddToCollection": "Hozzáadás a gyűjteményhez",
|
||||
"LabelAddToCollectionBatch": "{0} könyv hozzáadása a gyűjteményhez",
|
||||
|
@ -228,10 +237,15 @@
|
|||
"LabelAddedDate": "{0} Hozzáadva",
|
||||
"LabelAdminUsersOnly": "Csak admin felhasználók",
|
||||
"LabelAll": "Összes",
|
||||
"LabelAllEpisodesDownloaded": "Minden epizód letöltve",
|
||||
"LabelAllUsers": "Minden felhasználó",
|
||||
"LabelAllUsersExcludingGuests": "Minden felhasználó, vendégek kivételével",
|
||||
"LabelAllUsersIncludingGuests": "Minden felhasználó, beleértve a vendégeket is",
|
||||
"LabelAlreadyInYourLibrary": "Már a könyvtárában van",
|
||||
"LabelApiKeyCreated": "\"{0}\" API kulcs sikeresen létrehozva.",
|
||||
"LabelApiKeyCreatedDescription": "Feltétlenül másolja le az API kulcsot, mert később már nem fogja látni.",
|
||||
"LabelApiKeyUser": "Felhasználó nevében eljárva",
|
||||
"LabelApiKeyUserDescription": "Ez az API-kulcs ugyanazokkal a jogosultságokkal rendelkezik, mint az a felhasználó, akinek a nevében működik. A naplófájlokban ez úgy jelenik meg, mintha a felhasználó maga küldte volna a kérést.",
|
||||
"LabelApiToken": "API Token",
|
||||
"LabelAppend": "Hozzáfűzés",
|
||||
"LabelAudioBitrate": "Audió bitráta (pl.128k)",
|
||||
|
@ -251,7 +265,7 @@
|
|||
"LabelBackToUser": "Vissza a felhasználóhoz",
|
||||
"LabelBackupAudioFiles": "Audiófájlok biztonsági mentése",
|
||||
"LabelBackupLocation": "Biztonsági másolat helye",
|
||||
"LabelBackupsEnableAutomaticBackups": "Automatikus biztonsági másolatok engedélyezése",
|
||||
"LabelBackupsEnableAutomaticBackups": "Automatikus biztonsági másolatok",
|
||||
"LabelBackupsEnableAutomaticBackupsHelp": "Biztonsági másolatok mentése a /metadata/backups mappába",
|
||||
"LabelBackupsMaxBackupSize": "Maximális biztonsági másolat méret (GB-ban) (0-tól végtelenig)",
|
||||
"LabelBackupsMaxBackupSizeHelp": "A rossz konfiguráció elleni védelem érdekében a biztonsági másolatok meghiúsulnak, ha meghaladják a beállított méretet.",
|
||||
|
@ -261,7 +275,7 @@
|
|||
"LabelBonus": "Bónusz",
|
||||
"LabelBooks": "Könyvek",
|
||||
"LabelButtonText": "Gomb szövege",
|
||||
"LabelByAuthor": "{} által",
|
||||
"LabelByAuthor": "{0} által",
|
||||
"LabelChangePassword": "Jelszó megváltoztatása",
|
||||
"LabelChannels": "Csatornák",
|
||||
"LabelChapterCount": "{0} Fejezet",
|
||||
|
@ -275,14 +289,16 @@
|
|||
"LabelCollapseSeries": "Sorozat összecsukása",
|
||||
"LabelCollapseSubSeries": "Alszéria összecsukása",
|
||||
"LabelCollection": "Gyűjtemény",
|
||||
"LabelCollections": "Gyűjtemény",
|
||||
"LabelCollections": "Gyűjtemények",
|
||||
"LabelComplete": "Kész",
|
||||
"LabelConfirmPassword": "Jelszó megerősítése",
|
||||
"LabelContinueListening": "Hallgatás folytatása",
|
||||
"LabelContinueReading": "Olvasás folytatása",
|
||||
"LabelContinueSeries": "Sorozat folytatása",
|
||||
"LabelCorsAllowed": "Megengedett CORS Originek",
|
||||
"LabelCover": "Borító",
|
||||
"LabelCoverImageURL": "Borítókép URL",
|
||||
"LabelCoverProvider": "Borító Szolgáltató",
|
||||
"LabelCreatedAt": "Létrehozás ideje",
|
||||
"LabelCronExpression": "Cron kifejezés",
|
||||
"LabelCurrent": "Jelenlegi",
|
||||
|
@ -293,6 +309,7 @@
|
|||
"LabelDeleteFromFileSystemCheckbox": "Törlés a fájlrendszerről (ne jelölje be, ha csak az adatbázisból szeretné eltávolítani)",
|
||||
"LabelDescription": "Leírás",
|
||||
"LabelDeselectAll": "Minden kijelölés megszüntetése",
|
||||
"LabelDetectedPattern": "Észlelt minta:",
|
||||
"LabelDevice": "Eszköz",
|
||||
"LabelDeviceInfo": "Eszköz információ",
|
||||
"LabelDeviceIsAvailableTo": "Eszköz elérhető a következő számára...",
|
||||
|
@ -342,6 +359,10 @@
|
|||
"LabelExample": "Példa",
|
||||
"LabelExpandSeries": "Sorozat kinyitása",
|
||||
"LabelExpandSubSeries": "Alsorozat kinyitása",
|
||||
"LabelExpired": "Lejárt",
|
||||
"LabelExpiresAt": "Lejár",
|
||||
"LabelExpiresInSeconds": "Lejár (másodpercben)",
|
||||
"LabelExpiresNever": "Soha",
|
||||
"LabelExplicit": "Szókimondó",
|
||||
"LabelExplicitChecked": "Explicit (ellenőrizve)",
|
||||
"LabelExplicitUnchecked": "Nem explicit (nem ellenőrzött)",
|
||||
|
@ -391,7 +412,8 @@
|
|||
"LabelIntervalEvery6Hours": "Minden 6 órában",
|
||||
"LabelIntervalEveryDay": "Minden nap",
|
||||
"LabelIntervalEveryHour": "Minden órában",
|
||||
"LabelInvert": "Megfordítás",
|
||||
"LabelIntervalEveryMinute": "Minden percben",
|
||||
"LabelInvert": "Inverz",
|
||||
"LabelItem": "Elem",
|
||||
"LabelJumpBackwardAmount": "Visszafelé ugrás mennyisége",
|
||||
"LabelJumpForwardAmount": "Előre ugrás mennyisége",
|
||||
|
@ -400,6 +422,7 @@
|
|||
"LabelLanguages": "Nyelvek",
|
||||
"LabelLastBookAdded": "Utolsó hozzáadott könyv",
|
||||
"LabelLastBookUpdated": "Utolsó frissített könyv",
|
||||
"LabelLastProgressDate": "Legutóbbi haladás: {0}",
|
||||
"LabelLastSeen": "Utolsó látogatás",
|
||||
"LabelLastTime": "Utolsó alkalom",
|
||||
"LabelLastUpdate": "Utolsó frissítés",
|
||||
|
@ -412,6 +435,7 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Nem {0}",
|
||||
"LabelLibraryItem": "Könyvtári elem",
|
||||
"LabelLibraryName": "Könyvtár neve",
|
||||
"LabelLibrarySortByProgress": "Haladás frissítve",
|
||||
"LabelLimit": "Korlát",
|
||||
"LabelLineSpacing": "Sorköz",
|
||||
"LabelListenAgain": "Újrahallgatás",
|
||||
|
@ -420,6 +444,7 @@
|
|||
"LabelLogLevelWarn": "Figyelmeztetés",
|
||||
"LabelLookForNewEpisodesAfterDate": "Új epizódok keresése ezen a dátum után",
|
||||
"LabelLowestPriority": "Legalacsonyabb prioritás",
|
||||
"LabelMatchConfidence": "Bizalom",
|
||||
"LabelMatchExistingUsersBy": "Meglévő felhasználók egyeztetése",
|
||||
"LabelMatchExistingUsersByDescription": "Meglévő felhasználók összekapcsolására használt. Egyszer összekapcsolva, a felhasználók egyedülálló azonosítóval lesznek egyeztetve az Ön SSO szolgáltatójától",
|
||||
"LabelMaxEpisodesToDownload": "Letölthető epizódok maximális száma. Használja a 0-t a korlátlan letöltéshez.",
|
||||
|
@ -449,7 +474,9 @@
|
|||
"LabelNewestAuthors": "A legújabb szerzők",
|
||||
"LabelNewestEpisodes": "Legújabb epizódok",
|
||||
"LabelNextBackupDate": "Következő biztonsági másolat dátuma",
|
||||
"LabelNextChapters": "A következő fejezetek:",
|
||||
"LabelNextScheduledRun": "Következő ütemezett futtatás",
|
||||
"LabelNoApiKeys": "Nincs API kulcs",
|
||||
"LabelNoCustomMetadataProviders": "Nincsenek egyedi metaadat szolgáltatók",
|
||||
"LabelNoEpisodesSelected": "Nincsenek kiválasztott epizódok",
|
||||
"LabelNotFinished": "Nem befejezett",
|
||||
|
@ -465,6 +492,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Maximális értesítési események sorának mérete",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Az események korlátozva vannak, hogy másodpercenként 1-szer történjenek. Ha a sor maximális méretű, akkor az események figyelmen kívül lesznek hagyva. Ez megakadályozza az értesítések spamelését.",
|
||||
"LabelNumberOfBooks": "Könyvek száma",
|
||||
"LabelNumberOfChapters": "Fejezetek száma:",
|
||||
"LabelNumberOfEpisodes": "Epizódok száma",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Az OpenID-igény neve, amely a felhasználói műveletekre vonatkozó haladó jogosultságokat tartalmazza az alkalmazáson belül, és amely a nem adminisztrátori szerepkörökre vonatkozik (<b>ha konfigurálva van</b>). Ha az igény hiányzik a válaszból, az ABS-hez való hozzáférés megtagadásra kerül. Ha egyetlen opció hiányzik, azt <code>false</code>-ként fogja kezelni. Győződj meg arról, hogy az identitásszolgáltató igénye megfelel a várt struktúrának:",
|
||||
"LabelOpenIDClaims": "Hagyd üresen a következő opciókat, hogy letiltsd a haladó csoport- és jogosultság-hozzárendelést, ekkor automatikusan a ‘Felhasználó’ csoport kerül hozzárendelésre.",
|
||||
|
@ -486,6 +514,7 @@
|
|||
"LabelPersonalYearReview": "Az éved összefoglalása ({0})",
|
||||
"LabelPhotoPathURL": "Fénykép útvonal/URL",
|
||||
"LabelPlayMethod": "Lejátszási módszer",
|
||||
"LabelPlaybackRateIncrementDecrement": "Lejátszási sebesség növelés/csökkentés értéke",
|
||||
"LabelPlayerChapterNumberMarker": "{0} a {1} -ből",
|
||||
"LabelPlaylists": "Lejátszási listák",
|
||||
"LabelPodcast": "Podcast",
|
||||
|
@ -508,7 +537,7 @@
|
|||
"LabelPublishers": "Kiadók",
|
||||
"LabelRSSFeedCustomOwnerEmail": "Egyéni tulajdonos e-mail",
|
||||
"LabelRSSFeedCustomOwnerName": "Egyéni tulajdonos neve",
|
||||
"LabelRSSFeedOpen": "RSS hírcsatorna nyitva",
|
||||
"LabelRSSFeedOpen": "RSS-hírcsatorna nyitva",
|
||||
"LabelRSSFeedPreventIndexing": "Indexelés megakadályozása",
|
||||
"LabelRSSFeedSlug": "RSS hírcsatorna slug",
|
||||
"LabelRSSFeedURL": "RSS hírcsatorna URL",
|
||||
|
@ -525,6 +554,7 @@
|
|||
"LabelReleaseDate": "Megjelenés dátuma",
|
||||
"LabelRemoveAllMetadataAbs": "Az összes metadata.abs fájl eltávolítása",
|
||||
"LabelRemoveAllMetadataJson": "Az összes metadata.json fájl eltávolítása",
|
||||
"LabelRemoveAudibleBranding": "Audible intro és outro eltávolítása a fejezetekből",
|
||||
"LabelRemoveCover": "Borító eltávolítása",
|
||||
"LabelRemoveMetadataFile": "Metaadatfájlok eltávolítása a könyvtár elemek mappáiból",
|
||||
"LabelRemoveMetadataFileHelp": "A metadata.json és metadata.abs fájlokat eltávolítása a {0} mappáidból.",
|
||||
|
@ -537,6 +567,7 @@
|
|||
"LabelSelectAll": "Minden kiválasztása",
|
||||
"LabelSelectAllEpisodes": "Összes epizód kiválasztása",
|
||||
"LabelSelectEpisodesShowing": "Kiválasztás {0} megjelenített epizód",
|
||||
"LabelSelectUser": "Felhasználó kiválasztása",
|
||||
"LabelSelectUsers": "Felhasználók kiválasztása",
|
||||
"LabelSendEbookToDevice": "E-könyv küldése...",
|
||||
"LabelSequence": "Sorozat",
|
||||
|
@ -554,6 +585,8 @@
|
|||
"LabelSettingsBookshelfViewHelp": "Skeuomorfikus dizájn fa polcokkal",
|
||||
"LabelSettingsChromecastSupport": "Chromecast támogatás",
|
||||
"LabelSettingsDateFormat": "Dátumformátum",
|
||||
"LabelSettingsEnableWatcher": "Változások automatikus vizsgálata a könyvtárakban",
|
||||
"LabelSettingsEnableWatcherForLibrary": "Változások automatikus vizsgálata a könyvtárban",
|
||||
"LabelSettingsEnableWatcherHelp": "Engedélyezi az automatikus elem hozzáadás/frissítés funkciót, amikor fájlváltozásokat észlel. *Szerver újraindítása szükséges",
|
||||
"LabelSettingsEpubsAllowScriptedContent": "Szkriptelt tartalmak engedélyezése epub-okban",
|
||||
"LabelSettingsEpubsAllowScriptedContentHelp": "Megengedi, hogy az epub fájlok szkripteket hajtsanak végre. Ezt a beállítást kikapcsolva ajánlott tartani, kivéve, ha megbízik az epub fájlok forrásában.",
|
||||
|
@ -597,6 +630,7 @@
|
|||
"LabelSlug": "Rövid cím",
|
||||
"LabelSortAscending": "Emelkedő",
|
||||
"LabelSortDescending": "Csökkenő",
|
||||
"LabelSortPubDate": "Rendezés megjelenés dátuma szerint",
|
||||
"LabelStart": "Kezdés",
|
||||
"LabelStartTime": "Kezdési idő",
|
||||
"LabelStarted": "Elkezdődött",
|
||||
|
@ -630,6 +664,7 @@
|
|||
"LabelTheme": "Téma",
|
||||
"LabelThemeDark": "Sötét",
|
||||
"LabelThemeLight": "Világos",
|
||||
"LabelThemeSepia": "Szépia",
|
||||
"LabelTimeBase": "Időalap",
|
||||
"LabelTimeDurationXHours": "{0} óra",
|
||||
"LabelTimeDurationXMinutes": "{0} perc",
|
||||
|
@ -697,23 +732,33 @@
|
|||
"LabelYourProgress": "Haladásod",
|
||||
"MessageAddToPlayerQueue": "Hozzáadás a lejátszó sorhoz",
|
||||
"MessageAppriseDescription": "Ennek a funkció használatához futtatnia kell egy <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> példányt vagy egy olyan API-t, amely kezeli ezeket a kéréseket. <br />Az Apprise API URL-nek a teljes URL útvonalat kell tartalmaznia az értesítés elküldéséhez, például, ha az API példánya a <code>http://192.168.1.1:8337</code> címen szolgáltatva, akkor <code>http://192.168.1.1:8337/notify</code> értéket kell megadnia.",
|
||||
"MessageAsinCheck": "Győződjön meg róla, hogy az ASIN-t a megfelelő Audible régióból használja, nem az Amazonból.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "A régi API-tokenek a jövőben eltávolításra kerülnek. Helyette használja az <a href=\"/config/api-keys\">API-kulcsokat</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "A mentés után indítsa újra a szervert az OIDC módosítások alkalmazásához.",
|
||||
"MessageAuthenticationSecurityMessage": "A biztonság érdekében a hitelesítés folyamatát továbbfejlesztettük. Minden felhasználónak újra be kell jelentkeznie.",
|
||||
"MessageBackupsDescription": "A biztonsági másolatok tartalmazzák a felhasználókat, a felhasználói haladást, a könyvtári elem részleteit, a szerver beállításait és a képeket, amelyek a <code>/metadata/items</code> és <code>/metadata/authors</code> mappákban vannak tárolva. A biztonsági másolatok <strong>nem</strong> tartalmazzák a könyvtári mappákban tárolt fájlokat.",
|
||||
"MessageBackupsLocationEditNote": "Megjegyzés: A biztonsági mentés helyének frissítése nem mozgatja vagy módosítja a meglévő biztonsági mentéseket",
|
||||
"MessageBackupsLocationNoEditNote": "Megjegyzés: A biztonsági mentés helye egy környezeti változóval van beállítva, és itt nem módosítható.",
|
||||
"MessageBackupsLocationPathEmpty": "A biztonsági mentés helyének elérési útvonala nem lehet üres",
|
||||
"MessageBatchEditPopulateMapDetailsAllHelp": "Az engedélyezett mezők feltöltése az összes elem adatával. A több értéket tartalmazó mezők összevonásra kerülnek",
|
||||
"MessageBatchEditPopulateMapDetailsItemHelp": "A térkép engedélyezett adatmezőinek feltöltése ezen elem adataival",
|
||||
"MessageBatchQuickMatchDescription": "A Gyors egyeztetés megpróbálja hozzáadni a hiányzó borítókat és metaadatokat a kiválasztott elemekhez. Engedélyezze az alábbi opciókat, hogy a Gyors egyeztetés felülírhassa a meglévő borítókat és/vagy metaadatokat.",
|
||||
"MessageBookshelfNoCollections": "Még nem készített gyűjteményeket",
|
||||
"MessageBookshelfNoCollectionsHelp": "A gyűjtemények nyilvánosak. Minden, a könyvtárhoz hozzáféréssel rendelkező felhasználó láthatja őket.",
|
||||
"MessageBookshelfNoRSSFeeds": "Nincsenek nyitott RSS hírcsatornák",
|
||||
"MessageBookshelfNoResultsForFilter": "Nincs eredmény a \"{0}: {1}\" szűrőre",
|
||||
"MessageBookshelfNoResultsForQuery": "Nincs eredmény a lekérdezéshez",
|
||||
"MessageBookshelfNoSeries": "Nincsenek sorozatai",
|
||||
"MessageBulkChapterPattern": "Hány fejezetet szeretne hozzáadni ezzel a számozási mintával?",
|
||||
"MessageChapterEndIsAfter": "A fejezet vége a hangoskönyv végét követi",
|
||||
"MessageChapterErrorFirstNotZero": "Az első fejezetnek 0:00-kor kell kezdődnie",
|
||||
"MessageChapterErrorStartGteDuration": "Érvénytelen kezdési idő, kevesebbnek kell lennie, mint a hangoskönyv időtartama",
|
||||
"MessageChapterErrorStartLtPrev": "Érvénytelen kezdési idő, nagyobbnak kell lennie, mint az előző fejezet kezdési ideje",
|
||||
"MessageChapterStartIsAfter": "A fejezet kezdete a hangoskönyv végét követi",
|
||||
"MessageChaptersNotFound": "Fejezetek nem találhatók",
|
||||
"MessageCheckingCron": "Cron ellenőrzése...",
|
||||
"MessageConfirmCloseFeed": "Biztosan be szeretné zárni ezt a hírcsatornát?",
|
||||
"MessageConfirmDeleteApiKey": "Biztosan törölni szeretné az \"{0}\" API kulcsot?",
|
||||
"MessageConfirmDeleteBackup": "Biztosan törölni szeretné a(z) {0} biztonsági másolatot?",
|
||||
"MessageConfirmDeleteDevice": "Biztos, hogy törölni szeretné a „{0}” e-olvasó eszközt?",
|
||||
"MessageConfirmDeleteFile": "Ez törölni fogja a fájlt a fájlrendszerből. Biztos benne?",
|
||||
|
@ -741,6 +786,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Biztosan eltávolítja a(z) \"{0}\" szerzőt?",
|
||||
"MessageConfirmRemoveCollection": "Biztosan eltávolítja a(z) \"{0}\" gyűjteményt?",
|
||||
"MessageConfirmRemoveEpisode": "Biztosan eltávolítja a(z) \"{0}\" epizódot?",
|
||||
"MessageConfirmRemoveEpisodeNote": "Megjegyzés: Ez nem törli a hangfájlt, kivéve, ha a \"Hangfájl végleges törlése\" be van kapcsolva",
|
||||
"MessageConfirmRemoveEpisodes": "Biztosan eltávolítja a(z) {0} epizódot?",
|
||||
"MessageConfirmRemoveListeningSessions": "Biztosan eltávolítja a(z) {0} hallgatási munkamenetet?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Biztos, hogy az összes metaadatot el akarja távolítani {0} fájl van könyvtár mappáiban?",
|
||||
|
@ -766,8 +812,11 @@
|
|||
"MessageFeedURLWillBe": "A hírcsatorna URL-je {0} lesz",
|
||||
"MessageFetching": "Lekérdezés...",
|
||||
"MessageForceReScanDescription": "minden fájlt újra szkennel, mint egy friss szkennelés. Az audiofájlok ID3 címkéi, OPF fájlok és szövegfájlok újként lesznek szkennelve.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} hallgatja</strong> ezen {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Nincs hallgatás folyamatban ezen: {0}",
|
||||
"MessageImportantNotice": "Fontos közlemény!",
|
||||
"MessageInsertChapterBelow": "Fejezet beszúrása alulra",
|
||||
"MessageInvalidAsin": "Érvénytelen ASIN",
|
||||
"MessageItemsSelected": "{0} kiválasztott elem",
|
||||
"MessageItemsUpdated": "{0} frissített elem",
|
||||
"MessageJoinUsOn": "Csatlakozzon hozzánk a",
|
||||
|
@ -813,6 +862,7 @@
|
|||
"MessageNoTasksRunning": "Nincsenek futó feladatok",
|
||||
"MessageNoUpdatesWereNecessary": "Nem volt szükség frissítésekre",
|
||||
"MessageNoUserPlaylists": "Nincsenek felhasználói lejátszási listák",
|
||||
"MessageNoUserPlaylistsHelp": "A lejátszási listák személyesek. Csak az a felhasználó láthatja őket, aki létrehozta őket.",
|
||||
"MessageNotYetImplemented": "Még nem implementált",
|
||||
"MessageOpmlPreviewNote": "Megjegyzés: Ez egy előnézeti kép az elemzett OPML fájlról. A podcast tényleges címe az RSS hírcsatornából származik.",
|
||||
"MessageOr": "vagy",
|
||||
|
@ -835,8 +885,10 @@
|
|||
"MessageRestoreBackupConfirm": "Biztosan vissza szeretné állítani a biztonsági másolatot, amely ekkor készült:",
|
||||
"MessageRestoreBackupWarning": "A biztonsági mentés visszaállítása felülírja az egész adatbázist, amely a /config mappában található, valamint a borítóképeket a /metadata/items és /metadata/authors mappákban.<br /><br />A biztonsági mentések nem módosítják a könyvtár mappáiban található fájlokat. Ha engedélyezte a szerverbeállításokat a borítóképek és a metaadatok könyvtármappákban való tárolására, akkor ezek nem kerülnek biztonsági mentésre vagy felülírásra.<br /><br />A szerver használó összes kliens automatikusan frissül.",
|
||||
"MessageScheduleLibraryScanNote": "A legtöbb felhasználó számára ajánlott ezt a funkciót kikapcsolva hagyni, és engedélyezni a mappafigyelő beállítást. A mappafigyelő automatikusan észleli a könyvtári mappák változásait. A mappafigyelő nem működik minden fájlrendszernél (mint például az NFS), ezért helyette ütemezett könyvtárellenőrzéseket lehet használni.",
|
||||
"MessageScheduleRunEveryWeekdayAtTime": "Futás minden {1} óra {0}-kor",
|
||||
"MessageSearchResultsFor": "Keresési eredmények",
|
||||
"MessageSelected": "{0} kiválasztva",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "Sorozat sorrend nem tartalmazhat szóközt",
|
||||
"MessageServerCouldNotBeReached": "A szervert nem lehet elérni",
|
||||
"MessageSetChaptersFromTracksDescription": "Fejezetek beállítása minden egyes hangfájlt egy fejezetként használva, és a fejezet címét a hangfájl neveként",
|
||||
"MessageShareExpirationWillBe": "A lejárat: <strong>{0}</strong>",
|
||||
|
@ -861,6 +913,7 @@
|
|||
"MessageTaskNoFilesToScan": "Nincs beolvasandó fájl",
|
||||
"MessageTaskOpmlImport": "OPML import",
|
||||
"MessageTaskOpmlImportDescription": "Podcastok létrehozása {0} RSS hírcsatornából",
|
||||
"MessageTaskOpmlImportFeed": "OPML import hírcsatorna",
|
||||
"MessageTaskOpmlImportFeedDescription": "RSS feed „{0}” importálása",
|
||||
"MessageTaskOpmlImportFeedFailed": "Nem sikerült letölteni a podcast feedet",
|
||||
"MessageTaskOpmlImportFeedPodcastDescription": "„{0}” podcast létrehozása",
|
||||
|
@ -869,6 +922,7 @@
|
|||
"MessageTaskOpmlImportFinished": "{0} podcast hozzáadva",
|
||||
"MessageTaskOpmlParseFailed": "Az OPML fájl elemzése nem sikerült",
|
||||
"MessageTaskOpmlParseFastFail": "Érvénytelen OPML fájl: <opml> tag nem található VAGY nem találtak <outline> taget",
|
||||
"MessageTaskOpmlParseNoneFound": "Nem található feed az OPML fájlban",
|
||||
"MessageTaskScanItemsAdded": "{0} hozzáadva",
|
||||
"MessageTaskScanItemsMissing": "{0} hiányzik",
|
||||
"MessageTaskScanItemsUpdated": "{0} frissítve",
|
||||
|
@ -896,7 +950,10 @@
|
|||
"NotificationOnBackupCompletedDescription": "A biztonsági mentés befejezésekor aktiválódik",
|
||||
"NotificationOnBackupFailedDescription": "A biztonsági mentés sikertelensége esetén aktiválódik",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Egy podcast epizód automatikus letöltésekor aktiválódik",
|
||||
"NotificationOnRSSFeedDisabledDescription": "Akkor lép működésbe, ha az automatikus epizódletöltés a túl sok sikertelen próbálkozás miatt letiltásra kerül",
|
||||
"NotificationOnRSSFeedFailedDescription": "Akkor aktiválódik, ha az RSS feed kérés sikertelen az automatikus epizódletöltésnél",
|
||||
"NotificationOnTestDescription": "Esemény az értesítési rendszer teszteléséhez",
|
||||
"PlaceholderBulkChapterInput": "Írja be a fejezet címét vagy használjon számozást (pl. „1. epizód”, „10. fejezet”, „1.”)",
|
||||
"PlaceholderNewCollection": "Új gyűjtemény neve",
|
||||
"PlaceholderNewFolderPath": "Új mappa útvonala",
|
||||
"PlaceholderNewPlaylist": "Új lejátszási lista neve",
|
||||
|
@ -940,19 +997,29 @@
|
|||
"ToastBackupRestoreFailed": "A biztonsági mentés visszaállítása sikertelen",
|
||||
"ToastBackupUploadFailed": "A biztonsági mentés feltöltése sikertelen",
|
||||
"ToastBackupUploadSuccess": "Biztonsági mentés feltöltve",
|
||||
"ToastBatchApplyDetailsToItemsSuccess": "Tételekre alkalmazott részletek",
|
||||
"ToastBatchDeleteFailed": "A tömeges törlés nem sikerült",
|
||||
"ToastBatchDeleteSuccess": "Sikeres tömeges törlés",
|
||||
"ToastBatchQuickMatchFailed": "Tömeges Gyors Egyeztetés sikertelen!",
|
||||
"ToastBatchQuickMatchStarted": "{0} könyv Tömeges Gyors Egyeztetése elkezdődött!",
|
||||
"ToastBatchUpdateFailed": "Kötegelt frissítés sikertelen",
|
||||
"ToastBatchUpdateSuccess": "Kötegelt frissítés sikeres",
|
||||
"ToastBookmarkCreateFailed": "Könyvjelző létrehozása sikertelen",
|
||||
"ToastBookmarkCreateSuccess": "Könyvjelző hozzáadva",
|
||||
"ToastBookmarkRemoveSuccess": "Könyvjelző eltávolítva",
|
||||
"ToastBulkChapterInvalidCount": "Írjon be egy számot 1 és 150 között",
|
||||
"ToastCachePurgeFailed": "A gyorsítótár törlése sikertelen",
|
||||
"ToastCachePurgeSuccess": "A gyorsítótár sikeresen törölve",
|
||||
"ToastChapterLocked": "A fejezet zárolt.",
|
||||
"ToastChapterStartTimeAdjusted": "A fejezet kezdési ideje {0} másodperccel módosítva",
|
||||
"ToastChaptersAllLocked": "Minden fejezet zárolt. Nyisson meg néhány fejezetet, hogy módosítsa azok idejét.",
|
||||
"ToastChaptersHaveErrors": "A fejezetek hibákat tartalmaznak",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Érvénytelen eltolási érték. Az utolsó fejezet kezdési időpontja túlnyúlna a hangoskönyv időtartamán.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Érvénytelen eltolási érték. Az első fejezet hossza nulla vagy negatív lenne, és a második fejezet felülírná. Növelje a második fejezet kezdő időtartamát.",
|
||||
"ToastChaptersMustHaveTitles": "A fejezeteknek címekkel kell rendelkezniük",
|
||||
"ToastChaptersRemoved": "Fejezetek eltávolítva",
|
||||
"ToastChaptersUpdated": "Fejezetek frissítve",
|
||||
"ToastCollectionItemsAddFailed": "A tétel(ek) hozzáadása gyűjteményhez sikertelen",
|
||||
"ToastCollectionRemoveSuccess": "Gyűjtemény eltávolítva",
|
||||
"ToastCollectionUpdateSuccess": "Gyűjtemény frissítve",
|
||||
"ToastCoverUpdateFailed": "A borító frissítése nem sikerült",
|
||||
|
@ -967,14 +1034,19 @@
|
|||
"ToastEncodeCancelFailed": "A kódolás törlése sikertelen volt",
|
||||
"ToastEncodeCancelSucces": "Kódolás törölve",
|
||||
"ToastEpisodeDownloadQueueClearFailed": "Nem sikerült törölni a várólistát",
|
||||
"ToastEpisodeDownloadQueueClearSuccess": "Epizód letöltési várólista törölve",
|
||||
"ToastEpisodeUpdateSuccess": "{0} epizód frissítve",
|
||||
"ToastErrorCannotShare": "Ezen az eszközön nem lehet natívan megosztani",
|
||||
"ToastFailedToCreate": "Sikertelen létrehozás",
|
||||
"ToastFailedToDelete": "Sikertelen törlés",
|
||||
"ToastFailedToLoadData": "Sikertelen adatbetöltés",
|
||||
"ToastFailedToMatch": "Nem sikerült egyezőséget találni",
|
||||
"ToastFailedToShare": "Nem sikerült megosztani",
|
||||
"ToastFailedToUpdate": "Nem sikerült frissíteni",
|
||||
"ToastInvalidImageUrl": "Érvénytelen a kép URL címe",
|
||||
"ToastInvalidMaxEpisodesToDownload": "A letölthető epizódok száma érvénytelen",
|
||||
"ToastInvalidUrl": "Érvénytelen URL",
|
||||
"ToastInvalidUrls": "Egy vagy több URL érvénytelen",
|
||||
"ToastItemCoverUpdateSuccess": "Elem borítója frissítve",
|
||||
"ToastItemDeletedFailed": "Nem sikerült törölni az elemet",
|
||||
"ToastItemDeletedSuccess": "Elem törölve",
|
||||
|
@ -999,6 +1071,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Legalább egy elérési útvonalnak kell lennie",
|
||||
"ToastNameEmailRequired": "Név és e-mail cím megadása kötelező",
|
||||
"ToastNameRequired": "A név megadása kötelező",
|
||||
"ToastNewApiKeyUserError": "Ki kell választani egy felhasználót",
|
||||
"ToastNewEpisodesFound": "{0} új epizód",
|
||||
"ToastNewUserCreatedFailed": "Nem sikerült a fiókot létrehozni: „{0}”",
|
||||
"ToastNewUserCreatedSuccess": "Új fiók létrehozva",
|
||||
|
@ -1011,8 +1084,11 @@
|
|||
"ToastNoUpdatesNecessary": "Nincs szükség frissítésre",
|
||||
"ToastNotificationCreateFailed": "Értesítés létrehozása sikertelen",
|
||||
"ToastNotificationDeleteFailed": "Értesítés törlése sikertelen",
|
||||
"ToastNotificationFailedMaximum": "A sikertelen kísérletek maximális száma >= 0 kell, hogy legyen",
|
||||
"ToastNotificationQueueMaximum": "Az értesítési sor maximális száma >= 0 kell, hogy legyen",
|
||||
"ToastNotificationSettingsUpdateSuccess": "Értesítési beállítások frissítve",
|
||||
"ToastNotificationTestTriggerFailed": "Nem sikerült a tesztértesítést elindítani",
|
||||
"ToastNotificationTestTriggerSuccess": "Kiváltott tesztértesítés",
|
||||
"ToastNotificationUpdateSuccess": "Értesítés frissítve",
|
||||
"ToastPlaylistCreateFailed": "Lejátszási lista létrehozása sikertelen",
|
||||
"ToastPlaylistCreateSuccess": "Lejátszási lista létrehozva",
|
||||
|
@ -1020,6 +1096,8 @@
|
|||
"ToastPlaylistUpdateSuccess": "Lejátszási lista frissítve",
|
||||
"ToastPodcastCreateFailed": "Podcast létrehozása sikertelen",
|
||||
"ToastPodcastCreateSuccess": "A podcast sikeresen létrehozva",
|
||||
"ToastPodcastEpisodeUpdated": "Epizód frissítve",
|
||||
"ToastPodcastGetFeedFailed": "Nem sikerült podcast feedet kapni",
|
||||
"ToastPodcastNoEpisodesInFeed": "Nincsenek epizódok az RSS hírcsatornában",
|
||||
"ToastPodcastNoRssFeed": "A podcastnak nincs RSS-hírcsatornája",
|
||||
"ToastProgressIsNotBeingSynced": "Az előrehaladás nem szinkronizálódik, a lejátszás újraindul",
|
||||
|
@ -1032,10 +1110,18 @@
|
|||
"ToastRemoveFailed": "Sikertelen eltávolítás",
|
||||
"ToastRemoveItemFromCollectionFailed": "Tétel eltávolítása a gyűjteményből sikertelen",
|
||||
"ToastRemoveItemFromCollectionSuccess": "Tétel eltávolítva a gyűjteményből",
|
||||
"ToastRemoveItemsWithIssuesFailed": "Nem sikerült eltávolítani a hibás könyvtárelemeket",
|
||||
"ToastRemoveItemsWithIssuesSuccess": "Hibás könyvtárelemek eltávolítva",
|
||||
"ToastRenameFailed": "Sikertelen átnevezés",
|
||||
"ToastRescanFailed": "Sikertelen újrakeresés a következőnél: {0}",
|
||||
"ToastRescanRemoved": "A teljes újrabeolvasás befejezve, elem eltávolítva",
|
||||
"ToastRescanUpToDate": "A teljes újrabeolvasás befejezve, elem naprakész volt",
|
||||
"ToastRescanUpdated": "A teljes újrabeolvasás befejezve, elem frissítve",
|
||||
"ToastScanFailed": "Nem sikerült beolvasni a könyvtárelemet",
|
||||
"ToastSelectAtLeastOneUser": "Válasszon legalább egy felhasználót",
|
||||
"ToastSendEbookToDeviceFailed": "E-könyv küldése az eszközre sikertelen",
|
||||
"ToastSendEbookToDeviceSuccess": "E-könyv elküldve az eszközre \"{0}\"",
|
||||
"ToastSeriesSubmitFailedSameName": "Nem lehet két azonos nevű sorozatot hozzáadni",
|
||||
"ToastSeriesUpdateFailed": "Sorozat frissítése sikertelen",
|
||||
"ToastSeriesUpdateSuccess": "Sorozat frissítése sikeres",
|
||||
"ToastServerSettingsUpdateSuccess": "Szerver beállítások frissítve",
|
||||
|
@ -1043,6 +1129,8 @@
|
|||
"ToastSessionDeleteFailed": "Munkamenet törlése sikertelen",
|
||||
"ToastSessionDeleteSuccess": "Munkamenet törölve",
|
||||
"ToastSleepTimerDone": "Alvásidőzítő kész... zZzzZZz",
|
||||
"ToastSlugMustChange": "A Slug érvénytelen karaktereket tartalmaz",
|
||||
"ToastSlugRequired": "Slug szükséges",
|
||||
"ToastSocketConnected": "Socket csatlakoztatva",
|
||||
"ToastSocketDisconnected": "Socket lecsatlakoztatva",
|
||||
"ToastSocketFailedToConnect": "A Socket csatlakoztatása sikertelen",
|
||||
|
@ -1050,9 +1138,22 @@
|
|||
"ToastSortingPrefixesUpdateSuccess": "Rendezési előtagok frissítése ({0} elem)",
|
||||
"ToastTitleRequired": "A cím kötelező",
|
||||
"ToastUnknownError": "Ismeretlen hiba",
|
||||
"ToastUnlinkOpenIdFailed": "Nem sikerült leválasztani a felhasználót az OpenID-ről",
|
||||
"ToastUnlinkOpenIdSuccess": "Felhasználó leválasztva az OpenID-ről",
|
||||
"ToastUploaderFilepathExistsError": "A \"{0}\" fájl elérési útja már létezik a szerveren",
|
||||
"ToastUploaderItemExistsInSubdirectoryError": "A „{0}” elem a feltöltési útvonal egy alkönyvtárát használja.",
|
||||
"ToastUserDeleteFailed": "Felhasználó törlése sikertelen",
|
||||
"ToastUserDeleteSuccess": "Felhasználó törölve",
|
||||
"ToastUserPasswordChangeSuccess": "Jelszó sikeresen megváltoztatva",
|
||||
"ToastUserPasswordMismatch": "A jelszavak nem egyeznek",
|
||||
"ToastUserPasswordMustChange": "Az új jelszó nem egyezik a régi jelszóval",
|
||||
"ToastUserRootRequireName": "Egy root felhasználónevet kell megadnia"
|
||||
"ToastUserRootRequireName": "Egy root felhasználónevet kell megadnia",
|
||||
"TooltipAddChapters": "Fejezet(ek) hozzáadása",
|
||||
"TooltipAddOneSecond": "1 másodperc hozzáadása",
|
||||
"TooltipAdjustChapterStart": "Kattintson a kezdési idő beállításához",
|
||||
"TooltipLockAllChapters": "Az összes fejezet zárolása",
|
||||
"TooltipLockChapter": "Fejezet zárolása (Shift+kattintás a tartományhoz)",
|
||||
"TooltipSubtractOneSecond": "1 másodperc levonása",
|
||||
"TooltipUnlockAllChapters": "Az összes fejezet feloldása",
|
||||
"TooltipUnlockChapter": "Fejezet feloldása (Shift+kattintás a tartományhoz)"
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
{
|
||||
"ButtonAdd": "Aggiungi",
|
||||
"ButtonAddApiKey": "Aggiungi la chiave API",
|
||||
"ButtonAddChapters": "Aggiungi Capitoli",
|
||||
"ButtonAddDevice": "Aggiungi Dispositivo",
|
||||
"ButtonAddLibrary": "Aggiungi Libreria",
|
||||
"ButtonAddPodcasts": "Aggiungi Podcast",
|
||||
"ButtonAddUser": "Aggiungi User",
|
||||
"ButtonAddUser": "Aggiungi Utente",
|
||||
"ButtonAddYourFirstLibrary": "Aggiungi la tua prima libreria",
|
||||
"ButtonApply": "Applica",
|
||||
"ButtonApplyChapters": "Applica",
|
||||
"ButtonApplyChapters": "Applica Capitoli",
|
||||
"ButtonAuthors": "Autori",
|
||||
"ButtonBack": "Indietro",
|
||||
"ButtonBatchEditPopulateFromExisting": "Popola da esistente",
|
||||
"ButtonBatchEditPopulateMapDetails": "Inserisci i dettagli della mappa",
|
||||
"ButtonBrowseForFolder": "Per Cartella",
|
||||
"ButtonCancel": "Cancella",
|
||||
"ButtonBrowseForFolder": "Sfoglia per Cartella",
|
||||
"ButtonCancel": "Annulla",
|
||||
"ButtonCancelEncode": "Ferma la codifica",
|
||||
"ButtonChangeRootPassword": "Cambia la Password di root",
|
||||
"ButtonCheckAndDownloadNewEpisodes": "Controlla & scarica i nuovi episodi",
|
||||
"ButtonChooseAFolder": "Seleziona la Cartella",
|
||||
"ButtonChooseFiles": "Seleziona i File",
|
||||
"ButtonClearFilter": "Elimina filtri",
|
||||
"ButtonClose": "Chiudi",
|
||||
"ButtonCloseFeed": "Chiudi flusso",
|
||||
"ButtonCloseSession": "Chiudi la sessione aperta",
|
||||
"ButtonCollections": "Raccolte",
|
||||
|
@ -119,11 +121,13 @@
|
|||
"HeaderAccount": "Account",
|
||||
"HeaderAddCustomMetadataProvider": "Aggiungi fornitori di metadati personalizzati",
|
||||
"HeaderAdvanced": "Avanzate",
|
||||
"HeaderApiKeys": "Le chiavi API",
|
||||
"HeaderAppriseNotificationSettings": "Apprendi le impostazioni di Notifica",
|
||||
"HeaderAudioTracks": "Tracce audio",
|
||||
"HeaderAudiobookTools": "Strumenti di gestione file audiolibri",
|
||||
"HeaderAuthentication": "Authenticazione",
|
||||
"HeaderBackups": "Backup",
|
||||
"HeaderBulkChapterModal": "Aggiungere più capitoli",
|
||||
"HeaderChangePassword": "Cambia la password",
|
||||
"HeaderChapters": "Capitoli",
|
||||
"HeaderChooseAFolder": "Seleziona la cartella",
|
||||
|
@ -162,6 +166,7 @@
|
|||
"HeaderMetadataOrderOfPrecedence": "Priorità ordine Metadata",
|
||||
"HeaderMetadataToEmbed": "Metadata da incorporare",
|
||||
"HeaderNewAccount": "Nuovo Account",
|
||||
"HeaderNewApiKey": "Nuova chiave API",
|
||||
"HeaderNewLibrary": "Nuova Libreria",
|
||||
"HeaderNotificationCreate": "Crea una notifica",
|
||||
"HeaderNotificationUpdate": "Aggiornamento della notifica",
|
||||
|
@ -195,6 +200,7 @@
|
|||
"HeaderSettingsExperimental": "Opzioni Sperimentali",
|
||||
"HeaderSettingsGeneral": "Generale",
|
||||
"HeaderSettingsScanner": "Scanner",
|
||||
"HeaderSettingsSecurity": "Sicurezza",
|
||||
"HeaderSettingsWebClient": "Web Client",
|
||||
"HeaderSleepTimer": "Sveglia",
|
||||
"HeaderStatsLargestItems": "File pesanti",
|
||||
|
@ -206,6 +212,7 @@
|
|||
"HeaderTableOfContents": "Indice",
|
||||
"HeaderTools": "Strumenti",
|
||||
"HeaderUpdateAccount": "Aggiorna Account",
|
||||
"HeaderUpdateApiKey": "Aggiornamento chiave API",
|
||||
"HeaderUpdateAuthor": "Aggiorna Autore",
|
||||
"HeaderUpdateDetails": "Aggiorna Dettagli",
|
||||
"HeaderUpdateLibrary": "Aggiorna Libreria",
|
||||
|
@ -235,6 +242,10 @@
|
|||
"LabelAllUsersExcludingGuests": "Tutti gli Utenti Esclusi gli ospiti",
|
||||
"LabelAllUsersIncludingGuests": "Tutti gli Utenti Inclusi gli ospiti",
|
||||
"LabelAlreadyInYourLibrary": "Già esistente nella libreria",
|
||||
"LabelApiKeyCreated": "API Key \"{0}\" creato con successo.",
|
||||
"LabelApiKeyCreatedDescription": "Assicurarsi di copiare la chiave API ora poiché non si potrà rivederla.",
|
||||
"LabelApiKeyUser": "Agisce per conto dell'utente",
|
||||
"LabelApiKeyUserDescription": "Questa chiave API avrà le stesse autorizzazioni dell'utente per conto del quale agisce. Apparirà nei registri come se l'utente stesse facendo la richiesta.",
|
||||
"LabelApiToken": "API Token",
|
||||
"LabelAppend": "Appese",
|
||||
"LabelAudioBitrate": "Audio Bitrate (es. 128k)",
|
||||
|
@ -281,9 +292,10 @@
|
|||
"LabelCollections": "Raccolte",
|
||||
"LabelComplete": "Completo",
|
||||
"LabelConfirmPassword": "Conferma Password",
|
||||
"LabelContinueListening": "Continua ad Ascoltare",
|
||||
"LabelContinueReading": "Continua la Lettura",
|
||||
"LabelContinueListening": "Continua l'ascolto",
|
||||
"LabelContinueReading": "Continua la lettura",
|
||||
"LabelContinueSeries": "Continua serie",
|
||||
"LabelCorsAllowed": "CORS consentiti Origine",
|
||||
"LabelCover": "Copertina",
|
||||
"LabelCoverImageURL": "Indirizzo della cover URL",
|
||||
"LabelCoverProvider": "Cover Sorgente",
|
||||
|
@ -346,6 +358,10 @@
|
|||
"LabelExample": "Esempio",
|
||||
"LabelExpandSeries": "Espandi Serie",
|
||||
"LabelExpandSubSeries": "Espandi Sub Serie",
|
||||
"LabelExpired": "Scadenza",
|
||||
"LabelExpiresAt": "Scade a",
|
||||
"LabelExpiresInSeconds": "Scade in (secondi)",
|
||||
"LabelExpiresNever": "Mai",
|
||||
"LabelExplicit": "Esplicito",
|
||||
"LabelExplicitChecked": "Esplicito (selezionato)",
|
||||
"LabelExplicitUnchecked": "Non Esplicito (selezionato)",
|
||||
|
@ -405,6 +421,7 @@
|
|||
"LabelLanguages": "Lingua",
|
||||
"LabelLastBookAdded": "Ultimo Libro Aggiunto",
|
||||
"LabelLastBookUpdated": "Ultimo Libro Aggiornato",
|
||||
"LabelLastProgressDate": "Ultimi progressi: Si'",
|
||||
"LabelLastSeen": "Ultimi Visti",
|
||||
"LabelLastTime": "Ultima Volta",
|
||||
"LabelLastUpdate": "Ultimo Aggiornamento",
|
||||
|
@ -417,6 +434,8 @@
|
|||
"LabelLibraryFilterSublistEmpty": "Nessuno {0}",
|
||||
"LabelLibraryItem": "Elementi della biblioteca",
|
||||
"LabelLibraryName": "Nome della biblioteca",
|
||||
"LabelLibrarySortByProgress": "Aggiornamento dei progressi",
|
||||
"LabelLibrarySortByProgressStarted": "Data di inizio",
|
||||
"LabelLimit": "Limiti",
|
||||
"LabelLineSpacing": "Interlinea",
|
||||
"LabelListenAgain": "Ascolta ancora",
|
||||
|
@ -425,6 +444,7 @@
|
|||
"LabelLogLevelWarn": "Allarme",
|
||||
"LabelLookForNewEpisodesAfterDate": "Cerca nuovi episodi dopo questa data",
|
||||
"LabelLowestPriority": "Priorità Minima",
|
||||
"LabelMatchConfidence": "Fiducia",
|
||||
"LabelMatchExistingUsersBy": "Abbina gli utenti esistenti per",
|
||||
"LabelMatchExistingUsersByDescription": "Utilizzato per connettere gli utenti esistenti. Una volta connessi, gli utenti verranno abbinati a un ID univoco dal tuo provider SSO",
|
||||
"LabelMaxEpisodesToDownload": "Max # di episodi da scaricare. Usa 0 per illimitati.",
|
||||
|
@ -454,7 +474,9 @@
|
|||
"LabelNewestAuthors": "Nuovi autori",
|
||||
"LabelNewestEpisodes": "Nuovi episodi",
|
||||
"LabelNextBackupDate": "Data Prossimo Backup",
|
||||
"LabelNextChapters": "I prossimi capitoli saranno:",
|
||||
"LabelNextScheduledRun": "Data prossima esecuzione schedulata",
|
||||
"LabelNoApiKeys": "Nessuna chiave API",
|
||||
"LabelNoCustomMetadataProviders": "Nessun provider di metadati personalizzato",
|
||||
"LabelNoEpisodesSelected": "Nessun Episodio Selezionato",
|
||||
"LabelNotFinished": "Da completare",
|
||||
|
@ -470,6 +492,7 @@
|
|||
"LabelNotificationsMaxQueueSize": "Coda Massima di notifiche eventi",
|
||||
"LabelNotificationsMaxQueueSizeHelp": "Le notifiche sono limitate per 1 al secondo, per evitare lo spamming le notifiche verrano ignorare se superano la coda.",
|
||||
"LabelNumberOfBooks": "Numero di libri",
|
||||
"LabelNumberOfChapters": "Numero di capitoli:",
|
||||
"LabelNumberOfEpisodes": "Numero di episodi",
|
||||
"LabelOpenIDAdvancedPermsClaimDescription": "Nome dell'attestazione OpenID che contiene autorizzazioni avanzate per le azioni dell'utente all'interno dell'applicazione che verranno applicate ai ruoli non amministratori (<b>se configurato</b>). Se il reclamo manca nella risposta, l'accesso ad ABS verrà negato. Se manca una singola opzione, verrà trattata come<code>falsa</code>. Assicurati che l'attestazione del provider di identità corrisponda alla struttura prevista:",
|
||||
"LabelOpenIDClaims": "Lasciare vuote le seguenti opzioni per disabilitare l'assegnazione avanzata di gruppi e autorizzazioni, assegnando quindi automaticamente il gruppo \"Utente\".",
|
||||
|
@ -514,7 +537,7 @@
|
|||
"LabelPublishers": "Editori",
|
||||
"LabelRSSFeedCustomOwnerEmail": "E-mail del proprietario personalizzato",
|
||||
"LabelRSSFeedCustomOwnerName": "Nome del proprietario personalizzato",
|
||||
"LabelRSSFeedOpen": "Flusso RSS aperto",
|
||||
"LabelRSSFeedOpen": "Feed RSS aperto",
|
||||
"LabelRSSFeedPreventIndexing": "Impedisci l'indicizzazione",
|
||||
"LabelRSSFeedSlug": "Parole chiave del flusso RSS",
|
||||
"LabelRSSFeedURL": "URL del flusso RSS",
|
||||
|
@ -544,6 +567,7 @@
|
|||
"LabelSelectAll": "Seleziona tutto",
|
||||
"LabelSelectAllEpisodes": "Seleziona tutti gli Episodi",
|
||||
"LabelSelectEpisodesShowing": "Selezionati {0} episodi da visualizzare",
|
||||
"LabelSelectUser": "Seleziona l'utente",
|
||||
"LabelSelectUsers": "Selezione Utenti",
|
||||
"LabelSendEbookToDevice": "Invia il libro a...",
|
||||
"LabelSequence": "Sequenza",
|
||||
|
@ -640,6 +664,7 @@
|
|||
"LabelTheme": "Tema",
|
||||
"LabelThemeDark": "Scuro",
|
||||
"LabelThemeLight": "Chiaro",
|
||||
"LabelThemeSepia": "Seppia",
|
||||
"LabelTimeBase": "Tempo base",
|
||||
"LabelTimeDurationXHours": "{0} Ore",
|
||||
"LabelTimeDurationXMinutes": "{0} minuti",
|
||||
|
@ -708,6 +733,9 @@
|
|||
"MessageAddToPlayerQueue": "Aggiungi alla coda di riproduzione",
|
||||
"MessageAppriseDescription": "Per utilizzare questa funzione è necessario disporre di un'istanza di <a href=\"https://github.com/caronc/apprise-api\" target=\"_blank\">Apprise API</a> in esecuzione o un'API che gestirà quelle stesse richieste. <br />L'API Url dovrebbe essere il percorso URL completo per inviare la notifica, ad esempio se la tua istanza API è servita cosi .<code>http://192.168.1.1:8337</code> Allora dovrai mettere <code>http://192.168.1.1:8337/notify</code>.",
|
||||
"MessageAsinCheck": "Assicurati di utilizzare l'ASIN della regione Audible corretta, non di Amazon.",
|
||||
"MessageAuthenticationLegacyTokenWarning": "I token API legacy verranno rimossi in futuro. Utilizzare piuttosto le <a href=\"/config/api-keys\">chiavi API</a>.",
|
||||
"MessageAuthenticationOIDCChangesRestart": "Riavvia il tuo server dopo aver salvato per applicare le modifiche OIDC.",
|
||||
"MessageAuthenticationSecurityMessage": "L'autenticazione è stata migliorata per incrementare la sicurezza. Tutti gli utenti sono tenuti a rieffettuare il login.",
|
||||
"MessageBackupsDescription": "I backup includono utenti, progressi degli utenti, dettagli sugli elementi della libreria, impostazioni del server e immagini archiviate in <code>/metadata/items</code> & <code>/metadata/authors</code>. I backup non includono i file archiviati nelle cartelle della libreria.",
|
||||
"MessageBackupsLocationEditNote": "Nota: l'aggiornamento della posizione di backup non sposterà o modificherà i backup esistenti",
|
||||
"MessageBackupsLocationNoEditNote": "Nota: la posizione del backup viene impostata tramite una variabile di ambiente e non può essere modificata qui.",
|
||||
|
@ -721,6 +749,7 @@
|
|||
"MessageBookshelfNoResultsForFilter": "Nessun risultato per il filtro \"{0}: {1}\"",
|
||||
"MessageBookshelfNoResultsForQuery": "Nessun risultato per la query",
|
||||
"MessageBookshelfNoSeries": "Non c'è nessuna Serie",
|
||||
"MessageBulkChapterPattern": "Quanti capitoli vuoi aggiungere con questo motivo di numerazione?",
|
||||
"MessageChapterEndIsAfter": "La fine del capitolo è dopo la fine del tuo audiolibro",
|
||||
"MessageChapterErrorFirstNotZero": "Il primo capitolo deve iniziare da 0",
|
||||
"MessageChapterErrorStartGteDuration": "L'ora di inizio non valida deve essere inferiore alla durata dell'audiolibro",
|
||||
|
@ -729,6 +758,7 @@
|
|||
"MessageChaptersNotFound": "Capitoli non trovati",
|
||||
"MessageCheckingCron": "Controllo cron...",
|
||||
"MessageConfirmCloseFeed": "Sei sicuro di voler chiudere questo feed?",
|
||||
"MessageConfirmDeleteApiKey": "Sei sicuro di voler eliminare la chiave API \"{0}\"?",
|
||||
"MessageConfirmDeleteBackup": "Sei sicuro di voler eliminare il backup {0}?",
|
||||
"MessageConfirmDeleteDevice": "Sei sicuro/sicura di voler eliminare il lettore di libri {0}?",
|
||||
"MessageConfirmDeleteFile": "Questo eliminerà il file dal tuo file system. Sei sicuro?",
|
||||
|
@ -756,6 +786,7 @@
|
|||
"MessageConfirmRemoveAuthor": "Sei sicuro di voler rimuovere l'autore? \"{0}\"?",
|
||||
"MessageConfirmRemoveCollection": "Sei sicuro di voler rimuovere la Raccolta \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisode": "Sei sicuro di voler rimuovere l'episodio \"{0}\"?",
|
||||
"MessageConfirmRemoveEpisodeNote": "Nota: Questo non cancella il file audio a meno che non toggling \"Hard delete file\"",
|
||||
"MessageConfirmRemoveEpisodes": "Sei sicuro di voler rimuovere {0} episodi?",
|
||||
"MessageConfirmRemoveListeningSessions": "Sei sicuro di voler rimuovere {0} sessioni di Ascolto?",
|
||||
"MessageConfirmRemoveMetadataFiles": "Vuoi davvero rimuovere tutti i metadati.{0} file nelle cartelle degli elementi della tua libreria?",
|
||||
|
@ -781,6 +812,8 @@
|
|||
"MessageFeedURLWillBe": "l’URL del flusso sarà {0}",
|
||||
"MessageFetching": "Recupero info…",
|
||||
"MessageForceReScanDescription": "eseguirà nuovamente la scansione di tutti i file come una nuova scansione. I tag ID3 dei file audio, i file OPF e i file di testo verranno scansionati come nuovi.",
|
||||
"MessageHeatmapListeningTimeTooltip": "<strong>{0} in ascolto</strong> su {1}",
|
||||
"MessageHeatmapNoListeningSessions": "Nessuna sessione di ascolto su {0}",
|
||||
"MessageImportantNotice": "Avviso Importante!",
|
||||
"MessageInsertChapterBelow": "Inserisci capitolo sotto",
|
||||
"MessageInvalidAsin": "ASIN non Valido",
|
||||
|
@ -855,6 +888,7 @@
|
|||
"MessageScheduleRunEveryWeekdayAtTime": "Esegui ogni {0} alle {1}",
|
||||
"MessageSearchResultsFor": "cerca risultati per",
|
||||
"MessageSelected": "{0} selezionati",
|
||||
"MessageSeriesSequenceCannotContainSpaces": "La sequenza della serie non può contenere spazi",
|
||||
"MessageServerCouldNotBeReached": "Impossibile raggiungere il server",
|
||||
"MessageSetChaptersFromTracksDescription": "Impostare i capitoli utilizzando ciascun file audio come capitolo e il titolo del capitolo come nome del file audio",
|
||||
"MessageShareExpirationWillBe": "Scadrà tra <strong>{0}</strong>",
|
||||
|
@ -916,7 +950,10 @@
|
|||
"NotificationOnBackupCompletedDescription": "Attivato al completamento di un backup",
|
||||
"NotificationOnBackupFailedDescription": "Attivato quando un backup fallisce",
|
||||
"NotificationOnEpisodeDownloadedDescription": "Attivato quando un episodio di podcast viene scaricato automaticamente",
|
||||
"NotificationOnRSSFeedDisabledDescription": "Attivato quando i download automatici degli episodi vengono disabilitati a causa di troppi tentativi falliti",
|
||||
"NotificationOnRSSFeedFailedDescription": "Attivato quando la richiesta del feed RSS per il download automatico di un episodio fallisce",
|
||||
"NotificationOnTestDescription": "test il sistema di notifica",
|
||||
"PlaceholderBulkChapterInput": "Inserire il titolo del capitolo o utilizzate la numerazione (es. 'Episodio 1', 'Capitolo 10', '1.')",
|
||||
"PlaceholderNewCollection": "Nome Nuova Raccolta",
|
||||
"PlaceholderNewFolderPath": "Nuovo Percorso Cartella",
|
||||
"PlaceholderNewPlaylist": "Nome nuova playlist",
|
||||
|
@ -970,8 +1007,12 @@
|
|||
"ToastBookmarkCreateFailed": "Creazione segnalibro fallita",
|
||||
"ToastBookmarkCreateSuccess": "Segnalibro creato",
|
||||
"ToastBookmarkRemoveSuccess": "Segnalibro Rimosso",
|
||||
"ToastBulkChapterInvalidCount": "Inserire un numero tra 1 e 150",
|
||||
"ToastCachePurgeFailed": "Impossibile eliminare la cache",
|
||||
"ToastCachePurgeSuccess": "Cache eliminata correttamente",
|
||||
"ToastChapterLocked": "Il capitolo è bloccato.",
|
||||
"ToastChapterStartTimeAdjusted": "Tempo di inizio del capitolo modificato di {0} secondi",
|
||||
"ToastChaptersAllLocked": "Tutti i capitoli sono bloccati. Sblocca alcuni capitoli per modificarne i tempi.",
|
||||
"ToastChaptersHaveErrors": "I capitoli contengono errori",
|
||||
"ToastChaptersInvalidShiftAmountLast": "Quantità di spostamento non valida. L'orario di inizio dell'ultimo capitolo si estenderebbe oltre la durata di questo audiolibro.",
|
||||
"ToastChaptersInvalidShiftAmountStart": "Quantità di spostamento non valida. Il primo capitolo avrebbe una lunghezza pari a zero o negativa e verrebbe sovrascritto dal secondo capitolo. Aumentare la durata iniziale del secondo capitolo.",
|
||||
|
@ -996,6 +1037,8 @@
|
|||
"ToastEpisodeDownloadQueueClearSuccess": "Coda di download degli episodi cancellata",
|
||||
"ToastEpisodeUpdateSuccess": "{0} episodi aggiornati",
|
||||
"ToastErrorCannotShare": "Impossibile condividere in modo nativo su questo dispositivo",
|
||||
"ToastFailedToCreate": "Non creato",
|
||||
"ToastFailedToDelete": "Non eliminata",
|
||||
"ToastFailedToLoadData": "Impossibile caricare i dati",
|
||||
"ToastFailedToMatch": "Impossibile abbinare",
|
||||
"ToastFailedToShare": "Impossibile condividere",
|
||||
|
@ -1003,6 +1046,7 @@
|
|||
"ToastInvalidImageUrl": "URL dell'immagine non valido",
|
||||
"ToastInvalidMaxEpisodesToDownload": "Numero massimo di episodi non valido da scaricare",
|
||||
"ToastInvalidUrl": "URL non valido",
|
||||
"ToastInvalidUrls": "Uno o più URL sono invalidi",
|
||||
"ToastItemCoverUpdateSuccess": "Cover aggiornata",
|
||||
"ToastItemDeletedFailed": "Impossibile eliminare l'elemento",
|
||||
"ToastItemDeletedSuccess": "Elemento eliminato",
|
||||
|
@ -1027,6 +1071,7 @@
|
|||
"ToastMustHaveAtLeastOnePath": "Deve avere almeno un percorso",
|
||||
"ToastNameEmailRequired": "Nome ed email sono obbligatori",
|
||||
"ToastNameRequired": "Il nome è obbligatorio",
|
||||
"ToastNewApiKeyUserError": "Deve selezionare un utente",
|
||||
"ToastNewEpisodesFound": "{0} nuovi episodi trovati",
|
||||
"ToastNewUserCreatedFailed": "Impossibile creare l'account: \"{0}\"",
|
||||
"ToastNewUserCreatedSuccess": "Nuovo account creato",
|
||||
|
@ -1051,6 +1096,7 @@
|
|||
"ToastPlaylistUpdateSuccess": "Playlist Aggiornata",
|
||||
"ToastPodcastCreateFailed": "Errore creazione podcast",
|
||||
"ToastPodcastCreateSuccess": "Podcast creato correttamente",
|
||||
"ToastPodcastEpisodeUpdated": "Episodio aggiornato",
|
||||
"ToastPodcastGetFeedFailed": "Impossibile ottenere il feed del podcast",
|
||||
"ToastPodcastNoEpisodesInFeed": "Nessun episodio trovato nel feed RSS",
|
||||
"ToastPodcastNoRssFeed": "Il podcast non ha un feed RSS",
|
||||
|
@ -1101,5 +1147,13 @@
|
|||
"ToastUserPasswordChangeSuccess": "Password modificata con successo",
|
||||
"ToastUserPasswordMismatch": "Le password non corrispondono",
|
||||
"ToastUserPasswordMustChange": "La nuova password non può corrispondere alla vecchia password",
|
||||
"ToastUserRootRequireName": "È necessario immettere un nome utente root"
|
||||
"ToastUserRootRequireName": "È necessario immettere un nome utente root",
|
||||
"TooltipAddChapters": "Aggiungere capitolo/i",
|
||||
"TooltipAddOneSecond": "Aggiungere 1 secondo",
|
||||
"TooltipAdjustChapterStart": "Clicca per modificare il tempo di inizio",
|
||||
"TooltipLockAllChapters": "Bloccare tutti i capitoli",
|
||||
"TooltipLockChapter": "Bloccare capitolo (Shift+click per intervallo)",
|
||||
"TooltipSubtractOneSecond": "Sottrarre 1 secondo",
|
||||
"TooltipUnlockAllChapters": "Sbloccare tutti i capitoli",
|
||||
"TooltipUnlockChapter": "Sbloccare capitolo (Shift+click per intervallo)"
|
||||
}
|
||||
|
|
|
@ -1,15 +1,97 @@
|
|||
{
|
||||
"ButtonAdd": "追加",
|
||||
"ButtonAddApiKey": "APIキーの追加",
|
||||
"ButtonAddChapters": "チャプターの追加",
|
||||
"ButtonAddDevice": "端末の追加",
|
||||
"ButtonAddLibrary": "ライブラリーの追加",
|
||||
"ButtonAddPodcasts": "ポッドキャストの追加",
|
||||
"ButtonAddUser": "ユーザーの追加",
|
||||
"ButtonAddYourFirstLibrary": "最初のライブラリーを追加",
|
||||
"ButtonApply": "確定",
|
||||
"ButtonApplyChapters": "チャプターを確定する",
|
||||
"ButtonAuthors": "作者",
|
||||
"ButtonBack": "戻る",
|
||||
"ButtonBrowseForFolder": "フォルダーを選択する",
|
||||
"ButtonCancel": "キャンセル",
|
||||
"ButtonCancelEncode": "エンコードを取り消す",
|
||||
"ButtonChangeRootPassword": "Rootのパスワードを変更する",
|
||||
"ButtonChooseAFolder": "フォルダーを選ぶ",
|
||||
"ButtonChooseFiles": "ファイルを選ぶ",
|
||||
"ButtonClearFilter": "絞り込みを解除",
|
||||
"ButtonClose": "閉じる",
|
||||
"ButtonCloseFeed": "フィードを閉じる",
|
||||
"ButtonCollections": "コレクション",
|
||||
"ButtonConfigureScanner": "スキャナーの設定",
|
||||
"ButtonCreate": "作成",
|
||||
"ButtonCreateBackup": "バックアップを作成する",
|
||||
"ButtonDelete": "削除",
|
||||
"ButtonDownloadQueue": "次に再生",
|
||||
"ButtonEdit": "編集",
|
||||
"ButtonEditChapters": "チャプターの編集",
|
||||
"ButtonEditPodcast": "ポッドキャストの編集",
|
||||
"ButtonEnable": "オンにする",
|
||||
"ButtonForceReScan": "強制的に再スキャンする",
|
||||
"ButtonFullPath": "絶対パス",
|
||||
"ButtonHide": "非表示",
|
||||
"ButtonHome": "ホーム",
|
||||
"ButtonJumpBackward": "巻き戻し",
|
||||
"ButtonJumpForward": "早送り",
|
||||
"ButtonLatest": "最新",
|
||||
"ButtonLibrary": "ライブラリー",
|
||||
"ButtonLogout": "ログアウト",
|
||||
"ButtonManageTracks": "トラックの管理",
|
||||
"ButtonNevermind": "中止",
|
||||
"ButtonNext": "次",
|
||||
"ButtonNextChapter": "次のチャプター",
|
||||
"ButtonOk": "はい",
|
||||
"ButtonPlay": "プレイ",
|
||||
"ButtonOpenFeed": "フィードを開く",
|
||||
"ButtonPause": "一時停止",
|
||||
"ButtonPlay": "再生",
|
||||
"ButtonPlayAll": "全て再生",
|
||||
"ButtonPlaying": "プレイ中",
|
||||
"ButtonPlaylists": "プレイリスト",
|
||||
"ButtonPrevious": "先",
|
||||
"ButtonRead": "野村",
|
||||
"ButtonPreviousChapter": "前のチャプター",
|
||||
"ButtonPurgeAllCache": "全てのキャッシュを削除",
|
||||
"ButtonPurgeItemsCache": "項目のキャッシュを削除",
|
||||
"ButtonQueueAddItem": "次に再生する",
|
||||
"ButtonQueueRemoveItem": "次に再生から削除",
|
||||
"ButtonQuickEmbed": "クイック埋め込み",
|
||||
"ButtonReScan": "再スキャン",
|
||||
"ButtonRead": "読む",
|
||||
"ButtonReadLess": "閉じる",
|
||||
"ButtonReadMore": "もっと見る",
|
||||
"ButtonRefresh": "再読み込み",
|
||||
"ButtonRemove": "削除",
|
||||
"ButtonRemoveAll": "全て削除",
|
||||
"ButtonRemoveAllLibraryItems": "ライブラリーの項目を全て削除",
|
||||
"ButtonReset": "元に戻す",
|
||||
"ButtonResetToDefault": "デフォルトに戻す",
|
||||
"ButtonRestore": "復元",
|
||||
"ButtonSave": "保存",
|
||||
"ButtonSaveAndClose": "保存して閉じる",
|
||||
"ButtonScan": "スキャン",
|
||||
"ButtonScanLibrary": "ライブラリーをスキャン",
|
||||
"ButtonScrollLeft": "左にスクロール",
|
||||
"ButtonScrollRight": "右にスクロール",
|
||||
"ButtonSearch": "検索",
|
||||
"ButtonSeries": "シリーズ",
|
||||
"ButtonYes": "はい",
|
||||
"HeaderAccount": "アカウント",
|
||||
"HeaderChapters": "チャプター",
|
||||
"HeaderCollection": "コレクション",
|
||||
"HeaderCollectionItems": "コレクションの項目",
|
||||
"HeaderDetails": "詳細",
|
||||
"HeaderEbookFiles": "電子書籍ファイル",
|
||||
"HeaderEpisodes": "エピソード",
|
||||
"HeaderEreaderSettings": "電子書籍リーダーの設定",
|
||||
"HeaderLatestEpisodes": "最新のエピソード",
|
||||
"HeaderLibraries": "ライブラリー",
|
||||
"HeaderPlayerSettings": "プレーヤーの設定",
|
||||
"HeaderSettingsGeneral": "一般",
|
||||
"HeaderSettingsScanner": "スキャナー",
|
||||
"LabelBooks": "ほん",
|
||||
"LabelContinueListening": "続きから聞く",
|
||||
"LabelLanguage": "言語",
|
||||
"LabelLanguages": "言語",
|
||||
"LabelName": "名",
|
||||
|
@ -17,5 +99,17 @@
|
|||
"LabelNewPassword": "新しいのパスワード",
|
||||
"LabelPassword": "パスワード",
|
||||
"LabelPlaylists": "プレイリスト",
|
||||
"LabelPodcast": "ポッドキャスト"
|
||||
"LabelPodcast": "ポッドキャスト",
|
||||
"LabelSettingsFindCovers": "表紙を探す",
|
||||
"LabelSettingsFindCoversHelp": "もしオーディオブックに表紙が埋め込まれていない、もしくは表紙画像がフォルダー内に見つからなければ、スキャナーは表紙を探そうとします。<br>注記: これによってスキャン時間が長くなります",
|
||||
"LabelSettingsParseSubtitles": "サブタイトルを抽出する",
|
||||
"LabelSettingsParseSubtitlesHelp": "オーディオブックのフォルダー名からサブタイトルを抽出します。<br>サブタイトルは \"-\" で区切ってください<br>例: \"本のタイトル - ここにサブタイトル\" という名前だと \"ここにサブタイトル\" というサブタイトルになります",
|
||||
"LabelSettingsPreferMatchedMetadata": "一致したメタデータを優先する",
|
||||
"LabelSettingsPreferMatchedMetadataHelp": "クイックマッチを使用する時、一致したデータは書籍の詳細を上書きします。デフォルトでは、埋まっていない項目のみ入力されます。",
|
||||
"LabelSettingsSortingIgnorePrefixes": "並び替えでプレフィックスを無視する",
|
||||
"LabelSettingsSortingIgnorePrefixesHelp": "例: プレフィックス \"the\" の付いた本のタイトル \"The Book Title\" は \"Book Title, The\" として並び替えられます",
|
||||
"LabelSettingsStoreCoversWithItem": "表紙を項目と一緒に保存する",
|
||||
"LabelSettingsStoreCoversWithItemHelp": "デフォルトでは表紙は /metadata/items に保存されますが、この設定をオンにするとライブラリーの項目のフォルダーに保存されます。\"cover\" という名前のファイル一つのみが保持されます",
|
||||
"LabelSettingsStoreMetadataWithItem": "メタデータを項目と一緒に保存する",
|
||||
"LabelSettingsStoreMetadataWithItemHelp": "デフォルトではメタデータは/metadata/itemsに保存されますが、この設定をオンにするとライブラリーの項目のフォルダーに保存されます"
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue