diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 55b67d815..c0469d10a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ variables: testsFolder: './_tests' yarnCacheFolder: $(Pipeline.Workspace)/.yarn nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages - majorVersion: '2.1.0' + majorVersion: '2.1.6' minorVersion: $[counter('minorVersion', 1076)] lidarrVersion: '$(majorVersion).$(minorVersion)' buildName: '$(Build.SourceBranchName).$(lidarrVersion)' diff --git a/frontend/babel.config.js b/frontend/babel.config.js index 5c0d5ecdc..ade9f24a2 100644 --- a/frontend/babel.config.js +++ b/frontend/babel.config.js @@ -2,6 +2,8 @@ const loose = true; module.exports = { plugins: [ + '@babel/plugin-transform-logical-assignment-operators', + // Stage 1 '@babel/plugin-proposal-export-default-from', ['@babel/plugin-transform-optional-chaining', { loose }], diff --git a/frontend/src/Activity/History/HistoryEventTypeCell.js b/frontend/src/Activity/History/HistoryEventTypeCell.js index cc0495d67..937cedd98 100644 --- a/frontend/src/Activity/History/HistoryEventTypeCell.js +++ b/frontend/src/Activity/History/HistoryEventTypeCell.js @@ -3,9 +3,10 @@ import React from 'react'; import Icon from 'Components/Icon'; import TableRowCell from 'Components/Table/Cells/TableRowCell'; import { icons, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './HistoryEventTypeCell.css'; -function getIconName(eventType) { +function getIconName(eventType, data) { switch (eventType) { case 'grabbed': return icons.DOWNLOADING; @@ -16,7 +17,7 @@ function getIconName(eventType) { case 'downloadFailed': return icons.DOWNLOADING; case 'trackFileDeleted': - return icons.DELETE; + return data.reason === 'MissingFromDisk' ? icons.FILE_MISSING : icons.DELETE; case 'trackFileRenamed': return icons.ORGANIZE; case 'trackFileRetagged': @@ -54,11 +55,11 @@ function getTooltip(eventType, data) { case 'downloadFailed': return 'Album download failed'; case 'trackFileDeleted': - return 'Track file deleted'; + return data.reason === 'MissingFromDisk' ? translate('TrackFileMissingTooltip') : translate('TrackFileDeletedTooltip'); case 'trackFileRenamed': - return 'Track file renamed'; + return translate('TrackFileRenamedTooltip'); case 'trackFileRetagged': - return 'Track file tags updated'; + return translate('TrackFileTagsUpdatedTooltip'); case 'albumImportIncomplete': return 'Files downloaded but not all could be imported'; case 'downloadImported': @@ -71,7 +72,7 @@ function getTooltip(eventType, data) { } function HistoryEventTypeCell({ eventType, data }) { - const iconName = getIconName(eventType); + const iconName = getIconName(eventType, data); const iconKind = getIconKind(eventType); const tooltip = getTooltip(eventType, data); diff --git a/frontend/src/Activity/Queue/Queue.js b/frontend/src/Activity/Queue/Queue.js index fd500c967..0efc29f21 100644 --- a/frontend/src/Activity/Queue/Queue.js +++ b/frontend/src/Activity/Queue/Queue.js @@ -25,7 +25,7 @@ import toggleSelected from 'Utilities/Table/toggleSelected'; import QueueFilterModal from './QueueFilterModal'; import QueueOptionsConnector from './QueueOptionsConnector'; import QueueRowConnector from './QueueRowConnector'; -import RemoveQueueItemsModal from './RemoveQueueItemsModal'; +import RemoveQueueItemModal from './RemoveQueueItemModal'; class Queue extends Component { @@ -309,9 +309,16 @@ class Queue extends Component { } - { + const item = items.find((i) => i.id === id); + + return !!(item && item.downloadClientHasPostImportCategory); + }) + )} canIgnore={isConfirmRemoveModalOpen && ( selectedIds.every((id) => { const item = items.find((i) => i.id === id); @@ -319,7 +326,7 @@ class Queue extends Component { return !!(item && item.artistId && item.albumId); }) )} - allPending={isConfirmRemoveModalOpen && ( + pending={isConfirmRemoveModalOpen && ( selectedIds.every((id) => { const item = items.find((i) => i.id === id); diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js index 4c2829f55..d0f1fbacf 100644 --- a/frontend/src/Activity/Queue/QueueRow.js +++ b/frontend/src/Activity/Queue/QueueRow.js @@ -98,8 +98,10 @@ class QueueRow extends Component { indexer, outputPath, downloadClient, + downloadClientHasPostImportCategory, downloadForced, estimatedCompletionTime, + added, timeleft, size, sizeleft, @@ -328,6 +330,15 @@ class QueueRow extends Component { ); } + if (name === 'added') { + return ( + + ); + } + if (name === 'actions') { return ( { - this.setState({ removeFromClient: value }); - }; - - onBlocklistChange = ({ value }) => { - this.setState({ blocklist: value }); - }; - - onSkipRedownloadChange = ({ value }) => { - this.setState({ skipRedownload: value }); - }; - - onRemoveConfirmed = () => { - const state = this.state; - - this.resetState(); - this.props.onRemovePress(state); - }; - - onModalClose = () => { - this.resetState(); - this.props.onModalClose(); - }; - - // - // Render - - render() { - const { - isOpen, - sourceTitle, - canIgnore, - isPending - } = this.props; - - const { removeFromClient, blocklist, skipRedownload } = this.state; - - return ( - - - - Remove - {sourceTitle} - - - -
- Are you sure you want to remove '{sourceTitle}' from the queue? -
- - { - isPending ? - null : - - {translate('RemoveFromDownloadClient')} - - - - } - - - - {translate('BlocklistRelease')} - - - - - - { - blocklist && - - - {translate('SkipRedownload')} - - - - } - -
- - - - - - -
-
- ); - } -} - -RemoveQueueItemModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - sourceTitle: PropTypes.string.isRequired, - canIgnore: PropTypes.bool.isRequired, - isPending: PropTypes.bool.isRequired, - onRemovePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default RemoveQueueItemModal; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.tsx b/frontend/src/Activity/Queue/RemoveQueueItemModal.tsx new file mode 100644 index 000000000..2502c8226 --- /dev/null +++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.tsx @@ -0,0 +1,230 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import FormGroup from 'Components/Form/FormGroup'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import Button from 'Components/Link/Button'; +import Modal from 'Components/Modal/Modal'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import { inputTypes, kinds, sizes } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; +import styles from './RemoveQueueItemModal.css'; + +interface RemovePressProps { + removeFromClient: boolean; + changeCategory: boolean; + blocklist: boolean; + skipRedownload: boolean; +} + +interface RemoveQueueItemModalProps { + isOpen: boolean; + sourceTitle: string; + canChangeCategory: boolean; + canIgnore: boolean; + isPending: boolean; + selectedCount?: number; + onRemovePress(props: RemovePressProps): void; + onModalClose: () => void; +} + +type RemovalMethod = 'removeFromClient' | 'changeCategory' | 'ignore'; +type BlocklistMethod = + | 'doNotBlocklist' + | 'blocklistAndSearch' + | 'blocklistOnly'; + +function RemoveQueueItemModal(props: RemoveQueueItemModalProps) { + const { + isOpen, + sourceTitle, + canIgnore, + canChangeCategory, + isPending, + selectedCount, + onRemovePress, + onModalClose, + } = props; + + const multipleSelected = selectedCount && selectedCount > 1; + + const [removalMethod, setRemovalMethod] = + useState('removeFromClient'); + const [blocklistMethod, setBlocklistMethod] = + useState('doNotBlocklist'); + + const { title, message } = useMemo(() => { + if (!selectedCount) { + return { + title: translate('RemoveQueueItem', { sourceTitle }), + message: translate('RemoveQueueItemConfirmation', { sourceTitle }), + }; + } + + if (selectedCount === 1) { + return { + title: translate('RemoveSelectedItem'), + message: translate('RemoveSelectedItemQueueMessageText'), + }; + } + + return { + title: translate('RemoveSelectedItems'), + message: translate('RemoveSelectedItemsQueueMessageText', { + selectedCount, + }), + }; + }, [sourceTitle, selectedCount]); + + const removalMethodOptions = useMemo(() => { + return [ + { + key: 'removeFromClient', + value: translate('RemoveFromDownloadClient'), + hint: multipleSelected + ? translate('RemoveMultipleFromDownloadClientHint') + : translate('RemoveFromDownloadClientHint'), + }, + { + key: 'changeCategory', + value: translate('ChangeCategory'), + isDisabled: !canChangeCategory, + hint: multipleSelected + ? translate('ChangeCategoryMultipleHint') + : translate('ChangeCategoryHint'), + }, + { + key: 'ignore', + value: multipleSelected + ? translate('IgnoreDownloads') + : translate('IgnoreDownload'), + isDisabled: !canIgnore, + hint: multipleSelected + ? translate('IgnoreDownloadsHint') + : translate('IgnoreDownloadHint'), + }, + ]; + }, [canChangeCategory, canIgnore, multipleSelected]); + + const blocklistMethodOptions = useMemo(() => { + return [ + { + key: 'doNotBlocklist', + value: translate('DoNotBlocklist'), + hint: translate('DoNotBlocklistHint'), + }, + { + key: 'blocklistAndSearch', + value: translate('BlocklistAndSearch'), + hint: multipleSelected + ? translate('BlocklistAndSearchMultipleHint') + : translate('BlocklistAndSearchHint'), + }, + { + key: 'blocklistOnly', + value: translate('BlocklistOnly'), + hint: multipleSelected + ? translate('BlocklistMultipleOnlyHint') + : translate('BlocklistOnlyHint'), + }, + ]; + }, [multipleSelected]); + + const handleRemovalMethodChange = useCallback( + ({ value }: { value: RemovalMethod }) => { + setRemovalMethod(value); + }, + [setRemovalMethod] + ); + + const handleBlocklistMethodChange = useCallback( + ({ value }: { value: BlocklistMethod }) => { + setBlocklistMethod(value); + }, + [setBlocklistMethod] + ); + + const handleConfirmRemove = useCallback(() => { + onRemovePress({ + removeFromClient: removalMethod === 'removeFromClient', + changeCategory: removalMethod === 'changeCategory', + blocklist: blocklistMethod !== 'doNotBlocklist', + skipRedownload: blocklistMethod === 'blocklistOnly', + }); + + setRemovalMethod('removeFromClient'); + setBlocklistMethod('doNotBlocklist'); + }, [ + removalMethod, + blocklistMethod, + setRemovalMethod, + setBlocklistMethod, + onRemovePress, + ]); + + const handleModalClose = useCallback(() => { + setRemovalMethod('removeFromClient'); + setBlocklistMethod('doNotBlocklist'); + + onModalClose(); + }, [setRemovalMethod, setBlocklistMethod, onModalClose]); + + return ( + + + {title} + + +
{message}
+ + {isPending ? null : ( + + {translate('RemoveQueueItemRemovalMethod')} + + + + )} + + + + {multipleSelected + ? translate('BlocklistReleases') + : translate('BlocklistRelease')} + + + + +
+ + + + + + +
+
+ ); +} + +export default RemoveQueueItemModal; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js deleted file mode 100644 index f607161b0..000000000 --- a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js +++ /dev/null @@ -1,176 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './RemoveQueueItemsModal.css'; - -class RemoveQueueItemsModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - removeFromClient: true, - blocklist: false, - skipRedownload: false - }; - } - - // - // Control - - resetState = function() { - this.setState({ - removeFromClient: true, - blocklist: false, - skipRedownload: false - }); - }; - - // - // Listeners - - onRemoveFromClientChange = ({ value }) => { - this.setState({ removeFromClient: value }); - }; - - onBlocklistChange = ({ value }) => { - this.setState({ blocklist: value }); - }; - - onSkipRedownloadChange = ({ value }) => { - this.setState({ skipRedownload: value }); - }; - - onRemoveConfirmed = () => { - const state = this.state; - - this.resetState(); - this.props.onRemovePress(state); - }; - - onModalClose = () => { - this.resetState(); - this.props.onModalClose(); - }; - - // - // Render - - render() { - const { - isOpen, - selectedCount, - canIgnore, - allPending - } = this.props; - - const { removeFromClient, blocklist, skipRedownload } = this.state; - - return ( - - - - {selectedCount > 1 ? translate('RemoveSelectedItems') : translate('RemoveSelectedItem')} - - - -
- {selectedCount > 1 ? translate('RemoveSelectedItemsQueueMessageText', [selectedCount]) : translate('RemoveSelectedItemQueueMessageText')} -
- - { - allPending ? - null : - - {translate('RemoveFromDownloadClient')} - - - - } - - - - {selectedCount > 1 ? translate('BlocklistReleases') : translate('BlocklistRelease')} - - - - - - { - blocklist && - - - {translate('SkipRedownload')} - - - - } - -
- - - - - - -
-
- ); - } -} - -RemoveQueueItemsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - selectedCount: PropTypes.number.isRequired, - canIgnore: PropTypes.bool.isRequired, - allPending: PropTypes.bool.isRequired, - onRemovePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default RemoveQueueItemsModal; diff --git a/frontend/src/Album/Delete/DeleteAlbumModalContent.js b/frontend/src/Album/Delete/DeleteAlbumModalContent.js index c637c3dd4..e45985c97 100644 --- a/frontend/src/Album/Delete/DeleteAlbumModalContent.js +++ b/frontend/src/Album/Delete/DeleteAlbumModalContent.js @@ -58,8 +58,8 @@ class DeleteAlbumModalContent extends Component { } = this.props; const { - trackFileCount, - sizeOnDisk + trackFileCount = 0, + sizeOnDisk = 0 } = statistics; const deleteFiles = this.state.deleteFiles; @@ -133,14 +133,14 @@ class DeleteAlbumModalContent extends Component { diff --git a/frontend/src/Album/Details/AlbumDetails.css b/frontend/src/Album/Details/AlbumDetails.css index dd6626c96..d87920074 100644 --- a/frontend/src/Album/Details/AlbumDetails.css +++ b/frontend/src/Album/Details/AlbumDetails.css @@ -119,6 +119,7 @@ margin: 5px 10px 5px 0; } +.releaseDate, .sizeOnDisk, .qualityProfileName, .links, @@ -147,6 +148,12 @@ .headerContent { padding: 15px; } + + .title { + font-weight: 300; + font-size: 30px; + line-height: 30px; + } } @media only screen and (max-width: $breakpointLarge) { diff --git a/frontend/src/Album/Details/AlbumDetails.css.d.ts b/frontend/src/Album/Details/AlbumDetails.css.d.ts index 82ef9f0e0..4c126c8b5 100644 --- a/frontend/src/Album/Details/AlbumDetails.css.d.ts +++ b/frontend/src/Album/Details/AlbumDetails.css.d.ts @@ -19,6 +19,7 @@ interface CssExports { 'monitorToggleButton': string; 'overview': string; 'qualityProfileName': string; + 'releaseDate': string; 'sizeOnDisk': string; 'tags': string; 'title': string; diff --git a/frontend/src/Album/Details/AlbumDetails.js b/frontend/src/Album/Details/AlbumDetails.js index a23237bd9..783216a61 100644 --- a/frontend/src/Album/Details/AlbumDetails.js +++ b/frontend/src/Album/Details/AlbumDetails.js @@ -9,6 +9,7 @@ import EditAlbumModalConnector from 'Album/Edit/EditAlbumModalConnector'; import AlbumInteractiveSearchModalConnector from 'Album/Search/AlbumInteractiveSearchModalConnector'; import ArtistGenres from 'Artist/Details/ArtistGenres'; import ArtistHistoryModal from 'Artist/History/ArtistHistoryModal'; +import Alert from 'Components/Alert'; import HeartRating from 'Components/HeartRating'; import Icon from 'Components/Icon'; import Label from 'Components/Label'; @@ -215,8 +216,8 @@ class AlbumDetails extends Component { } = this.props; const { - trackFileCount, - sizeOnDisk + trackFileCount = 0, + sizeOnDisk = 0 } = statistics; const { @@ -414,6 +415,7 @@ class AlbumDetails extends Component { @@ -465,7 +465,7 @@ class AlbumDetails extends Component { /> - {monitored ? 'Monitored' : 'Unmonitored'} + {monitored ? translate('Monitored') : translate('Unmonitored')} @@ -499,7 +499,7 @@ class AlbumDetails extends Component { /> - Links + {translate('Links')} } @@ -531,23 +531,24 @@ class AlbumDetails extends Component { } { - !isFetching && albumsError && -
- {translate('LoadingAlbumsFailed')} -
+ !isFetching && albumsError ? + + {translate('AlbumsLoadError')} + : + null } { - !isFetching && trackFilesError && -
- {translate('LoadingTrackFilesFailed')} -
+ !isFetching && trackFilesError ? + + {translate('TrackFilesLoadError')} + : + null } { isPopulated && !!media.length &&
- { media.slice(0).map((medium) => { return ( diff --git a/frontend/src/Album/Details/AlbumDetailsConnector.js b/frontend/src/Album/Details/AlbumDetailsConnector.js index 5305c44da..7a5dbc95e 100644 --- a/frontend/src/Album/Details/AlbumDetailsConnector.js +++ b/frontend/src/Album/Details/AlbumDetailsConnector.js @@ -70,6 +70,12 @@ function createMapStateToProps() { isCommandExecuting(isSearchingCommand) && isSearchingCommand.body.albumIds.indexOf(album.id) > -1 ); + const isRenamingFiles = isCommandExecuting(findCommand(commands, { name: commandNames.RENAME_FILES, artistId: artist.id })); + const isRenamingArtistCommand = findCommand(commands, { name: commandNames.RENAME_ARTIST }); + const isRenamingArtist = ( + isCommandExecuting(isRenamingArtistCommand) && + isRenamingArtistCommand.body.artistIds.indexOf(artist.id) > -1 + ); const isFetching = tracks.isFetching || isTrackFilesFetching; const isPopulated = tracks.isPopulated && isTrackFilesPopulated; @@ -80,6 +86,8 @@ function createMapStateToProps() { shortDateFormat: uiSettings.shortDateFormat, artist, isSearching, + isRenamingFiles, + isRenamingArtist, isFetching, isPopulated, tracksError, @@ -113,8 +121,27 @@ class AlbumDetailsConnector extends Component { } componentDidUpdate(prevProps) { - if (!_.isEqual(getMonitoredReleases(prevProps), getMonitoredReleases(this.props)) || - (prevProps.anyReleaseOk === false && this.props.anyReleaseOk === true)) { + const { + id, + anyReleaseOk, + isRenamingFiles, + isRenamingArtist + } = this.props; + + if ( + (prevProps.isRenamingFiles && !isRenamingFiles) || + (prevProps.isRenamingArtist && !isRenamingArtist) || + !_.isEqual(getMonitoredReleases(prevProps), getMonitoredReleases(this.props)) || + (prevProps.anyReleaseOk === false && anyReleaseOk === true) + ) { + this.unpopulate(); + this.populate(); + } + + // If the id has changed we need to clear the album + // files and fetch from the server. + + if (prevProps.id !== id) { this.unpopulate(); this.populate(); } @@ -174,6 +201,8 @@ class AlbumDetailsConnector extends Component { AlbumDetailsConnector.propTypes = { id: PropTypes.number, anyReleaseOk: PropTypes.bool, + isRenamingFiles: PropTypes.bool.isRequired, + isRenamingArtist: PropTypes.bool.isRequired, isAlbumFetching: PropTypes.bool, isAlbumPopulated: PropTypes.bool, foreignAlbumId: PropTypes.string.isRequired, diff --git a/frontend/src/Album/Details/TrackRow.css b/frontend/src/Album/Details/TrackRow.css index 3162ac9cc..11ebb64fa 100644 --- a/frontend/src/Album/Details/TrackRow.css +++ b/frontend/src/Album/Details/TrackRow.css @@ -23,6 +23,7 @@ } .duration, +.size, .status { composes: cell from '~Components/Table/Cells/TableRowCell.css'; diff --git a/frontend/src/Album/Details/TrackRow.css.d.ts b/frontend/src/Album/Details/TrackRow.css.d.ts index 7b473fe05..c5644a2d4 100644 --- a/frontend/src/Album/Details/TrackRow.css.d.ts +++ b/frontend/src/Album/Details/TrackRow.css.d.ts @@ -5,6 +5,7 @@ interface CssExports { 'customFormatScore': string; 'duration': string; 'monitored': string; + 'size': string; 'status': string; 'title': string; 'trackNumber': string; diff --git a/frontend/src/Album/Details/TrackRow.js b/frontend/src/Album/Details/TrackRow.js index a8deb3e98..5f60df882 100644 --- a/frontend/src/Album/Details/TrackRow.js +++ b/frontend/src/Album/Details/TrackRow.js @@ -9,6 +9,7 @@ import { tooltipPositions } from 'Helpers/Props'; import MediaInfoConnector from 'TrackFile/MediaInfoConnector'; import * as mediaInfoTypes from 'TrackFile/mediaInfoTypes'; import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; +import formatBytes from 'Utilities/Number/formatBytes'; import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore'; import TrackActionsCell from './TrackActionsCell'; import styles from './TrackRow.css'; @@ -28,6 +29,7 @@ class TrackRow extends Component { title, duration, trackFilePath, + trackFileSize, customFormats, customFormatScore, columns, @@ -145,6 +147,17 @@ class TrackRow extends Component { ); } + if (name === 'size') { + return ( + + {!!trackFileSize && formatBytes(trackFileSize)} + + ); + } + if (name === 'status') { return ( { return { trackFilePath: trackFile ? trackFile.path : null, + trackFileSize: trackFile ? trackFile.size : null, customFormats: trackFile ? trackFile.customFormats : [], customFormatScore: trackFile ? trackFile.customFormatScore : 0 }; diff --git a/frontend/src/Album/Edit/EditAlbumModalContent.js b/frontend/src/Album/Edit/EditAlbumModalContent.js index 8c5ed58a6..b924f937b 100644 --- a/frontend/src/Album/Edit/EditAlbumModalContent.js +++ b/frontend/src/Album/Edit/EditAlbumModalContent.js @@ -43,6 +43,10 @@ class EditAlbumModalContent extends Component { ...otherProps } = this.props; + const { + trackFileCount = 0 + } = statistics; + const { monitored, anyReleaseOk, @@ -96,7 +100,7 @@ class EditAlbumModalContent extends Component { type={inputTypes.ALBUM_RELEASE_SELECT} name="releases" helpText={translate('ReleasesHelpText')} - isDisabled={anyReleaseOk.value && statistics.trackFileCount > 0} + isDisabled={anyReleaseOk.value && trackFileCount > 0} albumReleases={releases} onChange={onInputChange} /> diff --git a/frontend/src/Album/TrackQuality.js b/frontend/src/Album/TrackQuality.js index ca94227a0..6eac5d2f8 100644 --- a/frontend/src/Album/TrackQuality.js +++ b/frontend/src/Album/TrackQuality.js @@ -3,6 +3,7 @@ import React from 'react'; import Label from 'Components/Label'; import { kinds } from 'Helpers/Props'; import formatBytes from 'Utilities/Number/formatBytes'; +import translate from 'Utilities/String/translate'; function getTooltip(title, quality, size) { if (!title) { @@ -26,13 +27,44 @@ function getTooltip(title, quality, size) { return title; } +function revisionLabel(className, quality, showRevision) { + if (!showRevision) { + return; + } + + if (quality.revision.isRepack) { + return ( + + ); + } + + if (quality.revision.version && quality.revision.version > 1) { + return ( + + ); + } +} + function TrackQuality(props) { const { className, title, quality, size, - isCutoffNotMet + isCutoffNotMet, + showRevision } = props; if (!quality) { @@ -40,13 +72,15 @@ function TrackQuality(props) { } return ( - + + {revisionLabel(className, quality, showRevision)} + ); } @@ -55,11 +89,13 @@ TrackQuality.propTypes = { title: PropTypes.string, quality: PropTypes.object.isRequired, size: PropTypes.number, - isCutoffNotMet: PropTypes.bool + isCutoffNotMet: PropTypes.bool, + showRevision: PropTypes.bool }; TrackQuality.defaultProps = { - title: '' + title: '', + showRevision: false }; export default TrackQuality; diff --git a/frontend/src/App/State/AppState.ts b/frontend/src/App/State/AppState.ts index 5add86a4e..04f7a609f 100644 --- a/frontend/src/App/State/AppState.ts +++ b/frontend/src/App/State/AppState.ts @@ -39,8 +39,17 @@ export interface CustomFilter { filers: PropertyFilter[]; } +export interface AppSectionState { + dimensions: { + isSmallScreen: boolean; + width: number; + height: number; + }; +} + interface AppState { albums: AlbumAppState; + app: AppSectionState; artist: ArtistAppState; artistIndex: ArtistIndexAppState; history: HistoryAppState; diff --git a/frontend/src/App/State/QueueAppState.ts b/frontend/src/App/State/QueueAppState.ts index a4adc7c36..05d74acac 100644 --- a/frontend/src/App/State/QueueAppState.ts +++ b/frontend/src/App/State/QueueAppState.ts @@ -1,38 +1,10 @@ -import ModelBase from 'App/ModelBase'; -import { QualityModel } from 'Quality/Quality'; -import CustomFormat from 'typings/CustomFormat'; +import Queue from 'typings/Queue'; import AppSectionState, { AppSectionFilterState, AppSectionItemState, Error, } from './AppSectionState'; -export interface StatusMessage { - title: string; - messages: string[]; -} - -export interface Queue extends ModelBase { - quality: QualityModel; - customFormats: CustomFormat[]; - size: number; - title: string; - sizeleft: number; - timeleft: string; - estimatedCompletionTime: string; - status: string; - trackedDownloadStatus: string; - trackedDownloadState: string; - statusMessages: StatusMessage[]; - errorMessage: string; - downloadId: string; - protocol: string; - downloadClient: string; - outputPath: string; - artistId?: number; - albumId?: number; -} - export interface QueueDetailsAppState extends AppSectionState { params: unknown; } diff --git a/frontend/src/Artist/Delete/DeleteArtistModalContent.js b/frontend/src/Artist/Delete/DeleteArtistModalContent.js index 10e19ae20..0542f718b 100644 --- a/frontend/src/Artist/Delete/DeleteArtistModalContent.js +++ b/frontend/src/Artist/Delete/DeleteArtistModalContent.js @@ -56,8 +56,8 @@ class DeleteArtistModalContent extends Component { } = this.props; const { - trackFileCount, - sizeOnDisk + trackFileCount = 0, + sizeOnDisk = 0 } = statistics; const deleteFiles = this.state.deleteFiles; diff --git a/frontend/src/Artist/Details/AlbumRow.js b/frontend/src/Artist/Details/AlbumRow.js index d8f27b847..52cd07975 100644 --- a/frontend/src/Artist/Details/AlbumRow.js +++ b/frontend/src/Artist/Details/AlbumRow.js @@ -85,9 +85,9 @@ class AlbumRow extends Component { } = this.props; const { - trackCount, - trackFileCount, - totalTrackCount + trackCount = 0, + trackFileCount = 0, + totalTrackCount = 0 } = statistics; return ( @@ -257,7 +257,8 @@ AlbumRow.propTypes = { AlbumRow.defaultProps = { statistics: { trackCount: 0, - trackFileCount: 0 + trackFileCount: 0, + totalTrackCount: 0 } }; diff --git a/frontend/src/Artist/Details/ArtistDetails.css b/frontend/src/Artist/Details/ArtistDetails.css index ee2171999..43daa40d0 100644 --- a/frontend/src/Artist/Details/ArtistDetails.css +++ b/frontend/src/Artist/Details/ArtistDetails.css @@ -161,6 +161,12 @@ .headerContent { padding: 15px; } + + .title { + font-weight: 300; + font-size: 30px; + line-height: 30px; + } } @media only screen and (max-width: $breakpointLarge) { diff --git a/frontend/src/Artist/Details/ArtistDetails.js b/frontend/src/Artist/Details/ArtistDetails.js index f3ac56a15..c6fb445b7 100644 --- a/frontend/src/Artist/Details/ArtistDetails.js +++ b/frontend/src/Artist/Details/ArtistDetails.js @@ -8,6 +8,7 @@ import EditArtistModalConnector from 'Artist/Edit/EditArtistModalConnector'; import ArtistHistoryModal from 'Artist/History/ArtistHistoryModal'; import MonitoringOptionsModal from 'Artist/MonitoringOptions/MonitoringOptionsModal'; import ArtistInteractiveSearchModalConnector from 'Artist/Search/ArtistInteractiveSearchModalConnector'; +import Alert from 'Components/Alert'; import HeartRating from 'Components/HeartRating'; import Icon from 'Components/Icon'; import Label from 'Components/Label'; @@ -221,8 +222,8 @@ class ArtistDetails extends Component { } = this.props; const { - trackFileCount, - sizeOnDisk + trackFileCount = 0, + sizeOnDisk = 0 } = statistics; const { @@ -241,7 +242,7 @@ class ArtistDetails extends Component { } = this.state; const continuing = status === 'continuing'; - const endedString = artistType === 'Person' ? 'Deceased' : 'Inactive'; + const endedString = artistType === 'Person' ? translate('Deceased') : translate('Inactive'); let trackFilesCountMessage = translate('TrackFilesCountMessage'); @@ -555,7 +556,7 @@ class ArtistDetails extends Component { /> - Links + {translate('Links')} } @@ -611,17 +612,19 @@ class ArtistDetails extends Component { } { - !isFetching && albumsError && -
- {translate('LoadingAlbumsFailed')} -
+ !isFetching && albumsError ? + + {translate('AlbumsLoadError')} + : + null } { - !isFetching && trackFilesError && -
- {translate('LoadingTrackFilesFailed')} -
+ !isFetching && trackFilesError ? + + {translate('TrackFilesLoadError')} + : + null } { diff --git a/frontend/src/Artist/Details/ArtistDetailsConnector.js b/frontend/src/Artist/Details/ArtistDetailsConnector.js index cd2a911c5..bed30a937 100644 --- a/frontend/src/Artist/Details/ArtistDetailsConnector.js +++ b/frontend/src/Artist/Details/ArtistDetailsConnector.js @@ -107,7 +107,6 @@ function createMapStateToProps() { const isRefreshing = isArtistRefreshing || allArtistRefreshing; const isSearching = isCommandExecuting(findCommand(commands, { name: commandNames.ARTIST_SEARCH, artistId: artist.id })); const isRenamingFiles = isCommandExecuting(findCommand(commands, { name: commandNames.RENAME_FILES, artistId: artist.id })); - const isRenamingArtistCommand = findCommand(commands, { name: commandNames.RENAME_ARTIST }); const isRenamingArtist = ( isCommandExecuting(isRenamingArtistCommand) && diff --git a/frontend/src/Artist/History/ArtistHistoryModal.js b/frontend/src/Artist/History/ArtistHistoryModal.js index 7139d7633..a4362484c 100644 --- a/frontend/src/Artist/History/ArtistHistoryModal.js +++ b/frontend/src/Artist/History/ArtistHistoryModal.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import Modal from 'Components/Modal/Modal'; +import { sizes } from 'Helpers/Props'; import ArtistHistoryModalContentConnector from './ArtistHistoryModalContentConnector'; function ArtistHistoryModal(props) { @@ -13,6 +14,7 @@ function ArtistHistoryModal(props) { return ( translate('Date'), - isVisible: true - }, - { - name: 'details', - label: () => translate('Details'), + name: 'customFormats', + label: () => translate('CustomFormats'), + isSortable: false, isVisible: true }, { @@ -53,9 +49,13 @@ const columns = [ isSortable: true, isVisible: true }, + { + name: 'date', + label: () => translate('Date'), + isVisible: true + }, { name: 'actions', - label: () => translate('Actions'), isVisible: true } ]; diff --git a/frontend/src/Artist/History/ArtistHistoryRow.css b/frontend/src/Artist/History/ArtistHistoryRow.css index a62b9c2bb..33dba8df9 100644 --- a/frontend/src/Artist/History/ArtistHistoryRow.css +++ b/frontend/src/Artist/History/ArtistHistoryRow.css @@ -4,7 +4,6 @@ word-break: break-word; } -.details, .actions { composes: cell from '~Components/Table/Cells/TableRowCell.css'; diff --git a/frontend/src/Artist/History/ArtistHistoryRow.css.d.ts b/frontend/src/Artist/History/ArtistHistoryRow.css.d.ts index e3425487e..b0b91a6b8 100644 --- a/frontend/src/Artist/History/ArtistHistoryRow.css.d.ts +++ b/frontend/src/Artist/History/ArtistHistoryRow.css.d.ts @@ -2,7 +2,6 @@ // Please do not change this file! interface CssExports { 'actions': string; - 'details': string; 'sourceTitle': string; } export const cssExports: CssExports; diff --git a/frontend/src/Artist/History/ArtistHistoryRow.js b/frontend/src/Artist/History/ArtistHistoryRow.js index 4b2dfff42..fe8326378 100644 --- a/frontend/src/Artist/History/ArtistHistoryRow.js +++ b/frontend/src/Artist/History/ArtistHistoryRow.js @@ -11,7 +11,6 @@ import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellCo import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; import Popover from 'Components/Tooltip/Popover'; -import Tooltip from 'Components/Tooltip/Tooltip'; import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore'; import translate from 'Utilities/String/translate'; @@ -112,11 +111,19 @@ class ArtistHistoryRow extends Component { />
+ + + + + + {formatCustomFormatScore(customFormatScore, customFormats.length)} + + - + - - - } - position={tooltipPositions.BOTTOM} - /> - - - { eventType === 'grabbed' && } diff --git a/frontend/src/Artist/Index/Posters/ArtistIndexPosters.tsx b/frontend/src/Artist/Index/Posters/ArtistIndexPosters.tsx index 8c27d363d..9e5c3e885 100644 --- a/frontend/src/Artist/Index/Posters/ArtistIndexPosters.tsx +++ b/frontend/src/Artist/Index/Posters/ArtistIndexPosters.tsx @@ -201,11 +201,15 @@ export default function ArtistIndexPosters(props: ArtistIndexPostersProps) { if (isSmallScreen) { const padding = bodyPaddingSmallScreen - 5; + const width = window.innerWidth - padding * 2; + const height = window.innerHeight; - setSize({ - width: window.innerWidth - padding * 2, - height: window.innerHeight, - }); + if (width !== size.width || height !== size.height) { + setSize({ + width, + height, + }); + } return; } @@ -213,13 +217,18 @@ export default function ArtistIndexPosters(props: ArtistIndexPostersProps) { if (current) { const width = current.clientWidth; const padding = bodyPadding - 5; + const finalWidth = width - padding * 2; + + if (Math.abs(size.width - finalWidth) < 20 || size.width === finalWidth) { + return; + } setSize({ - width: width - padding * 2, + width: finalWidth, height: window.innerHeight, }); } - }, [isSmallScreen, scrollerRef, bounds]); + }, [isSmallScreen, size, scrollerRef, bounds]); useEffect(() => { const currentScrollListener = isSmallScreen ? window : scrollerRef.current; diff --git a/frontend/src/Artist/Index/Select/AlbumStudio/AlbumStudioAlbum.tsx b/frontend/src/Artist/Index/Select/AlbumStudio/AlbumStudioAlbum.tsx index f7e133a84..ec4ef9074 100644 --- a/frontend/src/Artist/Index/Select/AlbumStudio/AlbumStudioAlbum.tsx +++ b/frontend/src/Artist/Index/Select/AlbumStudio/AlbumStudioAlbum.tsx @@ -33,7 +33,11 @@ function AlbumStudioAlbum(props: AlbumStudioAlbumProps) { isSaving = false, } = props; - const { trackFileCount, totalTrackCount, percentOfTracks } = statistics; + const { + trackFileCount = 0, + totalTrackCount = 0, + percentOfTracks = 0, + } = statistics; const dispatch = useDispatch(); const onAlbumMonitoredPress = useCallback(() => { diff --git a/frontend/src/Artist/Index/Select/Edit/EditArtistModalContent.tsx b/frontend/src/Artist/Index/Select/Edit/EditArtistModalContent.tsx index befd4a434..94d1e87d2 100644 --- a/frontend/src/Artist/Index/Select/Edit/EditArtistModalContent.tsx +++ b/frontend/src/Artist/Index/Select/Edit/EditArtistModalContent.tsx @@ -215,6 +215,7 @@ function EditArtistModalContent(props: EditArtistModalContentProps) { value={metadataProfileId} includeNoChange={true} includeNoChangeDisabled={false} + includeNone={true} onChange={onInputChange} /> diff --git a/frontend/src/Calendar/CalendarConnector.js b/frontend/src/Calendar/CalendarConnector.js index 079b3e780..17221eb34 100644 --- a/frontend/src/Calendar/CalendarConnector.js +++ b/frontend/src/Calendar/CalendarConnector.js @@ -47,7 +47,7 @@ class CalendarConnector extends Component { gotoCalendarToday } = this.props; - registerPagePopulator(this.repopulate); + registerPagePopulator(this.repopulate, ['trackFileUpdated', 'trackFileDeleted']); if (useCurrentPage) { fetchCalendar(); diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js index 116bd3e8b..cd9c07053 100644 --- a/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js +++ b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js @@ -30,22 +30,24 @@ function CustomFiltersModalContent(props) { { - customFilters.map((customFilter) => { - return ( - - ); - }) + customFilters + .sort((a, b) => a.label.localeCompare(b.label)) + .map((customFilter) => { + return ( + + ); + }) }
diff --git a/frontend/src/Components/Form/FormInputGroup.js b/frontend/src/Components/Form/FormInputGroup.js index 7e6b0c7c9..c0f0bf5dd 100644 --- a/frontend/src/Components/Form/FormInputGroup.js +++ b/frontend/src/Components/Form/FormInputGroup.js @@ -276,6 +276,7 @@ FormInputGroup.propTypes = { name: PropTypes.string.isRequired, value: PropTypes.any, values: PropTypes.arrayOf(PropTypes.any), + isDisabled: PropTypes.bool, type: PropTypes.string.isRequired, kind: PropTypes.oneOf(kinds.all), min: PropTypes.number, @@ -289,6 +290,7 @@ FormInputGroup.propTypes = { autoFocus: PropTypes.bool, includeNoChange: PropTypes.bool, includeNoChangeDisabled: PropTypes.bool, + includeNone: PropTypes.bool, selectedValueOptions: PropTypes.object, pending: PropTypes.bool, errors: PropTypes.arrayOf(PropTypes.object), diff --git a/frontend/src/Components/Form/FormLabel.css b/frontend/src/Components/Form/FormLabel.css index 074b6091d..54a4678e8 100644 --- a/frontend/src/Components/Form/FormLabel.css +++ b/frontend/src/Components/Form/FormLabel.css @@ -2,8 +2,10 @@ display: flex; justify-content: flex-end; margin-right: $formLabelRightMarginWidth; + padding-top: 8px; + min-height: 35px; + text-align: end; font-weight: bold; - line-height: 35px; } .hasError { diff --git a/frontend/src/Components/Form/MetadataProfileSelectInputConnector.js b/frontend/src/Components/Form/MetadataProfileSelectInputConnector.js index e7c1535c1..3d763e713 100644 --- a/frontend/src/Components/Form/MetadataProfileSelectInputConnector.js +++ b/frontend/src/Components/Form/MetadataProfileSelectInputConnector.js @@ -17,7 +17,6 @@ function createMapStateToProps() { (state, { includeMixed }) => includeMixed, (state, { includeNone }) => includeNone, (metadataProfiles, includeNoChange, includeNoChangeDisabled = true, includeMixed, includeNone) => { - const profiles = metadataProfiles.items.filter((item) => item.name !== metadataProfileNames.NONE); const noneProfile = metadataProfiles.items.find((item) => item.name === metadataProfileNames.NONE); diff --git a/frontend/src/Components/Menu/FilterMenuContent.js b/frontend/src/Components/Menu/FilterMenuContent.js index 516fbb648..4ee406224 100644 --- a/frontend/src/Components/Menu/FilterMenuContent.js +++ b/frontend/src/Components/Menu/FilterMenuContent.js @@ -40,18 +40,26 @@ class FilterMenuContent extends Component { } { - customFilters.map((filter) => { - return ( - - {filter.label} - - ); - }) + customFilters.length > 0 ? + : + null + } + + { + customFilters + .sort((a, b) => a.label.localeCompare(b.label)) + .map((filter) => { + return ( + + {filter.label} + + ); + }) } { diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index 966097730..c970589c7 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -216,6 +216,8 @@ class SignalRConnector extends Component { this.props.dispatchUpdateItem({ section, ...body.resource }); } else if (body.action === 'deleted') { this.props.dispatchRemoveItem({ section, id: body.resource.id }); + + repopulatePage('trackFileDeleted'); } // Repopulate the page to handle recently imported file diff --git a/frontend/src/Content/Images/Icons/manifest.json b/frontend/src/Content/Images/Icons/manifest.json index cff971235..a7ffa6777 100644 --- a/frontend/src/Content/Images/Icons/manifest.json +++ b/frontend/src/Content/Images/Icons/manifest.json @@ -15,5 +15,5 @@ "start_url": "../../../../", "theme_color": "#3a3f51", "background_color": "#3a3f51", - "display": "standalone" + "display": "minimal-ui" } diff --git a/frontend/src/Helpers/Props/icons.js b/frontend/src/Helpers/Props/icons.js index 0cbc26278..77803e56e 100644 --- a/frontend/src/Helpers/Props/icons.js +++ b/frontend/src/Helpers/Props/icons.js @@ -55,6 +55,7 @@ import { faEye as fasEye, faFastBackward as fasFastBackward, faFastForward as fasFastForward, + faFileCircleQuestion as fasFileCircleQuestion, faFileExport as fasFileExport, faFileImport as fasFileImport, faFileInvoice as farFileInvoice, @@ -154,7 +155,8 @@ export const EXPORT = fasFileExport; export const EXTERNAL_LINK = fasExternalLinkAlt; export const FATAL = fasTimesCircle; export const FILE = farFile; -export const FILEIMPORT = fasFileImport; +export const FILE_IMPORT = fasFileImport; +export const FILE_MISSING = fasFileCircleQuestion; export const FILTER = fasFilter; export const FOLDER = farFolder; export const FOLDER_OPEN = fasFolderOpen; diff --git a/frontend/src/InteractiveImport/Album/SelectAlbumRow.js b/frontend/src/InteractiveImport/Album/SelectAlbumRow.js index 68d50fb8b..6b50a1ce9 100644 --- a/frontend/src/InteractiveImport/Album/SelectAlbumRow.js +++ b/frontend/src/InteractiveImport/Album/SelectAlbumRow.js @@ -44,9 +44,9 @@ class SelectAlbumRow extends Component { } = this.props; const { - trackCount, - trackFileCount, - totalTrackCount + trackCount = 0, + trackFileCount = 0, + totalTrackCount = 0 } = statistics; const extendedTitle = disambiguation ? `${title} (${disambiguation})` : title; @@ -134,7 +134,8 @@ SelectAlbumRow.propTypes = { SelectAlbumRow.defaultProps = { statistics: { trackCount: 0, - trackFileCount: 0 + trackFileCount: 0, + totalTrackCount: 0 } }; diff --git a/frontend/src/InteractiveImport/Track/SelectTrackRow.js b/frontend/src/InteractiveImport/Track/SelectTrackRow.js index ea621877d..d0a902576 100644 --- a/frontend/src/InteractiveImport/Track/SelectTrackRow.js +++ b/frontend/src/InteractiveImport/Track/SelectTrackRow.js @@ -51,11 +51,11 @@ class SelectTrackRow extends Component { iconKind = kinds.DEFAULT; iconTip = 'Track missing from library and no import selected.'; } else if (importSelected && hasFile) { - iconName = icons.FILEIMPORT; + iconName = icons.FILE_IMPORT; iconKind = kinds.WARNING; iconTip = 'Warning: Existing track will be replaced by download.'; } else if (importSelected && !hasFile) { - iconName = icons.FILEIMPORT; + iconName = icons.FILE_IMPORT; iconKind = kinds.DEFAULT; iconTip = 'Track missing from library and selected for import.'; } diff --git a/frontend/src/InteractiveSearch/InteractiveSearchRow.css b/frontend/src/InteractiveSearch/InteractiveSearchRow.css index c1079c792..ffea82600 100644 --- a/frontend/src/InteractiveSearch/InteractiveSearchRow.css +++ b/frontend/src/InteractiveSearch/InteractiveSearchRow.css @@ -22,6 +22,10 @@ text-align: center; } +.quality { + white-space: nowrap; +} + .customFormatScore { composes: cell from '~Components/Table/Cells/TableRowCell.css'; diff --git a/frontend/src/InteractiveSearch/InteractiveSearchRow.js b/frontend/src/InteractiveSearch/InteractiveSearchRow.js index ce32f12bd..3029d2d2f 100644 --- a/frontend/src/InteractiveSearch/InteractiveSearchRow.js +++ b/frontend/src/InteractiveSearch/InteractiveSearchRow.js @@ -178,7 +178,7 @@ class InteractiveSearchRow extends Component { - + diff --git a/frontend/src/Search/Artist/AddNewArtistSearchResult.js b/frontend/src/Search/Artist/AddNewArtistSearchResult.js index 8ad5f6061..83e287b5e 100644 --- a/frontend/src/Search/Artist/AddNewArtistSearchResult.js +++ b/frontend/src/Search/Artist/AddNewArtistSearchResult.js @@ -89,7 +89,7 @@ class AddNewArtistSearchResult extends Component { const linkProps = isExistingArtist ? { to: `/artist/${foreignArtistId}` } : { onPress: this.onPress }; - const endedString = artistType === 'Person' ? 'Deceased' : 'Inactive'; + const endedString = artistType === 'Person' ? translate('Deceased') : translate('Inactive'); const height = calculateHeight(230, isSmallScreen); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js index d55bbcdf9..02a31eda7 100644 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js +++ b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js @@ -49,7 +49,7 @@ function EditSpecificationModalContent(props) { {...otherProps} > { - fields && fields.some((x) => x.label === 'Regular Expression') && + fields && fields.some((x) => x.label === translate('CustomFormatsSpecificationRegularExpression')) &&
\\^$.|?*+()[{ have special meanings and need escaping with a \\' }} /> diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js index 7e43dea12..d3d51c7fc 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js +++ b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js @@ -139,7 +139,7 @@ class EditDownloadClientModalContent extends Component { { + dispatch(setManageDownloadClientsSort({ sortKey: value })); + }, + [dispatch] + ); + const onDeletePress = useCallback(() => { setIsDeleteModalOpen(true); }, [setIsDeleteModalOpen]); @@ -219,6 +232,9 @@ function ManageDownloadClientsModalContent( allSelected={allSelected} allUnselected={allUnselected} onSelectAllChange={onSelectAllChange} + sortKey={sortKey} + sortDirection={sortDirection} + onSortPress={onSortPress} > {items.map((item) => { diff --git a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js b/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js index 48d8f3410..262143590 100644 --- a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js +++ b/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js @@ -61,10 +61,12 @@ function DownloadClientOptions(props) { legend={translate('FailedDownloadHandling')} >
- - - {translate('Redownload')} - + + {translate('AutoRedownloadFailed')} + + { + settings.autoRedownloadFailed.value ? + + {translate('AutoRedownloadFailedFromInteractiveSearch')} + + + : + null + } + {translate('RemoveDownloadsAlert')} diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css index 349ebc925..7c603a8b5 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css @@ -8,11 +8,13 @@ } .artistName { - flex: 0 0 300px; + @add-mixin truncate; + + flex: 0 1 600px; } .foreignId { - flex: 0 0 400px; + flex: 0 0 290px; } .actions { diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css index 99e1c1e99..0e3f43824 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css @@ -4,12 +4,12 @@ font-weight: bold; } -.host { - flex: 0 0 300px; +.name { + flex: 0 1 600px; } -.path { - flex: 0 0 400px; +.foreignId { + flex: 0 0 290px; } .addImportListExclusion { diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts index bf7ee773c..397310d60 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.css.d.ts @@ -3,9 +3,9 @@ interface CssExports { 'addButton': string; 'addImportListExclusion': string; - 'host': string; + 'foreignId': string; 'importListExclusionsHeader': string; - 'path': string; + 'name': string; } export const cssExports: CssExports; export default cssExports; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js index fa1f5370a..12e3feabc 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js @@ -51,8 +51,10 @@ class ImportListExclusions extends Component { {...otherProps} >
-
{translate('Name')}
-
+
+ {translate('Name')} +
+
{translate('ForeignId')}
diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx index 37c4a3153..8137111f5 100644 --- a/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx +++ b/frontend/src/Settings/Indexers/Indexers/Manage/ManageIndexersModalContent.tsx @@ -14,9 +14,11 @@ import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; import useSelectState from 'Helpers/Hooks/useSelectState'; import { kinds } from 'Helpers/Props'; +import SortDirection from 'Helpers/Props/SortDirection'; import { bulkDeleteIndexers, bulkEditIndexers, + setManageIndexersSort, } from 'Store/Actions/settingsActions'; import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; import { SelectStateInputProps } from 'typings/props'; @@ -80,6 +82,8 @@ const COLUMNS = [ interface ManageIndexersModalContentProps { onModalClose(): void; + sortKey?: string; + sortDirection?: SortDirection; } function ManageIndexersModalContent(props: ManageIndexersModalContentProps) { @@ -92,6 +96,8 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) { isSaving, error, items, + sortKey, + sortDirection, }: IndexerAppState = useSelector( createClientSideCollectionSelector('settings.indexers') ); @@ -112,6 +118,13 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) { const selectedCount = selectedIds.length; + const onSortPress = useCallback( + (value: string) => { + dispatch(setManageIndexersSort({ sortKey: value })); + }, + [dispatch] + ); + const onDeletePress = useCallback(() => { setIsDeleteModalOpen(true); }, [setIsDeleteModalOpen]); @@ -214,6 +227,9 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) { allSelected={allSelected} allUnselected={allUnselected} onSelectAllChange={onSelectAllChange} + sortKey={sortKey} + sortDirection={sortDirection} + onSortPress={onSortPress} > {items.map((item) => { diff --git a/frontend/src/Settings/MediaManagement/MediaManagement.js b/frontend/src/Settings/MediaManagement/MediaManagement.js index d38bc7224..d1881c068 100644 --- a/frontend/src/Settings/MediaManagement/MediaManagement.js +++ b/frontend/src/Settings/MediaManagement/MediaManagement.js @@ -265,26 +265,24 @@ class MediaManagement extends Component { { - settings.importExtraFiles.value && + settings.importExtraFiles.value ? - - {translate('ImportExtraFiles')} - + {translate('ImportExtraFiles')} - + : null } } diff --git a/frontend/src/Settings/Notifications/Notifications/Notification.js b/frontend/src/Settings/Notifications/Notifications/Notification.js index 6e9b01f57..21f0e5ca8 100644 --- a/frontend/src/Settings/Notifications/Notifications/Notification.js +++ b/frontend/src/Settings/Notifications/Notifications/Notification.js @@ -60,8 +60,9 @@ class Notification extends Component { onReleaseImport, onUpgrade, onRename, - onAlbumDelete, + onArtistAdd, onArtistDelete, + onAlbumDelete, onHealthIssue, onHealthRestored, onDownloadFailure, @@ -72,8 +73,9 @@ class Notification extends Component { supportsOnReleaseImport, supportsOnUpgrade, supportsOnRename, - supportsOnAlbumDelete, + supportsOnArtistAdd, supportsOnArtistDelete, + supportsOnAlbumDelete, supportsOnHealthIssue, supportsOnHealthRestored, supportsOnDownloadFailure, @@ -95,59 +97,75 @@ class Notification extends Component {
{ - supportsOnGrab && onGrab && + supportsOnGrab && onGrab ? + : + null } { - supportsOnReleaseImport && onReleaseImport && + supportsOnReleaseImport && onReleaseImport ? + : + null } { - supportsOnUpgrade && onReleaseImport && onUpgrade && + supportsOnUpgrade && onReleaseImport && onUpgrade ? + : + null } { - supportsOnRename && onRename && + supportsOnRename && onRename ? + : + null } { - supportsOnTrackRetag && onTrackRetag && + supportsOnTrackRetag && onTrackRetag ? + : + null } { - supportsOnAlbumDelete && onAlbumDelete && + supportsOnArtistAdd && onArtistAdd ? + {translate('OnArtistAdd')} + : + null } { - supportsOnArtistDelete && onArtistDelete && + supportsOnArtistDelete && onArtistDelete ? + : + null } { - supportsOnHealthIssue && onHealthIssue && + supportsOnAlbumDelete && onAlbumDelete ? + : + null + } + + { + supportsOnHealthIssue && onHealthIssue ? + : + null } { @@ -159,35 +177,38 @@ class Notification extends Component { } { - supportsOnDownloadFailure && onDownloadFailure && + supportsOnDownloadFailure && onDownloadFailure ? + : + null } { - supportsOnImportFailure && onImportFailure && + supportsOnImportFailure && onImportFailure ? + : + null } { - supportsOnApplicationUpdate && onApplicationUpdate && + supportsOnApplicationUpdate && onApplicationUpdate ? + : + null } { - !onGrab && !onReleaseImport && !onRename && !onTrackRetag && !onAlbumDelete && !onArtistDelete && - !onHealthIssue && !onHealthRestored && !onDownloadFailure && !onImportFailure && !onApplicationUpdate && - + !onGrab && !onReleaseImport && !onRename && !onTrackRetag && !onArtistAdd && !onArtistDelete && !onAlbumDelete && !onHealthIssue && !onHealthRestored && !onDownloadFailure && !onImportFailure && !onApplicationUpdate ? + : + null }
@@ -148,18 +150,29 @@ function NotificationEventItems(props) {
+
+ +
+
{ + onSliderChange = ([sliderMinSize, sliderPreferredSize, sliderMaxSize]) => { this.setState({ sliderMinSize, - sliderMaxSize + sliderMaxSize, + sliderPreferredSize }); this.props.onSizeChange({ minSize: roundNumber(Math.pow(sliderMinSize, 1.1)), + preferredSize: sliderPreferredSize === (slider.max - 3) ? null : roundNumber(Math.pow(sliderPreferredSize, 1.1)), maxSize: sliderMaxSize === slider.max ? null : roundNumber(Math.pow(sliderMaxSize, 1.1)) }); }; @@ -72,12 +75,14 @@ class QualityDefinition extends Component { onAfterSliderChange = () => { const { minSize, - maxSize + maxSize, + preferredSize } = this.props; this.setState({ sliderMiSize: getSliderValue(minSize, slider.min), - sliderMaxSize: getSliderValue(maxSize, slider.max) + sliderMaxSize: getSliderValue(maxSize, slider.max), + sliderPreferredSize: getSliderValue(preferredSize, (slider.max - 3)) // fix }); }; @@ -90,7 +95,22 @@ class QualityDefinition extends Component { this.props.onSizeChange({ minSize, - maxSize: this.props.maxSize + maxSize: this.props.maxSize, + preferredSize: this.props.preferredSize + }); + }; + + onPreferredSizeChange = ({ value }) => { + const preferredSize = value === (MAX - 3) ? null : getValue(value); + + this.setState({ + sliderPreferredSize: getSliderValue(preferredSize, slider.preferred) + }); + + this.props.onSizeChange({ + minSize: this.props.minSize, + maxSize: this.props.maxSize, + preferredSize }); }; @@ -103,7 +123,8 @@ class QualityDefinition extends Component { this.props.onSizeChange({ minSize: this.props.minSize, - maxSize + maxSize, + preferredSize: this.props.preferredSize }); }; @@ -117,20 +138,25 @@ class QualityDefinition extends Component { title, minSize, maxSize, + preferredSize, advancedSettings, onTitleChange } = this.props; const { sliderMinSize, - sliderMaxSize + sliderMaxSize, + sliderPreferredSize } = this.state; const minBytes = minSize * 128; - const maxBytes = maxSize && maxSize * 128; - const minRate = `${formatBytes(minBytes, true)}/s`; - const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : 'Unlimited'; + + const preferredBytes = preferredSize * 128; + const preferredRate = preferredBytes ? `${formatBytes(preferredBytes, true)}/s` : translate('Unlimited'); + + const maxBytes = maxSize && maxSize * 128; + const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : translate('Unlimited'); return (
@@ -151,9 +177,10 @@ class QualityDefinition extends Component { min={slider.min} max={slider.max} step={slider.step} - minDistance={MIN_DISTANCE * 5} - value={[sliderMinSize, sliderMaxSize]} + minDistance={3} + value={[sliderMinSize, sliderPreferredSize, sliderMaxSize]} withTracks={true} + allowCross={false} snapDragDisabled={true} className={styles.slider} trackClassName={styles.bar} @@ -172,7 +199,23 @@ class QualityDefinition extends Component { body={ + } + position={tooltipPositions.BOTTOM} + /> +
+ +
+ {preferredRate} + } + title={translate('PreferredSize')} + body={ + } position={tooltipPositions.BOTTOM} @@ -188,7 +231,7 @@ class QualityDefinition extends Component { body={ } position={tooltipPositions.BOTTOM} @@ -201,14 +244,14 @@ class QualityDefinition extends Component { advancedSettings &&
- Min + {translate('Min')}
- Max + {translate('Preferred')} + + +
+ +
+ {translate('Max')} { + onSizeChange = ({ minSize, maxSize, preferredSize }) => { const { id, minSize: currentMinSize, - maxSize: currentMaxSize + maxSize: currentMaxSize, + preferredSize: currentPreferredSize } = this.props; if (minSize !== currentMinSize) { @@ -37,6 +38,10 @@ class QualityDefinitionConnector extends Component { if (maxSize !== currentMaxSize) { this.props.setQualityDefinitionValue({ id, name: 'maxSize', value: maxSize }); } + + if (preferredSize !== currentPreferredSize) { + this.props.setQualityDefinitionValue({ id, name: 'preferredSize', value: preferredSize }); + } }; // @@ -57,6 +62,7 @@ QualityDefinitionConnector.propTypes = { id: PropTypes.number.isRequired, minSize: PropTypes.number, maxSize: PropTypes.number, + preferredSize: PropTypes.number, setQualityDefinitionValue: PropTypes.func.isRequired, clearPendingChanges: PropTypes.func.isRequired }; diff --git a/frontend/src/Store/Actions/Settings/downloadClients.js b/frontend/src/Store/Actions/Settings/downloadClients.js index 12651039d..aee945ef5 100644 --- a/frontend/src/Store/Actions/Settings/downloadClients.js +++ b/frontend/src/Store/Actions/Settings/downloadClients.js @@ -1,4 +1,5 @@ import { createAction } from 'redux-actions'; +import { sortDirections } from 'Helpers/Props'; import createBulkEditItemHandler from 'Store/Actions/Creators/createBulkEditItemHandler'; import createBulkRemoveItemHandler from 'Store/Actions/Creators/createBulkRemoveItemHandler'; import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; @@ -7,6 +8,7 @@ import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHand import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler'; import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; +import createSetClientSideCollectionSortReducer from 'Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer'; import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer'; import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; import { createThunk } from 'Store/thunks'; @@ -33,6 +35,7 @@ export const CANCEL_TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelTestD export const TEST_ALL_DOWNLOAD_CLIENTS = 'settings/downloadClients/testAllDownloadClients'; export const BULK_EDIT_DOWNLOAD_CLIENTS = 'settings/downloadClients/bulkEditDownloadClients'; export const BULK_DELETE_DOWNLOAD_CLIENTS = 'settings/downloadClients/bulkDeleteDownloadClients'; +export const SET_MANAGE_DOWNLOAD_CLIENTS_SORT = 'settings/downloadClients/setManageDownloadClientsSort'; // // Action Creators @@ -49,6 +52,7 @@ export const cancelTestDownloadClient = createThunk(CANCEL_TEST_DOWNLOAD_CLIENT) export const testAllDownloadClients = createThunk(TEST_ALL_DOWNLOAD_CLIENTS); export const bulkEditDownloadClients = createThunk(BULK_EDIT_DOWNLOAD_CLIENTS); export const bulkDeleteDownloadClients = createThunk(BULK_DELETE_DOWNLOAD_CLIENTS); +export const setManageDownloadClientsSort = createAction(SET_MANAGE_DOWNLOAD_CLIENTS_SORT); export const setDownloadClientValue = createAction(SET_DOWNLOAD_CLIENT_VALUE, (payload) => { return { @@ -88,7 +92,14 @@ export default { isTesting: false, isTestingAll: false, items: [], - pendingChanges: {} + pendingChanges: {}, + sortKey: 'name', + sortDirection: sortDirections.ASCENDING, + sortPredicates: { + name: function(item) { + return item.name.toLowerCase(); + } + } }, // @@ -122,7 +133,10 @@ export default { return selectedSchema; }); - } + }, + + [SET_MANAGE_DOWNLOAD_CLIENTS_SORT]: createSetClientSideCollectionSortReducer(section) + } }; diff --git a/frontend/src/Store/Actions/Settings/indexers.js b/frontend/src/Store/Actions/Settings/indexers.js index c76750cf2..1e9aded2f 100644 --- a/frontend/src/Store/Actions/Settings/indexers.js +++ b/frontend/src/Store/Actions/Settings/indexers.js @@ -1,4 +1,5 @@ import { createAction } from 'redux-actions'; +import { sortDirections } from 'Helpers/Props'; import createBulkEditItemHandler from 'Store/Actions/Creators/createBulkEditItemHandler'; import createBulkRemoveItemHandler from 'Store/Actions/Creators/createBulkRemoveItemHandler'; import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; @@ -7,6 +8,7 @@ import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHand import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler'; import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; +import createSetClientSideCollectionSortReducer from 'Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer'; import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer'; import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; import { createThunk } from 'Store/thunks'; @@ -36,6 +38,7 @@ export const CANCEL_TEST_INDEXER = 'settings/indexers/cancelTestIndexer'; export const TEST_ALL_INDEXERS = 'settings/indexers/testAllIndexers'; export const BULK_EDIT_INDEXERS = 'settings/indexers/bulkEditIndexers'; export const BULK_DELETE_INDEXERS = 'settings/indexers/bulkDeleteIndexers'; +export const SET_MANAGE_INDEXERS_SORT = 'settings/indexers/setManageIndexersSort'; // // Action Creators @@ -53,6 +56,7 @@ export const cancelTestIndexer = createThunk(CANCEL_TEST_INDEXER); export const testAllIndexers = createThunk(TEST_ALL_INDEXERS); export const bulkEditIndexers = createThunk(BULK_EDIT_INDEXERS); export const bulkDeleteIndexers = createThunk(BULK_DELETE_INDEXERS); +export const setManageIndexersSort = createAction(SET_MANAGE_INDEXERS_SORT); export const setIndexerValue = createAction(SET_INDEXER_VALUE, (payload) => { return { @@ -92,7 +96,14 @@ export default { isTesting: false, isTestingAll: false, items: [], - pendingChanges: {} + pendingChanges: {}, + sortKey: 'name', + sortDirection: sortDirections.ASCENDING, + sortPredicates: { + name: function(item) { + return item.name.toLowerCase(); + } + } }, // @@ -142,7 +153,13 @@ export default { delete selectedSchema.name; selectedSchema.fields = selectedSchema.fields.map((field) => { - return { ...field }; + const newField = { ...field }; + + if (newField.privacy === 'apiKey' || newField.privacy === 'password') { + newField.value = ''; + } + + return newField; }); newState.selectedSchema = selectedSchema; @@ -153,7 +170,10 @@ export default { }; return updateSectionState(state, section, newState); - } + }, + + [SET_MANAGE_INDEXERS_SORT]: createSetClientSideCollectionSortReducer(section) + } }; diff --git a/frontend/src/Store/Actions/Settings/notifications.js b/frontend/src/Store/Actions/Settings/notifications.js index 15943255c..4e557db87 100644 --- a/frontend/src/Store/Actions/Settings/notifications.js +++ b/frontend/src/Store/Actions/Settings/notifications.js @@ -107,6 +107,8 @@ export default { selectedSchema.onReleaseImport = selectedSchema.supportsOnReleaseImport; selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade; selectedSchema.onRename = selectedSchema.supportsOnRename; + selectedSchema.onArtistAdd = selectedSchema.supportsOnArtistAdd; + selectedSchema.onArtistDelete = selectedSchema.supportsOnArtistDelete; selectedSchema.onHealthIssue = selectedSchema.supportsOnHealthIssue; selectedSchema.onDownloadFailure = selectedSchema.supportsOnDownloadFailure; selectedSchema.onImportFailure = selectedSchema.supportsOnImportFailure; diff --git a/frontend/src/Store/Actions/artistIndexActions.js b/frontend/src/Store/Actions/artistIndexActions.js index aa78daf40..756a6ee25 100644 --- a/frontend/src/Store/Actions/artistIndexActions.js +++ b/frontend/src/Store/Actions/artistIndexActions.js @@ -176,7 +176,7 @@ export const defaultState = { const { trackCount = 0, - trackFileCount + trackFileCount = 0 } = statistics; const progress = trackCount ? trackFileCount / trackCount * 100 : 100; @@ -201,7 +201,7 @@ export const defaultState = { albumCount: function(item) { const { statistics = {} } = item; - return statistics.albumCount; + return statistics.albumCount || 0; }, trackCount: function(item) { @@ -229,7 +229,7 @@ export const defaultState = { const { trackCount = 0, - trackFileCount + trackFileCount = 0 } = statistics; const progress = trackCount ? diff --git a/frontend/src/Store/Actions/interactiveImportActions.js b/frontend/src/Store/Actions/interactiveImportActions.js index e9008bb85..e0e295568 100644 --- a/frontend/src/Store/Actions/interactiveImportActions.js +++ b/frontend/src/Store/Actions/interactiveImportActions.js @@ -18,6 +18,7 @@ export const section = 'interactiveImport'; const albumsSection = `${section}.albums`; const trackFilesSection = `${section}.trackFiles`; +let abortCurrentFetchRequest = null; let abortCurrentRequest = null; let currentIds = []; @@ -35,6 +36,8 @@ export const defaultState = { pendingChanges: {}, sortKey: 'path', sortDirection: sortDirections.ASCENDING, + secondarySortKey: 'path', + secondarySortDirection: sortDirections.ASCENDING, recentFolders: [], importMode: 'chooseImportMode', sortPredicates: { @@ -75,6 +78,8 @@ export const defaultState = { }; export const persistState = [ + 'interactiveImport.sortKey', + 'interactiveImport.sortDirection', 'interactiveImport.recentFolders', 'interactiveImport.importMode' ]; @@ -123,6 +128,11 @@ export const clearInteractiveImportTrackFiles = createAction(CLEAR_INTERACTIVE_I // Action Handlers export const actionHandlers = handleThunks({ [FETCH_INTERACTIVE_IMPORT_ITEMS]: function(getState, payload, dispatch) { + if (abortCurrentFetchRequest) { + abortCurrentFetchRequest(); + abortCurrentFetchRequest = null; + } + if (!payload.downloadId && !payload.folder) { dispatch(set({ section, error: { message: '`downloadId` or `folder` is required.' } })); return; @@ -130,12 +140,14 @@ export const actionHandlers = handleThunks({ dispatch(set({ section, isFetching: true })); - const promise = createAjaxRequest({ + const { request, abortRequest } = createAjaxRequest({ url: '/manualimport', data: payload - }).request; + }); - promise.done((data) => { + abortCurrentFetchRequest = abortRequest; + + request.done((data) => { dispatch(batchActions([ update({ section, data }), @@ -148,7 +160,11 @@ export const actionHandlers = handleThunks({ ])); }); - promise.fail((xhr) => { + request.fail((xhr) => { + if (xhr.aborted) { + return; + } + dispatch(set({ section, isFetching: false, diff --git a/frontend/src/Store/Actions/queueActions.js b/frontend/src/Store/Actions/queueActions.js index f4a5018d7..4bf200a5c 100644 --- a/frontend/src/Store/Actions/queueActions.js +++ b/frontend/src/Store/Actions/queueActions.js @@ -146,6 +146,12 @@ export const defaultState = { isSortable: true, isVisible: true }, + { + name: 'added', + label: () => translate('Added'), + isSortable: true, + isVisible: false + }, { name: 'progress', label: () => translate('Progress'), @@ -406,13 +412,14 @@ export const actionHandlers = handleThunks({ id, removeFromClient, blocklist, - skipRedownload + skipRedownload, + changeCategory } = payload; dispatch(updateItem({ section: paged, id, isRemoving: true })); const promise = createAjaxRequest({ - url: `/queue/${id}?removeFromClient=${removeFromClient}&blocklist=${blocklist}&skipRedownload=${skipRedownload}`, + url: `/queue/${id}?removeFromClient=${removeFromClient}&blocklist=${blocklist}&skipRedownload=${skipRedownload}&changeCategory=${changeCategory}`, method: 'DELETE' }).request; @@ -430,7 +437,8 @@ export const actionHandlers = handleThunks({ ids, removeFromClient, blocklist, - skipRedownload + skipRedownload, + changeCategory } = payload; dispatch(batchActions([ @@ -446,7 +454,7 @@ export const actionHandlers = handleThunks({ ])); const promise = createAjaxRequest({ - url: `/queue/bulk?removeFromClient=${removeFromClient}&blocklist=${blocklist}&skipRedownload=${skipRedownload}`, + url: `/queue/bulk?removeFromClient=${removeFromClient}&blocklist=${blocklist}&skipRedownload=${skipRedownload}&changeCategory=${changeCategory}`, method: 'DELETE', dataType: 'json', contentType: 'application/json', diff --git a/frontend/src/Store/Actions/trackActions.js b/frontend/src/Store/Actions/trackActions.js index 3522939eb..bd1f472c3 100644 --- a/frontend/src/Store/Actions/trackActions.js +++ b/frontend/src/Store/Actions/trackActions.js @@ -58,6 +58,11 @@ export const defaultState = { label: () => translate('AudioInfo'), isVisible: true }, + { + name: 'size', + label: () => translate('Size'), + isVisible: false + }, { name: 'customFormats', label: 'Formats', diff --git a/frontend/src/Store/Selectors/createDimensionsSelector.js b/frontend/src/Store/Selectors/createDimensionsSelector.ts similarity index 69% rename from frontend/src/Store/Selectors/createDimensionsSelector.js rename to frontend/src/Store/Selectors/createDimensionsSelector.ts index ce26b2e2c..b9602cb02 100644 --- a/frontend/src/Store/Selectors/createDimensionsSelector.js +++ b/frontend/src/Store/Selectors/createDimensionsSelector.ts @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createDimensionsSelector() { return createSelector( - (state) => state.app.dimensions, + (state: AppState) => state.app.dimensions, (dimensions) => { return dimensions; } diff --git a/frontend/src/System/Status/About/About.js b/frontend/src/System/Status/About/About.js index 4635fef68..8af5b4717 100644 --- a/frontend/src/System/Status/About/About.js +++ b/frontend/src/System/Status/About/About.js @@ -22,9 +22,9 @@ class About extends Component { isNetCore, isDocker, runtimeVersion, - migrationVersion, databaseVersion, databaseType, + migrationVersion, appData, startupPath, mode, @@ -66,13 +66,13 @@ class About extends Component { } x.ArtistId)); artistsResources.ForEach(LinkRootFolderPath); // PopulateAlternateTitles(seriesResources); @@ -219,17 +219,14 @@ namespace Lidarr.Api.V1.Artist LinkArtistStatistics(resource, _artistStatisticsService.ArtistStatistics(resource.Id)); } - private void LinkArtistStatistics(List resources, List artistStatistics) + private void LinkArtistStatistics(List resources, Dictionary artistStatistics) { foreach (var artist in resources) { - var stats = artistStatistics.SingleOrDefault(ss => ss.ArtistId == artist.Id); - if (stats == null) + if (artistStatistics.TryGetValue(artist.Id, out var stats)) { - continue; + LinkArtistStatistics(artist, stats); } - - LinkArtistStatistics(artist, stats); } } diff --git a/src/Lidarr.Api.V1/Config/DownloadClientConfigResource.cs b/src/Lidarr.Api.V1/Config/DownloadClientConfigResource.cs index ee8d81b47..a3c3d50bd 100644 --- a/src/Lidarr.Api.V1/Config/DownloadClientConfigResource.cs +++ b/src/Lidarr.Api.V1/Config/DownloadClientConfigResource.cs @@ -1,4 +1,4 @@ -using Lidarr.Http.REST; +using Lidarr.Http.REST; using NzbDrone.Core.Configuration; namespace Lidarr.Api.V1.Config @@ -8,6 +8,7 @@ namespace Lidarr.Api.V1.Config public string DownloadClientWorkingFolders { get; set; } public bool EnableCompletedDownloadHandling { get; set; } public bool AutoRedownloadFailed { get; set; } + public bool AutoRedownloadFailedFromInteractiveSearch { get; set; } } public static class DownloadClientConfigResourceMapper @@ -19,7 +20,8 @@ namespace Lidarr.Api.V1.Config DownloadClientWorkingFolders = model.DownloadClientWorkingFolders, EnableCompletedDownloadHandling = model.EnableCompletedDownloadHandling, - AutoRedownloadFailed = model.AutoRedownloadFailed + AutoRedownloadFailed = model.AutoRedownloadFailed, + AutoRedownloadFailedFromInteractiveSearch = model.AutoRedownloadFailedFromInteractiveSearch }; } } diff --git a/src/Lidarr.Api.V1/History/HistoryController.cs b/src/Lidarr.Api.V1/History/HistoryController.cs index 150ef3b08..e53827d75 100644 --- a/src/Lidarr.Api.V1/History/HistoryController.cs +++ b/src/Lidarr.Api.V1/History/HistoryController.cs @@ -68,15 +68,14 @@ namespace Lidarr.Api.V1.History [HttpGet] [Produces("application/json")] - public PagingResource GetHistory([FromQuery] PagingRequestResource paging, bool includeArtist, bool includeAlbum, bool includeTrack, int? eventType, int? albumId, string downloadId, [FromQuery] int[] artistIds = null, [FromQuery] int[] quality = null) + public PagingResource GetHistory([FromQuery] PagingRequestResource paging, bool includeArtist, bool includeAlbum, bool includeTrack, [FromQuery(Name = "eventType")] int[] eventTypes, int? albumId, string downloadId, [FromQuery] int[] artistIds = null, [FromQuery] int[] quality = null) { var pagingResource = new PagingResource(paging); var pagingSpec = pagingResource.MapToPagingSpec("date", SortDirection.Descending); - if (eventType.HasValue) + if (eventTypes != null && eventTypes.Any()) { - var filterValue = (EntityHistoryEventType)eventType.Value; - pagingSpec.FilterExpressions.Add(v => v.EventType == filterValue); + pagingSpec.FilterExpressions.Add(v => eventTypes.Contains((int)v.EventType)); } if (albumId.HasValue) diff --git a/src/Lidarr.Api.V1/Indexers/ReleaseController.cs b/src/Lidarr.Api.V1/Indexers/ReleaseController.cs index 3ab9ea319..e36618e04 100644 --- a/src/Lidarr.Api.V1/Indexers/ReleaseController.cs +++ b/src/Lidarr.Api.V1/Indexers/ReleaseController.cs @@ -127,7 +127,7 @@ namespace Lidarr.Api.V1.Indexers throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse albums in the release"); } - await _downloadService.DownloadReport(remoteAlbum); + await _downloadService.DownloadReport(remoteAlbum, release.DownloadClientId); } catch (ReleaseDownloadException ex) { diff --git a/src/Lidarr.Api.V1/Indexers/ReleasePushController.cs b/src/Lidarr.Api.V1/Indexers/ReleasePushController.cs index e87e29101..741439503 100644 --- a/src/Lidarr.Api.V1/Indexers/ReleasePushController.cs +++ b/src/Lidarr.Api.V1/Indexers/ReleasePushController.cs @@ -21,6 +21,7 @@ namespace Lidarr.Api.V1.Indexers private readonly IMakeDownloadDecision _downloadDecisionMaker; private readonly IProcessDownloadDecisions _downloadDecisionProcessor; private readonly IIndexerFactory _indexerFactory; + private readonly IDownloadClientFactory _downloadClientFactory; private readonly Logger _logger; private static readonly object PushLock = new object(); @@ -28,6 +29,7 @@ namespace Lidarr.Api.V1.Indexers public ReleasePushController(IMakeDownloadDecision downloadDecisionMaker, IProcessDownloadDecisions downloadDecisionProcessor, IIndexerFactory indexerFactory, + IDownloadClientFactory downloadClientFactory, IQualityProfileService qualityProfileService, Logger logger) : base(qualityProfileService) @@ -35,6 +37,7 @@ namespace Lidarr.Api.V1.Indexers _downloadDecisionMaker = downloadDecisionMaker; _downloadDecisionProcessor = downloadDecisionProcessor; _indexerFactory = indexerFactory; + _downloadClientFactory = downloadClientFactory; _logger = logger; PostValidator.RuleFor(s => s.Title).NotEmpty(); @@ -44,6 +47,7 @@ namespace Lidarr.Api.V1.Indexers } [HttpPost] + [Consumes("application/json")] public ActionResult Create(ReleaseResource release) { _logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl); @@ -56,22 +60,25 @@ namespace Lidarr.Api.V1.Indexers ResolveIndexer(info); - List decisions; + var downloadClientId = ResolveDownloadClientId(release); + + DownloadDecision decision; lock (PushLock) { - decisions = _downloadDecisionMaker.GetRssDecision(new List { info }); - _downloadDecisionProcessor.ProcessDecisions(decisions).GetAwaiter().GetResult(); + var decisions = _downloadDecisionMaker.GetRssDecision(new List { info }, true); + + decision = decisions.FirstOrDefault(); + + _downloadDecisionProcessor.ProcessDecision(decision, downloadClientId).GetAwaiter().GetResult(); } - var firstDecision = decisions.FirstOrDefault(); - - if (firstDecision?.RemoteAlbum.ParsedAlbumInfo == null) + if (decision?.RemoteAlbum.ParsedAlbumInfo == null) { - throw new ValidationException(new List { new ValidationFailure("Title", "Unable to parse", release.Title) }); + throw new ValidationException(new List { new ("Title", "Unable to parse", release.Title) }); } - return MapDecisions(new[] { firstDecision }).First(); + return MapDecisions(new[] { decision }).First(); } private void ResolveIndexer(ReleaseInfo release) @@ -86,7 +93,7 @@ namespace Lidarr.Api.V1.Indexers } else { - _logger.Debug("Push Release {0} not associated with unknown indexer {1}.", release.Title, release.Indexer); + _logger.Debug("Push Release {0} not associated with known indexer {1}.", release.Title, release.Indexer); } } else if (release.IndexerId != 0 && release.Indexer.IsNullOrWhiteSpace()) @@ -99,7 +106,7 @@ namespace Lidarr.Api.V1.Indexers } catch (ModelNotFoundException) { - _logger.Debug("Push Release {0} not associated with unknown indexer {1}.", release.Title, release.IndexerId); + _logger.Debug("Push Release {0} not associated with known indexer {1}.", release.Title, release.IndexerId); release.IndexerId = 0; } } @@ -108,5 +115,26 @@ namespace Lidarr.Api.V1.Indexers _logger.Debug("Push Release {0} not associated with an indexer.", release.Title); } } + + private int? ResolveDownloadClientId(ReleaseResource release) + { + var downloadClientId = release.DownloadClientId.GetValueOrDefault(); + + if (downloadClientId == 0 && release.DownloadClient.IsNotNullOrWhiteSpace()) + { + var downloadClient = _downloadClientFactory.All().FirstOrDefault(v => v.Name.EqualsIgnoreCase(release.DownloadClient)); + + if (downloadClient != null) + { + _logger.Debug("Push Release {0} associated with download client {1} - {2}.", release.Title, downloadClientId, release.DownloadClient); + + return downloadClient.Id; + } + + _logger.Debug("Push Release {0} not associated with known download client {1}.", release.Title, release.DownloadClient); + } + + return release.DownloadClientId; + } } } diff --git a/src/Lidarr.Api.V1/Indexers/ReleaseResource.cs b/src/Lidarr.Api.V1/Indexers/ReleaseResource.cs index ca9acd4d1..5ad2b70d0 100644 --- a/src/Lidarr.Api.V1/Indexers/ReleaseResource.cs +++ b/src/Lidarr.Api.V1/Indexers/ReleaseResource.cs @@ -60,6 +60,12 @@ namespace Lidarr.Api.V1.Indexers // [JsonIgnore] public int? AlbumId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public int? DownloadClientId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public string DownloadClient { get; set; } } public static class ReleaseResourceMapper diff --git a/src/Lidarr.Api.V1/Notifications/NotificationResource.cs b/src/Lidarr.Api.V1/Notifications/NotificationResource.cs index 0f28e8140..96a80d382 100644 --- a/src/Lidarr.Api.V1/Notifications/NotificationResource.cs +++ b/src/Lidarr.Api.V1/Notifications/NotificationResource.cs @@ -9,8 +9,9 @@ namespace Lidarr.Api.V1.Notifications public bool OnReleaseImport { get; set; } public bool OnUpgrade { get; set; } public bool OnRename { get; set; } - public bool OnAlbumDelete { get; set; } + public bool OnArtistAdd { get; set; } public bool OnArtistDelete { get; set; } + public bool OnAlbumDelete { get; set; } public bool OnHealthIssue { get; set; } public bool OnHealthRestored { get; set; } public bool OnDownloadFailure { get; set; } @@ -21,8 +22,9 @@ namespace Lidarr.Api.V1.Notifications public bool SupportsOnReleaseImport { get; set; } public bool SupportsOnUpgrade { get; set; } public bool SupportsOnRename { get; set; } - public bool SupportsOnAlbumDelete { get; set; } + public bool SupportsOnArtistAdd { get; set; } public bool SupportsOnArtistDelete { get; set; } + public bool SupportsOnAlbumDelete { get; set; } public bool SupportsOnHealthIssue { get; set; } public bool SupportsOnHealthRestored { get; set; } public bool IncludeHealthWarnings { get; set; } @@ -48,8 +50,9 @@ namespace Lidarr.Api.V1.Notifications resource.OnReleaseImport = definition.OnReleaseImport; resource.OnUpgrade = definition.OnUpgrade; resource.OnRename = definition.OnRename; - resource.OnAlbumDelete = definition.OnAlbumDelete; + resource.OnArtistAdd = definition.OnArtistAdd; resource.OnArtistDelete = definition.OnArtistDelete; + resource.OnAlbumDelete = definition.OnAlbumDelete; resource.OnHealthIssue = definition.OnHealthIssue; resource.OnHealthRestored = definition.OnHealthRestored; resource.OnDownloadFailure = definition.OnDownloadFailure; @@ -60,8 +63,9 @@ namespace Lidarr.Api.V1.Notifications resource.SupportsOnReleaseImport = definition.SupportsOnReleaseImport; resource.SupportsOnUpgrade = definition.SupportsOnUpgrade; resource.SupportsOnRename = definition.SupportsOnRename; - resource.SupportsOnAlbumDelete = definition.SupportsOnAlbumDelete; + resource.SupportsOnArtistAdd = definition.SupportsOnArtistAdd; resource.SupportsOnArtistDelete = definition.SupportsOnArtistDelete; + resource.SupportsOnAlbumDelete = definition.SupportsOnAlbumDelete; resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue; resource.SupportsOnHealthRestored = definition.SupportsOnHealthRestored; resource.IncludeHealthWarnings = definition.IncludeHealthWarnings; @@ -86,8 +90,9 @@ namespace Lidarr.Api.V1.Notifications definition.OnReleaseImport = resource.OnReleaseImport; definition.OnUpgrade = resource.OnUpgrade; definition.OnRename = resource.OnRename; - definition.OnAlbumDelete = resource.OnAlbumDelete; + definition.OnArtistAdd = resource.OnArtistAdd; definition.OnArtistDelete = resource.OnArtistDelete; + definition.OnAlbumDelete = resource.OnAlbumDelete; definition.OnHealthIssue = resource.OnHealthIssue; definition.OnHealthRestored = resource.OnHealthRestored; definition.OnDownloadFailure = resource.OnDownloadFailure; @@ -98,8 +103,9 @@ namespace Lidarr.Api.V1.Notifications definition.SupportsOnReleaseImport = resource.SupportsOnReleaseImport; definition.SupportsOnUpgrade = resource.SupportsOnUpgrade; definition.SupportsOnRename = resource.SupportsOnRename; - definition.SupportsOnAlbumDelete = resource.SupportsOnAlbumDelete; + definition.SupportsOnArtistAdd = resource.SupportsOnArtistAdd; definition.SupportsOnArtistDelete = resource.SupportsOnArtistDelete; + definition.SupportsOnAlbumDelete = resource.SupportsOnAlbumDelete; definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue; definition.SupportsOnHealthRestored = resource.SupportsOnHealthRestored; definition.IncludeHealthWarnings = resource.IncludeHealthWarnings; diff --git a/src/Lidarr.Api.V1/Parse/ParseController.cs b/src/Lidarr.Api.V1/Parse/ParseController.cs index 2c8bfffaa..ddaed6411 100644 --- a/src/Lidarr.Api.V1/Parse/ParseController.cs +++ b/src/Lidarr.Api.V1/Parse/ParseController.cs @@ -1,7 +1,11 @@ using Lidarr.Api.V1.Albums; using Lidarr.Api.V1.Artist; +using Lidarr.Api.V1.CustomFormats; using Lidarr.Http; using Microsoft.AspNetCore.Mvc; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Download.Aggregation; using NzbDrone.Core.Parser; namespace Lidarr.Api.V1.Parse @@ -10,16 +14,27 @@ namespace Lidarr.Api.V1.Parse public class ParseController : Controller { private readonly IParsingService _parsingService; + private readonly IRemoteAlbumAggregationService _aggregationService; + private readonly ICustomFormatCalculationService _formatCalculator; - public ParseController(IParsingService parsingService) + public ParseController(IParsingService parsingService, + IRemoteAlbumAggregationService aggregationService, + ICustomFormatCalculationService formatCalculator) { _parsingService = parsingService; + _aggregationService = aggregationService; + _formatCalculator = formatCalculator; } [HttpGet] [Produces("application/json")] public ParseResource Parse(string title) { + if (title.IsNullOrWhiteSpace()) + { + return null; + } + var parsedAlbumInfo = Parser.ParseAlbumTitle(title); if (parsedAlbumInfo == null) @@ -34,12 +49,19 @@ namespace Lidarr.Api.V1.Parse if (remoteAlbum != null) { + _aggregationService.Augment(remoteAlbum); + + remoteAlbum.CustomFormats = _formatCalculator.ParseCustomFormat(remoteAlbum, 0); + remoteAlbum.CustomFormatScore = remoteAlbum?.Artist?.QualityProfile?.Value.CalculateCustomFormatScore(remoteAlbum.CustomFormats) ?? 0; + return new ParseResource { Title = title, ParsedAlbumInfo = remoteAlbum.ParsedAlbumInfo, Artist = remoteAlbum.Artist.ToResource(), - Albums = remoteAlbum.Albums.ToResource() + Albums = remoteAlbum.Albums.ToResource(), + CustomFormats = remoteAlbum.CustomFormats?.ToResource(false), + CustomFormatScore = remoteAlbum.CustomFormatScore }; } else diff --git a/src/Lidarr.Api.V1/Parse/ParseResource.cs b/src/Lidarr.Api.V1/Parse/ParseResource.cs index b7b22de3c..52c5310d3 100644 --- a/src/Lidarr.Api.V1/Parse/ParseResource.cs +++ b/src/Lidarr.Api.V1/Parse/ParseResource.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Lidarr.Api.V1.Albums; using Lidarr.Api.V1.Artist; +using Lidarr.Api.V1.CustomFormats; using Lidarr.Http.REST; using NzbDrone.Core.Parser.Model; @@ -12,5 +13,7 @@ namespace Lidarr.Api.V1.Parse public ParsedAlbumInfo ParsedAlbumInfo { get; set; } public ArtistResource Artist { get; set; } public List Albums { get; set; } + public List CustomFormats { get; set; } + public int CustomFormatScore { get; set; } } } diff --git a/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs b/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs index daedc62c3..854e91b65 100644 --- a/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs +++ b/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs @@ -15,6 +15,7 @@ namespace Lidarr.Api.V1.Qualities public double? MinSize { get; set; } public double? MaxSize { get; set; } + public double? PreferredSize { get; set; } } public static class QualityDefinitionResourceMapper @@ -33,7 +34,8 @@ namespace Lidarr.Api.V1.Qualities Title = model.Title, Weight = model.Weight, MinSize = model.MinSize, - MaxSize = model.MaxSize + MaxSize = model.MaxSize, + PreferredSize = model.PreferredSize }; } @@ -51,7 +53,8 @@ namespace Lidarr.Api.V1.Qualities Title = resource.Title, Weight = resource.Weight, MinSize = resource.MinSize, - MaxSize = resource.MaxSize + MaxSize = resource.MaxSize, + PreferredSize = resource.PreferredSize }; } diff --git a/src/Lidarr.Api.V1/Queue/QueueActionController.cs b/src/Lidarr.Api.V1/Queue/QueueActionController.cs index d29f7b43f..09adc5397 100644 --- a/src/Lidarr.Api.V1/Queue/QueueActionController.cs +++ b/src/Lidarr.Api.V1/Queue/QueueActionController.cs @@ -30,7 +30,7 @@ namespace Lidarr.Api.V1.Queue throw new NotFoundException(); } - await _downloadService.DownloadReport(pendingRelease.RemoteAlbum); + await _downloadService.DownloadReport(pendingRelease.RemoteAlbum, null); return new { }; } @@ -48,7 +48,7 @@ namespace Lidarr.Api.V1.Queue throw new NotFoundException(); } - await _downloadService.DownloadReport(pendingRelease.RemoteAlbum); + await _downloadService.DownloadReport(pendingRelease.RemoteAlbum, null); } return new { }; diff --git a/src/Lidarr.Api.V1/Queue/QueueController.cs b/src/Lidarr.Api.V1/Queue/QueueController.cs index 4f827a40f..3a584b23e 100644 --- a/src/Lidarr.Api.V1/Queue/QueueController.cs +++ b/src/Lidarr.Api.V1/Queue/QueueController.cs @@ -65,7 +65,7 @@ namespace Lidarr.Api.V1.Queue } [RestDeleteById] - public void RemoveAction(int id, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false) + public void RemoveAction(int id, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false, bool changeCategory = false) { var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id); @@ -83,12 +83,12 @@ namespace Lidarr.Api.V1.Queue throw new NotFoundException(); } - Remove(trackedDownload, removeFromClient, blocklist, skipRedownload); + Remove(trackedDownload, removeFromClient, blocklist, skipRedownload, changeCategory); _trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId); } [HttpDelete("bulk")] - public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false) + public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false, [FromQuery] bool changeCategory = false) { var trackedDownloadIds = new List(); var pendingToRemove = new List(); @@ -119,7 +119,7 @@ namespace Lidarr.Api.V1.Queue foreach (var trackedDownload in trackedToRemove.DistinctBy(t => t.DownloadItem.DownloadId)) { - Remove(trackedDownload, removeFromClient, blocklist, skipRedownload); + Remove(trackedDownload, removeFromClient, blocklist, skipRedownload, changeCategory); trackedDownloadIds.Add(trackedDownload.DownloadItem.DownloadId); } @@ -181,9 +181,16 @@ namespace Lidarr.Api.V1.Queue else if (pagingSpec.SortKey == "estimatedCompletionTime") { ordered = ascending - ? fullQueue.OrderBy(q => q.EstimatedCompletionTime, new EstimatedCompletionTimeComparer()) + ? fullQueue.OrderBy(q => q.EstimatedCompletionTime, new DatetimeComparer()) : fullQueue.OrderByDescending(q => q.EstimatedCompletionTime, - new EstimatedCompletionTimeComparer()); + new DatetimeComparer()); + } + else if (pagingSpec.SortKey == "added") + { + ordered = ascending + ? fullQueue.OrderBy(q => q.Added, new DatetimeComparer()) + : fullQueue.OrderByDescending(q => q.Added, + new DatetimeComparer()); } else if (pagingSpec.SortKey == "protocol") { @@ -262,7 +269,7 @@ namespace Lidarr.Api.V1.Queue _pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id); } - private TrackedDownload Remove(TrackedDownload trackedDownload, bool removeFromClient, bool blocklist, bool skipRedownload) + private TrackedDownload Remove(TrackedDownload trackedDownload, bool removeFromClient, bool blocklist, bool skipRedownload, bool changeCategory) { if (removeFromClient) { @@ -275,13 +282,24 @@ namespace Lidarr.Api.V1.Queue downloadClient.RemoveItem(trackedDownload.DownloadItem, true); } + else if (changeCategory) + { + var downloadClient = _downloadClientProvider.Get(trackedDownload.DownloadClient); + + if (downloadClient == null) + { + throw new BadRequestException(); + } + + downloadClient.MarkItemAsImported(trackedDownload.DownloadItem); + } if (blocklist) { _failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId, skipRedownload); } - if (!removeFromClient && !blocklist) + if (!removeFromClient && !blocklist && !changeCategory) { if (!_ignoredDownloadService.IgnoreDownload(trackedDownload)) { diff --git a/src/Lidarr.Api.V1/Queue/QueueResource.cs b/src/Lidarr.Api.V1/Queue/QueueResource.cs index f169db8be..25fab081d 100644 --- a/src/Lidarr.Api.V1/Queue/QueueResource.cs +++ b/src/Lidarr.Api.V1/Queue/QueueResource.cs @@ -26,6 +26,7 @@ namespace Lidarr.Api.V1.Queue public decimal Sizeleft { get; set; } public TimeSpan? Timeleft { get; set; } public DateTime? EstimatedCompletionTime { get; set; } + public DateTime? Added { get; set; } public string Status { get; set; } public TrackedDownloadStatus? TrackedDownloadStatus { get; set; } public TrackedDownloadState? TrackedDownloadState { get; set; } @@ -34,6 +35,7 @@ namespace Lidarr.Api.V1.Queue public string DownloadId { get; set; } public DownloadProtocol Protocol { get; set; } public string DownloadClient { get; set; } + public bool DownloadClientHasPostImportCategory { get; set; } public string Indexer { get; set; } public string OutputPath { get; set; } public bool DownloadForced { get; set; } @@ -66,6 +68,7 @@ namespace Lidarr.Api.V1.Queue Sizeleft = model.Sizeleft, Timeleft = model.Timeleft, EstimatedCompletionTime = model.EstimatedCompletionTime, + Added = model.Added, Status = model.Status.FirstCharToLower(), TrackedDownloadStatus = model.TrackedDownloadStatus, TrackedDownloadState = model.TrackedDownloadState, @@ -74,6 +77,7 @@ namespace Lidarr.Api.V1.Queue DownloadId = model.DownloadId, Protocol = model.Protocol, DownloadClient = model.DownloadClient, + DownloadClientHasPostImportCategory = model.DownloadClientHasPostImportCategory, Indexer = model.Indexer, OutputPath = model.OutputPath, DownloadForced = model.DownloadForced diff --git a/src/Lidarr.Api.V1/System/Backup/BackupController.cs b/src/Lidarr.Api.V1/System/Backup/BackupController.cs index 9b10fce10..fba675267 100644 --- a/src/Lidarr.Api.V1/System/Backup/BackupController.cs +++ b/src/Lidarr.Api.V1/System/Backup/BackupController.cs @@ -90,7 +90,7 @@ namespace Lidarr.Api.V1.System.Backup } [HttpPost("restore/upload")] - [RequestFormLimits(MultipartBodyLengthLimit = 500000000)] + [RequestFormLimits(MultipartBodyLengthLimit = 1000000000)] public object UploadAndRestore() { var files = Request.Form.Files; diff --git a/src/Lidarr.Api.V1/openapi.json b/src/Lidarr.Api.V1/openapi.json index fc9b166a3..60fb22607 100644 --- a/src/Lidarr.Api.V1/openapi.json +++ b/src/Lidarr.Api.V1/openapi.json @@ -2638,8 +2638,11 @@ "name": "eventType", "in": "query", "schema": { - "type": "integer", - "format": "int32" + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } } }, { @@ -6031,6 +6034,14 @@ "type": "boolean", "default": false } + }, + { + "name": "changeCategory", + "in": "query", + "schema": { + "type": "boolean", + "default": false + } } ], "responses": { @@ -6069,6 +6080,14 @@ "type": "boolean", "default": false } + }, + { + "name": "changeCategory", + "in": "query", + "schema": { + "type": "boolean", + "default": false + } } ], "requestBody": { @@ -6636,16 +6655,6 @@ "schema": { "$ref": "#/components/schemas/ReleaseResource" } - }, - "text/json": { - "schema": { - "$ref": "#/components/schemas/ReleaseResource" - } - }, - "application/*+json": { - "schema": { - "$ref": "#/components/schemas/ReleaseResource" - } } } }, @@ -9407,6 +9416,9 @@ }, "autoRedownloadFailed": { "type": "boolean" + }, + "autoRedownloadFailedFromInteractiveSearch": { + "type": "boolean" } }, "additionalProperties": false @@ -11100,6 +11112,17 @@ "$ref": "#/components/schemas/AlbumResource" }, "nullable": true + }, + "customFormats": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomFormatResource" + }, + "nullable": true + }, + "customFormatScore": { + "type": "integer", + "format": "int32" } }, "additionalProperties": false @@ -11437,6 +11460,11 @@ "type": "number", "format": "double", "nullable": true + }, + "preferredSize": { + "type": "number", + "format": "double", + "nullable": true } }, "additionalProperties": false @@ -11594,6 +11622,11 @@ "format": "date-time", "nullable": true }, + "added": { + "type": "string", + "format": "date-time", + "nullable": true + }, "status": { "type": "string", "nullable": true @@ -11626,6 +11659,9 @@ "type": "string", "nullable": true }, + "downloadClientHasPostImportCategory": { + "type": "boolean" + }, "indexer": { "type": "string", "nullable": true @@ -11936,6 +11972,15 @@ "type": "integer", "format": "int32", "nullable": true + }, + "downloadClientId": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "downloadClient": { + "type": "string", + "nullable": true } }, "additionalProperties": false diff --git a/src/Lidarr.Http/ClientSchema/SchemaBuilder.cs b/src/Lidarr.Http/ClientSchema/SchemaBuilder.cs index 9aacabbda..1ffa7ff8c 100644 --- a/src/Lidarr.Http/ClientSchema/SchemaBuilder.cs +++ b/src/Lidarr.Http/ClientSchema/SchemaBuilder.cs @@ -3,11 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text.Json; +using DryIoc; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.Extensions; using NzbDrone.Common.Reflection; using NzbDrone.Common.Serializer; using NzbDrone.Core.Annotations; +using NzbDrone.Core.Localization; namespace Lidarr.Http.ClientSchema { @@ -15,6 +17,12 @@ namespace Lidarr.Http.ClientSchema { private const string PRIVATE_VALUE = "********"; private static Dictionary _mappings = new Dictionary(); + private static ILocalizationService _localizationService; + + public static void Initialize(IContainer container) + { + _localizationService = container.Resolve(); + } public static List ToSchema(object model) { @@ -106,13 +114,27 @@ namespace Lidarr.Http.ClientSchema if (propertyInfo.PropertyType.IsSimpleType()) { var fieldAttribute = property.Item2; + + var label = fieldAttribute.Label.IsNotNullOrWhiteSpace() + ? _localizationService.GetLocalizedString(fieldAttribute.Label, + GetTokens(type, fieldAttribute.Label, TokenField.Label)) + : fieldAttribute.Label; + var helpText = fieldAttribute.HelpText.IsNotNullOrWhiteSpace() + ? _localizationService.GetLocalizedString(fieldAttribute.HelpText, + GetTokens(type, fieldAttribute.Label, TokenField.HelpText)) + : fieldAttribute.HelpText; + var helpTextWarning = fieldAttribute.HelpTextWarning.IsNotNullOrWhiteSpace() + ? _localizationService.GetLocalizedString(fieldAttribute.HelpTextWarning, + GetTokens(type, fieldAttribute.Label, TokenField.HelpTextWarning)) + : fieldAttribute.HelpTextWarning; + var field = new Field { Name = prefix + GetCamelCaseName(propertyInfo.Name), - Label = fieldAttribute.Label, + Label = label, Unit = fieldAttribute.Unit, - HelpText = fieldAttribute.HelpText, - HelpTextWarning = fieldAttribute.HelpTextWarning, + HelpText = helpText, + HelpTextWarning = helpTextWarning, HelpLink = fieldAttribute.HelpLink, Order = fieldAttribute.Order, Advanced = fieldAttribute.Advanced, @@ -172,6 +194,24 @@ namespace Lidarr.Http.ClientSchema .ToArray(); } + private static Dictionary GetTokens(Type type, string label, TokenField field) + { + var tokens = new Dictionary(); + + foreach (var propertyInfo in type.GetProperties()) + { + foreach (var attribute in propertyInfo.GetCustomAttributes(true)) + { + if (attribute is FieldTokenAttribute fieldTokenAttribute && fieldTokenAttribute.Field == field && fieldTokenAttribute.Label == label) + { + tokens.Add(fieldTokenAttribute.Token, fieldTokenAttribute.Value); + } + } + } + + return tokens; + } + private static List GetSelectOptions(Type selectOptions) { if (selectOptions.IsEnum) diff --git a/src/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs b/src/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs index de47d96ae..cb12aff19 100644 --- a/src/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs +++ b/src/NzbDrone.Api.Test/ClientSchemaTests/SchemaBuilderFixture.cs @@ -1,7 +1,10 @@ +using System.Collections.Generic; using FluentAssertions; using Lidarr.Http.ClientSchema; +using Moq; using NUnit.Framework; using NzbDrone.Core.Annotations; +using NzbDrone.Core.Localization; using NzbDrone.Test.Common; namespace NzbDrone.Api.Test.ClientSchemaTests @@ -9,6 +12,16 @@ namespace NzbDrone.Api.Test.ClientSchemaTests [TestFixture] public class SchemaBuilderFixture : TestBase { + [SetUp] + public void Setup() + { + Mocker.GetMock() + .Setup(s => s.GetLocalizedString(It.IsAny(), It.IsAny>())) + .Returns>((s, d) => s); + + SchemaBuilder.Initialize(Mocker.Container); + } + [Test] public void should_return_field_for_every_property() { diff --git a/src/NzbDrone.Common/Http/XmlRpcRequestBuilder.cs b/src/NzbDrone.Common/Http/XmlRpcRequestBuilder.cs index e03161702..e7ab0126d 100644 --- a/src/NzbDrone.Common/Http/XmlRpcRequestBuilder.cs +++ b/src/NzbDrone.Common/Http/XmlRpcRequestBuilder.cs @@ -92,6 +92,10 @@ namespace NzbDrone.Common.Http { data = new XElement("base64", Convert.ToBase64String(bytes)); } + else if (value is Dictionary d) + { + data = new XElement("struct", d.Select(p => new XElement("member", new XElement("name", p.Key), new XElement("value", p.Value)))); + } else { throw new InvalidOperationException($"Unhandled argument type {value.GetType().Name}"); diff --git a/src/NzbDrone.Common/Lidarr.Common.csproj b/src/NzbDrone.Common/Lidarr.Common.csproj index 10794a704..29e481cfc 100644 --- a/src/NzbDrone.Common/Lidarr.Common.csproj +++ b/src/NzbDrone.Common/Lidarr.Common.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs index 4a2b062fb..7a6b7e479 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs @@ -25,12 +25,30 @@ namespace NzbDrone.Core.Test.DecisionEngineTests public void Setup() { GivenPreferredDownloadProtocol(DownloadProtocol.Usenet); + + Mocker.GetMock() + .Setup(s => s.Get(It.IsAny())) + .Returns(new QualityDefinition { PreferredSize = null }); + } + + private void GivenPreferredSize(double? size) + { + Mocker.GetMock() + .Setup(s => s.Get(It.IsAny())) + .Returns(new QualityDefinition { PreferredSize = size }); } private Album GivenAlbum(int id) { + var release = Builder.CreateNew() + .With(e => e.AlbumId = id) + .With(e => e.Monitored = true) + .With(e => e.Duration = 3600000) + .Build(); + return Builder.CreateNew() .With(e => e.Id = id) + .With(e => e.AlbumReleases = new List { release }) .Build(); } @@ -130,6 +148,44 @@ namespace NzbDrone.Core.Test.DecisionEngineTests qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumHdLargeYoung); } + [Test] + public void should_order_by_closest_to_preferred_size_if_both_under() + { + // 1000 Kibit/Sec * 60 Min Duration = 439.5 MiB + GivenPreferredSize(1000); + + var remoteAlbumSmall = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 120.Megabytes(), age: 1); + var remoteAlbumLarge = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 400.Megabytes(), age: 1); + + var decisions = new List(); + decisions.Add(new DownloadDecision(remoteAlbumSmall)); + decisions.Add(new DownloadDecision(remoteAlbumLarge)); + + var qualifiedReports = Subject.PrioritizeDecisions(decisions); + qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumLarge); + } + + [Test] + public void should_order_by_closest_to_preferred_size_if_preferred_is_in_between() + { + // 700 Kibit/Sec * 60 Min Duration = 307.6 MiB + GivenPreferredSize(700); + + var remoteAlbum1 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 100.Megabytes(), age: 1); + var remoteAlbum2 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 200.Megabytes(), age: 1); + var remoteAlbum3 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 300.Megabytes(), age: 1); + var remoteAlbum4 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes(), age: 1); + + var decisions = new List(); + decisions.Add(new DownloadDecision(remoteAlbum1)); + decisions.Add(new DownloadDecision(remoteAlbum2)); + decisions.Add(new DownloadDecision(remoteAlbum3)); + decisions.Add(new DownloadDecision(remoteAlbum4)); + + var qualifiedReports = Subject.PrioritizeDecisions(decisions); + qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbum3); + } + [Test] public void should_order_by_youngest() { diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/QueueSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/QueueSpecificationFixture.cs index 4add10856..2ba6432b9 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/QueueSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/QueueSpecificationFixture.cs @@ -4,6 +4,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.Configuration; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download.TrackedDownloads; @@ -369,5 +370,31 @@ namespace NzbDrone.Core.Test.DecisionEngineTests Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeTrue(); } + + [Test] + public void should_return_false_if_same_quality_non_proper_in_queue_and_download_propers_is_do_not_upgrade() + { + _remoteAlbum.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_008, new Revision(2)); + _artist.QualityProfile.Value.Cutoff = _remoteAlbum.ParsedAlbumInfo.Quality.Quality.Id; + + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotUpgrade); + + var remoteAlbum = Builder.CreateNew() + .With(r => r.Artist = _artist) + .With(r => r.Albums = new List { _album }) + .With(r => r.ParsedAlbumInfo = new ParsedAlbumInfo + { + Quality = new QualityModel(Quality.MP3_008) + }) + .With(r => r.Release = _releaseInfo) + .With(r => r.CustomFormats = new List()) + .Build(); + + GivenQueue(new List { remoteAlbum }); + + Subject.IsSatisfiedBy(_remoteAlbum, null).Accepted.Should().BeFalse(); + } } } diff --git a/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs index 7e00b0680..569c9b0c9 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadApprovedReportsTests/DownloadApprovedFixture.cs @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum)); await Subject.ProcessDecisions(decisions); - Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny()), Times.Once()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny(), null), Times.Once()); } [Test] @@ -82,7 +82,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum)); await Subject.ProcessDecisions(decisions); - Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny()), Times.Once()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny(), null), Times.Once()); } [Test] @@ -101,7 +101,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum2)); await Subject.ProcessDecisions(decisions); - Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny()), Times.Once()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny(), null), Times.Once()); } [Test] @@ -172,7 +172,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests var decisions = new List(); decisions.Add(new DownloadDecision(remoteAlbum)); - Mocker.GetMock().Setup(s => s.DownloadReport(It.IsAny())).Throws(new Exception()); + Mocker.GetMock().Setup(s => s.DownloadReport(It.IsAny(), null)).Throws(new Exception()); var result = await Subject.ProcessDecisions(decisions); @@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary))); await Subject.ProcessDecisions(decisions); - Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny()), Times.Never()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny(), null), Times.Never()); } [Test] @@ -242,11 +242,11 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum)); - Mocker.GetMock().Setup(s => s.DownloadReport(It.IsAny())) + Mocker.GetMock().Setup(s => s.DownloadReport(It.IsAny(), null)) .Throws(new DownloadClientUnavailableException("Download client failed")); await Subject.ProcessDecisions(decisions); - Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny()), Times.Once()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.IsAny(), null), Times.Once()); } [Test] @@ -260,12 +260,12 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum2)); - Mocker.GetMock().Setup(s => s.DownloadReport(It.Is(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet))) + Mocker.GetMock().Setup(s => s.DownloadReport(It.Is(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet), null)) .Throws(new DownloadClientUnavailableException("Download client failed")); await Subject.ProcessDecisions(decisions); - Mocker.GetMock().Verify(v => v.DownloadReport(It.Is(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet)), Times.Once()); - Mocker.GetMock().Verify(v => v.DownloadReport(It.Is(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent)), Times.Once()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.Is(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet), null), Times.Once()); + Mocker.GetMock().Verify(v => v.DownloadReport(It.Is(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent), null), Times.Once()); } [Test] @@ -278,7 +278,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests decisions.Add(new DownloadDecision(remoteAlbum)); Mocker.GetMock() - .Setup(s => s.DownloadReport(It.IsAny())) + .Setup(s => s.DownloadReport(It.IsAny(), null)) .Throws(new ReleaseUnavailableException(remoteAlbum.Release, "That 404 Error is not just a Quirk")); var result = await Subject.ProcessDecisions(decisions); diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs index 0178d643a..e22ede193 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/SabnzbdTests/SabnzbdFixture.cs @@ -454,6 +454,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests [TestCase("0")] [TestCase("15d")] + [TestCase("")] + [TestCase(null)] public void should_set_history_removes_completed_downloads_false(string historyRetention) { _config.Misc.history_retention = historyRetention; diff --git a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs index 27cae1e9a..132ffc7df 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs @@ -83,7 +83,7 @@ namespace NzbDrone.Core.Test.Download var mock = WithUsenetClient(); mock.Setup(s => s.Download(It.IsAny(), It.IsAny())); - await Subject.DownloadReport(_parseResult); + await Subject.DownloadReport(_parseResult, null); VerifyEventPublished(); } @@ -94,7 +94,7 @@ namespace NzbDrone.Core.Test.Download var mock = WithUsenetClient(); mock.Setup(s => s.Download(It.IsAny(), It.IsAny())); - await Subject.DownloadReport(_parseResult); + await Subject.DownloadReport(_parseResult, null); mock.Verify(s => s.Download(It.IsAny(), It.IsAny()), Times.Once()); } @@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.Download mock.Setup(s => s.Download(It.IsAny(), It.IsAny())) .Throws(new WebException()); - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); VerifyEventNotPublished(); } @@ -121,7 +121,7 @@ namespace NzbDrone.Core.Test.Download throw new ReleaseDownloadException(v.Release, "Error", new WebException()); }); - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); Mocker.GetMock() .Verify(v => v.RecordFailure(It.IsAny(), It.IsAny()), Times.Once()); @@ -141,7 +141,7 @@ namespace NzbDrone.Core.Test.Download throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response)); }); - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); Mocker.GetMock() .Verify(v => v.RecordFailure(It.IsAny(), TimeSpan.FromMinutes(5.0)), Times.Once()); @@ -161,7 +161,7 @@ namespace NzbDrone.Core.Test.Download throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response)); }); - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); Mocker.GetMock() .Verify(v => v.RecordFailure(It.IsAny(), @@ -175,7 +175,7 @@ namespace NzbDrone.Core.Test.Download mock.Setup(s => s.Download(It.IsAny(), It.IsAny())) .Throws(new DownloadClientException("Some Error")); - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); Mocker.GetMock() .Verify(v => v.RecordFailure(It.IsAny(), It.IsAny()), Times.Never()); @@ -191,7 +191,7 @@ namespace NzbDrone.Core.Test.Download throw new ReleaseUnavailableException(v.Release, "Error", new WebException()); }); - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); Mocker.GetMock() .Verify(v => v.RecordFailure(It.IsAny(), It.IsAny()), Times.Never()); @@ -200,7 +200,7 @@ namespace NzbDrone.Core.Test.Download [Test] public void should_not_attempt_download_if_client_isnt_configured() { - Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult)); + Assert.ThrowsAsync(async () => await Subject.DownloadReport(_parseResult, null)); Mocker.GetMock().Verify(c => c.Download(It.IsAny(), It.IsAny()), Times.Never()); VerifyEventNotPublished(); @@ -222,7 +222,7 @@ namespace NzbDrone.Core.Test.Download } }); - await Subject.DownloadReport(_parseResult); + await Subject.DownloadReport(_parseResult, null); Mocker.GetMock().Verify(c => c.GetBlockedProviders(), Times.Never()); mockUsenet.Verify(c => c.Download(It.IsAny(), It.IsAny()), Times.Once()); @@ -235,7 +235,7 @@ namespace NzbDrone.Core.Test.Download var mockTorrent = WithTorrentClient(); var mockUsenet = WithUsenetClient(); - await Subject.DownloadReport(_parseResult); + await Subject.DownloadReport(_parseResult, null); mockTorrent.Verify(c => c.Download(It.IsAny(), It.IsAny()), Times.Never()); mockUsenet.Verify(c => c.Download(It.IsAny(), It.IsAny()), Times.Once()); @@ -249,7 +249,7 @@ namespace NzbDrone.Core.Test.Download _parseResult.Release.DownloadProtocol = DownloadProtocol.Torrent; - await Subject.DownloadReport(_parseResult); + await Subject.DownloadReport(_parseResult, null); mockTorrent.Verify(c => c.Download(It.IsAny(), It.IsAny()), Times.Once()); mockUsenet.Verify(c => c.Download(It.IsAny(), It.IsAny()), Times.Never()); diff --git a/src/NzbDrone.Core.Test/Download/Pending/PendingReleaseServiceTests/PendingReleaseServiceFixture.cs b/src/NzbDrone.Core.Test/Download/Pending/PendingReleaseServiceTests/PendingReleaseServiceFixture.cs index 5933db2e4..1b559c46e 100644 --- a/src/NzbDrone.Core.Test/Download/Pending/PendingReleaseServiceTests/PendingReleaseServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Download/Pending/PendingReleaseServiceTests/PendingReleaseServiceFixture.cs @@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests results.Should().NotBeEmpty(); Mocker.GetMock() - .Verify(v => v.GetRssDecision(It.Is>(d => d.Count == 0)), Times.Never()); + .Verify(v => v.GetRssDecision(It.Is>(d => d.Count == 0), It.IsAny()), Times.Never()); } [Test] diff --git a/src/NzbDrone.Core.Test/IndexerTests/FileListTests/FileListFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/FileListTests/FileListFixture.cs index 995332eca..91128bd1a 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/FileListTests/FileListFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/FileListTests/FileListFixture.cs @@ -33,7 +33,7 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests Mocker.GetMock() .Setup(o => o.ExecuteAsync(It.Is(v => v.Method == HttpMethod.Get))) - .Returns(r => Task.FromResult(new HttpResponse(r, new HttpHeader(), recentFeed))); + .Returns(r => Task.FromResult(new HttpResponse(r, new HttpHeader { { "Content-Type", "application/json" } }, recentFeed))); var releases = await Subject.FetchRecent(); diff --git a/src/NzbDrone.Core.Test/IndexerTests/RedactedTests/RedactedFixture.cs b/src/NzbDrone.Core.Test/IndexerTests/RedactedTests/RedactedFixture.cs index 06b462283..f08bc8b1b 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/RedactedTests/RedactedFixture.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/RedactedTests/RedactedFixture.cs @@ -45,9 +45,9 @@ namespace NzbDrone.Core.Test.IndexerTests.RedactedTests var releaseInfo = releases.First(); - releaseInfo.Title.Should().Be("Shania Twain - Shania Twain (1993) [FLAC 24bit Lossless] [WEB]"); + releaseInfo.Title.Should().Be("Shania Twain - Shania Twain (1993) [Album] [FLAC 24bit Lossless / WEB]"); releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent); - releaseInfo.DownloadUrl.Should().Be("https://redacted.ch/ajax.php?action=download&id=1541452&usetoken=0"); + releaseInfo.DownloadUrl.Should().Be("https://redacted.ch/ajax.php?action=download&id=1541452"); releaseInfo.InfoUrl.Should().Be("https://redacted.ch/torrents.php?id=106951&torrentid=1541452"); releaseInfo.CommentUrl.Should().Be(null); releaseInfo.Indexer.Should().Be(Subject.Definition.Name); diff --git a/src/NzbDrone.Core.Test/ParserTests/NormalizeTitleFixture.cs b/src/NzbDrone.Core.Test/ParserTests/NormalizeTitleFixture.cs index f2af9134e..8099c0973 100644 --- a/src/NzbDrone.Core.Test/ParserTests/NormalizeTitleFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/NormalizeTitleFixture.cs @@ -35,16 +35,13 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("or")] [TestCase("an")] [TestCase("of")] - public void should_remove_common_words(string word) + public void should_remove_common_words_from_middle_of_title(string word) { var dirtyFormat = new[] { "word.{0}.word", "word {0} word", - "word-{0}-word", - "word.word.{0}", - "word-word-{0}", - "word-word {0}", + "word-{0}-word" }; foreach (var s in dirtyFormat) @@ -54,6 +51,27 @@ namespace NzbDrone.Core.Test.ParserTests } } + [TestCase("the")] + [TestCase("and")] + [TestCase("or")] + [TestCase("an")] + [TestCase("of")] + public void should_not_remove_common_words_from_end_of_title(string word) + { + var dirtyFormat = new[] + { + "word.word.{0}", + "word-word-{0}", + "word-word {0}" + }; + + foreach (var s in dirtyFormat) + { + var dirty = string.Format(s, word); + dirty.CleanArtistName().Should().Be("wordword" + word.ToLower()); + } + } + [Test] public void should_remove_a_from_middle_of_title() { diff --git a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs index 4b5c2e83f..cc4db4e50 100644 --- a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs @@ -310,9 +310,15 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Artist Title - Album Title 2017 REPACK FLAC aAF", true, 2)] [TestCase("Artist.Title-Album.Title.2017.REPACK.FLAC-aAF", true, 2)] [TestCase("Artist.Title-Album.Title.2017.REPACK2.FLAC-aAF", true, 3)] - [TestCase("Artist Title - Album Title 2017 RERIP FLAC aAF", true, 2)] - [TestCase("Artist Title - Album Title 2017 RERIP2 FLAC aAF", true, 3)] - [TestCase("Artist Title - Album Title 2017 PROPER FLAC aAF", false, 2)] + [TestCase("Artist.Title-Album.Title.2017.PROPER.FLAC-aAF", false, 2)] + [TestCase("Artist.Title-Album.Title.2017.RERIP.FLAC-DEMAND", true, 2)] + [TestCase("Artist.Title-Album.Title.2017.RERIP2.FLAC-DEMAND", true, 3)] + [TestCase("Artist Title - Album Title 2017 MP3 V2 (VBR) aAF", false, 1)] + [TestCase("Artist.Title-Album.Title.2017.MP3.V2.VBR-aAF", false, 1)] + [TestCase("Artist.Title-Album.Title.2017.MP3.V2.VBR-aAF", false, 1)] + [TestCase("Artist.Title-Album.Title.2017.MP3.V2.VBR-aAF", false, 1)] + [TestCase("Artist.Title-Album.Title.2017.MP3.V2.VBR-DEMAND", false, 1)] + [TestCase("Artist.Title-Album.Title.2017.MP3.V2.VBR-DEMAND", false, 1)] public void should_be_able_to_parse_repack(string title, bool isRepack, int version) { var result = QualityParser.ParseQuality(title, null, 0); diff --git a/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs b/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs index 8d098d7f6..4a56117c3 100644 --- a/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs +++ b/src/NzbDrone.Core/Annotations/FieldDefinitionAttribute.cs @@ -41,6 +41,23 @@ namespace NzbDrone.Core.Annotations public string Hint { get; set; } } + [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] + public class FieldTokenAttribute : Attribute + { + public FieldTokenAttribute(TokenField field, string label = "", string token = "", object value = null) + { + Label = label; + Field = field; + Token = token; + Value = value?.ToString(); + } + + public string Label { get; set; } + public TokenField Field { get; set; } + public string Token { get; set; } + public string Value { get; set; } + } + public class FieldSelectOption { public int Value { get; set; } @@ -86,4 +103,11 @@ namespace NzbDrone.Core.Annotations ApiKey, UserName } + + public enum TokenField + { + Label, + HelpText, + HelpTextWarning + } } diff --git a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs index 783d94782..6734a3318 100644 --- a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs +++ b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs @@ -15,6 +15,7 @@ namespace NzbDrone.Core.Blocklisting public interface IBlocklistService { bool Blocklisted(int artistId, ReleaseInfo release); + bool BlocklistedTorrentHash(int artistId, string hash); PagingSpec Paged(PagingSpec pagingSpec); void Block(RemoteAlbum remoteAlbum, string message); void Delete(int id); @@ -36,30 +37,34 @@ namespace NzbDrone.Core.Blocklisting public bool Blocklisted(int artistId, ReleaseInfo release) { - var blocklistedByTitle = _blocklistRepository.BlocklistedByTitle(artistId, release.Title); - if (release.DownloadProtocol == DownloadProtocol.Torrent) { - var torrentInfo = release as TorrentInfo; - - if (torrentInfo == null) + if (release is not TorrentInfo torrentInfo) { return false; } - if (torrentInfo.InfoHash.IsNullOrWhiteSpace()) + if (torrentInfo.InfoHash.IsNotNullOrWhiteSpace()) { - return blocklistedByTitle.Where(b => b.Protocol == DownloadProtocol.Torrent) - .Any(b => SameTorrent(b, torrentInfo)); + var blocklistedByTorrentInfohash = _blocklistRepository.BlocklistedByTorrentInfoHash(artistId, torrentInfo.InfoHash); + + return blocklistedByTorrentInfohash.Any(b => SameTorrent(b, torrentInfo)); } - var blocklistedByTorrentInfohash = _blocklistRepository.BlocklistedByTorrentInfoHash(artistId, torrentInfo.InfoHash); - - return blocklistedByTorrentInfohash.Any(b => SameTorrent(b, torrentInfo)); + return _blocklistRepository.BlocklistedByTitle(artistId, release.Title) + .Where(b => b.Protocol == DownloadProtocol.Torrent) + .Any(b => SameTorrent(b, torrentInfo)); } - return blocklistedByTitle.Where(b => b.Protocol == DownloadProtocol.Usenet) - .Any(b => SameNzb(b, release)); + return _blocklistRepository.BlocklistedByTitle(artistId, release.Title) + .Where(b => b.Protocol == DownloadProtocol.Usenet) + .Any(b => SameNzb(b, release)); + } + + public bool BlocklistedTorrentHash(int artistId, string hash) + { + return _blocklistRepository.BlocklistedByTorrentInfoHash(artistId, hash).Any(b => + b.TorrentInfoHash.Equals(hash, StringComparison.InvariantCultureIgnoreCase)); } public PagingSpec Paged(PagingSpec pagingSpec) diff --git a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs index 03bbeb151..6ccf4fadc 100644 --- a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs +++ b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs @@ -329,8 +329,8 @@ namespace NzbDrone.Core.Configuration return; } - // If SSL is enabled and a cert hash is still in the config file disable SSL - if (EnableSsl && GetValue("SslCertHash", null).IsNotNullOrWhiteSpace()) + // If SSL is enabled and a cert hash is still in the config file or cert path is empty disable SSL + if (EnableSsl && (GetValue("SslCertHash", null).IsNotNullOrWhiteSpace() || SslCertPath.IsNullOrWhiteSpace())) { SetValue("EnableSsl", false); } diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index 89760de37..84a2bfe6d 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -144,6 +144,13 @@ namespace NzbDrone.Core.Configuration set { SetValue("AutoRedownloadFailed", value); } } + public bool AutoRedownloadFailedFromInteractiveSearch + { + get { return GetValueBoolean("AutoRedownloadFailedFromInteractiveSearch", true); } + + set { SetValue("AutoRedownloadFailedFromInteractiveSearch", value); } + } + public bool CreateEmptyArtistFolders { get { return GetValueBoolean("CreateEmptyArtistFolders", false); } diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index 6cef2ad88..4009ffb6d 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -20,6 +20,7 @@ namespace NzbDrone.Core.Configuration bool EnableCompletedDownloadHandling { get; set; } bool AutoRedownloadFailed { get; set; } + bool AutoRedownloadFailedFromInteractiveSearch { get; set; } // Media Management bool AutoUnmonitorPreviouslyDownloadedTracks { get; set; } diff --git a/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs b/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs index a6ef214fc..253bdcfdc 100644 --- a/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs +++ b/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Core.Blocklisting; using NzbDrone.Core.History; @@ -23,10 +24,12 @@ namespace NzbDrone.Core.CustomFormats public class CustomFormatCalculationService : ICustomFormatCalculationService { private readonly ICustomFormatService _formatService; + private readonly Logger _logger; - public CustomFormatCalculationService(ICustomFormatService formatService) + public CustomFormatCalculationService(ICustomFormatService formatService, Logger logger) { _formatService = formatService; + _logger = logger; } public List ParseCustomFormat(RemoteAlbum remoteAlbum, long size) @@ -145,26 +148,30 @@ namespace NzbDrone.Core.CustomFormats return matches.OrderBy(x => x.Name).ToList(); } - private static List ParseCustomFormat(TrackFile trackFile, Artist artist, List allCustomFormats) + private List ParseCustomFormat(TrackFile trackFile, Artist artist, List allCustomFormats) { - var sceneName = string.Empty; + var releaseTitle = string.Empty; + if (trackFile.SceneName.IsNotNullOrWhiteSpace()) { - sceneName = trackFile.SceneName; + _logger.Trace("Using scene name for release title: {0}", trackFile.SceneName); + releaseTitle = trackFile.SceneName; } else if (trackFile.OriginalFilePath.IsNotNullOrWhiteSpace()) { - sceneName = trackFile.OriginalFilePath; + _logger.Trace("Using original file path for release title: {0}", Path.GetFileName(trackFile.OriginalFilePath)); + releaseTitle = trackFile.OriginalFilePath; } else if (trackFile.Path.IsNotNullOrWhiteSpace()) { - sceneName = Path.GetFileName(trackFile.Path); + _logger.Trace("Using path for release title: {0}", Path.GetFileName(trackFile.Path)); + releaseTitle = Path.GetFileName(trackFile.Path); } var episodeInfo = new ParsedAlbumInfo { ArtistName = artist.Name, - ReleaseTitle = sceneName, + ReleaseTitle = releaseTitle, Quality = trackFile.Quality, ReleaseGroup = trackFile.ReleaseGroup }; diff --git a/src/NzbDrone.Core/CustomFormats/Specifications/RegexSpecificationBase.cs b/src/NzbDrone.Core/CustomFormats/Specifications/RegexSpecificationBase.cs index e548d858f..1c133e383 100644 --- a/src/NzbDrone.Core/CustomFormats/Specifications/RegexSpecificationBase.cs +++ b/src/NzbDrone.Core/CustomFormats/Specifications/RegexSpecificationBase.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.CustomFormats protected Regex _regex; protected string _raw; - [FieldDefinition(1, Label = "Regular Expression", HelpText = "Custom Format RegEx is Case Insensitive")] + [FieldDefinition(1, Label = "CustomFormatsSpecificationRegularExpression", HelpText = "CustomFormatsSpecificationRegularExpressionHelpText")] public string Value { get => _raw; diff --git a/src/NzbDrone.Core/Datastore/Database.cs b/src/NzbDrone.Core/Datastore/Database.cs index e36241ef0..b743fba13 100644 --- a/src/NzbDrone.Core/Datastore/Database.cs +++ b/src/NzbDrone.Core/Datastore/Database.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Data; +using System.Data.SQLite; using System.Text.RegularExpressions; using Dapper; using NLog; @@ -40,14 +41,7 @@ namespace NzbDrone.Core.Datastore { using (var db = _datamapperFactory()) { - if (db.ConnectionString.Contains(".db")) - { - return DatabaseType.SQLite; - } - else - { - return DatabaseType.PostgreSQL; - } + return db is SQLiteConnection ? DatabaseType.SQLite : DatabaseType.PostgreSQL; } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/061_postgres_update_timestamp_columns_to_with_timezone.cs b/src/NzbDrone.Core/Datastore/Migration/061_postgres_update_timestamp_columns_to_with_timezone.cs index 8dceff17e..c6567345c 100644 --- a/src/NzbDrone.Core/Datastore/Migration/061_postgres_update_timestamp_columns_to_with_timezone.cs +++ b/src/NzbDrone.Core/Datastore/Migration/061_postgres_update_timestamp_columns_to_with_timezone.cs @@ -8,6 +8,8 @@ namespace NzbDrone.Core.Datastore.Migration { protected override void MainDbUpgrade() { + Delete.FromTable("Commands").AllRows(); + Alter.Table("AlbumReleases").AlterColumn("ReleaseDate").AsDateTimeOffset().Nullable(); Alter.Table("Albums").AlterColumn("LastInfoSync").AsDateTimeOffset().Nullable(); Alter.Table("Albums").AlterColumn("ReleaseDate").AsDateTimeOffset().Nullable(); diff --git a/src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs b/src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs new file mode 100644 index 000000000..fceae48fb --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs @@ -0,0 +1,16 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(075)] + public class quality_definition_preferred_size : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("QualityDefinitions").AddColumn("PreferredSize").AsDouble().Nullable(); + + Execute.Sql("UPDATE \"QualityDefinitions\" SET \"PreferredSize\" = \"MaxSize\" - 5 WHERE \"MaxSize\" > 5"); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/Migration/076_add_on_artist_add_to_notifications.cs b/src/NzbDrone.Core/Datastore/Migration/076_add_on_artist_add_to_notifications.cs new file mode 100644 index 000000000..79c86ec5a --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/076_add_on_artist_add_to_notifications.cs @@ -0,0 +1,14 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(076)] + public class add_on_artist_add_to_notifications : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("Notifications").AddColumn("OnArtistAdd").AsBoolean().WithDefaultValue(false); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 0ea48c00b..df2296951 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -86,8 +86,9 @@ namespace NzbDrone.Core.Datastore .Ignore(i => i.SupportsOnReleaseImport) .Ignore(i => i.SupportsOnUpgrade) .Ignore(i => i.SupportsOnRename) - .Ignore(i => i.SupportsOnAlbumDelete) + .Ignore(i => i.SupportsOnArtistAdd) .Ignore(i => i.SupportsOnArtistDelete) + .Ignore(i => i.SupportsOnAlbumDelete) .Ignore(i => i.SupportsOnHealthIssue) .Ignore(i => i.SupportsOnHealthRestored) .Ignore(i => i.SupportsOnDownloadFailure) diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs index 40bf551ce..97e8eb889 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs @@ -13,14 +13,16 @@ namespace NzbDrone.Core.DecisionEngine { private readonly IConfigService _configService; private readonly IDelayProfileService _delayProfileService; + private readonly IQualityDefinitionService _qualityDefinitionService; public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y); public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y); - public DownloadDecisionComparer(IConfigService configService, IDelayProfileService delayProfileService) + public DownloadDecisionComparer(IConfigService configService, IDelayProfileService delayProfileService, IQualityDefinitionService qualityDefinitionService) { _configService = configService; _delayProfileService = delayProfileService; + _qualityDefinitionService = qualityDefinitionService; } public int Compare(DownloadDecision x, DownloadDecision y) @@ -166,8 +168,27 @@ namespace NzbDrone.Core.DecisionEngine private int CompareSize(DownloadDecision x, DownloadDecision y) { - // TODO: Is smaller better? Smaller for usenet could mean no par2 files. - return CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Release.Size.Round(200.Megabytes())); + var sizeCompare = CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => + { + var preferredSize = _qualityDefinitionService.Get(remoteAlbum.ParsedAlbumInfo.Quality.Quality).PreferredSize; + + var releaseDuration = remoteAlbum.Albums.Select(a => a.AlbumReleases.Value.Where(r => r.Monitored || a.AnyReleaseOk).Select(r => r.Duration).MaxOrDefault()).Sum() / 1000; + + // If no value for preferred it means unlimited so fallback to sort largest is best + if (preferredSize.HasValue && releaseDuration > 0) + { + var preferredAlbumSize = releaseDuration * preferredSize.Value.Kilobits(); + + // Calculate closest to the preferred size + return Math.Abs((remoteAlbum.Release.Size - preferredAlbumSize).Round(100.Megabytes())) * (-1); + } + else + { + return remoteAlbum.Release.Size.Round(100.Megabytes()); + } + }); + + return sizeCompare; } } } diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs index 09dfcd5ea..06d4a4ef0 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Core.DecisionEngine { public interface IMakeDownloadDecision { - List GetRssDecision(List reports); + List GetRssDecision(List reports, bool pushedRelease = false); List GetSearchDecision(List reports, SearchCriteriaBase searchCriteriaBase); } @@ -41,17 +41,17 @@ namespace NzbDrone.Core.DecisionEngine _logger = logger; } - public List GetRssDecision(List reports) + public List GetRssDecision(List reports, bool pushedRelease = false) { return GetAlbumDecisions(reports).ToList(); } public List GetSearchDecision(List reports, SearchCriteriaBase searchCriteriaBase) { - return GetAlbumDecisions(reports, searchCriteriaBase).ToList(); + return GetAlbumDecisions(reports, false, searchCriteriaBase).ToList(); } - private IEnumerable GetAlbumDecisions(List reports, SearchCriteriaBase searchCriteria = null) + private IEnumerable GetAlbumDecisions(List reports, bool pushedRelease = false, SearchCriteriaBase searchCriteria = null) { if (reports.Any()) { @@ -169,6 +169,26 @@ namespace NzbDrone.Core.DecisionEngine if (decision != null) { + var source = pushedRelease ? ReleaseSourceType.ReleasePush : ReleaseSourceType.Rss; + + if (searchCriteria != null) + { + if (searchCriteria.InteractiveSearch) + { + source = ReleaseSourceType.InteractiveSearch; + } + else if (searchCriteria.UserInvokedSearch) + { + source = ReleaseSourceType.UserInvokedSearch; + } + else + { + source = ReleaseSourceType.Search; + } + } + + decision.RemoteAlbum.ReleaseSource = source; + if (decision.Rejections.Any()) { _logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections)); diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs index f7b55535b..af1914814 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NzbDrone.Core.Configuration; using NzbDrone.Core.Profiles.Delay; +using NzbDrone.Core.Qualities; namespace NzbDrone.Core.DecisionEngine { @@ -14,11 +15,13 @@ namespace NzbDrone.Core.DecisionEngine { private readonly IConfigService _configService; private readonly IDelayProfileService _delayProfileService; + private readonly IQualityDefinitionService _qualityDefinitionService; - public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService) + public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService, IQualityDefinitionService qualityDefinitionService) { _configService = configService; _delayProfileService = delayProfileService; + _qualityDefinitionService = qualityDefinitionService; } public List PrioritizeDecisions(List decisions) @@ -26,7 +29,7 @@ namespace NzbDrone.Core.DecisionEngine return decisions.Where(c => c.RemoteAlbum.DownloadAllowed) .GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) => { - return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_configService, _delayProfileService)); + return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_configService, _delayProfileService, _qualityDefinitionService)); }) .SelectMany(c => c) .Union(decisions.Where(c => !c.RemoteAlbum.DownloadAllowed)) diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs index 1cfc12c6d..92b29adbb 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs @@ -49,7 +49,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var minSize = qualityDefinition.MinSize.Value.Kilobits(); // Multiply minSize by smallest release duration - minSize = minSize * minReleaseDuration; + minSize *= minReleaseDuration; // If the parsed size is smaller than minSize we don't want it if (subject.Release.Size < minSize) @@ -75,7 +75,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var maxSize = qualityDefinition.MaxSize.Value.Kilobits(); // Multiply maxSize by Album.Duration - maxSize = maxSize * maxReleaseDuration; + maxSize *= maxReleaseDuration; // If the parsed size is greater than maxSize we don't want it if (subject.Release.Size > maxSize) diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/QueueSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/QueueSpecification.cs index c56a6a4f8..e57e1cd56 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/QueueSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/QueueSpecification.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Core.Configuration; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.Download.TrackedDownloads; using NzbDrone.Core.IndexerSearch.Definitions; @@ -15,16 +16,19 @@ namespace NzbDrone.Core.DecisionEngine.Specifications private readonly IQueueService _queueService; private readonly UpgradableSpecification _upgradableSpecification; private readonly ICustomFormatCalculationService _formatService; + private readonly IConfigService _configService; private readonly Logger _logger; public QueueSpecification(IQueueService queueService, UpgradableSpecification upgradableSpecification, ICustomFormatCalculationService formatService, + IConfigService configService, Logger logger) { _queueService = queueService; _upgradableSpecification = upgradableSpecification; _formatService = formatService; + _configService = configService; _logger = logger; } @@ -85,6 +89,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications { return Decision.Reject("Another release is queued and the Quality profile does not allow upgrades"); } + + if (_upgradableSpecification.IsRevisionUpgrade(remoteAlbum.ParsedAlbumInfo.Quality, subject.ParsedAlbumInfo.Quality)) + { + if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade) + { + _logger.Debug("Auto downloading of propers is disabled"); + return Decision.Reject("Proper downloading is disabled"); + } + } } return Decision.Accept(); diff --git a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs index 5a33b736b..b008e070a 100644 --- a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs +++ b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs @@ -7,6 +7,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Parser.Model; @@ -27,8 +28,9 @@ namespace NzbDrone.Core.Download.Clients.Aria2 IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; } @@ -130,7 +132,7 @@ namespace NzbDrone.Core.Download.Clients.Aria2 CanMoveFiles = false, CanBeRemoved = torrent.Status == "complete", Category = null, - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = torrent.InfoHash?.ToUpper(), IsEncrypted = false, Message = torrent.ErrorMessage, diff --git a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Proxy.cs b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Proxy.cs index f141ef7ce..52f5a1bde 100644 --- a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Proxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Proxy.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using System.Xml.XPath; +using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Core.Download.Extensions; @@ -97,8 +98,14 @@ namespace NzbDrone.Core.Download.Clients.Aria2 public string AddMagnet(Aria2Settings settings, string magnet) { - var response = ExecuteRequest(settings, "aria2.addUri", GetToken(settings), new List { magnet }); + var options = new Dictionary(); + if (settings.Directory.IsNotNullOrWhiteSpace()) + { + options.Add("dir", settings.Directory); + } + + var response = ExecuteRequest(settings, "aria2.addUri", GetToken(settings), new List { magnet }, options); var gid = response.GetStringResponse(); return gid; @@ -106,8 +113,16 @@ namespace NzbDrone.Core.Download.Clients.Aria2 public string AddTorrent(Aria2Settings settings, byte[] torrent) { - var response = ExecuteRequest(settings, "aria2.addTorrent", GetToken(settings), torrent); + // Aria2's second parameter is an array of URIs and needs to be sent if options are provided, this satisfies that requirement. + var emptyListOfUris = new List(); + var options = new Dictionary(); + if (settings.Directory.IsNotNullOrWhiteSpace()) + { + options.Add("dir", settings.Directory); + } + + var response = ExecuteRequest(settings, "aria2.addTorrent", GetToken(settings), torrent, emptyListOfUris, options); var gid = response.GetStringResponse(); return gid; diff --git a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Settings.cs b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Settings.cs index e88bc4cc1..82e4d93ab 100644 --- a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Settings.cs +++ b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2Settings.cs @@ -41,6 +41,9 @@ namespace NzbDrone.Core.Download.Clients.Aria2 [FieldDefinition(4, Label = "Secret token", Type = FieldType.Password, Privacy = PrivacyLevel.Password)] public string SecretToken { get; set; } + [FieldDefinition(5, Label = "Directory", Type = FieldType.Textbox, HelpText = "DownloadClientAriaSettingsDirectoryHelpText")] + public string Directory { get; set; } + public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs b/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs index 94156a812..02639664a 100644 --- a/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs +++ b/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs @@ -7,6 +7,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Organizer; @@ -29,8 +30,9 @@ namespace NzbDrone.Core.Download.Clients.Blackhole IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _scanWatchFolder = scanWatchFolder; @@ -87,7 +89,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole { yield return new DownloadClientItem { - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = Definition.Name + "_" + item.DownloadId, Category = "Lidarr", Title = item.Title, diff --git a/src/NzbDrone.Core/Download/Clients/Blackhole/UsenetBlackhole.cs b/src/NzbDrone.Core/Download/Clients/Blackhole/UsenetBlackhole.cs index 4998fbb96..aedbc03c1 100644 --- a/src/NzbDrone.Core/Download/Clients/Blackhole/UsenetBlackhole.cs +++ b/src/NzbDrone.Core/Download/Clients/Blackhole/UsenetBlackhole.cs @@ -59,7 +59,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole { yield return new DownloadClientItem { - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = Definition.Name + "_" + item.DownloadId, Category = "Lidarr", Title = item.Title, diff --git a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs index 67afca474..9cbf3c4ca 100644 --- a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs +++ b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs @@ -7,6 +7,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Parser.Model; @@ -25,8 +26,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; } @@ -133,7 +135,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge item.Title = torrent.Name; item.Category = Settings.MusicCategory; - item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, Settings.MusicImportedCategory.IsNotNullOrWhiteSpace()); var outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.DownloadPath)); item.OutputPath = outputPath + torrent.Name; diff --git a/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs b/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs index 20a87c642..664900f60 100644 --- a/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs +++ b/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs @@ -8,6 +8,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.DownloadStation.Proxies; using NzbDrone.Core.MediaFiles.TorrentInfo; @@ -36,8 +37,9 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _dsInfoProxy = dsInfoProxy; _dsTaskProxySelector = dsTaskProxySelector; @@ -87,7 +89,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation var item = new DownloadClientItem() { Category = Settings.MusicCategory, - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = CreateDownloadId(torrent.Id, serialNumber), Title = torrent.Title, TotalSize = torrent.Size, diff --git a/src/NzbDrone.Core/Download/Clients/DownloadStation/UsenetDownloadStation.cs b/src/NzbDrone.Core/Download/Clients/DownloadStation/UsenetDownloadStation.cs index 0e01e8fc2..1add52b29 100644 --- a/src/NzbDrone.Core/Download/Clients/DownloadStation/UsenetDownloadStation.cs +++ b/src/NzbDrone.Core/Download/Clients/DownloadStation/UsenetDownloadStation.cs @@ -97,7 +97,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation var item = new DownloadClientItem() { Category = Settings.MusicCategory, - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = CreateDownloadId(nzb.Id, serialNumber), Title = nzb.Title, TotalSize = nzb.Size, diff --git a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs index 15e2d1369..3c775d563 100644 --- a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs +++ b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.Flood.Models; using NzbDrone.Core.MediaFiles.TorrentInfo; @@ -27,8 +28,9 @@ namespace NzbDrone.Core.Download.Clients.Flood IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; _downloadSeedConfigProvider = downloadSeedConfigProvider; @@ -70,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.Flood } } - return result; + return result.Where(t => t.IsNotNullOrWhiteSpace()); } public override string Name => "Flood"; @@ -106,7 +108,7 @@ namespace NzbDrone.Core.Download.Clients.Flood var item = new DownloadClientItem { - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = torrent.Key, Title = properties.Name, OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(properties.Directory)), diff --git a/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs b/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs index 5595aafb7..3109aed0f 100644 --- a/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs +++ b/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.FreeboxDownload.Responses; using NzbDrone.Core.MediaFiles.TorrentInfo; @@ -24,8 +25,9 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; } @@ -71,7 +73,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload Category = Settings.Category, Title = torrent.Name, TotalSize = torrent.Size, - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), RemainingSize = (long)(torrent.Size * (double)(1 - ((double)torrent.ReceivedPrct / 10000))), RemainingTime = torrent.Eta <= 0 ? null : TimeSpan.FromSeconds(torrent.Eta), SeedRatio = torrent.StopRatio <= 0 ? 0 : torrent.StopRatio / 100, diff --git a/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs b/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs index e43bdebde..261bce3da 100644 --- a/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs +++ b/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs @@ -5,6 +5,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.Hadouken.Models; using NzbDrone.Core.MediaFiles.TorrentInfo; @@ -24,8 +25,9 @@ namespace NzbDrone.Core.Download.Clients.Hadouken IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; } @@ -55,7 +57,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken var item = new DownloadClientItem { - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = torrent.InfoHash.ToUpper(), OutputPath = outputPath + torrent.Name, RemainingSize = torrent.TotalSize - torrent.DownloadedBytes, diff --git a/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs b/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs index 00488f667..dba7b3ffb 100644 --- a/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs +++ b/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs @@ -56,7 +56,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex { var queueItem = new DownloadClientItem(); - queueItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + queueItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false); queueItem.DownloadId = vortexQueueItem.AddUUID ?? vortexQueueItem.Id.ToString(); queueItem.Category = vortexQueueItem.GroupName; queueItem.Title = vortexQueueItem.UiTitle; diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs index b15e1c381..df3e86411 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget queueItem.Title = item.NzbName; queueItem.TotalSize = totalSize; queueItem.Category = item.Category; - queueItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + queueItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false); queueItem.CanMoveFiles = true; queueItem.CanBeRemoved = true; @@ -119,7 +119,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget var historyItem = new DownloadClientItem(); var itemDir = item.FinalDir.IsNullOrWhiteSpace() ? item.DestDir : item.FinalDir; - historyItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + historyItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false); historyItem.DownloadId = droneParameter == null ? item.Id.ToString() : droneParameter.Value.ToString(); historyItem.Title = item.Name; historyItem.TotalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo); diff --git a/src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs b/src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs index df47e136d..becc142d2 100644 --- a/src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs +++ b/src/NzbDrone.Core/Download/Clients/Pneumatic/Pneumatic.cs @@ -73,7 +73,7 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic var historyItem = new DownloadClientItem { - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = GetDownloadClientId(file), Title = title, diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs index 2b581343c..23f2564df 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs @@ -8,6 +8,7 @@ using NzbDrone.Common.Cache; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Parser.Model; @@ -34,8 +35,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, ICacheManager cacheManager, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxySelector = proxySelector; @@ -227,7 +229,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent Category = torrent.Category.IsNotNullOrWhiteSpace() ? torrent.Category : torrent.Label, Title = torrent.Name, TotalSize = torrent.Size, - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, Settings.MusicImportedCategory.IsNotNullOrWhiteSpace()), RemainingSize = (long)(torrent.Size * (1.0 - torrent.Progress)), RemainingTime = GetRemainingTime(torrent), SeedRatio = torrent.Ratio @@ -609,7 +611,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent } else if (torrent.RatioLimit == -2 && config.MaxRatioEnabled) { - if (torrent.Ratio >= config.MaxRatio) + if (Math.Round(torrent.Ratio, 2) >= config.MaxRatio) { return true; } diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentContentLayout.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentContentLayout.cs new file mode 100644 index 000000000..874fbff7a --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentContentLayout.cs @@ -0,0 +1,9 @@ +namespace NzbDrone.Core.Download.Clients.QBittorrent +{ + public enum QBittorrentContentLayout + { + Default = 0, + Original = 1, + Subfolder = 2 + } +} diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs index adb8b6196..5aca88f50 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs @@ -265,6 +265,15 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent { request.AddFormParameter("firstLastPiecePrio", true); } + + if ((QBittorrentContentLayout)settings.ContentLayout == QBittorrentContentLayout.Original) + { + request.AddFormParameter("contentLayout", "Original"); + } + else if ((QBittorrentContentLayout)settings.ContentLayout == QBittorrentContentLayout.Subfolder) + { + request.AddFormParameter("contentLayout", "Subfolder"); + } } public void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, QBittorrentSettings settings) diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs index 84976a094..fa2f37453 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs @@ -69,6 +69,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent [FieldDefinition(12, Label = "First and Last First", Type = FieldType.Checkbox, HelpText = "Download first and last pieces first (qBittorrent 4.1.0+)")] public bool FirstAndLast { get; set; } + [FieldDefinition(13, Label = "DownloadClientQbittorrentSettingsContentLayout", Type = FieldType.Select, SelectOptions = typeof(QBittorrentContentLayout), HelpText = "DownloadClientQbittorrentSettingsContentLayoutHelpText")] + public int ContentLayout { get; set; } + public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs index f6c725fa6..dc788f9e4 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs @@ -63,7 +63,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd } var queueItem = new DownloadClientItem(); - queueItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + queueItem.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false); queueItem.DownloadId = sabQueueItem.Id; queueItem.Category = sabQueueItem.Category; queueItem.Title = sabQueueItem.Title; @@ -118,7 +118,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd var historyItem = new DownloadClientItem { - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = sabHistoryItem.Id, Category = sabHistoryItem.Category, Title = sabHistoryItem.Title, @@ -276,7 +276,11 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd status.OutputRootFolders = new List { _remotePathMappingService.RemapRemoteToLocal(Settings.Host, category.FullPath) }; } - if (config.Misc.history_retention.IsNotNullOrWhiteSpace() && config.Misc.history_retention.EndsWith("d")) + if (config.Misc.history_retention.IsNullOrWhiteSpace()) + { + status.RemovesCompletedDownloads = false; + } + else if (config.Misc.history_retention.EndsWith("d")) { int.TryParse(config.Misc.history_retention.AsSpan(0, config.Misc.history_retention.Length - 1), out var daysRetention); diff --git a/src/NzbDrone.Core/Download/Clients/Transmission/Transmission.cs b/src/NzbDrone.Core/Download/Clients/Transmission/Transmission.cs index 369b9f961..bf4dd8c29 100644 --- a/src/NzbDrone.Core/Download/Clients/Transmission/Transmission.cs +++ b/src/NzbDrone.Core/Download/Clients/Transmission/Transmission.cs @@ -1,9 +1,10 @@ -using System; +using System; using System.Text.RegularExpressions; using FluentValidation.Results; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.RemotePathMappings; @@ -18,8 +19,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { } diff --git a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs index 6349e91ac..89d2eaa77 100644 --- a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs +++ b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Parser.Model; @@ -24,8 +25,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; } @@ -70,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission item.Category = Settings.MusicCategory; item.Title = torrent.Name; - item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false); item.OutputPath = GetOutputPath(outputPath, torrent); item.TotalSize = torrent.TotalSize; diff --git a/src/NzbDrone.Core/Download/Clients/Vuze/Vuze.cs b/src/NzbDrone.Core/Download/Clients/Vuze/Vuze.cs index fda64aa05..5ee5d6206 100644 --- a/src/NzbDrone.Core/Download/Clients/Vuze/Vuze.cs +++ b/src/NzbDrone.Core/Download/Clients/Vuze/Vuze.cs @@ -2,6 +2,7 @@ using FluentValidation.Results; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.Transmission; using NzbDrone.Core.MediaFiles.TorrentInfo; @@ -19,8 +20,9 @@ namespace NzbDrone.Core.Download.Clients.Vuze IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(proxy, torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { } diff --git a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs index 828010bfd..de5e3044a 100644 --- a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs @@ -8,6 +8,7 @@ using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.rTorrent; using NzbDrone.Core.Exceptions; @@ -34,8 +35,9 @@ namespace NzbDrone.Core.Download.Clients.RTorrent IRemotePathMappingService remotePathMappingService, IDownloadSeedConfigProvider downloadSeedConfigProvider, IRTorrentDirectoryValidator rTorrentDirectoryValidator, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; _rTorrentDirectoryValidator = rTorrentDirectoryValidator; @@ -141,7 +143,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent } var item = new DownloadClientItem(); - item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, Settings.MusicImportedCategory.IsNotNullOrWhiteSpace()); item.Title = torrent.Name; item.DownloadId = torrent.Hash; item.OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.Path)); diff --git a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs index ff714e832..60cf79c5f 100644 --- a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs @@ -8,6 +8,7 @@ using NzbDrone.Common.Cache; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Parser.Model; @@ -28,8 +29,9 @@ namespace NzbDrone.Core.Download.Clients.UTorrent IConfigService configService, IDiskProvider diskProvider, IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, Logger logger) - : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger) + : base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, blocklistService, logger) { _proxy = proxy; @@ -118,7 +120,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent item.Title = torrent.Name; item.TotalSize = torrent.Size; item.Category = torrent.Label; - item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this); + item.DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, Settings.MusicImportedCategory.IsNotNullOrWhiteSpace()); item.RemainingSize = torrent.Remaining; item.SeedRatio = torrent.Ratio; diff --git a/src/NzbDrone.Core/Download/DownloadClientBase.cs b/src/NzbDrone.Core/Download/DownloadClientBase.cs index 668d17011..314e8e500 100644 --- a/src/NzbDrone.Core/Download/DownloadClientBase.cs +++ b/src/NzbDrone.Core/Download/DownloadClientBase.cs @@ -1,15 +1,19 @@ using System; using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; using FluentValidation.Results; using NLog; using NzbDrone.Common.Disk; +using NzbDrone.Common.Http; using NzbDrone.Core.Configuration; using NzbDrone.Core.Indexers; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.RemotePathMappings; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Validation; +using Polly; +using Polly.Retry; namespace NzbDrone.Core.Download { @@ -21,6 +25,37 @@ namespace NzbDrone.Core.Download protected readonly IRemotePathMappingService _remotePathMappingService; protected readonly Logger _logger; + protected ResiliencePipeline RetryStrategy => new ResiliencePipelineBuilder() + .AddRetry(new RetryStrategyOptions + { + ShouldHandle = static args => args.Outcome switch + { + { Result.HasHttpServerError: true } => PredicateResult.True(), + { Result.StatusCode: HttpStatusCode.RequestTimeout } => PredicateResult.True(), + _ => PredicateResult.False() + }, + Delay = TimeSpan.FromSeconds(3), + MaxRetryAttempts = 2, + BackoffType = DelayBackoffType.Exponential, + UseJitter = true, + OnRetry = args => + { + var exception = args.Outcome.Exception; + + if (exception is not null) + { + _logger.Info(exception, "Request for {0} failed with exception '{1}'. Retrying in {2}s.", Definition.Name, exception.Message, args.RetryDelay.TotalSeconds); + } + else + { + _logger.Info("Request for {0} failed with status {1}. Retrying in {2}s.", Definition.Name, args.Outcome.Result?.StatusCode, args.RetryDelay.TotalSeconds); + } + + return default; + } + }) + .Build(); + public abstract string Name { get; } public Type ConfigContract => typeof(TSettings); @@ -54,10 +89,7 @@ namespace NzbDrone.Core.Download return GetType().Name; } - public abstract DownloadProtocol Protocol - { - get; - } + public abstract DownloadProtocol Protocol { get; } public abstract Task Download(RemoteAlbum remoteAlbum, IIndexer indexer); public abstract IEnumerable GetItems(); diff --git a/src/NzbDrone.Core/Download/DownloadClientItem.cs b/src/NzbDrone.Core/Download/DownloadClientItem.cs index aa44a3acf..c32afa1e3 100644 --- a/src/NzbDrone.Core/Download/DownloadClientItem.cs +++ b/src/NzbDrone.Core/Download/DownloadClientItem.cs @@ -38,8 +38,10 @@ namespace NzbDrone.Core.Download public string Type { get; set; } public int Id { get; set; } public string Name { get; set; } + public bool HasPostImportCategory { get; set; } - public static DownloadClientItemClientInfo FromDownloadClient(DownloadClientBase downloadClient) + public static DownloadClientItemClientInfo FromDownloadClient( + DownloadClientBase downloadClient, bool hasPostImportCategory) where TSettings : IProviderConfig, new() { return new DownloadClientItemClientInfo @@ -47,7 +49,8 @@ namespace NzbDrone.Core.Download Protocol = downloadClient.Protocol, Type = downloadClient.Name, Id = downloadClient.Definition.Id, - Name = downloadClient.Definition.Name + Name = downloadClient.Definition.Name, + HasPostImportCategory = hasPostImportCategory }; } } diff --git a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs index dd4ad5751..06a52830c 100644 --- a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs +++ b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using NzbDrone.Common.Messaging; using NzbDrone.Core.Download.TrackedDownloads; +using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Qualities; namespace NzbDrone.Core.Download @@ -22,5 +23,6 @@ namespace NzbDrone.Core.Download public Dictionary Data { get; set; } public TrackedDownload TrackedDownload { get; set; } public bool SkipRedownload { get; set; } + public ReleaseSourceType ReleaseSource { get; set; } } } diff --git a/src/NzbDrone.Core/Download/DownloadService.cs b/src/NzbDrone.Core/Download/DownloadService.cs index 8fab26e6c..538e37f6d 100644 --- a/src/NzbDrone.Core/Download/DownloadService.cs +++ b/src/NzbDrone.Core/Download/DownloadService.cs @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Download { public interface IDownloadService { - Task DownloadReport(RemoteAlbum remoteAlbum); + Task DownloadReport(RemoteAlbum remoteAlbum, int? downloadClientId); } public class DownloadService : IDownloadService @@ -50,13 +50,15 @@ namespace NzbDrone.Core.Download _logger = logger; } - public async Task DownloadReport(RemoteAlbum remoteAlbum) + public async Task DownloadReport(RemoteAlbum remoteAlbum, int? downloadClientId) { var filterBlockedClients = remoteAlbum.Release.PendingReleaseReason == PendingReleaseReason.DownloadClientUnavailable; var tags = remoteAlbum.Artist?.Tags; - var downloadClient = _downloadClientProvider.GetDownloadClient(remoteAlbum.Release.DownloadProtocol, remoteAlbum.Release.IndexerId, filterBlockedClients, tags); + var downloadClient = downloadClientId.HasValue + ? _downloadClientProvider.Get(downloadClientId.Value) + : _downloadClientProvider.GetDownloadClient(remoteAlbum.Release.DownloadProtocol, remoteAlbum.Release.IndexerId, filterBlockedClients, tags); await DownloadReport(remoteAlbum, downloadClient); } @@ -102,6 +104,11 @@ namespace NzbDrone.Core.Download _logger.Trace("Release {0} no longer available on indexer.", remoteAlbum); throw; } + catch (ReleaseBlockedException) + { + _logger.Trace("Release {0} previously added to blocklist, not sending to download client again.", remoteAlbum); + throw; + } catch (DownloadClientRejectedReleaseException) { _logger.Trace("Release {0} rejected by download client, possible duplicate.", remoteAlbum); @@ -126,7 +133,7 @@ namespace NzbDrone.Core.Download albumGrabbedEvent.DownloadClientId = downloadClient.Definition.Id; albumGrabbedEvent.DownloadClientName = downloadClient.Definition.Name; - if (!string.IsNullOrWhiteSpace(downloadClientId)) + if (downloadClientId.IsNotNullOrWhiteSpace()) { albumGrabbedEvent.DownloadId = downloadClientId; } diff --git a/src/NzbDrone.Core/Download/FailedDownloadService.cs b/src/NzbDrone.Core/Download/FailedDownloadService.cs index 1ac4ec3f4..a710a924f 100644 --- a/src/NzbDrone.Core/Download/FailedDownloadService.cs +++ b/src/NzbDrone.Core/Download/FailedDownloadService.cs @@ -1,9 +1,11 @@ +using System; using System.Collections.Generic; using System.Linq; using NzbDrone.Common.Extensions; using NzbDrone.Core.Download.TrackedDownloads; using NzbDrone.Core.History; using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Download { @@ -116,7 +118,8 @@ namespace NzbDrone.Core.Download private void PublishDownloadFailedEvent(List historyItems, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false) { - var historyItem = historyItems.First(); + var historyItem = historyItems.Last(); + Enum.TryParse(historyItem.Data.GetValueOrDefault(EntityHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource); var downloadFailedEvent = new DownloadFailedEvent { @@ -129,7 +132,8 @@ namespace NzbDrone.Core.Download Message = message, Data = historyItem.Data, TrackedDownload = trackedDownload, - SkipRedownload = skipRedownload + SkipRedownload = skipRedownload, + ReleaseSource = releaseSource }; _eventAggregator.PublishEvent(downloadFailedEvent); diff --git a/src/NzbDrone.Core/Download/Pending/PendingRelease.cs b/src/NzbDrone.Core/Download/Pending/PendingRelease.cs index 15a7cfefc..73d925cfb 100644 --- a/src/NzbDrone.Core/Download/Pending/PendingRelease.cs +++ b/src/NzbDrone.Core/Download/Pending/PendingRelease.cs @@ -12,8 +12,14 @@ namespace NzbDrone.Core.Download.Pending public ParsedAlbumInfo ParsedAlbumInfo { get; set; } public ReleaseInfo Release { get; set; } public PendingReleaseReason Reason { get; set; } + public PendingReleaseAdditionalInfo AdditionalInfo { get; set; } // Not persisted public RemoteAlbum RemoteAlbum { get; set; } } + + public class PendingReleaseAdditionalInfo + { + public ReleaseSourceType ReleaseSource { get; set; } + } } diff --git a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs index b3a69d16c..f41cae0d4 100644 --- a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs +++ b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs @@ -46,6 +46,8 @@ namespace NzbDrone.Core.Download.Pending private readonly IConfigService _configService; private readonly ICustomFormatCalculationService _formatCalculator; private readonly IRemoteAlbumAggregationService _aggregationService; + private readonly IDownloadClientFactory _downloadClientFactory; + private readonly IIndexerFactory _indexerFactory; private readonly IEventAggregator _eventAggregator; private readonly Logger _logger; @@ -58,6 +60,8 @@ namespace NzbDrone.Core.Download.Pending IConfigService configService, ICustomFormatCalculationService formatCalculator, IRemoteAlbumAggregationService aggregationService, + IDownloadClientFactory downloadClientFactory, + IIndexerFactory indexerFactory, IEventAggregator eventAggregator, Logger logger) { @@ -70,6 +74,8 @@ namespace NzbDrone.Core.Download.Pending _configService = configService; _formatCalculator = formatCalculator; _aggregationService = aggregationService; + _downloadClientFactory = downloadClientFactory; + _indexerFactory = indexerFactory; _eventAggregator = eventAggregator; _logger = logger; } @@ -107,9 +113,16 @@ namespace NzbDrone.Core.Download.Pending if (matchingReport.Reason != reason) { - _logger.Debug("The release {0} is already pending with reason {1}, changing to {2}", decision.RemoteAlbum, matchingReport.Reason, reason); - matchingReport.Reason = reason; - _repository.Update(matchingReport); + if (matchingReport.Reason == PendingReleaseReason.DownloadClientUnavailable) + { + _logger.Debug("The release {0} is already pending with reason {1}, not changing reason", decision.RemoteAlbum, matchingReport.Reason); + } + else + { + _logger.Debug("The release {0} is already pending with reason {1}, changing to {2}", decision.RemoteAlbum, matchingReport.Reason, reason); + matchingReport.Reason = reason; + _repository.Update(matchingReport); + } } else { @@ -168,51 +181,28 @@ namespace NzbDrone.Core.Download.Pending var nextRssSync = new Lazy(() => _taskManager.GetNextExecution(typeof(RssSyncCommand))); var pendingReleases = IncludeRemoteAlbums(_repository.WithoutFallback()); + foreach (var pendingRelease in pendingReleases) { + if (pendingRelease.RemoteAlbum.Albums.Empty()) + { + var noAlbumItem = GetQueueItem(pendingRelease, nextRssSync, null); + + noAlbumItem.ErrorMessage = "Unable to find matching album(s)"; + + queued.Add(noAlbumItem); + + continue; + } + foreach (var album in pendingRelease.RemoteAlbum.Albums) { - var ect = pendingRelease.Release.PublishDate.AddMinutes(GetDelay(pendingRelease.RemoteAlbum)); - - if (ect < nextRssSync.Value) - { - ect = nextRssSync.Value; - } - else - { - ect = ect.AddMinutes(_configService.RssSyncInterval); - } - - var timeleft = ect.Subtract(DateTime.UtcNow); - - if (timeleft.TotalSeconds < 0) - { - timeleft = TimeSpan.Zero; - } - - var queue = new Queue.Queue - { - Id = GetQueueId(pendingRelease, album), - Artist = pendingRelease.RemoteAlbum.Artist, - Album = album, - Quality = pendingRelease.RemoteAlbum.ParsedAlbumInfo.Quality, - Title = pendingRelease.Title, - Size = pendingRelease.RemoteAlbum.Release.Size, - Sizeleft = pendingRelease.RemoteAlbum.Release.Size, - RemoteAlbum = pendingRelease.RemoteAlbum, - Timeleft = timeleft, - EstimatedCompletionTime = ect, - Status = pendingRelease.Reason.ToString(), - Protocol = pendingRelease.RemoteAlbum.Release.DownloadProtocol, - Indexer = pendingRelease.RemoteAlbum.Release.Indexer - }; - - queued.Add(queue); + queued.Add(GetQueueItem(pendingRelease, nextRssSync, album)); } } // Return best quality release for each album - var deduped = queued.GroupBy(q => q.Album.Id).Select(g => + var deduped = queued.Where(q => q.Album != null).GroupBy(q => q.Album.Id).Select(g => { var artist = g.First().Artist; @@ -305,25 +295,34 @@ namespace NzbDrone.Core.Download.Pending return null; } - List albums; - - if (knownRemoteAlbums != null && knownRemoteAlbums.TryGetValue(release.Release.Title, out var knownRemoteAlbum)) - { - albums = knownRemoteAlbum.Albums; - } - else - { - albums = _parsingService.GetAlbums(release.ParsedAlbumInfo, artist); - } - release.RemoteAlbum = new RemoteAlbum { Artist = artist, - Albums = albums, + ReleaseSource = release.AdditionalInfo?.ReleaseSource ?? ReleaseSourceType.Unknown, ParsedAlbumInfo = release.ParsedAlbumInfo, Release = release.Release }; + if (knownRemoteAlbums != null && knownRemoteAlbums.TryGetValue(release.Release.Title, out var knownRemoteAlbum)) + { + release.RemoteAlbum.Albums = knownRemoteAlbum.Albums; + } + else + { + try + { + var remoteAlbums = _parsingService.GetAlbums(release.ParsedAlbumInfo, artist); + + release.RemoteAlbum.Albums = remoteAlbums; + } + catch (InvalidOperationException ex) + { + _logger.Debug(ex, ex.Message); + + release.RemoteAlbum.Albums = new List(); + } + } + _aggregationService.Augment(release.RemoteAlbum); release.RemoteAlbum.CustomFormats = _formatCalculator.ParseCustomFormat(release.RemoteAlbum, release.Release.Size); @@ -333,6 +332,58 @@ namespace NzbDrone.Core.Download.Pending return result; } + private Queue.Queue GetQueueItem(PendingRelease pendingRelease, Lazy nextRssSync, Album album) + { + var ect = pendingRelease.Release.PublishDate.AddMinutes(GetDelay(pendingRelease.RemoteAlbum)); + + if (ect < nextRssSync.Value) + { + ect = nextRssSync.Value; + } + else + { + ect = ect.AddMinutes(_configService.RssSyncInterval); + } + + var timeleft = ect.Subtract(DateTime.UtcNow); + + if (timeleft.TotalSeconds < 0) + { + timeleft = TimeSpan.Zero; + } + + string downloadClientName = null; + var indexer = _indexerFactory.Find(pendingRelease.Release.IndexerId); + + if (indexer is { DownloadClientId: > 0 }) + { + var downloadClient = _downloadClientFactory.Find(indexer.DownloadClientId); + + downloadClientName = downloadClient?.Name; + } + + var queue = new Queue.Queue + { + Id = GetQueueId(pendingRelease, album), + Artist = pendingRelease.RemoteAlbum.Artist, + Album = album, + Quality = pendingRelease.RemoteAlbum.ParsedAlbumInfo.Quality, + Title = pendingRelease.Title, + Size = pendingRelease.RemoteAlbum.Release.Size, + Sizeleft = pendingRelease.RemoteAlbum.Release.Size, + RemoteAlbum = pendingRelease.RemoteAlbum, + Timeleft = timeleft, + EstimatedCompletionTime = ect, + Added = pendingRelease.Added, + Status = pendingRelease.Reason.ToString(), + Protocol = pendingRelease.RemoteAlbum.Release.DownloadProtocol, + Indexer = pendingRelease.RemoteAlbum.Release.Indexer, + DownloadClient = downloadClientName + }; + + return queue; + } + private void Insert(DownloadDecision decision, PendingReleaseReason reason) { _repository.Insert(new PendingRelease @@ -342,7 +393,11 @@ namespace NzbDrone.Core.Download.Pending Release = decision.RemoteAlbum.Release, Title = decision.RemoteAlbum.Release.Title, Added = DateTime.UtcNow, - Reason = reason + Reason = reason, + AdditionalInfo = new PendingReleaseAdditionalInfo + { + ReleaseSource = decision.RemoteAlbum.ReleaseSource + } }); _eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent()); @@ -419,7 +474,7 @@ namespace NzbDrone.Core.Download.Pending private int GetQueueId(PendingRelease pendingRelease, Album album) { - return HashConverter.GetHashInt31(string.Format("pending-{0}-album{1}", pendingRelease.Id, album.Id)); + return HashConverter.GetHashInt31(string.Format("pending-{0}-album{1}", pendingRelease.Id, album?.Id ?? 0)); } private int PrioritizeDownloadProtocol(Artist artist, DownloadProtocol downloadProtocol) diff --git a/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs b/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs index 5dd85b2ff..e9eb025c2 100644 --- a/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs +++ b/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs @@ -14,6 +14,7 @@ namespace NzbDrone.Core.Download public interface IProcessDownloadDecisions { Task ProcessDecisions(List decisions); + Task ProcessDecision(DownloadDecision decision, int? downloadClientId); } public class ProcessDownloadDecisions : IProcessDownloadDecisions @@ -40,8 +41,6 @@ namespace NzbDrone.Core.Download var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(qualifiedReports); var grabbed = new List(); var pending = new List(); - - // var failed = new List(); var rejected = decisions.Where(d => d.Rejected).ToList(); var pendingAddQueue = new List>(); @@ -51,7 +50,6 @@ namespace NzbDrone.Core.Download foreach (var report in prioritizedDecisions) { - var remoteAlbum = report.RemoteAlbum; var downloadProtocol = report.RemoteAlbum.Release.DownloadProtocol; // Skip if already grabbed @@ -73,37 +71,48 @@ namespace NzbDrone.Core.Download continue; } - try - { - _logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteAlbum.Release.Indexer, remoteAlbum.Release.IndexerPriority); - await _downloadService.DownloadReport(remoteAlbum); - grabbed.Add(report); - } - catch (ReleaseUnavailableException) - { - _logger.Warn("Failed to download release from indexer, no longer available. " + remoteAlbum); - rejected.Add(report); - } - catch (Exception ex) - { - if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException) - { - _logger.Debug(ex, "Failed to send release to download client, storing until later. " + remoteAlbum); - PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable); + var result = await ProcessDecisionInternal(report); - if (downloadProtocol == DownloadProtocol.Usenet) + switch (result) + { + case ProcessedDecisionResult.Grabbed: { - usenetFailed = true; + grabbed.Add(report); + break; } - else if (downloadProtocol == DownloadProtocol.Torrent) + + case ProcessedDecisionResult.Pending: { - torrentFailed = true; + PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.Delay); + break; + } + + case ProcessedDecisionResult.Rejected: + { + rejected.Add(report); + break; + } + + case ProcessedDecisionResult.Failed: + { + PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable); + + if (downloadProtocol == DownloadProtocol.Usenet) + { + usenetFailed = true; + } + else if (downloadProtocol == DownloadProtocol.Torrent) + { + torrentFailed = true; + } + + break; + } + + case ProcessedDecisionResult.Skipped: + { + break; } - } - else - { - _logger.Warn(ex, "Couldn't add report to download queue. " + remoteAlbum); - } } } @@ -115,10 +124,44 @@ namespace NzbDrone.Core.Download return new ProcessedDecisions(grabbed, pending, rejected); } + public async Task ProcessDecision(DownloadDecision decision, int? downloadClientId) + { + if (decision == null) + { + return ProcessedDecisionResult.Skipped; + } + + if (!IsQualifiedReport(decision)) + { + return ProcessedDecisionResult.Rejected; + } + + if (decision.TemporarilyRejected) + { + _pendingReleaseService.Add(decision, PendingReleaseReason.Delay); + + return ProcessedDecisionResult.Pending; + } + + var result = await ProcessDecisionInternal(decision, downloadClientId); + + if (result == ProcessedDecisionResult.Failed) + { + _pendingReleaseService.Add(decision, PendingReleaseReason.DownloadClientUnavailable); + } + + return result; + } + internal List GetQualifiedReports(IEnumerable decisions) + { + return decisions.Where(IsQualifiedReport).ToList(); + } + + internal bool IsQualifiedReport(DownloadDecision decision) { // Process both approved and temporarily rejected - return decisions.Where(c => (c.Approved || c.TemporarilyRejected) && c.RemoteAlbum.Albums.Any()).ToList(); + return (decision.Approved || decision.TemporarilyRejected) && decision.RemoteAlbum.Albums.Any(); } private bool IsAlbumProcessed(List decisions, DownloadDecision report) @@ -148,5 +191,38 @@ namespace NzbDrone.Core.Download queue.Add(Tuple.Create(report, reason)); pending.Add(report); } + + private async Task ProcessDecisionInternal(DownloadDecision decision, int? downloadClientId = null) + { + var remoteAlbum = decision.RemoteAlbum; + + try + { + _logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteAlbum.Release.Indexer, remoteAlbum.Release.IndexerPriority); + await _downloadService.DownloadReport(remoteAlbum, downloadClientId); + + return ProcessedDecisionResult.Grabbed; + } + catch (ReleaseUnavailableException) + { + _logger.Warn("Failed to download release from indexer, no longer available. " + remoteAlbum); + return ProcessedDecisionResult.Rejected; + } + catch (Exception ex) + { + if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException) + { + _logger.Debug(ex, + "Failed to send release to download client, storing until later. " + remoteAlbum); + + return ProcessedDecisionResult.Failed; + } + else + { + _logger.Warn(ex, "Couldn't add report to download queue. " + remoteAlbum); + return ProcessedDecisionResult.Skipped; + } + } + } } } diff --git a/src/NzbDrone.Core/Download/ProcessedDecisionResult.cs b/src/NzbDrone.Core/Download/ProcessedDecisionResult.cs new file mode 100644 index 000000000..d1f27ed49 --- /dev/null +++ b/src/NzbDrone.Core/Download/ProcessedDecisionResult.cs @@ -0,0 +1,11 @@ +namespace NzbDrone.Core.Download +{ + public enum ProcessedDecisionResult + { + Grabbed, + Pending, + Rejected, + Failed, + Skipped + } +} diff --git a/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs b/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs index b920296ca..a7065e4f1 100644 --- a/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs +++ b/src/NzbDrone.Core/Download/RedownloadFailedDownloadService.cs @@ -5,6 +5,7 @@ using NzbDrone.Core.Messaging; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Music; +using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Download { @@ -41,6 +42,12 @@ namespace NzbDrone.Core.Download return; } + if (message.ReleaseSource == ReleaseSourceType.InteractiveSearch && !_configService.AutoRedownloadFailedFromInteractiveSearch) + { + _logger.Debug("Auto redownloading failed albums from interactive search is disabled"); + return; + } + if (message.AlbumIds.Count == 1) { _logger.Debug("Failed download only contains one album, searching again"); diff --git a/src/NzbDrone.Core/Download/TorrentClientBase.cs b/src/NzbDrone.Core/Download/TorrentClientBase.cs index 09e8ac551..4e3ec11ab 100644 --- a/src/NzbDrone.Core/Download/TorrentClientBase.cs +++ b/src/NzbDrone.Core/Download/TorrentClientBase.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Configuration; using NzbDrone.Core.Exceptions; using NzbDrone.Core.Indexers; @@ -21,17 +22,20 @@ namespace NzbDrone.Core.Download where TSettings : IProviderConfig, new() { protected readonly IHttpClient _httpClient; + private readonly IBlocklistService _blocklistService; protected readonly ITorrentFileInfoReader _torrentFileInfoReader; protected TorrentClientBase(ITorrentFileInfoReader torrentFileInfoReader, - IHttpClient httpClient, - IConfigService configService, - IDiskProvider diskProvider, - IRemotePathMappingService remotePathMappingService, - Logger logger) + IHttpClient httpClient, + IConfigService configService, + IDiskProvider diskProvider, + IRemotePathMappingService remotePathMappingService, + IBlocklistService blocklistService, + Logger logger) : base(configService, diskProvider, remotePathMappingService, logger) { _httpClient = httpClient; + _blocklistService = blocklistService; _torrentFileInfoReader = torrentFileInfoReader; } @@ -86,7 +90,7 @@ namespace NzbDrone.Core.Download { try { - return DownloadFromMagnetUrl(remoteAlbum, magnetUrl); + return DownloadFromMagnetUrl(remoteAlbum, indexer, magnetUrl); } catch (NotSupportedException ex) { @@ -100,7 +104,7 @@ namespace NzbDrone.Core.Download { try { - return DownloadFromMagnetUrl(remoteAlbum, magnetUrl); + return DownloadFromMagnetUrl(remoteAlbum, indexer, magnetUrl); } catch (NotSupportedException ex) { @@ -133,7 +137,9 @@ namespace NzbDrone.Core.Download request.Headers.Accept = "application/x-bittorrent"; request.AllowAutoRedirect = false; - var response = await _httpClient.GetAsync(request); + var response = await RetryStrategy + .ExecuteAsync(static async (state, _) => await state._httpClient.GetAsync(state.request), (_httpClient, request)) + .ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.MovedPermanently || response.StatusCode == HttpStatusCode.Found || @@ -147,7 +153,7 @@ namespace NzbDrone.Core.Download { if (locationHeader.StartsWith("magnet:")) { - return DownloadFromMagnetUrl(remoteAlbum, locationHeader); + return DownloadFromMagnetUrl(remoteAlbum, indexer, locationHeader); } request.Url += new HttpUri(locationHeader); @@ -190,6 +196,9 @@ namespace NzbDrone.Core.Download var filename = string.Format("{0}.torrent", FileNameBuilder.CleanFileName(remoteAlbum.Release.Title)); var hash = _torrentFileInfoReader.GetHashFromTorrentFile(torrentFile); + + EnsureReleaseIsNotBlocklisted(remoteAlbum, indexer, hash); + var actualHash = AddFromTorrentFile(remoteAlbum, hash, filename, torrentFile); if (actualHash.IsNotNullOrWhiteSpace() && hash != actualHash) @@ -203,7 +212,7 @@ namespace NzbDrone.Core.Download return actualHash; } - private string DownloadFromMagnetUrl(RemoteAlbum remoteAlbum, string magnetUrl) + private string DownloadFromMagnetUrl(RemoteAlbum remoteAlbum, IIndexer indexer, string magnetUrl) { string hash = null; string actualHash = null; @@ -214,13 +223,13 @@ namespace NzbDrone.Core.Download } catch (FormatException ex) { - _logger.Error(ex, "Failed to parse magnetlink for release '{0}': '{1}'", remoteAlbum.Release.Title, magnetUrl); - - return null; + throw new ReleaseDownloadException(remoteAlbum.Release, "Failed to parse magnetlink for release '{0}': '{1}'", ex, remoteAlbum.Release.Title, magnetUrl); } if (hash != null) { + EnsureReleaseIsNotBlocklisted(remoteAlbum, indexer, hash); + actualHash = AddFromMagnetLink(remoteAlbum, hash, magnetUrl); } @@ -234,5 +243,30 @@ namespace NzbDrone.Core.Download return actualHash; } + + private void EnsureReleaseIsNotBlocklisted(RemoteAlbum remoteAlbum, IIndexer indexer, string hash) + { + var indexerSettings = indexer?.Definition?.Settings as ITorrentIndexerSettings; + var torrentInfo = remoteAlbum.Release as TorrentInfo; + var torrentInfoHash = torrentInfo?.InfoHash; + + // If the release didn't come from an interactive search, + // the hash wasn't known during processing and the + // indexer is configured to reject blocklisted releases + // during grab check if it's already been blocklisted. + + if (torrentInfo != null && torrentInfoHash.IsNullOrWhiteSpace()) + { + // If the hash isn't known from parsing we set it here so it can be used for blocklisting. + torrentInfo.InfoHash = hash; + + if (remoteAlbum.ReleaseSource != ReleaseSourceType.InteractiveSearch && + indexerSettings?.RejectBlocklistedTorrentHashesWhileGrabbing == true && + _blocklistService.BlocklistedTorrentHash(remoteAlbum.Artist.Id, hash)) + { + throw new ReleaseBlockedException(remoteAlbum.Release, "Release previously added to blocklist"); + } + } + } } } diff --git a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownload.cs b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownload.cs index e12949bd1..d4b4cfe20 100644 --- a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownload.cs +++ b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownload.cs @@ -1,3 +1,4 @@ +using System; using NzbDrone.Core.Indexers; using NzbDrone.Core.Parser.Model; @@ -14,11 +15,12 @@ namespace NzbDrone.Core.Download.TrackedDownloads public TrackedDownloadStatusMessage[] StatusMessages { get; private set; } public DownloadProtocol Protocol { get; set; } public string Indexer { get; set; } + public DateTime? Added { get; set; } public bool IsTrackable { get; set; } public TrackedDownload() { - StatusMessages = System.Array.Empty(); + StatusMessages = Array.Empty(); } public void Warn(string message, params object[] args) diff --git a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs index 5c397349f..eed5d5405 100644 --- a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs +++ b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs @@ -145,6 +145,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads var grabbedEvent = historyItems.FirstOrDefault(v => v.EventType == EntityHistoryEventType.Grabbed); trackedDownload.Indexer = grabbedEvent?.Data["indexer"]; + trackedDownload.Added = grabbedEvent?.Date; if (parsedAlbumInfo == null || trackedDownload.RemoteAlbum == null || diff --git a/src/NzbDrone.Core/Download/UsenetClientBase.cs b/src/NzbDrone.Core/Download/UsenetClientBase.cs index 945739026..e14ac5a87 100644 --- a/src/NzbDrone.Core/Download/UsenetClientBase.cs +++ b/src/NzbDrone.Core/Download/UsenetClientBase.cs @@ -47,7 +47,9 @@ namespace NzbDrone.Core.Download var request = indexer?.GetDownloadRequest(url) ?? new HttpRequest(url); request.RateLimitKey = remoteAlbum?.Release?.IndexerId.ToString(); - var response = await _httpClient.GetAsync(request); + var response = await RetryStrategy + .ExecuteAsync(static async (state, _) => await state._httpClient.GetAsync(state.request), (_httpClient, request)) + .ConfigureAwait(false); nzbData = response.ResponseData; diff --git a/src/NzbDrone.Core/Exceptions/ReleaseBlockedException.cs b/src/NzbDrone.Core/Exceptions/ReleaseBlockedException.cs new file mode 100644 index 000000000..73d8b8f8d --- /dev/null +++ b/src/NzbDrone.Core/Exceptions/ReleaseBlockedException.cs @@ -0,0 +1,28 @@ +using System; +using NzbDrone.Core.Parser.Model; + +namespace NzbDrone.Core.Exceptions +{ + public class ReleaseBlockedException : ReleaseDownloadException + { + public ReleaseBlockedException(ReleaseInfo release, string message, params object[] args) + : base(release, message, args) + { + } + + public ReleaseBlockedException(ReleaseInfo release, string message) + : base(release, message) + { + } + + public ReleaseBlockedException(ReleaseInfo release, string message, Exception innerException, params object[] args) + : base(release, message, innerException, args) + { + } + + public ReleaseBlockedException(ReleaseInfo release, string message, Exception innerException) + : base(release, message, innerException) + { + } + } +} diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs index 0ef36d545..b7ed855f8 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs @@ -91,13 +91,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox return metadata; } - var parseResult = Parser.Parser.ParseMusicTitle(filename); - - if (parseResult != null) + if (Path.GetExtension(filename).ToLowerInvariant() == ".xml") { - var extension = Path.GetExtension(filename).ToLowerInvariant(); + var parseResult = Parser.Parser.ParseMusicTitle(filename); - if (extension == ".xml") + if (parseResult != null) { metadata.Type = MetadataType.TrackMetadata; return metadata; diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs index 1b3b34e12..d63f8d1f6 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs @@ -53,22 +53,21 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv return null; } - var metadata = new MetadataFile + if (Path.GetExtension(filename).ToLowerInvariant() == ".xml") { - ArtistId = artist.Id, - Consumer = GetType().Name, - RelativePath = artist.Path.GetRelativePath(path) - }; - - var parseResult = Parser.Parser.ParseMusicTitle(filename); - - if (parseResult != null) - { - switch (Path.GetExtension(filename).ToLowerInvariant()) + var metadata = new MetadataFile { - case ".xml": - metadata.Type = MetadataType.TrackMetadata; - return metadata; + ArtistId = artist.Id, + Consumer = GetType().Name, + RelativePath = artist.Path.GetRelativePath(path) + }; + + var parseResult = Parser.Parser.ParseMusicTitle(filename); + + if (parseResult != null) + { + metadata.Type = MetadataType.TrackMetadata; + return metadata; } } diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs index 2e45a7082..27ed74eb6 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs @@ -30,8 +30,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc _detectNfo = detectNfo; } - private static readonly Regex ArtistImagesRegex = new Regex(@"^(?folder|banner|fanart|logo)\.(?:png|jpg|jpeg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex AlbumImagesRegex = new Regex(@"^(?cover|disc)\.(?:png|jpg|jpeg)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex ArtistImagesRegex = new Regex(@"^(?folder|banner|fanart|logo|landscape|clearart|clearlogo)\.(?:png|jpe?g)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex AlbumImagesRegex = new Regex(@"^(?cover|disc|discart|back|spine)\.(?:png|jpe?g)", RegexOptions.Compiled | RegexOptions.IgnoreCase); public override string Name => "Kodi (XBMC) / Emby"; diff --git a/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs b/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs index 087a3f270..8aa0675e6 100644 --- a/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs +++ b/src/NzbDrone.Core/Extras/Metadata/MetadataService.cs @@ -492,6 +492,10 @@ namespace NzbDrone.Core.Extras.Metadata _mediaFileAttributeService.SetFilePermissions(fullPath); } } + catch (HttpException ex) + { + _logger.Warn(ex, "Couldn't download image {0} for {1}. {2}", image.Url, artist, ex.Message); + } catch (WebException ex) { _logger.Warn(ex, "Couldn't download image {0} for {1}. {2}", image.Url, artist, ex.Message); diff --git a/src/NzbDrone.Core/History/EntityHistory.cs b/src/NzbDrone.Core/History/EntityHistory.cs index c9aada55e..ffc7e8e7c 100644 --- a/src/NzbDrone.Core/History/EntityHistory.cs +++ b/src/NzbDrone.Core/History/EntityHistory.cs @@ -9,6 +9,7 @@ namespace NzbDrone.Core.History public class EntityHistory : ModelBase { public const string DOWNLOAD_CLIENT = "downloadClient"; + public const string RELEASE_SOURCE = "releaseSource"; public EntityHistory() { diff --git a/src/NzbDrone.Core/History/EntityHistoryRepository.cs b/src/NzbDrone.Core/History/EntityHistoryRepository.cs index e5f427bc0..4b66c88b7 100644 --- a/src/NzbDrone.Core/History/EntityHistoryRepository.cs +++ b/src/NzbDrone.Core/History/EntityHistoryRepository.cs @@ -121,23 +121,21 @@ namespace NzbDrone.Core.History public PagingSpec GetPaged(PagingSpec pagingSpec, int[] qualities) { - pagingSpec.Records = GetPagedRecords(PagedBuilder(pagingSpec, qualities), pagingSpec, PagedQuery); + pagingSpec.Records = GetPagedRecords(PagedBuilder(qualities), pagingSpec, PagedQuery); var countTemplate = $"SELECT COUNT(*) FROM (SELECT /**select**/ FROM \"{TableMapping.Mapper.TableNameMapping(typeof(EntityHistory))}\" /**join**/ /**innerjoin**/ /**leftjoin**/ /**where**/ /**groupby**/ /**having**/) AS \"Inner\""; - pagingSpec.TotalRecords = GetPagedRecordCount(PagedBuilder(pagingSpec, qualities).Select(typeof(EntityHistory)), pagingSpec, countTemplate); + pagingSpec.TotalRecords = GetPagedRecordCount(PagedBuilder(qualities).Select(typeof(EntityHistory)), pagingSpec, countTemplate); return pagingSpec; } - private SqlBuilder PagedBuilder(PagingSpec pagingSpec, int[] qualities) + private SqlBuilder PagedBuilder(int[] qualities) { var builder = Builder() .Join((h, a) => h.ArtistId == a.Id) .Join((h, a) => h.AlbumId == a.Id) .LeftJoin((h, t) => h.TrackId == t.Id); - AddFilters(builder, pagingSpec); - if (qualities is { Length: > 0 }) { builder.Where($"({BuildQualityWhereClause(qualities)})"); diff --git a/src/NzbDrone.Core/History/EntityHistoryService.cs b/src/NzbDrone.Core/History/EntityHistoryService.cs index 75c162510..d3e33f9b0 100644 --- a/src/NzbDrone.Core/History/EntityHistoryService.cs +++ b/src/NzbDrone.Core/History/EntityHistoryService.cs @@ -165,15 +165,14 @@ namespace NzbDrone.Core.History history.Data.Add("Protocol", ((int)message.Album.Release.DownloadProtocol).ToString()); history.Data.Add("DownloadForced", (!message.Album.DownloadAllowed).ToString()); history.Data.Add("CustomFormatScore", message.Album.CustomFormatScore.ToString()); + history.Data.Add("ReleaseSource", message.Album.ReleaseSource.ToString()); if (!message.Album.ParsedAlbumInfo.ReleaseHash.IsNullOrWhiteSpace()) { history.Data.Add("ReleaseHash", message.Album.ParsedAlbumInfo.ReleaseHash); } - var torrentRelease = message.Album.Release as TorrentInfo; - - if (torrentRelease != null) + if (message.Album.Release is TorrentInfo torrentRelease) { history.Data.Add("TorrentInfoHash", torrentRelease.InfoHash); } @@ -241,6 +240,7 @@ namespace NzbDrone.Core.History history.Data.Add("ImportedPath", message.ImportedTrack.Path); history.Data.Add("DownloadClient", message.DownloadClientInfo?.Name); history.Data.Add("ReleaseGroup", message.TrackInfo.ReleaseGroup); + history.Data.Add("Size", message.TrackInfo.Size.ToString()); _historyRepository.Insert(history); } @@ -263,6 +263,7 @@ namespace NzbDrone.Core.History history.Data.Add("DownloadClient", message.DownloadClient); history.Data.Add("Message", message.Message); + history.Data.Add("Size", message.TrackedDownload?.DownloadItem.TotalSize.ToString()); _historyRepository.Insert(history); } @@ -322,6 +323,7 @@ namespace NzbDrone.Core.History history.Data.Add("Reason", message.Reason.ToString()); history.Data.Add("ReleaseGroup", message.TrackFile.ReleaseGroup); + history.Data.Add("Size", message.TrackFile.Size.ToString()); _historyRepository.Insert(history); } @@ -348,6 +350,7 @@ namespace NzbDrone.Core.History history.Data.Add("SourcePath", sourcePath); history.Data.Add("Path", path); history.Data.Add("ReleaseGroup", message.TrackFile.ReleaseGroup); + history.Data.Add("Size", message.TrackFile.Size.ToString()); _historyRepository.Insert(history); } @@ -405,8 +408,9 @@ namespace NzbDrone.Core.History }; history.Data.Add("DownloadClient", message.DownloadClientInfo?.Name); - history.Data.Add("ReleaseGroup", message.TrackedDownload?.RemoteAlbum?.ParsedAlbumInfo?.ReleaseGroup); history.Data.Add("Message", message.Message); + history.Data.Add("ReleaseGroup", message.TrackedDownload?.RemoteAlbum?.ParsedAlbumInfo?.ReleaseGroup); + history.Data.Add("Size", message.TrackedDownload?.DownloadItem.TotalSize.ToString()); historyToAdd.Add(history); } diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListParser.cs b/src/NzbDrone.Core/Indexers/FileList/FileListParser.cs index 475301bdd..6fb1ef477 100644 --- a/src/NzbDrone.Core/Indexers/FileList/FileListParser.cs +++ b/src/NzbDrone.Core/Indexers/FileList/FileListParser.cs @@ -18,8 +18,6 @@ namespace NzbDrone.Core.Indexers.FileList public IList ParseResponse(IndexerResponse indexerResponse) { - var torrentInfos = new List(); - if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK) { throw new IndexerException(indexerResponse, @@ -27,6 +25,13 @@ namespace NzbDrone.Core.Indexers.FileList indexerResponse.HttpResponse.StatusCode); } + if (!indexerResponse.HttpResponse.Headers.ContentType.Contains(HttpAccept.Json.Value)) + { + throw new IndexerException(indexerResponse, "Unexpected response header '{0}' from indexer request, expected '{1}'", indexerResponse.HttpResponse.Headers.ContentType, HttpAccept.Json.Value); + } + + var torrentInfos = new List(); + var queryResults = JsonConvert.DeserializeObject>(indexerResponse.Content); foreach (var result in queryResults) diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListSettings.cs b/src/NzbDrone.Core/Indexers/FileList/FileListSettings.cs index e2e919265..09eca5d4f 100644 --- a/src/NzbDrone.Core/Indexers/FileList/FileListSettings.cs +++ b/src/NzbDrone.Core/Indexers/FileList/FileListSettings.cs @@ -54,6 +54,9 @@ namespace NzbDrone.Core.Indexers.FileList [FieldDefinition(7)] public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); + [FieldDefinition(8, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } + public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Indexers/Gazelle/GazelleSettings.cs b/src/NzbDrone.Core/Indexers/Gazelle/GazelleSettings.cs index b9dc2e59e..1996d4747 100644 --- a/src/NzbDrone.Core/Indexers/Gazelle/GazelleSettings.cs +++ b/src/NzbDrone.Core/Indexers/Gazelle/GazelleSettings.cs @@ -35,17 +35,20 @@ namespace NzbDrone.Core.Indexers.Gazelle [FieldDefinition(2, Label = "Password", Type = FieldType.Password, HelpText = "Password", Privacy = PrivacyLevel.Password)] public string Password { get; set; } - [FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] - public int MinimumSeeders { get; set; } + [FieldDefinition(3, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Will cause grabbing to fail if you do not have any tokens available", Advanced = true)] + public bool UseFreeleechToken { get; set; } - [FieldDefinition(4)] - public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); - - [FieldDefinition(5, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] + [FieldDefinition(4, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] public int? EarlyReleaseLimit { get; set; } - [FieldDefinition(6, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Will cause grabbing to fail if you do not have any tokens available", Advanced = true)] - public bool UseFreeleechToken { get; set; } + [FieldDefinition(5, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + public int MinimumSeeders { get; set; } + + [FieldDefinition(6)] + public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); + + [FieldDefinition(7, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } public NzbDroneValidationResult Validate() { diff --git a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsSettings.cs b/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsSettings.cs index 4a589e5ba..c03b5c90f 100644 --- a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsSettings.cs +++ b/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrentsSettings.cs @@ -32,14 +32,17 @@ namespace NzbDrone.Core.Indexers.IPTorrents [FieldDefinition(0, Label = "Feed URL", HelpText = "The full RSS feed url generated by IPTorrents, using only the categories you selected (HD, SD, x264, etc ...)")] public string BaseUrl { get; set; } - [FieldDefinition(1, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + [FieldDefinition(1, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] + public int? EarlyReleaseLimit { get; set; } + + [FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] public int MinimumSeeders { get; set; } - [FieldDefinition(2)] + [FieldDefinition(3)] public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); - [FieldDefinition(3, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] - public int? EarlyReleaseLimit { get; set; } + [FieldDefinition(4, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } public NzbDroneValidationResult Validate() { diff --git a/src/NzbDrone.Core/Indexers/ITorrentIndexerSettings.cs b/src/NzbDrone.Core/Indexers/ITorrentIndexerSettings.cs index c8df67ea1..ee9cc2398 100644 --- a/src/NzbDrone.Core/Indexers/ITorrentIndexerSettings.cs +++ b/src/NzbDrone.Core/Indexers/ITorrentIndexerSettings.cs @@ -5,5 +5,6 @@ namespace NzbDrone.Core.Indexers int MinimumSeeders { get; set; } SeedCriteriaSettings SeedCriteria { get; set; } + bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } } } diff --git a/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs b/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs index 31420c6d3..57881c48c 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs @@ -53,7 +53,6 @@ namespace NzbDrone.Core.Indexers.Newznab yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws")); yield return GetDefinition("NZBgeek", GetSettings("https://api.nzbgeek.info")); yield return GetDefinition("nzbplanet.net", GetSettings("https://api.nzbplanet.net")); - yield return GetDefinition("OZnzb.com", GetSettings("https://api.oznzb.com")); yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com")); yield return GetDefinition("Tabula Rasa", GetSettings("https://www.tabula-rasa.pw", apiPath: @"/api/v1/api")); yield return GetDefinition("VeryCouch LazyMuch", GetSettings("https://api.verycouch.com")); diff --git a/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs b/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs index 670baecc9..70d328572 100644 --- a/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs +++ b/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs @@ -10,7 +10,6 @@ namespace NzbDrone.Core.Indexers.Nyaa public override string Name => "Nyaa"; public override DownloadProtocol Protocol => DownloadProtocol.Torrent; - public override int PageSize => 75; public Nyaa(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger) : base(httpClient, indexerStatusService, configService, parsingService, logger) @@ -19,7 +18,7 @@ namespace NzbDrone.Core.Indexers.Nyaa public override IIndexerRequestGenerator GetRequestGenerator() { - return new NyaaRequestGenerator() { Settings = Settings, PageSize = PageSize }; + return new NyaaRequestGenerator() { Settings = Settings }; } public override IParseIndexerResponse GetParser() diff --git a/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs index 0b2d15ceb..7e7b16604 100644 --- a/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Nyaa/NyaaRequestGenerator.cs @@ -9,20 +9,11 @@ namespace NzbDrone.Core.Indexers.Nyaa { public NyaaSettings Settings { get; set; } - public int MaxPages { get; set; } - public int PageSize { get; set; } - - public NyaaRequestGenerator() - { - MaxPages = 3; - PageSize = 75; - } - public virtual IndexerPageableRequestChain GetRecentRequests() { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetPagedRequests(MaxPages, null)); + pageableRequests.Add(GetPagedRequests(null)); return pageableRequests; } @@ -34,7 +25,7 @@ namespace NzbDrone.Core.Indexers.Nyaa var artistQuery = searchCriteria.CleanArtistQuery.Replace("+", " ").Trim(); var albumQuery = searchCriteria.CleanAlbumQuery.Replace("+", " ").Trim(); - pageableRequests.Add(GetPagedRequests(MaxPages, PrepareQuery($"{artistQuery} {albumQuery}"))); + pageableRequests.Add(GetPagedRequests(PrepareQuery($"{artistQuery} {albumQuery}"))); return pageableRequests; } @@ -45,33 +36,21 @@ namespace NzbDrone.Core.Indexers.Nyaa var artistQuery = searchCriteria.CleanArtistQuery.Replace("+", " ").Trim(); - pageableRequests.Add(GetPagedRequests(MaxPages, PrepareQuery(artistQuery))); + pageableRequests.Add(GetPagedRequests(PrepareQuery(artistQuery))); return pageableRequests; } - private IEnumerable GetPagedRequests(int maxPages, string term) + private IEnumerable GetPagedRequests(string term) { - var baseUrl = string.Format("{0}/?page=rss{1}", Settings.BaseUrl.TrimEnd('/'), Settings.AdditionalParameters); + var baseUrl = $"{Settings.BaseUrl.TrimEnd('/')}/?page=rss{Settings.AdditionalParameters}"; if (term != null) { baseUrl += "&term=" + term; } - if (PageSize == 0) - { - yield return new IndexerRequest(baseUrl, HttpAccept.Rss); - } - else - { - yield return new IndexerRequest(baseUrl, HttpAccept.Rss); - - for (var page = 1; page < maxPages; page++) - { - yield return new IndexerRequest($"{baseUrl}&offset={page + 1}", HttpAccept.Rss); - } - } + yield return new IndexerRequest(baseUrl, HttpAccept.Rss); } private string PrepareQuery(string query) diff --git a/src/NzbDrone.Core/Indexers/Nyaa/NyaaSettings.cs b/src/NzbDrone.Core/Indexers/Nyaa/NyaaSettings.cs index 2ed9b2da1..23c06acb1 100644 --- a/src/NzbDrone.Core/Indexers/Nyaa/NyaaSettings.cs +++ b/src/NzbDrone.Core/Indexers/Nyaa/NyaaSettings.cs @@ -30,14 +30,17 @@ namespace NzbDrone.Core.Indexers.Nyaa [FieldDefinition(1, Label = "Additional Parameters", Advanced = true, HelpText = "Please note if you change the category you will have to add required/restricted rules about the subgroups to avoid foreign language releases.")] public string AdditionalParameters { get; set; } - [FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + [FieldDefinition(2, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] + public int? EarlyReleaseLimit { get; set; } + + [FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] public int MinimumSeeders { get; set; } - [FieldDefinition(3)] + [FieldDefinition(4)] public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); - [FieldDefinition(4, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] - public int? EarlyReleaseLimit { get; set; } + [FieldDefinition(5, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } public NzbDroneValidationResult Validate() { diff --git a/src/NzbDrone.Core/Indexers/Redacted/RedactedParser.cs b/src/NzbDrone.Core/Indexers/Redacted/RedactedParser.cs index a6a174a79..bb536e07c 100644 --- a/src/NzbDrone.Core/Indexers/Redacted/RedactedParser.cs +++ b/src/NzbDrone.Core/Indexers/Redacted/RedactedParser.cs @@ -47,28 +47,21 @@ namespace NzbDrone.Core.Indexers.Redacted foreach (var torrent in result.Torrents) { var id = torrent.TorrentId; + var title = WebUtility.HtmlDecode(GetTitle(result, torrent)); var artist = WebUtility.HtmlDecode(result.Artist); var album = WebUtility.HtmlDecode(result.GroupName); - var title = $"{result.Artist} - {result.GroupName} ({result.GroupYear}) [{torrent.Format} {torrent.Encoding}] [{torrent.Media}]"; - if (torrent.HasCue) - { - title += " [Cue]"; - } - torrentInfos.Add(new GazelleInfo { Guid = $"Redacted-{id}", + InfoUrl = GetInfoUrl(result.GroupId, id), + DownloadUrl = GetDownloadUrl(id, torrent.CanUseToken), + Title = title, Artist = artist, - - // Splice Title from info to avoid calling API again for every torrent. - Title = WebUtility.HtmlDecode(title), Album = album, Container = torrent.Encoding, Codec = torrent.Format, Size = long.Parse(torrent.Size), - DownloadUrl = GetDownloadUrl(id, torrent.CanUseToken), - InfoUrl = GetInfoUrl(result.GroupId, id), Seeders = int.Parse(torrent.Seeders), Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders), PublishDate = torrent.Time.ToUniversalTime(), @@ -85,13 +78,50 @@ namespace NzbDrone.Core.Indexers.Redacted .ToArray(); } + private string GetTitle(GazelleRelease result, GazelleTorrent torrent) + { + var title = $"{result.Artist} - {result.GroupName} ({result.GroupYear})"; + + if (result.ReleaseType.IsNotNullOrWhiteSpace() && result.ReleaseType != "Unknown") + { + title += " [" + result.ReleaseType + "]"; + } + + if (torrent.RemasterTitle.IsNotNullOrWhiteSpace()) + { + title += $" [{$"{torrent.RemasterTitle} {torrent.RemasterYear}".Trim()}]"; + } + + var flags = new List + { + $"{torrent.Format} {torrent.Encoding}", + $"{torrent.Media}" + }; + + if (torrent.HasLog) + { + flags.Add("Log (" + torrent.LogScore + "%)"); + } + + if (torrent.HasCue) + { + flags.Add("Cue"); + } + + return $"{title} [{string.Join(" / ", flags)}]"; + } + private string GetDownloadUrl(int torrentId, bool canUseToken) { var url = new HttpUri(_settings.BaseUrl) .CombinePath("/ajax.php") .AddQueryParam("action", "download") - .AddQueryParam("id", torrentId) - .AddQueryParam("usetoken", _settings.UseFreeleechToken && canUseToken ? 1 : 0); + .AddQueryParam("id", torrentId); + + if (_settings.UseFreeleechToken && canUseToken) + { + url = url.AddQueryParam("usetoken", "1"); + } return url.FullUri; } diff --git a/src/NzbDrone.Core/Indexers/Redacted/RedactedRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Redacted/RedactedRequestGenerator.cs index 84d34c953..754a1ef3c 100644 --- a/src/NzbDrone.Core/Indexers/Redacted/RedactedRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Redacted/RedactedRequestGenerator.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using NzbDrone.Common.Http; using NzbDrone.Core.IndexerSearch.Definitions; @@ -28,11 +29,11 @@ namespace NzbDrone.Core.Indexers.Redacted if (searchCriteria.CleanArtistQuery == "VA") { - pageableRequests.Add(GetRequest($"&groupname={searchCriteria.CleanAlbumQuery}")); + pageableRequests.Add(GetRequest($"groupname={searchCriteria.CleanAlbumQuery}")); } else { - pageableRequests.Add(GetRequest($"&artistname={searchCriteria.CleanArtistQuery}&groupname={searchCriteria.CleanAlbumQuery}")); + pageableRequests.Add(GetRequest($"artistname={searchCriteria.CleanArtistQuery}&groupname={searchCriteria.CleanAlbumQuery}")); } return pageableRequests; @@ -41,17 +42,26 @@ namespace NzbDrone.Core.Indexers.Redacted public IndexerPageableRequestChain GetSearchRequests(ArtistSearchCriteria searchCriteria) { var pageableRequests = new IndexerPageableRequestChain(); - pageableRequests.Add(GetRequest($"&artistname={searchCriteria.CleanArtistQuery}")); + pageableRequests.Add(GetRequest($"artistname={searchCriteria.CleanArtistQuery}")); return pageableRequests; } private IEnumerable GetRequest(string searchParameters) { - var req = RequestBuilder() - .Resource($"ajax.php?action=browse&searchstr={searchParameters}") - .Build(); + var requestBuilder = RequestBuilder() + .Resource($"ajax.php?{searchParameters}") + .AddQueryParam("action", "browse") + .AddQueryParam("order_by", "time") + .AddQueryParam("order_way", "desc"); - yield return new IndexerRequest(req); + var categories = _settings.Categories.ToList(); + + if (categories.Any()) + { + categories.ForEach(cat => requestBuilder.AddQueryParam($"filter_cat[{cat}]", "1")); + } + + yield return new IndexerRequest(requestBuilder.Build()); } private HttpRequestBuilder RequestBuilder() diff --git a/src/NzbDrone.Core/Indexers/Redacted/RedactedSettings.cs b/src/NzbDrone.Core/Indexers/Redacted/RedactedSettings.cs index 7c511cbb3..ed0001780 100644 --- a/src/NzbDrone.Core/Indexers/Redacted/RedactedSettings.cs +++ b/src/NzbDrone.Core/Indexers/Redacted/RedactedSettings.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using FluentValidation; using NzbDrone.Core.Annotations; using NzbDrone.Core.Validation; @@ -19,6 +20,7 @@ namespace NzbDrone.Core.Indexers.Redacted public RedactedSettings() { BaseUrl = "https://redacted.ch"; + Categories = new[] { (int)RedactedCategory.Music }; MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; } @@ -27,21 +29,45 @@ namespace NzbDrone.Core.Indexers.Redacted [FieldDefinition(1, Label = "ApiKey", HelpText = "Generate this in 'Access Settings' in your Redacted profile", Privacy = PrivacyLevel.ApiKey)] public string ApiKey { get; set; } - [FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] - public int MinimumSeeders { get; set; } + [FieldDefinition(2, Label = "Categories", Type = FieldType.Select, SelectOptions = typeof(RedactedCategory), HelpText = "If unspecified, all options are used.")] + public IEnumerable Categories { get; set; } - [FieldDefinition(3)] - public SeedCriteriaSettings SeedCriteria { get; set; } = new (); + [FieldDefinition(3, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Will cause grabbing to fail if you do not have any tokens available", Advanced = true)] + public bool UseFreeleechToken { get; set; } [FieldDefinition(4, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] public int? EarlyReleaseLimit { get; set; } - [FieldDefinition(5, Type = FieldType.Checkbox, Label = "Use Freeleech Token", HelpText = "Will cause grabbing to fail if you do not have any tokens available", Advanced = true)] - public bool UseFreeleechToken { get; set; } + [FieldDefinition(5, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + public int MinimumSeeders { get; set; } + + [FieldDefinition(6)] + public SeedCriteriaSettings SeedCriteria { get; set; } = new (); + + [FieldDefinition(7, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); } } + + public enum RedactedCategory + { + [FieldOption(label: "Music")] + Music = 1, + [FieldOption(label: "Applications")] + Applications = 2, + [FieldOption(label: "E-Books")] + EBooks = 3, + [FieldOption(label: "Audiobooks")] + Audiobooks = 4, + [FieldOption(label: "E-Learning Videos")] + ELearningVideos = 5, + [FieldOption(label: "Comedy")] + Comedy = 6, + [FieldOption(label: "Comics")] + Comics = 7 + } } diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerSettings.cs b/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerSettings.cs index 812320f5d..2d94fc881 100644 --- a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerSettings.cs +++ b/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexerSettings.cs @@ -34,14 +34,17 @@ namespace NzbDrone.Core.Indexers.TorrentRss [FieldDefinition(2, Type = FieldType.Checkbox, Label = "Allow Zero Size", HelpText = "Enabling this will allow you to use feeds that don't specify release size, but be careful, size related checks will not be performed.")] public bool AllowZeroSize { get; set; } - [FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + [FieldDefinition(3, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] + public int? EarlyReleaseLimit { get; set; } + + [FieldDefinition(4, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] public int MinimumSeeders { get; set; } - [FieldDefinition(4)] + [FieldDefinition(5)] public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); - [FieldDefinition(5, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] - public int? EarlyReleaseLimit { get; set; } + [FieldDefinition(6, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } public NzbDroneValidationResult Validate() { diff --git a/src/NzbDrone.Core/Indexers/Torrentleech/TorrentleechSettings.cs b/src/NzbDrone.Core/Indexers/Torrentleech/TorrentleechSettings.cs index 07b7641e2..367a694ae 100644 --- a/src/NzbDrone.Core/Indexers/Torrentleech/TorrentleechSettings.cs +++ b/src/NzbDrone.Core/Indexers/Torrentleech/TorrentleechSettings.cs @@ -31,14 +31,17 @@ namespace NzbDrone.Core.Indexers.Torrentleech [FieldDefinition(1, Label = "API Key", Privacy = PrivacyLevel.ApiKey)] public string ApiKey { get; set; } - [FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + [FieldDefinition(2, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] + public int? EarlyReleaseLimit { get; set; } + + [FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] public int MinimumSeeders { get; set; } - [FieldDefinition(3)] + [FieldDefinition(4)] public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); - [FieldDefinition(4, Type = FieldType.Number, Label = "Early Download Limit", Unit = "days", HelpText = "Time before release date Lidarr will download from this indexer, empty is no limit", Advanced = true)] - public int? EarlyReleaseLimit { get; set; } + [FieldDefinition(5, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } public NzbDroneValidationResult Validate() { diff --git a/src/NzbDrone.Core/Indexers/Torznab/TorznabSettings.cs b/src/NzbDrone.Core/Indexers/Torznab/TorznabSettings.cs index a40a14e92..3de57cd26 100644 --- a/src/NzbDrone.Core/Indexers/Torznab/TorznabSettings.cs +++ b/src/NzbDrone.Core/Indexers/Torznab/TorznabSettings.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Text.RegularExpressions; using FluentValidation; @@ -10,10 +11,7 @@ namespace NzbDrone.Core.Indexers.Torznab { public class TorznabSettingsValidator : AbstractValidator { - private static readonly string[] ApiKeyWhiteList = - { - "hd4free.xyz", - }; + private static readonly string[] ApiKeyWhiteList = Array.Empty(); private static bool ShouldHaveApiKey(TorznabSettings settings) { @@ -51,12 +49,15 @@ namespace NzbDrone.Core.Indexers.Torznab MinimumSeeders = IndexerDefaults.MINIMUM_SEEDERS; } - [FieldDefinition(6, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] + [FieldDefinition(7, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)] public int MinimumSeeders { get; set; } - [FieldDefinition(7)] + [FieldDefinition(8)] public SeedCriteriaSettings SeedCriteria { get; set; } = new SeedCriteriaSettings(); + [FieldDefinition(9, Type = FieldType.Checkbox, Label = "IndexerSettingsRejectBlocklistedTorrentHashes", HelpText = "IndexerSettingsRejectBlocklistedTorrentHashesHelpText", Advanced = true)] + public bool RejectBlocklistedTorrentHashesWhileGrabbing { get; set; } + public override NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Lidarr.Core.csproj b/src/NzbDrone.Core/Lidarr.Core.csproj index d0abcfcce..436a2404f 100644 --- a/src/NzbDrone.Core/Lidarr.Core.csproj +++ b/src/NzbDrone.Core/Lidarr.Core.csproj @@ -5,6 +5,7 @@ + @@ -16,7 +17,7 @@ - + @@ -24,7 +25,7 @@ - + diff --git a/src/NzbDrone.Core/Localization/Core/ar.json b/src/NzbDrone.Core/Localization/Core/ar.json index c11e1972a..65cbf1c87 100644 --- a/src/NzbDrone.Core/Localization/Core/ar.json +++ b/src/NzbDrone.Core/Localization/Core/ar.json @@ -24,10 +24,8 @@ "Mode": "الوضع", "Monitored": "مراقب", "MoreInfo": "مزيد من المعلومات", - "OnGrabHelpText": "عند الاستيلاء", "OnHealthIssue": "في قضية الصحة", "OnRename": "عند إعادة التسمية", - "OnRenameHelpText": "عند إعادة التسمية", "Options": "خيارات", "Path": "مسار", "Profiles": "مظهر", @@ -220,7 +218,7 @@ "CutoffHelpText": "بمجرد الوصول إلى هذه الجودة ، لن يقوم {appName} بتنزيل الأفلام", "CutoffUnmet": "قطع غير ملباة", "Dates": "تواريخ", - "DBMigration": "ترحيل DB", + "DatabaseMigration": "ترحيل DB", "DelayProfile": "ملف التأخير", "DelayProfiles": "ملفات تعريف التأخير", "Delete": "حذف", @@ -274,7 +272,6 @@ "ErrorLoadingContents": "خطأ في تحميل المحتويات", "ErrorLoadingPreviews": "خطأ في تحميل المعاينات", "Exception": "استثناء", - "ExtraFileExtensionsHelpTexts1": "قائمة مفصولة بفواصل بالملفات الإضافية المراد استيرادها (سيتم استيراد .nfo كـ .nfo-Orig)", "FileDateHelpText": "تغيير تاريخ الملف عند الاستيراد / إعادة الفحص", "FileManagement": "إدارة الملفات", "Filename": "اسم الملف", @@ -312,7 +309,6 @@ "ImportExtraFilesHelpText": "استيراد ملفات إضافية مطابقة (ترجمات ، nfo ، إلخ) بعد استيراد ملف فيلم", "ImportFailedInterp": "فشل الاستيراد: {0}", "Importing": "استيراد", - "IncludeHealthWarningsHelpText": "قم بتضمين التحذيرات الصحية", "IncludeUnknownArtistItemsHelpText": "إظهار العناصر بدون فيلم في قائمة الانتظار. يمكن أن يشمل ذلك الأفلام التي تمت إزالتها أو أي شيء آخر في فئة {appName}", "IncludeUnmonitored": "تضمين غير مراقب", "Indexer": "مفهرس", @@ -326,7 +322,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "يدعم Whisparr أي عميل تنزيل يستخدم معيار Newznab ، بالإضافة إلى عملاء التنزيل الآخرين المدرجة أدناه.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "يدعم {appName} أي مفهرس يستخدم معيار Newznab ، بالإضافة إلى مفهرسات أخرى مذكورة أدناه.", "LidarrTags": "العلامات الرادار", - "LoadingTrackFilesFailed": "فشل تحميل ملفات الفيلم", "LocalPath": "مسار محلي", "LocalPathHelpText": "المسار الذي يجب أن يستخدمه {appName} للوصول إلى المسار البعيد محليًا", "LogFiles": "ملفات الدخول", @@ -346,12 +341,9 @@ "NamingSettings": "إعدادات التسمية", "New": "جديد", "NoLeaveIt": "لا ، اتركها", - "NoLimitForAnyRuntime": "لا يوجد حد لأي وقت تشغيل", "NoLogFiles": "لا توجد ملفات سجل", - "NoMinimumForAnyRuntime": "لا يوجد حد أدنى لأي وقت تشغيل", "None": "لا شيء", "NotificationTriggers": "مشغلات الإخطار", - "PriorityHelpText": "أولوية المفهرس من 1 (الأعلى) إلى 50 (الأدنى). الافتراضي: 25.", "ReadTheWikiForMoreInformation": "اقرأ Wiki لمزيد من المعلومات", "RemoveTagRemovingTag": "إزالة العلامة", "RenameTracksHelpText": "سيستخدم {appName} اسم الملف الحالي إذا تم تعطيل إعادة التسمية", @@ -391,9 +383,7 @@ "BindAddressHelpText": "عنوان IP4 صالح أو \"*\" لجميع الواجهات", "CertificateValidationHelpText": "تغيير مدى صرامة التحقق من صحة شهادة HTTPS", "OnGrab": "عند الاستيلاء", - "OnHealthIssueHelpText": "في قضية الصحة", "OnUpgrade": "عند الترقية", - "OnUpgradeHelpText": "عند الترقية", "OpenBrowserOnStart": "افتح المتصفح عند البدء", "Original": "أصلي", "PackageVersion": "إصدار الحزمة", @@ -657,7 +647,6 @@ "ApplyTagsHelpTextAdd": "إضافة: أضف العلامات إلى قائمة العلامات الموجودة", "RemoveSelectedItemsQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟", "NoEventsFound": "لم يتم العثور على أحداث", - "RemoveFromDownloadClientHelpTextWarning": "ستؤدي الإزالة إلى إزالة التنزيل والملف (الملفات) من عميل التنزيل.", "RemoveSelectedItemQueueMessageText": "هل تريد بالتأكيد إزالة {0} عنصر {1} من قائمة الانتظار؟", "ApplyTagsHelpTextHowToApplyArtists": "كيفية تطبيق العلامات على الأفلام المختارة", "ApplyTagsHelpTextHowToApplyDownloadClients": "كيفية تطبيق العلامات على الأفلام المختارة", @@ -707,5 +696,12 @@ "ConditionUsingRegularExpressions": "يتطابق هذا الشرط مع استخدام التعبيرات العادية. لاحظ أن الأحرف {0} لها معاني خاصة وتحتاج إلى الهروب بعلامة {1}", "Connection": "الإتصال", "DeleteAutoTagHelpText": "هل أنت متأكد من أنك تريد حذف ملف تعريف الجودة {0}", - "RenameFiles": "إعادة تسمية الملفات" + "RenameFiles": "إعادة تسمية الملفات", + "NoLimitForAnyDuration": "لا يوجد حد لأي وقت تشغيل", + "NoMinimumForAnyDuration": "لا يوجد حد أدنى لأي وقت تشغيل", + "PreferredSize": "الحجم المفضل", + "Unlimited": "غير محدود", + "AddImportListExclusionAlbumHelpText": "منع إضافة الفيلم إلى {appName} بواسطة القوائم", + "ExtraFileExtensionsHelpTextsExamples": "أمثلة: \".sub أو .nfo\" أو \"sub، nfo\"", + "ExtraFileExtensionsHelpText": "قائمة مفصولة بفواصل بالملفات الإضافية المراد استيرادها (سيتم استيراد .nfo كـ .nfo-Orig)" } diff --git a/src/NzbDrone.Core/Localization/Core/bg.json b/src/NzbDrone.Core/Localization/Core/bg.json index 23d77fd54..dc0939f51 100644 --- a/src/NzbDrone.Core/Localization/Core/bg.json +++ b/src/NzbDrone.Core/Localization/Core/bg.json @@ -91,7 +91,7 @@ "CreateGroup": "Създай група", "CutoffHelpText": "След достигане на това качество {appName} вече няма да изтегля филми", "CutoffUnmet": "Прекъсване Неудовлетворено", - "DBMigration": "DB миграция", + "DatabaseMigration": "DB миграция", "Dates": "Дати", "DelayingDownloadUntilInterp": "Забавя се изтеглянето до {0} в {1}", "DeleteImportListExclusionMessageText": "Наистина ли искате да изтриете това изключване от списъка за импортиране?", @@ -205,7 +205,6 @@ "ErrorLoadingContents": "Грешка при зареждането на съдържанието", "ErrorLoadingPreviews": "Грешка при зареждането на визуализациите", "Exception": "Изключение", - "ExtraFileExtensionsHelpTexts1": "Списък с допълнителни файлове за импортиране, разделени със запетая (.nfo ще бъде импортиран като .nfo-orig)", "FileDateHelpText": "Променете датата на файла при импортиране / пресканиране", "GeneralSettings": "Основни настройки", "Global": "Глобален", @@ -234,7 +233,6 @@ "ImportExtraFilesHelpText": "Импортирайте съвпадащи допълнителни файлове (субтитри, nfo и т.н.) след импортиране на филмов файл", "ImportFailedInterp": "Неуспешно импортиране: {0}", "Importing": "Импортиране", - "IncludeHealthWarningsHelpText": "Включете здравни предупреждения", "IncludeUnknownArtistItemsHelpText": "Показване на елементи без филм в опашката. Това може да включва премахнати филми или нещо друго от категорията на {appName}", "IncludeUnmonitored": "Включете Без наблюдение", "Indexer": "Индексатор", @@ -246,7 +244,6 @@ "IsCutoffCutoff": "Отрязвам", "IsCutoffUpgradeUntilThisQualityIsMetOrExceeded": "Надстройте, докато това качество бъде постигнато или надвишено", "Level": "Ниво", - "LoadingTrackFilesFailed": "Зареждането на филмови файлове не бе успешно", "LocalPath": "Местен път", "LocalPathHelpText": "Път, който {appName} трябва да използва за локален достъп до отдалечения път", "LogFiles": "Лог файлове", @@ -280,20 +277,13 @@ "NoBackupsAreAvailable": "Няма налични резервни копия", "NoHistory": "Няма история", "NoLeaveIt": "Не, оставете го", - "NoLimitForAnyRuntime": "Няма ограничение за всяко време на изпълнение", "NoLogFiles": "Няма регистрационни файлове", - "NoMinimumForAnyRuntime": "Няма минимум за всяко време на изпълнение", "None": "Нито един", "NotificationTriggers": "Задействания за уведомяване", "NoUpdatesAreAvailable": "Няма налични актуализации", - "OnGrabHelpText": "На Граб", - "OnHealthIssueHelpText": "По здравен въпрос", - "OnRenameHelpText": "При преименуване", - "OnUpgradeHelpText": "При надстройка", "OpenBrowserOnStart": "Отворете браузъра при стартиране", "Options": "Настроики", "Original": "Оригинал", - "PriorityHelpText": "Приоритет на индексатора от 1 (най-висок) до 50 (най-нисък). По подразбиране: 25.", "Profiles": "Профили", "Proper": "Правилно", "PropersAndRepacks": "Propers и Repacks", @@ -656,7 +646,6 @@ "ApplyTagsHelpTextRemove": "Премахване: Премахнете въведените тагове", "NoEventsFound": "Няма намерени събития", "RemoveSelectedItemQueueMessageText": "Наистина ли искате да премахнете {0} елемент {1} от опашката?", - "RemoveFromDownloadClientHelpTextWarning": "Премахването ще премахне изтеглянето и файловете от клиента за изтегляне.", "RemoveSelectedItemsQueueMessageText": "Наистина ли искате да премахнете {0} елемент {1} от опашката?", "ApplyTagsHelpTextHowToApplyArtists": "Как да приложите тагове към избраните филми", "ApplyTagsHelpTextHowToApplyDownloadClients": "Как да приложите тагове към избраните филми", @@ -708,5 +697,13 @@ "Overview": "Общ преглед", "OverviewOptions": "Опции за преглед", "PosterOptions": "Опции за плакати", - "Small": "Малък" + "Small": "Малък", + "NoLimitForAnyDuration": "Няма ограничение за всяко време на изпълнение", + "NoMinimumForAnyDuration": "Няма минимум за всяко време на изпълнение", + "PreferredSize": "Предпочитан размер", + "Unlimited": "Неограничен", + "AddImportListExclusionAlbumHelpText": "Предотвратете добавянето на филм към {appName} чрез списъци", + "ExtraFileExtensionsHelpText": "Списък с допълнителни файлове за импортиране, разделени със запетая (.nfo ще бъде импортиран като .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Примери: '.sub, .nfo' или 'sub, nfo'", + "DeleteArtistFoldersHelpText": "Изтрийте папката с филма и съдържанието му" } diff --git a/src/NzbDrone.Core/Localization/Core/ca.json b/src/NzbDrone.Core/Localization/Core/ca.json index dfc479296..98ed1948f 100644 --- a/src/NzbDrone.Core/Localization/Core/ca.json +++ b/src/NzbDrone.Core/Localization/Core/ca.json @@ -1,20 +1,20 @@ { "New": "Nou", "Actions": "Accions", - "Password": "Contrassenya", + "Password": "Contrasenya", "QualityProfile": "Perfil de qualitat", "QualityProfiles": "Perfil de qualitat", "Queue": "Cua", "RecyclingBin": "Paperera de reciclatge", - "Refresh": "Actualització", - "Reload": "Recarregar", + "Refresh": "Actualitza", + "Reload": "Torna a carregar", "About": "Quant a", "UnableToLoadTags": "No es poden carregar les etiquetes", "Result": "Resultat", "Status": "Estat", "BindAddress": "Adreça d'enllaç", - "DeleteQualityProfileMessageText": "Esteu segur que voleu suprimir el perfil de qualitat {0}", - "DeleteReleaseProfile": "Suprimeix el perfil de retard", + "DeleteQualityProfileMessageText": "Esteu segur que voleu suprimir el perfil de qualitat '{name}'?", + "DeleteReleaseProfile": "Suprimeix el perfil de llançament", "DeleteReleaseProfileMessageText": "Esteu segur que voleu suprimir aquest perfil de retard?", "DownloadClients": "Descàrrega Clients", "EnableColorImpairedMode": "Activa el mode amb alteracions del color", @@ -81,7 +81,7 @@ "Tasks": "Tasques", "ThisCannotBeCancelled": "No es pot cancel·lar un cop iniciat sense desactivar tots els vostres indexadors.", "TorrentDelay": "Retard del torrent", - "TorrentDelayHelpText": "Retard en minuts per esperar abans de capturar un torrent", + "TorrentDelayHelpText": "Retard en minuts per a esperar abans de capturar un torrent", "Torrents": "Torrents", "UnableToLoadGeneralSettings": "No es pot carregar la configuració general", "UnableToLoadHistory": "No es pot carregar l'historial", @@ -94,7 +94,7 @@ "ShowDateAdded": "Mostra la data d'addició", "Size": " Mida", "ApplyTags": "Aplica etiquetes", - "BackupFolderHelpText": "Els camins relatius estaran sota el directori AppData del {appName}", + "BackupFolderHelpText": "Els camins relatius estaran sota el directori AppData de {appName}", "BackupRetentionHelpText": "Les còpies de seguretat automàtiques anteriors al període de retenció s'eliminaran automàticament", "Backups": "Còpies de seguretat", "BindAddressHelpTextWarning": "Cal reiniciar perquè tingui efecte", @@ -103,7 +103,7 @@ "ChangeHasNotBeenSavedYet": "El canvi encara no s'ha desat", "ChmodFolder": "Carpeta chmod", "DeleteImportListExclusion": "Suprimeix l'exclusió de la llista d'importació", - "DeleteImportListMessageText": "Esteu segur que voleu suprimir la llista '{0}'?", + "DeleteImportListMessageText": "Esteu segur que voleu suprimir la llista '{name}'?", "DeleteIndexer": "Suprimeix l'indexador", "DestinationPath": "Camí de destinació", "EnableCompletedDownloadHandlingHelpText": "Importa automàticament les descàrregues completades des del client de descàrregues", @@ -113,7 +113,6 @@ "ErrorLoadingContents": "S'ha produït un error en carregar el contingut", "Exception": "Excepció", "Track": "Traça", - "ExtraFileExtensionsHelpTexts1": "Llista separada per comes de fitxers addicionals per importar (.nfo s'importarà com a .nfo-orig)", "FileDateHelpText": "Canvia la data del fitxer en importar/reescanejar", "FileManagement": "Gestió del fitxers", "GoToInterp": "Vés a {0}", @@ -125,11 +124,10 @@ "Indexers": "Indexadors", "IndexerSettings": "Configuració de l'indexador", "Interval": "Interval", - "IsCutoffCutoff": "Tallar", + "IsCutoffCutoff": "Requisit", "IsTagUsedCannotBeDeletedWhileInUse": "No es pot suprimir mentre està en ús", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} admet qualsevol indexador que utilitzi l'estàndard Newznab, així com altres indexadors que s'enumeren a continuació.", "LidarrTags": "Etiquetes de {appName}", - "LoadingTrackFilesFailed": "No s'han pogut carregar els fitxers de pel·lícules", "Local": "Local", "LocalPath": "Camí local", "LocalPathHelpText": "Camí que {appName} hauria d'utilitzar per accedir al camí remot localment", @@ -142,14 +140,11 @@ "NoLeaveIt": "No, deixa-ho", "NotificationTriggers": "Activadors de notificacions", "NoUpdatesAreAvailable": "No hi ha actualitzacions disponibles", - "OnHealthIssueHelpText": "Al detectar incidència", - "OnRenameHelpText": "Al reanomenar", "RecycleBinHelpText": "Els fitxers de pel·lícula aniran aquí quan se suprimeixin en lloc de suprimir-se permanentment", "Redownload": "Torna a baixar", "ShowRelativeDates": "Mostra les dates relatives", "Language": "Idioma", "UILanguage": "Idioma de la interfície", - "OnApplicationUpdateHelpText": "A l'actualitzar de l'aplicació", "PreviewRename": "Vista prèvia reanomenat", "Proxy": "Servidor intermediari", "ProxyBypassFilterHelpText": "Utilitzeu ',' com a separador i '*.' com a comodí per als subdominis", @@ -179,10 +174,10 @@ "Restart": "Reinicia", "RestartLidarr": "Reinicia {appName}", "RestartNow": "Reinicia ara", - "RetentionHelpText": "Només Usenet: establiu-lo a zero per establir una retenció il·limitada", + "RetentionHelpText": "Només Usenet: establiu-lo a zero per a establir una retenció il·limitada", "RssSyncIntervalHelpText": "Interval en minuts. Establiu a zero per desactivar (això aturarà tota captura automàtica de llançaments)", "Scheduled": "Programat", - "Season": "temporada", + "Season": "Temporada", "Security": "Seguretat", "SendAnonymousUsageData": "Envia dades d'ús anònimes", "SetPermissions": "Estableix permisos", @@ -219,21 +214,21 @@ "UnableToLoadTheCalendar": "No es pot carregar el calendari", "Clear": "Esborra", "ClientPriority": "Prioritat del client", - "CloneIndexer": "Clona indexadors", + "CloneIndexer": "Clona l'indexador", "CloneProfile": "Clona el perfil", "Columns": "Columnes", "AgeWhenGrabbed": "Edat (quan es captura)", - "AlternateTitles": "Títol alternatiu", + "AlternateTitles": "Títols alternatius", "AlternateTitleslength1Title": "Títol", "AlternateTitleslength1Titles": "Títols", "Analytics": "Anàlisi", - "AnalyticsEnabledHelpText": "Envieu informació anònima d'ús i errors als servidors de {appName}. Això inclou informació sobre el vostre navegador, quines pàgines {appName} WebUI feu servir, informes d'errors, així com el sistema operatiu i la versió del temps d'execució. Utilitzarem aquesta informació per prioritzar les funcions i les correccions d'errors.", + "AnalyticsEnabledHelpText": "Envieu informació anònima d'ús i errors als servidors de {appName}. Això inclou informació sobre el vostre navegador, quines pàgines {appName} WebUI feu servir, informes d'errors, així com el sistema operatiu i la versió de l'entorn d'execució. Utilitzarem aquesta informació per a prioritzar les funcions i les correccions d'errors.", "AnalyticsEnabledHelpTextWarning": "Cal reiniciar perquè tingui efecte", "APIKey": "Clau API", "ApiKeyHelpTextWarning": "Cal reiniciar perquè tingui efecte", "AppDataDirectory": "Directori AppData", "Authentication": "Autenticació", - "AuthenticationMethodHelpText": "Requereix nom d'usuari i contrasenya per accedir al radar", + "AuthenticationMethodHelpText": "Es requereix nom d'usuari i contrasenya per a accedir a {appName}", "Automatic": "Automàtic", "AutoRedownloadFailedHelpText": "Cerca i intenta baixar automàticament una versió diferent", "BackupNow": "Fes ara la còpia de seguretat", @@ -258,29 +253,29 @@ "CutoffHelpText": "Un cop s'assoleixi aquesta qualitat, {appName} ja no baixarà pel·lícules", "CutoffUnmet": "Tall no assolit", "Dates": "Dates", - "DBMigration": "Migració de BD", + "DatabaseMigration": "Migració de BD", "DelayingDownloadUntilInterp": "S'està retardant la baixada fins a les {0} a les {1}", "DelayProfile": "Perfil de retard", "DelayProfiles": "Perfils de retard", "Delete": "Suprimeix", "DeleteBackup": "Suprimeix la còpia de seguretat", - "DeleteBackupMessageText": "Esteu segur que voleu suprimir la còpia de seguretat '{0}'?", + "DeleteBackupMessageText": "Esteu segur que voleu suprimir la còpia de seguretat '{name}'?", "DeleteDelayProfile": "Suprimeix el perfil de retard", "DeleteDelayProfileMessageText": "Esteu segur que voleu suprimir aquest perfil de retard?", "DeleteDownloadClient": "Suprimeix el client de descàrrega", - "DeleteDownloadClientMessageText": "Esteu segur que voleu suprimir el client de baixada '{0}'?", + "DeleteDownloadClientMessageText": "Esteu segur que voleu suprimir el client de baixada '{name}'?", "DeleteEmptyFolders": "Suprimeix les carpetes buides", "DeleteImportListExclusionMessageText": "Esteu segur que voleu suprimir aquesta exclusió de la llista d'importació?", - "DeleteIndexerMessageText": "Esteu segur que voleu suprimir l'indexador '{0}'?", + "DeleteIndexerMessageText": "Esteu segur que voleu suprimir l'indexador '{name}'?", "DeleteMetadataProfileMessageText": "Esteu segur que voleu suprimir el perfil de qualitat {0}", "DeleteNotification": "Suprimeix la notificació", - "DeleteNotificationMessageText": "Esteu segur que voleu suprimir la notificació '{0}'?", + "DeleteNotificationMessageText": "Esteu segur que voleu suprimir la notificació '{name}'?", "DeleteQualityProfile": "Suprimeix el perfil de qualitat", "DeleteRootFolderMessageText": "Esteu segur que voleu suprimir l'indexador '{0}'?", "DeleteSelectedTrackFiles": "Suprimeix els fitxers de pel·lícules seleccionats", "DeleteSelectedTrackFilesMessageText": "Esteu segur que voleu suprimir els fitxers de pel·lícules seleccionats?", "DeleteTag": "Suprimeix l'etiqueta", - "DeleteTagMessageText": "Esteu segur que voleu suprimir l'etiqueta '{0}'?", + "DeleteTagMessageText": "Esteu segur que voleu suprimir l'etiqueta '{label}'?", "DetailedProgressBar": "Barra de progrés detallada", "DetailedProgressBarHelpText": "Mostra el text a la barra de progrés", "DiskSpace": "Espai en disc", @@ -292,14 +287,14 @@ "Downloading": "S'està baixant", "DownloadPropersAndRepacksHelpTexts1": "Si s'ha d'actualitzar automàticament o no a Propers/Repacks", "DownloadWarningCheckDownloadClientForMoreDetails": "Avís de descàrrega: consulteu el client de descàrrega per obtenir més detalls", - "Duration": "durada", + "Duration": "Durada", "Edit": "Edita", "Enable": "Activa", - "EnableAutomaticAdd": "Activa l'Afegit automàtic", + "EnableAutomaticAdd": "Activa la captura automàtica", "EnableAutomaticSearch": "Activa la cerca automàtica", - "EnableColorImpairedModeHelpText": "Estil alternat per permetre als usuaris amb problemes de color distingir millor la informació codificada per colors", + "EnableColorImpairedModeHelpText": "Estil alterat per a permetre als usuaris amb problemes de color distingir millor la informació codificada per colors", "EnableSslHelpText": " Cal reiniciar l'execució com a administrador perquè tingui efecte", - "Ended": "S'ha acabat", + "Ended": "Acabat", "ErrorLoadingPreviews": "S'ha produït un error en carregar les previsualitzacions", "Files": "Fitxers", "Folders": "Carpetes", @@ -312,7 +307,7 @@ "History": "Història", "Host": "Amfitrió", "HostHelpText": "El mateix amfitrió que heu especificat per al client de baixada remota", - "ICalHttpUrlHelpText": "Copieu aquest URL als vostres clients o feu clic per subscriure's si el vostre navegador és compatible amb webcal", + "ICalHttpUrlHelpText": "Copieu aquest URL als vostres clients o feu clic per a subscriure's si el vostre navegador és compatible amb webcal", "IgnoredAddresses": "Adreces ignorades", "IgnoredHelpText": "La publicació es rebutjarà si conté un o més dels termes (no distingeix entre majúscules i minúscules)", "IgnoredPlaceHolder": "Afegeix una nova restricció", @@ -320,8 +315,7 @@ "ImportExtraFiles": "Importa fitxers addicionals", "ImportExtraFilesHelpText": "Importeu fitxers addicionals coincidents (subtítols, nfo, etc.) després d'importar un fitxer de pel·lícula", "ImportFailedInterp": "ImportFailedInterp", - "Importing": "s'està important", - "IncludeHealthWarningsHelpText": "Inclou advertències de salut", + "Importing": "S'està important", "IncludeUnmonitored": "Inclou no monitorat", "Indexer": "Indexador", "IndexerPriority": "Prioritat de l'indexador", @@ -339,24 +333,21 @@ "Medium": "Suport", "Message": "Missatge", "MIA": "MIA", - "MinimumAgeHelpText": "Només Usenet: edat mínima en minuts dels NZB abans de ser capturats. Utilitzeu-ho per donar temps a les noves versions per propagar-se al vostre proveïdor d'usenet.", + "MinimumAgeHelpText": "Només Usenet: edat mínima en minuts dels NZB abans de ser capturats. Utilitzeu-ho per a donar temps a les noves versions per propagar-se al vostre proveïdor d'usenet.", "MinimumFreeSpace": "Espai lliure mínim", "MinimumFreeSpaceWhenImportingHelpText": "Eviteu la importació si quedara menys d'aquesta quantitat d'espai disponible en disc", - "NoLimitForAnyRuntime": "Sense límit de temps d'execució", "NoLogFiles": "No hi ha fitxers de registre", - "NoMinimumForAnyRuntime": "No hi ha mínim per a cap temps d'execució", "None": "Cap", "OnHealthIssue": "Al detectar incidència", "OnRename": "Al reanomenar", "OnUpgrade": "A l'actualitzar", - "OnUpgradeHelpText": "A l'actualitzar", "OpenBrowserOnStart": "Obriu el navegador a l'inici", "Options": "Opcions", "Original": "Original", "PackageVersion": "Versió del paquet", "PageSize": "Mida de la pàgina", "PageSizeHelpText": "Nombre d'elements per mostrar a cada pàgina", - "Path": "Camí", + "Path": "Ruta", "Profiles": "Perfils", "Proper": "Proper", "PropersAndRepacks": "Propietats i Repacks", @@ -391,14 +382,14 @@ "SslCertPathHelpTextWarning": "Cal reiniciar perquè tingui efecte", "SSLPort": "Port SSL", "ThisWillApplyToAllIndexersPleaseFollowTheRulesSetForthByThem": "Això s'aplicarà a tots els indexadors, si us plau, seguiu les regles establertes per ells", - "UnableToAddANewRemotePathMappingPleaseTryAgain": "No es pot afegir una nova assignació de camins remots, torneu-ho a provar.", + "UnableToAddANewRemotePathMappingPleaseTryAgain": "No es pot afegir una nova assignació de ruta remota, torneu-ho a provar.", "UnableToLoadBlocklist": "No es pot carregar la llista de bloqueig", "UnableToLoadMediaManagementSettings": "No es pot carregar la configuració de gestió de mitjans", "UnableToLoadMetadata": "No es poden carregar les metadades", "UnableToLoadMetadataProfiles": "No es poden carregar els perfils de qualitat", "UnableToLoadNamingSettings": "No es pot carregar la configuració de nomenclatura", "UnableToLoadNotifications": "No es poden carregar les notificacions", - "UnableToLoadQualities": "No es poden carregar qualitats", + "UnableToLoadQualities": "No es poden carregar perfils de qualitat", "UnableToLoadRemotePathMappings": "No s'han pogut carregar els mapes de camins remots", "UnableToLoadRootFolders": "No es poden carregar les carpetes arrel", "UnableToLoadUISettings": "No es pot carregar la configuració de la IU", @@ -425,12 +416,12 @@ "UILanguageHelpText": "Idioma que utilitzarà {appName} per a la interfície d'usuari", "UILanguageHelpTextWarning": "Es requereix una recàrrega del navegador", "UnableToAddANewDownloadClientPleaseTryAgain": "No es pot afegir un nou client de descàrrega, torneu-ho a provar.", - "UnableToAddANewImportListExclusionPleaseTryAgain": "No es pot afegir una nova exclusió de llista, torneu-ho a provar.", + "UnableToAddANewImportListExclusionPleaseTryAgain": "No es pot afegir una nova llista d'exclusió, torneu-ho a provar.", "Uptime": "Temps de funcionament", "20MinutesTwenty": "60 minuts: {0}", "45MinutesFourtyFive": "60 minuts: {0}", "60MinutesSixty": "60 minuts: {0}", - "ClickToChangeQuality": "Feu clic per canviar la qualitat", + "ClickToChangeQuality": "Feu clic per a canviar la qualitat", "CompletedDownloadHandling": "Gestió de descàrregues completades", "Connections": "Connexions", "ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "Per obtenir més informació sobre les llistes d'importació individuals, feu clic als botons d'informació.", @@ -445,15 +436,14 @@ "MarkAsFailedMessageText": "Esteu segur que voleu marcar '{0}' com a fallat?", "MaximumLimits": "Límits màxims", "AddingTag": "Afegint etiqueta", - "AddListExclusion": "Afegeix l'exclusió de la llista", + "AddListExclusion": "Afegeix una llista d'exclusió", "AlbumIsDownloadingInterp": "La pel·lícula s'està baixant - {0}% {1}", - "AlreadyInYourLibrary": "Ja a la teva biblioteca", + "AlreadyInYourLibrary": "Ja a la vostra biblioteca", "Component": "Component", "Folder": "Carpeta", "HasPendingChangesSaveChanges": "Desa els canvis", "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} admet molts clients de baixada de torrent i usenet populars.", "OnGrab": "Al capturar", - "OnGrabHelpText": "Al capturar", "Permissions": "Permisos", "Port": "Port^", "PortNumber": "Número de port", @@ -471,7 +461,7 @@ "Activity": "Activitat", "AddDelayProfile": "Afegeix un perfil de retard", "Added": "Afegit", - "All": "Tots", + "All": "Tot", "Progress": "Progrés", "SizeLimit": "Límit de mida", "Backup": "Còpia de seguretat", @@ -482,7 +472,7 @@ "Seeders": "Llavors", "AddIndexer": "Afegeix un indexador", "AddMetadataProfile": "perfil de metadades", - "AddNew": "Afegir nou", + "AddNew": "Afegeix nou", "AddQualityProfile": "Afegeix un perfil de qualitat", "AllFiles": "Tots els fitxers", "Always": "Sempre", @@ -498,7 +488,7 @@ "DefaultDelayProfileHelpText": "Aquest és el perfil predeterminat. S'aplica a totes les pel·lícules que no tenen un perfil explícit.", "Deleted": "S'ha suprimit", "Details": "Detalls", - "Error": "error", + "Error": "Error", "ErrorRestoringBackup": "S'ha produït un error en restaurar la còpia de seguretat", "Events": "Esdeveniments", "EventType": "Tipus d'esdeveniment", @@ -510,7 +500,7 @@ "HideAdvanced": "Amaga avançat", "Ignored": "Ignorat", "Import": "Importa", - "IndexerDownloadClientHelpText": "Especifiqueu quin client de baixada s'utilitza per capturar des d'aquest indexador", + "IndexerDownloadClientHelpText": "Especifiqueu quin client de baixada s'utilitza per a capturar des d'aquest indexador", "InstanceNameHelpText": "Nom de la instància a la pestanya i per al nom de l'aplicació Syslog", "LastUsed": "Darrer ús", "LastWriteTime": "La darrera hora d'escriptura", @@ -530,7 +520,6 @@ "PreferAndUpgrade": "Marca preferit i actualitza", "PreferredProtocol": "Protocol preferit", "Presets": "Predefinits", - "PriorityHelpText": "Prioritat de l'indexador d'1 (la més alta) a 50 (la més baixa). Per defecte: 25. S'utilitza quan s'agafa llançaments com a desempat per a versions iguals, {appName} encara utilitzarà tots els indexadors habilitats per a la sincronització i la cerca RSS", "QualityLimitsHelpText": "Els límits s'ajusten automàticament per al temps d'execució de la pel·lícula.", "Queued": "En cua", "Rating": "Valoració", @@ -552,9 +541,9 @@ "UpgradesAllowed": "Actualitzacions permeses", "Wanted": "Demanat", "Warn": "Avís", - "WouldYouLikeToRestoreBackup": "Voleu restaurar la còpia de seguretat {0} ?", - "Add": "Afegiu", - "AddRemotePathMapping": "Afegeix un mapa de camins remots", + "WouldYouLikeToRestoreBackup": "Voleu restaurar la còpia de seguretat '{name}'?", + "Add": "Afegeix", + "AddRemotePathMapping": "Afegeix una asignació de ruta remota", "AddRootFolder": "Afegeix una carpeta arrel", "AfterManualRefresh": "Després de l'actualització manual", "Age": "Edat", @@ -584,7 +573,7 @@ "UnmonitoredOnly": "Només monitoritzat", "Started": "Començat", "EditMetadataProfile": "perfil de metadades", - "AddConnection": "Edita la col·lecció", + "AddConnection": "Afegeix una connexió", "AddImportListExclusion": "Suprimeix l'exclusió de la llista d'importació", "ImportListExclusions": "Suprimeix l'exclusió de la llista d'importació", "Database": "Base de dades", @@ -595,7 +584,7 @@ "BypassIfHighestQuality": "Bypass si és de màxima qualitat", "CustomFormatScore": "Puntuació de format personalitzat", "MinimumCustomFormatScore": "Puntuació mínima de format personalitzat", - "ClickToChangeReleaseGroup": "Feu clic per canviar el grup de llançaments", + "ClickToChangeReleaseGroup": "Feu clic per a canviar el grup de llançaments", "SelectReleaseGroup": "Seleccioneu grup de llançament", "ArtistAlbumClickToChangeTrack": "Feu clic per canviar la pel·lícula", "QualitiesHelpText": "Les qualitats més altes a la llista són més preferides encara que no es comproven. Les qualitats dins d'un mateix grup són iguals. Només es volen qualitats verificades", @@ -628,7 +617,7 @@ "UnableToLoadCustomFormats": "No es poden carregar formats personalitzats", "UnableToLoadInteractiveSearch": "No es poden carregar els resultats d'aquesta cerca de pel·lícules. Torna-ho a provar més tard", "TheArtistFolderStrongpathstrongAndAllOfItsContentWillBeDeleted": "La carpeta de pel·lícules '{0}' i tot el seu contingut es suprimiran.", - "CustomFormat": "Formats personalitzats", + "CustomFormat": "Format personalitzat", "CustomFormatRequiredHelpText": "La condició {0} ha de coincidir perquè s'apliqui el format personalitzat. En cas contrari, n'hi ha prou amb una única coincidència de {1}.", "CustomFormatSettings": "Configuració de formats personalitzats", "CustomFormats": "Formats personalitzats", @@ -636,7 +625,7 @@ "MaintenanceRelease": "Versió de manteniment: correcció d'errors i altres millores. Consulteu l'historial de publicacions de Github per a més detalls", "DownloadClientStatusCheckAllClientMessage": "Tots els clients de descàrrega no estan disponibles a causa d'errors", "DownloadClientStatusCheckSingleClientMessage": "Baixa els clients no disponibles a causa d'errors: {0}", - "HiddenClickToShow": "Amagat, feu clic per mostrar", + "HiddenClickToShow": "Amagat, feu clic per a mostrar", "ImportListStatusCheckAllClientMessage": "Totes les llistes no estan disponibles a causa d'errors", "IndexerJackettAll": "Indexadors que utilitzen el punt final \"tot\" no compatible amb Jackett: {0}", "IndexerLongTermStatusCheckAllClientMessage": "Tots els indexadors no estan disponibles a causa d'errors durant més de 6 hores", @@ -648,12 +637,12 @@ "ReplaceWithDash": "Substitueix per guió", "ReplaceWithSpaceDash": "Substitueix per espai i guió", "ReplaceWithSpaceDashSpace": "Substitueix per espai, guió i espai", - "ShownClickToHide": "Es mostra, feu clic per amagar", - "AppDataLocationHealthCheckMessage": "No es podrà actualitzar per evitar que s'eliminin AppData a l'actualització", + "ShownClickToHide": "Es mostra, feu clic per a amagar", + "AppDataLocationHealthCheckMessage": "No es podrà actualitzar per a evitar que s'eliminin AppData a l'actualització", "ColonReplacement": "Substitució de dos punts", "Disabled": "Desactivat", "DownloadClientCheckDownloadingToRoot": "El client de baixada {0} col·loca les baixades a la carpeta arrel {1}. No s'hauria de baixar a una carpeta arrel.", - "DownloadClientCheckNoneAvailableMessage": "No hi ha cap client de descàrrega disponible", + "DownloadClientCheckNoneAvailableMessage": "No hi ha cap client de baixada disponible", "DownloadClientCheckUnableToCommunicateMessage": "No es pot comunicar amb {0}.", "ProxyCheckBadRequestMessage": "No s'ha pogut provar el servidor intermediari. Codi d'estat: {0}", "ProxyCheckResolveIpMessage": "No s'ha pogut resoldre l'adreça IP de l'amfitrió intermediari configurat {0}", @@ -664,7 +653,7 @@ "RemotePathMappingCheckFilesLocalWrongOSPath": "El client de baixada local {0} ha informat de fitxers a {1}, però el camí {2} no és vàlid. Reviseu la configuració del vostre client de baixada.", "RemotePathMappingCheckFilesWrongOSPath": "El client de baixada remota {0} ha informat de fitxers a {1}, però el camí {2} no és vàlid. Reviseu els mapes de camins remots i baixeu la configuració del client.", "RemotePathMappingCheckGenericPermissions": "El client de baixada {0} col·loca les baixades a {1} però {appName} no pot veure aquest directori. És possible que hàgiu d'ajustar els permisos de la carpeta.", - "RemotePathMappingCheckImportFailed": "{appName} no ha pogut importar una pel·lícula. Comproveu els vostres registres per obtenir més informació.", + "RemotePathMappingCheckImportFailed": "{appName} no ha pogut importar una pel·lícula. Comproveu els vostres registres per a obtenir més informació.", "RemotePathMappingCheckLocalWrongOSPath": "El client de baixada local {0} col·loca les baixades a {1}, però el camí {2} no és vàlid. Reviseu la configuració del vostre client de baixada.", "RemotePathMappingCheckRemoteDownloadClient": "El client de baixada remota {0} ha informat de fitxers a {1}, però sembla que aquest directori no existeix. És probable que falti el mapa de camins remots.", "RootFolderCheckMultipleMessage": "Falten diverses carpetes arrel: {0}", @@ -688,14 +677,14 @@ "UpdateCheckStartupTranslocationMessage": "No es pot instal·lar l'actualització perquè la carpeta d'inici \"{0}\" es troba en una carpeta de translocació d'aplicacions.", "UpdateCheckUINotWritableMessage": "No es pot instal·lar l'actualització perquè l'usuari '{1}' no pot escriure la carpeta de la IU '{0}'.", "DeleteRemotePathMapping": "Editeu el mapa de camins remots", - "DeleteRemotePathMappingMessageText": "Esteu segur que voleu suprimir aquesta assignació remota de camins?", - "BlocklistReleases": "Publicacions de la llista de bloqueig", + "DeleteRemotePathMappingMessageText": "Esteu segur que voleu suprimir aquesta assignació de camins remots?", + "BlocklistReleases": "Llista de llançaments bloquejats", "BlocklistReleaseHelpText": "Impedeix que {appName} torni a capturar aquesta versió automàticament", "FailedToLoadQueue": "No s'ha pogut carregar la cua", "DeleteConditionMessageText": "Esteu segur que voleu suprimir la notificació '{0}'?", "DeleteSelectedDownloadClients": "Suprimeix el client de descàrrega", - "DeleteSelectedIndexers": "Suprimeix l'indexador", - "DeleteSelectedIndexersMessageText": "Esteu segur que voleu suprimir l'indexador '{0}'?", + "DeleteSelectedIndexers": "Suprimeix l'indexador(s)", + "DeleteSelectedIndexersMessageText": "Esteu segur que voleu suprimir {count} indexador(s) seleccionat(s)?", "DownloadClientSortingCheckMessage": "El client de baixada {0} té l'ordenació {1} activada per a la categoria de {appName}. Hauríeu de desactivar l'ordenació al vostre client de descàrrega per evitar problemes d'importació.", "ExistingTag": "Etiqueta existent", "ApplyTagsHelpTextRemove": "Eliminar: elimina les etiquetes introduïdes", @@ -704,7 +693,7 @@ "ResetTitlesHelpText": "Restableix els títols de definició i els valors", "SetTags": "Estableix etiquetes", "ApplyTagsHelpTextAdd": "Afegeix: afegeix les etiquetes a la llista d'etiquetes existent", - "ApplyTagsHelpTextReplace": "Substituïu: substituïu les etiquetes per les etiquetes introduïdes (no introduïu cap etiqueta per esborrar totes les etiquetes)", + "ApplyTagsHelpTextReplace": "Substitució: substituïu les etiquetes per les etiquetes introduïdes (no introduïu cap etiqueta per a esborrar totes les etiquetes)", "NoEventsFound": "No s'han trobat esdeveniments", "Required": "Obligatori", "DownloadClientTagHelpText": "Utilitzeu aquest indexador només per a pel·lícules amb almenys una etiqueta coincident. Deixeu-ho en blanc per utilitzar-ho amb totes les pel·lícules.", @@ -713,26 +702,25 @@ "QueueIsEmpty": "La cua està buida", "RemoveSelectedItem": "Elimina l'element seleccionat", "RemoveSelectedItems": "Elimina els elements seleccionats", - "RemoveFromDownloadClientHelpTextWarning": "L'eliminació esborrarà la baixada i els fitxers del client de baixada.", - "RemoveSelectedItemQueueMessageText": "Esteu segur que voleu eliminar {0} de la cua?", + "RemoveSelectedItemQueueMessageText": "Esteu segur que voleu eliminar 1 element de la cua?", "RemoveSelectedItemsQueueMessageText": "Esteu segur que voleu eliminar {0} de la cua?", - "DeleteSelectedDownloadClientsMessageText": "Esteu segur que voleu suprimir l'indexador '{0}'?", - "DeleteSelectedImportListsMessageText": "Esteu segur que voleu suprimir l'indexador '{0}'?", + "DeleteSelectedDownloadClientsMessageText": "Esteu segur que voleu suprimir {count} client(s) de baixada seleccionat(s)?", + "DeleteSelectedImportListsMessageText": "Esteu segur que voleu suprimir {count} llista(es) d'importació seleccionada(es)?", "ApplyTagsHelpTextHowToApplyArtists": "Com aplicar etiquetes a les pel·lícules seleccionades", - "ApplyTagsHelpTextHowToApplyImportLists": "Com aplicar etiquetes a les pel·lícules seleccionades", - "ApplyTagsHelpTextHowToApplyIndexers": "Com aplicar etiquetes a les pel·lícules seleccionades", + "ApplyTagsHelpTextHowToApplyImportLists": "Com aplicar etiquetes a les llistes d'importació seleccionades", + "ApplyTagsHelpTextHowToApplyIndexers": "Com aplicar etiquetes als indexadors seleccionats", "SomeResultsAreHiddenByTheAppliedFilter": "Alguns resultats estan ocults pel filtre aplicat", "SuggestTranslationChange": "Suggereix un canvi de traducció", "UpdateSelected": "Actualització seleccionada", - "ApplyTagsHelpTextHowToApplyDownloadClients": "Com aplicar etiquetes a les pel·lícules seleccionades", + "ApplyTagsHelpTextHowToApplyDownloadClients": "Com aplicar etiquetes als clients de baixada seleccionats", "AllResultsAreHiddenByTheAppliedFilter": "Tots els resultats estan ocults pel filtre aplicat", "NoResultsFound": "Sense resultats", "ConnectionLost": "Connexió perduda", - "ConnectionLostReconnect": "Radarr intentarà connectar-se automàticament, o podeu fer clic a recarregar.", + "ConnectionLostReconnect": "{appName} intentarà connectar-se automàticament, o podeu fer clic a recarregar.", "RecentChanges": "Canvis recents", "WhatsNew": "Que hi ha de nou?", - "NotificationStatusAllClientHealthCheckMessage": "Totes les llistes no estan disponibles a causa d'errors", - "ConnectionLostToBackend": "Radarr ha perdut la connexió amb el backend i s'haurà de tornar a carregar per restaurar la funcionalitat.", + "NotificationStatusAllClientHealthCheckMessage": "Totes les notificacions no estan disponibles a causa d'errors", + "ConnectionLostToBackend": "{appName} ha perdut la connexió amb el backend i s'haurà de tornar a carregar per a restaurar la funcionalitat.", "NotificationStatusSingleClientHealthCheckMessage": "Llistes no disponibles a causa d'errors: {0}", "ImportListRootFolderMissingRootHealthCheckMessage": "Falta la carpeta arrel per a les llistes d'importació: {0}", "ImportListRootFolderMultipleMissingRootsHealthCheckMessage": "Falten diverses carpetes arrel per a les llistes d'importació: {0}", @@ -754,19 +742,124 @@ "Posters": "Pòsters", "AuthBasic": "Basic (finestra emergent del navegador)", "AuthForm": "Formularis (pàgina d'inici de sessió)", - "AddAutoTagError": "No es pot afegir una llista nova, torneu-ho a provar.", + "AddAutoTagError": "No es pot afegir una etiqueta automàtica nova, torneu-ho a provar.", "AddConditionError": "No es pot afegir una condició nova, torneu-ho a provar.", "AlbumsLoadError": "No es poden carregar còpies de seguretat", "DeleteSpecificationHelpText": "Esteu segur que voleu suprimir la llista '{0}'?", - "AutoTaggingNegateHelpText": "Si està marcat, el format personalitzat no s'aplicarà si la condició {0} coincideix.", - "ConditionUsingRegularExpressions": "Aquesta condició coincideix amb expressions regulars. Tingueu en compte que els caràcters {0} tenen significats especials i cal escapar amb un {1}", + "AutoTaggingNegateHelpText": "Si està marcat, el format personalitzat no s'aplicarà si la condició {implementationName} coincideix.", + "ConditionUsingRegularExpressions": "Aquesta condició coincideix amb expressions regulars. Tingueu en compte que els caràcters `\\^$.|?*+()[{` tenen significats especials i cal escapar amb un `\\`", "Connection": "Connexió", - "DeleteAutoTagHelpText": "Esteu segur que voleu suprimir l'etiqueta '{0}'?", + "DeleteAutoTagHelpText": "Esteu segur que voleu suprimir l'etiqueta '{name}'?", "Negate": "Negació", "OrganizeSelectedArtists": "Organitza les pel·lícules seleccionades", "Small": "Petita", "AddListExclusionHelpText": "Eviteu que la pel·lícula s'afegeixi a {appName} per llistes", "DeleteArtistFoldersHelpText": "Suprimeix la carpeta de pel·lícules i el seu contingut", "AddNewArtistSearchForMissingAlbums": "Comenceu a cercar per pel·lícula absent", - "AddImportListExclusionArtistHelpText": "Eviteu que la pel·lícula s'afegeixi a {appName} per llistes" + "AddImportListExclusionArtistHelpText": "Eviteu que la pel·lícula s'afegeixi a {appName} per llistes", + "AppUpdated": "{appName} Actualitzada", + "AppUpdatedVersion": "{appName} s'ha actualitzat a la versió `{version}`, per tal d'obtenir els darrers canvis, haureu de tornar a carregar {appName}", + "DownloadClientQbittorrentSettingsContentLayout": "Disseny de contingut", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Si s'utilitza el disseny de contingut de qBittorrent s'utilitza el disseny original del torrent o es crea una subcarpeta (qBittorrent 4.3.2+)", + "EditAutoTag": "Edita etiquetatge automàtic", + "EditConditionImplementation": "Edita la condició - {implementationName}", + "EditSelectedDownloadClients": "Editeu els clients de descàrrega seleccionats", + "EditSelectedImportLists": "Edita les llistes d'importació seleccionades", + "EditSelectedIndexers": "Edita els indexadors seleccionats", + "HealthMessagesInfoBox": "Podeu trobar més informació sobre la causa d'aquests missatges de comprovació de salut fent clic a l'enllaç wiki (icona del llibre) al final de la fila o consultant els vostres [registres]({link}). Si teniu problemes per a interpretar aquests missatges, podeu posar-vos en contacte amb el nostre suport als enllaços següents.", + "OnHealthRestored": "Al resoldre les incidències", + "EditDownloadClientImplementation": "Edita el client de baixada - {implementationName}", + "ManageLists": "Gestiona les llistes", + "NoImportListsFound": "No s'han trobat llistes d'importació", + "NoHistoryBlocklist": "Sense historial de llistes de bloqueig", + "AutomaticAdd": "Afegeix automàticament", + "ApplyChanges": "Aplica els canvis", + "AddReleaseProfile": "Afegeix un perfil de llançament", + "AuthenticationRequiredWarning": "Per a evitar l'accés remot sense autenticació, ara {appName} requereix que l'autenticació estigui activada. Opcionalment, podeu desactivar l'autenticació des d'adreces locals.", + "AutoAdd": "Afegeix automàticament", + "DeleteRootFolder": "Suprimeix la carpeta arrel", + "Implementation": "Implementació", + "ListRefreshInterval": "Interval d'actualització de la llista", + "ManageImportLists": "Gestiona les llistes d'importació", + "NoDownloadClientsFound": "No s'han trobat clients de baixada", + "CloneCondition": "Clona la condició", + "ListWillRefreshEveryInterp": "La llista s'actualitzarà cada {0}", + "AutomaticUpdatesDisabledDocker": "Les actualitzacions automàtiques no s'admeten directament quan s'utilitza el mecanisme d'actualització de Docker. Haureu d'actualitzar la imatge del contenidor fora de {appName} o utilitzar un script", + "EnableProfile": "Activa el perfil", + "ManageDownloadClients": "Gestiona els clients de descàrrega", + "ManageClients": "Gestiona els clients", + "NoIndexersFound": "No s'han trobat indexadors", + "AddConnectionImplementation": "Afegeix una connexió - {implementationName}", + "AddConditionImplementation": "Afegeix una condició - {implementationName}", + "AddDownloadClientImplementation": "Afegeix un client de descàrrega - {implementationName}", + "AddIndexerImplementation": "Afegeix un indexador - {implementationName}", + "AddImportListImplementation": "Afegeix una llista d'importació - {implementationName}", + "EditIndexerImplementation": "Edita l'indexador - {implementationName}", + "EditImportListImplementation": "Afegeix una llista d'importació - {implementationName}", + "IndexerDownloadClientHealthCheckMessage": "Indexadors amb clients de baixada no vàlids: {0}.", + "ManageIndexers": "Gestiona els indexadors", + "DeleteImportList": "Suprimeix la llista d'importació", + "Absolute": "Absolut", + "InfoUrl": "URL d'informació", + "DeleteAutoTag": "Suprimeix l'etiquetatge automàtic", + "InvalidUILanguage": "La vostra IU està configurada en un idioma no vàlid, corregiu-lo i deseu la configuració", + "AuthenticationRequiredPasswordHelpTextWarning": "Introduïu una contrasenya nova", + "AuthenticationRequiredUsernameHelpTextWarning": "Introduïu un nom d'usuari nou", + "AuthenticationRequired": "Autenticació necessària", + "AuthenticationMethod": "Mètode d'autenticació", + "AuthenticationMethodHelpTextWarning": "Seleccioneu un mètode d'autenticació vàlid", + "AuthenticationRequiredHelpText": "Canvia per a quines sol·licituds cal autenticar. No canvieu tret que entengueu els riscos.", + "AddCondition": "Afegeix una condició", + "AddAutoTag": "Afegeix una etiqueta automàtica", + "AddImportList": "Afegeix una llista d'importació", + "AutoTagging": "Etiquetatge automàtic", + "DeleteCondition": "Suprimeix la condició", + "DeleteSelectedImportLists": "Suprimeix la(es) llista(es) d'importació", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirmeu la nova contrasenya", + "ClearBlocklist": "Esborra la llista de bloqueig", + "ClearBlocklistMessageText": "Esteu segur que voleu esborrar tots els elements de la llista de bloqueig?", + "CloneAutoTag": "Clona l'etiquetatge automàtic", + "AutoTaggingLoadError": "No es pot carregar l'etiquetatge automàtic", + "AutoTaggingRequiredHelpText": "Aquesta condició {implementationName} ha de coincidir perquè s'apliqui la regla d'etiquetatge automàtic. En cas contrari, una única coincidència {implementationName} és suficient.", + "ExpandAlbumByDefaultHelpText": "àlbum", + "ImportList": "llista d'importació", + "Loading": "Carregant", + "NoLimitForAnyDuration": "Sense límit de temps d'execució", + "NoMinimumForAnyDuration": "No hi ha mínim per a cap temps d'execució", + "PreferredSize": "Mida preferida", + "Unlimited": "Il·limitat", + "Artist": "artista", + "BypassIfAboveCustomFormatScore": "Ometre si està per sobre de la puntuació de format personalitzada", + "DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "El client de baixada {downloadClientName} està configurat per eliminar les baixades completades. Això pot provocar que les baixades s'eliminin del vostre client abans que {1} pugui importar-les.", + "EditConnectionImplementation": "Afegeix una connexió - {implementationName}", + "Episode": "Episodi", + "AddImportListExclusionAlbumHelpText": "Eviteu que la pel·lícula s'afegeixi a {appName} per llistes", + "ImportLists": "llista d'importació", + "ApiKeyValidationHealthCheckMessage": "Actualitzeu la vostra clau de l'API perquè tingui almenys {length} caràcters. Podeu fer-ho mitjançant la configuració o el fitxer de configuració", + "BypassIfAboveCustomFormatScoreHelpText": "Habiliteu l'omissió quan la versió tingui una puntuació superior a la puntuació mínima per al format personalitzat", + "Artists": "artista", + "CountDownloadClientsSelected": "{count} client(s) de baixada seleccionat(s)", + "EditReleaseProfile": "Afegeix un perfil de llançament", + "ReleaseProfiles": "Perfils de llançament", + "ExtraFileExtensionsHelpTextsExamples": "Exemples: '.sub, .nfo' o 'sub,nfo'", + "ExtraFileExtensionsHelpText": "Llista separada per comes de fitxers addicionals per importar (.nfo s'importarà com a .nfo-orig)", + "TBA": "Pendent el seu anunci", + "Album": "àlbum", + "CountArtistsSelected": "S'han seleccionat {count} llista(es) d'importació", + "MinimumCustomFormatScoreHelpText": "Puntuació mínima de format personalitzada necessaria per evitar el retard del protocol preferit", + "CatalogNumber": "número de catàleg", + "Albums": "àlbum", + "Discography": "discografia", + "ReleaseProfile": "perfil de llançament", + "Clone": "Clona", + "Continuing": "Continua", + "ChownGroup": "Canvia el grup propietari", + "AllExpandedCollapseAll": "Contreure-ho tot", + "DeleteArtistFolderCountConfirmation": "Esteu segur que voleu suprimir {count} llista(es) d'importació seleccionada(es)?", + "No": "No", + "Yes": "Si", + "Other": "Altres", + "External": "Extern", + "AutoRedownloadFailedFromInteractiveSearch": "Tornar a baixar baixades fallades des de la cerca interactiva", + "AutoRedownloadFailed": "Tornar a baixar les baixades fallades" } diff --git a/src/NzbDrone.Core/Localization/Core/cs.json b/src/NzbDrone.Core/Localization/Core/cs.json index 0f6f1c722..a9128e3fe 100644 --- a/src/NzbDrone.Core/Localization/Core/cs.json +++ b/src/NzbDrone.Core/Localization/Core/cs.json @@ -72,7 +72,6 @@ "ApiKeyHelpTextWarning": "Vyžaduje restart, aby se projevilo", "AppDataDirectory": "Adresář AppData", "ApplyTags": "Použít značky", - "IncludeHealthWarningsHelpText": "Zahrnout zdravotní varování", "IncludeUnknownArtistItemsHelpText": "Zobrazit položky bez filmu ve frontě. To by mohlo zahrnovat odstraněné filmy nebo cokoli jiného v kategorii {appName}", "IncludeUnmonitored": "Zahrnout Nesledováno", "Indexer": "Indexer", @@ -150,7 +149,7 @@ "BackupNow": "Ihned zálohovat", "BypassProxyForLocalAddresses": "Obcházení proxy serveru pro místní adresy", "ConnectSettings": "Nastavení připojení", - "DBMigration": "Migrace databáze", + "DatabaseMigration": "Migrace databáze", "Dates": "Termíny", "DelayingDownloadUntilInterp": "Zpoždění stahování do {0} o {1}", "Delete": "Vymazat", @@ -164,7 +163,6 @@ "IgnoredHelpText": "Vydání bude odmítnuto, pokud obsahuje jeden nebo více výrazů (nerozlišují se malá a velká písmena)", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} podporuje jakýkoli indexer, který používá standard Newznab, stejně jako další indexery uvedené níže.", "LidarrTags": "{appName} tagy", - "LoadingTrackFilesFailed": "Načítání filmových souborů se nezdařilo", "LocalPath": "Místní cesta", "MinimumFreeSpaceWhenImportingHelpText": "Zabraňte importu, pokud by bylo k dispozici méně než toto množství místa na disku", "Missing": "Chybějící", @@ -174,10 +172,8 @@ "NoBackupsAreAvailable": "Nejsou k dispozici žádné zálohy", "NoHistory": "Žádná historie", "NoLeaveIt": "Ne, nech to", - "NoLimitForAnyRuntime": "Žádné omezení za běhu", "NoLogFiles": "Žádné soubory protokolu", "NotificationTriggers": "Spouštěče oznámení", - "PriorityHelpText": "Priorita indexování od 1 (nejvyšší) do 50 (nejnižší). Výchozí: 25.", "Profiles": "Profily", "Proper": "Správně", "PropersAndRepacks": "Sponzoři a přebalení", @@ -370,7 +366,6 @@ "ErrorLoadingContents": "Chyba při načítání obsahu", "ErrorLoadingPreviews": "Chyba při načítání náhledů", "Exception": "Výjimka", - "ExtraFileExtensionsHelpTexts1": "Seznam extra souborů k importu oddělených čárkami (.nfo bude importován jako .nfo-orig)", "FileDateHelpText": "Změnit datum souboru při importu / opětovném skenování", "FileManagement": "Správa souborů", "FileNames": "Názvy souborů", @@ -414,13 +409,8 @@ "MoreInfo": "Více informací", "MustContain": "Musí obsahovat", "MustNotContain": "Nesmí obsahovat", - "NoMinimumForAnyRuntime": "Žádné minimum za běhu", "NoUpdatesAreAvailable": "Nejsou k dispozici žádné aktualizace", "None": "Žádný", - "OnGrabHelpText": "Chyť", - "OnHealthIssueHelpText": "K otázce zdraví", - "OnRenameHelpText": "Při přejmenování", - "OnUpgradeHelpText": "Při upgradu", "Proxy": "Proxy", "ProxyBypassFilterHelpText": "Použijte ',' jako oddělovač a '*.' jako zástupný znak pro subdomény", "ProxyPasswordHelpText": "Musíte pouze zadat uživatelské jméno a heslo, pokud je požadováno. Jinak je nechte prázdné.", @@ -655,7 +645,6 @@ "DeleteSelectedIndexers": "Odstranit indexer", "NoEventsFound": "Nebyly nalezeny žádné události", "Yes": "Ano", - "RemoveFromDownloadClientHelpTextWarning": "Odebráním odstraníte stažené soubory a soubory z klienta pro stahování.", "RemoveSelectedItemQueueMessageText": "Opravdu chcete odebrat {0} položku {1} z fronty?", "RemoveSelectedItemsQueueMessageText": "Opravdu chcete odebrat {0} položku {1} z fronty?", "DeleteSelectedDownloadClientsMessageText": "Opravdu chcete smazat {count} vybraných klientů pro stahování?", @@ -823,5 +812,13 @@ "AutoTagging": "Automatické označování", "ConditionUsingRegularExpressions": "Tato podmínka odpovídá regulárním výrazům. Všimněte si, že znaky `\\^$.|?*+()[{` mají speciální význam a je třeba je negovat pomocí `\\`", "Connection": "Spojení", - "ImportList": "Seznam k importu" + "ImportList": "Seznam k importu", + "NoLimitForAnyDuration": "Žádné omezení za běhu", + "NoMinimumForAnyDuration": "Žádné minimum za běhu", + "PreferredSize": "Preferovaná velikost", + "Unlimited": "Neomezený", + "ImportLists": "Seznam k importu", + "ExtraFileExtensionsHelpText": "Seznam extra souborů k importu oddělených čárkami (.nfo bude importován jako .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Příklady: „.sub, .nfo“ nebo „sub, nfo“", + "DeleteArtistFoldersHelpText": "Odstraňte složku filmu a její obsah" } diff --git a/src/NzbDrone.Core/Localization/Core/da.json b/src/NzbDrone.Core/Localization/Core/da.json index bf0fadb16..d857f7e56 100644 --- a/src/NzbDrone.Core/Localization/Core/da.json +++ b/src/NzbDrone.Core/Localization/Core/da.json @@ -13,7 +13,6 @@ "ImportExtraFilesHelpText": "Importer matchende ekstra filer (undertekster, nfo osv.) Efter import af en filmfil", "ImportFailedInterp": "Import mislykkedes: {0}", "Importing": "Importerer", - "IncludeHealthWarningsHelpText": "Inkluder sundhedsadvarsler", "IncludeUnknownArtistItemsHelpText": "Vis emner uden en film i køen. Dette kan omfatte fjernede film eller andet i {appName}s kategori", "IncludeUnmonitored": "Inkluder Uovervåget", "IndexerPriority": "Indekseringsprioritet", @@ -44,14 +43,9 @@ "Name": "Navn", "NoBackupsAreAvailable": "Ingen sikkerhedskopier er tilgængelige", "NoLogFiles": "Ingen logfiler", - "NoMinimumForAnyRuntime": "Intet minimum for enhver driftstid", "None": "Ingen", "NotificationTriggers": "Meddelelsesudløsere", "NoUpdatesAreAvailable": "Ingen opdateringer er tilgængelige", - "OnGrabHelpText": "On Grab", - "OnHealthIssueHelpText": "Om sundhedsspørgsmål", - "OnRenameHelpText": "Om omdøb", - "OnUpgradeHelpText": "Ved opgradering", "OpenBrowserOnStart": "Åbn browser ved start", "Options": "Muligheder", "Original": "Original", @@ -64,7 +58,6 @@ "Port": "Havn", "PortNumber": "Portnummer", "PreviewRename": "Vis eksempel Omdøb", - "PriorityHelpText": "Indekseringsprioritet fra 1 (højest) til 50 (lavest). Standard: 25.", "Profiles": "Profiler", "Proper": "Passende", "PropersAndRepacks": "Propers og Repacks", @@ -209,7 +202,6 @@ "New": "Ny", "NoHistory": "Ingen historie", "NoLeaveIt": "Nej, lad det være", - "NoLimitForAnyRuntime": "Ingen grænse for nogen runtime", "Quality": "Kvalitet", "QualityDefinitions": "Kvalitetsdefinitioner", "Queue": "Kø", @@ -290,7 +282,7 @@ "CutoffHelpText": "Når denne kvalitet er nået, downloader {appName} ikke længere film", "CutoffUnmet": "Afskåret ude", "Dates": "Datoer", - "DBMigration": "DB Migration", + "DatabaseMigration": "DB Migration", "DelayProfile": "Udskyd Profiler", "DelayProfiles": "Udskyd Profiler", "Delete": "Slet", @@ -396,7 +388,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} understøtter enhver downloadklient, der bruger Newznab-standarden, samt andre downloadklienter, der er anført nedenfor.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} understøtter enhver indekserer, der bruger Newznab-standarden såvel som andre indeksatorer, der er anført nedenfor.", "LidarrTags": "{appName} tags", - "LoadingTrackFilesFailed": "Indlæsning af filmfiler mislykkedes", "Local": "Lokal", "LocalPath": "Lokal sti", "LocalPathHelpText": "Sti, som {appName} skal bruge for at få adgang til den eksterne sti lokalt", @@ -452,7 +443,6 @@ "DeleteNotification": "Slet underretning", "DownloadFailedCheckDownloadClientForMoreDetails": "Download mislykkedes: tjek downloadklienten for flere detaljer", "Downloading": "Downloader", - "ExtraFileExtensionsHelpTexts1": "Kommasepareret liste over ekstra filer, der skal importeres (.nfo importeres som .nfo-orig)", "FileDateHelpText": "Skift fildato ved import / genscanning", "FileManagement": "Fil Håndtering", "OnGrab": "ved hentning", @@ -659,7 +649,6 @@ "SetTags": "Indstil tags", "NoEventsFound": "Ingen begivenheder fundet", "ApplyTagsHelpTextRemove": "Fjern: Fjern de indtastede tags", - "RemoveFromDownloadClientHelpTextWarning": "Fjernelse fjerner download og fil (er) fra download-klienten.", "RemoveSelectedItemQueueMessageText": "Er du sikker på, at du vil fjerne {0} element {1} fra køen?", "RemoveSelectedItemsQueueMessageText": "Er du sikker på, at du vil fjerne {0} element {1} fra køen?", "Yes": "Ja", @@ -711,5 +700,14 @@ "RenameFiles": "Omdøb filer", "Small": "Lille", "ReleaseProfile": "udgivelsesprofil", - "DeleteAutoTagHelpText": "Er du sikker på, at du vil slette kvalitetsprofilen {0}" + "DeleteAutoTagHelpText": "Er du sikker på, at du vil slette kvalitetsprofilen {0}", + "NoLimitForAnyDuration": "Ingen grænse for nogen runtime", + "NoMinimumForAnyDuration": "Intet minimum for enhver driftstid", + "PreferredSize": "Foretrukken størrelse", + "Unlimited": "Ubegrænset", + "AddImportListExclusionAlbumHelpText": "Undgå, at film føjes til {appName} af lister", + "ExtraFileExtensionsHelpText": "Kommasepareret liste over ekstra filer, der skal importeres (.nfo importeres som .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Eksempler: '.sub, .nfo' eller 'sub, nfo'", + "DeleteArtistFoldersHelpText": "Slet filmmappen og dens indhold", + "DeleteSpecificationHelpText": "Er du sikker på, at du vil slette kvalitetsprofilen {0}" } diff --git a/src/NzbDrone.Core/Localization/Core/de.json b/src/NzbDrone.Core/Localization/Core/de.json index 37e276f09..5ea9fd48f 100644 --- a/src/NzbDrone.Core/Localization/Core/de.json +++ b/src/NzbDrone.Core/Localization/Core/de.json @@ -21,7 +21,7 @@ "CopyUsingHardlinksHelpText": "Hardlinks erstellen wenn Torrents die noch geseeded werden kopiert werden sollen", "CopyUsingHardlinksHelpTextWarning": "Dateisperren Gelegentlich kann es vorkommen, dass Dateisperren das Umbenennen von Dateien verhindern, die gerade geseeded werden. Sie können das Seeding vorübergehend deaktivieren und die Umbenennungsfunktion von {appName} als Workaround verwenden.", "CreateGroup": "Gruppe erstellen", - "DBMigration": "DB Migration", + "DatabaseMigration": "DB Migration", "DelayProfile": "Verzögerungsprofil", "DeleteBackup": "Backup löschen", "DeleteBackupMessageText": "Backup '{0}' wirkich löschen?", @@ -105,7 +105,6 @@ "DeleteDelayProfileMessageText": "Bist du sicher, dass du dieses Verzögerung-Profil löschen willst?", "DeleteImportListExclusionMessageText": "Bist du sicher, dass du diesen Importlisten Ausschluss löschen willst?", "DeleteImportListMessageText": "Liste '{0}' wirklich löschen?", - "ExtraFileExtensionsHelpTexts1": "Kommaseparierte Liste von Dateiendungen die als Extra Dateien importiert werden sollen ( .nfo wird in .nfo-orig umbenannt )", "Fixed": "Behoben", "Indexer": "Indexer", "ReleaseGroup": "Release-Gruppe", @@ -167,7 +166,6 @@ "Port": "Port", "PortNumber": "Port Nummer", "PosterSize": "Plakatgröße", - "PriorityHelpText": "Indexer Priorität von 1 (höchste) bis 50 (niedrigste). Standard: 25.", "Profiles": "Profile", "Proper": "Korrekt", "PropersAndRepacks": "Propers und Repacks", @@ -317,7 +315,6 @@ "ImportExtraFilesHelpText": "Importiere zutreffende Extra Dateien (Untertitel, nfo, etc.) nach dem Importieren einer Filmdatei", "ImportFailedInterp": "Import fehlgeschlagen: {0}", "Importing": "Importiere", - "IncludeHealthWarningsHelpText": "Zustandswarnung", "IncludeUnmonitored": "Nicht beobachtete einbeziehen", "IndexerPriority": "Priorität", "Indexers": "Indexer", @@ -326,7 +323,6 @@ "LaunchBrowserHelpText": " Öffne die Startseite von {appName} im Webbrowser nach dem Start.", "Level": "Stufe", "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} unterstützt viele populäre Torrent und Usenet Download Clients.", - "LoadingTrackFilesFailed": "Laden der Film-Dateien fehlgeschlagen", "Local": "Lokal", "LogFiles": "Protokolldateien", "Logging": "Protokollierung", @@ -351,16 +347,10 @@ "NoBackupsAreAvailable": "Es sind keine Backups vorhanden", "NoHistory": "Kein Verlauf.", "NoLeaveIt": "Nein, nicht ändern", - "NoLimitForAnyRuntime": "Keine Begrenzung der Laufzeiten", "NoLogFiles": "Keine Log-Dateien", - "NoMinimumForAnyRuntime": "Kein Minimum für Laufzeiten", "None": "Keine", "NotificationTriggers": "Benachrichtigungs Auslöser", "NoUpdatesAreAvailable": "Es sind keine Updates verfügbar", - "OnGrabHelpText": "Erfassen", - "OnHealthIssueHelpText": "Zustandsproblem", - "OnRenameHelpText": "Umbennenen", - "OnUpgradeHelpText": "Upgrade", "OpenBrowserOnStart": "Browser beim Start öffnen", "Original": "Orginal", "PackageVersion": "Paket Version", @@ -485,7 +475,6 @@ "AllAlbums": "Alle Alben", "ExpandItemsByDefault": "Elemente standardmäßig ausklappen", "ExpandSingleByDefaultHelpText": "Singles", - "ExtraFileExtensionsHelpTexts2": "\"Beispiele:\".sub", "FirstAlbum": "Erstes Album", "FirstAlbumData": "Beobachte die ersten Alben. Alle anderen Alben werden ignoriert", "RemoveCompleted": "Abgeschlossene entfernen", @@ -509,14 +498,11 @@ "ImportListExclusions": "Ausschlüsse der Importliste", "IsInUseCantDeleteAQualityProfileThatIsAttachedToAnArtistOrImportList": "Ein Qualitätsprofil, dass einem Künstler oder einer Importliste zugeordnet ist, kann nicht gelöscht werden", "IsShowingMonitoredMonitorSelected": "Beobachte ausgewählte", - "LoadingAlbumsFailed": "Laden der Alben fehlgeschlagen", "MissingAlbums": "Fehlende Alben", "MissingTracksArtistMonitored": "Fehlende Titel (Beobachteter Künstler)", "MusicBrainzRecordingID": "MusicBrainz Aufnahme Id", "NoneData": "Es werden keine Alben beobachtet", "OnApplicationUpdate": "Bei Anwendungsaktualisierung", - "OnApplicationUpdateHelpText": "Bei Anwendungsaktualisierung", - "OnDownloadFailureHelpText": "Bei fehlgeschlagenem Download", "OnGrab": "Bei Erfassung", "OnImportFailure": "Bei fehlgeschlagenem Import", "PathHelpTextWarning": "Dies muss ein anderes Verzeichnis sein als das, in dem der Download Client die Dateien ablegt", @@ -612,12 +598,9 @@ "MusicBrainzReleaseID": "MusicBrainz Veröffentlichung Id", "MusicBrainzTrackID": "MusicBrainz Titel Id", "OnDownloadFailure": "Bei fehlgeschlagenem Download", - "OnImportFailureHelpText": "Bei fehlgeschlagenem Import", "OnReleaseImport": "Bei Veröffentlichungsimport", - "OnReleaseImportHelpText": "Bei Veröffentlichungsimport", "OnRename": "Bei Umbenennen", "OnTrackRetag": "Bei Titel Retag", - "OnTrackRetagHelpText": "Bei Titel Retag", "OnUpgrade": "Bei Aktualisierung", "Other": "Andere", "PastDays": "Vergangene Tage", @@ -627,7 +610,7 @@ "Release": " Veröffentlichung", "ReleaseProfiles": "Veröffentlichungsprofile", "RemoveDownloadsAlert": "Die Einstellungen zum Entfernen wurden in die individuellen Download Client Einstellungen in der obigen Tabelle verschoben.", - "RemoveFailed": "Entfernen fehlgeschlagen", + "RemoveFailed": "Fehlgeschlagene entfernen", "RootFolderPathHelpText": "Die Elemente im Stammverzeichnis werden hinzugefügt zu", "SceneInformation": "Szeneninformationen", "SceneNumberHasntBeenVerifiedYet": "Die Szenennummer wurde noch nicht verifiziert", @@ -671,7 +654,7 @@ "AddIndexer": "Indexer hinzufügen", "AddMetadataProfile": "Metadaten Profil", "AddNew": "Neue hinzufügen", - "AddQualityProfile": "Qualitätsprofil hinzufügen", + "AddQualityProfile": "Qualitäts Profil hinzufügen", "AddRemotePathMapping": "Entfernte Pfadzuordnung hinzufügen", "AddRootFolder": "Stammordner hinzufügen", "AfterManualRefresh": "Nach manuellen aktualisieren", @@ -764,7 +747,7 @@ "UnmappedFilesOnly": "Nur nicht zugeordnete Dateien", "UnmonitoredOnly": "Nur beobachtete", "UpgradesAllowed": "Upgrades erlaubt", - "Wanted": "› Gesuchte", + "Wanted": "› Gesucht", "Warn": "Warnung", "WouldYouLikeToRestoreBackup": "Willst du das Backup {0} wiederherstellen?", "Age": "Alter", @@ -922,7 +905,6 @@ "ReplaceWithSpaceDashSpace": "Mit Leerzeichen Bindestrich Leerzeichen ersetzen", "SystemTimeCheckMessage": "Die Systemzeit ist um einen Tag versetzt. Bis die Zeit korrigiert wurde, könnten die geplanten Aufgaben nicht korrekt ausgeführt werden", "ApiKeyValidationHealthCheckMessage": "Bitte den API Schlüssel korrigieren, dieser muss mindestens {0} Zeichen lang sein. Die Änderung kann über die Einstellungen oder die Konfigurationsdatei erfolgen", - "OnHealthRestoredHelpText": "Bei Wiederherstellung des Zustands", "OnHealthRestored": "Bei Wiederherstellung des Zustands", "ThereWasAnErrorLoadingThisItem": "Beim Laden des Eintrags ist ein Fehler aufgetreten", "ThereWasAnErrorLoadingThisPage": "Beim Laden der Seite ist ein Fehler aufgetreten", @@ -961,5 +943,27 @@ "AddConnectionImplementation": "Verbindung hinzufügen - {implementationName}", "AddDownloadClientImplementation": "Download-Client hinzufügen - {implementationName}", "AddIndexerImplementation": "Indexer hinzufügen - {implementationName}", - "AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu" + "AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu", + "AddNewArtistSearchForMissingAlbums": "Suche nach fehlenden Alben starten", + "AuthenticationRequiredHelpText": "Ändern, welche anfragen Authentifizierung benötigen. Ändere nichts wenn du dir nicht des Risikos bewusst bist.", + "AuthenticationRequiredUsernameHelpTextWarning": "Gib einen neuen Benutzernamen ein", + "AddNewAlbum": "Neues Album hinzufügen", + "AddNewArtist": "Neue:n Künstler:in hinzufügen", + "AddNewArtistRootFolderHelpText": "'{folder}' Unterordner wird automatisch erstellt werden", + "AuthenticationMethodHelpTextWarning": "Bitte wähle eine gültige Authentifizierungsmethode aus", + "AuthenticationRequiredWarning": "Um unberechtigte Fernzugriffe zu vermeiden benötigt {appName} jetzt , dass Authentifizierung eingeschaltet ist. Du kannst Authentifizierung optional für lokale Adressen ausschalten.", + "AddConditionError": "Neue Bedingung konnte nicht hinzugefügt werden, bitte erneut versuchen.", + "AddCondition": "Bedingung hinzufügen", + "AddAutoTag": "Automatischen Tag hinzufügen", + "AddAutoTagError": "Der neue automatische Tag konnte nicht hinzugefügt werden, bitte versuche es erneut.", + "AddAlbumWithTitle": "{albumTitle} hinzufügen", + "AddNewAlbumSearchForNewAlbum": "Suche nach neuem Album starten", + "AddArtistWithName": "{artistName} hinzufügen", + "AuthenticationRequired": "Authentifizierung benötigt", + "AuthenticationRequiredPasswordHelpTextWarning": "Gib ein neues Passwort ein", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Neues Passwort bestätigen", + "UpdateSelected": "Auswahl aktualisieren", + "RemoveFailedDownloads": "Fehlgeschlagene Downloads entfernen", + "CloneAutoTag": "Automatische Tags kopieren", + "ClearBlocklist": "Sperrliste leeren" } diff --git a/src/NzbDrone.Core/Localization/Core/el.json b/src/NzbDrone.Core/Localization/Core/el.json index f3464db44..3d3e05700 100644 --- a/src/NzbDrone.Core/Localization/Core/el.json +++ b/src/NzbDrone.Core/Localization/Core/el.json @@ -62,7 +62,6 @@ "PageSize": "Μέγεθος σελίδας", "PosterSize": "Μέγεθος αφίσας", "PreviewRename": "Μετονομασία προεπισκόπησης", - "PriorityHelpText": "Προτεραιότητα δείκτη από 1 (υψηλότερη) έως 50 (χαμηλότερη). Προεπιλογή: 25. Χρησιμοποιείται κατά τη λήψη εκδόσεων ως ισοπαλία για ίσες κατά τα άλλα εκδόσεις, το {appName} θα εξακολουθεί να χρησιμοποιεί όλα τα ενεργοποιημένα ευρετήρια για RSS Sync και Searching.", "Proper": "Κατάλληλος", "Protocol": "Πρωτόκολλο", "Proxy": "Πληρεξούσιο", @@ -258,7 +257,6 @@ "ErrorLoadingContents": "Σφάλμα κατά τη φόρτωση περιεχομένων", "ErrorLoadingPreviews": "Σφάλμα κατά τη φόρτωση προεπισκοπήσεων", "Exception": "Εξαίρεση", - "ExtraFileExtensionsHelpTexts1": "Λίστα πρόσθετων αρχείων που διαχωρίζονται με κόμμα για εισαγωγή (το .nfo θα εισαχθεί ως .nfo-orig)", "FileDateHelpText": "Αλλαγή ημερομηνίας αρχείου κατά την εισαγωγή / επανασύνδεση", "FileManagement": "Διαχείρηση Αρχείων", "Filename": "Όνομα Αρχείου", @@ -288,7 +286,6 @@ "IgnoredAddresses": "Διευθύνσεις που αγνοήθηκαν", "IgnoredPlaceHolder": "Προσθέστε νέο περιορισμό", "Importing": "Εισαγωγή", - "IncludeHealthWarningsHelpText": "Συμπεριλάβετε προειδοποιήσεις για την υγεία", "IncludeUnmonitored": "Συμπερίληψη χωρίς παρακολούθηση", "Indexer": "Ευρετήριο", "IndexerPriority": "Προτεραιότητα ευρετηρίου", @@ -296,7 +293,6 @@ "Interval": "Διάστημα", "IsTagUsedCannotBeDeletedWhileInUse": "Δεν είναι δυνατή η διαγραφή κατά τη χρήση", "LidarrTags": "Ετικέτες {appName}", - "LoadingTrackFilesFailed": "Η φόρτωση αρχείων ταινίας απέτυχε", "Local": "Τοπικός", "LocalPath": "Τοπικό μονοπάτι", "LocalPathHelpText": "Διαδρομή που πρέπει να χρησιμοποιήσει ο {appName} για πρόσβαση τοπικά στην απομακρυσμένη διαδρομή", @@ -333,16 +329,10 @@ "NoBackupsAreAvailable": "Δεν υπάρχουν διαθέσιμα αντίγραφα ασφαλείας", "NoHistory": "Χωρίς ιστορία.", "NoLeaveIt": "Όχι, άσε το", - "NoLimitForAnyRuntime": "Δεν υπάρχει όριο για οποιοδήποτε χρόνο εκτέλεσης", "NoLogFiles": "Δεν υπάρχουν αρχεία καταγραφής", - "NoMinimumForAnyRuntime": "Χωρίς ελάχιστο για κάθε χρόνο εκτέλεσης", "None": "Κανένας", "NotificationTriggers": "Ενεργοποιήσεις ειδοποίησης", "NoUpdatesAreAvailable": "Δεν υπάρχουν διαθέσιμες ενημερώσεις", - "OnGrabHelpText": "Στο Grab", - "OnHealthIssueHelpText": "Σχετικά με το θέμα της υγείας", - "OnRenameHelpText": "Μετονομασία", - "OnUpgradeHelpText": "Κατά την αναβάθμιση", "OpenBrowserOnStart": "Ανοίξτε το πρόγραμμα περιήγησης κατά την έναρξη", "Options": "Επιλογές", "Original": "Πρωτότυπο", @@ -450,7 +440,7 @@ "AnalyticsEnabledHelpTextWarning": "Απαιτείται επανεκκίνηση για να τεθεί σε ισχύ", "Automatic": "Αυτόματο", "BackupNow": "Δημιουργία Αντιγράφου Ασφαλείας", - "DBMigration": "Μετεγκατάσταση DB", + "DatabaseMigration": "Μετεγκατάσταση DB", "Dates": "Ημερομηνίες", "MarkAsFailed": "Επισήμανση ως αποτυχημένου", "DelayingDownloadUntilInterp": "Καθυστέρηση λήψης έως τις {0} στις {1}", @@ -599,7 +589,6 @@ "InstanceName": "Όνομα παράδειγμα", "InstanceNameHelpText": "Όνομα παρουσίας στην καρτέλα και για όνομα εφαρμογής Syslog", "OnApplicationUpdate": "Στην ενημέρωση της εφαρμογής", - "OnApplicationUpdateHelpText": "Στην ενημέρωση της εφαρμογής", "Database": "Βάση δεδομένων", "Duration": "Διάρκεια", "IndexerDownloadClientHelpText": "Καθορίστε ποιο πρόγραμμα-πελάτη λήψης χρησιμοποιείται για αρπαγές από αυτό το ευρετήριο", @@ -630,7 +619,6 @@ "MonitoredHelpText": "Λήψη παρακολουθούμενων άλμπουμ από αυτόν τον καλλιτέχνη", "OnImportFailure": "Σε περίπτωση αποτυχίας εισαγωγής", "OnTrackRetag": "Στο Track Retag", - "OnReleaseImportHelpText": "Κατά την εισαγωγή εισαγωγής", "PathHelpTextWarning": "Αυτό πρέπει να είναι διαφορετικό από τον κατάλογο όπου το πρόγραμμα-πελάτης λήψης τοποθετεί τα αρχεία", "SearchBoxPlaceHolder": "π.χ. Breaking Benjamin, lidarr:854a1807-025b-42a8-ba8c-2a39717f1d25", "Season": "Εποχή", @@ -672,8 +660,6 @@ "MonitorArtist": "Monitor Artist", "NoneData": "Κανένα άλμπουμ δεν θα παρακολουθείται", "OnAlbumDelete": "Στο άλμπουμ Διαγραφή", - "OnAlbumDeleteHelpText": "Στο άλμπουμ Διαγραφή", - "OnImportFailureHelpText": "Σε περίπτωση αποτυχίας εισαγωγής", "OnReleaseImport": "Κατά την εισαγωγή εισαγωγής", "Playlist": "Λίστα αναπαραγωγής", "PreviewRetag": "Προεπισκόπηση επανασύνδεσης", @@ -704,7 +690,6 @@ "MediaCount": "Καταμέτρηση μέσων", "NotDiscography": "Όχι δισκογραφία", "OnDownloadFailure": "Σε αποτυχία λήψης", - "OnTrackRetagHelpText": "Στο Track Retag", "Retagged": "Επανασήμανστηκε", "WatchRootFoldersForFileChanges": "Παρακολουθήστε τους φακέλους Root για αλλαγές αρχείων", "Inactive": "Αδρανής", @@ -744,14 +729,12 @@ "IsInUseCantDeleteAMetadataProfileThatIsAttachedToAnArtistOrImportList": "Δεν είναι δυνατή η διαγραφή ενός προφίλ μεταδεδομένων που είναι συνδεδεμένο με έναν καλλιτέχνη ή λίστα εισαγωγής", "IsInUseCantDeleteAQualityProfileThatIsAttachedToAnArtistOrImportList": "Δεν είναι δυνατή η διαγραφή ενός προφίλ ποιότητας που είναι συνδεδεμένο με έναν καλλιτέχνη ή λίστα εισαγωγής", "LatestAlbumData": "Παρακολουθήστε τα τελευταία άλμπουμ και τα μελλοντικά άλμπουμ", - "LoadingAlbumsFailed": "Η φόρτωση άλμπουμ απέτυχε", "MassAlbumsCutoffUnmetWarning": "Είστε βέβαιοι ότι θέλετε να αναζητήσετε όλα τα άλμπουμ \"{0}\" Cutoff Unmet;", "MassAlbumsSearchWarning": "Είστε βέβαιοι ότι θέλετε να αναζητήσετε όλα τα άλμπουμ \"{0}\" που λείπουν;", "MetadataProfiles": "Προφίλ μεταδεδομένων", "MinimumCustomFormatScoreHelpText": "Απαιτείται ελάχιστη βαθμολογία προσαρμοσμένης μορφής για την παράκαμψη της καθυστέρησης για το προτιμώμενο πρωτόκολλο", "MonitorAlbumExistingOnlyWarning": "Αυτή είναι μια εφάπαξ προσαρμογή της ρύθμισης παρακολούθησης για κάθε άλμπουμ. Χρησιμοποιήστε την επιλογή στην περιοχή Καλλιτέχνης/Επεξεργασία για να ελέγξετε τι συμβαίνει στα άλμπουμ που προστέθηκαν πρόσφατα", "MonitoringOptions": "Επιλογές παρακολούθησης", - "OnArtistDeleteHelpText": "Στο Διαγραφή καλλιτέχνη", "PrimaryTypes": "Πρωτογενείς τύποι", "ReleaseProfiles": "Προφίλ έκδοσης", "ReleasesHelpText": "Αλλαγή κυκλοφορίας για αυτό το άλμπουμ", @@ -797,7 +780,6 @@ "EnableRssHelpText": "Θα χρησιμοποιείται όταν το {appName} αναζητά περιοδικά εκδόσεις μέσω RSS Sync", "EpisodeDoesNotHaveAnAbsoluteEpisodeNumber": "Το επεισόδιο δεν έχει απόλυτο αριθμό επεισοδίου", "ExistingTagsScrubbed": "Οι υπάρχουσες ετικέτες καθαρίστηκαν", - "ExtraFileExtensionsHelpTexts2": "\"Παραδείγματα: \".sub", "FirstAlbum": "Πρώτο άλμπουμ", "IsExpandedHideAlbums": "Απόκρυψη άλμπουμ", "MusicBrainzArtistID": "Αναγνωριστικό καλλιτέχνη MusicBrainz", @@ -814,7 +796,6 @@ "FutureDaysHelpText": "Ημέρες για το iCal feed για να κοιτάξουμε στο μέλλον", "MissingTracks": "Λείπουν κομμάτια", "MissingTracksArtistNotMonitored": "Κομμάτια που λείπουν (Ο καλλιτέχνης δεν παρακολουθείται)", - "OnDownloadFailureHelpText": "Σε αποτυχία λήψης", "SelectedCountArtistsSelectedInterp": "Επιλέχθηκαν {0} καλλιτέχνες", "Theme": "Θέμα", "UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "Η ενημέρωση είναι απενεργοποιημένη μέσα σε ένα κοντέινερ docker. Αντ' αυτού, ενημερώστε την εικόνα του κοντέινερ.", @@ -956,7 +937,6 @@ "ThereWasAnErrorLoadingThisPage": "Υπήρξε ένα σφάλμα κατά τη φόρτωση της σελίδας", "DeleteRemotePathMapping": "Επεξεργασία αντιστοίχισης απομακρυσμένης διαδρομής", "DeleteRemotePathMappingMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτήν την αντιστοίχιση απομακρυσμένης διαδρομής;", - "OnHealthRestoredHelpText": "Στην Αποκατάσταση Υγείας", "RecycleBinUnableToWriteHealthCheck": "Δεν είναι δυνατή η εγγραφή στον επιλεγμένο φάκελο ανακύκλωσης: {0}. Ελέγξτε ότι ο φάκελος υπάρχει και είναι εγγράψιμος από τον χρήστη που τρέχει το {appName}", "ShowNextAlbum": "Εμφάνιση τελευταίου άλμπουμ", "DeleteCondition": "Διαγραφή συνθήκης", @@ -995,7 +975,6 @@ "ExistingTag": "Υφιστάμενη ετικέτα", "RemovingTag": "Κατάργηση ετικέτας", "Required": "Απαιτείται", - "RemoveFromDownloadClientHelpTextWarning": "Η κατάργηση θα καταργήσει τη λήψη και τα αρχεία από τον πελάτη λήψης.", "RemoveSelectedItemQueueMessageText": "Είστε σίγουροι πως θέλετε να διαγράψετε 1 αντικείμενο από την ουρά;", "ApplyTagsHelpTextHowToApplyArtists": "Πώς να εφαρμόσετε ετικέτες στις επιλεγμένες ταινίες", "DeleteSelectedDownloadClientsMessageText": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το ευρετήριο \"{0}\";", @@ -1073,5 +1052,14 @@ "DeleteSelectedArtists": "Διαγραφή επιλεγμένου καλλιτέχνη", "DeleteSpecification": "Διαγραφή ειδοποίησης", "DeleteSpecificationHelpText": "Είστε σίγουροι πως θέλετε να διαγράψετε τη συνθήκη '{name}';", - "ImportList": "Λίστες εισαγωγής" + "ImportList": "Λίστες εισαγωγής", + "NoLimitForAnyDuration": "Δεν υπάρχει όριο για οποιοδήποτε χρόνο εκτέλεσης", + "NoMinimumForAnyDuration": "Χωρίς ελάχιστο για κάθε χρόνο εκτέλεσης", + "PreferredSize": "Προτιμώμενο μέγεθος", + "Unlimited": "Απεριόριστος", + "AddImportListExclusionAlbumHelpText": "Αποτρέψτε την προσθήκη ταινίας στο {appName} από λίστες", + "ExtraFileExtensionsHelpText": "Λίστα πρόσθετων αρχείων που διαχωρίζονται με κόμμα για εισαγωγή (το .nfo θα εισαχθεί ως .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Παραδείγματα: «.sub, .nfo» ή «sub, nfo»", + "DeleteArtistFoldersHelpText": "Διαγράψτε το φάκελο της ταινίας και τα περιεχόμενά του", + "ArtistIsMonitored": "Ο συγγραφέας δεν παρακολουθείται" } diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 231723105..8b2eecae4 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -89,7 +89,7 @@ "AnyReleaseOkHelpText": "{appName} will automatically switch to the release best matching downloaded tracks", "ApiKeyHelpTextWarning": "Requires restart to take effect", "ApiKeyValidationHealthCheckMessage": "Please update your API key to be at least {0} characters long. You can do this via settings or the config file", - "AppDataDirectory": "AppData directory", + "AppDataDirectory": "AppData Directory", "AppDataLocationHealthCheckMessage": "Updating will not be possible to prevent deleting AppData on Update", "AppUpdated": "{appName} Updated", "AppUpdatedVersion": "{appName} has been updated to version `{version}`, in order to get the latest changes you'll need to reload {appName}", @@ -135,6 +135,9 @@ "AuthenticationRequiredWarning": "To prevent remote access without authentication, {appName} now requires authentication to be enabled. You can optionally disable authentication from local addresses.", "Auto": "Auto", "AutoAdd": "Auto Add", + "AutoRedownloadFailed": "Redownload Failed", + "AutoRedownloadFailedFromInteractiveSearch": "Redownload Failed from Interactive Search", + "AutoRedownloadFailedFromInteractiveSearchHelpText": "Automatically search for and attempt to download a different release when failed release was grabbed from interactive search", "AutoRedownloadFailedHelpText": "Automatically search for and attempt to download a different release", "AutoTagging": "Auto Tagging", "AutoTaggingLoadError": "Unable to load auto tagging", @@ -157,6 +160,12 @@ "BindAddressHelpText": "Valid IP address, localhost or '*' for all interfaces", "BindAddressHelpTextWarning": "Requires restart to take effect", "Blocklist": "Blocklist", + "BlocklistAndSearch": "Blocklist and Search", + "BlocklistAndSearchHint": "Start a search for a replacement after blocklisting", + "BlocklistAndSearchMultipleHint": "Start searches for replacements after blocklisting", + "BlocklistMultipleOnlyHint": "Blocklist without searching for replacements", + "BlocklistOnly": "Blocklist Only", + "BlocklistOnlyHint": "Blocklist without searching for a replacement", "BlocklistRelease": "Blocklist Release", "BlocklistReleaseHelpText": "Prevents {appName} from automatically grabbing these files again", "BlocklistReleases": "Blocklist Releases", @@ -173,6 +182,9 @@ "CatalogNumber": "Catalog Number", "CertificateValidation": "Certificate Validation", "CertificateValidationHelpText": "Change how strict HTTPS certification validation is. Do not change unless you understand the risks.", + "ChangeCategory": "Change Category", + "ChangeCategoryHint": "Changes download to the 'Post-Import Category' from Download Client", + "ChangeCategoryMultipleHint": "Changes downloads to the 'Post-Import Category' from Download Client", "ChangeFileDate": "Change File Date", "ChangeHasNotBeenSavedYet": "Change has not been saved yet", "ChmodFolder": "chmod Folder", @@ -236,13 +248,15 @@ "CustomFormatScore": "Custom Format Score", "CustomFormatSettings": "Custom Format Settings", "CustomFormats": "Custom Formats", + "CustomFormatsSpecificationRegularExpression": "Regular Expression", + "CustomFormatsSpecificationRegularExpressionHelpText": "Custom Format RegEx is Case Insensitive", "Customformat": "Custom Format", "CutoffFormatScoreHelpText": "Once this custom format score is reached {appName} will no longer grab album releases", "CutoffHelpText": "Once this quality is reached {appName} will no longer download albums", "CutoffUnmet": "Cutoff Unmet", - "DBMigration": "DB Migration", "DashOrSpaceDashDependingOnName": "Dash or Space Dash depending on name", "Database": "Database", + "DatabaseMigration": "Database Migration", "Date": "Date", "DateAdded": "Date Added", "Dates": "Dates", @@ -327,15 +341,21 @@ "DiscNumber": "Disc Number", "Discography": "Discography", "DiskSpace": "Disk Space", + "DoNotBlocklist": "Do not Blocklist", + "DoNotBlocklistHint": "Remove without blocklisting", "DoNotPrefer": "Do Not Prefer", "DoNotUpgradeAutomatically": "Do not Upgrade Automatically", "Docker": "Docker", "Donations": "Donations", "DoneEditingGroups": "Done Editing Groups", "DownloadClient": "Download Client", + "DownloadClientAriaSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Aria2 location", "DownloadClientCheckDownloadingToRoot": "Download client {0} places downloads in the root folder {1}. You should not download to a root folder.", "DownloadClientCheckNoneAvailableMessage": "No download client is available", "DownloadClientCheckUnableToCommunicateMessage": "Unable to communicate with {0}.", + "DownloadClientPriorityHelpText": "Download Client Priority from 1 (Highest) to 50 (Lowest). Default: 1. Round-Robin is used for clients with the same priority.", + "DownloadClientQbittorrentSettingsContentLayout": "Content Layout", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Whether to use qBittorrent's configured content layout, the original layout from the torrent or always create a subfolder (qBittorrent 4.3.2+)", "DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "Download client {0} is set to remove completed downloads. This can result in downloads being removed from your client before {1} can import them.", "DownloadClientSettings": "Download Client Settings", "DownloadClientSortingCheckMessage": "Download client {0} has {1} sorting enabled for {appName}'s category. You should disable sorting in your download client to avoid import issues.", @@ -419,8 +439,8 @@ "ExpandSingleByDefaultHelpText": "Singles", "ExportCustomFormat": "Export Custom Format", "External": "External", - "ExtraFileExtensionsHelpTexts1": "Comma separated list of extra files to import (.nfo will be imported as .nfo-orig)", - "ExtraFileExtensionsHelpTexts2": "\"Examples: \".sub", + "ExtraFileExtensionsHelpText": "Comma separated list of extra files to import (.nfo will be imported as .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Examples: '.sub, .nfo' or 'sub,nfo'", "FailedDownloadHandling": "Failed Download Handling", "FailedLoadingSearchResults": "Failed to load search results, please try again.", "FailedToLoadQueue": "Failed to load Queue", @@ -482,6 +502,10 @@ "ICalLink": "iCal Link", "IconForCutoffUnmet": "Icon for Cutoff Unmet", "IfYouDontAddAnImportListExclusionAndTheArtistHasAMetadataProfileOtherThanNoneThenThisAlbumMayBeReaddedDuringTheNextArtistRefresh": "If you don't add an import list exclusion and the artist has a metadata profile other than 'None' then this album may be re-added during the next artist refresh.", + "IgnoreDownload": "Ignore Download", + "IgnoreDownloadHint": "Stops {appName} from processing this download further", + "IgnoreDownloads": "Ignore Downloads", + "IgnoreDownloadsHint": "Stops {appName} from processing these downloads further", "Ignored": "Ignored", "IgnoredAddresses": "Ignored Addresses", "IgnoredHelpText": "The release will be rejected if it contains one or more of terms (case insensitive)", @@ -508,7 +532,7 @@ "Importing": "Importing", "Inactive": "Inactive", "IncludeCustomFormatWhenRenamingHelpText": "'Include in {Custom Formats} renaming format'", - "IncludeHealthWarningsHelpText": "Include Health Warnings", + "IncludeHealthWarnings": "Include Health Warnings", "IncludeUnknownArtistItemsHelpText": "Show items without a artist in the queue, this could include removed artists, movies or anything else in {appName}'s category", "IncludeUnmonitored": "Include Unmonitored", "Indexer": "Indexer", @@ -526,6 +550,8 @@ "IndexerSearchCheckNoAvailableIndexersMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors", "IndexerSearchCheckNoInteractiveMessage": "No indexers available with Interactive Search enabled, {appName} will not provide any interactive search results", "IndexerSettings": "Indexer Settings", + "IndexerSettingsRejectBlocklistedTorrentHashes": "Reject Blocklisted Torrent Hashes While Grabbing", + "IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "If a torrent is blocked by hash it may not properly be rejected during RSS/Search for some indexers, enabling this will allow it to be rejected after the torrent is grabbed, but before it is sent to the client.", "IndexerStatusCheckAllClientMessage": "All indexers are unavailable due to failures", "IndexerStatusCheckSingleClientMessage": "Indexers unavailable due to failures: {0}", "IndexerTagHelpText": "Only use this indexer for artist with at least one matching tag. Leave blank to use with all artists.", @@ -572,8 +598,6 @@ "ListRefreshInterval": "List Refresh Interval", "ListWillRefreshEveryInterp": "List will refresh every {0}", "Loading": "loading", - "LoadingAlbumsFailed": "Loading albums failed", - "LoadingTrackFilesFailed": "Loading track files failed", "Local": "Local", "LocalPath": "Local Path", "LocalPathHelpText": "Path that {appName} should use to access the remote path locally", @@ -682,9 +706,9 @@ "NoImportListsFound": "No import lists found", "NoIndexersFound": "No indexers found", "NoLeaveIt": "No, Leave It", - "NoLimitForAnyRuntime": "No limit for any runtime", + "NoLimitForAnyDuration": "No limit for any duration", "NoLogFiles": "No log files", - "NoMinimumForAnyRuntime": "No minimum for any runtime", + "NoMinimumForAnyDuration": "No minimum for any duration", "NoMissingItems": "No missing items", "NoResultsFound": "No results found", "NoTagsHaveBeenAddedYet": "No tags have been added yet", @@ -698,29 +722,18 @@ "NotificationTriggers": "Notification Triggers", "Ok": "Ok", "OnAlbumDelete": "On Album Delete", - "OnAlbumDeleteHelpText": "On Album Delete", "OnApplicationUpdate": "On Application Update", - "OnApplicationUpdateHelpText": "On Application Update", + "OnArtistAdd": "On Artist Add", "OnArtistDelete": "On Artist Delete", - "OnArtistDeleteHelpText": "On Artist Delete", "OnDownloadFailure": "On Download Failure", - "OnDownloadFailureHelpText": "On Download Failure", "OnGrab": "On Grab", - "OnGrabHelpText": "On Grab", "OnHealthIssue": "On Health Issue", - "OnHealthIssueHelpText": "On Health Issue", "OnHealthRestored": "On Health Restored", - "OnHealthRestoredHelpText": "On Health Restored", "OnImportFailure": "On Import Failure", - "OnImportFailureHelpText": "On Import Failure", "OnReleaseImport": "On Release Import", - "OnReleaseImportHelpText": "On Release Import", "OnRename": "On Rename", - "OnRenameHelpText": "On Rename", "OnTrackRetag": "On Track Retag", - "OnTrackRetagHelpText": "On Track Retag", "OnUpgrade": "On Upgrade", - "OnUpgradeHelpText": "On Upgrade", "OneAlbum": "1 album", "OnlyTorrent": "Only Torrent", "OnlyUsenet": "Only Usenet", @@ -756,13 +769,13 @@ "PreferTorrent": "Prefer Torrent", "PreferUsenet": "Prefer Usenet", "PreferredProtocol": "Preferred Protocol", + "PreferredSize": "Preferred Size", "Presets": "Presets", "PreviewRename": "Preview Rename", "PreviewRetag": "Preview Retag", "PrimaryAlbumTypes": "Primary Album Types", "PrimaryTypes": "Primary Types", "Priority": "Priority", - "PriorityHelpText": "Indexer Priority from 1 (Highest) to 50 (Lowest). Default: 25. Used when grabbing releases as a tiebreaker for otherwise equal releases, {appName} will still use all enabled indexers for RSS Sync and Searching.", "Proceed": "Proceed", "Profiles": "Profiles", "Progress": "Progress", @@ -852,9 +865,15 @@ "RemoveFailedDownloadsHelpText": "Remove failed downloads from download client history", "RemoveFilter": "Remove filter", "RemoveFromBlocklist": "Remove from blocklist", - "RemoveFromDownloadClient": "Remove From Download Client", - "RemoveFromDownloadClientHelpTextWarning": "Removing will remove the download and the file(s) from the download client.", + "RemoveFromDownloadClient": "Remove from Download Client", + "RemoveFromDownloadClientHint": "Removes download and file(s) from download client", "RemoveFromQueue": "Remove from queue", + "RemoveMultipleFromDownloadClientHint": "Removes downloads and files from download client", + "RemoveQueueItem": "Remove - {sourceTitle}", + "RemoveQueueItemConfirmation": "Are you sure you want to remove '{sourceTitle}' from the queue?", + "RemoveQueueItemRemovalMethod": "Removal Method", + "RemoveQueueItemRemovalMethodHelpTextWarning": "'Remove from Download Client' will remove the download and the file(s) from the download client.", + "RemoveQueueItemsRemovalMethodHelpTextWarning": "'Remove from Download Client' will remove the downloads and the files from the download client.", "RemoveSelected": "Remove Selected", "RemoveSelectedItem": "Remove Selected Item", "RemoveSelectedItemBlocklistMessageText": "Are you sure you want to remove the selected items from the blocklist?", @@ -1012,7 +1031,7 @@ "StandardTrackFormat": "Standard Track Format", "StartTypingOrSelectAPathBelow": "Start typing or select a path below", "Started": "Started", - "StartupDirectory": "Startup directory", + "StartupDirectory": "Startup Directory", "Status": "Status", "StatusEndedContinuing": "Continuing", "Style": "Style", @@ -1062,8 +1081,13 @@ "TrackCount": "Track Count", "TrackDownloaded": "Track Downloaded", "TrackFileCounttotalTrackCountTracksDownloadedInterp": "{0}/{1} tracks downloaded", + "TrackFileDeletedTooltip": "Track file deleted", + "TrackFileMissingTooltip": "Track file missing", + "TrackFileRenamedTooltip": "Track file renamed", + "TrackFileTagsUpdatedTooltip": "Track file tags updated", "TrackFiles": "Track Files", "TrackFilesCountMessage": "No track files", + "TrackFilesLoadError": "Unable to load track files", "TrackImported": "Track Imported", "TrackMissingFromDisk": "Track missing from disk", "TrackNaming": "Track Naming", @@ -1117,6 +1141,7 @@ "UnableToLoadTheCalendar": "Unable to load the calendar", "UnableToLoadUISettings": "Unable to load UI settings", "Ungroup": "Ungroup", + "Unlimited": "Unlimited", "UnmappedFiles": "Unmapped Files", "UnmappedFilesOnly": "Unmapped Files Only", "Unmonitored": "Unmonitored", diff --git a/src/NzbDrone.Core/Localization/Core/es.json b/src/NzbDrone.Core/Localization/Core/es.json index c560deafc..5c6b8eb10 100644 --- a/src/NzbDrone.Core/Localization/Core/es.json +++ b/src/NzbDrone.Core/Localization/Core/es.json @@ -2,7 +2,6 @@ "Language": "Idioma", "UILanguage": "Lenguaje de UI", "Connections": "Conexiones", - "NoMinimumForAnyRuntime": "Sin mínimo para el tiempo de ejecución", "Quality": "Calidad", "AuthenticationMethodHelpText": "Requerir nombre de usuario y contraseña para acceder {appName}", "AutoRedownloadFailedHelpText": "Buscar e intentar descargar automáticamente una versión diferente", @@ -12,8 +11,8 @@ "Backups": "Copias de seguridad", "BindAddress": "Dirección de Ligado", "BindAddressHelpText": "Dirección IP4 válida, localhost o '*' para todas las interfaces", - "Blocklist": "Bloqueadas", - "BlocklistRelease": "Lista de lanzamientos bloqueados", + "Blocklist": "Lista de bloqueos", + "BlocklistRelease": "Lista de bloqueos de lanzamiento", "Branch": "Rama", "BypassProxyForLocalAddresses": "Omitir Proxy para Direcciones Locales", "CalendarWeekColumnHeaderHelpText": "Mostrado sobre cada columna cuando la vista activa es semana", @@ -22,18 +21,18 @@ "ChmodFolderHelpTextWarning": "Esto solo funciona si el usuario que ejecuta {appName} es el propietario del archivo. Es mejor asegurarse de que el cliente de descarga establezca los permisos correctamente.", "ChownGroupHelpTextWarning": "Esto solo funciona si el usuario que ejecuta {appName} es el propietario del archivo. Es mejor asegurarse de que el cliente de descarga use el mismo grupo que {appName}.", "ConnectSettings": "Conectar Ajustes", - "CopyUsingHardlinksHelpTextWarning": "Ocasionalmente, los archivos bloqueados impiden renombrar los archivos que siguen seedeando. Puedes desactivar el seedeo temporalmete y usar la función de renombrado de Radarr como alternativa.", + "CopyUsingHardlinksHelpTextWarning": "Ocasionalmente, los archivos bloqueados impiden renombrar los archivos que están siendo sembrados. Puedes desactivar temporalmente la siembra y usar la función de renombrado de {appName} como alternativa.", "CutoffHelpText": "Una vez que se alcanze esta calidad, {appName} no descargará películas", - "CutoffUnmet": "Corte No Alcanzado", + "CutoffUnmet": "Umbrales no alcanzados", "DeleteBackupMessageText": "Seguro que quieres eliminar la copia de seguridad '{name}'?", - "DeleteDelayProfile": "Borrar Perfil de Retraso", - "DeleteDelayProfileMessageText": "Está seguro que quieres borrar este perfil de retraso?", - "DeleteDownloadClient": "Borrar Gestor de Descargas", - "DeleteTagMessageText": "¿Seguro que quieres eliminar la etiqueta '{label}'?", - "DestinationPath": "Ruta de Destino", + "DeleteDelayProfile": "Eliminar Perfil de Retardo", + "DeleteDelayProfileMessageText": "¿Está seguro de que desea borrar este perfil de retraso?", + "DeleteDownloadClient": "Borrar cliente de descarga", + "DeleteTagMessageText": "¿Está seguro de querer eliminar la etiqueta '{label}'?", + "DestinationPath": "Ruta de destino", "DetailedProgressBar": "Barra de Progreso Detallada", "DetailedProgressBarHelpText": "Mostrar texto en la barra de progreso", - "DownloadClient": "Gestor de Descargas", + "DownloadClient": "Cliente de descarga", "DownloadFailedCheckDownloadClientForMoreDetails": "Error de descarga: consulte el gestor de descargas para obtener más detalles", "DownloadPropersAndRepacksHelpTexts1": "Decidir si automaticamente actualizar a Propers/Repacks", "DownloadWarningCheckDownloadClientForMoreDetails": "Advertencia de descarga: consulte el gestor de descargas para obtener más detalles", @@ -41,11 +40,10 @@ "EnableSslHelpText": " Requiere reiniciar la aplicación como administrador para que surta efecto", "ErrorLoadingPreviews": "Error al cargar las previsualizaciones", "Exception": "Excepción", - "ExtraFileExtensionsHelpTexts1": "Separar con cons la lista de los archivos extra a importar (.nfo será impotado como .nfo-orig)", "FileDateHelpText": "Cambiar la fecha del archivo al importar/rescan", - "FileManagement": "Administración de Archivos", - "Filename": "Nombre del archivo", - "FileNames": "Nombres de Archivos", + "FileManagement": "Gestión de archivos", + "Filename": "Nombre de archivo", + "FileNames": "Nombres de archivos", "Files": "Archivos", "ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Para más información individual de los gestores de descarga, haz clic en los botones de información.", "ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "Para más información individual sobre las listas de importación, haz clic en los botones de información.", @@ -53,7 +51,6 @@ "IllRestartLater": "Lo reiniciaré más tarde", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} soporta cualquier indexer que utilice el estandar Newznab, como también cualquiera de los indexers listados debajo.", "LidarrTags": "Etiquetas de {appName}", - "LoadingTrackFilesFailed": "La carga de los archivos ha fallado", "Local": "Local", "LocalPath": "Ruta local", "LocalPathHelpText": "La ruta que {appName} tiene que usar para acceder a la ruta remota localmente", @@ -62,7 +59,7 @@ "LogLevel": "Nivel de Registro", "LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "El registro de seguimiento se ha de habilitar solo temporalmente", "LongDateFormat": "Formato Largo de Fecha", - "MaintenanceRelease": "Lanzamiento de mantenimiento", + "MaintenanceRelease": "Lanzamiento de mantenimiento: Corrección de errores y otras mejoras. Ver historial de commits de Github para mas detalle", "ManualImport": "Importar Manualmente", "MarkAsFailed": "Marcar como Fallida", "MarkAsFailedMessageText": "Seguro que quieres marcar '{0}' como fallida?", @@ -76,14 +73,11 @@ "MinimumFreeSpace": "Espacio Libre Mínimo", "MinimumFreeSpaceWhenImportingHelpText": "Evitar importación si dejase menos de esta cantidad en disco disponible", "MinimumLimits": "Límites Mínimos", - "Missing": "Falta", + "Missing": "Faltantes", "MustNotContain": "No Debe Contener", "NoHistory": "Sin historia", "NoLeaveIt": "No, Déjalo", - "NoLimitForAnyRuntime": "SIn límite para el tiempo de ejecución", "NoLogFiles": "Sin archivos de registro", - "OnRenameHelpText": "En Renombrado", - "OnUpgradeHelpText": "Al Actualizar", "OpenBrowserOnStart": "Abrir navegador al arrancar", "Options": "Opciones", "Original": "Original", @@ -96,7 +90,6 @@ "Port": "Puerto", "PosterSize": "Tamaño del Poster", "PreviewRename": "Previsualizar Renombrado", - "PriorityHelpText": "Prioridad del Indexer de 1 (La más alta) a 50 (La más baja). Por defecto: 25.", "Profiles": "Perfiles", "Proper": "Apropiado", "PropersAndRepacks": "Propers y Repacks", @@ -318,85 +311,84 @@ "ClickToChangeQuality": "Clic para cambiar la calidad", "Columns": "Columnas", "Component": "Componente", - "CopyUsingHardlinksHelpText": "Usar Hardlinks al intentar copiar ficheros de los torrents que siguen seedeando", + "CopyUsingHardlinksHelpText": "Usar Hardlinks para importar torrents a la carpeta del artista sin ocupar espacio extra en disco ni copiar todo el contenido del archivo. Los enlaces duros sólo funcionarán si el origen y el destino están en el mismo volumen.", "CreateEmptyArtistFolders": "Crear carpetas de películas vacías", "CreateEmptyArtistFoldersHelpText": "Crear carpetas de películas que faltan durante la exploración del disco", "CreateGroup": "Crear grupo", - "DBMigration": "Migración de DB", - "DelayProfile": "Perfil de Retraso", - "DelayProfiles": "Perfiles De Retraso", - "Delete": "Borrar", - "DeleteBackup": "Borrar Backup", - "DeleteDownloadClientMessageText": "¿Seguro que quieres eliminar el cliente de descargas '{name}'?", + "DatabaseMigration": "Migración de la base de datos", + "DelayProfile": "Perfil de retardo", + "DelayProfiles": "Perfiles de retardo", + "Delete": "Eliminar", + "DeleteBackup": "Eliminar copia de seguridad", + "DeleteDownloadClientMessageText": "Seguro que quieres eliminar el gestor de descargas '{name}'?", "DeleteEmptyFolders": "Borrar carpetas vacías", - "DeleteImportListExclusion": "Borrar exclusión de lista de importación", - "DeleteImportListExclusionMessageText": "Estás seguro de que quieres borrar esta exclusión de lista de importación?", + "DeleteImportListExclusion": "Eliminar exclusión de listas de importación", + "DeleteImportListExclusionMessageText": "¿Está seguro de que desea eliminar esta exclusión de la lista de importación?", "DeleteImportListMessageText": "Seguro que quieres eliminar la lista '{name}'?", "DeleteIndexer": "Borrar Indexer", "DeleteIndexerMessageText": "Seguro que quieres eliminar el indexer '{name}'?", "DeleteMetadataProfileMessageText": "¿Seguro que quieres eliminar el perfil de metadatos '{name}'?", - "DeleteNotification": "Borrar Notificación", - "DeleteNotificationMessageText": "¿Seguro que quieres eliminiar la notificación '{name}'?", - "DeleteQualityProfile": "Borrar Perfil de Calidad", + "DeleteNotification": "Borrar Notificacion", + "DeleteNotificationMessageText": "¿Seguro que quieres eliminar la notificación '{name}'?", + "DeleteQualityProfile": "Borrar perfil de calidad", "DeleteQualityProfileMessageText": "¿Seguro que quieres eliminar el perfil de calidad {name}?", - "DeleteReleaseProfile": "Borrar Perfil de Retraso", + "DeleteReleaseProfile": "Borrar perfil de estreno", "DeleteReleaseProfileMessageText": "Está seguro que quieres borrar este perfil de retraso?", "DeleteRootFolderMessageText": "¿Está seguro de querer eliminar la carpeta raíz '{0}'?", "DeleteSelectedTrackFiles": "Borrar Archivos Seleccionados", "DeleteSelectedTrackFilesMessageText": "Seguro que quieres eliminar el archivo de la película seleccionada?", - "DeleteTag": "Borrar Etiqueta", + "DeleteTag": "Eliminar Etiqueta", "DiskSpace": "Espacio en Disco", - "DownloadClients": "Gestores de Descargas", - "DownloadClientSettings": "Ajustes de Gestor de Descargas", + "DownloadClients": "Clientes de descarga", + "DownloadClientSettings": "Opciones del cliente de descarga", "DownloadFailedInterp": "Descarga fallida: {0}", "Downloading": "Descargando", "Edit": "Editar", "Enable": "Habilitar", - "EnableAutomaticAdd": "Habilitar Añadido Automático", + "EnableAutomaticAdd": "Habilitar añadido automático", "EnableAutomaticSearch": "Habilitar Búsqueda Automática", - "EnableColorImpairedMode": "Activar Modo De Color Degradado", + "EnableColorImpairedMode": "Habilitar Modo de dificultad con los colores", "EnableColorImpairedModeHelpText": "Estilo modificado para permitir que usuarios con problemas de color distingan mejor la información codificada por colores", "EnableCompletedDownloadHandlingHelpText": "Importar automáticamente las descargas completas del gestor de descargas", "EnableHelpText": "Habilitar la creación de un fichero de metadatos para este tipo de metadato", "EnableRSS": "Habilitar RSS", "EnableSSL": "Habilitar SSL", - "Ended": "Terminó", - "ErrorLoadingContents": "Error al cargar los contenidos", - "FirstDayOfWeek": "Primer Día de la Semana", + "Ended": "Finalizado", + "ErrorLoadingContents": "Error cargando contenidos", + "FirstDayOfWeek": "Primer día de la semana", "Fixed": "Arreglado", "Folder": "Carpeta", "Folders": "Carpetas", "ForMoreInformationOnTheIndividualIndexersClickOnTheInfoButtons": "Para más información individual sobre los indexers, haz clic en los botones de información.", - "GeneralSettings": "Ajustes Generales", + "GeneralSettings": "Opciones generales", "Global": "Global", "GoToInterp": "Ir a {0}", "Grab": "Capturar", - "GrabRelease": "Capturar Estreno", + "GrabRelease": "Capturar lanzamiento", "GrabReleaseMessageText": "{appName} no pudo determinar para qué película es este lanzamiento. {appName} no podrá importar este lanzamiento automáticamente. Quieres descargar {0}?", - "GrabSelected": "Capturar Seleccionados", + "GrabSelected": "Capturar seleccionado", "Group": "Grupo", "HasPendingChangesNoChanges": "Sin Cambios", "HasPendingChangesSaveChanges": "Guardar Cambios", "History": "Historial", "Host": "Host", "HostHelpText": "El mismo host especificado para el Gestor de Descargas remoto", - "Hostname": "Nombre del Host", - "ICalFeed": "iCal Feed", + "Hostname": "Nombre de host", + "ICalFeed": "Feed de iCal", "ICalHttpUrlHelpText": "Copia esta URL a tu gestor(es) o haz click en subscribir si tu navegador soporta webcal", - "ICalLink": "iCal Link", - "IconForCutoffUnmet": "Icono de Corte no alcanzado", - "IgnoredAddresses": "Direcciones Ignoradas", + "ICalLink": "Enlace de iCal", + "IconForCutoffUnmet": "Icono para Umbrales no alcanzados", + "IgnoredAddresses": "Ignorar direcciones", "IgnoredPlaceHolder": "Añadir nueva restricción", - "ImportedTo": "Importado a", - "ImportExtraFiles": "Importar Archivos Extra", + "ImportedTo": "Importar a", + "ImportExtraFiles": "Importar archivos adicionales", "ImportExtraFilesHelpText": "Importar archivos extra (subtítulos, info, etc) después de importar una película", "ImportFailedInterp": "Importación fallida: {0}", "Importing": "Importando", - "IncludeHealthWarningsHelpText": "Incluir Alertas de Salud", "IncludeUnknownArtistItemsHelpText": "Mostrar items sin ninguna película en la cola, esto incluye películas renombradas o cualquier otra cosa en la categoría de {appName}", - "IncludeUnmonitored": "Icluir No Monitoreados", + "IncludeUnmonitored": "Incluir sin monitorizar", "Indexer": "Indexador", - "IndexerPriority": "Prioridad del Indexer", + "IndexerPriority": "Prioridad del indexador", "Indexers": "Indexadores", "IndexerSettings": "Ajustes de Indexer", "InteractiveSearch": "Búsqueda Interactiva", @@ -424,8 +416,6 @@ "None": "Ninguna", "NotificationTriggers": "Desencadenantes de Notificaciones", "NoUpdatesAreAvailable": "No hay actualizaciones disponibles", - "OnGrabHelpText": "Al Capturar", - "OnHealthIssueHelpText": "En Problema de Salud", "PortNumber": "Número de Puerto", "Reason": "Razón", "RecycleBinCleanupDaysHelpText": "Ajustar a 0 para desactivar la limpieza automática", @@ -453,7 +443,7 @@ "Automatic": "Automático", "DelayingDownloadUntilInterp": "Retrasar descarga hasta {0} en {1}", "Docker": "Docker", - "AddMissing": "Añadir los que faltan", + "AddMissing": "Añadir faltantes", "AddNewItem": "Añadir nuevo item", "AllExpandedCollapseAll": "Cerrar todo", "AllExpandedExpandAll": "Expandir todo", @@ -461,7 +451,6 @@ "RemoveDownloadsAlert": "Los ajustes de eliminación se han trasladado a los ajustes individuales del cliente de descarga en la tabla anterior.", "Duration": "Duración", "OnApplicationUpdate": "Al actualizar la aplicación", - "OnApplicationUpdateHelpText": "Al actualizar la aplicación", "RemoveCompleted": "Eliminación completada", "AllowFingerprinting": "Permitir impresión digital", "OnRename": "En Renombrado", @@ -503,25 +492,25 @@ "Donations": "Donaciones", "DoNotPrefer": "No prefiero", "DoNotUpgradeAutomatically": "No actualizar automáticamente", - "DownloadFailed": "La descarga ha fallado", - "EditImportListExclusion": "Borrar exclusión de lista de importación", + "DownloadFailed": "La descarga falló", + "EditImportListExclusion": "Editar exclusión de lista de importación", "EditQualityProfile": "Editar perfil de calidad", - "EditRemotePathMapping": "Editar Mapping de Ruta Remota", + "EditRemotePathMapping": "Editar mapeo de ruta remota", "EditRootFolder": "Añadir Carpeta Raíz", "Error": "Error", - "ErrorRestoringBackup": "Error al restaurar la copia de seguridad", + "ErrorRestoringBackup": "Error restaurando la copia de seguridad", "Events": "Eventos", - "EventType": "Tipo de Evento", + "EventType": "Tipo de evento", "Filters": "Filtros", - "FreeSpace": "Espacio Libre", + "FreeSpace": "Espacio libre", "General": "General", "Genres": "Géneros", "Grabbed": "Añadido", - "HardlinkCopyFiles": "Hardlink/Copia de Archivos", - "HideAdvanced": "Ocultar Avanzado", + "HardlinkCopyFiles": "Enlace permanente/Copiar archivos", + "HideAdvanced": "Ocultar avanzado", "Ignored": "Ignorado", "Import": "Importar", - "IndexerDownloadClientHelpText": "Especifica qué cliente de descargas se utiliza para las descargas de este indexador", + "IndexerDownloadClientHelpText": "Especifica qué cliente de descarga es usado para capturas desde este indexador", "IndexerTagHelpText": "Solo utilizar este indexador para películas que coincidan con al menos una etiqueta. Déjelo en blanco para utilizarlo con todas las películas.", "InstanceName": "Nombre de Instancia", "InstanceNameHelpText": "Nombre de instancia en pestaña y para nombre de aplicación en Syslog", @@ -589,9 +578,9 @@ "AddConnection": "Añadir Conexión", "AddImportListExclusion": "Añadir Exclusión de Lista de Importación", "EditMetadataProfile": "perfil de metadatos", - "ImportListExclusions": "Borrar exclusión de lista de importación", + "ImportListExclusions": "Importar lista de exclusiones", "EditGroups": "Editar grupos", - "Database": "Base de Datos", + "Database": "Base de datos", "QualitiesHelpText": "Las calidades situadas mas arriba en la lista son las preferidas aunque no estén marcadas. Las calidades del mismo grupo son iguales. Sólo se buscarán las calidades marcadas", "DoneEditingGroups": "Terminado de editar grupos", "ChooseImportMethod": "Elegir Modo de Importación", @@ -607,15 +596,15 @@ "CustomFormat": "Formatos Personalizados", "CustomFormatRequiredHelpText": "Esta condición {0} ha de igualar al formato propio para aplicarse. Si no, una sóla {1} es suficiente.", "CustomFormatSettings": "Ajustes de Formatos Propios", - "CustomFormats": "Formatos Personalizados", + "CustomFormats": "Formatos personalizados", "Customformat": "Formatos Personalizados", "CutoffFormatScoreHelpText": "Una vez alcanzada esta puntuación del formato propio {appName} dejará de descargar películas", - "DeleteCustomFormat": "Borrar Formato Personalizado", + "DeleteCustomFormat": "Eliminar Formato Personalizado", "DeleteCustomFormatMessageText": "Seguro que quieres eliminar el indexer '{name}'?", "DeleteFormatMessageText": "¿Está seguro de que desea eliminar la etiqueta de formato {0}?", - "DownloadPropersAndRepacksHelpTextWarning": "Usar palabras preferidas para actualizaciones automáticas a propers/repacks", + "DownloadPropersAndRepacksHelpTextWarning": "Usar formatos personalizados para actualizaciones automáticas a propers/repacks", "DownloadedUnableToImportCheckLogsForDetails": "Descargado: no se puede importar: verifique los registros para obtener detalles", - "ExportCustomFormat": "Exportar Formato Personalizado", + "ExportCustomFormat": "Exportar formato personalizado", "FailedDownloadHandling": "Manipulación de Descargas Fallidas", "FailedLoadingSearchResults": "Error al cargar los resultados de la busqueda, prueba otra vez.", "Formats": "Formatos", @@ -634,8 +623,8 @@ "PreferTorrent": "Prefiero Torrent", "PreferUsenet": "Prefiero Usenet", "UnableToLoadInteractiveSearch": "No se pueden cargar los resultados de esta búsqueda de películas. Vuelve a intentarlo más tarde", - "EnableRssHelpText": "Se utilizará cuando {appName} busque periódicamente publicaciones a través de RSS Sync", - "HiddenClickToShow": "Oculto, clic para mostrar", + "EnableRssHelpText": "Se usará cuando {appName} busque periódicamente lanzamientos vía Sincronización RSS", + "HiddenClickToShow": "Oculto, click para mostrar", "Disabled": "Deshabilitado", "DownloadClientCheckDownloadingToRoot": "El cliente de descargas {0} coloca las descargas en la carpeta raíz {1}. No debe descargar a una carpeta raíz.", "DownloadClientStatusCheckAllClientMessage": "Los gestores de descargas no están disponibles debido a errores", @@ -686,17 +675,17 @@ "RemotePathMappingCheckLocalWrongOSPath": "El cliente de descarga local {0} coloca las descargas en {1} pero ésta no es una ruta válida {2}. Revise la configuración de su cliente de descarga.", "RemotePathMappingCheckWrongOSPath": "El cliente de descarga remota {0} coloca las descargas en {1} pero esta no es una ruta válida {2}. Revise los mapeos de las rutas remotas y la configuración del cliente de descarga.", "UpdateCheckUINotWritableMessage": "No se puede instalar la actualización porque la carpeta UI '{0}' no tiene permisos de escritura para el usuario '{1}'.", - "DeleteRemotePathMapping": "Editar Mapeo de Ruta Remota", + "DeleteRemotePathMapping": "Borrar mapeo de ruta remota", "BlocklistReleaseHelpText": "Evita que {appName} vuelva a capturar esta película automáticamente", "FailedToLoadQueue": "No se pudo cargar la cola", - "BlocklistReleases": "Lista de lanzamientos bloqueados", + "BlocklistReleases": "Lista de bloqueos de lanzamientos", "DeleteConditionMessageText": "Seguro que quieres eliminar la etiqueta '{0}'?", "Negated": "Negado", "Required": "Necesario", "ResetQualityDefinitions": "Restablecer definiciones de calidad", "DownloadClientSortingCheckMessage": "El cliente de descarga {0} tiene activada la clasificación {1} para la categoría de {appName}. Debe desactivar la clasificación en su cliente de descarga para evitar problemas de importación.", "DeleteSelectedDownloadClients": "Borrar Gestor de Descargas", - "DeleteSelectedIndexers": "Borrar Indexer", + "DeleteSelectedIndexers": "Borrar indexer(s)", "No": "No", "NoChange": "Sin Cambio", "QueueIsEmpty": "La cola está vacía", @@ -712,17 +701,16 @@ "RemoveSelectedItemQueueMessageText": "¿Está seguro de que desea eliminar el {0} elemento {1} de la cola?", "RemoveSelectedItemsQueueMessageText": "¿Estás seguro de que quieres eliminar {0} elementos de la cola?", "DownloadClientTagHelpText": "Solo utilizar este indexador para películas que coincidan con al menos una etiqueta. Déjelo en blanco para utilizarlo con todas las películas.", - "ExistingTag": "Etiqueta existente", + "ExistingTag": "Etiquetas existentes", "RemoveSelectedItem": "Eliminar el elemento seleccionado", "RemovingTag": "Eliminando etiqueta", "ResetQualityDefinitionsMessageText": "¿Está seguro de que desea restablecer las definiciones de calidad?", - "RemoveFromDownloadClientHelpTextWarning": "Eliminar borrará la descarga y el/los fichero(s) del gestor de descargas.", "ApplyTagsHelpTextHowToApplyArtists": "Cómo añadir etiquetas a las películas seleccionadas", "ApplyTagsHelpTextHowToApplyImportLists": "Cómo añadir etiquetas a las listas de importación seleccionadas", "ApplyTagsHelpTextHowToApplyIndexers": "Cómo añadir etiquetas a los indexadores seleccionados", - "DeleteSelectedDownloadClientsMessageText": "¿Estas seguro que quieres eliminar {count} cliente(s) de descarga seleccionado(s)?", + "DeleteSelectedDownloadClientsMessageText": "¿Está seguro de querer eliminar {count} cliente(s) de descarga seleccionado(s)?", "DeleteSelectedImportListsMessageText": "Seguro que quieres eliminar {count} lista(s) de importación seleccionada(s)?", - "DeleteSelectedIndexersMessageText": "Seguro que quieres eliminar {count} indexer seleccionado(s)?", + "DeleteSelectedIndexersMessageText": "¿Está seguro de querer eliminar {count} indexador(es) seleccionado(s)?", "ApplyTagsHelpTextHowToApplyDownloadClients": "Cómo añadir etiquetas a los clientes de descargas seleccionados", "SuggestTranslationChange": "Sugerir un cambio en la traducción", "UpdateSelected": "Actualizar Seleccionadas", @@ -768,7 +756,7 @@ "AllowFingerprintingHelpText": "Utilizar la huella digital para mejorar la precisión de la coincidencia de libros", "AllowFingerprintingHelpTextWarning": "Esto requiere que Readarr lea partes del archivo, lo que ralentizará los escaneos y puede provocar una alta actividad en el disco o en la red.", "ReleaseProfiles": "perfil de lanzamiento", - "AnyReleaseOkHelpText": "Readarr cambiará automáticamente a la edición que mejor coincida con los archivos descargados", + "AnyReleaseOkHelpText": "Readarrcambiará automáticamente a la versión que mejor coincida con las pistas descargadas", "CatalogNumber": "número de catálogo", "WhatsNew": "Que es lo nuevo?", "Discography": "discografía", @@ -779,7 +767,7 @@ "ArtistFolderFormat": "Formato de Carpeta de Autor", "BackupIntervalHelpText": "Intervalo para respaldar la base de datos y configuraciones de Readarr", "CloneCondition": "Clonar Condición", - "EditConnectionImplementation": "Agregar Condición - { implementationName}", + "EditConnectionImplementation": "Editar conexión - {implementationName}", "Enabled": "Habilitado", "Loading": "Cargando", "Priority": "Prioridad", @@ -789,22 +777,22 @@ "AutomaticUpdatesDisabledDocker": "Las actualizaciones automáticas no son compatibles directamente al usar el mecanismo de actualización de Docker. Deberás actualizar la imagen del contenedor fuera de {appName} o utilizar un script", "NotificationStatusAllClientHealthCheckMessage": "Las listas no están disponibles debido a errores", "TrackFileCounttotalTrackCountTracksDownloadedInterp": "{0}/{1} libros descargados", - "AddConnectionImplementation": "Agregar Condición - { implementationName}", + "AddConnectionImplementation": "Añadir Conexión - {implementationName}", "AddImportList": "Añadir Lista de Importación", "AddIndexerImplementation": "Añadir Indexador - {implementationName}", "Album": "álbum", "Albums": "álbum", - "EditConditionImplementation": "Agregar Condición - { implementationName}", - "EditReleaseProfile": "Añadir Perfil de Lanzamiento", + "EditConditionImplementation": "Editar Condición - {implementationName}", + "EditReleaseProfile": "Editar perfil de lanzamiento", "Absolute": "Absoluto", "AddNewArtistRootFolderHelpText": "La subcarpeta '{folder}' será creada automáticamente", "AddConditionImplementation": "Agregar Condición - { implementationName}", - "EditIndexerImplementation": "Agregar Condición - { implementationName}", + "EditIndexerImplementation": "Editar indexador - {implementationName}", "AddImportListImplementation": "Añadir lista de importación - {implementationName}", "DisabledForLocalAddresses": "Desactivado para direcciones locales", "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirma la nueva contraseña", - "ClearBlocklist": "Limpiar lista de bloqueadas", - "NoHistoryBlocklist": "Sin lista de bloqueo de historial", + "ClearBlocklist": "Limpiar lista de bloqueos", + "NoHistoryBlocklist": "Sin historial de la lista de bloqueos", "Connection": "Conexiones", "AutoTaggingNegateHelpText": "Si está marcado, la regla de etiquetado automático no aplicará si la condición {implementationName} coincide.", "AutoTaggingRequiredHelpText": "Esta condición {implementationName} debe coincidir para que la regla de etiquetado automático se aplique. De lo contrario una sola coincidencia de {0} será suficiente.", @@ -814,7 +802,7 @@ "CloneIndexer": "Clonar Indexer", "CompletedDownloadHandling": "Manipulación de descargas completas", "ColonReplacement": "Reemplazar dos puntos", - "ClearBlocklistMessageText": "¿Estás seguro de que quieres borrar todos los elementos de la lista de bloqueo?", + "ClearBlocklistMessageText": "¿Estás seguro de que quieres borrar todos los elementos de la lista de bloqueos?", "ClientPriority": "Prioridad del Cliente", "AuthenticationRequiredHelpText": "Cambiar para que las solicitudes requieran autenticación. No lo cambie a menos que entienda los riesgos.", "MinimumCustomFormatScoreHelpText": "Puntuación mínima de formato personalizado necesaria para evitar el retraso del protocolo preferido", @@ -843,12 +831,12 @@ "AuthenticationRequiredWarning": "Para evitar el acceso remoto sin autenticación, {appName} ahora requiere que la autenticación esté habilitada. Opcionalmente puede desactivar la autenticación desde una dirección local.", "Auto": "Auto", "AutoTagging": "Etiquetado Automático", - "DeleteSpecification": "Borrar Notificación", + "DeleteSpecification": "Borrar especificacion", "EditAutoTag": "Editar Etiquetado Automático", "EditDownloadClientImplementation": "Añadir Cliente de Descarga - {implementationName}", "EditImportListImplementation": "Añadir lista de importación - {implementationName}", "GrabId": "Capturar ID", - "ImportList": "lista de importación", + "ImportList": "Importar lista", "Negate": "Negar", "OrganizeSelectedArtists": "Organizar películas seleccionadas", "RenameFiles": "Renombrar Archivos", @@ -866,7 +854,105 @@ "BypassIfAboveCustomFormatScoreHelpText": "Habilitar ignorar cuando la versión tenga una puntuación superior a la puntuación mínima configurada para el formato personalizado", "BypassIfHighestQualityHelpText": "Evitar el retardo cuando el lanzamiento tiene habilitada la máxima calidad en el perfil de calidad con el protocolo preferido", "CloneAutoTag": "Clonar Etiquetado Automático", - "ConditionUsingRegularExpressions": "Esta condición coincide con el uso de Expresiones Regulares. Tenga en cuenta que los caracteres {0} tienen significados especiales y necesitan escapar con un {1}", - "DeleteSpecificationHelpText": "¿Seguro que quieres eliminiar la notificación '{name}'?", - "PosterOptions": "Opciones del Poster" + "ConditionUsingRegularExpressions": "Esta condición coincide con el uso de expresiones regulares. Tenga en cuenta que los caracteres `\\^$.|?*+()[{` tienen significados especiales y deben escaparse con un `\\`", + "DeleteSpecificationHelpText": "Esta seguro que desea borrar la especificacion '{name}'?", + "PosterOptions": "Opciones del Poster", + "EnableProfile": "Habilitar perfil", + "AddNewAlbum": "Añadir nuevo álbum", + "AddAlbumWithTitle": "Añadir {albumTitle}", + "AddArtistWithName": "Añadir {artistName}", + "Continuing": "Continua", + "ContinuingOnly": "Solo continuando", + "DownloadClientQbittorrentSettingsContentLayout": "Diseño del contenido", + "InfoUrl": "Información de la URL", + "InvalidUILanguage": "Su interfaz de usuario está configurada en un idioma no válido, corríjalo y guarde la configuración", + "HealthMessagesInfoBox": "Puede encontrar más información sobre la causa de estos mensajes de comprobación de salud haciendo clic en el enlace wiki (icono de libro) al final de la fila, o comprobando sus [logs]({link}). Si tienes dificultades para interpretar estos mensajes, puedes ponerte en contacto con nuestro servicio de asistencia en los enlaces que aparecen a continuación.", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Si usar el diseño de contenido configurado de qBittorrent, el diseño original del torrent o siempre crear una subcarpeta (qBittorrent 4.3.2+)", + "ChownGroup": "Cambiar grupo propietario", + "NoLimitForAnyDuration": "SIn límite para el tiempo de ejecución", + "NoMinimumForAnyDuration": "Sin mínimo para el tiempo de ejecución", + "PreferredSize": "Tamaño Preferido", + "ImportLists": "Importar listas", + "Unlimited": "Ilimitado", + "AddImportListExclusionAlbumHelpText": "Evitar que las series sean agregadas a {appName} por las listas", + "StatusEndedContinuing": "Continua", + "NoCutoffUnmetItems": "Sin objetos sin condiciones de corte incumplidas", + "ExtraFileExtensionsHelpText": "Lista de archivos adicionales separados por coma para importar (.nfo será importado como .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Ejemplos: '.sub, .nfo' o 'sub,nfo'", + "TBA": "Por determinar", + "DeleteArtistFoldersHelpText": "Eliminar la carpeta de películas y su contenido", + "DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "El cliente de descarga {downloadClientName} esta configurado para eliminar las descargas completadas. Esto puede causar que las descargas sean eliminadas del cliente antes que {1} las pueda importar.", + "DownloadClientAriaSettingsDirectoryHelpText": "Ubicación opcional en la que poner las descargas, dejar en blanco para usar la ubicación de Aria2 predeterminada", + "DownloadClientPriorityHelpText": "Prioridad del cliente de descarga desde 1 (la más alta) hasta 50 (la más baja). Predeterminada: 1. Se usa round-robin para clientes con la misma prioridad.", + "AutomaticallySwitchRelease": "Desbloqueo automático", + "AllMonitoringOptionHelpText": "Supervisar los artistas y todos los álbumes de cada artista incluido en la lista de importación", + "ArtistName": "Nombre del artista", + "CollapseMultipleAlbums": "Contraer varios álbumes", + "ContinuingNoAdditionalAlbumsAreExpected": "No se esperan álbumes adicionales", + "DefaultMonitorOptionHelpText": "Qué álbumes se deben supervisar en la adición inicial para los artistas detectados en esta carpeta", + "ArtistType": "Tipo de artista", + "ArtistMonitoring": "Seguimiento de artistas", + "DashOrSpaceDashDependingOnName": "Dash o Space Dash según el nombre", + "DefaultQualityProfileIdHelpText": "Perfil de calidad predeterminado para los artistas detectados en esta carpeta", + "AlbumTitle": "Título del álbum", + "AreYouSure": "¿Estás seguro?", + "ArtistClickToChangeAlbum": "Haz clic para cambiar de álbum", + "AlbumCount": "Recuento de álbumes", + "AlbumIsDownloading": "El álbum se está descargando", + "AlbumHasNotAired": "Álbum no emitido", + "AlbumReleaseDate": "Fecha de lanzamiento del álbum", + "AlbumStatus": "Estado del álbum", + "AlbumStudio": "Estudio del álbum", + "AlbumType": "Tipo de álbum", + "DateAdded": "Fecha de adición", + "DefaultMetadataProfileIdHelpText": "Perfil de metadatos predeterminado para los artistas detectados en esta carpeta", + "AnchorTooltip": "Este archivo ya está en su biblioteca para una versión que está importando actualmente", + "ArtistEditor": "Artista Editor", + "AlbumDetails": "Detalles del álbum", + "AlbumStudioTruncated": "Sólo se muestran los últimos 20 álbumes, vaya a detalles para ver todos los álbumes", + "AllAlbumsData": "Controlar todos los álbumes excepto los especiales", + "Banners": "Pancartas", + "BannerOptions": "Opciones de banner", + "CombineWithExistingFiles": "Combinar con archivos existentes", + "DeleteArtist": "Borrar artista seleccionado", + "AddNewArtist": "Añadir nuevo artista", + "AutoRedownloadFailedFromInteractiveSearchHelpText": "Búsqueda automática e intento de descarga de una versión diferente cuando se obtiene una versión fallida de la búsqueda interactiva", + "ContinuingAllTracksDownloaded": "Continúa (Todas las pistas descargadas)", + "ArtistIsMonitored": "Se supervisa al artista", + "ArtistIsUnmonitored": "El artista no está vigilado", + "AddNewAlbumSearchForNewAlbum": "Iniciar búsqueda de nuevo álbum", + "AlbumIsNotMonitored": "Álbum no Monitorizado", + "AlbumRelease": "Lanzamiento del álbum", + "AlbumStudioTracksDownloaded": "pistas descargadas", + "AllAlbums": "Todos los álbumes", + "AllArtistAlbums": "Todos los álbumes de artistas", + "ArtistsEditRootFolderHelpText": "Mover artistas a la misma carpeta raíz se puede utilizar para cambiar el nombre de las carpetas de artistas para que coincida con el nombre actualizado o el formato de nomenclatura", + "Country": "País", + "CollapseMultipleAlbumsHelpText": "Colapsar varios álbumes que salen el mismo día", + "AutoRedownloadFailed": "Descarga fallida", + "AutoRedownloadFailedFromInteractiveSearch": "Fallo al volver a descargar desde la búsqueda interactiva", + "ContinuingMoreAlbumsAreExpected": "Se esperan más álbumes", + "CountAlbums": "álbumes", + "CustomFormatsSpecificationRegularExpressionHelpText": "El formato personalizado RegEx no distingue mayúsculas de minúsculas", + "Deceased": "Fallecido", + "ErrorLoadingContent": "Hubo un error cargando este contenido", + "IndexerSettingsRejectBlocklistedTorrentHashes": "Rechazar hashes de torrents en la lista de bloqueos durante la captura", + "BlocklistAndSearch": "Lista de bloqueos y búsqueda", + "BlocklistAndSearchHint": "Inicia la búsqueda de un sustituto tras añadir a la lista de bloqueos", + "EndedOnly": "Solo finalizado", + "IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "Si un torrent es bloqueado por hash puede no ser adecuadamente rechazado durante RSS o búsqueda por algunos indexadores, habilitar esto permitirá que el torrent sea rechazado una vez sea capturado, pero antes es enviado al cliente.", + "ChangeCategoryMultipleHint": "Cambia las descargas a la 'categoría post-importación' desde el cliente de descarga", + "CustomFormatsSpecificationRegularExpression": "Expresión regular", + "DoNotBlocklist": "No añadir a la lista de bloqueos", + "DoNotBlocklistHint": "Eliminar sin añadir a la lista de bloqueos", + "ChangeCategory": "Cambiar categoría", + "ChangeCategoryHint": "Cambia la descarga a la 'categoría post-importación' desde el cliente de descarga", + "BlocklistOnlyHint": "Añadir a la lista de bloqueos sin buscar un sustituto", + "BlocklistMultipleOnlyHint": "Añadir a la lista de bloqueos sin buscar sustitutos", + "BlocklistOnly": "Solo añadir a la lista de bloqueos", + "BlocklistAndSearchMultipleHint": "Inicia búsquedas de sustitutos tras añadir a la lista de bloqueos", + "IgnoreDownloadHint": "Detiene {appName} de procesar esta descarga más adelante", + "IgnoreDownload": "Ignorar descarga", + "IgnoreDownloads": "Ignorar descargas", + "IgnoreDownloadsHint": "Detiene {appName} de procesar estas descargas más adelante" } diff --git a/src/NzbDrone.Core/Localization/Core/fi.json b/src/NzbDrone.Core/Localization/Core/fi.json index d9af52963..6caa20de2 100644 --- a/src/NzbDrone.Core/Localization/Core/fi.json +++ b/src/NzbDrone.Core/Localization/Core/fi.json @@ -2,29 +2,28 @@ "Language": "Kieli", "UILanguage": "Käyttöliittymän kieli", "ShowSearchActionHelpText": "Näytä hakupainike osoitettaessa.", - "DeleteImportListExclusion": "Poista poikkeussääntö", - "EnableColorImpairedModeHelpText": "Muokattu tyyli käyttäjille, joiden värinäkö on heikentynyt. Auttaa erottamaan värikoodatun tiedon.", + "DeleteImportListExclusion": "Poista tuontilistapoikkeus", + "EnableColorImpairedModeHelpText": "Vaihtoehtoinen tyyli, joka auttaa erottamaan värikoodatut tiedot paremmin.", "IndexerPriority": "Tietolähteiden painotus", - "ProxyPasswordHelpText": "Käyttäjätunnus ja salasana tulee syöttää vain tarvittaessa. Muussa tapauksessa jätä kentät tyhjiksi.", - "UpdateMechanismHelpText": "Käytä {appName}in sisäänrakennettua päivitystoimintoa tai omaa komentosarjaasi.", - "ProxyUsernameHelpText": "Käyttäjätunnus ja salasana tulee syöttää vain tarvittaessa. Muussa tapauksessa jätä kentät tyhjiksi.", - "MaintenanceRelease": "Huoltojulkaisu: Virhekorjauksia ja muita parannuksia. Lue lisää Githubin historiasta muutoshistoriasta.", + "ProxyPasswordHelpText": "Käyttäjätunnus ja salasana tulee täyttää vain tarvittaessa. Mikäli näitä ei ole, tulee kentät jättää tyhjiksi.", + "UpdateMechanismHelpText": "Käytä {appName}in sisäänrakennettua päivitystoimintoa tai komentosarjaa.", + "ProxyUsernameHelpText": "Käyttäjätunnus ja salasana tulee täyttää vain tarvittaessa. Mikäli näitä ei ole, tulee kentät jättää tyhjiksi.", + "MaintenanceRelease": "Huoltojulkaisu: korjauksia ja muita parannuksia. Lue lisää Githubin muutoshistoriasta.", "Username": "Käyttäjätunnus", "Host": "Osoite", - "NoLimitForAnyRuntime": "Ei toistoajan rajoitusta", "IllRestartLater": "Käynnistän uudelleen myöhemmin", "EnableRSS": "RSS-syöte", "SupportsRssvalueRSSIsNotSupportedWithThisIndexer": "RSS-syötettä ei ole käytettävissä tälle tietolähteelle", - "Logging": "Lokitietojen kirjaus", - "ProxyBypassFilterHelpText": "Käytä erottimena ',' ja '*.' jokerimerkkinä aliverkkotunnuksille (esim. www.esimerkki.fi,*.esimerkki.fi)", + "Logging": "Lokikirjaus", + "ProxyBypassFilterHelpText": "Erota aliverkkotunnukset pilkuilla ja käytä jokerimerkkinä tähteä ja pistettä (*.). Esimerkki: www.esimerkki.fi,*.esimerkki.fi).", "UnableToAddANewIndexerPleaseTryAgain": "Uuden tietolähteen lisäys epäonnistui. Yritä uudelleen.", "ForMoreInformationOnTheIndividualIndexersClickOnTheInfoButtons": "Lue lisää tietolähteestä painamalla 'Lisätietoja'.", - "ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Lataustyökalukohtaisia tietoja saat painamalla lisätietopainikkeita.", - "RssSyncIntervalHelpText": "Aikaväli minuutteina. Poista käytöstä asettamalla arvoksi '0' (tämä lopettaa julkaisujen automaattisen sieppauksen).", - "DefaultLidarrTags": "Oletustunnisteet", - "DefaultTagsHelpText": "Kansiosta löydetyille esittäjille oletusarvoisesti määritettävät tunnisteet.", + "ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Saat tietoja yksittäisistä lataustyökaluista painamalla niiden ohessa olevia lisätietopainikkeita.", + "RssSyncIntervalHelpText": "Aikaväli minuutteina. Arvo \"0\" (nolla) kytkee toiminnon pois käytöstä pysäyttäen automaattisen julkaisukaappauksen täysin.", + "DefaultLidarrTags": "Oletusarvoiset {appName}-oletustunnisteet", + "DefaultTagsHelpText": "Kansiosta löydetyille esittäjille oletusarvoisesti määritettävät {appName}-tunnisteet.", "IsTagUsedCannotBeDeletedWhileInUse": "Tunnistetta ei voi poistaa, koska se on käytössä", - "LidarrTags": "Tunnisteet", + "LidarrTags": "{appName}-tunnisteet", "RemoveTagRemovingTag": "Tunniste poistetaan", "ChmodFolderHelpText": "Octal, sovelletaan tuonnin/nimeämisen yhteydessä mediakansioihin ja -tiedostoihin (ilman suoritusbittejä).", "LaunchBrowserHelpText": " Avaa {appName}in verkkokäyttöliittymä verkkoselaimeen sovelluksen käynnistyksen yhteydessä.", @@ -33,207 +32,204 @@ "Refresh": "Päivitä", "ResetAPIKey": "Uudista API-avain", "Restart": "Käynnistä uudelleen", - "Scheduled": "Ajoitettu", + "Scheduled": "Ajoitukset", "SSLCertPath": "SSL-varmenteen sijainti", "UISettings": "Käyttöliittymän asetukset", "NoLeaveIt": "Ei, anna olla", "Torrents": "Torrentit", - "InteractiveSearch": "Vuorovaikutteinen haku", - "NoMinimumForAnyRuntime": "Ei toistoajan vähimmäiskestoa", - "BackupRetentionHelpText": "Säilytysjaksoa vanhemmat, automaattiset varmuuskopiot poistetaan automaattisesti.", - "ConnectSettings": "Kytkentöjen asetukset", - "DBMigration": "Tietokannan siirto", - "DeleteBackupMessageText": "Haluatko varmasti poistaa varmuuskopion '{0}'?", - "DeleteNotificationMessageText": "Haluatko varmasti poistaa kytkennän '{0}'?", + "InteractiveSearch": "Etsi manuaalisesti", + "BackupRetentionHelpText": "Säilytysjaksoa vanhemmat varmuuskopiot siivotaan automaattisesti.", + "ConnectSettings": "Kytkösasetukset", + "DatabaseMigration": "Tietokannan siirto", + "DeleteBackupMessageText": "Haluatko varmasti poistaa varmuuskopion \"{name}\"?", + "DeleteNotificationMessageText": "Haluatko varmasti poistaa ilmoituspalvelun \"{name}\"?", "EnableCompletedDownloadHandlingHelpText": "Tuo valmistuneet lataukset lataustyökalusta automaattisesti.", "Indexer": "Tietolähde", "UnableToAddANewDownloadClientPleaseTryAgain": "Uuden lataustyökalun lisäys epäonnistui. Yitä uudelleen.", - "GrabReleaseMessageText": "{appName} ei tunnistanut, mille esittäjälle ja albumille tämä julkaisu kuuluu, eikä julkaisun automaattinen tuonti onnistu. Haluatko siepata julkaisun '{0}'?", + "GrabReleaseMessageText": "{appName} ei tunnista mille esittäjälle ja albumille julkaisu kuuluu, eikä sen automaattinen tuonti onnistu. Haluatko kaapata julkaisun \"{0}\"?", "CalendarWeekColumnHeaderHelpText": "Näkyy jokaisen sarakkeen yläpuolella käytettäessä viikkonäkymää.", "ShownAboveEachColumnWhenWeekIsTheActiveView": "Näkyy jokaisen sarakkeen yläpuolella käytettäessä viikkonäkymää.", - "NotificationTriggers": "Laukaisijat", - "OnHealthIssueHelpText": "Kun havaitaan kuntoon liittyvä ongelma", - "PackageVersion": "Pakettiversio", + "NotificationTriggers": "Laukaisimet", + "PackageVersion": "Paketin versio", "Port": "Portti", "Indexers": "Tietolähteet", - "ChownGroupHelpTextWarning": "Tämä toimii vain, jos {appName}ia käyttävä käyttäjä on tiedoston omistaja. On parempi varmistaa, että lataustyökalu käyttää samaa ryhmää kuin {appName}.", - "CopyUsingHardlinksHelpText": "Käytä hardlink-kytköksiä, kun kopioit tiedostoja torrenteista, joita jaetaan vielä.", - "CopyUsingHardlinksHelpTextWarning": "Tiedostojen käytöstä johtuvat lukitukset saattavat joskus estää jaettavien tiedostojen uudelleennimeämisen. Voit lopettaa jaon väliaikaisesti ja käyttää {appName}in nimeämistoimintoa.", - "DeleteImportListMessageText": "Haluatko varmasti poistaa tuontilistan '{0}'?", - "DeleteIndexerMessageText": "Haluatko varmasti poistaa tietolähteen '{0}'?", - "DeleteTagMessageText": "Haluatko varmasti poistaa tunnisteen '{0}'?", + "ChownGroupHelpTextWarning": "Toimii vain, jos {appName}in suorittava käyttäjä on tiedoston omistaja. On parempi varmistaa, että lataustyökalu käyttää samaa ryhmää kuin {appName}.", + "CopyUsingHardlinksHelpText": "Hardlink-kytkösten avulla {appName} voi tuoda jaettavat torrentit ilman niiden täyttä kopiointia ja levytilan kaksinkertaista varausta. Tämä toimii vain lähde- ja kohdesijaintien ollessa samalla tallennusmedialla.", + "CopyUsingHardlinksHelpTextWarning": "Tiedostojen käsittelystä johtuvat lukitukset saattavat joskus estää jaettavien tiedostojen uudelleennimeämisen. Voit keskeyttää jakamisen väliaikaisesti ja käyttää {appName}in nimeämistoimintoa.", + "DeleteImportListMessageText": "Haluatko varmasti poistaa listan \"{name}\"?", + "DeleteIndexerMessageText": "Haluatko varmasti poistaa tietolähteen \"{0}\"?", + "DeleteTagMessageText": "Haluatko varmasti poistaa tunnisteen \"{label}\"?", "TagIsNotUsedAndCanBeDeleted": "Tunnistetta ei ole määritetty millekään kohteelle, joten sen voi poistaa.", "Security": "Suojaus", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} tukee Newznab- ja Torznab-yhteensopivien tietolähteiden ohella myös monia muita alla lueteltuja tietolähteitä.", "Actions": "Toiminnot", - "AddListExclusion": "Lisää tuontilistojen poikkeussääntö", - "ApiKeyHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", + "AddListExclusion": "Lisää listapoikkeus", + "ApiKeyHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", "APIKey": "API-avain", "AppDataDirectory": "AppData-kansio", - "Authentication": "Todennus", - "AuthenticationMethodHelpText": "Vaadi käyttäjätunnus ja salasana.", - "AutoRedownloadFailedHelpText": "Etsi ja yritä ladata toinen julkaisu automaattisesti", - "BackupFolderHelpText": "Suhteelliset polut kohdistuvat sovelluksen AppData-kansioon.", + "Authentication": "Tunnistautuminen", + "AuthenticationMethodHelpText": "Vaadi {appName}in käyttöön käyttäjätunnus ja salasana.", + "AutoRedownloadFailedHelpText": "Hae ja pyri laaamaan eri julkaisu automaattisesti.", + "BackupFolderHelpText": "Suhteelliset tiedostosijainnit ovat {appName}in AppData-kansiossa.", "BackupIntervalHelpText": "Tietokannan ja asetusten automaattisen varmuuskopioinnin ajoitus.", - "BindAddressHelpText": "Toimiva IP-osoite, localhost tai '*' (tähti) kaikille yhteyksille.", - "BindAddressHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", + "BindAddressHelpText": "Toimiva IP-osoite, localhost tai * (tähti) kaikille verkkoliitännöille.", + "BindAddressHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", "BackupNow": "Varmuuskopioi nyt", - "Backups": "Varmuuskopiointi", + "Backups": "Varmuuskopiot", "Blocklist": "Estolista", "BindAddress": "Sidososoite", "BypassProxyForLocalAddresses": "Ohjaa paikalliset osoitteet välityspalvelimen ohi", "Cancel": "Peruuta", - "Branch": "Kehityshaara", - "ClickToChangeQuality": "Vaihda laatua painamalla tästä", - "ChownGroupHelpText": "Ryhmän nimi tai GID. Käytä GID:ta etätietojärjestelmille.", - "ChmodFolderHelpTextWarning": "Tämä toimii vain, jos {appName}ia käyttävä käyttäjä on tiedoston omistaja. On parempi varmistaa, että lataustyökalu määrittää käyttöoikeudet oikein.", + "Branch": "Haara", + "ClickToChangeQuality": "Vaihda laatua klikkaamalla", + "ChownGroupHelpText": "Ryhmän nimi tai GID. Käytä GID:tä etätiedostojärjestelmille.", + "ChmodFolderHelpTextWarning": "Tämä toimii vain, jos käyttäjä suorittaa {appName}in tiedoston omistajana. Parempi vaihtoehto on varmistaa, että lataustyökalu asettaa oikeudet oikein.", "BlocklistRelease": "Lisää julkaisu estolistalle", "Columns": "Sarakkeet", "Calendar": "Kalenteri", - "CompletedDownloadHandling": "Latauksen käsittely on valmis", - "CloneIndexer": "Kloonaa tietolähde", + "CompletedDownloadHandling": "Valmistuneiden latausten käsittely", + "CloneIndexer": "Monista tietolähde", "CancelMessageText": "Haluatko varmasti perua tämän odottavan tehtävän?", "CertificateValidation": "Varmenteen vahvistus", - "CertificateValidationHelpText": "Muuta HTTPS-varmennevahvistuksen tarkkuutta. Älä muuta, jollet ymmärrä tähän liittyviä riskejä.", + "CertificateValidationHelpText": "Määritä HTTPS-varmennevahvistuksen tiukkuus. Älä muta, jos et ymmärrä riskejä.", "ClientPriority": "Lataustyökalun painotus", - "CloneProfile": "Kloonaa profiili", + "CloneProfile": "Monista profiili", "ChangeFileDate": "Muuta tiedoston päiväys", "ChangeHasNotBeenSavedYet": "Muutosta ei ole vielä tallennettu", "Component": "Komponentti", - "Connections": "Kytkennät", + "Connections": "Yhteydet", "CreateGroup": "Luo ryhmä", "CutoffHelpText": "Kun tämä laatu on saavutettu, {appName} ei enää lataa elokuvia", "DelayProfile": "Viiveprofiili", "Delete": "Poista", - "CutoffUnmet": "Katkaisua ei saavutettu", + "CutoffUnmet": "Katkaisutasoa ei savutettu", "Dates": "Päiväykset", "DelayProfiles": "Viiveprofiilit", "DeleteBackup": "Poista varmuuskopio", - "DeleteMetadataProfileMessageText": "Haluatko varmasti poistaa metatietoprofiilin '{0}'?", - "DeleteEmptyFoldersHelpText": "Poista tyhjät esittäjäkansiot levyn tarkistuksen yhteydessä ja kun kappaletiedostot poistetaan.", + "DeleteMetadataProfileMessageText": "Haluatko varmasti poistaa metatietoprofiilin \"{name}\"?", + "DeleteEmptyFoldersHelpText": "Poista tyhjät esittäjäkansiot kirjastotarkistuksen ja kappaletiedostojen poiston yhteydessä.", "DeleteDelayProfile": "Poista viiveprofiili", "DeleteDelayProfileMessageText": "Haluatko varmasti poistaa viiveprofiilin?", "DeleteEmptyFolders": "Poista tyhjät kansiot", - "DeleteImportListExclusionMessageText": "Haluatko varmasti poistaa poikkeussäännön?", + "DeleteImportListExclusionMessageText": "Haluatko varmasti poistaa tuontilistapoikkeuksen?", "DeleteFilesHelpText": "Poista kappaletiedostot ja esittäjäkansio", "DeleteImportList": "Poista tuontilista", "DeleteDownloadClient": "Poista lataustyökalu", - "DeleteDownloadClientMessageText": "Haluatko varmasti poistaa lataustyökalun '{0}'?", + "DeleteDownloadClientMessageText": "Haluatko varmasti poistaa lataustyökalun \"{name}\"?", "DeleteIndexer": "Poista tietolähde", - "DeleteNotification": "Poista kytkentä", + "DeleteNotification": "Poista ilmoitus", "DeleteQualityProfile": "Poista laatuprofiili", - "DeleteQualityProfileMessageText": "Haluatko varmasti poistaa laatuprofiilin '{0}'?", + "DeleteQualityProfileMessageText": "Haluatko varmasti poistaa laatuprofiilin \"{name}\"?", "DeleteReleaseProfile": "Poista julkaisuprofiili", - "DeleteRootFolderMessageText": "Haluatko varmasti poistaa pääkansion '{0}'?", - "DeleteReleaseProfileMessageText": "Haluatko varmasti poistaa julkaisuprofiilin?", + "DeleteRootFolderMessageText": "Haluatko varmasti poistaa juurikansion \"{name}\"?", + "DeleteReleaseProfileMessageText": "Haluatko varmasti poistaa tämän julkaisuprofiilin?", "DestinationPath": "Kohdesijainti", "Edit": "Muokkaa", "Docker": "Docker", - "DetailedProgressBar": "Yksityiskohtainen edistymispalkki", + "DetailedProgressBar": "Yksityiskohtainen tilapalkki", "DetailedProgressBarHelpText": "Näytä teksti edistymispalkissa.", "DownloadClient": "Lataustyökalu", "DownloadClients": "Lataustyökalut", - "DiskSpace": "Tallennustila", + "DiskSpace": "Levytila", "DownloadFailedCheckDownloadClientForMoreDetails": "Lataus epäonnistui: Katso tarkemmat tiedot lataustyökalusta", "DownloadFailedInterp": "Lataus epäonnistui: {0}", - "DownloadPropersAndRepacksHelpTexts1": "Määrittää päivitetäänkö tiedostot automaattisesti proper- ja repack-julkaisuihin (kunnollinen/uudelleenpaketoitu).", + "DownloadPropersAndRepacksHelpTexts1": "Määrittää päivitetäänkö tiedostot automaattisesti Proper- ja Repack-julkaisuihin (kunnollinen/uudelleenpaketoitu).", "DownloadWarningCheckDownloadClientForMoreDetails": "Latausvaroitus: Katso tarkempia tietoja lataustyökalusta", "DeleteTag": "Poista tunniste", "EnableColorImpairedMode": "Heikentyneen värinäön tila", - "EnableAutomaticSearch": "Automaattihaku", - "EnableInteractiveSearch": "Vuorovaikutteinen haku", - "EnableHelpText": "Luo tälle metatietotyypille metatietotiedostot.", + "EnableAutomaticSearch": "Käytä automaattihakua", + "EnableInteractiveSearch": "Käytä manuaalihakuun", + "EnableHelpText": "Luo metatietotiedostot tälle metatietotyypille.", "ExistingTagsScrubbed": "Olemassa olevat tunnisteet on poistettu", "EnableSSL": "SSL-salaus", - "EnableSslHelpText": " Käyttöönotto edellyttää uudelleenkäynnistystä järjestelmänvalvojan oikeuksilla.", - "ErrorLoadingContents": "Sisällönlatauksen virhe", + "EnableSslHelpText": " Käyttöönotto vaatii uudelleenkäynnistyksen järjestelmänvavojan oikeuksilla.", + "ErrorLoadingContents": "Virhe ladattaessa sisältöjä", "FirstDayOfWeek": "Viikon ensimmäinen päivä", "ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "Lue lisää tuontilistoista painamalla 'Lisätietoja'.", "ICalLink": "iCal-linkki", - "ImportListExclusions": "Tuotilistojen poikkeukset", - "GrabSelected": "Sieppaa valitut", + "ImportListExclusions": "Tuontilistojen poikkeukset", + "GrabSelected": "Kaappaa valitut", "Group": "Ryhmä", "Hostname": "Osoite", - "Importing": "Tiedostojen tuonti", - "IncludeHealthWarningsHelpText": "Sisällytä kuntovaroitukset", + "Importing": "Tuonti", "IncludeUnknownArtistItemsHelpText": "Näytä jonossa kohteet, joissa ei ole esittäjää. Tämä voi sisältää poistettuja esittäjiä, kappaleita tai mitä tahansa muuta {appName}ille luokiteltua.", - "Interval": "Aikaväli", - "IndexerSettings": "Tietolähteiden asetukset", - "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "Monet torrent- ja Usenet-lataustyökalut ovat tuettuja.", - "MetadataSettings": "Metatietojen asetukset", + "Interval": "Ajoitus", + "IndexerSettings": "Tietolähdeasetukset", + "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "Monet torrent- ja Usenet-lataajat ovat tuettuja.", + "MetadataSettings": "Metatietoasetukset", "MediaManagementSettings": "Medianhallinnan asetukset", - "MaximumSizeHelpText": "Haettavan julkaisun enimmäiskoko megatavuina. Aseta nollaan asettamaan rajoittamaton.", - "LogLevel": "Kirjauksen taso", + "MaximumSizeHelpText": "Kaapattavien julkaisujen enimmäiskoko megatavuina. Arvo \"0\" (nolla) poistaa rajoituksen.", + "LogLevel": "Lokikirjauksen laajuus", "Logs": "Lokitiedot", - "MaximumLimits": "Enimmäismäärät", + "MaximumLimits": "Enimmäisrajoitukset", "MIA": "Puuttuu", - "MinimumLimits": "Vähimmäismäärät", + "MinimumLimits": "Vähimmäisrajoitukset", "MoreInfo": "Lisätietoja", - "NamingSettings": "Nimeämisen asetukset", + "NamingSettings": "Nimeämisasetukset", "NoHistory": "Ei historiaa.", - "Options": "Valinnat", - "PageSizeHelpText": "Sivulla näytettävien kohteiden määrä.", - "PortNumber": "Portti", + "Options": "Asetukset", + "PageSizeHelpText": "Sivukohtainen kohdemäärä.", + "PortNumber": "Portin numero", "Protocol": "Protokolla", "Queue": "Jono", "QualityDefinitions": "Laatumääritykset", "Reload": "Lataa uudelleen", - "RemotePathHelpText": "Lataustyökalun käyttämän hakemiston juurisijainti", + "RemotePathHelpText": "Lataustyökalun käyttämän kansion juurisijainti.", "RemoveTagExistingTag": "Olemassa oleva tunniste", - "ReplaceIllegalCharactersHelpText": "Korvaa laittomat merkit. Jos ei käytössä, laittomat merkit poistetaan.", - "RequiresRestartToTakeEffect": "Käyttöönotto vaatii uudelleenkäynnistyksen.", + "ReplaceIllegalCharactersHelpText": "Korvaa laittomat merkit vaihtoehtoisella merkinnällä. Jos ei valittu, ne poistetaan.", + "RequiresRestartToTakeEffect": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", "Reset": "Uudista", "Restore": "Palauta", - "RSSSync": "RSS-synkronointi", - "RSSSyncInterval": "RSS-synkronointiväli", + "RSSSync": "Synkronoi RSS", + "RSSSyncInterval": "RSS-synkronoinnin ajoitus", "ShowName": "Näytä nimi", - "ShowPath": "Näytä sijainti", + "ShowPath": "Näytä tiedostosijainti", "ShowQualityProfile": "Näytä laatuprofiili", "ShowQualityProfileHelpText": "Näytä laatuprofiili julisteen alla.", - "ShowRelativeDates": "Näytä suhteutetut päiväykset", - "ShowRelativeDatesHelpText": "Näytä suhteutetut (tänään/eilen/yms.) tai absoluuttiset päiväykset.", + "ShowRelativeDates": "Käytä suhteellisia päiväyksiä", + "ShowRelativeDatesHelpText": "Korvaa absoluuttiset päiväykset suhteellisilla päiväyksillä (tänään/eilen/yms.).", "ShowSearch": "Näytä haku", - "ShowSizeOnDisk": "Näytä tiedostokoko", + "ShowSizeOnDisk": "Näytä koko levyllä", "ShowTitleHelpText": "Näytä esittäjän nimi julisteen alla", - "SslCertPasswordHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", - "SslCertPathHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", - "SslPortHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", + "SslCertPasswordHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", + "SslCertPathHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", + "SslPortHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", "ShowUnknownArtistItems": "Näytä 'Tuntematon esittäjä' -kohde", "StartupDirectory": "Käynnistyskansio", "StartTypingOrSelectAPathBelow": "Aloita kirjoitus tai valitse sijainti alta", - "SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Profiilia käytetään vuorovaikutteisen haun yhteydessä.", + "SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Profiilia käytetään manuaalihakuun.", "Tags": "Tunnisteet", - "TestAll": "Testaa kaikki", - "TestAllClients": "Testaa kaikki lataustyökalut", + "TestAll": "Kaikkien testaus", + "TestAllClients": "Lataustyökalujen testaus", "ThisWillApplyToAllIndexersPleaseFollowTheRulesSetForthByThem": "Tämä koskee kaikkia tietolähteitä. Noudata niiden asettamia sääntöjä.", "TagAudioFilesWithMetadata": "Tallenna metatiedot äänitiedostoihin", - "TestAllIndexers": "Testaa tietolähteet", - "UnableToLoadBackups": "Varmuuskopioiden lataus epäonnistui.", - "UnableToLoadDownloadClients": "Lataustyökalujen lataus epäonnistui.", + "TestAllIndexers": "Tietolähteiden testaus", + "UnableToLoadBackups": "Varmuuskopioiden lataus epäonnistui", + "UnableToLoadDownloadClients": "Lataustyökalujen lataus ei onistu", "UnableToLoadGeneralSettings": "Yleisten asetusten lataus epäonnistui.", "UnableToLoadIndexers": "Tietolähteiden lataus epäonnistui.", - "UnableToLoadIndexerOptions": "Tietolähteiden asetuksien lataus epäonnistui.", + "UnableToLoadIndexerOptions": "Tietolähdeasetusten lataus ei onnistu.", "UnableToLoadImportListExclusions": "Tuontilistojen poikkeuksien lataus epäonnistui", "UnableToLoadHistory": "Historian lataus epäonnistui", - "UnableToLoadTags": "Tunnisteiden lataus epäonnistui.", + "UnableToLoadTags": "Tunnisteiden lataus ei onnistu", "UnableToLoadQualityDefinitions": "Laatumäärityksien lataus epäonnistui.", "UpdateScriptPathHelpText": "Polku komentosarjaan, joka käsittelee puretun päivitystiedoston ja hoitaa asennuksen loppuosuuden.", - "UrlBaseHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", + "UrlBaseHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", "UsingExternalUpdateMechanismBranchUsedByExternalUpdateMechanism": "Ulkoisen päivitysratkaisun käyttämä kehityshaara.", "Version": "Versio", "Uptime": "Käyttöaika", "URLBase": "URL-perusta", "Usenet": "Usenet", - "AgeWhenGrabbed": "Ikä (siepatessa)", + "AgeWhenGrabbed": "Ikä (kaappaushetkellä)", "20MinutesTwenty": "20 minuuttia: {0}", "45MinutesFourtyFive": "45 minuuttia: {0}", "60MinutesSixty": "60 minuuttia: {0}", "AlternateTitles": "Vaihtoehtoiset nimet", - "AlreadyInYourLibrary": "Elokuva on jo kirjastossasi", + "AlreadyInYourLibrary": "Kohde on jo krijastossasi", "AlternateTitleslength1Title": "Nimike", "Analytics": "Analytiikka", "AlternateTitleslength1Titles": "Nimikkeet", - "AnalyticsEnabledHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", + "AnalyticsEnabledHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", "Automatic": "Automaattinen", "Clear": "Tyhjennä", "DelayingDownloadUntilInterp": "Lataus on siirretty alkamaan {0} klo {1}", @@ -242,122 +238,116 @@ "ScriptPath": "Komentosarjan sijainti", "Search": "Haku", "Size": " Koko", - "SkipFreeSpaceCheck": "Ohita vapaan levytilan tarkistus", - "SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vapaata tallennustilaa ei tunnisteta esittäjien juurikansiosta.", + "SkipFreeSpaceCheck": "Ohita vapaan tilan tarkastus", + "SkipFreeSpaceCheckWhenImportingHelpText": "Käytä kun juurikansion tallennusmedian vapaata tilaa ei tunnisteta tiedostotuonnin yhteydessä.", "WeekColumnHeader": "Viikkosarakkeen otsikko", "ChmodFolder": "chmod-kansio", - "UnableToAddANewNotificationPleaseTryAgain": "Kytkennän lisäys epäonnistui. Yritä uudelleen.", + "UnableToAddANewNotificationPleaseTryAgain": "Kytköksen lisäys epäonnistui. Yritä uudelleen.", "ApplyTags": "Tunnistetoimenpide", - "UnableToLoadNotifications": "Kytkentöjen lataus epäonnistui.", + "UnableToLoadNotifications": "Kytkösten lataus epäonnistui.", "DownloadClientSettings": "Lataustyökalujen asetukset", "GeneralSettings": "Yleiset asetukset", - "QualitySettings": "Laadun asetukset", + "QualitySettings": "Laatuasetukset", "Settings": "Asetukset", "UnableToLoadUISettings": "Käyttöliittymän asetuksien lataus epäonnistui.", - "UpdateAutomaticallyHelpText": "Lataa ja asenna päivitykset automaattisesti. Voit edelleen asentaa ne myös lähteestä System:Updates.", + "UpdateAutomaticallyHelpText": "Lataa ja asenna päivitykset automaattisesti. Voit myös edelleen suorittaa asennuksen järjestelmäasetusten päivitykset-osiosta.", "Filename": "Tiedostonimi", - "UrlBaseHelpText": "Käänteisen välityspalvelimen tuki (esim. 'http://[host]:[port]/[urlBase]'). Käytä oletusta jättämällä tyhjäksi.", - "YesCancel": "Kyllä, peruuta", + "UrlBaseHelpText": "Lisää {appName}in URL-osoitteeseen jälkiliitteen, esim. \"http://[osoite]:[portti]/[URL-perusta]\". Oletusarvo on tyhjä.", + "YesCancel": "Kyllä, peru", "Enable": "Käytä", - "EnableAutomaticAdd": "Automaattilisäys", + "EnableAutomaticAdd": "Käytä automaattilisäystä", "About": "Tietoja", "AddingTag": "Tunniste lisätään", "RefreshInformationAndScanDisk": "Päivitä tiedot ja tarkista levy", "ErrorLoadingPreviews": "Virhe ladattaessa esikatselua", "FileManagement": "Tiedostojen hallinta", - "ExtraFileExtensionsHelpTexts2": "Esimerkkejä: '.sub, .nfo' tai 'sub, nfo'.", - "ExtraFileExtensionsHelpTexts1": "Pilkulla eroteltu lista tuotavista oheistiedostoista (.nfo tuodaan nimellä .nfo-orig).", "FileDateHelpText": "Tiedoston päiväyksen muutos tuonnin ja uudellentarkistuksen yhteydessä.", - "EnabledHelpText": "Käytä tätä julkaisuprofiilia.", + "EnabledHelpText": "Käytä julkaisuprofiilia valitsemalla tämä.", "Files": "Tiedostot", "Fixed": "Korjattu", "GoToInterp": "Siirry kohteeseen '{0}'", - "Grab": "Sieppaa", - "GrabRelease": "Sieppaa julkaisu", - "ICalHttpUrlHelpText": "Kopioi URL-osoite kalenteripalveluusi/-sovellukseesi tai tilaa painamalla, jos selaimesi tukee Webcal-osoitteita.", + "Grab": "Kaappaa", + "GrabRelease": "Kaappaa julkaisu", + "ICalHttpUrlHelpText": "Kopioi URL-osoite kalenteripalveluusi/-sovellukseesi tai tilaa se painamalla tästä, jos selaimesi tukee Webcal-osoitteita.", "IgnoredAddresses": "Ohitetut osoitteet", - "IgnoredHelpText": "Julkaisu hylätään, jos se vastaa yhtä tai useampaa ehtoa (kirjainkokoa ei huomioida).", + "IgnoredHelpText": "Julkaisu hylätään, jos se sisältää yhden tai useampia näistä termeistä (kirjainkoolla ei ole merkitystä).", "IgnoredPlaceHolder": "Lisää rajoitus", - "ImportedTo": "Tuotu kohteeseen", + "ImportedTo": "Tuontikohde", "ImportExtraFilesHelpText": "Tuo kappaletiedoston tuonnin yhteydessä sääntöjä vastaavat tiedostot, kuten tekstitykset, .nfo-tiedostot, yms.", - "ImportExtraFiles": "Oheistiedostojen tuonti", - "IconForCutoffUnmet": "Katkaisutason kuvake", - "Global": "Järjestelmänlaajuiset", - "MinimumFreeSpace": "Vapaan tallennustilan vähimmäismäärä", - "Missing": "Puuttuvat", - "Monitored": "Valvottu", - "OnUpgradeHelpText": "Kun elokuva päivitetään", - "OnRenameHelpText": "Kun elokuva nimetään uudelleen", + "ImportExtraFiles": "Tuo oheistiedostot", + "IconForCutoffUnmet": "Katkaisutasokuvake", + "Global": "Yleiset", + "MinimumFreeSpace": "Vapaan tilan vähimmäismäärä", + "Missing": "Puuttuu", + "Monitored": "Valvotut", "OpenBrowserOnStart": "Avaa selain käynnistettäessä", "Profiles": "Profiilit", "Proper": "Kunnollinen", "RecyclingBin": "Roskakori", "RecycleBinHelpText": "Pysyvän poiston sijaan kappaletiedostot siirretään tähän kansioon.", "RecyclingBinCleanup": "Roskakorin tyhjennys", - "RequiredHelpText": "Julkaisun tulee sisältää ainakin yksi näistä termeistä (kirjainkokoa ei huomioida).", + "RequiredHelpText": "Julkaisun on sisällettävä ainakin yksi näistä termeistä (kirjainkokoa ei huomioida).", "RequiredPlaceHolder": "Lisää rajoitus", - "RescanAfterRefreshHelpTextWarning": "{appName} ei tunnista tiedostomuutoksia automaattisesti, jollei asetuksena ole 'Aina'.", + "RescanAfterRefreshHelpTextWarning": "{appName} ei tunnista tiedostomuutoksia automaattisesti, jos asetuksena ei ole \"Aina\".", "ReplaceIllegalCharacters": "Korvaa kielletyt merkit", "RescanAfterRefreshHelpText": "Tarkista esittäjäkansion sisältö uudelleen elokuvan päivityksen jälkeen.", "Style": "Ulkoasun tyyli", - "TorrentDelayHelpText": "Viive minuutteina ennen kuin torrentia siepataan.", + "TorrentDelayHelpText": "Minuuttiviive, joka odotetaan ennen julkaisun Torrent-kaappausta.", "UnableToAddANewQualityProfilePleaseTryAgain": "Laatuprofiilin lisäys epäonnistui. Yritä uudelleen.", - "UnableToAddANewRemotePathMappingPleaseTryAgain": "Etäsijainnin kartoituksen lisäys epäonnistui. Yritä uudelleen.", + "UnableToAddANewRemotePathMappingPleaseTryAgain": "Etäsijainnin kohdistuksen lisäys epäonnistui. Yritä uudelleen.", "UnableToLoadBlocklist": "Estonlistan lataus epäonnistui.", "UnableToLoadDelayProfiles": "Viiveprofiilien lataus epäonnistui.", - "UnableToLoadDownloadClientOptions": "Lataustyökalun asetuksien lataus epäonnistui.", + "UnableToLoadDownloadClientOptions": "Lataustyökalun asetusten lataus epäonnistui", "UnableToLoadLists": "Tuontilistojen lataus epäonnistui.", "UnableToLoadRootFolders": "Pääkansioiden lataus epäonnistui.", "UnableToLoadTheCalendar": "Kalenterin lataus epäonnistui.", - "Unmonitored": "Ei valvottu", + "Unmonitored": "Valvomattomat", "UnableToLoadMediaManagementSettings": "Medianhallinnan asetuksien lataus epäonnistui.", "UnableToLoadMetadata": "Metatietojen lataus epäonnistui.", "UnableToLoadNamingSettings": "Nimeämisen asetuksien lataus epäonnistui.", "UnableToLoadQualities": "Laatujen lataus epäonnistui.", "UnableToLoadQualityProfiles": "Laatuprofiilien lataus epäonnistui.", - "UnableToLoadRemotePathMappings": "Etäsijaintien kartoitusten lataus epäonnistui.", + "UnableToLoadRemotePathMappings": "Etäsijaintien kohdistusten lataus epäonnistui", "UnmonitoredHelpText": "Sisällytä ei-valvotut albumit iCal-syötteeseen.", "UpdateAll": "Päivitä kaikki", "UpgradeAllowedHelpText": "Jos käytöstä poistettuja laatuja ei päivitetä.", "RemoveFromBlocklist": "Poista estolistalta", "UseHardlinksInsteadOfCopy": "Käytä hardlink-kytköksiä", - "MinimumFreeSpaceWhenImportingHelpText": "Estä tuonti, jos vapaan levytilan määrä sen jälkeen jää tässä määritetyn arvon alle.", - "Folders": "Kansioiden käsittely", - "RecycleBinCleanupDaysHelpText": "Poista automaattinen tyhjennys käytöstä asettamalla arvoksi '0'.", - "RecycleBinCleanupDaysHelpTextWarning": "Tässä määritettyä aikaa vanhemmat tiedostot poistetaan roskakorista pysyvästi automaattisesti.", - "RootFolders": "Pääkansiot", - "Path": "Sijainti", + "MinimumFreeSpaceWhenImportingHelpText": "Estä tuonti, jos sen jälkeinen vapaa levytila olisi tässä määritettyä arvoa pienempi.", + "Folders": "Kansiot", + "RecycleBinCleanupDaysHelpText": "Arvo \"0\" (nolla) poistaa automaattityhjennyksen käytöstä.", + "RecycleBinCleanupDaysHelpTextWarning": "Määritettyä päiväystä vanhemmat tiedostot poistetaan roskakorista automaattisesti.", + "RootFolders": "Juurikansiot", + "Path": "Tiedostosijainti", "TorrentDelay": "Torrent-viive", - "OnGrabHelpText": "Kun elokuva siepataan", "SearchForMissing": "Etsi puuttuvia", "Source": "Lähdekoodi", - "ShowCutoffUnmetIconHelpText": "Näytä kuvake elokuville, joiden tiedostot eivät vastaa vielä määritettyä katkaisutasoa.", - "ShowMonitoredHelpText": "Näytä valvontatila julisteen alla.", - "ShowMonitored": "Näytä valvonta", + "ShowCutoffUnmetIconHelpText": "Näytä kuvake tiedostoille, joiden määritettyä katkaisutasoa ei ole vielä saavutettu.", + "ShowMonitoredHelpText": "Näytä valvonnan tila julisteen alla.", + "ShowMonitored": "Näytä valvontatila", "ShouldMonitorHelpText": "Tältä tuontilistalta lisätyt albumit lisätään ja niitä valvotaan.", - "TimeFormat": "Kellonajan esitystapa", - "Quality": "Laatumääritykset", + "TimeFormat": "Kellonajan esitys", + "Quality": "Laatu", "Local": "Paikalliset", "MonitoredHelpText": "Esittäjän albumeita etsitään ja ne ladataan, jos ne ovat saatavilla.", - "PriorityHelpText": "Tietolähteen painotus: 1 (korkein) - 50 (matalin). Oletusarvo on 25. Käytetään muutoin tasaveroisten julkaisujen sieppauspäätökseen. Kaikkia käytössä olevia tietolähteitä käytetään edelleen RSS-synkronointiin ja hakuun.", "PropersAndRepacks": "Proper- ja repack-julkaisut", "UnableToAddANewListPleaseTryAgain": "Tuontilistan lisäys epäonnistui. Yritä uudelleen.", - "IncludeUnmonitored": "Sisällytä ei valvotut", + "IncludeUnmonitored": "Sisällytä valvomattomat", "AllExpandedExpandAll": "Laajenna kaikki", - "Absolute": "Absoluuttinen", + "Absolute": "Ehdoton", "AddMissing": "Lisää puuttuvat", "AddNewItem": "Lisää uusi kohde", "AllExpandedCollapseAll": "Supista kaikki", "AllowArtistChangeClickToChangeArtist": "Paina vaihtaaksesi kirjailijaa", "Season": "Kausi", "ArtistAlbumClickToChangeTrack": "Vaihda kirjaa painamalla", - "ArtistFolderFormat": "Kirjailijakansion muoto", + "ArtistFolderFormat": "Esittäjäkansion kaava", "ArtistNameHelpText": "Poissuljettavan kirjailijan/kirjan nimi (voi olla mitä tahansa merkityksellistä)", - "CreateEmptyArtistFoldersHelpText": "Luo puuttuvat kirjailijakansiot levyn tarkistuksen yhteydessä", - "DefaultMetadataProfileIdHelpText": "Kansiosta löytyville esittäjille oletusarvoisesti asetettava metatietoprofiili.", + "CreateEmptyArtistFoldersHelpText": "Luo puuttuvat kirjailijakansiot kirjastotarkistusten yhteydessä", + "DefaultMetadataProfileIdHelpText": "Kansiosta löydetyille esittäjille oletustusarvoisesti asetettava metatietoprofiili.", "DefaultQualityProfileIdHelpText": "Kansiosta löydetyille esittäjille oletustusarvoisesti asetettava laatuprofiili.", "History": "Historia", - "HostHelpText": "Sama isäntä, jonka määritit etälatausasiakkaalle", + "HostHelpText": "Sama osoite, joka on määritty etälataustyökalulle.", "ICalFeed": "iCal-syöte", "ImportFailedInterp": "Tuonti epäonnistui: {0}", "RestartLidarr": "Käynnistä {appName} uudelleen", @@ -365,23 +355,23 @@ "RestoreBackup": "Palauta varmuuskopio", "RetentionHelpText": "Vain Usenet: Aseta nollaan asettamaan rajoittamaton säilytys", "RetryingDownloadInterp": "Yritetään ladata uudelleen {0} osoitteessa {1}", - "TestAllLists": "Testaa listat", + "TestAllLists": "Kaikkien listojen testaus", "Time": "Aika", - "TotalFileSize": "Tiedoston koko", - "Track": "Jäljitys", + "TotalFileSize": "Kokonaistiedostokoko", + "Track": "Valvo", "UnableToLoadReleaseProfiles": "Viiveprofiileja ei voi ladata", - "UsenetDelayHelpText": "Viivästy muutamassa minuutissa odottaaksesi, ennen kuin tartut julkaisun Usenetiin", + "UsenetDelayHelpText": "Minuuttiviive, joka odotetaan ennen julkaisun Usenet-kaappausta.", "UseProxy": "Käytä välityspalvelinta", "UserAgentProvidedByTheAppThatCalledTheAPI": "User-Agent-tiedon ilmoitti sovellus, joka kommunikoi API:n kanssa", - "UsingExternalUpdateMechanismBranchToUseToUpdateLidarr": "Sovelluksen versiopäivityksiin käytettävä kehityshaara.", - "AnalyticsEnabledHelpText": "Lähetä nimettömiä käyttö- ja virhetietoja sovelluksen palvelimille. Tämä sisältää tietoja selaimestasi, verkkokäyttöliittymän sivujen käytöstä, virheraportoinnista sekä käyttöjärjestelmästäsi ja versiosta. Käytämme näitä tietoja ominaisuuksien ja virhekorjauksien painotukseen.", + "UsingExternalUpdateMechanismBranchToUseToUpdateLidarr": "{appName}in versiopäivityksiin käytettävä kehityshaara.", + "AnalyticsEnabledHelpText": "Lähetä nimettömiä käyttö- ja virhetietoja {appName}in palvelimille. Tämä sisältää tietoja selaimestasi, käyttöliittymän sivujen käytöstä, virheraportoinnista, käyttöjärjestelmästä ja suoritusalustasta. Käytämme näitä tietoja ominaisuuksien ja vikakorjausten painotukseen.", "SearchAll": "Etsi kaikkia", "SetPermissionsLinuxHelpTextWarning": "Jos et ole varma näiden asetusten toiminnasta, älä muuta niitä.", - "ShortDateFormat": "Päiväyksen lyhyt esitystapa", + "ShortDateFormat": "Lyhyen päiväyksen esitys", "ShowDateAdded": "Näytä lisäyspäivä", "SorryThatAlbumCannotBeFound": "Valitettavasti elokuvaa ei löydy.", "SorryThatArtistCannotBeFound": "Valitettavasti kirjailijaa ei löydy.", - "SearchSelected": "Haku valittu", + "SearchSelected": "Etsi valittuja", "SendAnonymousUsageData": "Lähetä nimettömiä käyttötietoja", "SetPermissions": "Aseta käyttöoikeudet", "SetPermissionsLinuxHelpText": "Pitäisikö chmod suorittaa, kun tiedostoja tuodaan / nimetään uudelleen?", @@ -399,44 +389,43 @@ "IsCutoffCutoff": "Katkaista", "IsCutoffUpgradeUntilThisQualityIsMetOrExceeded": "Päivitä, kunnes tämä laatu saavutetaan tai ylitetään", "Level": "Taso", - "LoadingTrackFilesFailed": "Elokuvatiedostojen lataaminen epäonnistui", "LocalPath": "Paikallinen sijainti", "LocalPathHelpText": "Polku, jonka kautta etäsijaintia tulee käyttää paikallisesti.", "LogFiles": "Lokitiedostot", - "LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "Jäljityksen kirjaaminen tulisi ottaa käyttöön vain väliaikaisesti", - "LongDateFormat": "Pitkä päivämäärämuoto", + "LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "Jäljityskirjausta tulee käyttää vain tilapäisesti.", + "LongDateFormat": "Pitkän päiväyksen esitys", "ManualImport": "Manuaalinen tuonti", "MarkAsFailed": "Merkitse epäonnistuneeksi", "MarkAsFailedMessageText": "Haluatko varmasti merkitä kohteen {0} epäonnistuneeksi?", - "MaximumSize": "Suurin koko", + "MaximumSize": "Enimmäiskoko", "Mechanism": "Mekanismi", - "MediaInfo": "Mediatiedot", - "Medium": "Keskitaso", + "MediaInfo": "Median tiedot", + "Medium": "Keskikoko", "Message": "Viesti", "MinimumAge": "Vähimmäisikä", - "MinimumAgeHelpText": "Vain Usenet: NZB: n vähimmäisikä minuutteina, ennen kuin heidät napataan. Käytä tätä antaaksesi uusille julkaisuille aikaa levittää usenet-palveluntarjoajallesi.", + "MinimumAgeHelpText": "Vain Usenet: NZB:n vähimmäisikä minuutteina, ennen niiden kaappausta. Tämän avulla uusille julkaisuille voidaan antaa aikaa levitä Usenet-palveluntarjoajalle.", "Mode": "Tila", "MustContain": "Täytyy sisältää", - "MustNotContain": "Ei saa sisältää", + "MustNotContain": "Ei voi sisältää", "Name": "Nimi", - "New": "Uusi", - "NoBackupsAreAvailable": "Varmuuskopioita ei ole saatavilla", - "NoLogFiles": "Ei lokitiedostoja", + "New": "Uutta", + "NoBackupsAreAvailable": "Varmuuskopioita ei ole käytettävissä", + "NoLogFiles": "Lokitiedostoja ei ole", "None": "Ei mitään", "NoUpdatesAreAvailable": "Päivityksiä ei ole saatavilla", - "Original": "Alkuperäinen", + "Original": "Alkuperäiset", "PageSize": "Sivun koko", "Password": "Salasana", "Permissions": "Käyttöoikeudet", - "PosterSize": "Julisteen koko", - "PreviewRename": "Esikatsele nimeämistä", - "ProtocolHelpText": "Valitse käytettävä (t) protokolla (t) ja mikä on suositeltava, kun valitset muuten yhtä suurten julkaisujen välillä", + "PosterSize": "Julisteiden koko", + "PreviewRename": "Nimeämisen esikatselu", + "ProtocolHelpText": "Valitse käytettävä(t) protokolla(t) ja mitä käytetään ensisijaisesti valittaessa muutoin tasaveroisista julkaisuista.", "Proxy": "Välityspalvelin", "ProxyType": "Välityspalvelimen tyyppi", "PublishedDate": "Julkaisupäivä", "QualityProfile": "Laatuprofiili", "QualityProfiles": "Laatuprofiilit", - "ReadTheWikiForMoreInformation": "Lue lisätietoja Wikistä", + "ReadTheWikiForMoreInformation": "Wikistä löydät lisää tietoja", "Real": "Todellinen", "Reason": "Syy", "Redownload": "Lataa uudelleen", @@ -447,13 +436,13 @@ "ReleaseStatuses": "Julkaisutila", "ReleaseWillBeProcessedInterp": "Julkaisu käsitellään {0}", "RemotePath": "Etäsijainti", - "RemotePathMappings": "Etäreittien kartoitukset", + "RemotePathMappings": "Etäsijaintien kohdistukset", "Remove": "Poista", - "RemoveCompletedDownloadsHelpText": "Poista tuodut lataukset asiakasasiakashistoriasta", + "RemoveCompletedDownloadsHelpText": "Poista tuodut lataukset lataustyökalun historiasta", "RemovedFromTaskQueue": "Poistettu tehtäväjonosta", - "RemoveFailedDownloadsHelpText": "Poista epäonnistuneet lataukset latausasiakashistoriasta", + "RemoveFailedDownloadsHelpText": "Poista epäonnistuneet lataukset lataustyökalun historiasta", "RemoveFilter": "Poista suodatin", - "RemoveFromDownloadClient": "Poista Download Client -sovelluksesta", + "RemoveFromDownloadClient": "Poista lataustyökalusta", "RemoveFromQueue": "Poista jonosta", "RemoveSelected": "Poista valitut", "RenameTracksHelpText": "Jos uudelleennimeäminen ei ole käytössä, käytetään nykyistä tiedostonimeä.", @@ -462,16 +451,16 @@ "ResetAPIKeyMessageText": "Haluatko varmasti uudistaa API-avaimesi?", "Result": "Tulos", "Retention": "Säilytys", - "RootFolder": "Pääkansio", + "RootFolder": "Juurikansio", "SSLCertPassword": "SSL-varmenteen salasana", - "SslCertPasswordHelpText": "PFX-tiedoston salasana", + "SslCertPasswordHelpText": "Pfx-tiedoston salasana", "SslCertPathHelpText": "PFX-tiedoston sijainti", "SSLPort": "SSL-portti", - "StandardTrackFormat": "Elokuvan vakiomuoto", + "StandardTrackFormat": "Tavallisten kappaleiden kaava", "Status": "Tila", "SuccessMyWorkIsDoneNoFilesToRename": "Menestys! Työni on valmis, ei nimettäviä tiedostoja.", "SuccessMyWorkIsDoneNoFilesToRetag": "Menestys! Työni on valmis, ei nimettäviä tiedostoja.", - "SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "Hakemistoa ei tueta tällä hakemistolla", + "SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "Tämä tietolähde ei tue hakua.", "SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByLidarr": "Profiilia käytetään automaattihaun yhteydessä, kun haku suoritetaan käyttöliittymästä tai {appName}in toimesta.", "Tasks": "Tehtävät", "Type": "Tyyppi", @@ -482,14 +471,14 @@ "Updates": "Päivitykset", "UsenetDelay": "Usenet-viive", "NETCore": ".NET", - "UILanguageHelpText": "Käyttöliittymä näytetään tällä kielellä.", - "UILanguageHelpTextWarning": "Käyttöönotto vaatii selaimen sivupäivityksen.", + "UILanguageHelpText": "{appName}in käyttöliittymän kieli.", + "UILanguageHelpTextWarning": "Selaimen sivupäivitys vaaditaan", "Ungroup": "Pura ryhmä", "WriteMetadataToAudioFiles": "Kirjoita metatiedot äänitiedostoihin", "AlbumIsDownloadingInterp": "Kirjaa ladataan - {0} % {1}", "AnyReleaseOkHelpText": "{appName} vaihtaa automaattisesti versioon, joka vastaa ladattuja tiedostoja parhaiten", - "Label": "Tunniste", - "SourcePath": "Lähteen polku", + "Label": "Nimi", + "SourcePath": "Lähdesijainti", "Year": "Vuosi", "Album": "Albumi", "AlbumHasNotAired": "Albumia ei ole julkaistu", @@ -500,8 +489,7 @@ "AllAlbumsData": "Seuraa kaikkia albumeita, erikoisalbumeita lukuunottamatta", "AllArtistAlbums": "Kaikki artistin albumit", "MetadataProfile": "Metatietoprofiili", - "OnApplicationUpdate": "Sovelluksen päivittyessä", - "OnApplicationUpdateHelpText": "Sovelluksen päivittyessä", + "OnApplicationUpdate": "Kun sovellus päivitetään", "PathHelpTextWarning": "Tämä ei voi olla sama kansio, johon lataustyökalusi tallentaa tiedostot.", "QualityProfileIdHelpText": "Laatuprofiili, joka listalta lisätyille kohteille tulee asettaa.", "IsInUseCantDeleteAMetadataProfileThatIsAttachedToAnArtistOrImportList": "Esittäjään tai tuontilistaan liitettyä metatietoprofiilia ei voi poistaa.", @@ -518,24 +506,24 @@ "MetadataProfileIdHelpText": "Metatietoprofiili, joka listalta lisätyille kohteille tulee asettaa.", "MetadataProfiles": "Metatietoprofiilit", "PathHelpText": "Musiikkikokoelmasi pääkansio.", - "RemoveCompleted": "Poista valmistuneet", - "OnUpgrade": "Kun elokuva päivitetään", - "RemoveDownloadsAlert": "Poistoasetukset on siirretty yllä olevassa taulukossa yksittäisten lataustyökalujen alle.", - "SearchForAllMissingAlbums": "Etsi kaikkia puuttuvia kirjoja", + "RemoveCompleted": "Poisto on suoritettu", + "OnUpgrade": "Päivitettäessä", + "RemoveDownloadsAlert": "Poistoasetukset on siirretty yllä olevan taulukon lataustyökalukohtaisiin asetuksiin.", + "SearchForAllMissingAlbums": "Etsi kaikkia puuttuvia albumeita", "ThisCannotBeCancelled": "Tämän peruminen on aloituksen jälkeen mahdollista vain poistamalla kaikki tietolähteet käytöstä.", - "OnGrab": "Kun elokuva siepataan", - "OnHealthIssue": "Kun havaitaan kuntoon liittyvä ongelma", - "OnRename": "Kun elokuva nimetään uudelleen", + "OnGrab": "Kun julkaisu kaapataan", + "OnHealthIssue": "Vakausongelmat", + "OnRename": "Uudelleennimeäminen", "RemoveFailed": "Poisto epäonnistui", - "Other": "Muu", - "Tracks": "Jäljitys", + "Other": "Muut", + "Tracks": "Kappaleet", "WatchLibraryForChangesHelpText": "Suorita automaattinen uudelleentutkinta, kun juurikansiossa havaitaan tiedostomuutoksia.", "AddedArtistSettings": "Lisätyn esittäjän asetukset", "MonitorAlbumExistingOnlyWarning": "Tämä on albumikohtaisen valvonnan kertaluontoinen määritys. Määritä Esittäjä/Muokkaa-valinnalla mitä uusille albumilisäyksille tehdään.", "MonitoringOptionsHelpText": "Mitkä albumit asetetaan valvottaviksi esittäjän lisäyksen yhteydessä (kertaluontoinen määritys).", "MonitorNewItemsHelpText": "Uusien albumien valvontatapa.", "AddDelayProfile": "Lisää viiveprofiili", - "Added": "Lisätty", + "Added": "Lisäysaika", "AddImportListExclusion": "Lisää tuontilistapoikkeus", "AddIndexer": "Lisää tietolähde", "AddMetadataProfile": "Lisää metatietoprofiili", @@ -548,16 +536,16 @@ "All": "Kaikki", "AllFiles": "Kaikki tiedostot", "Always": "Aina", - "ApplicationURL": "Sovelluksen URL-osoite", - "ApplicationUrlHelpText": "Sovelluksen ulkoinen URL-osoite, johon sisältyy http(s)://, portti ja URL-perusta.", + "ApplicationURL": "Sovelluksen URL", + "ApplicationUrlHelpText": "Tämän sovelluksen ulkoinen URL-osoite, johon sisältyy http(s)://, portti ja URL-perusta.", "Apply": "Käytä", "AudioInfo": "Äänitiedot", - "Backup": "Varmuuskopio", + "Backup": "Varmuuskopiointi", "BeforeUpdate": "Ennen päivitystä", "Close": "Sulje", - "Connect": "Kytkennät", + "Connect": "Kytkökset", "Custom": "Mukautettu", - "CustomFilters": "Mukautetut suodattimet", + "CustomFilters": "Omat suodattimet", "Date": "Päiväys", "DefaultDelayProfileHelpText": "Tämä on oletusprofiili, jota sovelletaan kaikkiin esittäjiin, joille ei ole määritetty erillistä profiilia.", "Deleted": "Poistettu", @@ -566,92 +554,92 @@ "DoNotPrefer": "Älä suosi", "DoNotUpgradeAutomatically": "Älä päivitä automaattisesti", "DownloadFailed": "Lataus epäonnistui", - "EditImportListExclusion": "Poista poikkeussääntö", + "EditImportListExclusion": "Muokkaa tuontilistapoikkeusta", "EditQualityProfile": "Muokkaa laatuprofiilia", - "EditRemotePathMapping": "Muokkaa etäreittien kartoitusta", - "EditRootFolder": "Lisää juurikansio", + "EditRemotePathMapping": "Muokkaa etäsijainnin kohdistusta", + "EditRootFolder": "Muokkaa juurikansiota", "Error": "Virhe", - "ErrorRestoringBackup": "Varmuuskopion palautuksen virhe", + "ErrorRestoringBackup": "Virhe palautettaessa varmuuskopiota", "Events": "Tapahtumat", - "EventType": "Tapahtumatyyppi", + "EventType": "Tapahtuman tyyppi", "Filters": "Suodattimet", "General": "Yleiset", - "Genres": "Tyylilajit", - "Grabbed": "Siepattu", + "Genres": "Lajityypit", + "Grabbed": "Kaapattu", "HardlinkCopyFiles": "Hardlink/tiedostojen kopiointi", - "HideAdvanced": "Piilota edistyneet", + "HideAdvanced": "Piilota lisäasetukset", "Ignored": "Ohitettu", - "Import": "Tuonti", - "IndexerTagHelpText": "Tietolähdettä käytetään vähintään yhdellä täsmäävällä tunnisteella merkityille elokuville. Käytä kaikille jättämällä tyhjäksi.", + "Import": "Tuo", + "IndexerTagHelpText": "Tietolähdettä käytetään vain vähintään yhdellä täsmäävällä tunnisteella merkityille esittäjille. Käytä kaikille jättämällä tyhjäksi.", "Info": "Informatiivinen", "InstanceName": "Instanssin nimi", - "InstanceNameHelpText": "Instanssin nimi välilehdellä ja järjestelmälokissa", - "InteractiveImport": "Vuorovaikutteinen tuonti", + "InstanceNameHelpText": "Instanssin nimi välilehdellä ja järjestelmälokissa.", + "InteractiveImport": "Manuaalituonti", "LastDuration": "Edellinen kesto", "LastExecution": "Edellinen suoritus", "LastUsed": "Viimeksi käytetty", - "LastWriteTime": "Viimeisin kirjoitusaika", - "Library": "kirjasto", + "LastWriteTime": "Viimeksi tallennettu", + "Library": "Kirjasto", "Location": "Sijainti", "Manual": "Manuaalinen", "MediaManagement": "Median hallinta", "Metadata": "Metatiedot", - "MonitoredOnly": "Valvottu", + "MonitoredOnly": "Vain valvotut", "MoveAutomatically": "Siirrä automaattisesti", - "MoveFiles": "Siirrä tiedostoja", + "MoveFiles": "Siirrä tiedostot", "Never": "Ei koskaan", "NextExecution": "Seuraava suoritus", "NoTagsHaveBeenAddedYet": "Tunnisteita ei ole vielä lisätty.", "OnlyTorrent": "Vain Torrent", "OnlyUsenet": "Vain Usenet", "Peers": "Vertaiset", - "PreferAndUpgrade": "Valitse ja päivitä", + "PreferAndUpgrade": "Suosi ja päivitä", "PreferredProtocol": "Ensisijainen protokolla", "Presets": "Esiasetukset", - "Progress": "Edistyminen", - "QualityLimitsHelpText": "Rajoitukset suhteutetaan automaattisesti elokuvan kestoon.", - "Queued": "Jonossa", + "Progress": "Tilanne", + "QualityLimitsHelpText": "Rajoitukset suhteutetaan automaattisesti albumin kestoon.", + "Queued": "Lisätty jonoon", "Rating": "Arvio", - "RejectionCount": "Hylkäämisluku", - "ReleaseTitle": "Julkaisun otsikko", + "RejectionCount": "Hylkäysmäärä", + "ReleaseTitle": "Julkaisun nimike", "Replace": "Korvaa", - "RestartRequiredHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.", - "RestoreBackupAdditionalInfo": "Huomioi: Sovellus käynnistyy palautusprosessin aikana automaattisesti uudelleen.", + "RestartRequiredHelpTextWarning": "Käyttöönotto vaatii {appName}in uudelleenkäynnistyksen.", + "RestoreBackupAdditionalInfo": "Huomioi: {appName} käynnistyy palautusprosessin aikana automaattisesti uudelleen.", "Save": "Tallenna", "Seeders": "Jakajat", "Select...": "Valitse...", "SelectFolder": "Valitse kansio", - "SelectQuality": "Valitse Laatu", - "ShouldMonitorExistingHelpText": "Valvo automaattisesti tällä listalla olevia albumeita, jotka ovat jo kirjastossasi.", - "ShowAdvanced": "Näytä edistyneet", + "SelectQuality": "Valitse laatu", + "ShouldMonitorExistingHelpText": "Valvo automaattisesti tällä listalla olevia {appName}in kirjaston albumeita.", + "ShowAdvanced": "Näytä lisäasetukset", "SizeLimit": "Kokorajoitus", "SizeOnDisk": "Koko levyllä", - "SourceTitle": "Lähteen otsikko", + "SourceTitle": "Lähteen nimike", "Started": "Alkoi", "System": "Järjestelmä", - "Test": "Kokeile", + "Test": "Testaa", "TimeLeft": "Aikaa jäljellä", "Title": "Nimike", "TotalSpace": "Kokonaistila", "UI": "Käyttöliittymä", - "UnmappedFilesOnly": "Vain kartoittamattomat tiedostot", - "UnmonitoredOnly": "Valvottu", + "UnmappedFilesOnly": "Vain kohdistamattomat tiedostot", + "UnmonitoredOnly": "Vain valvomattomat", "UpgradesAllowed": "Päivitykset sallitaan", "Wanted": "Halutut", - "Warn": "Varoita", - "WouldYouLikeToRestoreBackup": "Haluatko palauttaa varmuuskopion {0}?", - "AddRemotePathMapping": "Lisää etäsijainnin kartoitus", + "Warn": "Varoitus", + "WouldYouLikeToRestoreBackup": "Haluatko palauttaa varmuuskopion \"{name}\"?", + "AddRemotePathMapping": "Lisää etäsijainnin kohdistus", "FreeSpace": "Vapaa tila", - "IndexerDownloadClientHelpText": "Määritä tämän tietolähteen kanssa käytettävä lataustyökalu", + "IndexerDownloadClientHelpText": "Määritä tämän tietolähteen kanssa käytettävä lataustyökalu.", "Ok": "Ok", - "Organize": "Järjestää", + "Organize": "Järjestä", "OutputPath": "Tallennussijainti", "Renamed": "Nimetty uudelleen", "Activity": "Tapahtumat", "EditDelayProfile": "Muokkaa viiveprofiilia", "Add": "Lisää", "AddConnection": "Lisää yhteys", - "EditMetadataProfile": "Metatietoprofiili", + "EditMetadataProfile": "Muokkaa metatietoprofiilia", "Database": "Tietokanta", "AllowFingerprinting": "Salli piiloleimaus", "MassAlbumsCutoffUnmetWarning": "Haluatko varmasti etsiä '{0}' albumia, joiden katkaisutasoa ei ole saavutettu?", @@ -663,7 +651,6 @@ "DiscNumber": "Levyn numero", "DiscCount": "Levyjen määrä", "EnableProfile": "Käytä profiilia", - "LoadingAlbumsFailed": "Albumien lataus epäonnistui", "MissingAlbums": "Puuttuvat albumit", "MissingAlbumsData": "Seuraa albumeita, joille ei ole tiedostoja tai joita ei ole vielä julkaistu.", "MissingTracks": "Puuttuvat kappaleet", @@ -687,7 +674,7 @@ "TrackMissingFromDisk": "Levyltä puuttuu kappale", "TrackNumber": "Kappaleiden numero", "UnableToLoadMetadataProviderSettings": "Metatietolähteen asetuksia ei voitu ladata", - "UnmappedFiles": "Kartoittamattomat tiedostot", + "UnmappedFiles": "Kohdistamattomat tiedostot", "FutureDays": "Tulevat päivät", "FutureDaysHelpText": "Päivien määrä, jonka verran tulevaisuuteen iCal-syötettä seurataan.", "AlbumStatus": "Albumin tila", @@ -701,11 +688,11 @@ "ForeignIdHelpText": "Ohitettavan esittäjän/albumin MusicBrainz-tunniste.", "FutureAlbums": "Tulevat albumit", "GoToArtistListing": "Avaa esittäjälistaus", - "IsExpandedHideFileInfo": "Piilota tiedostotiedot", + "IsExpandedHideFileInfo": "Piilota tiedostojen tiedot", "IsExpandedHideTracks": "Piilota kappaleet", "IsExpandedHideAlbums": "Piilota albumit", "IsExpandedShowAlbums": "Näytä albumit", - "IsExpandedShowFileInfo": "Näytä tiedostotiedot", + "IsExpandedShowFileInfo": "Näytä tiedostojen tiedot", "IsExpandedShowTracks": "Näytä kappaleet", "IsShowingMonitoredMonitorSelected": "Valvo valittuja", "IsShowingMonitoredUnmonitorSelected": "Lopeta valittujen valvonta", @@ -713,9 +700,8 @@ "MediaCount": "Median määrä", "MediumFormat": "Julkaisumuoto", "MetadataConsumers": "Metatietojen kuluttajat", - "MultiDiscTrackFormat": "Usean levyn kappalemuoto", + "MultiDiscTrackFormat": "Useden levyjen kappaleiden kaava", "OnImportFailure": "Tuonnin epäonistuessa", - "OnImportFailureHelpText": "Tuonnin epäonistuessa", "OnReleaseImport": "Tuotaessa julkaisu", "PastDays": "Menneet päivät", "PrimaryAlbumTypes": "Ensisijaiset albumityypit", @@ -726,28 +712,28 @@ "ReplaceExistingFiles": "Korvaa olemassa olevat tiedostot", "Retag": "Tagaa uudelleen", "Retagged": "Tagattu uudelleen", - "SceneInformation": "Kohtauksen tiedot", + "SceneInformation": "Kohtaustiedot", "SearchForMonitoredAlbums": "Etsi valvottuja albumeita", "SearchMonitored": "Etsi valvottuja", "SecondaryAlbumTypes": "Toissijaiset albumityypit", "SecondaryTypes": "Toissijaiset tyypit", "SelectArtist": "Valitse esittäjä", - "SelectedCountArtistsSelectedInterp": "{0} esittäjä(ä) valittu", + "SelectedCountArtistsSelectedInterp": "{selectedCount} esittäjä(ä) on valittu", "SelectTracks": "Valitse kappaleet", "ShouldSearch": "Etsi uusia kohteita", "ShouldSearchHelpText": "Etsi tietolähteistä hiljattain lisättyjä kohteita. Käytä suurien listojen kanssa varoen.", "ShowAlbumCount": "Näytä albumimäärä", "ShowBanners": "Näytä bannerit", - "ShowBannersHelpText": "Näytä nimien sijaan bannerit.", + "ShowBannersHelpText": "Korvaa nimet bannerikuvilla.", "ShowLastAlbum": "Näytä viimeinen albumi", "SkipRedownload": "Ohita uudelleenlataus", "SpecificAlbum": "Tietty albumi", "StatusEndedContinuing": "Jatkuu", "TBA": "Selviää myöhemmin", "TheAlbumsFilesWillBeDeleted": "Albumin tiedostot poistetaan.", - "TheArtistFolderStrongpathstrongAndAllOfItsContentWillBeDeleted": "Esittäjän kansio '{0}' ja kaikki sen sisältö poistetaan.", + "TheArtistFolderStrongpathstrongAndAllOfItsContentWillBeDeleted": "Esittäjäkansio \"{0}\" ja kaikki sen sisältö poistetaan.", "Theme": "Teema", - "ThemeHelpText": "Vaihda sovelluksen käyttöliittymän ulkoasua. \"Automaattinen\" vaihtaa vaalean ja tumman tilan käyttöjärjestelmäsi teemaa vastaavaksi. Innoittanut Theme.Park.", + "ThemeHelpText": "Vaihda sovelluksen käyttöliittymän ulkoasua. \"Automaattinen\" vaihtaa vaalean ja tumman tilan välillä järjestelmän teeman mukaan. Innoittanut Theme.Park.", "TotalTrackCountTracksTotalTrackFileCountTracksWithFilesInterp": "Yhteensä {0} kappaletta. {1} kappaleelle on tiedostoja.", "TrackArtist": "Kappaleen esittäjä", "TrackCount": "Kappaleiden määrä", @@ -756,10 +742,10 @@ "TrackStatus": "Kappaleiden tila", "TrackTitle": "Kappaleiden nimi", "UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "Päivittäminen ei ole Docker-säiliössä käytettävissä. Päivitä sen sijaan säiliön kuva.", - "WatchRootFoldersForFileChanges": "Seuraa juurikansioiden tiedostomuutoksia", + "WatchRootFoldersForFileChanges": "Valvo juurikansioiden tiedostomuutoksia", "WriteMetadataTags": "Tallenna metatietotagit", "ContinuingAllTracksDownloaded": "Jatkuva (kaikki kappaleet on ladattu)", - "Continuing": "Jatkuva", + "Continuing": "Jatkuu", "ContinuingMoreAlbumsAreExpected": "Albumeita odotetaan lisää", "ContinuingNoAdditionalAlbumsAreExpected": "Abumeita ei odoteta lisää", "OnDownloadFailure": "Latauksen epäonnistuessa", @@ -768,7 +754,7 @@ "ArtistEditor": "Esittäjäeditori", "Artists": "Esittäjät", "Country": "Maa", - "AddReleaseProfile": "Lisää julkaisuprofiili", + "AddReleaseProfile": "Lisää jukaisuprofiili", "AlbumRelease": "Albumin julkaisu", "AlbumReleaseDate": "Albumin julkaisupäivä", "AlbumTitle": "Albumin nimi", @@ -795,7 +781,7 @@ "HasMonitoredAlbumsNoMonitoredAlbumsForThisArtist": "Esittäjältä ei valvota albumeita", "ImportFailed": "Tuonti epäonnistui", "ImportFailures": "Tuontivirheet", - "ImportLists": "Tuotilistat", + "ImportLists": "Tuontilistat", "ImportListSettings": "Tuontilistojen yleiset asetukset", "HideAlbums": "Piilota albumit", "HideTracks": "Piilota kappaleet", @@ -806,8 +792,6 @@ "NewAlbums": "Uudet albumit", "NoneMonitoringOptionHelpText": "Älä valvo esittäjiä tai albumeita", "NotDiscography": "Ei ole diskografia", - "OnDownloadFailureHelpText": "Latauksen epäonnistuessa", - "OnReleaseImportHelpText": "Tuotaessa julkaisu", "Playlist": "Soittolista", "Proceed": "Jatka", "RootFolderPath": "Juurikansion sijainti", @@ -821,27 +805,269 @@ "MassAlbumsSearchWarning": "Haluatko varmasti etsiä '{0}' puuttuvaa albumia?", "EditArtist": "Muokkaa esittäjää", "DeleteSelected": "Poista valitut", - "ClickToChangeReleaseGroup": "Paina vaihtaaksesi julkaisuryhmää", - "EnableAutomaticAddHelpText": "Lisää esittäjät/albumit, kun synkronoinnit suoritetaan käyttöliittymästä tai sovelluksen toimesta.", - "IndexerIdHelpText": "Määritä mitä tietolähteitä proofiili koskee", + "ClickToChangeReleaseGroup": "Vaihda julkaisuryhmää painamalla tästä", + "EnableAutomaticAddHelpText": "Lisää esittäjät/albumit {appName}iin kun synkronointi suoritetaan käyttöliittymästä tai {appName}in toimesta.", + "IndexerIdHelpText": "Määritä mitä tietolähdettä profiili koskee.", "Inactive": "Ei aktiivinen", - "EnableRssHelpText": "Käytetään, kun sovellus etsii julkaisuja ajoitetusti RSS-synkronoinnilla.", + "EnableRssHelpText": "Käytetään {appName}in etsiessä julkaisuja ajoitetusti RSS-synkronoinnilla.", "AllMonitoringOptionHelpText": "Valvo esittäjiä ja jokaisen esittäjän kaikkia tuontilistan sisältämiä albumeita", "ContinuingOnly": "Vain jatkuvat", "EntityName": "Entiteetin nimi", "EpisodeDoesNotHaveAnAbsoluteEpisodeNumber": "Jaksolla ei ole tarkkaa jaksonumeroa", - "IndexerIdHelpTextWarning": "Tietyn tietolähteen käyttö painotetuilla sanoilla saattaa aiheuttaa julkaisujen kaksoiskappaleiden sieppauksia.", - "AllowFingerprintingHelpText": "Tarkenna kappaleiden täsmäystarkkuutta piiloleimauksen avulla.", - "BlocklistReleaseHelpText": "Estää julkaisun automaattisen uudelleensieppauksen.", - "RemotePathMappingCheckFilesGenericPermissions": "Lataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta kansiota ei nähdä. Saatat joutua muokkaamaan kansion käyttöoikeuksia.", - "RemotePathMappingCheckGenericPermissions": "Lataustyökalu \"{0}\" tallentaa lataukset sijaintiin \"{1}\", mutta kansiota ei nähdä. Saatat joutua muokkaamaan kansion käyttöoikeuksia.", - "RemotePathMappingCheckFolderPermissions": "Ladatauskansio \"{0}\" näkyy, mutta sitä ei voida käyttää. Todennäköinen syy on sijainnin käyttöoikeusvirhe.", + "IndexerIdHelpTextWarning": "Yksittäisen tietolähteen käyttö sanapainotuksen kanssa saattaa aiheuttaa julkaisujen kaksoiskappaleiden kaappauksia.", + "AllowFingerprintingHelpText": "Tarkenna kappaleiden tunnistustarkkuutta piiloleimauksen avulla.", + "BlocklistReleaseHelpText": "Estää {appName}ia lataamasta näitä tiedostoja uudelleen.", + "RemotePathMappingCheckFilesGenericPermissions": "Lataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta {appName} ei näe sitä. Kansion käyttöoikeuksia on ehkä muokattava.", + "RemotePathMappingCheckGenericPermissions": "Lataustyökalu \"{0}\" tallentaa lataukset kohteeseen \"{1}\", mutta {appName} ei näe sitä. Kansion käyttöoikeuksia on ehkä muokattava.", + "RemotePathMappingCheckFolderPermissions": "{appName} näkee ladatauskansion \"{0}\", mutta ei voi avata sitä. Tämä johtuu todennäköisesti liian rajallisista käyttöoikeuksista.", "DownloadedUnableToImportCheckLogsForDetails": "Ladattu - Tuonti ei onnistu: Katso tarkemmat tiedot lokista.", - "AppDataLocationHealthCheckMessage": "Päivitystä ei sallita, jotta AppData-kansion poisto päivityksen yhteydessä voidaan estää.", - "IndexerRssHealthCheckNoIndexers": "RSS-synkronointia käyttäviä tietolähteitä määritetty, jonka vuoksi uusia julkaisuja ei siepata automaattisesti.", - "IndexerSearchCheckNoAutomaticMessage": "Automaattista hakua varten ei ole määritetty tietolähteitä, jonka vuoksi haku ei löydä tuloksia.", - "IndexerSearchCheckNoInteractiveMessage": "Manuaalista hakua varten ei ole määritetty tietolähteitä, jonka vuoksi haku ei löydä tuloksia.", - "RecycleBinUnableToWriteHealthCheck": "Määritettyyn roskakorikansioon ei voi tallentaa: {0}. Varmista, että sijainti on olemassa ja että käyttäjällä on kirjoitusoikeus kansioon.", - "RemotePathMappingCheckDownloadPermissions": "Ladattu elokuva \"{0}\" näkyy, mutta sitä ei voida käyttää. Todennäköinen syy on sijainnin käyttöoikeusvirhe.", - "RemotePathMappingCheckImportFailed": "Albumin tuonti epäonnistui. Katso tarkemmat tiedot lokista." + "AppDataLocationHealthCheckMessage": "Päivityksiä ei sallita, jotta AppData-kansion poistaminen päivityksen yhteydessä voidaan estää.", + "IndexerRssHealthCheckNoIndexers": "RSS-synkronointia varten ei ole määritetty tietolähteitä ja tämän vuoksi {appName} ei kaappaa uusia julkaisuja automaattisesti.", + "IndexerSearchCheckNoAutomaticMessage": "Automaattihakua varten ei ole määritetty tietolähteitä ja tämän vuoksi {appName}in automaattihaku ei löydä tuloksia.", + "IndexerSearchCheckNoInteractiveMessage": "Manuaalihaulle ei ole määritetty tietolähteitä, eikä se sen vuoksi löydä tuloksia.", + "RecycleBinUnableToWriteHealthCheck": "Määritettyyn roskakorikansioon ei voida tallentaa: {0}. Varmista, että sijainti on olemassa ja että käyttäjällä on kirjoitusoikeus kansioon.", + "RemotePathMappingCheckDownloadPermissions": "{appName} näkee ladatun albumin \"{0}\", mutta ei voi avata sitä. Tämä johtuu todennäköisesti liian rajallisista käyttöoikeuksista.", + "RemotePathMappingCheckImportFailed": "{appName} ei voinut tuoda julkaisua. Katso tarkemmat tiedot lokista.", + "AddAutoTagError": "Virhe lisättäessä automaattimerkintää. Yritä uudelleen.", + "AddCondition": "Lisää ehto", + "AddConditionError": "Virhe lisättäessä ehtoa. Yritä uudelleen.", + "AddIndexerImplementation": "Lisätään tietolähdettä - {implementationName}", + "AddDownloadClientImplementation": "Lisäätään lataustyökalua - {implementationName}", + "AddImportList": "Lisää tuontilista", + "AddAutoTag": "Lisää automaattinen tunniste", + "CountDownloadClientsSelected": "{selectedCount} lataustyökalu(a) on valittu", + "ApplyTagsHelpTextHowToApplyDownloadClients": "Tunnisteiden käyttö valituissa lataustyökaluissa", + "NotificationStatusAllClientHealthCheckMessage": "Mikään ilmoituspavelu ei ole ongelmien vuoksi käytettävissä.", + "AppUpdatedVersion": "{appName} on päivitetty versioon {version} ja muutosten käyttöönottamiseksi se on käynnistettävä uudelleen.", + "DownloadClientQbittorrentSettingsContentLayout": "Sisällön rakenne", + "EditDownloadClientImplementation": "Muokataan lataustyökalua - {implementationName}", + "DownloadPropersAndRepacksHelpTextWarning": "Käytä mukautettuja muotoja automaattisiin Proper- ja Repack-päivityksiin.", + "PreferredSize": "Toivottu koko", + "RemotePathMappingCheckFilesBadDockerPath": "Käytät Dockeria ja lataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta se ei ole kelvollinen {2}-sijainti. Tarkista etäsijaintien kohdistukset ja lataustyökalun asetukset.", + "RemotePathMappingCheckLocalWrongOSPath": "Paikallinen lataustyökalu \"{0}\" tallentaa lataukset kohteeseen \"{1}\", mutta se ei ole kelvollinen {2}-sijainti. Tarkista lataustyökalun asetukset.", + "RemoveSelectedItemQueueMessageText": "Haluatko varmasti poistaa jonosta 1 kohteen?", + "RemoveTagsAutomatically": "Poista tunnisteet automaattisesti", + "RemoveTagsAutomaticallyHelpText": "Poista tunnisteet automaattisesti, jos ehdot eivät täyty.", + "ReplaceWithSpaceDashSpace": "Korvaa yhdistelmällä \"välilyönti yhdysmerkki välilyönti\"", + "SetTags": "Tunnisteiden määritys", + "SetAppTags": "Määritä {appName}-tunnisteet", + "UpdateSelected": "Päivitä valitut", + "ApplyTagsHelpTextAdd": "– \"Lisää\" syötetyt tunnisteet aiempiin tunnisteisiin", + "ApplyTagsHelpTextRemove": "- \"Poista\" tyhjentää syötetyt tunnisteet", + "DeleteRemotePathMapping": "Poista etäsijainnin kohdistus", + "ApplyChanges": "Toteuta muutokset", + "AutomaticAdd": "Automaattinen lisäys", + "BypassIfHighestQualityHelpText": "Ohitusviive kun julkaisun laatu vastaa laatuprofiilin korkeinta käytössä olevaa laatua halutulla protokollalla.", + "BlocklistReleases": "Lisää julkaisut estolistalle", + "CloneCondition": "Monista ehto", + "ConnectionLost": "Ei yhteyttä", + "ConnectionLostReconnect": "{appName} pyrkii ajoittain muodostamaan yhteyden automaattisesti tai voit painaa alta \"Lataa uudelleen\".", + "CustomFormat": "Mukautettu muoto", + "DeleteConditionMessageText": "Haluatko varmasti poistaa ehdon \"{name}\"?", + "DeleteFormatMessageText": "Haluatko varmasti poistaa muototunnisteen \"{name}\"?", + "DeleteSelectedImportListsMessageText": "Haluatko varmasti poistaa valitut {count} tuontilistaa?", + "DownloadClientCheckUnableToCommunicateMessage": "Viestintä lataustyökalun \"{0}\" kanssa ei onnistu.", + "DownloadClientSortingCheckMessage": "Lataustyökalun \"{0}\" {1} on kytketty käyttöön {appName}in kategorialle ja tuontiongelmien välttämiseksi se tulisi poistaa käytöstä.", + "EditSelectedDownloadClients": "Muokkaa valittuja lataustyökaluja", + "ErrorLoadingContent": "Virhe ladattaessa tätä sisältöä", + "IncludeCustomFormatWhenRenamingHelpText": "Mahdollista tämän muodon käyttö \"{Custom Formats}\" -nimeämiskaavan kanssa.", + "No": "Ei", + "NoDownloadClientsFound": "Lataustyökaluja ei löytynyt", + "NoHistoryBlocklist": "Estohistoriaa ei ole.", + "NotificationStatusSingleClientHealthCheckMessage": "Ilmoitukset eivät ole ongelmien vuoksi käytettävissä: {0}", + "PreferProtocol": "Suosi {preferredProtocol}-protokollaa", + "ProxyCheckBadRequestMessage": "Välityspalvelintesti epäonnistui. Tilakoodi: {0}.", + "QueueIsEmpty": "Jono on tyhjä", + "RecentChanges": "Viimeisimmät muutokset", + "ApplyTagsHelpTextHowToApplyIndexers": "Tunnisteiden käyttö valituissa tietolähteissä", + "RemotePathMappingCheckBadDockerPath": "Käytät Dockeria ja lataustyökalu \"{0}\" tallentaa lataukset kohteeseen \"{1}\", mutta se ei ole kelvollinen {2}-sijainti. Tarkista etäsijaintien kohdistukset ja lataustyökalun asetukset.", + "DeleteSelectedIndexers": "Poista tietoläh(de/teet)", + "RemotePathMappingCheckFilesWrongOSPath": "Etälataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta se ei ole kelvollinen {2}-sijainti. Tarkista etsijaintien kohdistukset lataustyökalun asetukset.", + "RemotePathMappingCheckRemoteDownloadClient": "Etälataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta sitä ei näytä olevan olemassa. Todennäköinen syy on puuttuva tai virheellinen etäsijainnin kohdistus.", + "RemotePathMappingCheckWrongOSPath": "Etälataustyökalu \"{0}\" tallentaa lataukset kohteeseen \"{1}\", mutta se ei ole kelvollinen {2}-sijainti. Tarkista etäsijaintien kohdistukset ja lataustyökalun asetukset.", + "RemotePathMappingsInfo": "Etäsijaintien kohdistuksia tarvitaan harvoin ja jos {appName} ja lataustyökalu suoritetaan samassa järjestelmässä, on parempi käyttää paikallisia polkuja. Lue lisää [wikistä]({wikiLink}).", + "RemoveSelectedItem": "Poista valittu kohde", + "ReplaceWithDash": "Korvaa yhdysmerkillä", + "ReplaceWithSpaceDash": "Korvaa yhdistelmällä \"välilyönti yhdysmerkki\"", + "ResetDefinitionTitlesHelpText": "Palauta määritysten nimet ja arvot.", + "ResetTitlesHelpText": "Palauta määritysten nimet ja arvot.", + "ResetQualityDefinitions": "Palauta laatumääritykset", + "UpdateCheckStartupNotWritableMessage": "Päivitystä ei voida asentaa, koska käyttäjällä \"{1}\" ei ole kirjoitusoikeutta käynnistyskansioon \"{0}\".", + "WhatsNew": "Mitä uutta?", + "Yes": "Kyllä", + "CustomFormats": "Mukautetut muodot", + "CutoffFormatScoreHelpText": "Kun albumi saavuttaa laaturajoituksen tai tämän mukautetun muodon pisteytyksen, ei siihen enää kaapata uusia julkaisuja tai tuoda päivityksiä.", + "DeleteCustomFormat": "Poista mukautettu muoto", + "DeleteCustomFormatMessageText": "Haluatko varmasti poistaa mukautetun muodon \"{name}\"?", + "Disabled": "Ei käytössä", + "DownloadClientCheckDownloadingToRoot": "Lataustyökalu \"{0}\" tallentaa lataukset juurikansioon \"{1}\", mutta ne tulisi tallentaa muualle.", + "DownloadClientStatusCheckAllClientMessage": "Lataustyökaluja ei ole ongelmien vuoksi käytettävissä", + "GroupInformation": "Ryhmän tiedot", + "MinimumCustomFormatScore": "Mukautetun muodon vähimmäispisteytys", + "Monitor": "Valvonta", + "DownloadClientTagHelpText": "Lataustyökalua käytetään vain vähintään yhdellä täsmäävällä tunnisteella merkityille esittäjille. Käytä kaikille jättämällä tyhjäksi.", + "MinFormatScoreHelpText": "Mukautetun muodon vähimmäispisteytys, jolla lataus sallitaan.", + "ExtraFileExtensionsHelpTextsExamples": "Esimerkiksi '\"sub, .nfo\" tai \"sub,nfo\".", + "ExtraFileExtensionsHelpText": "Pilkuin eroteltu listaus tuotavista oheistiedostoista (.nfo-tiedostot tuodaan \".nfo-orig\"-nimellä).", + "Conditions": "Ehdot", + "CountIndexersSelected": "{selectedCount} tietolähde(ttä) on valittu", + "DeleteSelectedDownloadClientsMessageText": "Haluatko varmasti poistaa {count} valit(n/tua) lataustyökalu(n/a)?", + "DeleteSelectedIndexersMessageText": "Haluatko varmasti poistaa {count} valit(un/tua) tietoläh(teen/dettä)?", + "EditSelectedIndexers": "Muokkaa valittuja sisältölähteitä", + "Negated": "Kielletty", + "NegateHelpText": "Jos käytössä, ei mukautettua muotoa sovelleta tämän \"{0}\" -ehdon täsmätessä.", + "NoChange": "Ei muutosta", + "DownloadClientStatusCheckSingleClientMessage": "Lataustyökaluja ei ole ongelmien vuoksi käytettävissä: {0}", + "Clone": "Monista", + "CloneCustomFormat": "Monista mukautettu muoto", + "BypassIfAboveCustomFormatScore": "Ohita, jos ylittää mukautetun muodon pisteytyksen", + "RemoveSelectedItemsQueueMessageText": "Haluatko varmasti poistaa jonosta {0} kohdetta?", + "RemoveFailedDownloads": "Poista epäonnistuneet lataukset", + "RemoveCompletedDownloads": "Poista valmistuneet lataukset", + "AddImportListImplementation": "Lisätään tuontilistaa - {implementationName}", + "AddConditionImplementation": "Lisätään ehtoa - {implementationName}", + "AddConnectionImplementation": "Lisätään kytköstä - {implementationName}", + "IndexerDownloadClientHealthCheckMessage": "Tietolähteet virheellisillä lataustyökaluilla: {0}.", + "IndexerStatusCheckAllClientMessage": "Tietolähteet eivät ole käytettävissä virheiden vuoksi", + "MinimumCustomFormatScoreHelpText": "Mukautetun muodon vähimmäispisteytys, jolla ensisijaisen protokollan viiveen ohitus sallitaan.", + "Monitoring": "Valvotaan", + "NoIndexersFound": "Tietolähteitä ei löytynyt", + "RemotePathMappingCheckFilesLocalWrongOSPath": "Paikallinen lataustyökalu \"{0}\" ilmoitti tiedostosijainniksi \"{1}\", mutta se ei ole kelvollinen {2}-sijainti. Tarkista lataustyökalun asetukset.", + "Formats": "Muodot", + "AuthBasic": "Perus (ponnahdusikkuna)", + "AuthForm": "Lomake (kirjautumissivu)", + "DeleteSelectedDownloadClients": "Poista lataustyökalu(t)", + "AllResultsAreHiddenByTheAppliedFilter": "Aktiivinen suodatin piilottaa kaikki tulokset.", + "ColonReplacement": "Kaksoispisteen korvaus", + "GrabId": "Kaappauksen tunniste", + "InfoUrl": "Tietojen URL", + "EditIndexerImplementation": "Muokataan tietolähdettä - {implementationName}", + "DisabledForLocalAddresses": "Ei käytössä paikallisille osoitteille", + "ApplyTagsHelpTextReplace": "- \"Korvaa\" nykyiset tunnisteet syötetyillä tai tyhjennä kaikki tunnisteet jättämällä tyhjäksi", + "AutoTagging": "Automaattinen tunnistemerkintä", + "AutoTaggingNegateHelpText": "Jos käytössä, ei automaattista merkintäsääntöä käytetä tämän \"{implementationName}\" -ehdon täsmätessä.", + "AutoTaggingLoadError": "Virhe ladattaessa automaattimerkintää", + "ClearBlocklist": "Tyhjennä estolista", + "ChownGroup": "chown-ryhmä", + "ClearBlocklistMessageText": "Haluatko varmasti tyhjentää kaikki estolistan kohteet?", + "ConditionUsingRegularExpressions": "Ehto vastaa säännöllisiä lausekkeita. Huomioi, että merkeillä \"\\^$.|?*+()[{\" on erityismerkityksiä ja ne on erotettava \"\\\"-merkillä.", + "ConnectionLostToBackend": "{appName} kadotti yhteyden taustajärjestelmään ja se on käynnistettävä uudelleen.", + "CloneAutoTag": "Monista automaattimerkintä", + "DeleteCondition": "Poista ehto", + "DeleteAutoTagHelpText": "Haluatko varmasti poistaa automaattitunnisteen '\"0}\"?", + "DeleteAutoTag": "Poista automaattitunniste", + "DeleteRemotePathMappingMessageText": "Haluatko varmasti poistaa tämän etäsijainnin kohdistuksen?", + "DeleteSelectedImportLists": "Poista tuontilista(t)", + "DeleteSpecificationHelpText": "Haluatko varmasti poistaa määrityksen \"{name}\"?", + "DeleteSpecification": "Poista määritys", + "DownloadClientCheckNoneAvailableMessage": "Lataustyökaluja ei ole käytettävissä", + "EditConditionImplementation": "Muokataan ehtoa - {implementationName}", + "EditConnectionImplementation": "Muokataan kytköstä - {implementationName}", + "EditAutoTag": "Muokkaa automaattimerkintää", + "ManageIndexers": "Hallitse tietolähteitä", + "RenameFiles": "Nimeä tiedostot", + "Small": "Pieni", + "RemoveSelectedItems": "Poista valitut kohteet", + "ResetTitles": "Palauta nimet", + "AddNewArtistRootFolderHelpText": "\"{folder}\" -alikansio luodaan automaattisesti.", + "AuthenticationRequiredUsernameHelpTextWarning": "Syötä uusi käyttäjätunnus", + "AutoAdd": "Automaattilisäys", + "DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "Lataustyökalu \"{0}\" on määritetty poistamaan valmistuneet lataukset, jonka seuraksena ne saatetaan poistaa ennen kuin {1} ehtii tuoda niitä.", + "Enabled": "Käytössä", + "RemotePathMappingCheckLocalFolderMissing": "Etälataustyökalu \"{0}\" tallentaa lataukset kohteeseen \"{1}\", mutta sitä ei näytä olevan olemassa. Todennäköinen syy on puuttuva tai virheellinen etäsijainnin kohdistus.", + "UpdateAvailable": "Uusi päivitys on saatavilla", + "UpdateMonitoring": "Päivitä valvontatila", + "ApplyTagsHelpTextHowToApplyImportLists": "Tunnisteiden käyttö valituissa tuontilistoissa", + "AutomaticUpdatesDisabledDocker": "Automaattisia päivityksiä ei tueta suoraan käytettäessä Dockerin päivitysmekanismia. Docker-säiliö on päivitettävä {appName}in ulkopuolella tai päivitys on suoritettava komentosarjalla.", + "UpdateCheckUINotWritableMessage": "Päivityksen asennus ei onnistu, koska käyttäjällä \"{1}\" ei ole kirjoitusoikeutta käyttöliittymäkansioon \"{0}\".", + "AuthenticationMethodHelpTextWarning": "Valitse sopiva tunnistautumistapa", + "AuthenticationMethod": "Tunnistautumistapa", + "AuthenticationRequiredHelpText": "Valitse mitkä pyynnöt vaativat tunnistautumisen. Älä muuta, jos et ymmärrä riskejä.", + "AuthenticationRequired": "Vaadi tunnistautuminen", + "CustomFormatScore": "Mukautetun muodon pisteytys", + "EditImportListImplementation": "Muokataan tuontilistaa - {implementationName}", + "Overview": "Yleiskatsaus", + "Posters": "Julisteet", + "PosterOptions": "Julistenäkymän asetukset", + "OverviewOptions": "Yleiskatsauksen asetukset", + "RemotePathMappingCheckDockerFolderMissing": "Käytät Dockeria ja lataustyökalu \"{0}\" tallentaa lataukset kohteeseen \"{1}\", mutta sitä ei löydy Docker-säiliöstä. Tarkista etäsijaintien kohdistukset ja säiliön tallennusmedian asetukset.", + "ResetQualityDefinitionsMessageText": "Haluatko varmasti palauttaa laatumääritykset?", + "SystemTimeCheckMessage": "Järjestelmän ajassa on ainakin vuorokauden heitto eivätkä ajoitetut tehtävät tämän vuoksi toimi oikein ennen kuin se on korjattu.", + "UnableToLoadInteractiveSearch": "Tämän albumihaun tulosten lataus ei onnistu. Yritä uudelleen.", + "AutoTaggingRequiredHelpText": "Tämän \"{implementationName}\" -ehdon on täsmättävä automaattimerkinnän säännön käyttämiseksi. Muutoin yksittäinen \"{implementationName}\" -vastaavuus riittää.", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Vahvista uusi salasana", + "Connection": "Yhteys", + "Large": "Suuri", + "ManageDownloadClients": "Hallitse lataustyökaluja", + "AuthenticationRequiredPasswordHelpTextWarning": "Syötä uusi salasana", + "Table": "Taulukko", + "BypassIfAboveCustomFormatScoreHelpText": "Käytä ohitusta, kun julkaisun pisteytys on määritetyn mukautetun muodon vähimmäispisteytystä korkeampi.", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Määrittää käytetäänkö qBittorrentista määritettyä rakennetta, torrentin alkuperäistä rakennetta vai luodaanko uusi alikansio (qBittorrent 4.3.2+).", + "ExistingTag": "Tunniste on jo olemassa", + "External": "Ulkoinen", + "Negate": "Kiellä", + "FailedDownloadHandling": "Latauksen käsittely epäonnistui", + "NoEventsFound": "Tapahtumia ei löytynyt", + "Implementation": "Toteutus", + "OnHealthRestored": "Terveystilan vakautuessa", + "ApiKeyValidationHealthCheckMessage": "Muuta API-avaimesi ainakin {0} merkin pituiseksi. Voit tehdä tämän asetuksista tai muokkaamalla asetustiedostoa.", + "FailedLoadingSearchResults": "Hakutulosten lataus epäonnistui. Yritä uudelleen.", + "ManageImportLists": "Tuontilistojen hallinta", + "SelectReleaseGroup": "Aseta julkaisuryhmä", + "InvalidUILanguage": "Käytöliittymän kielivalinta on virheellinen. Korjaa se ja tallenna asetukset.", + "HealthMessagesInfoBox": "Saat lisätietoja näiden vakausviestien syistä painamalla rivin lopussa olevaa wikilinkkiä (kirjakuvake) tai tarkastelemalla [lokitietoja]({link}). Mikäli kohtaat ongelmia näiden viestien tulkinnassa, tavoitat tukemme alla olevilla linkkeillä.", + "ManageLists": "Listojen hallunta", + "PasswordConfirmation": "Salasanan vahvistus", + "QueueFilterHasNoItems": "Mikään kohde ei vastaa valittua jonon suodatinta", + "EditSelectedImportLists": "Muokkaa valittuja tuontilistoja", + "AutoRedownloadFailedFromInteractiveSearchHelpText": "Etsi automaattisesti ja pyri lataamaan eri julkaisu vaikka epäonnistunut julkaisu oli kaapattu manuaalihausta.", + "IgnoreDownload": "Ohita lataus", + "IgnoreDownloadHint": "Estää {appName}ia käsittelemästä tätä latausta jatkossa.", + "IgnoreDownloads": "Ohita lataukset", + "IgnoreDownloadsHint": "Estää {appName}ia käsittelemästä näitä latauksia jatkossa.", + "ListRefreshInterval": "Listan päivityksen ajoitus", + "IndexerSettingsRejectBlocklistedTorrentHashes": "Hylkää estetyt torrent-hajautusarvot kaapattaessa", + "IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "Jos torrent on estetty hajautusarvon perusteella sitä ei välttämättä hylätä oikein etsittäessä joiltakin tietolähteiltä RSS-syötteen tai haun välityksellä. Tämä mahdollistaa tällaisten torrentien hylkäämisen kaappauksen jälkeen, mutta ennen välitystä lataustyökalulle.", + "ListWillRefreshEveryInterp": "Lista päivitetään {0} välein", + "NoImportListsFound": "Tuotilistoja ei löytynyt", + "ManageClients": "Hallitse työkaluja", + "CustomFormatsSpecificationRegularExpressionHelpText": "Mukautetun muodon säännöllisen lausekkeen kirjainkokoa ei huomioida.", + "DownloadClientPriorityHelpText": "Lautaustyökalujen painotus, 1– 50 (korkein-alin). Oletusarvo on 1 ja tasaveroiset erotetaan Round-Robin-tekniikalla.", + "SkipRedownloadHelpText": "Estää {appName}ia lataamasta vaihtoehtoisia julkaisuja poistetuille kohteille.", + "BypassIfHighestQuality": "Ohita, jos korkein laatu", + "RemoveQueueItemRemovalMethodHelpTextWarning": "\"Poista lataustyökalusta\" poistaa latauksen ja sen tiedostot.", + "UpdateFiltered": "Päivitä suodatetut", + "BlocklistAndSearch": "Estolista ja haku", + "BlocklistAndSearchHint": "Etsi korvaavaa kohdetta kun kohde lisätään estolistalle.", + "BlocklistAndSearchMultipleHint": "Etsi korvaavia kohteita kun kohteita lisätään estolistalle.", + "BlocklistMultipleOnlyHint": "Lisää estolistalle etsimättä korvaavia kohteita.", + "BlocklistOnly": "Vain esto", + "BlocklistOnlyHint": "Lisää estolistalle etsimättä korvaavaa kohdetta.", + "ChangeCategory": "Vaihda kategoria", + "CustomFormatsSpecificationRegularExpression": "Säännöllinen lauseke", + "Deceased": "Kuollut", + "DoNotBlocklist": "Älä estä", + "DoNotBlocklistHint": "Poista lisäämättä estolistalle.", + "RemoveFromDownloadClientHint": "Poistaa latauksen ja ladatut tiedostot lataustyökalusta.", + "RemoveMultipleFromDownloadClientHint": "Poistaa latauksen ja ladatut tiedostot lataustyökalusta.", + "RemoveQueueItemRemovalMethod": "Poistotapa", + "RemoveQueueItemsRemovalMethodHelpTextWarning": "\"Poista lataustyökalusta\" poistaa lataukset ja niiden tiedostot.", + "ThereWasAnErrorLoadingThisItem": "Virhe ladattaessa kohdetta", + "ThereWasAnErrorLoadingThisPage": "Virhe ladattaessa sivua", + "FilterAlbumPlaceholder": "Suodata albumeja", + "AddImportListExclusionAlbumHelpText": "Estä {appName}ia lisäämästä albumia listoilta.", + "ImportListRootFolderMultipleMissingRootsHealthCheckMessage": "Useita tuontilistojen juurikansioita puuttuu: {0}", + "FilterArtistPlaceholder": "Suodata esittäjiä", + "AddImportListExclusionArtistHelpText": "Estä {appName}ia lisäämästä esittäjää listoilta.", + "RootFolderCheckMultipleMessage": "Useita juurikansioita puuttuu: {0}", + "DeleteArtistFolders": "Poista esittäjäkansiot", + "SomeResultsAreHiddenByTheAppliedFilter": "Aktiivinen suodatin piilottaa joitakin tuloksia.", + "RemotePathMappingCheckFileRemoved": "Tiedosto \"{0}\" poistettiin kesken käsittelyn.", + "AddListExclusionHelpText": "Estä {appName}ia lisäämästä esittäjää listoilta.", + "ArtistsEditRootFolderHelpText": "Siirtämällä esittäjät samaan juurikansioon voidaan niiden kansioiden nimet päivittää vastaamaan päivittynyttä nimikettä tai nimeämiskaavaa.", + "DownloadClientAriaSettingsDirectoryHelpText": "Valinnainen latuasten tallennussijainti. Käytä Aria2-oletusta jättämällä tyhjäksi.", + "DeleteArtistFoldersHelpText": "Poista esittäjäkansiot ja niiden kaikki sisältö.", + "ChangeCategoryHint": "Vaihtaa latauksen kategoriaksi lataustyökalun \"Tuonnin jälkeinen kategoria\" -asetuksen kategorian.", + "ChangeCategoryMultipleHint": "Vaihtaa latausten kategoriaksi lataustyökalun \"Tuonnin jälkeinen kategoria\" -asetuksen kategorian.", + "AutoRedownloadFailedFromInteractiveSearch": "Uudelleenlataus manuaalihaun tuloksista epäonnistui" } diff --git a/src/NzbDrone.Core/Localization/Core/fr.json b/src/NzbDrone.Core/Localization/Core/fr.json index e77c69c67..a1bfbc219 100644 --- a/src/NzbDrone.Core/Localization/Core/fr.json +++ b/src/NzbDrone.Core/Localization/Core/fr.json @@ -64,7 +64,7 @@ "Component": "Composant", "Connections": "Connexions", "ConnectSettings": "Paramètres de connexion", - "CopyUsingHardlinksHelpText": "Utiliser des liens fixes quand on essaye de copier des fichiers appartenant à des torrents en cours de partage", + "CopyUsingHardlinksHelpText": "Les liens fixes permettent à {appName} d'importer des torrents seedés dans le dossier de l'artiste sans prendre d'espace disque supplémentaire ou copier tout le contenu du fichier. Les liens fixes ne fonctionnent que si la source et la destination se trouvent sur le même volume.", "CopyUsingHardlinksHelpTextWarning": "De temps en temps, des verrouillages de fichiers peuvent empêcher de renommer des fichiers qui sont en cours de partage. Vous pouvez temporairement arrêter le partage et utiliser la fonction de renommage de {appName} comme solution de contournement.", "CreateEmptyArtistFolders": "Créer des dossiers films vides", "CreateEmptyArtistFoldersHelpText": "Créer les dossiers films manquants pendant le scan du disque", @@ -72,7 +72,7 @@ "CutoffHelpText": "Quand cette qualité est atteinte, {appName} ne téléchargera plus de films", "CutoffUnmet": "Seuil non atteint", "Dates": "Dates", - "DBMigration": "Migration de la base de données", + "DatabaseMigration": "Migration de la base de données", "DelayProfiles": "Profils de retard", "Delete": "Supprimer", "DeleteBackup": "Supprimer la sauvegarde", @@ -97,15 +97,15 @@ "DeleteRootFolderMessageText": "Êtes-vous sûr de vouloir supprimer le dossier racine « {name} » ?", "DeleteSelectedTrackFiles": "Supprimer les fichiers film sélectionnés", "DeleteSelectedTrackFilesMessageText": "Voulez-vous vraiment supprimer les fichiers vidéo sélectionnés ?", - "DeleteTag": "Supprimer le tag", - "DeleteTagMessageText": "Voulez-vous vraiment supprimer la balise '{0}' ?", + "DeleteTag": "Supprimer l'étiquette", + "DeleteTagMessageText": "Voulez-vous vraiment supprimer l'étiquette '{label}' ?", "DeleteTrackFileMessageText": "Voulez-vous vraiment supprimer {0} ?", "DestinationPath": "Chemin de destination", "DetailedProgressBar": "Barre de progression détaillée", "DetailedProgressBarHelpText": "Afficher le texte sur la barre de progression", "DiskSpace": "Espace disque", "DownloadClient": "Client de téléchargement", - "DownloadClients": "Clients de téléchargement", + "DownloadClients": "Clients de télécharg.", "DownloadClientSettings": "Télécharger les paramètres client", "DownloadFailedCheckDownloadClientForMoreDetails": "Téléchargement échoué : voir le client de téléchargement pour plus de détails", "DownloadFailedInterp": "Échec du téléchargement : {0}", @@ -127,7 +127,6 @@ "ErrorLoadingContents": "Erreur lors du chargement du contenu", "ErrorLoadingPreviews": "Erreur lors du chargement des aperçus", "Exception": "Exception", - "ExtraFileExtensionsHelpTexts1": "Liste séparée par des virgules des fichiers supplémentaires à importer (.nfo sera importé en tant que .nfo-orig)", "FileDateHelpText": "Changer la date du fichier lors de l'import/re-scan", "FileManagement": "Gestion de fichiers", "Filename": "Nom de fichier", @@ -164,7 +163,6 @@ "ImportExtraFilesHelpText": "Importer les fichiers extra correspondants (sous-titres, .nfo etc.) après avoir importé un fichier film", "ImportFailedInterp": "Importation a échoué : {0}", "Importing": "Importation", - "IncludeHealthWarningsHelpText": "Inclure avertissements santé", "IncludeUnknownArtistItemsHelpText": "Afficher les éléments sans film dans la file d'attente. Cela peut inclure des films supprimés ou tout autre élément de la catégorie de {appName}", "IncludeUnmonitored": "Inclure les non surveillés", "Indexer": "Indexeur", @@ -182,7 +180,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} prend en charge tout client de téléchargement qui utilise le standard Newznab, ainsi que d'autres clients de téléchargement répertoriés ci-dessous.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} prend en charge tout indexeur qui utilise le standard Newznab, ainsi que d'autres indexeurs répertoriés ci-dessous.", "LidarrTags": "{appName} Tags", - "LoadingTrackFilesFailed": "Le chargement des fichiers vidéo a échoué", "Local": "Locale", "LocalPath": "Chemin local", "LocalPathHelpText": "Chemin local que {appName} doit utiliser pour accéder au chemin distant", @@ -216,15 +213,9 @@ "NoBackupsAreAvailable": "Aucune sauvegarde n'est disponible", "NoHistory": "Aucun historique.", "NoLeaveIt": "Non, laisse tomber", - "NoLimitForAnyRuntime": "Aucune limite pour aucune durée d'exécution", "NoLogFiles": "Aucun fichier journal", - "NoMinimumForAnyRuntime": "Aucun minimum pour aucune durée d'exécution", "None": "Aucun", "NoUpdatesAreAvailable": "Aucune mise à jour n'est disponible", - "OnGrabHelpText": "À la Récupération", - "OnHealthIssueHelpText": "Lors d'un problème de santé", - "OnRenameHelpText": "Lors du changement de nom", - "OnUpgradeHelpText": "Lors de la mise à niveau", "OpenBrowserOnStart": "Ouvrir le navigateur au démarrage", "Options": "Options", "Original": "Original", @@ -233,12 +224,11 @@ "PageSizeHelpText": "Nombre d'éléments à afficher sur chaque page", "Password": "Mot de passe", "Path": "Chemin", - "Permissions": "Permissions", + "Permissions": "Autorisations", "Port": "Port", "PortNumber": "Numéro de port", "PosterSize": "Poster taille", "PreviewRename": "Aperçu Renommer", - "PriorityHelpText": "Priorité de l'indexeur de 1 (la plus élevée) à 50 (la plus basse). Valeur par défaut : 25. Utilisé lors de la récupération des versions comme départage pour des versions par ailleurs égales, {appName} utilisera toujours tous les indexeurs activés pour la synchronisation RSS et la recherche.", "Profiles": "Profils", "Proper": "Approprié", "PropersAndRepacks": "Propres et Repacks", @@ -402,7 +392,7 @@ "UnmonitoredHelpText": "Inclure les films non surveillés dans le flux iCal", "UpdateAll": "Tout actualiser", "UpdateAutomaticallyHelpText": "Téléchargez et installez automatiquement les mises à jour. Vous pourrez toujours installer à partir du système : mises à jour", - "UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré de {appName} ou un script", + "UpdateMechanismHelpText": "Utilisez le programme de mise à jour intégré de {appName} ou un script", "UpdateScriptPathHelpText": "Chemin d'accès à un script personnalisé qui prend un package de mise à jour extrait et gère le reste du processus de mise à jour", "UpgradeAllowedHelpText": "Si désactivé, les qualités ne seront pas améliorées", "Uptime": "Disponibilité", @@ -419,8 +409,8 @@ "WeekColumnHeader": "En-tête de colonne de la semaine", "Year": "Année", "YesCancel": "Oui, annuler", - "20MinutesTwenty": "20 Minutes: {0}", - "45MinutesFourtyFive": "45 Minutes: {0}", + "20MinutesTwenty": "20 Minutes : {0}", + "45MinutesFourtyFive": "45 Minutes : {0}", "60MinutesSixty": "60 Minutes : {0}", "AgeWhenGrabbed": "Âge (au moment de la saisie)", "AlbumIsDownloadingInterp": "L'album est en cours de téléchargement - {0}% {1}", @@ -440,7 +430,7 @@ "ScriptPath": "Chemin du script", "Search": "Rechercher", "SearchAll": "Tout rechercher", - "SearchForMissing": "Recherche des manquants", + "SearchForMissing": "Rechercher les manquants", "SearchSelected": "Rechercher la sélection", "Season": "Saison", "Security": "Sécurité", @@ -494,7 +484,6 @@ "AlbumStudio": "Album Studio", "RemoveCompleted": "Supprimer terminé", "OnApplicationUpdate": "Sur la mise à jour de l'application", - "OnApplicationUpdateHelpText": "Lors de la mise à jour de l'app", "Duration": "Durée", "RemoveFailed": "Échec de la suppression", "RemoveDownloadsAlert": "Les paramètres de suppression ont été déplacés vers les paramètres individuels du client de téléchargement dans le tableau ci-dessus.", @@ -509,7 +498,7 @@ "DefaultLidarrTags": "Tags {appName} par défaut", "DefaultMetadataProfileIdHelpText": "Profil de métadonnées par défaut pour les auteurs détectés dans ce dossier", "DefaultQualityProfileIdHelpText": "Profil de qualité par défaut pour les auteurs détectés dans ce dossier", - "DefaultTagsHelpText": "Profil de métadonnées par défaut pour les auteurs détectés dans ce dossier", + "DefaultTagsHelpText": "Etiquettes {appName} par défaut pour les artistes détectés dans ce dossier", "DefaultMonitorOptionHelpText": "Quels livres doivent être surveillés lors de l'ajout initial pour les auteurs détectés dans ce dossier", "FutureAlbumsData": "Surveiller les livres qui ne sont pas encore sortis", "MetadataProfiles": "profil de métadonnées", @@ -534,7 +523,7 @@ "AddRootFolder": "Ajouter un dossier racine", "AfterManualRefresh": "Après le rafraîchissement manuel", "Age": "Âge", - "Albums": "Album", + "Albums": "Albums", "All": "Tout", "AllFiles": "Tous les fichiers", "AllMonitoringOptionHelpText": "Surveiller les auteurs et tous les livres pour chaque auteur inclus dans la liste d'importation", @@ -567,7 +556,7 @@ "Genres": "Genres", "Grabbed": "Saisie", "HardlinkCopyFiles": "Lien physique/Copie de fichiers", - "HideAdvanced": "Masquer param. av.", + "HideAdvanced": "Masquer les Options Avancées", "Ignored": "Ignoré", "IndexerDownloadClientHelpText": "Spécifiez quel client de téléchargement est utilisé pour les récupérations à partir de cet indexeur", "IndexerTagHelpText": "Utiliser seulement cet indexeur pour les films avec au moins un tag correspondant. Laissez vide pour l'utiliser avec tous les films.", @@ -678,7 +667,7 @@ "CustomFormat": "Format personnalisé", "CustomFormatRequiredHelpText": "Cette {0} condition doit correspondre pour que le format personnalisé s'applique. Sinon, une seule correspondance {1} est suffisante.", "CustomFormatSettings": "Réglages Formats Personnalisés", - "CustomFormats": "Formats personnalisés", + "CustomFormats": "Formats perso.", "Customformat": "Format Personnalisé", "CutoffFormatScoreHelpText": "Quand ce score de format personnalisé est atteint, {appName} ne téléchargera plus de films", "DeleteCustomFormat": "Supprimer le format personnalisé", @@ -727,7 +716,7 @@ "IndexerRssHealthCheckNoIndexers": "Aucun indexeur disponible avec la synchronisation RSS activée, {appName} ne récupérera pas automatiquement les nouvelles versions", "IndexerSearchCheckNoAutomaticMessage": "Aucun indexeur disponible avec la recherche automatique activée, {appName} ne fournira aucun résultat de recherche automatique", "IndexerSearchCheckNoAvailableIndexersMessage": "Tous les indexeurs compatibles avec la recherche sont temporairement indisponibles en raison d'erreurs d'indexation récentes", - "IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, {appName} ne fournira aucun résultat de recherche interactive", + "IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur actif n'est disponible avec la recherche interactive, {appName} ne fournira aucun résultat lors d'une recherche interactive", "IndexerStatusCheckAllClientMessage": "Tous les indexeurs sont indisponibles en raison d'échecs", "IndexerStatusCheckSingleClientMessage": "Indexeurs indisponibles en raison d'échecs : {0}", "Loading": "Chargement", @@ -792,7 +781,6 @@ "RemoveSelectedItemBlocklistMessageText": "Êtes-vous sûr de vouloir supprimer les films sélectionnés de la liste noire ?", "RemovingTag": "Supprimer la balise", "ResetTitlesHelpText": "Réinitialiser les titres des définitions ainsi que les valeurs", - "RemoveFromDownloadClientHelpTextWarning": "La suppression supprimera le téléchargement et le(s) fichier(s) du client de téléchargement.", "RemoveSelectedItemQueueMessageText": "Êtes-vous sûr de vouloir supprimer 1 élément de la file d'attente ?", "RemoveSelectedItemsQueueMessageText": "Voulez-vous vraiment supprimer {0} éléments de la file d'attente ?", "Yes": "Oui", @@ -854,14 +842,12 @@ "PreferProtocol": "Préféré {preferredProtocol}", "DeleteCondition": "Supprimer la condition", "IsShowingMonitoredUnmonitorSelected": "Arrêter de surveiller la sélection", - "ExtraFileExtensionsHelpTexts2": "« Exemples : ».sub", "NoMissingItems": "Aucun élément manquant", "DashOrSpaceDashDependingOnName": "Tiret ou espace puis tiret selon le nom", "MassAlbumsCutoffUnmetWarning": "Êtes-vous sûr de vouloir rechercher tous les albums « {0} » Cutoff Unmet ?", "ShouldMonitorExisting": "Surveiller les albums existants", "UnmappedFiles": "Fichiers non mappés", "DownloadImported": "Télécharger Importé", - "OnArtistDeleteHelpText": "Lors de la suppression de l'artiste", "FilterArtistPlaceholder": "Filtrer l'artiste", "FilterAlbumPlaceholder": "Filtrer l'album", "LatestAlbumData": "Surveillez les derniers albums et les futurs albums", @@ -892,9 +878,7 @@ "IsShowingMonitoredMonitorSelected": "Surveillance sélectionnée", "Monitoring": "Surveillance", "OnArtistDelete": "Lors de la suppression de l'artiste", - "OnImportFailureHelpText": "En cas d'échec de l'importation", "OnReleaseImport": "Lors de l'importation de la version", - "OnTrackRetagHelpText": "Lors de l’étiquetage de la piste", "RemotePathMappingsInfo": "Les mappages de chemins distants sont très rarement requis. Si {appName} et votre client de téléchargement sont sur le même système, il est préférable de faire correspondre vos chemins. Pour plus d'informations, consultez le [wiki]({wikiLink})", "Retag": "Réétiqueter", "RootFolderPath": "Chemin du dossier racine", @@ -928,7 +912,6 @@ "MonitorNewItemsHelpText": "Quels nouveaux albums doivent être surveillés", "MusicBrainzReleaseID": "ID de version MusicBrainz", "OnDownloadFailure": "En cas d'échec de téléchargement", - "OnDownloadFailureHelpText": "En cas d'échec de téléchargement", "PastDays": "Jours passés", "PrimaryTypes": "Types principaux", "RemoveCompletedDownloads": "Supprimer les téléchargements terminés", @@ -1020,7 +1003,6 @@ "MissingTracksArtistNotMonitored": "Pistes manquantes (artiste non surveillé)", "MultiDiscTrackFormat": "Format de piste multi-disque", "MusicBrainzAlbumID": "Identifiant de l'album MusicBrainz", - "OnAlbumDeleteHelpText": "Lors de la suppression de l'album", "PreviewRetag": "Aperçu du réétiquetage", "PrimaryAlbumTypes": "Types d'albums principaux", "CountAlbums": "{albumCount} albums", @@ -1047,14 +1029,11 @@ "EditImportListImplementation": "Modifier la liste d'importation - {implementationName}", "ManageImportLists": "Gérer les listes d'importation", "ManageLists": "Gérer les listes", - "LoadingAlbumsFailed": "Le chargement des albums a échoué", "NoCutoffUnmetItems": "Aucun élément non satisfait", "NoneMonitoringOptionHelpText": "Ne pas surveillez les artistes ou les albums", "NotDiscography": "Pas de discographie", "OnAlbumDelete": "Lors de la suppression de l'album", - "OnHealthRestoredHelpText": "Sur la santé restaurée", "OnImportFailure": "En cas d'échec de l'importation", - "OnReleaseImportHelpText": "Lors de l'importation de la version", "PastDaysHelpText": "Jours pour le flux iCal pour se pencher sur le passé", "PathHelpText": "Dossier racine contenant votre bibliothèque musicale", "QualityProfileIdHelpText": "Les éléments de la liste du profil de qualité doivent être ajoutés avec", @@ -1065,7 +1044,7 @@ "WatchRootFoldersForFileChanges": "Surveillez les dossiers racine pour les modifications de fichiers", "ExpandBroadcastByDefaultHelpText": "Diffuser", "ExpandEPByDefaultHelpText": "EPs", - "CountArtistsSelected": "{selectedCount} artiste(s) sélectionné(s)", + "CountArtistsSelected": "{count} artiste(s) sélectionné(s)", "ImportListSettings": "Paramètres généraux de la liste d'importation", "IndexerIdHelpText": "Spécifiez à quel indexeur le profil s'applique", "IsExpandedHideAlbums": "Masquer les albums", @@ -1094,12 +1073,12 @@ "AuthenticationRequiredPasswordHelpTextWarning": "Saisir un nouveau mot de passe", "AuthenticationRequiredUsernameHelpTextWarning": "Saisir un nouveau nom d'utilisateur", "Auto": "Auto", - "PosterOptions": "Poster options", + "PosterOptions": "Paramètres des affiches", "Table": "Tableau", "AddNewArtistSearchForMissingAlbums": "Lancer la recherche de film manquant", - "AlbumsLoadError": "Impossible de charger les sauvegardes", + "AlbumsLoadError": "Impossible de charger les albums", "AddListExclusionHelpText": "Empêcher les séries d'être ajoutées à Sonarr par des listes", - "AlbumStudioTruncated": "Seules les 25 dernières saisons sont affichées, allez aux détails pour voir toutes les saisons", + "AlbumStudioTruncated": "Seuls les 25 derniers albums sont affichés, allez dans les détails pour voir tous les albums", "DeleteArtistFolderCountWithFilesConfirmation": "Voulez-vous vraiment supprimer {count} séries sélectionnées et tous les contenus ?", "DeleteArtistFolderHelpText": "Supprimer le dossier de la série et son contenu", "Large": "Grand", @@ -1121,7 +1100,7 @@ "AuthenticationRequiredWarning": "Pour empêcher l'accès à distance sans authentification, {appName} exige désormais que l'authentification soit activée. Vous pouvez éventuellement désactiver l'authentification pour les adresses locales.", "UpdateFiltered": "Mise à jour filtrée", "AddAutoTag": "Ajouter un tag automatique", - "AddAutoTagError": "Impossible d'ajouter un tag automatique, réessayer.", + "AddAutoTagError": "Impossible d'ajouter un nouveau tag automatique, veuillez réessayer.", "AddCondition": "Ajouter une condition", "AddConditionError": "Impossible d'ajouter une nouvelle condition, Réessayer.", "QueueFilterHasNoItems": "Le filtre de file d'attente sélectionné ne contient aucun élément", @@ -1145,5 +1124,66 @@ "EditAutoTag": "Modifier la balise automatique", "Negate": "Nier", "OverviewOptions": "Options de présentation", - "RegularExpressionsCanBeTested": "Les expressions régulières peuvent être testées [ici](http://regexstorm.net/tester)." + "RegularExpressionsCanBeTested": "Les expressions régulières peuvent être testées [ici](http://regexstorm.net/tester).", + "DownloadClientQbittorrentSettingsContentLayout": "Disposition du contenu", + "NoLimitForAnyDuration": "Aucune limite pour aucune durée d'exécution", + "NoMinimumForAnyDuration": "Aucun minimum pour aucune durée d'exécution", + "PreferredSize": "Taille préférée", + "Unlimited": "Illimité", + "ExtraFileExtensionsHelpText": "Liste de fichiers supplémentaires séparés par des virgules à importer (.nfo sera importé en tant que .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Exemples : '.sub, .nfo' ou 'sub,nfo'", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Utiliser la disposition du contenu configurée par qBittorrent, la disposition originale du torrent ou toujours créer un sous-dossier (qBittorrent 4.3.2+)", + "DownloadClientPriorityHelpText": "Priorité du client de téléchargement de 1 (la plus haute) à 50 (la plus faible). Par défaut : 1. Le Round-Robin est utilisé pour les clients ayant la même priorité.", + "ArtistMonitoring": "Suivi des artistes", + "AddAlbumWithTitle": "Ajouter {albumTitle}", + "AddArtistWithName": "Ajouter {artistName}", + "AddNewAlbumSearchForNewAlbum": "Lancer la recherche de nouvel album", + "AlbumDetails": "Détails de l'album", + "AlbumStudioTracksDownloaded": "{trackFileCount}/{totalTrackCount} pistes téléchargées", + "ArtistIsMonitored": "Artiste surveillé", + "ArtistIsUnmonitored": "Artiste non surveillé", + "BannerOptions": "Options de la bannière", + "Banners": "Bannières", + "ArtistProgressBarText": "{trackFileCount} / {trackCount} (Total: {totalTrackCount})", + "BlocklistAndSearch": "Liste de blocage et recherche", + "BlocklistAndSearchHint": "Lancer la recherche d'un remplaçant après l'inscription sur la liste de blocage", + "BlocklistAndSearchMultipleHint": "Lancer la recherche de remplaçants après l'inscription sur la liste de blocage", + "BlocklistMultipleOnlyHint": "Liste de blocage sans recherche de remplaçants", + "BlocklistOnly": "Liste de blocage uniquement", + "BlocklistOnlyHint": "Liste de blocage sans recherche de remplaçant", + "ChangeCategory": "Changer de catégorie", + "ChangeCategoryHint": "Modifie le téléchargement dans la \"catégorie post-importation\" du client de téléchargement", + "ChangeCategoryMultipleHint": "Modifie les téléchargements dans la \"catégorie post-importation\" du client de téléchargement", + "AutoRedownloadFailed": "Échec du retéléchargement", + "AutoRedownloadFailedFromInteractiveSearch": "Échec du retéléchargement à partir de la recherche interactive", + "AutoRedownloadFailedFromInteractiveSearchHelpText": "Lance une recherche automatique et une tentative de téléchargement d'une version différente si la version trouvée automatiquement échoue", + "CustomFormatsSpecificationRegularExpression": "Expression régulière", + "CustomFormatsSpecificationRegularExpressionHelpText": "Format personnalisé RegEx est insensible à la casse", + "Deceased": "Décédé", + "DownloadClientAriaSettingsDirectoryHelpText": "Emplacement facultatif pour les téléchargements, laisser vide pour utiliser l'emplacement par défaut Aria2", + "IndexerSettingsRejectBlocklistedTorrentHashes": "Rejeter les hachages de torrents bloqués lors de la saisie", + "TrackFilesLoadError": "Impossible de charger les fichiers de pistes", + "SetAppTags": "Définir les étiquettes de {nom de l'application}", + "TrackFileMissingTooltip": "Fichier de la piste manquant", + "TrackFileDeletedTooltip": "Fichier de la piste supprimé", + "TrackFileRenamedTooltip": "Fichier de la piste renommé", + "TrackFileTagsUpdatedTooltip": "Etiquettes du fichier de la piste mises à jour", + "RetagSelectedArtists": "Modifier les étiquettes des artistes selectionnés", + "RemoveFromDownloadClientHint": "Supprime le téléchargement et le(s) fichier(s) du client de téléchargement", + "RemoveMultipleFromDownloadClientHint": "Supprime les téléchargements et les fichiers du client de téléchargement", + "RemoveQueueItemRemovalMethodHelpTextWarning": "\"Supprimer du client de téléchargement\" supprimera le téléchargement et le(s) fichier(s) du client de téléchargement.", + "DeleteArtistFolders": "Supprimer les dossiers de l'artiste", + "IgnoreDownload": "Ignorer le téléchargement", + "IgnoreDownloadHint": "Empêche {appName} de poursuivre le traitement de ce téléchargement", + "IgnoreDownloads": "Ignorer les téléchargements", + "IgnoreDownloadsHint": "Empêche {appName} de poursuivre le traitement de ces téléchargements", + "IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "Si un torrent est bloqué par le hachage, il peut ne pas être correctement rejeté pendant le RSS/recherche pour certains indexeurs. L'activation de cette fonction permet de le rejeter après que le torrent a été saisi, mais avant qu'il ne soit envoyé au client.", + "DeleteArtistFolder": "Supprimer le dossier de l'artiste", + "DoNotBlocklist": "Ne pas mettre sur liste noire", + "DoNotBlocklistHint": "Supprimer sans mettre sur liste noire", + "EditSelectedArtists": "Modifier les artistes selectionnés", + "RemoveQueueItem": "Retirer - {sourceTitle}", + "RemoveQueueItemConfirmation": "Êtes-vous sûr de vouloir retirer '{sourceTitle}' de la file d'attente ?", + "RemoveQueueItemRemovalMethod": "Méthode de suppression", + "RemoveQueueItemsRemovalMethodHelpTextWarning": "Supprimer du client de téléchargement\" supprimera les téléchargements et les fichiers du client de téléchargement." } diff --git a/src/NzbDrone.Core/Localization/Core/he.json b/src/NzbDrone.Core/Localization/Core/he.json index 89640dafa..aa130cabf 100644 --- a/src/NzbDrone.Core/Localization/Core/he.json +++ b/src/NzbDrone.Core/Localization/Core/he.json @@ -21,7 +21,7 @@ "CreateGroup": "צור קבוצה", "CutoffHelpText": "לאחר שהאיכות הזו תושג {appName} כבר לא תוריד סרטים", "Dates": "תאריכים", - "DBMigration": "הגירת DB", + "DatabaseMigration": "הגירת DB", "DelayProfile": "עיכוב פרופיל", "DelayProfiles": "עיכוב פרופילים", "Delete": "לִמְחוֹק", @@ -81,7 +81,6 @@ "ImportExtraFilesHelpText": "ייבא קבצים נוספים תואמים (כתוביות, nfo וכו ') לאחר ייבוא קובץ סרט", "ImportFailedInterp": "הייבוא נכשל: {0}", "Importing": "מייבא", - "IncludeHealthWarningsHelpText": "כלול אזהרות בריאות", "IncludeUnknownArtistItemsHelpText": "הצג פריטים ללא סרט בתור. זה יכול לכלול סרטים שהוסרו או כל דבר אחר בקטגוריה של {appName}", "IncludeUnmonitored": "כלול ללא פיקוח", "IndexerPriority": "עדיפות אינדקס", @@ -91,7 +90,6 @@ "Interval": "הַפסָקָה", "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} תומך בכל לקוח הורדות המשתמש בתקן Newznab, כמו גם בלקוחות הורדה אחרים המפורטים להלן.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} תומך בכל אינדקס שמשתמש בתקן Newznab, כמו גם באינדקסים אחרים המפורטים להלן.", - "LoadingTrackFilesFailed": "טעינת קבצי הסרט נכשלה", "Local": "מְקוֹמִי", "LocalPath": "נתיב מקומי", "LocalPathHelpText": "נתיב שבו {appName} אמור להשתמש כדי לגשת לנתיב המרוחק באופן מקומי", @@ -129,16 +127,10 @@ "NoBackupsAreAvailable": "אין גיבויים", "NoHistory": "אין היסטוריה", "NoLeaveIt": "לא, עזוב את זה", - "NoLimitForAnyRuntime": "אין הגבלה לכל זמן ריצה", "NoLogFiles": "אין קבצי יומן", - "NoMinimumForAnyRuntime": "אין מינימום לכל זמן ריצה", "None": "אף אחד", "NotificationTriggers": "מפעילים התראות", "NoUpdatesAreAvailable": "אין עדכונים זמינים", - "OnGrabHelpText": "על לתפוס", - "OnHealthIssueHelpText": "בנושא הבריאות", - "OnRenameHelpText": "על שינוי שם", - "OnUpgradeHelpText": "בשדרוג", "OpenBrowserOnStart": "פתח את הדפדפן בהתחלה", "Options": "אפשרויות", "Original": "מְקוֹרִי", @@ -152,7 +144,6 @@ "PortNumber": "מספר יציאה", "PosterSize": "גודל פוסטר", "PreviewRename": "תצוגה מקדימה של שינוי שם", - "PriorityHelpText": "עדיפות אינדקס מ -1 (הגבוה ביותר) ל -50 (הנמוך ביותר). ברירת מחדל: 25.", "Profiles": "פרופילים", "Proper": "תָקִין", "PropersAndRepacks": "Propers ו Repacks", @@ -265,7 +256,6 @@ "DeleteDelayProfile": "מחק פרופיל עיכוב", "Enable": "לְאַפשֵׁר", "EnableAutomaticAdd": "אפשר הוספה אוטומטית", - "ExtraFileExtensionsHelpTexts1": "רשימה מופרדת באמצעות פסיקים של קבצים נוספים לייבוא (.nfo יובא כ- nfo-orig)", "FileDateHelpText": "שנה את תאריך הקובץ בעת הייבוא / סריקה מחדש", "FileManagement": "ניהול קבצים", "UILanguageHelpText": "שפה בה {appName} ישתמש עבור ממשק המשתמש", @@ -464,7 +454,6 @@ "NETCore": ".NET Core", "Duration": "אורך", "OnApplicationUpdate": "כשהאפליקציה מעדכנת גרסא", - "OnApplicationUpdateHelpText": "כשהאפליקציה מעדכנת גרסא", "Activity": "פעילות", "Add": "הוסף", "AddDelayProfile": "הוסף פרופיל עיכוב", @@ -677,7 +666,6 @@ "DownloadClientTagHelpText": "השתמש באינדקסר זה רק לסרטים שתואמים לתויות. השאר ריק כדי לחפש את כל הסרטים.", "SetTags": "הגדר תגים", "Yes": "כן", - "RemoveFromDownloadClientHelpTextWarning": "הסרה תסיר את ההורדה ואת הקבצים מלקוח ההורדה.", "RemoveSelectedItemQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?", "RemoveSelectedItemsQueueMessageText": "האם אתה בטוח שברצונך להסיר את {0} פריט {1} מהתור?", "DeleteSelectedDownloadClientsMessageText": "האם אתה בטוח שברצונך למחוק את האינדקס '{0}'?", @@ -738,5 +726,15 @@ "OrganizeSelectedArtists": "ארגן סרטים נבחרים", "Overview": "סקירה כללית", "OverviewOptions": "אפשרויות סקירה כללית", - "PosterOptions": "אפשרויות פוסטר" + "PosterOptions": "אפשרויות פוסטר", + "NoLimitForAnyDuration": "אין הגבלה לכל זמן ריצה", + "NoMinimumForAnyDuration": "אין מינימום לכל זמן ריצה", + "PreferredSize": "גודל מועדף", + "Unlimited": "ללא הגבלה", + "ExtraFileExtensionsHelpText": "רשימה מופרדת באמצעות פסיקים של קבצים נוספים לייבוא (.nfo יובא כ- nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "דוגמאות: '.sub, .nfo' או 'sub, nfo'", + "Release": " מְשׁוּחרָר", + "AutoTaggingNegateHelpText": "אם מסומן, הפורמט המותאם אישית לא יחול אם תנאי זה {0} תואם.", + "DeleteArtistFoldersHelpText": "מחק את תיקיית הסרט ואת תוכנו", + "DeleteSpecificationHelpText": "האם אתה בטוח שברצונך למחוק את פרופיל האיכות {0}" } diff --git a/src/NzbDrone.Core/Localization/Core/hi.json b/src/NzbDrone.Core/Localization/Core/hi.json index 5a8d87c9a..7b45e9afc 100644 --- a/src/NzbDrone.Core/Localization/Core/hi.json +++ b/src/NzbDrone.Core/Localization/Core/hi.json @@ -40,7 +40,7 @@ "CutoffHelpText": "एक बार जब यह गुणवत्ता पहुँच जाती है तो Redarr फिल्में डाउनलोड नहीं करेगा", "CutoffUnmet": "कट-ऑफ Unmet", "Dates": "खजूर", - "DBMigration": "DB प्रवासन", + "DatabaseMigration": "DB प्रवासन", "DeleteImportListExclusionMessageText": "क्या आप वाकई इस आयात सूची बहिष्करण को हटाना चाहते हैं?", "DeleteImportListMessageText": "क्या आप वाकई '{0}' सूची को हटाना चाहते हैं?", "DeleteIndexer": "अनुक्रमणिका हटाएं", @@ -71,7 +71,6 @@ "ErrorLoadingContents": "सामग्री लोड करने में त्रुटि", "ErrorLoadingPreviews": "पूर्वावलोकन लोड करने में त्रुटि", "Exception": "अपवाद", - "ExtraFileExtensionsHelpTexts1": "आयात करने के लिए कोमा ने अतिरिक्त फ़ाइलों की सूची अलग कर दी (.nfo को .nfo- मूल के रूप में आयात किया जाएगा)", "FileDateHelpText": "आयात / रेस्क्यू पर फ़ाइल तिथि बदलें", "FileManagement": "फाइल प्रबंधन", "Filename": "फ़ाइल का नाम", @@ -118,9 +117,6 @@ "NoHistory": "कोई इतिहास नहीं", "NotificationTriggers": "अधिसूचना ट्रिगर", "NoUpdatesAreAvailable": "कोई अद्यतन उपलब्ध नहीं हैं", - "OnHealthIssueHelpText": "स्वास्थ्य के मुद्दे पर", - "OnRenameHelpText": "नाम बदलने पर", - "OnUpgradeHelpText": "अपग्रेड पर", "OpenBrowserOnStart": "प्रारंभ पर ब्राउज़र खोलें", "Options": "विकल्प", "Original": "मूल", @@ -217,7 +213,6 @@ "DeleteEmptyFolders": "खाली फ़ोल्डर हटाएँ", "ImportedTo": "आयात किया गया", "Importing": "आयात कर रहा है", - "IncludeHealthWarningsHelpText": "स्वास्थ्य चेतावनी शामिल करें", "IncludeUnknownArtistItemsHelpText": "कतार में एक मूवी के बिना आइटम दिखाएं। इसमें रेडर की श्रेणी में हटाई गई फिल्में या कुछ और भी शामिल हो सकते हैं", "IncludeUnmonitored": "अनिर्दिष्ट शामिल करें", "Indexer": "इंडेक्सर", @@ -230,7 +225,6 @@ "IsCutoffUpgradeUntilThisQualityIsMetOrExceeded": "इस गुणवत्ता के पूरा होने या अधिक होने तक नवीनीकरण करें", "PosterSize": "पोस्टर का आकार", "PreviewRename": "नाम बदलें", - "PriorityHelpText": "इंडेक्सर प्राथमिकता 1 (उच्चतम) से 50 (सबसे कम)। डिफ़ॉल्ट: 25", "Profiles": "प्रोफाइल", "Proper": "उचित", "PropersAndRepacks": "प्रोपर्स और रिपैक", @@ -344,7 +338,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "रेडियर किसी भी डाउनलोड क्लाइंट का समर्थन करता है जो न्यूज़ानब मानक का उपयोग करता है, साथ ही नीचे सूचीबद्ध अन्य डाउनलोड क्लाइंट भी।", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "रेडियर न्यूज़नाब मानक का उपयोग करने वाले किसी भी सूचकांक का समर्थन करता है, साथ ही साथ नीचे सूचीबद्ध अन्य सूचकांक भी।", "LidarrTags": "रेडर टैग", - "LoadingTrackFilesFailed": "फिल्म फ़ाइलें लोड करना विफल रहा", "Local": "स्थानीय", "LocalPath": "स्थानीय पथ", "LocalPathHelpText": "वह पथ जिसका उपयोग रेडर को स्थानीय रूप से दूरस्थ पथ तक पहुँचने के लिए करना चाहिए", @@ -359,11 +352,8 @@ "MarkAsFailedMessageText": "क्या आप वाकई '{0}' को चिह्नित करना चाहते हैं?", "MaximumLimits": "अधिकतम सीमा", "NoLeaveIt": "नहीं, इसे छोड़ो", - "NoLimitForAnyRuntime": "किसी भी रनटाइम के लिए कोई सीमा नहीं", "NoLogFiles": "कोई लॉग फ़ाइल नहीं", - "NoMinimumForAnyRuntime": "किसी रनटाइम के लिए कोई न्यूनतम नहीं", "None": "कोई नहीं", - "OnGrabHelpText": "हड़पने पर", "RefreshInformationAndScanDisk": "जानकारी को ताज़ा करें और डिस्क को स्कैन करें", "RefreshScan": "ताज़ा करें और स्कैन करें", "ReleaseDate": "रिलीज़ करने की तिथि", @@ -653,7 +643,6 @@ "Yes": "हाँ", "NoEventsFound": "कोई घटना नहीं मिली", "ApplyTagsHelpTextRemove": "निकालें: दर्ज किए गए टैग निकालें", - "RemoveFromDownloadClientHelpTextWarning": "हटाने से डाउनलोड और फ़ाइल को डाउनलोड क्लाइंट से निकाल दिया जाएगा।", "RemoveSelectedItemQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?", "RemoveSelectedItemsQueueMessageText": "क्या आप वाकई {0} आइटम {1} को कतार से हटाना चाहते हैं?", "Negated": "नकार दिया गया", @@ -697,5 +686,15 @@ "RenameFiles": "फ़ाइलों का नाम बदलें", "DeleteAutoTagHelpText": "क्या आप वाकई गुणवत्ता प्रोफ़ाइल {0} को हटाना चाहते हैं", "Small": "छोटा", - "Table": "टेबल" + "Table": "टेबल", + "NoLimitForAnyDuration": "किसी भी रनटाइम के लिए कोई सीमा नहीं", + "NoMinimumForAnyDuration": "किसी रनटाइम के लिए कोई न्यूनतम नहीं", + "PreferredSize": "पसंदीदा आकार", + "Unlimited": "असीमित", + "ExtraFileExtensionsHelpText": "आयात करने के लिए कोमा ने अतिरिक्त फ़ाइलों की सूची अलग कर दी (.nfo को .nfo- मूल के रूप में आयात किया जाएगा)", + "ExtraFileExtensionsHelpTextsExamples": "उदाहरण: '.sub, .nfo' या 'सब, nfo'", + "Release": " रिहा", + "DeleteArtistFoldersHelpText": "फिल्म फ़ोल्डर और उसकी सामग्री को हटा दें", + "DeleteSpecificationHelpText": "क्या आप वाकई गुणवत्ता प्रोफ़ाइल {0} को हटाना चाहते हैं", + "AutoTaggingNegateHelpText": "यदि जाँच की जाती है, तो कस्टम प्रारूप लागू नहीं होगा यदि यह {0} स्थिति से मेल खाता है।" } diff --git a/src/NzbDrone.Core/Localization/Core/hu.json b/src/NzbDrone.Core/Localization/Core/hu.json index 1f06e7e37..eaaf615ff 100644 --- a/src/NzbDrone.Core/Localization/Core/hu.json +++ b/src/NzbDrone.Core/Localization/Core/hu.json @@ -9,40 +9,40 @@ "45MinutesFourtyFive": "45 Perc: {0}", "60MinutesSixty": "60 Perc: {0}", "Absolute": "Abszolút", - "AppDataDirectory": "AppData Mappa", + "AppDataDirectory": "AppData Könyvtár", "ApplyTags": "Címkék alkalmazása", "Authentication": "Hitelesítés", "Automatic": "Automatikus", - "BackupNow": "Biztonsági Mentés Most", - "BackupRetentionHelpText": "A megőrzési időnél régebbi automatikus biztonsági másolatok automatikusan törlésre kerülnek", + "BackupNow": "Biztonsági Mentés", + "BackupRetentionHelpText": "A megőrzési időszaknál régebbi automatikus biztonsági másolatok automatikusan törlődnek", "Backups": "Biztonsági mentések", - "BindAddress": "Kapcsolási Cím", + "BindAddress": "Kötési cím", "BindAddressHelpText": "Érvényes IP-cím, localhost vagy '*' minden interfészhez", "Cancel": "Mégse", "CertificateValidation": "Tanúsítvány érvényesítése", "ChangeHasNotBeenSavedYet": "A változások még nem lettek elmentve", "Clear": "Törölni", - "ClientPriority": "Kliens Prioritás", - "CloneIndexer": "Indexer Klónozása", - "CloneProfile": "Profil Klónozása", + "ClientPriority": "Kliens prioritás", + "CloneIndexer": "Indexelő klónozása", + "CloneProfile": "Profil klónozása", "Columns": "Oszlopok", "Connections": "Kapcsolatok", - "ConnectSettings": "Kapcsolódási Beállítások", + "ConnectSettings": "Csatlakozási beállítások", "Dates": "Dátumok", - "DBMigration": "DB Migráció", + "DatabaseMigration": "DB Migráció", "Delete": "Törlés", - "DeleteBackupMessageText": "Biztosan törlöd a(z) „{0}” biztonsági mentést?", - "DeleteDownloadClient": "Letöltőkliens Törlése", + "DeleteBackupMessageText": "Biztosan törli a '{name}' biztonsági mentést?", + "DeleteDownloadClient": "Letöltőkliens törlése", "DeleteIndexer": "Indexer Törlése", - "DeleteIndexerMessageText": "Biztosan törlöd a(z) „{0}” indexert?", + "DeleteIndexerMessageText": "Biztosan törli a(z) \"{name}\" indexelőt?", "DeleteNotification": "Értesítés Törlése", - "DeleteNotificationMessageText": "Biztosan törlöd a(z) „{0}” értesítést?", + "DeleteNotificationMessageText": "Biztosan törli a(z) „{name}” értesítést?", "DeleteTag": "Címke Törlése", - "DeleteTagMessageText": "Biztosan törlöd a(z) „{0}” címkét?", + "DeleteTagMessageText": "Biztosan törli a „{label}” címkét?", "Docker": "Docker", - "DownloadClient": "Letöltési Kliens", - "DownloadClients": "Letöltőkliensek", - "Edit": "Szerkesztés", + "DownloadClient": "Letöltési kliens", + "DownloadClients": "Letöltő kliensek", + "Edit": "Szerkeszt", "Enable": "Aktiválás", "EnableAutomaticAdd": "Engedélyezd az automatikus hozzáadást", "EnableCompletedDownloadHandlingHelpText": "A befejezett letöltések automatikus importálása a letöltési kliensből", @@ -53,36 +53,33 @@ "ErrorLoadingContents": "Hiba történt a tartalom betöltésekor", "Exception": "Kivétel", "Filename": "Fájlnév", - "Files": "Fájl", + "Files": "Fájlok", "Fixed": "Kijavítva", "Folder": "Mappa", "History": "Történet", "Host": "Hoszt", "Hostname": "Hosztnév", - "IgnoredAddresses": "Ignorált Címek", + "IgnoredAddresses": "Ignorált címek", "IllRestartLater": "Később Újraindítom", - "IncludeHealthWarningsHelpText": "Tartalmazza a Állapot Figyelmeztetéseket", "Indexers": "Indexerek", "InteractiveSearch": "Interaktív Keresés", "Interval": "Intervallum", - "LogFiles": "Log Fájlok", + "LogFiles": "Naplófájlok", "Logging": "Loggolás", - "LogLevel": "Log Szint", - "Logs": "Logok", + "LogLevel": "Napló szint", + "Logs": "Naplók", "MIA": "MIA", "ProxyType": "Proxy Típusa", - "Mechanism": "Mechanizmus", + "Mechanism": "Gépezet", "Message": "Üzenet", - "MinimumLimits": "Minimális Határ", + "MinimumLimits": "Minimális korlátok", "Mode": "Mód", - "MoreInfo": "Több Információ", + "MoreInfo": "Több információ", "Name": "Név", "New": "Új", - "NoLeaveIt": "Nem, hagyd így", - "NoLogFiles": "Nincsen log fájl", - "NoMinimumForAnyRuntime": "Nincs minimális futásidő", - "NotificationTriggers": "Értesítés(ek) kiváltója", - "OnHealthIssueHelpText": "Állapotprobléma", + "NoLeaveIt": "Nem, Hagyd", + "NoLogFiles": "Nincsenek naplófájlok", + "NotificationTriggers": "Értesítési triggerek", "OpenBrowserOnStart": "Indításkor nyissa meg a böngészőt", "Options": "Opciók", "PackageVersion": "Csomagverzió", @@ -96,14 +93,14 @@ "QualityDefinitions": "Minőségi meghatározások", "QualitySettings": "Minőségi beállítások", "Queue": "Várakozási sor", - "ReadTheWikiForMoreInformation": "Olvasd el a Wiki-t további információkért", + "ReadTheWikiForMoreInformation": "További információkért olvassa el a Wikit", "Refresh": "Frissítés", - "Reload": "Újratöltés", + "Reload": "Újratölt", "RemoveFilter": "Szűrő törlése", "Reset": "Visszaállítás", - "Restart": "Újraindítás", + "Restart": "Újrakezd", "RestartNow": "Újraindítás Most", - "Restore": "Visszaállítás", + "Restore": "Visszaállít", "RestoreBackup": "Biztonsági mentés visszaállítása", "Result": "Eredmények", "Retention": "Visszatartás", @@ -114,14 +111,14 @@ "SSLCertPath": "Az SSL tanúsítvány elérési útvonala", "SSLPort": "SSL Port", "Settings": "Beállítások", - "ShowSearch": "Keresés(ek) megjelenítése", + "ShowSearch": "Keresés mutatása", "Source": "Forrás", "StartupDirectory": "Indítási könyvtár", "Status": "Állapot", "Style": "Stílus", "Tags": "Címkék", "Tasks": "Feladatok", - "TestAll": "Összes tesztelése", + "TestAll": "Összes Tesztelése", "Torrents": "Torrentek", "Type": "Típus", "UISettings": "A felhasználói felület beállításai", @@ -139,25 +136,24 @@ "Usenet": "Usenet", "UseProxy": "Proxy használata", "Username": "Felhasználónév", - "YesCancel": "Igen, Mégsem", + "YesCancel": "Igen, elvet", "Analytics": "Analitika", "BypassProxyForLocalAddresses": "Proxy megkerülése a helyi hálózatos címekhez", "CertificateValidationHelpText": "Módosítsa a HTTPS-tanúsítvány-ellenőrzés szigorúságát. Ne változtasson, hacsak nem érti a kockázatokat.", "DelayProfile": "Késleltetési Profil", - "DeleteBackup": "Biztonsági Mentés Törlése", - "DeleteDownloadClientMessageText": "Biztosan törlöd a(z) „{0}” letöltő klienst?", + "DeleteBackup": "Biztonsági Mentés törlése", + "DeleteDownloadClientMessageText": "Biztosan törli a(z) \"{name}\" letöltési klienst?", "DownloadClientSettings": "Letöltőkliens Beállítások", - "Downloading": "Letöltés Alatt", + "Downloading": "Letöltés", "EnableAutomaticSearch": "Automatikus keresés engedélyezése", "EnableColorImpairedMode": "Engedélyezze a színtévesztő módot", "GeneralSettings": "Általános Beállítások", - "Importing": "Importálás Folyamatban", + "Importing": "Importálás", "Indexer": "Indexelő", "IndexerPriority": "Indexer Prioritása", - "MaximumLimits": "Maximális Limit", - "NoBackupsAreAvailable": "Nincs elérhető biztonsági mentés", - "NoLimitForAnyRuntime": "Nincs futási idő korlát", - "NoUpdatesAreAvailable": "Nincsenek elérhető frissítések", + "MaximumLimits": "Maximális korlátok", + "NoBackupsAreAvailable": "Nincsenek biztonsági mentések", + "NoUpdatesAreAvailable": "Nem érhetők el frissítések", "PageSizeHelpText": "Az egyes oldalakon megjelenítendő elemek száma", "ProxyPasswordHelpText": "Csak akkor kell megadnod felhasználónevet és jelszót, ha szükséges. Egyébként hagyd üresen.", "ProxyUsernameHelpText": "Csak akkor kell megadnod felhasználónevet és jelszót, ha szükséges. Egyébként hagyd üresen.", @@ -166,8 +162,8 @@ "Scheduled": "Ütemezve", "SendAnonymousUsageData": "Névtelen használati adatok küldése", "StartTypingOrSelectAPathBelow": "Kezdd el gépelni, vagy válassz az alábbi útvonalak közül", - "TagIsNotUsedAndCanBeDeleted": "A címkét nincs használatban, és törölhető", - "TestAllClients": "Összes kliens tesztelése", + "TagIsNotUsedAndCanBeDeleted": "A címke nincs használatban, törölhető", + "TestAllClients": "Minden ügyfél tesztelése", "UnableToAddANewDownloadClientPleaseTryAgain": "Nem lehet új letöltőklienst hozzáadni, próbálkozz újra.", "UnableToLoadBackups": "Biztonsági mentés(ek) betöltése sikertelen", "UnableToLoadGeneralSettings": "Nem sikerült betölteni az általános beállításokat", @@ -177,8 +173,8 @@ "AddMissing": "Hiányzó hozzáadása", "AddNewItem": "Új elem hozzáadása", "APIKey": "API Kulcs", - "AddListExclusion": "Kizárási Lista Hozzáadása", - "AgeWhenGrabbed": "Kora (mikor hozzáadásra került)", + "AddListExclusion": "Listakizárás hozzáadása", + "AgeWhenGrabbed": "Életkor (amikor megragadták)", "Album": "Album", "AlbumHasNotAired": "Az album nem került kiadásra", "AlbumIsDownloadingInterp": "Az album letöltése folyamatban – {0}% {1}", @@ -192,11 +188,11 @@ "AllowFingerprinting": "Engedélyezze az ujjlenyomatot", "AllowFingerprintingHelpText": "Használjon ujjlenyomatot a számegyeztetés pontosságának javítására", "AllowFingerprintingHelpTextWarning": "Ehhez a Liddarr-nak el kell olvasnia a fájl olyan részeit, amelyek lelassítják a beolvasást, és magas lemez- vagy hálózati aktivitást okozhatnak.", - "AlreadyInYourLibrary": "Már hozzáadtad", - "AlternateTitles": "Alternatív cím", + "AlreadyInYourLibrary": "Már a könyvtárban", + "AlternateTitles": "Alternatív címek", "AlternateTitleslength1Title": "Cím", "AlternateTitleslength1Titles": "Címek", - "AnalyticsEnabledHelpText": "Küldjön névtelen használati és hibainformációkat a {appName} szervereire. Ez magában foglalja a böngészőjéről szóló információkat, mely {appName} WebUI oldalakat használja, a hibajelentést, valamint az operációs rendszer adatait. Ezeket az információkat a funkciók és a hibajavítások rangsorolására használjuk fel.", + "AnalyticsEnabledHelpText": "Névtelen használati és hibainformáció küldése {appName} szervereinek. Ez magában foglalja a böngészővel kapcsolatos információkat, a használt {appName} WebUI oldalakat, a hibajelentéseket, valamint az operációs rendszert és a futásidejű verziót. Ezeket az információkat a funkciók és a hibajavítások fontossági sorrendjének meghatározására fogjuk használni.", "AnalyticsEnabledHelpTextWarning": "Újraindítás szükséges a hatálybalépéshez", "AnchorTooltip": "Ez a fájl már szerepel a könyvtárában egy éppen importált kiadáshoz", "AnyReleaseOkHelpText": "A {appName} automatikusan átvált a legjobban illő letöltött számokra", @@ -210,14 +206,14 @@ "ArtistFolderFormat": "Előadó Album Formátum", "ArtistNameHelpText": "A kizárandó előadó/album neve (bármi lehet)", "Artists": "Előadó(k)", - "AuthenticationMethodHelpText": "Felhasználónév és jelszó szükséges a {appName}-hoz való hozzáféréshez", - "AutoRedownloadFailedHelpText": "Másik kiadás automatikus keresése és letöltése", + "AuthenticationMethodHelpText": "Felhasználónév és jelszó szükséges a(z) {appName} eléréséhez", + "AutoRedownloadFailedHelpText": "Egy másik kiadás automatikus keresése és letöltése", "AutomaticallySwitchRelease": "Automatikusan váltson másik megjelenésre", "BackupFolderHelpText": "Az elérési útvonalak a {appName} AppData könyvtárában lesznek", "BackupIntervalHelpText": "Időköz a {appName} adatbázis és a beállítások biztonsági mentéséhez", "BindAddressHelpTextWarning": "Újraindítás szükséges a hatálybalépéshez", "Blocklist": "Feketelista", - "BlocklistRelease": "Feketelistás Kiadás", + "BlocklistRelease": "Blokklista Release", "Calendar": "Naptár", "CalendarWeekColumnHeaderHelpText": "Minden oszlop felett jelenjen meg, hogy melyik hét az aktuális", "CancelMessageText": "Biztosan törlöd ezt a függőben lévő feladatot?", @@ -225,14 +221,14 @@ "ChangeFileDate": "Fájl Dátumának Módosítása", "ChmodFolder": "chmod Mappa", "ChmodFolderHelpText": "Octal, importáláskor / átnevezéskor alkalmazva a média mappákra és fájlokra (bitek végrehajtása nélkül)", - "ChmodFolderHelpTextWarning": "Ez csak akkor működik, ha a {appName}-t futtató felhasználó a fájl tulajdonosa. Jobb, ha ellenőrzöd a letöltési kliensben megfelelően vannak-e beállítva az engedélyek.", + "ChmodFolderHelpTextWarning": "Ez csak akkor működik, ha a(z) {appName} alkalmazást futtató felhasználó a fájl tulajdonosa. Jobb, ha megbizonyosodik arról, hogy a letöltési kliens megfelelően állítja be az engedélyeket.", "ChownGroup": "chown Csoport", - "ChownGroupHelpText": "Csoport neve vagy gid. A gid használata távoli fájlrendszerekhez.", - "ChownGroupHelpTextWarning": "Ez csak akkor működik, ha a {appName}-t futtató felhasználó a fájl tulajdonosa. Jobb, ha a letöltési kliens ugyanazt a csoportot használja, mint a {appName}.", + "ChownGroupHelpText": "Csoport neve vagy gid. Távoli fájlrendszerekhez használja a gid-t.", + "ChownGroupHelpTextWarning": "Ez csak akkor működik, ha a(z) {appName} alkalmazást futtató felhasználó a fájl tulajdonosa. Jobb, ha a letöltési kliens ugyanazt a csoportot használja, mint a {appName}.", "ClickToChangeQuality": "Kattints a minőség módosításához", "CollapseMultipleAlbums": "Több album összecsukása", "CollapseMultipleAlbumsHelpText": "Több, ugyanazon a napon megjelenő album összecsukása", - "CompletedDownloadHandling": "Kész Letöltések Kezelése", + "CompletedDownloadHandling": "Befejezett letöltéskezelés", "Continuing": "Folytatás", "ContinuingAllTracksDownloaded": "Folytatás (Minden szám letöltve)", "ContinuingMoreAlbumsAreExpected": "További albumok várhatók", @@ -251,34 +247,34 @@ "DefaultQualityProfileIdHelpText": "Alapértelmezett minőségi profil a mappában észlelt előadók számára", "DelayProfiles": "Késleltetési Profilok", "DelayingDownloadUntilInterp": "Késleltetni a letöltést {0} -tól {1} -ig", - "DeleteDelayProfile": "Késleltetési Profil Törlése", + "DeleteDelayProfile": "Késleltetési Profil törlése", "DefaultTagsHelpText": "Az ebben a mappában észlelt előadók alapértelmezett {appName} címkéi", "DeleteReleaseProfile": "Késleltetési Profil Törlése", "DeleteReleaseProfileMessageText": "Biztos hogy törölni szeretnéd ezt a késleltetési profilt?", - "DeleteRootFolder": "Gyökérmappa törlése", + "DeleteRootFolder": "Gyökérmappa törlés", "DeleteRootFolderMessageText": "Biztosan törlöd a(z) „{0}” gyökérmappát?", "Time": "Idő", - "DeleteDelayProfileMessageText": "Biztos hogy törölni szeretnéd ezt a késleltetési profilt?", + "DeleteDelayProfileMessageText": "Biztosan törli ezt a késleltetési profilt?", "DeleteEmptyFolders": "Üres Mappa Törlése", "DeleteEmptyFoldersHelpText": "Törölje az üres előadó- és albummappákat a lemezellenőrzés és a műsorszámfájlok törlésekor", "DeleteFilesHelpText": "Törölje a számfájlokat és az előadói mappát", - "DeleteImportList": "Importlista törlése", + "DeleteImportList": "Importálási lista törlése", "DeleteImportListExclusion": "Az importlista kizárásásainak törlése", - "DeleteImportListExclusionMessageText": "Biztos, hogy törölni szeretnéd az importálási lista kivételeit?", - "DeleteImportListMessageText": "Biztosan törlöd a(z) „{0}” listát?", + "DeleteImportListExclusionMessageText": "Biztosan törli ezt az importlista-kizárást?", + "DeleteImportListMessageText": "Biztosan törli a(z) „{name}” listát?", "DeleteMetadataProfile": "Metaadat-profil törlése", "Actions": "Teendők", - "Component": "Komponens", + "Component": "Összetevő", "Level": "Szint", "DeleteMetadataProfileMessageText": "Biztosan törli a {0} minőségi profilt?", "DeleteQualityProfile": "Minőségi Profil Törlése", - "DeleteQualityProfileMessageText": "Biztosan törli a {0} minőségi profilt?", + "DeleteQualityProfileMessageText": "Biztosan törli a(z) „{name}” minőségi profilt?", "RemotePathHelpText": "Gyökérútvonal a könyvtárhoz, amelyhez a letöltőkliens hozzáfér", - "SkipFreeSpaceCheckWhenImportingHelpText": "Akkor használja, ha a {appName} nem képes felismerni a gyökérmappában lévő szabad helyet", - "UpdateMechanismHelpText": "Használja a {appName} beépített frissítőjét vagy egy szkriptet", + "SkipFreeSpaceCheckWhenImportingHelpText": "Akkor használja, ha a(z) {appName} nem tud szabad helyet észlelni a gyökérmappában a fájlimportálás során", + "UpdateMechanismHelpText": "Használja a {appName} beépített frissítőjét vagy szkriptjét", "SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByLidarr": "Akkor használatos, ha az automatikus keresést a felhasználói felületen vagy a {appName} segítségével hajtja végre", "TagsHelpText": "A kiadási profilok azokra az előadókra vonatkoznak, akik legalább egy megfelelő címkével rendelkeznek. Hagyja üresen, ha minden előadóra vonatkozik", - "TorrentDelay": "Torrent késleltetés", + "TorrentDelay": "Torrent Késleltetés", "TotalTrackCountTracksTotalTrackFileCountTracksWithFilesInterp": "Összesen: {0} szám. {1} szám fájlokkal.", "TrackTitle": "Dal címe", "UnableToAddANewImportListExclusionPleaseTryAgain": "Nem lehet új listakizárást hozzáadni, próbálkozz újra.", @@ -294,7 +290,6 @@ "WatchLibraryForChangesHelpText": "Automatikus újrakeresés, amikor a fájlok megváltoznak egy gyökérmappában", "WriteAudioTagsHelpTextWarning": "Az „Összes fájl” kiválasztása megváltoztatja a meglévő fájlokat az importáláskor.", "DetailedProgressBarHelpText": "Szöveg megjelenítése a folyamatjelző sávon", - "ExtraFileExtensionsHelpTexts2": "Például: \".sub\"", "GoToArtistListing": "Ugrás az előadók listájára", "GrabReleaseMessageText": "{appName} nem tudta meghatározni, hogy melyik filmhez készült ez a kiadás. Lehet, hogy a {appName} nem tudja automatikusan importálni ezt a kiadást. Meg szeretnéd ragadni a (z) „{0}”-t?", "IfYouDontAddAnImportListExclusionAndTheArtistHasAMetadataProfileOtherThanNoneThenThisAlbumMayBeReaddedDuringTheNextArtistRefresh": "Ha nem ad hozzá importlista-kizárást, és az előadó metaadat-profilja a „Nincs”-től eltérő, akkor az albumot a következő előadói frissítés során újra hozzáadhatja.", @@ -311,7 +306,7 @@ "QualityProfileIdHelpText": "A Minőségi profil listaelemeket hozzá kell adni a következővel", "RecycleBinCleanupDaysHelpTextWarning": "A kiválasztott napoknál régebbi fájlok a lomtárban automatikusan törlésre kerülnek", "ReleaseStatuses": "Kiadások állapota", - "RemotePath": "Távoli elérési útvonal", + "RemotePath": "Távoli útvonal", "RemoveCompletedDownloadsHelpText": "Távolítsa el az importált letöltéseket a letöltési kliens előzményeiből", "RenameTracks": "Számok átnevezése", "RenameTracksHelpText": "A {appName} a meglévő fájlnevet fogja használni, ha az átnevezés le van tiltva", @@ -323,8 +318,8 @@ "SecondaryAlbumTypes": "Másodlagos albumtípusok", "SetPermissionsLinuxHelpText": "Futtatni kell a chmod-ot fájlok importálásakor / átnevezésekor?", "ShowBannersHelpText": "Bannerek megjelenítése nevek helyett", - "ShowMonitoredHelpText": "Monitorozott státusz kijelzése a poszter alatt", - "SkipFreeSpaceCheck": "A szabad hely ellenőrzésének kihagyása", + "ShowMonitoredHelpText": "A figyelt állapot megjelenítése a plakát alatt", + "SkipFreeSpaceCheck": "Kihagyja a szabad hely ellenőrzését", "SupportsRssvalueRSSIsNotSupportedWithThisIndexer": "Az RSS nem támogatott ezzel az indexerrel", "DeleteSelectedTrackFiles": "Törölje a kiválasztott sávfájlokat", "DeleteSelectedTrackFilesMessageText": "Biztos benne, hogy törölni kívánja a kiválasztott sávfájlokat?", @@ -335,7 +330,7 @@ "Disambiguation": "Egyértelművé tétel", "DiscCount": "Lemezszám", "DiscNumber": "Lemez száma", - "DiskSpace": "Szabad Tárhely", + "DiskSpace": "Lemez terület", "DownloadFailedCheckDownloadClientForMoreDetails": "Letöltés Sikertelen : Nézd meg a letöltőkliensed további információért", "DownloadFailedInterp": "Letöltés sikertelen: {0}", "EpisodeDoesNotHaveAnAbsoluteEpisodeNumber": "Az epizódnak nincs abszolút epizódszáma", @@ -348,9 +343,8 @@ "ExpandItemsByDefault": "Bontsa ki az elemeket alapértelmezés szerint", "ExpandOtherByDefaultHelpText": "Egyéb", "ExpandSingleByDefaultHelpText": "Egyedik", - "ExtraFileExtensionsHelpTexts1": "Az importálandó extra fájlok vesszővel lesznek elválasztva (.nfo .nfo-orig néven lesz importálva)", "FileDateHelpText": "A fájl dátumának módosítása az importáláskor / újrakereséskor", - "FileManagement": "Fájlkezelő", + "FileManagement": "Fájlkezelés", "FileNames": "Fájlnevek", "FirstAlbum": "Első album", "FirstAlbumData": "Figyelje az első albumokat. Az összes többi album figyelmen kívül lesz hagyva", @@ -404,24 +398,22 @@ "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "A {appName} minden olyan indexelőt támogat, amely a Newznab szabványt használja, valamint az alább felsorolt egyéb indexelőket.", "LidarrSupportsMultipleListsForImportingAlbumsAndArtistsIntoTheDatabase": "A {appName} több listát is támogat az albumok és előadók adatbázisba történő importálásához.", "LidarrTags": "{appName} Címkék", - "LoadingAlbumsFailed": "Az albumok betöltése nem sikerült", - "LoadingTrackFilesFailed": "A dalfájlok betöltése nem sikerült", "Local": "Helyi", "LocalPath": "Helyi útvonal", "LocalPathHelpText": "Elérési út, amelyet a {appName} használhat a távoli elérési út, helyi eléréséhez", - "LongDateFormat": "Hosszú dátumformátum", - "MaintenanceRelease": "Karbantartási kiadás", + "LongDateFormat": "Hosszú dátum formátum", + "MaintenanceRelease": "Karbantartási kiadás: hibajavítások és egyéb fejlesztések. További részletekért lásd: Github Commit History", "ManageTracks": "Számok kezelése", - "MediaInfo": "Média Információ", - "MediaManagementSettings": "Média Kezelési Beállítások", + "MediaInfo": "Média információ", + "MediaManagementSettings": "Médiakezelési beállítások", "Medium": "Közepes", "MediumFormat": "Közepes formátum", "MetadataConsumers": "Metaadat-fogyasztók", "MetadataProfile": "Metaadat-profil", "MetadataProfiles": "Metaadat-profilok", - "MetadataSettings": "Metaadat Beállítások", - "MinimumAge": "Minimális Kor", - "MinimumFreeSpace": "Minimális Szabad Tárhely", + "MetadataSettings": "Metaadat-beállítások", + "MinimumAge": "Minimális kor", + "MinimumFreeSpace": "Minimális szabad hely", "MinimumFreeSpaceWhenImportingHelpText": "Akadályozza meg az importálást, ha ennél kevesebb lemezterület maradna", "Missing": "Hiányzó", "MissingAlbums": "Hiányzó Albumok", @@ -439,7 +431,7 @@ "MusicBrainzReleaseID": "MusicBrainz kiadási azonosító", "MusicBrainzTrackID": "MusicBrainz zeneszám azonosítója", "MustContain": "Tartalmaznia kell", - "MustNotContain": "Nem tartalmazhatja", + "MustNotContain": "Nem tartalmazhat", "NETCore": ".NET", "NoHistory": "Nincs(enek) előzmény(ek).", "Other": "Egyéb", @@ -452,7 +444,6 @@ "PreviewRetag": "Előnézet újrataggelése", "PrimaryAlbumTypes": "Elsődleges albumtípusok", "PrimaryTypes": "Elsődleges típusok", - "PriorityHelpText": "Indexelő prioritás 1-től (legmagasabb) 50-ig (legalacsonyabb). Alapértelmezés: 25. A {appName} továbbra is az összes engedélyezett indexelőt fogja használni az RSS-szinkronizáláshoz és a kereséshez, amikor a kiadásokat megragadja az egyébként egyenlő kiadásokhoz.", "Profiles": "Profil(ok)", "Proper": "Proper", "PropersAndRepacks": "Properek és Repackok", @@ -461,23 +452,23 @@ "RecycleBinCleanupDaysHelpText": "Állítsd 0-ra az automatikus tisztítás letiltásához", "RecycleBinHelpText": "A zeneszámok törléskor ide kerülnek a végleges törlés helyett", "RecyclingBin": "Lomtár", - "RecyclingBinCleanup": "Lomtár kiürítése", + "RecyclingBinCleanup": "Lomtár tisztítása", "Redownload": "Letöltés újra", "RefreshArtist": "Előadó frissítése", "RefreshInformationAndScanDisk": "Információk frissítése és lemez átvizsgálása", "RefreshScan": "Frissítés & Keresés", "Release": " Kiadás", "ReleaseDate": "Megjelenés Dátuma", - "ReleaseGroup": "Kiadási Csoport", - "ReleaseProfiles": "Kiadási profilok", + "ReleaseGroup": "Release csapat", + "ReleaseProfiles": "Release profilok", "ReleaseRejected": "Kiadás elutasítva", "ReleasesHelpText": "Az album kiadásának módosítása", "ReleaseWillBeProcessedInterp": "A kiadás feldolgozása {0}", - "RemotePathMappings": "Távoli Elérési Útvonal", + "RemotePathMappings": "Távoli útvonal-leképezések", "Remove": "Eltávolítás", "RemoveFailedDownloadsHelpText": "Távolítsa el a sikertelen letöltéseket a letöltési kliens előzményeiből", "RemoveFromBlocklist": "Eltávolítás a feketelistáról", - "RemoveFromDownloadClient": "Eltávolítás a letöltési kliensből", + "RemoveFromDownloadClient": "Eltávolítás a Letöltési kliensből", "RemoveFromQueue": "Eltávolítás a sorból", "RemoveSelected": "Kiválaszottak törlése", "RemoveTagExistingTag": "Meglévő Címke", @@ -491,12 +482,12 @@ "RSSSyncInterval": "RSS Szikronizálás Intervalluma", "ShowRelativeDatesHelpText": "Relatív (Ma / Tegnap / stb.) vagy valós dátumok megjelenítése", "ShowSearchActionHelpText": "A kereső gomb megjelenítése az egérrel", - "ShowSizeOnDisk": "Használt hely megjelenítése", + "ShowSizeOnDisk": "Méret megjelenítése a lemezen", "ShowTitleHelpText": "Mutasd az előadó nevét a poszter alatt", "ShowUnknownArtistItems": "Ismeretlen előadó elemek megjelenítése", - "SslCertPasswordHelpText": "Jelszó a Pfx fájlhoz", + "SslCertPasswordHelpText": "Jelszó a pfx fájlhoz", "SslCertPasswordHelpTextWarning": "Újraindítás szükséges a hatálybalépéshez", - "SslCertPathHelpText": "A PFX fájl elérési útvonala", + "SslCertPathHelpText": "A pfx fájl elérési útja", "SslCertPathHelpTextWarning": "Újraindítás szükséges a hatálybalépéshez", "SslPortHelpTextWarning": "Újraindítás szükséges a hatálybalépéshez", "StandardTrackFormat": "Szabványos dalformátum", @@ -504,14 +495,14 @@ "SuccessMyWorkIsDoneNoFilesToRename": "Siker! Befejeztem a munkám, nincsenek átnevezésre váró fájlok.", "TBA": "Bejelentés alatt", "SuccessMyWorkIsDoneNoFilesToRetag": "Siker! Befejeztem a munkám, nincsenek átcimkézésre váró fájlok.", - "TestAllIndexers": "Indexerek tesztelése", - "TestAllLists": "Összes lista tesztelése", + "TestAllIndexers": "Tesztelje az összes indexelőt", + "TestAllLists": "Minden lista tesztelése", "TheAlbumsFilesWillBeDeleted": "Az album fájljai törlődnek.", "TheArtistFolderStrongpathstrongAndAllOfItsContentWillBeDeleted": "A(z) {path} előadói mappa és annak teljes tartalma törlődik.", "ThisWillApplyToAllIndexersPleaseFollowTheRulesSetForthByThem": "Ez minden indexerre vonatkozni fog, kérjük, tartsa be az általuk meghatározott szabályokat", - "TimeFormat": "Időformátum", - "TorrentDelayHelpText": "Eltolás percekben, mielőtt a torrentkliens elkezdi a letöltést", - "TotalFileSize": "Teljes fájl méret", + "TimeFormat": "Idő formátum", + "TorrentDelayHelpText": "Percek késése, hogy várjon, mielőtt megragad egy torrentet", + "TotalFileSize": "Összesített fájlméret", "Track": "Dal", "TrackArtist": "Dal előadója", "TrackDownloaded": "Dal letöltve", @@ -567,26 +558,19 @@ "IndexerIdHelpText": "Adja meg, hogy a profil milyen indexelőre vonatkozik", "IndexerIdHelpTextWarning": "Egy adott indexer előnyben részesített szavakkal történő használata megismételt kiadások kiválasztásához vezethet", "ManualDownload": "Kézi letöltés", - "ManualImport": "Manuális Importálás", - "MarkAsFailed": "Megjelölés Sikertelenként", + "ManualImport": "Kézi importálás", + "MarkAsFailed": "Megjelölés sikertelenként", "MarkAsFailedMessageText": "Biztosan sikertelennek szeretnéd jelölni a (z) „{0}”-t?", - "MaximumSize": "Maximális Méret", + "MaximumSize": "Maximális méret", "MaximumSizeHelpText": "A kiadás maximális mérete MB-ban. Állítsd nullára a korlátlan értékre.", "MusicbrainzId": "MusicBrainz azonosító", "Original": "Eredeti", - "None": "Nincs", + "None": "Egyik sem", "NoneData": "Az albumok nem lesznek monitorozva", - "OnDownloadFailureHelpText": "Letöltési hiba esetén", - "OnGrabHelpText": "Kiválasztás alatt", - "OnImportFailureHelpText": "Importálási hiba esetén", - "OnReleaseImportHelpText": "A kiadás importálásakor", - "OnRenameHelpText": "Átnevezés alatt", - "OnTrackRetagHelpText": "Dal átcímkézés alatt", - "OnUpgradeHelpText": "Minőségjavítás alatt", "Quality": "Minőség", "QualityProfile": "Minőségi profil", "QualityProfiles": "Minőségi profilok", - "Real": "Valódi", + "Real": "Igaz", "Reorder": "Átrendezés", "ReplaceIllegalCharacters": "Az illegális karakterek cseréje", "RequiredHelpText": "A kiadásnak tartalmaznia kell legalább egy ilyen kifejezést (a kis- és nagybetűk nem számítanak)", @@ -611,23 +595,23 @@ "SecondaryTypes": "Másodlagos típusok", "SelectedCountArtistsSelectedInterp": "{0} Előadó(k) kiválasztva", "ShowName": "Név megjelenítése", - "ShowPath": "Útvonal mutatása", - "ShowQualityProfile": "Minőségi profil megjelenítése", - "SetPermissions": "Engedélyek beállítása", - "ShowQualityProfileHelpText": "Minőségi profil megjelenítése a poszter alatt", + "ShowPath": "Útvonal megjelenítése", + "ShowQualityProfile": "Minőségi Profil mutatása", + "SetPermissions": "Állítsa be az engedélyeket", + "ShowQualityProfileHelpText": "Minőségi profil megjelenítése a plakát alatt", "ShowRelativeDates": "Relatív dátumok megjelenítése", "Size": " Méret", - "SetPermissionsLinuxHelpTextWarning": "Ha nem vagy biztos abban, hogy ezek a beállítások mit csinálnak, ne változtasd meg őket.", + "SetPermissionsLinuxHelpTextWarning": "Ha nem biztos abban, hogy ezek a beállítások mit csinálnak, ne módosítsa őket.", "ShortDateFormat": "Rövid dátumformátum", "ShouldMonitorHelpText": "A listáról hozzáadott előadók és albumok figyelése", "ShowAlbumCount": "Albumszám megjelenítése", "ShowBanners": "Bannerek megjelenítése", "ShowCutoffUnmetIconHelpText": "Szimbólum megjelenítése, ha a minőségi küszöböt még nem érték el", - "ShowDateAdded": "Hozzáadás dátuma", + "ShowDateAdded": "Hozzáadás dátumának megjelenítése", "ShowLastAlbum": "Az utolsó album mutatása", - "ShowMonitored": "Monitorozottak mutatása", + "ShowMonitored": "Megfigyelt megjelenítése", "ShownAboveEachColumnWhenWeekIsTheActiveView": "Minden oszlop felett jelenjen meg, hogy melyik hét az aktuális", - "SkipRedownload": "Az újraletöltés átugrása", + "SkipRedownload": "Az újraletöltés kihagyása", "SorryThatAlbumCannotBeFound": "Sajnos az album nem található.", "SorryThatArtistCannotBeFound": "Sajnáljuk, az előadó nem található.", "SourcePath": "Forrás útvonala", @@ -649,10 +633,9 @@ "WatchRootFoldersForFileChanges": "Gyökérmappák figyelése fájlváltozások érdekében", "UILanguageHelpText": "A {appName} által a felhasználói felülethez használt nyelv", "UILanguageHelpTextWarning": "Böngésző újratöltése szükséges", - "RemoveCompleted": "Eltávolítás Kész", + "RemoveCompleted": "Eltávolítás kész", "RemoveDownloadsAlert": "Az eltávolításhoz szükséges beállítások átkerültek a fenti táblázatban található egyéni letöltő beállítások közé.", - "RemoveFailed": "Eltávolítás Sikertelen", - "OnApplicationUpdateHelpText": "Alkalmazásfrissítésről", + "RemoveFailed": "Eltávolítás nem sikerült", "OnDownloadFailure": "Letöltési hiba esetén", "OnGrab": "Kiválasztás alatt", "OnHealthIssue": "Állapotprobléma", @@ -674,22 +657,22 @@ "Add": "Hozzáadás", "AddDelayProfile": "Késleltetési profil hozzáadása", "Added": "Hozzáadva", - "AddImportListExclusion": "Lista kizárások importálása", - "AddIndexer": "Indexer hozzáadása", + "AddImportListExclusion": "Importálási lista kizárásának hozzáadása", + "AddIndexer": "Indexelő hozzáadása", "AddMetadataProfile": "Metaadat-profil", "AddNew": "Új hozzáadása", "AddQualityProfile": "Minőségi Profil hozzáadása", - "AddRemotePathMapping": "Adj Meg Egy Távoli Elérési Útvonalat", + "AddRemotePathMapping": "Távoli útvonal-leképezés hozzáadása", "AddRootFolder": "Gyökérmappa hozzáadása", - "AfterManualRefresh": "A kézi frissítés után", + "AfterManualRefresh": "Kézi frissítés után", "Age": "Kor", "Albums": "Albumok", "All": "Összes", - "AllFiles": "Összes fájl", + "AllFiles": "Minden fájl", "AllMonitoringOptionHelpText": "Az importálási listán lévő szerzők összes könyvének monitorozása", "ApplicationURL": "Alkalmazás URL", - "ApplicationUrlHelpText": "Az alkalmazás külső URL-címe, beleértve a http(s)://-t, a portot és az URL-alapot", - "Apply": "Alkalmazás", + "ApplicationUrlHelpText": "Ennek az alkalmazásnak a külső URL-címe, beleértve a http-eket", + "Apply": "Alkamaz", "AudioInfo": "Hang Infó", "BeforeUpdate": "Alkalmazásfrissítés előtt", "Close": "Bezárás", @@ -702,12 +685,12 @@ "Details": "Részletek", "Donations": "Adományok", "DoNotPrefer": "Nem preferált", - "DoNotUpgradeAutomatically": "Ne frissítsen automatikusan", - "DownloadFailed": "Letöltés Sikertelen", + "DoNotUpgradeAutomatically": "Ne frissítse automatikusan", + "DownloadFailed": "Sikertelen letöltés", "EditDelayProfile": "Késleltetési profil szerkesztése", - "EditImportListExclusion": "Az importlista kizárásásainak törlése", - "EditQualityProfile": "Minőség profil szerkesztése", - "EditRemotePathMapping": "Távoli Elérési Útvonal Módosítása", + "EditImportListExclusion": "Importálási lista kizárásának szerkesztése", + "EditQualityProfile": "Minőségi profil szerkesztése", + "EditRemotePathMapping": "Távoli útvonal-leképezés szerkesztése", "EditRootFolder": "Gyökérmappa hozzáadása", "ErrorRestoringBackup": "Hiba a mentés visszaállítása közben", "Events": "Események", @@ -716,7 +699,7 @@ "FreeSpace": "Szabad Tárhely", "General": "Általános", "Genres": "Műfajok", - "Grabbed": "Megfogva", + "Grabbed": "Megragadta", "HardlinkCopyFiles": "Hardlinkelés/Fájl(ok) Másolása", "HideAdvanced": "Haladó elrejtése", "Ignored": "Ignorált", @@ -733,16 +716,16 @@ "LastUsed": "Utoljára használt", "LastWriteTime": "Utolsó írási idő", "Library": "Könyvtár", - "Location": "Lokáció", - "Manual": "Manuális", - "MediaManagement": "Média Kezelés", - "Metadata": "Metaadat(ok)", - "MonitoredOnly": "Csak a Megfigyelt", - "MoveAutomatically": "Automatikus Áthelyezés", - "MoveFiles": "Fájl(ok) mozgatása", + "Location": "Elhelyezkedés", + "Manual": "Kézi", + "MediaManagement": "Médiakezelés", + "Metadata": "Metaadat", + "MonitoredOnly": "Csak megfigyelt", + "MoveAutomatically": "Automatikus áthelyezés", + "MoveFiles": "Fájlok áthelyezése", "Never": "Soha", "NextExecution": "Következő végrehajtás", - "NoTagsHaveBeenAddedYet": "Még nem adtál hozzá címkéket", + "NoTagsHaveBeenAddedYet": "Még nem adtak hozzá címkéket", "Ok": "Ok", "OnlyTorrent": "Csak torrent", "OnlyUsenet": "Csak usenet", @@ -753,7 +736,7 @@ "Presets": "Előbeállítások", "Progress": "Folyamat", "QualityLimitsHelpText": "A korlátozások automatikusan beállítódnak a film hossza szerint.", - "Queued": "Sorba helyezve", + "Queued": "Sorban", "Rating": "Értékelés", "RejectionCount": "Elutasítások száma", "ReleaseTitle": "Kiadás címe", @@ -765,35 +748,35 @@ "Seeders": "Seederek", "Select...": "Válassza...", "SelectFolder": "Mappa kiválasztása", - "SelectQuality": "Válasszon minőséget", + "SelectQuality": "Minőség kiválasztása", "ShouldMonitorExistingHelpText": "A listán szereplő azon könyvek automatikus figyelése, amelyek már szerepelnek a Readarrban", "ShouldSearch": "Új elemek keresése", "ShouldSearchHelpText": "Az indexelők keresése az újonnan hozzáadott elemek után. Óvatosan használja a nagy listákat.", "ShowAdvanced": "Haladó nézet", "SizeLimit": "Méretkorlát", "SizeOnDisk": "Méret a lemezen", - "SourceTitle": "Forrás címe", - "Started": "Elkezdődött", + "SourceTitle": "Eredeti cím", + "Started": "Elindult", "System": "Rendszer", "Test": "Teszt", "TimeLeft": "Hátralévő idő", "Title": "Cím", - "TotalSpace": "Összes szabad hely", + "TotalSpace": "Összesített terület", "UnmappedFilesOnly": "Kizárólag fel nem térképezett fájlokat", "UnmonitoredOnly": "Csak a nem felügyelt", "UpgradesAllowed": "Frissítések Engedélyezve", "Wanted": "Keresett", - "Warn": "Figyelmeztet", + "Warn": "Figyelmeztetés", "WouldYouLikeToRestoreBackup": "Szeretnéd visszaállítani a {0} biztonsági mentést?", "WriteMetadataTags": "Írjon metaadat-címkéket", "Peers": "Peerek", "UI": "Felület", "Always": "Mindig", - "Backup": "Biztonsági Mentés", + "Backup": "Biztonsági mentés", "Error": "Hiba", - "AddConnection": "Gyűjtemény módosítása", + "AddConnection": "Csatlakozás hozzáadása", "EditMetadataProfile": "Metaadat-profil", - "AddReleaseProfile": "Kiadási profil hozzáadása", + "AddReleaseProfile": "Release profil hozzáadása", "AlbumRelease": "Album megjelenése", "AlbumReleaseDate": "Album megjelenési dátuma", "AlbumStatus": "Album állapota", @@ -811,7 +794,7 @@ "EditReleaseProfile": "Kiadási profil szerkesztése", "ForNewImportsOnly": "Csak új importokra", "EndedOnly": "Csak a véget értek", - "ContinuingOnly": "Csak folytatva", + "ContinuingOnly": "Csak folytatás", "ImportFailed": "Az importálás sikertelen", "MediaCount": "Médiaszám", "MissingTracks": "Hiányzó számok", @@ -831,7 +814,7 @@ "SelectTracks": "Szám kiválasztása", "ShouldMonitorExisting": "Meglévő albumok figyelése", "Theme": "Téma", - "ThemeHelpText": "Változtasd meg az alkalmazás felhasználói felület témáját, az „Auto” téma az operációs rendszer témáját használja a Világos vagy Sötét mód beállításához. A Theme.Park ihlette", + "ThemeHelpText": "Változtassa meg az alkalmazás felhasználói felület témáját, az \"Auto\" téma az operációs rendszer témáját használja a Világos vagy Sötét mód beállításához. A Theme.Park ihlette", "TrackCount": "Darabszám", "TrackImported": "Szám importálva", "TrackProgress": "Szám folyamata", @@ -840,19 +823,17 @@ "EditGroups": "Csoportok szerkesztése", "QualitiesHelpText": "A listán magasabb minőségek előnyösebbek, még akkor is, ha nincs bejelölve. Ugyanazon csoporton belül a tulajdonságok egyenlőek. Csak ellenőrzött minőségek szükségesek", "DoneEditingGroups": "A csoportok szerkesztése kész", - "OnAlbumDeleteHelpText": "Album törlésekor", "OnAlbumDelete": "Album törlésekor", "OnArtistDelete": "Előadó törlésekor", - "OnArtistDeleteHelpText": "Előadó törlésekor", "ChooseImportMethod": "Importálási mód kiválasztása", "ClickToChangeReleaseGroup": "Kiadási csoport módosítása", - "SelectReleaseGroup": "Kiadási csoport kiválasztása", + "SelectReleaseGroup": "Release csoport kiválasztása", "BypassIfHighestQuality": "Kihagyás ha a legjobb minőség elérhető", "EnableRssHelpText": "Akkor használatos, amikor a {appName} rendszeresen keres kiadásokat az RSS Sync segítségével", "CustomFormatScore": "Egyéni formátum pontszám", - "MinimumCustomFormatScore": "Minimum Egyéni Formátum száma", + "MinimumCustomFormatScore": "Minimális egyéni formátum pontszám", "CloneCustomFormat": "Egyéni formátum klónozása", - "Conditions": "Állapot", + "Conditions": "Körülmények", "CopyToClipboard": "Másold a Vágólapra", "CouldntFindAnyResultsForTerm": "Nincsen találat a következőre: \"{0}\"", "CustomFormat": "Egyéni formátum", @@ -873,7 +854,7 @@ "IncludeCustomFormatWhenRenamingHelpText": "Tartalmazza a(z) {Custom Formats} átnevezési formátumot", "ItsEasyToAddANewArtistJustStartTypingTheNameOfTheArtistYouWantToAdd": "Könnyű hozzáadni egy filmet, csak kezd el gépelni a kívánt film nevét", "MinFormatScoreHelpText": "A letöltéshez engedélyezett minimális egyéni formátum pontszám", - "Monitor": "Monitorozni", + "Monitor": "Monitor", "Monitoring": "Monitorozás", "NegateHelpText": "Ha be van jelölve, az egyéni formátum nem lesz érvényes, ha ez a(z) {0} feltétel megegyezik.", "PreferTorrent": "Torrent preferálása", @@ -884,7 +865,7 @@ "SpecificMonitoringOptionHelpText": "Monitorozza a szerzőket, de csak a listán kifejezetten szereplő könyveket", "UnableToLoadCustomFormats": "Nem lehet betölteni az egyéni formátumokat", "UnableToLoadInteractiveSearch": "Nem lehetséges betölteni a film keresés eredményeit. Próbálja meg később", - "Formats": "Formátumok", + "Formats": "Formátum", "HiddenClickToShow": "Rejtett, kattints a felfedéshez", "ImportListStatusCheckAllClientMessage": "Az összes lista elérhetetlen, hiba miatt", "ShownClickToHide": "Kattints, hogy elrejtsd", @@ -903,7 +884,7 @@ "RemotePathMappingCheckFilesWrongOSPath": "A távoli letöltőkliens {0} fájlokat jelentett a(z) {1} fájlban, de ez nem érvényes {2} elérési út. Ellenőrizze a távoli elérési utak hozzárendelését és a letöltőkliens beállításait.", "AppDataLocationHealthCheckMessage": "A frissítés nem lehetséges az alkalmazás adatok törlése nélkül", "ColonReplacement": "Kettőspont Helyettesítés", - "Disabled": "Letiltott", + "Disabled": "Tiltva", "DownloadClientCheckDownloadingToRoot": "A Letöltőkliens {0} a letöltéseket a gyökérmappába helyezi {1}. Nem szabad letölteni egy gyökérmappába.", "DownloadClientCheckNoneAvailableMessage": "Nem található letöltési kliens", "DownloadClientCheckUnableToCommunicateMessage": "Nem lehet kommunikálni a következővel: {0}.", @@ -947,43 +928,128 @@ "BlocklistReleaseHelpText": "Megakadályozza, hogy a {appName} automatikusan letöltse újra", "FailedToLoadQueue": "Nem sikerült betölteni a várólistát", "QueueIsEmpty": "A várakozási sor üres", - "BlocklistReleases": "Feketelistás Kiadás", - "Negated": "Megtagadva", - "NoHistoryBlocklist": "Nincs blokkolási előzménylista", + "BlocklistReleases": "Feketelista kiadása", + "Negated": "Negatív", + "NoHistoryBlocklist": "Nincs előzmény a tiltólistán", "DownloadClientSortingCheckMessage": "A(z) {0} letöltési kliensben engedélyezve van a(z) {1} rendezés a {appName} kategóriájához. Az importálási problémák elkerülése érdekében le kell tiltania a rendezést a letöltési kliensben.", "ApplyChanges": "Változások alkalmazása", "AutomaticAdd": "Automatikus hozzáadás", "CountIndexersSelected": "{0} Indexelő(k) kiválasztva", "DeleteConditionMessageText": "Biztosan törölni akarod a '{0}' feltételt?", "DeleteSelectedDownloadClients": "Letöltőkliens Törlése", - "DeleteSelectedImportLists": "Importlista törlése", - "DeleteSelectedIndexers": "Indexer Törlése", - "EditSelectedDownloadClients": "Kiválasztott letöltési kliensek szerkesztése", - "EditSelectedImportLists": "Kiválasztott import listák szerkesztése", - "ExistingTag": "Meglévő Címke", + "DeleteSelectedImportLists": "Importálási lista(k) törlése", + "DeleteSelectedIndexers": "Indexelő(k) törlése", + "EditSelectedDownloadClients": "Kijelölt letöltési kliensek szerkesztése", + "EditSelectedImportLists": "Kijelölt importálási listák szerkesztése", + "ExistingTag": "Létező címke", "EditSelectedIndexers": "Kiválasztott indexelők szerkesztése", "No": "Nem", - "NoChange": "Nincs változtatás", + "NoChange": "Nincs változás", "RecycleBinUnableToWriteHealthCheck": "Nem lehet írni a konfigurált lomtár mappába {0}. Győződjön meg arról, hogy ez az elérési útvonal létezik, és az a felhasználó, aki a Sonarr-t futtatja, írási jogosultsággal rendelkezik", "RemovingTag": "Címke eltávolítása", "Yes": "Igen", - "NoEventsFound": "Nem található esemény", + "NoEventsFound": "Nem található események", "ResetQualityDefinitions": "Állítsd vissza a minőségi meghatározásokat", "ResetTitlesHelpText": "A definíciócímek és értékek visszaállítása", - "ApplyTagsHelpTextAdd": "Hozzáadás: Új címkék hozzáadása a meglévő címkékhez", + "ApplyTagsHelpTextAdd": "Hozzáadás: Adja hozzá a címkéket a meglévő címkék listájához", "ApplyTagsHelpTextRemove": "Eltávolítás: Távolítsa el a beírt címkéket", - "ApplyTagsHelpTextReplace": "Csere: Cserélje ki a címkéket a beírt címkékre (az összes címke törléséhez ne adjon meg címkéket)", - "RemoveFromDownloadClientHelpTextWarning": "Az eltávolítás eltávolítja a letöltést és a fájl(oka)t a letöltési kliensből.", + "ApplyTagsHelpTextReplace": "Csere: Cserélje ki a címkéket a megadott címkékkel (az összes címke törléséhez ne írjon be címkéket)", "RemoveSelectedItemQueueMessageText": "Biztosan el akar távolítani 1 elemet a várólistáról?", "RemoveSelectedItemsQueueMessageText": "Biztosan el akar távolítani {0} elemet a várólistáról?", "DownloadClientTagHelpText": "Csak olyan filmekhez használja ezt az indexelőt, amelyek legalább egy megfelelő címkével rendelkeznek. Hagyja üresen az összes filmhez való használathoz.", "SetTags": "Címkék beállítása", "SkipRedownloadHelpText": "Megakadályozza, hogy a {appName} megpróbálja letölteni az eltávolított elemek alternatív kiadásait", "ApplyTagsHelpTextHowToApplyArtists": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez", - "ApplyTagsHelpTextHowToApplyDownloadClients": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez", + "ApplyTagsHelpTextHowToApplyDownloadClients": "Címkék alkalmazása a kiválasztott letöltési kliensekre", "RemoveCompletedDownloads": "Befejezett letöltések eltávolítása", "RemoveFailedDownloads": "Sikertelen letöltések eltávolítása", - "ApplyTagsHelpTextHowToApplyImportLists": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez", - "ApplyTagsHelpTextHowToApplyIndexers": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez", - "AutoAdd": "Automatikus hozzáadás" + "ApplyTagsHelpTextHowToApplyImportLists": "Címkék alkalmazása a kiválasztott importlistákra", + "ApplyTagsHelpTextHowToApplyIndexers": "Címkék alkalmazása a kiválasztott indexelőkre", + "AutoAdd": "Automatikus hozzáadás", + "AddConditionImplementation": "Feltétel hozzáadása –{megvalósítás név}", + "AddDownloadClientImplementation": "Letöltési kliens hozzáadása – {implementationName}", + "AddAutoTag": "Automatikus címke hozzáadása", + "AddAlbumWithTitle": "{albumTitle} hozzáadása", + "AddArtistWithName": "{artistName} hozzáadása", + "AppUpdated": "{appName} frissítve", + "NoDownloadClientsFound": "Nem találhatók letöltő kliensek", + "ManageImportLists": "Importálási listák kezelése", + "ManageLists": "Listák kezelése", + "NoImportListsFound": "Nem található importálási lista", + "NoIndexersFound": "Nem található indexelő", + "AddAutoTagError": "Nem sikerült új automatikus címkét hozzáadni, próbálkozzon újra.", + "AddConditionError": "Nem sikerült új feltételt hozzáadni, próbálkozzon újra.", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Erősítsd meg az új jelszót", + "AddConnectionImplementation": "Csatlakozás hozzáadása - {implementationName}", + "AllResultsAreHiddenByTheAppliedFilter": "Az összes eredményt elrejti az alkalmazott szűrő", + "ManageIndexers": "Indexelők kezelése", + "AuthBasic": "Alap (böngésző előugró ablak)", + "AuthenticationMethodHelpTextWarning": "Kérjük, válasszon érvényes hitelesítési módot", + "AuthenticationRequired": "Azonosítás szükséges", + "AuthenticationRequiredPasswordHelpTextWarning": "Adjon meg új jelszót", + "AuthenticationRequiredUsernameHelpTextWarning": "Adjon meg új felhasználónevet", + "AuthenticationRequiredWarning": "A hitelesítés nélküli távoli hozzáférés megakadályozása érdekében a(z) {appName} alkalmazásnak engedélyeznie kell a hitelesítést. Opcionálisan letilthatja a helyi címekről történő hitelesítést.", + "AddCondition": "Feltétel hozzáadása", + "AddImportList": "Importálási lista hozzáadása", + "AddImportListImplementation": "Importálási lista hozzáadása -{implementationName}", + "AddIndexerImplementation": "Indexelő hozzáadása - {implementationName}", + "AutoTagging": "Automatikus címkézés", + "AuthenticationMethod": "Hitelesítési Módszer", + "AuthForm": "Űrlapok (bejelentkezési oldal)", + "AutoRedownloadFailed": "Az újraletöltés nem sikerült", + "AutoRedownloadFailedFromInteractiveSearch": "Az újraletöltés nem sikerült az interaktív keresésből", + "AutoTaggingLoadError": "Nem sikerült betölteni az automatikus címkézést", + "AppUpdatedVersion": "{appName} frissítve lett `{version}` verzióra, ahhoz hogy a legutóbbi változtatások életbelépjenek, töltsd újra a {appName}-t", + "ReleaseProfile": "Release profil", + "DownloadClientAriaSettingsDirectoryHelpText": "Választható hely a letöltések elhelyezéséhez, hagyja üresen az alapértelmezett Aria2 hely használatához", + "DownloadClientQbittorrentSettingsContentLayout": "Tartalom elrendezése", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Függetlenül attól, hogy a qBittorrent konfigurált tartalomelrendezését használja, az eredeti elrendezést a torrentből, vagy mindig hozzon létre egy almappát (qBittorrent 4.3.2)", + "EditAutoTag": "Automatikus címke szerkesztése", + "External": "Külső", + "InvalidUILanguage": "A felhasználói felület érvénytelen nyelvre van állítva, javítsa ki, és mentse el a beállításait", + "Negate": "Negatív", + "NoResultsFound": "Nincs találat", + "RecentChanges": "Friss változások", + "RegularExpressionsCanBeTested": "A reguláris kifejezések [here] tesztelhetők (http://regexstorm.net/tester).", + "EditConnectionImplementation": "Kapcsolat szerkesztése - {implementationName}", + "ExtraFileExtensionsHelpTextsExamples": "Példák: \".sub, .nfo\" vagy \"sub,nfo\"", + "ConnectionLostReconnect": "A(z) {appName} automatikusan megpróbál csatlakozni, vagy kattintson az újratöltés gombra lent.", + "DeleteRemotePathMappingMessageText": "Biztosan törli ezt a távoli útvonal-leképezést?", + "DeleteSelectedIndexersMessageText": "Biztosan törölni szeretne {count} kiválasztott indexelőt?", + "DeleteSelectedImportListsMessageText": "Biztosan törölni szeretne {count} kiválasztott importlistát?", + "DisabledForLocalAddresses": "Helyi címeknél letiltva", + "EditImportListImplementation": "Importálási lista szerkesztése – {implementationName}", + "ManageDownloadClients": "Letöltési kliensek kezelése", + "NotificationStatusAllClientHealthCheckMessage": "Az összes értesítés nem érhető el hibák miatt", + "EditIndexerImplementation": "Indexelő szerkesztése – {implementationName}", + "DeleteSelectedDownloadClientsMessageText": "Biztosan törölni szeretné a kiválasztott {count} letöltési klienst?", + "EditDownloadClientImplementation": "Letöltési kliens szerkesztése – {implementationName}", + "ManageClients": "Ügyfelek kezelése", + "AuthenticationRequiredHelpText": "Módosítsa, hogy mely kérésekhez van szükség hitelesítésre. Ne változtasson, hacsak nem érti a kockázatokat.", + "Connection": "Kapcsolat", + "AutoRedownloadFailedFromInteractiveSearchHelpText": "Automatikusan keressen és kíséreljen meg egy másik kiadást letölteni, ha az interaktív keresésből sikertelen kiadást ragadtak meg", + "AutomaticUpdatesDisabledDocker": "Az automatikus frissítések közvetlenül nem támogatottak a Docker frissítési mechanizmus használatakor. Frissítenie kell a tároló képét a {appName} alkalmazáson kívül, vagy szkriptet kell használnia", + "ClearBlocklistMessageText": "Biztosan törli az összes elemet a tiltólistáról?", + "ConnectionLostToBackend": "A(z) {appName} megszakadt a kapcsolat a háttérrendszerrel, ezért újra kell tölteni a működés visszaállításához.", + "CloneAutoTag": "Auto Tag klónozása", + "ConnectionLost": "A kapcsolat megszakadt", + "DeleteAutoTag": "Automatikus címke törlése", + "DeleteAutoTagHelpText": "Biztosan törli a(z) „{name}” automatikus címkét?", + "EditConditionImplementation": "Feltétel szerkesztése – {implementationName}", + "DownloadClientPriorityHelpText": "Töltse le a kliens prioritást 1-től (legmagasabb) 50-ig (legalacsonyabb). Alapértelmezés: 1. A Round-Robint az azonos prioritású kliensek használják.", + "SmartReplace": "Intelligens csere", + "SomeResultsAreHiddenByTheAppliedFilter": "Néhány eredményt elrejtett az alkalmazott szűrő", + "BlocklistAndSearchMultipleHint": "Indítsa el a helyettesítők keresését a tiltólistázás után", + "ChangeCategoryHint": "A módosítások letöltése az „Importálás utáni kategóriára” a Download Clientből", + "Small": "Kicsi", + "BlocklistAndSearch": "Feketelista és Keresés", + "BlocklistAndSearchHint": "Indítsa el a csere keresését a tiltólistázás után", + "BlocklistMultipleOnlyHint": "Blokklista helyettesítők keresése nélkül", + "BlocklistOnly": "Csak blokkolólista", + "BlocklistOnlyHint": "Blokklista csere keresése nélkül", + "ChangeCategory": "Kategória módosítása", + "ChangeCategoryMultipleHint": "Módosítja a letöltéseket az „Importálás utáni kategóriára” a Download Clientből", + "Total": "Összesen", + "Table": "Táblázat", + "CustomFormatsSpecificationRegularExpression": "Reguláris kifejezés" } diff --git a/src/NzbDrone.Core/Localization/Core/is.json b/src/NzbDrone.Core/Localization/Core/is.json index bef238003..e69587df6 100644 --- a/src/NzbDrone.Core/Localization/Core/is.json +++ b/src/NzbDrone.Core/Localization/Core/is.json @@ -47,7 +47,7 @@ "CutoffHelpText": "Þegar þessum gæðum er náð mun {appName} ekki lengur hlaða niður kvikmyndum", "CutoffUnmet": "Cut-off Ómetið", "Dates": "Dagsetningar", - "DBMigration": "DB fólksflutningar", + "DatabaseMigration": "DB fólksflutningar", "DelayProfile": "Seinka prófíl", "DelayProfiles": "Seinka snið", "Delete": "Eyða", @@ -103,7 +103,6 @@ "ErrorLoadingContents": "Villa við að hlaða innihald", "ErrorLoadingPreviews": "Villa við að hlaða forskoðun", "Exception": "Undantekning", - "ExtraFileExtensionsHelpTexts1": "Komma aðskilinn listi yfir auka skrár til að flytja inn (.nfo verður fluttur inn sem .nfo-orig)", "FileDateHelpText": "Breyttu dagsetningu skráar við innflutning / endurskoðun", "Filename": "Skráarnafn", "FileNames": "Skráarnöfn", @@ -139,7 +138,6 @@ "ImportExtraFilesHelpText": "Flyttu inn samsvarandi auka skrár (texta, nfo, etc) eftir að hafa flutt inn kvikmyndaskrá", "ImportFailedInterp": "Innflutningur mistókst: {0}", "Importing": "Innflutningur", - "IncludeHealthWarningsHelpText": "Láttu heilsuviðvaranir fylgja með", "IncludeUnknownArtistItemsHelpText": "Sýnið atriði án kvikmyndar í biðröðinni. Þetta gæti falið í sér fjarlægðar kvikmyndir eða annað í flokknum {appName}", "IncludeUnmonitored": "Hafa óeftirlit með", "Indexer": "Indexer", @@ -154,7 +152,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} styður hvaða niðurhals viðskiptavinur sem notar Newznab staðalinn, auk annarra niðurhals viðskiptavina sem taldir eru upp hér að neðan.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} styður alla vísitölufyrirtæki sem nota Newznab staðalinn, svo og aðrir verðtryggingaraðilar sem taldir eru upp hér að neðan.", "LidarrTags": "{appName} merkimiðar", - "LoadingTrackFilesFailed": "Ekki tókst að hlaða kvikmyndaskrár", "Medium": "Miðlungs", "Message": "Skilaboð", "MinimumFreeSpaceWhenImportingHelpText": "Koma í veg fyrir innflutning ef það myndi skilja eftir minna en þetta magn af diskaplássi", @@ -338,16 +335,10 @@ "NoBackupsAreAvailable": "Engin afrit eru í boði", "NoHistory": "Engin saga", "NoLeaveIt": "Nei, skilið það eftir", - "NoLimitForAnyRuntime": "Engin takmörk fyrir neina keyrslutíma", "NoLogFiles": "Engar logskrár", - "NoMinimumForAnyRuntime": "Ekkert lágmark fyrir neina keyrslutíma", "None": "Enginn", "NotificationTriggers": "Tilkynningakveikjur", "NoUpdatesAreAvailable": "Engar uppfærslur eru í boði", - "OnGrabHelpText": "Á grípa", - "OnHealthIssueHelpText": "Um heilbrigðismál", - "OnRenameHelpText": "Um Endurnefna", - "OnUpgradeHelpText": "Við uppfærslu", "OpenBrowserOnStart": "Opnaðu vafra við byrjun", "Options": "Valkostir", "Original": "Frumlegt", @@ -359,7 +350,6 @@ "Permissions": "Heimildir", "PosterSize": "Veggspjaldastærð", "PreviewRename": "Forskoða Endurnefna", - "PriorityHelpText": "Forgangur flokkara frá 1 (Hæstur) til 50 (Lægstur). Sjálfgefið: 25.", "Profiles": "Snið", "Proper": "Rétt", "PropersAndRepacks": "Propers og Repacks", @@ -657,7 +647,6 @@ "RemoveSelectedItemsQueueMessageText": "Ertu viss um að þú viljir fjarlægja {0} hlut {1} úr biðröðinni?", "RemovingTag": "Fjarlægir merkið", "SetTags": "Settu merki", - "RemoveFromDownloadClientHelpTextWarning": "Fjarlæging fjarlægir niðurhalið og skrána / skrána úr niðurhalsviðskiptavininum.", "ApplyTagsHelpTextHowToApplyArtists": "Hvernig á að setja merki á völdu kvikmyndirnar", "ApplyTagsHelpTextHowToApplyImportLists": "Hvernig á að setja merki á völdu kvikmyndirnar", "ApplyTagsHelpTextHowToApplyIndexers": "Hvernig á að setja merki á völdu kvikmyndirnar" diff --git a/src/NzbDrone.Core/Localization/Core/it.json b/src/NzbDrone.Core/Localization/Core/it.json index 1d9bef4e9..ce12931ab 100644 --- a/src/NzbDrone.Core/Localization/Core/it.json +++ b/src/NzbDrone.Core/Localization/Core/it.json @@ -7,11 +7,11 @@ "60MinutesSixty": "60 Minuti: {0}", "APIKey": "Chiavi API", "Absolute": "Assoluto", - "AddListExclusion": "Aggiungi Lista di esclusione", + "AddListExclusion": "Aggiungi Lista Esclusioni", "AddMissing": "Aggiungi ai mancanti", "AddNewItem": "Aggiungi Nuovo Elemento", "AddingTag": "Aggiungendo etichetta", - "AgeWhenGrabbed": "Età (quando trovato)", + "AgeWhenGrabbed": "Età (quando recuperato)", "Album": "Album", "AlbumIsDownloading": "Album in scaricamento", "AlbumIsDownloadingInterp": "Album in scaricamento - {0}% {1}", @@ -28,10 +28,10 @@ "AllowArtistChangeClickToChangeArtist": "Clicca per cambiare l’artista", "AllowFingerprinting": "Consenti impronte", "AlreadyInYourLibrary": "Già presente nella tua libreria", - "AlternateTitles": "Titoli alternativi", + "AlternateTitles": "Titolo alternativo", "AlternateTitleslength1Title": "Titolo", "AlternateTitleslength1Titles": "Titoli", - "Analytics": "Analisi", + "Analytics": "Statistiche", "Size": " Dimensioni", "SkipFreeSpaceCheck": "Salta controllo spazio libero", "ApiKeyHelpTextWarning": "Richiede il riavvio per avere effetti", @@ -40,38 +40,38 @@ "ApplyTagsHelpTextReplace": "Sostituire: Sostituisce le etichette con quelle inserite (non inserire nessuna etichette per eliminarle tutte)", "ArtistAlbumClickToChangeTrack": "Clicca per cambiare film", "Authentication": "Autenticazione", - "AuthenticationMethodHelpText": "Utilizza nome utente e password per accedere a {appName}", + "AuthenticationMethodHelpText": "Inserisci Username e Password per accedere a {appName}", "AutoRedownloadFailedHelpText": "Ricerca automatica e tentativo di scaricare un'altra versione", - "BackupFolderHelpText": "I percorsi relativi saranno sotto la directory AppData di {appName}", + "BackupFolderHelpText": "I percorsi relativi saranno nella cartella AppData di {appName}", "BackupNow": "Esegui backup ora", - "BackupRetentionHelpText": "I backup automatici più vecchi del periodo di conservazione verranno eliminati automaticamente", + "BackupRetentionHelpText": "I backup più vecchi del periodo specificato saranno cancellati automaticamente", "Backups": "Backups", - "BindAddress": "Indirizzo per il collegamento", - "BindAddressHelpText": "Indirizzo IP valido, localhost o '*' per tutte le interfacce di rete", + "BindAddress": "Indirizzo di Ascolto", + "BindAddressHelpText": "Indirizzi IP validi, localhost o '*' per tutte le interfacce", "BindAddressHelpTextWarning": "Richiede il riavvio per avere effetti", "Blocklist": "Lista dei Blocchi", "BlocklistRelease": "Release in blacklist", "Branch": "Ramo", "BypassProxyForLocalAddresses": "Evita il Proxy per gli indirizzi locali", "CancelMessageText": "Sei sicuro di voler cancellare questa operazione in sospeso?", - "CertificateValidation": "Convalida del certificato", + "CertificateValidation": "Convalida del Certificato", "CertificateValidationHelpText": "Cambia quanto rigorosamente vengono validati i certificati HTTPS. Non cambiare senza conoscerne i rischi.", - "ChangeFileDate": "Cambiare la data del file", + "ChangeFileDate": "Cambiare la Data del File", "ChangeHasNotBeenSavedYet": "Il cambiamento non è stato ancora salvato", "ChmodFolder": "Permessi Cartella", - "ChmodFolderHelpText": "Octal, applicato durante importazione/rinomina di cartelle e file (senza execute bits)", - "ChmodFolderHelpTextWarning": "Funziona solo se l'utente di {appName} è il proprietario del file. E' meglio assicurarsi che i client di download impostino i permessi correttamente.", - "ChownGroupHelpText": "Nome Gruppo o guida. Usa guida per sistemi remoti.", - "ChownGroupHelpTextWarning": "Funziona solo se l'utente di {appName} è il proprietario del file. E' meglio assicurarsi che i client di download usino lo stesso gruppo di {appName}.", - "ClickToChangeQuality": "Clicca per cambiare qualità", - "ClientPriority": "Priorità del Client", - "CloneIndexer": "Clona Indexer", - "CloneProfile": "Clona il Profilo", + "ChmodFolderHelpText": "Octal, applicato durante l'importazione/rinomina verso cartelle e file (senza bits di esecuzione)", + "ChmodFolderHelpTextWarning": "Funziona solo se l'utente di {appName} è il proprietario del file. E' meglio assicurarsi che il client di download imposti i permessi correttamente.", + "ChownGroupHelpText": "Nome del gruppo o gid. Usa gid per sistemi di file remoti.", + "ChownGroupHelpTextWarning": "Funziona solo se l'utente di {appName} è il proprietario del file. E' meglio assicurarsi che il client di download usi lo stesso gruppo di {appName}.", + "ClickToChangeQuality": "Click per cambiare qualità", + "ClientPriority": "Priorità Client", + "CloneIndexer": "Copia Indicizzatore", + "CloneProfile": "Copia Profilo", "Columns": "Colonne", "CompletedDownloadHandling": "Gestione dei Download Completati", "Component": "Componente", - "Connections": "Collegamenti", - "ConnectSettings": "Impostazioni di connessione", + "Connections": "Connessioni", + "ConnectSettings": "Impostazioni Collegamento", "CopyUsingHardlinksHelpText": "Utilizzare gli Hardlink quando si cerca di copiare file da un torrent che è ancora in fase di seeding", "CopyUsingHardlinksHelpTextWarning": "Occasionalmente, i blocchi dei file possono impedire la ridenominazione dei file in fase di seeding. È possibile disattivare temporaneamente il seeding e utilizzare la funzione di rinomina di {appName} per evitare il problema.", "CreateEmptyArtistFolders": "Crea le cartelle dei film se non esistono", @@ -80,24 +80,24 @@ "CutoffHelpText": "Una volta raggiunta questa qualità, {appName} non scaricherà più film", "CutoffUnmet": "Soglia Non Raggiunta", "Dates": "Date", - "DBMigration": "Migrazione del DataBase", + "DatabaseMigration": "Migrazione del DataBase", "DelayProfile": "Profili di Ritardo", "DelayProfiles": "Profili di Ritardo", "Delete": "Cancella", - "DeleteBackup": "Cancellare il backup", + "DeleteBackup": "Cancella Backup", "DeleteBackupMessageText": "Sei sicuro di voler cancellare il backup '{0}'?", "DeleteDelayProfile": "Cancellare il profilo di ritardo", "DeleteDelayProfileMessageText": "Sei sicuro di voler cancellare questo profilo di ritardo?", - "DeleteDownloadClient": "Cancellare il client di download", + "DeleteDownloadClient": "Cancella Client di Download", "DeleteDownloadClientMessageText": "Sei sicuro di voler eliminare il client di download '{0}'?", "DeleteEmptyFolders": "Cancellare le cartelle vuote", "DeleteImportListExclusion": "Cancellare la lista delle esclusioni", "DeleteImportListExclusionMessageText": "Sei sicuro di voler cancellare questa lista di esclusioni delle importazioni?", "DeleteImportListMessageText": "Sei sicuro di voler eliminare la lista '{0}'?", - "DeleteIndexer": "Cancella Indexer", + "DeleteIndexer": "Cancella Indicizzatore", "DeleteIndexerMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?", "DeleteMetadataProfileMessageText": "Sicuro di voler cancellare il profilo di qualità {0}", - "DeleteNotification": "Cancellare la notifica", + "DeleteNotification": "Cancella Notifica", "DeleteNotificationMessageText": "Sei sicuro di voler eliminare la notifica '{0}'?", "DeleteQualityProfile": "Cancellare il profilo di qualità", "DeleteQualityProfileMessageText": "Sicuro di voler cancellare il profilo di qualità {0}", @@ -124,12 +124,12 @@ "Edit": "Modifica", "Enable": "Abilita", "EnableAutomaticAdd": "Attiva l'aggiunta automatica", - "EnableAutomaticSearch": "Attiva la ricerca automatica", + "EnableAutomaticSearch": "Attiva la Ricerca Automatica", "EnableColorImpairedMode": "Abilità la modalità a colori alternati", "EnableColorImpairedModeHelpText": "Stile alterato per permettere agli utenti daltonici di distinguere meglio le informazioni con colori codificati", "EnableCompletedDownloadHandlingHelpText": "Importa automaticamente i download completati dai client di download", "EnableHelpText": "Abilita la creazione del file di metadati per questo tipo di metadati", - "EnableInteractiveSearch": "Abilita la ricerca interattiva", + "EnableInteractiveSearch": "Abilita la Ricerca Interattiva", "EnableRSS": "Abilita RSS", "EnableSSL": "Abilita SSL", "EnableSslHelpText": " Richiede il riavvio come amministratore per avere effetto", @@ -137,7 +137,6 @@ "ErrorLoadingContents": "Errore nel caricare i contenuti", "ErrorLoadingPreviews": "Errore nel caricare le anteprime", "Exception": "Eccezione", - "ExtraFileExtensionsHelpTexts1": "Liste di file Extra da importare separate da virgola (.nfo saranno importate come .nfo-orig)", "FileDateHelpText": "Modifica la data dei file in importazione/rescan", "FileManagement": "Gestione dei File", "Filename": "Nome del File", @@ -176,7 +175,6 @@ "ImportExtraFilesHelpText": "Importa file Extra corrispondenti (sottotitoli, nfo, ecc) dopo aver importato un film", "ImportFailedInterp": "Importazione fallita: {0}", "Importing": "Importazione", - "IncludeHealthWarningsHelpText": "Includi gli avvisi di salute", "IncludeUnknownArtistItemsHelpText": "Mostra le voci senza un film nella coda. Ciò potrebbe include film spostati o altro nelle categorie di {appName}", "IncludeUnmonitored": "Includi non Monitorati", "Indexer": "Indicizzatore", @@ -194,7 +192,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} supporta qualunque client di download che usi gli standard Newznab, cosi come gli altri client sotto.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} supporta qualunque indexer che usi gli standard Newznab, cosi come gli altri Indexer sotto.", "LidarrTags": "Tag di {appName}", - "LoadingTrackFilesFailed": "Caricamento dei file del Film fallito", "Local": "Locale", "LocalPath": "Percorso locale", "LocalPathHelpText": "Percorso che {appName} dovrebbe usare per accedere localmente al percorso remoto", @@ -235,9 +232,7 @@ "NoBackupsAreAvailable": "Nessun Backup disponibile", "NoHistory": "Nessuna Storia", "NoLeaveIt": "No, lascialo", - "NoLimitForAnyRuntime": "Nessun limite di durata", "NoLogFiles": "Nessun file di log", - "NoMinimumForAnyRuntime": "Nessuna durata minima", "None": "Nessuna", "NotificationTriggers": "Selettori di notifica", "NoUpdatesAreAvailable": "Nessun aggiornamento disponibile", @@ -247,7 +242,6 @@ "PortNumber": "Numero di porta", "PosterSize": "Dimensione del poster", "PreviewRename": "Anteprima Rinomina", - "PriorityHelpText": "Priorità dell'indexer da 1 (più alto) a 50 (più basso). Default: 25.", "Profiles": "Profili", "Proper": "Proper", "PropersAndRepacks": "Propers e Repack", @@ -381,7 +375,7 @@ "UnmonitoredHelpText": "Includi i film non monitorati nei feed di iCal", "UpdateAll": "Aggiorna Tutto", "UpdateAutomaticallyHelpText": "Download e installazione automatica degli aggiornamenti. Sarai comunque in grado in installarli dal menu Sistema: Aggiornamenti", - "UpdateMechanismHelpText": "Usa il programma di aggiornamento incorporato in {appName} o uno script", + "UpdateMechanismHelpText": "Usa il sistema di aggiornamento interno di {appName} o uno script", "Updates": "Aggiornamenti", "UpdateScriptPathHelpText": "Percorso verso uno script che prende un pacchetto di aggiornamento estratto e gestisce il resto del processo di aggiornamento", "UpgradeAllowedHelpText": "Se disabilitato la qualità non verrà incrementata", @@ -401,7 +395,7 @@ "Year": "Anno", "YesCancel": "Si, annulla", "About": "Info", - "AnalyticsEnabledHelpText": "Inviare informazioni anonime sull'utilizzo e sugli errori ai server di {appName}. Ciò include informazioni del tuo browser, come le pagine di {appName} che utilizzi, la segnalazione di errori e la versione del sistema operativo e del runtime. Utilizzeremo queste informazioni per dare priorità alle funzioni e alle correzioni di bug.", + "AnalyticsEnabledHelpText": "Inviare informazioni anonime sull'utilizzo e sugli errori ai server di {appName}. Ciò include informazioni sul tuo browser, quali pagine dell'interfaccia di {appName} usi, la segnalazione di errori così come la versione del sistema operativo e del runtime. Utilizzeremo queste informazioni per dare priorità alle nuove funzioni e alle correzioni di bug.", "AnalyticsEnabledHelpTextWarning": "Richiede il riavvio per avere effetti", "Automatic": "Automatico", "DelayingDownloadUntilInterp": "Ritardare il download fino al {0} a {1}", @@ -428,15 +422,11 @@ "SourcePath": "Percorso origine", "Calendar": "Calendario", "CalendarWeekColumnHeaderHelpText": "Mostra sopra ogni colonna quando la settimana è la vista attiva", - "Cancel": "Cancella", + "Cancel": "Annulla", "Clear": "Cancella", "ExpandAlbumByDefaultHelpText": "Album", "IgnoredAddresses": "Indirizzi ignorati", "NETCore": ".NET", - "OnGrabHelpText": "Quando viene prelevato", - "OnHealthIssueHelpText": "Quando c'è un problema", - "OnRenameHelpText": "Durante la rinomina", - "OnUpgradeHelpText": "In aggiornamento", "OpenBrowserOnStart": "Apri il browser all'avvio", "Options": "Opzioni", "Original": "Originale", @@ -485,7 +475,6 @@ "RemoveCompleted": "Rimuovi completati", "RemoveFailed": "Rimozione fallita", "ThisCannotBeCancelled": "Questo non può essere annullato una volta avviato senza disabilitare tutti i tuoi indexers.", - "OnApplicationUpdateHelpText": "All'aggiornamento dell'applicazione", "RemoveDownloadsAlert": "Le impostazioni per la rimozione sono stati spostati nelle impostazioni individuali dei Client di Download nella tabella sopra.", "OnApplicationUpdate": "All'aggiornamento dell'applicazione", "OnGrab": "Quando viene prelevato", @@ -510,7 +499,7 @@ "AddIndexer": "Aggiungi Indicizzatore", "AddMetadataProfile": "profilo metadati", "AddNew": "Aggiungi Nuovo", - "AddQualityProfile": "Aggiungi Profilo Qualità", + "AddQualityProfile": "Aggiungi un Profilo Qualità", "AddRemotePathMapping": "Aggiungi Mappatura di un Percorso Remoto", "AddRootFolder": "Aggiungi Cartella Radice", "AfterManualRefresh": "Dopo l'aggiornamento manuale", @@ -524,7 +513,7 @@ "Backup": "Backup", "BeforeUpdate": "Prima di aggiornare", "Close": "Chiudi", - "Connect": "Collega", + "Connect": "Collegamento", "Custom": "Personalizzato", "CustomFilters": "Filtri Personalizzati", "Date": "Data", @@ -617,7 +606,7 @@ "ArtistEditor": "Direttore Artistico", "CatalogNumber": "Numero Catalogo", "AddConnection": "Aggiungi Connessione", - "AddReleaseProfile": "Aggiungi Profilo di Pubblicazione", + "AddReleaseProfile": "Aggiungi un Profilo Release", "AlbumRelease": "Pubblicazione Album", "AlbumReleaseDate": "Data di Pubblicazione dell'Album", "AlbumStatus": "Stato Album", @@ -641,12 +630,12 @@ "DiscNumber": "Numero Disco", "Database": "Database", "EnableAutomaticAddHelpText": "Aggiungi Artista/Album a {appName} quando le sincronizzazione sono completare attraverso l'interfaccia o da {appName}", - "ChownGroup": "chown Group", - "Continuing": "Continuando", + "ChownGroup": "Gruppo chown", + "Continuing": "In Corso", "ContinuingAllTracksDownloaded": "Continuando (Tutte le tracce scaricate)", "ContinuingMoreAlbumsAreExpected": "Sono richiesti più Albums", "ContinuingNoAdditionalAlbumsAreExpected": "Non sono richiesti più Albums", - "ContinuingOnly": "Solo Continuare", + "ContinuingOnly": "Solo In Corso", "Country": "Nazione", "DateAdded": "Aggiunto in Data", "DeleteFilesHelpText": "Cancella le tracce e le cartelle degli artisti", @@ -667,14 +656,14 @@ "EditGroups": "Modifica Gruppi", "ChooseImportMethod": "Selezionare Metodo di Importazione", "BypassIfHighestQuality": "Aggira se è di Qualità Massima", - "CustomFormatScore": "Punteggio del Formato Personalizzato", + "CustomFormatScore": "Formato Personalizzato Punteggio", "MinimumCustomFormatScore": "Punteggio formato personalizzato minimo", "ClickToChangeReleaseGroup": "Clicca per cambiare gruppo di rilascio", - "CloneCustomFormat": "Duplica Formato Personalizzato", + "CloneCustomFormat": "Copia Formato Personalizzato", "Conditions": "Condizioni", "CopyToClipboard": "Copia negli Appunti", "CouldntFindAnyResultsForTerm": "Nessun risultato trovato per '{0}'", - "CustomFormat": "Formati Personalizzati", + "CustomFormat": "Formato Personalizzato", "CustomFormatRequiredHelpText": "Questa {0} condizione deve soddisfare il formato personalizzato per l'applicazione. Altrimenti una sola {1} corrispondenza è sufficiente.", "CustomFormatSettings": "Impostazioni dei Formati Personalizzati", "CustomFormats": "Formati Personalizzati", @@ -771,15 +760,14 @@ "ApplyTagsHelpTextRemove": "Rimuovi: Rimuove le etichette inserite", "DownloadClientTagHelpText": "Usa questo indicizzatore per i film con almeno un tag corrispondente. Lascia in bianco per usarlo con tutti i film.", "Yes": "Si", - "RemoveFromDownloadClientHelpTextWarning": "La rimozione eliminerà il download e i file dal client di download.", "RemoveSelectedItemQueueMessageText": "Sei sicuro di voler rimuovere {0} dalla coda?", "RemoveSelectedItemsQueueMessageText": "Sei sicuro di voler rimuovere {0} dalla coda?", "DeleteSelectedDownloadClientsMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?", "DeleteSelectedImportListsMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?", "DeleteSelectedIndexersMessageText": "Sei sicuro di voler eliminare l'indexer '{0}'?", "ApplyTagsHelpTextHowToApplyArtists": "Come applicare etichette agli indicizzatori selezionati", - "ApplyTagsHelpTextHowToApplyDownloadClients": "Come applicare etichette agli autori selezionati", - "ApplyTagsHelpTextHowToApplyImportLists": "Come applicare etichette agli autori selezionati", + "ApplyTagsHelpTextHowToApplyDownloadClients": "Come applicare etichette ai client di download selezionati", + "ApplyTagsHelpTextHowToApplyImportLists": "Come applicare etichette alle liste di importazione selezionate", "ApplyTagsHelpTextHowToApplyIndexers": "Come applicare etichette agli indicizzatori selezionati", "SomeResultsAreHiddenByTheAppliedFilter": "Tutti i risultati sono nascosti dai filtri applicati", "SuggestTranslationChange": "Suggerisci un cambio nella traduzione", @@ -810,21 +798,21 @@ "AlbumsLoadError": "Non riesco a caricare i backup", "OrganizeSelectedArtists": "Organizza i film selezionati", "AuthBasic": "Base (Popup del Browser)", - "AuthForm": "Moduli (Pagina di Accesso)", + "AuthForm": "Form (Pagina di Login)", "AuthenticationRequired": "Autenticazione richiesta", - "AuthenticationRequiredHelpText": "Cambia a quali richieste l'autenticazione verrà richiesta. Non cambiare se non comprendi i rischi.", + "AuthenticationRequiredHelpText": "Cambia a quali richieste l'autenticazione verrà chiesta. Non cambiare se non comprendi i rischi.", "Auto": "Auto", "UpdateFiltered": "Aggiorna Filtrati", - "AddAutoTagError": "Non riesco ad aggiungere una nuova lista, riprova.", - "AddConditionError": "Non riesco ad aggiungere una nuova condizione, riprova.", + "AddAutoTagError": "Non è stato possibile aggiungere una nuova etichetta automatica. Riprova.", + "AddConditionError": "Non è stato possibile aggiungere una nuova condizione. Riprova.", "DeleteSpecification": "Cancella la Notifica", "DeleteSpecificationHelpText": "Sei sicuro di voler eliminare la condizione '{name}'?", "AddNewArtistSearchForMissingAlbums": "Avvia ricerca film mancanti", - "Connection": "Collegamenti", + "Connection": "Connessione", "Large": "Grande", "Negate": "Negare", "RenameFiles": "Rinomina File", - "AuthenticationRequiredWarning": "Per impedire accessi remoti senza autenticazione, {appName} ora richiede che l'autenticazione venga attivata. Puoi disattivare l'autenticazione per indirizzi privati.", + "AuthenticationRequiredWarning": "Per prevenire accessi remoti non autorizzati, {appName} da ora richiede che l'autenticazione sia abilitata. Opzionalmente puoi disabilitare l'autenticazione per gli indirizzi di rete locali.", "BypassIfHighestQualityHelpText": "Evita il ritardo quando la release ha la qualità massima abilitata nel profilo qualità con il protocollo preferito", "ConditionUsingRegularExpressions": "Questa condizione si applica usando espressione regolari. Nota che i caratteri {0} hanno significati speciali e devono essere evitati con un {1}", "DeleteArtistFolderHelpText": "Elimina la cartella del film e il suo contenuto", @@ -835,5 +823,36 @@ "PosterOptions": "Opzioni dei poster", "Posters": "Locandine", "Small": "Piccolo", - "Table": "Tabella" + "Table": "Tabella", + "AddImportListExclusionAlbumHelpText": "Impedire che il film venga aggiunto a {appName} dalle liste", + "ExtraFileExtensionsHelpText": "Liste di file Extra da importare separate da virgola (.nfo saranno importate come .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Esempi: '.sub, .nfo' or 'sub,nfo'", + "NoLimitForAnyDuration": "Nessun limite di durata", + "NoMinimumForAnyDuration": "Nessuna durata minima", + "PreferredSize": "Dimensione preferita", + "Unlimited": "Illimitato", + "CloneCondition": "Duplica Condizione", + "DeleteArtistFoldersHelpText": "Elimina la cartella del film e il suo contenuto", + "AddCondition": "Aggiungi Condizione", + "AppUpdated": "{appName} Aggiornato", + "Clone": "Copia", + "EditSelectedDownloadClients": "Modifica i Client di Download Selezionati", + "EditSelectedImportLists": "Modifica le Liste di Importazione Selezionate", + "DeleteCondition": "Cancella Condizione", + "AddConnectionImplementation": "Aggiungi Connessione - {implementationName}", + "AddConditionImplementation": "Aggiungi Condizione - {implementationName}", + "AddDownloadClientImplementation": "Aggiungi un Client di Download - {implementationName}", + "AddIndexerImplementation": "Aggiungi indicizzatore - {implementationName}", + "AuthenticationMethod": "Metodo di Autenticazione", + "AuthenticationMethodHelpTextWarning": "Selezione un metodo di autenticazione valido", + "AuthenticationRequiredPasswordHelpTextWarning": "Inserisci la nuova password", + "AddAutoTag": "Aggiungi Etichetta Automatica", + "AutoTagging": "Tagging Automatico", + "ClearBlocklist": "Svuota Lista dei Blocchi", + "ClearBlocklistMessageText": "Sicuro di voler cancellare la Lista dei Blocchi?", + "CloneAutoTag": "Copia Auto Tag", + "AuthenticationRequiredUsernameHelpTextWarning": "Inserisci username", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Conferma la nuova password", + "AddImportListImplementation": "Aggiungi lista di importazione - {implementationName}", + "AutoRedownloadFailed": "Download fallito" } diff --git a/src/NzbDrone.Core/Localization/Core/ja.json b/src/NzbDrone.Core/Localization/Core/ja.json index 6c6533a62..5ad565e85 100644 --- a/src/NzbDrone.Core/Localization/Core/ja.json +++ b/src/NzbDrone.Core/Localization/Core/ja.json @@ -54,7 +54,6 @@ "ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "個々のダウンロードクライアントの詳細については、情報ボタンをクリックしてください。", "ForMoreInformationOnTheIndividualIndexersClickOnTheInfoButtons": "個々のインデクサーの詳細については、情報ボタンをクリックしてください。", "ForMoreInformationOnTheIndividualListsClickOnTheInfoButtons": "個々のインポートリストの詳細については、情報ボタンをクリックしてください。", - "IncludeHealthWarningsHelpText": "健康上の警告を含める", "IncludeUnknownArtistItemsHelpText": "キューに映画がないアイテムを表示します。これには、削除された映画や、ラダーのカテゴリに含まれるその他のものが含まれる可能性があります", "IncludeUnmonitored": "監視されていないものを含める", "IndexerPriority": "インデクサの優先順位", @@ -68,7 +67,6 @@ "LaunchBrowserHelpText": " Webブラウザーを開き、アプリの起動時にRadarrホームページに移動します。", "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "Radarrは、Newznab標準を使用するすべてのダウンロードクライアント、および以下にリストされている他のダウンロードクライアントをサポートします。", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Radarrは、Newznab標準を使用するすべてのインデクサー、および以下にリストされている他のインデクサーをサポートします。", - "LoadingTrackFilesFailed": "動画ファイルの読み込みに失敗しました", "Local": "地元", "LocalPath": "ローカルパス", "LocalPathHelpText": "Radarrがリモートパスにローカルにアクセスするために使用する必要があるパス", @@ -107,15 +105,9 @@ "NoBackupsAreAvailable": "バックアップは利用できません", "NoHistory": "履歴はありません", "NoLeaveIt": "いいえ、そのままにしておきます", - "NoLimitForAnyRuntime": "ランタイムに制限はありません", "NoLogFiles": "ログファイルがありません", - "NoMinimumForAnyRuntime": "ランタイムの最小値はありません", "NotificationTriggers": "通知トリガー", "NoUpdatesAreAvailable": "利用可能なアップデートはありません", - "OnGrabHelpText": "グラブで", - "OnHealthIssueHelpText": "健康問題について", - "OnRenameHelpText": "名前の変更について", - "OnUpgradeHelpText": "アップグレード時", "OpenBrowserOnStart": "起動時にブラウザを開く", "Options": "オプション", "Original": "元の", @@ -128,7 +120,6 @@ "PortNumber": "ポート番号", "PosterSize": "ポスターサイズ", "PreviewRename": "プレビューの名前変更", - "PriorityHelpText": "インデクサーの優先度は1(最高)から50(最低)です。デフォルト:25。", "Profiles": "プロファイル", "Proper": "適切な", "PropersAndRepacks": "適切なものと再梱包", @@ -264,7 +255,7 @@ "CutoffHelpText": "この品質に達すると、Radarrは映画をダウンロードしなくなります", "CutoffUnmet": "カットオフアンメット", "Dates": "日付", - "DBMigration": "DB移行", + "DatabaseMigration": "DB移行", "Delete": "削除", "DeleteImportListExclusion": "インポートリストの除外を削除する", "DeleteImportListExclusionMessageText": "このインポートリストの除外を削除してもよろしいですか?", @@ -301,7 +292,6 @@ "EnableInteractiveSearch": "インタラクティブ検索を有効にする", "EnableRSS": "RSSを有効にする", "EnableSSL": "SSLを有効にする", - "ExtraFileExtensionsHelpTexts1": "インポートする追加ファイルのコンマ区切りリスト(.nfoは.nfo-origとしてインポートされます)", "FileDateHelpText": "インポート/再スキャン時にファイルの日付を変更する", "FileManagement": "ファイル管理", "Filename": "ファイル名", @@ -653,7 +643,6 @@ "ApplyTagsHelpTextAdd": "追加:既存のタグリストにタグを追加します", "ApplyTagsHelpTextRemove": "削除:入力したタグを削除します", "ApplyTagsHelpTextReplace": "置換:タグを入力したタグに置き換えます(すべてのタグをクリアするには、タグを入力しないでください)", - "RemoveFromDownloadClientHelpTextWarning": "削除すると、ダウンロードとファイルがダウンロードクライアントから削除されます。", "RemoveSelectedItemQueueMessageText": "キューから{0}アイテム{1}を削除してもよろしいですか?", "RemoveSelectedItemsQueueMessageText": "キューから{0}アイテム{1}を削除してもよろしいですか?", "SetTags": "タグを設定する", @@ -703,5 +692,12 @@ "DeleteArtistFoldersHelpText": "ムービーフォルダとその内容を削除します", "DeleteAutoTagHelpText": "品質プロファイル{0}を削除してもよろしいですか", "Negate": "ネゲート", - "Table": "テーブル" + "Table": "テーブル", + "AddImportListExclusionAlbumHelpText": "リストによって映画が{appName}に追加されないようにする", + "NoLimitForAnyDuration": "ランタイムに制限はありません", + "NoMinimumForAnyDuration": "ランタイムの最小値はありません", + "PreferredSize": "推奨サイズ", + "Unlimited": "無制限", + "ExtraFileExtensionsHelpText": "インポートする追加ファイルのコンマ区切りリスト(.nfoは.nfo-origとしてインポートされます)", + "ExtraFileExtensionsHelpTextsExamples": "例: '。sub、.nfo'または 'sub、nfo'" } diff --git a/src/NzbDrone.Core/Localization/Core/ko.json b/src/NzbDrone.Core/Localization/Core/ko.json index 19a2aa2d0..db28654e4 100644 --- a/src/NzbDrone.Core/Localization/Core/ko.json +++ b/src/NzbDrone.Core/Localization/Core/ko.json @@ -54,7 +54,7 @@ "CreateGroup": "그룹 만들기", "CutoffHelpText": "이 품질에 도달하면 Radarr는 더 이상 영화를 다운로드 하지 않습니다.", "CutoffUnmet": "컷오프 미충족", - "DBMigration": "DB 마이그레이션", + "DatabaseMigration": "DB 마이그레이션", "DelayProfile": "지연 프로필", "DelayProfiles": "지연 프로필", "Delete": "지우다", @@ -110,7 +110,6 @@ "ErrorLoadingContents": "콘텐츠로드 오류", "ErrorLoadingPreviews": "미리보기를로드하는 중에 오류가 발생했습니다.", "Exception": "예외", - "ExtraFileExtensionsHelpTexts1": "가져올 추가 파일의 쉼표로 구분 된 목록 (.nfo는 .nfo-orig로 가져옴)", "FileDateHelpText": "가져 오기 / 재검색시 파일 날짜 변경", "FileManagement": "파일 관리", "Filename": "파일 이름", @@ -154,7 +153,6 @@ "IsCutoffUpgradeUntilThisQualityIsMetOrExceeded": "이 품질이 충족되거나 초과 될 때까지 업그레이드", "IsTagUsedCannotBeDeletedWhileInUse": "사용 중에는 삭제할 수 없습니다.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Radarr는 Newznab 표준을 사용하는 모든 인덱서와 아래 나열된 다른 인덱서를 지원합니다.", - "LoadingTrackFilesFailed": "영화 파일을로드하지 못했습니다.", "Local": "현지", "LocalPath": "로컬 경로", "LocalPathHelpText": "Radarr가 원격 경로에 로컬로 액세스하는 데 사용해야하는 경로", @@ -187,12 +185,9 @@ "Monitored": "모니터링", "MoreInfo": "더 많은 정보", "NoLogFiles": "로그 파일 없음", - "NoMinimumForAnyRuntime": "런타임에 대한 최소값 없음", "None": "없음", "NotificationTriggers": "알림 트리거", "NoUpdatesAreAvailable": "사용 가능한 업데이트가 없습니다.", - "OnRenameHelpText": "이름 변경시", - "OnUpgradeHelpText": "업그레이드시", "OpenBrowserOnStart": "시작시 브라우저 열기", "Options": "옵션", "Original": "실물", @@ -205,7 +200,6 @@ "Port": "포트", "PortNumber": "포트 번호", "PreviewRename": "이름 변경 미리보기", - "PriorityHelpText": "인덱서 우선 순위는 1 (가장 높음)에서 50 (가장 낮음)까지입니다. 기본값 : 25.", "Profiles": "프로필", "Proper": "적절한", "PropersAndRepacks": "적절하고 재 포장", @@ -393,7 +387,6 @@ "ImportExtraFilesHelpText": "동영상 파일을 가져온 후 일치하는 추가 파일 (자막, nfo 등) 가져 오기", "ImportFailedInterp": "가져 오기 실패 : {0}", "Importing": "가져 오기", - "IncludeHealthWarningsHelpText": "건강 경고 포함", "IncludeUnknownArtistItemsHelpText": "대기열에 영화가없는 항목을 표시합니다. 여기에는 제거 된 영화 또는 {appName} 카테고리의 다른 항목이 포함될 수 있습니다.", "LaunchBrowserHelpText": " 웹 브라우저를 열고 앱 시작시 {appName} 홈페이지로 이동합니다.", "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "Radarr는 Newznab 표준을 사용하는 모든 다운로드 클라이언트와 아래 나열된 다른 다운로드 클라이언트를 지원합니다.", @@ -405,9 +398,6 @@ "NoBackupsAreAvailable": "사용 가능한 백업이 없습니다.", "NoHistory": "역사 없음", "NoLeaveIt": "아니, 놔둬", - "NoLimitForAnyRuntime": "런타임 제한 없음", - "OnGrabHelpText": "잡기", - "OnHealthIssueHelpText": "건강 문제", "QualityDefinitions": "품질 정의", "QualityProfile": "품질 프로필", "QualityProfiles": "품질 프로필", @@ -647,7 +637,6 @@ "RemoveSelectedItemQueueMessageText": "대기열에서 {0} 항목 {1}을 제거하시겠습니까?", "RemoveSelectedItemsQueueMessageText": "대기열에서 {0} 항목 {1}을 제거하시겠습니까?", "ExistingTag": "기존 태그", - "RemoveFromDownloadClientHelpTextWarning": "제거하면 다운로드 클라이언트에서 다운로드 및 파일이 제거됩니다.", "DeleteSelectedIndexersMessageText": "인덱서 '{0}'을 (를) 삭제 하시겠습니까?", "ApplyTagsHelpTextHowToApplyArtists": "선택한 동영상에 태그를 적용하는 방법", "ApplyTagsHelpTextHowToApplyDownloadClients": "선택한 동영상에 태그를 적용하는 방법", @@ -683,5 +672,11 @@ "DeleteAutoTagHelpText": "품질 프로필 {0}을 (를) 삭제 하시겠습니까?", "DeleteSpecification": "알림 삭제", "DeleteSpecificationHelpText": "품질 프로필 {0}을 (를) 삭제 하시겠습니까?", - "LidarrTags": "{appName} 태그" + "LidarrTags": "{appName} 태그", + "AddImportListExclusionAlbumHelpText": "영화가 목록별로 {appName}에 추가되지 않도록 방지", + "ExtraFileExtensionsHelpText": "가져올 추가 파일의 쉼표로 구분 된 목록 (.nfo는 .nfo-orig로 가져옴)", + "ExtraFileExtensionsHelpTextsExamples": "예 : '.sub, .nfo'또는 'sub, nfo'", + "NoLimitForAnyDuration": "런타임 제한 없음", + "NoMinimumForAnyDuration": "런타임에 대한 최소값 없음", + "DeleteArtistFoldersHelpText": "동영상 폴더 및 내용 삭제" } diff --git a/src/NzbDrone.Core/Localization/Core/lv.json b/src/NzbDrone.Core/Localization/Core/lv.json index 0967ef424..ccb0acbe1 100644 --- a/src/NzbDrone.Core/Localization/Core/lv.json +++ b/src/NzbDrone.Core/Localization/Core/lv.json @@ -1 +1,12 @@ -{} +{ + "AddConditionImplementation": "Pievienot Nosacījumu - {implementationName}", + "AddDelayProfile": "Pievienot Aizkaves Profilu", + "AddConnectionImplementation": "Pievienot Savienojumu - {implementationName}", + "Actions": "Darbības", + "About": "Par", + "Activity": "Aktivitāte", + "Add": "Pievienot", + "AddAutoTag": "Pievienot Automātisko Tagu", + "AddCondition": "Pievienot Nosacījumu", + "AddConnection": "Pievienot Savienojumu" +} diff --git a/src/NzbDrone.Core/Localization/Core/nb_NO.json b/src/NzbDrone.Core/Localization/Core/nb_NO.json index 6a7905cce..45f59a58b 100644 --- a/src/NzbDrone.Core/Localization/Core/nb_NO.json +++ b/src/NzbDrone.Core/Localization/Core/nb_NO.json @@ -149,7 +149,7 @@ "Seeders": "Delere", "Title": "Tittel", "UI": "Grensesnitt", - "Add": "Legge til", + "Add": "Legg til", "EditDelayProfile": "Legg til forsinkelsesprofil", "Peers": "Likemenn", "EditMetadataProfile": "metadataprofil", @@ -227,5 +227,7 @@ "ConnectionLostToBackend": "Radarr har mistet tilkoblingen til baksystemet og må lastes inn på nytt for å gjenopprette funksjonalitet.", "ImportLists": "importeringsliste", "Enabled": "Aktiver", - "Release": " utgivelse" + "Release": " utgivelse", + "AddAlbumWithTitle": "Legg til {albumTitle}", + "AddArtistWithName": "Legg til {artistName}" } diff --git a/src/NzbDrone.Core/Localization/Core/nl.json b/src/NzbDrone.Core/Localization/Core/nl.json index 706a07c23..780537bd8 100644 --- a/src/NzbDrone.Core/Localization/Core/nl.json +++ b/src/NzbDrone.Core/Localization/Core/nl.json @@ -40,17 +40,17 @@ "DelayProfiles": "Vertragingsprofielen", "Delete": "Verwijder", "DeleteBackup": "Verwijder Backup", - "DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{0}' wilt verwijderen?", + "DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{name}' wilt verwijderen?", "DeleteDelayProfile": "Verwijder Vertragingsprofiel", "DeleteDelayProfileMessageText": "Weet u zeker dat u dit vertragingsprofiel wilt verwijderen?", "DeleteDownloadClient": "Verwijder Downloader", - "DeleteDownloadClientMessageText": "Bent u zeker dat u de downloader '{0}' wilt verwijderen?", + "DeleteDownloadClientMessageText": "Bent u zeker dat u de downloader '{name}' wilt verwijderen?", "DeleteEmptyFolders": "Verwijder lege mappen", "DeleteImportListExclusion": "Verwijder van Uitzonderingenlijst", "DeleteImportListExclusionMessageText": "Bent u zeker dat u dit van de uitzonderingenlijst wilt verwijderen?", "DeleteImportListMessageText": "Bent u zeker dat u de lijst '{0}' wilt verwijderen?", "DeleteIndexer": "Verwijder Indexeerder", - "DeleteIndexerMessageText": "Bent u zeker dat u de indexeerder '{0}' wilt verwijderen?", + "DeleteIndexerMessageText": "Bent u zeker dat u de indexeerder '{name}' wilt verwijderen?", "DeleteMetadataProfileMessageText": "Bent u zeker dat u het kwaliteitsprofiel {name} wilt verwijderen?", "DeleteNotification": "Verwijder Notificatie", "DeleteNotificationMessageText": "Bent u zeker dat u de notificatie '{0}' wilt verwijderen?", @@ -78,7 +78,6 @@ "ErrorLoadingContents": "Fout bij laden van inhoud", "ErrorLoadingPreviews": "Fout bij laden van voorvertoningen", "Exception": "Uitzondering", - "ExtraFileExtensionsHelpTexts1": "Komma gescheiden lijst met extra bestanden om te importeren (.nfo zal als .nfo-orig worden geïmporteerd)", "FileDateHelpText": "Pas bestandsdatum aan tijdens het importeren/herscannen", "FileManagement": "Bestandsbeheer", "Filename": "Bestandsnaam", @@ -117,7 +116,6 @@ "ImportExtraFilesHelpText": "Importeer bijhorende extra bestanden (ondertitels, nfo, enz.) na het importeren van een film", "ImportFailedInterp": "Importeren mislukt: {0}", "Importing": "Importeren", - "IncludeHealthWarningsHelpText": "Voeg Gezondheidswaarschuwingen Toe", "IncludeUnknownArtistItemsHelpText": "Toon items zonder een film in de wachtrij, dit kan verwijderde films, TV series of iets anders in {appName} zijn categorie omvatten", "IncludeUnmonitored": "Voeg Onbewaakte Toe", "Indexer": "Indexeerder", @@ -134,12 +132,8 @@ "NoBackupsAreAvailable": "Geen veiligheidskopieën beschikbaar", "NoHistory": "Geen geschiedenis", "NoLeaveIt": "Nee, Ongemoeid Laten", - "NoLimitForAnyRuntime": "Geen limiet voor eender welke speelduur", "NoLogFiles": "Geen logbestanden", - "NoMinimumForAnyRuntime": "Geen minimum voor een speelduur", "None": "Geen", - "OnHealthIssueHelpText": "Bij Gezondheidsprobleem", - "OnRenameHelpText": "Bij Hernoemen", "Original": "Origineel", "PackageVersion": "Pakket Versie", "PageSize": "Pagina Grootte", @@ -150,7 +144,6 @@ "PortNumber": "Poort Nummer", "PosterSize": "Affiche Grootte", "PreviewRename": "Voorbeeldweergave Naamswijziging", - "PriorityHelpText": "Indexeerder Prioriteit van 1 (Hoogste) tot 50 (Laagste). Standaard: 25.", "Profiles": "Profielen", "Proper": "PROPER", "PropersAndRepacks": "PROPERS en REPACKS", @@ -366,7 +359,7 @@ "CutoffHelpText": "Wanneer deze kwaliteit is behaald, zal {appName} niet langer films downloaden", "CutoffUnmet": "Onbereikte Drempel", "Dates": "Datum en tijd", - "DBMigration": "DB Migratie", + "DatabaseMigration": "DB Migratie", "DelayProfile": "Uitstel profiel", "DeleteQualityProfileMessageText": "Bent u zeker dat u het kwaliteitsprofiel {name} wilt verwijderen?", "DeleteReleaseProfile": "Verwijder Vertragingsprofiel", @@ -389,7 +382,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} ondersteund elke downloader die gebruik maakt van de Newznab standaard, tevens ook de ander hieronder weergegeven downloaders.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} ondersteund elke indexeerder die gebruik maakt van de Newznab standaard, tevens ook de ander hieronder weergegeven indexeerders.", "LidarrTags": "{appName} Tags", - "LoadingTrackFilesFailed": "Laden van filmbestanden is mislukt", "Local": "Lokaal", "LocalPath": "Lokaal Pad", "LocalPathHelpText": "Het pad dat {appName} lokaal moet gebruiken om toegang te krijgen tot het externe pad", @@ -425,8 +417,6 @@ "MustNotContain": "Mag Niet Bevatten", "NotificationTriggers": "Melding Reactiestarters", "NoUpdatesAreAvailable": "Geen updates beschikbaar", - "OnGrabHelpText": "Bij Ophalen", - "OnUpgradeHelpText": "Bij Opwaarderen", "OpenBrowserOnStart": "Open de browser bij het starten", "Options": "Opties", "Path": "Pad", @@ -462,7 +452,6 @@ "Label": "Label", "Scheduled": "Gepland", "AddMissing": "Voeg ontbrekende toe", - "OnApplicationUpdateHelpText": "Bij applicatie update", "Duration": "Duur", "OnApplicationUpdate": "Bij applicatie update", "OnHealthIssue": "Bij Gezondheidsprobleem", @@ -684,7 +673,6 @@ "UpdateCheckUINotWritableMessage": "Kan de update niet installeren omdat de UI map '{0}' niet schrijfbaar is voor de gebruiker '{1}'.", "ApiKeyValidationHealthCheckMessage": "Maak je API sleutel alsjeblieft minimaal {0} karakters lang. Dit kan gedaan worden via de instellingen of het configuratiebestand", "IndexerJackettAll": "Indexeerders die het niet ondersteunde 'all' endpoint van Jacket gebruiken: {0}", - "OnHealthRestoredHelpText": "Bij opgelost gezondheidsprobleem", "OnHealthRestored": "Bij opgelost gezondheidsprobleem", "RemoveDownloadsAlert": "De verwijderopties zijn verplaatst naar de opties voor de individuele downloadprogramma's in de tabel hierboven.", "RemoveFailed": "Verwijderen mislukt", @@ -725,7 +713,6 @@ "RemoveSelectedItem": "Verwijder geselecteerde item", "DownloadClientTagHelpText": "Gebruik deze indexer alleen voor films met ten minste één overeenkomende tag. Laat leeg om te gebruiken met alle films.", "QueueIsEmpty": "Wachtrij is leeg", - "RemoveFromDownloadClientHelpTextWarning": "Het verwijderen zal zowel de download als de bestanden verwijderen bij de downloader.", "RemoveSelectedItemQueueMessageText": "Weet je zeker dat je {0} van de wachtrij wilt verwijderen?", "RemoveSelectedItemsQueueMessageText": "Weet je zeker dat je {0} van de wachtrij wilt verwijderen?", "DeleteSelectedDownloadClientsMessageText": "Bent u zeker dat u de indexeerder '{0}' wilt verwijderen?", @@ -762,7 +749,7 @@ "ErrorLoadingContent": "Er ging iets fout bij het laden van dit item", "AddConditionImplementation": "Voeg voorwaarde toe - {implementationName}", "AddConnectionImplementation": "Voeg connectie toe - {implementationName}", - "AddDownloadClientImplementation": "Voeg Downloadclient toe - {implementationName}", + "AddDownloadClientImplementation": "Voeg Downloadclient Toe - {implementationName}", "AddIndexerImplementation": "Indexeerder toevoegen - {implementationName}", "AppUpdated": "{appName} is geüpdatet", "AppUpdatedVersion": "{appName} is geüpdatet naar versie '{version}', om de laatste wijzigingen door te voeren moet je mogelijk {appName} herstarten", @@ -770,5 +757,65 @@ "AddImportList": "Importlijst toevoegen", "AuthenticationMethod": "Authenticatiemethode", "AuthenticationMethodHelpTextWarning": "Selecteer een geldige verificatie methode", - "AddImportListImplementation": "Importlijst toevoegen - {implementationName}" + "AddImportListImplementation": "Importlijst toevoegen - {implementationName}", + "EditImportListImplementation": "Importlijst toevoegen - {implementationName}", + "EditIndexerImplementation": "Indexeerder toevoegen - {implementationName}", + "ReleaseProfile": "releaseprofiel", + "Small": "Klein", + "AuthenticationRequiredHelpText": "Pas aan welke requests verificatie nodig hebben. Pas niets aan als je de risico's niet begrijpt.", + "AuthenticationRequiredPasswordHelpTextWarning": "Voer een nieuw wachtwoord in", + "AddImportListExclusionArtistHelpText": "Voorkom toevoegen van series aan {appName} door lijsten", + "ReleaseProfiles": "releaseprofiel", + "EditDownloadClientImplementation": "Voeg Downloadclient toe - {implementationName}", + "EditReleaseProfile": "Voeg Releaseprofiel toe", + "Episode": "aflevering", + "ExtraFileExtensionsHelpText": "Komma gescheiden lijst met extra bestanden om te importeren (.nfo zal als .nfo-orig worden geïmporteerd)", + "ExtraFileExtensionsHelpTextsExamples": "Voorbeelden: '.sub, .nfo' of 'sub,nfo'", + "GrabId": "ID Ophalen", + "ImportList": "importlijst", + "Large": "Groot", + "Negate": "Negeren", + "NoLimitForAnyDuration": "Geen limiet voor eender welke speelduur", + "NoMinimumForAnyDuration": "Geen minimum voor een speelduur", + "OrganizeSelectedArtists": "Sorteer Geselecteerde Films", + "Overview": "Overzicht", + "OverviewOptions": "Overzicht Opties", + "PreferredSize": "Gewenste Grootte", + "RenameFiles": "Hernoem Bestanden", + "Unlimited": "Onbeperkt", + "ImportLists": "importlijst", + "DisabledForLocalAddresses": "Uitgeschakeld voor lokale adressen", + "TBA": "NNB", + "PosterOptions": "Affiche Opties", + "Posters": "Affiches", + "Table": "Tabel", + "AddImportListExclusionAlbumHelpText": "Voorkom toevoegen van series aan {appName} door lijsten", + "EditConditionImplementation": "Voeg connectie toe - {implementationName}", + "EditConnectionImplementation": "Voeg connectie toe - {implementationName}", + "AlbumsLoadError": "Kon geen veiligheidskopieën laden", + "AuthForm": "Formulier (inlogpagina)", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Bevestig het nieuwe wachtwoord", + "AuthenticationRequiredUsernameHelpTextWarning": "Voeg een nieuwe gebruikersnaam in", + "AuthenticationRequiredWarning": "Om toegang zonder authenticatie te voorkomen vereist {appName} nu verificatie. Je kan dit optioneel uitschakelen voor lokale adressen.", + "AutoTagging": "Automatisch Taggen", + "AutoTaggingLoadError": "Laden van automatisch taggen is mislukt", + "AutoTaggingNegateHelpText": "Als aangevinkt worden de automatisch taggen regels worden niet toegepast als {implementationName} condities overeen komen.", + "BypassIfHighestQualityHelpText": "Vertraging negeren wanneer een release de hoogst mogelijke kwaliteit heeft in het kwaliteitsprofiel van het geprefereerde protocol", + "CloneAutoTag": "Kopieer Automatische Tag", + "ConditionUsingRegularExpressions": "Deze conditie toont een overeenkomst vanwege Reguliere Expressie. Merk op dat de karakters {0} een speciale betekenis hebben en met {1} moeten worden voorgegaan om hun oorspronkelijke betekenis te krijgen", + "Connection": "Connectie", + "DeleteArtistFolderHelpText": "Verwijder de film map en zijn inhoud", + "DeleteAutoTagHelpText": "Bent u zeker dat u de lijst '{name}' wilt verwijderen?", + "DeleteSpecification": "Verwijder Notificatie", + "DeleteSpecificationHelpText": "Bent u zeker dat u de lijst '{name}' wilt verwijderen?", + "AddListExclusionHelpText": "Voorkom toevoegen van series aan {appName} door lijsten", + "AddReleaseProfile": "Voeg Releaseprofiel toe", + "Auto": "Automatisch", + "AddAutoTag": "Voeg Automatische Tag toe", + "AddAutoTagError": "Niet in staat een nieuw automatisch label toe te voegen, probeer het opnieuw.", + "AddCondition": "Voeg Conditie toe", + "AddConditionError": "Kon geen nieuwe conditie toevoegen, gelieve opnieuw te proberen.", + "AddNewArtistSearchForMissingAlbums": "Begin met zoeken naar ontbrekende film", + "AuthBasic": "Basic (Browser Pop-up)", + "DeleteArtistFoldersHelpText": "Verwijder de film map en zijn inhoud" } diff --git a/src/NzbDrone.Core/Localization/Core/pl.json b/src/NzbDrone.Core/Localization/Core/pl.json index b2c143294..d90d361e2 100644 --- a/src/NzbDrone.Core/Localization/Core/pl.json +++ b/src/NzbDrone.Core/Localization/Core/pl.json @@ -38,7 +38,7 @@ "CutoffHelpText": "Po osiągnięciu tej jakości {appName} nie będzie już pobierał filmów", "CutoffUnmet": "Odcięcie niespełnione", "Dates": "Daktyle", - "DBMigration": "Migracja bazy danych", + "DatabaseMigration": "Migracja bazy danych", "DelayProfile": "Profil opóźnienia", "DelayProfiles": "Profile opóźnień", "Delete": "Usunąć", @@ -106,7 +106,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName} obsługuje każdego klienta pobierania, który używa standardu Newznab, a także innych klientów pobierania wymienionych poniżej.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} obsługuje każdy indeksator, który używa standardu Newznab, a także inne indeksatory wymienione poniżej.", "LidarrTags": "Tagi radarowe", - "LoadingTrackFilesFailed": "Ładowanie plików filmowych nie powiodło się", "Local": "Lokalny", "MarkAsFailed": "Oznacz jako niepowodzenie", "MarkAsFailedMessageText": "Czy na pewno chcesz oznaczyć „{0}” jako nieudany?", @@ -128,21 +127,14 @@ "New": "Nowy", "NoBackupsAreAvailable": "Brak dostępnych kopii zapasowych", "NoLeaveIt": "Nie, zostaw to", - "NoLimitForAnyRuntime": "Brak ograniczeń dla dowolnego czasu wykonywania", "NoLogFiles": "Brak plików dziennika", - "NoMinimumForAnyRuntime": "Brak minimum dla dowolnego środowiska uruchomieniowego", "None": "Żaden", "NotificationTriggers": "Wyzwalacze powiadomień", "NoUpdatesAreAvailable": "Brak dostępnych aktualizacji", - "OnGrabHelpText": "Na Grab", - "OnHealthIssueHelpText": "W kwestii zdrowia", - "OnRenameHelpText": "Zmiana nazwy", - "OnUpgradeHelpText": "Przy aktualizacji", "OpenBrowserOnStart": "Otwórz przeglądarkę przy starcie", "Options": "Opcje", "Original": "Oryginalny", "PackageVersion": "Wersja pakietu", - "PriorityHelpText": "Priorytet indeksatora od 1 (najwyższy) do 50 (najniższy). Domyślnie: 25.", "Profiles": "Profile", "Proper": "Właściwy", "PropersAndRepacks": "Propers and Repacks", @@ -273,7 +265,7 @@ "SourcePath": "Ścieżka źródłowa", "Uptime": "Dostępność", "EnableRSS": "Włącz RSS", - "Actions": "Aktywności", + "Actions": "Akcje", "ApiKeyHelpTextWarning": "Wymaga ponownego uruchomienia, aby odniosło skutek", "ApplyTags": "Zastosuj tagi", "ApplyTagsHelpTextReplace": "Zastąp: Zastąp tagi wprowadzonymi tagami (nie wprowadzaj tagów, aby usunąć wszystkie tagi)", @@ -300,7 +292,6 @@ "ErrorLoadingContents": "Błąd podczas ładowania treści", "ErrorLoadingPreviews": "Błąd podczas ładowania podglądów", "Exception": "Wyjątek", - "ExtraFileExtensionsHelpTexts1": "Rozdzielana przecinkami lista dodatkowych plików do zaimportowania (.nfo zostanie zaimportowane jako .nfo-orig)", "FileDateHelpText": "Zmień datę pliku przy imporcie / ponownym skanowaniu", "FileManagement": "Zarządzanie plikami", "Filename": "Nazwa pliku", @@ -325,7 +316,6 @@ "HasPendingChangesSaveChanges": "Zapisz zmiany", "History": "Historia", "HostHelpText": "Ten sam host, który podałeś dla zdalnego klienta pobierania", - "IncludeHealthWarningsHelpText": "Uwzględnij ostrzeżenia zdrowotne", "IncludeUnknownArtistItemsHelpText": "Pokaż elementy bez filmu w kolejce. Może to obejmować usunięte filmy lub cokolwiek innego w kategorii {appName}", "IsTagUsedCannotBeDeletedWhileInUse": "Nie można usunąć, gdy jest używany", "LocalPath": "Ścieżka lokalna", @@ -465,13 +455,12 @@ "RemoveDownloadsAlert": "Ustawienia usuwania zostały przeniesione do ustawień poszczególnych klientów pobierania powyżej.", "RemoveFailed": "Usuń nieudane", "OnApplicationUpdate": "Przy aktualizacji aplikacji", - "OnApplicationUpdateHelpText": "Przy aktualizacji aplikacji", "Duration": "Czas trwania", "UserAgentProvidedByTheAppThatCalledTheAPI": "User-Agent podawany przez aplikację wywołującą API", "Add": "Dodaj", "AddDelayProfile": "Dodaj profil opóźnienia", "Added": "Dodane", - "AddIndexer": "Dodaj indeksator", + "AddIndexer": "Dodaj indekser", "AddNew": "Dodaj nowy", "AddQualityProfile": "Dodaj profil jakości", "AddRemotePathMapping": "Dodaj zdalne mapowanie ścieżki", @@ -577,7 +566,7 @@ "OutputPath": "Ścieżka wyjściowa", "Activity": "Aktywność", "AddConnection": "Dodaj połączenie", - "AddImportListExclusion": "Usuń wykluczenie listy importu", + "AddImportListExclusion": "Dodaj wykluczenie listy importu", "General": "Generał", "Started": "Rozpoczęto", "TimeLeft": "Pozostały czas", @@ -699,7 +688,6 @@ "DownloadClientTagHelpText": "Korzystaj z tego indeksera wyłącznie w przypadku filmów z co najmniej jednym pasującym tagiem. Pozostaw pole puste, by używać do wszystkich filmów.", "QueueIsEmpty": "Kolejka jest pusta", "RemoveSelectedItems": "Usuń wybrane", - "RemoveFromDownloadClientHelpTextWarning": "Usunięcie spowoduje usunięcie pobierania i plików z klienta pobierania.", "RemoveSelectedItemQueueMessageText": "Czy na pewno chcesz usunąć {0} element {1} z kolejki?", "DeleteSelectedDownloadClientsMessageText": "Czy na pewno chcesz usunąć indeksator „{0}”?", "DeleteSelectedImportListsMessageText": "Czy na pewno chcesz usunąć indeksator „{0}”?", @@ -760,5 +748,17 @@ "Negate": "Negować", "PosterOptions": "Opcje plakatu", "Posters": "Plakaty", - "RenameFiles": "Zmień nazwy plików" + "RenameFiles": "Zmień nazwy plików", + "ExtraFileExtensionsHelpText": "Rozdzielana przecinkami lista dodatkowych plików do zaimportowania (.nfo zostanie zaimportowane jako .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Przykłady: „.sub, .nfo” lub „sub, nfo”", + "NoLimitForAnyDuration": "Brak ograniczeń dla dowolnego czasu wykonywania", + "NoMinimumForAnyDuration": "Brak minimum dla dowolnego środowiska uruchomieniowego", + "PreferredSize": "Preferowany rozmiar", + "Unlimited": "Nieograniczony", + "AddImportListExclusionAlbumHelpText": "Zapobiegaj dodawaniu filmu do {appName} przez listy", + "AddConditionImplementation": "Dodaj condition - {implementationName}", + "AddConnectionImplementation": "Dodaj Connection - {implementationName}", + "AddDownloadClientImplementation": "Dodaj klienta pobierania - {implementationName}", + "AddAlbumWithTitle": "Dodaj {albumTitle}", + "AddArtistWithName": "Dodaj {artistName}" } diff --git a/src/NzbDrone.Core/Localization/Core/pt.json b/src/NzbDrone.Core/Localization/Core/pt.json index 34a97fa67..7a91b489b 100644 --- a/src/NzbDrone.Core/Localization/Core/pt.json +++ b/src/NzbDrone.Core/Localization/Core/pt.json @@ -9,7 +9,6 @@ "Exception": "Exceção", "Host": "Anfitrião", "IconForCutoffUnmet": "Ícone para Limite não correspondido", - "IncludeHealthWarningsHelpText": "Incluir avisos de estado de funcionamento", "ChangeFileDate": "Modificar data do ficheiro", "DeleteBackupMessageText": "Tem a certeza que quer eliminar a cópia de segurança \"{name}\"?", "DeleteDelayProfile": "Eliminar perfil de atraso", @@ -24,7 +23,6 @@ "Logging": "guardar nos registos", "MediaManagementSettings": "Definições de gestão de multimédia", "OnApplicationUpdate": "Quando a aplicação atualizar", - "OnApplicationUpdateHelpText": "Quando a aplicação atualizar", "RemoveDownloadsAlert": "As definições de remoção foram movidas para as respetivas definições de cada Cliente de Transferências na tabela acima.", "SSLCertPassword": "Palavra-passe do certificado SSL", "RemoveCompleted": "Eliminação Completa", @@ -55,12 +53,9 @@ "NoBackupsAreAvailable": "Não há cópias de segurança disponíveis", "NoHistory": "Sem histórico.", "NoLeaveIt": "Não, deixe-o", - "NoLimitForAnyRuntime": "Sem limite de tempo de execução", "NoLogFiles": "Sem ficheiros de log", - "NoMinimumForAnyRuntime": "Sem mínimo para tempo de execução", "None": "Nenhum", "OnUpgrade": "Ao atualizar", - "OnUpgradeHelpText": "Ao atualizar", "PageSizeHelpText": "Número de itens por página", "PastDays": "Dias anteriores", "PastDaysHelpText": "Dias anteriores a exibir no feed do iCal", @@ -70,7 +65,6 @@ "PosterSize": "Tamanho do cartaz", "PreviewRename": "Pré-visualizar renomeação", "PreviewRetag": "Pré-visualizar nova etiqueta", - "PriorityHelpText": "Prioridade do indexador de 1 (mais alta) a 50 (mais baixa). Padrão: 25.", "Profiles": "Perfis", "Proper": "Proper", "PropersAndRepacks": "Propers e Repacks", @@ -148,13 +142,9 @@ "UserAgentProvidedByTheAppThatCalledTheAPI": "Par Utilizador-Agente fornecido pela aplicação que chamou a API", "UsingExternalUpdateMechanismBranchToUseToUpdateLidarr": "Ramificação utilizada para atualizar o {appName}", "OnHealthIssue": "Ao ter problemas no estado de funcionamento", - "OnHealthIssueHelpText": "Ao ter problemas no estado de funcionamento", "OnImportFailure": "Ao ocorrer falha na importação", - "OnImportFailureHelpText": "Ao ocorrer falha na importação", "OnReleaseImport": "Ao importar versão", - "OnReleaseImportHelpText": "Ao importar versão", "OnRename": "Ao renomear", - "OnRenameHelpText": "Ao renomear", "PackageVersion": "Versão do pacote", "PageSize": "Tamanho da página", "Redownload": "Transferir novamente", @@ -226,7 +216,7 @@ "Authentication": "Autenticação", "AuthenticationMethodHelpText": "Solicitar nome de utilizador e palavra-passe para acessar ao {appName}", "AutoRedownloadFailedHelpText": "Procurar automaticamente e tente baixar uma versão diferente", - "BackupFolderHelpText": "Caminhos relativos estarão na pasta AppData do {appName}", + "BackupFolderHelpText": "Caminhos relativos estarão no diretório AppData do {appName}", "BackupIntervalHelpText": "Intervalo para criar cópia de segurança das configurações e da base de dados do {appName}", "BackupNow": "Criar cópia de segurança", "BackupRetentionHelpText": "Cópias de segurança automáticas anteriores ao período de retenção serão eliminadas automaticamente", @@ -327,7 +317,6 @@ "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "O {appName} suporta qualquer indexador que utiliza o padrão Newznab, bem como outros listados abaixo.", "LidarrSupportsMultipleListsForImportingAlbumsAndArtistsIntoTheDatabase": "O {appName} suporta múltiplas listas para importação de livros e autores para a base de dados.", "LidarrTags": "Etiquetas do {appName}", - "LoadingTrackFilesFailed": "Falha no carregamento dos ficheiros do livro", "Local": "Local", "LocalPathHelpText": "Caminho que o {appName} deve usar para acessar localmente ao caminho remoto", "LogLevel": "Nível de log", @@ -423,7 +412,7 @@ "UnableToAddANewNotificationPleaseTryAgain": "Não foi possível adicionar uma nova notificação, tenta novamente.", "UnableToAddANewQualityProfilePleaseTryAgain": "Não foi possível adicionar um novo perfil de qualidade, tenta novamente.", "UnableToLoadRemotePathMappings": "Não foi possível carregar os mapeamentos de caminhos remoto", - "DBMigration": "Migração da base de dados", + "DatabaseMigration": "Migração da base de dados", "DefaultMetadataProfileIdHelpText": "Há um perfil de qualidade padrão para autores nesta pasta", "DefaultQualityProfileIdHelpText": "Há um perfil de qualidade padrão para autores nesta pasta", "Delete": "Eliminar", @@ -448,7 +437,6 @@ "EnableSSL": "Ativar SSL", "ExistingTagsScrubbed": "Etiquetas existentes eliminadas", "ExpandOtherByDefaultHelpText": "Outros", - "ExtraFileExtensionsHelpTexts1": "Lista separada por vírgulas de ficheiros adicionais a importar (.nfo será importado como .nfo-orig)", "FileDateHelpText": "Mudar data do ficheiro ao importar/analisar", "FileManagement": "Gestão do ficheiro", "Filename": "Nome do ficheiro", @@ -484,7 +472,6 @@ "Medium": "Médio", "NotificationTriggers": "Acionadores de notificação", "NoUpdatesAreAvailable": "Não há atualizações disponíveis", - "OnGrabHelpText": "Ao capturar", "Proxy": "Proxy", "ProxyBypassFilterHelpText": "Utilizar \",\" como separador e \"*.\" como caráter universal para subdomínios", "ProxyType": "Tipo de proxy", @@ -548,7 +535,7 @@ "ApplicationUrlHelpText": "O URL desta aplicação externa, incluindo http(s)://, porta e URL base", "Apply": "Aplicar", "AudioInfo": "Informações do áudio", - "Backup": "Cópia de segurança", + "Backup": "Backup", "BeforeUpdate": "Antes de atualizar", "Close": "Fechar", "Connect": "Conexões", @@ -761,7 +748,6 @@ "ApplyTagsHelpTextRemove": "Remover: eliminar as etiquetas adicionadas", "ApplyTagsHelpTextAdd": "Adicionar: agregar as etiquetas à lista existente de etiquetas", "ApplyTagsHelpTextReplace": "Substituir: mudar as etiquetas pelas adicionadas (deixe em branco para limpar todas as etiquetas)", - "RemoveFromDownloadClientHelpTextWarning": "Remover eliminará a transferência e o(s) ficheiro(s) do cliente de transferências.", "RemoveSelectedItemQueueMessageText": "Tem a certeza que deseja remover {0} da fila?", "RemoveSelectedItemsQueueMessageText": "Tem a certeza que deseja remover {0} da fila?", "BlocklistReleases": "Bloquear versão", @@ -890,5 +876,17 @@ "PosterOptions": "Opções do cartaz", "Posters": "Cartazes", "ReleaseProfile": "Perfis de versão", - "Small": "Pequeno" + "Small": "Pequeno", + "AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirmar nova senha", + "AutoTaggingRequiredHelpText": "Esta condição de {implementationName} deve corresponder para que a regra de marcação automática seja aplicada. Caso contrário, uma única correspondência de {implementationName} é suficiente.", + "AddImportListExclusionAlbumHelpText": "Impedir série de ser adicionada ao {appName} através de listas", + "ExtraFileExtensionsHelpText": "Lista separada por vírgulas de ficheiros adicionais a importar (.nfo será importado como .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Exemplos: \".sub, .nfo\" ou \"sub,nfo\"", + "ImportLists": "importar lista", + "NoLimitForAnyDuration": "Sem limite de tempo de execução", + "NoMinimumForAnyDuration": "Sem mínimo para tempo de execução", + "PreferredSize": "Tamanho preferido", + "Unlimited": "Ilimitado", + "DeleteArtistFoldersHelpText": "Elimine a pasta do filme e seu conteúdo", + "ArtistIsMonitored": "Autor não monitorado" } diff --git a/src/NzbDrone.Core/Localization/Core/pt_BR.json b/src/NzbDrone.Core/Localization/Core/pt_BR.json index 3761373fc..6fc15e345 100644 --- a/src/NzbDrone.Core/Localization/Core/pt_BR.json +++ b/src/NzbDrone.Core/Localization/Core/pt_BR.json @@ -168,7 +168,7 @@ "CreateGroup": "Criar grupo", "CutoffHelpText": "Assim que esta qualidade for alcançada, o {appName} não baixará mais filmes", "CutoffUnmet": "Corte não atendido", - "DBMigration": "Migração de banco de dados", + "DatabaseMigration": "Migração de banco de dados", "DefaultLidarrTags": "Tags padrão do {appName}", "DefaultMetadataProfileIdHelpText": "Há um perfil de metadados padrão para autores nesta pasta", "DefaultQualityProfileIdHelpText": "Há um perfil de qualidade padrão para autores nesta pasta", @@ -202,7 +202,7 @@ "DeleteRootFolderMessageText": "Tem certeza de que deseja excluir a pasta raiz '{name}'?", "DeleteSelectedTrackFiles": "Excluir arquivos do livro selecionado", "DeleteSelectedTrackFilesMessageText": "Tem certeza de que deseja excluir os arquivos do livro selecionado?", - "DeleteTag": "Excluir tag", + "DeleteTag": "Excluir Etiqueta", "DeleteTagMessageText": "Tem certeza de que deseja excluir a tag '{label}'?", "DeleteTrackFileMessageText": "Tem certeza que deseja excluir {0}?", "DestinationPath": "Caminho de destino", @@ -246,7 +246,6 @@ "ExistingTagsScrubbed": "Tags existentes apagadas", "ExpandAlbumByDefaultHelpText": "Álbum", "ExpandOtherByDefaultHelpText": "Outros", - "ExtraFileExtensionsHelpTexts1": "Lista separada por vírgulas de arquivos adicionais a importar (.nfo será importado como .nfo-orig)", "FileDateHelpText": "Alterar a data do arquivo ao importar/verificar novamente", "Filename": "Nome do arquivo", "FileNames": "Nomes de arquivo", @@ -268,7 +267,7 @@ "Grab": "Obter", "GrabRelease": "Obter lançamento", "GrabReleaseMessageText": "O {appName} não conseguiu determinar para qual artista e álbum é este lançamento. O {appName} pode não conseguir importar automaticamente este lançamento. Deseja obter \"{0}\"?", - "GrabSelected": "Obter selecionado", + "GrabSelected": "Baixar Selecionado", "Group": "Grupo", "HasPendingChangesNoChanges": "Sem alterações", "HasPendingChangesSaveChanges": "Salvar alterações", @@ -293,7 +292,6 @@ "Importing": "Importando", "ImportListExclusions": "Importar exclusões de lista", "ImportLists": "Listas de importação", - "IncludeHealthWarningsHelpText": "Incluir avisos de integridade", "IncludeUnknownArtistItemsHelpText": "Mostrar itens sem um autor na fila. Isso pode incluir autores e filmes removidos, ou qualquer outra coisa na categoria do {appName}", "IncludeUnmonitored": "Incluir não monitorados", "Indexer": "Indexador", @@ -340,7 +338,7 @@ "MetadataSettings": "Configurações de metadados", "MIA": "Desaparecidos", "MinimumAge": "Idade miníma", - "MinimumAgeHelpText": "Somente Usenet: idade mínima, em minutos, dos NZBs antes de serem capturados. Use isso para dar aos novos lançamentos tempo para se propagar para seu provedor de Usenet.", + "MinimumAgeHelpText": "Somente Usenet: idade mínima, em minutos, dos NZBs antes de serem baixados. Use isso para dar aos novos lançamentos tempo para se propagar para seu provedor de Usenet.", "MinimumFreeSpace": "Mínimo de espaço livre", "MustNotContain": "Não deve conter", "NamingSettings": "Configurações de nomenclatura", @@ -348,19 +346,10 @@ "NoBackupsAreAvailable": "Não há backups disponíveis", "NoHistory": "Não há histórico.", "NoLeaveIt": "Não, deixe", - "NoLimitForAnyRuntime": "Sem limite para qualquer duração", "NoLogFiles": "Nenhum arquivo de registro", - "NoMinimumForAnyRuntime": "Sem mínimo para qualquer duração", "None": "Nenhum", "NotificationTriggers": "Gatilhos de Notificação", "NoUpdatesAreAvailable": "Não há atualizações disponíveis", - "OnDownloadFailureHelpText": "Ao ocorrer falha no download", - "OnGrabHelpText": "Ao obter", - "OnHealthIssueHelpText": "Ao ter problema de integridade", - "OnImportFailureHelpText": "Ao ocorrer falha na importação", - "OnReleaseImportHelpText": "Ao importar lançamento", - "OnRenameHelpText": "Ao renomear", - "OnUpgradeHelpText": "Ao atualizar", "OpenBrowserOnStart": "Abrir navegador ao iniciar", "Options": "Opções", "Original": "Original", @@ -380,7 +369,6 @@ "PosterSize": "Tamanho do pôster", "PreviewRename": "Visualizar renomeação", "PreviewRetag": "Visualizar adição de nova tag", - "PriorityHelpText": "Prioridade do indexador de 1 (mais alta) a 50 (mais baixa). Padrão: 25. Usado ao obter lançamentos como um desempate para lançamentos iguais, o {appName} ainda usará todos os indexadores habilitados para sincronização e pesquisa de RSS.", "NETCore": ".NET", "PropersAndRepacks": "Propers e repacks", "Protocol": "Protocolo", @@ -462,7 +450,7 @@ "SslPortHelpTextWarning": "Requer reiniciar para ter efeito", "StandardTrackFormat": "Formato de livro padrão", "StartTypingOrSelectAPathBelow": "Comece a digitar ou selecione um caminho abaixo", - "StartupDirectory": "Diretório de inicialização", + "StartupDirectory": "Diretório de Inicialização", "Status": "Status", "StatusEndedContinuing": "Continuação", "Style": "Estilo", @@ -543,7 +531,6 @@ "FileManagement": "Gerenciamento de arquivo", "LidarrSupportsMultipleListsForImportingAlbumsAndArtistsIntoTheDatabase": "O {appName} oferece suporte a várias listas para importar livros e autores para o banco de dados.", "LidarrTags": "Tags do {appName}", - "LoadingTrackFilesFailed": "Falha ao carregar arquivos do livro", "Local": "Local", "LocalPath": "Caminho local", "LocalPathHelpText": "Caminho que o {appName} deve usar para acessar o caminho remoto localmente", @@ -574,7 +561,7 @@ "ReplaceIllegalCharactersHelpText": "Substituir caracteres ilegais. Se desmarcada, o {appName} irá removê-los", "RemoveFilter": "Remover filtro", "RemoveFromBlocklist": "Remover da lista de bloqueio", - "RemoveFromDownloadClient": "Remover do cliente de download", + "RemoveFromDownloadClient": "Remover do Cliente de Download", "RemoveFromQueue": "Remover da fila", "ResetAPIKeyMessageText": "Tem certeza de que deseja redefinir sua chave de API?", "Restart": "Reiniciar", @@ -616,7 +603,6 @@ "IsExpandedShowTracks": "Mostrar faixas", "LatestAlbum": "Último Álbum", "LatestAlbumData": "Monitorar os últimos e futuros álbuns", - "LoadingAlbumsFailed": "Falha ao carregar álbuns", "ManageTracks": "Gerenciar Faixas", "MissingAlbums": "Álbuns Ausentes", "MissingAlbumsData": "Monitorar álbuns que você não tem arquivos ou não foram lançados ainda", @@ -627,7 +613,6 @@ "MultiDiscTrackFormat": "Formato de Faixa Multi-Disco", "MusicBrainzAlbumID": "ID do Álbum no MusicBrainz", "NoneData": "Nenhum álbum irá ser monitorado", - "OnTrackRetagHelpText": "Ao Retag Faixa", "PrimaryAlbumTypes": "Tipos de Álbum Primário", "PrimaryTypes": "Tipos Primário", "RefreshArtist": "Atualizar Artista", @@ -650,14 +635,12 @@ "TheArtistFolderStrongpathstrongAndAllOfItsContentWillBeDeleted": "A pasta do artista '{0}' e todo o seu conteúdo serão excluídos.", "ExpandEPByDefaultHelpText": "EPs", "ExpandSingleByDefaultHelpText": "Singles", - "ExtraFileExtensionsHelpTexts2": "\"Exemplos: \".sub", - "OnApplicationUpdateHelpText": "Ao atualizar o aplicativo", "OnApplicationUpdate": "Na Atualização do Aplicativo", "OnRename": "Ao Renomear", "OnTrackRetag": "Ao Retag Faixa", "OnUpgrade": "Ao Atualizar", "OnDownloadFailure": "Na Falha do Download", - "OnGrab": "Ao obter", + "OnGrab": "Ao Baixar", "OnReleaseImport": "Ao Importar Lançamento", "OnImportFailure": "Ao Falhar na Importação", "OnHealthIssue": "Ao Problema de Saúde", @@ -781,7 +764,7 @@ "TotalSpace": "Espaço Total", "UI": "IU", "UnmappedFilesOnly": "Somente Arquivos Não Mapeados", - "UnmonitoredOnly": "Somente não monitorado", + "UnmonitoredOnly": "Somente Não Monitorados", "UpgradesAllowed": "Atualizações Permitidas", "Wanted": "Procurado", "Warn": "Alerta", @@ -841,8 +824,6 @@ "EditGroups": "Editar grupos", "OnAlbumDelete": "Ao Excluir Álbum", "OnArtistDelete": "Ao Excluir Artista", - "OnArtistDeleteHelpText": "Ao Excluir Artista", - "OnAlbumDeleteHelpText": "Ao Excluir Álbum", "ContinuingOnly": "Continuando apenas", "DeleteSelected": "Excluir Selecionado", "SelectReleaseGroup": "Selecionar Grupo do Lançamento", @@ -926,7 +907,6 @@ "MonitorAlbum": "Monitorar Álbum", "MountCheckMessage": "A montagem que contém um caminho de filme é montada somente para leitura: ", "OnHealthRestored": "Com a Saúde Restaurada", - "OnHealthRestoredHelpText": "Com a Saúde Restaurada", "ProxyCheckBadRequestMessage": "Falha ao testar o proxy. Código de status: {0}", "ProxyCheckFailedToTestMessage": "Falha ao testar o proxy: {0}", "ProxyCheckResolveIpMessage": "Falha ao resolver o endereço IP do host de proxy configurado {0}", @@ -1012,7 +992,7 @@ "EditSelectedIndexers": "Editar indexadores selecionados", "ExistingTag": "Tag existente", "Implementation": "Implementação", - "ManageClients": "Gerenciar clientes", + "ManageClients": "Gerenciar Clientes", "ManageIndexers": "Gerenciar indexadores", "NoChange": "Sem alteração", "RemovingTag": "Removendo a tag", @@ -1020,7 +1000,6 @@ "Yes": "Sim", "No": "Não", "DownloadClientTagHelpText": "Use este cliente de download apenas para artistas com pelo menos uma tag correspondente. Deixe em branco para usar com todos os artistas.", - "RemoveFromDownloadClientHelpTextWarning": "A remoção removerá o download e o(s) arquivo(s) do cliente de download.", "RemoveSelectedItemQueueMessageText": "Tem certeza de que deseja remover 1 item da fila?", "RemoveSelectedItemsQueueMessageText": "Tem certeza de que deseja remover {0} itens da fila?", "SkipRedownloadHelpText": "Evita que o {appName} tente baixar versões alternativas para os itens removidos", @@ -1162,5 +1141,49 @@ "AddArtistWithName": "Adicionar {artistName}", "AddNewArtistSearchForMissingAlbums": "Iniciar a procurar álbuns perdidos", "AddAlbumWithTitle": "Adicionar {albumTitle}", - "AddNewAlbumSearchForNewAlbum": "Iniciar busca por novo álbum" + "AddNewAlbumSearchForNewAlbum": "Iniciar busca por novo álbum", + "TrackFilesLoadError": "Não foi possível carregar arquivos das faixas", + "ExtraFileExtensionsHelpTextsExamples": "Exemplos: '.sub, .nfo' or 'sub,nfo'", + "ExtraFileExtensionsHelpText": "Lista separada por vírgulas de arquivos extras para importar (.nfo será importado como .nfo-orig)", + "DownloadClientQbittorrentSettingsContentLayout": "Layout de Conteúdo", + "NoLimitForAnyDuration": "Sem limite para qualquer duração", + "NoMinimumForAnyDuration": "Sem mínimo para qualquer duração", + "PreferredSize": "Tamanho Preferido", + "Unlimited": "Ilimitado", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "Seja para usar o layout de conteúdo configurado do qBittorrent, o layout original do torrent ou sempre criar uma subpasta (qBittorrent 4.3.2+)", + "AutoRedownloadFailed": "Falha no Novo Download", + "AutoRedownloadFailedFromInteractiveSearch": "Falha no Novo Download da Pesquisa Interativa", + "AutoRedownloadFailedFromInteractiveSearchHelpText": "Procure e tente baixar automaticamente uma versão diferente quando a versão com falha for obtida da pesquisa interativa", + "DownloadClientAriaSettingsDirectoryHelpText": "Local opcional para colocar downloads, deixe em branco para usar o local padrão do Aria2", + "IndexerSettingsRejectBlocklistedTorrentHashes": "Rejeitar Torrent com Hashes na Lista de Bloqueio Enquanto Capturando", + "IndexerSettingsRejectBlocklistedTorrentHashesHelpText": "se um torrent for bloqueado por hash, ele pode não ser rejeitado corretamente durante o RSS/Pesquisa de alguns indexadores. Ativar isso permitirá que ele seja rejeitado após o torrent ser capturado, mas antes de ser enviado ao cliente.", + "TrackFileDeletedTooltip": "Arquivo da faixa excluído", + "TrackFileMissingTooltip": "Arquivo da faixa ausente", + "TrackFileRenamedTooltip": "Arquivo da faixa renomeado", + "TrackFileTagsUpdatedTooltip": "Arquivo da faixa com etiquetas atualizadas", + "DownloadClientPriorityHelpText": "Prioridade do Cliente de Download de 1 (mais alta) a 50 (mais baixa). Padrão: 1. Round-Robin é usado para clientes com a mesma prioridade.", + "BlocklistAndSearch": "Lista de Bloqueio e Pesquisa", + "BlocklistAndSearchHint": "Inicie uma busca por um substituto após adicionar a lista de bloqueio", + "ChangeCategory": "Alterar Categoria", + "ChangeCategoryHint": "Altera o download para a 'Categoria Pós-Importação' do Cliente de Download", + "CustomFormatsSpecificationRegularExpressionHelpText": "RegEx do Formato Personalizado Não Diferencia Maiúsculas de Minúsculas", + "RemoveQueueItemConfirmation": "Tem certeza de que deseja remover '{sourceTitle}' da fila?", + "RemoveQueueItemsRemovalMethodHelpTextWarning": "'Remover do Cliente de Download' removerá os downloads e os arquivos do cliente de download.", + "DoNotBlocklistHint": "Remover sem colocar na lista de bloqueio", + "IgnoreDownload": "Ignorar Download", + "IgnoreDownloadHint": "Impede que {appName} processe ainda mais este download", + "IgnoreDownloads": "Ignorar Downloads", + "IgnoreDownloadsHint": "Impede que {appName} processe ainda mais esses downloads", + "BlocklistOnlyHint": "Adiciona a Lista de bloqueio sem procurar um substituto", + "DoNotBlocklist": "Não coloque na lista de bloqueio", + "RemoveFromDownloadClientHint": "Remove download e arquivo(s) do cliente de download", + "BlocklistOnly": "Apenas Adicionar a Lista de Bloqueio", + "BlocklistAndSearchMultipleHint": "Iniciar pesquisas por substitutos após adicionar a lista de bloqueio", + "BlocklistMultipleOnlyHint": "Adiciona a Lista de bloqueio sem procurar substitutos", + "ChangeCategoryMultipleHint": "Altera os downloads para a 'Categoria Pós-Importação' do Cliente de Download", + "CustomFormatsSpecificationRegularExpression": "Expressão Regular", + "RemoveMultipleFromDownloadClientHint": "Remove downloads e arquivos do cliente de download", + "RemoveQueueItem": "Remover - {sourceTitle}", + "RemoveQueueItemRemovalMethod": "Método de Remoção", + "RemoveQueueItemRemovalMethodHelpTextWarning": "'Remover do cliente de download' removerá o download e os arquivos do cliente de download." } diff --git a/src/NzbDrone.Core/Localization/Core/ro.json b/src/NzbDrone.Core/Localization/Core/ro.json index 7917e144e..e4d3244d8 100644 --- a/src/NzbDrone.Core/Localization/Core/ro.json +++ b/src/NzbDrone.Core/Localization/Core/ro.json @@ -23,8 +23,6 @@ "Monitored": "Monitorizat", "NotificationTriggers": "Declanșatoare de notificări", "NoUpdatesAreAvailable": "Nu sunt disponibile actualizări", - "OnGrabHelpText": "Pe Grab", - "OnHealthIssueHelpText": "Cu privire la problema sănătății", "ProxyPasswordHelpText": "Trebuie să introduceți un nume de utilizator și o parolă numai dacă este necesară. Lasă-le necompletate altfel.", "ProxyUsernameHelpText": "Trebuie să introduceți un nume de utilizator și o parolă numai dacă este necesară. Lasă-le necompletate altfel.", "PublishedDate": "Data publicării", @@ -133,9 +131,7 @@ "OnGrab": "Pe Grab", "OnHealthIssue": "Cu privire la problema sănătății", "OnRename": "La Redenumire", - "OnRenameHelpText": "La Redenumire", "OnUpgrade": "La actualizare", - "OnUpgradeHelpText": "La actualizare", "OpenBrowserOnStart": "Deschideți browserul la pornire", "Options": "Opțiuni", "Original": "Original", @@ -220,7 +216,7 @@ "CutoffHelpText": "Odată atinsă această calitate, {appName} nu va mai descărca filme", "CutoffUnmet": "Calitate maximă neatinsă", "Dates": "Date", - "DBMigration": "Migrarea DB", + "DatabaseMigration": "Migrarea DB", "DelayProfile": "Profile de întârziere", "DelayProfiles": "Profile de întârziere", "Delete": "Șterge", @@ -306,7 +302,6 @@ "Level": "Nivel", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} acceptă orice indexer care utilizează standardul Newznab, precum și alți indexatori enumerați mai jos.", "LidarrTags": "Etichete {appName}", - "LoadingTrackFilesFailed": "Încărcarea fișierelor film a eșuat", "Local": "Local", "LocalPath": "Calea locală", "ReleaseDate": "Date de lansare", @@ -360,7 +355,6 @@ "Port": "Port", "PortNumber": "Număr port", "PreviewRename": "Previzualizare Redenumire", - "PriorityHelpText": "Prioritatea indexerului de la 1 (cea mai mare) la 50 (cea mai mică). Implicit: 25.", "Profiles": "Profile", "PropersAndRepacks": "Propers și Repacks", "ProxyType": "Tip proxy", @@ -391,7 +385,6 @@ "DeleteTag": "Ștergeți eticheta", "DeleteTagMessageText": "Sigur doriți să ștergeți eticheta „{0}”?", "Docker": "Docker", - "ExtraFileExtensionsHelpTexts1": "Lista separată prin virgulă a fișierelor suplimentare de importat (.nfo va fi importat ca .nfo-orig)", "FileDateHelpText": "Schimbați data fișierului la import / rescanare", "Group": "grup", "HasPendingChangesNoChanges": "Nicio Modificare", @@ -407,7 +400,6 @@ "IgnoredAddresses": "Adrese ignorate", "IgnoredHelpText": "Eliberarea va fi respinsă dacă conține unul sau mai mulți termeni (insensibili la majuscule)", "IllRestartLater": "Voi reporni mai târziu", - "IncludeHealthWarningsHelpText": "Includeți avertismente de sănătate", "IncludeUnmonitored": "Includeți Unmonitored", "LocalPathHelpText": "Calea pe care {appName} ar trebui să o folosească pentru a accesa calea la distanță local", "LogFiles": "Fișiere de loguri", @@ -432,9 +424,7 @@ "NoBackupsAreAvailable": "Nu sunt disponibile copii de rezervă", "NoHistory": "Fără istorie", "NoLeaveIt": "Nu, lasă-l", - "NoLimitForAnyRuntime": "Fără limită pentru orice timp de rulare", "NoLogFiles": "Nu există fișiere jurnal", - "NoMinimumForAnyRuntime": "Niciun minim pentru orice timp de rulare", "None": "Nici unul", "PosterSize": "Dimensiunea posterului", "Proper": "Corect", @@ -658,7 +648,6 @@ "ApplyTagsHelpTextRemove": "Eliminați: eliminați etichetele introduse", "RemoveSelectedItemQueueMessageText": "Sigur doriți să eliminați {0} elementul {1} din coadă?", "RemoveSelectedItemsQueueMessageText": "Sigur doriți să eliminați {0} elementul {1} din coadă?", - "RemoveFromDownloadClientHelpTextWarning": "Eliminarea va elimina descărcarea și fișierele din clientul de descărcare.", "DeleteSelectedDownloadClientsMessageText": "Sigur doriți să ștergeți indexatorul „{0}”?", "ApplyTagsHelpTextHowToApplyArtists": "Cum se aplică etichete indexatoarelor selectate", "ApplyTagsHelpTextHowToApplyDownloadClients": "Cum se aplică etichete clienților de descărcare selectați", diff --git a/src/NzbDrone.Core/Localization/Core/ru.json b/src/NzbDrone.Core/Localization/Core/ru.json index 6ec8f33f1..7ed4dbffc 100644 --- a/src/NzbDrone.Core/Localization/Core/ru.json +++ b/src/NzbDrone.Core/Localization/Core/ru.json @@ -4,7 +4,6 @@ "Quality": "Качество", "FileDateHelpText": "Заменить дату файла при импорте/сканировании", "Docker": "Docker", - "OnHealthIssueHelpText": "О проблемах в системе", "ImportExtraFiles": "Импортировать дополнительные файлы", "UnableToLoadIndexerOptions": "Не удалось загрузить параметры индексатора", "ClickToChangeQuality": "Нажмите чтобы изменить качество", @@ -42,12 +41,8 @@ "MinimumLimits": "Минимальные ограничения", "Missing": "Не найдено", "MoreInfo": "Ещё инфо", - "NoMinimumForAnyRuntime": "Нет минимума для любого времени", "None": "Ничто", "NotificationTriggers": "Триггеры уведомления", - "OnGrabHelpText": "При захвате", - "OnRenameHelpText": "При переименовании", - "OnUpgradeHelpText": "При обновлении", "OpenBrowserOnStart": "Открывать браузер при запуске", "Options": "Опции", "Original": "Оригинал", @@ -56,7 +51,6 @@ "PortNumber": "Номер порта", "PosterSize": "Размер постера", "PreviewRename": "Предпросмотр переименований", - "PriorityHelpText": "Приоритет индексаторов от 1 (наивысший) до 50 (низший). По-умолчанию: 25.", "Profiles": "Профили", "Proper": "Правильный", "PropersAndRepacks": "Проперы и репаки", @@ -197,7 +191,6 @@ "URLBase": "Базовый URL", "UrlBaseHelpText": "Для поддержки обратного прокси, по умолчанию пусто", "YesCancel": "Да, отменить", - "OnApplicationUpdateHelpText": "О обновлении приложения", "OnGrab": "При захвате", "OnHealthIssue": "О проблемах в системе", "OnRename": "При переименовании", @@ -353,7 +346,6 @@ "ImportExtraFilesHelpText": "Импортировать совпадающие экстра файлы (субтитры, nfo, и т.д.) после импорта фильма", "ImportFailedInterp": "Неудачный импорт: {0}", "Importing": "Импортирование", - "IncludeHealthWarningsHelpText": "Включая предупреждения о здоровье", "IncludeUnknownArtistItemsHelpText": "Показывать без фильма в очереди. Может включать в себя удалённые фильмы или что-то еще в списке", "IncludeUnmonitored": "Включая неотслеживаемые", "Indexer": "Индексатор", @@ -386,7 +378,6 @@ "MIA": "MIA", "Mode": "Режим", "Monitored": "Отслеживается", - "NoLimitForAnyRuntime": "Нет ограничений для любого времени", "NoLogFiles": "Нет файлов журнала", "NoUpdatesAreAvailable": "Нет обновлений", "Tracks": "След", @@ -414,7 +405,6 @@ "ApiKeyHelpTextWarning": "Для вступления в силу требуется перезапуск", "AppDataDirectory": "AppData директория", "ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Для получения дополнительной информации о каждом из клиентов загрузки нажмите на кнопки с дополнительной информацией.", - "ExtraFileExtensionsHelpTexts1": "Список экстра файлов для импорта разделенных двоеточием(.info будет заменено на .nfo-orig)", "FileManagement": "Управление файлами", "Filename": "Имя файла", "FileNames": "Имена файлов", @@ -425,7 +415,6 @@ "Indexers": "Индексаторы", "IndexerSettings": "Настройки индексатора", "Interval": "Интервал", - "LoadingTrackFilesFailed": "Неудачная загрузка файлов фильма", "Local": "Местный", "LocalPathHelpText": "Путь, который {appName} должен использовать для локального доступа к удаленному пути", "LogFiles": "Файлы журнала", @@ -452,7 +441,7 @@ "ReleaseWillBeProcessedInterp": "Выпуск будет обработан {0}", "Status": "Статус", "CutoffUnmet": "Порог невыполнен", - "DBMigration": "Перенос БД", + "DatabaseMigration": "Перенос БД", "20MinutesTwenty": "60 минут: {0}", "45MinutesFourtyFive": "60 минут: {0}", "60MinutesSixty": "60 минут: {0}", @@ -711,7 +700,6 @@ "Required": "Необходимо", "ResetTitlesHelpText": "Сбросить заголовки определений, а также значения", "ApplyTagsHelpTextRemove": "Удалить: удалить введенные теги", - "RemoveFromDownloadClientHelpTextWarning": "Удаление приведет к удалению загрузки и файла(ов) из клиента загрузки.", "RemoveSelectedItemQueueMessageText": "Вы уверены, что хотите удалить 1 элемент из очереди?", "RemoveSelectedItemsQueueMessageText": "Вы действительно хотите удалить {0} из очереди?", "SetTags": "Установить теги", @@ -770,6 +758,5 @@ "DeleteRemotePathMappingMessageText": "Вы уверены, что хотите удалить это сопоставление удаленного пути?", "ResetQualityDefinitionsMessageText": "Вы уверены, что хотите сбросить определения качества?", "OnHealthRestored": "При восстановлении работоспособности", - "OnHealthRestoredHelpText": "При восстановлении работоспособности", "AllResultsAreHiddenByTheAppliedFilter": "Все результаты скрыты фильтром" } diff --git a/src/NzbDrone.Core/Localization/Core/sv.json b/src/NzbDrone.Core/Localization/Core/sv.json index 1df600188..97075aaab 100644 --- a/src/NzbDrone.Core/Localization/Core/sv.json +++ b/src/NzbDrone.Core/Localization/Core/sv.json @@ -18,7 +18,6 @@ "EnableColorImpairedModeHelpText": "Ändrad stil för att göra det möjligt för användare med färgstörning att bättre skilja färgkodad information", "ExistingAlbums": "Existerande Albums", "ExpandItemsByDefault": "Expandera Saker som Standard", - "ExtraFileExtensionsHelpTexts1": "Kommaseparerad lista med extra filer som ska importeras (.nfo importeras som .nfo-orig)", "ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "För mer information om individuella nedladdningsklienter, klicka på informationsknappen.", "GrabReleaseMessageText": "{appName} kunde inte avgöra vilken artist och album denna utgåva tillhör. {appName} kanske inte kan importera den här utgåvan automatiskt. Vill du ta hämta \"{0}\"?", "Global": "Global", @@ -112,7 +111,7 @@ "CutoffHelpText": "När denna kvalitet har uppnåtts kommer {appName} inte längre att ladda ner filmer", "CutoffUnmet": "Avgränsande ej tillgodosedd", "Dates": "Datum", - "DBMigration": "DB Migration", + "DatabaseMigration": "DB Migration", "DefaultMonitorOptionHelpText": "Standard Metadata Profil för albums upptäckta i den här mappen", "DefaultQualityProfileIdHelpText": "Standard Kvalitet Profil för artister upptäckta i den här mappen", "DelayingDownloadUntilInterp": "Försenar nedladdningen till {0} kl. {1}", @@ -189,7 +188,6 @@ "ExpandEPByDefaultHelpText": "EPs", "ExpandOtherByDefaultHelpText": "Annat", "ExpandSingleByDefaultHelpText": "Singlar", - "ExtraFileExtensionsHelpTexts2": "\"Exempel: \".sub", "FileDateHelpText": "Ändra fildatum vid import/omskanning", "FileManagement": "Filhantering", "FileNames": "Filnamn", @@ -238,9 +236,6 @@ "MetadataProfiles": "Metadata Profiler", "MusicBrainzTrackID": "MusicBrainz Spår ID", "NETCore": ".NET Core", - "OnDownloadFailureHelpText": "När Nedladdning Misslyckas", - "OnImportFailureHelpText": "När Import Misslyckas", - "OnReleaseImportHelpText": "När Utgåvo-Import", "MonitoringOptions": "Bevakar Alternativ", "MusicbrainzId": "Musicbrainz Id", "MusicBrainzRecordingID": "MusicBrainz Inspelnings ID", @@ -337,7 +332,6 @@ "MinimumLimits": "Minsta gränser", "Missing": "Saknas", "MissingAlbumsData": "Bevaka album som har filer eller inte har släppts än", - "OnUpgradeHelpText": "Vid uppgradering", "OpenBrowserOnStart": "Öppna webbläsare vid start", "Options": "Alternativ", "Original": "Orginal", @@ -402,7 +396,6 @@ "ImportExtraFilesHelpText": "Importera matchande extrafiler (undertexter, nfo, etc) efter import av en filmfil", "ImportFailedInterp": "Import misslyckades: {0}", "Importing": "Importerar", - "IncludeHealthWarningsHelpText": "Inkludera hälsovarningar", "IncludeUnknownArtistItemsHelpText": "Visa objekt utan film i kön. Detta kan inkludera borttagna filmer eller något annat i Radarrs kategori", "IncludeUnmonitored": "Inkludera obevakade", "Indexer": "Indexerare", @@ -420,7 +413,6 @@ "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} stöder alla indexerare som använder Newznab-standarden, liksom andra indexerare som anges nedan.", "LidarrSupportsMultipleListsForImportingAlbumsAndArtistsIntoTheDatabase": "{appName} stödjer flera listor för att importera Böcker och Författare in i databasen.", "LidarrTags": "{appName} taggar", - "LoadingTrackFilesFailed": "Det gick inte att ladda filmfiler", "Local": "Lokal", "LocalPath": "Lokal sökväg", "LocalPathHelpText": "Sökväg som {appName} ska använda för att komma åt fjärrvägen lokalt", @@ -452,15 +444,10 @@ "New": "Ny", "NoBackupsAreAvailable": "Inga säkerhetskopior tillgängliga", "NoLeaveIt": "Nej, lämna det", - "NoLimitForAnyRuntime": "Ingen gräns för någon körtid", "NoLogFiles": "Inga loggfiler", - "NoMinimumForAnyRuntime": "Inget minimum för någon körtid", "None": "Ingen", "NotificationTriggers": "Meddelandeutlösare", "NoUpdatesAreAvailable": "Inga uppdateringar är tillgängliga", - "OnGrabHelpText": "Vid hämtning", - "OnHealthIssueHelpText": "På hälsofrågan", - "OnRenameHelpText": "På Byt namn", "Path": "Sökväg", "PathHelpText": "Rotmappen innehåller ditt bok-bibliotek", "Permissions": "Behörigheter", @@ -468,7 +455,6 @@ "PortNumber": "Portnummer", "PosterSize": "Affisch storlek", "PreviewRename": "Förhandsvisa namnbyte", - "PriorityHelpText": "Indexeringsprioritet från 1 (högst) till 50 (lägst). Standard: 25.", "Profiles": "Profiler", "Proper": "Rätt", "PropersAndRepacks": "Propers och Repacks", diff --git a/src/NzbDrone.Core/Localization/Core/th.json b/src/NzbDrone.Core/Localization/Core/th.json index 4395f260b..2ff2642b0 100644 --- a/src/NzbDrone.Core/Localization/Core/th.json +++ b/src/NzbDrone.Core/Localization/Core/th.json @@ -31,12 +31,10 @@ "New": "ใหม่", "NoBackupsAreAvailable": "ไม่มีการสำรองข้อมูล", "NoLogFiles": "ไม่มีไฟล์บันทึก", - "NoMinimumForAnyRuntime": "ไม่มีขั้นต่ำสำหรับรันไทม์ใด ๆ", "None": "ไม่มี", "NotificationTriggers": "ทริกเกอร์การแจ้งเตือน", "NoUpdatesAreAvailable": "ไม่มีการอัปเดต", "OnUpgrade": "ในการอัพเกรด", - "OnUpgradeHelpText": "ในการอัพเกรด", "OpenBrowserOnStart": "เปิดเบราว์เซอร์เมื่อเริ่มต้น", "Options": "ตัวเลือก", "Original": "ต้นฉบับ", @@ -50,7 +48,6 @@ "PortNumber": "หมายเลขพอร์ต", "PosterSize": "ขนาดโปสเตอร์", "PreviewRename": "ดูตัวอย่างการเปลี่ยนชื่อ", - "PriorityHelpText": "ลำดับความสำคัญของดัชนีจาก 1 (สูงสุด) ถึง 50 (ต่ำสุด) ค่าเริ่มต้น: 25.", "Profiles": "โปรไฟล์", "Proper": "เหมาะสม", "PropersAndRepacks": "ใบพัดและ Repacks", @@ -199,9 +196,7 @@ "WeekColumnHeader": "ส่วนหัวคอลัมน์สัปดาห์", "Year": "ปี", "YesCancel": "ใช่ยกเลิก", - "OnHealthIssueHelpText": "เกี่ยวกับปัญหาสุขภาพ", "OnRename": "ในการเปลี่ยนชื่อ", - "OnRenameHelpText": "ในการเปลี่ยนชื่อ", "RecycleBinCleanupDaysHelpTextWarning": "ไฟล์ในถังรีไซเคิลที่เก่ากว่าจำนวนวันที่เลือกจะถูกล้างโดยอัตโนมัติ", "RecycleBinHelpText": "ไฟล์ภาพยนตร์จะอยู่ที่นี่เมื่อถูกลบแทนที่จะถูกลบอย่างถาวร", "RecyclingBin": "ถังขยะรีไซเคิล", @@ -272,7 +267,7 @@ "CutoffHelpText": "เมื่อถึงคุณภาพนี้แล้ว {appName} จะไม่ดาวน์โหลดภาพยนตร์อีกต่อไป", "CutoffUnmet": "ตัด Unmet", "Dates": "วันที่", - "DBMigration": "การย้ายฐานข้อมูล", + "DatabaseMigration": "การย้ายฐานข้อมูล", "DelayProfile": "โปรไฟล์ล่าช้า", "DelayProfiles": "โปรไฟล์ล่าช้า", "Delete": "ลบ", @@ -344,7 +339,6 @@ "ErrorLoadingContents": "เกิดข้อผิดพลาดในการโหลดเนื้อหา", "ErrorLoadingPreviews": "เกิดข้อผิดพลาดในการโหลดตัวอย่าง", "Exception": "ข้อยกเว้น", - "ExtraFileExtensionsHelpTexts1": "รายการไฟล์พิเศษที่คั่นด้วยจุลภาคที่จะนำเข้า (.nfo จะนำเข้าเป็น. nfo-orig)", "FileDateHelpText": "เปลี่ยนวันที่ของไฟล์ในการนำเข้า / สแกนใหม่", "FileManagement": "การจัดการไฟล์", "Filename": "ชื่อไฟล์", @@ -382,7 +376,6 @@ "ImportExtraFilesHelpText": "นำเข้าไฟล์พิเศษที่ตรงกัน (คำบรรยาย nfo ฯลฯ ) หลังจากนำเข้าไฟล์ภาพยนตร์", "ImportFailedInterp": "การนำเข้าล้มเหลว: {0}", "Importing": "กำลังนำเข้า", - "IncludeHealthWarningsHelpText": "รวมคำเตือนด้านสุขภาพ", "IncludeUnknownArtistItemsHelpText": "แสดงรายการที่ไม่มีภาพยนตร์อยู่ในคิว ซึ่งอาจรวมถึงภาพยนตร์ที่ถูกนำออกหรือสิ่งอื่นใดในหมวดหมู่ของ {appName}", "Indexer": "Indexer", "IndexerPriority": "ลำดับความสำคัญของ Indexer", @@ -397,7 +390,6 @@ "Level": "ระดับ", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} รองรับตัวสร้างดัชนีใด ๆ ที่ใช้มาตรฐาน Newznab รวมถึงดัชนีอื่น ๆ ที่แสดงด้านล่าง", "LidarrTags": "แท็กเรดาร์", - "LoadingTrackFilesFailed": "การโหลดไฟล์ภาพยนตร์ล้มเหลว", "Local": "ท้องถิ่น", "LocalPath": "เส้นทางท้องถิ่น", "LocalPathHelpText": "เส้นทางที่ {appName} ควรใช้เพื่อเข้าถึงเส้นทางระยะไกลในเครื่อง", @@ -407,7 +399,6 @@ "LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "ควรเปิดใช้งานการบันทึกการติดตามชั่วคราวเท่านั้น", "Logs": "บันทึก", "LongDateFormat": "รูปแบบวันที่ยาว", - "NoLimitForAnyRuntime": "ไม่มีขีด จำกัด สำหรับรันไทม์ใด ๆ", "ProxyBypassFilterHelpText": "ใช้ \",\" เป็นตัวคั่นและ \"*.\" เป็นสัญลักษณ์แทนสำหรับโดเมนย่อย", "RemoveTagRemovingTag": "กำลังลบแท็ก", "RenameTracksHelpText": "{appName} จะใช้ชื่อไฟล์ที่มีอยู่หากปิดใช้งานการเปลี่ยนชื่อ", @@ -416,7 +407,6 @@ "CertificateValidationHelpText": "เปลี่ยนวิธีการตรวจสอบการรับรอง HTTPS ที่เข้มงวด", "NETCore": ".NET Core", "OnGrab": "บน Grab", - "OnGrabHelpText": "บน Grab", "OnHealthIssue": "เกี่ยวกับปัญหาสุขภาพ", "Reason": "เหตุผล", "RecycleBinCleanupDaysHelpText": "ตั้งค่าเป็น 0 เพื่อปิดใช้งานการล้างข้อมูลอัตโนมัติ", diff --git a/src/NzbDrone.Core/Localization/Core/tr.json b/src/NzbDrone.Core/Localization/Core/tr.json index 2240d9ec0..689f383d7 100644 --- a/src/NzbDrone.Core/Localization/Core/tr.json +++ b/src/NzbDrone.Core/Localization/Core/tr.json @@ -66,7 +66,7 @@ "SorryThatArtistCannotBeFound": "Maalesef o film bulunamıyor.", "Source": "Kaynak", "SourcePath": "Kaynak Yolu", - "Actions": "Etkiler", + "Actions": "Eylemler", "ArtistAlbumClickToChangeTrack": "Filmi değiştirmek için tıklayın", "Authentication": "Doğrulama", "AuthenticationMethodHelpText": "{appName}'a erişmek için Kullanıcı Adı ve Şifre gerektir", @@ -112,7 +112,7 @@ "CreateGroup": "Grup oluştur", "CutoffHelpText": "Bu kaliteye ulaşıldığında {appName} artık film indirmeyecektir", "CutoffUnmet": "Kesme Karşılanmadı", - "DBMigration": "DB Geçişi", + "DatabaseMigration": "DB Geçişi", "DelayProfile": "Gecikme Profilleri", "DelayProfiles": "Gecikme Profilleri", "Delete": "Sil", @@ -168,7 +168,6 @@ "ErrorLoadingContents": "İçerik yüklenirken hata oluştu", "ErrorLoadingPreviews": "Önizlemeler yüklenirken hata oluştu", "Exception": "İstisna", - "ExtraFileExtensionsHelpTexts1": "İçe aktarılacak ekstra dosyaların virgülle ayrılmış listesi (.nfo, .nfo-orig olarak içe aktarılacaktır)", "FileDateHelpText": "İçe aktarmada / yeniden taramada dosya tarihini değiştirin", "FileManagement": "Dosya idare", "Filename": "Dosya adı", @@ -208,7 +207,6 @@ "ImportExtraFilesHelpText": "Bir film dosyasını içe aktardıktan sonra eşleşen ekstra dosyaları (altyazılar, bilgi notları vb.) İçe aktarın", "ImportFailedInterp": "İçe aktarma başarısız oldu: {0}", "Importing": "İçe aktarılıyor", - "IncludeHealthWarningsHelpText": "Sağlık Uyarılarını Dahil Et", "IncludeUnknownArtistItemsHelpText": "Kuyrukta film olmayan öğeleri gösterin. Bu, kaldırılan filmleri veya {appName}'ın kategorisindeki herhangi bir şeyi içerebilir", "IncludeUnmonitored": "İzlenmeyenleri Dahil Et", "Indexer": "Dizin oluşturucu", @@ -225,7 +223,6 @@ "LidarrSupportsAnyDownloadClientThatUsesTheNewznabStandardAsWellAsOtherDownloadClientsListedBelow": "{appName}, Newznab standardını kullanan herhangi bir indirme istemcisinin yanı sıra aşağıda listelenen diğer indirme istemcilerini de destekler.", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName}, Newznab standardını kullanan tüm indeksleyicileri ve aşağıda listelenen diğer indeksleyicileri destekler.", "LidarrTags": "{appName} Etiketleri", - "LoadingTrackFilesFailed": "Film dosyaları yüklenemedi", "Local": "Yerel", "LocalPath": "Yerel Yol", "LocalPathHelpText": "{appName}'ın uzak yola yerel olarak erişmek için kullanması gereken yol", @@ -264,16 +261,10 @@ "NoBackupsAreAvailable": "Kullanılabilir yedek yok", "NoHistory": "Tarih yok", "NoLeaveIt": "Hayır, Bırak", - "NoLimitForAnyRuntime": "Herhangi bir çalışma zamanı için sınır yok", "NoLogFiles": "Günlük dosyası yok", - "NoMinimumForAnyRuntime": "Herhangi bir çalışma süresi için minimum değer yok", "None": "Yok", "NotificationTriggers": "Bildirim Tetikleyicileri", "NoUpdatesAreAvailable": "Güncelleme yok", - "OnGrabHelpText": "Yakalandığında", - "OnHealthIssueHelpText": "Sağlık Sorunu Hakkında", - "OnRenameHelpText": "Yeniden Adlandırıldığında", - "OnUpgradeHelpText": "Yükseltme sırasında", "OpenBrowserOnStart": "Başlangıçta tarayıcıyı aç", "Options": "Seçenekler", "Original": "Orijinal", @@ -287,7 +278,6 @@ "PortNumber": "Port numarası", "PosterSize": "Poster Boyutu", "PreviewRename": "Ad değiştirmeyi ön izle", - "PriorityHelpText": "1 (En Yüksek) ila 50 (En Düşük) arasında Dizin Oluşturucu Önceliği. Varsayılan: 25.", "Profiles": "Profiller", "Proper": "Uygun", "PropersAndRepacks": "Propers ve Repacks", @@ -641,7 +631,6 @@ "ApplyTagsHelpTextAdd": "Ekle: Etiketleri mevcut etiket listesine ekleyin", "ApplyTagsHelpTextRemove": "Kaldır: Girilen etiketleri kaldırın", "ApplyTagsHelpTextReplace": "Değiştir: Etiketleri girilen etiketlerle değiştirin (tüm etiketleri temizlemek için hiçbir etiket girmeyin)", - "RemoveFromDownloadClientHelpTextWarning": "Kaldırma, indirmeyi ve dosyaları indirme istemcisinden kaldırır.", "RemoveSelectedItemQueueMessageText": "Sıradan {0} öğeyi {1} kaldırmak istediğinizden emin misiniz?", "RemoveSelectedItemsQueueMessageText": "Sıradan {0} öğeyi {1} kaldırmak istediğinizden emin misiniz?", "SetTags": "Etiketleri Ayarla", @@ -684,21 +673,20 @@ "Priority": "Öncelik", "AddMetadataProfile": "üstveri profili", "EditMetadataProfile": "üstveri profili", - "AddConditionImplementation": "Koşul Ekle - {uygulama Adı}", + "AddConditionImplementation": "Koşul Ekle - {implementationName}", "AddConnection": "Bağlantı Ekle", "AddAutoTag": "Otomatik Etiket Ekle", "AddCondition": "Koşul Ekle", "Release": " Yayınlandı", "EditConditionImplementation": "Koşul Ekle - {uygulama Adı}", - "AddConnectionImplementation": "Koşul Ekle - {uygulama Adı}", "Overview": "Genel Bakış", "GrabId": "Grab ID", - "AddIndexerImplementation": "Koşul Ekle - {uygulama Adı}", + "AddIndexerImplementation": "Koşul Ekle - {implementationName}", "DeleteArtistFolderHelpText": "Film klasörünü ve içeriğini silin", "DeleteAutoTagHelpText": "Kalite profilini silmek istediğinizden emin misiniz {0}", "DeleteSpecification": "Bildirimi Sil", "DisabledForLocalAddresses": "Yerel Adresler için Devre Dışı Bırakıldı", - "EditConnectionImplementation": "Koşul Ekle - {uygulama Adı}", + "EditConnectionImplementation": "Koşul Ekle - {implementationName}", "Negate": "Reddet", "OverviewOptions": "Genel Bakış Seçenekler", "PosterOptions": "Poster Seçenekleri", @@ -719,7 +707,15 @@ "Small": "Küçük", "AddImportListExclusionArtistHelpText": "Listelerle filmin {appName}'a eklenmesini önleyin", "AddListExclusionHelpText": "Listelerle filmin {appName}'a eklenmesini önleyin", - "EditIndexerImplementation": "Koşul Ekle - {uygulama Adı}", + "EditIndexerImplementation": "Koşul Ekle - {implementationName}", "DeleteArtistFoldersHelpText": "Film klasörünü ve içeriğini silin", - "AddNewArtistSearchForMissingAlbums": "Kayıp filmi aramaya başlayın" + "AddNewArtistSearchForMissingAlbums": "Kayıp filmi aramaya başlayın", + "AddConnectionImplementation": "Koşul Ekle - {implementationName}", + "AddImportListExclusionAlbumHelpText": "Listelerle filmin {appName}'a eklenmesini önleyin", + "ExtraFileExtensionsHelpText": "İçe aktarılacak ekstra dosyaların virgülle ayrılmış listesi (.nfo, .nfo-orig olarak içe aktarılacaktır)", + "ExtraFileExtensionsHelpTextsExamples": "Örnekler: \".sub, .nfo\" veya \"sub, nfo\"", + "NoLimitForAnyDuration": "Herhangi bir çalışma zamanı için sınır yok", + "NoMinimumForAnyDuration": "Herhangi bir çalışma süresi için minimum değer yok", + "PreferredSize": "Tercih Edilen Boyut", + "Unlimited": "Sınırsız" } diff --git a/src/NzbDrone.Core/Localization/Core/uk.json b/src/NzbDrone.Core/Localization/Core/uk.json index bd4e09be4..89c20c8cb 100644 --- a/src/NzbDrone.Core/Localization/Core/uk.json +++ b/src/NzbDrone.Core/Localization/Core/uk.json @@ -1,8 +1,8 @@ { - "About": "Деталі", + "About": "Про нас", "Actions": "Дії", "AddingTag": "Додавання тегу", - "AddListExclusion": "Додати винятки списку", + "AddListExclusion": "Додати виняток зі списку", "AgeWhenGrabbed": "Вік (коли схоплено)", "AutoRedownloadFailedHelpText": "Автоматичний пошук і спроба завантажити інший випуск", "BackupRetentionHelpText": "Автоматичні резервні копії, старіші за період зберігання, очищаються автоматично", @@ -41,7 +41,7 @@ "ConnectSettings": "Налаштування підключення", "CreateGroup": "Створити групу", "Dates": "Дати", - "DBMigration": "Міграція БД", + "DatabaseMigration": "Міграція БД", "DelayingDownloadUntilInterp": "Завантаження відкладається до {0} о {1}", "DelayProfile": "Профіль затримки", "DelayProfiles": "Профілі затримки", @@ -86,9 +86,9 @@ "Deleted": "Видалено", "Activity": "Активність", "Add": "Додати", - "AddDelayProfile": "Додати профіль затримки", + "AddDelayProfile": "Додати Профіль Затримки", "Added": "Додано", - "AddIndexer": "Додати індексатор", + "AddIndexer": "Додати Індексер", "AddNew": "Додати", "AddQualityProfile": "Додати профіль якості", "AddRemotePathMapping": "Додати віддалений шлях", @@ -292,7 +292,6 @@ "ImportExtraFiles": "Імпорт додаткових файлів", "Hostname": "Ім'я хоста", "ICalHttpUrlHelpText": "Скопіюйте цю URL-адресу до своїх клієнтів або натисніть, щоб підписатися, якщо ваш браузер підтримує веб-канал", - "IncludeHealthWarningsHelpText": "Включайте попередження про здоров’я", "UnableToLoadMediaManagementSettings": "Не вдалося завантажити налаштування керування медіафайлами", "UnableToLoadQualityProfiles": "Не вдалося завантажити профілі якості", "Indexers": "Індексатори", @@ -316,11 +315,8 @@ "MinimumAge": "Мінімальний вік", "MinimumFreeSpace": "Мінімальний вільний простір", "NoLeaveIt": "Ні, залиште це", - "NoLimitForAnyRuntime": "Немає обмежень для будь-якого часу виконання", "OnApplicationUpdate": "Оновлення програми", - "OnApplicationUpdateHelpText": "Оновлення програми", "OnHealthIssue": "Про питання здоров'я", - "OnHealthIssueHelpText": "Про питання здоров'я", "UpgradesAllowed": "Якщо відключені якості не будуть покращені", "PortNumber": "Номер порту", "RecycleBinCleanupDaysHelpText": "Встановіть значення 0, щоб вимкнути автоматичне очищення", @@ -362,7 +358,6 @@ "Events": "Події", "EventType": "Тип події", "Exception": "Виняток", - "ExtraFileExtensionsHelpTexts1": "Розділений комами список додаткових файлів для імпорту (.nfo буде імпортовано як .nfo-orig)", "FileDateHelpText": "Змінити дату файлу під час імпорту/повторного сканування", "Filename": "Ім'я файлу", "FileNames": "Імена файлів", @@ -405,9 +400,7 @@ "NextExecution": "Наступне виконання", "NoBackupsAreAvailable": "Немає резервних копій", "NoLogFiles": "Немає файлів журналу", - "NoMinimumForAnyRuntime": "Немає мінімуму для будь-якого часу виконання", "None": "Жодного", - "OnUpgradeHelpText": "При оновленні", "OpenBrowserOnStart": "Відкрийте браузер при запуску", "Options": "Опції", "Organize": "Організувати", @@ -417,7 +410,6 @@ "OnlyTorrent": "Тільки торрент", "OnlyUsenet": "Тільки Usenet", "OnRename": "При перейменуванні", - "OnRenameHelpText": "При перейменуванні", "OnUpgrade": "При оновленні", "QualitySettings": "Налаштування якості", "Queue": "Черга", @@ -467,7 +459,6 @@ "Logging": "Журналування", "MediaManagementSettings": "Налаштування Управління медіа", "OnGrab": "При захопленні", - "OnGrabHelpText": "При захопленні", "Grabbed": "Захоплений", "GrabRelease": "Захопити реліз", "GrabSelected": "Захопити вибране", @@ -475,5 +466,19 @@ "MetadataSettings": "Налаштування метаданих", "Monitored": "Відстежується", "MonitoredOnly": "Тільки під контролем", - "Usenet": "Usenet" + "Usenet": "Usenet", + "AddConditionImplementation": "Додати умову - {implementationName}", + "UpdateMechanismHelpText": "Використайте вбудоване оновлення {appName}'у або скрипт", + "AddImportListExclusion": "Додати виняток до списку імпорту", + "AddConnection": "Додати Підключення", + "AddConnectionImplementation": "Додати Підключення - {implementationName}", + "Absolute": "Абсолютний", + "AddAutoTag": "Додати Авто Тег", + "AddAutoTagError": "Не вдалося додати новий авто тег, спробуйте ще раз.", + "AddConditionError": "Не вдалося додати нову умову, спробуйте ще раз.", + "AddCondition": "Додати Умову", + "AddDownloadClientImplementation": "Додати клієнт завантаження - {implementationName}", + "AddImportListImplementation": "Додати список імпорту - {implementationName}", + "AddIndexerImplementation": "Додати індексер - {implementationName}", + "AddImportList": "Додати список імпорту" } diff --git a/src/NzbDrone.Core/Localization/Core/vi.json b/src/NzbDrone.Core/Localization/Core/vi.json index de12f6942..172cfdb02 100644 --- a/src/NzbDrone.Core/Localization/Core/vi.json +++ b/src/NzbDrone.Core/Localization/Core/vi.json @@ -50,16 +50,12 @@ "NoBackupsAreAvailable": "Không có bản sao lưu nào", "NoHistory": "Không có lịch sử", "NoLeaveIt": "Không để nó", - "NoLimitForAnyRuntime": "Không có giới hạn cho bất kỳ thời gian chạy nào", "NoLogFiles": "Không có tệp nhật ký", - "NoMinimumForAnyRuntime": "Không có tối thiểu cho bất kỳ thời gian chạy nào", "None": "không ai", "NotificationTriggers": "Kích hoạt thông báo", "NoUpdatesAreAvailable": "Không có bản cập nhật nào có sẵn", "OnRename": "Khi đổi tên", - "OnRenameHelpText": "Khi đổi tên", "OnUpgrade": "Đang nâng cấp", - "OnUpgradeHelpText": "Đang nâng cấp", "OpenBrowserOnStart": "Mở trình duyệt khi bắt đầu", "Options": "Tùy chọn", "Original": "Nguyên", @@ -70,7 +66,6 @@ "PortNumber": "Số cổng", "PosterSize": "Kích thước áp phích", "PreviewRename": "Xem trước Đổi tên", - "PriorityHelpText": "Mức độ ưu tiên của người lập chỉ mục từ 1 (Cao nhất) đến 50 (Thấp nhất). Mặc định: 25.", "Profiles": "Hồ sơ", "Proper": "Thích hợp", "PropersAndRepacks": "Người ủng hộ và người đóng gói", @@ -213,9 +208,7 @@ "UseHardlinksInsteadOfCopy": "Sử dụng liên kết cứng thay vì sao chép", "UsenetDelay": "Sự chậm trễ của Usenet", "OnGrab": "Trên Grab", - "OnGrabHelpText": "Trên Grab", "OnHealthIssue": "Về vấn đề sức khỏe", - "OnHealthIssueHelpText": "Về vấn đề sức khỏe", "Password": "Mật khẩu", "RecycleBinCleanupDaysHelpText": "Đặt thành 0 để tắt tính năng dọn dẹp tự động", "RecycleBinCleanupDaysHelpTextWarning": "Các tệp trong thùng rác cũ hơn số ngày đã chọn sẽ tự động được dọn dẹp", @@ -296,7 +289,7 @@ "CreateGroup": "Tạo nhóm", "CutoffHelpText": "Khi đạt đến chất lượng này {appName} sẽ không tải phim nữa", "CutoffUnmet": "Cắt bỏ chưa được đáp ứng", - "DBMigration": "Di chuyển DB", + "DatabaseMigration": "Di chuyển DB", "DelayProfile": "Hồ sơ trì hoãn", "DelayProfiles": "Hồ sơ trì hoãn", "Delete": "Xóa bỏ", @@ -353,7 +346,6 @@ "ErrorLoadingContents": "Lỗi khi tải nội dung", "ErrorLoadingPreviews": "Lỗi khi tải bản xem trước", "Exception": "ngoại lệ", - "ExtraFileExtensionsHelpTexts1": "Danh sách các tệp bổ sung cần nhập được phân tách bằng dấu phẩy (.nfo sẽ được nhập dưới dạng .nfo-orig)", "FileDateHelpText": "Thay đổi ngày tệp khi nhập / quét lại", "FileManagement": "Quản lý tệp", "Filename": "Tên tệp", @@ -392,7 +384,6 @@ "ImportExtraFilesHelpText": "Nhập các tệp bổ sung phù hợp (phụ đề, nfo, v.v.) sau khi nhập tệp phim", "ImportFailedInterp": "Nhập không thành công: {0}", "Importing": "Nhập khẩu", - "IncludeHealthWarningsHelpText": "Bao gồm các cảnh báo về sức khỏe", "IncludeUnknownArtistItemsHelpText": "Hiển thị các mục không có phim trong hàng đợi. Điều này có thể bao gồm các phim đã bị xóa hoặc bất kỳ thứ gì khác trong danh mục của {appName}", "IncludeUnmonitored": "Bao gồm Không theo dõi", "Indexer": "Người lập chỉ mục", @@ -408,7 +399,6 @@ "Level": "Cấp độ", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "{appName} hỗ trợ bất kỳ trình chỉ mục nào sử dụng tiêu chuẩn Newznab, cũng như các trình chỉ mục khác được liệt kê bên dưới.", "LidarrTags": "Thẻ {appName}", - "LoadingTrackFilesFailed": "Tải tệp phim không thành công", "Local": "Địa phương", "LocalPath": "Đường dẫn địa phương", "LocalPathHelpText": "Đường dẫn mà {appName} nên sử dụng để truy cập cục bộ đường dẫn từ xa", @@ -664,7 +654,6 @@ "NoEventsFound": "Không tìm thấy sự kiện", "RemovingTag": "Xóa thẻ", "AutomaticAdd": "Tự động thêm", - "RemoveFromDownloadClientHelpTextWarning": "Việc xóa sẽ xóa phần tải xuống và (các) tệp khỏi ứng dụng khách tải xuống.", "RemoveSelectedItemQueueMessageText": "Bạn có chắc chắn muốn xóa {0} khỏi hàng đợi không?", "SetTags": "Đặt thẻ", "Required": "Cần thiết", @@ -709,5 +698,12 @@ "AddImportListExclusionArtistHelpText": "Ngăn phim được thêm vào {appName} theo danh sách", "AddListExclusionHelpText": "Ngăn phim được thêm vào {appName} theo danh sách", "DeleteArtistFoldersHelpText": "Xóa thư mục phim và nội dung của nó", - "AddNewArtistSearchForMissingAlbums": "Bắt đầu tìm kiếm phim bị thiếu" + "AddNewArtistSearchForMissingAlbums": "Bắt đầu tìm kiếm phim bị thiếu", + "AddImportListExclusionAlbumHelpText": "Ngăn phim được thêm vào {appName} theo danh sách", + "ExtraFileExtensionsHelpText": "Danh sách các tệp bổ sung cần nhập được phân tách bằng dấu phẩy (.nfo sẽ được nhập dưới dạng .nfo-orig)", + "ExtraFileExtensionsHelpTextsExamples": "Ví dụ: '.sub, .nfo' hoặc 'sub, nfo'", + "NoLimitForAnyDuration": "Không có giới hạn cho bất kỳ thời gian chạy nào", + "NoMinimumForAnyDuration": "Không có tối thiểu cho bất kỳ thời gian chạy nào", + "PreferredSize": "Kích thước ưa thích", + "Unlimited": "Vô hạn" } diff --git a/src/NzbDrone.Core/Localization/Core/zh_CN.json b/src/NzbDrone.Core/Localization/Core/zh_CN.json index 6d3ceb0a0..330d99746 100644 --- a/src/NzbDrone.Core/Localization/Core/zh_CN.json +++ b/src/NzbDrone.Core/Localization/Core/zh_CN.json @@ -17,12 +17,10 @@ "Fixed": "已修复", "Folder": "文件夹", "GeneralSettings": "通用设置", - "IncludeHealthWarningsHelpText": "包含健康度警告", "Indexer": "索引器", "IndexerPriority": "索引器优先级", "MaximumLimits": "最大限制", "NoBackupsAreAvailable": "无备份可用", - "NoLimitForAnyRuntime": "不限制任何歌曲时长", "NoUpdatesAreAvailable": "无可用更新", "ProxyBypassFilterHelpText": "使用“ , ”作为分隔符,和“ *. ”作为二级域名的通配符", "ProxyUsernameHelpText": "如果需要,您只需要输入用户名和密码。否则就让它们为空。", @@ -55,7 +53,7 @@ "Columns": "列", "Connections": "连接", "ConnectSettings": "连接设置", - "DBMigration": "数据库迁移版本", + "DatabaseMigration": "数据库迁移版本", "DelayProfile": "延时配置", "Delete": "删除", "DeleteBackup": "删除备份", @@ -65,7 +63,7 @@ "DeleteIndexerMessageText": "您确定要删除索引器“{name}”吗?", "DeleteNotification": "删除消息推送", "DeleteTag": "删除标签", - "DeleteTagMessageText": "您确定要删除标签 '{0}' 吗?", + "DeleteTagMessageText": "您确定要删除标签 '{label}' 吗?", "Edit": "编辑", "Enable": "启用", "EnableAutomaticAdd": "启用自动添加", @@ -74,7 +72,7 @@ "EnableCompletedDownloadHandlingHelpText": "自动从下载客户端导入已完成的下载内容", "EnableHelpText": "启用此元数据类型的元数据文件创建", "EnableInteractiveSearch": "启用手动搜索", - "EnableSSL": "启用SSL", + "EnableSSL": "启用 SSL", "EnableSslHelpText": " 重启生效", "ErrorLoadingContents": "加载内容出错", "Exception": "例外", @@ -105,9 +103,7 @@ "New": "新的", "NoLeaveIt": "不,就这样", "NoLogFiles": "没有日志文件", - "NoMinimumForAnyRuntime": "歌曲时间没有最小限制", "NotificationTriggers": "通知触发器", - "OnHealthIssueHelpText": "健康度异常", "OpenBrowserOnStart": "打开浏览器时启动", "Options": "选项", "PackageVersion": "Package版本", @@ -198,7 +194,6 @@ "AllowFingerprintingHelpTextWarning": "这需要读取部分文件,这将减慢扫描速度,并可能导致磁盘或网络活动频繁。", "AlternateTitles": "别名", "MinimumAgeHelpText": "仅限Usenet:抓取NewzBin文件的最小时间间隔(分钟)。开启此功能会让新版本有时间传播到你的usenet提供商。", - "OnApplicationUpdateHelpText": "在程序更新时", "OnApplicationUpdate": "程序更新时", "Duration": "时长", "LocalPath": "本地路径", @@ -241,22 +236,18 @@ "Medium": "中", "MetadataSettings": "元数据设置", "MinimumFreeSpace": "最小剩余空间", - "Missing": "缺少", - "Monitored": "监控中", + "Missing": "缺失", + "Monitored": "已监控", "MustContain": "必须包含", "MustNotContain": "必须不包含", "NamingSettings": "命名设置", "NETCore": ".NET", "NoHistory": "无历史记录。", "None": "无", - "OnGrabHelpText": "抓取中", "OnRename": "重命名中", - "OnRenameHelpText": "重命名中", "OnUpgrade": "升级中", - "OnUpgradeHelpText": "升级中", "Original": "原始的", "PosterSize": "海报大小", - "PriorityHelpText": "搜刮器优先级从1(最高)到50(最低),默认25,优先级当搜刮结果评分相同时使用,并不是搜刮器的启动顺序。", "Proper": "合适的", "PropersAndRepacks": "适合的和重封装的Propers and Repacks", "ProtocolHelpText": "在其他相同版本之间进行选择时,选择要使用的协议以及首选的协议", @@ -406,11 +397,10 @@ "DownloadFailedInterp": "下载失败: {0}", "DownloadPropersAndRepacksHelpTexts1": "是否自动更新至合适的或者Repack", "DownloadWarningCheckDownloadClientForMoreDetails": "下载警告:查看下载客户端获取更多信息", - "EnableRSS": "启用RSS", + "EnableRSS": "启用 RSS", "Ended": "已完结", "ErrorLoadingPreviews": "读取预告片错误", "ExpandAlbumByDefaultHelpText": "专辑", - "ExtraFileExtensionsHelpTexts1": "导入逗号分隔其他文件(.nfo将做为.nfo-orig被导入)", "FileDateHelpText": "导入和重新扫描时修改文件日期", "FileManagement": "文件管理", "FileNames": "文件名", @@ -486,7 +476,6 @@ "IgnoredPlaceHolder": "添加新限制", "LidarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Radarr支持任何使用Newznab标准的搜刮器,以及下面列出的其他搜刮器。", "LidarrTags": "Radarr标签", - "LoadingTrackFilesFailed": "读取歌曲文件失败", "Local": "本地", "LocalPathHelpText": "Radarr在本地访问远程路径时应该使用的路径", "LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "追踪日志只应该暂时启用", @@ -534,7 +523,6 @@ "UnmappedFiles": "未映射文件", "UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "更新在docker容器内被禁用. 改为更新容器映像。", "OnDownloadFailure": "在下载失败时", - "OnDownloadFailureHelpText": "在下载失败时", "PathHelpText": "根目录文件夹包含您的书籍库", "PathHelpTextWarning": "这必须与下载客户端放置文件的目录不同", "SearchForAllMissingAlbums": "搜索所有丢失的书籍", @@ -643,7 +631,7 @@ "MediaManagement": "媒体管理", "Metadata": "元数据", "MonitorAlbumExistingOnlyWarning": "这是对每本书籍的监控设置的一次性调整 使用作者/编辑下的选项来控制新添加的书籍将如何", - "MonitoredOnly": "监控中", + "MonitoredOnly": "仅监控", "MonitoringOptions": "监控选项", "MonitoringOptionsHelpText": "添加作者后应该监控哪些书籍(一次性调整)", "MonitorNewItemsHelpText": "哪些新书应被监控", @@ -659,7 +647,6 @@ "OnImportFailure": "在导入失败时", "OnlyTorrent": "只有torrent", "OnlyUsenet": "只有usenet", - "OnReleaseImportHelpText": "在发行导入时", "PastDays": "过去天数", "PastDaysHelpText": "iCal订阅地址 过去天数", "Peers": "用户", @@ -703,12 +690,11 @@ "UnmappedFilesOnly": "仅限未映射的文件", "UnmonitoredOnly": "监控中", "UpgradesAllowed": "允许升级", - "Wanted": "想要的", + "Wanted": "已追踪", "Warn": "警告", "WouldYouLikeToRestoreBackup": "是否要还原备份“{name}”?", "WriteMetadataTags": "编写元数据标签", "WriteMetadataToAudioFiles": "将元数据写入音频文件", - "OnImportFailureHelpText": "在导入失败时", "SkipRedownload": "跳过重新下载", "DiscCount": "磁盘数量", "DiscNumber": "磁盘编号", @@ -728,10 +714,8 @@ "QualitiesHelpText": "即使未选中,列表中的质量排序越高优先级也越高。同组内的质量优先级相同。质量只有选中才标记为需要", "ImportFailed": "导入失败", "TrackArtist": "歌曲歌手", - "OnAlbumDeleteHelpText": "当专辑删除时", "OnAlbumDelete": "当专辑删除时", "OnArtistDelete": "当歌手删除时", - "OnArtistDeleteHelpText": "当歌手删除时", "PrimaryAlbumTypes": "首要唱片类型", "PrimaryTypes": "首要类型", "SecondaryTypes": "次要类型", @@ -763,7 +747,6 @@ "IsExpandedShowTracks": "显示歌曲", "CombineWithExistingFiles": "和现有文件合并", "Episode": "集", - "LoadingAlbumsFailed": "专辑加载失败", "TrackNaming": "歌曲命名", "MassAlbumsSearchWarning": "你确定要搜索所有 '{0}' 个缺失专辑么?", "MediumFormat": "媒体格式", @@ -784,7 +767,6 @@ "AllAlbumsData": "除非特别设置,监控所有专辑", "FirstAlbum": "首张专辑", "ExpandSingleByDefaultHelpText": "单曲", - "ExtraFileExtensionsHelpTexts2": "例如:'.sub' 或者 'sub'", "ExpandItemsByDefault": "默认展开列表", "HasMonitoredAlbumsNoMonitoredAlbumsForThisArtist": "该歌手无监控专辑", "HideAlbums": "隐藏专辑", @@ -828,7 +810,6 @@ "NoneMonitoringOptionHelpText": "不要监控歌手和专辑", "NotDiscography": "不是音乐作品目录", "OnTrackRetag": "当歌曲被重新打标时", - "OnTrackRetagHelpText": "当歌曲被重新打标时", "Playlist": "播放列表", "Proceed": "已处理", "ReplaceExistingFiles": "替换当前文件", @@ -866,7 +847,7 @@ "HiddenClickToShow": "隐藏,点击显示", "IncludeCustomFormatWhenRenamingHelpText": "在 {Custom Formats} 中包含重命名格式", "IndexerRssHealthCheckNoAvailableIndexers": "由于索引器错误,所有支持rss的索引器暂时不可用", - "IndexerRssHealthCheckNoIndexers": "没有任何索引器开启了RSS同步,Radarr不会自动抓取新发布的影片", + "IndexerRssHealthCheckNoIndexers": "没有任何索引器开启了RSS同步,{appName}不会自动抓取新发布的影片", "IndexerSearchCheckNoInteractiveMessage": "没有可用的交互式搜索的索引器,因此 {appName} 不会提供任何交互式搜索的结果", "ItsEasyToAddANewArtistJustStartTypingTheNameOfTheArtistYouWantToAdd": "添加新的艺术家很容易,只需开始输入要添加的艺术家的名称即可。", "Loading": "加载中", @@ -916,7 +897,7 @@ "IndexerLongTermStatusCheckAllClientMessage": "由于故障超过6小时,所有索引器均不可用", "IndexerLongTermStatusCheckSingleClientMessage": "由于故障6小时,下列索引器都已不可用:{0}", "IndexerSearchCheckNoAvailableIndexersMessage": "由于最近的索引器错误,所有支持搜索的索引器暂时不可用", - "IndexerSearchCheckNoAutomaticMessage": "没有索引器开启自动搜索,Radarr不会提供任何自动搜索结果", + "IndexerSearchCheckNoAutomaticMessage": "没有索引器开启自动搜索,{appName}不会提供任何自动搜索结果", "MinFormatScoreHelpText": "允许下载的最小自定义格式分数", "Monitoring": "监控中", "RemotePathMappingCheckFolderPermissions": "Radarr可以找到但是无法访问已下载的目录 {0} ,可能是权限错误。", @@ -947,7 +928,7 @@ "CountImportListsSelected": "{selectedCount}导入列表已选中", "CountIndexersSelected": "{selectedCount}索引器已选中", "DeleteSelectedDownloadClients": "删除选定的下载客户端", - "DeleteSelectedDownloadClientsMessageText": "您确定要删除{count}选定的下载客户端吗?", + "DeleteSelectedDownloadClientsMessageText": "您确定要删除 {count} 个选定的下载客户端吗?", "DeleteSelectedImportLists": "删除导入列表", "DeleteSelectedImportListsMessageText": "您确定要删除选定的{count}导入列表吗?", "DeleteSelectedIndexers": "删除索引器", @@ -967,7 +948,6 @@ "NoHistoryBlocklist": "没有历史黑名单", "NoImportListsFound": "未找到导入列表", "NoIndexersFound": "未找到索引器", - "OnHealthRestoredHelpText": "健康度恢复", "OnHealthRestored": "健康度恢复", "RemoveSelectedItemBlocklistMessageText": "您确定要从阻止列表中删除所选项目吗?", "ResetQualityDefinitionsMessageText": "您确定要重置质量定义吗?", @@ -988,7 +968,6 @@ "NoEventsFound": "无事件", "RemoveSelectedItem": "删除所选项目", "RemoveSelectedItems": "删除所选项目", - "RemoveFromDownloadClientHelpTextWarning": "删除将从下载客户端删除下载和文件。", "RemovingTag": "移除标签", "Yes": "确定", "ResetQualityDefinitions": "重置质量定义", @@ -1076,12 +1055,12 @@ "TrackFiles": "跟踪文件", "AddNewAlbum": "添加新专辑", "AddNewArtist": "添加新艺术家", - "DeleteSelected": "删除所选", + "DeleteSelected": "删除所选项", "FilterArtistPlaceholder": "过滤艺术家", - "DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "下载客户端 {0} 已被设置为删除已完成的下载。这可能导致在 {1} 导入之前,已下载的文件会被从您的客户端中移除。", + "DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "下载客户端 {0} 被设置为删除已完成的下载。这可能导致在 {1} 导入之前,已下载的文件会被从您的客户端中移除。", "InfoUrl": "信息 URL", "GrabId": "抓取ID", - "InvalidUILanguage": "语言", + "InvalidUILanguage": "您的UI设置为无效语言,请纠正并保存设置", "AuthenticationMethod": "认证方式", "AuthenticationMethodHelpTextWarning": "请选择一个有效的身份验证方式", "AuthenticationRequired": "需要身份验证", @@ -1149,5 +1128,20 @@ "Small": "小", "AlbumStudioTruncated": "只显示最新的25季,点击详情查看所有的季", "ArtistIsMonitored": "作者未监控", - "AddNewArtistSearchForMissingAlbums": "开始搜索缺失影片" + "AddNewArtistSearchForMissingAlbums": "开始搜索缺失影片", + "EnableProfile": "启用配置", + "AlbumDetails": "专辑详情", + "AddAlbumWithTitle": "添加 {albumTitle}", + "AddArtistWithName": "添加 {artistName}", + "AddNewAlbumSearchForNewAlbum": "开始搜索新专辑", + "ExtraFileExtensionsHelpTextsExamples": "示例:’.sub,.nfo‘ 或 ’sub,nfo‘", + "ExtraFileExtensionsHelpText": "要导入的额外文件列表,以逗号分隔(.nfo 文件会被导入为 .nfo-orig)", + "DownloadClientQbittorrentSettingsContentLayout": "内容布局", + "DownloadClientQbittorrentSettingsContentLayoutHelpText": "是否使用 qBittorrent 配置的内容布局,使用种子的原始布局或始终创建子文件夹(qBittorrent 4.3.2+)", + "NoLimitForAnyDuration": "不限制任何运行环境", + "NoMinimumForAnyDuration": "运行环境没有最小限制", + "PreferredSize": "首选影片大小", + "Unlimited": "无限制", + "DownloadClientPriorityHelpText": "下载客户端优先级,从1(最高)到50(最低),默认为1。具有相同优先级的客户端将轮换使用。", + "IndexerSettingsRejectBlocklistedTorrentHashes": "抓取时舍弃列入黑名单的种子散列值" } diff --git a/src/NzbDrone.Core/Localization/Core/zh_TW.json b/src/NzbDrone.Core/Localization/Core/zh_TW.json index 75731d2ab..b3ca2825f 100644 --- a/src/NzbDrone.Core/Localization/Core/zh_TW.json +++ b/src/NzbDrone.Core/Localization/Core/zh_TW.json @@ -6,7 +6,7 @@ "All": "全部", "EditDelayProfile": "新增延時配置", "Add": "新增", - "AddDelayProfile": "新增延時配置", + "AddDelayProfile": "加入延遲設定", "Added": "已新增", "AddIndexer": "新增索引", "Age": "年齡", @@ -45,5 +45,33 @@ "AddRemotePathMapping": "加入遠程路徑對應", "AddRootFolder": "加入根目錄資料夾", "AfterManualRefresh": "在手動重新整理之後", - "AddQualityProfile": "加入品質設定檔" + "AddQualityProfile": "加入品質設定檔", + "AddImportListExclusionAlbumHelpText": "阻止專輯透過匯入清單加入到 {appName}", + "AddImportListExclusionArtistHelpText": "阻止藝人透過匯入清單加入到 {appName}", + "APIKey": "API密鑰", + "AddConditionImplementation": "新增條件 - {implementationName}", + "AddConnectionImplementation": "新增連接 - {implementationName}", + "AddImportList": "新增匯入清單", + "AddImportListImplementation": "新增匯入清單 - {implementationName}", + "20MinutesTwenty": "20分鐘:{0}", + "45MinutesFourtyFive": "45分鐘:{0}", + "60MinutesSixty": "60分鐘:{0}", + "Absolute": "絕對", + "AddConnection": "新增連接", + "AddImportListExclusion": "新增匯入排除清單", + "AddDownloadClientImplementation": "新增下載用戶端 - {implementationName}", + "AddAutoTagError": "無法加入新的自動標籤,請重新嘗試。", + "AddConditionError": "無法加入新的條件,請重新嘗試。", + "AddAutoTag": "新增自動標籤", + "AddCondition": "新增條件", + "AddArtistWithName": "新增{artistName}", + "AddIndexerImplementation": "新增索引 - {implementationName}", + "AddAlbumWithTitle": "新增{albumTitle}", + "AppUpdatedVersion": "重新載入", + "AppUpdated": "{appName}已更新", + "ApplyTagsHelpTextHowToApplyDownloadClients": "如何將標籤套用在被選擇的下載客戶端", + "ApplyTagsHelpTextAdd": "加入:將標籤加入已存在的標籤清單", + "ApplyTagsHelpTextHowToApplyImportLists": "如何套用標籤在所選擇的輸入清單", + "AgeWhenGrabbed": "年齡(當獲取時)", + "ApplyChanges": "應用" } diff --git a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs index 1d364318c..18e8a6ccd 100644 --- a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs +++ b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs @@ -220,6 +220,10 @@ namespace NzbDrone.Core.MediaCover updated = true; } } + catch (HttpException e) + { + _logger.Warn("Couldn't download media cover for {0}. {1}", album, e.Message); + } catch (WebException e) { _logger.Warn("Couldn't download media cover for {0}. {1}", album, e.Message); diff --git a/src/NzbDrone.Core/MediaFiles/DownloadedTracksImportService.cs b/src/NzbDrone.Core/MediaFiles/DownloadedTracksImportService.cs index 29fc54e1a..bf64d64fa 100644 --- a/src/NzbDrone.Core/MediaFiles/DownloadedTracksImportService.cs +++ b/src/NzbDrone.Core/MediaFiles/DownloadedTracksImportService.cs @@ -116,7 +116,9 @@ namespace NzbDrone.Core.MediaFiles try { var audioFiles = _diskScanService.GetAudioFiles(directoryInfo.FullName); - var rarFiles = _diskProvider.GetFiles(directoryInfo.FullName, true).Where(f => Path.GetExtension(f).Equals(".rar", StringComparison.OrdinalIgnoreCase)); + var rarFiles = _diskProvider.GetFiles(directoryInfo.FullName, true).Where(f => + Path.GetExtension(f).Equals(".rar", + StringComparison.OrdinalIgnoreCase)); foreach (var audioFile in audioFiles) { @@ -145,6 +147,11 @@ namespace NzbDrone.Core.MediaFiles _logger.Debug(e, "Folder {0} has already been removed", directoryInfo.FullName); return false; } + catch (Exception e) + { + _logger.Debug(e, "Unable to determine whether folder {0} should be removed", directoryInfo.FullName); + return false; + } } private List ProcessFolder(IDirectoryInfo directoryInfo, ImportMode importMode, DownloadClientItem downloadClientItem) diff --git a/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs index 00036eb6a..fe48b4d6d 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs @@ -92,7 +92,7 @@ namespace NzbDrone.Core.MediaFiles if (_configService.CopyUsingHardlinks) { - _logger.Debug("Hardlinking track file: {0} to {1}", trackFile.Path, filePath); + _logger.Debug("Attempting to hardlink track file: {0} to {1}", trackFile.Path, filePath); return TransferFile(trackFile, localTrack.Artist, localTrack.Tracks, filePath, TransferMode.HardLinkOrCopy); } diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/AggregationService.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/AggregationService.cs index e91b05f11..c9fc89c86 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/AggregationService.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/AggregationService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators; @@ -26,8 +27,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Aggregation IDiskProvider diskProvider, Logger logger) { - _trackAugmenters = trackAugmenters; - _albumAugmenters = albumAugmenters; + _trackAugmenters = trackAugmenters.OrderBy(a => a.Order).ToList(); + _albumAugmenters = albumAugmenters.OrderBy(a => a.Order).ToList(); _diskProvider = diskProvider; _logger = logger; } diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateFilenameInfo.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateFilenameInfo.cs index f40b6ec6e..28c2c3633 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateFilenameInfo.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateFilenameInfo.cs @@ -11,6 +11,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators { public class AggregateFilenameInfo : IAggregate { + public int Order => 1; + private readonly Logger _logger; private static readonly List> CharsAndSeps = new List> diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateQuality.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateQuality.cs index b2ecf8487..3a9ef0481 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateQuality.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateQuality.cs @@ -4,6 +4,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators { public class AggregateQuality : IAggregate { + public int Order => 1; + public LocalTrack Aggregate(LocalTrack localTrack, bool otherFiles) { var quality = localTrack.FileTrackInfo?.Quality; diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateReleaseGroup.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateReleaseGroup.cs index d62fad478..4370b3364 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateReleaseGroup.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/AggregateReleaseGroup.cs @@ -5,6 +5,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators { public class AggregateReleaseGroup : IAggregate { + public int Order => 1; + public LocalTrack Aggregate(LocalTrack localTrack, bool otherFiles) { var releaseGroup = localTrack.DownloadClientAlbumInfo?.ReleaseGroup; diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/IAggregateLocalTrack.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/IAggregateLocalTrack.cs index c9a219b5a..9a26110a2 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/IAggregateLocalTrack.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Aggregation/Aggregators/IAggregateLocalTrack.cs @@ -2,6 +2,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators { public interface IAggregate { + int Order { get; } T Aggregate(T item, bool otherFiles); } } diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Identification/TrackGroupingService.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Identification/TrackGroupingService.cs index 6eabc393c..c434055b0 100644 --- a/src/NzbDrone.Core/MediaFiles/TrackImport/Identification/TrackGroupingService.cs +++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Identification/TrackGroupingService.cs @@ -22,8 +22,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Identification private const string MultiDiscPatternFormat = @"^(?.*%s[\W_]*)\d"; private static readonly Logger _logger = NzbDroneLogger.GetLogger(typeof(TrackGroupingService)); - private static readonly List MultiDiscMarkers = new List { @"dis[ck]", @"cd" }; - private static readonly List VariousArtistTitles = new List { "", "various artists", "various", "va", "unknown" }; + private static readonly List MultiDiscMarkers = new () { @"dis[ck]", @"cd" }; + private static readonly List VariousArtistTitles = new () { "", "various artists", "various", "va", "unknown" }; public List GroupTracks(List localTracks) { @@ -115,8 +115,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Identification const double tagFuzz = 0.9; // check that any Album/Release MBID is unique - if (tracks.Select(x => x.FileTrackInfo.AlbumMBId).Distinct().Where(x => x.IsNotNullOrWhiteSpace()).Count() > 1 || - tracks.Select(x => x.FileTrackInfo.ReleaseMBId).Distinct().Where(x => x.IsNotNullOrWhiteSpace()).Count() > 1) + if (tracks.Select(x => x.FileTrackInfo.AlbumMBId).Distinct().Count(x => x.IsNotNullOrWhiteSpace()) > 1 || + tracks.Select(x => x.FileTrackInfo.ReleaseMBId).Distinct().Count(x => x.IsNotNullOrWhiteSpace()) > 1) { _logger.Trace("LooksLikeSingleRelease: MBIDs are not unique"); return false; @@ -152,7 +152,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Identification const double artistTagThreshold = 0.75; const double tagFuzz = 0.9; - var artistTags = tracks.Select(x => x.FileTrackInfo.ArtistTitle); + var artistTags = tracks.Select(x => x.FileTrackInfo.ArtistTitle).ToList(); if (!HasCommonEntry(artistTags, artistTagThreshold, tagFuzz)) { @@ -178,7 +178,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Identification // and group them. // we only bother doing this for the immediate parent directory. - var trackFolders = tracks.Select(x => Tuple.Create(x, Path.GetDirectoryName(x.Path))); + var trackFolders = tracks.Select(x => Tuple.Create(x, Path.GetDirectoryName(x.Path))).ToList(); var distinctFolders = trackFolders.Select(x => x.Item2).Distinct().ToList(); distinctFolders.Sort(); diff --git a/src/NzbDrone.Core/Music/Events/ArtistAddCompletedEvent.cs b/src/NzbDrone.Core/Music/Events/ArtistAddCompletedEvent.cs new file mode 100644 index 000000000..861936676 --- /dev/null +++ b/src/NzbDrone.Core/Music/Events/ArtistAddCompletedEvent.cs @@ -0,0 +1,14 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.Music.Events +{ + public class ArtistAddCompletedEvent : IEvent + { + public Artist Artist { get; private set; } + + public ArtistAddCompletedEvent(Artist artist) + { + Artist = artist; + } + } +} diff --git a/src/NzbDrone.Core/Music/Handlers/ArtistScannedHandler.cs b/src/NzbDrone.Core/Music/Handlers/ArtistScannedHandler.cs index 7a415e72b..97221d909 100644 --- a/src/NzbDrone.Core/Music/Handlers/ArtistScannedHandler.cs +++ b/src/NzbDrone.Core/Music/Handlers/ArtistScannedHandler.cs @@ -3,6 +3,7 @@ using NzbDrone.Core.IndexerSearch; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Events; +using NzbDrone.Core.Music.Events; namespace NzbDrone.Core.Music { @@ -13,38 +14,46 @@ namespace NzbDrone.Core.Music private readonly IArtistService _artistService; private readonly IManageCommandQueue _commandQueueManager; private readonly IAlbumAddedService _albumAddedService; + private readonly IEventAggregator _eventAggregator; private readonly Logger _logger; public ArtistScannedHandler(IAlbumMonitoredService albumMonitoredService, IArtistService artistService, IManageCommandQueue commandQueueManager, IAlbumAddedService albumAddedService, + IEventAggregator eventAggregator, Logger logger) { _albumMonitoredService = albumMonitoredService; _artistService = artistService; _commandQueueManager = commandQueueManager; _albumAddedService = albumAddedService; + _eventAggregator = eventAggregator; _logger = logger; } private void HandleScanEvents(Artist artist) { - if (artist.AddOptions != null) + var addOptions = artist.AddOptions; + + if (addOptions == null) { - _logger.Info("[{0}] was recently added, performing post-add actions", artist.Name); - _albumMonitoredService.SetAlbumMonitoredStatus(artist, artist.AddOptions); - - if (artist.AddOptions.SearchForMissingAlbums) - { - _commandQueueManager.Push(new MissingAlbumSearchCommand(artist.Id)); - } - - artist.AddOptions = null; - _artistService.RemoveAddOptions(artist); + _albumAddedService.SearchForRecentlyAdded(artist.Id); + return; } - _albumAddedService.SearchForRecentlyAdded(artist.Id); + _logger.Info("[{0}] was recently added, performing post-add actions", artist.Name); + _albumMonitoredService.SetAlbumMonitoredStatus(artist, addOptions); + + _eventAggregator.PublishEvent(new ArtistAddCompletedEvent(artist)); + + if (artist.AddOptions.SearchForMissingAlbums) + { + _commandQueueManager.Push(new MissingAlbumSearchCommand(artist.Id)); + } + + artist.AddOptions = null; + _artistService.RemoveAddOptions(artist); } public void Handle(ArtistScannedEvent message) diff --git a/src/NzbDrone.Core/Music/Services/ArtistService.cs b/src/NzbDrone.Core/Music/Services/ArtistService.cs index 8b44ce4d5..320430dd9 100644 --- a/src/NzbDrone.Core/Music/Services/ArtistService.cs +++ b/src/NzbDrone.Core/Music/Services/ArtistService.cs @@ -224,9 +224,13 @@ namespace NzbDrone.Core.Music public Artist UpdateArtist(Artist artist, bool publishUpdatedEvent = true) { _cache.Clear(); - var storedArtist = GetArtist(artist.Id); - var updatedArtist = _artistRepository.Update(artist); + var storedArtist = GetArtist(artist.Id); + + // Never update AddOptions when updating an artist, keep it the same as the existing stored artist. + artist.AddOptions = storedArtist.AddOptions; + + var updatedArtist = _artistRepository.Update(artist); if (publishUpdatedEvent) { _eventAggregator.PublishEvent(new ArtistEditedEvent(updatedArtist, storedArtist)); diff --git a/src/NzbDrone.Core/Notifications/Apprise/Apprise.cs b/src/NzbDrone.Core/Notifications/Apprise/Apprise.cs index 59dc96f4f..893686840 100644 --- a/src/NzbDrone.Core/Notifications/Apprise/Apprise.cs +++ b/src/NzbDrone.Core/Notifications/Apprise/Apprise.cs @@ -27,9 +27,9 @@ namespace NzbDrone.Core.Notifications.Apprise _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -37,6 +37,11 @@ namespace NzbDrone.Core.Notifications.Apprise _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/ArtistAddMessage.cs b/src/NzbDrone.Core/Notifications/ArtistAddMessage.cs new file mode 100644 index 000000000..db03c2fac --- /dev/null +++ b/src/NzbDrone.Core/Notifications/ArtistAddMessage.cs @@ -0,0 +1,15 @@ +using NzbDrone.Core.Music; + +namespace NzbDrone.Core.Notifications +{ + public class ArtistAddMessage + { + public string Message { get; set; } + public Artist Artist { get; set; } + + public override string ToString() + { + return Message; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs index a3225bf6a..4749a30f6 100644 --- a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs +++ b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs @@ -186,6 +186,45 @@ namespace NzbDrone.Core.Notifications.CustomScript ExecuteScript(environmentVariables); } + public override void OnArtistAdd(ArtistAddMessage message) + { + var artist = message.Artist; + var environmentVariables = new StringDictionary(); + + environmentVariables.Add("Lidarr_EventType", "ArtistAdd"); + environmentVariables.Add("Lidarr_InstanceName", _configFileProvider.InstanceName); + environmentVariables.Add("Lidarr_ApplicationUrl", _configService.ApplicationUrl); + environmentVariables.Add("Lidarr_Artist_Id", artist.Id.ToString()); + environmentVariables.Add("Lidarr_Artist_Title", artist.Metadata.Value.Name); + environmentVariables.Add("Lidarr_Artist_Path", artist.Path); + environmentVariables.Add("Lidarr_Artist_MBId", artist.Metadata.Value.ForeignArtistId.ToString()); + environmentVariables.Add("Lidarr_Artist_Type", artist.Metadata.Value.Type); + environmentVariables.Add("Lidarr_Artist_Genres", string.Join("|", artist.Metadata.Value.Genres)); + environmentVariables.Add("Lidarr_Artist_Tags", string.Join("|", artist.Tags.Select(t => _tagRepository.Get(t).Label))); + + ExecuteScript(environmentVariables); + } + + public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) + { + var artist = deleteMessage.Artist; + var environmentVariables = new StringDictionary(); + + environmentVariables.Add("Lidarr_EventType", "ArtistDeleted"); + environmentVariables.Add("Lidarr_InstanceName", _configFileProvider.InstanceName); + environmentVariables.Add("Lidarr_ApplicationUrl", _configService.ApplicationUrl); + environmentVariables.Add("Lidarr_Artist_Id", artist.Id.ToString()); + environmentVariables.Add("Lidarr_Artist_Title", artist.Metadata.Value.Name); + environmentVariables.Add("Lidarr_Artist_Path", artist.Path); + environmentVariables.Add("Lidarr_Artist_MBId", artist.Metadata.Value.ForeignArtistId.ToString()); + environmentVariables.Add("Lidarr_Artist_Type", artist.Metadata.Value.Type); + environmentVariables.Add("Lidarr_Artist_Genres", string.Join("|", artist.Metadata.Value.Genres)); + environmentVariables.Add("Lidarr_Artist_Tags", string.Join("|", artist.Tags.Select(t => _tagRepository.Get(t).Label))); + environmentVariables.Add("Lidarr_Artist_DeletedFiles", deleteMessage.DeletedFiles.ToString()); + + ExecuteScript(environmentVariables); + } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) { var artist = deleteMessage.Album.Artist.Value; @@ -212,26 +251,6 @@ namespace NzbDrone.Core.Notifications.CustomScript ExecuteScript(environmentVariables); } - public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) - { - var artist = deleteMessage.Artist; - var environmentVariables = new StringDictionary(); - - environmentVariables.Add("Lidarr_EventType", "ArtistDeleted"); - environmentVariables.Add("Lidarr_InstanceName", _configFileProvider.InstanceName); - environmentVariables.Add("Lidarr_ApplicationUrl", _configService.ApplicationUrl); - environmentVariables.Add("Lidarr_Artist_Id", artist.Id.ToString()); - environmentVariables.Add("Lidarr_Artist_Title", artist.Metadata.Value.Name); - environmentVariables.Add("Lidarr_Artist_Path", artist.Path); - environmentVariables.Add("Lidarr_Artist_MBId", artist.Metadata.Value.ForeignArtistId.ToString()); - environmentVariables.Add("Lidarr_Artist_Type", artist.Metadata.Value.Type); - environmentVariables.Add("Lidarr_Artist_Genres", string.Join("|", artist.Metadata.Value.Genres)); - environmentVariables.Add("Lidarr_Artist_Tags", string.Join("|", artist.Tags.Select(t => _tagRepository.Get(t).Label))); - environmentVariables.Add("Lidarr_Artist_DeletedFiles", deleteMessage.DeletedFiles.ToString()); - - ExecuteScript(environmentVariables); - } - public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var environmentVariables = new StringDictionary(); diff --git a/src/NzbDrone.Core/Notifications/Discord/Discord.cs b/src/NzbDrone.Core/Notifications/Discord/Discord.cs index adf1f29a9..41c0ae0d7 100644 --- a/src/NzbDrone.Core/Notifications/Discord/Discord.cs +++ b/src/NzbDrone.Core/Notifications/Discord/Discord.cs @@ -234,20 +234,20 @@ namespace NzbDrone.Core.Notifications.Discord _proxy.SendPayload(payload, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - var album = deleteMessage.Album; + var artist = message.Artist; var attachments = new List - { - new Embed - { - Title = album.Title, - Description = deleteMessage.DeletedFilesMessage - } - }; + { + new Embed + { + Title = artist.Name, + Description = message.Message + } + }; - var payload = CreatePayload("Album Deleted", attachments); + var payload = CreatePayload("Artist Added", attachments); _proxy.SendPayload(payload, Settings); } @@ -257,19 +257,37 @@ namespace NzbDrone.Core.Notifications.Discord var artist = deleteMessage.Artist; var attachments = new List - { - new Embed - { - Title = artist.Metadata.Value.Name, - Description = deleteMessage.DeletedFilesMessage - } - }; + { + new Embed + { + Title = artist.Name, + Description = deleteMessage.DeletedFilesMessage + } + }; var payload = CreatePayload("Artist Deleted", attachments); _proxy.SendPayload(payload, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + var album = deleteMessage.Album; + + var attachments = new List + { + new Embed + { + Title = album.Title, + Description = deleteMessage.DeletedFilesMessage + } + }; + + var payload = CreatePayload("Album Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var attachments = new List diff --git a/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs b/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs index 255bb6310..5e88486cd 100644 --- a/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs +++ b/src/NzbDrone.Core/Notifications/Discord/DiscordSettings.cs @@ -19,11 +19,38 @@ namespace NzbDrone.Core.Notifications.Discord public DiscordSettings() { // Set Default Fields - GrabFields = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; - ImportFields = new[] { 0, 1, 2, 3, 5, 6, 7, 8, 9 }; + GrabFields = new[] + { + (int)DiscordGrabFieldType.Overview, + (int)DiscordGrabFieldType.Rating, + (int)DiscordGrabFieldType.Genres, + (int)DiscordGrabFieldType.Quality, + (int)DiscordGrabFieldType.Group, + (int)DiscordGrabFieldType.Size, + (int)DiscordGrabFieldType.Links, + (int)DiscordGrabFieldType.Release, + (int)DiscordGrabFieldType.Poster, + (int)DiscordGrabFieldType.Fanart, + (int)DiscordGrabFieldType.Indexer, + (int)DiscordGrabFieldType.CustomFormats, + (int)DiscordGrabFieldType.CustomFormatScore + }; + ImportFields = new[] + { + (int)DiscordImportFieldType.Overview, + (int)DiscordImportFieldType.Rating, + (int)DiscordImportFieldType.Genres, + (int)DiscordImportFieldType.Quality, + (int)DiscordImportFieldType.Group, + (int)DiscordImportFieldType.Size, + (int)DiscordImportFieldType.Links, + (int)DiscordImportFieldType.Release, + (int)DiscordImportFieldType.Poster, + (int)DiscordImportFieldType.Fanart + }; } - private static readonly DiscordSettingsValidator Validator = new DiscordSettingsValidator(); + private static readonly DiscordSettingsValidator Validator = new (); [FieldDefinition(0, Label = "Webhook URL", HelpText = "Discord channel webhook url")] public string WebHookUrl { get; set; } @@ -37,10 +64,10 @@ namespace NzbDrone.Core.Notifications.Discord [FieldDefinition(3, Label = "Host", Advanced = true, HelpText = "Override the Host that shows for this notification, Blank is machine name", Type = FieldType.Textbox)] public string Author { get; set; } - [FieldDefinition(4, Label = "On Grab Fields", Advanced = true, SelectOptions = typeof(DiscordGrabFieldType), HelpText = "Change the fields that are passed in for this 'on grab' notification", Type = FieldType.TagSelect)] + [FieldDefinition(4, Label = "On Grab Fields", Advanced = true, SelectOptions = typeof(DiscordGrabFieldType), HelpText = "Change the fields that are passed in for this 'on grab' notification", Type = FieldType.Select)] public IEnumerable GrabFields { get; set; } - [FieldDefinition(5, Label = "On Import Fields", Advanced = true, SelectOptions = typeof(DiscordImportFieldType), HelpText = "Change the fields that are passed for this 'on import' notification", Type = FieldType.TagSelect)] + [FieldDefinition(5, Label = "On Import Fields", Advanced = true, SelectOptions = typeof(DiscordImportFieldType), HelpText = "Change the fields that are passed for this 'on import' notification", Type = FieldType.Select)] public IEnumerable ImportFields { get; set; } public NzbDroneValidationResult Validate() diff --git a/src/NzbDrone.Core/Notifications/Email/Email.cs b/src/NzbDrone.Core/Notifications/Email/Email.cs index 1155b51f6..c1bde9140 100644 --- a/src/NzbDrone.Core/Notifications/Email/Email.cs +++ b/src/NzbDrone.Core/Notifications/Email/Email.cs @@ -40,11 +40,11 @@ namespace NzbDrone.Core.Notifications.Email SendEmail(Settings, ALBUM_DOWNLOADED_TITLE_BRANDED, body); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - var body = $"{deleteMessage.Message}"; + var body = $"{message.Message}"; - SendEmail(Settings, ALBUM_DELETED_TITLE_BRANDED, body); + SendEmail(Settings, ARTIST_ADDED_TITLE_BRANDED, body); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -54,6 +54,13 @@ namespace NzbDrone.Core.Notifications.Email SendEmail(Settings, ARTIST_DELETED_TITLE_BRANDED, body); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + var body = $"{deleteMessage.Message}"; + + SendEmail(Settings, ALBUM_DELETED_TITLE_BRANDED, body); + } + public override void OnHealthIssue(HealthCheck.HealthCheck message) { SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message); diff --git a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs index 058bd6c4a..a41a78594 100644 --- a/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs +++ b/src/NzbDrone.Core/Notifications/Gotify/Gotify.cs @@ -33,9 +33,9 @@ namespace NzbDrone.Core.Notifications.Gotify SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, message.Artist); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, deleteMessage.Album?.Artist); + SendNotification(ARTIST_ADDED_TITLE, message.Message, message.Artist); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -43,6 +43,11 @@ namespace NzbDrone.Core.Notifications.Gotify SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, deleteMessage.Artist); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, deleteMessage.Album?.Artist); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, null); diff --git a/src/NzbDrone.Core/Notifications/INotification.cs b/src/NzbDrone.Core/Notifications/INotification.cs index 4ede325c2..4187259c3 100644 --- a/src/NzbDrone.Core/Notifications/INotification.cs +++ b/src/NzbDrone.Core/Notifications/INotification.cs @@ -12,8 +12,9 @@ namespace NzbDrone.Core.Notifications void OnGrab(GrabMessage grabMessage); void OnReleaseImport(AlbumDownloadMessage message); void OnRename(Artist artist, List renamedFiles); - void OnAlbumDelete(AlbumDeleteMessage deleteMessage); + void OnArtistAdd(ArtistAddMessage message); void OnArtistDelete(ArtistDeleteMessage deleteMessage); + void OnAlbumDelete(AlbumDeleteMessage deleteMessage); void OnHealthIssue(HealthCheck.HealthCheck healthCheck); void OnHealthRestored(HealthCheck.HealthCheck previousCheck); void OnApplicationUpdate(ApplicationUpdateMessage updateMessage); @@ -25,8 +26,9 @@ namespace NzbDrone.Core.Notifications bool SupportsOnReleaseImport { get; } bool SupportsOnUpgrade { get; } bool SupportsOnRename { get; } - bool SupportsOnAlbumDelete { get; } + bool SupportsOnArtistAdd { get; } bool SupportsOnArtistDelete { get; } + bool SupportsOnAlbumDelete { get; } bool SupportsOnHealthIssue { get; } bool SupportsOnHealthRestored { get; } bool SupportsOnApplicationUpdate { get; } diff --git a/src/NzbDrone.Core/Notifications/Join/Join.cs b/src/NzbDrone.Core/Notifications/Join/Join.cs index ff1102d4b..6ca9b4ca9 100644 --- a/src/NzbDrone.Core/Notifications/Join/Join.cs +++ b/src/NzbDrone.Core/Notifications/Join/Join.cs @@ -27,9 +27,9 @@ namespace NzbDrone.Core.Notifications.Join _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE_BRANDED, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE_BRANDED, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -37,6 +37,11 @@ namespace NzbDrone.Core.Notifications.Join _proxy.SendNotification(ARTIST_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck message) { _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs index f68fef06f..8647fff32 100644 --- a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs +++ b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs @@ -29,9 +29,11 @@ namespace NzbDrone.Core.Notifications.Mailgun _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, downloadMessage.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + var body = $"{message.Message}"; + + _proxy.SendNotification(ARTIST_ADDED_TITLE, body, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -39,6 +41,11 @@ namespace NzbDrone.Core.Notifications.Mailgun _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheckMessage) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowser.cs b/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowser.cs index daa4230f6..db41933ea 100644 --- a/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowser.cs +++ b/src/NzbDrone.Core/Notifications/MediaBrowser/MediaBrowser.cs @@ -47,16 +47,16 @@ namespace NzbDrone.Core.Notifications.Emby } } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { if (Settings.Notify) { - _mediaBrowserService.Notify(Settings, ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message); + _mediaBrowserService.Notify(Settings, ARTIST_ADDED_TITLE_BRANDED, message.Message); } if (Settings.UpdateLibrary) { - _mediaBrowserService.Update(Settings, deleteMessage.Album.Artist); + _mediaBrowserService.Update(Settings, message.Artist); } } @@ -73,6 +73,19 @@ namespace NzbDrone.Core.Notifications.Emby } } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + if (Settings.Notify) + { + _mediaBrowserService.Notify(Settings, ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message); + } + + if (Settings.UpdateLibrary) + { + _mediaBrowserService.Update(Settings, deleteMessage.Album.Artist); + } + } + public override void OnHealthIssue(HealthCheck.HealthCheck message) { if (Settings.Notify) diff --git a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs index 041d8fdc9..3d5300de8 100644 --- a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs +++ b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs @@ -52,9 +52,9 @@ namespace NzbDrone.Core.Notifications.Notifiarr _proxy.SendNotification(BuildOnTrackRetagPayload(message), Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(BuildOnAlbumDelete(deleteMessage), Settings); + _proxy.SendNotification(BuildOnArtistAdd(message), Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -62,6 +62,11 @@ namespace NzbDrone.Core.Notifications.Notifiarr _proxy.SendNotification(BuildOnArtistDelete(deleteMessage), Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(BuildOnAlbumDelete(deleteMessage), Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(BuildHealthPayload(healthCheck), Settings); diff --git a/src/NzbDrone.Core/Notifications/NotificationBase.cs b/src/NzbDrone.Core/Notifications/NotificationBase.cs index 7b5da7f1d..4110a9fa9 100644 --- a/src/NzbDrone.Core/Notifications/NotificationBase.cs +++ b/src/NzbDrone.Core/Notifications/NotificationBase.cs @@ -12,8 +12,9 @@ namespace NzbDrone.Core.Notifications { protected const string ALBUM_GRABBED_TITLE = "Album Grabbed"; protected const string ALBUM_DOWNLOADED_TITLE = "Album Downloaded"; - protected const string ALBUM_DELETED_TITLE = "Album Deleted"; + protected const string ARTIST_ADDED_TITLE = "Artist Added"; protected const string ARTIST_DELETED_TITLE = "Artist Deleted"; + protected const string ALBUM_DELETED_TITLE = "Album Deleted"; protected const string HEALTH_ISSUE_TITLE = "Health Check Failure"; protected const string HEALTH_RESTORED_TITLE = "Health Check Restored"; protected const string DOWNLOAD_FAILURE_TITLE = "Download Failed"; @@ -23,8 +24,9 @@ namespace NzbDrone.Core.Notifications protected const string ALBUM_GRABBED_TITLE_BRANDED = "Lidarr - " + ALBUM_GRABBED_TITLE; protected const string ALBUM_DOWNLOADED_TITLE_BRANDED = "Lidarr - " + ALBUM_DOWNLOADED_TITLE; - protected const string ALBUM_DELETED_TITLE_BRANDED = "Lidarr - " + ALBUM_DELETED_TITLE; + protected const string ARTIST_ADDED_TITLE_BRANDED = "Lidarr - " + ARTIST_ADDED_TITLE; protected const string ARTIST_DELETED_TITLE_BRANDED = "Lidarr - " + ARTIST_DELETED_TITLE; + protected const string ALBUM_DELETED_TITLE_BRANDED = "Lidarr - " + ALBUM_DELETED_TITLE; protected const string HEALTH_ISSUE_TITLE_BRANDED = "Lidarr - " + HEALTH_ISSUE_TITLE; protected const string HEALTH_RESTORED_TITLE_BRANDED = "Lidarr - " + HEALTH_RESTORED_TITLE; protected const string DOWNLOAD_FAILURE_TITLE_BRANDED = "Lidarr - " + DOWNLOAD_FAILURE_TITLE; @@ -57,7 +59,7 @@ namespace NzbDrone.Core.Notifications { } - public virtual void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public virtual void OnArtistAdd(ArtistAddMessage message) { } @@ -65,6 +67,10 @@ namespace NzbDrone.Core.Notifications { } + public virtual void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + } + public virtual void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { } @@ -97,8 +103,9 @@ namespace NzbDrone.Core.Notifications public bool SupportsOnRename => HasConcreteImplementation("OnRename"); public bool SupportsOnReleaseImport => HasConcreteImplementation("OnReleaseImport"); public bool SupportsOnUpgrade => SupportsOnReleaseImport; - public bool SupportsOnAlbumDelete => HasConcreteImplementation("OnAlbumDelete"); + public bool SupportsOnArtistAdd => HasConcreteImplementation("OnArtistAdd"); public bool SupportsOnArtistDelete => HasConcreteImplementation("OnArtistDelete"); + public bool SupportsOnAlbumDelete => HasConcreteImplementation("OnAlbumDelete"); public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue"); public bool SupportsOnHealthRestored => HasConcreteImplementation("OnHealthRestored"); public bool SupportsOnDownloadFailure => HasConcreteImplementation("OnDownloadFailure"); diff --git a/src/NzbDrone.Core/Notifications/NotificationDefinition.cs b/src/NzbDrone.Core/Notifications/NotificationDefinition.cs index 1dc9d8026..f5f4e2f05 100644 --- a/src/NzbDrone.Core/Notifications/NotificationDefinition.cs +++ b/src/NzbDrone.Core/Notifications/NotificationDefinition.cs @@ -8,8 +8,9 @@ namespace NzbDrone.Core.Notifications public bool OnReleaseImport { get; set; } public bool OnUpgrade { get; set; } public bool OnRename { get; set; } - public bool OnAlbumDelete { get; set; } + public bool OnArtistAdd { get; set; } public bool OnArtistDelete { get; set; } + public bool OnAlbumDelete { get; set; } public bool OnHealthIssue { get; set; } public bool OnHealthRestored { get; set; } public bool OnDownloadFailure { get; set; } @@ -20,8 +21,9 @@ namespace NzbDrone.Core.Notifications public bool SupportsOnReleaseImport { get; set; } public bool SupportsOnUpgrade { get; set; } public bool SupportsOnRename { get; set; } - public bool SupportsOnAlbumDelete { get; set; } + public bool SupportsOnArtistAdd { get; set; } public bool SupportsOnArtistDelete { get; set; } + public bool SupportsOnAlbumDelete { get; set; } public bool SupportsOnHealthIssue { get; set; } public bool SupportsOnHealthRestored { get; set; } public bool IncludeHealthWarnings { get; set; } @@ -30,6 +32,6 @@ namespace NzbDrone.Core.Notifications public bool SupportsOnTrackRetag { get; set; } public bool SupportsOnApplicationUpdate { get; set; } - public override bool Enable => OnGrab || OnReleaseImport || (OnReleaseImport && OnUpgrade) || OnAlbumDelete || OnArtistDelete || OnHealthIssue || OnHealthRestored || OnDownloadFailure || OnImportFailure || OnTrackRetag || OnApplicationUpdate; + public override bool Enable => OnGrab || OnReleaseImport || (OnReleaseImport && OnUpgrade) || OnArtistAdd || OnArtistDelete || OnAlbumDelete || OnHealthIssue || OnHealthRestored || OnDownloadFailure || OnImportFailure || OnTrackRetag || OnApplicationUpdate; } } diff --git a/src/NzbDrone.Core/Notifications/NotificationFactory.cs b/src/NzbDrone.Core/Notifications/NotificationFactory.cs index 77548146e..d8217896c 100644 --- a/src/NzbDrone.Core/Notifications/NotificationFactory.cs +++ b/src/NzbDrone.Core/Notifications/NotificationFactory.cs @@ -14,8 +14,9 @@ namespace NzbDrone.Core.Notifications List OnReleaseImportEnabled(bool filterBlockedNotifications = true); List OnUpgradeEnabled(bool filterBlockedNotifications = true); List OnRenameEnabled(bool filterBlockedNotifications = true); - List OnAlbumDeleteEnabled(bool filterBlockedNotifications = true); + List OnArtistAddEnabled(bool filterBlockedNotifications = true); List OnArtistDeleteEnabled(bool filterBlockedNotifications = true); + List OnAlbumDeleteEnabled(bool filterBlockedNotifications = true); List OnHealthIssueEnabled(bool filterBlockedNotifications = true); List OnHealthRestoredEnabled(bool filterBlockedNotifications = true); List OnDownloadFailureEnabled(bool filterBlockedNotifications = true); @@ -81,14 +82,14 @@ namespace NzbDrone.Core.Notifications return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnRename).ToList(); } - public List OnAlbumDeleteEnabled(bool filterBlockedNotifications = true) + public List OnArtistAddEnabled(bool filterBlockedNotifications = true) { if (filterBlockedNotifications) { - return FilterBlockedNotifications(GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnAlbumDelete)).ToList(); + return FilterBlockedNotifications(GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnArtistAdd)).ToList(); } - return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnAlbumDelete).ToList(); + return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnArtistAdd).ToList(); } public List OnArtistDeleteEnabled(bool filterBlockedNotifications = true) @@ -101,6 +102,16 @@ namespace NzbDrone.Core.Notifications return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnArtistDelete).ToList(); } + public List OnAlbumDeleteEnabled(bool filterBlockedNotifications = true) + { + if (filterBlockedNotifications) + { + return FilterBlockedNotifications(GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnAlbumDelete)).ToList(); + } + + return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnAlbumDelete).ToList(); + } + public List OnHealthIssueEnabled(bool filterBlockedNotifications = true) { if (filterBlockedNotifications) @@ -185,8 +196,9 @@ namespace NzbDrone.Core.Notifications definition.SupportsOnReleaseImport = provider.SupportsOnReleaseImport; definition.SupportsOnUpgrade = provider.SupportsOnUpgrade; definition.SupportsOnRename = provider.SupportsOnRename; - definition.SupportsOnAlbumDelete = provider.SupportsOnAlbumDelete; + definition.SupportsOnArtistAdd = provider.SupportsOnArtistAdd; definition.SupportsOnArtistDelete = provider.SupportsOnArtistDelete; + definition.SupportsOnAlbumDelete = provider.SupportsOnAlbumDelete; definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue; definition.SupportsOnHealthRestored = provider.SupportsOnHealthRestored; definition.SupportsOnDownloadFailure = provider.SupportsOnDownloadFailure; diff --git a/src/NzbDrone.Core/Notifications/NotificationService.cs b/src/NzbDrone.Core/Notifications/NotificationService.cs index 1a5408aee..1dda2c7bd 100644 --- a/src/NzbDrone.Core/Notifications/NotificationService.cs +++ b/src/NzbDrone.Core/Notifications/NotificationService.cs @@ -20,8 +20,9 @@ namespace NzbDrone.Core.Notifications : IHandle, IHandle, IHandle, - IHandle, + IHandle, IHandle, + IHandle, IHandle, IHandle, IHandle, @@ -214,24 +215,29 @@ namespace NzbDrone.Core.Notifications } } - public void Handle(AlbumDeletedEvent message) + public void Handle(ArtistAddCompletedEvent message) { - var deleteMessage = new AlbumDeleteMessage(message.Album, message.DeleteFiles); + var artist = message.Artist; + var addMessage = new ArtistAddMessage + { + Artist = artist, + Message = artist.Name + }; - foreach (var notification in _notificationFactory.OnAlbumDeleteEnabled()) + foreach (var notification in _notificationFactory.OnArtistAddEnabled()) { try { - if (ShouldHandleArtist(notification.Definition, deleteMessage.Album.Artist)) + if (ShouldHandleArtist(notification.Definition, artist)) { - notification.OnAlbumDelete(deleteMessage); + notification.OnArtistAdd(addMessage); _notificationStatusService.RecordSuccess(notification.Definition.Id); } } catch (Exception ex) { _notificationStatusService.RecordFailure(notification.Definition.Id); - _logger.Warn(ex, "Unable to send OnAlbumDelete notification to: " + notification.Definition.Name); + _logger.Warn(ex, "Unable to send OnArtistAdd notification to: " + notification.Definition.Name); } } } @@ -261,6 +267,28 @@ namespace NzbDrone.Core.Notifications } } + public void Handle(AlbumDeletedEvent message) + { + var deleteMessage = new AlbumDeleteMessage(message.Album, message.DeleteFiles); + + foreach (var notification in _notificationFactory.OnAlbumDeleteEnabled()) + { + try + { + if (ShouldHandleArtist(notification.Definition, deleteMessage.Album.Artist)) + { + notification.OnAlbumDelete(deleteMessage); + _notificationStatusService.RecordSuccess(notification.Definition.Id); + } + } + catch (Exception ex) + { + _notificationStatusService.RecordFailure(notification.Definition.Id); + _logger.Warn(ex, "Unable to send OnAlbumDelete notification to: " + notification.Definition.Name); + } + } + } + public void Handle(HealthCheckFailedEvent message) { // Don't send health check notifications during the start up grace period, diff --git a/src/NzbDrone.Core/Notifications/Ntfy/Ntfy.cs b/src/NzbDrone.Core/Notifications/Ntfy/Ntfy.cs index 680338b49..8fefccadb 100644 --- a/src/NzbDrone.Core/Notifications/Ntfy/Ntfy.cs +++ b/src/NzbDrone.Core/Notifications/Ntfy/Ntfy.cs @@ -28,9 +28,9 @@ namespace NzbDrone.Core.Notifications.Ntfy _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE_BRANDED, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE_BRANDED, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -38,6 +38,11 @@ namespace NzbDrone.Core.Notifications.Ntfy _proxy.SendNotification(ARTIST_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Plex/Server/PlexServer.cs b/src/NzbDrone.Core/Notifications/Plex/Server/PlexServer.cs index a2cc153de..4c78ee37f 100644 --- a/src/NzbDrone.Core/Notifications/Plex/Server/PlexServer.cs +++ b/src/NzbDrone.Core/Notifications/Plex/Server/PlexServer.cs @@ -54,12 +54,9 @@ namespace NzbDrone.Core.Notifications.Plex.Server UpdateIfEnabled(message.Artist); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - if (deleteMessage.DeletedFiles) - { - UpdateIfEnabled(deleteMessage.Album.Artist); - } + UpdateIfEnabled(message.Artist); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -70,6 +67,14 @@ namespace NzbDrone.Core.Notifications.Plex.Server } } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + if (deleteMessage.DeletedFiles) + { + UpdateIfEnabled(deleteMessage.Album.Artist); + } + } + private void UpdateIfEnabled(Artist artist) { _plexTvService.Ping(Settings.AuthToken); diff --git a/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs b/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs index 5560fa27a..513770d73 100644 --- a/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs +++ b/src/NzbDrone.Core/Notifications/Prowl/Prowl.cs @@ -26,9 +26,9 @@ namespace NzbDrone.Core.Notifications.Prowl _prowlProxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _prowlProxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _prowlProxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -36,6 +36,11 @@ namespace NzbDrone.Core.Notifications.Prowl _prowlProxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _prowlProxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs index b12cf6a95..6ae32d91c 100644 --- a/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs +++ b/src/NzbDrone.Core/Notifications/PushBullet/PushBullet.cs @@ -29,9 +29,9 @@ namespace NzbDrone.Core.Notifications.PushBullet _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE_BRANDED, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -39,6 +39,11 @@ namespace NzbDrone.Core.Notifications.PushBullet _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs b/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs index 53f37847f..7488769fc 100644 --- a/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs +++ b/src/NzbDrone.Core/Notifications/Pushcut/Pushcut.cs @@ -36,9 +36,9 @@ namespace NzbDrone.Core.Notifications.Pushcut _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, $"{message.Artist.Name} added to library", Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -46,6 +46,11 @@ namespace NzbDrone.Core.Notifications.Pushcut _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs b/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs index a2e296b23..15880e886 100644 --- a/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs +++ b/src/NzbDrone.Core/Notifications/Pushover/Pushover.cs @@ -26,9 +26,9 @@ namespace NzbDrone.Core.Notifications.Pushover _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -36,6 +36,11 @@ namespace NzbDrone.Core.Notifications.Pushover _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs b/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs index c1149b411..6fa6bd7cd 100644 --- a/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs +++ b/src/NzbDrone.Core/Notifications/SendGrid/SendGrid.cs @@ -29,9 +29,9 @@ namespace NzbDrone.Core.Notifications.SendGrid _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -39,6 +39,11 @@ namespace NzbDrone.Core.Notifications.SendGrid _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Signal/Signal.cs b/src/NzbDrone.Core/Notifications/Signal/Signal.cs index 3d7efd9ed..e8bf44bb5 100644 --- a/src/NzbDrone.Core/Notifications/Signal/Signal.cs +++ b/src/NzbDrone.Core/Notifications/Signal/Signal.cs @@ -26,9 +26,9 @@ namespace NzbDrone.Core.Notifications.Signal _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -36,6 +36,11 @@ namespace NzbDrone.Core.Notifications.Signal _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Simplepush/Simplepush.cs b/src/NzbDrone.Core/Notifications/Simplepush/Simplepush.cs index 06ca177d1..e0dbe2b6f 100644 --- a/src/NzbDrone.Core/Notifications/Simplepush/Simplepush.cs +++ b/src/NzbDrone.Core/Notifications/Simplepush/Simplepush.cs @@ -26,9 +26,9 @@ namespace NzbDrone.Core.Notifications.Simplepush _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -36,6 +36,11 @@ namespace NzbDrone.Core.Notifications.Simplepush _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Slack/Slack.cs b/src/NzbDrone.Core/Notifications/Slack/Slack.cs index 019195710..19994301c 100644 --- a/src/NzbDrone.Core/Notifications/Slack/Slack.cs +++ b/src/NzbDrone.Core/Notifications/Slack/Slack.cs @@ -70,18 +70,17 @@ namespace NzbDrone.Core.Notifications.Slack _proxy.SendPayload(payload, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { var attachments = new List - { - new Attachment - { - Title = deleteMessage.Album.Title, - Text = deleteMessage.DeletedFilesMessage - } - }; + { + new Attachment + { + Title = message.Artist.Metadata.Value.Name, + } + }; - var payload = CreatePayload("Album Deleted", attachments); + var payload = CreatePayload("Artist Added", attachments); _proxy.SendPayload(payload, Settings); } @@ -89,19 +88,35 @@ namespace NzbDrone.Core.Notifications.Slack public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) { var attachments = new List - { - new Attachment - { - Title = deleteMessage.Artist.Metadata.Value.Name, - Text = deleteMessage.DeletedFilesMessage - } - }; + { + new Attachment + { + Title = deleteMessage.Artist.Metadata.Value.Name, + Text = deleteMessage.DeletedFilesMessage + } + }; var payload = CreatePayload("Artist Deleted", attachments); _proxy.SendPayload(payload, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + var attachments = new List + { + new Attachment + { + Title = deleteMessage.Album.Title, + Text = deleteMessage.DeletedFilesMessage + } + }; + + var payload = CreatePayload("Album Deleted", attachments); + + _proxy.SendPayload(payload, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { var attachments = new List diff --git a/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs b/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs index c8c97a260..85c266fe2 100644 --- a/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs +++ b/src/NzbDrone.Core/Notifications/Subsonic/Subsonic.cs @@ -41,9 +41,9 @@ namespace NzbDrone.Core.Notifications.Subsonic Update(); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - Notify(Settings, ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message); + Notify(Settings, ARTIST_ADDED_TITLE_BRANDED, message.Message); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -51,6 +51,11 @@ namespace NzbDrone.Core.Notifications.Subsonic Notify(Settings, ARTIST_DELETED_TITLE_BRANDED, deleteMessage.Message); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + Notify(Settings, ALBUM_DELETED_TITLE_BRANDED, deleteMessage.Message); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message); diff --git a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs index b1e5f0333..4e5b6b4ce 100644 --- a/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs +++ b/src/NzbDrone.Core/Notifications/Synology/SynologyIndexer.cs @@ -55,14 +55,11 @@ namespace NzbDrone.Core.Notifications.Synology } } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - if (deleteMessage.DeletedFiles) + if (Settings.UpdateLibrary) { - if (Settings.UpdateLibrary) - { - _indexerProxy.DeleteFolder(deleteMessage.Album.Artist.Value.Path); - } + _indexerProxy.UpdateFolder(message.Artist.Path); } } @@ -77,6 +74,17 @@ namespace NzbDrone.Core.Notifications.Synology } } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + if (deleteMessage.DeletedFiles) + { + if (Settings.UpdateLibrary) + { + _indexerProxy.DeleteFolder(deleteMessage.Album.Artist.Value.Path); + } + } + } + public override ValidationResult Test() { var failures = new List(); diff --git a/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs b/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs index f95de3338..96b0d4bb6 100644 --- a/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs +++ b/src/NzbDrone.Core/Notifications/Telegram/Telegram.cs @@ -26,9 +26,9 @@ namespace NzbDrone.Core.Notifications.Telegram _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, message.Message, Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + _proxy.SendNotification(ARTIST_ADDED_TITLE, message.Message, Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -36,6 +36,11 @@ namespace NzbDrone.Core.Notifications.Telegram _proxy.SendNotification(ARTIST_DELETED_TITLE, deleteMessage.Message, Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendNotification(ALBUM_DELETED_TITLE, deleteMessage.Message, Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); diff --git a/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs b/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs index ef423b316..6584fa1da 100644 --- a/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs +++ b/src/NzbDrone.Core/Notifications/Twitter/Twitter.cs @@ -28,9 +28,9 @@ namespace NzbDrone.Core.Notifications.Twitter _twitterService.SendNotification($"Imported: {message.Message}", Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _twitterService.SendNotification($"Album Deleted: {deleteMessage.Message}", Settings); + _twitterService.SendNotification($"Artist Added: {message.Message}", Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -38,6 +38,11 @@ namespace NzbDrone.Core.Notifications.Twitter _twitterService.SendNotification($"Artist Deleted: {deleteMessage.Message}", Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _twitterService.SendNotification($"Album Deleted: {deleteMessage.Message}", Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings); diff --git a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs index 3bce52990..9c0f1855b 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/Webhook.cs @@ -50,9 +50,9 @@ namespace NzbDrone.Core.Notifications.Webhook _proxy.SendWebhook(BuildOnTrackRetagPayload(message), Settings); } - public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + public override void OnArtistAdd(ArtistAddMessage message) { - _proxy.SendWebhook(BuildOnAlbumDelete(deleteMessage), Settings); + _proxy.SendWebhook(BuildOnArtistAdd(message), Settings); } public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) @@ -60,6 +60,11 @@ namespace NzbDrone.Core.Notifications.Webhook _proxy.SendWebhook(BuildOnArtistDelete(deleteMessage), Settings); } + public override void OnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + _proxy.SendWebhook(BuildOnAlbumDelete(deleteMessage), Settings); + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { _proxy.SendWebhook(BuildHealthPayload(healthCheck), Settings); diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookArtistAddPayload.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookArtistAddPayload.cs new file mode 100644 index 000000000..eb8683c15 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookArtistAddPayload.cs @@ -0,0 +1,7 @@ +namespace NzbDrone.Core.Notifications.Webhook +{ + public class WebhookArtistAddPayload : WebhookPayload + { + public WebhookArtist Artist { get; set; } + } +} diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs index f4450612f..9504a87a8 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs @@ -130,15 +130,14 @@ namespace NzbDrone.Core.Notifications.Webhook }; } - public WebhookAlbumDeletePayload BuildOnAlbumDelete(AlbumDeleteMessage deleteMessage) + protected WebhookArtistAddPayload BuildOnArtistAdd(ArtistAddMessage addMessage) { - return new WebhookAlbumDeletePayload + return new WebhookArtistAddPayload { - EventType = WebhookEventType.AlbumDelete, + EventType = WebhookEventType.ArtistAdd, InstanceName = _configFileProvider.InstanceName, ApplicationUrl = _configService.ApplicationUrl, - Album = new WebhookAlbum(deleteMessage.Album), - DeletedFiles = deleteMessage.DeletedFiles + Artist = new WebhookArtist(addMessage.Artist), }; } @@ -154,6 +153,18 @@ namespace NzbDrone.Core.Notifications.Webhook }; } + public WebhookAlbumDeletePayload BuildOnAlbumDelete(AlbumDeleteMessage deleteMessage) + { + return new WebhookAlbumDeletePayload + { + EventType = WebhookEventType.AlbumDelete, + InstanceName = _configFileProvider.InstanceName, + ApplicationUrl = _configService.ApplicationUrl, + Album = new WebhookAlbum(deleteMessage.Album), + DeletedFiles = deleteMessage.DeletedFiles + }; + } + protected WebhookHealthPayload BuildHealthPayload(HealthCheck.HealthCheck healthCheck) { return new WebhookHealthPayload diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs index f598d554c..310c8c42d 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookEventType.cs @@ -14,8 +14,9 @@ namespace NzbDrone.Core.Notifications.Webhook DownloadFailure, ImportFailure, Rename, - AlbumDelete, + ArtistAdd, ArtistDelete, + AlbumDelete, Health, Retag, ApplicationUpdate, diff --git a/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs b/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs index e08ec1b28..95e43ba40 100644 --- a/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs +++ b/src/NzbDrone.Core/Notifications/Xbmc/Xbmc.cs @@ -42,6 +42,25 @@ namespace NzbDrone.Core.Notifications.Xbmc UpdateAndClean(artist); } + public override void OnArtistAdd(ArtistAddMessage message) + { + const string header = "Lidarr - Artist Added"; + + Notify(Settings, header, message.Message); + UpdateAndClean(message.Artist, true); + } + + public override void OnArtistDelete(ArtistDeleteMessage deleteMessage) + { + if (deleteMessage.DeletedFiles) + { + const string header = "Lidarr - Artist Deleted"; + + Notify(Settings, header, deleteMessage.Message); + UpdateAndClean(deleteMessage.Artist, true); + } + } + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) { Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message); diff --git a/src/NzbDrone.Core/Parser/Model/RemoteAlbum.cs b/src/NzbDrone.Core/Parser/Model/RemoteAlbum.cs index d05bf094b..3df40b57e 100644 --- a/src/NzbDrone.Core/Parser/Model/RemoteAlbum.cs +++ b/src/NzbDrone.Core/Parser/Model/RemoteAlbum.cs @@ -17,6 +17,7 @@ namespace NzbDrone.Core.Parser.Model public TorrentSeedConfiguration SeedConfiguration { get; set; } public List CustomFormats { get; set; } public int CustomFormatScore { get; set; } + public ReleaseSourceType ReleaseSource { get; set; } public RemoteAlbum() { @@ -34,4 +35,14 @@ namespace NzbDrone.Core.Parser.Model return Release.Title; } } + + public enum ReleaseSourceType + { + Unknown = 0, + Rss = 1, + Search = 2, + UserInvokedSearch = 3, + InteractiveSearch = 4, + ReleasePush = 5 + } } diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 629e39468..3434ea8ef 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -154,7 +154,7 @@ namespace NzbDrone.Core.Parser new Regex(@"^b00bs$", RegexOptions.Compiled | RegexOptions.IgnoreCase) }; - private static readonly RegexReplace NormalizeRegex = new RegexReplace(@"((?:\b|_)(?proper)\b", + private static readonly Regex ProperRegex = new (@"\b(?proper)\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex RepackRegex = new Regex(@"\b(?repack\d?|rerip\d?)\b", + private static readonly Regex RepackRegex = new (@"\b(?repack\d?|rerip\d?)\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex VersionRegex = new Regex(@"\d[-._ ]?v(?\d)[-._ ]|\[v(?\d)\]|repack(?\d)|rerip(?\d)", + private static readonly Regex VersionRegex = new (@"(?:\d(?\d)[-._ ]|\[v(?\d)\]|repack(?\d)|rerip(?\d)", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex RealRegex = new Regex(@"\b(?REAL)\b", + private static readonly Regex RealRegex = new (@"\b(?REAL)\b", RegexOptions.Compiled); - private static readonly Regex BitRateRegex = new Regex(@"\b(?:(?96[ ]?kbps|96|[\[\(].*96.*[\]\)])| + private static readonly Regex BitRateRegex = new (@"\b(?:(?96[ ]?kbps|96|[\[\(].*96.*[\]\)])| (?128[ ]?kbps|128|[\[\(].*128.*[\]\)])| (?160[ ]?kbps|160|[\[\(].*160.*[\]\)]|q5)| (?192[ ]?kbps|192|[\[\(].*192.*[\]\)]|q6)| @@ -39,12 +39,13 @@ namespace NzbDrone.Core.Parser (?V2[ ]?kbps|V2|[\[\(].*V2.*[\]\)]))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - private static readonly Regex SampleSizeRegex = new Regex(@"\b(?:(?24[ ]?bit|tr24|24-(?:44|48|96|192)|[\[\(].*24bit.*[\]\)]))\b", RegexOptions.Compiled); + private static readonly Regex SampleSizeRegex = new (@"\b(?:(?24[ ]?bit|tr24|24-(?:44|48|96|192)|[\[\(].*24bit.*[\]\)]))\b", RegexOptions.Compiled); + private static readonly Regex CodecRegex = new Regex(@"\b(?:(?MPEG Version \d(.5)? Audio, Layer 1|MP1)|(?MPEG Version \d(.5)? Audio, Layer 2|MP2)|(?MP3.*VBR|MPEG Version \d(.5)? Audio, Layer 3 vbr)|(?MP3|MPEG Version \d(.5)? Audio, Layer 3)|(?(web)?flac|TR24)|(?wavpack|wv)|(?alac)|(?WMA\d?)|(?WAV|PCM)|(?MKA|M4A|M4P|M4B|AAC|mp4a|MPEG-4 Audio(?!.*alac))|(?MKA|OGG|OGA|Vorbis))\b|(?monkey's audio|[\[|\(].*\bape\b.*[\]|\)])|(?Opus Version \d(.5)? Audio|[\[|\(].*\bopus\b.*[\]|\)])", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex WebRegex = new Regex(@"\b(?WEB)(?:\b|$|[ .])", + private static readonly Regex WebRegex = new (@"\b(?WEB)(?:\b|$|[ .])", RegexOptions.Compiled | RegexOptions.IgnoreCase); public static QualityModel ParseQuality(string name, IAudioCodec audioCodec) diff --git a/src/NzbDrone.Core/Qualities/Quality.cs b/src/NzbDrone.Core/Qualities/Quality.cs index 0e30964ca..cac866b14 100644 --- a/src/NzbDrone.Core/Qualities/Quality.cs +++ b/src/NzbDrone.Core/Qualities/Quality.cs @@ -161,44 +161,44 @@ namespace NzbDrone.Core.Qualities DefaultQualityDefinitions = new HashSet { - new QualityDefinition(Quality.Unknown) { Weight = 1, MinSize = 0, MaxSize = 350, GroupWeight = 1 }, - new QualityDefinition(Quality.MP3_008) { Weight = 2, MinSize = 0, MaxSize = 10, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_016) { Weight = 3, MinSize = 0, MaxSize = 20, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_024) { Weight = 4, MinSize = 0, MaxSize = 30, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_032) { Weight = 5, MinSize = 0, MaxSize = 40, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_040) { Weight = 6, MinSize = 0, MaxSize = 45, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_048) { Weight = 7, MinSize = 0, MaxSize = 55, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_056) { Weight = 8, MinSize = 0, MaxSize = 65, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_064) { Weight = 9, MinSize = 0, MaxSize = 75, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_080) { Weight = 10, MinSize = 0, MaxSize = 95, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_096) { Weight = 11, MinSize = 0, MaxSize = 110, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_112) { Weight = 12, MinSize = 0, MaxSize = 125, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_128) { Weight = 13, MinSize = 0, MaxSize = 140, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.VORBIS_Q5) { Weight = 14, MinSize = 0, MaxSize = 175, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_160) { Weight = 14, MinSize = 0, MaxSize = 175, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_192) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.VORBIS_Q6) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.AAC_192) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.WMA) { Weight = 15, MinSize = 0, MaxSize = 350, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.MP3_224) { Weight = 16, MinSize = 0, MaxSize = 245, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.VORBIS_Q7) { Weight = 17, MinSize = 0, MaxSize = 245, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.MP3_VBR_V2) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.MP3_256) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.VORBIS_Q8) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.AAC_256) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.MP3_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.AAC_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.MP3_320) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.VORBIS_Q9) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.AAC_320) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.VORBIS_Q10) { Weight = 21, MinSize = 0, MaxSize = 550, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.FLAC) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.ALAC) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.APE) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.WAVPACK) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.FLAC_24) { Weight = 23, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.ALAC_24) { Weight = 23, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.WAV) { Weight = 24, MinSize = 0, MaxSize = null, GroupWeight = 8 } + new QualityDefinition(Quality.Unknown) { Weight = 1, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupWeight = 1 }, + new QualityDefinition(Quality.MP3_008) { Weight = 2, MinSize = 0, MaxSize = 10, PreferredSize = 5, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_016) { Weight = 3, MinSize = 0, MaxSize = 20, PreferredSize = 15, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_024) { Weight = 4, MinSize = 0, MaxSize = 30, PreferredSize = 25, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_032) { Weight = 5, MinSize = 0, MaxSize = 40, PreferredSize = 35, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_040) { Weight = 6, MinSize = 0, MaxSize = 45, PreferredSize = 40, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_048) { Weight = 7, MinSize = 0, MaxSize = 55, PreferredSize = 50, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_056) { Weight = 8, MinSize = 0, MaxSize = 65, PreferredSize = 60, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_064) { Weight = 9, MinSize = 0, MaxSize = 75, PreferredSize = 70, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_080) { Weight = 10, MinSize = 0, MaxSize = 95, PreferredSize = 90, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_096) { Weight = 11, MinSize = 0, MaxSize = 110, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_112) { Weight = 12, MinSize = 0, MaxSize = 125, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_128) { Weight = 13, MinSize = 0, MaxSize = 140, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.VORBIS_Q5) { Weight = 14, MinSize = 0, MaxSize = 175, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_160) { Weight = 14, MinSize = 0, MaxSize = 175, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_192) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.VORBIS_Q6) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.AAC_192) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.WMA) { Weight = 15, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.MP3_224) { Weight = 16, MinSize = 0, MaxSize = 245, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.VORBIS_Q7) { Weight = 17, MinSize = 0, MaxSize = 245, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.MP3_VBR_V2) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.MP3_256) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.VORBIS_Q8) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.AAC_256) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.MP3_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.AAC_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.MP3_320) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.VORBIS_Q9) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.AAC_320) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.VORBIS_Q10) { Weight = 21, MinSize = 0, MaxSize = 550, PreferredSize = 295, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.FLAC) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.ALAC) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.APE) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.WAVPACK) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.FLAC_24) { Weight = 23, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.ALAC_24) { Weight = 23, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.WAV) { Weight = 24, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupWeight = 8 } }; } diff --git a/src/NzbDrone.Core/Qualities/QualityDefinition.cs b/src/NzbDrone.Core/Qualities/QualityDefinition.cs index 6adb1bf41..5c60df7a5 100644 --- a/src/NzbDrone.Core/Qualities/QualityDefinition.cs +++ b/src/NzbDrone.Core/Qualities/QualityDefinition.cs @@ -14,6 +14,7 @@ namespace NzbDrone.Core.Qualities public double? MinSize { get; set; } public double? MaxSize { get; set; } + public double? PreferredSize { get; set; } public QualityDefinition() { diff --git a/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs b/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs index 0aea96a75..2dde9d4e6 100644 --- a/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs +++ b/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs @@ -121,6 +121,7 @@ namespace NzbDrone.Core.Qualities existing.MinSize = definition.MinSize; existing.MaxSize = definition.MaxSize; + existing.PreferredSize = definition.PreferredSize; existing.Title = message.ResetTitles ? definition.Title : existing.Title; updateList.Add(existing); diff --git a/src/NzbDrone.Core/Queue/EstimatedCompletionTimeComparer.cs b/src/NzbDrone.Core/Queue/DatetimeComparer.cs similarity index 90% rename from src/NzbDrone.Core/Queue/EstimatedCompletionTimeComparer.cs rename to src/NzbDrone.Core/Queue/DatetimeComparer.cs index e8c52e1ab..e851d5a5f 100644 --- a/src/NzbDrone.Core/Queue/EstimatedCompletionTimeComparer.cs +++ b/src/NzbDrone.Core/Queue/DatetimeComparer.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace NzbDrone.Core.Queue { - public class EstimatedCompletionTimeComparer : IComparer + public class DatetimeComparer : IComparer { public int Compare(DateTime? x, DateTime? y) { diff --git a/src/NzbDrone.Core/Queue/Queue.cs b/src/NzbDrone.Core/Queue/Queue.cs index e8e994b37..d05d03947 100644 --- a/src/NzbDrone.Core/Queue/Queue.cs +++ b/src/NzbDrone.Core/Queue/Queue.cs @@ -19,6 +19,7 @@ namespace NzbDrone.Core.Queue public decimal Sizeleft { get; set; } public TimeSpan? Timeleft { get; set; } public DateTime? EstimatedCompletionTime { get; set; } + public DateTime? Added { get; set; } public string Status { get; set; } public TrackedDownloadStatus? TrackedDownloadStatus { get; set; } public TrackedDownloadState? TrackedDownloadState { get; set; } @@ -27,6 +28,7 @@ namespace NzbDrone.Core.Queue public RemoteAlbum RemoteAlbum { get; set; } public DownloadProtocol Protocol { get; set; } public string DownloadClient { get; set; } + public bool DownloadClientHasPostImportCategory { get; set; } public string Indexer { get; set; } public string OutputPath { get; set; } public string ErrorMessage { get; set; } diff --git a/src/NzbDrone.Core/Queue/QueueService.cs b/src/NzbDrone.Core/Queue/QueueService.cs index 855a9371b..68c4389ba 100644 --- a/src/NzbDrone.Core/Queue/QueueService.cs +++ b/src/NzbDrone.Core/Queue/QueueService.cs @@ -89,7 +89,9 @@ namespace NzbDrone.Core.Queue DownloadClient = trackedDownload.DownloadItem.DownloadClientInfo.Name, Indexer = trackedDownload.Indexer, OutputPath = trackedDownload.DownloadItem.OutputPath.ToString(), - DownloadForced = downloadForced + DownloadForced = downloadForced, + Added = trackedDownload.Added, + DownloadClientHasPostImportCategory = trackedDownload.DownloadItem.DownloadClientInfo.HasPostImportCategory }; queue.Id = HashConverter.GetHashInt31($"trackedDownload-{trackedDownload.DownloadClient}-{trackedDownload.DownloadItem.DownloadId}-album{album?.Id ?? 0}"); diff --git a/src/NzbDrone.Core/Update/InstallUpdateService.cs b/src/NzbDrone.Core/Update/InstallUpdateService.cs index 0684fbf00..f4616f155 100644 --- a/src/NzbDrone.Core/Update/InstallUpdateService.cs +++ b/src/NzbDrone.Core/Update/InstallUpdateService.cs @@ -107,6 +107,11 @@ namespace NzbDrone.Core.Update var updateSandboxFolder = _appFolderInfo.GetUpdateSandboxFolder(); + if (_diskProvider.GetTotalSize(updateSandboxFolder) < 1.Gigabytes()) + { + _logger.Warn("Temporary location '{0}' has less than 1 GB free space, Lidarr may not be able to update itself.", updateSandboxFolder); + } + var packageDestination = Path.Combine(updateSandboxFolder, updatePackage.FileName); if (_diskProvider.FolderExists(updateSandboxFolder)) diff --git a/src/NzbDrone.Host/Bootstrap.cs b/src/NzbDrone.Host/Bootstrap.cs index 38828dc72..30dd1e627 100644 --- a/src/NzbDrone.Host/Bootstrap.cs +++ b/src/NzbDrone.Host/Bootstrap.cs @@ -8,6 +8,7 @@ using System.Security.Cryptography.X509Certificates; using System.Text; using DryIoc; using DryIoc.Microsoft.DependencyInjection; +using Lidarr.Http.ClientSchema; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -150,6 +151,8 @@ namespace NzbDrone.Host .AddNzbDroneLogger() .AddDatabase() .AddStartupContext(context); + + SchemaBuilder.Initialize(c); }) .ConfigureServices(services => { diff --git a/src/NzbDrone.Integration.Test/IntegrationTest.cs b/src/NzbDrone.Integration.Test/IntegrationTest.cs index 778082a27..811f269b0 100644 --- a/src/NzbDrone.Integration.Test/IntegrationTest.cs +++ b/src/NzbDrone.Integration.Test/IntegrationTest.cs @@ -1,5 +1,6 @@ +using System; +using System.Linq; using System.Threading; -using Lidarr.Http.ClientSchema; using NLog; using NUnit.Framework; using NzbDrone.Common.Extensions; @@ -50,17 +51,20 @@ namespace NzbDrone.Integration.Test // Make sure tasks have been initialized so the config put below doesn't cause errors WaitForCompletion(() => Tasks.All().SelectList(x => x.TaskName).Contains("RssSync"), 30000); - Indexers.Post(new Lidarr.Api.V1.Indexers.IndexerResource + var indexer = Indexers.Schema().FirstOrDefault(i => i.Implementation == nameof(Newznab)); + + if (indexer == null) { - EnableRss = false, - EnableInteractiveSearch = false, - EnableAutomaticSearch = false, - ConfigContract = nameof(NewznabSettings), - Implementation = nameof(Newznab), - Name = "NewznabTest", - Protocol = Core.Indexers.DownloadProtocol.Usenet, - Fields = SchemaBuilder.ToSchema(new NewznabSettings()) - }); + throw new NullReferenceException("Expected valid indexer schema, found null"); + } + + indexer.EnableRss = false; + indexer.EnableInteractiveSearch = false; + indexer.EnableAutomaticSearch = false; + indexer.ConfigContract = nameof(NewznabSettings); + indexer.Implementation = nameof(Newznab); + indexer.Name = "NewznabTest"; + indexer.Protocol = Core.Indexers.DownloadProtocol.Usenet; // Change Console Log Level to Debug so we get more details. var config = HostConfig.Get(1); diff --git a/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/MacOsVersionAdapterFixture.cs b/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/MacOsVersionAdapterFixture.cs index 8bc8c9668..c191fa153 100644 --- a/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/MacOsVersionAdapterFixture.cs +++ b/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/MacOsVersionAdapterFixture.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters versionName.FullName.Should().Be("macOS " + versionString); } - [TestCase] + [Test] public void should_detect_server() { var fileContent = File.ReadAllText(GetTestPath("Files/macOS/SystemVersion.plist")); @@ -63,7 +63,7 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters versionName.Name.Should().Be("macOS Server"); } - [TestCase] + [Test] public void should_return_null_if_folder_doesnt_exist() { Mocker.GetMock() diff --git a/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs b/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs index a1eb60a46..e42355819 100644 --- a/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs +++ b/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs @@ -29,6 +29,8 @@ namespace NzbDrone.Test.Common.AutoMoq AssemblyLoader.RegisterSQLiteResolver(); } + public IContainer Container => _container; + public virtual T Resolve() { var result = _container.Resolve();