Translate Frontend Components, Episode and Helpers
This commit is contained in:
parent
074aa6f445
commit
e777b70184
|
@ -1,5 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import StackTrace from 'stacktrace-js';
|
import StackTrace from 'stacktrace-js';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './ErrorBoundaryError.css';
|
import styles from './ErrorBoundaryError.css';
|
||||||
|
|
||||||
interface ErrorBoundaryErrorProps {
|
interface ErrorBoundaryErrorProps {
|
||||||
|
@ -18,7 +19,7 @@ function ErrorBoundaryError(props: ErrorBoundaryErrorProps) {
|
||||||
className = styles.container,
|
className = styles.container,
|
||||||
messageClassName = styles.message,
|
messageClassName = styles.message,
|
||||||
detailsClassName = styles.details,
|
detailsClassName = styles.details,
|
||||||
message = 'There was an error loading this content',
|
message = translate('ErrorLoadingContent'),
|
||||||
error,
|
error,
|
||||||
info,
|
info,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import React, { Component } from 'react';
|
||||||
import Alert from 'Components/Alert';
|
import Alert from 'Components/Alert';
|
||||||
import PathInput from 'Components/Form/PathInput';
|
import PathInput from 'Components/Form/PathInput';
|
||||||
import Button from 'Components/Link/Button';
|
import Button from 'Components/Link/Button';
|
||||||
import Link from 'Components/Link/Link';
|
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import ModalBody from 'Components/Modal/ModalBody';
|
import ModalBody from 'Components/Modal/ModalBody';
|
||||||
import ModalContent from 'Components/Modal/ModalContent';
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
|
@ -14,6 +13,7 @@ import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
import { kinds, scrollDirections } from 'Helpers/Props';
|
import { kinds, scrollDirections } from 'Helpers/Props';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
|
import InlineMarkdown from '../Markdown/InlineMarkdown';
|
||||||
import FileBrowserRow from './FileBrowserRow';
|
import FileBrowserRow from './FileBrowserRow';
|
||||||
import styles from './FileBrowserModalContent.css';
|
import styles from './FileBrowserModalContent.css';
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ class FileBrowserModalContent extends Component {
|
||||||
onModalClose={onModalClose}
|
onModalClose={onModalClose}
|
||||||
>
|
>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
File Browser
|
{translate('FileBrowser')}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody
|
<ModalBody
|
||||||
|
@ -117,13 +117,13 @@ class FileBrowserModalContent extends Component {
|
||||||
className={styles.mappedDrivesWarning}
|
className={styles.mappedDrivesWarning}
|
||||||
kind={kinds.WARNING}
|
kind={kinds.WARNING}
|
||||||
>
|
>
|
||||||
Mapped network drives are not available when running as a Windows Service, see the <Link className={styles.faqLink} to="https://wiki.servarr.com/sonarr/faq#why-cant-sonarr-see-my-files-on-a-remote-server">FAQ</Link> for more information.
|
<InlineMarkdown data={translate('MappedNetworkDrivesWindowsService')} />
|
||||||
</Alert>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
<PathInput
|
<PathInput
|
||||||
className={styles.pathInput}
|
className={styles.pathInput}
|
||||||
placeholder="Start typing or select a path below"
|
placeholder={translate('FileBrowserPlaceholderText')}
|
||||||
hasFileBrowser={false}
|
hasFileBrowser={false}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
value={this.state.currentPath}
|
value={this.state.currentPath}
|
||||||
|
@ -137,7 +137,7 @@ class FileBrowserModalContent extends Component {
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
!!error &&
|
!!error &&
|
||||||
<div>Error loading contents</div>
|
<div>{translate('ErrorLoadingContents')}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -151,7 +151,7 @@ class FileBrowserModalContent extends Component {
|
||||||
emptyParent &&
|
emptyParent &&
|
||||||
<FileBrowserRow
|
<FileBrowserRow
|
||||||
type="computer"
|
type="computer"
|
||||||
name="My Computer"
|
name={translate('MyComputer')}
|
||||||
path={parent}
|
path={parent}
|
||||||
onPress={this.onRowPress}
|
onPress={this.onRowPress}
|
||||||
/>
|
/>
|
||||||
|
@ -212,13 +212,13 @@ class FileBrowserModalContent extends Component {
|
||||||
<Button
|
<Button
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Cancel
|
{translate('Cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onPress={this.onOkPress}
|
onPress={this.onOkPress}
|
||||||
>
|
>
|
||||||
Ok
|
{translate('Ok')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import TagInputTag from 'Components/Form/TagInputTag';
|
import TagInputTag from 'Components/Form/TagInputTag';
|
||||||
import { kinds } from 'Helpers/Props';
|
import { kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './FilterBuilderRowValueTag.css';
|
import styles from './FilterBuilderRowValueTag.css';
|
||||||
|
|
||||||
function FilterBuilderRowValueTag(props) {
|
function FilterBuilderRowValueTag(props) {
|
||||||
|
@ -18,7 +19,7 @@ function FilterBuilderRowValueTag(props) {
|
||||||
props.isLastTag ?
|
props.isLastTag ?
|
||||||
null :
|
null :
|
||||||
<div className={styles.or}>
|
<div className={styles.or}>
|
||||||
or
|
{translate('or')}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,32 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||||
|
|
||||||
const seriesStatusList = [
|
const seriesStatusList = [
|
||||||
{ id: 'continuing', name: 'Continuing' },
|
{
|
||||||
{ id: 'upcoming', name: 'Upcoming' },
|
id: 'continuing',
|
||||||
{ id: 'ended', name: 'Ended' },
|
get name() {
|
||||||
{ id: 'deleted', name: 'Deleted' }
|
return translate('Continuing');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'upcoming',
|
||||||
|
get name() {
|
||||||
|
return translate('Upcoming');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ended',
|
||||||
|
get name() {
|
||||||
|
return translate('Ended');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'deleted',
|
||||||
|
get name() {
|
||||||
|
return translate('Deleted');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function SeriesStatusFilterBuilderRowValue(props) {
|
function SeriesStatusFilterBuilderRowValue(props) {
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||||
|
|
||||||
const seriesTypeList = [
|
const seriesTypeList = [
|
||||||
{ id: 'anime', name: 'Anime' },
|
{
|
||||||
{ id: 'daily', name: 'Daily' },
|
id: 'anime',
|
||||||
{ id: 'standard', name: 'Standard' }
|
get name() {
|
||||||
|
return translate('Anime');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'daily',
|
||||||
|
get name() {
|
||||||
|
return translate('Daily');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'standard',
|
||||||
|
get name() {
|
||||||
|
return translate('Standard');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function SeriesTypeFilterBuilderRowValue(props) {
|
function SeriesTypeFilterBuilderRowValue(props) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React, { Component } from 'react';
|
||||||
import IconButton from 'Components/Link/IconButton';
|
import IconButton from 'Components/Link/IconButton';
|
||||||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './CustomFilter.css';
|
import styles from './CustomFilter.css';
|
||||||
|
|
||||||
class CustomFilter extends Component {
|
class CustomFilter extends Component {
|
||||||
|
@ -89,7 +90,7 @@ class CustomFilter extends Component {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SpinnerIconButton
|
<SpinnerIconButton
|
||||||
title="Remove filter"
|
title={translate('RemoveFilter')}
|
||||||
name={icons.REMOVE}
|
name={icons.REMOVE}
|
||||||
isSpinning={this.state.isDeleting}
|
isSpinning={this.state.isDeleting}
|
||||||
onPress={this.onRemovePress}
|
onPress={this.onRemovePress}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||||
import ModalContent from 'Components/Modal/ModalContent';
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import CustomFilter from './CustomFilter';
|
import CustomFilter from './CustomFilter';
|
||||||
import styles from './CustomFiltersModalContent.css';
|
import styles from './CustomFiltersModalContent.css';
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ function CustomFiltersModalContent(props) {
|
||||||
return (
|
return (
|
||||||
<ModalContent onModalClose={onModalClose}>
|
<ModalContent onModalClose={onModalClose}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
Custom Filters
|
{translate('CustomFilters')}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@ -49,7 +50,7 @@ function CustomFiltersModalContent(props) {
|
||||||
|
|
||||||
<div className={styles.addButtonContainer}>
|
<div className={styles.addButtonContainer}>
|
||||||
<Button onPress={onAddCustomFilter}>
|
<Button onPress={onAddCustomFilter}>
|
||||||
Add Custom Filter
|
{translate('AddCustomFilter')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
@ -58,7 +59,7 @@ function CustomFiltersModalContent(props) {
|
||||||
<Button
|
<Button
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Close
|
{translate('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { fetchDownloadClients } from 'Store/Actions/settingsActions';
|
import { fetchDownloadClients } from 'Store/Actions/settingsActions';
|
||||||
import sortByName from 'Utilities/Array/sortByName';
|
import sortByName from 'Utilities/Array/sortByName';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -32,7 +33,7 @@ function createMapStateToProps() {
|
||||||
if (includeAny) {
|
if (includeAny) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 0,
|
key: 0,
|
||||||
value: '(Any)'
|
value: `(${translate('Any')})`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import { inputTypes, kinds } from 'Helpers/Props';
|
import { inputTypes, kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import AutoCompleteInput from './AutoCompleteInput';
|
import AutoCompleteInput from './AutoCompleteInput';
|
||||||
import CaptchaInputConnector from './CaptchaInputConnector';
|
import CaptchaInputConnector from './CaptchaInputConnector';
|
||||||
import CheckInput from './CheckInput';
|
import CheckInput from './CheckInput';
|
||||||
|
@ -215,7 +216,7 @@ function FormInputGroup(props) {
|
||||||
<Link
|
<Link
|
||||||
to={helpLink}
|
to={helpLink}
|
||||||
>
|
>
|
||||||
More Info
|
{translate('MoreInfo')}
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { fetchIndexers } from 'Store/Actions/settingsActions';
|
import { fetchIndexers } from 'Store/Actions/settingsActions';
|
||||||
import sortByName from 'Utilities/Array/sortByName';
|
import sortByName from 'Utilities/Array/sortByName';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -29,7 +30,7 @@ function createMapStateToProps() {
|
||||||
if (includeAny) {
|
if (includeAny) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 0,
|
key: 0,
|
||||||
value: '(Any)'
|
value: `(${translate('Any')})`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import monitorOptions from 'Utilities/Series/monitorOptions';
|
import monitorOptions from 'Utilities/Series/monitorOptions';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import SelectInput from './SelectInput';
|
import SelectInput from './SelectInput';
|
||||||
|
|
||||||
function MonitorEpisodesSelectInput(props) {
|
function MonitorEpisodesSelectInput(props) {
|
||||||
|
@ -15,7 +16,9 @@ function MonitorEpisodesSelectInput(props) {
|
||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
get value() {
|
||||||
|
return translate('NoChange');
|
||||||
|
},
|
||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -23,7 +26,9 @@ function MonitorEpisodesSelectInput(props) {
|
||||||
if (includeMixed) {
|
if (includeMixed) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'mixed',
|
key: 'mixed',
|
||||||
value: '(Mixed)',
|
get value() {
|
||||||
|
return `(${translate('Mixed')})`;
|
||||||
|
},
|
||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
||||||
import sortByName from 'Utilities/Array/sortByName';
|
import sortByName from 'Utilities/Array/sortByName';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -24,7 +25,9 @@ function createMapStateToProps() {
|
||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
get value() {
|
||||||
|
return translate('NoChange');
|
||||||
|
},
|
||||||
disabled: includeNoChangeDisabled
|
disabled: includeNoChangeDisabled
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -32,7 +35,9 @@ function createMapStateToProps() {
|
||||||
if (includeMixed) {
|
if (includeMixed) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'mixed',
|
key: 'mixed',
|
||||||
value: '(Mixed)',
|
get value() {
|
||||||
|
return `(${translate('Mixed')})`;
|
||||||
|
},
|
||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { addRootFolder } from 'Store/Actions/rootFolderActions';
|
import { addRootFolder } from 'Store/Actions/rootFolderActions';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import RootFolderSelectInput from './RootFolderSelectInput';
|
import RootFolderSelectInput from './RootFolderSelectInput';
|
||||||
|
|
||||||
const ADD_NEW_KEY = 'addNew';
|
const ADD_NEW_KEY = 'addNew';
|
||||||
|
@ -27,7 +28,9 @@ function createMapStateToProps() {
|
||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
get value() {
|
||||||
|
return translate('NoChange');
|
||||||
|
},
|
||||||
isDisabled: includeNoChangeDisabled,
|
isDisabled: includeNoChangeDisabled,
|
||||||
isMissing: false
|
isMissing: false
|
||||||
});
|
});
|
||||||
|
@ -53,7 +56,7 @@ function createMapStateToProps() {
|
||||||
|
|
||||||
values.push({
|
values.push({
|
||||||
key: ADD_NEW_KEY,
|
key: ADD_NEW_KEY,
|
||||||
value: 'Add a new path'
|
value: translate('AddANewPath')
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInputOption from './EnhancedSelectInputOption';
|
import EnhancedSelectInputOption from './EnhancedSelectInputOption';
|
||||||
import styles from './RootFolderSelectInputOption.css';
|
import styles from './RootFolderSelectInputOption.css';
|
||||||
|
|
||||||
|
@ -47,14 +48,14 @@ function RootFolderSelectInputOption(props) {
|
||||||
freeSpace == null ?
|
freeSpace == null ?
|
||||||
null :
|
null :
|
||||||
<div className={styles.freeSpace}>
|
<div className={styles.freeSpace}>
|
||||||
{formatBytes(freeSpace)} Free
|
{translate('RootFolderSelectFreeSpace', { freeSpace: formatBytes(freeSpace) })}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
isMissing ?
|
isMissing ?
|
||||||
<div className={styles.isMissing}>
|
<div className={styles.isMissing}>
|
||||||
Missing
|
{translate('Missing')}
|
||||||
</div> :
|
</div> :
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue';
|
import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue';
|
||||||
import styles from './RootFolderSelectInputSelectedValue.css';
|
import styles from './RootFolderSelectInputSelectedValue.css';
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ function RootFolderSelectInputSelectedValue(props) {
|
||||||
{
|
{
|
||||||
freeSpace != null && includeFreeSpace &&
|
freeSpace != null && includeFreeSpace &&
|
||||||
<div className={styles.freeSpace}>
|
<div className={styles.freeSpace}>
|
||||||
{formatBytes(freeSpace)} Free
|
{translate('RootFolderSelectFreeSpace', { freeSpace: formatBytes(freeSpace) })}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</EnhancedSelectInputSelectedValue>
|
</EnhancedSelectInputSelectedValue>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as seriesTypes from 'Utilities/Series/seriesTypes';
|
import * as seriesTypes from 'Utilities/Series/seriesTypes';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
import SeriesTypeSelectInputOption from './SeriesTypeSelectInputOption';
|
import SeriesTypeSelectInputOption from './SeriesTypeSelectInputOption';
|
||||||
import SeriesTypeSelectInputSelectedValue from './SeriesTypeSelectInputSelectedValue';
|
import SeriesTypeSelectInputSelectedValue from './SeriesTypeSelectInputSelectedValue';
|
||||||
|
@ -21,17 +22,23 @@ const seriesTypeOptions: ISeriesTypeOption[] = [
|
||||||
{
|
{
|
||||||
key: seriesTypes.STANDARD,
|
key: seriesTypes.STANDARD,
|
||||||
value: 'Standard',
|
value: 'Standard',
|
||||||
format: 'Season and episode numbers (S01E05)',
|
get format() {
|
||||||
|
return translate('StandardTypeFormat', { format: 'S01E05' });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: seriesTypes.DAILY,
|
key: seriesTypes.DAILY,
|
||||||
value: 'Daily / Date',
|
value: 'Daily / Date',
|
||||||
format: 'Date (2020-05-25)',
|
get format() {
|
||||||
|
return translate('DailyTypeFormat', { format: '2020-05-25' });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: seriesTypes.ANIME,
|
key: seriesTypes.ANIME,
|
||||||
value: 'Anime / Absolute',
|
value: 'Anime / Absolute',
|
||||||
format: 'Absolute episode Number (005)',
|
get format() {
|
||||||
|
return translate('AnimeTypeFormat', { format: '005' });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -47,7 +54,7 @@ function SeriesTypeSelectInput(props: SeriesTypeSelectInputProps) {
|
||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
value: translate('NoChange'),
|
||||||
disabled: includeNoChangeDisabled,
|
disabled: includeNoChangeDisabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -55,7 +62,7 @@ function SeriesTypeSelectInput(props: SeriesTypeSelectInputProps) {
|
||||||
if (includeMixed) {
|
if (includeMixed) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'mixed',
|
key: 'mixed',
|
||||||
value: '(Mixed)',
|
value: `(${translate('Mixed')})`,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,44 @@
|
||||||
/* eslint-disable no-bitwise */
|
/* eslint-disable no-bitwise */
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
import styles from './UMaskInput.css';
|
import styles from './UMaskInput.css';
|
||||||
|
|
||||||
const umaskOptions = [
|
const umaskOptions = [
|
||||||
{
|
{
|
||||||
key: '755',
|
key: '755',
|
||||||
value: '755 - Owner write, Everyone else read',
|
get value() {
|
||||||
|
return translate('Umask755Description', { octal: '755' });
|
||||||
|
},
|
||||||
hint: 'drwxr-xr-x'
|
hint: 'drwxr-xr-x'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '775',
|
key: '775',
|
||||||
value: '775 - Owner & Group write, Other read',
|
get value() {
|
||||||
|
return translate('Umask775Description', { octal: '775' });
|
||||||
|
},
|
||||||
hint: 'drwxrwxr-x'
|
hint: 'drwxrwxr-x'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '770',
|
key: '770',
|
||||||
value: '770 - Owner & Group write',
|
get value() {
|
||||||
|
return translate('Umask770Description', { octal: '770' });
|
||||||
|
},
|
||||||
hint: 'drwxrwx---'
|
hint: 'drwxrwx---'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '750',
|
key: '750',
|
||||||
value: '750 - Owner write, Group read',
|
get value() {
|
||||||
|
return translate('Umask750Description', { octal: '750' });
|
||||||
|
},
|
||||||
hint: 'drwxr-x---'
|
hint: 'drwxr-x---'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '777',
|
key: '777',
|
||||||
value: '777 - Everyone write',
|
get value() {
|
||||||
|
return translate('Umask777Description', { octal: '777' });
|
||||||
|
},
|
||||||
hint: 'drwxrwxrwx'
|
hint: 'drwxrwxrwx'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -101,16 +112,16 @@ class UMaskInput extends Component {
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.details}>
|
<div className={styles.details}>
|
||||||
<div>
|
<div>
|
||||||
<label>UMask</label>
|
<label>{translate('UMask')}</label>
|
||||||
<div className={styles.value}>{umask}</div>
|
<div className={styles.value}>{umask}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>Folder</label>
|
<label>{translate('Folder')}</label>
|
||||||
<div className={styles.value}>{folder}</div>
|
<div className={styles.value}>{folder}</div>
|
||||||
<div className={styles.unit}>d{formatPermissions(folderNum)}</div>
|
<div className={styles.unit}>d{formatPermissions(folderNum)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>File</label>
|
<label>{translate('File')}</label>
|
||||||
<div className={styles.value}>{file}</div>
|
<div className={styles.value}>{file}</div>
|
||||||
<div className={styles.unit}>{formatPermissions(fileNum)}</div>
|
<div className={styles.unit}>{formatPermissions(fileNum)}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Icon from 'Components/Icon';
|
import Icon from 'Components/Icon';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import Link from './Link';
|
import Link from './Link';
|
||||||
import styles from './IconButton.css';
|
import styles from './IconButton.css';
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ function IconButton(props) {
|
||||||
className,
|
className,
|
||||||
isDisabled && styles.isDisabled
|
isDisabled && styles.isDisabled
|
||||||
)}
|
)}
|
||||||
aria-label="Table Options Button"
|
aria-label={translate('TableOptionsButton')}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import FilterMenuContent from './FilterMenuContent';
|
import FilterMenuContent from './FilterMenuContent';
|
||||||
import Menu from './Menu';
|
import Menu from './Menu';
|
||||||
import ToolbarMenuButton from './ToolbarMenuButton';
|
import ToolbarMenuButton from './ToolbarMenuButton';
|
||||||
|
@ -58,7 +59,7 @@ class FilterMenu extends Component {
|
||||||
<ButtonComponent
|
<ButtonComponent
|
||||||
iconName={icons.FILTER}
|
iconName={icons.FILTER}
|
||||||
showIndicator={selectedFilterKey !== 'all'}
|
showIndicator={selectedFilterKey !== 'all'}
|
||||||
text="Filter"
|
text={translate('Filter')}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import FilterMenuItem from './FilterMenuItem';
|
import FilterMenuItem from './FilterMenuItem';
|
||||||
import MenuContent from './MenuContent';
|
import MenuContent from './MenuContent';
|
||||||
import MenuItem from './MenuItem';
|
import MenuItem from './MenuItem';
|
||||||
|
@ -61,7 +62,7 @@ class FilterMenuContent extends Component {
|
||||||
{
|
{
|
||||||
showCustomFilters &&
|
showCustomFilters &&
|
||||||
<MenuItem onPress={onCustomFiltersPress}>
|
<MenuItem onPress={onCustomFiltersPress}>
|
||||||
Custom Filters
|
{translate('CustomFilters')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
}
|
}
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
||||||
import { Manager, Popper, Reference } from 'react-popper';
|
import { Manager, Popper, Reference } from 'react-popper';
|
||||||
import Portal from 'Components/Portal';
|
import Portal from 'Components/Portal';
|
||||||
import { align } from 'Helpers/Props';
|
import { align } from 'Helpers/Props';
|
||||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
import getUniqueElementId from 'Utilities/getUniqueElementId';
|
||||||
import styles from './Menu.css';
|
import styles from './Menu.css';
|
||||||
|
|
||||||
const sharedPopperOptions = {
|
const sharedPopperOptions = {
|
||||||
|
@ -38,8 +38,8 @@ class Menu extends Component {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this._scheduleUpdate = null;
|
this._scheduleUpdate = null;
|
||||||
this._menuButtonId = getUniqueElememtId();
|
this._menuButtonId = getUniqueElementId();
|
||||||
this._menuContentId = getUniqueElememtId();
|
this._menuContentId = getUniqueElementId();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isMenuOpen: false,
|
isMenuOpen: false,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
import Menu from 'Components/Menu/Menu';
|
import Menu from 'Components/Menu/Menu';
|
||||||
import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
|
import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
|
||||||
import { align, icons } from 'Helpers/Props';
|
import { align, icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
function SortMenu(props) {
|
function SortMenu(props) {
|
||||||
const {
|
const {
|
||||||
|
@ -19,7 +20,7 @@ function SortMenu(props) {
|
||||||
>
|
>
|
||||||
<ToolbarMenuButton
|
<ToolbarMenuButton
|
||||||
iconName={icons.SORT}
|
iconName={icons.SORT}
|
||||||
text="Sort"
|
text={translate('Sort')}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
import Menu from 'Components/Menu/Menu';
|
import Menu from 'Components/Menu/Menu';
|
||||||
import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
|
import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
|
||||||
import { align, icons } from 'Helpers/Props';
|
import { align, icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
function ViewMenu(props) {
|
function ViewMenu(props) {
|
||||||
const {
|
const {
|
||||||
|
@ -17,7 +18,7 @@ function ViewMenu(props) {
|
||||||
>
|
>
|
||||||
<ToolbarMenuButton
|
<ToolbarMenuButton
|
||||||
iconName={icons.VIEW}
|
iconName={icons.VIEW}
|
||||||
text="View"
|
text={translate('View')}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './MetadataAttribution.css';
|
import styles from './MetadataAttribution.css';
|
||||||
|
|
||||||
export default function MetadataAttribution() {
|
export default function MetadataAttribution() {
|
||||||
|
@ -9,7 +10,7 @@ export default function MetadataAttribution() {
|
||||||
className={styles.attribution}
|
className={styles.attribution}
|
||||||
to="/settings/metadatasource"
|
to="/settings/metadatasource"
|
||||||
>
|
>
|
||||||
Metadata is provided by TheTVDB
|
{translate('MetadataProvidedBy', { provider: 'TheTVDB' })}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||||
import ModalContent from 'Components/Modal/ModalContent';
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './ModalError.css';
|
import styles from './ModalError.css';
|
||||||
|
|
||||||
function ModalError(props) {
|
function ModalError(props) {
|
||||||
|
@ -17,7 +18,7 @@ function ModalError(props) {
|
||||||
return (
|
return (
|
||||||
<ModalContent onModalClose={onModalClose}>
|
<ModalContent onModalClose={onModalClose}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
Error
|
{translate('Error')}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@ -25,7 +26,7 @@ function ModalError(props) {
|
||||||
messageClassName={styles.message}
|
messageClassName={styles.message}
|
||||||
detailsClassName={styles.details}
|
detailsClassName={styles.details}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
message='There was an error loading this item'
|
message={translate('ErrorLoadingItem')}
|
||||||
/>
|
/>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ function ModalError(props) {
|
||||||
<Button
|
<Button
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Close
|
{translate('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -3,18 +3,19 @@ import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './MonitorToggleButton.css';
|
import styles from './MonitorToggleButton.css';
|
||||||
|
|
||||||
function getTooltip(monitored, isDisabled) {
|
function getTooltip(monitored, isDisabled) {
|
||||||
if (isDisabled) {
|
if (isDisabled) {
|
||||||
return 'Cannot toggle monitored state when series is unmonitored';
|
return translate('ToggleMonitoredSeriesUnmonitored ');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monitored) {
|
if (monitored) {
|
||||||
return 'Monitored, click to unmonitor';
|
return translate('ToggleMonitoredToUnmonitored');
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Unmonitored, click to monitor';
|
return translate('ToggleUnmonitoredToMonitored');
|
||||||
}
|
}
|
||||||
|
|
||||||
class MonitorToggleButton extends Component {
|
class MonitorToggleButton extends Component {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './NotFound.css';
|
import styles from './NotFound.css';
|
||||||
|
|
||||||
function NotFound({ message }) {
|
function NotFound(props) {
|
||||||
|
const { message = translate('DefaultNotFoundMessage') } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="MIA">
|
<PageContent title="MIA">
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
@ -21,11 +24,7 @@ function NotFound({ message }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NotFound.propTypes = {
|
NotFound.propTypes = {
|
||||||
message: PropTypes.string.isRequired
|
message: PropTypes.string
|
||||||
};
|
|
||||||
|
|
||||||
NotFound.defaultProps = {
|
|
||||||
message: 'You must be lost, nothing to see here.'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NotFound;
|
export default NotFound;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './ErrorPage.css';
|
import styles from './ErrorPage.css';
|
||||||
|
|
||||||
function ErrorPage(props) {
|
function ErrorPage(props) {
|
||||||
|
@ -16,24 +17,24 @@ function ErrorPage(props) {
|
||||||
systemStatusError
|
systemStatusError
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
let errorMessage = 'Failed to load Sonarr';
|
let errorMessage = translate('FailedToLoadSonarr');
|
||||||
|
|
||||||
if (!isLocalStorageSupported) {
|
if (!isLocalStorageSupported) {
|
||||||
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
|
errorMessage = translate('LocalStorageIsNotSupported');
|
||||||
} else if (translationsError) {
|
} else if (translationsError) {
|
||||||
errorMessage = getErrorMessage(translationsError, 'Failed to load translations from API');
|
errorMessage = getErrorMessage(translationsError, translate('FailedToLoadTranslationsFromApi'));
|
||||||
} else if (seriesError) {
|
} else if (seriesError) {
|
||||||
errorMessage = getErrorMessage(seriesError, 'Failed to load series from API');
|
errorMessage = getErrorMessage(seriesError, translate('FailedToLoadSeriesFromApi'));
|
||||||
} else if (customFiltersError) {
|
} else if (customFiltersError) {
|
||||||
errorMessage = getErrorMessage(customFiltersError, 'Failed to load custom filters from API');
|
errorMessage = getErrorMessage(customFiltersError, translate('FailedToLoadCustomFiltersFromApi'));
|
||||||
} else if (tagsError) {
|
} else if (tagsError) {
|
||||||
errorMessage = getErrorMessage(tagsError, 'Failed to load tags from API');
|
errorMessage = getErrorMessage(tagsError, translate('FailedToLoadTagsFromApi'));
|
||||||
} else if (qualityProfilesError) {
|
} else if (qualityProfilesError) {
|
||||||
errorMessage = getErrorMessage(qualityProfilesError, 'Failed to load quality profiles from API');
|
errorMessage = getErrorMessage(qualityProfilesError, translate('FailedToLoadQualityProfilesFromApi'));
|
||||||
} else if (uiSettingsError) {
|
} else if (uiSettingsError) {
|
||||||
errorMessage = getErrorMessage(uiSettingsError, 'Failed to load UI settings from API');
|
errorMessage = getErrorMessage(uiSettingsError, translate('FailedToLoadUiSettingsFromApi'));
|
||||||
} else if (systemStatusError) {
|
} else if (systemStatusError) {
|
||||||
errorMessage = getErrorMessage(uiSettingsError, 'Failed to load system status from API');
|
errorMessage = getErrorMessage(uiSettingsError, translate('FailedToLoadSystemStatusFromApi'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -43,7 +44,7 @@ function ErrorPage(props) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.version}>
|
<div className={styles.version}>
|
||||||
Version {version}
|
{translate('VersionNumber', { version })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||||
import ModalContent from 'Components/Modal/ModalContent';
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './KeyboardShortcutsModalContent.css';
|
import styles from './KeyboardShortcutsModalContent.css';
|
||||||
|
|
||||||
function getShortcuts() {
|
function getShortcuts() {
|
||||||
|
@ -47,7 +48,7 @@ function KeyboardShortcutsModalContent(props) {
|
||||||
return (
|
return (
|
||||||
<ModalContent onModalClose={onModalClose}>
|
<ModalContent onModalClose={onModalClose}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
Keyboard Shortcuts
|
{translate('KeyboardShortcuts')}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@ -75,7 +76,7 @@ function KeyboardShortcutsModalContent(props) {
|
||||||
<Button
|
<Button
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Close
|
{translate('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
|
||||||
import IconButton from 'Components/Link/IconButton';
|
import IconButton from 'Components/Link/IconButton';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
||||||
import PageHeaderActionsMenuConnector from './PageHeaderActionsMenuConnector';
|
import PageHeaderActionsMenuConnector from './PageHeaderActionsMenuConnector';
|
||||||
import SeriesSearchInputConnector from './SeriesSearchInputConnector';
|
import SeriesSearchInputConnector from './SeriesSearchInputConnector';
|
||||||
|
@ -77,7 +78,7 @@ class PageHeader extends Component {
|
||||||
<IconButton
|
<IconButton
|
||||||
className={styles.donate}
|
className={styles.donate}
|
||||||
name={icons.HEART}
|
name={icons.HEART}
|
||||||
aria-label="Donate"
|
aria-label={translate('Donate')}
|
||||||
to="https://sonarr.tv/donate.html"
|
to="https://sonarr.tv/donate.html"
|
||||||
size={14}
|
size={14}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import MenuContent from 'Components/Menu/MenuContent';
|
||||||
import MenuItem from 'Components/Menu/MenuItem';
|
import MenuItem from 'Components/Menu/MenuItem';
|
||||||
import MenuItemSeparator from 'Components/Menu/MenuItemSeparator';
|
import MenuItemSeparator from 'Components/Menu/MenuItemSeparator';
|
||||||
import { align, icons, kinds } from 'Helpers/Props';
|
import { align, icons, kinds } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './PageHeaderActionsMenu.css';
|
import styles from './PageHeaderActionsMenu.css';
|
||||||
|
|
||||||
function PageHeaderActionsMenu(props) {
|
function PageHeaderActionsMenu(props) {
|
||||||
|
@ -32,7 +33,7 @@ function PageHeaderActionsMenu(props) {
|
||||||
className={styles.itemIcon}
|
className={styles.itemIcon}
|
||||||
name={icons.KEYBOARD}
|
name={icons.KEYBOARD}
|
||||||
/>
|
/>
|
||||||
Keyboard Shortcuts
|
{translate('KeyboardShortcuts')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<MenuItemSeparator />
|
<MenuItemSeparator />
|
||||||
|
@ -42,7 +43,7 @@ function PageHeaderActionsMenu(props) {
|
||||||
className={styles.itemIcon}
|
className={styles.itemIcon}
|
||||||
name={icons.RESTART}
|
name={icons.RESTART}
|
||||||
/>
|
/>
|
||||||
Restart
|
{translate('Restart')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<MenuItem onPress={onShutdownPress}>
|
<MenuItem onPress={onShutdownPress}>
|
||||||
|
@ -51,7 +52,7 @@ function PageHeaderActionsMenu(props) {
|
||||||
name={icons.SHUTDOWN}
|
name={icons.SHUTDOWN}
|
||||||
kind={kinds.DANGER}
|
kind={kinds.DANGER}
|
||||||
/>
|
/>
|
||||||
Shutdown
|
{translate('Shutdown')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -69,7 +70,7 @@ function PageHeaderActionsMenu(props) {
|
||||||
className={styles.itemIcon}
|
className={styles.itemIcon}
|
||||||
name={icons.LOGOUT}
|
name={icons.LOGOUT}
|
||||||
/>
|
/>
|
||||||
Logout
|
{translate('Logout')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
}
|
}
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Icon from 'Components/Icon';
|
||||||
import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
|
import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import FuseWorker from './fuse.worker';
|
import FuseWorker from './fuse.worker';
|
||||||
import SeriesSearchResult from './SeriesSearchResult';
|
import SeriesSearchResult from './SeriesSearchResult';
|
||||||
import styles from './SeriesSearchInput.css';
|
import styles from './SeriesSearchInput.css';
|
||||||
|
@ -91,7 +92,7 @@ class SeriesSearchInput extends Component {
|
||||||
if (item.type === ADD_NEW_TYPE) {
|
if (item.type === ADD_NEW_TYPE) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.addNewSeriesSuggestion}>
|
<div className={styles.addNewSeriesSuggestion}>
|
||||||
Search for {query}
|
{translate('SearchForQuery', { query })}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -271,14 +272,14 @@ class SeriesSearchInput extends Component {
|
||||||
|
|
||||||
if (suggestions.length || loading) {
|
if (suggestions.length || loading) {
|
||||||
suggestionGroups.push({
|
suggestionGroups.push({
|
||||||
title: 'Existing Series',
|
title: translate('ExistingSeries'),
|
||||||
loading,
|
loading,
|
||||||
suggestions
|
suggestions
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
suggestionGroups.push({
|
suggestionGroups.push({
|
||||||
title: 'Add New Series',
|
title: translate('AddNewSeries'),
|
||||||
suggestions: [
|
suggestions: [
|
||||||
{
|
{
|
||||||
type: ADD_NEW_TYPE,
|
type: ADD_NEW_TYPE,
|
||||||
|
@ -292,7 +293,7 @@ class SeriesSearchInput extends Component {
|
||||||
className: styles.input,
|
className: styles.input,
|
||||||
name: 'seriesSearch',
|
name: 'seriesSearch',
|
||||||
value,
|
value,
|
||||||
placeholder: 'Search',
|
placeholder: translate('Search'),
|
||||||
autoComplete: 'off',
|
autoComplete: 'off',
|
||||||
spellCheck: false,
|
spellCheck: false,
|
||||||
onChange: this.onChange,
|
onChange: this.onChange,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ErrorBoundaryError from 'Components/Error/ErrorBoundaryError';
|
import ErrorBoundaryError from 'Components/Error/ErrorBoundaryError';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import PageContentBody from './PageContentBody';
|
import PageContentBody from './PageContentBody';
|
||||||
import styles from './PageContentError.css';
|
import styles from './PageContentError.css';
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ function PageContentError(props) {
|
||||||
<PageContentBody>
|
<PageContentBody>
|
||||||
<ErrorBoundaryError
|
<ErrorBoundaryError
|
||||||
{...props}
|
{...props}
|
||||||
message='There was an error loading this page'
|
message={translate('ErrorLoadingPage')}
|
||||||
/>
|
/>
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
|
||||||
import { forEach } from 'Helpers/elementChildren';
|
import { forEach } from 'Helpers/elementChildren';
|
||||||
import { align, icons } from 'Helpers/Props';
|
import { align, icons } from 'Helpers/Props';
|
||||||
import dimensions from 'Styles/Variables/dimensions';
|
import dimensions from 'Styles/Variables/dimensions';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import PageToolbarOverflowMenuItem from './PageToolbarOverflowMenuItem';
|
import PageToolbarOverflowMenuItem from './PageToolbarOverflowMenuItem';
|
||||||
import styles from './PageToolbarSection.css';
|
import styles from './PageToolbarSection.css';
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ class PageToolbarSection extends Component {
|
||||||
<ToolbarMenuButton
|
<ToolbarMenuButton
|
||||||
className={styles.overflowMenuButton}
|
className={styles.overflowMenuButton}
|
||||||
iconName={icons.OVERFLOW}
|
iconName={icons.OVERFLOW}
|
||||||
text="More"
|
text={translate('More')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ColorImpairedConsumer } from 'App/ColorImpairedContext';
|
import { ColorImpairedConsumer } from 'App/ColorImpairedContext';
|
||||||
import { kinds, sizes } from 'Helpers/Props';
|
import { kinds, sizes } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './ProgressBar.css';
|
import styles from './ProgressBar.css';
|
||||||
|
|
||||||
function ProgressBar(props) {
|
function ProgressBar(props) {
|
||||||
|
@ -57,7 +58,7 @@ function ProgressBar(props) {
|
||||||
enableColorImpairedMode && 'colorImpaired'
|
enableColorImpairedMode && 'colorImpaired'
|
||||||
)}
|
)}
|
||||||
role="meter"
|
role="meter"
|
||||||
aria-label={`Progress Bar at ${progress.toFixed(0)}%`}
|
aria-label={translate('ProgressBarProgress', { progress: progress.toFixed(0) })}
|
||||||
aria-valuenow={progress.toFixed(0)}
|
aria-valuenow={progress.toFixed(0)}
|
||||||
aria-valuemin="0"
|
aria-valuemin="0"
|
||||||
aria-valuemax="100"
|
aria-valuemax="100"
|
||||||
|
|
|
@ -15,6 +15,7 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
import { inputTypes } from 'Helpers/Props';
|
import { inputTypes } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import TableOptionsColumn from './TableOptionsColumn';
|
import TableOptionsColumn from './TableOptionsColumn';
|
||||||
import TableOptionsColumnDragPreview from './TableOptionsColumnDragPreview';
|
import TableOptionsColumnDragPreview from './TableOptionsColumnDragPreview';
|
||||||
import TableOptionsColumnDragSource from './TableOptionsColumnDragSource';
|
import TableOptionsColumnDragSource from './TableOptionsColumnDragSource';
|
||||||
|
@ -50,9 +51,9 @@ class TableOptionsModal extends Component {
|
||||||
let pageSizeError = null;
|
let pageSizeError = null;
|
||||||
|
|
||||||
if (value < 5) {
|
if (value < 5) {
|
||||||
pageSizeError = 'Page size must be at least 5';
|
pageSizeError = translate('TablePageSizeMinimum', { minimumValue: '5' });
|
||||||
} else if (value > 250) {
|
} else if (value > 250) {
|
||||||
pageSizeError = 'Page size must not exceed 250';
|
pageSizeError = translate('TablePageSizeMaximum', { maximumValue: '250' });
|
||||||
} else {
|
} else {
|
||||||
this.props.onTableOptionChange({ pageSize: value });
|
this.props.onTableOptionChange({ pageSize: value });
|
||||||
}
|
}
|
||||||
|
@ -136,7 +137,7 @@ class TableOptionsModal extends Component {
|
||||||
isOpen ?
|
isOpen ?
|
||||||
<ModalContent onModalClose={onModalClose}>
|
<ModalContent onModalClose={onModalClose}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
Table Options
|
{translate('TableOptions')}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@ -144,13 +145,13 @@ class TableOptionsModal extends Component {
|
||||||
{
|
{
|
||||||
hasPageSize ?
|
hasPageSize ?
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>Page Size</FormLabel>
|
<FormLabel>{translate('PageSize')}</FormLabel>
|
||||||
|
|
||||||
<FormInputGroup
|
<FormInputGroup
|
||||||
type={inputTypes.NUMBER}
|
type={inputTypes.NUMBER}
|
||||||
name="pageSize"
|
name="pageSize"
|
||||||
value={pageSize || 0}
|
value={pageSize || 0}
|
||||||
helpText="Number of items to show on each page"
|
helpText={translate('TablePageSizeHelpText')}
|
||||||
errors={pageSizeError ? [{ message: pageSizeError }] : undefined}
|
errors={pageSizeError ? [{ message: pageSizeError }] : undefined}
|
||||||
onChange={this.onPageSizeChange}
|
onChange={this.onPageSizeChange}
|
||||||
/>
|
/>
|
||||||
|
@ -168,11 +169,11 @@ class TableOptionsModal extends Component {
|
||||||
{
|
{
|
||||||
canModifyColumns ?
|
canModifyColumns ?
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>Columns</FormLabel>
|
<FormLabel>{translate('TableColumns')}</FormLabel>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<FormInputHelpText
|
<FormInputHelpText
|
||||||
text="Choose which columns are visible and which order they appear in"
|
text={translate('TableColumnsHelpText')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={styles.columns}>
|
<div className={styles.columns}>
|
||||||
|
@ -231,7 +232,7 @@ class TableOptionsModal extends Component {
|
||||||
<Button
|
<Button
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Close
|
{translate('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent> :
|
</ModalContent> :
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Icon from 'Components/Icon';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './TablePager.css';
|
import styles from './TablePager.css';
|
||||||
|
|
||||||
class TablePager extends Component {
|
class TablePager extends Component {
|
||||||
|
@ -156,7 +157,7 @@ class TablePager extends Component {
|
||||||
|
|
||||||
<div className={styles.recordsContainer}>
|
<div className={styles.recordsContainer}>
|
||||||
<div className={styles.records}>
|
<div className={styles.records}>
|
||||||
Total records: {totalRecords}
|
{translate('TotalRecords', { totalRecords })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,31 +1,42 @@
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import getDisplayName from 'Helpers/getDisplayName';
|
import getDisplayName from 'Helpers/getDisplayName';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
export const shortcuts = {
|
export const shortcuts = {
|
||||||
OPEN_KEYBOARD_SHORTCUTS_MODAL: {
|
OPEN_KEYBOARD_SHORTCUTS_MODAL: {
|
||||||
key: '?',
|
key: '?',
|
||||||
name: 'Open This Modal'
|
get name() {
|
||||||
|
return translate('KeyboardShortcutsOpenModal');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
CLOSE_MODAL: {
|
CLOSE_MODAL: {
|
||||||
key: 'Esc',
|
key: 'Esc',
|
||||||
name: 'Close Current Modal'
|
get name() {
|
||||||
|
return translate('KeyboardShortcutsCloseModal');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ACCEPT_CONFIRM_MODAL: {
|
ACCEPT_CONFIRM_MODAL: {
|
||||||
key: 'Enter',
|
key: 'Enter',
|
||||||
name: 'Accept Confirmation Modal'
|
get name() {
|
||||||
|
return translate('KeyboardShortcutsConfirmModal');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SERIES_SEARCH_INPUT: {
|
SERIES_SEARCH_INPUT: {
|
||||||
key: 's',
|
key: 's',
|
||||||
name: 'Focus Search Box'
|
get name() {
|
||||||
|
return translate('KeyboardShortcutsFocusSearchBox');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SAVE_SETTINGS: {
|
SAVE_SETTINGS: {
|
||||||
key: 'mod+s',
|
key: 'mod+s',
|
||||||
name: 'Save Settings'
|
get name() {
|
||||||
|
return translate('KeyboardShortcutsSaveSettings');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
import MonitorToggleButton from 'Components/MonitorToggleButton';
|
import MonitorToggleButton from 'Components/MonitorToggleButton';
|
||||||
import episodeEntities from 'Episode/episodeEntities';
|
import episodeEntities from 'Episode/episodeEntities';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EpisodeHistoryConnector from './History/EpisodeHistoryConnector';
|
import EpisodeHistoryConnector from './History/EpisodeHistoryConnector';
|
||||||
import EpisodeSearchConnector from './Search/EpisodeSearchConnector';
|
import EpisodeSearchConnector from './Search/EpisodeSearchConnector';
|
||||||
import SeasonEpisodeNumber from './SeasonEpisodeNumber';
|
import SeasonEpisodeNumber from './SeasonEpisodeNumber';
|
||||||
|
@ -117,21 +118,21 @@ class EpisodeDetailsModalContent extends Component {
|
||||||
className={styles.tab}
|
className={styles.tab}
|
||||||
selectedClassName={styles.selectedTab}
|
selectedClassName={styles.selectedTab}
|
||||||
>
|
>
|
||||||
Details
|
{translate('Details')}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab
|
<Tab
|
||||||
className={styles.tab}
|
className={styles.tab}
|
||||||
selectedClassName={styles.selectedTab}
|
selectedClassName={styles.selectedTab}
|
||||||
>
|
>
|
||||||
History
|
{translate('History')}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab
|
<Tab
|
||||||
className={styles.tab}
|
className={styles.tab}
|
||||||
selectedClassName={styles.selectedTab}
|
selectedClassName={styles.selectedTab}
|
||||||
>
|
>
|
||||||
Search
|
{translate('Search')}
|
||||||
</Tab>
|
</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
|
|
||||||
|
@ -173,14 +174,14 @@ class EpisodeDetailsModalContent extends Component {
|
||||||
to={seriesLink}
|
to={seriesLink}
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Open Series
|
{translate('OpenSeries')}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onPress={onModalClose}
|
onPress={onModalClose}
|
||||||
>
|
>
|
||||||
Close
|
{translate('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
import Label from 'Components/Label';
|
import Label from 'Components/Label';
|
||||||
import Popover from 'Components/Tooltip/Popover';
|
import Popover from 'Components/Tooltip/Popover';
|
||||||
import { kinds, tooltipPositions } from 'Helpers/Props';
|
import { kinds, tooltipPositions } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
function EpisodeLanguages(props) {
|
function EpisodeLanguages(props) {
|
||||||
const {
|
const {
|
||||||
|
@ -34,10 +35,10 @@ function EpisodeLanguages(props) {
|
||||||
className={className}
|
className={className}
|
||||||
kind={isCutoffNotMet ? kinds.INVERSE : kinds.DEFAULT}
|
kind={isCutoffNotMet ? kinds.INVERSE : kinds.DEFAULT}
|
||||||
>
|
>
|
||||||
Multi-Languages
|
{translate('MultiLanguages')}
|
||||||
</Label>
|
</Label>
|
||||||
}
|
}
|
||||||
title={'Languages'}
|
title={translate('Languages')}
|
||||||
body={
|
body={
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Popover from 'Components/Tooltip/Popover';
|
||||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||||
import padNumber from 'Utilities/Number/padNumber';
|
import padNumber from 'Utilities/Number/padNumber';
|
||||||
import filterAlternateTitles from 'Utilities/Series/filterAlternateTitles';
|
import filterAlternateTitles from 'Utilities/Series/filterAlternateTitles';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import SceneInfo from './SceneInfo';
|
import SceneInfo from './SceneInfo';
|
||||||
import styles from './EpisodeNumber.css';
|
import styles from './EpisodeNumber.css';
|
||||||
|
|
||||||
|
@ -12,11 +13,11 @@ function getWarningMessage(unverifiedSceneNumbering, seriesType, absoluteEpisode
|
||||||
const messages = [];
|
const messages = [];
|
||||||
|
|
||||||
if (unverifiedSceneNumbering) {
|
if (unverifiedSceneNumbering) {
|
||||||
messages.push('Scene number hasn\'t been verified yet');
|
messages.push(translate('SceneNumberNotVerified'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seriesType === 'anime' && !absoluteEpisodeNumber) {
|
if (seriesType === 'anime' && !absoluteEpisodeNumber) {
|
||||||
messages.push('Episode does not have an absolute episode number');
|
messages.push(translate('EpisodeMissingAbsoluteNumber'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return messages.join('\n');
|
return messages.join('\n');
|
||||||
|
@ -70,7 +71,7 @@ function EpisodeNumber(props) {
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
title="Scene Information"
|
title={translate('SceneInformation')}
|
||||||
body={
|
body={
|
||||||
<SceneInfo
|
<SceneInfo
|
||||||
seasonNumber={seasonNumber}
|
seasonNumber={seasonNumber}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Icon from 'Components/Icon';
|
||||||
import ProgressBar from 'Components/ProgressBar';
|
import ProgressBar from 'Components/ProgressBar';
|
||||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||||
import isBefore from 'Utilities/Date/isBefore';
|
import isBefore from 'Utilities/Date/isBefore';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EpisodeQuality from './EpisodeQuality';
|
import EpisodeQuality from './EpisodeQuality';
|
||||||
import styles from './EpisodeStatus.css';
|
import styles from './EpisodeStatus.css';
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ function EpisodeStatus(props) {
|
||||||
<div className={styles.center}>
|
<div className={styles.center}>
|
||||||
<Icon
|
<Icon
|
||||||
name={icons.DOWNLOADING}
|
name={icons.DOWNLOADING}
|
||||||
title="Episode is downloading"
|
title={translate('EpisodeIsDownloading')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -66,7 +67,7 @@ function EpisodeStatus(props) {
|
||||||
quality={quality}
|
quality={quality}
|
||||||
size={episodeFile.size}
|
size={episodeFile.size}
|
||||||
isCutoffNotMet={isCutoffNotMet}
|
isCutoffNotMet={isCutoffNotMet}
|
||||||
title="Episode Downloaded"
|
title={translate('EpisodeDownloaded')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -77,7 +78,7 @@ function EpisodeStatus(props) {
|
||||||
<div className={styles.center}>
|
<div className={styles.center}>
|
||||||
<Icon
|
<Icon
|
||||||
name={icons.TBA}
|
name={icons.TBA}
|
||||||
title="TBA"
|
title={translate('Tba')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -89,7 +90,7 @@ function EpisodeStatus(props) {
|
||||||
<Icon
|
<Icon
|
||||||
name={icons.UNMONITORED}
|
name={icons.UNMONITORED}
|
||||||
kind={kinds.DISABLED}
|
kind={kinds.DISABLED}
|
||||||
title="Episode is not monitored"
|
title={translate('EpisodeIsNotMonitored')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -100,7 +101,7 @@ function EpisodeStatus(props) {
|
||||||
<div className={styles.center}>
|
<div className={styles.center}>
|
||||||
<Icon
|
<Icon
|
||||||
name={icons.MISSING}
|
name={icons.MISSING}
|
||||||
title="Episode missing from disk"
|
title={translate('EpisodeMissingFromDisk')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -110,7 +111,7 @@ function EpisodeStatus(props) {
|
||||||
<div className={styles.center}>
|
<div className={styles.center}>
|
||||||
<Icon
|
<Icon
|
||||||
name={icons.NOT_AIRED}
|
name={icons.NOT_AIRED}
|
||||||
title="Episode has not aired"
|
title={translate('EpisodeHasNotAired')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -79,13 +79,13 @@ class EpisodeHistory extends Component {
|
||||||
|
|
||||||
if (!isFetching && !!error) {
|
if (!isFetching && !!error) {
|
||||||
return (
|
return (
|
||||||
<Alert kind={kinds.DANGER}>Unable to load episode history.</Alert>
|
<Alert kind={kinds.DANGER}>{translate('EpisodeHistoryLoadError')}</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPopulated && !hasItems && !error) {
|
if (isPopulated && !hasItems && !error) {
|
||||||
return (
|
return (
|
||||||
<Alert kind={kinds.INFO}>No episode history.</Alert>
|
<Alert kind={kinds.INFO}>{translate('NoEpisodeHistory')}</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import EpisodeLanguages from 'Episode/EpisodeLanguages';
|
||||||
import EpisodeQuality from 'Episode/EpisodeQuality';
|
import EpisodeQuality from 'Episode/EpisodeQuality';
|
||||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||||
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
|
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './EpisodeHistoryRow.css';
|
import styles from './EpisodeHistoryRow.css';
|
||||||
|
|
||||||
function getTitle(eventType) {
|
function getTitle(eventType) {
|
||||||
|
@ -137,7 +138,7 @@ class EpisodeHistoryRow extends Component {
|
||||||
{
|
{
|
||||||
eventType === 'grabbed' &&
|
eventType === 'grabbed' &&
|
||||||
<IconButton
|
<IconButton
|
||||||
title="Mark as failed"
|
title={translate('MarkAsFailed')}
|
||||||
name={icons.REMOVE}
|
name={icons.REMOVE}
|
||||||
onPress={this.onMarkAsFailedPress}
|
onPress={this.onMarkAsFailedPress}
|
||||||
/>
|
/>
|
||||||
|
@ -147,9 +148,9 @@ class EpisodeHistoryRow extends Component {
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={isMarkAsFailedModalOpen}
|
isOpen={isMarkAsFailedModalOpen}
|
||||||
kind={kinds.DANGER}
|
kind={kinds.DANGER}
|
||||||
title="Mark as Failed"
|
title={translate('MarkAsFailed')}
|
||||||
message={`Are you sure you want to mark '${sourceTitle}' as failed?`}
|
message={translate('MarkAsFailedConfirmation', { sourceTitle })}
|
||||||
confirmLabel="Mark as Failed"
|
confirmLabel={translate('MarkAsFailed')}
|
||||||
onConfirm={this.onConfirmMarkAsFailed}
|
onConfirm={this.onConfirmMarkAsFailed}
|
||||||
onCancel={this.onMarkAsFailedModalClose}
|
onCancel={this.onMarkAsFailedModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||||
import padNumber from 'Utilities/Number/padNumber';
|
import padNumber from 'Utilities/Number/padNumber';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './SceneInfo.css';
|
import styles from './SceneInfo.css';
|
||||||
|
|
||||||
function SceneInfo(props) {
|
function SceneInfo(props) {
|
||||||
|
@ -56,7 +57,7 @@ function SceneInfo(props) {
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
titleClassName={styles.title}
|
titleClassName={styles.title}
|
||||||
descriptionClassName={styles.description}
|
descriptionClassName={styles.description}
|
||||||
title="Season"
|
title={translate('Season')}
|
||||||
data={sceneSeasonNumber}
|
data={sceneSeasonNumber}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -66,7 +67,7 @@ function SceneInfo(props) {
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
titleClassName={styles.title}
|
titleClassName={styles.title}
|
||||||
descriptionClassName={styles.description}
|
descriptionClassName={styles.description}
|
||||||
title="Episode"
|
title={translate('Episode')}
|
||||||
data={sceneEpisodeNumber}
|
data={sceneEpisodeNumber}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -76,7 +77,7 @@ function SceneInfo(props) {
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
titleClassName={styles.title}
|
titleClassName={styles.title}
|
||||||
descriptionClassName={styles.description}
|
descriptionClassName={styles.description}
|
||||||
title="Absolute"
|
title={translate('Absolute')}
|
||||||
data={sceneAbsoluteEpisodeNumber}
|
data={sceneAbsoluteEpisodeNumber}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -86,7 +87,7 @@ function SceneInfo(props) {
|
||||||
<DescriptionListItem
|
<DescriptionListItem
|
||||||
titleClassName={styles.title}
|
titleClassName={styles.title}
|
||||||
descriptionClassName={styles.description}
|
descriptionClassName={styles.description}
|
||||||
title={groupedAlternateTitles.length === 1 ? 'Title' : 'Titles'}
|
title={groupedAlternateTitles.length === 1 ? translate('Title') : translate('Titles')}
|
||||||
data={
|
data={
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
import Icon from 'Components/Icon';
|
import Icon from 'Components/Icon';
|
||||||
import Button from 'Components/Link/Button';
|
import Button from 'Components/Link/Button';
|
||||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import styles from './EpisodeSearch.css';
|
import styles from './EpisodeSearch.css';
|
||||||
|
|
||||||
function EpisodeSearch(props) {
|
function EpisodeSearch(props) {
|
||||||
|
@ -24,7 +25,7 @@ function EpisodeSearch(props) {
|
||||||
name={icons.QUICK}
|
name={icons.QUICK}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Quick Search
|
{translate('QuickSearch')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ function EpisodeSearch(props) {
|
||||||
name={icons.INTERACTIVE}
|
name={icons.INTERACTIVE}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Interactive Search
|
{translate('InteractiveSearch')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import formatTime from 'Utilities/Date/formatTime';
|
||||||
import isInNextWeek from 'Utilities/Date/isInNextWeek';
|
import isInNextWeek from 'Utilities/Date/isInNextWeek';
|
||||||
import isToday from 'Utilities/Date/isToday';
|
import isToday from 'Utilities/Date/isToday';
|
||||||
import isTomorrow from 'Utilities/Date/isTomorrow';
|
import isTomorrow from 'Utilities/Date/isTomorrow';
|
||||||
|
import translate from '../../Utilities/String/translate';
|
||||||
|
|
||||||
function EpisodeAiring(props) {
|
function EpisodeAiring(props) {
|
||||||
const {
|
const {
|
||||||
|
@ -26,10 +27,11 @@ function EpisodeAiring(props) {
|
||||||
</Label>
|
</Label>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: Update InlineMarkdown to accept tags and pass in networkLabel object, for now blank string passed into translation
|
||||||
if (!airDateUtc) {
|
if (!airDateUtc) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
TBA on {networkLabel}
|
{translate('AirsTbaOn', { networkLabel: '' })}networkLabel
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +41,7 @@ function EpisodeAiring(props) {
|
||||||
if (!showRelativeDates) {
|
if (!showRelativeDates) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{moment(airDateUtc).format(shortDateFormat)} at {time} on {networkLabel}
|
{translate('AirsDateAtTimeOn', { date: moment(airDateUtc).format(shortDateFormat), time, networkLabel: '' })}{networkLabel}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +49,7 @@ function EpisodeAiring(props) {
|
||||||
if (isToday(airDateUtc)) {
|
if (isToday(airDateUtc)) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{time} on {networkLabel}
|
{translate('AirsTimeOn', { time, networkLabel: '' })}{networkLabel}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +57,7 @@ function EpisodeAiring(props) {
|
||||||
if (isTomorrow(airDateUtc)) {
|
if (isTomorrow(airDateUtc)) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
Tomorrow at {time} on {networkLabel}
|
{translate('AirsTomorrowOn', { time, networkLabel: '' })}{networkLabel}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -63,14 +65,14 @@ function EpisodeAiring(props) {
|
||||||
if (isInNextWeek(airDateUtc)) {
|
if (isInNextWeek(airDateUtc)) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{moment(airDateUtc).format('dddd')} at {time} on {networkLabel}
|
{translate('AirsDateAtTimeOn', { date: moment(airDateUtc).format('dddd'), time, networkLabel: '' })}{networkLabel}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{moment(airDateUtc).format(shortDateFormat)} at {time} on {networkLabel}
|
{translate('AirsDateAtTimeOn', { date: moment(airDateUtc).format(shortDateFormat), time, networkLabel: '' })}{networkLabel}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import EpisodeLanguages from 'Episode/EpisodeLanguages';
|
||||||
import EpisodeQuality from 'Episode/EpisodeQuality';
|
import EpisodeQuality from 'Episode/EpisodeQuality';
|
||||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import MediaInfo from './MediaInfo';
|
import MediaInfo from './MediaInfo';
|
||||||
import styles from './EpisodeFileRow.css';
|
import styles from './EpisodeFileRow.css';
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ class EpisodeFileRow extends Component {
|
||||||
name={icons.MEDIA_INFO}
|
name={icons.MEDIA_INFO}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
title="Media Info"
|
title={translate('MediaInfo')}
|
||||||
body={<MediaInfo {...mediaInfo} />}
|
body={<MediaInfo {...mediaInfo} />}
|
||||||
position={tooltipPositions.LEFT}
|
position={tooltipPositions.LEFT}
|
||||||
/> :
|
/> :
|
||||||
|
@ -148,7 +149,7 @@ class EpisodeFileRow extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
title="Delete episode from disk"
|
title={translate('DeleteEpisodeFromDisk')}
|
||||||
name={icons.REMOVE}
|
name={icons.REMOVE}
|
||||||
onPress={this.onRemoveEpisodeFilePress}
|
onPress={this.onRemoveEpisodeFilePress}
|
||||||
/>
|
/>
|
||||||
|
@ -163,9 +164,9 @@ class EpisodeFileRow extends Component {
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={this.state.isRemoveEpisodeFileModalOpen}
|
isOpen={this.state.isRemoveEpisodeFileModalOpen}
|
||||||
kind={kinds.DANGER}
|
kind={kinds.DANGER}
|
||||||
title="Delete Episode File"
|
title={translate('DeleteEpisodeFile')}
|
||||||
message={`Are you sure you want to delete '${path}'?`}
|
message={translate('DeleteEpisodeFileMessage', { path })}
|
||||||
confirmLabel="Delete"
|
confirmLabel={translate('Delete')}
|
||||||
onConfirm={this.onConfirmRemoveEpisodeFile}
|
onConfirm={this.onConfirmRemoveEpisodeFile}
|
||||||
onCancel={this.onRemoveEpisodeFileModalClose}
|
onCancel={this.onRemoveEpisodeFileModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -103,7 +103,7 @@ class EpisodeSummary extends Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span className={styles.infoTitle}>Airs</span>
|
<span className={styles.infoTitle}>{translate('Airs')}</span>
|
||||||
|
|
||||||
<EpisodeAiringConnector
|
<EpisodeAiringConnector
|
||||||
airDateUtc={airDateUtc}
|
airDateUtc={airDateUtc}
|
||||||
|
@ -112,7 +112,7 @@ class EpisodeSummary extends Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<span className={styles.infoTitle}>Quality Profile</span>
|
<span className={styles.infoTitle}>{translate('QualityProfile')}</span>
|
||||||
|
|
||||||
<Label
|
<Label
|
||||||
kind={kinds.PRIMARY}
|
kind={kinds.PRIMARY}
|
||||||
|
@ -128,7 +128,7 @@ class EpisodeSummary extends Component {
|
||||||
{
|
{
|
||||||
hasOverview ?
|
hasOverview ?
|
||||||
overview :
|
overview :
|
||||||
'No episode overview.'
|
translate('NoEpisodeOverview')
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -155,9 +155,9 @@ class EpisodeSummary extends Component {
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
isOpen={this.state.isRemoveEpisodeFileModalOpen}
|
isOpen={this.state.isRemoveEpisodeFileModalOpen}
|
||||||
kind={kinds.DANGER}
|
kind={kinds.DANGER}
|
||||||
title="Delete Episode File"
|
title={translate('DeleteEpisodeFile')}
|
||||||
message={`Are you sure you want to delete '${path}'?`}
|
message={translate('DeleteEpisodeFileMessage', { path })}
|
||||||
confirmLabel="Delete"
|
confirmLabel={translate('Delete')}
|
||||||
onConfirm={this.onConfirmRemoveEpisodeFile}
|
onConfirm={this.onConfirmRemoveEpisodeFile}
|
||||||
onCancel={this.onRemoveEpisodeFileModalClose}
|
onCancel={this.onRemoveEpisodeFileModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import * as filterTypes from './filterTypes';
|
import * as filterTypes from './filterTypes';
|
||||||
|
|
||||||
export const ARRAY = 'array';
|
export const ARRAY = 'array';
|
||||||
|
@ -20,49 +21,127 @@ export const all = [
|
||||||
|
|
||||||
export const possibleFilterTypes = {
|
export const possibleFilterTypes = {
|
||||||
[ARRAY]: [
|
[ARRAY]: [
|
||||||
{ key: filterTypes.CONTAINS, value: 'contains' },
|
{
|
||||||
{ key: filterTypes.NOT_CONTAINS, value: 'does not contain' }
|
key: filterTypes.CONTAINS,
|
||||||
|
value: () => translate('FilterContains')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_CONTAINS,
|
||||||
|
value: () => translate('FilterDoesNotContain')
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
[CONTAINS]: [
|
[CONTAINS]: [
|
||||||
{ key: filterTypes.CONTAINS, value: 'contains' }
|
{
|
||||||
|
key: filterTypes.CONTAINS,
|
||||||
|
value: () => translate('FilterContains')
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
[DATE]: [
|
[DATE]: [
|
||||||
{ key: filterTypes.LESS_THAN, value: 'is before' },
|
{
|
||||||
{ key: filterTypes.GREATER_THAN, value: 'is after' },
|
key: filterTypes.LESS_THAN,
|
||||||
{ key: filterTypes.IN_LAST, value: 'in the last' },
|
value: () => translate('FilterIsBefore')
|
||||||
{ key: filterTypes.NOT_IN_LAST, value: 'not in the last' },
|
},
|
||||||
{ key: filterTypes.IN_NEXT, value: 'in the next' },
|
{
|
||||||
{ key: filterTypes.NOT_IN_NEXT, value: 'not in the next' }
|
key: filterTypes.GREATER_THAN,
|
||||||
|
value: () => translate('FilterIsAfter')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.IN_LAST,
|
||||||
|
value: () => translate('FilterInLast')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_IN_LAST,
|
||||||
|
value: () => translate('FilterNotInLast')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.IN_NEXT,
|
||||||
|
value: () => translate('FilterInNext')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_IN_NEXT,
|
||||||
|
value: () => translate('FilterNotInNext')
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
[EQUAL]: [
|
[EQUAL]: [
|
||||||
{ key: filterTypes.EQUAL, value: 'is' }
|
{
|
||||||
|
key: filterTypes.EQUAL,
|
||||||
|
value: () => translate('FilterIs')
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
[EXACT]: [
|
[EXACT]: [
|
||||||
{ key: filterTypes.EQUAL, value: 'is' },
|
{
|
||||||
{ key: filterTypes.NOT_EQUAL, value: 'is not' }
|
key: filterTypes.EQUAL,
|
||||||
|
value: () => translate('FilterIs')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_EQUAL,
|
||||||
|
value: () => translate('FilterIsNot')
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
[NUMBER]: [
|
[NUMBER]: [
|
||||||
{ key: filterTypes.EQUAL, value: 'equal' },
|
{
|
||||||
{ key: filterTypes.GREATER_THAN, value: 'greater than' },
|
key: filterTypes.EQUAL,
|
||||||
{ key: filterTypes.GREATER_THAN_OR_EQUAL, value: 'greater than or equal' },
|
value: () => translate('FilterEqual')
|
||||||
{ key: filterTypes.LESS_THAN, value: 'less than' },
|
},
|
||||||
{ key: filterTypes.LESS_THAN_OR_EQUAL, value: 'less than or equal' },
|
{
|
||||||
{ key: filterTypes.NOT_EQUAL, value: 'not equal' }
|
key: filterTypes.GREATER_THAN,
|
||||||
|
value: () => translate('FilterGreaterThan')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.GREATER_THAN_OR_EQUAL,
|
||||||
|
value: () => translate('FilterGreaterThanOrEqual')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.LESS_THAN,
|
||||||
|
value: () => translate('FilterLessThan')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.LESS_THAN_OR_EQUAL,
|
||||||
|
value: () => translate('FilterLessThanOrEqual')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_EQUAL,
|
||||||
|
value: () => translate('FilterNotEqual')
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
[STRING]: [
|
[STRING]: [
|
||||||
{ key: filterTypes.CONTAINS, value: 'contains' },
|
{
|
||||||
{ key: filterTypes.NOT_CONTAINS, value: 'does not contain' },
|
key: filterTypes.CONTAINS,
|
||||||
{ key: filterTypes.EQUAL, value: 'equal' },
|
value: () => translate('FilterContains')
|
||||||
{ key: filterTypes.NOT_EQUAL, value: 'not equal' },
|
},
|
||||||
{ key: filterTypes.STARTS_WITH, value: 'starts with' },
|
{
|
||||||
{ key: filterTypes.NOT_STARTS_WITH, value: 'does not start with' },
|
key: filterTypes.NOT_CONTAINS,
|
||||||
{ key: filterTypes.ENDS_WITH, value: 'ends with' },
|
value: () => translate('FilterDoesNotContain')
|
||||||
{ key: filterTypes.NOT_ENDS_WITH, value: 'does not end with' }
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.EQUAL,
|
||||||
|
value: () => translate('FilterEqual')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_EQUAL,
|
||||||
|
value: () => translate('FilterNotEqual')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.STARTS_WITH,
|
||||||
|
value: () => translate('FilterStartsWith')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_STARTS_WITH,
|
||||||
|
value: () => translate('FilterDoesNotStartWith')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.ENDS_WITH,
|
||||||
|
value: () => translate('FilterEndsWith')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: filterTypes.NOT_ENDS_WITH,
|
||||||
|
value: () => translate('FilterDoesNotEndWith')
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
{
|
{
|
||||||
"About": "About",
|
"About": "About",
|
||||||
|
"Absolute": "Absolute",
|
||||||
"AbsoluteEpisodeNumber": "Absolute Episode Number",
|
"AbsoluteEpisodeNumber": "Absolute Episode Number",
|
||||||
"AbsoluteEpisodeNumbers": "Absolute Episode Number(s)",
|
"AbsoluteEpisodeNumbers": "Absolute Episode Number(s)",
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
"Activity": "Activity",
|
"Activity": "Activity",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"AddANewPath": "Add a new path",
|
||||||
"AddAutoTag": "Add Auto Tag",
|
"AddAutoTag": "Add Auto Tag",
|
||||||
"AddAutoTagError": "Unable to add a new auto tag, please try again.",
|
"AddAutoTagError": "Unable to add a new auto tag, please try again.",
|
||||||
"AddCondition": "Add Condition",
|
"AddCondition": "Add Condition",
|
||||||
"AddConditionError": "Unable to add a new condition, please try again.",
|
"AddConditionError": "Unable to add a new condition, please try again.",
|
||||||
"AddConnection": "Add Connection",
|
"AddConnection": "Add Connection",
|
||||||
|
"AddCustomFilter": "Add Custom Filter",
|
||||||
"AddCustomFormat": "Add Custom Format",
|
"AddCustomFormat": "Add Custom Format",
|
||||||
"AddCustomFormatError": "Unable to add a new custom format, please try again.",
|
"AddCustomFormatError": "Unable to add a new custom format, please try again.",
|
||||||
"AddDelayProfile": "Add Delay Profile",
|
"AddDelayProfile": "Add Delay Profile",
|
||||||
|
@ -48,6 +51,11 @@
|
||||||
"AgeWhenGrabbed": "Age (when grabbed)",
|
"AgeWhenGrabbed": "Age (when grabbed)",
|
||||||
"Agenda": "Agenda",
|
"Agenda": "Agenda",
|
||||||
"AirDate": "Air Date",
|
"AirDate": "Air Date",
|
||||||
|
"Airs": "Airs",
|
||||||
|
"AirsDateAtTimeOn": "{date} at {time} on {networkLabel}",
|
||||||
|
"AirsTbaOn": "TBA on {networkLabel}",
|
||||||
|
"AirsTimeOn": "{time} on {networkLabel}",
|
||||||
|
"AirsTomorrowOn": "Tomorrow at {time} on {networkLabel}",
|
||||||
"All": "All",
|
"All": "All",
|
||||||
"AllResultsAreHiddenByTheAppliedFilter": "All results are hidden by the applied filter",
|
"AllResultsAreHiddenByTheAppliedFilter": "All results are hidden by the applied filter",
|
||||||
"AllSeriesInRootFolderHaveBeenImported": "All series in {path} have been imported",
|
"AllSeriesInRootFolderHaveBeenImported": "All series in {path} have been imported",
|
||||||
|
@ -62,6 +70,8 @@
|
||||||
"Anime": "Anime",
|
"Anime": "Anime",
|
||||||
"AnimeEpisodeFormat": "Anime Episode Format",
|
"AnimeEpisodeFormat": "Anime Episode Format",
|
||||||
"AnimeTypeDescription": "Episodes released using an absolute episode number",
|
"AnimeTypeDescription": "Episodes released using an absolute episode number",
|
||||||
|
"AnimeTypeFormat": "Absolute episode number ({format})",
|
||||||
|
"Any": "Any",
|
||||||
"ApiKey": "API Key",
|
"ApiKey": "API Key",
|
||||||
"ApiKeyValidationHealthCheckMessage": "Please update your API key to be at least {0} characters long. You can do this via settings or the config file",
|
"ApiKeyValidationHealthCheckMessage": "Please update your API key to be at least {0} characters long. You can do this via settings or the config file",
|
||||||
"AppDataDirectory": "AppData directory",
|
"AppDataDirectory": "AppData directory",
|
||||||
|
@ -181,6 +191,7 @@
|
||||||
"ConnectionLostReconnect": "{appName} will try to connect automatically, or you can click reload below.",
|
"ConnectionLostReconnect": "{appName} will try to connect automatically, or you can click reload below.",
|
||||||
"ConnectionLostToBackend": "{appName} has lost its connection to the backend and will need to be reloaded to restore functionality.",
|
"ConnectionLostToBackend": "{appName} has lost its connection to the backend and will need to be reloaded to restore functionality.",
|
||||||
"Connections": "Connections",
|
"Connections": "Connections",
|
||||||
|
"Continuing": "Continuing",
|
||||||
"ContinuingOnly": "Continuing Only",
|
"ContinuingOnly": "Continuing Only",
|
||||||
"CopyToClipboard": "Copy to Clipboard",
|
"CopyToClipboard": "Copy to Clipboard",
|
||||||
"CopyUsingHardlinksHelpText": "Hardlinks allow Sonarr to import seeding torrents to 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",
|
"CopyUsingHardlinksHelpText": "Hardlinks allow Sonarr to import seeding torrents to 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",
|
||||||
|
@ -195,6 +206,7 @@
|
||||||
"CreateGroup": "Create Group",
|
"CreateGroup": "Create Group",
|
||||||
"CurrentlyInstalled": "Currently Installed",
|
"CurrentlyInstalled": "Currently Installed",
|
||||||
"Custom": "Custom",
|
"Custom": "Custom",
|
||||||
|
"CustomFilters": "Custom Filters",
|
||||||
"CustomFormat": "Custom Format",
|
"CustomFormat": "Custom Format",
|
||||||
"CustomFormatHelpText": "Sonarr scores each release using the sum of scores for matching custom formats. If a new release would improve the score, at the same or better quality, then Sonarr will grab it.",
|
"CustomFormatHelpText": "Sonarr scores each release using the sum of scores for matching custom formats. If a new release would improve the score, at the same or better quality, then Sonarr will grab it.",
|
||||||
"CustomFormatScore": "Custom Format Score",
|
"CustomFormatScore": "Custom Format Score",
|
||||||
|
@ -209,6 +221,7 @@
|
||||||
"Daily": "Daily",
|
"Daily": "Daily",
|
||||||
"DailyEpisodeFormat": "Daily Episode Format",
|
"DailyEpisodeFormat": "Daily Episode Format",
|
||||||
"DailyTypeDescription": "Episodes released daily or less frequently that use year-month-day (2023-08-04)",
|
"DailyTypeDescription": "Episodes released daily or less frequently that use year-month-day (2023-08-04)",
|
||||||
|
"DailyTypeFormat": "Date ({format})",
|
||||||
"Dash": "Dash",
|
"Dash": "Dash",
|
||||||
"Date": "Date",
|
"Date": "Date",
|
||||||
"Dates": "Dates",
|
"Dates": "Dates",
|
||||||
|
@ -216,6 +229,7 @@
|
||||||
"Debug": "Debug",
|
"Debug": "Debug",
|
||||||
"DefaultCase": "Default Case",
|
"DefaultCase": "Default Case",
|
||||||
"DefaultDelayProfile": "This is the default profile. It applies to all series that don't have an explicit profile.",
|
"DefaultDelayProfile": "This is the default profile. It applies to all series that don't have an explicit profile.",
|
||||||
|
"DefaultNotFoundMessage": "You must be lost, nothing to see here.",
|
||||||
"DelayMinutes": "{delay} Minutes",
|
"DelayMinutes": "{delay} Minutes",
|
||||||
"DelayProfile": "Delay Profile",
|
"DelayProfile": "Delay Profile",
|
||||||
"DelayProfileProtocol": "Protocol: {preferredProtocol}",
|
"DelayProfileProtocol": "Protocol: {preferredProtocol}",
|
||||||
|
@ -238,6 +252,9 @@
|
||||||
"DeleteDownloadClientMessageText": "Are you sure you want to delete the download client '{name}'?",
|
"DeleteDownloadClientMessageText": "Are you sure you want to delete the download client '{name}'?",
|
||||||
"DeleteEmptyFolders": "Delete Empty Folders",
|
"DeleteEmptyFolders": "Delete Empty Folders",
|
||||||
"DeleteEmptyFoldersHelpText": "Delete empty series and season folders during disk scan and when episode files are deleted",
|
"DeleteEmptyFoldersHelpText": "Delete empty series and season folders during disk scan and when episode files are deleted",
|
||||||
|
"DeleteEpisodeFile": "Delete Episode File",
|
||||||
|
"DeleteEpisodeFileMessage": "Are you sure you want to delete '{path}'?",
|
||||||
|
"DeleteEpisodeFromDisk": "Delete episode from disk",
|
||||||
"DeleteImportList": "Delete Import List",
|
"DeleteImportList": "Delete Import List",
|
||||||
"DeleteImportListExclusion": "Delete Import List Exclusion",
|
"DeleteImportListExclusion": "Delete Import List Exclusion",
|
||||||
"DeleteImportListExclusionMessageText": "Are you sure you want to delete this import list exclusion?",
|
"DeleteImportListExclusionMessageText": "Are you sure you want to delete this import list exclusion?",
|
||||||
|
@ -279,6 +296,7 @@
|
||||||
"DoNotUpgradeAutomatically": "Do not Upgrade Automatically",
|
"DoNotUpgradeAutomatically": "Do not Upgrade Automatically",
|
||||||
"Docker": "Docker",
|
"Docker": "Docker",
|
||||||
"DockerUpdater": "Update the docker container to receive the update",
|
"DockerUpdater": "Update the docker container to receive the update",
|
||||||
|
"Donate": "Donate",
|
||||||
"Donations": "Donations",
|
"Donations": "Donations",
|
||||||
"DoneEditingGroups": "Done Editing Groups",
|
"DoneEditingGroups": "Done Editing Groups",
|
||||||
"DotNetVersion": ".NET",
|
"DotNetVersion": ".NET",
|
||||||
|
@ -356,15 +374,20 @@
|
||||||
"Episode": "Episode",
|
"Episode": "Episode",
|
||||||
"EpisodeAirDate": "Episode Air Date",
|
"EpisodeAirDate": "Episode Air Date",
|
||||||
"EpisodeCount": "Episode Count",
|
"EpisodeCount": "Episode Count",
|
||||||
|
"EpisodeDownloaded": "Episode Downloaded",
|
||||||
"EpisodeFileDeleted": "Episode File Deleted",
|
"EpisodeFileDeleted": "Episode File Deleted",
|
||||||
"EpisodeFileDeletedTooltip": "Episode file deleted",
|
"EpisodeFileDeletedTooltip": "Episode file deleted",
|
||||||
"EpisodeFileRenamed": "Episode File Renamed",
|
"EpisodeFileRenamed": "Episode File Renamed",
|
||||||
"EpisodeFileRenamedTooltip": "Episode file renamed",
|
"EpisodeFileRenamedTooltip": "Episode file renamed",
|
||||||
|
"EpisodeHasNotAired": "Episode has not aired",
|
||||||
|
"EpisodeHistoryLoadError": "Unable to load episode history",
|
||||||
"EpisodeImported": "Episode Imported",
|
"EpisodeImported": "Episode Imported",
|
||||||
"EpisodeImportedTooltip": "Episode downloaded successfully and picked up from download client",
|
"EpisodeImportedTooltip": "Episode downloaded successfully and picked up from download client",
|
||||||
"EpisodeInfo": "Episode Info",
|
"EpisodeInfo": "Episode Info",
|
||||||
"EpisodeIsDownloading": "Episode is downloading",
|
"EpisodeIsDownloading": "Episode is downloading",
|
||||||
|
"EpisodeIsNotMonitored": "Episode is not monitored",
|
||||||
"EpisodeMissingAbsoluteNumber": "Episode does not have an absolute episode number",
|
"EpisodeMissingAbsoluteNumber": "Episode does not have an absolute episode number",
|
||||||
|
"EpisodeMissingFromDisk": "Episode missing from disk",
|
||||||
"EpisodeNaming": "Episode Naming",
|
"EpisodeNaming": "Episode Naming",
|
||||||
"EpisodeNumbers": "Episode Number(s)",
|
"EpisodeNumbers": "Episode Number(s)",
|
||||||
"EpisodeProgress": "Episode Progress",
|
"EpisodeProgress": "Episode Progress",
|
||||||
|
@ -374,12 +397,17 @@
|
||||||
"EpisodeTitleRequiredHelpText": "Prevent importing for up to 48 hours if the episode title is in the naming format and the episode title is TBA",
|
"EpisodeTitleRequiredHelpText": "Prevent importing for up to 48 hours if the episode title is in the naming format and the episode title is TBA",
|
||||||
"Episodes": "Episodes",
|
"Episodes": "Episodes",
|
||||||
"Error": "Error",
|
"Error": "Error",
|
||||||
|
"ErrorLoadingContent": "There was an error loading this content",
|
||||||
|
"ErrorLoadingContents": "Error loading contents",
|
||||||
|
"ErrorLoadingItem": "There was an error loading this item",
|
||||||
|
"ErrorLoadingPage": "There was an error loading this page",
|
||||||
"ErrorRestoringBackup": "Error restoring backup",
|
"ErrorRestoringBackup": "Error restoring backup",
|
||||||
"EventType": "Event Type",
|
"EventType": "Event Type",
|
||||||
"Events": "Events",
|
"Events": "Events",
|
||||||
"Example": "Example",
|
"Example": "Example",
|
||||||
"Exception": "Exception",
|
"Exception": "Exception",
|
||||||
"Existing": "Existing",
|
"Existing": "Existing",
|
||||||
|
"ExistingSeries": "Existing Series",
|
||||||
"ExistingTag": "Existing tag",
|
"ExistingTag": "Existing tag",
|
||||||
"ExportCustomFormat": "Export Custom Format",
|
"ExportCustomFormat": "Export Custom Format",
|
||||||
"Extend": "Extend",
|
"Extend": "Extend",
|
||||||
|
@ -389,12 +417,44 @@
|
||||||
"ExtraFileExtensionsHelpTextsExamples": "Examples: '.sub, .nfo' or 'sub,nfo'",
|
"ExtraFileExtensionsHelpTextsExamples": "Examples: '.sub, .nfo' or 'sub,nfo'",
|
||||||
"Failed": "Failed",
|
"Failed": "Failed",
|
||||||
"FailedToFetchUpdates": "Failed to fetch updates",
|
"FailedToFetchUpdates": "Failed to fetch updates",
|
||||||
|
"FailedToLoadCustomFiltersFromApi": "Failed to load custom filters from API",
|
||||||
|
"FailedToLoadQualityProfilesFromApi": "Failed to load quality profiles from API",
|
||||||
|
"FailedToLoadSeriesFromApi": "Failed to load series from API",
|
||||||
|
"FailedToLoadSonarr": "Failed to load Sonarr",
|
||||||
|
"FailedToLoadSystemStatusFromApi": "Failed to load system status from API",
|
||||||
|
"FailedToLoadTagsFromApi": "Failed to load tags from API",
|
||||||
|
"FailedToLoadTranslationsFromApi": "Failed to load translations from API",
|
||||||
|
"FailedToLoadUiSettingsFromApi": "Failed to load UI settings from API",
|
||||||
"FailedToUpdateSettings": "Failed to update settings",
|
"FailedToUpdateSettings": "Failed to update settings",
|
||||||
"FeatureRequests": "Feature Requests",
|
"FeatureRequests": "Feature Requests",
|
||||||
|
"File": "File",
|
||||||
|
"FileBrowser": "File Browser",
|
||||||
|
"FileBrowserPlaceholderText": "Start typing or select a path below",
|
||||||
"FileManagement": "File Management",
|
"FileManagement": "File Management",
|
||||||
"FileNameTokens": "File Name Tokens",
|
"FileNameTokens": "File Name Tokens",
|
||||||
"FileNames": "File Names",
|
"FileNames": "File Names",
|
||||||
"Filename": "Filename",
|
"Filename": "Filename",
|
||||||
|
"Filter": "Filter",
|
||||||
|
"FilterContains": "contains",
|
||||||
|
"FilterDoesNotContain": "does not contain",
|
||||||
|
"FilterDoesNotEndWith": "does not end with",
|
||||||
|
"FilterDoesNotStartWith": "does not start with",
|
||||||
|
"FilterEndsWith": "ends with",
|
||||||
|
"FilterEqual": "equal",
|
||||||
|
"FilterGreaterThan": "greater than",
|
||||||
|
"FilterGreaterThanOrEqual": "greater than or equal",
|
||||||
|
"FilterInLast": "in the last",
|
||||||
|
"FilterInNext": "in the next",
|
||||||
|
"FilterIs": "is",
|
||||||
|
"FilterIsAfter": "is after",
|
||||||
|
"FilterIsBefore": "is before",
|
||||||
|
"FilterIsNot": "is not",
|
||||||
|
"FilterLessThan": "less than",
|
||||||
|
"FilterLessThanOrEqual": "less than or equal",
|
||||||
|
"FilterNotEqual": "not equal",
|
||||||
|
"FilterNotInLast": "not in the last",
|
||||||
|
"FilterNotInNext": "not in the next",
|
||||||
|
"FilterStartsWith": "starts with",
|
||||||
"FinaleTooltip": "Series or season finale",
|
"FinaleTooltip": "Series or season finale",
|
||||||
"FirstDayOfWeek": "First Day of Week",
|
"FirstDayOfWeek": "First Day of Week",
|
||||||
"Fixed": "Fixed",
|
"Fixed": "Fixed",
|
||||||
|
@ -436,6 +496,7 @@
|
||||||
"ICalIncludeUnmonitoredHelpText": "Include unmonitored episodes in the iCal feed",
|
"ICalIncludeUnmonitoredHelpText": "Include unmonitored episodes in the iCal feed",
|
||||||
"ICalLink": "iCal Link",
|
"ICalLink": "iCal Link",
|
||||||
"ICalSeasonPremieresOnlyHelpText": "Only the first episode in a season will be in the feed",
|
"ICalSeasonPremieresOnlyHelpText": "Only the first episode in a season will be in the feed",
|
||||||
|
"ICalShowAsAllDayEvents": "Show as All-Day Events",
|
||||||
"ICalShowAsAllDayEventsHelpText": "Events will appear as all-day events in your calendar",
|
"ICalShowAsAllDayEventsHelpText": "Events will appear as all-day events in your calendar",
|
||||||
"ICalTagsHelpText": "Feed will only contain series with at least one matching tag",
|
"ICalTagsHelpText": "Feed will only contain series with at least one matching tag",
|
||||||
"IRC": "IRC",
|
"IRC": "IRC",
|
||||||
|
@ -514,6 +575,12 @@
|
||||||
"InteractiveSearch": "Interactive Search",
|
"InteractiveSearch": "Interactive Search",
|
||||||
"Interval": "Interval",
|
"Interval": "Interval",
|
||||||
"InvalidFormat": "Invalid Format",
|
"InvalidFormat": "Invalid Format",
|
||||||
|
"KeyboardShortcuts": "Keyboard Shortcuts",
|
||||||
|
"KeyboardShortcutsCloseModal": "Close Current Modal",
|
||||||
|
"KeyboardShortcutsConfirmModal": "Accept Confirmation Modal",
|
||||||
|
"KeyboardShortcutsFocusSearchBox": "Focus Search Box",
|
||||||
|
"KeyboardShortcutsOpenModal": "Open This Modal",
|
||||||
|
"KeyboardShortcutsSaveSettings": "Save Settings",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
"Languages": "Languages",
|
"Languages": "Languages",
|
||||||
"LanguagesLoadError": "Unable to load languages",
|
"LanguagesLoadError": "Unable to load languages",
|
||||||
|
@ -539,12 +606,14 @@
|
||||||
"Local": "Local",
|
"Local": "Local",
|
||||||
"LocalAirDate": "Local Air Date",
|
"LocalAirDate": "Local Air Date",
|
||||||
"LocalPath": "Local Path",
|
"LocalPath": "Local Path",
|
||||||
|
"LocalStorageIsNotSupported": "Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.",
|
||||||
"Location": "Location",
|
"Location": "Location",
|
||||||
"LogFiles": "Log Files",
|
"LogFiles": "Log Files",
|
||||||
"LogFilesLocation": "Log files are located in: {location}",
|
"LogFilesLocation": "Log files are located in: {location}",
|
||||||
"LogLevel": "Log Level",
|
"LogLevel": "Log Level",
|
||||||
"LogLevelTraceHelpTextWarning": "Trace logging should only be enabled temporarily",
|
"LogLevelTraceHelpTextWarning": "Trace logging should only be enabled temporarily",
|
||||||
"Logging": "Logging",
|
"Logging": "Logging",
|
||||||
|
"Logout": "Logout",
|
||||||
"Logs": "Logs",
|
"Logs": "Logs",
|
||||||
"LongDateFormat": "Long Date Format",
|
"LongDateFormat": "Long Date Format",
|
||||||
"Lowercase": "Lowercase",
|
"Lowercase": "Lowercase",
|
||||||
|
@ -556,7 +625,9 @@
|
||||||
"ManageLists": "Manage Lists",
|
"ManageLists": "Manage Lists",
|
||||||
"Manual": "Manual",
|
"Manual": "Manual",
|
||||||
"ManualImportItemsLoadError": "Unable to load manual import items",
|
"ManualImportItemsLoadError": "Unable to load manual import items",
|
||||||
|
"MappedNetworkDrivesWindowsService": "Mapped network drives are not available when running as a Windows Service, see the [FAQ](https://wiki.servarr.com/sonarr/faq#why-cant-sonarr-see-my-files-on-a-remote-server) for more information.",
|
||||||
"MarkAsFailed": "Mark as Failed",
|
"MarkAsFailed": "Mark as Failed",
|
||||||
|
"MarkAsFailedConfirmation": "Are you sure you want to mark '{sourceTitle}' as failed?",
|
||||||
"MatchedToEpisodes": "Matched to Episodes",
|
"MatchedToEpisodes": "Matched to Episodes",
|
||||||
"MatchedToSeason": "Matched to Season",
|
"MatchedToSeason": "Matched to Season",
|
||||||
"MatchedToSeries": "Matched to Series",
|
"MatchedToSeries": "Matched to Series",
|
||||||
|
@ -577,6 +648,7 @@
|
||||||
"Message": "Message",
|
"Message": "Message",
|
||||||
"Metadata": "Metadata",
|
"Metadata": "Metadata",
|
||||||
"MetadataLoadError": "Unable to load Metadata",
|
"MetadataLoadError": "Unable to load Metadata",
|
||||||
|
"MetadataProvidedBy": "Metadata is provided by {provider}",
|
||||||
"MetadataSettings": "Metadata Settings",
|
"MetadataSettings": "Metadata Settings",
|
||||||
"MetadataSettingsSummary": "Create metadata files when episodes are imported or series are refreshed",
|
"MetadataSettingsSummary": "Create metadata files when episodes are imported or series are refreshed",
|
||||||
"MetadataSource": "Metadata Source",
|
"MetadataSource": "Metadata Source",
|
||||||
|
@ -595,6 +667,7 @@
|
||||||
"MinutesThirty": "30 Minutes: {thirty}",
|
"MinutesThirty": "30 Minutes: {thirty}",
|
||||||
"Missing": "Missing",
|
"Missing": "Missing",
|
||||||
"MissingEpisodes": "Missing Episodes",
|
"MissingEpisodes": "Missing Episodes",
|
||||||
|
"Mixed": "Mixed",
|
||||||
"Mode": "Mode",
|
"Mode": "Mode",
|
||||||
"Monday": "Monday",
|
"Monday": "Monday",
|
||||||
"Monitor": "Monitor",
|
"Monitor": "Monitor",
|
||||||
|
@ -618,6 +691,7 @@
|
||||||
"MonitoredOnly": "Monitored Only",
|
"MonitoredOnly": "Monitored Only",
|
||||||
"MonitoringOptions": "Monitoring Options",
|
"MonitoringOptions": "Monitoring Options",
|
||||||
"Month": "Month",
|
"Month": "Month",
|
||||||
|
"More": "More",
|
||||||
"MoreDetails": "More details",
|
"MoreDetails": "More details",
|
||||||
"MoreInfo": "More Info",
|
"MoreInfo": "More Info",
|
||||||
"MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ",
|
"MountHealthCheckMessage": "Mount containing a series path is mounted read-only: ",
|
||||||
|
@ -625,11 +699,13 @@
|
||||||
"MultiEpisode": "Multi Episode",
|
"MultiEpisode": "Multi Episode",
|
||||||
"MultiEpisodeInvalidFormat": "Multi Episode: Invalid Format",
|
"MultiEpisodeInvalidFormat": "Multi Episode: Invalid Format",
|
||||||
"MultiEpisodeStyle": "Multi Episode Style",
|
"MultiEpisodeStyle": "Multi Episode Style",
|
||||||
|
"MultiLanguages": "Multi-Languages",
|
||||||
"MultiSeason": "Multi-Season",
|
"MultiSeason": "Multi-Season",
|
||||||
"MustContain": "Must Contain",
|
"MustContain": "Must Contain",
|
||||||
"MustContainHelpText": "The release must contain at least one of these terms (case insensitive)",
|
"MustContainHelpText": "The release must contain at least one of these terms (case insensitive)",
|
||||||
"MustNotContain": "Must Not Contain",
|
"MustNotContain": "Must Not Contain",
|
||||||
"MustNotContainHelpText": "The release will be rejected if it contains one or more of terms (case insensitive)",
|
"MustNotContainHelpText": "The release will be rejected if it contains one or more of terms (case insensitive)",
|
||||||
|
"MyComputer": "My Computer",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"NamingSettings": "Naming Settings",
|
"NamingSettings": "Naming Settings",
|
||||||
"NamingSettingsLoadError": "Unable to load Naming settings",
|
"NamingSettingsLoadError": "Unable to load Naming settings",
|
||||||
|
@ -647,6 +723,8 @@
|
||||||
"NoChanges": "No Changes",
|
"NoChanges": "No Changes",
|
||||||
"NoDelay": "No Delay",
|
"NoDelay": "No Delay",
|
||||||
"NoDownloadClientsFound": "No download clients found",
|
"NoDownloadClientsFound": "No download clients found",
|
||||||
|
"NoEpisodeHistory": "No episode history",
|
||||||
|
"NoEpisodeOverview": "No episode overview",
|
||||||
"NoEventsFound": "No events found",
|
"NoEventsFound": "No events found",
|
||||||
"NoHistoryBlocklist": "No history blocklist",
|
"NoHistoryBlocklist": "No history blocklist",
|
||||||
"NoHistoryFound": "No history found",
|
"NoHistoryFound": "No history found",
|
||||||
|
@ -691,8 +769,10 @@
|
||||||
"OnlyUsenet": "Only Usenet",
|
"OnlyUsenet": "Only Usenet",
|
||||||
"OpenBrowserOnStart": "Open browser on start",
|
"OpenBrowserOnStart": "Open browser on start",
|
||||||
"OpenBrowserOnStartHelpText": " Open a web browser and navigate to the Sonarr homepage on app start.",
|
"OpenBrowserOnStartHelpText": " Open a web browser and navigate to the Sonarr homepage on app start.",
|
||||||
|
"OpenSeries": "Open Series",
|
||||||
"OptionalName": "Optional name",
|
"OptionalName": "Optional name",
|
||||||
"Options": "Options",
|
"Options": "Options",
|
||||||
|
"Or": "or",
|
||||||
"Original": "Original",
|
"Original": "Original",
|
||||||
"OriginalLanguage": "Original Language",
|
"OriginalLanguage": "Original Language",
|
||||||
"Other": "Other",
|
"Other": "Other",
|
||||||
|
@ -730,6 +810,7 @@
|
||||||
"Profiles": "Profiles",
|
"Profiles": "Profiles",
|
||||||
"ProfilesSettingsSummary": "Quality, Language Delay and Release profiles",
|
"ProfilesSettingsSummary": "Quality, Language Delay and Release profiles",
|
||||||
"Progress": "Progress",
|
"Progress": "Progress",
|
||||||
|
"ProgressBarProgress": "Progress Bar at {progress}%",
|
||||||
"Proper": "Proper",
|
"Proper": "Proper",
|
||||||
"Protocol": "Protocol",
|
"Protocol": "Protocol",
|
||||||
"ProtocolHelpText": "Choose which protocol(s) to use and which one is preferred when choosing between otherwise equal releases",
|
"ProtocolHelpText": "Choose which protocol(s) to use and which one is preferred when choosing between otherwise equal releases",
|
||||||
|
@ -760,6 +841,7 @@
|
||||||
"QueueIsEmpty": "Queue is empty",
|
"QueueIsEmpty": "Queue is empty",
|
||||||
"QueueLoadError": "Failed to load Queue",
|
"QueueLoadError": "Failed to load Queue",
|
||||||
"Queued": "Queued",
|
"Queued": "Queued",
|
||||||
|
"QuickSearch": "Quick Search",
|
||||||
"Range": "Range",
|
"Range": "Range",
|
||||||
"Rating": "Rating",
|
"Rating": "Rating",
|
||||||
"ReadTheWikiForMoreInformation": "Read the Wiki for more information",
|
"ReadTheWikiForMoreInformation": "Read the Wiki for more information",
|
||||||
|
@ -821,6 +903,7 @@
|
||||||
"RemoveFailed": "Remove Failed",
|
"RemoveFailed": "Remove Failed",
|
||||||
"RemoveFailedDownloads": "Remove Failed Downloads",
|
"RemoveFailedDownloads": "Remove Failed Downloads",
|
||||||
"RemoveFailedDownloadsHelpText": "Remove failed downloads from download client history",
|
"RemoveFailedDownloadsHelpText": "Remove failed downloads from download client history",
|
||||||
|
"RemoveFilter": "Remove filter",
|
||||||
"RemoveFromBlocklist": "Remove from Blocklist",
|
"RemoveFromBlocklist": "Remove from Blocklist",
|
||||||
"RemoveFromDownloadClient": "Remove From Download Client",
|
"RemoveFromDownloadClient": "Remove From Download Client",
|
||||||
"RemoveFromDownloadClientHelpTextWarning": "Removing will remove the download and the file(s) from the download client.",
|
"RemoveFromDownloadClientHelpTextWarning": "Removing will remove the download and the file(s) from the download client.",
|
||||||
|
@ -885,6 +968,7 @@
|
||||||
"RootFolderMissingHealthCheckMessage": "Missing root folder: {0}",
|
"RootFolderMissingHealthCheckMessage": "Missing root folder: {0}",
|
||||||
"RootFolderMultipleMissingHealthCheckMessage": "Multiple root folders are missing: {0}",
|
"RootFolderMultipleMissingHealthCheckMessage": "Multiple root folders are missing: {0}",
|
||||||
"RootFolderPath": "Root Folder Path",
|
"RootFolderPath": "Root Folder Path",
|
||||||
|
"RootFolderSelectFreeSpace": "{freeSpace} Free",
|
||||||
"RootFolders": "Root Folders",
|
"RootFolders": "Root Folders",
|
||||||
"RootFoldersLoadError": "Unable to load root folders",
|
"RootFoldersLoadError": "Unable to load root folders",
|
||||||
"Rss": "RSS",
|
"Rss": "RSS",
|
||||||
|
@ -898,16 +982,19 @@
|
||||||
"SaveChanges": "Save Changes",
|
"SaveChanges": "Save Changes",
|
||||||
"SaveSettings": "Save Settings",
|
"SaveSettings": "Save Settings",
|
||||||
"Scene": "Scene",
|
"Scene": "Scene",
|
||||||
|
"SceneInformation": "Scene Information",
|
||||||
"SceneNumberNotVerified": "Scene number hasn't been verified yet",
|
"SceneNumberNotVerified": "Scene number hasn't been verified yet",
|
||||||
"SceneNumbering": "Scene Numbering",
|
"SceneNumbering": "Scene Numbering",
|
||||||
"Scheduled": "Scheduled",
|
"Scheduled": "Scheduled",
|
||||||
"Score": "Score",
|
"Score": "Score",
|
||||||
"Script": "Script",
|
"Script": "Script",
|
||||||
"ScriptPath": "Script Path",
|
"ScriptPath": "Script Path",
|
||||||
|
"Search": "Search",
|
||||||
"SearchByTvdbId": "You can also search using TVDB ID of a show. eg. tvdb:71663",
|
"SearchByTvdbId": "You can also search using TVDB ID of a show. eg. tvdb:71663",
|
||||||
"SearchFailedError": "Search failed, please try again later.",
|
"SearchFailedError": "Search failed, please try again later.",
|
||||||
"SearchForMissing": "Search for Missing",
|
"SearchForMissing": "Search for Missing",
|
||||||
"SearchForMonitoredEpisodes": "Search for monitored episodes",
|
"SearchForMonitoredEpisodes": "Search for monitored episodes",
|
||||||
|
"SearchForQuery": "Search for {query}",
|
||||||
"SearchIsNotSupportedWithThisIndexer": "Search is not supported with this indexer",
|
"SearchIsNotSupportedWithThisIndexer": "Search is not supported with this indexer",
|
||||||
"Season": "Season",
|
"Season": "Season",
|
||||||
"SeasonCount": "Season Count",
|
"SeasonCount": "Season Count",
|
||||||
|
@ -946,7 +1033,6 @@
|
||||||
"Settings": "Settings",
|
"Settings": "Settings",
|
||||||
"ShortDateFormat": "Short Date Format",
|
"ShortDateFormat": "Short Date Format",
|
||||||
"ShowAdvanced": "Show Advanced",
|
"ShowAdvanced": "Show Advanced",
|
||||||
"ICalShowAsAllDayEvents": "Show as All-Day Events",
|
|
||||||
"ShowEpisodeInformation": "Show Episode Information",
|
"ShowEpisodeInformation": "Show Episode Information",
|
||||||
"ShowEpisodeInformationHelpText": "Show episode title and number",
|
"ShowEpisodeInformationHelpText": "Show episode title and number",
|
||||||
"ShowRelativeDates": "Show Relative Dates",
|
"ShowRelativeDates": "Show Relative Dates",
|
||||||
|
@ -954,6 +1040,7 @@
|
||||||
"ShownClickToHide": "Shown, click to hide",
|
"ShownClickToHide": "Shown, click to hide",
|
||||||
"ShownUnknownSeriesItems": "Show Unknown Series Items",
|
"ShownUnknownSeriesItems": "Show Unknown Series Items",
|
||||||
"ShownUnknownSeriesItemsHelpText": "Show items without a series in the queue, this could include removed series, movies or anything else in Sonarr's category",
|
"ShownUnknownSeriesItemsHelpText": "Show items without a series in the queue, this could include removed series, movies or anything else in Sonarr's category",
|
||||||
|
"Shutdown": "Shutdown",
|
||||||
"SingleEpisode": "Single Episode",
|
"SingleEpisode": "Single Episode",
|
||||||
"SingleEpisodeInvalidFormat": "Single Episode: Invalid Format",
|
"SingleEpisodeInvalidFormat": "Single Episode: Invalid Format",
|
||||||
"Size": "Size",
|
"Size": "Size",
|
||||||
|
@ -969,6 +1056,7 @@
|
||||||
"Socks5": "Socks5 (Support TOR)",
|
"Socks5": "Socks5 (Support TOR)",
|
||||||
"SomeResultsAreHiddenByTheAppliedFilter": "Some results are hidden by the applied filter",
|
"SomeResultsAreHiddenByTheAppliedFilter": "Some results are hidden by the applied filter",
|
||||||
"SonarrTags": "Sonarr Tags",
|
"SonarrTags": "Sonarr Tags",
|
||||||
|
"Sort": "Sort",
|
||||||
"Source": "Source",
|
"Source": "Source",
|
||||||
"SourcePath": "Source Path",
|
"SourcePath": "Source Path",
|
||||||
"SourceRelativePath": "Source Relative Path",
|
"SourceRelativePath": "Source Relative Path",
|
||||||
|
@ -985,6 +1073,7 @@
|
||||||
"Standard": "Standard",
|
"Standard": "Standard",
|
||||||
"StandardEpisodeFormat": "Standard Episode Format",
|
"StandardEpisodeFormat": "Standard Episode Format",
|
||||||
"StandardTypeDescription": "Episodes released with SxxEyy pattern",
|
"StandardTypeDescription": "Episodes released with SxxEyy pattern",
|
||||||
|
"StandardTypeFormat": "Season and episode numbers ({format})",
|
||||||
"StartImport": "Start Import",
|
"StartImport": "Start Import",
|
||||||
"StartProcessing": "Start Processing",
|
"StartProcessing": "Start Processing",
|
||||||
"Started": "Started",
|
"Started": "Started",
|
||||||
|
@ -1004,6 +1093,14 @@
|
||||||
"SupportedListsMoreInfo": "For more information on the individual lists, click on the more info buttons.",
|
"SupportedListsMoreInfo": "For more information on the individual lists, click on the more info buttons.",
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"SystemTimeHealthCheckMessage": "System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected",
|
"SystemTimeHealthCheckMessage": "System time is off by more than 1 day. Scheduled tasks may not run correctly until the time is corrected",
|
||||||
|
"TableColumns": "Columns",
|
||||||
|
"TableColumnsHelpText": "Choose which columns are visible and which order they appear in",
|
||||||
|
"TableOptions": "Table Options",
|
||||||
|
"TableOptionsButton": "Table Options Button",
|
||||||
|
"TablePageSize": "Page Size",
|
||||||
|
"TablePageSizeHelpText": "Number of items to show on each page",
|
||||||
|
"TablePageSizeMaximum": "Page size must not exceed {maximumValue}",
|
||||||
|
"TablePageSizeMinimum": "Page size must be at least {minimumValue}",
|
||||||
"TagCannotBeDeletedWhileInUse": "Tag cannot be deleted while in use",
|
"TagCannotBeDeletedWhileInUse": "Tag cannot be deleted while in use",
|
||||||
"TagDetails": "Tag Details - {label}",
|
"TagDetails": "Tag Details - {label}",
|
||||||
"TagIsNotUsedAndCanBeDeleted": "Tag is not used and can be deleted",
|
"TagIsNotUsedAndCanBeDeleted": "Tag is not used and can be deleted",
|
||||||
|
@ -1012,6 +1109,7 @@
|
||||||
"TagsSettingsSummary": "See all tags and how they are used. Unused tags can be removed",
|
"TagsSettingsSummary": "See all tags and how they are used. Unused tags can be removed",
|
||||||
"TaskUserAgentTooltip": "User-Agent provided by the app that called the API",
|
"TaskUserAgentTooltip": "User-Agent provided by the app that called the API",
|
||||||
"Tasks": "Tasks",
|
"Tasks": "Tasks",
|
||||||
|
"Tba": "TBA",
|
||||||
"TestAll": "Test All",
|
"TestAll": "Test All",
|
||||||
"TestAllClients": "Test All Clients",
|
"TestAllClients": "Test All Clients",
|
||||||
"TestAllIndexers": "Test All Indexers",
|
"TestAllIndexers": "Test All Indexers",
|
||||||
|
@ -1025,12 +1123,17 @@
|
||||||
"TimeFormat": "Time Format",
|
"TimeFormat": "Time Format",
|
||||||
"TimeLeft": "Time Left",
|
"TimeLeft": "Time Left",
|
||||||
"Title": "Title",
|
"Title": "Title",
|
||||||
|
"Titles": "Titles",
|
||||||
"Today": "Today",
|
"Today": "Today",
|
||||||
|
"ToggleMonitoredSeriesUnmonitored ": "Cannot toggle monitored state when series is unmonitored",
|
||||||
|
"ToggleMonitoredToUnmonitored": "Monitored, click to unmonitor",
|
||||||
|
"ToggleUnmonitoredToMonitored": "Unmonitored, click to monitor",
|
||||||
"TorrentDelay": "Torrent Delay",
|
"TorrentDelay": "Torrent Delay",
|
||||||
"TorrentDelayHelpText": "Delay in minutes to wait before grabbing a torrent",
|
"TorrentDelayHelpText": "Delay in minutes to wait before grabbing a torrent",
|
||||||
"TorrentDelayTime": "Torrent Delay: {torrentDelay}",
|
"TorrentDelayTime": "Torrent Delay: {torrentDelay}",
|
||||||
"Torrents": "Torrents",
|
"Torrents": "Torrents",
|
||||||
"TorrentsDisabled": "Torrents Disabled",
|
"TorrentsDisabled": "Torrents Disabled",
|
||||||
|
"TotalRecords": "Total records: {totalRecords}",
|
||||||
"TotalSpace": "Total Space",
|
"TotalSpace": "Total Space",
|
||||||
"Trace": "Trace",
|
"Trace": "Trace",
|
||||||
"TvdbId": "TVDB ID",
|
"TvdbId": "TVDB ID",
|
||||||
|
@ -1044,6 +1147,12 @@
|
||||||
"UiSettings": "UI Settings",
|
"UiSettings": "UI Settings",
|
||||||
"UiSettingsLoadError": "Unable to load UI settings",
|
"UiSettingsLoadError": "Unable to load UI settings",
|
||||||
"UiSettingsSummary": "Calendar, date and color impaired options",
|
"UiSettingsSummary": "Calendar, date and color impaired options",
|
||||||
|
"Umask": "Umask",
|
||||||
|
"Umask750Description": "{octal} - Owner write, Group read",
|
||||||
|
"Umask755Description": "{octal} - Owner write, Everyone else read",
|
||||||
|
"Umask770Description": "{octal} - Owner & Group write",
|
||||||
|
"Umask775Description": "{octal} - Owner & Group write, Other read",
|
||||||
|
"Umask777Description": "{octal} - Everyone write",
|
||||||
"UnableToLoadAutoTagging": "Unable to load auto tagging",
|
"UnableToLoadAutoTagging": "Unable to load auto tagging",
|
||||||
"UnableToLoadBackups": "Unable to load backups",
|
"UnableToLoadBackups": "Unable to load backups",
|
||||||
"UnableToLoadRootFolders": "Unable to load root folders",
|
"UnableToLoadRootFolders": "Unable to load root folders",
|
||||||
|
@ -1095,8 +1204,10 @@
|
||||||
"Username": "Username",
|
"Username": "Username",
|
||||||
"UtcAirDate": "UTC Air Date",
|
"UtcAirDate": "UTC Air Date",
|
||||||
"Version": "Version",
|
"Version": "Version",
|
||||||
|
"VersionNumber": "Version {version}",
|
||||||
"VideoCodec": "Video Codec",
|
"VideoCodec": "Video Codec",
|
||||||
"VideoDynamicRange": "Video Dynamic Range",
|
"VideoDynamicRange": "Video Dynamic Range",
|
||||||
|
"View": "View",
|
||||||
"VisitTheWikiForMoreDetails": "Visit the wiki for more details: ",
|
"VisitTheWikiForMoreDetails": "Visit the wiki for more details: ",
|
||||||
"WaitingToImport": "Waiting to Import",
|
"WaitingToImport": "Waiting to Import",
|
||||||
"WaitingToProcess": "Waiting to Process",
|
"WaitingToProcess": "Waiting to Process",
|
||||||
|
|
Loading…
Reference in New Issue