mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-11-07 08:34:10 +01:00
Merge master
This commit is contained in:
commit
36e00e8d6a
@ -338,9 +338,15 @@ export default {
|
||||
libraryItemsAdded(libraryItems) {
|
||||
console.log('libraryItems added', libraryItems)
|
||||
|
||||
const isThisLibrary = !libraryItems.some((li) => li.libraryId !== this.currentLibraryId)
|
||||
if (!this.search && isThisLibrary) {
|
||||
this.fetchCategories()
|
||||
const recentlyAddedShelf = this.shelves.find((shelf) => shelf.id === 'recently-added')
|
||||
if (!recentlyAddedShelf) return
|
||||
|
||||
// Add new library item to the recently added shelf
|
||||
for (const libraryItem of libraryItems) {
|
||||
if (libraryItem.libraryId === this.currentLibraryId && !recentlyAddedShelf.entities.some((ent) => ent.id === libraryItem.id)) {
|
||||
// Add to front of array
|
||||
recentlyAddedShelf.entities.unshift(libraryItem)
|
||||
}
|
||||
}
|
||||
},
|
||||
libraryItemsUpdated(items) {
|
||||
|
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<div id="authentication-settings">
|
||||
<app-settings-content :header-text="$strings.HeaderAuthentication">
|
||||
<div class="w-full border border-white/10 rounded-xl p-4 my-4 bg-primary/25">
|
||||
<div class="flex items-center">
|
||||
<ui-checkbox v-model="enableLocalAuth" checkbox-bg="bg" />
|
||||
<p class="text-lg pl-4">Password Authentication</p>
|
||||
<p class="text-lg pl-4">{{ $strings.HeaderPasswordAuthentication }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full border border-white/10 rounded-xl p-4 my-4 bg-primary/25">
|
||||
<div class="flex items-center">
|
||||
<ui-checkbox v-model="enableOpenIDAuth" checkbox-bg="bg" />
|
||||
<p class="text-lg pl-4">OpenID Connect Authentication</p>
|
||||
<p class="text-lg pl-4">{{ $strings.HeaderOpenIDConnectAuthentication }}</p>
|
||||
</div>
|
||||
|
||||
<transition name="slide">
|
||||
@ -41,25 +41,25 @@
|
||||
|
||||
<ui-text-input-with-label ref="openidClientSecret" v-model="newAuthSettings.authOpenIDClientSecret" :disabled="savingSettings" :label="'Client Secret'" class="mb-2" />
|
||||
|
||||
<ui-text-input-with-label ref="buttonTextInput" v-model="newAuthSettings.authOpenIDButtonText" :disabled="savingSettings" :label="'Button Text'" class="mb-2" />
|
||||
<ui-text-input-with-label ref="buttonTextInput" v-model="newAuthSettings.authOpenIDButtonText" :disabled="savingSettings" :label="$strings.LabelButtonText" class="mb-2" />
|
||||
|
||||
<div class="flex items-center pt-1 mb-2">
|
||||
<div class="w-44">
|
||||
<ui-dropdown v-model="newAuthSettings.authOpenIDMatchExistingBy" small :items="matchingExistingOptions" label="Match existing users by" :disabled="savingSettings" />
|
||||
<ui-dropdown v-model="newAuthSettings.authOpenIDMatchExistingBy" small :items="matchingExistingOptions" :label="$strings.LabelMatchExistingUsersBy" :disabled="savingSettings" />
|
||||
</div>
|
||||
<p class="pl-4 text-sm text-gray-300 mt-5">Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider</p>
|
||||
<p class="pl-4 text-sm text-gray-300 mt-5">{{ $strings.LabelMatchExistingUsersByDescription }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-4 px-1">
|
||||
<ui-toggle-switch labeledBy="auto-redirect-toggle" v-model="newAuthSettings.authOpenIDAutoLaunch" :disabled="savingSettings" />
|
||||
<p id="auto-redirect-toggle" class="pl-4">Auto Launch</p>
|
||||
<p class="pl-4 text-sm text-gray-300">Redirect to the auth provider automatically when navigating to the login page</p>
|
||||
<p id="auto-redirect-toggle" class="pl-4 whitespace-nowrap">{{ $strings.LabelAutoLaunch }}</p>
|
||||
<p class="pl-4 text-sm text-gray-300" v-html="$strings.LabelAutoLaunchDescription" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center py-4 px-1">
|
||||
<ui-toggle-switch labeledBy="auto-register-toggle" v-model="newAuthSettings.authOpenIDAutoRegister" :disabled="savingSettings" />
|
||||
<p id="auto-register-toggle" class="pl-4">Auto Register</p>
|
||||
<p class="pl-4 text-sm text-gray-300">Automatically create new users after logging in</p>
|
||||
<p id="auto-register-toggle" class="pl-4 whitespace-nowrap">{{ $strings.LabelAutoRegister }}</p>
|
||||
<p class="pl-4 text-sm text-gray-300">{{ $strings.LabelAutoRegisterDescription }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -227,3 +227,13 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#authentication-settings code {
|
||||
font-size: 0.8rem;
|
||||
border-radius: 6px;
|
||||
background-color: rgb(82, 82, 82);
|
||||
color: white;
|
||||
padding: 2px 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nový účet",
|
||||
"HeaderNewLibrary": "Nová knihovna",
|
||||
"HeaderNotifications": "Oznámení",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Otevřít RSS kanál",
|
||||
"HeaderOtherFiles": "Ostatní soubory",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Oprávnění",
|
||||
"HeaderPlayerQueue": "Fronta přehrávače",
|
||||
"HeaderPlaylist": "Seznam skladeb",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Autor (příjmení a jméno)",
|
||||
"LabelAuthors": "Autoři",
|
||||
"LabelAutoDownloadEpisodes": "Automaticky stahovat epizody",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Zpět k uživateli",
|
||||
"LabelBackupLocation": "Umístění zálohy",
|
||||
"LabelBackupsEnableAutomaticBackups": "Povolit automatické zálohování",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Najednou bude odstraněna pouze 1 záloha, takže pokud již máte více záloh, měli byste je odstranit ručně.",
|
||||
"LabelBitrate": "Datový tok",
|
||||
"LabelBooks": "Knihy",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Změnit heslo",
|
||||
"LabelChannels": "Kanály",
|
||||
"LabelChapters": "Kapitoly",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Varovat",
|
||||
"LabelLookForNewEpisodesAfterDate": "Hledat nové epizody po tomto datu",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Přehrávač médií",
|
||||
"LabelMediaType": "Typ média",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Ny Konto",
|
||||
"HeaderNewLibrary": "Nyt Bibliotek",
|
||||
"HeaderNotifications": "Meddelelser",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Åbn RSS Feed",
|
||||
"HeaderOtherFiles": "Andre Filer",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Tilladelser",
|
||||
"HeaderPlayerQueue": "Afspilningskø",
|
||||
"HeaderPlaylist": "Afspilningsliste",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Forfatter (Efternavn, Fornavn)",
|
||||
"LabelAuthors": "Forfattere",
|
||||
"LabelAutoDownloadEpisodes": "Auto Download Episoder",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Tilbage til Bruger",
|
||||
"LabelBackupLocation": "Backup Placering",
|
||||
"LabelBackupsEnableAutomaticBackups": "Aktivér automatisk sikkerhedskopiering",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Kun 1 sikkerhedskopi fjernes ad gangen, så hvis du allerede har flere sikkerhedskopier end dette, skal du fjerne dem manuelt.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Bøger",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Ændre Adgangskode",
|
||||
"LabelChannels": "Kanaler",
|
||||
"LabelChapters": "Kapitler",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Advarsel",
|
||||
"LabelLookForNewEpisodesAfterDate": "Søg efter nye episoder efter denne dato",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Medieafspiller",
|
||||
"LabelMediaType": "Medietype",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -92,7 +92,7 @@
|
||||
"HeaderAppriseNotificationSettings": "Apprise Benachrichtigungseinstellungen",
|
||||
"HeaderAudiobookTools": "Hörbuch-Dateiverwaltungstools",
|
||||
"HeaderAudioTracks": "Audiodateien",
|
||||
"HeaderAuthentication": "Authentication",
|
||||
"HeaderAuthentication": "Authentifizierung",
|
||||
"HeaderBackups": "Sicherungen",
|
||||
"HeaderChangePassword": "Passwort ändern",
|
||||
"HeaderChapters": "Kapitel",
|
||||
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Neues Konto",
|
||||
"HeaderNewLibrary": "Neue Bibliothek",
|
||||
"HeaderNotifications": "Benachrichtigungen",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentifizierung",
|
||||
"HeaderOpenRSSFeed": "RSS-Feed öffnen",
|
||||
"HeaderOtherFiles": "Sonstige Dateien",
|
||||
"HeaderPasswordAuthentication": "Password Authentifizierung",
|
||||
"HeaderPermissions": "Berechtigungen",
|
||||
"HeaderPlayerQueue": "Spieler Warteschlange",
|
||||
"HeaderPlaylist": "Wiedergabeliste",
|
||||
@ -182,11 +184,11 @@
|
||||
"LabelAddToCollectionBatch": "Füge {0} Hörbüch(er)/Podcast(s) der Sammlung hinzu",
|
||||
"LabelAddToPlaylist": "Zur Wiedergabeliste hinzufügen",
|
||||
"LabelAddToPlaylistBatch": "Füge {0} Hörbüch(er)/Podcast(s) der Wiedergabeliste hinzu",
|
||||
"LabelAdminUsersOnly": "Admin users only",
|
||||
"LabelAdminUsersOnly": "Nur Admin Benutzer",
|
||||
"LabelAll": "Alle",
|
||||
"LabelAllUsers": "Alle Benutzer",
|
||||
"LabelAllUsersExcludingGuests": "All users excluding guests",
|
||||
"LabelAllUsersIncludingGuests": "All users including guests",
|
||||
"LabelAllUsersExcludingGuests": "Alle Benutzer außer Gästen",
|
||||
"LabelAllUsersIncludingGuests": "All Benutzer und Gäste",
|
||||
"LabelAlreadyInYourLibrary": "In der Bibliothek vorhanden",
|
||||
"LabelAppend": "Anhängen",
|
||||
"LabelAuthor": "Autor",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Autor (Nachname, Vorname)",
|
||||
"LabelAuthors": "Autoren",
|
||||
"LabelAutoDownloadEpisodes": "Episoden automatisch herunterladen",
|
||||
"LabelAutoLaunch": "Automatischer Start",
|
||||
"LabelAutoLaunchDescription": "Automatische Weiterleitung zum Authentifizierungsanbieter beim Navigieren zur Anmeldeseite (manueller Überschreibungspfad <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Automatische Registrierung",
|
||||
"LabelAutoRegisterDescription": "Automatische neue Neutzer anlegen nach dem Einloggen",
|
||||
"LabelBackToUser": "Zurück zum Benutzer",
|
||||
"LabelBackupLocation": "Backup-Ort",
|
||||
"LabelBackupsEnableAutomaticBackups": "Automatische Sicherung aktivieren",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Es wird immer nur 1 Sicherung auf einmal entfernt. Wenn Sie bereits mehrere Sicherungen als die definierte max. Anzahl haben, sollten Sie diese manuell entfernen.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Bücher",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Passwort ändern",
|
||||
"LabelChannels": "Kanäle",
|
||||
"LabelChapters": "Kapitel",
|
||||
@ -233,7 +240,7 @@
|
||||
"LabelDeselectAll": "Alles abwählen",
|
||||
"LabelDevice": "Gerät",
|
||||
"LabelDeviceInfo": "Geräteinformationen",
|
||||
"LabelDeviceIsAvailableTo": "Device is available to...",
|
||||
"LabelDeviceIsAvailableTo": "Dem Geärt ist es möglich zu ...",
|
||||
"LabelDirectory": "Verzeichnis",
|
||||
"LabelDiscFromFilename": "CD aus dem Dateinamen",
|
||||
"LabelDiscFromMetadata": "CD aus den Metadaten",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warnungen",
|
||||
"LabelLookForNewEpisodesAfterDate": "Suchen nach neuen Episoden nach diesem Datum",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Zuordnen existierender Benutzer mit",
|
||||
"LabelMatchExistingUsersByDescription": "Wird zum Verbinden vorhandener Benutzer verwendet. Sobald die Verbindung hergestellt ist, wird den Benutzern eine eindeutige ID von Ihrem SSO-Anbieter zugeordnet",
|
||||
"LabelMediaPlayer": "Mediaplayer",
|
||||
"LabelMediaType": "Medientyp",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
@ -401,7 +410,7 @@
|
||||
"LabelSeason": "Staffel",
|
||||
"LabelSelectAllEpisodes": "Alle Episoden auswählen",
|
||||
"LabelSelectEpisodesShowing": "{0} ausgewählte Episoden werden angezeigt",
|
||||
"LabelSelectUsers": "Select users",
|
||||
"LabelSelectUsers": "Benutzer auswählen",
|
||||
"LabelSendEbookToDevice": "E-Book senden an...",
|
||||
"LabelSequence": "Reihenfolge",
|
||||
"LabelSeries": "Serien",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "New Account",
|
||||
"HeaderNewLibrary": "New Library",
|
||||
"HeaderNotifications": "Notifications",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Open RSS Feed",
|
||||
"HeaderOtherFiles": "Other Files",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Permissions",
|
||||
"HeaderPlayerQueue": "Player Queue",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Author (Last, First)",
|
||||
"LabelAuthors": "Authors",
|
||||
"LabelAutoDownloadEpisodes": "Auto Download Episodes",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Back to User",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Enable automatic backups",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Only 1 backup will be removed at a time so if you already have more backups than this you should manually remove them.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Books",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Change Password",
|
||||
"LabelChannels": "Channels",
|
||||
"LabelChapters": "Chapters",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Look for new episodes after this date",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Media Player",
|
||||
"LabelMediaType": "Media Type",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nueva Cuenta",
|
||||
"HeaderNewLibrary": "Nueva Biblioteca",
|
||||
"HeaderNotifications": "Notificaciones",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Abrir fuente RSS",
|
||||
"HeaderOtherFiles": "Otros Archivos",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Permisos",
|
||||
"HeaderPlayerQueue": "Fila del Reproductor",
|
||||
"HeaderPlaylist": "Lista de Reproducción",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Autor (Apellido, Nombre)",
|
||||
"LabelAuthors": "Autores",
|
||||
"LabelAutoDownloadEpisodes": "Descargar Episodios Automáticamente",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Regresar a Usuario",
|
||||
"LabelBackupLocation": "Ubicación del Respaldo",
|
||||
"LabelBackupsEnableAutomaticBackups": "Habilitar Respaldo Automático",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Solamente 1 respaldo se removerá a la vez. Si tiene mas respaldos guardados, debe removerlos manualmente.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Libros",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Cambiar Contraseña",
|
||||
"LabelChannels": "Canales",
|
||||
"LabelChapters": "Capítulos",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Advertencia",
|
||||
"LabelLookForNewEpisodesAfterDate": "Buscar Nuevos Episodios a partir de esta Fecha",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Reproductor de Medios",
|
||||
"LabelMediaType": "Tipo de Multimedia",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nouveau compte",
|
||||
"HeaderNewLibrary": "Nouvelle bibliothèque",
|
||||
"HeaderNotifications": "Notifications",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Ouvrir Flux RSS",
|
||||
"HeaderOtherFiles": "Autres fichiers",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Permissions",
|
||||
"HeaderPlayerQueue": "Liste d’écoute",
|
||||
"HeaderPlaylist": "Liste de lecture",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Auteur (Nom, Prénom)",
|
||||
"LabelAuthors": "Auteurs",
|
||||
"LabelAutoDownloadEpisodes": "Téléchargement automatique d’épisode",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Revenir à l’Utilisateur",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Activer les sauvegardes automatiques",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Une seule sauvegarde sera effacée à la fois. Si vous avez plus de sauvegardes à effacer, vous devrez le faire manuellement.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Livres",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Modifier le mot de passe",
|
||||
"LabelChannels": "Canaux",
|
||||
"LabelChapters": "Chapitres",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Chercher de nouveaux épisode après cette date",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Lecteur multimédia",
|
||||
"LabelMediaType": "Type de média",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "New Account",
|
||||
"HeaderNewLibrary": "New Library",
|
||||
"HeaderNotifications": "Notifications",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Open RSS Feed",
|
||||
"HeaderOtherFiles": "Other Files",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Permissions",
|
||||
"HeaderPlayerQueue": "Player Queue",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Author (Last, First)",
|
||||
"LabelAuthors": "Authors",
|
||||
"LabelAutoDownloadEpisodes": "Auto Download Episodes",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Back to User",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Enable automatic backups",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Only 1 backup will be removed at a time so if you already have more backups than this you should manually remove them.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Books",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Change Password",
|
||||
"LabelChannels": "Channels",
|
||||
"LabelChapters": "Chapters",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Look for new episodes after this date",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Media Player",
|
||||
"LabelMediaType": "Media Type",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "New Account",
|
||||
"HeaderNewLibrary": "New Library",
|
||||
"HeaderNotifications": "Notifications",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Open RSS Feed",
|
||||
"HeaderOtherFiles": "Other Files",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Permissions",
|
||||
"HeaderPlayerQueue": "Player Queue",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Author (Last, First)",
|
||||
"LabelAuthors": "Authors",
|
||||
"LabelAutoDownloadEpisodes": "Auto Download Episodes",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Back to User",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Enable automatic backups",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Only 1 backup will be removed at a time so if you already have more backups than this you should manually remove them.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Books",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Change Password",
|
||||
"LabelChannels": "Channels",
|
||||
"LabelChapters": "Chapters",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Look for new episodes after this date",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Media Player",
|
||||
"LabelMediaType": "Media Type",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Novi korisnički račun",
|
||||
"HeaderNewLibrary": "Nova biblioteka",
|
||||
"HeaderNotifications": "Obavijesti",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Otvori RSS Feed",
|
||||
"HeaderOtherFiles": "Druge datoteke",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Dozvole",
|
||||
"HeaderPlayerQueue": "Player Queue",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Author (Last, First)",
|
||||
"LabelAuthors": "Autori",
|
||||
"LabelAutoDownloadEpisodes": "Automatski preuzmi epizode",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Nazad k korisniku",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Uključi automatski backup",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Samo 1 backup će biti odjednom obrisan. Ako koristite više njih, morati ćete ih ručno ukloniti.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Knjige",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Promijeni lozinku",
|
||||
"LabelChannels": "Channels",
|
||||
"LabelChapters": "Chapters",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Traži nove epizode nakon ovog datuma",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Media Player",
|
||||
"LabelMediaType": "Media Type",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nuovo Account",
|
||||
"HeaderNewLibrary": "Nuova Libreria",
|
||||
"HeaderNotifications": "Notifiche",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Apri RSS Feed",
|
||||
"HeaderOtherFiles": "Altri File",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Permessi",
|
||||
"HeaderPlayerQueue": "Coda Riproduzione",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Autori (Per Cognome)",
|
||||
"LabelAuthors": "Autori",
|
||||
"LabelAutoDownloadEpisodes": "Auto Download Episodi",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Torna a Utenti",
|
||||
"LabelBackupLocation": "Percorso del Backup",
|
||||
"LabelBackupsEnableAutomaticBackups": "Abilita backup Automatico",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Verrà rimosso solo 1 backup alla volta, quindi se hai più backup, dovrai rimuoverli manualmente.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Libri",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Cambia Password",
|
||||
"LabelChannels": "Canali",
|
||||
"LabelChapters": "Capitoli",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Allarme",
|
||||
"LabelLookForNewEpisodesAfterDate": "Cerca nuovi episodi dopo questa data",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Media Player",
|
||||
"LabelMediaType": "Tipo Media",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nauja paskyra",
|
||||
"HeaderNewLibrary": "Nauja biblioteka",
|
||||
"HeaderNotifications": "Pranešimai",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Atidaryti RSS srautą",
|
||||
"HeaderOtherFiles": "Kiti failai",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Leidimai",
|
||||
"HeaderPlayerQueue": "Grotuvo eilė",
|
||||
"HeaderPlaylist": "Grojaraštis",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Autorius (Pavardė, Vardas)",
|
||||
"LabelAuthors": "Autoriai",
|
||||
"LabelAutoDownloadEpisodes": "Automatiškai atsisiųsti epizodus",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Grįžti į naudotoją",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Įjungti automatinį atsarginių kopijų kūrimą",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Tik viena atsarginė kopija bus pašalinta vienu metu, todėl jei jau turite daugiau atsarginių kopijų nei nurodyta, turite jas pašalinti rankiniu būdu.",
|
||||
"LabelBitrate": "Bitų sparta",
|
||||
"LabelBooks": "Knygos",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Pakeisti slaptažodį",
|
||||
"LabelChannels": "Kanalai",
|
||||
"LabelChapters": "Skyriai",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Ieškoti naujų epizodų po šios datos",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Grotuvas",
|
||||
"LabelMediaType": "Medijos tipas",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nieuwe account",
|
||||
"HeaderNewLibrary": "Nieuwe bibliotheek",
|
||||
"HeaderNotifications": "Notificaties",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Open RSS-feed",
|
||||
"HeaderOtherFiles": "Andere bestanden",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Toestemmingen",
|
||||
"HeaderPlayerQueue": "Afspeelwachtrij",
|
||||
"HeaderPlaylist": "Afspeellijst",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Auteur (Achternaam, Voornaam)",
|
||||
"LabelAuthors": "Auteurs",
|
||||
"LabelAutoDownloadEpisodes": "Afleveringen automatisch downloaden",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Terug naar gebruiker",
|
||||
"LabelBackupLocation": "Back-up locatie",
|
||||
"LabelBackupsEnableAutomaticBackups": "Automatische back-ups inschakelen",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Er wordt slechts 1 back-up per keer verwijderd, dus als je reeds meer back-ups dan dit hebt moet je ze handmatig verwijderen.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Boeken",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Wachtwoord wijzigen",
|
||||
"LabelChannels": "Kanalen",
|
||||
"LabelChapters": "Hoofdstukken",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Waarschuwing",
|
||||
"LabelLookForNewEpisodesAfterDate": "Zoek naar nieuwe afleveringen na deze datum",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Mediaspeler",
|
||||
"LabelMediaType": "Mediatype",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Ny konto",
|
||||
"HeaderNewLibrary": "Ny bibliotek",
|
||||
"HeaderNotifications": "Notifikasjoner",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Åpne RSS Feed",
|
||||
"HeaderOtherFiles": "Andre filer",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Rettigheter",
|
||||
"HeaderPlayerQueue": "Spiller kø",
|
||||
"HeaderPlaylist": "Spilleliste",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Forfatter (Etternavn Fornavn)",
|
||||
"LabelAuthors": "Forfattere",
|
||||
"LabelAutoDownloadEpisodes": "Last ned episoder automatisk",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Tilbake til bruker",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Aktiver automatisk sikkerhetskopi",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Kun 1 sikkerhetskopi vil bli fjernet om gangen, hvis du allerede har flere sikkerhetskopier enn dette bør du fjerne de manuelt.",
|
||||
"LabelBitrate": "Bithastighet",
|
||||
"LabelBooks": "Bøker",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Endre passord",
|
||||
"LabelChannels": "Kanaler",
|
||||
"LabelChapters": "Kapitler",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Se etter nye episoder etter denne datoen",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Mediespiller",
|
||||
"LabelMediaType": "Medie type",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nowe konto",
|
||||
"HeaderNewLibrary": "Nowa biblioteka",
|
||||
"HeaderNotifications": "Powiadomienia",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Utwórz kanał RSS",
|
||||
"HeaderOtherFiles": "Inne pliki",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Uprawnienia",
|
||||
"HeaderPlayerQueue": "Player Queue",
|
||||
"HeaderPlaylist": "Playlist",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Author (Malejąco)",
|
||||
"LabelAuthors": "Autorzy",
|
||||
"LabelAutoDownloadEpisodes": "Automatyczne pobieranie odcinków",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Powrót",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Włącz automatyczne kopie zapasowe",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Tylko 1 kopia zapasowa zostanie usunięta, więc jeśli masz już więcej kopii zapasowych, powinieneś je ręcznie usunąć.",
|
||||
"LabelBitrate": "Bitrate",
|
||||
"LabelBooks": "Książki",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Zmień hasło",
|
||||
"LabelChannels": "Channels",
|
||||
"LabelChapters": "Chapters",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Ostrzeżenie",
|
||||
"LabelLookForNewEpisodesAfterDate": "Szukaj nowych odcinków po dacie",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Odtwarzacz",
|
||||
"LabelMediaType": "Typ mediów",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Новая учетная запись",
|
||||
"HeaderNewLibrary": "Новая библиотека",
|
||||
"HeaderNotifications": "Уведомления",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Открыть RSS-канал",
|
||||
"HeaderOtherFiles": "Другие файлы",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Разрешения",
|
||||
"HeaderPlayerQueue": "Очередь воспроизведения",
|
||||
"HeaderPlaylist": "Плейлист",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Автор (Фамилия, Имя)",
|
||||
"LabelAuthors": "Авторы",
|
||||
"LabelAutoDownloadEpisodes": "Скачивать эпизоды автоматически",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Назад к пользователю",
|
||||
"LabelBackupLocation": "Backup Location",
|
||||
"LabelBackupsEnableAutomaticBackups": "Включить автоматическое бэкапирование",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "За один раз только 1 бэкап будет удален, так что если у вас будет больше бэкапов, то их нужно удалить вручную.",
|
||||
"LabelBitrate": "Битрейт",
|
||||
"LabelBooks": "Книги",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Изменить пароль",
|
||||
"LabelChannels": "Каналы",
|
||||
"LabelChapters": "Главы",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Warn",
|
||||
"LabelLookForNewEpisodesAfterDate": "Искать новые эпизоды после этой даты",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Медиа проигрыватель",
|
||||
"LabelMediaType": "Тип медиа",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "Nytt konto",
|
||||
"HeaderNewLibrary": "Nytt bibliotek",
|
||||
"HeaderNotifications": "Meddelanden",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "Öppna RSS-flöde",
|
||||
"HeaderOtherFiles": "Andra filer",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "Behörigheter",
|
||||
"HeaderPlayerQueue": "Spelarkö",
|
||||
"HeaderPlaylist": "Spellista",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "Författare (Efternamn, Förnamn)",
|
||||
"LabelAuthors": "Författare",
|
||||
"LabelAutoDownloadEpisodes": "Automatisk nedladdning av avsnitt",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "Tillbaka till användaren",
|
||||
"LabelBackupLocation": "Säkerhetskopia Plats",
|
||||
"LabelBackupsEnableAutomaticBackups": "Aktivera automatiska säkerhetskopior",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "Endast en säkerhetskopia tas bort åt gången, så om du redan har fler säkerhetskopior än detta bör du ta bort dem manuellt.",
|
||||
"LabelBitrate": "Bitfrekvens",
|
||||
"LabelBooks": "Böcker",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "Ändra lösenord",
|
||||
"LabelChannels": "Kanaler",
|
||||
"LabelChapters": "Kapitel",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "Felsökningsnivå: Varning",
|
||||
"LabelLookForNewEpisodesAfterDate": "Sök efter nya avsnitt efter detta datum",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "Mediaspelare",
|
||||
"LabelMediaType": "Mediatyp",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
@ -132,8 +132,10 @@
|
||||
"HeaderNewAccount": "新建帐户",
|
||||
"HeaderNewLibrary": "新建媒体库",
|
||||
"HeaderNotifications": "通知",
|
||||
"HeaderOpenIDConnectAuthentication": "OpenID Connect Authentication",
|
||||
"HeaderOpenRSSFeed": "打开 RSS 源",
|
||||
"HeaderOtherFiles": "其他文件",
|
||||
"HeaderPasswordAuthentication": "Password Authentication",
|
||||
"HeaderPermissions": "权限",
|
||||
"HeaderPlayerQueue": "播放队列",
|
||||
"HeaderPlaylist": "播放列表",
|
||||
@ -194,6 +196,10 @@
|
||||
"LabelAuthorLastFirst": "作者 (名, 姓)",
|
||||
"LabelAuthors": "作者",
|
||||
"LabelAutoDownloadEpisodes": "自动下载剧集",
|
||||
"LabelAutoLaunch": "Auto Launch",
|
||||
"LabelAutoLaunchDescription": "Redirect to the auth provider automatically when navigating to the login page (manual override path <code>/login?autoLaunch=0</code>)",
|
||||
"LabelAutoRegister": "Auto Register",
|
||||
"LabelAutoRegisterDescription": "Automatically create new users after logging in",
|
||||
"LabelBackToUser": "返回到用户",
|
||||
"LabelBackupLocation": "备份位置",
|
||||
"LabelBackupsEnableAutomaticBackups": "启用自动备份",
|
||||
@ -204,6 +210,7 @@
|
||||
"LabelBackupsNumberToKeepHelp": "一次只能删除一个备份, 因此如果你已经有超过此数量的备份, 则应手动删除它们.",
|
||||
"LabelBitrate": "比特率",
|
||||
"LabelBooks": "图书",
|
||||
"LabelButtonText": "Button Text",
|
||||
"LabelChangePassword": "修改密码",
|
||||
"LabelChannels": "声道",
|
||||
"LabelChapters": "章节",
|
||||
@ -319,6 +326,8 @@
|
||||
"LabelLogLevelWarn": "警告",
|
||||
"LabelLookForNewEpisodesAfterDate": "在此日期后查找新剧集",
|
||||
"LabelLowestPriority": "Lowest Priority",
|
||||
"LabelMatchExistingUsersBy": "Match existing users by",
|
||||
"LabelMatchExistingUsersByDescription": "Used for connecting existing users. Once connected, users will be matched by a unique id from your SSO provider",
|
||||
"LabelMediaPlayer": "媒体播放器",
|
||||
"LabelMediaType": "媒体类型",
|
||||
"LabelMetadataOrderOfPrecedenceDescription": "Higher priority metadata sources will override lower priority metadata sources",
|
||||
|
208
package-lock.json
generated
208
package-lock.json
generated
@ -15,6 +15,7 @@
|
||||
"express-session": "^1.17.3",
|
||||
"graceful-fs": "^4.2.10",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"lru-cache": "^10.0.3",
|
||||
"node-tone": "^1.0.1",
|
||||
"nodemailer": "^6.9.2",
|
||||
"openid-client": "^5.6.1",
|
||||
@ -603,6 +604,17 @@
|
||||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
@ -641,6 +653,18 @@
|
||||
"semver": "^7.3.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@npmcli/fs/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@npmcli/fs/node_modules/semver": {
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
|
||||
@ -1126,6 +1150,18 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/caching-transform": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
|
||||
@ -2619,6 +2655,18 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-lib-report/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-lib-report/node_modules/make-dir": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
|
||||
@ -2783,6 +2831,17 @@
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -2917,14 +2976,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.3.tgz",
|
||||
"integrity": "sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": "14 || >=16.14"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
@ -2976,6 +3032,18 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/make-fetch-happen/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
@ -3552,6 +3620,18 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp/node_modules/nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
@ -3841,6 +3921,17 @@
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/openid-client/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
@ -4386,6 +4477,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/sequelize/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/sequelize/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -5777,6 +5879,14 @@
|
||||
"tar": "^6.1.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
@ -5805,6 +5915,15 @@
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
|
||||
@ -6192,6 +6311,17 @@
|
||||
"ssri": "^8.0.1",
|
||||
"tar": "^6.0.2",
|
||||
"unique-filename": "^1.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"caching-transform": {
|
||||
@ -7291,6 +7421,15 @@
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
|
||||
@ -7408,6 +7547,14 @@
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -7529,12 +7676,9 @@
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.3.tgz",
|
||||
"integrity": "sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg=="
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "3.1.0",
|
||||
@ -7573,6 +7717,17 @@
|
||||
"promise-retry": "^2.0.1",
|
||||
"socks-proxy-agent": "^6.0.0",
|
||||
"ssri": "^8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"media-typer": {
|
||||
@ -8000,6 +8155,15 @@
|
||||
"wide-align": "^1.1.5"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
@ -8220,6 +8384,16 @@
|
||||
"lru-cache": "^6.0.0",
|
||||
"object-hash": "^2.2.0",
|
||||
"oidc-token-hash": "^5.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
@ -8588,6 +8762,14 @@
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
|
@ -42,6 +42,7 @@
|
||||
"express-session": "^1.17.3",
|
||||
"graceful-fs": "^4.2.10",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"lru-cache": "^10.0.3",
|
||||
"node-tone": "^1.0.1",
|
||||
"nodemailer": "^6.9.2",
|
||||
"openid-client": "^5.6.1",
|
||||
|
@ -566,6 +566,69 @@ class Auth {
|
||||
Source: global.Source
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} password
|
||||
* @param {*} user
|
||||
* @returns {boolean}
|
||||
*/
|
||||
comparePassword(password, user) {
|
||||
if (user.type === 'root' && !password && !user.pash) return true
|
||||
if (!password || !user.pash) return false
|
||||
return bcrypt.compare(password, user.pash)
|
||||
}
|
||||
|
||||
/**
|
||||
* User changes their password from request
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async userChangePassword(req, res) {
|
||||
let { password, newPassword } = req.body
|
||||
newPassword = newPassword || ''
|
||||
const matchingUser = req.user
|
||||
|
||||
// Only root can have an empty password
|
||||
if (matchingUser.type !== 'root' && !newPassword) {
|
||||
return res.json({
|
||||
error: 'Invalid new password - Only root can have an empty password'
|
||||
})
|
||||
}
|
||||
|
||||
// Check password match
|
||||
const compare = await this.comparePassword(password, matchingUser)
|
||||
if (!compare) {
|
||||
return res.json({
|
||||
error: 'Invalid password'
|
||||
})
|
||||
}
|
||||
|
||||
let pw = ''
|
||||
if (newPassword) {
|
||||
pw = await this.hashPass(newPassword)
|
||||
if (!pw) {
|
||||
return res.json({
|
||||
error: 'Hash failed'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
matchingUser.pash = pw
|
||||
|
||||
const success = await Database.updateUser(matchingUser)
|
||||
if (success) {
|
||||
Logger.info(`[Auth] User "${matchingUser.username}" changed password`)
|
||||
res.json({
|
||||
success: true
|
||||
})
|
||||
} else {
|
||||
res.json({
|
||||
error: 'Unknown error'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Auth
|
@ -5,6 +5,7 @@ class Logger {
|
||||
constructor() {
|
||||
this.isDev = process.env.NODE_ENV !== 'production'
|
||||
this.logLevel = !this.isDev ? LogLevel.INFO : LogLevel.TRACE
|
||||
this.hideDevLogs = process.env.HIDE_DEV_LOGS === undefined ? !this.isDev : process.env.HIDE_DEV_LOGS === '1'
|
||||
this.socketListeners = []
|
||||
|
||||
this.logManager = null
|
||||
@ -92,7 +93,7 @@ class Logger {
|
||||
* @param {...any} args
|
||||
*/
|
||||
dev(...args) {
|
||||
if (!this.isDev || process.env.HIDE_DEV_LOGS === '1') return
|
||||
if (this.hideDevLogs) return
|
||||
console.log(`[${this.timestamp}] DEV:`, ...args)
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,13 @@ const PodcastManager = require('./managers/PodcastManager')
|
||||
const AudioMetadataMangaer = require('./managers/AudioMetadataManager')
|
||||
const RssFeedManager = require('./managers/RssFeedManager')
|
||||
const CronManager = require('./managers/CronManager')
|
||||
const ApiCacheManager = require('./managers/ApiCacheManager')
|
||||
const LibraryScanner = require('./scanner/LibraryScanner')
|
||||
|
||||
//Import the main Passport and Express-Session library
|
||||
const passport = require('passport')
|
||||
const expressSession = require('express-session')
|
||||
|
||||
|
||||
class Server {
|
||||
constructor(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH, ROUTER_BASE_PATH) {
|
||||
this.Port = PORT
|
||||
@ -73,6 +73,7 @@ class Server {
|
||||
this.audioMetadataManager = new AudioMetadataMangaer()
|
||||
this.rssFeedManager = new RssFeedManager()
|
||||
this.cronManager = new CronManager(this.podcastManager)
|
||||
this.apiCacheManager = new ApiCacheManager()
|
||||
|
||||
// Routers
|
||||
this.apiRouter = new ApiRouter(this)
|
||||
@ -117,6 +118,7 @@ class Server {
|
||||
|
||||
const libraries = await Database.libraryModel.getAllOldLibraries()
|
||||
await this.cronManager.init(libraries)
|
||||
this.apiCacheManager.init()
|
||||
|
||||
if (Database.serverSettings.scannerDisableWatcher) {
|
||||
Logger.info(`[Server] Watcher is disabled`)
|
||||
@ -138,11 +140,13 @@ class Server {
|
||||
* The mobile app ereader is using fetch api in Capacitor that is currently difficult to switch to native requests
|
||||
* so we have to allow cors for specific origins to the /api/items/:id/ebook endpoint
|
||||
* @see https://ionicframework.com/docs/troubleshooting/cors
|
||||
*
|
||||
* Running in development allows cors to allow testing the mobile apps in the browser
|
||||
*/
|
||||
app.use((req, res, next) => {
|
||||
if (req.path.match(/\/api\/items\/([a-z0-9-]{36})\/ebook(\/[0-9]+)?/)) {
|
||||
if (Logger.isDev || req.path.match(/\/api\/items\/([a-z0-9-]{36})\/ebook(\/[0-9]+)?/)) {
|
||||
const allowedOrigins = ['capacitor://localhost', 'http://localhost']
|
||||
if (allowedOrigins.some(o => o === req.get('origin'))) {
|
||||
if (Logger.isDev || allowedOrigins.some(o => o === req.get('origin'))) {
|
||||
res.header('Access-Control-Allow-Origin', req.get('origin'))
|
||||
res.header("Access-Control-Allow-Methods", 'GET, POST, PATCH, PUT, DELETE, OPTIONS')
|
||||
res.header('Access-Control-Allow-Headers', '*')
|
||||
|
@ -192,9 +192,9 @@ class SocketAuthority {
|
||||
|
||||
this.adminEmitter('user_online', client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions))
|
||||
|
||||
// Update user lastSeen
|
||||
// Update user lastSeen without firing sequelize bulk update hooks
|
||||
user.lastSeen = Date.now()
|
||||
await Database.updateUser(user)
|
||||
await Database.userModel.updateFromOld(user, false)
|
||||
|
||||
const initialPayload = {
|
||||
userId: client.user.id,
|
||||
|
54
server/managers/ApiCacheManager.js
Normal file
54
server/managers/ApiCacheManager.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { LRUCache } = require('lru-cache')
|
||||
const Logger = require('../Logger')
|
||||
const Database = require('../Database')
|
||||
|
||||
class ApiCacheManager {
|
||||
|
||||
defaultCacheOptions = { max: 1000, maxSize: 10 * 1000 * 1000, sizeCalculation: item => (item.body.length + JSON.stringify(item.headers).length) }
|
||||
defaultTtlOptions = { ttl: 30 * 60 * 1000 }
|
||||
|
||||
constructor(cache = new LRUCache(this.defaultCacheOptions), ttlOptions = this.defaultTtlOptions) {
|
||||
this.cache = cache
|
||||
this.ttlOptions = ttlOptions
|
||||
}
|
||||
|
||||
init(database = Database) {
|
||||
let hooks = ['afterCreate', 'afterUpdate', 'afterDestroy', 'afterBulkCreate', 'afterBulkUpdate', 'afterBulkDestroy']
|
||||
hooks.forEach(hook => database.sequelize.addHook(hook, (model) => this.clear(model, hook)))
|
||||
}
|
||||
|
||||
clear(model, hook) {
|
||||
Logger.debug(`[ApiCacheManager] ${model.constructor.name}.${hook}: Clearing cache`)
|
||||
this.cache.clear()
|
||||
}
|
||||
|
||||
get middleware() {
|
||||
return (req, res, next) => {
|
||||
const key = { user: req.user.username, url: req.url }
|
||||
const stringifiedKey = JSON.stringify(key)
|
||||
Logger.debug(`[ApiCacheManager] count: ${this.cache.size} size: ${this.cache.calculatedSize}`)
|
||||
const cached = this.cache.get(stringifiedKey)
|
||||
if (cached) {
|
||||
Logger.debug(`[ApiCacheManager] Cache hit: ${stringifiedKey}`)
|
||||
res.set(cached.headers)
|
||||
res.status(cached.statusCode)
|
||||
res.send(cached.body)
|
||||
return
|
||||
}
|
||||
res.originalSend = res.send
|
||||
res.send = (body) => {
|
||||
Logger.debug(`[ApiCacheManager] Cache miss: ${stringifiedKey}`)
|
||||
const cached = { body, headers: res.getHeaders(), statusCode: res.statusCode }
|
||||
if (key.url.search(/^\/libraries\/.*?\/personalized/) !== -1) {
|
||||
Logger.debug(`[ApiCacheManager] Caching with ${this.ttlOptions.ttl} ms TTL`)
|
||||
this.cache.set(stringifiedKey, cached, this.ttlOptions)
|
||||
} else {
|
||||
this.cache.set(stringifiedKey, cached)
|
||||
}
|
||||
res.originalSend(body)
|
||||
}
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = ApiCacheManager
|
@ -99,11 +99,13 @@ class User extends Model {
|
||||
* Update User from old user model
|
||||
*
|
||||
* @param {oldUser} oldUser
|
||||
* @param {boolean} [hooks=true] Run before / after bulk update hooks?
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
static updateFromOld(oldUser) {
|
||||
static updateFromOld(oldUser, hooks = true) {
|
||||
const user = this.getFromOld(oldUser)
|
||||
return this.update(user, {
|
||||
hooks: !!hooks,
|
||||
where: {
|
||||
id: user.id
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ class ApiRouter {
|
||||
this.cronManager = Server.cronManager
|
||||
this.notificationManager = Server.notificationManager
|
||||
this.emailManager = Server.emailManager
|
||||
this.apiCacheManager = Server.apiCacheManager
|
||||
|
||||
this.router = express()
|
||||
this.router.disable('x-powered-by')
|
||||
@ -58,6 +59,7 @@ class ApiRouter {
|
||||
//
|
||||
// Library Routes
|
||||
//
|
||||
this.router.get(/^\/libraries/, this.apiCacheManager.middleware)
|
||||
this.router.post('/libraries', LibraryController.create.bind(this))
|
||||
this.router.get('/libraries', LibraryController.findAll.bind(this))
|
||||
this.router.get('/libraries/:id', LibraryController.middleware.bind(this), LibraryController.findOne.bind(this))
|
||||
|
97
test/server/managers/ApiCacheManager.test.js
Normal file
97
test/server/managers/ApiCacheManager.test.js
Normal file
@ -0,0 +1,97 @@
|
||||
// Import dependencies and modules for testing
|
||||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
const ApiCacheManager = require('../../../server/managers/ApiCacheManager')
|
||||
|
||||
describe('ApiCacheManager', () => {
|
||||
let cache
|
||||
let req
|
||||
let res
|
||||
let next
|
||||
let manager
|
||||
|
||||
beforeEach(() => {
|
||||
cache = { get: sinon.stub(), set: sinon.spy() }
|
||||
req = { user: { username: 'testUser' }, url: '/test-url' }
|
||||
res = { send: sinon.spy(), getHeaders: sinon.stub(), statusCode: 200, status: sinon.spy(), set: sinon.spy() }
|
||||
next = sinon.spy()
|
||||
})
|
||||
|
||||
describe('middleware', () => {
|
||||
it('should send cached data if available', () => {
|
||||
// Arrange
|
||||
const cachedData = { body: 'cached data', headers: { 'content-type': 'application/json' }, statusCode: 200 }
|
||||
cache.get.returns(cachedData)
|
||||
const key = JSON.stringify({ user: req.user.username, url: req.url })
|
||||
manager = new ApiCacheManager(cache)
|
||||
|
||||
// Act
|
||||
manager.middleware(req, res, next)
|
||||
|
||||
// Assert
|
||||
expect(cache.get.calledOnce).to.be.true
|
||||
expect(cache.get.calledWith(key)).to.be.true
|
||||
expect(res.set.calledOnce).to.be.true
|
||||
expect(res.set.calledWith(cachedData.headers)).to.be.true
|
||||
expect(res.status.calledOnce).to.be.true
|
||||
expect(res.status.calledWith(cachedData.statusCode)).to.be.true
|
||||
expect(res.send.calledOnce).to.be.true
|
||||
expect(res.send.calledWith(cachedData.body)).to.be.true
|
||||
expect(res.originalSend).to.be.undefined
|
||||
expect(next.called).to.be.false
|
||||
expect(cache.set.called).to.be.false
|
||||
})
|
||||
|
||||
it('should cache and send response if data is not cached', () => {
|
||||
// Arrange
|
||||
cache.get.returns(null)
|
||||
const headers = { 'content-type': 'application/json' }
|
||||
res.getHeaders.returns(headers)
|
||||
const body = 'response data'
|
||||
const statusCode = 200
|
||||
const responseData = { body, headers, statusCode }
|
||||
const key = JSON.stringify({ user: req.user.username, url: req.url })
|
||||
manager = new ApiCacheManager(cache)
|
||||
|
||||
// Act
|
||||
manager.middleware(req, res, next)
|
||||
res.send(body)
|
||||
|
||||
// Assert
|
||||
expect(cache.get.calledOnce).to.be.true
|
||||
expect(cache.get.calledWith(key)).to.be.true
|
||||
expect(next.calledOnce).to.be.true
|
||||
expect(cache.set.calledOnce).to.be.true
|
||||
expect(cache.set.calledWith(key, responseData)).to.be.true
|
||||
expect(res.originalSend.calledOnce).to.be.true
|
||||
expect(res.originalSend.calledWith(body)).to.be.true
|
||||
})
|
||||
|
||||
it('should cache personalized response with 30 minutes TTL', () => {
|
||||
// Arrange
|
||||
cache.get.returns(null)
|
||||
const headers = { 'content-type': 'application/json' }
|
||||
res.getHeaders.returns(headers)
|
||||
const body = 'personalized data'
|
||||
const statusCode = 200
|
||||
const responseData = { body, headers, statusCode }
|
||||
req.url = '/libraries/id/personalized'
|
||||
const key = JSON.stringify({ user: req.user.username, url: req.url })
|
||||
const ttlOptions = { ttl: 30 * 60 * 1000 }
|
||||
manager = new ApiCacheManager(cache, ttlOptions)
|
||||
|
||||
// Act
|
||||
manager.middleware(req, res, next)
|
||||
res.send(body)
|
||||
|
||||
// Assert
|
||||
expect(cache.get.calledOnce).to.be.true
|
||||
expect(cache.get.calledWith(key)).to.be.true
|
||||
expect(next.calledOnce).to.be.true
|
||||
expect(cache.set.calledOnce).to.be.true
|
||||
expect(cache.set.calledWith(key, responseData, ttlOptions)).to.be.true
|
||||
expect(res.originalSend.calledOnce).to.be.true
|
||||
expect(res.originalSend.calledWith(body)).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user