mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-26 22:46:37 -04:00
Localization framework
This commit is contained in:
@@ -11,6 +11,7 @@ import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import { inputTypes, sizes } from 'Helpers/Props';
|
||||
import RemotePathMappingsConnector from 'Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector';
|
||||
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import NamingConnector from './Naming/NamingConnector';
|
||||
import RootFoldersConnector from './RootFolder/RootFoldersConnector';
|
||||
|
||||
@@ -56,7 +57,7 @@ class MediaManagement extends Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<PageContent title="Media Management Settings">
|
||||
<PageContent title={translate('MediaManagementSettings')}>
|
||||
<SettingsToolbarConnector
|
||||
advancedSettings={advancedSettings}
|
||||
{...otherProps}
|
||||
@@ -70,15 +71,17 @@ class MediaManagement extends Component {
|
||||
|
||||
{
|
||||
isFetching &&
|
||||
<FieldSet legend="Naming Settings">
|
||||
<FieldSet legend={translate('NamingSettings')}>
|
||||
<LoadingIndicator />
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<FieldSet legend="Naming Settings">
|
||||
<div>Unable to load Media Management settings</div>
|
||||
<FieldSet legend={translate('NamingSettings')}>
|
||||
<div>
|
||||
{translate('UnableToLoadMediaManagementSettings')}
|
||||
</div>
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
@@ -90,18 +93,20 @@ class MediaManagement extends Component {
|
||||
>
|
||||
{
|
||||
advancedSettings &&
|
||||
<FieldSet legend="Folders">
|
||||
<FieldSet legend={translate('Folders')}>
|
||||
<FormGroup
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Create empty author folders</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CreateEmptyAuthorFolders')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="createEmptyAuthorFolders"
|
||||
helpText="Create missing author folders during disk scan"
|
||||
helpText={translate('CreateEmptyAuthorFoldersHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.createEmptyAuthorFolders}
|
||||
/>
|
||||
@@ -112,12 +117,14 @@ 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 author folders during disk scan and when book files are deleted"
|
||||
helpText={translate('DeleteEmptyFoldersHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.deleteEmptyFolders}
|
||||
/>
|
||||
@@ -128,7 +135,7 @@ class MediaManagement extends Component {
|
||||
{
|
||||
advancedSettings &&
|
||||
<FieldSet
|
||||
legend="Importing"
|
||||
legend={translate('Importing')}
|
||||
>
|
||||
{
|
||||
!isWindows &&
|
||||
@@ -137,12 +144,14 @@ 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 Readarr is unable to detect free space from your author root folder"
|
||||
helpText={translate('SkipFreeSpaceCheckWhenImportingHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.skipFreeSpaceCheckWhenImporting}
|
||||
/>
|
||||
@@ -154,13 +163,15 @@ 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('MinimumFreeSpaceWhenImportingHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.minimumFreeSpaceWhenImporting}
|
||||
/>
|
||||
@@ -171,25 +182,29 @@ 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="Use Hardlinks when trying to copy files from torrents that are still being seeded"
|
||||
helpTextWarning="Occasionally, file locks may prevent renaming files that are being seeded. You may temporarily disable seeding and use Readarr's rename function as a work around."
|
||||
helpText={translate('CopyUsingHardlinksHelpText')}
|
||||
helpTextWarning={translate('CopyUsingHardlinksHelpTextWarning')}
|
||||
onChange={onInputChange}
|
||||
{...settings.copyUsingHardlinks}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<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 book file"
|
||||
helpText={translate('ImportExtraFilesHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.importExtraFiles}
|
||||
/>
|
||||
@@ -201,14 +216,16 @@ 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('ExtraFileExtensionsHelpTexts1'),
|
||||
translate('ExtraFileExtensionsHelpTexts2')
|
||||
]}
|
||||
onChange={onInputChange}
|
||||
{...settings.extraFileExtensions}
|
||||
@@ -219,15 +236,17 @@ class MediaManagement extends Component {
|
||||
}
|
||||
|
||||
<FieldSet
|
||||
legend="File Management"
|
||||
legend={translate('FileManagement')}
|
||||
>
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Ignore Deleted Books</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('IgnoreDeletedBooks')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="autoUnmonitorPreviouslyDownloadedBooks"
|
||||
helpText="Books deleted from disk are automatically unmonitored in Readarr"
|
||||
helpText={translate('AutoUnmonitorPreviouslyDownloadedBooksHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.autoUnmonitorPreviouslyDownloadedBooks}
|
||||
/>
|
||||
@@ -238,14 +257,16 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Propers and Repacks</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('PropersAndRepacks')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="downloadPropersAndRepacks"
|
||||
helpTexts={[
|
||||
'Whether or not to automatically upgrade to Propers/Repacks',
|
||||
'Use \'Do not Prefer\' to sort by preferred word score over propers/repacks'
|
||||
translate('DownloadPropersAndRepacksHelpTexts1'),
|
||||
translate('DownloadPropersAndRepacksHelpTexts2')
|
||||
]}
|
||||
helpTextWarning={
|
||||
settings.downloadPropersAndRepacks.value === 'doNotPrefer' ?
|
||||
@@ -263,12 +284,14 @@ class MediaManagement extends Component {
|
||||
isAdvanced={true}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
<FormLabel>Watch Root Folders for file changes</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('WatchRootFoldersForFileChanges')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="watchLibraryForChanges"
|
||||
helpText="Rescan automatically when files change in a root folder"
|
||||
helpText={translate('WatchLibraryForChangesHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.watchLibraryForChanges}
|
||||
/>
|
||||
@@ -278,13 +301,15 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Rescan Author Folder after Refresh</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('RescanAuthorFolderAfterRefresh')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="rescanAfterRefresh"
|
||||
helpText="Rescan the author folder after refreshing the author"
|
||||
helpTextWarning="Readarr will not automatically detect changes to files when not set to 'Always'"
|
||||
helpText={translate('RescanAfterRefreshHelpText')}
|
||||
helpTextWarning={translate('RescanAfterRefreshHelpTextWarning')}
|
||||
values={rescanAfterRefreshOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.rescanAfterRefresh}
|
||||
@@ -295,13 +320,15 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Allow Fingerprinting</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('AllowFingerprinting')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="allowFingerprinting"
|
||||
helpText="Use fingerprinting to improve accuracy of book matching"
|
||||
helpTextWarning="This requires Readarr to read parts of the file which will slow down scans and may cause high disk or network activity."
|
||||
helpText={translate('AllowFingerprintingHelpText')}
|
||||
helpTextWarning={translate('AllowFingerprintingHelpTextWarning')}
|
||||
values={allowFingerprintingOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.allowFingerprinting}
|
||||
@@ -312,12 +339,14 @@ 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('FileDateHelpText')}
|
||||
values={fileDateOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.fileDate}
|
||||
@@ -328,12 +357,14 @@ class MediaManagement extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Recycling Bin</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('RecyclingBin')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PATH}
|
||||
name="recycleBin"
|
||||
helpText="Book files will go here when deleted instead of being permanently deleted"
|
||||
helpText={translate('RecycleBinHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.recycleBin}
|
||||
/>
|
||||
@@ -343,13 +374,15 @@ 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('RecycleBinCleanupDaysHelpText')}
|
||||
helpTextWarning={translate('RecycleBinCleanupDaysHelpTextWarning')}
|
||||
min={0}
|
||||
onChange={onInputChange}
|
||||
{...settings.recycleBinCleanupDays}
|
||||
@@ -360,20 +393,22 @@ 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}
|
||||
/>
|
||||
@@ -383,13 +418,15 @@ 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 Readarr 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}
|
||||
/>
|
||||
@@ -399,13 +436,15 @@ 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 Readarr is the owner of the file. It's better to ensure the download client uses the same group as Readarr."
|
||||
helpText={translate('ChownGroupHelpText')}
|
||||
helpTextWarning={translate('ChownGroupHelpTextWarning')}
|
||||
values={fileDateOptions}
|
||||
onChange={onInputChange}
|
||||
{...settings.chownGroup}
|
||||
|
||||
@@ -8,6 +8,7 @@ import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import { inputTypes, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import NamingModal from './NamingModal';
|
||||
import styles from './Naming.css';
|
||||
|
||||
@@ -94,7 +95,7 @@ class Naming extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<FieldSet legend="Book Naming">
|
||||
<FieldSet legend={translate('BookNaming')}>
|
||||
{
|
||||
isFetching &&
|
||||
<LoadingIndicator />
|
||||
@@ -102,31 +103,37 @@ class Naming extends Component {
|
||||
|
||||
{
|
||||
!isFetching && error &&
|
||||
<div>Unable to load Naming settings</div>
|
||||
<div>
|
||||
{translate('UnableToLoadNamingSettings')}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
hasSettings && !isFetching && !error &&
|
||||
<Form>
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Rename Books</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('RenameBooks')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="renameBooks"
|
||||
helpText="Readarr will use the existing file name if renaming is disabled"
|
||||
helpText={translate('RenameBooksHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.renameBooks}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup size={sizes.MEDIUM}>
|
||||
<FormLabel>Replace Illegal Characters</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('ReplaceIllegalCharacters')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="replaceIllegalCharacters"
|
||||
helpText="Replace or Remove illegal characters"
|
||||
helpText={translate('ReplaceIllegalCharactersHelpText')}
|
||||
onChange={onInputChange}
|
||||
{...settings.replaceIllegalCharacters}
|
||||
/>
|
||||
@@ -136,7 +143,9 @@ class Naming extends Component {
|
||||
renameBooks &&
|
||||
<div>
|
||||
<FormGroup size={sizes.LARGE}>
|
||||
<FormLabel>Standard Book Format</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('StandardBookFormat')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
@@ -156,7 +165,9 @@ class Naming extends Component {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Author Folder Format</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('AuthorFolderFormat')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
inputClassName={styles.namingInput}
|
||||
|
||||
@@ -10,6 +10,7 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import NamingOption from './NamingOption';
|
||||
import styles from './NamingModal.css';
|
||||
|
||||
@@ -207,7 +208,7 @@ class NamingModal extends Component {
|
||||
|
||||
{
|
||||
!advancedSettings &&
|
||||
<FieldSet legend="File Names">
|
||||
<FieldSet legend={translate('FileNames')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
fileNameTokens.map(({ token, example }) => {
|
||||
@@ -232,7 +233,7 @@ class NamingModal extends Component {
|
||||
</FieldSet>
|
||||
}
|
||||
|
||||
<FieldSet legend="Author">
|
||||
<FieldSet legend={translate('Author')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
authorTokens.map(({ token, example }) => {
|
||||
@@ -257,7 +258,7 @@ class NamingModal extends Component {
|
||||
{
|
||||
book &&
|
||||
<div>
|
||||
<FieldSet legend="Book">
|
||||
<FieldSet legend={translate('Book')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
bookTokens.map(({ token, example }) => {
|
||||
@@ -279,7 +280,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Release Date">
|
||||
<FieldSet legend={translate('ReleaseDate')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
releaseDateTokens.map(({ token, example }) => {
|
||||
@@ -306,7 +307,7 @@ class NamingModal extends Component {
|
||||
{
|
||||
book &&
|
||||
<div>
|
||||
<FieldSet legend="Medium">
|
||||
<FieldSet legend={translate('Medium')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
mediumTokens.map(({ token, example }) => {
|
||||
@@ -328,7 +329,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Medium Format">
|
||||
<FieldSet legend={translate('MediumFormat')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
mediumFormatTokens.map(({ token, example }) => {
|
||||
@@ -356,7 +357,7 @@ class NamingModal extends Component {
|
||||
{
|
||||
additional &&
|
||||
<div>
|
||||
<FieldSet legend="Quality">
|
||||
<FieldSet legend={translate('Quality')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
qualityTokens.map(({ token, example }) => {
|
||||
@@ -378,7 +379,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Media Info">
|
||||
<FieldSet legend={translate('MediaInfo')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
mediaInfoTokens.map(({ token, example }) => {
|
||||
@@ -400,7 +401,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Other">
|
||||
<FieldSet legend={translate('Other')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
otherTokens.map(({ token, example }) => {
|
||||
@@ -422,7 +423,7 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend="Original">
|
||||
<FieldSet legend={translate('Original')}>
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
originalTokens.map(({ token, example }) => {
|
||||
|
||||
@@ -16,6 +16,7 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { calibreProfiles, icons, inputTypes, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './EditRootFolderModalContent.css';
|
||||
|
||||
function EditRootFolderModalContent(props) {
|
||||
@@ -71,14 +72,18 @@ function EditRootFolderModalContent(props) {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>Unable to add a new root folder, please try again.</div>
|
||||
<div>
|
||||
{translate('UnableToAddANewRootFolderPleaseTryAgain')}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && !error &&
|
||||
<Form {...otherProps}>
|
||||
<FormGroup>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('Name')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
@@ -89,14 +94,16 @@ function EditRootFolderModalContent(props) {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Path</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('Path')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={id ? inputTypes.TEXT : inputTypes.PATH}
|
||||
readOnly={!!id}
|
||||
name="path"
|
||||
helpText="Root Folder containing your book library"
|
||||
helpTextWarning="This must be different to the directory where your download client puts files"
|
||||
helpText={translate('PathHelpText')}
|
||||
helpTextWarning={translate('PathHelpTextWarning')}
|
||||
{...path}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -112,7 +119,7 @@ function EditRootFolderModalContent(props) {
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Calibre content server"
|
||||
title={translate('CalibreContentServer')}
|
||||
body={'Using a Calibre content server allows Readarr to add books to your Calibre library and trigger conversions between formats'}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
@@ -121,7 +128,7 @@ function EditRootFolderModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="isCalibreLibrary"
|
||||
helpText="Use Calibre content server to manipulate library"
|
||||
helpText={translate('IsCalibreLibraryHelpText')}
|
||||
{...isCalibreLibrary}
|
||||
onChange={onInputChange}
|
||||
helpLink={'https://manual.calibre-ebook.com/server.html'}
|
||||
@@ -132,24 +139,28 @@ function EditRootFolderModalContent(props) {
|
||||
isCalibreLibrary !== undefined && isCalibreLibrary.value &&
|
||||
<div>
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Host</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CalibreHost')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="host"
|
||||
helpText="Calibre content server host"
|
||||
helpText={translate('HostHelpText')}
|
||||
{...host}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Port</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CalibrePort')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="port"
|
||||
helpText="Calibre content server port"
|
||||
helpText={translate('PortHelpText')}
|
||||
{...port}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -159,48 +170,56 @@ function EditRootFolderModalContent(props) {
|
||||
advancedSettings={advancedSettings}
|
||||
isAdvanced={true}
|
||||
>
|
||||
<FormLabel>Calibre Url Base</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CalibreUrlBase')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="urlBase"
|
||||
helpText="Adds a prefix to the Calibre url, e.g. http://[host]:[port]/[urlBase]"
|
||||
helpText={translate('UrlBaseHelpText')}
|
||||
{...urlBase}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Username</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CalibreUsername')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="username"
|
||||
helpText="Calibre content server username"
|
||||
helpText={translate('UsernameHelpText')}
|
||||
{...username}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Password</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CalibrePassword')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.PASSWORD}
|
||||
name="password"
|
||||
helpText="Calibre content server password"
|
||||
helpText={translate('PasswordHelpText')}
|
||||
{...password}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Calibre Library</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('CalibreLibrary')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="library"
|
||||
helpText="Calibre content server library name. Leave blank for default."
|
||||
helpText={translate('LibraryHelpText')}
|
||||
{...library}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -216,7 +235,7 @@ function EditRootFolderModalContent(props) {
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Calibre output format"
|
||||
title={translate('CalibreOutputFormat')}
|
||||
body={'Specify the output format. Options are: MOBI, EPUB, AZW3, DOCX, FB2, HTMLZ, LIT, LRF, PDB, PDF, PMLZ, RB, RTF, SNB, TCR, TXT, TXTZ, ZIP'}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
@@ -225,7 +244,7 @@ function EditRootFolderModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="outputFormat"
|
||||
helpText="Optionally ask Calibre to convert to other formats on import. Comma separated list."
|
||||
helpText={translate('OutputFormatHelpText')}
|
||||
{...outputFormat}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -241,7 +260,7 @@ function EditRootFolderModalContent(props) {
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Calibre output profile"
|
||||
title={translate('CalibreOutputProfile')}
|
||||
body={'Specify the output profile. The output profile tells the Calibre conversion system how to optimize the created document for the specified device (such as by resizing images for the device screen size). In some cases, an output profile can be used to optimize the output for a particular device, but this is rarely necessary.'}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
@@ -258,12 +277,14 @@ function EditRootFolderModalContent(props) {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Use SSL</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('UseSSL')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="useSsl"
|
||||
helpText="Use SSL to connect to Calibre content server"
|
||||
helpText={translate('UseSslHelpText')}
|
||||
{...useSsl}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -282,7 +303,7 @@ function EditRootFolderModalContent(props) {
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Monitoring Options"
|
||||
title={translate('MonitoringOptions')}
|
||||
body={<AuthorMonitoringOptionsPopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
@@ -293,18 +314,20 @@ function EditRootFolderModalContent(props) {
|
||||
name="defaultMonitorOption"
|
||||
onChange={onInputChange}
|
||||
{...defaultMonitorOption}
|
||||
helpText="Default Monitoring Options for books by authors detected in this folder"
|
||||
helpText={translate('DefaultMonitorOptionHelpText')}
|
||||
/>
|
||||
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Quality Profile</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('QualityProfile')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.QUALITY_PROFILE_SELECT}
|
||||
name="defaultQualityProfileId"
|
||||
helpText="Default Quality Profile for authors detected in this folder"
|
||||
helpText={translate('DefaultQualityProfileIdHelpText')}
|
||||
{...defaultQualityProfileId}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
@@ -320,7 +343,7 @@ function EditRootFolderModalContent(props) {
|
||||
name={icons.INFO}
|
||||
/>
|
||||
}
|
||||
title="Metadata Profile"
|
||||
title={translate('MetadataProfile')}
|
||||
body={<AuthorMetadataProfilePopoverContent />}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
@@ -329,7 +352,7 @@ function EditRootFolderModalContent(props) {
|
||||
<FormInputGroup
|
||||
type={inputTypes.METADATA_PROFILE_SELECT}
|
||||
name="defaultMetadataProfileId"
|
||||
helpText="Default Metadata Profile for authors detected in this folder"
|
||||
helpText={translate('DefaultMetadataProfileIdHelpText')}
|
||||
{...defaultMetadataProfileId}
|
||||
includeNone={true}
|
||||
onChange={onInputChange}
|
||||
@@ -337,12 +360,14 @@ function EditRootFolderModalContent(props) {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>Default Readarr Tags</FormLabel>
|
||||
<FormLabel>
|
||||
{translate('DefaultReadarrTags')}
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="defaultTags"
|
||||
helpText="Default Readarr Tags for authors detected in this folder"
|
||||
helpText={translate('DefaultTagsHelpText')}
|
||||
{...defaultTags}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,7 @@ import Card from 'Components/Card';
|
||||
import Label from 'Components/Label';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditRootFolderModalConnector from './EditRootFolderModalConnector';
|
||||
import styles from './RootFolder.css';
|
||||
|
||||
@@ -93,9 +94,9 @@ class RootFolder extends Component {
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isDeleteRootFolderModalOpen}
|
||||
kind={kinds.DANGER}
|
||||
title="Delete Root Folder"
|
||||
message={`Are you sure you want to delete the root folder '${name}'?`}
|
||||
confirmLabel="Delete"
|
||||
title={translate('DeleteRootFolder')}
|
||||
message={translate('DeleteRootFolderMessageText', [name])}
|
||||
confirmLabel={translate('Delete')}
|
||||
onConfirm={this.onConfirmDeleteRootFolder}
|
||||
onCancel={this.onDeleteRootFolderModalClose}
|
||||
/>
|
||||
|
||||
@@ -6,6 +6,7 @@ import Icon from 'Components/Icon';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import sortByName from 'Utilities/Array/sortByName';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditRootFolderModalConnector from './EditRootFolderModalConnector';
|
||||
import RootFolder from './RootFolder';
|
||||
import styles from './RootFolders.css';
|
||||
@@ -47,9 +48,9 @@ class RootFolders extends Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldSet legend="Root Folders">
|
||||
<FieldSet legend={translate('RootFolders')}>
|
||||
<PageSectionContent
|
||||
errorMessage="Unable to load root folders"
|
||||
errorMessage={translate('UnableToLoadRootFolders')}
|
||||
{...otherProps}
|
||||
>
|
||||
<div className={styles.rootFolders}>
|
||||
|
||||
Reference in New Issue
Block a user