mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-22 22:16:13 -04:00
Translate frontend series pages
This commit is contained in:
@@ -16,6 +16,7 @@ import Series from 'Series/Series';
|
||||
import { bulkDeleteSeries, setDeleteOption } from 'Store/Actions/seriesActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import { CheckInputChanged } from 'typings/inputs';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './DeleteSeriesModalContent.css';
|
||||
|
||||
interface DeleteSeriesModalContentProps {
|
||||
@@ -86,34 +87,38 @@ function DeleteSeriesModalContent(props: DeleteSeriesModalContentProps) {
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>Delete Selected Series</ModalHeader>
|
||||
<ModalHeader>{translate('DeleteSelectedSeries')}</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<div>
|
||||
<FormGroup>
|
||||
<FormLabel>Add List Exclusion</FormLabel>
|
||||
<FormLabel>{translate('AddListExclusion')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="addImportListExclusion"
|
||||
value={addImportListExclusion}
|
||||
helpText="Prevent series from being added to Sonarr by lists"
|
||||
helpText={translate('AddListExclusionHelpText')}
|
||||
onChange={onDeleteOptionChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{`Delete Series Folder${
|
||||
series.length > 1 ? 's' : ''
|
||||
}`}</FormLabel>
|
||||
<FormLabel>
|
||||
{series.length > 1
|
||||
? translate('DeleteSeriesFolders')
|
||||
: translate('DeleteSeriesFolder')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="deleteFiles"
|
||||
value={deleteFiles}
|
||||
helpText={`Delete Series Folder${
|
||||
series.length > 1 ? 's' : ''
|
||||
} and all contents`}
|
||||
helpText={
|
||||
series.length > 1
|
||||
? translate('DeleteSeriesFoldersHelpText')
|
||||
: translate('DeleteSeriesFolderHelpText')
|
||||
}
|
||||
kind={kinds.DANGER}
|
||||
onChange={onDeleteFilesChange}
|
||||
/>
|
||||
@@ -121,9 +126,13 @@ function DeleteSeriesModalContent(props: DeleteSeriesModalContentProps) {
|
||||
</div>
|
||||
|
||||
<div className={styles.message}>
|
||||
{`Are you sure you want to delete ${series.length} selected series${
|
||||
deleteFiles ? ' and all contents' : ''
|
||||
}?`}
|
||||
{deleteFiles
|
||||
? translate('DeleteSeriesFolderCountWithFilesConfirmation', {
|
||||
count: series.length,
|
||||
})
|
||||
: translate('DeleteSeriesFolderCountConfirmation', {
|
||||
count: series.length,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
@@ -144,10 +153,10 @@ function DeleteSeriesModalContent(props: DeleteSeriesModalContentProps) {
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>Cancel</Button>
|
||||
<Button onPress={onModalClose}>{translate('Cancel')}</Button>
|
||||
|
||||
<Button kind={kinds.DANGER} onPress={onDeleteSeriesConfirmed}>
|
||||
Delete
|
||||
{translate('Delete')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -30,15 +30,47 @@ interface EditSeriesModalContentProps {
|
||||
const NO_CHANGE = 'noChange';
|
||||
|
||||
const monitoredOptions = [
|
||||
{ key: NO_CHANGE, value: 'No Change', disabled: true },
|
||||
{ key: 'monitored', value: 'Monitored' },
|
||||
{ key: 'unmonitored', value: 'Unmonitored' },
|
||||
{
|
||||
key: NO_CHANGE,
|
||||
get value() {
|
||||
return translate('NoChange');
|
||||
},
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
key: 'monitored',
|
||||
get value() {
|
||||
return translate('Monitored');
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'unmonitored',
|
||||
get value() {
|
||||
return translate('Unmonitored');
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const seasonFolderOptions = [
|
||||
{ key: NO_CHANGE, value: 'No Change', disabled: true },
|
||||
{ key: 'yes', value: 'Yes' },
|
||||
{ key: 'no', value: 'No' },
|
||||
{
|
||||
key: NO_CHANGE,
|
||||
get value() {
|
||||
return translate('NoChange');
|
||||
},
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
key: 'yes',
|
||||
get value() {
|
||||
return translate('Yes');
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'no',
|
||||
get value() {
|
||||
return translate('No');
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
@@ -152,7 +184,7 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>{translate('Edit Selected Series')}</ModalHeader>
|
||||
<ModalHeader>{translate('EditSelectedSeries')}</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<FormGroup>
|
||||
@@ -168,7 +200,7 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Quality Profile')}</FormLabel>
|
||||
<FormLabel>{translate('QualityProfile')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.QUALITY_PROFILE_SELECT}
|
||||
@@ -181,7 +213,7 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Series Type')}</FormLabel>
|
||||
<FormLabel>{translate('SeriesType')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SERIES_TYPE_SELECT}
|
||||
@@ -189,15 +221,13 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
value={seriesType}
|
||||
includeNoChange={true}
|
||||
includeNoChangeDisabled={false}
|
||||
helpText={translate(
|
||||
'Series type is used for renaming, parsing and searching'
|
||||
)}
|
||||
helpText={translate('SeriesTypesHelpText')}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Season Folder')}</FormLabel>
|
||||
<FormLabel>{translate('SeasonFolder')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
@@ -209,7 +239,7 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Root Folder')}</FormLabel>
|
||||
<FormLabel>{translate('RootFolder')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.ROOT_FOLDER_SELECT}
|
||||
@@ -218,9 +248,7 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
includeNoChange={true}
|
||||
includeNoChangeDisabled={false}
|
||||
selectedValueOptions={{ includeFreeSpace: false }}
|
||||
helpText={translate(
|
||||
'Moving series to the same root folder can be used to rename series folders to match updated title or naming format'
|
||||
)}
|
||||
helpText={translate('SeriesEditRootFolderHelpText')}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -228,7 +256,7 @@ function EditSeriesModalContent(props: EditSeriesModalContentProps) {
|
||||
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<div className={styles.selected}>
|
||||
{translate('{count} series selected', { count: selectedCount })}
|
||||
{translate('CountSeriesSelected', { count: selectedCount })}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { icons, kinds } from 'Helpers/Props';
|
||||
import Series from 'Series/Series';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './OrganizeSeriesModalContent.css';
|
||||
|
||||
interface OrganizeSeriesModalContentProps {
|
||||
@@ -55,18 +56,20 @@ function OrganizeSeriesModalContent(props: OrganizeSeriesModalContentProps) {
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>Organize Selected Series</ModalHeader>
|
||||
<ModalHeader>
|
||||
{translate('OrganizeSelectedSeriesModalHeader')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<Alert>
|
||||
Tip: To preview a rename, select "Cancel", then select any series
|
||||
title and use the
|
||||
{translate('OrganizeSelectedSeriesModalAlert')}
|
||||
<Icon className={styles.renameIcon} name={icons.ORGANIZE} />
|
||||
</Alert>
|
||||
|
||||
<div className={styles.message}>
|
||||
Are you sure you want to organize all files in the{' '}
|
||||
{seriesTitles.length} selected series?
|
||||
{translate('OrganizeSelectedSeriesModalConfirmation', {
|
||||
count: seriesTitles.length,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
@@ -77,10 +80,10 @@ function OrganizeSeriesModalContent(props: OrganizeSeriesModalContentProps) {
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>Cancel</Button>
|
||||
<Button onPress={onModalClose}>{translate('Cancel')}</Button>
|
||||
|
||||
<Button kind={kinds.DANGER} onPress={onOrganizePress}>
|
||||
Organize
|
||||
{translate('Organize')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -46,7 +46,7 @@ function ChangeMonitoringModalContent(
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>{translate('Monitor Series')}</ModalHeader>
|
||||
<ModalHeader>{translate('MonitorSeries')}</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<Form {...otherProps}>
|
||||
@@ -56,7 +56,7 @@ function ChangeMonitoringModalContent(
|
||||
|
||||
<Popover
|
||||
anchor={<Icon className={styles.labelIcon} name={icons.INFO} />}
|
||||
title={translate('Monitoring Options')}
|
||||
title={translate('MonitoringOptions')}
|
||||
body={<SeriesMonitoringOptionsPopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
@@ -75,7 +75,7 @@ function ChangeMonitoringModalContent(
|
||||
|
||||
<ModalFooter className={styles.modalFooter}>
|
||||
<div className={styles.selected}>
|
||||
{translate('{count} series selected', { count: selectedCount })}
|
||||
{translate('CountSeriesSelected', { count: selectedCount })}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Season } from 'Series/Series';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SeasonPassSeason from './SeasonPassSeason';
|
||||
import styles from './SeasonDetails.css';
|
||||
|
||||
@@ -39,7 +40,7 @@ function SeasonDetails(props: SeasonDetailsProps) {
|
||||
|
||||
{latestSeasons.length < seasons.length ? (
|
||||
<div className={styles.truncated}>
|
||||
Only latest 25 seasons are shown, go to details to see all seasons
|
||||
{translate('SeasonPassTruncated')}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,10 @@ import classNames from 'classnames';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import MonitorToggleButton from 'Components/MonitorToggleButton';
|
||||
import formatSeason from 'Season/formatSeason';
|
||||
import { Statistics } from 'Series/Series';
|
||||
import { toggleSeasonMonitored } from 'Store/Actions/seriesActions';
|
||||
import padNumber from 'Utilities/Number/padNumber';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './SeasonPassSeason.css';
|
||||
|
||||
interface SeasonPassSeasonProps {
|
||||
@@ -46,9 +47,7 @@ function SeasonPassSeason(props: SeasonPassSeasonProps) {
|
||||
onPress={onSeasonMonitoredPress}
|
||||
/>
|
||||
|
||||
<span>
|
||||
{seasonNumber === 0 ? 'Specials' : `S${padNumber(seasonNumber, 2)}`}
|
||||
</span>
|
||||
<span>{formatSeason(seasonNumber, true)}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -56,7 +55,10 @@ function SeasonPassSeason(props: SeasonPassSeasonProps) {
|
||||
styles.episodes,
|
||||
percentOfEpisodes === 100 && styles.allEpisodes
|
||||
)}
|
||||
title={`${episodeFileCount}/${totalEpisodeCount} episodes downloaded`}
|
||||
title={translate('SeasonPassEpisodesDownloaded', {
|
||||
episodeFileCount,
|
||||
totalEpisodeCount,
|
||||
})}
|
||||
>
|
||||
{totalEpisodeCount === 0
|
||||
? '0/0'
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
|
||||
import { useSelect } from 'App/SelectContext';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
interface SeriesIndexSelectAllButtonProps {
|
||||
label: string;
|
||||
@@ -30,7 +31,7 @@ function SeriesIndexSelectAllButton(props: SeriesIndexSelectAllButtonProps) {
|
||||
|
||||
return isSelectMode ? (
|
||||
<PageToolbarButton
|
||||
label={allSelected ? 'Unselect All' : 'Select All'}
|
||||
label={allSelected ? translate('UnselectAll') : translate('SelectAll')}
|
||||
iconName={icon}
|
||||
onPress={onPress}
|
||||
/>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
|
||||
import { useSelect } from 'App/SelectContext';
|
||||
import PageToolbarOverflowMenuItem from 'Components/Page/Toolbar/PageToolbarOverflowMenuItem';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
interface SeriesIndexSelectAllMenuItemProps {
|
||||
label: string;
|
||||
@@ -31,7 +32,7 @@ function SeriesIndexSelectAllMenuItem(
|
||||
|
||||
return isSelectMode ? (
|
||||
<PageToolbarOverflowMenuItem
|
||||
label={allSelected ? 'Unselect All' : 'Select All'}
|
||||
label={allSelected ? translate('UnselectAll') : translate('SelectAll')}
|
||||
iconName={iconName}
|
||||
onPress={onPressWrapper}
|
||||
/>
|
||||
|
||||
@@ -198,7 +198,7 @@ function SeriesIndexSelectFooter() {
|
||||
isDisabled={!anySelected || isOrganizingSeries}
|
||||
onPress={onOrganizePress}
|
||||
>
|
||||
{translate('Rename Files')}
|
||||
{translate('RenameFiles')}
|
||||
</SpinnerButton>
|
||||
|
||||
<SpinnerButton
|
||||
@@ -206,7 +206,7 @@ function SeriesIndexSelectFooter() {
|
||||
isDisabled={!anySelected || isOrganizingSeries}
|
||||
onPress={onTagsPress}
|
||||
>
|
||||
{translate('Set Tags')}
|
||||
{translate('SetTags')}
|
||||
</SpinnerButton>
|
||||
|
||||
<SpinnerButton
|
||||
@@ -214,7 +214,7 @@ function SeriesIndexSelectFooter() {
|
||||
isDisabled={!anySelected || isOrganizingSeries}
|
||||
onPress={onMonitoringPress}
|
||||
>
|
||||
{translate('Update Monitoring')}
|
||||
{translate('UpdateMonitoring')}
|
||||
</SpinnerButton>
|
||||
</div>
|
||||
|
||||
@@ -231,7 +231,7 @@ function SeriesIndexSelectFooter() {
|
||||
</div>
|
||||
|
||||
<div className={styles.selected}>
|
||||
{translate('{count} series selected', { count: selectedCount })}
|
||||
{translate('CountSeriesSelected', { count: selectedCount })}
|
||||
</div>
|
||||
|
||||
<EditSeriesModal
|
||||
|
||||
@@ -67,9 +67,18 @@ function TagsModalContent(props: TagsModalContentProps) {
|
||||
}, [tags, applyTags, onApplyTagsPress]);
|
||||
|
||||
const applyTagsOptions = [
|
||||
{ key: 'add', value: 'Add' },
|
||||
{ key: 'remove', value: 'Remove' },
|
||||
{ key: 'replace', value: 'Replace' },
|
||||
{
|
||||
key: 'add',
|
||||
value: translate('Add'),
|
||||
},
|
||||
{
|
||||
key: 'remove',
|
||||
value: translate('Remove'),
|
||||
},
|
||||
{
|
||||
key: 'replace',
|
||||
value: translate('Replace'),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user