diff --git a/frontend/src/Components/Icon.js b/frontend/src/Components/Icon.js index 8c534d8d4..90842b039 100644 --- a/frontend/src/Components/Icon.js +++ b/frontend/src/Components/Icon.js @@ -43,7 +43,7 @@ class Icon extends PureComponent { return ( {icon} @@ -60,7 +60,7 @@ Icon.propTypes = { name: PropTypes.object.isRequired, kind: PropTypes.string.isRequired, size: PropTypes.number.isRequired, - title: PropTypes.string, + title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), darken: PropTypes.bool.isRequired, isSpinning: PropTypes.bool.isRequired, fixedWidth: PropTypes.bool.isRequired diff --git a/frontend/src/Store/Actions/episodeActions.js b/frontend/src/Store/Actions/episodeActions.js index c7f05aa8b..b84dfe168 100644 --- a/frontend/src/Store/Actions/episodeActions.js +++ b/frontend/src/Store/Actions/episodeActions.js @@ -119,9 +119,8 @@ export const defaultState = { }, label: React.createElement(Icon, { name: icons.SCORE, - get title() { - return translate('CustomFormatScore'); - } + title: () => translate('CustomFormatScore') + }), isVisible: false }, diff --git a/frontend/src/Store/Middleware/createPersistState.js b/frontend/src/Store/Middleware/createPersistState.js index fc6b5c88c..aa16ffa9e 100644 --- a/frontend/src/Store/Middleware/createPersistState.js +++ b/frontend/src/Store/Middleware/createPersistState.js @@ -36,10 +36,17 @@ function mergeColumns(path, initialState, persistedState, computedState) { const column = initialColumns.find((i) => i.name === persistedColumn.name); if (column) { - columns.push({ - ...column, - isVisible: persistedColumn.isVisible - }); + const newColumn = {}; + + // We can't use a spread operator or Object.assign to clone the column + // or any accessors are lost and can break translations. + for (const prop of Object.keys(column)) { + Object.defineProperty(newColumn, prop, Object.getOwnPropertyDescriptor(column, prop)); + } + + newColumn.isVisible = persistedColumn.isVisible; + + columns.push(newColumn); } }); diff --git a/frontend/src/System/Backup/BackupRow.js b/frontend/src/System/Backup/BackupRow.js index ca36b98dc..ad63544e3 100644 --- a/frontend/src/System/Backup/BackupRow.js +++ b/frontend/src/System/Backup/BackupRow.js @@ -9,6 +9,7 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; import { icons, kinds } from 'Helpers/Props'; import formatBytes from 'Utilities/Number/formatBytes'; +import translate from 'Utilities/String/translate'; import RestoreBackupModalConnector from './RestoreBackupModalConnector'; import styles from './BackupRow.css'; @@ -75,14 +76,14 @@ class BackupRow extends Component { } = this.state; let iconClassName = icons.SCHEDULED; - let iconTooltip = 'Scheduled'; + let iconTooltip = translate('Scheduled'); if (type === 'manual') { iconClassName = icons.INTERACTIVE; - iconTooltip = 'Manual'; + iconTooltip = translate('Manual'); } else if (type === 'update') { iconClassName = icons.UPDATE; - iconTooltip = 'Before update'; + iconTooltip = translate('BeforeUpdate'); } return ( @@ -115,12 +116,13 @@ class BackupRow extends Component { @@ -136,9 +138,11 @@ class BackupRow extends Component { diff --git a/frontend/src/System/Backup/Backups.js b/frontend/src/System/Backup/Backups.js index c4adfbf50..fa78dd769 100644 --- a/frontend/src/System/Backup/Backups.js +++ b/frontend/src/System/Backup/Backups.js @@ -10,6 +10,7 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; import { icons, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import BackupRow from './BackupRow'; import RestoreBackupModalConnector from './RestoreBackupModalConnector'; @@ -20,17 +21,23 @@ const columns = [ }, { name: 'name', - label: 'Name', + get label() { + return translate('Name'); + }, isVisible: true }, { name: 'size', - label: 'Size', + get label() { + return translate('Size'); + }, isVisible: true }, { name: 'time', - label: 'Time', + get label() { + return translate('Time'); + }, isVisible: true }, { @@ -81,18 +88,18 @@ class Backups extends Component { const noBackups = isPopulated && !items.length; return ( - + @@ -108,14 +115,14 @@ class Backups extends Component { { !isFetching && !!error && - Unable to load backups + {translate('UnableToLoadBackups')} } { noBackups && - No backups are available + {translate('NoBackupsAreAvailable')} } diff --git a/frontend/src/System/Backup/RestoreBackupModalContent.js b/frontend/src/System/Backup/RestoreBackupModalContent.js index 71bd5a3b9..9b5daa9f4 100644 --- a/frontend/src/System/Backup/RestoreBackupModalContent.js +++ b/frontend/src/System/Backup/RestoreBackupModalContent.js @@ -9,11 +9,12 @@ import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import { icons, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './RestoreBackupModalContent.css'; function getErrorMessage(error) { if (!error || !error.responseJSON || !error.responseJSON.message) { - return 'Error restoring backup'; + return translate('ErrorRestoringBackup'); } return error.responseJSON.message; @@ -145,7 +146,9 @@ class RestoreBackupModalContent extends Component { { - !!id && `Would you like to restore the backup '${name}'?` + !!id && translate('WouldYouLikeToRestoreBackup', { + name + }) } { @@ -167,7 +170,9 @@ class RestoreBackupModalContent extends Component { /> -
Restore
+
+ {translate('Restore')} +
@@ -178,7 +183,9 @@ class RestoreBackupModalContent extends Component { />
-
Restart
+
+ {translate('Restart')} +
@@ -189,18 +196,20 @@ class RestoreBackupModalContent extends Component { />
-
Reload
+
+ {translate('Reload')} +
- Note: Sonarr will automatically restart and reload the UI during the restore process. + {translate('RestartReloadNote')}
- Restore + {translate('Restore')}
diff --git a/frontend/src/System/Events/LogsTable.js b/frontend/src/System/Events/LogsTable.js index 5d4bc8513..1c37a03ba 100644 --- a/frontend/src/System/Events/LogsTable.js +++ b/frontend/src/System/Events/LogsTable.js @@ -13,6 +13,7 @@ import TableBody from 'Components/Table/TableBody'; import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper'; import TablePager from 'Components/Table/TablePager'; import { align, icons, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import LogsTableRow from './LogsTableRow'; function LogsTable(props) { @@ -33,11 +34,11 @@ function LogsTable(props) { } = props; return ( - + @@ -83,7 +84,7 @@ function LogsTable(props) { { isPopulated && !error && !items.length && - No events found + {translate('NoEventsFound')} } diff --git a/frontend/src/System/Events/LogsTableDetailsModal.js b/frontend/src/System/Events/LogsTableDetailsModal.js index c3681220d..13329f17b 100644 --- a/frontend/src/System/Events/LogsTableDetailsModal.js +++ b/frontend/src/System/Events/LogsTableDetailsModal.js @@ -8,6 +8,7 @@ import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import Scroller from 'Components/Scroller/Scroller'; import { scrollDirections } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './LogsTableDetailsModal.css'; function LogsTableDetailsModal(props) { @@ -27,11 +28,13 @@ function LogsTableDetailsModal(props) { onModalClose={onModalClose} > - Details + {translate('Details')} -
Message
+
+ {translate('Message')} +
-
Exception
+
+ {translate('Exception')} +
diff --git a/frontend/src/System/Logs/Files/LogFiles.js b/frontend/src/System/Logs/Files/LogFiles.js index 3d7f708aa..23b3bb40e 100644 --- a/frontend/src/System/Logs/Files/LogFiles.js +++ b/frontend/src/System/Logs/Files/LogFiles.js @@ -1,7 +1,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import Alert from 'Components/Alert'; -import Link from 'Components/Link/Link'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import PageContent from 'Components/Page/PageContent'; import PageContentBody from 'Components/Page/PageContentBody'; @@ -12,18 +11,24 @@ import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; import { icons, kinds } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; +import InlineMarkdown from '../../../Components/Markdown/InlineMarkdown'; import LogsNavMenu from '../LogsNavMenu'; import LogFilesTableRow from './LogFilesTableRow'; const columns = [ { name: 'filename', - label: 'Filename', + get label() { + return translate('Filename'); + }, isVisible: true }, { name: 'lastWriteTime', - label: 'Last Write Time', + get label() { + return translate('LastWriteTime'); + }, isVisible: true }, { @@ -50,7 +55,7 @@ class LogFiles extends Component { } = this.props; return ( - + @@ -58,7 +63,7 @@ class LogFiles extends Component {
- Log files are located in: {location} + {translate('LogFilesLocation', { + location + })}
{ currentLogView === 'Log Files' &&
- The log level defaults to 'Info' and can be changed in General Settings +
}
@@ -118,7 +125,7 @@ class LogFiles extends Component { { !isFetching && !items.length && - No log files + {translate('NoLogFiles')} } diff --git a/frontend/src/System/Logs/Files/LogFilesConnector.js b/frontend/src/System/Logs/Files/LogFilesConnector.js index 98a55f32f..75921f346 100644 --- a/frontend/src/System/Logs/Files/LogFilesConnector.js +++ b/frontend/src/System/Logs/Files/LogFilesConnector.js @@ -7,6 +7,7 @@ import { executeCommand } from 'Store/Actions/commandActions'; import { fetchLogFiles } from 'Store/Actions/systemActions'; import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; import combinePath from 'Utilities/String/combinePath'; +import translate from 'Utilities/String/translate'; import LogFiles from './LogFiles'; function createMapStateToProps() { @@ -29,7 +30,7 @@ function createMapStateToProps() { isFetching, items, deleteFilesExecuting, - currentLogView: 'Log Files', + currentLogView: translate('LogFiles'), location: combinePath(isWindows, appData, ['logs']) }; } diff --git a/frontend/src/System/Logs/Files/LogFilesTableRow.js b/frontend/src/System/Logs/Files/LogFilesTableRow.js index ef08ada4e..ba0339b84 100644 --- a/frontend/src/System/Logs/Files/LogFilesTableRow.js +++ b/frontend/src/System/Logs/Files/LogFilesTableRow.js @@ -4,6 +4,7 @@ import Link from 'Components/Link/Link'; import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; +import translate from 'Utilities/String/translate'; import styles from './LogFilesTableRow.css'; class LogFilesTableRow extends Component { @@ -32,7 +33,7 @@ class LogFilesTableRow extends Component { target="_blank" noRouter={true} > - Download + {translate('Download')}
diff --git a/frontend/src/System/Logs/LogsNavMenu.js b/frontend/src/System/Logs/LogsNavMenu.js index cc485f270..923e4f41c 100644 --- a/frontend/src/System/Logs/LogsNavMenu.js +++ b/frontend/src/System/Logs/LogsNavMenu.js @@ -4,6 +4,7 @@ import Menu from 'Components/Menu/Menu'; import MenuButton from 'Components/Menu/MenuButton'; import MenuContent from 'Components/Menu/MenuContent'; import MenuItem from 'Components/Menu/MenuItem'; +import translate from 'Utilities/String/translate'; class LogsNavMenu extends Component { @@ -50,13 +51,13 @@ class LogsNavMenu extends Component { - Log Files + {translate('LogFiles')} - Updater Log Files + {translate('UpdaterLogFiles')} diff --git a/frontend/src/System/Status/About/About.js b/frontend/src/System/Status/About/About.js index f212ef947..b0b289135 100644 --- a/frontend/src/System/Status/About/About.js +++ b/frontend/src/System/Status/About/About.js @@ -5,6 +5,7 @@ import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem' import FieldSet from 'Components/FieldSet'; import InlineMarkdown from 'Components/Markdown/InlineMarkdown'; import titleCase from 'Utilities/String/titleCase'; +import translate from 'Utilities/String/translate'; import StartTime from './StartTime'; import styles from './About.css'; @@ -30,25 +31,32 @@ class About extends Component { } = this.props; return ( -
+
{ packageVersion && {packageVersion} {' by '} : packageVersion)} + title={translate('PackageVersion')} + data={(packageAuthor ? + : + packageVersion + )} /> } { isNetCore && } @@ -56,28 +64,28 @@ class About extends Component { { isDocker && } +
{ isFetching && diff --git a/frontend/src/System/Status/Health/Health.js b/frontend/src/System/Status/Health/Health.js index ee0689fe4..8c021ed66 100644 --- a/frontend/src/System/Status/Health/Health.js +++ b/frontend/src/System/Status/Health/Health.js @@ -11,6 +11,7 @@ import TableBody from 'Components/Table/TableBody'; import TableRow from 'Components/Table/TableRow'; import { icons, kinds } from 'Helpers/Props'; import titleCase from 'Utilities/String/titleCase'; +import translate from 'Utilities/String/translate'; import styles from './Health.css'; function getInternalLink(source) { @@ -23,7 +24,7 @@ function getInternalLink(source) { return ( ); @@ -33,7 +34,7 @@ function getInternalLink(source) { return ( ); @@ -41,7 +42,7 @@ function getInternalLink(source) { return ( ); @@ -49,7 +50,7 @@ function getInternalLink(source) { return ( ); @@ -64,7 +65,7 @@ function getTestLink(source, props) { return ( @@ -74,7 +75,7 @@ function getTestLink(source, props) { return ( @@ -93,12 +94,16 @@ const columns = [ }, { name: 'message', - label: 'Message', + get label() { + return translate('Message'); + }, isVisible: true }, { name: 'actions', - label: 'Actions', + get label() { + return translate('Actions'); + }, isVisible: true } ]; @@ -121,7 +126,7 @@ class Health extends Component {
- Health + {translate('Health')} { isFetching && isPopulated && @@ -141,7 +146,7 @@ class Health extends Component { { !healthIssues &&
- No issues with your configuration + {translate('NoIssuesWithYourConfiguration')}
} @@ -186,7 +191,7 @@ class Health extends Component { { diff --git a/frontend/src/System/Status/MoreInfo/MoreInfo.js b/frontend/src/System/Status/MoreInfo/MoreInfo.js index 490230413..53618d882 100644 --- a/frontend/src/System/Status/MoreInfo/MoreInfo.js +++ b/frontend/src/System/Status/MoreInfo/MoreInfo.js @@ -4,6 +4,7 @@ import DescriptionListItemDescription from 'Components/DescriptionList/Descripti import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle'; import FieldSet from 'Components/FieldSet'; import Link from 'Components/Link/Link'; +import translate from 'Utilities/String/translate'; class MoreInfo extends Component { @@ -12,34 +13,46 @@ class MoreInfo extends Component { render() { return ( -
+
- Home page + + {translate('HomePage')} + sonarr.tv - Wiki + + {translate('Wiki')} + wiki.servarr.com/sonarr - Forums + + {translate('Forums')} + forums.sonarr.tv - Twitter + + {translate('Twitter')} + @sonarrtv - Discord + + {translate('Discord')} + discord.sonarr.tv - IRC + + {translate('IRC')} + #sonarr on Libera @@ -47,17 +60,23 @@ class MoreInfo extends Component { Libera webchat - Donations + + {translate('Donations')} + sonarr.tv/donate - Source + + {translate('Source')} + github.com/Sonarr/Sonarr - Feature Requests + + {translate('FeatureRequests')} + forums.sonarr.tv diff --git a/frontend/src/System/Status/Status.js b/frontend/src/System/Status/Status.js index a325495e5..429a149ee 100644 --- a/frontend/src/System/Status/Status.js +++ b/frontend/src/System/Status/Status.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import PageContent from 'Components/Page/PageContent'; import PageContentBody from 'Components/Page/PageContentBody'; +import translate from 'Utilities/String/translate'; import AboutConnector from './About/AboutConnector'; import DiskSpaceConnector from './DiskSpace/DiskSpaceConnector'; import HealthConnector from './Health/HealthConnector'; @@ -13,7 +14,7 @@ class Status extends Component { render() { return ( - + diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRow.js b/frontend/src/System/Tasks/Queued/QueuedTaskRow.js index 31015501d..8b8a62d3a 100644 --- a/frontend/src/System/Tasks/Queued/QueuedTaskRow.js +++ b/frontend/src/System/Tasks/Queued/QueuedTaskRow.js @@ -11,6 +11,7 @@ import formatDate from 'Utilities/Date/formatDate'; import formatDateTime from 'Utilities/Date/formatDateTime'; import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; import titleCase from 'Utilities/String/titleCase'; +import translate from 'Utilities/String/translate'; import styles from './QueuedTaskRow.css'; function getStatusIconProps(status, message) { @@ -198,8 +199,8 @@ class QueuedTaskRow extends Component { { clientUserAgent ? - - from: {clientUserAgent} + + {translate('From')}: {clientUserAgent} : null } @@ -236,7 +237,7 @@ class QueuedTaskRow extends Component { { status === 'queued' && @@ -246,10 +247,10 @@ class QueuedTaskRow extends Component { diff --git a/frontend/src/System/Tasks/Queued/QueuedTasks.js b/frontend/src/System/Tasks/Queued/QueuedTasks.js index e856df532..30301702c 100644 --- a/frontend/src/System/Tasks/Queued/QueuedTasks.js +++ b/frontend/src/System/Tasks/Queued/QueuedTasks.js @@ -4,6 +4,7 @@ import FieldSet from 'Components/FieldSet'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; +import translate from 'Utilities/String/translate'; import QueuedTaskRowConnector from './QueuedTaskRowConnector'; const columns = [ @@ -14,27 +15,37 @@ const columns = [ }, { name: 'commandName', - label: 'Name', + get label() { + return translate('Name'); + }, isVisible: true }, { name: 'queued', - label: 'Queued', + get label() { + return translate('Queued'); + }, isVisible: true }, { name: 'started', - label: 'Started', + get label() { + return translate('Started'); + }, isVisible: true }, { name: 'ended', - label: 'Ended', + get label() { + return translate('Ended'); + }, isVisible: true }, { name: 'duration', - label: 'Duration', + get label() { + return translate('Duration'); + }, isVisible: true }, { @@ -51,7 +62,7 @@ function QueuedTasks(props) { } = props; return ( -
+
{ isFetching && !isPopulated && diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js b/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js index 1176db157..c1b17122d 100644 --- a/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js +++ b/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js @@ -4,32 +4,43 @@ import FieldSet from 'Components/FieldSet'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import Table from 'Components/Table/Table'; import TableBody from 'Components/Table/TableBody'; +import translate from 'Utilities/String/translate'; import ScheduledTaskRowConnector from './ScheduledTaskRowConnector'; const columns = [ { name: 'name', - label: 'Name', + get label() { + return translate('Name'); + }, isVisible: true }, { name: 'interval', - label: 'Interval', + get label() { + return translate('Interval'); + }, isVisible: true }, { name: 'lastExecution', - label: 'Last Execution', + get label() { + return translate('LastExecution'); + }, isVisible: true }, { name: 'lastDuration', - label: 'Last Duration', + get label() { + return translate('LastDuration'); + }, isVisible: true }, { name: 'nextExecution', - label: 'Next Execution', + get label() { + return translate('NextExecution'); + }, isVisible: true }, { @@ -46,7 +57,7 @@ function ScheduledTasks(props) { } = props; return ( -
+
{ isFetching && !isPopulated && diff --git a/frontend/src/System/Tasks/Tasks.js b/frontend/src/System/Tasks/Tasks.js index e08792145..032dbede8 100644 --- a/frontend/src/System/Tasks/Tasks.js +++ b/frontend/src/System/Tasks/Tasks.js @@ -1,12 +1,13 @@ import React from 'react'; import PageContent from 'Components/Page/PageContent'; import PageContentBody from 'Components/Page/PageContentBody'; +import translate from 'Utilities/String/translate'; import QueuedTasksConnector from './Queued/QueuedTasksConnector'; import ScheduledTasksConnector from './Scheduled/ScheduledTasksConnector'; function Tasks() { return ( - + diff --git a/frontend/src/System/Updates/Updates.js b/frontend/src/System/Updates/Updates.js index cb032dd7f..bded2676d 100644 --- a/frontend/src/System/Updates/Updates.js +++ b/frontend/src/System/Updates/Updates.js @@ -12,6 +12,7 @@ import PageContentBody from 'Components/Page/PageContentBody'; import { icons, kinds } from 'Helpers/Props'; import formatDate from 'Utilities/Date/formatDate'; import formatDateTime from 'Utilities/Date/formatDateTime'; +import translate from 'Utilities/String/translate'; import UpdateChanges from './UpdateChanges'; import styles from './Updates.css'; @@ -43,15 +44,15 @@ class Updates extends Component { const hasUpdateToInstall = hasUpdates && _.some(items, { installable: true, latest: true }); const noUpdateToInstall = hasUpdates && !hasUpdateToInstall; - const externalUpdaterPrefix = 'Unable to update Sonarr directly,'; + const externalUpdaterPrefix = translate('UnableToUpdateSonarrDirectly'); const externalUpdaterMessages = { - external: 'Sonarr is configured to use an external update mechanism', - apt: 'use apt to install the update', - docker: 'update the docker container to receive the update' + external: translate('ExternalUpdater'), + apt: translate('AptUpdater'), + docker: translate('DockerUpdater') }; return ( - + { !isPopulated && !hasError && @@ -61,7 +62,7 @@ class Updates extends Component { { noUpdates && - No updates are available + {translate('NoUpdatesAreAvailable')} } @@ -76,7 +77,7 @@ class Updates extends Component { isSpinning={isInstallingUpdate} onPress={onInstallLatestPress} > - Install Latest + {translate('InstallLatest')} : @@ -112,7 +113,7 @@ class Updates extends Component { />
- The latest version of Sonarr is already installed + {translate('OnLatestVersion')}
{ @@ -164,7 +165,7 @@ class Updates extends Component { kind={kinds.SUCCESS} title={formatDateTime(update.installedOn, longDateFormat, timeFormat)} > - Currently Installed + {translate('CurrentlyInstalled')} : null } @@ -176,7 +177,7 @@ class Updates extends Component { kind={kinds.INVERSE} title={formatDateTime(update.installedOn, longDateFormat, timeFormat)} > - Previously Installed + {translate('PreviouslyInstalled')} : null } @@ -184,19 +185,21 @@ class Updates extends Component { { !hasChanges && -
Maintenance Release: See GitHub commit history for details.
+
+ {translate('MaintenanceRelease')} +
} { hasChanges &&
@@ -211,14 +214,14 @@ class Updates extends Component { { !!updatesError &&
- Failed to fetch updates + {translate('FailedToFetchUpdates')}
} { !!generalSettingsError &&
- Failed to update settings + {translate('FailedToUpdateSettings')}
}
diff --git a/src/NzbDrone.Core/Localization/Core/de.json b/src/NzbDrone.Core/Localization/Core/de.json index 503f5738b..e9cf1d13c 100644 --- a/src/NzbDrone.Core/Localization/Core/de.json +++ b/src/NzbDrone.Core/Localization/Core/de.json @@ -14,9 +14,9 @@ "DownloadClientSortingHealthCheckMessage": "Im Download-Client {0} ist die Sortierung {1} für die Kategorie von Sonarr aktiviert. Sie sollten die Sortierung in Ihrem Download-Client deaktivieren, um Importprobleme zu vermeiden.", "DownloadClientStatusSingleClientHealthCheckMessage": "Download-Clients sind aufgrund von Fehlern nicht verfügbar: {0}", "DownloadClientStatusAllClientHealthCheckMessage": "Alle Download-Clients sind aufgrund von Fehlern nicht verfügbar", - "EditSelectedDownloadClients": "Ausgewählte Download-Clients bearbeiten", - "EditSelectedImportLists": "Ausgewählte Importlisten bearbeiten", - "EditSelectedIndexers": "Ausgewählte Indexer bearbeiten", + "EditSelectedDownloadClients": "Ausgewählte Download Clienten bearbeiten", + "EditSelectedImportLists": "Ausgewählte Einspiel-Liste bearbeten", + "EditSelectedIndexers": "Ausgewähle Indexer bearbeiten", "EditSeries": "Serie bearbeiten", "EnableAutomaticSearch": "Automatische Suche einschalten", "EnableInteractiveSearch": "Interaktive Suche einschalten", @@ -26,5 +26,17 @@ "DeleteConditionMessageText": "Bist du sicher, dass du die Bedingung '{0}' löschen willst?", "DeleteCustomFormatMessageText": "Bist du sicher, dass du das eigene Format '{0}' löschen willst?", "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?" + "RemoveSelectedItemsQueueMessageText": "Bist du sicher, dass du {0} Einträge aus der Warteschlange entfernen willst?", + "DeleteSelectedDownloadClients": "Lösche Download Client(s)", + "DeleteSelectedIndexers": "Lösche Indexer", + "DeleteSelectedImportLists": "Lösche Einspiel Liste", + "Implementation": "Integration", + "ManageIndexers": "Verwalte Indexer", + "ManageLists": "Verwalte Listen", + "NoImportListsFound": "Keine Einspiel-Listen gefunden", + "NoIndexersFound": "Keine Indexer gefunden", + "ManageClients": "Verwalte Clienten", + "ManageDownloadClients": "Verwalte Download Clienten", + "ManageImportLists": "Verwalte Einspiel-Listen", + "NoDownloadClientsFound": "Keine Download Clienten gefunden" } diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index ea48be0ff..31d7cfe44 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1,13 +1,16 @@ { + "About": "About", "AbsoluteEpisodeNumbers": "Absolute Episode Number(s)", + "Actions": "Actions", "Activity": "Activity", "Add": "Add", - "AddNew": "Add New", "Added": "Added", "AddingTag": "Adding tag", + "AddNew": "Add New", "AirDate": "Air Date", "AllTitles": "All Titles", "ApiKeyValidationHealthCheckMessage": "Please update your API key to be at least {0} characters long. You can do this via settings or the config file", + "AppDataDirectory": "AppData directory", "AppDataLocationHealthCheckMessage": "Updating will not be possible to prevent deleting AppData on Update", "Apply": "Apply", "ApplyChanges": "Apply Changes", @@ -20,9 +23,13 @@ "ApplyTagsHelpTextHowToApplySeries": "How to apply tags to the selected series", "ApplyTagsHelpTextRemove": "Remove: Remove the entered tags", "ApplyTagsHelpTextReplace": "Replace: Replace the tags with the entered tags (enter no tags to clear all tags)", + "AptUpdater": "Use apt to install the update", "AutoAdd": "Auto Add", "AutomaticAdd": "Automatic Add", "Backup": "Backup", + "BackupNow": "Backup Now", + "Backups": "Backups", + "BeforeUpdate": "Before update", "Blocklist": "Blocklist", "BlocklistRelease": "Blocklist Release", "BlocklistReleaseHelpText": "Prevents Sonarr from automatically grabbing this release again", @@ -30,6 +37,8 @@ "Browser Reload Required": "Browser Reload Required", "Calendar": "Calendar", "Cancel": "Cancel", + "CancelPendingTask": "Are you sure you want to cancel this pending task?", + "Clear": "Clear", "CloneCondition": "Clone Condition", "CloneCustomFormat": "Clone Custom Format", "Close": "Close", @@ -38,11 +47,14 @@ "CountImportListsSelected": "{count} import list(s) selected", "CountIndexersSelected": "{count} indexer(s) selected", "CountSeasons": "{count} seasons", - "CustomFormatScore": "Custom Format Score", + "CurrentlyInstalled": "Currently Installed", "CustomFormats": "Custom Formats", + "CustomFormatScore": "Custom Format Score", "CutoffUnmet": "Cutoff Unmet", "Daily": "Daily", "Delete": "Delete", + "DeleteBackup": "Delete Backup", + "DeleteBackupMessageText": "Are you sure you want to delete the backup '{name}'?", "DeleteCondition": "Delete Condition", "DeleteConditionMessageText": "Are you sure you want to delete the condition '{0}'?", "DeleteCustomFormat": "Delete Custom Format", @@ -55,39 +67,61 @@ "DeleteSelectedIndexersMessageText": "Are you sure you want to delete {count} selected indexer(s)?", "Details": "Details", "Disabled": "Disabled", + "Discord": "Discord", + "DiskSpace": "Disk Space", + "Docker": "Docker", + "DockerUpdater": "Update the docker container to receive the update", + "Donations": "Donations", + "DotNetVersion": ".NET", + "Download": "Download", "DownloadClientCheckNoneAvailableHealthCheckMessage": "No download client is available", "DownloadClientCheckUnableToCommunicateWithHealthCheckMessage": "Unable to communicate with {0}.", "DownloadClientRootFolderHealthCheckMessage": "Download client {0} places downloads in the root folder {1}. You should not download to a root folder.", + "DownloadClients": "Download Clients", "DownloadClientSortingHealthCheckMessage": "Download client {0} has {1} sorting enabled for Sonarr's category. You should disable sorting in your download client to avoid import issues.", "DownloadClientStatusAllClientHealthCheckMessage": "All download clients are unavailable due to failures", "DownloadClientStatusSingleClientHealthCheckMessage": "Download clients unavailable due to failures: {0}", - "DownloadClients": "Download Clients", + "Duration": "Duration", "Edit": "Edit", "EditSelectedDownloadClients": "Edit Selected Download Clients", "EditSelectedImportLists": "Edit Selected Import Lists", "EditSelectedIndexers": "Edit Selected Indexers", "EditSeries": "Edit Series", "EnableAutomaticSearch": "Enable Automatic Search", + "Enabled": "Enabled", "EnableInteractiveSearch": "Enable Interactive Search", "EnableRSS": "Enable RSS", - "Enabled": "Enabled", "Ended": "Ended", "EpisodeInfo": "Episode Info", "EpisodeNumbers": "Episode Number(s)", + "ErrorRestoringBackup": "Error restoring backup", "Events": "Events", + "Exception": "Exception", "ExistingTag": "Existing tag", "ExportCustomFormat": "Export Custom Format", + "ExternalUpdater": "Sonarr is configured to use an external update mechanism", + "FailedToFetchUpdates": "Failed to fetch updates", + "FailedToUpdateSettings": "Failed to update settings", + "FeatureRequests": "Feature Requests", + "Filename": "Filename", + "Fixed": "Fixed", + "Forums": "Forums", + "FreeSpace": "Free Space", + "From": "From", "FullSeason": "Full Season", "General": "General", + "GeneralSettings": "General Settings", + "Health": "Health", "HiddenClickToShow": "Hidden, click to show", "HideAdvanced": "Hide Advanced", "History": "History", + "HomePage": "Home Page", "Implementation": "Implementation", "ImportListRootFolderMissingRootHealthCheckMessage": "Missing root folder for import list(s): {0}", "ImportListRootFolderMultipleMissingRootsHealthCheckMessage": "Multiple root folders are missing for import lists: {0}", + "ImportLists": "Import Lists", "ImportListStatusAllUnavailableHealthCheckMessage": "All lists are unavailable due to failures", "ImportListStatusUnavailableHealthCheckMessage": "Lists unavailable due to failures: {0}", - "ImportLists": "Import Lists", "ImportMechanismEnableCompletedDownloadHandlingIfPossibleHealthCheckMessage": "Enable Completed Download Handling if possible", "ImportMechanismEnableCompletedDownloadHandlingIfPossibleMultiComputerHealthCheckMessage": "Enable Completed Download Handling if possible (Multi-Computer unsupported)", "ImportMechanismHandlingDisabledHealthCheckMessage": "Enable Completed Download Handling", @@ -96,47 +130,74 @@ "IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures for more than 6 hours: {0}", "IndexerRssNoIndexersAvailableHealthCheckMessage": "All rss-capable indexers are temporarily unavailable due to recent indexer errors", "IndexerRssNoIndexersEnabledHealthCheckMessage": "No indexers available with RSS sync enabled, Sonarr will not grab new releases automatically", + "Indexers": "Indexers", "IndexerSearchNoAutomaticHealthCheckMessage": "No indexers available with Automatic Search enabled, Sonarr will not provide any automatic search results", "IndexerSearchNoAvailableIndexersHealthCheckMessage": "All search-capable indexers are temporarily unavailable due to recent indexer errors", "IndexerSearchNoInteractiveHealthCheckMessage": "No indexers available with Interactive Search enabled, Sonarr will not provide any interactive search results", "IndexerStatusAllUnavailableHealthCheckMessage": "All indexers are unavailable due to failures", "IndexerStatusUnavailableHealthCheckMessage": "Indexers unavailable due to failures: {0}", - "Indexers": "Indexers", + "InstallLatest": "Install Latest", + "Interval": "Interval", + "IRC": "IRC", "Language": "Language", "Language that Sonarr will use for UI": "Language that Sonarr will use for UI", "Languages": "Languages", + "LastDuration": "Last Duration", + "LastExecution": "Last Execution", + "LastWriteTime": "Last Write Time", "LibraryImport": "Library Import", + "Location": "Location", "LogFiles": "Log Files", + "LogFilesLocation": "Log files are located in: {location}", + "Logs": "Logs", + "MaintenanceRelease": "Maintenance Release: bug fixes and other improvements. See Github Commit History for more details", "ManageClients": "Manage Clients", "ManageDownloadClients": "Manage Download Clients", "ManageImportLists": "Manage Import Lists", "ManageIndexers": "Manage Indexers", "ManageLists": "Manage Lists", + "Manual": "Manual", "MatchedToEpisodes": "Matched to Episodes", "MatchedToSeason": "Matched to Season", "MatchedToSeries": "Matched to Series", "MediaManagement": "Media Management", + "Message": "Message", "Metadata": "Metadata", "MetadataSource": "Metadata Source", "Missing": "Missing", + "Mode": "Mode", "Monitored": "Monitored", + "MoreInfo": "More Info", "MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ", "MultiSeason": "Multi-Season", "Name": "Name", "Negated": "Negated", "Network": "Network", + "New": "New", "NextAiring": "Next Airing", + "NextExecution": "Next Execution", "No": "No", + "NoBackupsAreAvailable": "No backups are available", "NoChange": "No Change", "NoDownloadClientsFound": "No download clients found", + "NoEventsFound": "No events found", "NoImportListsFound": "No import lists found", "NoIndexersFound": "No indexers found", + "NoIssuesWithYourConfiguration": "No issues with your configuration", + "NoLeaveIt": "No, Leave It", + "NoLogFiles": "No log files", "NoSeasons": "No seasons", + "NoUpdatesAreAvailable": "No updates are available", "OneSeason": "1 season", + "OnLatestVersion": "The latest version of Radarr is already installed", + "Options": "Options", "OriginalLanguage": "Original Language", + "PackageVersion": "Package Version", + "PackageVersionInfo": "{packageVersion} by {packageAuthor}", "PartialSeason": "Partial Season", "Path": "Path", "PreviousAiring": "Previous Airing", + "PreviouslyInstalled": "Previously Installed", "Priority": "Priority", "Profiles": "Profiles", "Proper": "Proper", @@ -146,13 +207,17 @@ "Quality": "Quality", "QualityProfile": "Quality Profile", "Queue": "Queue", + "Queued": "Queued", + "ReadTheWikiForMoreInformation": "Read the Wiki for more information", "Real": "Real", "RecycleBinUnableToWriteHealthCheckMessage": "Unable to write to configured recycling bin folder: {0}. Ensure this path exists and is writable by the user running Sonarr", + "Refresh": "Refresh", "RefreshSeries": "Refresh Series", "Release": "Release", "ReleaseGroup": "Release Group", "ReleaseHash": "Release Hash", "ReleaseTitle": "Release Title", + "Reload": "Reload", "RemotePathMappingBadDockerPathHealthCheckMessage": "You are using docker; download client {0} places downloads in {1} but this is not a valid {2} path. Review your remote path mappings and download client settings.", "RemotePathMappingDockerFolderMissingHealthCheckMessage": "You are using docker; download client {0} places downloads in {1} but this directory does not appear to exist inside the container. Review your remote path mappings and container volume settings.", "RemotePathMappingDownloadPermissionsHealthCheckMessage": "Sonarr can see but not access downloaded episode {0}. Likely permissions error.", @@ -171,6 +236,9 @@ "Remove": "Remove", "RemoveCompleted": "Remove Completed", "RemoveCompletedDownloads": "Remove Completed Downloads", + "RemovedFromTaskQueue": "Removed from task queue", + "RemovedSeriesMultipleRemovedHealthCheckMessage": "Series {0} were removed from TheTVDB", + "RemovedSeriesSingleRemovedHealthCheckMessage": "Series {0} was removed from TheTVDB", "RemoveFailed": "Remove Failed", "RemoveFailedDownloads": "Remove Failed Downloads", "RemoveFromDownloadClient": "Remove From Download Client", @@ -179,40 +247,67 @@ "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?", - "RemovedSeriesMultipleRemovedHealthCheckMessage": "Series {0} were removed from TheTVDB", - "RemovedSeriesSingleRemovedHealthCheckMessage": "Series {0} was removed from TheTVDB", "RemovingTag": "Removing tag", "Repack": "Repack", "Replace": "Replace", "Required": "Required", + "Reset": "Reset", + "ResetDefinitionTitlesHelpText": "Reset definition titles as well as values", + "ResetQualityDefinitions": "Reset Quality Definitions", + "ResetQualityDefinitionsMessageText": "Are you sure you want to reset quality definitions?", + "ResetTitles": "Reset Titles", + "Restart": "Restart", + "RestartReloadNote": "Note: Sonarr will automatically restart and reload the UI during the restore process.", + "Restore": "Restore", + "RestoreBackup": "Restore Backup", "Result": "Result", "RootFolder": "Root Folder", "RootFolderMissingHealthCheckMessage": "Missing root folder: {0}", "RootFolderMultipleMissingHealthCheckMessage": "Multiple root folders are missing: {0}", + "Scheduled": "Scheduled", "SearchForMonitoredEpisodes": "Search for monitored episodes", "SeasonNumber": "Season Number", "Series": "Series", + "SeriesEditor": "Series Editor", "SeriesTitle": "Series Title", "SetTags": "Set Tags", "Settings": "Settings", "ShowAdvanced": "Show Advanced", "ShownClickToHide": "Shown, click to hide", + "Size": "Size", "SizeOnDisk": "Size on disk", + "Source": "Source", "Special": "Special", + "Started": "Started", + "StartupDirectory": "Startup directory", + "Status": "Status", "System": "System", "SystemTimeHealthCheckMessage": "System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected", "Tags": "Tags", "Tasks": "Tasks", + "TaskUserAgentTooltip": "User-Agent provided by the app that called the API", + "TestAll": "Test All", "TestParsing": "Test Parsing", + "TheLogLevelDefault": "The log level defaults to 'Info' and can be changed in [General Settings](/settings/general)", + "Time": "Time", + "TotalSpace": "Total Space", + "Twitter": "Twitter", "UI": "UI", "UI Language": "UI Language", + "UnableToLoadBackups": "Unable to load backups", + "UnableToUpdateSonarrDirectly": "Unable to update Sonarr directly,", "Unmonitored": "Unmonitored", "UpdateAvailableHealthCheckMessage": "New update is available", + "UpdaterLogFiles": "Updater Log Files", + "Updates": "Updates", "UpdateStartupNotWritableHealthCheckMessage": "Cannot install update because startup folder '{0}' is not writable by the user '{1}'.", "UpdateStartupTranslocationHealthCheckMessage": "Cannot install update because startup folder '{0}' is in an App Translocation folder.", "UpdateUINotWritableHealthCheckMessage": "Cannot install update because UI folder '{0}' is not writable by the user '{1}'.", - "Updates": "Updates", + "Uptime": "Uptime", "Version": "Version", "Wanted": "Wanted", - "Yes": "Yes" + "Wiki": "Wiki", + "WouldYouLikeToRestoreBackup": "Would you like to restore the backup '{name}'?", + "Yes": "Yes", + "YesCancel": "Yes, Cancel" } diff --git a/src/NzbDrone.Core/Localization/Core/fr.json b/src/NzbDrone.Core/Localization/Core/fr.json index baaeec6d4..61da69911 100644 --- a/src/NzbDrone.Core/Localization/Core/fr.json +++ b/src/NzbDrone.Core/Localization/Core/fr.json @@ -3,11 +3,15 @@ "UI Language": "UI Langue", "Language that Sonarr will use for UI": "Langue que Sonarr utilisera pour l'interface utilisateur", "Browser Reload Required": "Rechargement du navigateur requis", - "Added": "Ajouter", + "Added": "Ajouté", "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", "AppDataLocationHealthCheckMessage": "La mise à jour ne sera pas possible pour empêcher la suppression de AppData lors de la mise à jour", "ApplyChanges": "Appliquer les modifications", "AutomaticAdd": "Ajout automatique", "CountSeasons": "{count} saisons", - "DownloadClientCheckNoneAvailableHealthCheckMessage": "Aucun client de téléchargement disponible" + "DownloadClientCheckNoneAvailableHealthCheckMessage": "Aucun client de téléchargement disponible", + "Add": "Ajouter", + "AddingTag": "Ajout d'un tag", + "Apply": "Appliquer", + "ApplyTags": "Appliquer les tags" } diff --git a/src/NzbDrone.Core/Localization/Core/he.json b/src/NzbDrone.Core/Localization/Core/he.json index 52cbf6691..9efdba569 100644 --- a/src/NzbDrone.Core/Localization/Core/he.json +++ b/src/NzbDrone.Core/Localization/Core/he.json @@ -1,4 +1,6 @@ { "Added": "נוסף", - "ApiKeyValidationHealthCheckMessage": "עדכן בבקשה את מפתח ה API שלך שיהיה עם לפחות {0} תווים. ניתן לעשות זאת דרך ההגדות או קובץ הקונפיגורציה" + "ApiKeyValidationHealthCheckMessage": "עדכן בבקשה את מפתח ה־API שלך כדי שיהיה באורך של לפחות {0} תווים. תוכל לעשות זאת בהגדרות או דרך קובץ הקונפיגורציה.", + "Add": "הוסף", + "Activity": "פעילות" } diff --git a/src/NzbDrone.Core/Localization/Core/hu.json b/src/NzbDrone.Core/Localization/Core/hu.json index e70656414..ee5d3acc1 100644 --- a/src/NzbDrone.Core/Localization/Core/hu.json +++ b/src/NzbDrone.Core/Localization/Core/hu.json @@ -35,7 +35,6 @@ "DownloadClientStatusSingleClientHealthCheckMessage": "Letöltési kliensek elérhetetlenek meghibásodások miatt: {0}", "EnableAutomaticSearch": "Automatikus keresés engedélyezése", "EditSeries": "Sorozat szerkesztése", - "EnableRss": "RSS engedélyezése", "EnableInteractiveSearch": "Interaktív keresés engedélyezése", "Ended": "Vége", "HideAdvanced": "Haladó elrejtése", diff --git a/src/NzbDrone.Core/Localization/Core/id.json b/src/NzbDrone.Core/Localization/Core/id.json index 13ca72fe3..f30d18dad 100644 --- a/src/NzbDrone.Core/Localization/Core/id.json +++ b/src/NzbDrone.Core/Localization/Core/id.json @@ -1,3 +1,41 @@ { - "Added": "Ditambahkan" + "Added": "Ditambahkan", + "BlocklistReleaseHelpText": "Mencegah Sonarr memperoleh rilis ini secara otomatis", + "Delete": "Hapus", + "Close": "Tutup", + "Language that Sonarr will use for UI": "Bahasa yang digunakan UI Sonarr", + "EnableAutomaticSearch": "Aktifkan Penelusuran Otomatis", + "EnableInteractiveSearch": "Aktifkan Penelusuran Interaktif", + "Enabled": "Aktif", + "Language": "Bahasa", + "Network": "Jaringan", + "NextAiring": "Tayang Selanjutnya", + "Monitored": "Dimonitor", + "Path": "Path", + "PreviousAiring": "Sebelumnya Tayang", + "OriginalLanguage": "Bahasa Asli", + "Priority": "Prioritas", + "ProxyFailedToTestHealthCheckMessage": "Gagal menguji proxy: {0}", + "ProxyBadRequestHealthCheckMessage": "Gagal menguji proxy. Kode Status: {0}", + "QualityProfile": "Profil Kualitas", + "Add": "Tambah", + "Cancel": "Batal", + "NoSeasons": "Tidak ada musim", + "OneSeason": "1 musim", + "Disabled": "Nonaktif", + "Activity": "Aktivitas", + "Calendar": "Kalender", + "EnableRSS": "Aktifkan RSS", + "Ended": "Berakhir", + "LibraryImport": "Impor Pustaka", + "LogFiles": "Berkas Log", + "MediaManagement": "Pengelolaan Media", + "Metadata": "Metadata", + "MetadataSource": "Sumber Metadata", + "Name": "Nama", + "No": "Tidak", + "NoChange": "Tidak Ada Perubahan", + "Profiles": "Profil", + "Quality": "Kualitas", + "Queue": "Antrean" } diff --git a/src/NzbDrone.Core/Localization/Core/pt_BR.json b/src/NzbDrone.Core/Localization/Core/pt_BR.json index 073019bd0..881648a48 100644 --- a/src/NzbDrone.Core/Localization/Core/pt_BR.json +++ b/src/NzbDrone.Core/Localization/Core/pt_BR.json @@ -7,7 +7,6 @@ "DownloadClientStatusAllClientHealthCheckMessage": "Todos os clientes de download estão indisponíveis devido a falhas", "EditSelectedDownloadClients": "Editar clientes de download selecionados", "EditSelectedImportLists": "Editar listas de importação selecionadas", - "EnableRss": "Ativar Rss", "Enabled": "Habilitado", "Ended": "Terminou", "HideAdvanced": "Ocultar Avançado", @@ -92,14 +91,14 @@ "UpdateStartupNotWritableHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' não pode ser gravada pelo usuário '{1}'.", "UpdateStartupTranslocationHealthCheckMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' está em uma pasta de translocação de aplicativo.", "BlocklistReleaseHelpText": "Impede que o Sonarr pegue automaticamente esta versão novamente", - "BlocklistReleases": "Lista de Bloqueio de Lançamentos", - "CloneCondition": "Condição de Clone", - "CloneCustomFormat": "Clonar Formato Personalizado", + "BlocklistReleases": "Lançamentos na lista de bloqueio", + "CloneCondition": "Condição de clone", + "CloneCustomFormat": "Clonar formato personalizado", "Close": "Fechar", "Delete": "Excluir", - "DeleteCondition": "Excluir Condição", + "DeleteCondition": "Excluir condição", "DeleteConditionMessageText": "Tem certeza de que deseja excluir a condição '{0}'?", - "DeleteCustomFormat": "Excluir Formato Personalizado", + "DeleteCustomFormat": "Excluir formato personalizado", "DeleteCustomFormatMessageText": "Tem certeza de que deseja excluir o formato personalizado '{0}'?", "ExportCustomFormat": "Exportar Formato Personalizado", "Negated": "Negado", @@ -111,5 +110,109 @@ "RemoveSelectedItems": "Remover Itens Selecionados", "RemoveSelectedItemsQueueMessageText": "Tem certeza de que deseja remover {0} itens da fila?", "Required": "Requerido", - "BlocklistRelease": "Lista de Bloqueio de Lançamentos" + "BlocklistRelease": "Lançamento na lista de bloqueio", + "Add": "Adicionar", + "AddingTag": "Adicionar tag", + "Apply": "Aplicar", + "ApplyTags": "Aplicar Tags", + "Cancel": "Cancelar", + "CountDownloadClientsSelected": "{count} cliente(s) de download selecionado(s)", + "CountImportListsSelected": "{count} lista(s) de importação selecionada(s)", + "CountIndexersSelected": "{count} indexador(es) selecionado(s)", + "DeleteSelectedDownloadClients": "Excluir cliente(s) de download", + "DeleteSelectedImportLists": "Excluir lista(s) de importação", + "DeleteSelectedIndexers": "Excluir indexador(es)", + "DeleteSelectedDownloadClientsMessageText": "Tem certeza de que deseja excluir {count} cliente(s) de download selecionado(s)?", + "DeleteSelectedImportListsMessageText": "Tem certeza de que deseja excluir {count} lista(s) de importação selecionada(s)?", + "ExistingTag": "Etiqueta existente", + "Implementation": "Implementação", + "Disabled": "Desabilitado", + "Edit": "Editar", + "EnableRSS": "Habilitar RSS", + "ManageClients": "Gerenciar clientes", + "ManageIndexers": "Gerenciar indexadores", + "ManageDownloadClients": "Gerenciar clientes de download", + "ManageImportLists": "Gerenciar listas de importação", + "No": "Não", + "ManageLists": "Gerenciar listas", + "Name": "Nome", + "NoChange": "Sem alteração", + "NoDownloadClientsFound": "Nenhum cliente de download encontrado", + "NoImportListsFound": "Nenhuma lista de importação encontrada", + "NoIndexersFound": "Nenhum indexador encontrado", + "RemoveFailed": "Falha na remoção", + "Replace": "Substituir", + "Result": "Resultado", + "SetTags": "Definir etiquetas", + "Yes": "Sim", + "Tags": "Tags", + "AutoAdd": "Adicionar automaticamente", + "RemovingTag": "Removendo etiqueta", + "DeleteSelectedIndexersMessageText": "Tem certeza de que deseja excluir {count} indexadores selecionados?", + "RemoveCompleted": "Remoção Concluída", + "LibraryImport": "Importar para biblioteca", + "LogFiles": "Arquivos de registro", + "MediaManagement": "Gerenciamento de Mídia", + "Metadata": "Metadados", + "MetadataSource": "Fonte de Metadados", + "Missing": "Ausente", + "Profiles": "Perfis", + "Quality": "Qualidade", + "Queue": "Fila", + "Series": "Séries", + "Settings": "Configurações", + "System": "Sistema", + "Tasks": "Tarefas", + "UI": "UI", + "Updates": "Atualizações", + "Wanted": "Procurado", + "ApplyTagsHelpTextHowToApply": "Como aplicar tags nos indexadores selecionados", + "ApplyTagsHelpTextAdd": "Adicionar: adicione as etiquetas à lista existente de etiquetas", + "ApplyTagsHelpTextReplace": "Substituir: Substitua as etiquetas pelas etiquetas inseridas (não digite nenhuma etiqueta para limpar todas as etiquetas)", + "ApplyTagsHelpTextRemove": "Remover: remove as etiquetas inseridas", + "CustomFormatScore": "Pontuação do formato personalizado", + "Activity": "Atividade", + "AddNew": "Adicionar Novo", + "Backup": "Backup", + "Blocklist": "Lista de Bloqueio", + "Calendar": "Calendário", + "Connect": "Conectar", + "CustomFormats": "Formatos personalizados", + "CutoffUnmet": "Corte não alcançado", + "DownloadClients": "Clientes de download", + "Events": "Eventos", + "General": "Geral", + "History": "Histórico", + "ImportLists": "Listas de importação", + "Indexers": "Indexadores", + "AbsoluteEpisodeNumbers": "Número(s) absoluto(s) do episódio", + "AirDate": "Data de Exibição", + "Daily": "Diário", + "Details": "Detalhes", + "AllTitles": "Todos os Títulos", + "Version": "Versão", + "ApplyTagsHelpTextHowToApplyDownloadClients": "Como aplicar tags aos clientes de download selecionados", + "ApplyTagsHelpTextHowToApplyImportLists": "Como aplicar tags às listas de importação selecionadas", + "ApplyTagsHelpTextHowToApplyIndexers": "Como aplicar tags aos indexadores selecionados", + "ApplyTagsHelpTextHowToApplySeries": "Como aplicar tags à série selecionada", + "EpisodeInfo": "Info do Episódio", + "EpisodeNumbers": "Número(s) do(s) Episódio(s)", + "FullSeason": "Temporada Completa", + "Languages": "Idiomas", + "MatchedToEpisodes": "Correspondente aos Episódios", + "MatchedToSeason": "Correspondente a Temporada", + "MatchedToSeries": "Correspondente à Série", + "MultiSeason": "Multi-Temporada", + "PartialSeason": "Temporada Parcial", + "Proper": "Proper", + "Real": "Real", + "Release": "Lançamento", + "ReleaseGroup": "Grupo do Lançamento", + "ReleaseHash": "Hash do Lançamento", + "ReleaseTitle": "Título do Lançamento", + "Repack": "Repack", + "SeasonNumber": "Número da Temporada", + "SeriesTitle": "Título da Série", + "Special": "Especial", + "TestParsing": "Análise de Teste" } diff --git a/src/NzbDrone.Core/Localization/Core/ru.json b/src/NzbDrone.Core/Localization/Core/ru.json index 4f2fc743a..9cdf4829e 100644 --- a/src/NzbDrone.Core/Localization/Core/ru.json +++ b/src/NzbDrone.Core/Localization/Core/ru.json @@ -17,7 +17,6 @@ "EditSeries": "Редактировать серию", "EnableAutomaticSearch": "Включить автоматический поиск", "EnableInteractiveSearch": "Включить интерактивный поиск", - "EnableRss": "Включить RSS", "Enabled": "Включено", "HiddenClickToShow": "Скрыто, нажмите чтобы показать", "HideAdvanced": "Скрыть расширенные", diff --git a/src/NzbDrone.Core/Localization/Core/zh_CN.json b/src/NzbDrone.Core/Localization/Core/zh_CN.json index 501060179..8c07b9b47 100644 --- a/src/NzbDrone.Core/Localization/Core/zh_CN.json +++ b/src/NzbDrone.Core/Localization/Core/zh_CN.json @@ -3,5 +3,38 @@ "DeleteCondition": "删除条件", "DeleteConditionMessageText": "是否确实要删除条件“{0}”?", "DeleteCustomFormatMessageText": "是否确实要删除条件“{0}”?", - "ApiKeyValidationHealthCheckMessage": "请将API密钥更新为至少{0}个字符长。您可以通过设置或配置文件执行此操作" + "ApiKeyValidationHealthCheckMessage": "请将API密钥更新为至少{0}个字符长。您可以通过设置或配置文件执行此操作", + "RemoveSelectedItemQueueMessageText": "您确定要从队列中删除 1 项吗?", + "RemoveSelectedItemsQueueMessageText": "您确定要从队列中删除 {0} 个项目吗?", + "ApplyChanges": "应用更改", + "AutomaticAdd": "自动添加", + "Browser Reload Required": "需要重新加载浏览器", + "EditSelectedDownloadClients": "编辑选定的下载客户端", + "EditSelectedIndexers": "编辑选定的索引器", + "EditSelectedImportLists": "编辑选定的导入列表", + "HiddenClickToShow": "隐藏,点击显示", + "HideAdvanced": "隐藏高级", + "Language": "语言", + "RemoveCompletedDownloads": "删除已完成的下载", + "RemoveFailedDownloads": "删除失败的下载", + "ShowAdvanced": "显示高级", + "ShownClickToHide": "显示,点击隐藏", + "UI Language": "用户界面语言", + "DeleteSelectedDownloadClients": "删除下载客户端", + "DeleteSelectedImportLists": "删除导入列表", + "DeleteSelectedIndexers": "删除索引器", + "Implementation": "执行", + "ManageClients": "管理客户", + "ManageDownloadClients": "管理下载客户端", + "ManageImportLists": "管理导入列表", + "ManageIndexers": "管理索引器", + "ManageLists": "管理列表", + "NoDownloadClientsFound": "找不到下载客户端", + "NoImportListsFound": "未找到导入列表", + "NoIndexersFound": "未找到索引器", + "Added": "已添加", + "Add": "添加", + "AddingTag": "添加标签", + "Apply": "应用", + "ApplyTags": "应用标签" } diff --git a/src/NzbDrone.Core/RemotePathMappings/RemotePathMappingService.cs b/src/NzbDrone.Core/RemotePathMappings/RemotePathMappingService.cs index 859bcbee4..5e033b582 100644 --- a/src/NzbDrone.Core/RemotePathMappings/RemotePathMappingService.cs +++ b/src/NzbDrone.Core/RemotePathMappings/RemotePathMappingService.cs @@ -101,12 +101,12 @@ namespace NzbDrone.Core.RemotePathMappings if (remotePath.IsEmpty) { - throw new ArgumentException("Invalid RemotePath"); + throw new ArgumentException("Invalid RemotePath. RemotePath cannot be empty."); } if (localPath.IsEmpty || !localPath.IsRooted) { - throw new ArgumentException("Invalid LocalPath"); + throw new ArgumentException("Invalid LocalPath. LocalPath cannot be empty and must not be the root."); } if (!_diskProvider.FolderExists(localPath.FullPath)) @@ -116,7 +116,7 @@ namespace NzbDrone.Core.RemotePathMappings if (existing.Exists(r => r.Host == mapping.Host && r.RemotePath == mapping.RemotePath)) { - throw new InvalidOperationException("RemotePath already mounted."); + throw new InvalidOperationException("RemotePath already configured."); } } @@ -127,11 +127,14 @@ namespace NzbDrone.Core.RemotePathMappings return remotePath; } + _logger.Trace("Evaluating remote path remote mappings for match to host [{0}] and remote path [{1}]", host, remotePath.FullPath); foreach (var mapping in All()) { + _logger.Trace("Checking configured remote path mapping: {0} - {1}", mapping.Host, mapping.RemotePath); if (host.Equals(mapping.Host, StringComparison.InvariantCultureIgnoreCase) && new OsPath(mapping.RemotePath).Contains(remotePath)) { var localPath = new OsPath(mapping.LocalPath) + (remotePath - new OsPath(mapping.RemotePath)); + _logger.Debug("Remapped remote path [{0}] to local path [{1}] for host [{2}]", remotePath, localPath, host); return localPath; } @@ -147,11 +150,14 @@ namespace NzbDrone.Core.RemotePathMappings return localPath; } + _logger.Trace("Evaluating remote path local mappings for match to host [{0}] and local path [{1}]", host, localPath.FullPath); foreach (var mapping in All()) { + _logger.Trace("Checking configured remote path mapping {0} - {1}", mapping.Host, mapping.RemotePath); if (host.Equals(mapping.Host, StringComparison.InvariantCultureIgnoreCase) && new OsPath(mapping.LocalPath).Contains(localPath)) { var remotePath = new OsPath(mapping.RemotePath) + (localPath - new OsPath(mapping.LocalPath)); + _logger.Debug("Remapped local path [{0}] to remote path [{1}] for host [{2}]", localPath, remotePath, host); return remotePath; } diff --git a/src/Sonarr.Api.V3/openapi.json b/src/Sonarr.Api.V3/openapi.json index 15432ae5a..f585f2877 100644 --- a/src/Sonarr.Api.V3/openapi.json +++ b/src/Sonarr.Api.V3/openapi.json @@ -3327,18 +3327,6 @@ } } }, - "/initialize.js": { - "get": { - "tags": [ - "InitializeJs" - ], - "responses": { - "200": { - "description": "Success" - } - } - } - }, "/api/v3/language": { "get": { "tags": [ @@ -9025,6 +9013,10 @@ }, "nullable": true }, + "customFormatScore": { + "type": "integer", + "format": "int32" + }, "rejections": { "type": "array", "items": {