mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-28 18:05:51 -04:00
Compare commits
68 Commits
v0.3.10.22
...
v0.3.14.23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2749479283 | ||
|
|
4cbafa76d8 | ||
|
|
73782cc233 | ||
|
|
de396fe9be | ||
|
|
71cb9e1dd7 | ||
|
|
ee5ed57fcc | ||
|
|
d20a049a5a | ||
|
|
a9f77ace37 | ||
|
|
0341a2ec26 | ||
|
|
d6796bbe1a | ||
|
|
9066f8558c | ||
|
|
c4e37528ee | ||
|
|
5937c952af | ||
|
|
0f4bd3c472 | ||
|
|
cf415e61de | ||
|
|
9865e92cea | ||
|
|
1cf956a9d9 | ||
|
|
8989c55c8c | ||
|
|
dc83e0127e | ||
|
|
34eb312426 | ||
|
|
9d5cdebdb2 | ||
|
|
a0ab224acd | ||
|
|
05aa35a54d | ||
|
|
ca7f8775f5 | ||
|
|
2a01e9b445 | ||
|
|
7d30c7d1ea | ||
|
|
50be87e5a4 | ||
|
|
0572d1ac80 | ||
|
|
d2240514d7 | ||
|
|
ad47dc032d | ||
|
|
6c6df7d7d9 | ||
|
|
2121204064 | ||
|
|
61004ea33f | ||
|
|
54c1c7862e | ||
|
|
43dfdc8bf5 | ||
|
|
0d1ae0ca4e | ||
|
|
9902889a30 | ||
|
|
04d7061030 | ||
|
|
fd201912a9 | ||
|
|
c412701a3d | ||
|
|
7451a66365 | ||
|
|
a6431fdb0b | ||
|
|
060b133f6d | ||
|
|
5ed13b942b | ||
|
|
89f3d8167b | ||
|
|
77b027374f | ||
|
|
650490abb2 | ||
|
|
7d2e215d61 | ||
|
|
65ff890c74 | ||
|
|
50c0b0dbaa | ||
|
|
d5f36d0144 | ||
|
|
fab7558bd4 | ||
|
|
3dc86b3a01 | ||
|
|
24ad6134e3 | ||
|
|
033f8c40af | ||
|
|
4c73a619eb | ||
|
|
3ca798e983 | ||
|
|
d9827fd6a6 | ||
|
|
f4f03a853f | ||
|
|
4f4e4bf2ca | ||
|
|
413a70a312 | ||
|
|
a8f2b91010 | ||
|
|
68a4ee6000 | ||
|
|
5196ce311b | ||
|
|
ae92b22727 | ||
|
|
0bccffef01 | ||
|
|
bca899b9c0 | ||
|
|
2bb576a94b |
@@ -9,13 +9,13 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '0.3.10'
|
||||
majorVersion: '0.3.14'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
readarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
||||
sentryOrg: 'servarr'
|
||||
sentryUrl: 'https://sentry.servarr.com'
|
||||
dotnetVersion: '6.0.413'
|
||||
dotnetVersion: '6.0.417'
|
||||
nodeVersion: '16.X'
|
||||
innoVersion: '6.2.0'
|
||||
windowsImage: 'windows-2022'
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.filterIcon {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.authorNavigationButtons {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
||||
@@ -6,6 +6,7 @@ interface CssExports {
|
||||
'authorUpButton': string;
|
||||
'contentContainer': string;
|
||||
'errorMessage': string;
|
||||
'filterIcon': string;
|
||||
'innerContentBody': string;
|
||||
'metadataMessage': string;
|
||||
'selectedTab': string;
|
||||
|
||||
@@ -239,9 +239,14 @@ class AuthorDetails extends Component {
|
||||
saveError,
|
||||
isDeleting,
|
||||
deleteError,
|
||||
statistics
|
||||
statistics = {}
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
bookFileCount = 0,
|
||||
totalBookCount = 0
|
||||
} = statistics;
|
||||
|
||||
const {
|
||||
isOrganizeModalOpen,
|
||||
isRetagModalOpen,
|
||||
@@ -435,7 +440,7 @@ class AuthorDetails extends Component {
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
>
|
||||
{translate('BooksTotal', [statistics.totalBookCount])}
|
||||
{translate('BooksTotal', [totalBookCount])}
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
@@ -463,7 +468,7 @@ class AuthorDetails extends Component {
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
>
|
||||
{translate('FilesTotal', [statistics.bookFileCount])}
|
||||
{translate('FilesTotal', [bookFileCount])}
|
||||
</Tab>
|
||||
|
||||
{
|
||||
|
||||
@@ -136,8 +136,9 @@
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 300;
|
||||
font-size: 30px;
|
||||
line-height: 50px;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 AuthorHistoryContentConnector from './AuthorHistoryContentConnector';
|
||||
import AuthorHistoryModalContent from './AuthorHistoryModalContent';
|
||||
|
||||
@@ -14,6 +15,7 @@ function AuthorHistoryModal(props) {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
size={sizes.EXTRA_LARGE}
|
||||
onModalClose={onModalClose}
|
||||
>
|
||||
<AuthorHistoryContentConnector
|
||||
|
||||
@@ -5,6 +5,7 @@ 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 translate from 'Utilities/String/translate';
|
||||
import AuthorHistoryTableContent from './AuthorHistoryTableContent';
|
||||
|
||||
class AuthorHistoryModalContent extends Component {
|
||||
@@ -20,7 +21,7 @@ class AuthorHistoryModalContent extends Component {
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
History
|
||||
{translate('History')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
@@ -31,7 +32,7 @@ class AuthorHistoryModalContent extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
Close
|
||||
{translate('Close')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.details,
|
||||
.actions {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'actions': string;
|
||||
'details': string;
|
||||
'sourceTitle': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
|
||||
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import HistoryDetailsConnector from 'Activity/History/Details/HistoryDetailsConnector';
|
||||
import HistoryEventTypeCell from 'Activity/History/HistoryEventTypeCell';
|
||||
import BookFormats from 'Book/BookFormats';
|
||||
import BookQuality from 'Book/BookQuality';
|
||||
import Icon from 'Components/Icon';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
@@ -11,6 +12,7 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './AuthorHistoryRow.css';
|
||||
|
||||
@@ -75,6 +77,8 @@ class AuthorHistoryRow extends Component {
|
||||
sourceTitle,
|
||||
quality,
|
||||
qualityCutoffNotMet,
|
||||
customFormats,
|
||||
customFormatScore,
|
||||
date,
|
||||
data,
|
||||
book
|
||||
@@ -106,11 +110,19 @@ class AuthorHistoryRow extends Component {
|
||||
/>
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell>
|
||||
<BookFormats formats={customFormats} />
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell>
|
||||
{formatCustomFormatScore(customFormatScore, customFormats.length)}
|
||||
</TableRowCell>
|
||||
|
||||
<RelativeDateCellConnector
|
||||
date={date}
|
||||
/>
|
||||
|
||||
<TableRowCell className={styles.details}>
|
||||
<TableRowCell className={styles.actions}>
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
@@ -127,14 +139,13 @@ class AuthorHistoryRow extends Component {
|
||||
}
|
||||
position={tooltipPositions.LEFT}
|
||||
/>
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
{
|
||||
eventType === 'grabbed' &&
|
||||
<IconButton
|
||||
title={translate('MarkAsFailed')}
|
||||
name={icons.REMOVE}
|
||||
size={14}
|
||||
onPress={this.onMarkAsFailedPress}
|
||||
/>
|
||||
}
|
||||
@@ -160,6 +171,8 @@ AuthorHistoryRow.propTypes = {
|
||||
sourceTitle: PropTypes.string.isRequired,
|
||||
quality: PropTypes.object.isRequired,
|
||||
qualityCutoffNotMet: PropTypes.bool.isRequired,
|
||||
customFormats: PropTypes.arrayOf(PropTypes.object),
|
||||
customFormatScore: PropTypes.number.isRequired,
|
||||
date: PropTypes.string.isRequired,
|
||||
data: PropTypes.object.isRequired,
|
||||
fullAuthor: PropTypes.bool.isRequired,
|
||||
|
||||
9
frontend/src/Author/History/AuthorHistoryTable.css
Normal file
9
frontend/src/Author/History/AuthorHistoryTable.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.container {
|
||||
border: 1px solid var(--borderColor);
|
||||
border-radius: 4px;
|
||||
background-color: var(--inputBackgroundColor);
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
7
frontend/src/Author/History/AuthorHistoryTable.css.d.ts
vendored
Normal file
7
frontend/src/Author/History/AuthorHistoryTable.css.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'container': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import AuthorHistoryContentConnector from 'Author/History/AuthorHistoryContentConnector';
|
||||
import AuthorHistoryTableContent from 'Author/History/AuthorHistoryTableContent';
|
||||
import styles from './AuthorHistoryTable.css';
|
||||
|
||||
function AuthorHistoryTable(props) {
|
||||
const {
|
||||
@@ -8,10 +9,12 @@ function AuthorHistoryTable(props) {
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<AuthorHistoryContentConnector
|
||||
component={AuthorHistoryTableContent}
|
||||
{...otherProps}
|
||||
/>
|
||||
<div className={styles.container}>
|
||||
<AuthorHistoryContentConnector
|
||||
component={AuthorHistoryTableContent}
|
||||
{...otherProps}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.blankpad {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 2em;
|
||||
}
|
||||
7
frontend/src/Author/History/AuthorHistoryTableContent.css.d.ts
vendored
Normal file
7
frontend/src/Author/History/AuthorHistoryTableContent.css.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'blankpad': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,12 +1,14 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import Icon from 'Components/Icon';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import AuthorHistoryRowConnector from './AuthorHistoryRowConnector';
|
||||
import styles from './AuthorHistoryTableContent.css';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@@ -15,32 +17,41 @@ const columns = [
|
||||
},
|
||||
{
|
||||
name: 'book',
|
||||
label: 'Book',
|
||||
label: () => translate('Book'),
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'sourceTitle',
|
||||
label: 'Source Title',
|
||||
label: () => translate( 'SourceTitle'),
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'quality',
|
||||
label: 'Quality',
|
||||
label: () => translate('Quality'),
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'customFormats',
|
||||
label: () => translate('CustomFormats'),
|
||||
isSortable: false,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'customFormatScore',
|
||||
label: React.createElement(Icon, {
|
||||
name: icons.SCORE,
|
||||
title: () => translate('CustomFormatScore')
|
||||
}),
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'date',
|
||||
label: 'Date',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'details',
|
||||
label: 'Details',
|
||||
label: () => translate('Date'),
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'actions',
|
||||
label: 'Actions',
|
||||
isVisible: true
|
||||
}
|
||||
];
|
||||
@@ -64,7 +75,7 @@ class AuthorHistoryTableContent extends Component {
|
||||
const hasItems = !!items.length;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{
|
||||
isFetching &&
|
||||
<LoadingIndicator />
|
||||
@@ -79,7 +90,7 @@ class AuthorHistoryTableContent extends Component {
|
||||
|
||||
{
|
||||
isPopulated && !hasItems && !error &&
|
||||
<div>
|
||||
<div className={styles.blankpad}>
|
||||
{translate('NoHistory')}
|
||||
</div>
|
||||
}
|
||||
@@ -103,7 +114,7 @@ class AuthorHistoryTableContent extends Component {
|
||||
</TableBody>
|
||||
</Table>
|
||||
}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, isMonitored, isCutoffNotMet) {
|
||||
const revision = quality.revision;
|
||||
@@ -28,6 +29,36 @@ function getTooltip(title, quality, size, isMonitored, isCutoffNotMet) {
|
||||
return title;
|
||||
}
|
||||
|
||||
function revisionLabel(className, quality, showRevision) {
|
||||
if (!showRevision) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (quality.revision.isRepack) {
|
||||
return (
|
||||
<Label
|
||||
className={className}
|
||||
kind={kinds.PRIMARY}
|
||||
title={translate('Repack')}
|
||||
>
|
||||
R
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
|
||||
if (quality.revision.version && quality.revision.version > 1) {
|
||||
return (
|
||||
<Label
|
||||
className={className}
|
||||
kind={kinds.PRIMARY}
|
||||
title={translate('Proper')}
|
||||
>
|
||||
P
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function BookQuality(props) {
|
||||
const {
|
||||
className,
|
||||
@@ -35,7 +66,8 @@ function BookQuality(props) {
|
||||
quality,
|
||||
size,
|
||||
isMonitored,
|
||||
isCutoffNotMet
|
||||
isCutoffNotMet,
|
||||
showRevision
|
||||
} = props;
|
||||
|
||||
let kind = kinds.DEFAULT;
|
||||
@@ -50,13 +82,15 @@ function BookQuality(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<Label
|
||||
className={className}
|
||||
kind={kind}
|
||||
title={getTooltip(title, quality, size, isMonitored, isCutoffNotMet)}
|
||||
>
|
||||
{quality.quality.name}
|
||||
</Label>
|
||||
<span>
|
||||
<Label
|
||||
className={className}
|
||||
kind={kind}
|
||||
title={getTooltip(title, quality, size, isMonitored, isCutoffNotMet)}
|
||||
>
|
||||
{quality.quality.name}
|
||||
</Label>{revisionLabel(className, quality, showRevision)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -66,12 +100,14 @@ BookQuality.propTypes = {
|
||||
quality: PropTypes.object.isRequired,
|
||||
size: PropTypes.number,
|
||||
isMonitored: PropTypes.bool,
|
||||
isCutoffNotMet: PropTypes.bool
|
||||
isCutoffNotMet: PropTypes.bool,
|
||||
showRevision: PropTypes.bool
|
||||
};
|
||||
|
||||
BookQuality.defaultProps = {
|
||||
title: '',
|
||||
isMonitored: true
|
||||
isMonitored: true,
|
||||
showRevision: false
|
||||
};
|
||||
|
||||
export default BookQuality;
|
||||
|
||||
@@ -99,9 +99,14 @@ class BookDetails extends Component {
|
||||
nextBook,
|
||||
isSearching,
|
||||
onRefreshPress,
|
||||
onSearchPress
|
||||
onSearchPress,
|
||||
statistics = {}
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
bookFileCount = 0
|
||||
} = statistics;
|
||||
|
||||
const {
|
||||
isOrganizeModalOpen,
|
||||
isRetagModalOpen,
|
||||
@@ -238,21 +243,21 @@ class BookDetails extends Component {
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
>
|
||||
History
|
||||
{translate('History')}
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
>
|
||||
Search
|
||||
{translate('Search')}
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
>
|
||||
Files
|
||||
{translate('FilesTotal', [bookFileCount])}
|
||||
</Tab>
|
||||
|
||||
{
|
||||
@@ -335,6 +340,7 @@ BookDetails.propTypes = {
|
||||
ratings: PropTypes.object.isRequired,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
links: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
statistics: PropTypes.object.isRequired,
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
isSaving: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -117,8 +117,9 @@
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 300;
|
||||
font-size: 30px;
|
||||
line-height: 50px;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,6 @@ class BookIndexRow extends Component {
|
||||
className={styles[name]}
|
||||
>
|
||||
{bookFileCount}
|
||||
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
9
frontend/src/BookFile/Editor/BookFileEditorTable.css
Normal file
9
frontend/src/BookFile/Editor/BookFileEditorTable.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.container {
|
||||
border: 1px solid var(--borderColor);
|
||||
border-radius: 4px;
|
||||
background-color: var(--inputBackgroundColor);
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
7
frontend/src/BookFile/Editor/BookFileEditorTable.css.d.ts
vendored
Normal file
7
frontend/src/BookFile/Editor/BookFileEditorTable.css.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'container': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import BookFileEditorTableContentConnector from './BookFileEditorTableContentConnector';
|
||||
import styles from './BookFileEditorTable.css';
|
||||
|
||||
function BookFileEditorTable(props) {
|
||||
const {
|
||||
@@ -7,9 +8,11 @@ function BookFileEditorTable(props) {
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<BookFileEditorTableContentConnector
|
||||
{...otherProps}
|
||||
/>
|
||||
<div className={styles.container}>
|
||||
<BookFileEditorTableContentConnector
|
||||
{...otherProps}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.filesTable {
|
||||
margin-bottom: 20px;
|
||||
padding-top: 15px;
|
||||
margin: 10px;
|
||||
padding-top: 5px;
|
||||
border: 1px solid var(--borderColor);
|
||||
border-top: 1px solid var(--borderColor);
|
||||
border-radius: 4px;
|
||||
@@ -13,9 +13,15 @@
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
margin-right: auto;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.selectInput {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.blankpad {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'actions': string;
|
||||
'blankpad': string;
|
||||
'filesTable': string;
|
||||
'selectInput': string;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import SelectInput from 'Components/Form/SelectInput';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
@@ -120,7 +121,7 @@ class BookFileEditorTableContent extends Component {
|
||||
const hasSelectedFiles = this.getSelectedIds().length > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{
|
||||
isFetching && !isPopulated ?
|
||||
<LoadingIndicator /> :
|
||||
@@ -129,13 +130,13 @@ class BookFileEditorTableContent extends Component {
|
||||
|
||||
{
|
||||
!isFetching && error ?
|
||||
<div>{error}</div> :
|
||||
<Alert kind={kinds.DANGER}>{error}</Alert> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
isPopulated && !items.length ?
|
||||
<div>
|
||||
<div className={styles.blankpad}>
|
||||
No book files to manage.
|
||||
</div> :
|
||||
null
|
||||
@@ -173,26 +174,30 @@ class BookFileEditorTableContent extends Component {
|
||||
null
|
||||
}
|
||||
|
||||
<div className={styles.actions}>
|
||||
<SpinnerButton
|
||||
kind={kinds.DANGER}
|
||||
isSpinning={isDeleting}
|
||||
isDisabled={!hasSelectedFiles}
|
||||
onPress={this.onDeletePress}
|
||||
>
|
||||
Delete
|
||||
</SpinnerButton>
|
||||
{
|
||||
isPopulated && items.length ? (
|
||||
<div className={styles.actions}>
|
||||
<SpinnerButton
|
||||
kind={kinds.DANGER}
|
||||
isSpinning={isDeleting}
|
||||
isDisabled={!hasSelectedFiles}
|
||||
onPress={this.onDeletePress}
|
||||
>
|
||||
{translate('Delete')}
|
||||
</SpinnerButton>
|
||||
|
||||
<div className={styles.selectInput}>
|
||||
<SelectInput
|
||||
name="quality"
|
||||
value="selectQuality"
|
||||
values={qualityOptions}
|
||||
isDisabled={!hasSelectedFiles}
|
||||
onChange={this.onQualityChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.selectInput}>
|
||||
<SelectInput
|
||||
name="quality"
|
||||
value="selectQuality"
|
||||
values={qualityOptions}
|
||||
isDisabled={!hasSelectedFiles}
|
||||
onChange={this.onQualityChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={isConfirmDeleteModalOpen}
|
||||
@@ -203,7 +208,7 @@ class BookFileEditorTableContent extends Component {
|
||||
onConfirm={this.onConfirmDelete}
|
||||
onCancel={this.onConfirmDeleteModalClose}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class CalendarConnector extends Component {
|
||||
gotoCalendarToday
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate);
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated', 'bookFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchCalendar();
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
.description {
|
||||
line-height: $lineHeight;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-left: 0;
|
||||
line-height: $lineHeight;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
||||
@@ -202,6 +202,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('bookFileDeleted');
|
||||
}
|
||||
|
||||
// Repopulate the page to handle recently imported file
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
"start_url": "../../../../",
|
||||
"theme_color": "#3a3f51",
|
||||
"background_color": "#3a3f51",
|
||||
"display": "standalone"
|
||||
"display": "minimal-ui"
|
||||
}
|
||||
|
||||
120
frontend/src/Diag/ConsoleApi.js
Normal file
120
frontend/src/Diag/ConsoleApi.js
Normal file
@@ -0,0 +1,120 @@
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
|
||||
// This file contains some helpers for power users in a browser console
|
||||
|
||||
let hasWarned = false;
|
||||
|
||||
function checkActivationWarning() {
|
||||
if (!hasWarned) {
|
||||
console.log('Activated ReadarrApi console helpers.');
|
||||
console.warn('Be warned: There will be no further confirmation checks.');
|
||||
hasWarned = true;
|
||||
}
|
||||
}
|
||||
|
||||
function attachAsyncActions(promise) {
|
||||
promise.filter = function() {
|
||||
const args = arguments;
|
||||
const res = this.then((d) => d.filter(...args));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
promise.map = function() {
|
||||
const args = arguments;
|
||||
const res = this.then((d) => d.map(...args));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
promise.all = function() {
|
||||
const res = this.then((d) => Promise.all(d));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
promise.forEach = function(action) {
|
||||
const res = this.then((d) => Promise.all(d.map(action)));
|
||||
attachAsyncActions(res);
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
class ResourceApi {
|
||||
constructor(api, url) {
|
||||
this.api = api;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
single(id) {
|
||||
return this.api.fetch(`${this.url}/${id}`);
|
||||
}
|
||||
|
||||
all() {
|
||||
return this.api.fetch(this.url);
|
||||
}
|
||||
|
||||
filter(pred) {
|
||||
return this.all().filter(pred);
|
||||
}
|
||||
|
||||
update(resource) {
|
||||
return this.api.fetch(`${this.url}/${resource.id}`, { method: 'PUT', data: resource });
|
||||
}
|
||||
|
||||
delete(resource) {
|
||||
if (typeof resource === 'object' && resource !== null && resource.id) {
|
||||
resource = resource.id;
|
||||
}
|
||||
|
||||
if (!resource || !Number.isInteger(resource)) {
|
||||
throw Error('Invalid resource', resource);
|
||||
}
|
||||
|
||||
return this.api.fetch(`${this.url}/${resource}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
fetch(url, options) {
|
||||
return this.api.fetch(`${this.url}${url}`, options);
|
||||
}
|
||||
}
|
||||
|
||||
class ConsoleApi {
|
||||
constructor() {
|
||||
this.author = new ResourceApi(this, '/author');
|
||||
}
|
||||
|
||||
resource(url) {
|
||||
return new ResourceApi(this, url);
|
||||
}
|
||||
|
||||
fetch(url, options) {
|
||||
checkActivationWarning();
|
||||
|
||||
options = options || {};
|
||||
|
||||
const req = {
|
||||
url,
|
||||
method: options.method || 'GET'
|
||||
};
|
||||
|
||||
if (options.data) {
|
||||
req.dataType = 'json';
|
||||
req.data = JSON.stringify(options.data);
|
||||
}
|
||||
|
||||
const promise = createAjaxRequest(req).request;
|
||||
|
||||
promise.fail((xhr) => {
|
||||
console.error(`Failed to fetch ${url}`, xhr);
|
||||
});
|
||||
|
||||
attachAsyncActions(promise);
|
||||
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
window.ReadarrApi = new ConsoleApi();
|
||||
|
||||
export default ConsoleApi;
|
||||
@@ -28,6 +28,10 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quality {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customFormatScore {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ class InteractiveSearchRow extends Component {
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.quality}>
|
||||
<BookQuality quality={quality} />
|
||||
<BookQuality quality={quality} showRevision={true} />
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.customFormatScore}>
|
||||
|
||||
@@ -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 {
|
||||
bulkDeleteDownloadClients,
|
||||
bulkEditDownloadClients,
|
||||
setManageDownloadClientsSort,
|
||||
} from 'Store/Actions/settingsActions';
|
||||
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
||||
import { SelectStateInputProps } from 'typings/props';
|
||||
@@ -80,6 +82,8 @@ const COLUMNS = [
|
||||
|
||||
interface ManageDownloadClientsModalContentProps {
|
||||
onModalClose(): void;
|
||||
sortKey?: string;
|
||||
sortDirection?: SortDirection;
|
||||
}
|
||||
|
||||
function ManageDownloadClientsModalContent(
|
||||
@@ -94,6 +98,8 @@ function ManageDownloadClientsModalContent(
|
||||
isSaving,
|
||||
error,
|
||||
items,
|
||||
sortKey,
|
||||
sortDirection,
|
||||
}: DownloadClientAppState = useSelector(
|
||||
createClientSideCollectionSelector('settings.downloadClients')
|
||||
);
|
||||
@@ -114,6 +120,13 @@ function ManageDownloadClientsModalContent(
|
||||
|
||||
const selectedCount = selectedIds.length;
|
||||
|
||||
const onSortPress = useCallback(
|
||||
(value: string) => {
|
||||
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}
|
||||
>
|
||||
<TableBody>
|
||||
{items.map((item) => {
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1 0 300px;
|
||||
@add-mixin truncate;
|
||||
|
||||
flex: 0 1 600px;
|
||||
}
|
||||
|
||||
.foreignId {
|
||||
flex: 0 0 200px;
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.foreignId {
|
||||
flex: 0 0 200px;
|
||||
.name {
|
||||
flex: 0 1 600px;
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1 0 300px;
|
||||
.foreignId {
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.addImportListExclusion {
|
||||
|
||||
@@ -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}
|
||||
>
|
||||
<TableBody>
|
||||
{items.map((item) => {
|
||||
|
||||
@@ -212,26 +212,24 @@ class MediaManagement extends Component {
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
settings.importExtraFiles.value &&
|
||||
settings.importExtraFiles.value ?
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>
|
||||
{translate('ImportExtraFiles')}
|
||||
</FormLabel>
|
||||
<FormLabel>{translate('ImportExtraFiles')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="extraFileExtensions"
|
||||
helpTexts={[
|
||||
translate('ExtraFileExtensionsHelpTexts1'),
|
||||
translate('ExtraFileExtensionsHelpTexts2')
|
||||
translate('ExtraFileExtensionsHelpText'),
|
||||
translate('ExtraFileExtensionsHelpTextsExamples')
|
||||
]}
|
||||
onChange={onInputChange}
|
||||
{...settings.extraFileExtensions}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormGroup> : null
|
||||
}
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
@@ -223,6 +223,13 @@ class UISettings extends Component {
|
||||
helpTextWarning={translate('UILanguageHelpTextWarning')}
|
||||
onChange={onInputChange}
|
||||
{...settings.uiLanguage}
|
||||
errors={
|
||||
languages.some((language) => language.key === settings.uiLanguage.value) ?
|
||||
settings.uiLanguage.errors :
|
||||
[
|
||||
...settings.uiLanguage.errors,
|
||||
{ message: translate('InvalidUILanguage') }
|
||||
]}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FieldSet>
|
||||
|
||||
@@ -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,9 @@ export default {
|
||||
isTesting: false,
|
||||
isTestingAll: false,
|
||||
items: [],
|
||||
pendingChanges: {}
|
||||
pendingChanges: {},
|
||||
sortKey: 'name',
|
||||
sortDirection: sortDirections.DESCENDING
|
||||
},
|
||||
|
||||
//
|
||||
@@ -121,7 +127,10 @@ export default {
|
||||
|
||||
return selectedSchema;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
[SET_MANAGE_DOWNLOAD_CLIENTS_SORT]: createSetClientSideCollectionSortReducer(section)
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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,9 @@ export default {
|
||||
isTesting: false,
|
||||
isTestingAll: false,
|
||||
items: [],
|
||||
pendingChanges: {}
|
||||
pendingChanges: {},
|
||||
sortKey: 'name',
|
||||
sortDirection: sortDirections.DESCENDING
|
||||
},
|
||||
|
||||
//
|
||||
@@ -151,7 +157,10 @@ export default {
|
||||
};
|
||||
|
||||
return updateSectionState(state, section, newState);
|
||||
}
|
||||
},
|
||||
|
||||
[SET_MANAGE_INDEXERS_SORT]: createSetClientSideCollectionSortReducer(section)
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -41,6 +41,14 @@ export const defaultState = {
|
||||
},
|
||||
|
||||
columns: [
|
||||
{
|
||||
name: 'select',
|
||||
columnLabel: 'Select',
|
||||
isSortable: false,
|
||||
isVisible: true,
|
||||
isModifiable: false,
|
||||
isHidden: true
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
label: 'Path',
|
||||
|
||||
@@ -158,7 +158,7 @@ export const defaultState = {
|
||||
bookFileCount: function(item) {
|
||||
const { statistics = {} } = item;
|
||||
|
||||
return statistics.bookCount || 0;
|
||||
return statistics.bookFileCount || 0;
|
||||
},
|
||||
|
||||
ratings: function(item) {
|
||||
|
||||
@@ -84,11 +84,6 @@ export const defaultState = {
|
||||
label: 'Source Title',
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'sourceTitle',
|
||||
label: 'Source Title',
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'customFormatScore',
|
||||
columnLabel: 'Custom Format Score',
|
||||
|
||||
@@ -5,6 +5,7 @@ import { sortDirections } from 'Helpers/Props';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||
import naturalExpansion from 'Utilities/String/naturalExpansion';
|
||||
import { set, update, updateItem } from './baseActions';
|
||||
import createFetchHandler from './Creators/createFetchHandler';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
@@ -17,6 +18,7 @@ export const section = 'interactiveImport';
|
||||
|
||||
const booksSection = `${section}.books`;
|
||||
const bookFilesSection = `${section}.bookFiles`;
|
||||
let abortCurrentFetchRequest = null;
|
||||
let abortCurrentRequest = null;
|
||||
let currentIds = [];
|
||||
|
||||
@@ -32,15 +34,17 @@ export const defaultState = {
|
||||
error: null,
|
||||
items: [],
|
||||
pendingChanges: {},
|
||||
sortKey: 'quality',
|
||||
sortDirection: sortDirections.DESCENDING,
|
||||
sortKey: 'path',
|
||||
sortDirection: sortDirections.ASCENDING,
|
||||
secondarySortKey: 'path',
|
||||
secondarySortDirection: sortDirections.ASCENDING,
|
||||
recentFolders: [],
|
||||
importMode: 'chooseImportMode',
|
||||
sortPredicates: {
|
||||
path: function(item, direction) {
|
||||
const path = item.path;
|
||||
|
||||
return path.toLowerCase();
|
||||
return naturalExpansion(path.toLowerCase());
|
||||
},
|
||||
|
||||
author: function(item, direction) {
|
||||
@@ -74,6 +78,8 @@ export const defaultState = {
|
||||
};
|
||||
|
||||
export const persistState = [
|
||||
'interactiveImport.sortKey',
|
||||
'interactiveImport.sortDirection',
|
||||
'interactiveImport.recentFolders',
|
||||
'interactiveImport.importMode'
|
||||
];
|
||||
@@ -122,6 +128,11 @@ export const clearInteractiveImportBookFiles = createAction(CLEAR_INTERACTIVE_IM
|
||||
// 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;
|
||||
@@ -129,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 }),
|
||||
|
||||
@@ -147,7 +160,11 @@ export const actionHandlers = handleThunks({
|
||||
]));
|
||||
});
|
||||
|
||||
promise.fail((xhr) => {
|
||||
request.fail((xhr) => {
|
||||
if (xhr.aborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(set({
|
||||
section,
|
||||
isFetching: false,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
@@ -9,8 +10,12 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import VirtualTable from 'Components/Table/VirtualTable';
|
||||
import VirtualTableRow from 'Components/Table/VirtualTableRow';
|
||||
import { align, icons, sortDirections } from 'Helpers/Props';
|
||||
import { align, icons, kinds, sortDirections } from 'Helpers/Props';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import UnmappedFilesTableHeader from './UnmappedFilesTableHeader';
|
||||
import UnmappedFilesTableRow from './UnmappedFilesTableRow';
|
||||
|
||||
@@ -23,10 +28,43 @@ class UnmappedFilesTable extends Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
scroller: null
|
||||
scroller: null,
|
||||
allSelected: false,
|
||||
allUnselected: false,
|
||||
lastToggled: null,
|
||||
selectedState: {}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setSelectedState();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const {
|
||||
items,
|
||||
sortKey,
|
||||
sortDirection,
|
||||
isDeleting,
|
||||
deleteError
|
||||
} = this.props;
|
||||
|
||||
if (sortKey !== prevProps.sortKey ||
|
||||
sortDirection !== prevProps.sortDirection ||
|
||||
hasDifferentItemsOrOrder(prevProps.items, items)
|
||||
) {
|
||||
this.setSelectedState();
|
||||
}
|
||||
|
||||
const hasFinishedDeleting = prevProps.isDeleting &&
|
||||
!isDeleting &&
|
||||
!deleteError;
|
||||
|
||||
if (hasFinishedDeleting) {
|
||||
this.onSelectAllChange({ value: false });
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Control
|
||||
|
||||
@@ -34,6 +72,68 @@ class UnmappedFilesTable extends Component {
|
||||
this.setState({ scroller: ref });
|
||||
};
|
||||
|
||||
getSelectedIds = () => {
|
||||
if (this.state.allUnselected) {
|
||||
return [];
|
||||
}
|
||||
return getSelectedIds(this.state.selectedState);
|
||||
};
|
||||
|
||||
setSelectedState() {
|
||||
const {
|
||||
items
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
selectedState
|
||||
} = this.state;
|
||||
|
||||
const newSelectedState = {};
|
||||
|
||||
items.forEach((file) => {
|
||||
const isItemSelected = selectedState[file.id];
|
||||
|
||||
if (isItemSelected) {
|
||||
newSelectedState[file.id] = isItemSelected;
|
||||
} else {
|
||||
newSelectedState[file.id] = false;
|
||||
}
|
||||
});
|
||||
|
||||
const selectedCount = getSelectedIds(newSelectedState).length;
|
||||
const newStateCount = Object.keys(newSelectedState).length;
|
||||
let isAllSelected = false;
|
||||
let isAllUnselected = false;
|
||||
|
||||
if (selectedCount === 0) {
|
||||
isAllUnselected = true;
|
||||
} else if (selectedCount === newStateCount) {
|
||||
isAllSelected = true;
|
||||
}
|
||||
|
||||
this.setState({ selectedState: newSelectedState, allSelected: isAllSelected, allUnselected: isAllUnselected });
|
||||
}
|
||||
|
||||
onSelectAllChange = ({ value }) => {
|
||||
this.setState(selectAll(this.state.selectedState, value));
|
||||
};
|
||||
|
||||
onSelectAllPress = () => {
|
||||
this.onSelectAllChange({ value: !this.state.allSelected });
|
||||
};
|
||||
|
||||
onSelectedChange = ({ id, value, shiftKey = false }) => {
|
||||
this.setState((state) => {
|
||||
return toggleSelected(state, this.props.items, id, value, shiftKey);
|
||||
});
|
||||
};
|
||||
|
||||
onDeleteUnmappedFilesPress = () => {
|
||||
const selectedIds = this.getSelectedIds();
|
||||
|
||||
this.props.deleteUnmappedFiles(selectedIds);
|
||||
};
|
||||
|
||||
rowRenderer = ({ key, rowIndex, style }) => {
|
||||
const {
|
||||
items,
|
||||
@@ -41,6 +141,10 @@ class UnmappedFilesTable extends Component {
|
||||
deleteUnmappedFile
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
selectedState
|
||||
} = this.state;
|
||||
|
||||
const item = items[rowIndex];
|
||||
|
||||
return (
|
||||
@@ -51,6 +155,8 @@ class UnmappedFilesTable extends Component {
|
||||
<UnmappedFilesTableRow
|
||||
key={item.id}
|
||||
columns={columns}
|
||||
isSelected={selectedState[item.id]}
|
||||
onSelectedChange={this.onSelectedChange}
|
||||
deleteUnmappedFile={deleteUnmappedFile}
|
||||
{...item}
|
||||
/>
|
||||
@@ -63,6 +169,7 @@ class UnmappedFilesTable extends Component {
|
||||
const {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
isDeleting,
|
||||
error,
|
||||
items,
|
||||
columns,
|
||||
@@ -72,13 +179,19 @@ class UnmappedFilesTable extends Component {
|
||||
onSortPress,
|
||||
isScanningFolders,
|
||||
onAddMissingAuthorsPress,
|
||||
deleteUnmappedFiles,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
scroller
|
||||
scroller,
|
||||
allSelected,
|
||||
allUnselected,
|
||||
selectedState
|
||||
} = this.state;
|
||||
|
||||
const selectedTrackFileIds = this.getSelectedIds();
|
||||
|
||||
return (
|
||||
<PageContent title={translate('UnmappedFiles')}>
|
||||
<PageToolbar>
|
||||
@@ -90,6 +203,13 @@ class UnmappedFilesTable extends Component {
|
||||
isSpinning={isScanningFolders}
|
||||
onPress={onAddMissingAuthorsPress}
|
||||
/>
|
||||
<PageToolbarButton
|
||||
label={translate('DeleteSelected')}
|
||||
iconName={icons.DELETE}
|
||||
isDisabled={selectedTrackFileIds.length === 0}
|
||||
isSpinning={isDeleting}
|
||||
onPress={this.onDeleteUnmappedFilesPress}
|
||||
/>
|
||||
</PageToolbarSection>
|
||||
|
||||
<PageToolbarSection alignContent={align.RIGHT}>
|
||||
@@ -117,9 +237,9 @@ class UnmappedFilesTable extends Component {
|
||||
|
||||
{
|
||||
isPopulated && !error && !items.length &&
|
||||
<div>
|
||||
<Alert kind={kinds.INFO}>
|
||||
Success! My work is done, all files on disk are matched to known books.
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
@@ -138,8 +258,12 @@ class UnmappedFilesTable extends Component {
|
||||
sortDirection={sortDirection}
|
||||
onTableOptionChange={onTableOptionChange}
|
||||
onSortPress={onSortPress}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={this.onSelectAllChange}
|
||||
/>
|
||||
}
|
||||
selectedState={selectedState}
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
/>
|
||||
@@ -153,6 +277,8 @@ class UnmappedFilesTable extends Component {
|
||||
UnmappedFilesTable.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
isDeleting: PropTypes.bool.isRequired,
|
||||
deleteError: PropTypes.object,
|
||||
error: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
@@ -161,6 +287,7 @@ UnmappedFilesTable.propTypes = {
|
||||
onTableOptionChange: PropTypes.func.isRequired,
|
||||
onSortPress: PropTypes.func.isRequired,
|
||||
deleteUnmappedFile: PropTypes.func.isRequired,
|
||||
deleteUnmappedFiles: PropTypes.func.isRequired,
|
||||
isScanningFolders: PropTypes.bool.isRequired,
|
||||
onAddMissingAuthorsPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import withCurrentPage from 'Components/withCurrentPage';
|
||||
import { deleteBookFile, fetchBookFiles, setBookFilesSort, setBookFilesTableOption } from 'Store/Actions/bookFileActions';
|
||||
import { deleteBookFile, deleteBookFiles, fetchBookFiles, setBookFilesSort, setBookFilesTableOption } from 'Store/Actions/bookFileActions';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
@@ -28,7 +28,9 @@ function createMapStateToProps() {
|
||||
items,
|
||||
...otherProps
|
||||
} = bookFiles;
|
||||
|
||||
const unmappedFiles = _.filter(items, { bookId: 0 });
|
||||
|
||||
return {
|
||||
items: unmappedFiles,
|
||||
...otherProps,
|
||||
@@ -57,6 +59,10 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatch(deleteBookFile({ id }));
|
||||
},
|
||||
|
||||
deleteUnmappedFiles(bookFileIds) {
|
||||
dispatch(deleteBookFiles({ bookFileIds }));
|
||||
},
|
||||
|
||||
onAddMissingAuthorsPress() {
|
||||
dispatch(executeCommand({
|
||||
name: commandNames.RESCAN_FOLDERS,
|
||||
@@ -106,7 +112,8 @@ UnmappedFilesTableConnector.propTypes = {
|
||||
onSortPress: PropTypes.func.isRequired,
|
||||
onTableOptionChange: PropTypes.func.isRequired,
|
||||
fetchUnmappedFiles: PropTypes.func.isRequired,
|
||||
deleteUnmappedFile: PropTypes.func.isRequired
|
||||
deleteUnmappedFile: PropTypes.func.isRequired,
|
||||
deleteUnmappedFiles: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default withCurrentPage(
|
||||
|
||||
@@ -4,6 +4,7 @@ import IconButton from 'Components/Link/IconButton';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
|
||||
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
|
||||
import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
|
||||
import { icons } from 'Helpers/Props';
|
||||
// import hasGrowableColumns from './hasGrowableColumns';
|
||||
import styles from './UnmappedFilesTableHeader.css';
|
||||
@@ -12,6 +13,9 @@ function UnmappedFilesTableHeader(props) {
|
||||
const {
|
||||
columns,
|
||||
onTableOptionChange,
|
||||
allSelected,
|
||||
allUnselected,
|
||||
onSelectAllChange,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
@@ -30,6 +34,17 @@ function UnmappedFilesTableHeader(props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name === 'select') {
|
||||
return (
|
||||
<VirtualTableSelectAllHeaderCell
|
||||
key={name}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'actions') {
|
||||
return (
|
||||
<VirtualTableHeaderCell
|
||||
@@ -71,6 +86,9 @@ function UnmappedFilesTableHeader(props) {
|
||||
|
||||
UnmappedFilesTableHeader.propTypes = {
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
allSelected: PropTypes.bool.isRequired,
|
||||
allUnselected: PropTypes.bool.isRequired,
|
||||
onSelectAllChange: PropTypes.func.isRequired,
|
||||
onTableOptionChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
||||
@@ -20,3 +20,9 @@
|
||||
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.checkInput {
|
||||
composes: input from '~Components/Form/CheckInput.css';
|
||||
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'actions': string;
|
||||
'checkInput': string;
|
||||
'dateAdded': string;
|
||||
'path': string;
|
||||
'quality': string;
|
||||
|
||||
@@ -6,6 +6,7 @@ import IconButton from 'Components/Link/IconButton';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
|
||||
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
@@ -69,7 +70,9 @@ class UnmappedFilesTableRow extends Component {
|
||||
size,
|
||||
dateAdded,
|
||||
quality,
|
||||
columns
|
||||
columns,
|
||||
isSelected,
|
||||
onSelectedChange
|
||||
} = this.props;
|
||||
|
||||
const folder = path.substring(0, Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')));
|
||||
@@ -93,6 +96,19 @@ class UnmappedFilesTableRow extends Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name === 'select') {
|
||||
return (
|
||||
<VirtualTableSelectCell
|
||||
inputClassName={styles.checkInput}
|
||||
id={id}
|
||||
key={name}
|
||||
isSelected={isSelected}
|
||||
isDisabled={false}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'path') {
|
||||
return (
|
||||
<VirtualTableRowCell
|
||||
@@ -208,6 +224,8 @@ UnmappedFilesTableRow.propTypes = {
|
||||
quality: PropTypes.object.isRequired,
|
||||
dateAdded: PropTypes.string.isRequired,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
onSelectedChange: PropTypes.func.isRequired,
|
||||
deleteUnmappedFile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
||||
11
frontend/src/Utilities/String/naturalExpansion.js
Normal file
11
frontend/src/Utilities/String/naturalExpansion.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const regex = /\d+/g;
|
||||
|
||||
function naturalExpansion(input) {
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return input.replace(regex, (n) => n.padStart(8, '0'));
|
||||
}
|
||||
|
||||
export default naturalExpansion;
|
||||
@@ -1,9 +1,11 @@
|
||||
const regex = /\b\w+/g;
|
||||
|
||||
function titleCase(input) {
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return input.replace(/\b\w+/g, (match) => {
|
||||
return input.replace(regex, (match) => {
|
||||
return match.charAt(0).toUpperCase() + match.substr(1).toLowerCase();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class CutoffUnmetConnector extends Component {
|
||||
gotoCutoffUnmetFirstPage
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated']);
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated', 'bookFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchCutoffUnmet();
|
||||
|
||||
@@ -50,7 +50,7 @@ class MissingConnector extends Component {
|
||||
gotoMissingFirstPage
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated']);
|
||||
registerPagePopulator(this.repopulate, ['bookFileUpdated', 'bookFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchMissing();
|
||||
|
||||
@@ -4,6 +4,8 @@ import { render } from 'react-dom';
|
||||
import createAppStore from 'Store/createAppStore';
|
||||
import App from './App/App';
|
||||
|
||||
import 'Diag/ConsoleApi';
|
||||
|
||||
export async function bootstrap() {
|
||||
const history = createBrowserHistory();
|
||||
const store = createAppStore(history);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"@fortawesome/free-regular-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@fortawesome/react-fontawesome": "0.2.0",
|
||||
"@microsoft/signalr": "6.0.21",
|
||||
"@microsoft/signalr": "6.0.25",
|
||||
"@sentry/browser": "7.51.2",
|
||||
"@sentry/integrations": "7.51.2",
|
||||
"@types/node": "18.16.16",
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
<PackageVersion Include="AutoFixture" Version="4.17.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" PrivateAssets="all" />
|
||||
<PackageVersion Include="Dapper" Version="2.0.123" />
|
||||
<PackageVersion Include="DryIoc.dll" Version="5.4.1" />
|
||||
<PackageVersion Include="DryIoc.dll" Version="5.4.3" />
|
||||
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||
<PackageVersion Include="Equ" Version="2.3.0" />
|
||||
<PackageVersion Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageVersion Include="Polly" Version="8.2.0" />
|
||||
<PackageVersion Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
|
||||
<PackageVersion Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
|
||||
<PackageVersion Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
|
||||
@@ -16,11 +17,11 @@
|
||||
<PackageVersion Include="ImpromptuInterface" Version="7.0.1" />
|
||||
<PackageVersion Include="LazyCache" Version="2.4.0" />
|
||||
<PackageVersion Include="Mailkit" Version="3.6.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.21" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.25" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
@@ -32,7 +33,7 @@
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.2.3" />
|
||||
<PackageVersion Include="NLog" Version="5.1.4" />
|
||||
<PackageVersion Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||
<PackageVersion Include="Npgsql" Version="7.0.4" />
|
||||
<PackageVersion Include="Npgsql" Version="7.0.6" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NunitXml.TestLogger" Version="3.0.117" />
|
||||
@@ -59,7 +60,7 @@
|
||||
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="6.0.8" />
|
||||
<PackageVersion Include="System.Text.Json" Version="6.0.9" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageVersion Include="TagLibSharp-Lidarr" Version="2.2.0.19" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Test.Common;
|
||||
using Readarr.Http.ClientSchema;
|
||||
|
||||
@@ -9,6 +12,16 @@ namespace NzbDrone.Api.Test.ClientSchemaTests
|
||||
[TestFixture]
|
||||
public class SchemaBuilderFixture : TestBase
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Mocker.GetMock<ILocalizationService>()
|
||||
.Setup(s => s.GetLocalizedString(It.IsAny<string>(), It.IsAny<Dictionary<string, object>>()))
|
||||
.Returns<string, Dictionary<string, object>>((s, d) => s);
|
||||
|
||||
SchemaBuilder.Initialize(Mocker.Container);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_field_for_every_property()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Books;
|
||||
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(_remoteBook, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_if_same_quality_non_proper_in_queue_and_download_propers_is_do_not_upgrade()
|
||||
{
|
||||
_remoteBook.ParsedBookInfo.Quality = new QualityModel(Quality.FLAC, new Revision(2));
|
||||
_author.QualityProfile.Value.Cutoff = _remoteBook.ParsedBookInfo.Quality.Quality.Id;
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(s => s.DownloadPropersAndRepacks)
|
||||
.Returns(ProperDownloadTypes.DoNotUpgrade);
|
||||
|
||||
var remoteBook = Builder<RemoteBook>.CreateNew()
|
||||
.With(r => r.Author = _author)
|
||||
.With(r => r.Books = new List<Book> { _book })
|
||||
.With(r => r.ParsedBookInfo = new ParsedBookInfo
|
||||
{
|
||||
Quality = new QualityModel(Quality.FLAC)
|
||||
})
|
||||
.With(r => r.Release = _releaseInfo)
|
||||
.With(r => r.CustomFormats = new List<CustomFormat>())
|
||||
.Build();
|
||||
|
||||
GivenQueue(new List<RemoteBook> { remoteBook });
|
||||
|
||||
Subject.IsSatisfiedBy(_remoteBook, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace NzbDrone.Core.Test.ImportListTests
|
||||
|
||||
_importListReports = new List<ImportListItemInfo> { importListItem1 };
|
||||
|
||||
var mockImportList = new Mock<IImportList>();
|
||||
|
||||
Mocker.GetMock<IFetchAndParseImportList>()
|
||||
.Setup(v => v.Fetch())
|
||||
.Returns(_importListReports);
|
||||
@@ -53,6 +55,10 @@ namespace NzbDrone.Core.Test.ImportListTests
|
||||
.Setup(v => v.Get(It.IsAny<int>()))
|
||||
.Returns(new ImportListDefinition { ShouldMonitor = ImportListMonitorType.SpecificBook });
|
||||
|
||||
Mocker.GetMock<IImportListFactory>()
|
||||
.Setup(v => v.AutomaticAddEnabled(It.IsAny<bool>()))
|
||||
.Returns(new List<IImportList> { mockImportList.Object });
|
||||
|
||||
Mocker.GetMock<IFetchAndParseImportList>()
|
||||
.Setup(v => v.Fetch())
|
||||
.Returns(_importListReports);
|
||||
@@ -322,5 +328,31 @@ namespace NzbDrone.Core.Test.ImportListTests
|
||||
t.First().AddOptions.BooksToMonitor.Count == expectedBooksMonitored &&
|
||||
t.First().Monitored == expectedAuthorMonitored), false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_fetch_if_no_lists_are_enabled()
|
||||
{
|
||||
Mocker.GetMock<IImportListFactory>()
|
||||
.Setup(v => v.AutomaticAddEnabled(It.IsAny<bool>()))
|
||||
.Returns(new List<IImportList>());
|
||||
|
||||
Subject.Execute(new ImportListSyncCommand());
|
||||
|
||||
Mocker.GetMock<IFetchAndParseImportList>()
|
||||
.Verify(v => v.Fetch(), Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_no_items_are_returned()
|
||||
{
|
||||
Mocker.GetMock<IFetchAndParseImportList>()
|
||||
.Setup(v => v.Fetch())
|
||||
.Returns(new List<ImportListItemInfo>());
|
||||
|
||||
Subject.Execute(new ImportListSyncCommand());
|
||||
|
||||
Mocker.GetMock<IImportListExclusionService>()
|
||||
.Verify(v => v.All(), Times.Never);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Localization
|
||||
{
|
||||
[TestFixture]
|
||||
public class LocalizationServiceFixture : CoreTest<LocalizationService>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>().Setup(m => m.UILanguage).Returns((int)Language.English);
|
||||
|
||||
Mocker.GetMock<IAppFolderInfo>().Setup(m => m.StartUpFolder).Returns(TestContext.CurrentContext.TestDirectory);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_string_in_dictionary_if_lang_exists_and_string_exists()
|
||||
{
|
||||
var localizedString = Subject.GetLocalizedString("UiLanguage");
|
||||
|
||||
localizedString.Should().Be("UI Language");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_string_in_french()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>().Setup(m => m.UILanguage).Returns((int)Language.French);
|
||||
|
||||
var localizedString = Subject.GetLocalizedString("UiLanguage");
|
||||
|
||||
localizedString.Should().Be("Langue de l'IU");
|
||||
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_string_in_default_dictionary_if_unknown_language_and_string_exists()
|
||||
{
|
||||
Mocker.GetMock<IConfigService>().Setup(m => m.UILanguage).Returns(0);
|
||||
var localizedString = Subject.GetLocalizedString("UiLanguage");
|
||||
|
||||
localizedString.Should().Be("UI Language");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_argument_if_string_doesnt_exists()
|
||||
{
|
||||
var localizedString = Subject.GetLocalizedString("badString");
|
||||
|
||||
localizedString.Should().Be("badString");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_argument_if_string_doesnt_exists_default_lang()
|
||||
{
|
||||
var localizedString = Subject.GetLocalizedString("badString");
|
||||
|
||||
localizedString.Should().Be("badString");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_empty_string_passed()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => Subject.GetLocalizedString(""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_null_string_passed()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => Subject.GetLocalizedString(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,15 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Books;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
@@ -166,7 +169,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_duration(string filename, string[] ignored)
|
||||
{
|
||||
var path = Path.Combine(_testdir, filename);
|
||||
@@ -177,7 +180,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_write_tags(string filename, string[] skipProperties)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -198,7 +201,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_audiotag_from_file_with_no_tags(string filename, string[] skipProperties)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -220,7 +223,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_parsedtrackinfo_from_file_with_no_tags(string filename, string[] skipProperties)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -235,7 +238,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_set_quality_and_mediainfo_for_corrupt_file(string filename, string[] skipProperties)
|
||||
{
|
||||
// use missing to simulate corrupt
|
||||
@@ -250,7 +253,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_read_file_with_only_title_tag(string filename, string[] ignored)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -270,7 +273,7 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestCaseFactory), "TestCases")]
|
||||
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
||||
public void should_remove_date_from_tags_when_not_in_metadata(string filename, string[] ignored)
|
||||
{
|
||||
GivenFileCopy(filename);
|
||||
@@ -365,6 +368,29 @@ namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
||||
var fileInfo = _diskProvider.GetFileInfo(file.Path);
|
||||
file.Modified.Should().Be(fileInfo.LastWriteTimeUtc);
|
||||
file.Size.Should().Be(fileInfo.Length);
|
||||
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<BookFileRetaggedEvent>()), Times.Once());
|
||||
}
|
||||
|
||||
[TestCase("nin.mp3")]
|
||||
public void write_tags_should_not_update_tags_if_already_updated(string filename)
|
||||
{
|
||||
Mocker.GetMock<IConfigService>()
|
||||
.Setup(x => x.ScrubAudioTags)
|
||||
.Returns(true);
|
||||
|
||||
GivenFileCopy(filename);
|
||||
|
||||
var file = GivenPopulatedTrackfile(0);
|
||||
|
||||
file.Path = _copiedFile;
|
||||
Subject.WriteTags(file, false, true);
|
||||
Subject.WriteTags(file, false, true);
|
||||
Subject.WriteTags(file, false, true);
|
||||
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<BookFileRetaggedEvent>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -13,6 +13,7 @@ using NzbDrone.Core.Test.Framework;
|
||||
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class BookInfoProxyFixture : CoreTest<BookInfoProxy>
|
||||
{
|
||||
private MetadataProfile _metadataProfile;
|
||||
|
||||
@@ -15,6 +15,7 @@ using NzbDrone.Test.Common;
|
||||
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Waiting for metadata to be back again", Until = "2023-12-31 00:00:00Z")]
|
||||
public class BookInfoProxySearchFixture : CoreTest<BookInfoProxy>
|
||||
{
|
||||
[SetUp]
|
||||
|
||||
@@ -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.CleanAuthorName().Should().Be("wordword" + word.ToLower());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_remove_a_from_middle_of_title()
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
@@ -83,4 +100,11 @@ namespace NzbDrone.Core.Annotations
|
||||
ApiKey,
|
||||
UserName
|
||||
}
|
||||
|
||||
public enum TokenField
|
||||
{
|
||||
Label,
|
||||
HelpText,
|
||||
HelpTextWarning
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Disk;
|
||||
@@ -218,11 +219,11 @@ namespace NzbDrone.Core.Books.Calibre
|
||||
double? seriesIndex = null;
|
||||
if (double.TryParse(serieslink?.Position, out var index))
|
||||
{
|
||||
_logger.Trace($"Parsed {serieslink?.Position} as {index}");
|
||||
_logger.Trace("Parsed '{0}' as '{1}'", serieslink.Position, index);
|
||||
seriesIndex = index;
|
||||
}
|
||||
|
||||
_logger.Trace($"Book: {book} Series: {series?.Title}, Position: {seriesIndex}");
|
||||
_logger.Trace("Book: {0} Series: {1}, Position: {2}", book, series?.Title, seriesIndex);
|
||||
|
||||
var cover = edition.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Cover);
|
||||
string image = null;
|
||||
@@ -275,7 +276,9 @@ namespace NzbDrone.Core.Books.Calibre
|
||||
|
||||
var updatedPath = GetOriginalFormat(updated.Formats);
|
||||
|
||||
if (updatedPath != null && updatedPath != file.Path)
|
||||
_logger.Trace("File path from Calibre: '{0}'", updatedPath);
|
||||
|
||||
if (updatedPath.IsNotNullOrWhiteSpace() && updatedPath != file.Path)
|
||||
{
|
||||
_rootFolderWatchingService.ReportFileSystemChangeBeginning(updatedPath);
|
||||
file.Path = updatedPath;
|
||||
@@ -304,6 +307,7 @@ namespace NzbDrone.Core.Books.Calibre
|
||||
|
||||
var request = builder.Build();
|
||||
request.SetContent(payload.ToJson());
|
||||
request.ContentSummary = payload.ToJson(Formatting.None);
|
||||
|
||||
_httpClient.Execute(request);
|
||||
}
|
||||
|
||||
@@ -322,6 +322,20 @@ namespace NzbDrone.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
public void MigrateConfigFile()
|
||||
{
|
||||
if (!File.Exists(_configFile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteOldValues()
|
||||
{
|
||||
var xDoc = LoadConfigFile();
|
||||
@@ -404,6 +418,7 @@ namespace NzbDrone.Core.Configuration
|
||||
|
||||
public void HandleAsync(ApplicationStartedEvent message)
|
||||
{
|
||||
MigrateConfigFile();
|
||||
EnsureDefaultConfigFile();
|
||||
DeleteOldValues();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public interface IConnectionStringFactory
|
||||
{
|
||||
string MainDbConnectionString { get; }
|
||||
string LogDbConnectionString { get; }
|
||||
string CacheDbConnectionString { get; }
|
||||
DatabaseConnectionInfo MainDbConnection { get; }
|
||||
DatabaseConnectionInfo LogDbConnection { get; }
|
||||
DatabaseConnectionInfo CacheDbConnection { get; }
|
||||
string GetDatabasePath(string connectionString);
|
||||
}
|
||||
|
||||
@@ -23,19 +23,19 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
_configFileProvider = configFileProvider;
|
||||
|
||||
MainDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
|
||||
MainDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
|
||||
GetConnectionString(appFolderInfo.GetDatabase());
|
||||
|
||||
LogDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
|
||||
LogDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
|
||||
GetConnectionString(appFolderInfo.GetLogDatabase());
|
||||
|
||||
CacheDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresCacheDb) :
|
||||
CacheDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresCacheDb) :
|
||||
GetConnectionString(appFolderInfo.GetCacheDatabase());
|
||||
}
|
||||
|
||||
public string MainDbConnectionString { get; private set; }
|
||||
public string LogDbConnectionString { get; private set; }
|
||||
public string CacheDbConnectionString { get; private set; }
|
||||
public DatabaseConnectionInfo MainDbConnection { get; private set; }
|
||||
public DatabaseConnectionInfo LogDbConnection { get; private set; }
|
||||
public DatabaseConnectionInfo CacheDbConnection { get; private set; }
|
||||
|
||||
public string GetDatabasePath(string connectionString)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Datastore
|
||||
return connectionBuilder.DataSource;
|
||||
}
|
||||
|
||||
private static string GetConnectionString(string dbPath)
|
||||
private static DatabaseConnectionInfo GetConnectionString(string dbPath)
|
||||
{
|
||||
var connectionBuilder = new SQLiteConnectionStringBuilder
|
||||
{
|
||||
@@ -62,21 +62,22 @@ namespace NzbDrone.Core.Datastore
|
||||
connectionBuilder.Add("Full FSync", true);
|
||||
}
|
||||
|
||||
return connectionBuilder.ConnectionString;
|
||||
return new DatabaseConnectionInfo(DatabaseType.SQLite, connectionBuilder.ConnectionString);
|
||||
}
|
||||
|
||||
private string GetPostgresConnectionString(string dbName)
|
||||
private DatabaseConnectionInfo GetPostgresConnectionString(string dbName)
|
||||
{
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder();
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder
|
||||
{
|
||||
Database = dbName,
|
||||
Host = _configFileProvider.PostgresHost,
|
||||
Username = _configFileProvider.PostgresUser,
|
||||
Password = _configFileProvider.PostgresPassword,
|
||||
Port = _configFileProvider.PostgresPort,
|
||||
Enlist = false
|
||||
};
|
||||
|
||||
connectionBuilder.Database = dbName;
|
||||
connectionBuilder.Host = _configFileProvider.PostgresHost;
|
||||
connectionBuilder.Username = _configFileProvider.PostgresUser;
|
||||
connectionBuilder.Password = _configFileProvider.PostgresPassword;
|
||||
connectionBuilder.Port = _configFileProvider.PostgresPort;
|
||||
connectionBuilder.Enlist = false;
|
||||
|
||||
return connectionBuilder.ConnectionString;
|
||||
return new DatabaseConnectionInfo(DatabaseType.PostgreSQL, connectionBuilder.ConnectionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
src/NzbDrone.Core/Datastore/DatabaseConnectionInfo.cs
Normal file
14
src/NzbDrone.Core/Datastore/DatabaseConnectionInfo.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class DatabaseConnectionInfo
|
||||
{
|
||||
public DatabaseConnectionInfo(DatabaseType databaseType, string connectionString)
|
||||
{
|
||||
DatabaseType = databaseType;
|
||||
ConnectionString = connectionString;
|
||||
}
|
||||
|
||||
public DatabaseType DatabaseType { get; internal set; }
|
||||
public string ConnectionString { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Data.Common;
|
||||
using System.Data.SQLite;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Npgsql;
|
||||
using NzbDrone.Common.Disk;
|
||||
@@ -59,30 +60,30 @@ namespace NzbDrone.Core.Datastore
|
||||
|
||||
public IDatabase Create(MigrationContext migrationContext)
|
||||
{
|
||||
string connectionString;
|
||||
DatabaseConnectionInfo connectionInfo;
|
||||
|
||||
switch (migrationContext.MigrationType)
|
||||
{
|
||||
case MigrationType.Main:
|
||||
{
|
||||
connectionString = _connectionStringFactory.MainDbConnectionString;
|
||||
CreateMain(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.MainDbConnection;
|
||||
CreateMain(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MigrationType.Log:
|
||||
{
|
||||
connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||
CreateLog(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.LogDbConnection;
|
||||
CreateLog(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MigrationType.Cache:
|
||||
{
|
||||
connectionString = _connectionStringFactory.CacheDbConnectionString;
|
||||
CreateLog(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.CacheDbConnection;
|
||||
CreateLog(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -97,14 +98,14 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
DbConnection conn;
|
||||
|
||||
if (connectionString.Contains(".db"))
|
||||
if (connectionInfo.DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
conn = SQLiteFactory.Instance.CreateConnection();
|
||||
conn.ConnectionString = connectionString;
|
||||
conn.ConnectionString = connectionInfo.ConnectionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn = new NpgsqlConnection(connectionString);
|
||||
conn = new NpgsqlConnection(connectionInfo.ConnectionString);
|
||||
}
|
||||
|
||||
conn.Open();
|
||||
@@ -114,12 +115,12 @@ namespace NzbDrone.Core.Datastore
|
||||
return db;
|
||||
}
|
||||
|
||||
private void CreateMain(string connectionString, MigrationContext migrationContext)
|
||||
private void CreateMain(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_restoreDatabaseService.Restore();
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
@@ -142,15 +143,17 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
Logger.Error(e, "Failure to connect to Postgres DB, {0} retries remaining", retryCount);
|
||||
|
||||
Thread.Sleep(5000);
|
||||
|
||||
try
|
||||
{
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (--retryCount > 0)
|
||||
{
|
||||
System.Threading.Thread.Sleep(5000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -169,11 +172,11 @@ namespace NzbDrone.Core.Datastore
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLog(string connectionString, MigrationContext migrationContext)
|
||||
private void CreateLog(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
@@ -193,7 +196,7 @@ namespace NzbDrone.Core.Datastore
|
||||
Logger.Error("Unable to recreate logging database automatically. It will need to be removed manually.");
|
||||
}
|
||||
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
{
|
||||
public interface IMigrationController
|
||||
{
|
||||
void Migrate(string connectionString, MigrationContext migrationContext);
|
||||
void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType);
|
||||
}
|
||||
|
||||
public class MigrationController : IMigrationController
|
||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
_migrationLoggerProvider = migrationLoggerProvider;
|
||||
}
|
||||
|
||||
public void Migrate(string connectionString, MigrationContext migrationContext)
|
||||
public void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
|
||||
ServiceProvider serviceProvider;
|
||||
|
||||
var db = connectionString.Contains(".db") ? "sqlite" : "postgres";
|
||||
var db = databaseType == DatabaseType.SQLite ? "sqlite" : "postgres";
|
||||
|
||||
serviceProvider = new ServiceCollection()
|
||||
.AddLogging(b => b.AddNLog())
|
||||
|
||||
@@ -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(remoteBook.ParsedBookInfo.Quality, subject.ParsedBookInfo.Quality))
|
||||
{
|
||||
if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
|
||||
{
|
||||
_logger.Debug("Auto downloading of propers is disabled");
|
||||
return Decision.Reject("Proper downloading is disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result.Where(t => t.IsNotNullOrWhiteSpace());
|
||||
}
|
||||
|
||||
public override string Name => "Flood";
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
{
|
||||
public enum QBittorrentContentLayout
|
||||
{
|
||||
Default = 0,
|
||||
Original = 1,
|
||||
Subfolder = 2
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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<HttpResponse> RetryStrategy => new ResiliencePipelineBuilder<HttpResponse>()
|
||||
.AddRetry(new RetryStrategyOptions<HttpResponse>
|
||||
{
|
||||
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<string> Download(RemoteBook remoteBook, IIndexer indexer);
|
||||
public abstract IEnumerable<DownloadClientItem> GetItems();
|
||||
|
||||
@@ -133,7 +133,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 ||
|
||||
|
||||
@@ -47,7 +47,9 @@ namespace NzbDrone.Core.Download
|
||||
var request = indexer?.GetDownloadRequest(url) ?? new HttpRequest(url);
|
||||
request.RateLimitKey = remoteBook?.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;
|
||||
|
||||
|
||||
@@ -368,6 +368,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, author, ex.Message);
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
_logger.Warn(ex, "Couldn't download image {0} for {1}. {2}", image.Url, author, ex.Message);
|
||||
|
||||
@@ -67,41 +67,51 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
private List<Book> SyncAll()
|
||||
{
|
||||
if (_importListFactory.AutomaticAddEnabled().Empty())
|
||||
{
|
||||
_logger.Debug("No import lists with automatic add enabled");
|
||||
|
||||
return new List<Book>();
|
||||
}
|
||||
|
||||
_logger.ProgressInfo("Starting Import List Sync");
|
||||
|
||||
var rssReleases = _listFetcherAndParser.Fetch();
|
||||
var listItems = _listFetcherAndParser.Fetch().ToList();
|
||||
|
||||
var reports = rssReleases.ToList();
|
||||
|
||||
return ProcessReports(reports);
|
||||
return ProcessListItems(listItems);
|
||||
}
|
||||
|
||||
private List<Book> SyncList(ImportListDefinition definition)
|
||||
{
|
||||
_logger.ProgressInfo(string.Format("Starting Import List Refresh for List {0}", definition.Name));
|
||||
_logger.ProgressInfo($"Starting Import List Refresh for List {definition.Name}");
|
||||
|
||||
var rssReleases = _listFetcherAndParser.FetchSingleList(definition);
|
||||
var listItems = _listFetcherAndParser.FetchSingleList(definition).ToList();
|
||||
|
||||
var reports = rssReleases.ToList();
|
||||
|
||||
return ProcessReports(reports);
|
||||
return ProcessListItems(listItems);
|
||||
}
|
||||
|
||||
private List<Book> ProcessReports(List<ImportListItemInfo> reports)
|
||||
private List<Book> ProcessListItems(List<ImportListItemInfo> items)
|
||||
{
|
||||
var processed = new List<Book>();
|
||||
var authorsToAdd = new List<Author>();
|
||||
var booksToAdd = new List<Book>();
|
||||
|
||||
_logger.ProgressInfo("Processing {0} list items", reports.Count);
|
||||
if (items.Count == 0)
|
||||
{
|
||||
_logger.ProgressInfo("No list items to process");
|
||||
|
||||
return new List<Book>();
|
||||
}
|
||||
|
||||
_logger.ProgressInfo("Processing {0} list items", items.Count);
|
||||
|
||||
var reportNumber = 1;
|
||||
|
||||
var listExclusions = _importListExclusionService.All();
|
||||
|
||||
foreach (var report in reports)
|
||||
foreach (var report in items)
|
||||
{
|
||||
_logger.ProgressTrace("Processing list item {0}/{1}", reportNumber, reports.Count);
|
||||
_logger.ProgressTrace("Processing list item {0}/{1}", reportNumber, items.Count);
|
||||
|
||||
reportNumber++;
|
||||
|
||||
@@ -130,7 +140,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
var addedAuthors = _addAuthorService.AddAuthors(authorsToAdd, false);
|
||||
var addedBooks = _addBookService.AddBooks(booksToAdd, false);
|
||||
|
||||
var message = string.Format($"Import List Sync Completed. Items found: {reports.Count}, Authors added: {authorsToAdd.Count}, Books added: {booksToAdd.Count}");
|
||||
var message = string.Format($"Import List Sync Completed. Items found: {items.Count}, Authors added: {authorsToAdd.Count}, Books added: {booksToAdd.Count}");
|
||||
|
||||
_logger.ProgressInfo(message);
|
||||
|
||||
@@ -364,7 +374,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
var existingAuthor = _authorService.FindById(report.AuthorGoodreadsId);
|
||||
|
||||
// Check to see if author excluded
|
||||
var excludedAuthor = listExclusions.Where(s => s.ForeignId == report.AuthorGoodreadsId).SingleOrDefault();
|
||||
var excludedAuthor = listExclusions.SingleOrDefault(s => s.ForeignId == report.AuthorGoodreadsId);
|
||||
|
||||
// Check to see if author in import
|
||||
var existingImportAuthor = authorsToAdd.Find(i => i.ForeignAuthorId == report.AuthorGoodreadsId);
|
||||
@@ -425,16 +435,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
public void Execute(ImportListSyncCommand message)
|
||||
{
|
||||
List<Book> processed;
|
||||
|
||||
if (message.DefinitionId.HasValue)
|
||||
{
|
||||
processed = SyncList(_importListFactory.Get(message.DefinitionId.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
processed = SyncAll();
|
||||
}
|
||||
var processed = message.DefinitionId.HasValue ? SyncList(_importListFactory.Get(message.DefinitionId.Value)) : SyncAll();
|
||||
|
||||
_eventAggregator.PublishEvent(new ImportListSyncCompleteEvent(processed));
|
||||
}
|
||||
|
||||
@@ -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("Usenet Crawler", GetSettings("https://www.usenet-crawler.com"));
|
||||
|
||||
@@ -85,16 +85,15 @@ namespace NzbDrone.Core.Instrumentation
|
||||
|
||||
log.Level = logEvent.Level.Name;
|
||||
|
||||
var connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||
var connectionInfo = _connectionStringFactory.LogDbConnection;
|
||||
|
||||
//TODO: Probably need more robust way to differentiate what's being used
|
||||
if (connectionString.Contains(".db"))
|
||||
if (connectionInfo.DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
WriteSqliteLog(log, connectionString);
|
||||
WriteSqliteLog(log, connectionInfo.ConnectionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePostgresLog(log, connectionString);
|
||||
WritePostgresLog(log, connectionInfo.ConnectionString);
|
||||
}
|
||||
}
|
||||
catch (SQLiteException ex)
|
||||
|
||||
@@ -216,8 +216,6 @@
|
||||
"FileManagement": "إدارة الملفات",
|
||||
"FileDateHelpText": "تغيير تاريخ الملف عند الاستيراد / إعادة الفحص",
|
||||
"FailedDownloadHandling": "فشل معالجة التنزيل",
|
||||
"ExtraFileExtensionsHelpTexts2": "أمثلة: \".sub أو .nfo\" أو \"sub، nfo\"",
|
||||
"ExtraFileExtensionsHelpTexts1": "قائمة مفصولة بفواصل بالملفات الإضافية المراد استيرادها (سيتم استيراد .nfo كـ .nfo-Orig)",
|
||||
"Exception": "استثناء",
|
||||
"ErrorLoadingPreviews": "خطأ في تحميل المعاينات",
|
||||
"ErrorLoadingContents": "خطأ في تحميل المحتويات",
|
||||
@@ -628,5 +626,7 @@
|
||||
"AddNew": "اضف جديد",
|
||||
"System": "النظام",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "يتم إخفاء جميع النتائج بواسطة عامل التصفية المطبق",
|
||||
"Backup": "دعم"
|
||||
"Backup": "دعم",
|
||||
"ExtraFileExtensionsHelpText": "قائمة مفصولة بفواصل بالملفات الإضافية المراد استيرادها (سيتم استيراد .nfo كـ .nfo-Orig)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "أمثلة: \".sub أو .nfo\" أو \"sub، nfo\""
|
||||
}
|
||||
|
||||
@@ -122,8 +122,6 @@
|
||||
"ErrorLoadingContents": "Грешка при зареждането на съдържанието",
|
||||
"ErrorLoadingPreviews": "Грешка при зареждането на визуализациите",
|
||||
"Exception": "Изключение",
|
||||
"ExtraFileExtensionsHelpTexts1": "Списък с допълнителни файлове за импортиране, разделени със запетая (.nfo ще бъде импортиран като .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Примери: '.sub, .nfo' или 'sub, nfo'",
|
||||
"FailedDownloadHandling": "Неуспешно обработване на изтеглянето",
|
||||
"FileDateHelpText": "Променете датата на файла при импортиране / пресканиране",
|
||||
"FileManagement": "Управление на файлове",
|
||||
@@ -628,5 +626,7 @@
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Всички резултати са скрити от приложения филтър",
|
||||
"Backup": "Архивиране",
|
||||
"MetadataProfiles": "Добави профил на метадата",
|
||||
"MetadataProfile": "Добави профил на метадата"
|
||||
"MetadataProfile": "Добави профил на метадата",
|
||||
"ExtraFileExtensionsHelpText": "Списък с допълнителни файлове за импортиране, разделени със запетая (.nfo ще бъде импортиран като .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "Примери: '.sub, .nfo' или 'sub, nfo'"
|
||||
}
|
||||
|
||||
@@ -326,7 +326,6 @@
|
||||
"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}",
|
||||
"Duration": "durada",
|
||||
"ExtraFileExtensionsHelpTexts1": "Llista separada per comes de fitxers addicionals per importar (.nfo s'importarà com a .nfo-orig)",
|
||||
"FileWasDeletedByViaUI": "El fitxer s'ha suprimit mitjançant la interfície d'usuari",
|
||||
"GeneralSettingsSummary": "Port, SSL, nom d'usuari/contrasenya, servidor intermediari, analítiques i actualitzacions",
|
||||
"GrabRelease": "Captura novetat",
|
||||
@@ -528,7 +527,6 @@
|
||||
"CutoffUnmet": "Tall no assolit",
|
||||
"DeleteDelayProfileMessageText": "Esteu segur que voleu suprimir aquest perfil de retard?",
|
||||
"DeleteImportListExclusionMessageText": "Esteu segur que voleu suprimir aquesta exclusió de la llista d'importació?",
|
||||
"ExtraFileExtensionsHelpTexts2": "Exemples: '.sub, .nfo' o 'sub,nfo'",
|
||||
"HasPendingChangesSaveChanges": "Desa els canvis",
|
||||
"ICalLink": "Enllaç iCal`",
|
||||
"IgnoredHelpText": "La publicació es rebutjarà si conté un o més dels termes (no distingeix entre majúscules i minúscules)",
|
||||
|
||||
@@ -80,19 +80,19 @@
|
||||
"DeleteDelayProfile": "Odstranění profilu zpoždění",
|
||||
"DeleteDelayProfileMessageText": "Opravdu chcete smazat tento profil zpoždění?",
|
||||
"DeleteDownloadClient": "Odstranění klienta pro stahování",
|
||||
"DeleteDownloadClientMessageText": "Opravdu chcete odstranit klienta pro stahování „{0}“?",
|
||||
"DeleteDownloadClientMessageText": "Opravdu chcete odstranit klienta pro stahování '{name}'?",
|
||||
"DeleteEmptyFolders": "Odstraňte prázdné složky",
|
||||
"DeleteEmptyFoldersHelpText": "Během skenování disku a při mazání filmových souborů odstraňte prázdné složky s filmy",
|
||||
"DeleteImportListExclusion": "Odstranit vyloučení seznamu importů",
|
||||
"DeleteImportListExclusionMessageText": "Opravdu chcete toto vyloučení importního seznamu smazat?",
|
||||
"DeleteImportListMessageText": "Opravdu chcete smazat seznam „{0}“?",
|
||||
"DeleteImportListMessageText": "Opravdu chcete smazat seznam '{name}'?",
|
||||
"DeleteIndexer": "Odstranit indexer",
|
||||
"DeleteIndexerMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteMetadataProfileMessageText": "Opravdu chcete smazat kvalitní profil {0}",
|
||||
"DeleteIndexerMessageText": "Opravdu chcete odstranit indexer '{name}'?",
|
||||
"DeleteMetadataProfileMessageText": "Opravdu chcete smazat profil metadat '{name}'?",
|
||||
"DeleteNotification": "Smazat oznámení",
|
||||
"DeleteNotificationMessageText": "Opravdu chcete smazat oznámení „{0}“?",
|
||||
"DeleteNotificationMessageText": "Opravdu chcete smazat oznámení '{name}'?",
|
||||
"DeleteQualityProfile": "Smažte profil kvality",
|
||||
"DeleteQualityProfileMessageText": "Opravdu chcete smazat kvalitní profil {0}",
|
||||
"DeleteQualityProfileMessageText": "Opravdu chcete smazat profil kvality '{name}'?",
|
||||
"DeleteReleaseProfile": "Smazat profil zpoždění",
|
||||
"DeleteReleaseProfileMessageText": "Opravdu chcete smazat tento profil zpoždění?",
|
||||
"DeleteSelectedBookFiles": "Odstranit vybrané filmové soubory",
|
||||
@@ -128,8 +128,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)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Příklady: „.sub, .nfo“ nebo „sub, nfo“",
|
||||
"FailedDownloadHandling": "Zpracování stahování se nezdařilo",
|
||||
"FileDateHelpText": "Změnit datum souboru při importu / opětovném skenování",
|
||||
"FileManagement": "Správa souborů",
|
||||
@@ -588,23 +586,23 @@
|
||||
"Required": "Požadované",
|
||||
"NoEventsFound": "Nebyly nalezeny žádné události",
|
||||
"RedownloadFailed": "Stažení se nezdařilo",
|
||||
"DeleteSelectedImportListsMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedImportListsMessageText": "Opravdu chcete smazat {count} vybraných seznamů k importu?",
|
||||
"DeleteSelectedIndexers": "Odstranit indexer",
|
||||
"ExistingTag": "Stávající značka",
|
||||
"ApplyTagsHelpTextHowToApplyAuthors": "Jak použít značky na vybrané filmy",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Opravdu chcete smazat {count} vybraných klientů pro stahování?",
|
||||
"No": "Ne",
|
||||
"NoChange": "Žádná změna",
|
||||
"RemovingTag": "Odebírání značky",
|
||||
"SetTags": "Nastavit značky",
|
||||
"ApplyTagsHelpTextAdd": "Přidat: Přidá značky k již existujícímu seznamu",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Jak použít značky na vybrané klienty pro stahování",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Jak použít značky na vybrané importní seznamy",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Jak použít značky na vybrané indexátory",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Jak použít značky na vybrané seznamy k importu",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Jak použít značky na vybrané indexery",
|
||||
"ApplyTagsHelpTextRemove": "Odebrat: Odebrat zadané značky",
|
||||
"ApplyTagsHelpTextReplace": "Nahradit: Nahradit značky zadanými značkami (zadáním žádné značky vymažete všechny značky)",
|
||||
"DeleteSelectedDownloadClients": "Odstranit staženého klienta",
|
||||
"DeleteSelectedIndexersMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"ApplyTagsHelpTextReplace": "Nahradit: Nahradit značky zadanými značkami (prázdné pole vymaže všechny značky)",
|
||||
"DeleteSelectedDownloadClients": "Odstranit klienta pro stahování",
|
||||
"DeleteSelectedIndexersMessageText": "Opravdu chcete smazat {count} vybraný(ch) indexer(ů)?",
|
||||
"Yes": "Ano",
|
||||
"NotificationStatusAllClientHealthCheckMessage": "Všechny seznamy nejsou k dispozici z důvodu selhání",
|
||||
"Small": "Malý",
|
||||
@@ -624,7 +622,7 @@
|
||||
"TotalSpace": "Celkový prostor",
|
||||
"ConnectionLost": "Spojení ztraceno",
|
||||
"ConnectionLostReconnect": "{appName} se pokusí připojit automaticky, nebo můžete kliknout na tlačítko znovunačtení níže.",
|
||||
"ConnectionLostToBackend": "{appName} ztratila spojení s backendem a pro obnovení funkčnosti bude třeba ji znovu načíst.",
|
||||
"ConnectionLostToBackend": "{appName} ztratil spojení s backendem a pro obnovení funkčnosti bude třebaho znovu načíst.",
|
||||
"Large": "Velký",
|
||||
"LastDuration": "lastDuration",
|
||||
"Ui": "UI",
|
||||
@@ -645,8 +643,8 @@
|
||||
"CloneCondition": "Klonovat podmínku",
|
||||
"Clone": "Klonovat",
|
||||
"ApiKeyValidationHealthCheckMessage": "Aktualizujte svůj klíč API tak, aby měl alespoň {0} znaků. Můžete to provést prostřednictvím nastavení nebo konfiguračního souboru",
|
||||
"ChooseImportMethod": "Vyberte mód importu",
|
||||
"CatalogNumber": "katalogové číslo",
|
||||
"ChooseImportMethod": "Vyberte způsob importu",
|
||||
"CatalogNumber": "Katalogové číslo",
|
||||
"Publisher": "Vydavatel",
|
||||
"StatusEndedContinuing": "Pokračující",
|
||||
"MetadataProfiles": "profil metadat",
|
||||
@@ -655,7 +653,7 @@
|
||||
"Label": "Etiketa",
|
||||
"Library": "Knihovna",
|
||||
"BypassIfAboveCustomFormatScore": "Obejít, pokud je vyšší než skóre vlastního formátu",
|
||||
"AppUpdatedVersion": "{appName} byla aktualizována na verzi `{version}`, abyste získali nejnovější změny, musíte znovu načíst {appName}.",
|
||||
"AppUpdatedVersion": "{appName} byl aktualizován na verzi `{version}`, abyste získali nejnovější změny, musíte znovu načíst {appName}",
|
||||
"BypassIfAboveCustomFormatScoreHelpText": "Povolit obcházení, pokud má vydání vyšší skóre, než je nakonfigurované minimální skóre vlastního formátu",
|
||||
"BypassIfHighestQuality": "Obejít v případě nejvyšší kvality",
|
||||
"Theme": "Motiv",
|
||||
@@ -666,5 +664,24 @@
|
||||
"CountDownloadClientsSelected": "{count} vybraných klientů ke stahování",
|
||||
"ImportListMissingRoot": "Chybí kořenový adresář pro import seznamu: {0}",
|
||||
"IndexerDownloadClientHelpText": "Zvolte, který klient pro stahování bude použit pro zachytávání z toho indexeru",
|
||||
"ImportListMultipleMissingRoots": "Několik kořenových adresářů chybí pro seznamy importu: {0}"
|
||||
"ImportListMultipleMissingRoots": "Několik kořenových adresářů chybí pro seznamy importu: {0}",
|
||||
"EditSelectedDownloadClients": "Upravit vybrané klienty pro stahování",
|
||||
"EditSelectedIndexers": "Upravit vybrané indexery",
|
||||
"EnableProfile": "Povolit profil",
|
||||
"DeleteImportList": "Smazat seznam importovaných položek",
|
||||
"AddNewItem": "Přidat novou položku",
|
||||
"AddMissing": "Přidat chybějící",
|
||||
"EditSelectedImportLists": "Upravit vybrané seznamy k importu",
|
||||
"DeleteSelectedImportLists": "Smazat seznam k importu",
|
||||
"Duration": "Trvání",
|
||||
"DeleteRootFolder": "Smazat kořenový adresář",
|
||||
"DownloadClientTagHelpText": "Tohoto klienta pro stahování používat pouze pro filmy s alespoň jednou odpovídající značkou. Pro použití se všemi filmy ponechte prázdné pole.",
|
||||
"AddedAuthorSettings": "Nastavení umělce přidáno",
|
||||
"DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "Klient stahování {downloadClientName} je nastaven na odstranění dokončených stahování. To může vést k tomu, že stahování budou z klienta odstraněna dříve, než je bude moci importovat {1}.",
|
||||
"IndexerTagsHelpText": "Tohoto klienta pro stahování používat pouze pro filmy s alespoň jednou odpovídající značkou. Pro použití se všemi filmy ponechte prázdné pole.",
|
||||
"BlocklistReleaseHelpText": "Zabránit {appName}u v opětovném sebrání tohoto vydání",
|
||||
"ListsSettingsSummary": "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“",
|
||||
"ImportLists": "Seznam k importu"
|
||||
}
|
||||
|
||||
@@ -123,8 +123,6 @@
|
||||
"ErrorLoadingContents": "Fejl ved indlæsning af indhold",
|
||||
"ErrorLoadingPreviews": "Fejl ved indlæsning af forhåndsvisning",
|
||||
"Exception": "Undtagelse",
|
||||
"ExtraFileExtensionsHelpTexts1": "Kommasepareret liste over ekstra filer, der skal importeres (.nfo importeres som .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Eksempler: '.sub, .nfo' eller 'sub, nfo'",
|
||||
"FailedDownloadHandling": "Fejlet Download Håndtering",
|
||||
"FileDateHelpText": "Skift fildato ved import / genscanning",
|
||||
"FileManagement": "Fil Håndtering",
|
||||
@@ -635,5 +633,7 @@
|
||||
"Large": "Stor",
|
||||
"Library": "Bibliotek",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Alle resultater skjules af det anvendte filter",
|
||||
"AddNewItem": "Tilføj Ny Genstand"
|
||||
"AddNewItem": "Tilføj Ny Genstand",
|
||||
"ExtraFileExtensionsHelpText": "Kommasepareret liste over ekstra filer, der skal importeres (.nfo importeres som .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "Eksempler: '.sub, .nfo' eller 'sub, nfo'"
|
||||
}
|
||||
|
||||
@@ -9,52 +9,52 @@
|
||||
"About": "Über",
|
||||
"AddListExclusion": "Listenausschluss hinzufügen",
|
||||
"AddingTag": "Tag hinzufügen",
|
||||
"AgeWhenGrabbed": "Alter (beim erfassen)",
|
||||
"AlreadyInYourLibrary": "Bereits in deiner Mediathek",
|
||||
"AgeWhenGrabbed": "Alter (zum Zeitpunkt der Entführung)",
|
||||
"AlreadyInYourLibrary": "Bereits in Ihrer Bibliothek",
|
||||
"AlternateTitles": "Alternative Titel",
|
||||
"Analytics": "Analytik",
|
||||
"Analytics": "Analysen",
|
||||
"AnalyticsEnabledHelpText": "Sende anonyme Nutzungs- und Fehlerinformationen an die Server von Readarr. Dazu gehören Informationen über Browser, welche Seiten der Readarr-Weboberfläche aufgerufen wurden, Fehlerberichte sowie Betriebssystem- und Laufzeitversion. Wir werden diese Informationen verwenden, um Funktionen und Fehlerbehebungen zu priorisieren.",
|
||||
"AnalyticsEnabledHelpTextWarning": "Erfordert einen Neustart",
|
||||
"AppDataDirectory": "AppData Ordner",
|
||||
"ApplyTags": "Tags setzen",
|
||||
"AppDataDirectory": "AppData-Verzeichnis",
|
||||
"ApplyTags": "Schlagworte anwenden",
|
||||
"Authentication": "Authentifizierung",
|
||||
"AuthenticationMethodHelpText": "Für den Zugriff auf Readarr sind Benutzername und Passwort erforderlich",
|
||||
"AuthorClickToChangeBook": "Klicken um den Film zu bearbeiten",
|
||||
"AutoRedownloadFailedHelpText": "Automatisch nach einem anderen Release suchen",
|
||||
"AutoRedownloadFailedHelpText": "Suchen Sie automatisch nach einer anderen Version und versuchen Sie, sie herunterzuladen",
|
||||
"AutoUnmonitorPreviouslyDownloadedBooksHelpText": "Auf der Festplatte gelöschte Filme auch automatisch in Radarr nicht mehr beobachten",
|
||||
"Automatic": "Automatisch",
|
||||
"BackupFolderHelpText": "Relative Pfade befinden sich unter Readarrs AppData Ordner",
|
||||
"BackupNow": "Jetzt sichern",
|
||||
"BackupRetentionHelpText": "Automatische Backups, die älter als die Aufbewahrungsfrist sind, werden automatisch gelöscht",
|
||||
"BackupRetentionHelpText": "Automatische Backups, die älter als der Aufbewahrungszeitraum sind, werden automatisch bereinigt",
|
||||
"Backups": "Sicherungen",
|
||||
"BindAddress": "Adresse binden",
|
||||
"BindAddressHelpText": "Gültige IPv4 Adresse oder \"*\" für alle Netzwerke",
|
||||
"BindAddressHelpText": "Gültige IP-Adresse, localhost oder „*“ für alle Schnittstellen",
|
||||
"BookIsDownloading": "Film ist am herunterladen",
|
||||
"BookIsDownloadingInterp": "Film lädt herunter - {0}% {1}",
|
||||
"Branch": "Git-Branch",
|
||||
"Branch": "Branch",
|
||||
"BypassProxyForLocalAddresses": "Proxy für lokale Adressen umgehen",
|
||||
"Calendar": "Kalender",
|
||||
"CalendarWeekColumnHeaderHelpText": "Wird in der Wochenansicht über jeder Spalte angezeigt",
|
||||
"Cancel": "Abbrechen",
|
||||
"CancelMessageText": "Diese laufende Aufgabe wirklich abbrechen?",
|
||||
"CertificateValidation": "Zertifikat Validierung",
|
||||
"CertificateValidationHelpText": "Ändere wie streng die Validierung der HTTPS-Zertifizierung ist. Ändern Sie nicht wenn Ihnen die Risiken nicht bewusst sind.",
|
||||
"ChangeFileDate": "Erstelldatum der Datei anpassen",
|
||||
"CertificateValidation": "Zertifikatsvalidierung",
|
||||
"CertificateValidationHelpText": "Ändern Sie, wie streng die Validierung der HTTPS-Zertifizierung ist. Ändern Sie nichts, es sei denn, Sie verstehen die Risiken.",
|
||||
"ChangeFileDate": "Ändern Sie das Dateidatum",
|
||||
"ChangeHasNotBeenSavedYet": "Änderung wurde noch nicht gespeichert",
|
||||
"ChmodFolder": "chmod Ordner",
|
||||
"ChmodFolderHelpText": "Oktal, wird beim Importieren/Umbenennen von Medienordnern und Dateien angewendet (ohne Ausführungsbits)",
|
||||
"ChmodFolderHelpText": "Oktal, angewendet beim Importieren/Umbenennen auf Medienordner und -dateien (ohne Ausführungsbits)",
|
||||
"ChmodFolderHelpTextWarning": "Dies funktioniert nur, wenn der Benutzer, der Readarr ausführt, der Eigentümer der Datei ist. Es ist besser, sicherzustellen, dass der Download-Client die Berechtigungen richtig setzt.",
|
||||
"ChownGroupHelpText": "Gruppenname oder gid. Verwenden Sie gid für entfernte Dateisysteme.",
|
||||
"ChownGroupHelpText": "Gruppenname oder GID. Verwenden Sie GID für Remote-Dateisysteme.",
|
||||
"ChownGroupHelpTextWarning": "Dies funktioniert nur, wenn der Benutzer, der Radarr ausführt, der Eigentümer der Datei ist. Es ist besser, sicherzustellen, dass der Download-Client die gleiche Gruppe wie Radarr verwendet.",
|
||||
"Clear": "Leeren",
|
||||
"ClickToChangeQuality": "Hier klicken um die Qualität zu ändern",
|
||||
"ClickToChangeQuality": "Klicken Sie, um die Qualität zu ändern",
|
||||
"ClientPriority": "Priorität",
|
||||
"CloneIndexer": "Indexer kopieren",
|
||||
"CloneProfile": "Profil kopieren",
|
||||
"CloneIndexer": "Indexer klonen",
|
||||
"CloneProfile": "Profil klonen",
|
||||
"Close": "Schließen",
|
||||
"Columns": "Spalten",
|
||||
"CompletedDownloadHandling": "Verarbeitung abgeschlossener Downloads",
|
||||
"ConnectSettings": "Eintellungen für Verbindungen",
|
||||
"CompletedDownloadHandling": "Download-Handhabung abgeschlossen",
|
||||
"ConnectSettings": "Verbindungseinstellungen",
|
||||
"Connections": "Verbindungen",
|
||||
"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 Readarr als Workaround verwenden.",
|
||||
@@ -68,24 +68,22 @@
|
||||
"DelayProfiles": "Verzögerungsprofile",
|
||||
"DelayingDownloadUntilInterp": "Download verzögern bis {0} um {1}",
|
||||
"Delete": "Löschen",
|
||||
"DeleteBackup": "Backup löschen",
|
||||
"DeleteBackupMessageText": "Backup '{0}' wirkich löschen?",
|
||||
"DeleteBackup": "Sicherung löschen",
|
||||
"DeleteBackupMessageText": "Sind Sie sicher, dass Sie die Sicherung „{name}“ löschen möchten?",
|
||||
"DeleteDelayProfile": "Verzögerungsprofil löschen",
|
||||
"DeleteDelayProfileMessageText": "Bist du sicher, dass du dieses Verzögerung-Profil löschen willst?",
|
||||
"DeleteDownloadClient": "Downloader löschen",
|
||||
"DeleteDownloadClientMessageText": "Downloader '{0}' wirklich löschen?",
|
||||
"DeleteDelayProfileMessageText": "Sind Sie sicher, dass Sie dieses Verzögerungsprofil löschen möchten?",
|
||||
"DeleteDownloadClient": "Download-Client löschen",
|
||||
"DeleteDownloadClientMessageText": "Sind Sie sicher, dass Sie den Download-Client „{name}“ löschen möchten?",
|
||||
"DeleteEmptyFolders": "Leere Ordner löschen",
|
||||
"DeleteEmptyFoldersHelpText": "Lösche leere Autorordner während des Scans oder wenn Buchdateien gelöscht werden",
|
||||
"DeleteImportListExclusion": "Importlisten Ausschluss löschen",
|
||||
"DeleteImportListExclusionMessageText": "Bist du sicher, dass du diesen Importlisten Ausschluss löschen willst?",
|
||||
"DeleteImportListMessageText": "Liste '{0}' wirklich löschen?",
|
||||
"DeleteImportListMessageText": "Sind Sie sicher, dass Sie die Liste „{name}“ löschen möchten?",
|
||||
"DeleteIndexer": "Indexer löschen",
|
||||
"DeleteIndexerMessageText": "Indexer '{0}' wirklich löschen?",
|
||||
"DeleteIndexerMessageText": "Sind Sie sicher, dass Sie den Indexer „{name}“ löschen möchten?",
|
||||
"DeleteMetadataProfileMessageText": "Qualitätsprofil '{0}' wirklich löschen?",
|
||||
"DeleteNotification": "Benachrichtigung löschen",
|
||||
"DeleteNotificationMessageText": "Benachrichtigung '{0}' wirklich löschen?",
|
||||
"DeleteQualityProfile": "Qualitätsdefinition löschen",
|
||||
"DeleteQualityProfileMessageText": "Qualitätsprofil '{0}' wirklich löschen?",
|
||||
"DeleteNotificationMessageText": "Sind Sie sicher, dass Sie die Benachrichtigung „{name}“ löschen möchten?",
|
||||
"DeleteQualityProfile": "Qualitätsprofil löschen",
|
||||
"DeleteQualityProfileMessageText": "Sind Sie sicher, dass Sie das Qualitätsprofil „{name}“ löschen möchten?",
|
||||
"DeleteReleaseProfile": "Release-Profil löschen",
|
||||
"DeleteReleaseProfileMessageText": "Bist du sicher, dass du dieses Release-Profil löschen willst?",
|
||||
"DeleteRootFolderMessageText": "Indexer '{0}' wirklich löschen?",
|
||||
@@ -94,11 +92,10 @@
|
||||
"DeleteTag": "Tag löschen",
|
||||
"DeleteTagMessageText": "Tag '{0}' wirklich löschen?",
|
||||
"DestinationPath": "Zielpfad",
|
||||
"DetailedProgressBar": "Erweiterter Fortschrittsbalken",
|
||||
"DetailedProgressBar": "Detaillierter Fortschrittsbalken",
|
||||
"DetailedProgressBarHelpText": "Text auf Fortschrittsbalken anzeigen",
|
||||
"DiskSpace": "Speicherplatz",
|
||||
"DiskSpace": "Festplattenplatz",
|
||||
"Docker": "Docker",
|
||||
"DownloadClient": "Downloader",
|
||||
"DownloadClientSettings": "Downloader Einstellungen",
|
||||
"DownloadClients": "Downloader",
|
||||
"DownloadFailedCheckDownloadClientForMoreDetails": "Download fehlgeschlagen: Prüfe den Downloader für mehr Details",
|
||||
@@ -122,8 +119,6 @@
|
||||
"ErrorLoadingContents": "Fehler beim laden der Inhalte",
|
||||
"ErrorLoadingPreviews": "Fehler beim laden der Vorschauen",
|
||||
"Exception": "Ausnahme",
|
||||
"ExtraFileExtensionsHelpTexts1": "Kommaseparierte Liste von Dateiendungen die als Extra Dateien importiert werden sollen ( .nfo wird in .nfo-orig umbenannt )",
|
||||
"ExtraFileExtensionsHelpTexts2": "Vorschläge: sub, nfo, srt, jpg",
|
||||
"FailedDownloadHandling": "Verarbeitung fehlgeschlagener Downloads",
|
||||
"FileDateHelpText": "Aktualisiere das Erstelldatum beim Import oder Re-Scan",
|
||||
"FileManagement": "Dateiverwaltung",
|
||||
@@ -240,32 +235,32 @@
|
||||
"PortNumber": "Port Nummer",
|
||||
"PosterSize": "Plakatgröße",
|
||||
"Profiles": "Profile",
|
||||
"Proper": "Proper",
|
||||
"Proper": "Korrekt",
|
||||
"PropersAndRepacks": "Propers und Repacks",
|
||||
"Protocol": "Protokoll",
|
||||
"ProtocolHelpText": "Wählen Sie, welche(s) Protokoll(e) verwendet werden soll(en) und welches Protokoll bei der Wahl zwischen ansonsten gleichwertigen Releases bevorzugt wird",
|
||||
"ProtocolHelpText": "Wählen Sie aus, welche(s) Protokoll(e) Sie verwenden möchten und welches Protokoll Sie bevorzugen, wenn Sie zwischen ansonsten gleichen Versionen wählen",
|
||||
"Proxy": "Proxy",
|
||||
"ProxyBypassFilterHelpText": "Verwende ',' als Trennzeichen und '*.' als Platzhalter für Subdomains",
|
||||
"ProxyPasswordHelpText": "Nur wenn ein Benutzername und Passwort erforderlich ist, muss es eingegeben werden. Ansonsten leer lassen.",
|
||||
"ProxyType": "Proxy Typ",
|
||||
"PublishedDate": "Veröffentlichungs Datum",
|
||||
"ProxyBypassFilterHelpText": "Verwenden Sie ',' als Trennzeichen und '*.' als Wildcard für Subdomains",
|
||||
"ProxyPasswordHelpText": "Sie müssen nur einen Benutzernamen und ein Passwort eingeben, wenn dies erforderlich ist. Andernfalls lassen Sie sie leer.",
|
||||
"ProxyType": "Proxy-Typ",
|
||||
"PublishedDate": "Veröffentlichungsdatum",
|
||||
"Quality": "Qualität",
|
||||
"QualityDefinitions": "Qualitätsdefinitionen",
|
||||
"QualityProfile": "Qualitätsprofil",
|
||||
"QualityProfiles": "Qualitätsprofile",
|
||||
"QualitySettings": "Qualitäts Einstellungen",
|
||||
"QualitySettings": "Qualitätseinstellungen",
|
||||
"Queue": "Warteschlange",
|
||||
"RSSSync": "RSS-Sync",
|
||||
"RSSSyncInterval": "RSS Synchronisierungs Intervall",
|
||||
"ReadTheWikiForMoreInformation": "Lese das Wiki für mehr Informationen",
|
||||
"ReadTheWikiForMoreInformation": "Lesen Sie das Wiki für weitere Informationen",
|
||||
"ReadarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Jeder Indexer der den Newznab-Standard verwendet oder unten aufgelistet ist wird untertützt.",
|
||||
"ReadarrTags": "Radarr Tags",
|
||||
"Real": "Echt",
|
||||
"Reason": "Grund",
|
||||
"Real": "Real",
|
||||
"Reason": "Begründung",
|
||||
"RecycleBinCleanupDaysHelpText": "Auf 0 setzen um das automatische leeren des Papierkorbs zu deaktivieren",
|
||||
"RecycleBinCleanupDaysHelpTextWarning": "Datien im Papierkorb die älter sind als der gewählte Wert, werden endgültig gelöscht",
|
||||
"RecycleBinHelpText": "Gelöschte Filmdateien werden hierher verschoben anstatt sie direkt endgültig zu löschen",
|
||||
"RecyclingBinCleanup": "Papierkorb aufräumen",
|
||||
"RecyclingBinCleanup": "Papierkorb leeren",
|
||||
"Redownload": "Nochmal herunterladen",
|
||||
"Refresh": "Aktualisieren",
|
||||
"RefreshInformationAndScanDisk": "Metadaten aktualisieren und Festplatte scannen",
|
||||
@@ -277,15 +272,15 @@
|
||||
"RemotePathMappings": "Remote-Pfadzuordnungen",
|
||||
"Remove": "Entfernen",
|
||||
"RemoveCompletedDownloadsHelpText": "Importierte Downloads aus dem Downloader Verlauf entfernen",
|
||||
"RemoveFailedDownloadsHelpText": "Fehlgeschlagene Downloads aus dem Downloader Verlauf entfernen",
|
||||
"RemoveFailedDownloadsHelpText": "Entfernen Sie fehlgeschlagene Downloads aus dem Download-Client-Verlauf",
|
||||
"RemoveFilter": "Filter entfernen",
|
||||
"RemoveFromDownloadClient": "Aus dem Downloader entfernen",
|
||||
"RemoveFromDownloadClient": "Vom Download-Client entfernen",
|
||||
"RemoveFromQueue": "Aus der Warteschlage entfernen",
|
||||
"RemoveHelpTextWarning": "Dies wird den Download und alle bereits heruntergeladenen Dateien aus dem Downloader entfernen.",
|
||||
"RemoveSelected": "Auswahl entfernen",
|
||||
"RemoveTagExistingTag": "Vorhandener Tag",
|
||||
"RemoveTagRemovingTag": "Tag entfernen",
|
||||
"RemovedFromTaskQueue": "Aus der Aufgabenwarteschlage entfernt",
|
||||
"RemovedFromTaskQueue": "Aus der Aufgabenwarteschlange entfernt",
|
||||
"RenameBooksHelpText": "Wenn das umbennen deaktiviert ist, wird der vorhandene Dateiname benutzt",
|
||||
"Reorder": "Neu sortieren",
|
||||
"ReplaceIllegalCharacters": "Sonderzeichen ersetzen",
|
||||
@@ -295,15 +290,14 @@
|
||||
"RescanAuthorFolderAfterRefresh": "Nach dem Aktualisieren den Autorordner neu scannen",
|
||||
"Reset": "Zurücksetzen",
|
||||
"ResetAPIKey": "API-Schlüssel zurücksetzen",
|
||||
"ResetAPIKeyMessageText": "Bist du sicher, dass du den API-Schlüssel zurücksetzen willst?",
|
||||
"Restart": "Neustarten",
|
||||
"ResetAPIKeyMessageText": "Sind Sie sicher, dass Sie Ihren API-Schlüssel zurücksetzen möchten?",
|
||||
"Restart": "Neu starten",
|
||||
"RestartNow": "Jetzt neustarten",
|
||||
"RestartReadarr": "Radarr Neustarten",
|
||||
"Restore": "Wiederherstellen",
|
||||
"RestoreBackup": "Backup einspielen",
|
||||
"RestoreBackup": "Sicherung wiederherstellen",
|
||||
"Result": "Ergebnis",
|
||||
"Retention": "Aufbewahrung ( Retention )",
|
||||
"RetentionHelpText": "Nur Usenet: Für eine umbegrenzte Aufbewahrung auf 0 setzen",
|
||||
"RetentionHelpText": "Nur Usenet: Auf Null setzen, um eine unbegrenzte Aufbewahrung festzulegen",
|
||||
"RetryingDownloadInterp": "Herunterladen nochmal versuchen {0} um {1}",
|
||||
"RootFolder": "Stammordner",
|
||||
"RootFolders": "Stammordner",
|
||||
@@ -318,16 +312,14 @@
|
||||
"SearchForMissing": "Suche fehlende",
|
||||
"SearchSelected": "Auswahl suchen",
|
||||
"Security": "Sicherheit",
|
||||
"SendAnonymousUsageData": "Anonyme Nutzungsdaten übertragen",
|
||||
"SendAnonymousUsageData": "Sende anonyme Nutzungsdaten",
|
||||
"SetPermissions": "Rechte setzen",
|
||||
"SetPermissionsLinuxHelpText": "Soll CHMOD ausgeführt werden wenn Datien importiert/umbenannt werden?",
|
||||
"SetPermissionsLinuxHelpTextWarning": "Ändere diese Einstellung nur, wenn du weißt was sie bewirken.",
|
||||
"SetPermissionsLinuxHelpTextWarning": "Wenn Sie nicht sicher sind, was diese Einstellungen bewirken, ändern Sie sie nicht.",
|
||||
"Settings": "Einstellungen",
|
||||
"ShortDateFormat": "Kurzes Datumsformat",
|
||||
"ShowCutoffUnmetIconHelpText": "Symbol zeigen wenn die Qualitätsschwelle noch nicht erreicht wurde",
|
||||
"ShowDateAdded": "Datum \"Hinzugefügt\" anzeigen",
|
||||
"ShowMonitored": "Beobachtete anzeigen",
|
||||
"ShowMonitoredHelpText": "Beobachtungsstatus unter dem Plakat anzeigen",
|
||||
"ShowDateAdded": "Datum der Hinzufügung anzeigen",
|
||||
"ShowPath": "Pfad anzeigen",
|
||||
"ShowQualityProfile": "Qualitätsdefinition anzeigen",
|
||||
"ShowQualityProfileHelpText": "Qualitätsprofil unter dem Plakat anzeigen",
|
||||
@@ -344,9 +336,9 @@
|
||||
"SorryThatBookCannotBeFound": "Schade, dieser Film kann nicht gefunden werden.",
|
||||
"Source": "Quelle",
|
||||
"SourcePath": "Quellpfad",
|
||||
"SslCertPasswordHelpText": "Passwort für die PFX Datei",
|
||||
"SslCertPasswordHelpText": "Passwort für die PFX-Datei",
|
||||
"SslCertPasswordHelpTextWarning": "Erfordert einen Neustart",
|
||||
"SslCertPathHelpText": "Pfad zur PFX Datei",
|
||||
"SslCertPathHelpText": "Pfad zur PFX-Datei",
|
||||
"SslCertPathHelpTextWarning": "Erfordert einen Neustart",
|
||||
"StandardBookFormat": "Standard Filmformat",
|
||||
"StartTypingOrSelectAPathBelow": "Eingeben oder unten auswählen",
|
||||
@@ -360,20 +352,18 @@
|
||||
"SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "Der Indexer unterstützt keine Suchen",
|
||||
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Wird für automatische Suchen genutzt die vom Benutzer oder von Radarr gestartet werden",
|
||||
"SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Wird für die manuelle Suche benutzt",
|
||||
"TagIsNotUsedAndCanBeDeleted": "Tag wird nicht benutzt und kann gelöscht werden",
|
||||
"Tags": "Tags",
|
||||
"Tasks": "Aufgaben",
|
||||
"TestAll": "Alle testen",
|
||||
"TestAllClients": "Alle testen",
|
||||
"TestAllIndexers": "Alle testen",
|
||||
"TestAllLists": "Alle testen",
|
||||
"TestAll": "Alle prüfen",
|
||||
"TestAllClients": "Prüfe alle Clients",
|
||||
"TestAllIndexers": "Prüfe alle Indexer",
|
||||
"TestAllLists": "Prüfe alle Listen",
|
||||
"ThisWillApplyToAllIndexersPleaseFollowTheRulesSetForthByThem": "Dies wird alle Indexer betreffen. Bitte folge deren Regeln",
|
||||
"TimeFormat": "Zeitformat",
|
||||
"Title": "Titel",
|
||||
"TorrentDelay": "Torrent Verzögerung",
|
||||
"TorrentDelayHelpText": "Verzögerung in Minuten bevor ein Torrent-Release erfasst wird",
|
||||
"TorrentDelay": "Torrent-Verzögerung",
|
||||
"TorrentDelayHelpText": "Verzögerung in Minuten, bevor ein Torrent herunterladen wird",
|
||||
"Torrents": "Torrents",
|
||||
"TotalFileSize": "Gesamte Dateigröße",
|
||||
"TotalFileSize": "Gesamtdateigröße",
|
||||
"UILanguage": "Oberflächen Sprache ( UI Language )",
|
||||
"UILanguageHelpText": "Sprache für die gesamte Oberfläche",
|
||||
"UILanguageHelpTextWarning": "Seite muss neugeladen werden",
|
||||
@@ -388,7 +378,7 @@
|
||||
"UnableToAddANewQualityProfilePleaseTryAgain": "Das neue Qualitätsprofil konnte nicht hinzugefügt werden, bitte erneut probieren.",
|
||||
"UnableToAddANewRemotePathMappingPleaseTryAgain": "Die neue entfernte Pfadzuordnung konnte nicht hinzugefügt werden, bitte erneut probieren.",
|
||||
"UnableToAddANewRootFolderPleaseTryAgain": "Das neue eigene Format konnte nicht hinzugefügt werden, bitte erneut probieren.",
|
||||
"UnableToLoadBackups": "Backups konnten nicht geladen werden",
|
||||
"UnableToLoadBackups": "Sicherungen können nicht geladen werden",
|
||||
"UnableToLoadDelayProfiles": "Verzögerungsprofile konnten nicht geladen werden",
|
||||
"UnableToLoadDownloadClientOptions": "Downloader Einstellungen konnten nicht geladen werden",
|
||||
"UnableToLoadDownloadClients": "Downloader konnten nicht geladen werden",
|
||||
@@ -407,35 +397,34 @@
|
||||
"UnableToLoadQualityProfiles": "Qualitätsprofile konnten nicht geladen werden",
|
||||
"UnableToLoadReleaseProfiles": "Verzögerungsprofile konnten nicht geladen werden",
|
||||
"UnableToLoadRemotePathMappings": "Entfernte Pfadzuordnungen konnten nicht geladen werden",
|
||||
"UnableToLoadRootFolders": "Stammordner konnten nicht geladen werden",
|
||||
"UnableToLoadRootFolders": "Stammordner können nicht geladen werden",
|
||||
"UnableToLoadTags": "Tags konnten nicht geladen werden",
|
||||
"UnableToLoadTheCalendar": "Kalender konnte nicht geladen werden",
|
||||
"UnableToLoadUISettings": "Oberflächen Einstellungen konnten nicht geladen werden",
|
||||
"Ungroup": "Gruppe entfernen",
|
||||
"Unmonitored": "Nicht beobachtet",
|
||||
"UnmonitoredHelpText": "Nicht beobachtete Filme im iCal-Feed einschließen",
|
||||
"UpdateAll": "Alle aktualisieren",
|
||||
"UpdateAutomaticallyHelpText": "Updates automatisch herunteraden und installieren. Es kann weiterhin unter \"System -> Updates\" ein manuelles Update angestoßen werden",
|
||||
"UpdateAutomaticallyHelpText": "Updates automatisch herunterladen und installieren. Sie können weiterhin über System: Updates installieren",
|
||||
"UpdateMechanismHelpText": "Readarr's Built-In Updater oder ein Script verwenden",
|
||||
"UpdateScriptPathHelpText": "Pfad zu einem benutzerdefinierten Skript, das ein extrahiertes Update-Paket übernimmt und den Rest des Update-Prozesses abwickelt",
|
||||
"Updates": "Updates",
|
||||
"Updates": "Aktualisierung",
|
||||
"UpgradeAllowedHelpText": "Wenn deaktiviert wird die Qualität nicht verbessert",
|
||||
"Uptime": "Laufzeit",
|
||||
"Uptime": "Betriebszeit",
|
||||
"UrlBaseHelpTextWarning": "Erfordert einen Neustart",
|
||||
"UseHardlinksInsteadOfCopy": "Hardlinks anstatt kopieren verwenden",
|
||||
"UseProxy": "Proxy benutzen",
|
||||
"UsenetDelay": "Usenet Verzögerung",
|
||||
"UsenetDelayHelpText": "Verzögerung in Minuten before ein Usenet-Release erfasst wird",
|
||||
"Username": "Benutzername",
|
||||
"UseHardlinksInsteadOfCopy": "Verwende Hardlinks statt Kopieren",
|
||||
"UseProxy": "Verwende Proxy",
|
||||
"UsenetDelay": "Usenet-Verzögerung",
|
||||
"UsenetDelayHelpText": "Verzögerung in Minuten, bevor Sie eine Veröffentlichung aus dem Usenet erhalten",
|
||||
"Username": "Nutzername",
|
||||
"UsingExternalUpdateMechanismBranchToUseToUpdateReadarr": "Branch zum updaten von Radarr",
|
||||
"UsingExternalUpdateMechanismBranchUsedByExternalUpdateMechanism": "Branch für den externen Updateablauf",
|
||||
"Version": "Version",
|
||||
"WeekColumnHeader": "Wochen Spalten Titel",
|
||||
"WeekColumnHeader": "Spaltenüberschrift „Woche“.",
|
||||
"Year": "Jahr",
|
||||
"YesCancel": "Ja, abbrechen",
|
||||
"YesCancel": "Ja Abbrechen",
|
||||
"BindAddressHelpTextWarning": "Erfordert einen Neustart",
|
||||
"LoadingBooksFailed": "Laden der Film-Dateien fehlgeschlagen",
|
||||
"ProxyUsernameHelpText": "Nur wenn ein Benutzername und Passwort erforderlich ist, muss es eingegeben werden. Ansonsten leer lassen.",
|
||||
"ProxyUsernameHelpText": "Sie müssen nur einen Benutzernamen und ein Passwort eingeben, wenn dies erforderlich ist. Andernfalls lassen Sie sie leer.",
|
||||
"SslPortHelpTextWarning": "Erfordert einen Neustart",
|
||||
"UnableToLoadMetadataProfiles": "Verzögerungsprofile konnten nicht geladen werden",
|
||||
"ApiKeyHelpTextWarning": "Erfordert einen Neustart",
|
||||
@@ -513,12 +502,12 @@
|
||||
"BlocklistRelease": "Release sperren",
|
||||
"RescanAfterRefreshHelpText": "Nach dem aktualisieren des Films, den Filmordner neu scannen",
|
||||
"ShowUnknownAuthorItems": "Unzugeordente Filmeinträge anzeigen",
|
||||
"SelectAll": "Alle wählen",
|
||||
"SelectAll": "Alles auswählen",
|
||||
"SelectedCountBooksSelectedInterp": "{0} Film(e) ausgewählt",
|
||||
"ThisCannotBeCancelled": "Nach dem Start kann dies nicht mehr abgebrochen werden ohne alle Indexer zu deaktivieren.",
|
||||
"UnselectAll": "Keine wählen",
|
||||
"UnselectAll": "Alle abwählen",
|
||||
"UpdateSelected": "Auswahl aktualisieren",
|
||||
"Wanted": "› Gesuchte",
|
||||
"Wanted": "Gesucht",
|
||||
"CreateEmptyAuthorFolders": "Leere Filmordner erstellen",
|
||||
"All": "Alle",
|
||||
"Country": "Land",
|
||||
@@ -582,7 +571,7 @@
|
||||
"TrackNumber": "Titelnummer",
|
||||
"ExistingBooks": "Existierende Bücher",
|
||||
"BookList": "Buchliste",
|
||||
"Continuing": "Fortsetzen",
|
||||
"Continuing": "Fortsetzung",
|
||||
"ExistingItems": "Existierende Artikel",
|
||||
"ForeignIdHelpText": "Die Musicbrainz Id des Autors/Buches die ausgeschlossen werden soll",
|
||||
"IndexersSettingsSummary": "Indexer- und Releasebeschränkungen",
|
||||
@@ -603,7 +592,7 @@
|
||||
"PreviewRetag": "Retag Vorschau",
|
||||
"EnabledHelpText": "Anhaken um Veröffentlichungsprofile zu aktivieren",
|
||||
"EntityName": "Objekt Name",
|
||||
"ShowBanners": "Zeige Banner",
|
||||
"ShowBanners": "Banner anzeigen",
|
||||
"ShowBannersHelpText": "Zeige Banner anstatt Namen",
|
||||
"ImportFailures": "Importfehler",
|
||||
"IndexerIdHelpText": "Angabe, welcher Indexer für das Profil gilt",
|
||||
@@ -630,7 +619,7 @@
|
||||
"StatusEndedContinuing": "Fortfahren",
|
||||
"UnableToLoadMetadataProviderSettings": "Einstellungen für Metadata Provider konnten nicht geladen werden",
|
||||
"UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "Aktualisierung innerhalb des Docker Containers ist deaktiviert. Aktualisieren Sie stattdessen das Container Image.",
|
||||
"Started": "gestartet",
|
||||
"Started": "Gestartet",
|
||||
"ContinuingNoAdditionalBooksAreExpected": "Keine weiteren Bücher werden erwartet",
|
||||
"DefaultMetadataProfileIdHelpText": "Standard Metadaten Profil für in diesem Ordner erkannte Autoren",
|
||||
"DefaultMonitorOptionHelpText": "Welche Bücher sollen beim erstmaligen Hinzufügen von Autoren, die in diesem Ordner gefunden wurden beobachtet werden",
|
||||
@@ -689,13 +678,13 @@
|
||||
"AllowFingerprintingHelpText": "Benutze Fingerabdrücke um die Genauigkeit der Buch Übereinstimmungen zu verbessern",
|
||||
"AllowFingerprintingHelpTextWarning": "Dies erfordert, dass Readarr Teile der Datei ließt, was dazu führt, dass Scans verlangsamt werden und eventuell hohe Schreib-/Netzwerkaktivitäten entstehen.",
|
||||
"AddImportListExclusionHelpText": "Verhindern, dass ein Buch zu Readarr durch Importlisten oder Aktualisierung des Autors hinzugefügt wird",
|
||||
"TimeLeft": "Restzeit",
|
||||
"TimeLeft": "Zeit übrig",
|
||||
"UpdateCheckStartupTranslocationMessage": "Update kann nicht installiert werden, da sich der Startordner '{0}' in einem App Translocation-Ordner befindet.",
|
||||
"PathHelpText": "Stammordner für die Musikbibliothek",
|
||||
"ProxyCheckBadRequestMessage": "Proxy konnte nicht getestet werden. StatusCode: {0}",
|
||||
"ProxyCheckFailedToTestMessage": "Proxy konnte nicht getestet werden: {0}",
|
||||
"Queued": "In der Warteschlange",
|
||||
"RefreshAndScan": "Aktualisieren",
|
||||
"Queued": "In Warteschlange",
|
||||
"RefreshAndScan": "Aktualisieren und scannen",
|
||||
"SettingsRemotePathMappingRemotePathHelpText": "Root-Pfad zum Verzeichnis, auf das der Download-Client zugreift",
|
||||
"Yesterday": "Gestern",
|
||||
"UpdateAvailable": "Neue Version verfügbar",
|
||||
@@ -750,20 +739,20 @@
|
||||
"IfYouDontAddAnImportListExclusionAndTheAuthorHasAMetadataProfileOtherThanNoneThenThisBookMayBeReaddedDuringTheNextAuthorRefresh": "Wenn kein Ausschluss der Import Liste hinzugefügt wird und der Künstler ein anderes Metadaten Profil als 'Keine' hat, kann es passieren, dass dieses Album bei der nächsten Aktualisierung des Künstlers erneut hinzugefügt wird.",
|
||||
"MissingFromDisk": "Radarr konnte die Datei nicht auf der Festplatte finden, daher wurde die Verknüpfung auf die Datei aus der Datenbank entfernt",
|
||||
"ProxyCheckResolveIpMessage": "Fehler beim Auflösen der IP-Adresse für den konfigurierten Proxy-Host {0}",
|
||||
"QualitySettingsSummary": "Qualitätgrößen und Bennenung",
|
||||
"QueueIsEmpty": "Warteschlange ist leer",
|
||||
"QualitySettingsSummary": "Qualitätsgrößen und Namensgebung",
|
||||
"QueueIsEmpty": "Die Warteschlange ist leer",
|
||||
"ReadarrSupportsMultipleListsForImportingBooksAndAuthorsIntoTheDatabase": "Lidarr unterstützt mehrere Listen für den Import von Alben und Künstlern in die Datenbank.",
|
||||
"TotalBookCountBooksTotalBookFileCountBooksWithFilesInterp": "{0} Titel insgesamt. {1} Titel mit Dateien.",
|
||||
"SearchFiltered": "Suche gefilterte",
|
||||
"AddList": "Liste hinzufügen",
|
||||
"InstanceName": "Instanzname",
|
||||
"InstanceNameHelpText": "Instanzname im Browser-Tab und für Syslog-Anwendungsname",
|
||||
"RestartRequiredHelpTextWarning": "Erfordert einen Neustart",
|
||||
"RestartRequiredHelpTextWarning": "Erfordert einen Neustart, damit die Aktion wirksam wird",
|
||||
"UseCalibreContentServer": "Calibre-Content-Server",
|
||||
"DataExistingBooks": "Beobachte Bücher die Dateien haben oder noch nicht veröffentlicht wurden",
|
||||
"DataFirstBook": "Beobachte das erste Buch. Alle anderen Bücher werden ignoriert",
|
||||
"DataMissingBooks": "Beobachte Bücher, die noch keine Dateien haben oder noch nicht veröffentlicht wurden",
|
||||
"Test": "Testen",
|
||||
"Test": "Prüfen",
|
||||
"DataNone": "Es werden keine Bücher beobachtet",
|
||||
"RenameFiles": "Dateien umbenennen",
|
||||
"LoadingEditionsFailed": "Das Laden der Ausgaben ist fehlgeschlagen",
|
||||
@@ -858,36 +847,36 @@
|
||||
"TagsHelpText": "Gilt für Autoren mit mindestens einem passenden Tag. Leer lassen, um auf alle Autoren anzuwenden",
|
||||
"TagsSettingsSummary": "Verwalten von Autoren-, Profil-, Beschränkungs- und Benachrichtigungs-Tags",
|
||||
"ApplicationURL": "Anwendungs-URL",
|
||||
"ApplicationUrlHelpText": "Die externe URL der Anwendung inklusive http(s)://, Port und URL-Basis",
|
||||
"ApplicationUrlHelpText": "Die externe URL dieser Anwendung, einschließlich http(s)://, Port und URL-Basis",
|
||||
"HardlinkCopyFiles": "Hardlink/Dateien kopieren",
|
||||
"MoveFiles": "Dateien verschieben",
|
||||
"OnApplicationUpdate": "Bei Anwendungsaktualisierung",
|
||||
"OnApplicationUpdateHelpText": "Bei Anwendungsaktualisierung",
|
||||
"ChooseImportMethod": "Wähle eine Importmethode",
|
||||
"ClickToChangeReleaseGroup": "Releasegruppe ändern",
|
||||
"ClickToChangeReleaseGroup": "Klicken Sie hier, um die Release-Gruppe zu ändern",
|
||||
"EnableRssHelpText": "Wird benutzt, wenn Radarr mittels RSS-Sync regelmäßig nach Releases schaut",
|
||||
"Theme": "Design",
|
||||
"ThemeHelpText": "Anwendungsdesign ändern, das 'Auto' Design passt sich an den Light/Dark-Mode deines Systems an. Inspiriert von Theme.Park",
|
||||
"ThemeHelpText": "Ändern Sie das Benutzeroberflächen-Design der Anwendung. Das „Auto“-Design verwendet Ihr Betriebssystemdesign, um den Hell- oder Dunkelmodus festzulegen. Inspiriert vom Theme.Park",
|
||||
"BypassIfHighestQuality": "Ignoriere wenn höchste Qualität",
|
||||
"MinimumCustomFormatScore": "Minimum der eigenen Formate Bewertungspunkte",
|
||||
"CustomFormatScore": "Eigenes Format Bewertungspunkte",
|
||||
"CloneCustomFormat": "Eigenes Format kopieren",
|
||||
"CloneCustomFormat": "Benutzerdefiniertes Format klonen",
|
||||
"Conditions": "Bedingungen",
|
||||
"CopyToClipboard": "In die Zwischenablage kopieren",
|
||||
"CustomFormat": "Eigenes Format",
|
||||
"CustomFormats": "Eigene Formate",
|
||||
"CustomFormat": "Benutzerdefiniertes Format",
|
||||
"CustomFormats": "Benutzerdefinierte Formate",
|
||||
"CutoffFormatScoreHelpText": "Sobald diese eigener Format Bewertung erreicht wird, werden keine neuen Releases erfasst",
|
||||
"DeleteFormatMessageText": "Bist du sicher, dass du das Formatierungstag {0} löschen willst?",
|
||||
"ExportCustomFormat": "Eigenes Format exportieren",
|
||||
"Formats": "Formate",
|
||||
"MinFormatScoreHelpText": "Mindester eigener Format Score bis zum Download",
|
||||
"NegateHelpText": "Wenn aktiviert wird das eigene Format nicht angewendet solange diese {0} Bedingung zutrifft.",
|
||||
"ResetDefinitionTitlesHelpText": "Definitionstitel und Werte zurücksetzen",
|
||||
"ResetDefinitionTitlesHelpText": "Definitionstitel und -werte zurücksetzen",
|
||||
"ResetDefinitions": "Definitionen zurücksetzen",
|
||||
"UpgradesAllowed": "Upgrades erlaubt",
|
||||
"CustomFormatSettings": "Einstellungen für eigene Formate",
|
||||
"DataFutureBooks": "Überwachung von Alben die noch nicht veröffentlicht wurden",
|
||||
"DeleteCustomFormat": "Eigenes Format löschen",
|
||||
"DeleteCustomFormat": "Benutzerdefiniertes Format löschen",
|
||||
"DeleteCustomFormatMessageText": "Bist du sicher, dass du das eigene Format '{0}' löschen willst?",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "In {Custom Formats} umbennenungs Format",
|
||||
"ResetTitles": "Titel zurücksetzen",
|
||||
@@ -899,21 +888,21 @@
|
||||
"RecycleBinUnableToWriteHealthCheck": "Schreiben in konfigurierten Papierkorbordner nicht möglich: {0}. Stelle sicher, dass dieser Pfad existiert und von dem Benutzer, der Radarr ausführt, beschreibbar ist",
|
||||
"HiddenClickToShow": "Versteckt, klicken zum anzeigen",
|
||||
"HideAdvanced": "Erweiterte Ansicht",
|
||||
"ShowAdvanced": "Einfache Ansicht",
|
||||
"ShownClickToHide": "Angezeigt, zum verstecken klicken",
|
||||
"ColonReplacement": "Doppelpunkt-Ersatz",
|
||||
"ShowAdvanced": "Erweitert anzeigen",
|
||||
"ShownClickToHide": "Angezeigt, zum Ausblenden klicken",
|
||||
"ColonReplacement": "Doppelpunktersatz",
|
||||
"ReplaceWithDash": "Mit Bindestrich ersetzen",
|
||||
"ReplaceWithSpaceDash": "Mit Leerzeichen Bindestrich ersetzen",
|
||||
"ReplaceWithSpaceDashSpace": "Mit Leerzeichen Bindestrich Leerzeichen ersetzen",
|
||||
"ApiKeyValidationHealthCheckMessage": "Bitte den API Schlüssel korrigieren, dieser muss mindestens {0} Zeichen lang sein. Die Änderung kann über die Einstellungen oder die Konfigurationsdatei erfolgen",
|
||||
"ThereWasAnErrorLoadingThisItem": "Beim Laden des Eintrags ist ein Fehler aufgetreten",
|
||||
"ThereWasAnErrorLoadingThisPage": "Beim Laden der Seite ist ein Fehler aufgetreten",
|
||||
"DeleteRemotePathMapping": "Entfernte Pfadzuordnung löschen",
|
||||
"DeleteRemotePathMappingMessageText": "Bist du sicher, dass du das diese entfernte Pfadzuordnung löschen willst?",
|
||||
"DeleteRemotePathMapping": "Remote-Pfad-Zuordnung löschen",
|
||||
"DeleteRemotePathMappingMessageText": "Sind Sie sicher, dass Sie diese Remote-Pfadzuordnung löschen möchten?",
|
||||
"CloneCondition": "Bedingung klonen",
|
||||
"DeleteCondition": "Bedingung löschen",
|
||||
"RemoveSelectedItemBlocklistMessageText": "Bist du sicher, dass du die ausgewählten Einträge aus der Sperrliste entfernen willst?",
|
||||
"ResetQualityDefinitionsMessageText": "Bist du sicher, dass du die Qualitätsdefinitionen zurücksetzen willst?",
|
||||
"ResetQualityDefinitionsMessageText": "Sind Sie sicher, dass Sie Qualitätsdefinitionen zurücksetzen möchten?",
|
||||
"RemoveSelectedItemQueueMessageText": "Bist du sicher, dass du ein Eintrag aus der Warteschlange entfernen willst?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Bist du sicher, dass du {0} Einträge aus der Warteschlange entfernen willst?",
|
||||
"ListRefreshInterval": "Listen Aktualisierungsintervall",
|
||||
@@ -921,7 +910,7 @@
|
||||
"ApplyTagsHelpTextHowToApplyAuthors": "Wie werden Tags zu ausgewählten Indexern zugeteilt",
|
||||
"DeleteSelectedImportLists": "Lösche Einspiel Liste",
|
||||
"DownloadClientTagHelpText": "Benutze den Indexer nur für Filme mit mindesens einen zutreffenden Tag. Leer lassen für alle Filme.",
|
||||
"DeleteSelectedIndexersMessageText": "Indexer '{0}' wirklich löschen?",
|
||||
"DeleteSelectedIndexersMessageText": "Sind Sie sicher, dass Sie {count} ausgewählte(n) Indexer löschen möchten?",
|
||||
"EditSelectedDownloadClients": "Ausgewählte Download Clienten bearbeiten",
|
||||
"Implementation": "Integration",
|
||||
"NoEventsFound": "Keine Events gefunden",
|
||||
@@ -938,24 +927,24 @@
|
||||
"Negated": "Negiert",
|
||||
"ResetQualityDefinitions": "Qualitätsdefinitionen zurücksetzen",
|
||||
"RemoveSelectedItem": "Entferne ausgewählten Eintrag",
|
||||
"RemoveSelectedItems": "Entferne ausgewählte Einträge",
|
||||
"RemoveSelectedItems": "Markierte Einträge löschen",
|
||||
"Required": "Erforderlich",
|
||||
"RedownloadFailed": "Download fehlgeschlagen",
|
||||
"RemoveFailed": "Entfernen fehlgeschlagen",
|
||||
"RemoveFailed": "Entferne fehlgeschlagene",
|
||||
"RemoveCompleted": "Abgeschlossene entfernen",
|
||||
"ApplyChanges": "Änderungen anwenden",
|
||||
"ApplyTagsHelpTextAdd": "Hinzufügen: Füge neu Tags zu den existierenden Tags hinzu",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Wie werden Tags zu ausgewählten Filmen zugeteilt",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Wie werden Tags zu ausgewählten Indexern zugeteilt",
|
||||
"ApplyTagsHelpTextAdd": "Hinzufügen: Fügen Sie die Tags der vorhandenen Tag-Liste hinzu",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "So wenden Sie Tags auf die ausgewählten Importlisten an",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "So wenden Sie Tags auf die ausgewählten Indexer an",
|
||||
"AutomaticAdd": "Automatisch hinzufügen",
|
||||
"ApplyTagsHelpTextRemove": "Entfernen: Eingegebene Tags entfernen",
|
||||
"ApplyTagsHelpTextReplace": "Ersetzen: Nur eingegebene Tags übernehmen und vorhandene entfernen( keine Tags eingeben um alle zu entfernen )",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Wie werden Tags zu ausgewählten Filmen zugeteilt",
|
||||
"ApplyTagsHelpTextRemove": "Entfernen: Die eingegebenen Tags entfernen",
|
||||
"ApplyTagsHelpTextReplace": "Ersetzen: Ersetzen Sie die Tags durch die eingegebenen Tags (geben Sie keine Tags ein, um alle Tags zu löschen).",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "So wenden Sie Tags auf die ausgewählten Download-Clients an",
|
||||
"CountIndexersSelected": "{0} Indexer ausgewählt",
|
||||
"DeleteSelectedDownloadClients": "Lösche Download Client(s)",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Indexer '{0}' wirklich löschen?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Sind Sie sicher, dass Sie {count} ausgewählte Download-Clients löschen möchten?",
|
||||
"DeleteSelectedIndexers": "Lösche Indexer",
|
||||
"DeleteSelectedImportListsMessageText": "Indexer '{0}' wirklich löschen?",
|
||||
"DeleteSelectedImportListsMessageText": "Sind Sie sicher, dass Sie {count} ausgewählte Importliste(n) löschen möchten?",
|
||||
"EditSelectedImportLists": "Ausgewählte Einspiel-Liste bearbeten",
|
||||
"EditSelectedIndexers": "Ausgewähle Indexer bearbeiten",
|
||||
"ExistingTag": "Vorhandener Tag",
|
||||
@@ -967,14 +956,14 @@
|
||||
"No": "Nein",
|
||||
"NoChange": "Keine Änderung",
|
||||
"NoDownloadClientsFound": "Keine Download Clienten gefunden",
|
||||
"SetTags": "Tags setzen",
|
||||
"SetTags": "Tags festlegen",
|
||||
"Loading": "Lade",
|
||||
"ConnectionLostReconnect": "Radarr wird automatisch versuchen zu verbinden oder klicke unten auf neuladen.",
|
||||
"ConnectionLostToBackend": "Radarr hat die Verbindung zum Backend verloren und muss neugeladen werden.",
|
||||
"ConnectionLostReconnect": "{appName} wird versuchen, automatisch eine Verbindung herzustellen, oder Sie können unten auf „Neu laden“ klicken.",
|
||||
"ConnectionLostToBackend": "{appName} hat die Verbindung zum Backend verloren und muss neu geladen werden, um die Funktionalität wiederherzustellen.",
|
||||
"NotificationStatusAllClientHealthCheckMessage": "Wegen Fehlern sind keine Applikationen verfügbar",
|
||||
"NotificationStatusSingleClientHealthCheckMessage": "Applikationen wegen folgender Fehler nicht verfügbar: {0}",
|
||||
"TotalSpace": "Speicherkapazität",
|
||||
"Ui": "Oberfläche",
|
||||
"TotalSpace": "Gesamter Speicherplatz",
|
||||
"Ui": "Benutzeroberfläche",
|
||||
"FreeSpace": "Freier Speicher",
|
||||
"Large": "Groß",
|
||||
"LastExecution": "Letzte Ausführung",
|
||||
@@ -985,15 +974,21 @@
|
||||
"ConnectionLost": "Verbindung unterbrochen",
|
||||
"Events": "Events",
|
||||
"LastDuration": "Letzte Dauer",
|
||||
"RecentChanges": "Neuste Änderungen",
|
||||
"RecentChanges": "Kürzliche Änderungen",
|
||||
"System": "System",
|
||||
"WhatsNew": "Was gibt's Neues?",
|
||||
"WhatsNew": "Was ist neu?",
|
||||
"NextExecution": "Nächste Ausführung",
|
||||
"NoResultsFound": "Keine Ergebnisse gefunden",
|
||||
"SomeResultsAreHiddenByTheAppliedFilter": "Einige Ergebnisse werden wegen der aktiven Filter nicht angezeigt",
|
||||
"SomeResultsAreHiddenByTheAppliedFilter": "Einige Ergebnisse werden durch den angewendeten Filter ausgeblendet",
|
||||
"Medium": "Medium",
|
||||
"Activity": "Aktivität",
|
||||
"AddNew": "Hinzufügen",
|
||||
"Backup": "Backups",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Keine Ergebnisse mit den ausgewählten Filtern"
|
||||
"AddNew": "Neue hinzufügen",
|
||||
"Backup": "Sicherung",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Alle Ergebnisse werden durch den angewendeten Filter ausgeblendet",
|
||||
"AppUpdated": "{appName} aktualisiert",
|
||||
"AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu",
|
||||
"Clone": "Klonen",
|
||||
"AutomaticUpdatesDisabledDocker": "Automatische Updates werden bei Verwendung des Docker-Update-Mechanismus nicht direkt unterstützt. Sie müssen das Container-Image außerhalb von {appName} aktualisieren oder ein Skript verwenden",
|
||||
"AutoAdd": "Automatisch hinzufügen",
|
||||
"WouldYouLikeToRestoreBackup": "Möchten Sie die Sicherung „{name}“ wiederherstellen?"
|
||||
}
|
||||
|
||||
@@ -124,8 +124,6 @@
|
||||
"ErrorLoadingContents": "Σφάλμα κατά τη φόρτωση περιεχομένων",
|
||||
"ErrorLoadingPreviews": "Σφάλμα κατά τη φόρτωση προεπισκοπήσεων",
|
||||
"Exception": "Εξαίρεση",
|
||||
"ExtraFileExtensionsHelpTexts1": "Λίστα πρόσθετων αρχείων που διαχωρίζονται με κόμμα για εισαγωγή (το .nfo θα εισαχθεί ως .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Παραδείγματα: «.sub, .nfo» ή «sub, nfo»",
|
||||
"FailedDownloadHandling": "Η Διαχείρηση Λήψης Απέτυχε",
|
||||
"FileDateHelpText": "Αλλαγή ημερομηνίας αρχείου κατά την εισαγωγή / επανασύνδεση",
|
||||
"FileManagement": "Διαχείρηση Αρχείων",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"DeleteRemotePathMappingMessageText": "Are you sure you want to delete this remote path mapping?",
|
||||
"DeleteRootFolder": "Delete Root Folder",
|
||||
"DeleteRootFolderMessageText": "Are you sure you want to delete the root folder '{name}'?",
|
||||
"DeleteSelected": "Delete Selected",
|
||||
"DeleteSelectedBookFiles": "Delete Selected Book Files",
|
||||
"DeleteSelectedBookFilesMessageText": "Are you sure you want to delete the selected book files?",
|
||||
"DeleteSelectedDownloadClients": "Delete Download Client(s)",
|
||||
@@ -265,6 +266,8 @@
|
||||
"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}.",
|
||||
"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",
|
||||
"DownloadClientStatusCheckAllClientMessage": "All download clients are unavailable due to failures",
|
||||
@@ -317,8 +320,8 @@
|
||||
"ExistingTag": "Existing tag",
|
||||
"ExistingTagsScrubbed": "Existing tags scrubbed",
|
||||
"ExportCustomFormat": "Export Custom Format",
|
||||
"ExtraFileExtensionsHelpTexts1": "Comma separated list of extra files to import (.nfo will be imported as .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Examples: \".sub, .nfo\" or \"sub,nfo\"",
|
||||
"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",
|
||||
"FailedToLoadQueue": "Failed to load Queue",
|
||||
"FileDateHelpText": "Change file date on import/rescan",
|
||||
@@ -431,6 +434,7 @@
|
||||
"InstanceName": "Instance Name",
|
||||
"InstanceNameHelpText": "Instance name in tab and for Syslog app name",
|
||||
"Interval": "Interval",
|
||||
"InvalidUILanguage": "Your UI is set to an invalid language, correct it and save your settings",
|
||||
"IsCalibreLibraryHelpText": "Use Calibre Content Server to manipulate library",
|
||||
"IsCutoffCutoff": "Cutoff",
|
||||
"IsCutoffUpgradeUntilThisQualityIsMetOrExceeded": "Upgrade until this quality is met or exceeded",
|
||||
@@ -866,6 +870,7 @@
|
||||
"SorryThatBookCannotBeFound": "Sorry, that book cannot be found.",
|
||||
"Source": "Source",
|
||||
"SourcePath": "Source Path",
|
||||
"SourceTitle": "Source Title",
|
||||
"SpecificBook": "Specific Book",
|
||||
"SslCertPasswordHelpText": "Password for pfx file",
|
||||
"SslCertPasswordHelpTextWarning": "Requires restart to take effect",
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
"60MinutesSixty": "60 Minutos: {0}",
|
||||
"APIKey": "Clave API",
|
||||
"About": "Acerca de",
|
||||
"AddListExclusion": "Añadir Exclusión De Lista",
|
||||
"AddListExclusion": "Agregar Lista de Exclusión",
|
||||
"AddingTag": "Añadir etiqueta",
|
||||
"AgeWhenGrabbed": "Antigüedad (cuando se añadió)",
|
||||
"AlreadyInYourLibrary": "Ya en tu biblioteca",
|
||||
"AlternateTitles": "Título alternativo",
|
||||
"AlternateTitles": "Titulos alternativos",
|
||||
"Analytics": "Analíticas",
|
||||
"AnalyticsEnabledHelpText": "Envíe información anónima de uso y error a los servidores de Radarr. Esto incluye información sobre su navegador, qué páginas de Radarr WebUI utiliza, informes de errores, así como el sistema operativo y la versión en tiempo de ejecución. Usaremos esta información para priorizar funciones y correcciones de errores.",
|
||||
"AnalyticsEnabledHelpTextWarning": "Requiere reiniciar para que surta efecto",
|
||||
@@ -45,9 +45,9 @@
|
||||
"CalendarWeekColumnHeaderHelpText": "Mostrado sobre cada columna cuando la vista activa es semana",
|
||||
"Cancel": "Cancelar",
|
||||
"CancelMessageText": "Seguro que quieres cancelar esta tarea pendiente?",
|
||||
"CertificateValidation": "Validación del certificado",
|
||||
"CertificateValidationHelpText": "Cambiar la rigidez de la validación de la certificación HTTPS",
|
||||
"ChangeFileDate": "Cambiar Fecha de Archivo",
|
||||
"CertificateValidation": "Validacion de certificado",
|
||||
"CertificateValidationHelpText": "Cambiar como es la validacion de la certificacion estricta de HTTPS. No cambiar a menos que entiendas las consecuencias.",
|
||||
"ChangeFileDate": "Cambiar fecha de archivo",
|
||||
"ChangeHasNotBeenSavedYet": "El cambio aún no se ha guardado",
|
||||
"ChmodFolder": "Carpeta chmod",
|
||||
"ChmodFolderHelpText": "Octal, aplicado durante la importación / cambio de nombre a carpetas y archivos multimedia (sin bits de ejecución)",
|
||||
@@ -56,12 +56,7 @@
|
||||
"ChownGroupHelpTextWarning": "Esto solo funciona si el usuario que ejecuta Radarr es el propietario del archivo. Es mejor asegurarse de que el cliente de descarga use el mismo grupo que Radarr.",
|
||||
"Clear": "Borrar",
|
||||
"ClickToChangeQuality": "Clic para cambiar la calidad",
|
||||
"ClientPriority": "Prioridad de Cliente",
|
||||
"CloneIndexer": "Clonar Indexer",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"Close": "Cerrar",
|
||||
"Columns": "Columnas",
|
||||
"CompletedDownloadHandling": "Manipulación de descargas completas",
|
||||
"ConnectSettings": "Conectar Ajustes",
|
||||
"Connections": "Conexiones",
|
||||
"CopyUsingHardlinksHelpText": "Usar Hardlinks al intentar copiar ficheros de los torrents que siguen seedeando",
|
||||
@@ -69,7 +64,7 @@
|
||||
"CreateEmptyAuthorFoldersHelpText": "Crear carpetas de películas que faltan durante la exploración del disco",
|
||||
"CreateGroup": "Crear grupo",
|
||||
"CutoffHelpText": "Una vez que se alcanze esta calidad, Radarr no descargará películas",
|
||||
"CutoffUnmet": "Corte No Alcanzado",
|
||||
"CutoffUnmet": "Límite no alcanzado",
|
||||
"DBMigration": "Migración de DB",
|
||||
"Dates": "Fechas",
|
||||
"DelayProfile": "Perfil de Retraso",
|
||||
@@ -81,7 +76,7 @@
|
||||
"DeleteDelayProfile": "Borrar Perfil de Retraso",
|
||||
"DeleteDelayProfileMessageText": "Está seguro que quieres borrar este perfil de retraso?",
|
||||
"DeleteDownloadClient": "Borrar Gestor de Descargas",
|
||||
"DeleteDownloadClientMessageText": "¿Seguro que quieres eliminar el cliente de descargas '{name}'?",
|
||||
"DeleteDownloadClientMessageText": "Seguro que quieres eliminar el gestor de descargas '{name}'?",
|
||||
"DeleteEmptyFolders": "Borrar carpetas vacías",
|
||||
"DeleteEmptyFoldersHelpText": "Borrar carpetas vacías durante la exploración del disco y cuando se eliminen archivos",
|
||||
"DeleteImportListExclusion": "Borrar exclusión de lista de importación",
|
||||
@@ -89,9 +84,9 @@
|
||||
"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 calidad {0}",
|
||||
"DeleteMetadataProfileMessageText": "¿Seguro que quieres eliminar el perfil de metadatos '{name}'?",
|
||||
"DeleteNotification": "Borrar Notificación",
|
||||
"DeleteNotificationMessageText": "¿Seguro que quieres eliminiar la notificación '{name}'?",
|
||||
"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",
|
||||
@@ -129,8 +124,6 @@
|
||||
"ErrorLoadingContents": "Error al cargar los contenidos",
|
||||
"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)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Ejemplos : '.sub, .nfo' o 'sub,nfo'",
|
||||
"FailedDownloadHandling": "Manipulación de Descargas Fallidas",
|
||||
"FileDateHelpText": "Cambiar la fecha del archivo al importar/rescan",
|
||||
"FileManagement": "Administración de Archivos",
|
||||
@@ -154,7 +147,7 @@
|
||||
"GrabSelected": "Capturar Seleccionados",
|
||||
"HasPendingChangesNoChanges": "Sin Cambios",
|
||||
"HasPendingChangesSaveChanges": "Guardar Cambios",
|
||||
"History": "Historia",
|
||||
"History": "Historial",
|
||||
"Host": "Host",
|
||||
"Hostname": "Nombre del Host",
|
||||
"ICalFeed": "iCal Feed",
|
||||
@@ -210,7 +203,7 @@
|
||||
"MinimumLimits": "Límites Mínimos",
|
||||
"Missing": "Falta",
|
||||
"Mode": "Modo",
|
||||
"Monitored": "Monitoreada",
|
||||
"Monitored": "Monitorizado",
|
||||
"MoreInfo": "Más Información",
|
||||
"MustContain": "Debe Contener",
|
||||
"MustNotContain": "No Debe Contener",
|
||||
@@ -440,7 +433,7 @@
|
||||
"YesCancel": "Sí, Cancelar",
|
||||
"20MinutesTwenty": "20 Minutos: {0}",
|
||||
"DownloadClientCheckDownloadingToRoot": "El cliente de descargas {0} coloca las descargas en la carpeta raíz {1}. No debe descargar a una carpeta raíz.",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento: Corrección de errores y otras mejoras. Ver historial de commits de Github para mas detalle",
|
||||
"ReplaceIllegalCharactersHelpText": "Reemplazar caracteres ilegales. Si está desactivado, Radarr los eliminará si no",
|
||||
"Actions": "Acciones",
|
||||
"Today": "Hoy",
|
||||
@@ -462,7 +455,7 @@
|
||||
"Level": "Nivel",
|
||||
"ReleaseBranchCheckOfficialBranchMessage": "Las versión {0} no es una versión válida de Radarr, no recibirás actualizaciones",
|
||||
"Blocklist": "Bloqueadas",
|
||||
"BlocklistRelease": "Bloquear este Estreno",
|
||||
"BlocklistRelease": "Lista de lanzamientos bloqueados",
|
||||
"CreateEmptyAuthorFolders": "Crear carpetas de películas vacías",
|
||||
"SelectAll": "Seleccionar Todas",
|
||||
"SelectedCountBooksSelectedInterp": "{0} Película(s) Seleccionada(s)",
|
||||
@@ -587,7 +580,7 @@
|
||||
"Test": "Test",
|
||||
"InstanceName": "Nombre de Instancia",
|
||||
"InstanceNameHelpText": "Nombre de instancia en pestaña y para nombre de aplicación en Syslog",
|
||||
"Database": "Base de Datos",
|
||||
"Database": "Base de datos",
|
||||
"ManualImportSelectEdition": "Importar Manualmente - Seleccionar Película",
|
||||
"ImportListExclusions": "Borrar exclusión de lista de importación",
|
||||
"ChooseImportMethod": "Elegir Modo de Importación",
|
||||
@@ -599,11 +592,10 @@
|
||||
"BypassIfHighestQuality": "Pasar sí es la calidad más alta",
|
||||
"CustomFormatScore": "Puntuación de Formato personalizado",
|
||||
"MinimumCustomFormatScore": "Puntuación mínima de formato personalizado",
|
||||
"CloneCustomFormat": "Clonar Formato Personalizado",
|
||||
"Conditions": "Condiciones",
|
||||
"CopyToClipboard": "Copiar al portapapeles",
|
||||
"CustomFormat": "Formatos Personalizados",
|
||||
"CustomFormats": "Formatos Personalizados",
|
||||
"CustomFormats": "Formatos personalizados",
|
||||
"DeleteCustomFormat": "Borrar Formato Personalizado",
|
||||
"DeleteFormatMessageText": "¿Está seguro de que desea eliminar la etiqueta de formato {0}?",
|
||||
"Formats": "Formatos",
|
||||
@@ -630,12 +622,11 @@
|
||||
"HideAdvanced": "Ocultar Avanzado",
|
||||
"ShowAdvanced": "Mostrar Avanzado",
|
||||
"ShownClickToHide": "Mostrado, clic para ocultar",
|
||||
"ColonReplacement": "Reemplazo dos puntos",
|
||||
"ReplaceWithDash": "Reemplazar con Dash",
|
||||
"ReplaceWithSpaceDash": "Reemplazar con Space Dash",
|
||||
"ReplaceWithSpaceDashSpace": "Reemplazar con Space Dash Space",
|
||||
"DeleteRemotePathMapping": "Editar Mapeo de Ruta Remota",
|
||||
"BlocklistReleases": "Bloquear este Estreno",
|
||||
"BlocklistReleases": "Lista de lanzamientos bloqueados",
|
||||
"DeleteConditionMessageText": "Seguro que quieres eliminar la etiqueta '{0}'?",
|
||||
"Negated": "Negado",
|
||||
"RemoveSelectedItem": "Eliminar el elemento seleccionado",
|
||||
@@ -649,7 +640,7 @@
|
||||
"BlocklistReleaseHelpText": "Evita que Radarr vuelva a capturar esta película automáticamente",
|
||||
"NoEventsFound": "No se encontraron eventos",
|
||||
"ApplyTagsHelpTextHowToApplyAuthors": "Cómo añadir etiquetas a las películas seleccionadas",
|
||||
"DeleteSelectedIndexersMessageText": "Seguro que quieres eliminar el indexer '{0}'?",
|
||||
"DeleteSelectedIndexersMessageText": "¿Está seguro de querer eliminar {count} indexador(es) seleccionado(s)?",
|
||||
"Yes": "Sí",
|
||||
"RedownloadFailed": "La descarga ha fallado",
|
||||
"RemoveCompleted": "Eliminación completada",
|
||||
@@ -662,8 +653,8 @@
|
||||
"ApplyTagsHelpTextRemove": "Eliminar: Eliminar las etiquetas introducidas",
|
||||
"ApplyTagsHelpTextReplace": "Reemplazar: Reemplazar las etiquetas con las etiquetas introducidas (no introducir etiquetas para eliminar todas las etiquetas)",
|
||||
"DeleteSelectedDownloadClients": "Borrar Gestor de Descargas",
|
||||
"DeleteSelectedDownloadClientsMessageText": "¿Estas seguro que quieres eliminar {count} cliente(s) de descarga seleccionado(s)?",
|
||||
"DeleteSelectedImportListsMessageText": "Seguro que quieres eliminar el indexer '{0}'?",
|
||||
"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)?",
|
||||
"DeleteSelectedIndexers": "Borrar Indexer",
|
||||
"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",
|
||||
@@ -723,7 +714,7 @@
|
||||
"NextExecution": "Siguiente ejecución",
|
||||
"NoResultsFound": "No se han encontrado resultados",
|
||||
"RecentChanges": "Cambios recientes",
|
||||
"WhatsNew": "¿Qué hay de nuevo?",
|
||||
"WhatsNew": "Que es lo nuevo?",
|
||||
"Loading": "Cargando",
|
||||
"Events": "Eventos",
|
||||
"Medium": "Medio",
|
||||
@@ -746,7 +737,7 @@
|
||||
"ASIN": "ASIN",
|
||||
"AnyEditionOkHelpText": "Readarr cambiará automáticamente a la edición que mejor coincida con los archivos descargados",
|
||||
"AppUpdated": "{appName} Actualizada",
|
||||
"AppUpdatedVersion": "{appName} ha sido actualizado a la versión `{version}`, para obtener los cambios más recientes, necesitaras recargar {appName}",
|
||||
"AppUpdatedVersion": "{appName} ha sido actualizado a la versión `{version}`, para obtener los cambios más recientes necesitará recargar {appName}",
|
||||
"AuthorFolderFormat": "Formato de Carpeta de Autor",
|
||||
"AuthorNameHelpText": "El nombre del autor/libro a excluir (puede ser cualquier cosa significativa)",
|
||||
"BookMonitoring": "Monitoreo de libros",
|
||||
@@ -755,5 +746,26 @@
|
||||
"Book": "Libro",
|
||||
"AutomaticallySwitchEdition": "Cambiar edición automáticamente",
|
||||
"BookNaming": "Nombrado de libros",
|
||||
"Books": "Libro"
|
||||
"Books": "Libro",
|
||||
"NoHistoryBlocklist": "Sin lista de bloqueo de historial",
|
||||
"WouldYouLikeToRestoreBackup": "Te gustaria restaurar la copia de seguridad '{name}'?",
|
||||
"IsShowingMonitoredUnmonitorSelected": "Monitorizar Seleccionados",
|
||||
"CloneCustomFormat": "Clonar formato personalizado",
|
||||
"MinimumCustomFormatScoreHelpText": "Puntuación mínima de formato personalizado necesaria para evitar el retraso del protocolo preferido",
|
||||
"BypassIfAboveCustomFormatScore": "Omitir si está por encima de la puntuación del formato personalizado",
|
||||
"BypassIfAboveCustomFormatScoreHelpText": "Habilitar ignorar cuando la versión tenga una puntuación superior a la puntuación mínima configurada para el formato personalizado",
|
||||
"IsShowingMonitoredMonitorSelected": "Monitorizar Seleccionados",
|
||||
"ClientPriority": "Prioridad del Cliente",
|
||||
"ColonReplacement": "Reemplazar dos puntos",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"Close": "Cerrar",
|
||||
"CloneIndexer": "Clonar Indexer",
|
||||
"CompletedDownloadHandling": "Manipulación de descargas completas",
|
||||
"EnableProfile": "Habilitar perfil",
|
||||
"ListsSettingsSummary": "lista de importación",
|
||||
"ExtraFileExtensionsHelpText": "Separar con cons la lista de los archivos extra a importar (.nfo será impotado como .nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "Ejemplos : '.sub, .nfo' o 'sub,nfo'",
|
||||
"ImportLists": "lista de importación",
|
||||
"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.",
|
||||
"Continuing": "Continua"
|
||||
}
|
||||
|
||||
@@ -123,8 +123,6 @@
|
||||
"ErrorLoadingContents": "Sisällönlatauksen virhe",
|
||||
"ErrorLoadingPreviews": "Virhe ladattaessa esikatselua",
|
||||
"Exception": "Poikkeus",
|
||||
"ExtraFileExtensionsHelpTexts1": "Pilkulla eroteltu lista tuotavista oheistiedostoista (.nfo tuodaan nimellä .nfo-orig).",
|
||||
"ExtraFileExtensionsHelpTexts2": "Esimerkkejä: '.sub, .nfo' tai 'sub, nfo'.",
|
||||
"FailedDownloadHandling": "Latauksen käsittely epäonnistui",
|
||||
"FileDateHelpText": "Muuta tiedoston päiväys tuonnin ja uudelleentarkistuksen yhteydessä.",
|
||||
"FileManagement": "Tiedostojen hallinta",
|
||||
@@ -883,5 +881,7 @@
|
||||
"AutomaticUpdatesDisabledDocker": "Suoraa automaattista päivitystä ei tueta käytettäessä Dockerin päivitysmekanismia. Joko Docker-säiliö on päivitettävä {appName}in ulkopuolella tai päivitys on suoritettava skriptillä.",
|
||||
"AppUpdated": "{appName} on päivitetty",
|
||||
"AppUpdatedVersion": "{appName} on päivitetty versioon {version} ja muutosten käyttöönottamiseksi se on ladattava uudelleen.",
|
||||
"Iso639-3": "ISO 639-3 -kielikoodit tai \"null\" (pilkuin eroteltuna)"
|
||||
"Iso639-3": "ISO 639-3 -kielikoodit tai \"null\" (pilkuin eroteltuna)",
|
||||
"ExtraFileExtensionsHelpText": "Pilkulla eroteltu lista tuotavista oheistiedostoista (.nfo tuodaan nimellä .nfo-orig).",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "Esimerkkejä: '.sub, .nfo' tai 'sub, nfo'."
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"DiskSpace": "Espace disque",
|
||||
"DownloadClient": "Client de téléchargement",
|
||||
"DownloadClientSettings": "Télécharger les paramètres client",
|
||||
"DownloadClients": "Clients de téléchargements",
|
||||
"DownloadClients": "Clients de téléchargement",
|
||||
"DownloadFailedCheckDownloadClientForMoreDetails": "Téléchargement échoué : voir le client de téléchargement pour plus de détails",
|
||||
"DownloadFailedInterp": "Échec du téléchargement : {0}",
|
||||
"DownloadPropersAndRepacksHelpTexts1": "S'il faut ou non mettre à niveau automatiquement vers Propres/Repacks",
|
||||
@@ -132,15 +132,13 @@
|
||||
"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)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Exemples : '.sub, .nfo' ou 'sub,nfo'",
|
||||
"FailedDownloadHandling": "Gestion des échecs de téléchargement",
|
||||
"FileDateHelpText": "Changer la date du fichier lors de l'import/re-scan",
|
||||
"FileNames": "Noms de fichier",
|
||||
"Filename": "Nom de fichier",
|
||||
"Files": "Fichiers",
|
||||
"FirstDayOfWeek": "Premier jour de la semaine",
|
||||
"Fixed": "Fixé",
|
||||
"Fixed": "Corrigés",
|
||||
"Folder": "Dossier",
|
||||
"Folders": "Dossiers",
|
||||
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Pour plus d'informations sur les clients de téléchargement individuels, cliquez sur les boutons d'information.",
|
||||
@@ -158,7 +156,7 @@
|
||||
"HasPendingChangesNoChanges": "Aucune modification",
|
||||
"HasPendingChangesSaveChanges": "Sauvegarder les modifications",
|
||||
"History": "Historique",
|
||||
"Hostname": "Hostname",
|
||||
"Hostname": "Nom d'hôte",
|
||||
"ICalFeed": "Flux iCal",
|
||||
"ICalHttpUrlHelpText": "Copiez cette URL dans votre/vos client(s) ou cliquez pour abonner si votre navigateur est compatible avec webcal",
|
||||
"ICalLink": "Lien iCal",
|
||||
@@ -244,9 +242,9 @@
|
||||
"Port": "Port",
|
||||
"PortHelpTextWarning": "Nécessite un redémarrage pour prendre effet",
|
||||
"PortNumber": "Numéro de port",
|
||||
"PosterSize": "Poster taille",
|
||||
"PosterSize": "Taille des affiches",
|
||||
"PreviewRename": "Aperçu Renommer",
|
||||
"Profiles": "Profiles",
|
||||
"Profiles": "Profils",
|
||||
"Proper": "Approprié",
|
||||
"PropersAndRepacks": "Propres et Repacks",
|
||||
"Protocol": "Protocole",
|
||||
@@ -265,7 +263,7 @@
|
||||
"RSSSyncInterval": "Intervalle de synchronisation RSS",
|
||||
"ReadTheWikiForMoreInformation": "Lisez le wiki pour plus d'informations",
|
||||
"ReadarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "Readarr prend en charge tout indexeur qui utilise le standard Newznab, ainsi que d'autres indexeurs répertoriés ci-dessous.",
|
||||
"ReadarrTags": "Readarr Tags",
|
||||
"ReadarrTags": "Étiquettes Readarr",
|
||||
"Real": "Réel",
|
||||
"Reason": "Raison",
|
||||
"RecycleBinCleanupDaysHelpText": "Définir sur 0 pour désactiver le nettoyage automatique",
|
||||
@@ -398,7 +396,7 @@
|
||||
"UnableToLoadDownloadClientOptions": "Impossible de charger les options du client de téléchargement",
|
||||
"UnableToLoadDownloadClients": "Impossible de charger les clients de téléchargement",
|
||||
"UnableToLoadGeneralSettings": "Impossible de charger les paramètres généraux",
|
||||
"UnableToLoadHistory": "Impossible de charger l'historique",
|
||||
"UnableToLoadHistory": "Impossible de charger l'historique.",
|
||||
"UnableToLoadImportListExclusions": "Impossible de charger les exclusions de liste",
|
||||
"UnableToLoadIndexerOptions": "Impossible de charger les options de l'indexeur",
|
||||
"UnableToLoadIndexers": "Impossible de charger les indexeurs",
|
||||
@@ -465,7 +463,7 @@
|
||||
"ReplaceIllegalCharactersHelpText": "Remplacer les caractères illégaux. Si non coché, Readarr les supprimera",
|
||||
"Level": "Niveau",
|
||||
"Publisher": "Éditeur",
|
||||
"Label": "Label",
|
||||
"Label": "Libellé",
|
||||
"RemoveFromBlocklist": "Supprimer de la liste noire",
|
||||
"UnableToLoadBlocklist": "Impossible de charger la liste noire",
|
||||
"Component": "Composant",
|
||||
@@ -502,7 +500,7 @@
|
||||
"Save": "Sauvegarder",
|
||||
"BackupIntervalHelpText": "Intervalle entre les sauvegardes automatiques",
|
||||
"CatalogNumber": "Numéro de catalogue",
|
||||
"Metadata": "Metadonnées",
|
||||
"Metadata": "Métadonnées",
|
||||
"Disabled": "Désactivé",
|
||||
"IndexersSettingsSummary": "Indexeurs et restrictions de version",
|
||||
"OnUpgrade": "Lors de la mise à niveau",
|
||||
@@ -525,7 +523,7 @@
|
||||
"ImportListStatusCheckAllClientMessage": "Toutes les listes ne sont pas disponibles en raison d'échecs",
|
||||
"ImportMechanismHealthCheckMessage": "Activer la gestion des téléchargements terminés",
|
||||
"IndexerRssHealthCheckNoIndexers": "Aucun indexeur disponible avec la synchronisation RSS activée, Readarr ne récupérera pas automatiquement les nouvelles versions",
|
||||
"CouldntFindAnyResultsForTerm": "Pas de résultats pour '{0}'",
|
||||
"CouldntFindAnyResultsForTerm": "Aucun résultat pour de résultats pour '{0}'",
|
||||
"ReadarrSupportsAnyDownloadClient": "Readarr prend en charge de nombreux clients de téléchargement torrent et usenet.",
|
||||
"RefreshAndScan": "Actualiser et analyser",
|
||||
"RemotePathMappingCheckFileRemoved": "Le fichier {0} a été supprimé pendant le processus.",
|
||||
@@ -605,7 +603,7 @@
|
||||
"AuthorIndex": "Index de l'auteur",
|
||||
"BookEditor": "Éditeur de livres",
|
||||
"BookIndex": "Index du livre",
|
||||
"DefaultReadarrTags": "Tags Readarr par défaut",
|
||||
"DefaultReadarrTags": "Étiquettes Readarr par défaut",
|
||||
"AddedAuthorSettings": "Ajout des paramètres de l'auteur",
|
||||
"AllBooks": "Tous les livres",
|
||||
"BookList": "Liste des livres",
|
||||
@@ -675,7 +673,7 @@
|
||||
"BypassIfAboveCustomFormatScore": "Contourner si au-dessus du score du format personnalisé",
|
||||
"BypassIfHighestQuality": "Contourner si la qualité est la plus élevée",
|
||||
"BypassIfAboveCustomFormatScoreHelpText": "Activez le contournement lorsque la version a un score supérieur au score minimum configuré pour le format personnalisé",
|
||||
"CustomFormatScore": "Partition au format personnalisé",
|
||||
"CustomFormatScore": "Score du format personnalisé",
|
||||
"MinimumCustomFormatScore": "Score minimum de format personnalisé",
|
||||
"Theme": "Thème",
|
||||
"ThemeHelpText": "Modifiez le thème de l'interface utilisateur de l'application, le thème « Auto » utilisera le thème de votre système d'exploitation pour définir le mode clair ou sombre. Inspiré par Theme.Park",
|
||||
@@ -685,10 +683,10 @@
|
||||
"CopyToClipboard": "Copier dans le presse-papier",
|
||||
"CustomFormat": "Format personnalisé",
|
||||
"CustomFormatSettings": "Réglages Formats Personnalisés",
|
||||
"CustomFormats": "Formats perso.",
|
||||
"CustomFormats": "Formats personnalisés",
|
||||
"DeleteCustomFormat": "Supprimer le format personnalisé",
|
||||
"DeleteCustomFormatMessageText": "Voulez-vous vraiment supprimer le format personnalisé « {name} » ?",
|
||||
"DeleteFormatMessageText": "Êtes-vous sûr de vouloir supprimer le tag {0} ?",
|
||||
"DeleteFormatMessageText": "Êtes-vous sûr de vouloir supprimer le tag « {0} » ?",
|
||||
"ExportCustomFormat": "Exporter un format personnalisé",
|
||||
"Formats": "Formats",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Inclus dans {Custom Formats} renommer le format",
|
||||
@@ -713,7 +711,7 @@
|
||||
"ApiKeyValidationHealthCheckMessage": "Veuillez mettre à jour votre clé API pour qu'elle contienne au moins {0} caractères. Vous pouvez le faire via les paramètres ou le fichier de configuration",
|
||||
"DeleteBookFile": "Effacer le fichier du livre",
|
||||
"HiddenClickToShow": "Masqué, cliquez pour afficher",
|
||||
"HideAdvanced": "Masquer param. av.",
|
||||
"HideAdvanced": "Masquer les Options Avancées",
|
||||
"ShowAdvanced": "Afficher les paramètres avancés",
|
||||
"ShownClickToHide": "Affiché, cliquez pour masquer",
|
||||
"ColonReplacement": "Remplacement pour le « deux-points »",
|
||||
@@ -760,7 +758,7 @@
|
||||
"ExistingTag": "Balise existante",
|
||||
"No": "Non",
|
||||
"RemovingTag": "Supprimer la balise",
|
||||
"SetTags": "Définir des balises",
|
||||
"SetTags": "Définir des étiquettes",
|
||||
"CountDownloadClientsSelected": "{selectedCount} client(s) de téléchargement sélectionné(s)",
|
||||
"EditSelectedDownloadClients": "Modifier les clients de téléchargement sélectionnés",
|
||||
"EditSelectedIndexers": "Modifier les indexeurs sélectionnés",
|
||||
@@ -789,7 +787,7 @@
|
||||
"TotalSpace": "Espace total",
|
||||
"Ui": "Interface utilisateur",
|
||||
"Activity": "Activité",
|
||||
"AddNew": "Ajouter une nouvelle",
|
||||
"AddNew": "Ajouter",
|
||||
"Backup": "Sauvegarde",
|
||||
"AutoAdd": "Ajout automatique",
|
||||
"AutomaticUpdatesDisabledDocker": "Les mises à jour automatiques ne sont pas directement prises en charge lors de l'utilisation du mécanisme de mise à jour de Docker. Vous devrez mettre à jour l'image du conteneur en dehors de {appName} ou utiliser un script",
|
||||
@@ -881,11 +879,11 @@
|
||||
"TrackTitle": "Titre de la piste",
|
||||
"UpdatingIsDisabledInsideADockerContainerUpdateTheContainerImageInstead": "La mise à jour est désactivée dans un conteneur Docker. Mettez plutôt à jour l’image du conteneur.",
|
||||
"WatchRootFoldersForFileChanges": "Surveillez les dossiers racine pour les modifications de fichiers",
|
||||
"WriteMetadataTags": "Écrire des balises de métadonnées",
|
||||
"WriteMetadataTags": "Écrire des étiquettes de métadonnées",
|
||||
"IndexerIdHelpText": "Spécifiez à quel indexeur le profil s'applique",
|
||||
"Monitoring": "Surveillance",
|
||||
"UnmappedFiles": "Fichiers non mappés",
|
||||
"Bookshelf": "Étagère à livres",
|
||||
"Bookshelf": "Bibliothèque",
|
||||
"ErrorLoadingContent": "Une erreur s'est produite lors du chargement de ce contenu",
|
||||
"OnReleaseImportHelpText": "Lors de l'importation de la version",
|
||||
"UnableToLoadMetadataProviderSettings": "Impossible de charger les paramètres du fournisseur de métadonnées",
|
||||
@@ -921,5 +919,12 @@
|
||||
"ReadarrSupportsMultipleListsForImportingBooksAndAuthorsIntoTheDatabase": "Lidarr prend en charge plusieurs listes pour importer des albums et des artistes dans la base de données.",
|
||||
"TotalBookCountBooksTotalBookFileCountBooksWithFilesInterp": "{0} pistes au total. {1} pistes avec fichiers.",
|
||||
"SearchForAllMissingBooks": "Rechercher tous les albums manquants",
|
||||
"ForeignIdHelpText": "L'identifiant Musicbrainz de l'artiste/album à exclure"
|
||||
"ForeignIdHelpText": "L'identifiant Musicbrainz de l'artiste/album à exclure",
|
||||
"EnableProfile": "Activer profil",
|
||||
"Development": "Développement",
|
||||
"FilesTotal": "Fichiers ({0})",
|
||||
"SearchBoxPlaceHolder": "Par ex. Guerre et Paix, goodreads:656, isbn:067003469X, asin:B00JCDK5ME",
|
||||
"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'",
|
||||
"UseSSL": "Utiliser SSL"
|
||||
}
|
||||
|
||||
@@ -109,8 +109,6 @@
|
||||
"ErrorLoadingContents": "שגיאה בטעינת התוכן",
|
||||
"ErrorLoadingPreviews": "שגיאה בטעינת תצוגה מקדימה",
|
||||
"Exception": "יוצא מן הכלל",
|
||||
"ExtraFileExtensionsHelpTexts1": "רשימה מופרדת באמצעות פסיקים של קבצים נוספים לייבוא (.nfo יובא כ- nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTexts2": "דוגמאות: '.sub, .nfo' או 'sub, nfo'",
|
||||
"FailedDownloadHandling": "הטיפול בהורדות נכשל",
|
||||
"FileDateHelpText": "שנה את תאריך הקובץ בעת הייבוא / סריקה מחדש",
|
||||
"FileManagement": "ניהול קבצים",
|
||||
@@ -657,5 +655,7 @@
|
||||
"System": "מערכת",
|
||||
"Theme": "ערכת נושא",
|
||||
"TotalSpace": "השטח הכולל",
|
||||
"Publisher": "מוציא לאור"
|
||||
"Publisher": "מוציא לאור",
|
||||
"ExtraFileExtensionsHelpText": "רשימה מופרדת באמצעות פסיקים של קבצים נוספים לייבוא (.nfo יובא כ- nfo-orig)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "דוגמאות: '.sub, .nfo' או 'sub, nfo'"
|
||||
}
|
||||
|
||||
@@ -114,8 +114,6 @@
|
||||
"ErrorLoadingContents": "सामग्री लोड करने में त्रुटि",
|
||||
"ErrorLoadingPreviews": "पूर्वावलोकन लोड करने में त्रुटि",
|
||||
"Exception": "अपवाद",
|
||||
"ExtraFileExtensionsHelpTexts1": "आयात करने के लिए कोमा ने अतिरिक्त फ़ाइलों की सूची अलग कर दी (.nfo को .nfo- मूल के रूप में आयात किया जाएगा)",
|
||||
"ExtraFileExtensionsHelpTexts2": "उदाहरण: '.sub, .nfo' या 'सब, nfo'",
|
||||
"FailedDownloadHandling": "डाउनलोड हैंडलिंग विफल",
|
||||
"FileDateHelpText": "आयात / रेस्क्यू पर फ़ाइल तिथि बदलें",
|
||||
"FileManagement": "फाइल प्रबंधन",
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"AlternateTitles": "Alternatív cím",
|
||||
"AlternateTitles": "Alternatív címek",
|
||||
"Analytics": "Analitika",
|
||||
"AnalyticsEnabledHelpText": "Küldjön névtelen használati és hibainformációkat a Readarr szervereire. Ez magában foglalja a böngészőjéről szóló információkat, mely Readarr 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.",
|
||||
"AppDataDirectory": "AppData Mappa",
|
||||
"AppDataDirectory": "AppData Könyvtár",
|
||||
"ApplyTags": "Címkék alkalmazása",
|
||||
"Authentication": "Hitelesítés",
|
||||
"AuthenticationMethodHelpText": "Felhasználónév és Jelszó szükséges a Readarr-hoz való hozzáféréshez",
|
||||
"AuthorClickToChangeBook": "Kattints a film módosításához",
|
||||
"AutoRedownloadFailedHelpText": "Másik kiadás automatikus keresése és letöltése",
|
||||
"AutoRedownloadFailedHelpText": "Egy másik kiadás automatikus keresése és letöltése",
|
||||
"AutoUnmonitorPreviouslyDownloadedBooksHelpText": "A lemezről törölt filmeket a Radarr automatikusan eltávolítja a megfigyelt filmek közül",
|
||||
"Automatic": "Automatikus",
|
||||
"BackupFolderHelpText": "Az elérési útvonalak a Readarr AppData könyvtárában lesznek",
|
||||
"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",
|
||||
"BindAddressHelpText": "Érvényes IPv4-cím, vagy „*” minden interfészhez",
|
||||
@@ -27,7 +27,7 @@
|
||||
"CancelMessageText": "Biztosan törlöd ezt a függőben lévő feladatot?",
|
||||
"CertificateValidation": "Tanúsítvány érvényesítése",
|
||||
"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.",
|
||||
"ChangeFileDate": "Fájl Dátumának Módosítása",
|
||||
"ChangeFileDate": "Fájl dátumának módosítása",
|
||||
"ChangeHasNotBeenSavedYet": "A változások még nem lettek elmentve",
|
||||
"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)",
|
||||
@@ -35,7 +35,7 @@
|
||||
"ChownGroupHelpText": "Csoport neve vagy gid. A gid használata távoli fájlrendszerekhez.",
|
||||
"ChownGroupHelpTextWarning": "Ez csak akkor működik, ha a Radarrt futtató felhasználó a fájl tulajdonosa. Jobb, ha a letöltési kliens ugyanazt a csoportot használja, mint a Radarr.",
|
||||
"Clear": "Törölni",
|
||||
"ClickToChangeQuality": "Kattints a minőség módosításához",
|
||||
"ClickToChangeQuality": "Kattintson a minőség módosításához",
|
||||
"ClientPriority": "Kliens Prioritás",
|
||||
"CloneIndexer": "Indexer Klónozása",
|
||||
"CloneProfile": "Profil Klónozása",
|
||||
@@ -56,11 +56,11 @@
|
||||
"DelayProfiles": "Késleltetési Profilok",
|
||||
"DelayingDownloadUntilInterp": "Késleltetni a letöltést {0} -tól {1} -ig",
|
||||
"Delete": "Törlés",
|
||||
"DeleteBackup": "Biztonsági Mentés Törlése",
|
||||
"DeleteBackupMessageText": "Biztosan törlöd a(z) „{0}” biztonsági mentést?",
|
||||
"DeleteDelayProfile": "Késleltetési Profil Törlése",
|
||||
"DeleteBackup": "Biztonsági Mentés törlése",
|
||||
"DeleteBackupMessageText": "Biztosan törli a '{name}' biztonsági mentést?",
|
||||
"DeleteDelayProfile": "Késleltetési Profil törlése",
|
||||
"DeleteDelayProfileMessageText": "Biztos hogy törölni szeretnéd ezt a késleltetési profilt?",
|
||||
"DeleteDownloadClient": "Letöltőkliens Törlése",
|
||||
"DeleteDownloadClient": "Letöltőkliens törlése",
|
||||
"DeleteDownloadClientMessageText": "Biztosan törlöd a(z) „{0}” letöltő klienst?",
|
||||
"DeleteEmptyFolders": "Üres Mappa Törlése",
|
||||
"DeleteEmptyFoldersHelpText": "Törölje az üres könyvmappákat a lemezfrissítés és a könyvfájlokfájlok törlése során",
|
||||
@@ -92,7 +92,7 @@
|
||||
"DownloadFailedInterp": "Letöltés sikertelen: {0}",
|
||||
"DownloadPropersAndRepacksHelpTexts1": "Függetlenül attól, hogy automatikusan frissíteni kell-e Propers/Repacks verzióra",
|
||||
"DownloadWarningCheckDownloadClientForMoreDetails": "Letöltési figyelmeztetés: Nézd meg a letöltőkliensed további információért",
|
||||
"Edit": "Szerkesztés",
|
||||
"Edit": "szerkeszt",
|
||||
"Edition": "Kiadás",
|
||||
"Enable": "Aktiválás",
|
||||
"EnableAutomaticAdd": "Engedélyezd az automatikus hozzáadást",
|
||||
@@ -109,16 +109,14 @@
|
||||
"ErrorLoadingContents": "Hiba történt a tartalom betöltésekor",
|
||||
"ErrorLoadingPreviews": "Hiba történt az előnézetek betöltése közben",
|
||||
"Exception": "Kivétel",
|
||||
"ExtraFileExtensionsHelpTexts1": "Az importálandó extra fájlok vesszővel lesznek elválasztva (.nfo .nfo-orig néven lesz importálva)",
|
||||
"ExtraFileExtensionsHelpTexts2": "Például: '.sub, .nfo' vagy 'sub, nfo'",
|
||||
"FailedDownloadHandling": "Nem sikerült a letöltés kezelése",
|
||||
"FileDateHelpText": "A fájl dátumának módosítása az importáláskor / újrakereséskor",
|
||||
"FileManagement": "Fájlkezelő",
|
||||
"FileNames": "Fájlnevek",
|
||||
"Filename": "Fájlnév",
|
||||
"Filename": "Fájl név",
|
||||
"Files": "Fájl",
|
||||
"FirstDayOfWeek": "A Hét Első Napja",
|
||||
"Fixed": "Kijavítva",
|
||||
"Fixed": "Rögzített",
|
||||
"Folder": "Mappa",
|
||||
"Folders": "Mappák",
|
||||
"ForMoreInformationOnTheIndividualDownloadClientsClickOnTheInfoButtons": "Ha többet szeretnél megtudni a különböző letöltési kliensekről, kattints az információs gombokra.",
|
||||
@@ -135,7 +133,7 @@
|
||||
"Group": "Csoport",
|
||||
"HasPendingChangesNoChanges": "Nincsenek változások",
|
||||
"HasPendingChangesSaveChanges": "Változtatások mentése",
|
||||
"History": "Történet",
|
||||
"History": "Előzmény",
|
||||
"Host": "Hoszt",
|
||||
"Hostname": "Hosztnév",
|
||||
"ICalFeed": "iCal-Feed",
|
||||
@@ -143,7 +141,7 @@
|
||||
"ICalLink": "iCal Link(ek)",
|
||||
"IconForCutoffUnmet": "Ikon a Sikertelen Küszöbszint Elérésére",
|
||||
"IconTooltip": "Ütemezve",
|
||||
"IgnoredAddresses": "Ignorált Címek",
|
||||
"IgnoredAddresses": "Ignorált címek",
|
||||
"IgnoredHelpText": "A kiadás elutasításra kerül, ha egy vagy több kifejezést tartalmaz (A kis- és nagybetűket nem vesszük figyelembe)",
|
||||
"IgnoredPlaceHolder": "Új korlátozás hozzáadása",
|
||||
"IllRestartLater": "Később Újraindítom",
|
||||
@@ -171,7 +169,7 @@
|
||||
"LogLevel": "Log Szint",
|
||||
"LogLevelvalueTraceTraceLoggingShouldOnlyBeEnabledTemporarily": "A nyomkövetést csak ideiglenesen szabad engedélyezni",
|
||||
"Logging": "Loggolás",
|
||||
"Logs": "Logok",
|
||||
"Logs": "Naplók",
|
||||
"LongDateFormat": "Hosszú dátumformátum",
|
||||
"MIA": "MIA",
|
||||
"ManualImport": "Manuális Importálás",
|
||||
@@ -212,7 +210,7 @@
|
||||
"OnRenameHelpText": "Átnevezés alatt",
|
||||
"OnUpgradeHelpText": "Minőségjavítás alatt",
|
||||
"OpenBrowserOnStart": "Indításkor nyissa meg a böngészőt",
|
||||
"Options": "Opciók",
|
||||
"Options": "Lehetőségek",
|
||||
"Original": "Eredeti",
|
||||
"Overview": "Áttekintés",
|
||||
"PackageVersion": "Csomagverzió",
|
||||
@@ -226,8 +224,8 @@
|
||||
"PortNumber": "Port száma",
|
||||
"PosterSize": "Poszter mérete",
|
||||
"PreviewRename": "Előnézet átnevezése",
|
||||
"Profiles": "Profil(ok)",
|
||||
"Proper": "Proper",
|
||||
"Profiles": "Profilok",
|
||||
"Proper": "Megfelelő",
|
||||
"PropersAndRepacks": "Properek és Repackok",
|
||||
"Protocol": "Protokoll",
|
||||
"ProtocolHelpText": "Válasszd ki a használni kívánt protokoll(oka)t és melyiket részesíted előnyben, ha az egyébként egyforma kiadások közül választasz",
|
||||
@@ -236,7 +234,7 @@
|
||||
"ProxyType": "Proxy Típusa",
|
||||
"ProxyUsernameHelpText": "Csak akkor kell megadnod felhasználónevet és jelszót, ha szükséges. Egyébként hagyd üresen.",
|
||||
"PublishedDate": "Közzététel dátuma",
|
||||
"Quality": "Minőség",
|
||||
"Quality": "minőség",
|
||||
"QualityDefinitions": "Minőségi meghatározások",
|
||||
"QualityProfile": "Minőségi profil",
|
||||
"QualityProfiles": "Minőségi profilok",
|
||||
@@ -247,7 +245,7 @@
|
||||
"ReadTheWikiForMoreInformation": "Olvasd el a Wiki-t további információkért",
|
||||
"ReadarrSupportsAnyIndexerThatUsesTheNewznabStandardAsWellAsOtherIndexersListedBelow": "A Radarr minden indexert támogat, amely a Newznab szabványt használja, valamint az alább felsorolt egyéb indexereket.",
|
||||
"ReadarrTags": "Radarr Címkék",
|
||||
"Real": "Valódi",
|
||||
"Real": "Igazi",
|
||||
"Reason": "Ok",
|
||||
"RecycleBinCleanupDaysHelpText": "Állítsd 0-ra az automatikus tisztítás letiltásához",
|
||||
"RecycleBinCleanupDaysHelpTextWarning": "A kiválasztott napoknál régebbi fájlok a lomtárban automatikusan törlésre kerülnek",
|
||||
@@ -289,7 +287,7 @@
|
||||
"RestartReadarr": "Radarr Újraindítása",
|
||||
"Restore": "Visszaállítás",
|
||||
"RestoreBackup": "Biztonsági mentés visszaállítása",
|
||||
"Result": "Eredmények",
|
||||
"Result": "Eredmény",
|
||||
"Retention": "Visszatartás",
|
||||
"RetentionHelpText": "Usenet: Állítsa nullára a korlátlan megőrzés beállításához",
|
||||
"RetryingDownloadInterp": "A letöltés újrapróbálása {0} itt {1}",
|
||||
@@ -347,19 +345,19 @@
|
||||
"SupportsSearchvalueSearchIsNotSupportedWithThisIndexer": "A keresés nem támogatott ezzel az Indexerrel",
|
||||
"SupportsSearchvalueWillBeUsedWhenAutomaticSearchesArePerformedViaTheUIOrByReadarr": "Akkor kerül felhasználásra, ha az automatikus kereséseket a kezelőfelületen vagy a Radarr-on keresztül hajtják végre",
|
||||
"SupportsSearchvalueWillBeUsedWhenInteractiveSearchIsUsed": "Interaktív keresés esetén is felhasználható",
|
||||
"TagIsNotUsedAndCanBeDeleted": "A címkét nincs használatban, és törölhető",
|
||||
"TagIsNotUsedAndCanBeDeleted": "A címke nincs használatban, törölhető",
|
||||
"Tasks": "Feladatok",
|
||||
"TestAll": "Összes tesztelése",
|
||||
"TestAll": "Összes Tesztelése",
|
||||
"TestAllClients": "Összes kliens tesztelése",
|
||||
"TestAllIndexers": "Indexerek tesztelése",
|
||||
"TestAllLists": "Összes lista tesztelése",
|
||||
"ThisWillApplyToAllIndexersPleaseFollowTheRulesSetForthByThem": "Ez minden indexerre vonatkozni fog, kérjük, tartsa be az általuk meghatározott szabályokat",
|
||||
"TimeFormat": "Időformátum",
|
||||
"TimeFormat": "Idő formátum",
|
||||
"Title": "Cím",
|
||||
"TorrentDelay": "Torrent késleltetés",
|
||||
"TorrentDelayHelpText": "Eltolás percekben, mielőtt a torrentkliens elkezdi a letöltést",
|
||||
"Torrents": "Torrentek",
|
||||
"TotalFileSize": "Teljes fájl méret",
|
||||
"TotalFileSize": "Összesített fájlméret",
|
||||
"UILanguage": "Felület nyelve",
|
||||
"UILanguageHelpText": "A Radarr által a felhasználói felülethez használt nyelv",
|
||||
"UILanguageHelpTextWarning": "Böngésző újratöltése szükséges",
|
||||
@@ -397,10 +395,10 @@
|
||||
"60MinutesSixty": "60 Perc: {0}",
|
||||
"APIKey": "API Kulcs",
|
||||
"About": "Névjegy",
|
||||
"AddListExclusion": "Kizárási Lista Hozzáadása",
|
||||
"AddListExclusion": "Listakizárás hozzáadása",
|
||||
"AddingTag": "Címke hozzáadása",
|
||||
"AgeWhenGrabbed": "Kora (mikor hozzáadásra került)",
|
||||
"AlreadyInYourLibrary": "Már hozzáadtad",
|
||||
"AgeWhenGrabbed": "Életkor (amikor megragadták)",
|
||||
"AlreadyInYourLibrary": "Már a könyvtárban",
|
||||
"UnableToLoadRemotePathMappings": "Nem lehet betölteni a Távoli útvonal-hozzárendeléseket",
|
||||
"None": "Nincs",
|
||||
"UnableToLoadRootFolders": "Nem lehet betölteni a gyökérmappákat",
|
||||
@@ -686,7 +684,7 @@
|
||||
"ExistingItems": "Meglévő elemek",
|
||||
"SeriesTotal": "Sorozat ({0})",
|
||||
"TooManyBooks": "Hiányzik valamelyik, vagy túl sok a könyv? Módosíts vagy hozzon létre újat",
|
||||
"BlocklistRelease": "Feketelistás Kiadás",
|
||||
"BlocklistRelease": "Blokklista Release",
|
||||
"NoHistoryBlocklist": "Nincs blokkolási előzménylista",
|
||||
"Blocklist": "Feketelista",
|
||||
"RemoveFromBlocklist": "Eltávolítás a feketelistáról",
|
||||
@@ -723,7 +721,7 @@
|
||||
"UseCalibreContentServer": "Használja a Calibre Tartalomkiszolgálót",
|
||||
"All": "Összes",
|
||||
"Wanted": "Keresett",
|
||||
"Disabled": "Letiltott",
|
||||
"Disabled": "Tiltva",
|
||||
"OnAuthorDelete": "A Szerző törlésekor",
|
||||
"OnAuthorDeleteHelpText": "A Szerző törlésekor",
|
||||
"OnBookDelete": "A könyv törlésekor",
|
||||
@@ -784,7 +782,7 @@
|
||||
"IndexerRssHealthCheckNoIndexers": "Nincs elérhető indexer RSS szinkronizálással, így a Readarr nem fogja automatikusan megragadni az új kiadásokat",
|
||||
"IndexerSearchCheckNoAvailableIndexersMessage": "Az összes keresésre képes indexer átmenetileg nem elérhető, a legutóbbi indexelő hibák miatt",
|
||||
"Lists": "Listák",
|
||||
"Metadata": "Metaadat(ok)",
|
||||
"Metadata": "metaadat",
|
||||
"Monitor": "Monitorozni",
|
||||
"MountCheckMessage": "A szerzőt tartalmazó mappa csak olvasható: ",
|
||||
"Queued": "Sorba helyezve",
|
||||
@@ -860,7 +858,7 @@
|
||||
"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",
|
||||
"ChooseImportMethod": "Importálási mód kiválasztása",
|
||||
"ClickToChangeReleaseGroup": "Kiadási csoport módosítása",
|
||||
"ClickToChangeReleaseGroup": "Kattintson a kiadási csoport módosításához",
|
||||
"HardlinkCopyFiles": "Hardlinkelés/Fájl(ok) Másolása",
|
||||
"MoveFiles": "Fájl(ok) mozgatása",
|
||||
"OnApplicationUpdate": "Alkalmazásfrissítésről",
|
||||
@@ -924,16 +922,16 @@
|
||||
"RemoveFailedDownloads": "Sikertelen letöltések eltávolítása",
|
||||
"SetTags": "Címkék beállítása",
|
||||
"Yes": "Igen",
|
||||
"BlocklistReleases": "Feketelistás Kiadás",
|
||||
"BlocklistReleases": "Feketelista kiadása",
|
||||
"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",
|
||||
"RedownloadFailed": "Letöltés Sikertelen",
|
||||
"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é.",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Címkék alkalmazása a kiválasztott letöltési kliensekre",
|
||||
"ApplyChanges": "Változások alkalmazása",
|
||||
"ApplyTagsHelpTextAdd": "Hozzáadás: Új címkék hozzáadása a meglévő címkékhez",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Hogyan adjunk hozzá címkéket a kiválasztott filmhez",
|
||||
"ApplyTagsHelpTextAdd": "Hozzáadás: Adja hozzá a címkéket a meglévő címkék listájához",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Címkék alkalmazása a kiválasztott importlistákra",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Címkék alkalmazása a kiválasztott indexelőkre",
|
||||
"ApplyTagsHelpTextRemove": "Eltávolítás: Távolítsa el a beírt címkéket",
|
||||
"CountIndexersSelected": "{0} Indexelő(k) kiválasztva",
|
||||
"DeleteConditionMessageText": "Biztosan törölni akarod a '{0}' feltételt?",
|
||||
@@ -959,7 +957,7 @@
|
||||
"NoResultsFound": "Nem eredményezett találatot",
|
||||
"SomeResultsAreHiddenByTheAppliedFilter": "Néhány találat nem látható az alkalmazott szűrők miatt",
|
||||
"System": "Rendszer",
|
||||
"TotalSpace": "Összes szabad hely",
|
||||
"TotalSpace": "Összesített terület",
|
||||
"Ui": "Felület",
|
||||
"ConnectionLost": "Kapcsolódás Elveszett",
|
||||
"ConnectionLostReconnect": "A Radarr megpróbál automatikusan csatlakozni, vagy kattints a frissítés gombra.",
|
||||
@@ -971,11 +969,16 @@
|
||||
"LastExecution": "Utolsó végrehajtás",
|
||||
"LastWriteTime": "Utolsó írási idő",
|
||||
"Library": "Könyvtár",
|
||||
"Location": "Lokáció",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Az alkalmazott szűrők miatt, az összes keresési eredmény rejtve marad",
|
||||
"Location": "Elhelyezkedés",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Az összes eredményt elrejti az alkalmazott szűrő",
|
||||
"Activity": "Aktivitás",
|
||||
"AddNew": "Új hozzáadása",
|
||||
"Backup": "Biztonsági Mentés",
|
||||
"Backup": "biztonsági mentés",
|
||||
"Medium": "Közepes",
|
||||
"AutoAdd": "Automatikus hozzáadás"
|
||||
"AutoAdd": "Automatikus hozzáadás",
|
||||
"ExtraFileExtensionsHelpText": "Az importálandó extra fájlok vesszővel lesznek elválasztva (.nfo .nfo-orig néven lesz importálva)",
|
||||
"ExtraFileExtensionsHelpTextsExamples": "Például: '.sub, .nfo' vagy 'sub, nfo'",
|
||||
"Implementation": "Végrehajtás",
|
||||
"Clone": "Klón",
|
||||
"AppUpdated": "{appName} frissítve"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"Actions": "Tindakan",
|
||||
"AgeWhenGrabbed": "Usia (saat diperoleh)",
|
||||
"All": "Semua",
|
||||
"AlreadyInYourLibrary": "Sudah ada di pustaka kamu",
|
||||
"AlreadyInYourLibrary": "Sudah di pustakamu",
|
||||
"Analytics": "Analitik",
|
||||
"AnalyticsEnabledHelpText": "Kirimkan informasi penggunaan secara anonim ke server Radarr. Informasi tersebut mengandung browser kamu, halaman WebUI Radarr yang kamu gunakan, pelaporan masalah serta OS dan versi runtime. Kami akan memanfaatkan informasi ini untuk memprioritaskan fitur dan perbaikan bug.",
|
||||
"ApplicationURL": "URL Aplikasi",
|
||||
@@ -28,7 +28,7 @@
|
||||
"ClickToChangeQuality": "Klik untuk mengubah kualitas",
|
||||
"AlternateTitles": "Judul Lain",
|
||||
"AppDataDirectory": "Direktori AppData",
|
||||
"Connections": "Koleksi",
|
||||
"Connections": "Koneksi",
|
||||
"ExportCustomFormat": "Tambahkan Format Khusus",
|
||||
"AuthorClickToChangeBook": "Klik untuk mengubah film",
|
||||
"Automatic": "Otomatis",
|
||||
@@ -38,7 +38,7 @@
|
||||
"EnableRSS": "Aktifkan RSS",
|
||||
"MetadataSource": "Sumber Metadata",
|
||||
"Language": "Bahasa",
|
||||
"LogFiles": "Berkas Log",
|
||||
"LogFiles": "File Log",
|
||||
"MediaManagement": "Pengelolaan Media",
|
||||
"Metadata": "Metadata",
|
||||
"Queue": "Antrean",
|
||||
@@ -67,7 +67,23 @@
|
||||
"Activity": "Aktivitas",
|
||||
"Backup": "Cadangan",
|
||||
"ConnectionLost": "Koneksi Terputus",
|
||||
"ConnectionLostReconnect": "Radarr akan mencoba untuk menghubungi secara otomatis, atau klik muat ulang di bawah.",
|
||||
"ConnectionLostReconnect": "{appName} akan mencoba untuk menghubungkan secara otomatis, atau silakan klik muat ulang di bawah.",
|
||||
"SomeResultsAreHiddenByTheAppliedFilter": "Seluruh hasil disembunyikan karena penyaringan yang diterapkan",
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Seluruh hasil disembunyikan karena penyaringan yang diterapkan"
|
||||
"AllResultsAreHiddenByTheAppliedFilter": "Seluruh hasil disembunyikan karena penyaringan yang diterapkan",
|
||||
"Today": "Hari Ini",
|
||||
"TotalFileSize": "Jumlah Ukuran File",
|
||||
"Unmonitored": "Tidak Dimonitor",
|
||||
"ConnectSettings": "Pengaturan Koneksi",
|
||||
"Yesterday": "Kemarin",
|
||||
"ClickToChangeReleaseGroup": "Klik untuk mengubah rilis grup",
|
||||
"Connect": "Koneksi",
|
||||
"Continuing": "Berlanjut",
|
||||
"Edit": "Edit",
|
||||
"Files": "File",
|
||||
"AddNew": "Tambah",
|
||||
"Search": "Cari",
|
||||
"Refresh": "Muat Ulang",
|
||||
"ConnectionLostToBackend": "Koneksi {appName} telah terputus dari backend dan perlu dimuat ulang untuk dipulihkan.",
|
||||
"ApplyChanges": "Terapkan Perubahan",
|
||||
"History": "Riwayat"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user