Translate Activity pages

This commit is contained in:
Stevie Robinson 2023-08-05 22:59:07 +02:00 committed by Mark McDowall
parent 02b0710814
commit 322836e2b3
17 changed files with 180 additions and 106 deletions

View File

@ -15,6 +15,7 @@ import TablePager from 'Components/Table/TablePager';
import { align, icons, kinds } from 'Helpers/Props';
import getRemovedItems from 'Utilities/Object/getRemovedItems';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import translate from 'Utilities/String/translate';
import getSelectedIds from 'Utilities/Table/getSelectedIds';
import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
import selectAll from 'Utilities/Table/selectAll';
@ -116,11 +117,11 @@ class Blocklist extends Component {
const selectedIds = this.getSelectedIds();
return (
<PageContent title="Blocklist">
<PageContent title={translate('Blocklist')}>
<PageToolbar>
<PageToolbarSection>
<PageToolbarButton
label="Remove Selected"
label={translate('RemoveSelected')}
iconName={icons.REMOVE}
isDisabled={!selectedIds.length}
isSpinning={isRemoving}
@ -128,7 +129,7 @@ class Blocklist extends Component {
/>
<PageToolbarButton
label="Clear"
label={translate('Clear')}
iconName={icons.CLEAR}
isSpinning={isClearingBlocklistExecuting}
onPress={onClearBlocklistPress}
@ -141,7 +142,7 @@ class Blocklist extends Component {
columns={columns}
>
<PageToolbarButton
label="Options"
label={translate('Options')}
iconName={icons.TABLE}
/>
</TableOptionsModalWrapper>
@ -156,13 +157,15 @@ class Blocklist extends Component {
{
!isFetching && !!error &&
<Alert kind={kinds.DANGER}>Unable to load blocklist</Alert>
<Alert kind={kinds.DANGER}>
{translate('BlocklistLoadError')}
</Alert>
}
{
isPopulated && !error && !items.length &&
<Alert kind={kinds.INFO}>
No history blocklist
{translate('NoHistoryBlocklist')}
</Alert>
}
@ -206,9 +209,9 @@ class Blocklist extends Component {
<ConfirmModal
isOpen={isConfirmRemoveModalOpen}
kind={kinds.DANGER}
title="Remove Selected"
message={'Are you sure you want to remove the selected items from the blocklist?'}
confirmLabel="Remove Selected"
title={translate('RemoveSelected')}
message={translate('RemoveSelectedBlocklistMessageText')}
confirmLabel={translate('RemoveSelected')}
onConfirm={this.onRemoveSelectedConfirmed}
onCancel={this.onConfirmRemoveModalClose}
/>

View File

@ -8,6 +8,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';
class BlocklistDetailsModal extends Component {
@ -39,19 +40,19 @@ class BlocklistDetailsModal extends Component {
<ModalBody>
<DescriptionList>
<DescriptionListItem
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
<DescriptionListItem
title="Protocol"
title={translate('Protocol')}
data={protocol}
/>
{
!!message &&
<DescriptionListItem
title="Indexer"
title={translate('Indexer')}
data={indexer}
/>
}
@ -59,7 +60,7 @@ class BlocklistDetailsModal extends Component {
{
!!message &&
<DescriptionListItem
title="Message"
title={translate('Message')}
data={message}
/>
}
@ -68,7 +69,7 @@ class BlocklistDetailsModal extends Component {
<ModalFooter>
<Button onPress={onModalClose}>
Close
{translate('Close')}
</Button>
</ModalFooter>
</ModalContent>

View File

@ -10,6 +10,7 @@ import EpisodeLanguages from 'Episode/EpisodeLanguages';
import EpisodeQuality from 'Episode/EpisodeQuality';
import { icons, kinds } from 'Helpers/Props';
import SeriesTitleLink from 'Series/SeriesTitleLink';
import translate from 'Utilities/String/translate';
import BlocklistDetailsModal from './BlocklistDetailsModal';
import styles from './BlocklistRow.css';
@ -164,7 +165,7 @@ class BlocklistRow extends Component {
/>
<IconButton
title="Remove from blocklist"
title={translate('RemoveFromBlocklist')}
name={icons.REMOVE}
kind={kinds.DANGER}
onPress={onRemovePress}

View File

@ -8,6 +8,7 @@ import Link from 'Components/Link/Link';
import formatDateTime from 'Utilities/Date/formatDateTime';
import formatAge from 'Utilities/Number/formatAge';
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
import translate from 'Utilities/String/translate';
import styles from './HistoryDetails.css';
function HistoryDetails(props) {
@ -41,14 +42,14 @@ function HistoryDetails(props) {
<DescriptionList>
<DescriptionListItem
descriptionClassName={styles.description}
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
{
indexer ?
<DescriptionListItem
title="Indexer"
title={translate('Indexer')}
data={indexer}
/> :
null
@ -58,7 +59,7 @@ function HistoryDetails(props) {
releaseGroup ?
<DescriptionListItem
descriptionClassName={styles.description}
title="Release Group"
title={translate('ReleaseGroup')}
data={releaseGroup}
/> :
null
@ -67,7 +68,7 @@ function HistoryDetails(props) {
{
customFormatScore && customFormatScore !== '0' ?
<DescriptionListItem
title="Custom Format Score"
title={translate('CustomFormatScore')}
data={formatCustomFormatScore(customFormatScore)}
/> :
null
@ -77,7 +78,7 @@ function HistoryDetails(props) {
seriesMatchType ?
<DescriptionListItem
descriptionClassName={styles.description}
title="Series Match Type"
title={translate('SeriesMatchType')}
data={seriesMatchType}
/> :
null
@ -87,7 +88,7 @@ function HistoryDetails(props) {
nzbInfoUrl ?
<span>
<DescriptionListItemTitle>
Info URL
{translate('InfoUrl')}
</DescriptionListItemTitle>
<DescriptionListItemDescription>
@ -100,7 +101,7 @@ function HistoryDetails(props) {
{
downloadClientNameInfo ?
<DescriptionListItem
title="Download Client"
title={translate('DownloadClient')}
data={downloadClientNameInfo}
/> :
null
@ -109,7 +110,7 @@ function HistoryDetails(props) {
{
downloadId ?
<DescriptionListItem
title="Grab ID"
title={translate('GrabId')}
data={downloadId}
/> :
null
@ -118,7 +119,7 @@ function HistoryDetails(props) {
{
age || ageHours || ageMinutes ?
<DescriptionListItem
title="Age (when grabbed)"
title={translate('AgeWhenGrabbed')}
data={formatAge(age, ageHours, ageMinutes)}
/> :
null
@ -127,7 +128,7 @@ function HistoryDetails(props) {
{
publishedDate ?
<DescriptionListItem
title="Published Date"
title={translate('PublishedDate')}
data={formatDateTime(publishedDate, shortDateFormat, timeFormat, { includeSeconds: true })}
/> :
null
@ -145,14 +146,14 @@ function HistoryDetails(props) {
<DescriptionList>
<DescriptionListItem
descriptionClassName={styles.description}
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
{
message ?
<DescriptionListItem
title="Message"
title={translate('Message')}
data={message}
/> :
null
@ -172,7 +173,7 @@ function HistoryDetails(props) {
<DescriptionList>
<DescriptionListItem
descriptionClassName={styles.description}
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
@ -180,7 +181,7 @@ function HistoryDetails(props) {
droppedPath ?
<DescriptionListItem
descriptionClassName={styles.description}
title="Source"
title={translate('Source')}
data={droppedPath}
/> :
null
@ -190,7 +191,7 @@ function HistoryDetails(props) {
importedPath ?
<DescriptionListItem
descriptionClassName={styles.description}
title="Imported To"
title={translate('ImportedTo')}
data={importedPath}
/> :
null
@ -199,7 +200,7 @@ function HistoryDetails(props) {
{
customFormatScore && customFormatScore !== '0' ?
<DescriptionListItem
title="Custom Format Score"
title={translate('CustomFormatScore')}
data={formatCustomFormatScore(customFormatScore)}
/> :
null
@ -218,13 +219,13 @@ function HistoryDetails(props) {
switch (reason) {
case 'Manual':
reasonMessage = 'File was deleted by via UI';
reasonMessage = translate('DeletedReasonManual');
break;
case 'MissingFromDisk':
reasonMessage = 'Sonarr was unable to find the file on disk so the file was unlinked from the episode in the database';
reasonMessage = translate('DeletedReasonMissingFromDisk');
break;
case 'Upgrade':
reasonMessage = 'File was deleted to import an upgrade';
reasonMessage = translate('DeletedReasonUpgrade');
break;
default:
reasonMessage = '';
@ -233,19 +234,19 @@ function HistoryDetails(props) {
return (
<DescriptionList>
<DescriptionListItem
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
<DescriptionListItem
title="Reason"
title={translate('Reason')}
data={reasonMessage}
/>
{
customFormatScore && customFormatScore !== '0' ?
<DescriptionListItem
title="Custom Format Score"
title={translate('CustomFormatScore')}
data={formatCustomFormatScore(customFormatScore)}
/> :
null
@ -265,22 +266,22 @@ function HistoryDetails(props) {
return (
<DescriptionList>
<DescriptionListItem
title="Source Path"
title={translate('SourcePath')}
data={sourcePath}
/>
<DescriptionListItem
title="Source Relative Path"
title={translate('SourceRelativePath')}
data={sourceRelativePath}
/>
<DescriptionListItem
title="Destination Path"
title={translate('DestinationPath')}
data={path}
/>
<DescriptionListItem
title="Destination Relative Path"
title={translate('DestinationRelativePath')}
data={relativePath}
/>
</DescriptionList>
@ -296,14 +297,14 @@ function HistoryDetails(props) {
<DescriptionList>
<DescriptionListItem
descriptionClassName={styles.description}
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
{
message ?
<DescriptionListItem
title="Message"
title={translate('Message')}
data={message}
/> :
null
@ -316,7 +317,7 @@ function HistoryDetails(props) {
<DescriptionList>
<DescriptionListItem
descriptionClassName={styles.description}
title="Name"
title={translate('Name')}
data={sourceTitle}
/>
</DescriptionList>

View File

@ -8,25 +8,26 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import HistoryDetails from './HistoryDetails';
import styles from './HistoryDetailsModal.css';
function getHeaderTitle(eventType) {
switch (eventType) {
case 'grabbed':
return 'Grabbed';
return translate('Grabbed');
case 'downloadFailed':
return 'Download Failed';
return translate('DownloadFailed');
case 'downloadFolderImported':
return 'Episode Imported';
return translate('EpisodeImported');
case 'episodeFileDeleted':
return 'Episode File Deleted';
return translate('EpisodeFileDeleted');
case 'episodeFileRenamed':
return 'Episode File Renamed';
return translate('EpisodeFileRenamed');
case 'downloadIgnored':
return 'Download Ignored';
return translate('DownloadIgnored');
default:
return 'Unknown';
return translate('Unknown');
}
}
@ -72,14 +73,14 @@ function HistoryDetailsModal(props) {
isSpinning={isMarkingAsFailed}
onPress={onMarkAsFailedPress}
>
Mark as Failed
{translate('MarkAsFailed')}
</SpinnerButton>
}
<Button
onPress={onModalClose}
>
Close
{translate('Close')}
</Button>
</ModalFooter>
</ModalContent>

View File

@ -14,6 +14,7 @@ import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptions
import TablePager from 'Components/Table/TablePager';
import { align, icons, kinds } from 'Helpers/Props';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import translate from 'Utilities/String/translate';
import HistoryRowConnector from './HistoryRowConnector';
class History extends Component {
@ -65,11 +66,11 @@ class History extends Component {
const hasError = error || episodesError;
return (
<PageContent title="History">
<PageContent title={translate('History')}>
<PageToolbar>
<PageToolbarSection>
<PageToolbarButton
label="Refresh"
label={translate('Refresh')}
iconName={icons.REFRESH}
isSpinning={isFetching}
onPress={onFirstPagePress}
@ -82,7 +83,7 @@ class History extends Component {
columns={columns}
>
<PageToolbarButton
label="Options"
label={translate('Options')}
iconName={icons.TABLE}
/>
</TableOptionsModalWrapper>
@ -105,7 +106,9 @@ class History extends Component {
{
!isFetchingAny && hasError &&
<Alert kind={kinds.DANGER}>Unable to load history</Alert>
<Alert kind={kinds.DANGER}>
{translate('HistoryLoadError')}
</Alert>
}
{
@ -114,7 +117,7 @@ class History extends Component {
isPopulated && !hasError && !items.length &&
<Alert kind={kinds.INFO}>
No history found
{translate('NoHistoryFound')}
</Alert>
}

View File

@ -3,6 +3,7 @@ import React from 'react';
import Icon from 'Components/Icon';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import { icons, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './HistoryEventTypeCell.css';
function getIconName(eventType) {
@ -38,21 +39,21 @@ function getIconKind(eventType) {
function getTooltip(eventType, data) {
switch (eventType) {
case 'grabbed':
return `Episode grabbed from ${data.indexer} and sent to ${data.downloadClient}`;
return translate('GrabbedHistoryTooltip', { indexer: data.indexer, downloadClient: data.downloadClient });
case 'seriesFolderImported':
return 'Episode imported from series folder';
return translate('SeriesFolderImportedTooltip');
case 'downloadFolderImported':
return 'Episode downloaded successfully and picked up from download client';
return translate('EpisodeImportedTooltip');
case 'downloadFailed':
return 'Episode download failed';
return translate('DownloadFailedTooltip');
case 'episodeFileDeleted':
return 'Episode file deleted';
return translate('EpisodeFileDeletedTooltip');
case 'episodeFileRenamed':
return 'Episode file renamed';
return translate('EpisodeFileRenamedTooltip');
case 'downloadIgnored':
return 'Episode Download Ignored';
return translate('DownloadIgnoredTooltip');
default:
return 'Unknown event';
return translate('UnknownEventTooltip');
}
}

View File

@ -16,6 +16,7 @@ import TablePager from 'Components/Table/TablePager';
import { align, icons, kinds } from 'Helpers/Props';
import getRemovedItems from 'Utilities/Object/getRemovedItems';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import translate from 'Utilities/String/translate';
import getSelectedIds from 'Utilities/Table/getSelectedIds';
import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
import selectAll from 'Utilities/Table/selectAll';
@ -175,7 +176,7 @@ class Queue extends Component {
const disableSelectedActions = selectedCount === 0;
return (
<PageContent title="Queue">
<PageContent title={translate('Queue')}>
<PageToolbar>
<PageToolbarSection>
<PageToolbarButton
@ -188,7 +189,7 @@ class Queue extends Component {
<PageToolbarSeparator />
<PageToolbarButton
label="Grab Selected"
label={translate('GrabSelected')}
iconName={icons.DOWNLOAD}
isDisabled={disableSelectedActions || !isPendingSelected}
isSpinning={isGrabbing}
@ -196,7 +197,7 @@ class Queue extends Component {
/>
<PageToolbarButton
label="Remove Selected"
label={translate('RemoveSelected')}
iconName={icons.REMOVE}
isDisabled={disableSelectedActions}
isSpinning={isRemoving}
@ -213,7 +214,7 @@ class Queue extends Component {
optionsComponent={QueueOptionsConnector}
>
<PageToolbarButton
label="Options"
label={translate('Options')}
iconName={icons.TABLE}
/>
</TableOptionsModalWrapper>
@ -230,7 +231,7 @@ class Queue extends Component {
{
!isRefreshing && hasError ?
<Alert kind={kinds.DANGER}>
Failed to load Queue
{translate('QueueLoadError')}
</Alert> :
null
}
@ -238,7 +239,7 @@ class Queue extends Component {
{
isAllPopulated && !hasError && !items.length ?
<Alert kind={kinds.INFO}>
Queue is empty
{translate('QueueIsEmpty')}
</Alert> :
null
}

View File

@ -3,6 +3,7 @@ import React from 'react';
import Icon from 'Components/Icon';
import Popover from 'Components/Tooltip/Popover';
import { icons, tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import QueueStatus from './QueueStatus';
import styles from './QueueDetails.css';
@ -30,7 +31,7 @@ function QueueDetails(props) {
!hasWarning &&
!hasError
) {
const state = isPaused ? 'Paused' : 'Downloading';
const state = isPaused ? translate('Paused') : translate('Downloading');
if (progress < 5) {
return (

View File

@ -4,6 +4,7 @@ import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import { inputTypes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
class QueueOptions extends Component {
@ -54,13 +55,13 @@ class QueueOptions extends Component {
return (
<Fragment>
<FormGroup>
<FormLabel>Show Unknown Series Items</FormLabel>
<FormLabel>{translate('ShowUnknownSeriesItems')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="includeUnknownSeriesItems"
value={includeUnknownSeriesItems}
helpText="Show items without a series in the queue, this could include removed series, movies or anything else in Sonarr's category"
helpText={translate('ShownUnknownSeriesItemsHelpText')}
onChange={this.onOptionChange}
/>
</FormGroup>

View File

@ -19,6 +19,7 @@ import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
import SeriesTitleLink from 'Series/SeriesTitleLink';
import formatBytes from 'Utilities/Number/formatBytes';
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
import translate from 'Utilities/String/translate';
import QueueStatusCell from './QueueStatusCell';
import RemoveQueueItemModal from './RemoveQueueItemModal';
import TimeleftCell from './TimeleftCell';
@ -386,7 +387,7 @@ class QueueRow extends Component {
}
<SpinnerIconButton
title="Remove from queue"
title={translate('RemoveFromQueue')}
name={icons.REMOVE}
isSpinning={isRemoving}
onPress={this.onRemoveQueueItemPress}

View File

@ -3,6 +3,7 @@ import React from 'react';
import Icon from 'Components/Icon';
import Popover from 'Components/Tooltip/Popover';
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './QueueStatus.css';
function getDetailedPopoverBody(statusMessages) {
@ -53,34 +54,34 @@ function QueueStatus(props) {
// status === 'downloading'
let iconName = icons.DOWNLOADING;
let iconKind = kinds.DEFAULT;
let title = 'Downloading';
let title = translate('Downloading');
if (status === 'paused') {
iconName = icons.PAUSED;
title = 'Paused';
title = translate('Paused');
}
if (status === 'queued') {
iconName = icons.QUEUED;
title = 'Queued';
title = translate('Queued');
}
if (status === 'completed') {
iconName = icons.DOWNLOADED;
title = 'Downloaded';
title = translate('Downloaded');
if (trackedDownloadState === 'importPending') {
title += ' - Waiting to Import';
title += ` - ${translate('WaitingToImport')}`;
iconKind = kinds.PURPLE;
}
if (trackedDownloadState === 'importing') {
title += ' - Importing';
title += ` - ${translate('Importing')}`;
iconKind = kinds.PURPLE;
}
if (trackedDownloadState === 'failedPending') {
title += ' - Waiting to Process';
title += ` - ${translate('WaitingToProcess')}`;
iconKind = kinds.DANGER;
}
}
@ -91,36 +92,37 @@ function QueueStatus(props) {
if (status === 'delay') {
iconName = icons.PENDING;
title = 'Pending';
title = translate('Pending');
}
if (status === 'downloadClientUnavailable') {
iconName = icons.PENDING;
iconKind = kinds.WARNING;
title = 'Pending - Download client is unavailable';
title = translate('PendingDownloadClientUnavailable');
}
if (status === 'failed') {
iconName = icons.DOWNLOADING;
iconKind = kinds.DANGER;
title = 'Download failed';
title = translate('DownloadFailed');
}
if (status === 'warning') {
iconName = icons.DOWNLOADING;
iconKind = kinds.WARNING;
title = `Download warning: ${errorMessage || 'check download client for more details'}`;
const warningMessage = errorMessage || translate('CheckDownloadClientForDetails');
title = translate('DownloadWarning', { warningMessage });
}
if (hasError) {
if (status === 'completed') {
iconName = icons.DOWNLOAD;
iconKind = kinds.DANGER;
title = `Import failed: ${sourceTitle}`;
title = translate('ImportFailed', { sourceTitle });
} else {
iconName = icons.DOWNLOADING;
iconKind = kinds.DANGER;
title = 'Download failed';
title = translate('DownloadFailed');
}
}
@ -152,8 +154,8 @@ QueueStatus.propTypes = {
};
QueueStatus.defaultProps = {
trackedDownloadStatus: 'Ok',
trackedDownloadState: 'Downloading',
trackedDownloadStatus: translate('Ok'),
trackedDownloadState: translate('Downloading'),
canFlip: false
};

View File

@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import { tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import QueueStatus from './QueueStatus';
import styles from './QueueStatusCell.css';
@ -40,8 +41,8 @@ QueueStatusCell.propTypes = {
};
QueueStatusCell.defaultProps = {
trackedDownloadStatus: 'Ok',
trackedDownloadState: 'Downloading'
trackedDownloadStatus: translate('Ok'),
trackedDownloadState: translate('Downloading')
};
export default QueueStatusCell;

View File

@ -88,25 +88,25 @@ class RemoveQueueItemModal extends Component {
onModalClose={this.onModalClose}
>
<ModalHeader>
Remove - {sourceTitle}
{translate('RemoveQueueItem', { sourceTitle })}
</ModalHeader>
<ModalBody>
<div>
Are you sure you want to remove '{sourceTitle}' from the queue?
{translate('RemoveQueueItemConfirmation', { sourceTitle })}
</div>
{
isPending ?
null :
<FormGroup>
<FormLabel>Remove From Download Client</FormLabel>
<FormLabel>{translate('RemoveFromDownloadClient')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="remove"
value={remove}
helpTextWarning="Removing will remove the download and the file(s) from the download client."
helpTextWarning={translate('RemoveHelpTextWarning')}
isDisabled={!canIgnore}
onChange={this.onRemoveChange}
/>
@ -114,13 +114,13 @@ class RemoveQueueItemModal extends Component {
}
<FormGroup>
<FormLabel>Add Release To Blocklist</FormLabel>
<FormLabel>{translate('BlocklistRelease')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="blocklist"
value={blocklist}
helpText="Starts a search for this episode again and prevents this release from being grabbed again"
helpText={translate('BlocklistReleaseHelpText')}
onChange={this.onBlocklistChange}
/>
</FormGroup>
@ -143,14 +143,14 @@ class RemoveQueueItemModal extends Component {
<ModalFooter>
<Button onPress={this.onModalClose}>
Close
{translate('Close')}
</Button>
<Button
kind={kinds.DANGER}
onPress={this.onRemoveConfirmed}
>
Remove
{translate('Remove')}
</Button>
</ModalFooter>
</ModalContent>

View File

@ -94,7 +94,7 @@ class RemoveQueueItemsModal extends Component {
<ModalBody>
<div className={styles.message}>
{selectedCount > 1 ? translate('RemoveSelectedItemsQueueMessageText', selectedCount) : translate('RemoveSelectedItemQueueMessageText')}
{selectedCount > 1 ? translate('RemoveSelectedItemsQueueMessageText', { selectedCount }) : translate('RemoveSelectedItemQueueMessageText')}
</div>
{

View File

@ -5,6 +5,7 @@ import formatTime from 'Utilities/Date/formatTime';
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
import formatBytes from 'Utilities/Number/formatBytes';
import translate from 'Utilities/String/translate';
import styles from './TimeleftCell.css';
function TimeleftCell(props) {
@ -26,7 +27,7 @@ function TimeleftCell(props) {
return (
<TableRowCell
className={styles.timeleft}
title={`Delaying download until ${date} at ${time}`}
title={translate('DelayingDownloadUntil', { date, time })}
>
-
</TableRowCell>
@ -40,7 +41,7 @@ function TimeleftCell(props) {
return (
<TableRowCell
className={styles.timeleft}
title={`Retrying download ${date} at ${time}`}
title={translate('RetryingDownload', { date, time })}
>
-
</TableRowCell>

View File

@ -45,6 +45,7 @@
"AddingTag": "Adding tag",
"AfterManualRefresh": "After Manual Refresh",
"Age": "Age",
"AgeWhenGrabbed": "Age (when grabbed)",
"AirDate": "Air Date",
"All": "All",
"AllResultsAreHiddenByTheAppliedFilter": "All results are hidden by the applied filter",
@ -107,7 +108,7 @@
"Blocklist": "Blocklist",
"BlocklistLoadError": "Unable to load blocklist",
"BlocklistRelease": "Blocklist Release",
"BlocklistReleaseHelpText": "Prevents Sonarr from automatically grabbing this release again",
"BlocklistReleaseHelpText": "Starts a search for this episode again and prevents this release from being grabbed again",
"BlocklistReleases": "Blocklist Releases",
"Branch": "Branch",
"BranchUpdate": "Branch to use to update Sonarr",
@ -131,6 +132,7 @@
"Certification": "Certification",
"ChangeFileDate": "Change File Date",
"ChangeFileDateHelpText": "Change file date on import/rescan",
"CheckDownloadClientForDetails": "check download client for more details",
"ChmodFolder": "chmod Folder",
"ChmodFolderHelpText": "Octal, applied during import/rename to media folders and files (without execute bits)",
"ChmodFolderHelpTextWarning": "This only works if the user running sonarr is the owner of the file. It's better to ensure the download client sets the permissions properly.",
@ -199,6 +201,7 @@
"DelayProfileTagsHelpText": "Applies to series with at least one matching tag",
"DelayProfiles": "Delay Profiles",
"DelayProfilesLoadError": "Unable to load Delay Profiles",
"DelayingDownloadUntil": "Delaying download until {date} at {time}",
"Delete": "Delete",
"DeleteAutoTag": "Delete Auto Tag",
"DeleteAutoTagHelpText": "Are you sure you want to delete the auto tag '{name}'?",
@ -241,6 +244,11 @@
"DeleteTag": "DeleteTag",
"DeleteTagMessageText": "Are you sure you want to delete the tag '{label}'?",
"Deleted": "Deleted",
"DeletedReasonManual": "File was deleted by via UI",
"DeletedReasonMissingFromDisk": "Sonarr was unable to find the file on disk so the file was unlinked from the episode in the database",
"DeletedReasonUpgrade": "File was deleted to import an upgrade",
"DestinationPath": "Destination Path",
"DestinationRelativePath": "Destination Relative Path",
"Details": "Details",
"Disabled": "Disabled",
"DisabledForLocalAddresses": "Disabled for Local Addresses",
@ -267,10 +275,17 @@
"DownloadClients": "Download Clients",
"DownloadClientsLoadError": "Unable to load download clients",
"DownloadClientsSettingsSummary": "Download clients, download handling and remote path mappings",
"DownloadFailed": "Download Failed",
"DownloadFailedTooltip": "Episode download failed",
"DownloadIgnored": "Download Ignored",
"DownloadIgnoredTooltip": "Episode Download Ignored",
"DownloadPropersAndRepacks": "Propers and Repacks",
"DownloadPropersAndRepacksHelpText": "Whether or not to automatically upgrade to Propers/Repacks",
"DownloadPropersAndRepacksHelpTextCustomFormat": "Use 'Do not Prefer' to sort by custom format score over Propers/Repacks",
"DownloadPropersAndRepacksHelpTextWarning": "Use custom formats for automatic upgrades to Propers/Repacks",
"DownloadWarning": "Download warning: {warningMessage}",
"Downloaded": "Downloaded",
"Downloading": "Downloading",
"Duplicate": "Duplicate",
"Duration": "Duration",
"Edit": "Edit",
@ -320,6 +335,12 @@
"Episode": "Episode",
"EpisodeAirDate": "Episode Air Date",
"EpisodeCount": "Episode Count",
"EpisodeFileDeleted": "Episode File Deleted",
"EpisodeFileDeletedTooltip": "Episode file deleted",
"EpisodeFileRenamed": "Episode File Renamed",
"EpisodeFileRenamedTooltip": "Episode file renamed",
"EpisodeImported": "Episode Imported",
"EpisodeImportedTooltip": "Episode downloaded successfully and picked up from download client",
"EpisodeInfo": "Episode Info",
"EpisodeNaming": "Episode Naming",
"EpisodeNumbers": "Episode Number(s)",
@ -365,7 +386,10 @@
"GeneralSettingsLoadError": "Unable to load General settings",
"GeneralSettingsSummary": "Port, SSL, username/password, proxy, analytics and updates",
"Genres": "Genres",
"GrabId": "Grab ID",
"GrabSelected": "Grab Selected",
"Grabbed": "Grabbed",
"GrabbedHistoryTooltip": "Episode grabbed from {indexer} and sent to {downloadClient}",
"Group": "Group",
"HasMissingSeason": "Has Missing Season",
"Health": "Health",
@ -392,6 +416,7 @@
"ImportExistingSeries": "Import Existing Series",
"ImportExtraFiles": "Import Extra Files",
"ImportExtraFilesHelpText": "Import matching extra files (subtitles, nfo, etc) after importing an episode file",
"ImportFailed": "Import Failed: {sourceTitle}",
"ImportList": "Import List",
"ImportListExclusions": "Import List Exclusions",
"ImportListExclusionsLoadError": "Unable to load Import List Exclusions",
@ -412,6 +437,7 @@
"ImportUsingScript": "Import Using Script",
"ImportUsingScriptHelpText": "Copy files for importing using a script (ex. for transcoding)",
"Imported": "Imported",
"ImportedTo": "Imported To",
"Importing": "Importing",
"IncludeCustomFormatWhenRenaming": "Include Custom Format when Renaming",
"IncludeCustomFormatWhenRenamingHelpText": "Include in {Custom Formats} renaming format",
@ -439,6 +465,7 @@
"IndexersLoadError": "Unable to load Indexers",
"IndexersSettingsSummary": "Indexers and indexer options",
"Info": "Info",
"InfoUrl": "Info URL",
"InstallLatest": "Install Latest",
"InstanceName": "Instance Name",
"InstanceNameHelpText": "Instance name in tab and for Syslog app name",
@ -487,6 +514,7 @@
"ManageLists": "Manage Lists",
"Manual": "Manual",
"ManualImportItemsLoadError": "Unable to load manual import items",
"MarkAsFailed": "Mark as Failed",
"MatchedToEpisodes": "Matched to Episodes",
"MatchedToSeason": "Matched to Season",
"MatchedToSeries": "Matched to Series",
@ -577,6 +605,8 @@
"NoDelay": "No Delay",
"NoDownloadClientsFound": "No download clients found",
"NoEventsFound": "No events found",
"NoHistoryBlocklist": "No history blocklist",
"NoHistoryFound": "No history found",
"NoImportListsFound": "No import lists found",
"NoIndexersFound": "No indexers found",
"NoIssuesWithYourConfiguration": "No issues with your configuration",
@ -597,6 +627,7 @@
"NotificationTriggersHelpText": "Select which events should trigger this notification",
"NotificationsLoadError": "Unable to load Notifications",
"NotificationsTagsHelpText": "Only send notifications for series with at least one matching tag",
"Ok": "Ok",
"OnApplicationUpdate": "On Application Update",
"OnEpisodeFileDelete": "On Episode File Delete",
"OnEpisodeFileDeleteForUpgrade": "On Episode File Delete For Upgrade",
@ -628,10 +659,13 @@
"PartialSeason": "Partial Season",
"Password": "Password",
"Path": "Path",
"Paused": "Paused",
"Peers": "Peers",
"Pending": "Pending",
"PendingChangesDiscardChanges": "Discard changes and leave",
"PendingChangesMessage": "You have unsaved changes, are you sure you want to leave this page?",
"PendingChangesStayReview": "Stay and review changes",
"PendingDownloadClientUnavailable": "Pending - Download client is unavailable",
"Period": "Period",
"Permissions": "Permissions",
"PortNumber": "Port Number",
@ -664,6 +698,7 @@
"ProxyResolveIpHealthCheckMessage": "Failed to resolve the IP Address for the Configured Proxy Host {0}",
"ProxyType": "Proxy Type",
"ProxyUsernameHelpText": "You only need to enter a username and password if one is required. Leave them blank otherwise.",
"PublishedDate": "Published Date",
"Qualities": "Qualities",
"QualitiesHelpText": "Qualities higher in the list are more preferred. Qualities within the same group are equal. Only checked qualities are wanted",
"QualitiesLoadError": "Unable to load qualities",
@ -678,11 +713,14 @@
"QualitySettings": "Quality Settings",
"QualitySettingsSummary": "Quality sizes and naming",
"Queue": "Queue",
"QueueIsEmpty": "Queue is empty",
"QueueLoadError": "Failed to load Queue",
"Queued": "Queued",
"Range": "Range",
"Rating": "Rating",
"ReadTheWikiForMoreInformation": "Read the Wiki for more information",
"Real": "Real",
"Reason": "Reason",
"RecycleBinUnableToWriteHealthCheckMessage": "Unable to write to configured recycling bin folder: {0}. Ensure this path exists and is writable by the user running Sonarr",
"RecyclingBin": "Recycling Bin",
"RecyclingBinCleanup": "Recycling Bin Cleanup",
@ -738,13 +776,19 @@
"RemoveFailed": "Remove Failed",
"RemoveFailedDownloads": "Remove Failed Downloads",
"RemoveFailedDownloadsHelpText": "Remove failed downloads from download client history",
"RemoveFromBlocklist": "Remove from Blocklist",
"RemoveFromDownloadClient": "Remove From Download Client",
"RemoveFromDownloadClientHelpTextWarning": "Removing will remove the download and the file(s) from the download client.",
"RemoveFromQueue": "Remove from queue",
"RemoveQueueItem": "Remove - {sourceTitle}",
"RemoveQueueItemConfirmation": "Are you sure you want to remove '{sourceTitle}' from the queue?",
"RemoveRootFolder": "Remove root folder",
"RemoveSelected": "Remove Selected",
"RemoveSelectedBlocklistMessageText": "Are you sure you want to remove the selected items from the blocklist?",
"RemoveSelectedItem": "Remove Selected Item",
"RemoveSelectedItemQueueMessageText": "Are you sure you want to remove 1 item from the queue?",
"RemoveSelectedItems": "Remove Selected Items",
"RemoveSelectedItemsQueueMessageText": "Are you sure you want to remove {0} items from the queue?",
"RemoveSelectedItemsQueueMessageText": "Are you sure you want to remove {selectedCount} items from the queue?",
"RemoveTagsAutomatically": "Remove Tags Automatically",
"RemoveTagsAutomaticallyHelpText": "Remove tags automatically if conditions are not met",
"RemovedFromTaskQueue": "Removed from task queue",
@ -790,6 +834,7 @@
"Result": "Result",
"Retention": "Retention",
"RetentionHelpText": "Usenet only: Set to zero to set for unlimited retention",
"RetryingDownloadOn": "Retrying download on {date} at {time}",
"RootFolder": "Root Folder",
"RootFolderLoadError": "Unable to add root folder",
"RootFolderMissingHealthCheckMessage": "Missing root folder: {0}",
@ -832,8 +877,10 @@
"SeriesEditor": "Series Editor",
"SeriesFolderFormat": "Series Folder Format",
"SeriesFolderFormatHelpText": "Used when adding a new series or moving series via the series editor",
"SeriesFolderImportedTooltip": "Episode imported from series folder",
"SeriesID": "Series ID",
"SeriesLoadError": "Unable to load Series",
"SeriesMatchType": "Series Match Type",
"SeriesTitle": "Series Title",
"SeriesTitleToExcludeHelpText": "The name of the series to exclude",
"SeriesType": "Series Type",
@ -849,6 +896,8 @@
"ShowRelativeDates": "Show Relative Dates",
"ShowRelativeDatesHelpText": "Show relative (Today/Yesterday/etc) or absolute dates",
"ShownClickToHide": "Shown, click to hide",
"ShownUnknownSeriesItems": "Show Unknown Series Items",
"ShownUnknownSeriesItemsHelpText": "Show items without a series in the queue, this could include removed series, movies or anything else in Sonarr's category",
"SingleEpisode": "Single Episode",
"SingleEpisodeInvalidFormat": "Single Episode: Invalid Format",
"Size": "Size",
@ -865,6 +914,8 @@
"SomeResultsAreHiddenByTheAppliedFilter": "Some results are hidden by the applied filter",
"SonarrTags": "Sonarr Tags",
"Source": "Source",
"SourcePath": "Source Path",
"SourceRelativePath": "Source Relative Path",
"SourceTitle": "Source Title",
"Space": "Space",
"Special": "Special",
@ -942,6 +993,8 @@
"Unavailable": "Unavailable",
"Underscore": "Underscore",
"Ungroup": "Ungroup",
"Unknown": "Unknown",
"UnknownEventTooltip": "Unknown event",
"Unlimited": "Unlimited",
"UnmappedFolders": "Unmapped Folders",
"UnmonitorDeletedEpisodes": "Unmonitor Deleted Episodes",
@ -987,6 +1040,8 @@
"VideoCodec": "Video Codec",
"VideoDynamicRange": "Video Dynamic Range",
"VisitTheWikiForMoreDetails": "Visit the wiki for more details: ",
"WaitingToImport": "Waiting to Import",
"WaitingToProcess": "Waiting to Process",
"WantMoreControlAddACustomFormat": "Want more control over which downloads are preferred? Add a [Custom Format](/settings/customformats)",
"Wanted": "Wanted",
"Warn": "Warn",