Translate Frontend InteractiveSearch

This commit is contained in:
Stevie Robinson 2023-08-15 09:18:35 +02:00 committed by Mark McDowall
parent 78d4dee461
commit efca704388
7 changed files with 76 additions and 37 deletions

View File

@ -139,10 +139,9 @@ function InteractiveSearch(props) {
{
errorMessage ?
<Fragment>
Search failed because its {errorMessage.charAt(0).toLowerCase() + errorMessage.slice(1)}.
Try refreshing the series info and verify the necessary information is present before searching again
{translate('InteractiveSearchResultsFailedErrorMessage', { message: errorMessage.charAt(0).toLowerCase() + errorMessage.slice(1) })}
</Fragment> :
'Unable to load results for this episode search. Try again later'
translate('EpisodeSearchResultsLoadError')
}
</div> :
null

View File

@ -20,6 +20,7 @@ import formatDateTime from 'Utilities/Date/formatDateTime';
import formatAge from 'Utilities/Number/formatAge';
import formatBytes from 'Utilities/Number/formatBytes';
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
import translate from 'Utilities/String/translate';
import OverrideMatchModal from './OverrideMatch/OverrideMatchModal';
import Peers from './Peers';
import ReleaseEpisode from './ReleaseEpisode';
@ -62,12 +63,12 @@ function getDownloadTooltip(
if (isGrabbing) {
return '';
} else if (isGrabbed) {
return 'Added to download queue';
return translate('AddToDownloadQueue');
} else if (grabError) {
return grabError;
}
return 'Add to download queue';
return translate('AddedToDownloadQueue');
}
interface InteractiveSearchRowProps {
@ -261,7 +262,7 @@ function InteractiveSearchRow(props: InteractiveSearchRowProps) {
{rejections.length ? (
<Popover
anchor={<Icon name={icons.DANGER} kind={kinds.DANGER} />}
title="Release Rejected"
title={translate('ReleaseRejected')}
body={
<ul>
{rejections.map((rejection, index) => {
@ -285,7 +286,7 @@ function InteractiveSearchRow(props: InteractiveSearchRowProps) {
<Link
className={styles.manualDownloadContent}
title="Override and add to download queue"
title={translate('OverrideAndAddToDownloadQueue')}
onPress={onOverridePress}
>
<div className={styles.manualDownloadContent}>
@ -307,9 +308,9 @@ function InteractiveSearchRow(props: InteractiveSearchRowProps) {
<ConfirmModal
isOpen={isConfirmGrabModalOpen}
kind={kinds.WARNING}
title="Grab Release"
message={`Sonarr was unable to determine which series and episode this release was for. Sonarr may be unable to automatically import this release. Do you want to grab '${title}'?`}
confirmLabel="Grab"
title={translate('GrabRelease')}
message={translate('GrabReleaseMessageText', { title })}
confirmLabel={translate('Grab')}
onConfirm={onGrabConfirm}
onCancel={onGrabCancel}
/>

View File

@ -32,13 +32,17 @@ function SelectDownloadClientModalContent(
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>{modalTitle} - Select Download Client</ModalHeader>
<ModalHeader>
{translate('SelectDownloadClientModalTitle', { modalTitle })}
</ModalHeader>
<ModalBody>
{isFetching ? <LoadingIndicator /> : null}
{!isFetching && error ? (
<Alert kind={kinds.DANGER}>Unable to load download clients</Alert>
<Alert kind={kinds.DANGER}>
{translate('DownloadClientsLoadError')}
</Alert>
) : null}
{isPopulated && !error ? (

View File

@ -1,5 +1,6 @@
import React, { useCallback } from 'react';
import Link from 'Components/Link/Link';
import translate from 'Utilities/String/translate';
import styles from './SelectDownloadClientRow.css';
interface SelectSeasonRowProps {
@ -23,7 +24,7 @@ function SelectDownloadClientRow(props: SelectSeasonRowProps) {
onPress={onSeasonSelectWrapper}
>
<div>{name}</div>
<div>Priority: {priority}</div>
<div>{translate('PrioritySettings', { priority })}</div>
</Link>
);
}

View File

@ -56,7 +56,7 @@ interface OverrideMatchModalContentProps {
}
function OverrideMatchModalContent(props: OverrideMatchModalContentProps) {
const modalTitle = 'Manual Grab';
const modalTitle = translate('ManualGrab');
const {
indexerId,
title,
@ -185,16 +185,16 @@ function OverrideMatchModalContent(props: OverrideMatchModalContentProps) {
const onGrabPress = useCallback(() => {
if (!seriesId) {
setError('Series must be selected');
setError(translate('OverrideGrabNoSeries'));
return;
} else if (!episodes.length) {
setError('At least one episode must be selected');
setError(translate('OverrideGrabNoEpisode'));
return;
} else if (!quality) {
setError('Quality must be selected');
setError(translate('OverrideGrabNoQuality'));
return;
} else if (!languages.length) {
setError('At least one language must be selected');
setError(translate('OverrideGrabNoLanguage'));
return;
}
@ -239,7 +239,7 @@ function OverrideMatchModalContent(props: OverrideMatchModalContentProps) {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{translate('Override and Grab - {title}', { title })}
{translate('OverrideGrabModalTitle', { title })}
</ModalHeader>
<ModalBody>
@ -257,7 +257,7 @@ function OverrideMatchModalContent(props: OverrideMatchModalContentProps) {
<DescriptionListItem
className={styles.item}
title={translate('Season Number')}
title={translate('SeasonNumber')}
data={
<OverrideMatchData
value={seasonNumber}
@ -311,13 +311,13 @@ function OverrideMatchModalContent(props: OverrideMatchModalContentProps) {
{downloadClients.length > 1 ? (
<DescriptionListItem
className={styles.item}
title={translate('Download Client')}
title={translate('DownloadClient')}
data={
<OverrideMatchData
value={
downloadClients.find(
(downloadClient) => downloadClient.id === downloadClientId
)?.name ?? 'Default'
)?.name ?? translate('Default')
}
onPress={onSelectDownloadClientPress}
/>
@ -338,7 +338,7 @@ function OverrideMatchModalContent(props: OverrideMatchModalContentProps) {
error={grabError}
onPress={onGrabPress}
>
{translate('Grab Release')}
{translate('GrabRelease')}
</SpinnerErrorButton>
</div>
</ModalFooter>

View File

@ -6,6 +6,7 @@ import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'
import Icon from 'Components/Icon';
import Popover from 'Components/Tooltip/Popover';
import { icons, tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './ReleaseSceneIndicator.css';
function formatReleaseNumber(
@ -32,7 +33,7 @@ function formatReleaseNumber(
}
if (seasonNumber !== undefined) {
return `Season ${seasonNumber}`;
return translate('SeasonNumberToken', { seasonNumber });
}
return null;
@ -112,22 +113,28 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
level = styles.levelMixed;
messages.push(
<div key="source">
{comment ?? 'Source'} releases exist with ambiguous numbering, unable to
reliably identify episode.
{translate('ReleaseSceneIndicatorSourceMessage', {
message: comment ?? 'Source',
})}
</div>
);
} else if (isUnknown) {
level = styles.levelUnknown;
messages.push(
<div key="unknown">
Numbering varies for this episode and release does not match any known
mappings.
{translate('ReleaseSceneIndicatorUnknownMessage')}
</div>
);
if (sceneOrigin === 'unknown') {
messages.push(<div key="origin">Assuming Scene numbering.</div>);
messages.push(
<div key="origin">
{translate('ReleaseSceneIndicatorAssumingScene')}.
</div>
);
} else if (sceneOrigin === 'unknown:tvdb') {
messages.push(<div key="origin">Assuming TheTVDB numbering.</div>);
messages.push(
<div key="origin">{translate('ReleaseSceneIndicatorAssumingTvdb')}</div>
);
}
} else if (mappingDifferent) {
level = styles.levelMapped;
@ -142,11 +149,15 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
if (mappedNumber) {
messages.push(
<div key="not-requested">
Mapped episode wasn't requested in this search.
{translate('ReleaseSceneIndicatorMappedNotRequested')}
</div>
);
} else {
messages.push(<div key="unknown-series">Unknown episode or series.</div>);
messages.push(
<div key="unknown-series">
{translate('ReleaseSceneIndicatorUnknownSeries')}
</div>
);
}
}
@ -156,7 +167,7 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Mapping"
title={translate('Mapping')}
data={comment}
/>
)}
@ -165,7 +176,7 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Title"
title={translate('Title')}
data={title}
/>
)}
@ -174,7 +185,7 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="Release"
title={translate('Release')}
data={releaseNumber ?? 'unknown'}
/>
)}
@ -183,7 +194,7 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
<DescriptionListItem
titleClassName={styles.title}
descriptionClassName={styles.description}
title="TheTVDB"
title={translate('TheTvdb')}
data={mappedNumber ?? 'unknown'}
/>
)}
@ -197,7 +208,7 @@ function ReleaseSceneIndicator(props: ReleaseSceneIndicatorProps) {
<Icon name={icons.SCENE_MAPPING} />
</div>
}
title="Scene Info"
title={translate('SceneInfo')}
body={
<div>
{table}

View File

@ -48,7 +48,9 @@
"AddRemotePathMappingError": "Unable to add a new remote path mapping, please try again.",
"AddRootFolder": "Add Root Folder",
"AddSeriesWithTitle": "Add {title}",
"AddToDownloadQueue": "Add to download queue",
"Added": "Added",
"AddedToDownloadQueue": "Added to download queue",
"AddingTag": "Adding tag",
"AfterManualRefresh": "After Manual Refresh",
"Age": "Age",
@ -241,6 +243,7 @@
"Dates": "Dates",
"Day": "Day",
"Debug": "Debug",
"Default": "Default",
"DefaultCase": "Default Case",
"DefaultDelayProfile": "This is the default profile. It applies to all series that don't have an explicit profile.",
"DefaultNotFoundMessage": "You must be lost, nothing to see here.",
@ -494,7 +497,10 @@
"GeneralSettingsSummary": "Port, SSL, username/password, proxy, analytics and updates",
"Genres": "Genres",
"Global": "Global",
"Grab": "Grab",
"GrabId": "Grab ID",
"GrabRelease": "GrabRelease",
"GrabReleaseMessageText": "Sonarr was unable to determine which series and episode this release was for. Sonarr may be unable to automatically import this release. Do you want to grab '{title}'?",
"GrabSelected": "Grab Selected",
"Grabbed": "Grabbed",
"GrabbedHistoryTooltip": "Episode grabbed from {indexer} and sent to {downloadClient}",
@ -602,6 +608,7 @@
"InteractiveImportNoSeason": "Season must be chosen for each selected file",
"InteractiveImportNoSeries": "Series must be chosen for each selected file",
"InteractiveSearch": "Interactive Search",
"InteractiveSearchResultsFailedErrorMessage": "Search failed because its {message}. Try refreshing the series info and verify the necessary information is present before searching again.",
"Interval": "Interval",
"InvalidFormat": "Invalid Format",
"KeyboardShortcuts": "Keyboard Shortcuts",
@ -653,9 +660,11 @@
"ManageIndexers": "Manage Indexers",
"ManageLists": "Manage Lists",
"Manual": "Manual",
"ManualGrab": "Manual Grab",
"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.",
"Mapping": "Mapping",
"MarkAsFailed": "Mark as Failed",
"MarkAsFailedConfirmation": "Are you sure you want to mark '{sourceTitle}' as failed?",
"MatchedToEpisodes": "Matched to Episodes",
@ -811,6 +820,12 @@
"OriginalLanguage": "Original Language",
"Other": "Other",
"OutputPath": "Output Path",
"OverrideAndAddToDownloadQueue": "Override and add to download queue",
"OverrideGrabModalTitle": "Override and Grab - {title}",
"OverrideGrabNoEpisode": "At least one episode must be selected",
"OverrideGrabNoLanguage": "At least one language must be selected",
"OverrideGrabNoQuality": "Quality must be selected",
"OverrideGrabNoSeries": "Series must be selected",
"PackageVersion": "Package Version",
"PackageVersionInfo": "{packageVersion} by {packageAuthor}",
"PartialSeason": "Partial Season",
@ -907,6 +922,12 @@
"ReleaseProfiles": "Release Profiles",
"ReleaseProfilesLoadError": "Unable to load Release Profiles",
"ReleaseRejected": "Release Rejected",
"ReleaseSceneIndicatorAssumingScene": "Assuming Scene numbering.",
"ReleaseSceneIndicatorAssumingTvdb": "Assuming TVDB numbering.",
"ReleaseSceneIndicatorMappedNotRequested": "Mapped episode wasn't requested in this search.",
"ReleaseSceneIndicatorSourceMessage": "{message} releases exist with ambiguous numbering, unable to reliably identify episode.",
"ReleaseSceneIndicatorUnknownMessage": "Numbering varies for this episode and release does not match any known mappings.",
"ReleaseSceneIndicatorUnknownSeries": "Unknown episode or series.",
"ReleaseTitle": "Release Title",
"Reload": "Reload",
"RemotePath": "Remote Path",
@ -1017,6 +1038,7 @@
"SaveChanges": "Save Changes",
"SaveSettings": "Save Settings",
"Scene": "Scene",
"SceneInfo": "Scene Info",
"SceneInformation": "Scene Information",
"SceneNumberNotVerified": "Scene number hasn't been verified yet",
"SceneNumbering": "Scene Numbering",
@ -1044,6 +1066,7 @@
"Seasons": "Seasons",
"Security": "Security",
"Seeders": "Seeders",
"SelectDownloadClientModalTitle": "{modalTitle} - Select Download Client",
"SelectDropdown": "Select...",
"SelectEpisodes": "Select Episode(s)",
"SelectEpisodesModalTitle": "{modalTitle} - Select Episode(s)",