diff --git a/frontend/src/InteractiveImport/Episode/SelectEpisodeModalContent.tsx b/frontend/src/InteractiveImport/Episode/SelectEpisodeModalContent.tsx index e6b10ddc2..598b64a70 100644 --- a/frontend/src/InteractiveImport/Episode/SelectEpisodeModalContent.tsx +++ b/frontend/src/InteractiveImport/Episode/SelectEpisodeModalContent.tsx @@ -71,7 +71,7 @@ interface SelectEpisodeModalContentProps { isAnime: boolean; sortKey?: string; sortDirection?: string; - modalTitle?: string; + modalTitle: string; onEpisodesSelect(selectedEpisodes: SelectedEpisode[]): unknown; onModalClose(): unknown; } @@ -103,7 +103,7 @@ function SelectEpisodeModalContent(props: SelectEpisodeModalContentProps) { const dispatch = useDispatch(); const filterEpisodeNumber = parseInt(filter); - const errorMessage = getErrorMessage(error, 'Unable to load episodes'); + const errorMessage = getErrorMessage(error, translate('EpisodesLoadError')); const selectedCount = selectedIds.length; const selectedEpisodesCount = getSelectedIds(selectedState).length; const selectionIsValid = @@ -197,13 +197,15 @@ function SelectEpisodeModalContent(props: SelectEpisodeModalContentProps) { if (!details) { details = selectedCount > 1 - ? `${selectedCount} selected files` - : `${selectedCount} selected file`; + ? translate('CountSelectedFiles', { selectedCount }) + : translate('CountSelectedFile', { selectedCount }); } return ( - {modalTitle} - Select Episode(s) + + {translate('SelectEpisodesModalTitle', { modalTitle })} + @@ -265,14 +267,14 @@ function SelectEpisodeModalContent(props: SelectEpisodeModalContentProps) {
{details}
- +
diff --git a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.tsx b/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.tsx index a4f0e82e7..8013765f9 100644 --- a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.tsx +++ b/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.tsx @@ -100,7 +100,7 @@ function InteractiveImportSelectFolderModalContent( return ( - {modalTitle} - {translate('SelectFolder')} + {translate('SelectFolderModalTitle', { modalTitle })} diff --git a/frontend/src/InteractiveImport/Folder/RecentFolderRow.js b/frontend/src/InteractiveImport/Folder/RecentFolderRow.js index 5b205ba7b..3903f0d71 100644 --- a/frontend/src/InteractiveImport/Folder/RecentFolderRow.js +++ b/frontend/src/InteractiveImport/Folder/RecentFolderRow.js @@ -5,6 +5,7 @@ import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellCo import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRowButton from 'Components/Table/TableRowButton'; import { icons } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './RecentFolderRow.css'; class RecentFolderRow extends Component { @@ -44,7 +45,7 @@ class RecentFolderRow extends Component { diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.tsx b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.tsx index 8e5276217..d191e8d10 100644 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.tsx +++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.tsx @@ -147,9 +147,19 @@ const COLUMNS = [ ]; const importModeOptions = [ - { key: 'chooseImportMode', value: 'Choose Import Mode', disabled: true }, - { key: 'move', value: 'Move Files' }, - { key: 'copy', value: 'Hardlink/Copy Files' }, + { + key: 'chooseImportMode', + value: () => translate('ChooseImportMode'), + disabled: true, + }, + { + key: 'move', + value: () => translate('MoveFiles'), + }, + { + key: 'copy', + value: () => translate('HardlinkCopyFiles'), + }, ]; function isSameEpisodeFile( @@ -260,12 +270,31 @@ function InteractiveImportModalContent( useState(null); const [selectState, setSelectState] = useSelectState(); const [bulkSelectOptions, setBulkSelectOptions] = useState([ - { key: 'select', value: 'Select...', disabled: true }, - { key: 'season', value: 'Select Season' }, - { key: 'episode', value: 'Select Episode(s)' }, - { key: 'quality', value: 'Select Quality' }, - { key: 'releaseGroup', value: 'Select Release Group' }, - { key: 'language', value: 'Select Language' }, + { + key: 'select', + value: translate('SelectDropdown'), + disabled: true, + }, + { + key: 'season', + value: translate('SelectSeason'), + }, + { + key: 'episode', + value: translate('SelectEpisodes'), + }, + { + key: 'quality', + value: translate('SelectQuality'), + }, + { + key: 'releaseGroup', + value: translate('SelectReleaseGroup'), + }, + { + key: 'language', + value: translate('SelectLanguage'), + }, ]); const { allSelected, allUnselected, selectedState } = selectState; const previousIsDeleting = usePrevious(isDeleting); @@ -296,7 +325,7 @@ function InteractiveImportModalContent( newBulkSelectOptions.splice(1, 0, { key: 'series', - value: 'Select Series', + value: translate('SelectSeries'), }); setBulkSelectOptions(newBulkSelectOptions); @@ -410,7 +439,9 @@ function InteractiveImportModalContent( const files: InteractiveImportCommandOptions[] = []; if (finalImportMode === 'chooseImportMode') { - setInteractiveImportErrorMessage('An import mode must be selected'); + setInteractiveImportErrorMessage( + translate('InteractiveImportNoImportMode') + ); return; } @@ -431,35 +462,35 @@ function InteractiveImportModalContent( if (!series) { setInteractiveImportErrorMessage( - 'Series must be chosen for each selected file' + translate('InteractiveImportNoSeries') ); return; } if (isNaN(seasonNumber)) { setInteractiveImportErrorMessage( - 'Season must be chosen for each selected file' + translate('InteractiveImportNoSeason') ); return; } if (!episodes || !episodes.length) { setInteractiveImportErrorMessage( - 'One or more episodes must be chosen for each selected file' + translate('InteractiveImportNoEpisode') ); return; } if (!quality) { setInteractiveImportErrorMessage( - 'Quality must be chosen for each selected file' + translate('InteractiveImportNoQuality') ); return; } if (!languages) { setInteractiveImportErrorMessage( - 'Language(s) must be chosen for each selected file' + translate('InteractiveImportNoLanguage') ); return; } @@ -699,7 +730,7 @@ function InteractiveImportModalContent( const errorMessage = getErrorMessage( error, - 'Unable to load manual import items' + translate('InteractiveImportLoadError') ); return ( @@ -716,7 +747,9 @@ function InteractiveImportModalContent(
- {filterExistingFiles ? 'Unmapped Files Only' : 'All Files'} + {filterExistingFiles + ? translate('UnmappedFilesOnly') + : translate('AllFiles')}
@@ -726,7 +759,7 @@ function InteractiveImportModalContent( isSelected={!filterExistingFiles} onPress={onFilterExistingFilesChange} > - All Files + {translate('AllFiles')} - Unmapped Files Only + {translate('UnmappedFilesOnly')} @@ -777,7 +810,7 @@ function InteractiveImportModalContent( ) : null} {isPopulated && !items.length && !isFetching - ? 'No video files were found in the selected folder' + ? translate('InteractiveImportNoFilesFound') : null}
@@ -793,7 +826,7 @@ function InteractiveImportModalContent( } onPress={onDeleteSelectedPress} > - Delete + {translate('Delete')} ) : null} @@ -831,7 +864,7 @@ function InteractiveImportModalContent( isDisabled={!selectedIds.length || !!invalidRowsSelected.length} onPress={onImportSelectedPress} > - Import + {translate('Import')} @@ -891,9 +924,9 @@ function InteractiveImportModalContent( diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.tsx b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.tsx index 3689a74cd..ff81794bc 100644 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.tsx +++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.tsx @@ -348,7 +348,9 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { {isSeriesColumnVisible ? ( {showSeriesPlaceholder ? ( @@ -361,7 +363,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { {showSeasonNumberPlaceholder ? ( @@ -379,7 +381,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { isDisabled={!series || requiresSeasonNumber} title={ series && !requiresSeasonNumber - ? 'Click to change episode' + ? translate('ClickToChangeEpisode') : undefined } onPress={onSelectEpisodePress} @@ -392,7 +394,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { {showReleaseGroupPlaceholder ? ( @@ -404,7 +406,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { {showQualityPlaceholder && } @@ -416,7 +418,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { {showLanguagePlaceholder && } @@ -450,7 +452,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) { {rejections.length ? ( } - title="Release Rejected" + title={translate('ReleaseRejected')} body={
    {rejections.map((rejection, index) => { diff --git a/frontend/src/InteractiveImport/InteractiveImportModal.tsx b/frontend/src/InteractiveImport/InteractiveImportModal.tsx index 811bbf0f2..37b26012e 100644 --- a/frontend/src/InteractiveImport/InteractiveImportModal.tsx +++ b/frontend/src/InteractiveImport/InteractiveImportModal.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import Modal from 'Components/Modal/Modal'; import usePrevious from 'Helpers/Hooks/usePrevious'; import { sizes } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import InteractiveImportSelectFolderModalContent from './Folder/InteractiveImportSelectFolderModalContent'; import InteractiveImportModalContent from './Interactive/InteractiveImportModalContent'; @@ -18,7 +19,7 @@ function InteractiveImportModal(props: InteractiveImportModalProps) { isOpen, folder, downloadId, - modalTitle = 'Manual Import', + modalTitle = translate('ManualImport'), onModalClose, ...otherProps } = props; diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.tsx b/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.tsx index 42f21aa68..a0ae1e4dc 100644 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.tsx +++ b/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.tsx @@ -16,6 +16,7 @@ import ModalHeader from 'Components/Modal/ModalHeader'; import { inputTypes, kinds, sizes } from 'Helpers/Props'; import Language from 'Language/Language'; import createLanguagesSelector from 'Store/Selectors/createLanguagesSelector'; +import translate from 'Utilities/String/translate'; import styles from './SelectLanguageModalContent.css'; interface SelectLanguageModalContentProps { @@ -78,13 +79,15 @@ function SelectLanguageModalContent(props: SelectLanguageModalContentProps) { return ( - {modalTitle} - Select Language + + {translate('SelectLanguageModalTitle', { modalTitle })} + {isFetching ? : null} {!isFetching && error ? ( - Unable to load Languages + {translate('LanguagesLoadError')} ) : null} {isPopulated && !error ? ( @@ -111,10 +114,10 @@ function SelectLanguageModalContent(props: SelectLanguageModalContentProps) { - + diff --git a/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.tsx b/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.tsx index 87d5e0e14..edb65663c 100644 --- a/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.tsx +++ b/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.tsx @@ -19,6 +19,7 @@ import Quality, { QualityModel } from 'Quality/Quality'; import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; import { CheckInputChanged } from 'typings/inputs'; import getQualities from 'Utilities/Quality/getQualities'; +import translate from 'Utilities/String/translate'; interface QualitySchemaState { isFetching: boolean; @@ -128,13 +129,13 @@ function SelectQualityModalContent(props: SelectQualityModalContentProps) { {isFetching && } {!isFetching && error ? ( - Unable to load qualities + {translate('QualitiesLoadError')} ) : null} {isPopulated && !error ? (
    - Quality + {translate('Quality')} - Proper + {translate('Proper')} - Real + {translate('Real')} Cancel diff --git a/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.tsx b/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.tsx index ed44d2030..f937c125d 100644 --- a/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.tsx +++ b/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.tsx @@ -9,6 +9,7 @@ import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import { inputTypes, kinds, scrollDirections } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './SelectReleaseGroupModalContent.css'; interface SelectReleaseGroupModalContentProps { @@ -37,7 +38,9 @@ function SelectReleaseGroupModalContent( return ( - {modalTitle} - Set Release Group + + {translate('SetReleaseGroupModalTitle', { modalTitle })} + - Release Group + {translate('ReleaseGroup')} - + diff --git a/frontend/src/InteractiveImport/Season/SelectSeasonModalContent.tsx b/frontend/src/InteractiveImport/Season/SelectSeasonModalContent.tsx index b0e18a6ef..3139d3001 100644 --- a/frontend/src/InteractiveImport/Season/SelectSeasonModalContent.tsx +++ b/frontend/src/InteractiveImport/Season/SelectSeasonModalContent.tsx @@ -7,6 +7,7 @@ import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import { Season } from 'Series/Series'; import { createSeriesSelectorForHook } from 'Store/Selectors/createSeriesSelector'; +import translate from 'Utilities/String/translate'; import SelectSeasonRow from './SelectSeasonRow'; interface SelectSeasonModalContentProps { @@ -25,7 +26,9 @@ function SelectSeasonModalContent(props: SelectSeasonModalContentProps) { return ( - {modalTitle} - Select Season + + {translate('SelectSeasonModalTitle', { modalTitle })} + {seasons.map((item) => { @@ -40,7 +43,7 @@ function SelectSeasonModalContent(props: SelectSeasonModalContentProps) { - + ); diff --git a/frontend/src/InteractiveImport/Season/SelectSeasonRow.tsx b/frontend/src/InteractiveImport/Season/SelectSeasonRow.tsx index b8196b06c..d93d01a28 100644 --- a/frontend/src/InteractiveImport/Season/SelectSeasonRow.tsx +++ b/frontend/src/InteractiveImport/Season/SelectSeasonRow.tsx @@ -1,5 +1,6 @@ import React, { useCallback } from 'react'; import Link from 'Components/Link/Link'; +import translate from 'Utilities/String/translate'; import styles from './SelectSeasonRow.css'; interface SelectSeasonRowProps { @@ -20,7 +21,9 @@ function SelectSeasonRow(props: SelectSeasonRowProps) { component="div" onPress={onSeasonSelectWrapper} > - {seasonNumber === 0 ? 'Specials' : `Season ${seasonNumber}`} + {seasonNumber === 0 + ? translate('Specials') + : translate('SeasonNumberToken', { seasonNumber })} ); } diff --git a/frontend/src/InteractiveImport/Series/SelectSeriesModalContent.tsx b/frontend/src/InteractiveImport/Series/SelectSeriesModalContent.tsx index c3c9a92a5..038cdd2cc 100644 --- a/frontend/src/InteractiveImport/Series/SelectSeriesModalContent.tsx +++ b/frontend/src/InteractiveImport/Series/SelectSeriesModalContent.tsx @@ -10,6 +10,7 @@ import Scroller from 'Components/Scroller/Scroller'; import { scrollDirections } from 'Helpers/Props'; import Series from 'Series/Series'; import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector'; +import translate from 'Utilities/String/translate'; import SelectSeriesRow from './SelectSeriesRow'; import styles from './SelectSeriesModalContent.css'; @@ -61,7 +62,7 @@ function SelectSeriesModalContent(props: SelectSeriesModalContentProps) { > - + ); diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index ff95889bc..5d8a48a27 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -61,6 +61,7 @@ "AirsTimeOn": "{time} on {networkLabel}", "AirsTomorrowOn": "Tomorrow at {time} on {networkLabel}", "All": "All", + "AllFiles": "All Files", "AllResultsAreHiddenByTheAppliedFilter": "All results are hidden by the applied filter", "AllSeriesInRootFolderHaveBeenImported": "All series in {path} have been imported", "AllTitles": "All Titles", @@ -166,10 +167,17 @@ "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.", "ChooseAnotherFolder": "Choose another folder", + "ChooseImportMode": "Choose Import Mode", "ChownGroup": "chown Group", "ChownGroupHelpText": "Group name or gid. Use gid for remote file systems.", "ChownGroupHelpTextWarning": "This only works if the user running sonarr is the owner of the file. It's better to ensure the download client uses the same group as sonarr.", "Clear": "Clear", + "ClickToChangeEpisode": "Click to change episode", + "ClickToChangeLanguage": "Click to change language", + "ClickToChangeQuality": "Click to change quality", + "ClickToChangeReleaseGroup": "Click to change release group", + "ClickToChangeSeason": "Click to change season", + "ClickToChangeSeries": "Click to change series", "ClientPriority": "Client Priority", "Clone": "Clone", "CloneAutoTag": "Clone Auto Tag", @@ -205,6 +213,8 @@ "CountImportListsSelected": "{count} import list(s) selected", "CountIndexersSelected": "{count} indexer(s) selected", "CountSeasons": "{count} Seasons", + "CountSelectedFile": "{selectedCount} selected file", + "CountSelectedFiles": "{selectedCount} selected files", "CreateEmptySeriesFolders": "Create Empty Series Folders", "CreateEmptySeriesFoldersHelpText": "Create missing series folders during disk scan", "CreateGroup": "Create Group", @@ -277,6 +287,8 @@ "DeleteRootFolderMessageText": "Are you sure you want to delete the root folder '{path}'?", "DeleteSelectedDownloadClients": "Delete Download Client(s)", "DeleteSelectedDownloadClientsMessageText": "Are you sure you want to delete {count} selected download client(s)?", + "DeleteSelectedEpisodeFiles": "Delete Selected Episode Files", + "DeleteSelectedEpisodeFilesHelpText": "Are you sure you want to delete the selected episode files?", "DeleteSelectedImportLists": "Delete Import List(s)", "DeleteSelectedImportListsMessageText": "Are you sure you want to delete {count} selected import list(s)?", "DeleteSelectedIndexers": "Delete Indexer(s)", @@ -401,6 +413,7 @@ "EpisodeTitleRequired": "Episode Title Required", "EpisodeTitleRequiredHelpText": "Prevent importing for up to 48 hours if the episode title is in the naming format and the episode title is TBA", "Episodes": "Episodes", + "EpisodesLoadError": "Unable to load episodes", "Error": "Error", "ErrorLoadingContent": "There was an error loading this content", "ErrorLoadingContents": "Error loading contents", @@ -445,6 +458,7 @@ "FilterDoesNotEndWith": "does not end with", "FilterDoesNotStartWith": "does not start with", "FilterEndsWith": "ends with", + "FilterEpisodesPlaceholder": "Filter episodes by title or number", "FilterEqual": "equal", "FilterGreaterThan": "greater than", "FilterGreaterThanOrEqual": "greater than or equal", @@ -459,6 +473,7 @@ "FilterNotEqual": "not equal", "FilterNotInLast": "not in the last", "FilterNotInNext": "not in the next", + "FilterSeriesPlaceholder": "Filter series", "FilterStartsWith": "starts with", "FinaleTooltip": "Series or season finale", "FirstDayOfWeek": "First Day of Week", @@ -484,6 +499,7 @@ "Grabbed": "Grabbed", "GrabbedHistoryTooltip": "Episode grabbed from {indexer} and sent to {downloadClient}", "Group": "Group", + "HardlinkCopyFiles": "Hardlink/Copy Files", "HasMissingSeason": "Has Missing Season", "Health": "Health", "Here": "here", @@ -577,6 +593,14 @@ "InstanceName": "Instance Name", "InstanceNameHelpText": "Instance name in tab and for Syslog app name", "InteractiveImport": "Interactive Import", + "InteractiveImportLoadError": "Unable to load manual import items", + "InteractiveImportNoEpisode": "One or more episodes must be chosen for each selected file", + "InteractiveImportNoFilesFound": "No video files were found in the selected folder", + "InteractiveImportNoImportMode": "An import mode must be selected", + "InteractiveImportNoLanguage": "Language(s) must be chosen for each selected file", + "InteractiveImportNoQuality": "Quality must be chosen for each selected file", + "InteractiveImportNoSeason": "Season must be chosen for each selected file", + "InteractiveImportNoSeries": "Series must be chosen for each selected file", "InteractiveSearch": "Interactive Search", "Interval": "Interval", "InvalidFormat": "Invalid Format", @@ -629,6 +653,7 @@ "ManageIndexers": "Manage Indexers", "ManageLists": "Manage Lists", "Manual": "Manual", + "ManualImport": "Manual Import", "ManualImportItemsLoadError": "Unable to load manual import items", "MappedNetworkDrivesWindowsService": "Mapped network drives are not available when running as a Windows Service, see the [FAQ](https://wiki.servarr.com/sonarr/faq#why-cant-sonarr-see-my-files-on-a-remote-server) for more information.", "MarkAsFailed": "Mark as Failed", @@ -701,6 +726,7 @@ "MoreInfo": "More Info", "MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ", "MoveAutomatically": "Move Automatically", + "MoveFiles": "Move Files", "MultiEpisode": "Multi Episode", "MultiEpisodeInvalidFormat": "Multi Episode: Invalid Format", "MultiEpisodeStyle": "Multi Episode Style", @@ -730,6 +756,7 @@ "NoDownloadClientsFound": "No download clients found", "NoEpisodeHistory": "No episode history", "NoEpisodeOverview": "No episode overview", + "NoEpisodesFoundForSelectedSeason": "No episodes were found for the selected season", "NoEventsFound": "No events found", "NoHistoryBlocklist": "No history blocklist", "NoHistoryFound": "No history found", @@ -877,6 +904,7 @@ "ReleaseProfileTagHelpText": "Release profiles will apply to series with at least one matching tag. Leave blank to apply to all series", "ReleaseProfiles": "Release Profiles", "ReleaseProfilesLoadError": "Unable to load Release Profiles", + "ReleaseRejected": "Release Rejected", "ReleaseTitle": "Release Title", "Reload": "Reload", "RemotePath": "Remote Path", @@ -1007,13 +1035,26 @@ "SeasonFolder": "Season Folder", "SeasonFolderFormat": "Season Folder Format", "SeasonNumber": "Season Number", + "SeasonNumberToken": "Season {seasonNumber}", "SeasonPack": "Season Pack", "SeasonPremiere": "Season Premiere", "SeasonPremieresOnly": "Season Premieres Only", "Seasons": "Seasons", "Security": "Security", "Seeders": "Seeders", + "SelectDropdown": "Select...", + "SelectEpisodes": "Select Episode(s)", + "SelectEpisodesModalTitle": "{modalTitle} - Select Episode(s)", "SelectFolder": "Select Folder", + "SelectFolderModalTitle": "{modalTitle} - Select Folder", + "SelectLanguage": "Select Language", + "SelectLanguageModalTitle": "{modalTitle} - Select Language", + "SelectLanguages": "Select Languages", + "SelectQuality": "Select Quality", + "SelectReleaseGroup": "Select Release Group", + "SelectSeason": "Select Season", + "SelectSeasonModalTitle": "{modalTitle} - Select Season", + "SelectSeries": "Select Series", "SendAnonymousUsageData": "Send Anonymous Usage Data", "Series": "Series", "SeriesAndEpisodeInformationIsProvidedByTheTVDB": "Series and episode information is provided by TheTVDB.com. [Please consider supporting them](https://www.thetvdb.com/subscribe).", @@ -1034,6 +1075,8 @@ "SetPermissions": "Set Permissions", "SetPermissionsLinuxHelpText": "Should chmod be run when files are imported/renamed?", "SetPermissionsLinuxHelpTextWarning": "If you're unsure what these settings do, do not alter them.", + "SetReleaseGroup": "Set Release Group", + "SetReleaseGroupModalTitle": "{modalTitle} - Set Release Group", "SetTags": "Set Tags", "Settings": "Settings", "ShortDateFormat": "Short Date Format", @@ -1069,6 +1112,7 @@ "Space": "Space", "Special": "Special", "SpecialEpisode": "Special Episode", + "Specials": "Specials", "SpecialsFolderFormat": "Specials Folder Format", "SslCertPassword": "SSL Cert Password", "SslCertPasswordHelpText": "Password for pfx file", @@ -1168,6 +1212,7 @@ "Unknown": "Unknown", "UnknownEventTooltip": "Unknown event", "Unlimited": "Unlimited", + "UnmappedFilesOnly": "Unmapped Files Only", "UnmappedFolders": "Unmapped Folders", "UnmonitorDeletedEpisodes": "Unmonitor Deleted Episodes", "UnmonitorDeletedEpisodesHelpText": "Episodes deleted from disk are automatically unmonitored in Sonarr",