mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-27 23:06:29 -04:00
Add Translations to Settings Pages
This commit is contained in:
committed by
Mark McDowall
parent
8008610d47
commit
f2c31e92ce
@@ -17,27 +17,87 @@ import NamingConnector from './Naming/NamingConnector';
|
||||
import AddRootFolder from './RootFolder/AddRootFolder';
|
||||
|
||||
const episodeTitleRequiredOptions = [
|
||||
{ key: 'always', value: 'Always' },
|
||||
{ key: 'bulkSeasonReleases', value: 'Only for Bulk Season Releases' },
|
||||
{ key: 'never', value: 'Never' }
|
||||
{
|
||||
key: 'always',
|
||||
get value() {
|
||||
return translate('Always');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'bulkSeasonReleases',
|
||||
get value() {
|
||||
return translate('OnlyForBulkSeasonReleases');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'never',
|
||||
get value() {
|
||||
return translate('Never');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const rescanAfterRefreshOptions = [
|
||||
{ key: 'always', value: 'Always' },
|
||||
{ key: 'afterManual', value: 'After Manual Refresh' },
|
||||
{ key: 'never', value: 'Never' }
|
||||
{
|
||||
key: 'always',
|
||||
get value() {
|
||||
return translate('Always');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'afterManual',
|
||||
get value() {
|
||||
return translate('AfterManualRefresh');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'never',
|
||||
get value() {
|
||||
return translate('Never');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const downloadPropersAndRepacksOptions = [
|
||||
{ key: 'preferAndUpgrade', value: 'Prefer and Upgrade' },
|
||||
{ key: 'doNotUpgrade', value: 'Do not Upgrade Automatically' },
|
||||
{ key: 'doNotPrefer', value: 'Do not Prefer' }
|
||||
{
|
||||
key: 'preferAndUpgrade',
|
||||
get value() {
|
||||
return translate('PreferAndUpgrade');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'doNotUpgrade',
|
||||
get value() {
|
||||
return translate('DoNotUpgradeAutomatically');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'doNotPrefer',
|
||||
get value() {
|
||||
return translate('DoNotPrefer');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const fileDateOptions = [
|
||||
{ key: 'none', value: 'None' },
|
||||
{ key: 'localAirDate', value: 'Local Air Date' },
|
||||
{ key: 'utcAirDate', value: 'UTC Air Date' }
|
||||
{
|
||||
key: 'none',
|
||||
get value() {
|
||||
return translate('None');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'localAirDate',
|
||||
get value() {
|
||||
return translate('LocalAirDate');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'utcAirDate',
|
||||
get value() {
|
||||
return translate('UtcAirDate');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
class MediaManagement extends Component {
|
||||
@@ -59,7 +119,7 @@ class MediaManagement extends Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<PageContent title="Media Management Settings">
|
||||
<PageContent title={translate('MediaManagementSettings')}>
|
||||
<SettingsToolbarConnector
|
||||
advancedSettings={advancedSettings}
|
||||
{...otherProps}
|
||||
@@ -71,15 +131,17 @@ class MediaManagement extends Component {
|
||||
|
||||
{
|
||||
isFetching ?
|
||||
<FieldSet legend="Naming Settings">
|
||||
<FieldSet legend={translate('NamingSettings')}>
|
||||
<LoadingIndicator />
|
||||
</FieldSet> : null
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && error ?
|
||||
<FieldSet legend="Naming Settings">
|
||||
<Alert kind={kinds.DANGER}>Unable to load Media Management settings</Alert>
|
||||
<FieldSet legend={translate('NamingSettings')}>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('MediaManagementSettingsLoadError')}
|
||||
</Alert>
|
||||
</FieldSet> : null
|
||||
}
|
||||
|
||||
@@ -91,18 +153,18 @@ class MediaManagement extends Component {
|
||||
>
|
||||
{
|
||||
advancedSettings ?
|
||||
<FieldSet legend="Folders">
|
||||
<FieldSet legend={translate('Folders')}>
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Create empty series folders</FormLabel>
|
||||
<FormLabel>{translate('CreateEmptySeriesFolders')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="createEmptySeriesFolders"
|
||||
helpText="Create missing series folders during disk scan"
|
||||
helpText={translate('CreateEmptySeriesFoldersHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.createEmptySeriesFolders}
|
||||
/>
|
||||
@@ -113,12 +175,12 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Delete empty folders</FormLabel>
|
||||
<FormLabel>{translate('DeleteEmptyFolders')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="deleteEmptyFolders"
|
||||
helpText="Delete empty series and season folders during disk scan and when episode files are deleted"
|
||||
helpText={translate('DeleteEmptyFoldersHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.deleteEmptyFolders}
|
||||
/>
|
||||
@@ -129,19 +191,19 @@ class MediaManagement extends Component {
|
||||
{
|
||||
advancedSettings ?
|
||||
<FieldSet
|
||||
legend="Importing"
|
||||
legend={translate('Importing')}
|
||||
>
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.SMALL}
|
||||
>
|
||||
<FormLabel>Episode Title Required</FormLabel>
|
||||
<FormLabel>{translate('EpisodeTitleRequired')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="episodeTitleRequired"
|
||||
helpText="Prevent importing for up to 48 hours if the episode title is in the naming format and the episode title is TBA"
|
||||
helpText={translate('EpisodeTitleRequiredHelpText')}
|
||||
values={episodeTitleRequiredOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.episodeTitleRequired}
|
||||
@@ -156,12 +218,12 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Skip Free Space Check</FormLabel>
|
||||
<FormLabel>{translate('SkipFreeSpaceCheck')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="skipFreeSpaceCheckWhenImporting"
|
||||
helpText="Use when Sonarr is unable to detect free space from your series root folder"
|
||||
helpText={translate('SkipFreeSpaceCheckWhenImportingHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.skipFreeSpaceCheckWhenImporting}
|
||||
/>
|
||||
@@ -173,13 +235,13 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Minimum Free Space</FormLabel>
|
||||
<FormLabel>{translate('MinimumFreeSpace')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
unit='MB'
|
||||
name="minimumFreeSpaceWhenImporting"
|
||||
helpText="Prevent import if it would leave less than this amount of disk space available"
|
||||
helpText={translate('MinimumFreeSpaceHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.minimumFreeSpaceWhenImporting}
|
||||
/>
|
||||
@@ -190,13 +252,13 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Use Hardlinks instead of Copy</FormLabel>
|
||||
<FormLabel>{translate('UseHardlinksInsteadOfCopy')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="copyUsingHardlinks"
|
||||
helpText="Hardlinks allow Sonarr to import seeding torrents to the the series folder without taking extra disk space or copying the entire contents of the file. Hardlinks will only work if the source and destination are on the same volume"
|
||||
helpTextWarning="Occasionally, file locks may prevent renaming files that are being seeded. You may temporarily disable seeding and use Sonarr's rename function as a work around."
|
||||
helpText={translate('CopyUsingHardlinksHelpText')}
|
||||
helpTextWarning={translate('CopyUsingHardlinksHelpTextWarning')}
|
||||
onChange={onInputChange}
|
||||
{...settings.copyUsingHardlinks}
|
||||
/>
|
||||
@@ -207,12 +269,12 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Import Using Script</FormLabel>
|
||||
<FormLabel>{translate('ImportUsingScript')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="useScriptImport"
|
||||
helpText="Copy files for importing using a script (ex. for transcoding)"
|
||||
helpText={translate('ImportUsingScriptHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.useScriptImport}
|
||||
/>
|
||||
@@ -224,13 +286,13 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Import Script Path</FormLabel>
|
||||
<FormLabel>{translate('ImportScriptPath')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PATH}
|
||||
includeFiles={true}
|
||||
name="scriptImportPath"
|
||||
helpText="The path to the script to use for importing"
|
||||
helpText={translate('ImportScriptPathHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.scriptImportPath}
|
||||
/>
|
||||
@@ -238,12 +300,12 @@ class MediaManagement extends Component {
|
||||
}
|
||||
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Import Extra Files</FormLabel>
|
||||
<FormLabel>{translate('ImportExtraFiles')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="importExtraFiles"
|
||||
helpText="Import matching extra files (subtitles, nfo, etc) after importing an episode file"
|
||||
helpText={translate('ImportExtraFilesHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.importExtraFiles}
|
||||
/>
|
||||
@@ -255,14 +317,14 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Import Extra Files</FormLabel>
|
||||
<FormLabel>{translate('ImportExtraFiles')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="extraFileExtensions"
|
||||
helpTexts={[
|
||||
'Comma separated list of extra files to import (.nfo will be imported as .nfo-orig)',
|
||||
'Examples: ".sub, .nfo" or "sub,nfo"'
|
||||
translate('ExtraFileExtensionsHelpText'),
|
||||
translate('ExtraFileExtensionsHelpTextsExamples')
|
||||
]}
|
||||
onChange={onInputChange}
|
||||
{...settings.extraFileExtensions}
|
||||
@@ -273,15 +335,15 @@ class MediaManagement extends Component {
|
||||
}
|
||||
|
||||
<FieldSet
|
||||
legend="File Management"
|
||||
legend={translate('FileManagement')}
|
||||
>
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Unmonitor Deleted Episodes</FormLabel>
|
||||
<FormLabel>{translate('UnmonitorDeletedEpisodes')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="autoUnmonitorPreviouslyDownloadedEpisodes"
|
||||
helpText="Episodes deleted from disk are automatically unmonitored in Sonarr"
|
||||
helpText={translate('UnmonitorDeletedEpisodesHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.autoUnmonitorPreviouslyDownloadedEpisodes}
|
||||
/>
|
||||
@@ -292,18 +354,18 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Propers and Repacks</FormLabel>
|
||||
<FormLabel>{translate('DownloadPropersAndRepacks')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="downloadPropersAndRepacks"
|
||||
helpTexts={[
|
||||
'Whether or not to automatically upgrade to Propers/Repacks',
|
||||
'Use \'Do not Prefer\' to sort by custom format score over propers/repacks'
|
||||
translate('DownloadPropersAndRepacksHelpText'),
|
||||
translate('DownloadPropersAndRepacksHelpTextCustomFormat')
|
||||
]}
|
||||
helpTextWarning={
|
||||
settings.downloadPropersAndRepacks.value === 'doNotPrefer' ?
|
||||
'Use custom formats for automatic upgrades to propers/repacks' :
|
||||
translate('DownloadPropersAndRepacksHelpTextWarning') :
|
||||
undefined
|
||||
}
|
||||
values={downloadPropersAndRepacksOptions}
|
||||
@@ -317,12 +379,12 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Analyse video files</FormLabel>
|
||||
<FormLabel>{translate('AnalyseVideoFiles')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="enableMediaInfo"
|
||||
helpText="Extract video information such as resolution, runtime and codec information from files. This requires Sonarr to read parts of the file which may cause high disk or network activity during scans."
|
||||
helpText={translate('AnalyseVideoFilesHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.enableMediaInfo}
|
||||
/>
|
||||
@@ -332,13 +394,13 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Rescan Series Folder after Refresh</FormLabel>
|
||||
<FormLabel>{translate('RescanSeriesFolderAfterRefresh')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="rescanAfterRefresh"
|
||||
helpText="Rescan the series folder after refreshing the series"
|
||||
helpTextWarning="Sonarr will not automatically detect changes to files when not set to 'Always'"
|
||||
helpText={translate('RescanAfterRefreshHelpText')}
|
||||
helpTextWarning={translate('RescanAfterRefreshHelpTextWarning')}
|
||||
values={rescanAfterRefreshOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.rescanAfterRefresh}
|
||||
@@ -349,12 +411,12 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Change File Date</FormLabel>
|
||||
<FormLabel>{translate('ChangeFileDate')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="fileDate"
|
||||
helpText="Change file date on import/rescan"
|
||||
helpText={translate('ChangeFileDateHelpText')}
|
||||
values={fileDateOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.fileDate}
|
||||
@@ -365,12 +427,12 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Recycling Bin</FormLabel>
|
||||
<FormLabel>{translate('RecyclingBin')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PATH}
|
||||
name="recycleBin"
|
||||
helpText="Episode files will go here when deleted instead of being permanently deleted"
|
||||
helpText={translate('RecyclingBinHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.recycleBin}
|
||||
/>
|
||||
@@ -380,13 +442,13 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Recycling Bin Cleanup</FormLabel>
|
||||
<FormLabel>{translate('RecyclingBinCleanup')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="recycleBinCleanupDays"
|
||||
helpText="Set to 0 to disable automatic cleanup"
|
||||
helpTextWarning="Files in the recycle bin older than the selected number of days will be cleaned up automatically"
|
||||
helpText={translate('RecyclingBinCleanupHelpText')}
|
||||
helpTextWarning={translate('RecyclingBinCleanupHelpTextWarning')}
|
||||
min={0}
|
||||
onChange={onInputChange}
|
||||
{...settings.recycleBinCleanupDays}
|
||||
@@ -397,20 +459,20 @@ class MediaManagement extends Component {
|
||||
{
|
||||
advancedSettings && !isWindows ?
|
||||
<FieldSet
|
||||
legend="Permissions"
|
||||
legend={translate('Permissions')}
|
||||
>
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Set Permissions</FormLabel>
|
||||
<FormLabel>{translate('SetPermissions')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="setPermissionsLinux"
|
||||
helpText="Should chmod be run when files are imported/renamed?"
|
||||
helpTextWarning="If you're unsure what these settings do, do not alter them."
|
||||
helpText={translate('SetPermissionsLinuxHelpText')}
|
||||
helpTextWarning={translate('SetPermissionsLinuxHelpTextWarning')}
|
||||
onChange={onInputChange}
|
||||
{...settings.setPermissionsLinux}
|
||||
/>
|
||||
@@ -420,13 +482,13 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>chmod Folder</FormLabel>
|
||||
<FormLabel>{translate('ChmodFolder')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.UMASK}
|
||||
name="chmodFolder"
|
||||
helpText="Octal, applied during import/rename to media folders and files (without execute bits)"
|
||||
helpTextWarning="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."
|
||||
helpText={translate('ChmodFolderHelpText')}
|
||||
helpTextWarning={translate('ChmodFolderHelpTextWarning')}
|
||||
onChange={onInputChange}
|
||||
{...settings.chmodFolder}
|
||||
/>
|
||||
@@ -436,13 +498,13 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>chown Group</FormLabel>
|
||||
<FormLabel>{translate('ChownGroup')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="chownGroup"
|
||||
helpText="Group name or gid. Use gid for remote file systems."
|
||||
helpTextWarning="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."
|
||||
helpText={translate('ChownGroupHelpText')}
|
||||
helpTextWarning={translate('ChownGroupHelpTextWarning')}
|
||||
values={fileDateOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.chownGroup}
|
||||
|
||||
@@ -9,6 +9,7 @@ import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import NamingModal from './NamingModal';
|
||||
import styles from './Naming.css';
|
||||
|
||||
@@ -124,20 +125,20 @@ class Naming extends Component {
|
||||
const replaceIllegalCharacters = hasSettings && settings.replaceIllegalCharacters.value;
|
||||
|
||||
const multiEpisodeStyleOptions = [
|
||||
{ key: 0, value: 'Extend', hint: 'S01E01-02-03' },
|
||||
{ key: 1, value: 'Duplicate', hint: 'S01E01.S01E02' },
|
||||
{ key: 2, value: 'Repeat', hint: 'S01E01E02E03' },
|
||||
{ key: 3, value: 'Scene', hint: 'S01E01-E02-E03' },
|
||||
{ key: 4, value: 'Range', hint: 'S01E01-03' },
|
||||
{ key: 5, value: 'Prefixed Range', hint: 'S01E01-E03' }
|
||||
{ key: 0, value: translate('Extend'), hint: 'S01E01-02-03' },
|
||||
{ key: 1, value: translate('Duplicate'), hint: 'S01E01.S01E02' },
|
||||
{ key: 2, value: translate('Repeat'), hint: 'S01E01E02E03' },
|
||||
{ key: 3, value: translate('Scene'), hint: 'S01E01-E02-E03' },
|
||||
{ key: 4, value: translate('Range'), hint: 'S01E01-03' },
|
||||
{ key: 5, value: translate('PrefixedRange'), hint: 'S01E01-E03' }
|
||||
];
|
||||
|
||||
const colonReplacementOptions = [
|
||||
{ key: 0, value: 'Delete' },
|
||||
{ key: 1, value: 'Replace with Dash' },
|
||||
{ key: 2, value: 'Replace with Space Dash' },
|
||||
{ key: 3, value: 'Replace with Space Dash Space' },
|
||||
{ key: 4, value: 'Smart Replace', hint: 'Dash or Space Dash depending on name' }
|
||||
{ key: 0, value: translate('Delete') },
|
||||
{ key: 1, value: translate('ReplaceWithDash') },
|
||||
{ key: 2, value: translate('ReplaceWithSpaceDash') },
|
||||
{ key: 3, value: translate('ReplaceWithSpaceDashSpace') },
|
||||
{ key: 4, value: translate('SmartReplace'), hint: translate('SmartReplaceHint') }
|
||||
];
|
||||
|
||||
const standardEpisodeFormatHelpTexts = [];
|
||||
@@ -155,56 +156,56 @@ class Naming extends Component {
|
||||
|
||||
if (examplesPopulated) {
|
||||
if (examples.singleEpisodeExample) {
|
||||
standardEpisodeFormatHelpTexts.push(`Single Episode: ${examples.singleEpisodeExample}`);
|
||||
standardEpisodeFormatHelpTexts.push(`${translate('SingleEpisode')}: ${examples.singleEpisodeExample}`);
|
||||
} else {
|
||||
standardEpisodeFormatErrors.push({ message: 'Single Episode: Invalid Format' });
|
||||
standardEpisodeFormatErrors.push({ message: translate('SingleEpisodeInvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.multiEpisodeExample) {
|
||||
standardEpisodeFormatHelpTexts.push(`Multi Episode: ${examples.multiEpisodeExample}`);
|
||||
standardEpisodeFormatHelpTexts.push(`${translate('MultiEpisode')}: ${examples.multiEpisodeExample}`);
|
||||
} else {
|
||||
standardEpisodeFormatErrors.push({ message: 'Multi Episode: Invalid Format' });
|
||||
standardEpisodeFormatErrors.push({ message: translate('MultiEpisodeInvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.dailyEpisodeExample) {
|
||||
dailyEpisodeFormatHelpTexts.push(`Example: ${examples.dailyEpisodeExample}`);
|
||||
dailyEpisodeFormatHelpTexts.push(`${translate('Example')}: ${examples.dailyEpisodeExample}`);
|
||||
} else {
|
||||
dailyEpisodeFormatErrors.push({ message: 'Invalid Format' });
|
||||
dailyEpisodeFormatErrors.push({ message: translate('InvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.animeEpisodeExample) {
|
||||
animeEpisodeFormatHelpTexts.push(`Single Episode: ${examples.animeEpisodeExample}`);
|
||||
animeEpisodeFormatHelpTexts.push(`${translate('SingleEpisode')}: ${examples.animeEpisodeExample}`);
|
||||
} else {
|
||||
animeEpisodeFormatErrors.push({ message: 'Single Episode: Invalid Format' });
|
||||
animeEpisodeFormatErrors.push({ message: translate('SingleEpisodeInvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.animeMultiEpisodeExample) {
|
||||
animeEpisodeFormatHelpTexts.push(`Multi Episode: ${examples.animeMultiEpisodeExample}`);
|
||||
animeEpisodeFormatHelpTexts.push(`${translate('MultiEpisode')}: ${examples.animeMultiEpisodeExample}`);
|
||||
} else {
|
||||
animeEpisodeFormatErrors.push({ message: 'Multi Episode: Invalid Format' });
|
||||
animeEpisodeFormatErrors.push({ message: translate('MultiEpisodeInvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.seriesFolderExample) {
|
||||
seriesFolderFormatHelpTexts.push(`Example: ${examples.seriesFolderExample}`);
|
||||
seriesFolderFormatHelpTexts.push(`${translate('Example')}: ${examples.seriesFolderExample}`);
|
||||
} else {
|
||||
seriesFolderFormatErrors.push({ message: 'Invalid Format' });
|
||||
seriesFolderFormatErrors.push({ message: translate('InvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.seasonFolderExample) {
|
||||
seasonFolderFormatHelpTexts.push(`Example: ${examples.seasonFolderExample}`);
|
||||
seasonFolderFormatHelpTexts.push(`${translate('Example')}: ${examples.seasonFolderExample}`);
|
||||
} else {
|
||||
seasonFolderFormatErrors.push({ message: 'Invalid Format' });
|
||||
seasonFolderFormatErrors.push({ message: translate('InvalidFormat') });
|
||||
}
|
||||
|
||||
if (examples.specialsFolderExample) {
|
||||
specialsFolderFormatHelpTexts.push(`Example: ${examples.specialsFolderExample}`);
|
||||
specialsFolderFormatHelpTexts.push(`${translate('Example')}: ${examples.specialsFolderExample}`);
|
||||
} else {
|
||||
specialsFolderFormatErrors.push({ message: 'Invalid Format' });
|
||||
specialsFolderFormatErrors.push({ message: translate('InvalidFormat') });
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<FieldSet legend="Episode Naming">
|
||||
<FieldSet legend={translate('EpisodeNaming')}>
|
||||
{
|
||||
isFetching &&
|
||||
<LoadingIndicator />
|
||||
@@ -212,31 +213,33 @@ class Naming extends Component {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<Alert kind={kinds.DANGER}>Unable to load Naming settings</Alert>
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('NamingSettingsLoadError')}
|
||||
</Alert>
|
||||
}
|
||||
|
||||
{
|
||||
hasSettings && !isFetching && !error &&
|
||||
<Form>
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Rename Episodes</FormLabel>
|
||||
<FormLabel>{translate('RenameEpisodes')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="renameEpisodes"
|
||||
helpText="Sonarr will use the existing file name if renaming is disabled"
|
||||
helpText={translate('RenameEpisodesHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.renameEpisodes}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Replace Illegal Characters</FormLabel>
|
||||
<FormLabel>{translate('ReplaceIllegalCharacters')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="replaceIllegalCharacters"
|
||||
helpText="Replace illegal characters. If unchecked, Sonarr will remove them instead"
|
||||
helpText={translate('ReplaceIllegalCharactersHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.replaceIllegalCharacters}
|
||||
/>
|
||||
@@ -245,12 +248,13 @@ class Naming extends Component {
|
||||
{
|
||||
replaceIllegalCharacters ?
|
||||
<FormGroup>
|
||||
<FormLabel>Colon Replacement</FormLabel>
|
||||
<FormLabel>{translate('ColonReplacement')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="colonReplacementFormat"
|
||||
values={colonReplacementOptions}
|
||||
helpText={translate('ColonReplacementFormatHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.colonReplacementFormat}
|
||||
/>
|
||||
@@ -262,7 +266,7 @@ class Naming extends Component {
|
||||
renameEpisodes &&
|
||||
<div>
|
||||
<FormGroup size={sizes.LARGE}>
|
||||
<FormLabel>Standard Episode Format</FormLabel>
|
||||
<FormLabel>{translate('StandardEpisodeFormat')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -277,7 +281,7 @@ class Naming extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup size={sizes.LARGE}>
|
||||
<FormLabel>Daily Episode Format</FormLabel>
|
||||
<FormLabel>{translate('DailyEpisodeFormat')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -292,7 +296,7 @@ class Naming extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup size={sizes.LARGE}>
|
||||
<FormLabel>Anime Episode Format</FormLabel>
|
||||
<FormLabel>{translate('DailyEpisodeFormat')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -312,7 +316,7 @@ class Naming extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Series Folder Format</FormLabel>
|
||||
<FormLabel>{translate('SeriesFolderFormat')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -321,13 +325,13 @@ class Naming extends Component {
|
||||
buttons={<FormInputButton onPress={this.onSeriesFolderNamingModalOpenClick}>?</FormInputButton>}
|
||||
onChange={onInputChange}
|
||||
{...settings.seriesFolderFormat}
|
||||
helpTexts={['Used when adding a new series or moving series via the series editor', ...seriesFolderFormatHelpTexts]}
|
||||
helpTexts={[translate('SeriesFolderFormatHelpText'), ...seriesFolderFormatHelpTexts]}
|
||||
errors={[...seriesFolderFormatErrors, ...settings.seriesFolderFormat.errors]}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Season Folder Format</FormLabel>
|
||||
<FormLabel>{translate('SeasonFolderFormat')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -345,7 +349,7 @@ class Naming extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Specials Folder Format</FormLabel>
|
||||
<FormLabel>{translate('SpecialsFolderFormat')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -360,7 +364,7 @@ class Naming extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Multi-Episode Style</FormLabel>
|
||||
<FormLabel>{translate('MultiEpisodeStyle')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
|
||||
@@ -11,20 +11,57 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { icons, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import InlineMarkdown from '../../../Components/Markdown/InlineMarkdown';
|
||||
import NamingOption from './NamingOption';
|
||||
import styles from './NamingModal.css';
|
||||
|
||||
const separatorOptions = [
|
||||
{ key: ' ', value: 'Space ( )' },
|
||||
{ key: '.', value: 'Period (.)' },
|
||||
{ key: '_', value: 'Underscore (_)' },
|
||||
{ key: '-', value: 'Dash (-)' }
|
||||
{
|
||||
key: ' ',
|
||||
get value() {
|
||||
return `${translate('Space')} ( )`;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '.',
|
||||
get value() {
|
||||
return `${translate('Period')} (.)`;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '_',
|
||||
get value() {
|
||||
return `${translate('Underscore')} (_)`;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '-',
|
||||
get value() {
|
||||
return `${translate('Dash')} (-)`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const caseOptions = [
|
||||
{ key: 'title', value: 'Default Case' },
|
||||
{ key: 'lower', value: 'Lowercase' },
|
||||
{ key: 'upper', value: 'Uppercase' }
|
||||
{
|
||||
key: 'title',
|
||||
get value() {
|
||||
return translate('DefaultCase');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'lower',
|
||||
get value() {
|
||||
return translate('Lowercase');
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'upper',
|
||||
get value() {
|
||||
return translate('Uppercase');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const fileNameTokens = [
|
||||
@@ -208,7 +245,7 @@ class NamingModal extends Component {
|
||||
>
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
File Name Tokens
|
||||
{translate('FileNameTokens')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
@@ -232,7 +269,7 @@ class NamingModal extends Component {
|
||||
|
||||
{
|
||||
!advancedSettings &&
|
||||
<FieldSet legend="File Names">
|
||||
<FieldSet legend={translate('FileNames')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
fileNameTokens.map(({ token, example }) => {
|
||||
@@ -257,7 +294,7 @@ class NamingModal extends Component {
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
<FieldSet legend="Series">
|
||||
<FieldSet legend={translate('Series')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
seriesTokens.map(({ token, example }) => {
|
||||
@@ -279,7 +316,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Series ID">
|
||||
<FieldSet legend={translate('SeriesID')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
seriesIdTokens.map(({ token, example }) => {
|
||||
@@ -303,7 +340,7 @@ class NamingModal extends Component {
|
||||
|
||||
{
|
||||
season &&
|
||||
<FieldSet legend="Season">
|
||||
<FieldSet legend={translate('Season')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
seasonTokens.map(({ token, example }) => {
|
||||
@@ -329,7 +366,7 @@ class NamingModal extends Component {
|
||||
{
|
||||
episode &&
|
||||
<div>
|
||||
<FieldSet legend="Episode">
|
||||
<FieldSet legend={translate('Episode')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
episodeTokens.map(({ token, example }) => {
|
||||
@@ -351,7 +388,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Air-Date">
|
||||
<FieldSet legend={translate('AirDate')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
airDateTokens.map(({ token, example }) => {
|
||||
@@ -375,7 +412,7 @@ class NamingModal extends Component {
|
||||
|
||||
{
|
||||
anime &&
|
||||
<FieldSet legend="Absolute Episode Number">
|
||||
<FieldSet legend={translate('AbsoluteEpisodeNumber')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
absoluteTokens.map(({ token, example }) => {
|
||||
@@ -403,7 +440,7 @@ class NamingModal extends Component {
|
||||
{
|
||||
additional &&
|
||||
<div>
|
||||
<FieldSet legend="Episode Title">
|
||||
<FieldSet legend={translate('EpisodeTitle')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
episodeTitleTokens.map(({ token, example }) => {
|
||||
@@ -425,7 +462,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Quality">
|
||||
<FieldSet legend={translate('Quality')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
qualityTokens.map(({ token, example }) => {
|
||||
@@ -447,7 +484,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Media Info">
|
||||
<FieldSet legend={translate('MediaInfo')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
mediaInfoTokens.map(({ token, example, footNote }) => {
|
||||
@@ -471,14 +508,11 @@ class NamingModal extends Component {
|
||||
|
||||
<div className={styles.footNote}>
|
||||
<Icon className={styles.icon} name={icons.FOOTNOTE} />
|
||||
<div>
|
||||
MediaInfo Full/AudioLanguages/SubtitleLanguages support a <code>:EN+DE</code> suffix allowing you to filter the languages included in the filename. Use <code>-DE</code> to exclude specific languages.
|
||||
Appending <code>+</code> (eg <code>:EN+</code>) will output <code>[EN]</code>/<code>[EN+--]</code>/<code>[--]</code> depending on excluded languages. For example <code>{'{'}MediaInfo Full:EN+DE{'}'}</code>.
|
||||
</div>
|
||||
<InlineMarkdown data={translate('MediaInfoFootNote')} />
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Other">
|
||||
<FieldSet legend={translate('Other')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
otherTokens.map(({ token, example }) => {
|
||||
@@ -500,7 +534,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Original">
|
||||
<FieldSet legend={translate('Original')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
originalTokens.map(({ token, example }) => {
|
||||
@@ -534,7 +568,7 @@ class NamingModal extends Component {
|
||||
onSelectionChange={this.onInputSelectionChange}
|
||||
/>
|
||||
<Button onPress={onModalClose}>
|
||||
Close
|
||||
{translate('Close')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
Reference in New Issue
Block a user