1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-26 22:56:23 -04:00

New: Add translations for managing bulk indexers, lists and clients

This commit is contained in:
Bogdan
2023-07-11 10:17:38 +03:00
committed by Mark McDowall
parent 45336389e6
commit e641c57ad9
19 changed files with 258 additions and 149 deletions
@@ -6,6 +6,7 @@ import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import { icons } from 'Helpers/Props';
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
import translate from 'Utilities/String/translate';
import IndexersConnector from './Indexers/IndexersConnector';
import ManageIndexersModal from './Indexers/Manage/ManageIndexersModal';
import IndexerOptionsConnector from './Options/IndexerOptionsConnector';
@@ -84,7 +85,7 @@ class IndexerSettings extends Component {
/>
<PageToolbarButton
label="Manage Indexers"
label={translate('ManageIndexers')}
iconName={icons.MANAGE}
onPress={this.onManageIndexersPress}
/>
@@ -27,9 +27,9 @@ interface ManageIndexersEditModalContentProps {
const NO_CHANGE = 'noChange';
const enableOptions = [
{ key: NO_CHANGE, value: 'No Change', disabled: true },
{ key: 'enabled', value: 'Enabled' },
{ key: 'disabled', value: 'Disabled' },
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
{ key: 'enabled', value: translate('Enabled') },
{ key: 'disabled', value: translate('Disabled') },
];
function ManageIndexersEditModalContent(
@@ -97,7 +97,7 @@ function ManageIndexersEditModalContent(
setPriority(value);
break;
default:
console.warn('EditIndexersModalContent Unknown Input');
console.warn(`EditIndexersModalContent Unknown Input: '${name}'`);
}
},
[]
@@ -111,7 +111,7 @@ function ManageIndexersEditModalContent(
<ModalBody>
<FormGroup>
<FormLabel>{translate('EnableRss')}</FormLabel>
<FormLabel>{translate('EnableRSS')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
@@ -162,13 +162,15 @@ function ManageIndexersEditModalContent(
<ModalFooter className={styles.modalFooter}>
<div className={styles.selected}>
{translate('{count} indexers selected', { count: selectedCount })}
{translate('CountIndexersSelected', {
count: selectedCount,
})}
</div>
<div>
<Button onPress={onModalClose}>{translate('Cancel')}</Button>
<Button onPress={save}>{translate('Apply Changes')}</Button>
<Button onPress={save}>{translate('ApplyChanges')}</Button>
</div>
</ModalFooter>
</ModalContent>
@@ -1,6 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { IndexerAppState } from 'App/State/SettingsAppState';
import Alert from 'Components/Alert';
import Button from 'Components/Link/Button';
import SpinnerButton from 'Components/Link/SpinnerButton';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
@@ -20,6 +21,7 @@ import {
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import { SelectStateInputProps } from 'typings/props';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import translate from 'Utilities/String/translate';
import getSelectedIds from 'Utilities/Table/getSelectedIds';
import ManageIndexersEditModal from './Edit/ManageIndexersEditModal';
import ManageIndexersModalRow from './ManageIndexersModalRow';
@@ -34,43 +36,43 @@ type OnSelectedChangeCallback = React.ComponentProps<
const COLUMNS = [
{
name: 'name',
label: 'Name',
label: translate('Name'),
isSortable: true,
isVisible: true,
},
{
name: 'implementation',
label: 'Implementation',
label: translate('Implementation'),
isSortable: true,
isVisible: true,
},
{
name: 'enableRss',
label: 'Enable RSS',
label: translate('EnableRSS'),
isSortable: true,
isVisible: true,
},
{
name: 'enableAutomaticSearch',
label: 'Enable Automatic Search',
label: translate('EnableAutomaticSearch'),
isSortable: true,
isVisible: true,
},
{
name: 'enableInteractiveSearch',
label: 'Enable Interactive Search',
label: translate('EnableInteractiveSearch'),
isSortable: true,
isVisible: true,
},
{
name: 'priority',
label: 'Priority',
label: translate('Priority'),
isSortable: true,
isVisible: true,
},
{
name: 'tags',
label: 'Tags',
label: translate('Tags'),
isSortable: true,
isVisible: true,
},
@@ -189,17 +191,21 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
[items, setSelectState]
);
const errorMessage = getErrorMessage(error, 'Unable to load import lists.');
const errorMessage = getErrorMessage(error, 'Unable to load indexers.');
const anySelected = selectedCount > 0;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>Manage Import Lists</ModalHeader>
<ModalHeader>{translate('ManageIndexers')}</ModalHeader>
<ModalBody>
{isFetching ? <LoadingIndicator /> : null}
{error ? <div>{errorMessage}</div> : null}
{isPopulated && !error && !items.length && (
<Alert kind={kinds.INFO}>{translate('NoIndexersFound')}</Alert>
)}
{isPopulated && !!items.length && !isFetching && !isFetching ? (
<Table
columns={COLUMNS}
@@ -234,7 +240,7 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
isDisabled={!anySelected}
onPress={onDeletePress}
>
Delete
{translate('Delete')}
</SpinnerButton>
<SpinnerButton
@@ -242,7 +248,7 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
isDisabled={!anySelected}
onPress={onEditPress}
>
Edit
{translate('Edit')}
</SpinnerButton>
<SpinnerButton
@@ -250,11 +256,11 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
isDisabled={!anySelected}
onPress={onTagsPress}
>
Set Tags
{translate('SetTags')}
</SpinnerButton>
</div>
<Button onPress={onModalClose}>Close</Button>
<Button onPress={onModalClose}>{translate('Close')}</Button>
</ModalFooter>
<ManageIndexersEditModal
@@ -274,9 +280,11 @@ function ManageIndexersModalContent(props: ManageIndexersModalContentProps) {
<ConfirmModal
isOpen={isDeleteModalOpen}
kind={kinds.DANGER}
title="Delete Import List(s)"
message={`Are you sure you want to delete ${selectedIds.length} import list(s)?`}
confirmLabel="Delete"
title={translate('DeleteSelectedIndexers')}
message={translate('DeleteSelectedIndexersMessageText', {
count: selectedIds.length,
})}
confirmLabel={translate('Delete')}
onConfirm={onConfirmDelete}
onCancel={onDeleteModalClose}
/>
@@ -1,10 +1,13 @@
import React, { useCallback } from 'react';
import Label from 'Components/Label';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
import Column from 'Components/Table/Column';
import TableRow from 'Components/Table/TableRow';
import TagListConnector from 'Components/TagListConnector';
import { kinds } from 'Helpers/Props';
import { SelectStateInputProps } from 'typings/props';
import translate from 'Utilities/String/translate';
import styles from './ManageIndexersModalRow.css';
interface ManageIndexersModalRowProps {
@@ -59,15 +62,30 @@ function ManageIndexersModalRow(props: ManageIndexersModalRowProps) {
</TableRowCell>
<TableRowCell className={styles.enableRss}>
{enableRss ? 'Yes' : 'No'}
<Label
kind={enableRss ? kinds.SUCCESS : kinds.DISABLED}
outline={!enableRss}
>
{enableRss ? translate('Yes') : translate('No')}
</Label>
</TableRowCell>
<TableRowCell className={styles.enableAutomaticSearch}>
{enableAutomaticSearch ? 'Yes' : 'No'}
<Label
kind={enableAutomaticSearch ? kinds.SUCCESS : kinds.DISABLED}
outline={!enableAutomaticSearch}
>
{enableAutomaticSearch ? translate('Yes') : translate('No')}
</Label>
</TableRowCell>
<TableRowCell className={styles.enableInteractiveSearch}>
{enableInteractiveSearch ? 'Yes' : 'No'}
<Label
kind={enableInteractiveSearch ? kinds.SUCCESS : kinds.DISABLED}
outline={!enableInteractiveSearch}
>
{enableInteractiveSearch ? translate('Yes') : translate('No')}
</Label>
</TableRowCell>
<TableRowCell className={styles.priority}>{priority}</TableRowCell>
@@ -17,6 +17,7 @@ import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
import createTagsSelector from 'Store/Selectors/createTagsSelector';
import Indexer from 'typings/Indexer';
import translate from 'Utilities/String/translate';
import styles from './TagsModalContent.css';
interface TagsModalContentProps {
@@ -36,7 +37,7 @@ function TagsModalContent(props: TagsModalContentProps) {
const [tags, setTags] = useState<number[]>([]);
const [applyTags, setApplyTags] = useState('add');
const seriesTags = useMemo(() => {
const indexersTags = useMemo(() => {
const tags = ids.reduce((acc: number[], id) => {
const s = allIndexers.items.find((s: Indexer) => s.id === id);
@@ -69,19 +70,19 @@ 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 (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>Tags</ModalHeader>
<ModalHeader>{translate('Tags')}</ModalHeader>
<ModalBody>
<Form>
<FormGroup>
<FormLabel>Tags</FormLabel>
<FormLabel>{translate('Tags')}</FormLabel>
<FormInputGroup
type={inputTypes.TAG}
@@ -92,7 +93,7 @@ function TagsModalContent(props: TagsModalContentProps) {
</FormGroup>
<FormGroup>
<FormLabel>Apply Tags</FormLabel>
<FormLabel>{translate('ApplyTags')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
@@ -100,20 +101,20 @@ function TagsModalContent(props: TagsModalContentProps) {
value={applyTags}
values={applyTagsOptions}
helpTexts={[
'How to apply tags to the selected indexer(s)',
'Add: Add the tags the existing list of tags',
'Remove: Remove the entered tags',
'Replace: Replace the tags with the entered tags (enter no tags to clear all tags)',
translate('ApplyTagsHelpTexts1'),
translate('ApplyTagsHelpTexts2'),
translate('ApplyTagsHelpTexts3'),
translate('ApplyTagsHelpTexts4'),
]}
onChange={onApplyTagsChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>Result</FormLabel>
<FormLabel>{translate('Result')}</FormLabel>
<div className={styles.result}>
{seriesTags.map((id) => {
{indexersTags.map((id) => {
const tag = tagList.find((t) => t.id === id);
if (!tag) {
@@ -127,7 +128,11 @@ function TagsModalContent(props: TagsModalContentProps) {
return (
<Label
key={tag.id}
title={removeTag ? 'Removing tag' : 'Existing tag'}
title={
removeTag
? translate('RemovingTag')
: translate('ExistingTag')
}
kind={removeTag ? kinds.INVERSE : kinds.INFO}
size={sizes.LARGE}
>
@@ -144,14 +149,14 @@ function TagsModalContent(props: TagsModalContentProps) {
return null;
}
if (seriesTags.indexOf(id) > -1) {
if (indexersTags.indexOf(id) > -1) {
return null;
}
return (
<Label
key={tag.id}
title={'Adding tag'}
title={translate('AddingTag')}
kind={kinds.SUCCESS}
size={sizes.LARGE}
>
@@ -165,10 +170,10 @@ function TagsModalContent(props: TagsModalContentProps) {
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>Cancel</Button>
<Button onPress={onModalClose}>{translate('Cancel')}</Button>
<Button kind={kinds.PRIMARY} onPress={onApplyPress}>
Apply
{translate('Apply')}
</Button>
</ModalFooter>
</ModalContent>